Improve FIT locations support
[GPXSee.git] / src / data / twonavparser.cpp
blob63c4b526fc44875b0711cdf525457a9cc0d4625f
1 #include "common/textcodec.h"
2 #include "map/gcs.h"
3 #include "twonavparser.h"
6 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
7 #define SKIP_EMPTY QString::SkipEmptyParts
8 #else // Qt 5.14
9 #define SKIP_EMPTY Qt::SkipEmptyParts
10 #endif
12 static double lon(const QString &str)
14 QStringList l(str.split(QChar(0xBA)));
15 if (l.size() < 2)
16 return NAN;
18 bool ok;
19 double val = l.at(0).toDouble(&ok);
20 if (!ok)
21 return NAN;
23 if (l.at(1) == "W")
24 return -val;
25 else if (l.at(1) == "E")
26 return val;
27 else
28 return NAN;
31 static double lat(const QString &str)
33 QStringList l(str.split(QChar(0xBA)));
34 if (l.size() < 2)
35 return NAN;
37 bool ok;
38 double val = l.at(0).toDouble(&ok);
39 if (!ok)
40 return NAN;
42 if (l.at(1) == "S")
43 return -val;
44 else if (l.at(1) == "N")
45 return val;
46 else
47 return NAN;
50 static QDateTime timestamp(const QString &dateStr, const QString &timeStr)
52 QLocale l("C");
54 QDate date(l.toDate(dateStr, "dd-MMM-yy"));
55 if (date.isValid())
56 date = date.addYears(100);
57 else {
58 date = l.toDate(dateStr, "dd-MMM-yyyy");
59 if (!date.isValid())
60 return QDateTime();
63 QTime time(l.toTime(timeStr, "H:m:s.z"));
64 if (!time.isValid()) {
65 time = l.toTime(timeStr, "H:m:s");
66 if (!time.isValid())
67 return QDateTime();
70 return QDateTime(date, time);
73 bool TwoNavParser::parse(QFile *file, QList<TrackData> &tracks,
74 QList<RouteData> &routes, QList<Area> &polygons,
75 QVector<Waypoint> &waypoints)
77 Q_UNUSED(polygons);
78 TextCodec codec(1252);
79 GCS gcs;
80 bool ok, route = false, track = false, waypoint = false;
82 _errorLine = 1;
83 _errorString.clear();
85 quint8 bom[3];
86 if (file->peek((char*)bom, sizeof(bom)) == sizeof(bom)
87 && bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF) {
88 file->seek(3);
89 codec = TextCodec(65001);
92 while (!file->atEnd()) {
93 QByteArray line(file->readLine(4096).trimmed());
94 if (!line.size())
95 continue;
97 switch (line.at(0)) {
98 case 'B':
99 {line.remove(0, 1);
100 QByteArray encoding(line.trimmed());
101 if (encoding == "UTF-8")
102 codec = TextCodec(65001);
103 else {
104 _errorString = "Invalid/unknown encoding";
105 return false;
107 break;
108 case 'G':
109 {line.remove(0, 1);
110 QString datum(line.trimmed());
111 gcs = GCS::gcs(datum);
112 if (gcs.isNull()) {
113 _errorString = "Invalid/unknown datum";
114 return false;
116 break;
117 case 'U':
118 {line.remove(0, 1);
119 QByteArray cs(line.trimmed());
120 if (cs != "1") {
121 _errorString = "Invalid/unknown coordinate system";
122 return false;
124 break;
125 case 'T':
126 {QStringList list(codec.toString(line).split(' ', SKIP_EMPTY));
127 if (list.size() < 4) {
128 _errorString = "Parse error";
129 return false;
131 Coordinates c(lon(list.at(3)), lat(list.at(2)));
132 if (!c.isValid()) {
133 _errorString = "Invalid coordinates";
134 return false;
137 Trackpoint t(gcs.toWGS84(c));
139 if (list.size() > 5) {
140 QDateTime ts(timestamp(list.at(4), list.at(5)));
141 if (ts.isValid())
142 t.setTimestamp(ts);
144 if (list.size() > 7) {
145 qreal elevation = list.at(7).toDouble(&ok);
146 if (!ok) {
147 _errorString = "Invalid altitude";
148 return false;
150 t.setElevation(elevation);
153 if (!track) {
154 tracks.append(SegmentData());
155 track = true;
158 tracks.last().last().append(t);}
159 break;
160 case 'W':
161 {QStringList list(codec.toString(line).split(' ', SKIP_EMPTY));
162 if (list.size() < 5) {
163 _errorString = "Parse error";
164 return false;
166 Coordinates c(lon(list.at(4)), lat(list.at(3)));
167 if (!c.isValid()) {
168 _errorString = "Invalid coordinates";
169 return false;
172 Waypoint w(gcs.toWGS84(c));
173 QString name(list.at(1));
174 w.setName(name.replace('_', ' ').trimmed());
176 if (list.size() > 6) {
177 QDateTime ts(timestamp(list.at(5), list.at(6)));
178 if (ts.isValid())
179 w.setTimestamp(ts);
181 if (list.size() > 7) {
182 qreal elevation = list.at(7).toDouble(&ok);
183 if (!ok) {
184 _errorString = "Invalid altitude";
185 return false;
187 w.setElevation(elevation);
189 if (list.size() > 8)
190 w.setDescription(list.mid(8).join(' '));
192 if (route)
193 routes.last().append(w);
194 else {
195 waypoints.append(w);
196 waypoint = true;
198 break;
199 case 'w':
200 {line.remove(0, 1);
201 QStringList list(codec.toString(line).split(','));
202 if (list.size() && waypoints.size())
203 waypoints.last().setSymbol(list.at(0).trimmed());}
204 break;
205 case 'R':
206 {QStringList list(codec.toString(line).split(','));
207 routes.append(RouteData());
208 if (list.size() > 1)
209 routes.last().setName(list.at(1));
210 route = true;}
211 break;
214 _errorLine++;
217 if (!(waypoint | route | track)) {
218 _errorString = "No valid data found";
219 return false;
220 } else
221 return true;