1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-27 21:24:47 +01:00

Fixed track tooltip area handling

Added some more waypoint info to waypoint tooltips.
Refactoring & optimization.
This commit is contained in:
Martin Tůma 2016-07-28 00:23:22 +02:00
parent dac06b9537
commit 7de08d116a
21 changed files with 380 additions and 210 deletions

View File

@ -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 {

View File

@ -564,6 +564,21 @@
<source>m</source>
<translation>m</translation>
</message>
<message>
<location filename="../src/trackitem.cpp" line="14"/>
<source>Date:</source>
<translation>Datum:</translation>
</message>
<message>
<location filename="../src/trackitem.cpp" line="15"/>
<source>Distance:</source>
<translation>Vzdálenost:</translation>
</message>
<message>
<location filename="../src/trackitem.cpp" line="16"/>
<source>Time:</source>
<translation>Čas:</translation>
</message>
</context>
<context>
<name>SpeedGraph</name>
@ -678,22 +693,4 @@
<translation>F</translation>
</message>
</context>
<context>
<name>TrackView</name>
<message>
<location filename="../src/trackview.cpp" line="55"/>
<source>Date:</source>
<translation>Datum:</translation>
</message>
<message>
<location filename="../src/trackview.cpp" line="55"/>
<source>Distance:</source>
<translation>Vzdálenost:</translation>
</message>
<message>
<location filename="../src/trackview.cpp" line="56"/>
<source>Time:</source>
<translation>Cas:</translation>
</message>
</context>
</TS>

View File

@ -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 ;
}

View File

@ -2,10 +2,13 @@
#define MISC_H
#include <QString>
#include <QPoint>
#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

View File

@ -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();
}

View File

@ -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<QVector<Trackpoint> > &_tracks;

View File

@ -1,6 +1,8 @@
#include <QFile>
#include <QSet>
#include <QList>
#include <QPainterPath>
#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<Waypoint> POI::points(const QVector<QPointF> &path, qreal radius) const
QVector<Waypoint> POI::points(const QPainterPath &path, qreal radius) const
{
QVector<Waypoint> ret;
QSet<int> 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<int>::const_iterator i = set.constBegin();
while (i != set.constEnd()) {
ret.append(_data.at(*i));
++i;
}
return ret;
}
QVector<Waypoint> POI::points(const QList<WaypointItem*> &list, qreal radius)
const
{
QVector<Waypoint> ret;
QSet<int> 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;

View File

@ -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<Waypoint> points(const QVector<QPointF> &path,
qreal radius = 0.01) const;
QVector<Waypoint> points(const QPainterPath &path,
qreal radius = POI_RADIUS) const;
QVector<Waypoint> points(const QList<WaypointItem*> &list,
qreal radius = POI_RADIUS) const;
const QStringList &files() const {return _files;}
void enableFile(const QString &fileName, bool enable);
void clear();

View File

@ -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);
}

View File

@ -85,7 +85,8 @@ Track::Track(const QVector<Trackpoint> &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<QPointF> &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<QPointF> &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<QPointF> &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<QPointF> &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<QPointF> &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();
}

View File

@ -19,6 +19,8 @@ public:
qreal time() const;
QDateTime date() const;
bool isNull() const {return (_data.count() < 2) ? true : false;}
private:
const QVector<Trackpoint> &_data;
QVector<qreal> _dd;

75
src/trackitem.cpp Normal file
View File

@ -0,0 +1,75 @@
#include <QCursor>
#include <QPen>
#include "ll.h"
#include "misc.h"
#include "trackitem.h"
#define TRACK_WIDTH 3
QString TrackItem::toolTip()
{
QString date = _date.date().toString(Qt::SystemLocaleShortDate);
return "<b>" + QObject::tr("Date:") + "</b> " + date + "<br><b>"
+ QObject::tr("Distance:") + "</b> " + distance(_distance, _units)
+ "<br><b>" + QObject::tr("Time:") + "</b> " + 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<QPointF> 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());
}

32
src/trackitem.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef TRACKITEM_H
#define TRACKITEM_H
#include <QGraphicsPathItem>
#include <QDateTime>
#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

View File

@ -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();
}

View File

@ -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 &timestamp() 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 &timestamp) {_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);

View File

@ -2,19 +2,18 @@
#include <QGraphicsScene>
#include <QPainterPath>
#include <QWheelEvent>
#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 "<b>" + tr("Date:") + "</b> " + date + "<br><b>" + tr("Distance:")
+ "</b> " + distance(info.distance, _units) + "<br><b>" + tr("Time:")
+ "</b> " + timeSpan(info.time);
}
void TrackView::addTrack(const QVector<QPointF> &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<Waypoint> &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<QPointF> 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<Waypoint, WaypointItem*>::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<Waypoint> &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<Waypoint, WaypointItem*>::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();

View File

@ -5,7 +5,6 @@
#include <QVector>
#include <QHash>
#include <QList>
#include <QDateTime>
#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<QPointF> &track, const TrackInfo &info);
void addTrack(const Track &track);
void addWaypoints(const QList<Waypoint> &waypoints);
void addPOI(const QVector<Waypoint> &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<QGraphicsPathItem*> _paths;
QList<TrackInfo> _info;
QList<TrackItem*> _paths;
QList<MarkerItem*> _markers;
QList<WaypointItem*> _locations;
QList<WaypointItem*> _waypoints;
QHash<Waypoint, WaypointItem*> _pois;
QList<QVector<QPointF> > _tracks;
QVector<QPointF> _waypoints;
Map *_map;
ScaleItem *_mapScale;

9
src/waypoint.cpp Normal file
View File

@ -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();
}

View File

@ -3,25 +3,33 @@
#include <QPointF>
#include <QString>
#include <QDateTime>
#include <QHash>
#include <QDebug>
#include <cmath>
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 &timestamp() 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 &timestamp) {_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

View File

@ -1,21 +1,36 @@
#include <QPainter>
#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 "<b>" + QObject::tr("Coordinates:") + "</b> "
+ coordinates(waypoint.coordinates()) + "<br><b>"
+ QObject::tr("Description:") + "</b> " + waypoint.description()
+ "<br><b>" + QObject::tr("Elevation:") + "</b> "
+ QString::number(waypoint.elevation() - waypoint.geoidHeight())
+ "<br><b>" + QObject::tr("Date:") + "</b> " + 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());
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);

View File

@ -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;
};