mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-06-27 03:29:16 +02:00
Added support for "data defined" styles
This commit is contained in:
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 ×tamp);
|
||||
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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;}
|
||||
|
||||
|
@ -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
56
src/data/style.h
Normal 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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 ×tamp() 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;
|
||||
|
Reference in New Issue
Block a user