From 6194519b187b9ef24bd9d60df40d6d68d39c35b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Wed, 8 Aug 2018 20:18:08 +0200 Subject: [PATCH] Added support for geocaching.com LOC files --- gpxsee.pro | 6 ++-- src/data/data.cpp | 8 +++-- src/data/locparser.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++ src/data/locparser.h | 23 +++++++++++++ 4 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 src/data/locparser.cpp create mode 100644 src/data/locparser.h diff --git a/gpxsee.pro b/gpxsee.pro index 5f92c547..3e106777 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -137,7 +137,8 @@ HEADERS += src/config.h \ src/map/mercator.h \ src/map/jnxmap.h \ src/map/krovak.h \ - src/GUI/kv.h + src/GUI/kv.h \ + src/data/locparser.h SOURCES += src/main.cpp \ src/common/coordinates.cpp \ src/common/rectc.cpp \ @@ -238,7 +239,8 @@ SOURCES += src/main.cpp \ src/map/mercator.cpp \ src/map/jnxmap.cpp \ src/map/krovak.cpp \ - src/map/map.cpp + src/map/map.cpp \ + src/data/locparser.cpp RESOURCES += gpxsee.qrc TRANSLATIONS = lang/gpxsee_cs.ts \ diff --git a/src/data/data.cpp b/src/data/data.cpp index dd374b6a..b19cdfed 100644 --- a/src/data/data.cpp +++ b/src/data/data.cpp @@ -9,6 +9,7 @@ #include "igcparser.h" #include "nmeaparser.h" #include "oziparsers.h" +#include "locparser.h" #include "data.h" @@ -22,6 +23,7 @@ static NMEAParser nmea; static PLTParser plt; static WPTParser wpt; static RTEParser rte; +static LOCParser loc; static QHash parsers() { @@ -37,6 +39,7 @@ static QHash parsers() hash.insert("plt", &plt); hash.insert("wpt", &wpt); hash.insert("rte", &rte); + hash.insert("loc", &loc); return hash; } @@ -108,10 +111,11 @@ QString Data::formats() { return tr("Supported files") - + " (*.csv *.fit *.gpx *.igc *.kml *.nmea *.plt *.rte *.tcx *.wpt);;" + + " (*.csv *.fit *.gpx *.igc *.kml *.loc *.nmea *.plt *.rte *.tcx *.wpt);;" + tr("CSV files") + " (*.csv);;" + tr("FIT files") + " (*.fit);;" + tr("GPX files") + " (*.gpx);;" + tr("IGC files") + " (*.igc);;" - + tr("KML files") + " (*.kml);;" + tr("NMEA files") + " (*.nmea);;" + + tr("KML files") + " (*.kml);;" + tr("LOC files") + " (*.loc);;" + + tr("NMEA files") + " (*.nmea);;" + tr("OziExplorer files") + " (*.plt *.rte *.wpt);;" + tr("TCX files") + " (*.tcx);;" + tr("All files") + " (*)"; } diff --git a/src/data/locparser.cpp b/src/data/locparser.cpp new file mode 100644 index 00000000..fb42cf36 --- /dev/null +++ b/src/data/locparser.cpp @@ -0,0 +1,77 @@ +#include "locparser.h" + +Coordinates LOCParser::coordinates() +{ + bool res; + qreal lon, lat; + const QXmlStreamAttributes &attr = _reader.attributes(); + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + lon = attr.value("lon").toString().toDouble(&res); +#else // QT_VERSION < 5 + lon = attr.value("lon").toDouble(&res); +#endif // QT_VERSION < 5 + if (!res || (lon < -180.0 || lon > 180.0)) { + _reader.raiseError("Invalid longitude"); + return Coordinates(); + } +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + lat = attr.value("lat").toString().toDouble(&res); +#else // QT_VERSION < 5 + lat = attr.value("lat").toDouble(&res); +#endif // QT_VERSION < 5 + if (!res || (lat < -90.0 || lat > 90.0)) { + _reader.raiseError("Invalid latitude"); + return Coordinates(); + } + + return Coordinates(lon, lat); +} + +void LOCParser::waypoint(Waypoint &waypoint) +{ + while (_reader.readNextStartElement()) { + if (_reader.name() == "name") { + const QXmlStreamAttributes &attr = _reader.attributes(); + waypoint.setName(attr.value("id").toString()); + waypoint.setDescription(_reader.readElementText()); + } else if (_reader.name() == "coord") { + waypoint.setCoordinates(coordinates()); + _reader.skipCurrentElement(); + } else + _reader.skipCurrentElement(); + } + + if (waypoint.coordinates().isNull()) + _reader.raiseError("Missing waypoint coordinates"); +} + +void LOCParser::loc(QList &waypoints) +{ + while (_reader.readNextStartElement()) { + if (_reader.name() == "waypoint") { + waypoints.append(Waypoint()); + waypoint(waypoints.last()); + } else + _reader.skipCurrentElement(); + } +} + +bool LOCParser::parse(QFile *file, QList &tracks, + QList &routes, QList &waypoints) +{ + Q_UNUSED(tracks); + Q_UNUSED(routes); + + _reader.clear(); + _reader.setDevice(file); + + if (_reader.readNextStartElement()) { + if (_reader.name() == "loc") + loc(waypoints); + else + _reader.raiseError("Not a LOC file"); + } + + return !_reader.error(); +} diff --git a/src/data/locparser.h b/src/data/locparser.h new file mode 100644 index 00000000..a7593978 --- /dev/null +++ b/src/data/locparser.h @@ -0,0 +1,23 @@ +#ifndef LOCPARSER_H +#define LOCPARSER_H + +#include +#include "parser.h" + +class LOCParser : public Parser +{ +public: + bool parse(QFile *file, QList &tracks, + QList &routes, QList &waypoints); + QString errorString() const {return _reader.errorString();} + int errorLine() const {return _reader.lineNumber();} + +private: + void loc(QList &waypoints); + void waypoint(Waypoint &waypoint); + Coordinates coordinates(); + + QXmlStreamReader _reader; +}; + +#endif // LOCPARSER_H