mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-28 05:00:20 +00:00
ff18de053f
This replaces the C-code XML parsing with a Qt infrastructure. QXmlStreamReader is used to parse the GPX file. It also takes into account comments by @neolit123 Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
87 lines
3.3 KiB
C++
87 lines
3.3 KiB
C++
// SPDX-License-Identifier: GPL-2.0
|
|
#include "core/parse-gpx.h"
|
|
#include "core/dive.h"
|
|
#include <QXmlStreamReader>
|
|
|
|
// Find the coordinates at the time specified in coords.start_dive
|
|
// by searching the gpx file "fileName". Here is a typical trkpt element in GPX:
|
|
// <trkpt lat="-26.84" lon="32.88"><ele>-53.7</ele><time>2017-08-06T04:56:42Z</time></trkpt>
|
|
int getCoordsFromGPXFile(struct dive_coords *coords, QString fileName)
|
|
{
|
|
struct tm tm1;
|
|
time_t trkpt_time = 0;
|
|
time_t divetime;
|
|
int64_t time_offset = coords->settingsDiff_offset + coords->timeZone_offset;
|
|
double lon = 0, lat = 0;
|
|
int line = 0;
|
|
bool first_line = true;
|
|
bool found = false;
|
|
bool trkpt_found = false;
|
|
divetime = coords->start_dive;
|
|
QFile gpxFile;
|
|
gpxFile.setFileName(fileName);
|
|
if (!gpxFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
QByteArray local8bitBAString1 = fileName.toLocal8Bit();
|
|
char *fname = local8bitBAString1.data(); // convert QString to a C string fileName
|
|
fprintf(stderr, "GPS file open error: file name = %s\n", fname);
|
|
return 1;
|
|
}
|
|
|
|
#ifdef GPSDEBUG
|
|
struct tm time; // decode the time of start of dive:
|
|
utc_mkdate(divetime, &time);
|
|
int dyr,dmon,dday,dhr,dmin;
|
|
dyr = time.tm_year;
|
|
dmon = time.tm_mon;
|
|
dday = time.tm_mday;
|
|
dhr = time.tm_hour;
|
|
dmin = time.tm_min;
|
|
#endif
|
|
|
|
QXmlStreamReader gpxReader(&gpxFile);
|
|
while (!gpxReader.atEnd()) {
|
|
gpxReader.readNext();
|
|
if (gpxReader.isStartElement()) {
|
|
if (gpxReader.name() == "trkpt") {
|
|
trkpt_found = true;
|
|
line++;
|
|
foreach (const QXmlStreamAttribute &attr, gpxReader.attributes()) {
|
|
if (attr.name().toString() == QLatin1String("lat"))
|
|
lat = attr.value().toString().toDouble();
|
|
else if (attr.name().toString() == QLatin1String("lon"))
|
|
lon = attr.value().toString().toDouble();
|
|
}
|
|
}
|
|
if (gpxReader.name() == "time" && trkpt_found) { // Ignore the <time> element in the GPX file header
|
|
QString dateTimeString = gpxReader.readElementText();
|
|
bool ok;
|
|
tm1.tm_year = dateTimeString.left(4).toInt(&ok, 10); // Extract the date/time components:
|
|
tm1.tm_mon = dateTimeString.mid(5,2).toInt(&ok,10) - 1;
|
|
tm1.tm_mday = dateTimeString.mid(8,2).toInt(&ok,10);
|
|
tm1.tm_hour = dateTimeString.mid(11,2).toInt(&ok,10);
|
|
tm1.tm_min = dateTimeString.mid(14,2).toInt(&ok,10);
|
|
tm1.tm_sec = dateTimeString.mid(17,2).toInt(&ok,10);
|
|
trkpt_time = utc_mktime(&tm1) + time_offset;
|
|
if (first_line) {
|
|
first_line = false;
|
|
coords->start_track = trkpt_time; // Local time of start of GPS track
|
|
}
|
|
if (trkpt_time >= divetime && found == false) { // This GPS local time corresponds to the start time of the dive
|
|
coords->lon = lon; // save the coordinates
|
|
coords->lat = lat;
|
|
found = true;
|
|
}
|
|
|
|
#ifdef GPSDEBUG
|
|
utc_mkdate(trkpt_time, &time); // print coordinates and time of each trkpt element of the GPX file as well as dive start time
|
|
fprintf(stderr, " %02d: lat=%f lon=%f timestamp=%ld (%ld) %02d/%02d/%02d %02d:%02d dt=%ld %02d/%02d/%02d %02d:%02d\n", line, lat,
|
|
lon, trkpt_time, time_offset, time.tm_year, time.tm_mon+1, time.tm_mday, time.tm_hour, time.tm_min, divetime, dyr, dmon+1, dday,dhr, dmin);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
} // while !at.End() // This loop executes until EOF causes a break out of the loop
|
|
coords->end_track = trkpt_time; // This is the local time of the end of the GPS track
|
|
gpxFile.close();
|
|
return 0;
|
|
}
|