From c688b5fc096031aae9375317fc741f6497160b3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 23 May 2019 08:44:55 +0200 Subject: [PATCH] Added optional km/mi markers closes #84 --- src/GUI/axisitem.cpp | 4 +- src/GUI/gui.cpp | 13 +++++ src/GUI/gui.h | 1 + src/GUI/mapview.cpp | 12 +++++ src/GUI/mapview.h | 3 +- src/GUI/pathitem.cpp | 107 +++++++++++++++++++++++++++++++++++++++++- src/GUI/pathitem.h | 16 ++++++- src/GUI/routeitem.cpp | 13 +++-- src/GUI/routeitem.h | 3 +- src/GUI/scaleitem.cpp | 10 ++-- src/GUI/settings.h | 2 + src/GUI/trackitem.cpp | 1 + src/common/util.cpp | 2 +- src/common/util.h | 2 +- 14 files changed, 167 insertions(+), 22 deletions(-) diff --git a/src/GUI/axisitem.cpp b/src/GUI/axisitem.cpp index e3a591e7..f1cdb6d9 100644 --- a/src/GUI/axisitem.cpp +++ b/src/GUI/axisitem.cpp @@ -29,8 +29,8 @@ private: Ticks::Ticks(double minValue, double maxValue, int maxCount) { - double range = niceNum(maxValue - minValue, 0); - _d = niceNum(range / maxCount, 1); + double range = niceNum(maxValue - minValue, false); + _d = niceNum(range / maxCount, true); _min = ceil(minValue / _d) * _d; _max = floor(maxValue / _d) * _d; } diff --git a/src/GUI/gui.cpp b/src/GUI/gui.cpp index a074e2f3..fdad0011 100644 --- a/src/GUI/gui.cpp +++ b/src/GUI/gui.cpp @@ -349,6 +349,11 @@ void GUI::createActions() _showRouteWaypointsAction->setCheckable(true); connect(_showRouteWaypointsAction, SIGNAL(triggered(bool)), _mapView, SLOT(showRouteWaypoints(bool))); + _showTicksAction = new QAction(tr("km/mi markers"), this); + _showTicksAction->setMenuRole(QAction::NoRole); + _showTicksAction->setCheckable(true); + connect(_showTicksAction, SIGNAL(triggered(bool)), _mapView, + SLOT(showTicks(bool))); // Graph actions _showGraphsAction = new QAction(QIcon(SHOW_GRAPHS_ICON), tr("Show graphs"), @@ -536,6 +541,7 @@ void GUI::createMenus() QMenu *displayMenu = dataMenu->addMenu(tr("Display")); displayMenu->addAction(_showWaypointLabelsAction); displayMenu->addAction(_showRouteWaypointsAction); + displayMenu->addAction(_showTicksAction); dataMenu->addSeparator(); dataMenu->addAction(_showTracksAction); dataMenu->addAction(_showRoutesAction); @@ -1721,6 +1727,9 @@ void GUI::writeSettings() if (_showRouteWaypointsAction->isChecked() != SHOW_ROUTE_WAYPOINTS_DEFAULT) settings.setValue(SHOW_ROUTE_WAYPOINTS_SETTING, _showRouteWaypointsAction->isChecked()); + if (_showTicksAction->isChecked() != SHOW_TICKS_DEFAULT) + settings.setValue(SHOW_TICKS_SETTING, + _showTicksAction->isChecked()); settings.endGroup(); settings.beginGroup(EXPORT_SETTINGS_GROUP); @@ -1984,6 +1993,10 @@ void GUI::readSettings() _mapView->showRouteWaypoints(false); else _showRouteWaypointsAction->setChecked(true); + if (settings.value(SHOW_TICKS_SETTING, SHOW_TICKS_DEFAULT).toBool()) { + _mapView->showTicks(true); + _showTicksAction->setChecked(true); + } settings.endGroup(); settings.beginGroup(EXPORT_SETTINGS_GROUP); diff --git a/src/GUI/gui.h b/src/GUI/gui.h index 2b900aa6..d985131d 100644 --- a/src/GUI/gui.h +++ b/src/GUI/gui.h @@ -192,6 +192,7 @@ private: QAction *_showAreasAction; QAction *_showRouteWaypointsAction; QAction *_showMarkersAction; + QAction *_showTicksAction; QAction *_showCoordinatesAction; QAction *_openOptionsAction; QAction *_mapsEnd; diff --git a/src/GUI/mapview.cpp b/src/GUI/mapview.cpp index 333388dc..d4485c53 100644 --- a/src/GUI/mapview.cpp +++ b/src/GUI/mapview.cpp @@ -75,6 +75,7 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent) _overlapPOIs = true; _showRouteWaypoints = true; _showMarkers = true; + _showPathTicks = false; _trackWidth = 3; _routeWidth = 3; _trackStyle = Qt::SolidLine; @@ -125,6 +126,7 @@ PathItem *MapView::addTrack(const Track &track) ti->setDigitalZoom(_digitalZoom); ti->setMarkerColor(_markerColor); ti->showMarker(_showMarkers); + ti->showTicks(_showPathTicks); _scene->addItem(ti); if (_showTracks) @@ -154,6 +156,7 @@ PathItem *MapView::addRoute(const Route &route) ri->setDigitalZoom(_digitalZoom); ri->setMarkerColor(_markerColor); ri->showMarker(_showMarkers); + ri->showTicks(_showPathTicks); _scene->addItem(ri); if (_showRoutes) @@ -724,6 +727,15 @@ void MapView::showMarkers(bool show) _routes.at(i)->showMarker(show); } +void MapView::showTicks(bool show) +{ + _showPathTicks = show; + for (int i = 0; i < _tracks.size(); i++) + _tracks.at(i)->showTicks(show); + for (int i = 0; i < _routes.size(); i++) + _routes.at(i)->showTicks(show); +} + void MapView::showMap(bool show) { _showMap = show; diff --git a/src/GUI/mapview.h b/src/GUI/mapview.h index c3cbd2da..d47f14da 100644 --- a/src/GUI/mapview.h +++ b/src/GUI/mapview.h @@ -79,6 +79,7 @@ public slots: void showRouteWaypoints(bool show); void showMarkers(bool show); void showCoordinates(bool show); + void showTicks(bool show); void clearMapCache(); void setCoordinatesFormat(CoordinatesFormat format); void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); @@ -139,7 +140,7 @@ private: bool _showMap, _showTracks, _showRoutes, _showAreas, _showWaypoints, _showWaypointLabels, _showPOI, _showPOILabels, _showRouteWaypoints, - _showMarkers; + _showMarkers, _showPathTicks; bool _overlapPOIs; int _trackWidth, _routeWidth, _areaWidth; Qt::PenStyle _trackStyle, _routeStyle, _areaStyle; diff --git a/src/GUI/pathitem.cpp b/src/GUI/pathitem.cpp index 9c6cc882..30014458 100644 --- a/src/GUI/pathitem.cpp +++ b/src/GUI/pathitem.cpp @@ -3,6 +3,7 @@ #include #include "common/greatcircle.h" #include "map/map.h" +#include "font.h" #include "pathitem.h" @@ -18,16 +19,30 @@ static inline unsigned segments(qreal distance) return ceil(distance / GEOGRAPHICAL_MILE); } +static QFont font() +{ + QFont font; + font.setPixelSize(10); + font.setFamily(FONT_FAMILY); + font.setBold(true); + + return font; +} + +QFont PathItem::_font = font(); + PathItem::PathItem(const Path &path, Map *map, QGraphicsItem *parent) : QGraphicsObject(parent), _path(path), _map(map) { Q_ASSERT(_path.isValid()); + _units = Metric; _digitalZoom = 0; _width = 3; QBrush brush(Qt::SolidPattern); _pen = QPen(brush, _width); _showMarker = true; + _showTicks = false; updatePainterPath(); updateShape(); @@ -38,6 +53,8 @@ PathItem::PathItem(const Path &path, Map *map, QGraphicsItem *parent) setCursor(Qt::ArrowCursor); setAcceptHoverEvents(true); + + computeTickInfo(); } void PathItem::updateShape() @@ -110,9 +127,29 @@ void PathItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, painter->setPen(_pen); painter->drawPath(_painterPath); + if (_showTicks) { + painter->setFont(_font); + painter->setRenderHint(QPainter::Antialiasing, false); + + for (int i = 1; i < _tickCount; i++) { + QPointF pos(position(i * _tickSize * xInM())); + QPointF arrow[3] = {pos, QPointF(pos.x() + 3, pos.y() - 3), + QPointF(pos.x() - 3, pos.y() - 3)}; + QString val(QString::number(i * _tickSize)); + + QRect br(_tickRect); + br.moveCenter(QPoint(pos.x(), pos.y() - br.height()/2 - 5)); + painter->setPen(Qt::white); + painter->setBrush(_pen.color()); + painter->drawPolygon(arrow, 3); + painter->drawRoundedRect(br, 2, 2); + painter->drawText(br, Qt::AlignCenter, val); + } + } + /* - QPen p = QPen(QBrush(Qt::red), 0); - painter->setPen(p); + painter->setBrush(Qt::NoBrush); + painter->setPen(Qt::red); painter->drawRect(boundingRect()); */ } @@ -284,6 +321,64 @@ void PathItem::showMarker(bool show) _marker->setVisible(show && isValid(position(_markerDistance))); } +qreal PathItem::xInM() const +{ + return (_units == Nautical) ? NMIINM : (_units == Imperial) ? MIINM : KMINM; +} + +unsigned PathItem::tickSize() const +{ + qreal r = _path.last().last().distance() / xInM(); + + if (r < 1) + return 0; + else if (r < 10) + return 1; + else if (r < 50) + return 5; + else if (r < 100) + return 10; + else if (r < 500) + return 50; + else if (r < 1000) + return 100; + else if (r < 5000) + return 500; + else + return 1000; +} + +void PathItem::computeTickInfo() +{ + _tickSize = tickSize(); + qreal f = xInM(); + _tickCount = (int)_path.last().last().distance() / (_tickSize * f) + 1; + + QFontMetrics fm(_font); + _tickRect = fm.boundingRect(QRect(), Qt::AlignCenter, + QString::number(qMax(_tickSize * (_tickCount - 1), 10))) + .adjusted(-2, 0, 2, 0); +} + +void PathItem::showTicks(bool show) +{ + if (_showTicks == show) + return; + + prepareGeometryChange(); + _showTicks = show; +} + +void PathItem::setUnits(Units units) +{ + if (_units == units) + return; + + prepareGeometryChange(); + _units = units; + computeTickInfo(); +} + void PathItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { Q_UNUSED(event); @@ -305,3 +400,11 @@ void PathItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) emit selected(false); } + +QRectF PathItem::boundingRect() const +{ + return _showTicks + ? _shape.boundingRect().adjusted(-_tickRect.width()/2, + -(_tickRect.height() + 4), _tickRect.width()/2, 0) + : _shape.boundingRect(); +} diff --git a/src/GUI/pathitem.h b/src/GUI/pathitem.h index b15bd25f..0d3676ed 100644 --- a/src/GUI/pathitem.h +++ b/src/GUI/pathitem.h @@ -5,6 +5,7 @@ #include #include "data/path.h" #include "markeritem.h" +#include "units.h" class Map; @@ -16,7 +17,7 @@ public: PathItem(const Path &path, Map *map, QGraphicsItem *parent = 0); QPainterPath shape() const {return _shape;} - QRectF boundingRect() const {return _shape.boundingRect();} + QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); @@ -24,12 +25,16 @@ public: void setMap(Map *map); + void setUnits(Units units); void setColor(const QColor &color); void setWidth(qreal width); void setStyle(Qt::PenStyle style); void setDigitalZoom(int zoom); void setMarkerColor(const QColor &color); void showMarker(bool show); + void showTicks(bool show); + + Units units() const {return _units;} public slots: void moveMarker(qreal distance); @@ -49,6 +54,9 @@ private: void updateShape(); void addSegment(const Coordinates &c1, const Coordinates &c2); + qreal xInM() const; + unsigned tickSize() const; + void computeTickInfo(); void hoverEnterEvent(QGraphicsSceneHoverEvent *event); void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); @@ -57,11 +65,17 @@ private: qreal _markerDistance; int _digitalZoom; + Units _units; qreal _width; QPen _pen; QPainterPath _shape; QPainterPath _painterPath; bool _showMarker; + bool _showTicks; + QRect _tickRect; + int _tickSize, _tickCount; + + static QFont _font; }; #endif // PATHITEM_H diff --git a/src/GUI/routeitem.cpp b/src/GUI/routeitem.cpp index 5be3814c..513e4838 100644 --- a/src/GUI/routeitem.cpp +++ b/src/GUI/routeitem.cpp @@ -31,7 +31,6 @@ RouteItem::RouteItem(const Route &route, Map *map, QGraphicsItem *parent) _name = route.name(); _desc = route.description(); - _units = Metric; _coordinatesFormat = DecimalDegrees; setToolTip(toolTip(Metric)); @@ -50,20 +49,20 @@ void RouteItem::setMap(Map *map) PathItem::setMap(map); } -void RouteItem::setUnits(Units units) +void RouteItem::setUnits(Units u) { - if (_units == units) + if (units() == u) return; - _units = units; + PathItem::setUnits(u); - setToolTip(toolTip(_units)); + setToolTip(toolTip(units())); QList childs = childItems(); for (int i = 0; i < childs.count(); i++) { if (childs.at(i) != _marker) { WaypointItem *wi = static_cast(childs.at(i)); - wi->setToolTipFormat(_units, _coordinatesFormat); + wi->setToolTipFormat(units(), _coordinatesFormat); } } } @@ -79,7 +78,7 @@ void RouteItem::setCoordinatesFormat(CoordinatesFormat format) for (int i = 0; i < childs.count(); i++) { if (childs.at(i) != _marker) { WaypointItem *wi = static_cast(childs.at(i)); - wi->setToolTipFormat(_units, _coordinatesFormat); + wi->setToolTipFormat(units(), _coordinatesFormat); } } } diff --git a/src/GUI/routeitem.h b/src/GUI/routeitem.h index 481b4a5b..8b99ab8c 100644 --- a/src/GUI/routeitem.h +++ b/src/GUI/routeitem.h @@ -17,7 +17,7 @@ public: void setMap(Map *map); - void setUnits(Units units); + void setUnits(Units u); void setCoordinatesFormat(CoordinatesFormat format); void showWaypoints(bool show); void showWaypointLabels(bool show); @@ -27,7 +27,6 @@ private: QString _name; QString _desc; - Units _units; CoordinatesFormat _coordinatesFormat; }; diff --git a/src/GUI/scaleitem.cpp b/src/GUI/scaleitem.cpp index 17dd2d23..bc0e98b3 100644 --- a/src/GUI/scaleitem.cpp +++ b/src/GUI/scaleitem.cpp @@ -61,9 +61,9 @@ void ScaleItem::computeScale() qreal res = _res * pow(2, -_digitalZoom); if (_units == Imperial) { - _length = niceNum((res * M2FT * SCALE_WIDTH) / SEGMENTS, 1); + _length = niceNum((res * M2FT * SCALE_WIDTH) / SEGMENTS, true); if (_length >= MIINFT) { - _length = niceNum((res * M2MI * SCALE_WIDTH) / SEGMENTS, 1); + _length = niceNum((res * M2MI * SCALE_WIDTH) / SEGMENTS, true); _width = (_length / (res * M2MI)); _scale = true; } else { @@ -71,9 +71,9 @@ void ScaleItem::computeScale() _scale = false; } } else if (_units == Nautical) { - _length = niceNum((res * M2FT * SCALE_WIDTH) / SEGMENTS, 1); + _length = niceNum((res * M2FT * SCALE_WIDTH) / SEGMENTS, true); if (_length >= NMIINFT) { - _length = niceNum((res * M2NMI * SCALE_WIDTH) / SEGMENTS, 1); + _length = niceNum((res * M2NMI * SCALE_WIDTH) / SEGMENTS, true); _width = (_length / (res * M2NMI)); _scale = true; } else { @@ -81,7 +81,7 @@ void ScaleItem::computeScale() _scale = false; } } else { - _length = niceNum((res * SCALE_WIDTH) / SEGMENTS, 1); + _length = niceNum((res * SCALE_WIDTH) / SEGMENTS, true); if (_length >= KMINM) { _length *= M2KM; _width = (_length / (res * M2KM)); diff --git a/src/GUI/settings.h b/src/GUI/settings.h index e15003bb..780e3b0b 100644 --- a/src/GUI/settings.h +++ b/src/GUI/settings.h @@ -32,6 +32,8 @@ #define SHOW_GRAPH_SLIDER_INFO_DEFAULT true #define SHOW_MARKERS_SETTING "pathMarkers" #define SHOW_MARKERS_DEFAULT true +#define SHOW_TICKS_SETTING "pathTicks" +#define SHOW_TICKS_DEFAULT false #define MAP_SETTINGS_GROUP "Map" #define CURRENT_MAP_SETTING "map" diff --git a/src/GUI/trackitem.cpp b/src/GUI/trackitem.cpp index bda072d6..d24e36db 100644 --- a/src/GUI/trackitem.cpp +++ b/src/GUI/trackitem.cpp @@ -39,5 +39,6 @@ TrackItem::TrackItem(const Track &track, Map *map, QGraphicsItem *parent) void TrackItem::setUnits(Units units) { + PathItem::setUnits(units); setToolTip(toolTip(units)); } diff --git a/src/common/util.cpp b/src/common/util.cpp index 2e235dc4..664f296a 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -17,7 +17,7 @@ int str2int(const char *str, int len) return res; } -double niceNum(double x, int round) +double niceNum(double x, bool round) { int expv; double f; diff --git a/src/common/util.h b/src/common/util.h index f0586100..a42367e5 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -2,6 +2,6 @@ #define UTIL_H int str2int(const char *str, int len); -double niceNum(double x, int round); +double niceNum(double x, bool round); #endif // UTIL_H