From 7de08d116aaf92b8d28ac4703d2911261bbe81ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 28 Jul 2016 00:23:22 +0200 Subject: [PATCH] Fixed track tooltip area handling Added some more waypoint info to waypoint tooltips. Refactoring & optimization. --- gpxsee.pro | 7 ++- lang/gpxsee_cs.ts | 33 +++++----- src/misc.cpp | 10 +++ src/misc.h | 3 + src/parser.cpp | 44 ++++++++----- src/parser.h | 12 ++-- src/poi.cpp | 50 ++++++++++++--- src/poi.h | 11 +++- src/temperaturegraph.cpp | 4 +- src/track.cpp | 23 ++++--- src/track.h | 2 + src/trackitem.cpp | 75 ++++++++++++++++++++++ src/trackitem.h | 32 ++++++++++ src/trackpoint.cpp | 8 +-- src/trackpoint.h | 50 ++++++++++----- src/trackview.cpp | 130 ++++++++++++--------------------------- src/trackview.h | 22 ++----- src/waypoint.cpp | 9 +++ src/waypoint.h | 25 ++++++-- src/waypointitem.cpp | 33 +++++++--- src/waypointitem.h | 7 ++- 21 files changed, 380 insertions(+), 210 deletions(-) create mode 100644 src/trackitem.cpp create mode 100644 src/trackitem.h create mode 100644 src/waypoint.cpp diff --git a/gpxsee.pro b/gpxsee.pro index 02046532..bc923a50 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -45,7 +45,8 @@ HEADERS += src/config.h \ src/margins.h \ src/temperaturegraph.h \ src/graphtab.h \ - src/misc.h + src/misc.h \ + src/trackitem.h SOURCES += src/main.cpp \ src/gui.cpp \ src/gpx.cpp \ @@ -77,7 +78,9 @@ SOURCES += src/main.cpp \ src/fileselectwidget.cpp \ src/temperaturegraph.cpp \ src/trackpoint.cpp \ - src/misc.cpp + src/misc.cpp \ + src/waypoint.cpp \ + src/trackitem.cpp RESOURCES += gpxsee.qrc TRANSLATIONS = lang/gpxsee_cs.ts macx { diff --git a/lang/gpxsee_cs.ts b/lang/gpxsee_cs.ts index 379e3cf3..a1036171 100644 --- a/lang/gpxsee_cs.ts +++ b/lang/gpxsee_cs.ts @@ -564,6 +564,21 @@ m m + + + Date: + Datum: + + + + Distance: + Vzdálenost: + + + + Time: + Čas: + SpeedGraph @@ -678,22 +693,4 @@ F - - TrackView - - - Date: - Datum: - - - - Distance: - Vzdálenost: - - - - Time: - Cas: - - diff --git a/src/misc.cpp b/src/misc.cpp index 18faf995..4672f23d 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -64,3 +64,13 @@ QString distance(qreal value, Units units) + UNIT_SPACE + QObject::tr("km"); } } + +QString coordinates(const QPointF &value) +{ + QChar yH = (value.y() < 0) ? 'S' : 'N'; + QChar xH = (value.x() < 0) ? 'W' : 'E'; + + return QString::number(qAbs(value.y()), 'f', 5) + QChar(0x00B0) + " " + yH + + ", " + QString::number(qAbs(value.x()), 'f', 5) + QChar(0x00B0) + " " + + xH ; +} diff --git a/src/misc.h b/src/misc.h index ac1615f2..79bddae6 100644 --- a/src/misc.h +++ b/src/misc.h @@ -2,10 +2,13 @@ #define MISC_H #include +#include #include "units.h" double niceNum(double x, int round); + QString timeSpan(qreal time); QString distance(qreal value, Units units); +QString coordinates(const QPointF &value); #endif // MISC_H diff --git a/src/parser.cpp b/src/parser.cpp index 63b12e4f..be30fbc7 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1,48 +1,58 @@ #include "parser.h" -void Parser::handleTrackpointData(TrackpointElement element, - const QString &value) +void Parser::handleTrackpointData(DataType type, const QString &value) { - switch (element) { + switch (type) { case Elevation: - _track->last().elevation = value.toLatin1().toDouble(); + _track->last().setElevation(value.toLatin1().toDouble()); break; case Time: - _track->last().timestamp = QDateTime::fromString(value.toLatin1(), - Qt::ISODate); + _track->last().setTimestamp(QDateTime::fromString(value.toLatin1(), + Qt::ISODate)); break; case Geoidheight: - _track->last().geoidheight = value.toLatin1().toDouble(); + _track->last().setGeoidHeight(value.toLatin1().toDouble()); break; case Speed: - _track->last().speed = value.toDouble(); + _track->last().setSpeed(value.toDouble()); break; case HeartRate: - _track->last().heartRate = value.toDouble(); + _track->last().setHeartRate(value.toDouble()); break; case Temperature: - _track->last().temperature = value.toDouble(); + _track->last().setTemperature(value.toDouble()); break; } } -void Parser::handleWaypointData(WaypointElement element, const QString &value) +void Parser::handleWaypointData(DataType type, const QString &value) { - switch (element) { + switch (type) { case Name: _waypoints.last().setName(value); break; case Description: _waypoints.last().setDescription(value); break; + case Time: + _waypoints.last().setTimestamp(QDateTime::fromString( + value.toLatin1(), Qt::ISODate)); + break; + case Elevation: + _waypoints.last().setElevation(value.toLatin1().toDouble()); + break; + case Geoidheight: + _waypoints.last().setGeoidHeight(value.toLatin1().toDouble()); + break; } } void Parser::handleTrackpointAttributes(const QXmlStreamAttributes &attr) { - _track->last().coordinates.setY(attr.value("lat").toLatin1().toDouble()); - _track->last().coordinates.setX(attr.value("lon").toLatin1().toDouble()); + _track->last().setCoordinates(QPointF( + attr.value("lon").toLatin1().toDouble(), + attr.value("lat").toLatin1().toDouble())); } void Parser::handleWaypointAttributes(const QXmlStreamAttributes &attr) @@ -125,6 +135,12 @@ void Parser::waypointData() handleWaypointData(Name, _reader.readElementText()); else if (_reader.name() == "desc") handleWaypointData(Description, _reader.readElementText()); + else if (_reader.name() == "ele") + handleWaypointData(Elevation, _reader.readElementText()); + else if (_reader.name() == "geoidheight") + handleWaypointData(Geoidheight, _reader.readElementText()); + else if (_reader.name() == "time") + handleWaypointData(Time, _reader.readElementText()); else _reader.skipCurrentElement(); } diff --git a/src/parser.h b/src/parser.h index 787a3ca9..cbc5f588 100644 --- a/src/parser.h +++ b/src/parser.h @@ -18,11 +18,9 @@ public: int errorLine() const {return _reader.lineNumber();} private: - enum TrackpointElement { - Elevation, Time, Geoidheight, Speed, HeartRate, Temperature - }; - enum WaypointElement { - Name, Description + enum DataType { + Name, Description, Elevation, Time, Geoidheight, Speed, HeartRate, + Temperature }; bool parse(); @@ -35,9 +33,9 @@ private: void waypointData(); void handleWaypointAttributes(const QXmlStreamAttributes &attr); - void handleWaypointData(WaypointElement element, const QString &value); + void handleWaypointData(DataType type, const QString &value); void handleTrackpointAttributes(const QXmlStreamAttributes &attr); - void handleTrackpointData(TrackpointElement element, const QString &value); + void handleTrackpointData(DataType type, const QString &value); QXmlStreamReader _reader; QList > &_tracks; diff --git a/src/poi.cpp b/src/poi.cpp index f017d3e8..361b05c6 100644 --- a/src/poi.cpp +++ b/src/poi.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include "waypointitem.h" #include "ll.h" #include "gpx.h" #include "poi.h" @@ -50,10 +52,10 @@ bool POI::loadGPXFile(const QString &fileName) index.end = _data.size() - 1; for (int i = index.start; i <= index.end; i++) { - const QPointF &p = _data.at(i).coordinates(); + QPointF p = ll2mercator(_data.at(i).coordinates()); qreal c[2]; c[0] = p.x(); - c[1] = p.y(); + c[1] = -p.y(); _tree.Insert(c, c, i); } @@ -105,24 +107,27 @@ bool POI::loadCSVFile(const QString &fileName) _errorLine = ln; return false; } + Waypoint wp(QPointF(lon, lat)); + QByteArray ba = list[2].trimmed(); QString name = QString::fromUtf8(ba.data(), ba.size()); - QString description; + wp.setName(name); + if (list.size() > 3) { ba = list[3].trimmed(); - description = QString::fromUtf8(ba.data(), ba.size()); + wp.setDescription(QString::fromUtf8(ba.data(), ba.size())); } - _data.append(Waypoint(QPointF(lon, lat), name, description)); + _data.append(wp); ln++; } index.end = _data.size() - 1; for (int i = index.start; i <= index.end; i++) { - const QPointF &p = _data.at(i).coordinates(); + QPointF p = ll2mercator(_data.at(i).coordinates()); qreal c[2]; c[0] = p.x(); - c[1] = p.y(); + c[1] = -p.y(); _tree.Insert(c, c, i); } @@ -140,14 +145,39 @@ static bool cb(size_t data, void* context) return true; } -QVector POI::points(const QVector &path, qreal radius) const +QVector POI::points(const QPainterPath &path, qreal radius) const { QVector ret; QSet set; qreal min[2], max[2]; - for (int i = 0; i < path.count(); i++) { - const QPointF &p = path.at(i); + for (int i = 0; i < path.elementCount(); i++) { + const QPointF &p = path.elementAt(i); + min[0] = p.x() - radius; + min[1] = p.y() - radius; + max[0] = p.x() + radius; + max[1] = p.y() + radius; + _tree.Search(min, max, cb, &set); + } + + QSet::const_iterator i = set.constBegin(); + while (i != set.constEnd()) { + ret.append(_data.at(*i)); + ++i; + } + + return ret; +} + +QVector POI::points(const QList &list, qreal radius) + const +{ + QVector ret; + QSet set; + qreal min[2], max[2]; + + for (int i = 0; i < list.count(); i++) { + const QPointF &p = list.at(i)->coordinates(); min[0] = p.x() - radius; min[1] = p.y() - radius; max[0] = p.x() + radius; diff --git a/src/poi.h b/src/poi.h index 975f0a88..c1f56656 100644 --- a/src/poi.h +++ b/src/poi.h @@ -8,6 +8,10 @@ #include "waypoint.h" #include "rtree.h" +class QPainterPath; +class WaypointItem; + +#define POI_RADIUS 0.01 class POI { @@ -17,8 +21,11 @@ public: const QString &errorString() const {return _error;} int errorLine() const {return _errorLine;} - QVector points(const QVector &path, - qreal radius = 0.01) const; + QVector points(const QPainterPath &path, + qreal radius = POI_RADIUS) const; + QVector points(const QList &list, + qreal radius = POI_RADIUS) const; + const QStringList &files() const {return _files;} void enableFile(const QString &fileName, bool enable); void clear(); diff --git a/src/temperaturegraph.cpp b/src/temperaturegraph.cpp index c9e65be8..3c894cab 100644 --- a/src/temperaturegraph.cpp +++ b/src/temperaturegraph.cpp @@ -94,11 +94,11 @@ void TemperatureGraph::setXUnits() void TemperatureGraph::setYUnits() { if (_units == Metric) { - GraphView::setYUnits(QString::fromUtf8("\xC2\xB0") + tr("C")); + GraphView::setYUnits(QChar(0x00B0) + tr("C")); setYScale(1); setYOffset(0); } else { - GraphView::setYUnits(QString::fromUtf8("\xC2\xB0") + tr("F")); + GraphView::setYUnits(QChar(0x00B0) + tr("F")); setYScale(C2FS); setYOffset(C2FO); } diff --git a/src/track.cpp b/src/track.cpp index b1902820..7fb6cb8c 100644 --- a/src/track.cpp +++ b/src/track.cpp @@ -85,7 +85,8 @@ Track::Track(const QVector &data) : _data(data) _dd.append(dist); for (int i = 1; i < _data.count(); i++) { - dist += llDistance(_data.at(i).coordinates, _data.at(i-1).coordinates); + dist += llDistance(_data.at(i).coordinates(), + _data.at(i-1).coordinates()); _dd.append(dist); } } @@ -99,8 +100,8 @@ void Track::elevationGraph(QVector &graph) const for (int i = 0; i < _data.size(); i++) if (_data.at(i).hasElevation()) - raw.append(QPointF(_dd.at(i), _data.at(i).elevation - - _data.at(i).geoidheight)); + raw.append(QPointF(_dd.at(i), _data.at(i).elevation() + - _data.at(i).geoidHeight())); graph = filter(raw, WINDOW_EF); } @@ -117,9 +118,10 @@ void Track::speedGraph(QVector &graph) const raw.append(QPointF(0, 0)); for (int i = 1; i < _data.size(); i++) { if (_data.at(i).hasSpeed()) - v = _data.at(i).speed; + v = _data.at(i).speed(); else if (_data.at(i).hasTimestamp()) { - if (!(dt = _data.at(i-1).timestamp.msecsTo(_data.at(i).timestamp))) + dt = _data.at(i-1).timestamp().msecsTo(_data.at(i).timestamp()); + if (!dt) continue; ds = _dd.at(i) - _dd.at(i-1); v = ds / ((qreal)dt / 1000.0); @@ -141,7 +143,7 @@ void Track::heartRateGraph(QVector &graph) const for (int i = 0; i < _data.count(); i++) if (_data.at(i).hasHeartRate()) - raw.append(QPointF(_dd.at(i), _data.at(i).heartRate)); + raw.append(QPointF(_dd.at(i), _data.at(i).heartRate())); graph = filter(eliminate(raw, WINDOW_HE), WINDOW_HF); } @@ -153,13 +155,13 @@ void Track::temperatureGraph(QVector &graph) const for (int i = 0; i < _data.size(); i++) if (_data.at(i).hasTemperature()) - graph.append(QPointF(_dd.at(i), _data.at(i).temperature)); + graph.append(QPointF(_dd.at(i), _data.at(i).temperature())); } void Track::track(QVector &track) const { for (int i = 0; i < _data.size(); i++) - track.append(_data.at(i).coordinates); + track.append(_data.at(i).coordinates()); } qreal Track::time() const @@ -167,13 +169,14 @@ qreal Track::time() const if (_data.size() < 2) return 0; - return (_data.first().timestamp.msecsTo(_data.last().timestamp) / 1000.0); + return (_data.first().timestamp().msecsTo(_data.last().timestamp()) + / 1000.0); } QDateTime Track::date() const { if (_data.size()) - return _data.first().timestamp; + return _data.first().timestamp(); else return QDateTime(); } diff --git a/src/track.h b/src/track.h index 400795f8..b8d09f18 100644 --- a/src/track.h +++ b/src/track.h @@ -19,6 +19,8 @@ public: qreal time() const; QDateTime date() const; + bool isNull() const {return (_data.count() < 2) ? true : false;} + private: const QVector &_data; QVector _dd; diff --git a/src/trackitem.cpp b/src/trackitem.cpp new file mode 100644 index 00000000..0ca7ae66 --- /dev/null +++ b/src/trackitem.cpp @@ -0,0 +1,75 @@ +#include +#include +#include "ll.h" +#include "misc.h" +#include "trackitem.h" + + +#define TRACK_WIDTH 3 + +QString TrackItem::toolTip() +{ + QString date = _date.date().toString(Qt::SystemLocaleShortDate); + + return "" + QObject::tr("Date:") + " " + date + "
" + + QObject::tr("Distance:") + " " + distance(_distance, _units) + + "
" + QObject::tr("Time:") + " " + timeSpan(_time); +} + +void TrackItem::updateShape() +{ + QPainterPathStroker s; + s.setWidth(TRACK_WIDTH * 1.0/scale()); + _shape = s.createStroke(path().simplified()); +} + +TrackItem::TrackItem(const Track &track) +{ + QVector t; + QPainterPath path; + + track.track(t); + Q_ASSERT(t.count() >= 2); + + const QPointF &p = t.at(0); + path.moveTo(ll2mercator(QPointF(p.x(), -p.y()))); + for (int i = 1; i < t.size(); i++) { + const QPointF &p = t.at(i); + path.lineTo(ll2mercator(QPointF(p.x(), -p.y()))); + } + + _units = Metric; + _date = track.date(); + _distance = track.distance(); + _time = track.time(); + + setPath(path); + setToolTip(toolTip()); + setCursor(Qt::ArrowCursor); + + updateShape(); + + QBrush brush(Qt::SolidPattern); + QPen pen(brush, TRACK_WIDTH); + pen.setCosmetic(true); + setPen(pen); +} + +void TrackItem::setScale(qreal scale) +{ + QGraphicsPathItem::setScale(scale); + updateShape(); +} + +void TrackItem::setColor(const QColor &color) +{ + QPen p(pen()); + p.setColor(color); + setPen(p); +} + +void TrackItem::setUnits(enum Units units) +{ + _units = units; + setToolTip(toolTip()); +} diff --git a/src/trackitem.h b/src/trackitem.h new file mode 100644 index 00000000..7ed11ae6 --- /dev/null +++ b/src/trackitem.h @@ -0,0 +1,32 @@ +#ifndef TRACKITEM_H +#define TRACKITEM_H + +#include +#include +#include "units.h" +#include "track.h" + +class TrackItem : public QGraphicsPathItem +{ +public: + TrackItem(const Track &track); + + QPainterPath shape() const {return _shape;} + void setScale(qreal scale); + + void setUnits(enum Units units); + void setColor(const QColor &color); + +private: + void updateShape(); + QString toolTip(); + + QPainterPath _shape; + + Units _units; + QDateTime _date; + qreal _time; + qreal _distance; +}; + +#endif // TRACKITEM_H diff --git a/src/trackpoint.cpp b/src/trackpoint.cpp index b6ef4207..6ce0fab2 100644 --- a/src/trackpoint.cpp +++ b/src/trackpoint.cpp @@ -2,10 +2,10 @@ QDebug operator<<(QDebug dbg, const Trackpoint &trackpoint) { - dbg.nospace() << "Trackpoint(" << trackpoint.coordinates << ", " - << trackpoint.timestamp << ", " << trackpoint.elevation << ", " - << trackpoint.geoidheight << ", " << trackpoint.speed << ", " - << trackpoint.heartRate << ", " << trackpoint.temperature << ")"; + dbg.nospace() << "Trackpoint(" << trackpoint.coordinates() << ", " + << trackpoint.timestamp() << ", " << trackpoint.elevation() << ", " + << trackpoint.geoidHeight() << ", " << trackpoint.speed() << ", " + << trackpoint.heartRate() << ", " << trackpoint.temperature() << ")"; return dbg.maybeSpace(); } diff --git a/src/trackpoint.h b/src/trackpoint.h index c2601da9..909bb5de 100644 --- a/src/trackpoint.h +++ b/src/trackpoint.h @@ -10,26 +10,42 @@ class Trackpoint { public: Trackpoint() { - elevation = NAN; - geoidheight = 0; - speed = NAN; - heartRate = NAN; - temperature = NAN; + _elevation = NAN; _geoidHeight = 0; _speed = NAN; _heartRate = NAN; + _temperature = NAN; } + Trackpoint(const QPointF &coordinates) {_coordinates = coordinates;} - bool hasTimestamp() const {return !timestamp.isNull();} - bool hasElevation() const {return !std::isnan(elevation);} - bool hasSpeed() const {return !std::isnan(speed);} - bool hasHeartRate() const {return !std::isnan(heartRate);} - bool hasTemperature() const {return !std::isnan(temperature);} + const QPointF &coordinates() const {return _coordinates;} + const QDateTime ×tamp() const {return _timestamp;} + qreal elevation() const {return _elevation;} + qreal geoidHeight() const {return _geoidHeight;} + qreal speed() const {return _speed;} + qreal heartRate() const {return _heartRate;} + qreal temperature() const {return _temperature;} - QPointF coordinates; - QDateTime timestamp; - qreal elevation; - qreal geoidheight; - qreal speed; - qreal heartRate; - qreal temperature; + void setCoordinates(const QPointF &coordinates) + {_coordinates = coordinates;} + void setTimestamp(const QDateTime ×tamp) {_timestamp = timestamp;} + void setElevation(qreal elevation) {_elevation = elevation;} + void setGeoidHeight(qreal geoidHeight) {_geoidHeight = geoidHeight;} + void setSpeed(qreal speed) {_speed = speed;} + void setHeartRate(qreal heartRate) {_heartRate = heartRate;} + void setTemperature(qreal temperature) {_temperature = temperature;} + + bool hasTimestamp() const {return !_timestamp.isNull();} + bool hasElevation() const {return !std::isnan(_elevation);} + bool hasSpeed() const {return !std::isnan(_speed);} + bool hasHeartRate() const {return !std::isnan(_heartRate);} + bool hasTemperature() const {return !std::isnan(_temperature);} + +private: + QPointF _coordinates; + QDateTime _timestamp; + qreal _elevation; + qreal _geoidHeight; + qreal _speed; + qreal _heartRate; + qreal _temperature; }; QDebug operator<<(QDebug dbg, const Trackpoint &trackpoint); diff --git a/src/trackview.cpp b/src/trackview.cpp index 9176e254..7f870c5f 100644 --- a/src/trackview.cpp +++ b/src/trackview.cpp @@ -2,19 +2,18 @@ #include #include #include +#include "ll.h" #include "poi.h" #include "gpx.h" #include "map.h" +#include "trackitem.h" #include "waypointitem.h" #include "markeritem.h" #include "scaleitem.h" -#include "ll.h" -#include "misc.h" #include "trackview.h" #define MARGIN 10.0 -#define TRACK_WIDTH 3 #define SCALE_OFFSET 7 TrackView::TrackView(QWidget *parent) @@ -48,71 +47,41 @@ TrackView::~TrackView() delete _mapScale; } -QString TrackView::toolTip(const TrackInfo &info) +void TrackView::addTrack(const Track &track) { - QString date = info.date.date().toString(Qt::SystemLocaleShortDate); - - return "" + tr("Date:") + " " + date + "
" + tr("Distance:") - + " " + distance(info.distance, _units) + "
" + tr("Time:") - + " " + timeSpan(info.time); -} - -void TrackView::addTrack(const QVector &track, const TrackInfo &info) -{ - QPainterPath path; - QGraphicsPathItem *pi; - MarkerItem *mi; - - - if (track.size() < 2) { + if (track.isNull()) { _palette.color(); return; } - _tracks.append(track); - - const QPointF &p = track.at(0); - path.moveTo(ll2mercator(QPointF(p.x(), -p.y()))); - for (int i = 1; i < track.size(); i++) { - const QPointF &p = track.at(i); - path.lineTo(ll2mercator(QPointF(p.x(), -p.y()))); - } - - _maxPath = qMax(path.length(), _maxPath); - - pi = new QGraphicsPathItem(path); + TrackItem *pi = new TrackItem(track); _paths.append(pi); - _info.append(info); _zoom = qMin(_zoom, scale2zoom(trackScale())); _scale = mapScale(_zoom); - QBrush brush(_palette.color(), Qt::SolidPattern); - QPen pen(brush, TRACK_WIDTH * _scale); - pi->setPen(pen); pi->setScale(1.0/_scale); - pi->setToolTip(toolTip(info)); - pi->setCursor(Qt::ArrowCursor); + pi->setColor(_palette.color()); _scene->addItem(pi); - mi = new MarkerItem(pi); + MarkerItem *mi = new MarkerItem(pi); _markers.append(mi); mi->setPos(pi->path().pointAtPercent(0)); mi->setScale(_scale); + + _maxPath = qMax(pi->path().length(), _maxPath); + _maxDistance = qMax(track.distance(), _maxDistance); } void TrackView::addWaypoints(const QList &waypoints) { for (int i = 0; i < waypoints.count(); i++) { const Waypoint &w = waypoints.at(i); - WaypointItem *wi = new WaypointItem( - Waypoint(ll2mercator(QPointF(w.coordinates().x(), - -w.coordinates().y())), w.name(), w.description())); - wi->setPos(wi->entry().coordinates() * 1.0/_scale); + WaypointItem *wi = new WaypointItem(w); + wi->setPos(wi->coordinates() * 1.0/_scale); wi->setZValue(1); _scene->addItem(wi); - _locations.append(wi); - _waypoints.append(w.coordinates()); + _waypoints.append(wi); } _zoom = qMin(_zoom, scale2zoom(waypointScale())); @@ -123,22 +92,15 @@ void TrackView::loadGPX(const GPX &gpx) { int zoom = _zoom; - for (int i = 0; i < gpx.trackCount(); i++) { - QVector track; - TrackInfo info = {gpx.track(i).date(), gpx.track(i).distance(), - gpx.track(i).time()}; - gpx.track(i).track(track); - addTrack(track, info); - _maxDistance = qMax(gpx.track(i).distance(), _maxDistance); - } - + for (int i = 0; i < gpx.trackCount(); i++) + addTrack(gpx.track(i)); addWaypoints(gpx.waypoints()); - if (_paths.empty() && _locations.empty()) + if (_paths.empty() && _waypoints.empty()) return; if ((_paths.size() > 1 && _zoom < zoom) - || (_locations.size() && _zoom < zoom)) + || (_waypoints.size() && _zoom < zoom)) rescale(_scale); QRectF br = trackBoundingRect() | waypointBoundingRect(); @@ -168,17 +130,17 @@ QRectF TrackView::waypointBoundingRect() const { qreal bottom, top, left, right; - if (_locations.empty()) + if (_waypoints.empty()) return QRectF(); - const QPointF &p = _locations.at(0)->pos(); + const QPointF &p = _waypoints.at(0)->pos(); bottom = p.y(); top = p.y(); left = p.x(); right = p.x(); - for (int i = 1; i < _locations.size(); i++) { - const QPointF &p = _locations.at(i)->pos(); + for (int i = 1; i < _waypoints.size(); i++) { + const QPointF &p = _waypoints.at(i)->pos(); bottom = qMax(bottom, p.y()); top = qMin(top, p.y()); right = qMax(right, p.x()); @@ -208,17 +170,17 @@ qreal TrackView::waypointScale() const { qreal bottom, top, left, right; - if (_locations.size() < 2) + if (_waypoints.size() < 2) return mapScale(ZOOM_MAX); - const QPointF &p = _locations.at(0)->entry().coordinates(); + const QPointF &p = _waypoints.at(0)->coordinates(); bottom = p.y(); top = p.y(); left = p.x(); right = p.x(); - for (int i = 1; i < _locations.size(); i++) { - const QPointF &p = _locations.at(i)->entry().coordinates(); + for (int i = 1; i < _waypoints.size(); i++) { + const QPointF &p = _waypoints.at(i)->coordinates(); bottom = qMax(bottom, p.y()); top = qMin(top, p.y()); right = qMax(right, p.x()); @@ -242,19 +204,14 @@ void TrackView::rescale(qreal scale) for (int i = 0; i < _paths.size(); i++) { _markers.at(i)->setScale(scale); _paths.at(i)->setScale(1.0/scale); - - QPen pen(_paths.at(i)->pen()); - pen.setWidthF(TRACK_WIDTH * scale); - _paths.at(i)->setPen(pen); } - for (int i = 0; i < _locations.size(); i++) - _locations.at(i)->setPos(_locations.at(i)->entry().coordinates() - * 1.0/scale); + for (int i = 0; i < _waypoints.size(); i++) + _waypoints.at(i)->setPos(_waypoints.at(i)->coordinates() * 1.0/scale); QHash::const_iterator it, jt; for (it = _pois.constBegin(); it != _pois.constEnd(); it++) { - it.value()->setPos(it.value()->entry().coordinates() * 1.0/scale); + it.value()->setPos(it.value()->coordinates() * 1.0/scale); it.value()->show(); } @@ -277,11 +234,8 @@ void TrackView::addPOI(const QVector &waypoints) if (_pois.contains(w)) continue; - WaypointItem *pi = new WaypointItem( - Waypoint(ll2mercator(QPointF(w.coordinates().x(), - -w.coordinates().y())), w.name(), w.description())); - - pi->setPos(pi->entry().coordinates() * 1.0/_scale); + WaypointItem *pi = new WaypointItem(w); + pi->setPos(pi->coordinates() * 1.0/_scale); pi->setZValue(1); _scene->addItem(pi); @@ -293,11 +247,11 @@ void TrackView::loadPOI(const POI &poi) { QHash::const_iterator it,jt; - if (!_tracks.size() && !_waypoints.size()) + if (!_paths.size() && !_waypoints.size()) return; - for (int i = 0; i < _tracks.size(); i++) - addPOI(poi.points(_tracks.at(i))); + for (int i = 0; i < _paths.size(); i++) + addPOI(poi.points(_paths.at(i)->path())); addPOI(poi.points(_waypoints)); for (it = _pois.constBegin(); it != _pois.constEnd(); it++) { @@ -324,8 +278,8 @@ void TrackView::setUnits(enum Units units) _mapScale->setUnits(units); - for (int i = 0; i < _info.count(); i++) - _paths[i]->setToolTip(toolTip(_info.at(i))); + for (int i = 0; i < _paths.count(); i++) + _paths[i]->setUnits(units); } void TrackView::redraw() @@ -342,7 +296,7 @@ void TrackView::rescale() void TrackView::zoom(int z, const QPointF &pos) { - if (_paths.isEmpty() && _locations.isEmpty()) + if (_paths.isEmpty() && _waypoints.isEmpty()) return; qreal scale = _scale; @@ -366,7 +320,7 @@ void TrackView::zoom(int z, const QPointF &pos) void TrackView::wheelEvent(QWheelEvent *event) { - if (_paths.isEmpty() && _locations.isEmpty()) + if (_paths.isEmpty() && _waypoints.isEmpty()) return; QPointF pos = mapToScene(event->pos()); @@ -444,15 +398,11 @@ void TrackView::clear() _pois.clear(); _paths.clear(); - _info.clear(); - _locations.clear(); + _waypoints.clear(); _markers.clear(); _scene->clear(); _palette.reset(); - _tracks.clear(); - _waypoints.clear(); - _maxPath = 0; _maxDistance = 0; _zoom = ZOOM_MAX; @@ -479,7 +429,7 @@ void TrackView::movePositionMarker(qreal val) void TrackView::drawBackground(QPainter *painter, const QRectF &rect) { - if ((_paths.isEmpty() && _locations.isEmpty()) || !_map) { + if ((_paths.isEmpty() && _waypoints.isEmpty()) || !_map) { painter->fillRect(rect, Qt::white); return; } @@ -510,7 +460,7 @@ void TrackView::drawBackground(QPainter *painter, const QRectF &rect) void TrackView::resizeEvent(QResizeEvent *e) { - if (_paths.isEmpty() && _locations.isEmpty()) + if (_paths.isEmpty() && _waypoints.isEmpty()) return; rescale(); diff --git a/src/trackview.h b/src/trackview.h index 32d6bb75..29d75d56 100644 --- a/src/trackview.h +++ b/src/trackview.h @@ -5,7 +5,6 @@ #include #include #include -#include #include "units.h" #include "palette.h" #include "waypoint.h" @@ -13,6 +12,8 @@ class GPX; class POI; class Map; +class Track; +class TrackItem; class WaypointItem; class MarkerItem; class ScaleItem; @@ -37,25 +38,17 @@ public: void plot(QPainter *painter, const QRectF &target); int trackCount() const {return _paths.count();} - int waypointCount() const {return _locations.count();} + int waypointCount() const {return _waypoints.count();} public slots: void movePositionMarker(qreal val); void redraw(); private: - struct TrackInfo { - QDateTime date; - qreal distance; - qreal time; - }; - - void addTrack(const QVector &track, const TrackInfo &info); + void addTrack(const Track &track); void addWaypoints(const QList &waypoints); void addPOI(const QVector &waypoints); - QString toolTip(const TrackInfo &info); - QRectF trackBoundingRect() const; QRectF waypointBoundingRect() const; qreal trackScale() const; @@ -72,13 +65,10 @@ private: void paintEvent(QPaintEvent *e); QGraphicsScene *_scene; - QList _paths; - QList _info; + QList _paths; QList _markers; - QList _locations; + QList _waypoints; QHash _pois; - QList > _tracks; - QVector _waypoints; Map *_map; ScaleItem *_mapScale; diff --git a/src/waypoint.cpp b/src/waypoint.cpp new file mode 100644 index 00000000..17480d0d --- /dev/null +++ b/src/waypoint.cpp @@ -0,0 +1,9 @@ +#include "waypoint.h" + +QDebug operator<<(QDebug dbg, const Waypoint &waypoint) +{ + dbg.nospace() << "Waypoint(" << waypoint.coordinates() << ", " + << waypoint.name() << ", " << waypoint.description() << ")"; + + return dbg.maybeSpace(); +} diff --git a/src/waypoint.h b/src/waypoint.h index 9272be1e..cae61c69 100644 --- a/src/waypoint.h +++ b/src/waypoint.h @@ -3,25 +3,33 @@ #include #include +#include #include +#include +#include class Waypoint { public: - Waypoint() {} - Waypoint(const QPointF &coordinates, const QString &name, - const QString &description) - : _coordinates(coordinates), _name(name), _description(description) {} + Waypoint() {_elevation = NAN; _geoidHeight = 0;} + Waypoint(const QPointF &coordinates) + : _coordinates(coordinates) {_elevation = NAN; _geoidHeight = 0;} const QPointF &coordinates() const {return _coordinates;} const QString &name() const {return _name;} const QString &description() const {return _description;} + const QDateTime ×tamp() const {return _timestamp;} + qreal elevation() const {return _elevation;} + qreal geoidHeight() const {return _geoidHeight;} + void setCoordinates(const QPointF &coordinates) {_coordinates = coordinates;} - void setName(const QString &name) - {_name = name;} + void setName(const QString &name) {_name = name;} void setDescription(const QString &description) {_description = description;} + void setTimestamp(const QDateTime ×tamp) {_timestamp = timestamp;} + void setElevation(qreal elevation) {_elevation = elevation;} + void setGeoidHeight(qreal geoidHeight) {_geoidHeight = geoidHeight;} bool operator==(const Waypoint &other) const {return this->_name == other._name @@ -31,6 +39,9 @@ private: QPointF _coordinates; QString _name; QString _description; + QDateTime _timestamp; + qreal _elevation; + qreal _geoidHeight; }; inline uint qHash(const Waypoint &key) @@ -38,4 +49,6 @@ inline uint qHash(const Waypoint &key) return ::qHash(key.name()); } +QDebug operator<<(QDebug dbg, const Waypoint &Waypoint); + #endif // WAYPOINT_H diff --git a/src/waypointitem.cpp b/src/waypointitem.cpp index 5978fa61..4885081d 100644 --- a/src/waypointitem.cpp +++ b/src/waypointitem.cpp @@ -1,20 +1,35 @@ #include #include "config.h" +#include "ll.h" +#include "misc.h" #include "waypointitem.h" #define POINT_SIZE 8 -WaypointItem::WaypointItem(const Waypoint &entry, QGraphicsItem *parent) +static QString tt(const Waypoint &waypoint) +{ + QString date = waypoint.timestamp().toString(Qt::SystemLocaleShortDate); + + return "" + QObject::tr("Coordinates:") + " " + + coordinates(waypoint.coordinates()) + "
" + + QObject::tr("Description:") + " " + waypoint.description() + + "
" + QObject::tr("Elevation:") + " " + + QString::number(waypoint.elevation() - waypoint.geoidHeight()) + + "
" + QObject::tr("Date:") + " " + date; +} + +WaypointItem::WaypointItem(const Waypoint &waypoint, QGraphicsItem *parent) : QGraphicsItem(parent) { - _entry = entry; + _label = waypoint.name(); + _coordinates = ll2mercator(QPointF(waypoint.coordinates().x(), + -waypoint.coordinates().y())); + updateBoundingRect(); - if (!entry.description().isEmpty()) { - setToolTip(entry.description()); - setCursor(Qt::ArrowCursor); - } + setToolTip(tt(waypoint)); + setCursor(Qt::ArrowCursor); } void WaypointItem::updateBoundingRect() @@ -23,7 +38,7 @@ void WaypointItem::updateBoundingRect() font.setPixelSize(FONT_SIZE); font.setFamily(FONT_FAMILY); QFontMetrics fm(font); - QRect ts = fm.tightBoundingRect(_entry.name()); + QRect ts = fm.tightBoundingRect(_label); _boundingRect = QRectF(-POINT_SIZE/2, -POINT_SIZE/2, ts.width() + POINT_SIZE, ts.height() + fm.descent() + POINT_SIZE); @@ -38,11 +53,11 @@ void WaypointItem::paint(QPainter *painter, font.setPixelSize(FONT_SIZE); font.setFamily(FONT_FAMILY); QFontMetrics fm(font); - QRect ts = fm.tightBoundingRect(_entry.name()); + QRect ts = fm.tightBoundingRect(_label); painter->setFont(font); painter->drawText(POINT_SIZE/2 - qMax(ts.x(), 0), POINT_SIZE/2 + ts.height(), - _entry.name()); + _label); painter->setBrush(Qt::SolidPattern); painter->drawEllipse(-POINT_SIZE/2, -POINT_SIZE/2, POINT_SIZE, POINT_SIZE); diff --git a/src/waypointitem.h b/src/waypointitem.h index 6d5de713..aa817c63 100644 --- a/src/waypointitem.h +++ b/src/waypointitem.h @@ -7,8 +7,8 @@ class WaypointItem : public QGraphicsItem { public: - WaypointItem(const Waypoint &entry, QGraphicsItem *parent = 0); - const Waypoint &entry() const {return _entry;} + WaypointItem(const Waypoint &waypoint, QGraphicsItem *parent = 0); + const QPointF &coordinates() {return _coordinates;} QRectF boundingRect() const {return _boundingRect;} void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, @@ -17,7 +17,8 @@ public: private: void updateBoundingRect(); - Waypoint _entry; + QString _label; + QPointF _coordinates; QRectF _boundingRect; };