GPS Sport Sniffer is a open source GPS application developed with Qt and made in...
[gpssportsniffer] / utils.cpp
1 #include "utils.h"
2 #include "constants.h"
3 #include "track.h"
4 #include <QFile>
5 #include <QDebug>
6 #include <QXmlStreamReader>
7
8 uint qHash(const QPoint& p)
9 {
10     return p.x() * 17 ^ p.y();
11 }
12
13
14 qreal max(qreal a, qreal b){
15
16     if(a>=b){
17         return a;
18     }else
19         return b;
20 }
21
22 qreal min(qreal a, qreal b){
23
24     if(a<b){
25         return a;
26     }else
27         return b;
28 }
29
30 QString stringDateFromSeconds(qreal amount){
31
32
33
34     int hours = static_cast<int>(amount/3600);
35     int minutes = static_cast<int>((static_cast<int>(amount)%3600)/60);
36     int seconds = (static_cast<int>(amount)%3600)%60;
37
38     QString dateString=QString("%1h %2m %3s").arg(hours).arg(minutes).arg(seconds);
39
40     //qDebug()<<"amount " << amount << " seconds has been transformated to:" << dateString;
41     return dateString;
42 }
43
44 qreal toRad(qreal degrees){
45     qreal radians = degrees*PI/180;
46     return radians;
47 }
48
49 Track* readFromXML(QString fileName){
50
51     // I need this function to work by now, When I've time I've to make it proper
52     // It doesn't work with no valid XML files!!!
53
54     QFile* file= new QFile(fileName);
55     bool nameFound=false;
56
57     qDebug() << "going to read file:" << fileName;
58
59     Track* myTrack = new Track();
60     myTrack->addActivity("doesn'tmatter");
61
62     if (!file->open(QIODevice::ReadOnly | QIODevice::Text)) {
63         qDebug() << "Error: Cannot read file "
64                  << qPrintable(fileName) << ": "
65                  << qPrintable(file->errorString());
66         return myTrack;
67     }
68
69     XMLFileType fileType;
70
71     if(fileName.endsWith(".tcx",Qt::CaseInsensitive)){
72         fileType=XMLFile_TCX;
73     }else if(fileName.endsWith(".gpx",Qt::CaseInsensitive)){
74         fileType=XMLFile_GPX;
75     }else{
76         qDebug()<<"Error: XML not recognized. " << "nameFile:" << fileName;
77     }
78
79     QXmlStreamReader xml(file);
80
81     while (!xml.atEnd() && !xml.hasError()) {
82
83         /* Read next element.*/
84         QXmlStreamReader::TokenType token = xml.readNext();
85         /* If token is just StartDocument, we'll go to next.*/
86         if(token == QXmlStreamReader::StartDocument) {
87             continue;
88         }
89         /* If token is StartElement, we'll see if we can read it.*/
90         if(token == QXmlStreamReader::StartElement) {
91             // just read Positions, dont care about nothing more...
92             // this means, all activities, laps or  track sequences are
93             // processed as a single one!
94
95             if(fileType==XMLFile_GPX){
96                 if(xml.name() == "trkpt") {
97                     GpsPoint* point = parseGPXGpsPoint(xml);
98                     //qDebug()<<"adding point: " << point->toString();
99                     myTrack->addPoint(point);
100                 }else{
101                     continue;
102                 }
103             }else if(fileType==XMLFile_TCX){
104                 if(xml.name() == "Trackpoint") {
105                     GpsPoint* point = parseTCXGpsPoint(xml);
106                     //qDebug()<<"adding point: " << point->toString();
107                     myTrack->addPoint(point);
108
109                 }else{
110                     continue;
111                 }
112             }
113             if(xml.name()=="name"){
114                 myTrack->setName(parseStringElement(xml,"name"));
115                 nameFound=true;
116             }
117             if(xml.name()=="Activity" && !nameFound){
118
119                 myTrack->setName(parseAttribute(xml,"Activity","Sport"));
120                 nameFound=true;
121             }
122         }
123     }
124     /* Error handling. */
125     if(xml.hasError()) {
126         qDebug() << "Error: in readFromXML "
127                  << qPrintable(fileName) << ": "
128                  << qPrintable(file->errorString());
129     }
130     /* Removes any device() or data from the reader
131         * and resets its internal state to the initial state. */
132     qDebug()<<"clearing xml!";
133     xml.clear();
134     qDebug() << "going to return myTrack";
135     return myTrack;
136 }
137
138 qreal parseDoubleAttribute(QXmlStreamReader& xml, const char* stringElement, const char* stringAttribute){
139     QString sValue = parseAttribute(xml,stringElement,stringAttribute);
140     return sValue.toDouble();
141 }
142
143 QString parseAttribute(QXmlStreamReader& xml, const char* stringElement, const char* stringAttribute){
144
145     QString value = QString();
146     if(xml.tokenType() == QXmlStreamReader::StartElement && (xml.name() == stringElement)) {
147         // Let's get the attributes
148         QXmlStreamAttributes attributes = xml.attributes();
149         // Let's check that element has the attribute
150         if(attributes.hasAttribute(stringAttribute)) {
151             value.append(attributes.value(stringAttribute).toString());
152         }
153     }
154     return value;
155 }
156
157 QString parseStringElement(QXmlStreamReader& xml,const char* stringElement){
158
159     // It is suposed the XML is valid!
160     QString value = QString();
161     if(xml.tokenType() == QXmlStreamReader::StartElement && (xml.name() == stringElement)) {
162         /* We've found the element */
163
164         xml.readNext();
165         if(xml.tokenType() == QXmlStreamReader::Characters) {
166
167             value.append(xml.text().toString());
168         }
169     }
170     return value;
171 }
172
173 qreal parseDoubleElement(QXmlStreamReader& xml,const char* stringElement){
174     // It is suposed the XML is valid!
175     qreal value=0;
176     if(xml.tokenType() == QXmlStreamReader::StartElement && (xml.name() == stringElement)) {
177         /* We've found the element */
178
179         xml.readNext();
180         if(xml.tokenType() == QXmlStreamReader::Characters) {
181             /* Now we can add it to the point.*/
182             QString valueString = xml.text().toString();
183             value=valueString.toDouble();
184         }
185     }
186     return value;
187 }
188
189 QDateTime parseDateElement(QXmlStreamReader& xml,const char* stringElement){
190     // It is suposed the XML is valid!
191     QDateTime value;
192     if(xml.tokenType() == QXmlStreamReader::StartElement && (xml.name() == stringElement)) {
193         /* We've found the element */
194
195         xml.readNext();
196         if(xml.tokenType() == QXmlStreamReader::Characters) {
197             /* Now we can add it to the point.*/
198             QString valueString = xml.text().toString();
199             value = QDateTime::fromString(valueString,XML_DATE_FORMAT);
200         }
201     }
202     return value;
203 }
204
205
206 GpsPoint* parseGPXGpsPoint(QXmlStreamReader& xml){
207     GpsPoint* point = new GpsPoint(0,0,0);
208     /* Let's check that we're really getting a Trackpoint. */
209     if(xml.tokenType() != QXmlStreamReader::StartElement &&
210             xml.name() == "trkpt") {
211         return point;
212     }
213     // Let's take latitude and longitude attributes.
214
215     point->setLatitude(parseDoubleAttribute(xml,"trkpt","lat"));
216     point->setLongitude(parseDoubleAttribute(xml,"trkpt","lon"));
217
218     xml.readNext();
219
220     while(!(xml.tokenType() == QXmlStreamReader::EndElement &&
221             xml.name() == "trkpt")){
222
223         if(xml.tokenType() == QXmlStreamReader::StartElement) {
224
225             if(xml.name() == "ele"){
226                 //qDebug()<<"found ele element";
227                 point->setElevation(parseDoubleElement(xml,"ele"));
228             }
229             if(xml.name() == "time"){
230                 point->setTime(parseDateElement(xml,"time"));
231                 //qDebug()<<"found Trackpoint element";
232             }
233         }
234         xml.readNext();
235     }
236     return point;
237 }
238
239 GpsPoint* parseTCXGpsPoint(QXmlStreamReader& xml){
240
241     GpsPoint* point = new GpsPoint(0,0,0);
242     /* Let's check that we're really getting a Trackpoint. */
243     if(xml.tokenType() != QXmlStreamReader::StartElement &&
244             xml.name() == "Trackpoint") {
245         return point;
246     }
247     xml.readNext();
248
249
250     while(!(xml.tokenType() == QXmlStreamReader::EndElement &&
251             xml.name() == "Trackpoint")){
252
253         if(xml.tokenType() == QXmlStreamReader::StartElement) {
254
255             if(xml.name() == "Time"){
256                 //qDebug()<<"found Time element";
257                 point->setTime(parseDateElement(xml,"Time"));
258             }
259             if(xml.name() == "Position"){
260                 //qDebug()<<"found Position element";
261                 xml.readNext();
262                 while(!(xml.tokenType() == QXmlStreamReader::EndElement &&
263                         xml.name() == "Position")){
264                     if(xml.tokenType()==QXmlStreamReader::StartElement && xml.name() == "LongitudeDegrees"){
265                         //qDebug()<<"found LongitudeDegrees element";
266                         point->setLongitude(parseDoubleElement(xml,"LongitudeDegrees"));
267                     }if(xml.tokenType()==QXmlStreamReader::StartElement && xml.name() == "LatitudeDegrees"){
268                         //qDebug()<<"found LatitudeDegrees element";
269                         point->setLatitude(parseDoubleElement(xml,"LatitudeDegrees"));
270                     }
271                     xml.readNext();
272                     //qDebug()<<"element readed: " << xml.name();
273                 }
274             }
275             if(xml.tokenType()==QXmlStreamReader::StartElement && xml.name() == "AltitudeMeters"){
276                 point->setElevation(parseDoubleElement(xml,"AltitudeMeters"));
277                 //qDebug()<<"found Trackpoint element";
278             }
279             if(xml.tokenType()==QXmlStreamReader::StartElement && xml.name() == "DistanceMeters"){
280                 point->setDistancePrev(parseDoubleElement(xml,"DistanceMeters"));
281                 //qDebug()<<"found Trackpoint element";
282             }
283         }
284         xml.readNext();
285     }
286     return point;
287 }
288