1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-24 03:35:53 +01:00

Added support for "data defined" styles

This commit is contained in:
Martin Tůma 2022-09-23 02:34:18 +02:00
parent e8e1e98775
commit a8299050c5
27 changed files with 475 additions and 130 deletions

View File

@ -114,6 +114,7 @@ HEADERS += src/common/config.h \
src/GUI/pngexportdialog.h \
src/GUI/timezoneinfo.h \
src/GUI/passwordedit.h \
src/data/style.h \
src/data/twonavparser.h \
src/map/IMG/section.h \
src/map/gemfmap.h \

View File

@ -28,10 +28,17 @@ AreaItem::AreaItem(const Area &area, Map *map, GraphicsItem *parent)
_map = map;
_digitalZoom = 0;
if (_area.style().isValid()) {
_width = (_area.style().pen().style() == Qt::NoPen)
? 0 : _area.style().pen().width();
_pen = _area.style().pen();
_brush = _area.style().brush();
} else {
_width = 2;
_opacity = 0.5;
QBrush brush(Qt::SolidPattern);
_pen = QPen(brush, _width);
}
updatePainterPath();
@ -91,6 +98,8 @@ void AreaItem::setMap(Map *map)
void AreaItem::setColor(const QColor &color)
{
if (_area.style().isValid())
return;
if (_pen.color() == color)
return;
@ -104,6 +113,8 @@ void AreaItem::setColor(const QColor &color)
void AreaItem::setOpacity(qreal opacity)
{
if (_area.style().isValid())
return;
if (_opacity == opacity)
return;
@ -117,6 +128,8 @@ void AreaItem::setOpacity(qreal opacity)
void AreaItem::setWidth(qreal width)
{
if (_area.style().isValid())
return;
if (_width == width)
return;
@ -128,6 +141,8 @@ void AreaItem::setWidth(qreal width)
void AreaItem::setStyle(Qt::PenStyle style)
{
if (_area.style().isValid())
return;
if (_pen.style() == style)
return;

View File

@ -11,7 +11,8 @@ GraphItem::GraphItem(const Graph &graph, GraphType type, int width,
Q_ASSERT(_graph.isValid());
_units = Metric;
_pen = QPen(color, width, style, Qt::FlatCap);
_pen = QPen(graph.color().isValid() ? graph.color() : color, width, style,
Qt::FlatCap);
_sx = 0; _sy = 0;
_time = _graph.hasTime();
setZValue(2.0);
@ -54,6 +55,8 @@ void GraphItem::setGraphType(GraphType type)
void GraphItem::setColor(const QColor &color)
{
if (_graph.color().isValid())
return;
if (_pen.color() == color)
return;

View File

@ -32,15 +32,16 @@ static inline unsigned segments(qreal distance)
Units PathItem::_units = Metric;
QTimeZone PathItem::_timeZone = QTimeZone::utc();
PathItem::PathItem(const Path &path, Map *map, QGraphicsItem *parent)
: GraphicsItem(parent), _path(path), _map(map), _graph(0)
PathItem::PathItem(const Path &path, const LineStyle &style, Map *map,
QGraphicsItem *parent) : GraphicsItem(parent), _path(path), _style(style),
_map(map), _graph(0)
{
Q_ASSERT(_path.isValid());
_digitalZoom = 0;
_width = 3;
QBrush brush(Qt::SolidPattern);
_pen = QPen(brush, _width);
_width = (_style.width() >= 0) ? _style.width() : 3;
_pen = _style.color().isValid()
? QPen(_style.color(), _width) : QPen(QBrush(Qt::SolidPattern), _width);
_showMarker = true;
_showTicks = false;
_markerInfoType = MarkerInfoItem::None;
@ -153,6 +154,8 @@ void PathItem::setMap(Map *map)
void PathItem::setColor(const QColor &color)
{
if (_style.color().isValid())
return;
if (_pen.color() == color)
return;
@ -166,6 +169,8 @@ void PathItem::setColor(const QColor &color)
void PathItem::setWidth(qreal width)
{
if (_style.color().isValid())
return;
if (_width == width)
return;

View File

@ -5,6 +5,8 @@
#include <QPen>
#include <QTimeZone>
#include "data/path.h"
#include "data/link.h"
#include "data/style.h"
#include "graphicsscene.h"
#include "markerinfoitem.h"
#include "units.h"
@ -19,7 +21,8 @@ class PathItem : public QObject, public GraphicsItem
Q_OBJECT
public:
PathItem(const Path &path, Map *map, QGraphicsItem *parent = 0);
PathItem(const Path &path, const LineStyle &style, Map *map,
QGraphicsItem *parent = 0);
virtual ~PathItem() {}
QPainterPath shape() const {return _shape;}
@ -66,6 +69,11 @@ protected:
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
QString _name;
QString _desc;
QString _comment;
QVector<Link> _links;
static Units _units;
static QTimeZone _timeZone;
@ -81,6 +89,7 @@ private:
unsigned tickSize() const;
Path _path;
LineStyle _style;
Map *_map;
QList<GraphItem *> _graphs;
GraphItem *_graph;

View File

@ -36,7 +36,7 @@ ToolTip RouteItem::info() const
}
RouteItem::RouteItem(const Route &route, Map *map, QGraphicsItem *parent)
: PathItem(route.path(), map, parent)
: PathItem(route.path(), route.style(), map, parent)
{
const RouteData &waypoints = route.data();

View File

@ -1,7 +1,6 @@
#ifndef ROUTEITEM_H
#define ROUTEITEM_H
#include "data/link.h"
#include "pathitem.h"
class Map;
@ -26,11 +25,6 @@ public:
QDateTime date() const {return QDateTime();}
private:
QString _name;
QString _desc;
QString _comment;
QVector<Link> _links;
QVector<WaypointItem*> _waypoints;
};

View File

@ -41,7 +41,7 @@ ToolTip TrackItem::info() const
}
TrackItem::TrackItem(const Track &track, Map *map, QGraphicsItem *parent)
: PathItem(track.path(), map, parent)
: PathItem(track.path(), track.style(), map, parent)
{
_name = track.name();
_desc = track.description();

View File

@ -2,7 +2,6 @@
#define TRACKITEM_H
#include <QDateTime>
#include "data/link.h"
#include "pathitem.h"
class Map;
@ -19,10 +18,6 @@ public:
QDateTime date() const {return _date;}
private:
QString _name;
QString _desc;
QString _comment;
QVector<Link> _links;
QDateTime _date;
qreal _time;
qreal _movingTime;

View File

@ -77,12 +77,14 @@ WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map,
_waypoint = waypoint;
_showLabel = true;
_showIcon = false;
_size = 8;
_color = Qt::black;
_size = (_waypoint.style().size() >= 0)
? _waypoint.style().size() : 8;
_color = (_waypoint.style().color().isValid())
? _waypoint.style().color() : Qt::black;
_icon = (_waypoint.icon().isNull())
_icon = (_waypoint.style().icon().isNull())
? Waypoint::symbolIcon(_waypoint.symbol())
: &_waypoint.icon();
: &_waypoint.style().icon();
_font.setPixelSize(FS(_size));
_font.setFamily(FONT_FAMILY);
@ -98,6 +100,7 @@ void WaypointItem::updateCache()
{
QPainterPath p;
qreal pointSize = _font.bold() ? HS(_size) : _size;
const QPixmap &icon = _waypoint.style().icon();
if (_showLabel && !_waypoint.name().isEmpty()) {
QFontMetrics fm(_font);
@ -105,15 +108,15 @@ void WaypointItem::updateCache()
if (_showIcon && _icon) {
if (_font.bold())
p.addRect(-_icon->width() * 0.625, _waypoint.icon().isNull()
p.addRect(-_icon->width() * 0.625, icon.isNull()
? -_icon->height() * 1.25 : -_icon->height() * 0.625,
_icon->width() * 1.25, _icon->height() * 1.25);
else
p.addRect(-_icon->width()/2.0, _waypoint.icon().isNull()
p.addRect(-_icon->width()/2.0, icon.isNull()
? -_icon->height() : -_icon->height()/2, _icon->width(),
_icon->height());
if (_waypoint.icon().isNull())
if (icon.isNull())
p.addRect(0, 0, _labelBB.width(), _labelBB.height()
+ fm.descent());
else
@ -127,11 +130,11 @@ void WaypointItem::updateCache()
} else {
if (_showIcon && _icon) {
if (_font.bold())
p.addRect(-_icon->width() * 0.625, _waypoint.icon().isNull()
p.addRect(-_icon->width() * 0.625, icon.isNull()
? -_icon->height() * 1.25 : -_icon->height() * 0.625,
_icon->width() * 1.25, _icon->height() * 1.25);
else
p.addRect(-_icon->width()/2, _waypoint.icon().isNull()
p.addRect(-_icon->width()/2, icon.isNull()
? -_icon->height() : -_icon->height()/2, _icon->width(),
_icon->height());
} else
@ -147,13 +150,14 @@ void WaypointItem::paint(QPainter *painter,
Q_UNUSED(option);
Q_UNUSED(widget);
qreal pointSize = _font.bold() ? HS(_size) : _size;
const QPixmap &icon = _waypoint.style().icon();
painter->setPen(_color);
if (_showLabel && !_waypoint.name().isEmpty()) {
painter->setFont(_font);
if (_showIcon && _icon) {
if (_waypoint.icon().isNull())
if (icon.isNull())
painter->drawText(-qMax(_labelBB.x(), 0), _labelBB.height(),
_waypoint.name());
else
@ -167,12 +171,12 @@ void WaypointItem::paint(QPainter *painter,
painter->setBrush(QBrush(_color, Qt::SolidPattern));
if (_showIcon && _icon) {
if (_font.bold())
painter->drawPixmap(-_icon->width() * 0.625, _waypoint.icon().isNull()
painter->drawPixmap(-_icon->width() * 0.625, icon.isNull()
? -_icon->height() * 1.25 : -_icon->height() * 0.625,
_icon->scaled(_icon->width() * 1.25, _icon->height() * 1.25,
Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
else
painter->drawPixmap(-_icon->width()/2.0, _waypoint.icon().isNull()
painter->drawPixmap(-_icon->width()/2.0, icon.isNull()
? -_icon->height() : -_icon->height()/2, *_icon);
} else
painter->drawEllipse(-pointSize/2, -pointSize/2, pointSize, pointSize);
@ -184,6 +188,8 @@ void WaypointItem::paint(QPainter *painter,
void WaypointItem::setSize(int size)
{
if (_waypoint.style().size() >= 0)
return;
if (_size == size)
return;
@ -195,6 +201,8 @@ void WaypointItem::setSize(int size)
void WaypointItem::setColor(const QColor &color)
{
if (_waypoint.style().color().isValid())
return;
if (_color == color)
return;

View File

@ -4,6 +4,7 @@
#include <QString>
#include <QList>
#include "common/polygon.h"
#include "style.h"
class Area
{
@ -27,6 +28,7 @@ public:
const QString &description() const {return _desc;}
const QList<Polygon> &polygons() const {return _polygons;}
const RectC &boundingRect() const {return _boundingRect;}
const PolygonStyle &style() const {return _style;}
bool isValid() const
{
@ -47,11 +49,13 @@ public:
void setName(const QString &name) {_name = name;}
void setDescription(const QString &desc) {_desc = desc;}
void setStyle(const PolygonStyle &style) {_style = style;}
private:
QList<Polygon> _polygons;
QString _name;
QString _desc;
PolygonStyle _style;
RectC _boundingRect;
};

View File

@ -2,6 +2,109 @@
#include <QJsonArray>
#include "geojsonparser.h"
#define MARKER_SIZE_MEDIUM 12
#define MARKER_SIZE_SMALL 8
#define MARKER_SIZE_LARGE 16
static int markerSize(const QString &str)
{
if (str == "small")
return MARKER_SIZE_SMALL;
else if (str == "medium")
return MARKER_SIZE_MEDIUM;
else if (str == "large")
return MARKER_SIZE_LARGE;
else
return -1;
}
static void setAreaProperties(Area &area, const QJsonValue &properties)
{
if (!properties.isObject())
return;
QJsonObject o(properties.toObject());
if (o["name"].isString())
area.setName(o["name"].toString());
if (o["title"].isString())
area.setName(o["title"].toString());
if (o["description"].isString())
area.setDescription(o["description"].toString());
QColor strokeColor(0x55, 0x55, 0x55);
QColor fillColor(0x55, 0x55, 0x55);
double strokeWidth = 2;
if (o["stroke"].isString())
strokeColor = QColor(o["stroke"].toString());
if (o["stroke-opacity"].isDouble())
strokeColor.setAlphaF(o["stroke-opacity"].toDouble());
if (o["stroke-width"].isDouble())
strokeWidth = o["stroke-width"].toDouble();
if (o["fill"].isString())
fillColor = QColor(o["fill"].toString());
if (o["fill-opacity"].isDouble())
fillColor.setAlphaF(o["fill-opacity"].toDouble());
else
fillColor.setAlphaF(0.6);
area.setStyle(PolygonStyle(QPen(strokeColor, strokeWidth),
QBrush(fillColor)));
}
static void setTrackProperties(TrackData &track, const QJsonValue &properties)
{
if (!properties.isObject())
return;
QJsonObject o(properties.toObject());
if (o["name"].isString())
track.setName(o["name"].toString());
if (o["title"].isString())
track.setName(o["title"].toString());
if (o["description"].isString())
track.setDescription(o["description"].toString());
QColor color(0x55, 0x55, 0x55);
double width = 2;
if (o["stroke"].isString())
color = QColor(o["stroke"].toString());
if (o["stroke-opacity"].isDouble())
color.setAlphaF(o["stroke-opacity"].toDouble());
if (o["stroke-width"].isDouble())
width = o["stroke-width"].toDouble();
track.setStyle(LineStyle(color, width));
}
static void setWaypointProperties(Waypoint &waypoint,
const QJsonValue &properties)
{
if (!properties.isObject())
return;
QJsonObject o(properties.toObject());
if (o["name"].isString())
waypoint.setName(o["name"].toString());
if (o["title"].isString())
waypoint.setName(o["title"].toString());
if (o["description"].isString())
waypoint.setDescription(o["description"].toString());
QColor color(0x7e, 0x7e, 0x7e);
int size = MARKER_SIZE_MEDIUM;
if (o["marker-color"].isString())
color = QColor(o["marker-color"].toString());
if (o["marker-symbol"].isString())
waypoint.setSymbol(o["marker-symbol"].toString());
if (o["marker-size"].isString())
size = markerSize(o["marker-size"].toString());
waypoint.setStyle(PointStyle(QPixmap(), color, size));
}
GeoJSONParser::Type GeoJSONParser::type(const QJsonObject &json)
{
@ -30,7 +133,7 @@ GeoJSONParser::Type GeoJSONParser::type(const QJsonObject &json)
}
bool GeoJSONParser::point(const QJsonArray &coordinates, Waypoint &waypoint,
const QJsonObject &properties)
const QJsonValue &properties)
{
if (coordinates.count() < 2 || !coordinates.at(0).isDouble()
|| !coordinates.at(1).isDouble()) {
@ -38,23 +141,18 @@ bool GeoJSONParser::point(const QJsonArray &coordinates, Waypoint &waypoint,
return false;
}
setWaypointProperties(waypoint, properties);
waypoint.setCoordinates(Coordinates(coordinates.at(0).toDouble(),
coordinates.at(1).toDouble()));
if (coordinates.count() == 3 && coordinates.at(2).isDouble())
waypoint.setElevation(coordinates.at(2).toDouble());
if (properties.contains("title") && properties["title"].isString())
waypoint.setName(properties["title"].toString());
if (properties.contains("name") && properties["name"].isString())
waypoint.setName(properties["name"].toString());
if (properties.contains("description")
&& properties["description"].isString())
waypoint.setDescription(properties["description"].toString());
return true;
}
bool GeoJSONParser::multiPoint(const QJsonArray &coordinates,
QVector<Waypoint> &waypoints, const QJsonObject &properties)
QVector<Waypoint> &waypoints, const QJsonValue &properties)
{
for (int i = 0; i < coordinates.size(); i++) {
if (!coordinates.at(i).isArray()) {
@ -92,15 +190,9 @@ bool GeoJSONParser::lineString(const QJsonArray &coordinates,
}
bool GeoJSONParser::lineString(const QJsonArray &coordinates, TrackData &track,
const QJsonObject &properties)
const QJsonValue &properties)
{
if (properties.contains("title") && properties["title"].isString())
track.setName(properties["title"].toString());
if (properties.contains("name") && properties["name"].isString())
track.setName(properties["name"].toString());
if (properties.contains("description")
&& properties["description"].isString())
track.setDescription(properties["description"].toString());
setTrackProperties(track, properties);
track.append(SegmentData());
@ -110,15 +202,9 @@ bool GeoJSONParser::lineString(const QJsonArray &coordinates, TrackData &track,
}
bool GeoJSONParser::multiLineString(const QJsonArray &coordinates,
TrackData &track, const QJsonObject &properties)
TrackData &track, const QJsonValue &properties)
{
if (properties.contains("title") && properties["title"].isString())
track.setName(properties["title"].toString());
if (properties.contains("name") && properties["name"].isString())
track.setName(properties["name"].toString());
if (properties.contains("description")
&& properties["description"].isString())
track.setDescription(properties["description"].toString());
setTrackProperties(track, properties);
for (int i = 0; i < coordinates.size(); i++) {
if (!coordinates.at(i).isArray()) {
@ -163,15 +249,9 @@ bool GeoJSONParser::polygon(const QJsonArray &coordinates, ::Polygon &pg)
}
bool GeoJSONParser::polygon(const QJsonArray &coordinates, Area &area,
const QJsonObject &properties)
const QJsonValue &properties)
{
if (properties.contains("title") && properties["title"].isString())
area.setName(properties["title"].toString());
if (properties.contains("name") && properties["name"].isString())
area.setName(properties["name"].toString());
if (properties.contains("description")
&& properties["description"].isString())
area.setDescription(properties["description"].toString());
setAreaProperties(area, properties);
::Polygon p;
if (!polygon(coordinates, p))
@ -182,15 +262,9 @@ bool GeoJSONParser::polygon(const QJsonArray &coordinates, Area &area,
}
bool GeoJSONParser::multiPolygon(const QJsonArray &coordinates,
Area &area, const QJsonObject &properties)
Area &area, const QJsonValue &properties)
{
if (properties.contains("title") && properties["title"].isString())
area.setName(properties["title"].toString());
if (properties.contains("name") && properties["name"].isString())
area.setName(properties["name"].toString());
if (properties.contains("description")
&& properties["description"].isString())
area.setDescription(properties["description"].toString());
setAreaProperties(area, properties);
for (int i = 0; i < coordinates.size(); i++) {
if (!coordinates.at(i).isArray()) {
@ -209,7 +283,7 @@ bool GeoJSONParser::multiPolygon(const QJsonArray &coordinates,
bool GeoJSONParser::geometryCollection(const QJsonObject &json,
QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints, const QJsonObject &properties)
QVector<Waypoint> &waypoints, const QJsonValue &properties)
{
if (!json.contains("geometries") || !json["geometries"].isArray()) {
_errorString = "Invalid/missing GeometryCollection geometries array";
@ -273,7 +347,7 @@ bool GeoJSONParser::geometryCollection(const QJsonObject &json,
bool GeoJSONParser::feature(const QJsonObject &json, QList<TrackData> &tracks,
QList<Area> &areas, QVector<Waypoint> &waypoints)
{
QJsonObject properties(json["properties"].toObject());
QJsonValue properties(json["properties"]);
QJsonObject geometry(json["geometry"].toObject());
switch (type(geometry)) {

View File

@ -31,22 +31,22 @@ private:
Type type(const QJsonObject &json);
bool point(const QJsonArray &coordinates, Waypoint &waypoint,
const QJsonObject &properties = QJsonObject());
const QJsonValue &properties = QJsonValue());
bool multiPoint(const QJsonArray &coordinates,
QVector<Waypoint> &waypoints, const QJsonObject &properties = QJsonObject());
QVector<Waypoint> &waypoints, const QJsonValue &properties = QJsonValue());
bool lineString(const QJsonArray &coordinates, SegmentData &segment);
bool lineString(const QJsonArray &coordinates, TrackData &track,
const QJsonObject &properties = QJsonObject());
const QJsonValue &properties = QJsonValue());
bool multiLineString(const QJsonArray &coordinates,
TrackData &track, const QJsonObject &properties = QJsonObject());
TrackData &track, const QJsonValue &properties = QJsonValue());
bool polygon(const QJsonArray &coordinates, ::Polygon &pg);
bool polygon(const QJsonArray &coordinates, Area &area,
const QJsonObject &properties = QJsonObject());
const QJsonValue &properties = QJsonValue());
bool multiPolygon(const QJsonArray &coordinates, Area &area,
const QJsonObject &properties = QJsonObject());
const QJsonValue &properties = QJsonValue());
bool geometryCollection(const QJsonObject &json, QList<TrackData> &tracks,
QList<Area> &areas, QVector<Waypoint> &waypoints,
const QJsonObject &properties = QJsonObject());
const QJsonValue &properties = QJsonValue());
bool feature(const QJsonObject &json, QList<TrackData> &tracks,
QList<Area> &areas, QVector<Waypoint> &waypoints);
bool featureCollection(const QJsonObject &json, QList<TrackData> &tracks,

View File

@ -695,7 +695,7 @@ static void readPOIDatabase(DataStream &stream, QVector<Waypoint> &waypoints,
for (int i = 0; i < il.size(); i++) {
const QPair<int, quint16> &e = il.at(i);
if (e.second < icons.size())
waypoints[e.first].setIcon(icons.at(e.second));
waypoints[e.first].setStyle(icons.at(e.second));
}
if (ds != rh.size)

View File

@ -228,6 +228,26 @@ void GPXParser::trackpoints(SegmentData &segment)
}
}
void GPXParser::routeExtension(RouteData &route)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("DisplayColor"))
route.setStyle(LineStyle(QColor(_reader.readElementText())));
else
_reader.skipCurrentElement();
}
}
void GPXParser::routeExtensions(RouteData &track)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("RouteExtension"))
routeExtension(track);
else
_reader.skipCurrentElement();
}
}
void GPXParser::routepoints(RouteData &route, QList<TrackData> &tracks)
{
TrackData autoRoute;
@ -253,6 +273,8 @@ void GPXParser::routepoints(RouteData &route, QList<TrackData> &tracks)
link10.setURL(_reader.readElementText());
else if (_reader.name() == QLatin1String("urlname"))
link10.setText(_reader.readElementText());
else if (_reader.name() == QLatin1String("extensions"))
routeExtensions(route);
else
_reader.skipCurrentElement();
}
@ -267,6 +289,26 @@ void GPXParser::routepoints(RouteData &route, QList<TrackData> &tracks)
}
}
void GPXParser::trackExtension(TrackData &track)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("DisplayColor"))
track.setStyle(LineStyle(QColor(_reader.readElementText())));
else
_reader.skipCurrentElement();
}
}
void GPXParser::trackExtensions(TrackData &track)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("TrackExtension"))
trackExtension(track);
else
_reader.skipCurrentElement();
}
}
void GPXParser::track(TrackData &track)
{
Link link10;
@ -289,6 +331,8 @@ void GPXParser::track(TrackData &track)
link10.setURL(_reader.readElementText());
else if (_reader.name() == QLatin1String("urlname"))
link10.setText(_reader.readElementText());
else if (_reader.name() == QLatin1String("extensions"))
trackExtensions(track);
else
_reader.skipCurrentElement();
}

View File

@ -25,6 +25,10 @@ private:
void waypointExtensions(Waypoint &waypoint, SegmentData *autoRoute);
void area(Area &area);
void gpxExtensions(QList<Area> &areas);
void trackExtensions(TrackData &track);
void trackExtension(TrackData &track);
void routeExtensions(RouteData &route);
void routeExtension(RouteData &route);
void trackpointData(Trackpoint &trackpoint);
void waypointData(Waypoint &waypoint, SegmentData *autoRoute = 0);
void address(Waypoint &waypoint);

View File

@ -65,6 +65,12 @@ public:
}
return true;
}
const QColor &color() const {return _color;}
void setColor(const QColor &color) {_color = color;}
private:
QColor _color;
};
class GraphPair

View File

@ -525,10 +525,12 @@ void KMLParser::multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
}
void KMLParser::photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
QMap<QString, QPixmap> &icons)
PointStyleMap &pointStyles)
{
QString img, id;
Waypoint w;
QMap<QString, PolygonStyle> unused;
QMap<QString, LineStyle> unused2;
static QRegularExpression re("\\$\\[[^\\]]+\\]");
while (_reader.readNextStartElement()) {
@ -543,10 +545,10 @@ void KMLParser::photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
else if (_reader.name() == QLatin1String("TimeStamp"))
w.setTimestamp(timeStamp());
else if (_reader.name() == QLatin1String("Style")) {
style(ctx.dir, icons);
style(ctx.dir, pointStyles, unused, unused2);
id = QString();
} else if (_reader.name() == QLatin1String("StyleMap"))
styleMap(icons);
styleMap(pointStyles, unused, unused2);
else if (_reader.name() == QLatin1String("Icon"))
img = icon();
else if (_reader.name() == QLatin1String("Point"))
@ -558,7 +560,7 @@ void KMLParser::photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
}
if (!w.coordinates().isNull()) {
w.setIcon(icons.value(id));
w.setStyle(pointStyles.value(id));
img.replace(re, "0");
if (!QUrl(img).scheme().isEmpty())
@ -579,8 +581,8 @@ void KMLParser::photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
}
void KMLParser::placemark(const Ctx &ctx, QList<TrackData> &tracks,
QList<Area> &areas, QVector<Waypoint> &waypoints,
QMap<QString, QPixmap> &icons)
QList<Area> &areas, QVector<Waypoint> &waypoints, PointStyleMap &pointStyles,
PolygonStyleMap &polyStyles, LineStyleMap &lineStyles)
{
QString name, desc, phone, address, id;
QDateTime timestamp;
@ -600,10 +602,10 @@ void KMLParser::placemark(const Ctx &ctx, QList<TrackData> &tracks,
else if (_reader.name() == QLatin1String("TimeStamp"))
timestamp = timeStamp();
else if (_reader.name() == QLatin1String("Style")) {
style(ctx.dir, icons);
style(ctx.dir, pointStyles, polyStyles, lineStyles);
id = QString();
} else if (_reader.name() == QLatin1String("StyleMap"))
styleMap(icons);
styleMap(pointStyles, polyStyles, lineStyles);
else if (_reader.name() == QLatin1String("MultiGeometry"))
multiGeometry(tracks, areas, waypoints, name, desc, timestamp);
else if (_reader.name() == QLatin1String("Point")) {
@ -641,13 +643,15 @@ void KMLParser::placemark(const Ctx &ctx, QList<TrackData> &tracks,
wp->setTimestamp(timestamp);
wp->setAddress(address);
wp->setPhone(phone);
wp->setIcon(icons.value(id));
wp->setStyle(pointStyles.value(id));
} else if (tp) {
tp->setName(name);
tp->setDescription(desc);
tp->setStyle(lineStyles.value(id));
} else if (ap) {
ap->setName(name);
ap->setDescription(desc);
ap->setStyle(polyStyles.value(id));
}
}
@ -672,17 +676,66 @@ QString KMLParser::styleUrl()
}
void KMLParser::iconStyle(const QDir &dir, const QString &id,
QMap<QString, QPixmap> &icons)
PointStyleMap &styles)
{
QPixmap img;
QColor color(Qt::white);
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("Icon"))
icons.insert(id, QPixmap(dir.absoluteFilePath(icon())));
img = QPixmap(dir.absoluteFilePath(icon()));
else if (_reader.name() == QLatin1String("color"))
color = QColor("#" + _reader.readElementText());
else
_reader.skipCurrentElement();
}
styles.insert(id, PointStyle(img, color));
}
void KMLParser::styleMapPair(const QString &id, QMap<QString, QPixmap> &icons)
void KMLParser::polyStyle(const QString &id, PolygonStyleMap &styles)
{
QColor color(Qt::white);
uint fill = 1, outline = 1;
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("color"))
color = QColor("#" + _reader.readElementText());
else if (_reader.name() == QLatin1String("fill"))
fill = _reader.readElementText().toUInt();
else if (_reader.name() == QLatin1String("outline"))
outline = _reader.readElementText().toUInt();
else
_reader.skipCurrentElement();
}
QPen pen = (color.isValid() && outline)
? QPen(color) : QPen(Qt::NoPen);
QBrush brush = (color.isValid() && fill)
? QBrush(color) : QBrush(Qt::NoBrush);
styles.insert(id, PolygonStyle(pen, brush));
}
void KMLParser::lineStyle(const QString &id, LineStyleMap &styles)
{
QColor color(Qt::white);
uint width = 1;
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("color"))
color = QColor("#" + _reader.readElementText());
else if (_reader.name() == QLatin1String("width"))
width = _reader.readElementText().toUInt();
else
_reader.skipCurrentElement();
}
styles.insert(id, LineStyle(color, width));
}
void KMLParser::styleMapPair(const QString &id, PointStyleMap &pointStyles,
PolygonStyleMap &polyStyles, LineStyleMap &lineStyles)
{
QString key, url;
@ -695,29 +748,38 @@ void KMLParser::styleMapPair(const QString &id, QMap<QString, QPixmap> &icons)
_reader.skipCurrentElement();
}
if (key == "normal")
icons.insert(id, icons.value(url));
if (key == "normal") {
pointStyles.insert(id, pointStyles.value(url));
polyStyles.insert(id, polyStyles.value(url));
lineStyles.insert(id, lineStyles.value(url));
}
}
void KMLParser::styleMap(QMap<QString, QPixmap> &icons)
void KMLParser::styleMap(PointStyleMap &pointStyles,
PolygonStyleMap &polyStyles, LineStyleMap &lineStyles)
{
QString id = _reader.attributes().value("id").toString();
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("Pair"))
styleMapPair(id, icons);
styleMapPair(id, pointStyles, polyStyles, lineStyles);
else
_reader.skipCurrentElement();
}
}
void KMLParser::style(const QDir &dir, QMap<QString, QPixmap> &icons)
void KMLParser::style(const QDir &dir, PointStyleMap &pointStyles,
PolygonStyleMap &polyStyles, LineStyleMap &lineStyles)
{
QString id = _reader.attributes().value("id").toString();
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("IconStyle"))
iconStyle(dir, id, icons);
iconStyle(dir, id, pointStyles);
else if (_reader.name() == QLatin1String("PolyStyle"))
polyStyle(id, polyStyles);
else if (_reader.name() == QLatin1String("LineStyle"))
lineStyle(id, lineStyles);
else
_reader.skipCurrentElement();
}
@ -725,17 +787,20 @@ void KMLParser::style(const QDir &dir, QMap<QString, QPixmap> &icons)
void KMLParser::folder(const Ctx &ctx, QList<TrackData> &tracks,
QList<Area> &areas, QVector<Waypoint> &waypoints,
QMap<QString, QPixmap> &icons)
PointStyleMap &pointStyles, PolygonStyleMap &polyStyles,
LineStyleMap &lineStyles)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("Document"))
document(ctx, tracks, areas, waypoints);
else if (_reader.name() == QLatin1String("Folder"))
folder(ctx, tracks, areas, waypoints, icons);
folder(ctx, tracks, areas, waypoints, pointStyles, polyStyles,
lineStyles);
else if (_reader.name() == QLatin1String("Placemark"))
placemark(ctx, tracks, areas, waypoints, icons);
placemark(ctx, tracks, areas, waypoints, pointStyles, polyStyles,
lineStyles);
else if (_reader.name() == QLatin1String("PhotoOverlay"))
photoOverlay(ctx, waypoints, icons);
photoOverlay(ctx, waypoints, pointStyles);
else
_reader.skipCurrentElement();
}
@ -744,21 +809,25 @@ void KMLParser::folder(const Ctx &ctx, QList<TrackData> &tracks,
void KMLParser::document(const Ctx &ctx, QList<TrackData> &tracks,
QList<Area> &areas, QVector<Waypoint> &waypoints)
{
QMap<QString, QPixmap> icons;
PointStyleMap pointStyles;
PolygonStyleMap polyStyles;
LineStyleMap lineStyles;
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("Document"))
document(ctx, tracks, areas, waypoints);
else if (_reader.name() == QLatin1String("Folder"))
folder(ctx, tracks, areas, waypoints, icons);
folder(ctx, tracks, areas, waypoints, pointStyles, polyStyles,
lineStyles);
else if (_reader.name() == QLatin1String("Placemark"))
placemark(ctx, tracks, areas, waypoints, icons);
placemark(ctx, tracks, areas, waypoints, pointStyles, polyStyles,
lineStyles);
else if (_reader.name() == QLatin1String("PhotoOverlay"))
photoOverlay(ctx, waypoints, icons);
photoOverlay(ctx, waypoints, pointStyles);
else if (_reader.name() == QLatin1String("Style"))
style(ctx.dir, icons);
style(ctx.dir, pointStyles, polyStyles, lineStyles);
else if (_reader.name() == QLatin1String("StyleMap"))
styleMap(icons);
styleMap(pointStyles, polyStyles, lineStyles);
else
_reader.skipCurrentElement();
}
@ -767,17 +836,21 @@ void KMLParser::document(const Ctx &ctx, QList<TrackData> &tracks,
void KMLParser::kml(const Ctx &ctx, QList<TrackData> &tracks,
QList<Area> &areas, QVector<Waypoint> &waypoints)
{
QMap<QString, QPixmap> icons;
PointStyleMap pointStyles;
PolygonStyleMap polyStyles;
LineStyleMap lineStyles;
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("Document"))
document(ctx, tracks, areas, waypoints);
else if (_reader.name() == QLatin1String("Folder"))
folder(ctx, tracks, areas, waypoints, icons);
folder(ctx, tracks, areas, waypoints, pointStyles, polyStyles,
lineStyles);
else if (_reader.name() == QLatin1String("Placemark"))
placemark(ctx, tracks, areas, waypoints, icons);
placemark(ctx, tracks, areas, waypoints, pointStyles, polyStyles,
lineStyles);
else if (_reader.name() == QLatin1String("PhotoOverlay"))
photoOverlay(ctx, waypoints, icons);
photoOverlay(ctx, waypoints, pointStyles);
else
_reader.skipCurrentElement();
}

View File

@ -24,19 +24,25 @@ private:
bool zip;
};
typedef QMap<QString, PointStyle> PointStyleMap;
typedef QMap<QString, PolygonStyle> PolygonStyleMap;
typedef QMap<QString, LineStyle> LineStyleMap;
void kml(const Ctx &ctx, QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints);
void document(const Ctx &ctx, QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints);
void folder(const Ctx &ctx, QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints, QMap<QString, QPixmap> &icons);
QVector<Waypoint> &waypoints, PointStyleMap &pointStyles,
PolygonStyleMap &polyStyles, LineStyleMap &lineStyles);
void placemark(const Ctx &ctx, QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints, QMap<QString, QPixmap> &icons);
QVector<Waypoint> &waypoints, PointStyleMap &pointStyles,
PolygonStyleMap &polyStyles, LineStyleMap &lineStyles);
void multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints, const QString &name, const QString &desc,
const QDateTime &timestamp);
void photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
QMap<QString, QPixmap> &icons);
PointStyleMap &pointStyles);
void track(SegmentData &segment);
void multiTrack(TrackData &t);
void lineString(SegmentData &segment);
@ -59,11 +65,15 @@ private:
QDateTime time();
QString icon();
QString styleUrl();
void style(const QDir &dir, QMap<QString, QPixmap> &icons);
void styleMapPair(const QString &id, QMap<QString, QPixmap> &icons);
void styleMap(QMap<QString, QPixmap> &icons);
void iconStyle(const QDir &dir, const QString &id,
QMap<QString, QPixmap> &icons);
void style(const QDir &dir, PointStyleMap &pointStyles,
PolygonStyleMap &polyStyles, LineStyleMap &lineStyles);
void styleMapPair(const QString &id, PointStyleMap &pointStyles,
PolygonStyleMap &polyStyles, LineStyleMap &lineStyles);
void styleMap(PointStyleMap &pointStyles, PolygonStyleMap &polyStyles,
LineStyleMap &lineStyles);
void iconStyle(const QDir &dir, const QString &id, PointStyleMap &style);
void polyStyle(const QString &id, PolygonStyleMap &styles);
void lineStyle(const QString &id, LineStyleMap &styles);
QXmlStreamReader _reader;
};

View File

@ -38,6 +38,9 @@ Graph Route::gpsElevation() const
if (_data.at(i).hasElevation())
gs.append(GraphPoint(_distance.at(i), NAN, _data.at(i).elevation()));
if (_data.style().color().isValid())
graph.setColor(_data.style().color());
return graph;
}
@ -53,6 +56,9 @@ Graph Route::demElevation() const
gs.append(GraphPoint(_distance.at(i), NAN, dem));
}
if (_data.style().color().isValid())
graph.setColor(_data.style().color());
return graph;
}

View File

@ -20,6 +20,7 @@ public:
const QString &description() const {return _data.description();}
const QString &comment() const {return _data.comment();}
const QVector<Link> &links() const {return _data.links();}
const LineStyle &style() const {return _data.style();}
bool isValid() const {return _data.size() >= 2;}

View File

@ -5,6 +5,7 @@
#include <QString>
#include "waypoint.h"
#include "link.h"
#include "style.h"
class RouteData : public QVector<Waypoint>
{
@ -13,17 +14,20 @@ public:
const QString &description() const {return _desc;}
const QString &comment() const {return _comment;}
const QVector<Link> &links() const {return _links;}
const LineStyle &style() const {return _style;}
void setName(const QString &name) {_name = name;}
void setDescription(const QString &desc) {_desc = desc;}
void setComment(const QString &comment) {_comment = comment;}
void addLink(const Link &link) {_links.append(link);}
void setStyle(const LineStyle &style) {_style = style;}
private:
QString _name;
QString _desc;
QString _comment;
QVector<Link> _links;
LineStyle _style;
};
#endif // ROUTEDATA_H

56
src/data/style.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef STYLE_H
#define STYLE_H
#include <QPen>
#include <QBrush>
#include <QPixmap>
class PointStyle {
public:
PointStyle() : _size(-1) {}
PointStyle(const QPixmap &icon, const QColor &color = QColor(), int size = -1)
: _icon(icon), _color(color), _size(size) {}
const QColor &color() const {return _color;}
const QPixmap &icon() const {return _icon;}
int size() const {return _size;}
private:
QPixmap _icon;
QColor _color;
int _size;
};
class PolygonStyle {
public:
PolygonStyle()
: _pen(QPen(Qt::NoPen)), _brush(QBrush(Qt::NoBrush)) {}
PolygonStyle(const QPen &pen, const QBrush &brush)
: _pen(pen), _brush(brush) {}
const QPen &pen() const {return _pen;}
const QBrush &brush() const {return _brush;}
bool isValid() const
{return _pen.style() != Qt::NoPen || _brush.style() != Qt::NoBrush;}
private:
QPen _pen;
QBrush _brush;
};
class LineStyle {
public:
LineStyle() : _width(-1) {}
LineStyle(const QColor &color, int width = -1)
: _color(color), _width(width) {}
const QColor &color() const {return _color;}
int width() const {return _width;}
private:
QColor _color;
int _width;
};
#endif // STYLE_H

View File

@ -254,6 +254,9 @@ Graph Track::gpsElevation() const
ret.append(filter(gs, _elevationWindow));
}
if (_data.style().color().isValid())
ret.setColor(_data.style().color());
return ret;
}
@ -278,6 +281,9 @@ Graph Track::demElevation() const
ret.append(filter(gs, _elevationWindow));
}
if (_data.style().color().isValid())
ret.setColor(_data.style().color());
return ret;
}
@ -330,6 +336,9 @@ Graph Track::computedSpeed() const
filtered[stop.at(j)].setY(0);
}
if (_data.style().color().isValid())
ret.setColor(_data.style().color());
return ret;
}
@ -365,6 +374,9 @@ Graph Track::reportedSpeed() const
filtered[stop.at(j)].setY(0);
}
if (_data.style().color().isValid())
ret.setColor(_data.style().color());
return ret;
}
@ -406,6 +418,9 @@ Graph Track::heartRate() const
ret.append(filter(gs, _heartRateWindow));
}
if (_data.style().color().isValid())
ret.setColor(_data.style().color());
return ret;
}
@ -429,6 +444,9 @@ Graph Track::temperature() const
ret.append(gs);
}
if (_data.style().color().isValid())
ret.setColor(_data.style().color());
return ret;
}
@ -451,6 +469,9 @@ Graph Track::ratio() const
ret.append(gs);
}
if (_data.style().color().isValid())
ret.setColor(_data.style().color());
return ret;
}
@ -486,6 +507,9 @@ Graph Track::cadence() const
filtered[stop.at(j)].setY(0);
}
if (_data.style().color().isValid())
ret.setColor(_data.style().color());
return ret;
}
@ -522,6 +546,9 @@ Graph Track::power() const
filtered[stop.at(j)].setY(0);
}
if (_data.style().color().isValid())
ret.setColor(_data.style().color());
return ret;
}

View File

@ -34,6 +34,7 @@ public:
const QString &description() const {return _data.description();}
const QString &comment() const {return _data.comment();}
const QVector<Link> &links() const {return _data.links();}
const LineStyle &style() const {return _data.style();}
bool isValid() const;

View File

@ -6,6 +6,7 @@
#include <QString>
#include "trackpoint.h"
#include "link.h"
#include "style.h"
typedef QVector<Trackpoint> SegmentData;
@ -16,17 +17,20 @@ public:
const QString &description() const {return _desc;}
const QString &comment() const {return _comment;}
const QVector<Link> &links() const {return _links;}
const LineStyle &style() const {return _style;}
void setName(const QString &name) {_name = name;}
void setDescription(const QString &desc) {_desc = desc;}
void setComment(const QString &comment) {_comment = comment;}
void addLink(const Link &link) {_links.append(link);}
void setStyle(const LineStyle &style) {_style = style;}
private:
QString _name;
QString _desc;
QString _comment;
QVector<Link> _links;
LineStyle _style;
};
#endif // TRACKDATA_H

View File

@ -10,6 +10,7 @@
#include "common/config.h"
#include "common/coordinates.h"
#include "link.h"
#include "style.h"
class Waypoint
{
@ -30,7 +31,7 @@ public:
const QVector<Link> &links() const {return _links;}
const QDateTime &timestamp() const {return _timestamp;}
qreal elevation() const {return _elevation;}
const QPixmap &icon() const {return _icon;}
const PointStyle &style() const {return _style;}
QPair<qreal, qreal> elevations() const;
@ -47,7 +48,7 @@ public:
void setElevation(qreal elevation) {_elevation = elevation;}
void addImage(const QString &path) {_images.append(path);}
void addLink(const Link &link) {_links.append(link);}
void setIcon(const QPixmap &icon) {_icon = icon;}
void setStyle(const PointStyle &style) {_style = style;}
bool hasElevation() const {return !std::isnan(_elevation);}
@ -74,7 +75,7 @@ private:
QVector<Link> _links;
QDateTime _timestamp;
qreal _elevation;
QPixmap _icon;
PointStyle _style;
static bool _useDEM;
static bool _show2ndElevation;