Subversion Repositories public

Rev

Rev 225 | Rev 313 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
224 andreas 1
/***************************************************************************
232 andreas 2
 *   Copyright (C) 2007 - 2009 by Andreas Theofilu                         *
224 andreas 3
 *   andreas@theosys.at                                                    *
4
 *                                                                         *
5
 *   This program is free software; you can redistribute it and/or modify  *
6
 *   it under the terms of the GNU General Public License as published by  *
7
 *   the Free Software Foundation version 3 of the License.                *
8
 *                                                                         *
9
 *   This program is distributed in the hope that it will be useful,       *
10
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12
 *   GNU General Public License for more details.                          *
13
 *                                                                         *
14
 *   You should have received a copy of the GNU General Public License     *
15
 *   along with this program; if not, write to the                         *
16
 *   Free Software Foundation, Inc.,                                       *
17
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18
 ***************************************************************************/
19
#include <time.h>
20
#include <string.h>
21
#include <math.h>
22
 
23
#include <qlistview.h>
24
#include <qdatetime.h>
232 andreas 25
#include <QXmlReader>
224 andreas 26
 
27
#include <klocale.h>
28
 
29
#include "import.h"
30
 
31
#define FLD_NAME		1
32
#define FLD_TOTALTIMESECONDS	2
33
#define FLD_DISTANCEMETERS	3
34
#define FLD_LATITUDEDEGREES	4
35
#define FLD_LONGITUDEDEGREES	5
36
#define FLD_VALUE		6
37
#define FLD_INTENSITY		7
38
#define FLD_TIME		8
39
#define FLD_ALTITUDEMETERS	9
40
#define FLD_SENSORSTATE		10
41
#define FLD_STARTTIME		11
42
#define FLD_AVERAGECADENCE	12
43
#define FLD_SPORTTYPE		13
44
#define FLD_VERSIONMAJOR	14
45
#define FLD_VERSIONMINOR	15
46
#define FLD_BUILDMAJOR		16
47
#define FLD_BUILDMINOR		17
48
#define FLD_TYPE		18
49
#define FLD_BUILDER		19
50
#define FLD_LANGID		20
51
#define FLD_PARTNUMBER		21
52
#define FLD_CADENCE		22
53
#define FLD_MAXSPEED		23
54
#define FLD_CALORIES		24
225 andreas 55
#define FLD_ID			25
56
#define FLD_TRIGGERMETHOD	26
57
#define FLD_TPX			27
58
#define FLD_UNITID		28
59
#define FLD_PRODUCTID		29
60
#define FLD_NOTES		30
224 andreas 61
 
62
#define CON_COURSES		100
63
#define CON_COURSE		101
64
#define CON_LAP			102
65
#define CON_BEGINPOSITION	103
66
#define CON_ENDPOSITION		104
67
#define CON_AVERAGEHEARTRATEBPM	105
68
#define CON_MAXIMUMHEARTRATEBPM	106
69
#define CON_TRACK		107
70
#define CON_TRACKPOINT		108
71
#define CON_POSITION		109
72
#define CON_HEARTRATEBPM	110
73
#define CON_AUTHOR		111
74
#define CON_VERSION		112
75
#define CON_BUILD		113
225 andreas 76
#define CON_ACTIVITY		114
77
#define CON_EXTENSIONS		115
78
#define CON_CREATOR		116
79
#define CON_MULTISPORTSESSION	117
80
#define CON_FIRSTSPORT		118
81
#define CON_NEXTSPORT		119
82
#define CON_TRAINING		120
83
#define CON_QUICKWORKOUTRESULTS	121
224 andreas 84
 
225 andreas 85
#define ATT_CADENCESENSOR	200
86
 
224 andreas 87
#define STOPSTOP		0
88
 
89
KEYS keys[] = {
90
	/* Fields */
91
	{ FLD_NAME,			QString("name") },
92
	{ FLD_TOTALTIMESECONDS,		QString("TotalTimeSeconds") },
93
	{ FLD_DISTANCEMETERS,		QString("DistanceMeters") },
94
	{ FLD_LATITUDEDEGREES,		QString("LatitudeDegrees") },
95
	{ FLD_LONGITUDEDEGREES,		QString("LongitudeDegrees") },
96
	{ FLD_VALUE,			QString("Value") },
97
	{ FLD_INTENSITY,		QString("Intensity") },
98
	{ FLD_TIME,			QString("Time") },
99
	{ FLD_ALTITUDEMETERS,		QString("AltitudeMeters") },
100
	{ FLD_SENSORSTATE,		QString("SensorState") },
101
	{ FLD_STARTTIME,		QString("StartTime") },
102
	{ FLD_AVERAGECADENCE,		QString("AverageCadence") },
103
	{ FLD_SPORTTYPE,		QString("SportType") },
104
	{ FLD_VERSIONMAJOR,		QString("VersionMajor") },
105
	{ FLD_VERSIONMINOR,		QString("VersionMinor") },
106
	{ FLD_BUILDMAJOR,		QString("BuildMajor") },
107
	{ FLD_BUILDMINOR,		QString("BuildMinor") },
108
	{ FLD_TYPE,			QString("Type") },
109
	{ FLD_BUILDER,			QString("Builder") },
110
	{ FLD_LANGID,			QString("LangID") },
111
	{ FLD_PARTNUMBER,		QString("PartNumber") },
112
	{ FLD_CADENCE,			QString("Cadence") },
113
	{ FLD_CALORIES,			QString("Calories") },
114
	{ FLD_MAXSPEED,			QString("MaximumSpeed") },
225 andreas 115
	{ FLD_ID,			QString("Id") },
116
	{ FLD_TRIGGERMETHOD,		QString("TriggerMethod") },
117
	{ FLD_TPX,			QString("TPX") },
118
	{ FLD_UNITID,			QString("UnitId") },
119
	{ FLD_PRODUCTID,		QString("ProductID") },
120
	{ FLD_NOTES,			QString("Notes") },
121
	/* Attributes */
122
	{ ATT_CADENCESENSOR,		QString("CadenceSensor") },
224 andreas 123
	/* Container */
124
	{ CON_COURSES,			QString("Courses") },
125
	{ CON_COURSE,			QString("Course") },
126
	{ CON_LAP,			QString("Lap") },
127
	{ CON_BEGINPOSITION,		QString("BeginPosition") },
128
	{ CON_ENDPOSITION,		QString("EndPosition") },
129
	{ CON_AVERAGEHEARTRATEBPM,	QString("AverageHeartRateBpm") },
130
	{ CON_MAXIMUMHEARTRATEBPM,	QString("MaximumHeartRateBpm") },
131
	{ CON_TRACK,			QString("Track") },
132
	{ CON_TRACKPOINT,		QString("Trackpoint") },
133
	{ CON_POSITION,			QString("Position") },
134
	{ CON_HEARTRATEBPM,		QString("HeartRateBpm") },
135
	{ CON_AUTHOR,			QString("Author") },
136
	{ CON_VERSION,			QString("Version") },
137
	{ CON_BUILD,			QString("Build") },
225 andreas 138
	{ CON_ACTIVITY,			QString("Activity") },
139
	{ CON_EXTENSIONS,		QString("Extensions") },
140
	{ CON_CREATOR,			QString("Creator") },
141
	{ CON_MULTISPORTSESSION,	QString("MultiSportSession") },
142
	{ CON_FIRSTSPORT,		QString("FirstSport") },
143
	{ CON_NEXTSPORT,		QString("NextSport") },
144
	{ CON_TRAINING,			QString("Training") },
145
	{ CON_QUICKWORKOUTRESULTS,	QString("QuickWorkoutResults") },
224 andreas 146
	/* Errors */
147
	{ ERR_OK,			QString("OK") },	// this is no error
148
	{ ERR_NOFILE,			i18n("IMPORT: No file name to parse XML!") },	// but this
149
	{ ERR_TAGS,			i18n("IMPORT: More end tags than open tags! Invalid XML file.") },
150
	{ ERR_ALLOCGMN,			i18n("IMPORT: Error allocating memory for base Garmin structure.") },
151
	{ ERR_ALLOCLAP,			i18n("IMPORT: Error allocating memory for a lap.") },
152
	{ ERR_ALLOCPOINT,		i18n("IMPORT: Error allocating memory for a track point.") },
153
	{ ERR_ALLOCRUN,			i18n("IMPORT: Error allocating memory for running information.") },
154
	{ ERR_ALLOCLIST,		i18n("IMPORT: Error allocating memory for a list node.") },
155
	{ STOPSTOP,			QString::null }
156
};
157
 
158
void gmn_import::Initialize()
159
{
160
	qfstat = false;
161
	qfopen = false;
162
	__error = 0;
163
	gmn = 0;
164
	list_lap = list_track = 0;
165
	ds = 0;
225 andreas 166
	history = false;
224 andreas 167
}
168
 
169
gmn_import::gmn_import (const QFile &qfile)
170
{
171
	Initialize ();
232 andreas 172
	file.setFileName (qfile.fileName ());
224 andreas 173
 
174
	if (file.exists ())
175
	   qfstat = true;
176
}
177
 
178
void gmn_import::setFile (const QFile &qfile)
179
{
180
	if (qfopen)
181
	{
182
	   file.close ();
183
	   qfopen = false;
184
	}
185
 
186
	qfstat = false;
232 andreas 187
	file.setFileName (qfile.fileName ());
224 andreas 188
 
189
	if (file.exists ())
190
	   qfstat = true;
191
}
192
 
193
void gmn_import::setFile (const QString &sfile)
194
{
195
	if (qfopen)
196
	{
197
	   file.close ();
198
	   qfopen = false;
199
	   __error = 1;
200
	}
201
 
202
	qfstat = false;
232 andreas 203
	file.setFileName (sfile);
224 andreas 204
 
205
	if (file.exists ())
206
	   qfstat = true;
207
}
208
 
209
/*
210
 * Convert an ISO8601 formated date into garmin epoch.
211
 */
212
unsigned int gmn_import::garmin_time (const QString& tstamp)
213
{
214
QDateTime dt;
215
time_t tval;
216
 
217
	/*
218
	 * tstamp should contain a valid ISO8601 formated date and time stamp.
219
	 * We will convert it to a kind of epoch, but with a garmin specific
220
	 * offset.
221
	 */
222
	dt = dt.fromString(tstamp, Qt::ISODate);
223
 
224
	if (!dt.isValid())
225
	   return 0;
226
 
227
	tval = dt.toTime_t() - TIME_OFFSET;
228
	return (unsigned int)tval;
229
}
230
 
231
/*
232
 * This function initializes the XML parser.
233
 */
234
bool gmn_import::startDocument()
235
{
236
	indent = 0;
232 andreas 237
	con.clear();
238
	subCon.clear();
224 andreas 239
	lpos = tpos = oldLPos = 0;
225 andreas 240
	history = fakeLap = false;
241
	first_tpos = 0;
242
	prun = 0;
243
	plap = 0;
224 andreas 244
	return TRUE;
245
}
246
 
247
/*
248
 * This is called every time a new start element was parsed.
249
 */
250
bool gmn_import::startElement( const QString&, const QString&,
251
                                    const QString& qName,
252
                                    const QXmlAttributes&)
253
{
254
int i = CON_FIRST;
255
 
256
	while (i <= CON_LAST)
257
	{
232 andreas 258
	   if (qName.toLower() == getKey(i).toLower())
224 andreas 259
	   {
232 andreas 260
	      if (qName.toLower() == QString("course") || qName.toLower() == QString("activity"))
224 andreas 261
	      {
262
		 memset (&run, 0, sizeof (D1009));
225 andreas 263
 
264
		 if (i == CON_ACTIVITY)
265
		 {
232 andreas 266
		    con = "activity";
225 andreas 267
		    history = true;
268
		 }
269
		 else
232 andreas 270
		    con = "course";
225 andreas 271
 
224 andreas 272
		 run.track_index = 0;
273
		 run.first_lap_index = 0;
274
		 run.sport_type = 0;		// Running
275
		 tk = i;
276
	      }
277
 
232 andreas 278
	      if (qName.toLower() == QString("lap"))
224 andreas 279
	      {
280
		 memset (&lap, 0, sizeof (D1015));
281
		 lap.index = lpos;
282
		 lap.begin.lat = 0x7fffffff;
283
		 lap.begin.lon = 0x7fffffff;
284
		 lap.end.lat = 0x7fffffff;
285
		 lap.end.lon = 0x7fffffff;
232 andreas 286
		 con = "lap";
224 andreas 287
		 lpos++;
288
		 tk = i;
289
	      }
290
 
232 andreas 291
	      if (con == QString("lap") && qName.toLower() == QString("BeginPosition").toLower())
292
		 subCon = qName.toLower();
293
	      else if (con == QString("lap") && qName.toLower() == QString("EndPosition").toLower())
294
		 subCon = qName.toLower();
295
	      else if (con == QString("lap") && qName.toLower() == QString("AverageHeartRateBpm").toLower())
296
		 subCon = qName.toLower();
297
	      else if (con == QString("lap") && qName.toLower() == QString("MaximumHeartRateBpm").toLower())
298
		 subCon = qName.toLower();
224 andreas 299
 
232 andreas 300
	      if (history && qName.toLower() == QString("track") && con.toLower() == QString("lap"))
225 andreas 301
	      {
302
		 first_tpos = tpos + 1;
303
		 endElement (QString::null, QString::null, QString("Lap"));
304
		 indent++;
232 andreas 305
		 con = "lap";
225 andreas 306
		 fakeLap = true;
307
	      }
308
 
232 andreas 309
	      if (qName.toLower() == QString("trackpoint"))
224 andreas 310
	      {
311
		 memset (&point, 0, sizeof (D304));
312
		 point.alt = 1.0e24;
313
		 point.posn.lat = 0x7fffffff;
314
		 point.posn.lon = 0x7fffffff;
232 andreas 315
		 con = "trackpoint";
224 andreas 316
		 tpos++;
317
		 tk = i;
318
	      }
319
 
232 andreas 320
	      if (con == QString("trackpoint") && qName.toLower() == QString("position"))
321
		 subCon = qName.toLower();
322
	      else if (con == QString("trackpoint") && qName.toLower() == QString("heartratebpm"))
323
		 subCon = qName.toLower();
224 andreas 324
	   }
325
 
326
	   i++;
327
	}
328
 
329
	i = FLD_FIRST;
330
 
331
	while (i <= FLD_LAST)
332
	{
232 andreas 333
	   if (qName.toLower() == getKey(i).toLower())
224 andreas 334
	      tk = i;
335
 
336
	   i++;
337
	}
338
 
339
	indent++;
340
	return TRUE;
341
}
342
 
343
/*
344
 * This is called every time an element is closed.
345
 */
346
bool gmn_import::endElement( const QString&, const QString&, const QString& qName)
347
{
225 andreas 348
	if (!fakeLap)
349
	   indent--;
224 andreas 350
 
232 andreas 351
	if (qName.toLower() == QString("lap"))
224 andreas 352
	{
353
	   garmin_data *gdt;
354
	   garmin_list *l;
355
 
225 andreas 356
	   if (!fakeLap)
232 andreas 357
	      con.clear();
224 andreas 358
 
225 andreas 359
	   if (history && fakeLap)
360
	   {
361
	      fakeLap = false;
362
	      return TRUE;
363
	   }
364
 
224 andreas 365
	   if (!gmn)		/* allocating space for first structure */
366
	   {
367
	      if ((gmn = garmin_alloc_data (data_Dlist)) == NULL)
368
	      {
369
		 __error = 3;
370
		 return FALSE;
371
	      }
372
 
373
	      list = (garmin_list *)gmn->data;
374
	      /*
375
	       * This is the first data structure. It contains the total
376
	       * number of laps and the name of the course, if it was
377
	       * named.
378
	       */
379
	      if ((gdt = garmin_alloc_data (data_D1009)) == NULL)
380
	      {
381
		 __error = 6;
382
		 return FALSE;
383
	      }
384
 
385
	      memmove (gdt->data, &run, sizeof (D1009));
386
	      prun = (D1009 *)gdt->data;
387
 
388
	      if (ds)
389
		 ds->garmin_print_data (gdt);
390
 
391
	      if ((l = garmin_list_append (list, gdt)) == NULL)
392
	      {
393
		 __error = 7;
394
		 return FALSE;
395
	      }
396
 
397
	      list = l;
398
	   }
399
 
400
	   if (!list_lap)
401
	   {
402
	      if ((gmn_lap = garmin_alloc_data (data_Dlist)) == NULL)
403
	      {
404
		 __error = 3;
405
		 return FALSE;
406
	      }
407
 
408
	      list_lap = (garmin_list *)gmn_lap->data;
409
 
410
	      if (garmin_list_append (list, gmn_lap) == NULL)
411
	      {
412
		 __error = 7;
413
		 return FALSE;
414
	      }
415
 
416
	      list = list_lap;
417
	   }
418
	   else
419
	      list = list_lap;
420
 
421
	   if ((gdt = garmin_alloc_data (data_D1015)) == NULL)
422
	   {
423
	      __error = 4;
424
	      return FALSE;
425
	   }
426
 
427
	   memmove (gdt->data, &lap, sizeof (D1015));
225 andreas 428
	   plap = (D1015 *)gdt->data;
224 andreas 429
 
430
	   if (ds)
431
	      ds->garmin_print_data (gdt);
432
 
433
	   if ((l = garmin_list_append (list, gdt)) == NULL)
434
	   {
435
	      __error = 7;
436
	      return FALSE;
437
	   }
438
 
439
	   list = l;
440
	}
441
 
232 andreas 442
	if (history && qName.toLower() == QString("track"))
225 andreas 443
	   first_tpos = 0;
444
 
232 andreas 445
	if (qName.toLower() == QString("trackpoint"))
224 andreas 446
	{
447
	   garmin_data *gdt;
448
	   garmin_list *l;
449
 
232 andreas 450
	   con.clear();
224 andreas 451
 
452
	   if (!gmn)		/* allocating space for first structure */
453
	   {
454
	      if ((gmn = garmin_alloc_data (data_Dlist)) == NULL)
455
	      {
456
		 __error = 3;
457
		 return FALSE;
458
	      }
459
 
460
	      list = (garmin_list *)gmn->data;
461
	      /*
462
	       * This is the first data structure. It contains the total
463
	       * number of laps and the name of the course, if it was
464
	       * named.
465
	       */
466
	      if ((gdt = garmin_alloc_data (data_D1009)) == NULL)
467
	      {
468
		 __error = 6;
469
		 return FALSE;
470
	      }
471
 
472
	      memmove (gdt->data, &run, sizeof (D1009));
473
	      prun = (D1009 *)gdt->data;
474
 
475
	      if (ds)
476
		 ds->garmin_print_data (gdt);
477
 
478
	      if ((l = garmin_list_append (list, gdt)) == NULL)
479
	      {
480
		 __error = 7;
481
		 return FALSE;
482
	      }
483
 
484
	      list = l;
485
	   }
486
 
487
	   if (!list_track)
488
	   {
489
	      if ((gmn_track = garmin_alloc_data (data_Dlist)) == NULL)
490
	      {
491
		 __error = 3;
492
		 return FALSE;
493
	      }
494
 
495
	      list_track = (garmin_list *)gmn_track->data;
496
 
497
	      if (garmin_list_append (list, gmn_track) == NULL)
498
	      {
499
		 __error = 7;
500
		 return FALSE;
501
	      }
502
 
503
	      list = list_track;
504
	   }
505
	   else
506
	      list = list_track;
507
 
508
	   if ((gdt = garmin_alloc_data (data_D304)) == NULL)
509
	   {
510
	      __error = 5;
511
	      return FALSE;
512
	   }
513
 
514
	   memmove (gdt->data, &point, sizeof (D304));
515
 
516
	   if (ds)
517
	      ds->garmin_print_data (gdt);
518
 
519
	   if ((l = garmin_list_append (list, gdt)) == NULL)
520
	   {
521
	      __error = 7;
522
	      return FALSE;
523
	   }
524
 
525
	   list = l;
526
	}
527
 
232 andreas 528
	if (qName.toLower() == QString("course") || qName.toLower() == QString("activity"))
224 andreas 529
	{
232 andreas 530
	   con.clear();
224 andreas 531
	   run.track_index = tpos - 1;
532
	   run.last_lap_index = lpos - 1;
533
	   memmove (prun, &run, sizeof (D1009));
225 andreas 534
	   history = false;
224 andreas 535
	}
536
 
232 andreas 537
	if (qName.toLower() == QString("beginposition") || qName.toLower() == QString("endposition") ||
538
	    qName.toLower() == QString("averageheartratebpm") || qName.toLower() == QString("maximumheartratebpm"))
539
	   subCon.clear();
224 andreas 540
 
232 andreas 541
	if (qName.toLower() == QString("heartratebpm") || qName.toLower() == QString("position"))
542
	   subCon.clear();
224 andreas 543
 
544
	if (indent < 0)
545
	{
546
	   __error = 2;
547
	   return FALSE;
548
	}
549
 
550
	return TRUE;
551
}
552
 
553
/*
554
 * The reader calls this function when it has parsed a chunk of character data
555
 * - either normal character data or character data inside a CDATA section.
556
 */
557
bool gmn_import::characters (const QString& ch)
558
{
559
	if (con == QString("course"))
560
	{
561
	   if (tk == FLD_NAME)
562
	   {
232 andreas 563
	      strncpy (run.workout.name, ch.toAscii(), 15);
224 andreas 564
	      run.workout.name[15] = 0;
565
	      tk = 0;
566
	   }
567
	}
568
 
225 andreas 569
	if (history && con == QString("activity"))
570
	{
571
	   if (tk == FLD_ID)
572
	   {
232 andreas 573
	      strncpy (run.workout.name, ch.toAscii(), 15);
225 andreas 574
	      run.workout.name[15] = 0;
575
	      tk = 0;
576
	   }
577
	}
578
 
224 andreas 579
	if (con == QString("lap"))
580
	{
581
	   if (tk == FLD_DISTANCEMETERS)
582
	   {
583
	      lap.total_dist = (float32)ch.toFloat();
584
	      tk = 0;
585
	   }
586
 
587
	   if (tk == FLD_INTENSITY)
588
	   {
232 andreas 589
	      lap.intensity = (ch.toLower() == QString("activ")) ? 0 : 1;
224 andreas 590
	      tk = 0;
591
	   }
592
 
593
	   if (tk == FLD_STARTTIME)
594
	   {
595
	      lap.start_time = garmin_time (ch);
596
	      tk = 0;
597
	   }
598
 
599
	   if (tk == FLD_TOTALTIMESECONDS)
600
	   {
601
	      lap.total_time = (uint32)(ch.toDouble() * 100.0);
602
	      tk = 0;
603
	   }
604
 
605
	   if (tk == FLD_CADENCE)
606
	   {
607
	      lap.avg_cadence = (uint8)ch.toUInt();
608
	      tk = 0;
609
	   }
610
 
611
	   if (tk == FLD_CALORIES)
612
	   {
613
	      lap.calories = (uint16)ch.toUInt();
614
	      tk = 0;
615
	   }
616
 
617
	   if (tk == FLD_MAXSPEED)
618
	   {
619
	      lap.max_speed = (float32)ch.toFloat();
620
	      tk = 0;
621
	   }
622
 
225 andreas 623
	   if (tk == FLD_TRIGGERMETHOD)
624
	   {
232 andreas 625
	      if (ch.toLower() == QString("manual"))
225 andreas 626
		 lap.trigger_method = D1011_manual;
232 andreas 627
	      else if (ch.toLower() == QString("distance"))
225 andreas 628
		 lap.trigger_method = D1011_distance;
232 andreas 629
	      else if (ch.toLower() == QString("location"))
225 andreas 630
		 lap.trigger_method = D1011_location;
232 andreas 631
	      else if (ch.toLower() == QString("time"))
225 andreas 632
		 lap.trigger_method = D1011_time;
232 andreas 633
	      else if (ch.toLower() == QString("HeartRate"))
225 andreas 634
		 lap.trigger_method = D1011_heart_rate;
635
	   }
636
 
232 andreas 637
	   if (subCon.toLower() == QString("BeginPosition").toLower())
224 andreas 638
	   {
639
	      if (tk == FLD_LATITUDEDEGREES)
640
	      {
641
		 lap.begin.lat = (ch.toDouble() == 180.0) ? 0x7fffffff : (sint32)DEG2SEMI(ch.toDouble());
642
		 tk = 0;
643
	      }
644
 
645
	      if (tk == FLD_LONGITUDEDEGREES)
646
	      {
647
		 lap.begin.lon = (ch.toDouble() == 180.0) ? 0x7fffffff : (sint32)DEG2SEMI(ch.toDouble());
648
		 tk = 0;
649
	      }
650
	   }
232 andreas 651
	   else if (subCon.toLower() == QString("EndPosition").toLower())
224 andreas 652
	   {
653
	      if (tk == FLD_LATITUDEDEGREES)
654
	      {
655
		 lap.end.lat = (ch.toDouble() == 180.0) ? 0x7fffffff : (sint32)DEG2SEMI(ch.toDouble());
656
		 tk = 0;
657
	      }
658
 
659
	      if (tk == FLD_LONGITUDEDEGREES)
660
	      {
661
		 lap.end.lon = (ch.toDouble() == 180.0) ? 0x7fffffff : (sint32)DEG2SEMI(ch.toDouble());
662
		 tk = 0;
663
	      }
664
	   }
232 andreas 665
	   else if (subCon.toLower() == QString("AverageHeartRateBpm").toLower())
224 andreas 666
	   {
667
	      if (tk == FLD_VALUE)
668
	      {
669
		 lap.avg_heart_rate = (uint8)ch.toInt();
670
		 tk = 0;
671
	      }
672
	   }
232 andreas 673
	   else if (subCon.toLower() == QString("MaximumHeartRateBpm").toLower())
224 andreas 674
	   {
675
	      if (tk == FLD_VALUE)
676
	      {
677
		 lap.max_heart_rate = (uint8)ch.toInt();
678
		 tk = 0;
679
	      }
680
	   }
681
	}
682
 
683
	if (con == QString("trackpoint"))
684
	{
685
	   if (tk == FLD_TIME)
686
	   {
687
	      point.time = garmin_time (ch);
225 andreas 688
 
689
	      if (history && first_tpos == tpos && plap)
690
		 plap->start_time = point.time;
691
 
224 andreas 692
	      tk = 0;
693
	   }
694
 
695
	   if (tk == FLD_ALTITUDEMETERS)
696
	   {
697
	      point.alt = (ch.toFloat() >= 1.0e24) ? 1.0e24 : (float32)ch.toFloat();
698
	      tk = 0;
699
	   }
700
 
701
	   if (tk == FLD_DISTANCEMETERS)
702
	   {
703
	      point.distance = (ch.toFloat() >= 1.0e24) ? 1.0e24 : (float32)ch.toFloat();
704
	      tk = 0;
705
	   }
706
 
707
	   if (tk == FLD_SENSORSTATE)
708
	   {
232 andreas 709
	      point.sensor = (ch.toLower() == QString("absent")) ? false : true;
224 andreas 710
	      tk = 0;
711
	   }
712
 
232 andreas 713
	   if (subCon.toLower() == QString("position"))
224 andreas 714
	   {
715
	      if (tk == FLD_LATITUDEDEGREES)
716
	      {
717
		 point.posn.lat = (ch.toDouble() == 180.0) ? 0x7fffffff : (sint32)DEG2SEMI(ch.toDouble());
225 andreas 718
 
719
		 if (history && tpos == first_tpos && plap)	// Add mising information to first lap
720
		    plap->begin.lat = point.posn.lat;
721
		 else if (history && point.posn.lat != 0x7fffffff && plap)
722
		    plap->end.lat = point.posn.lat;
723
 
224 andreas 724
		 tk = 0;
725
	      }
726
 
727
	      if (tk == FLD_LONGITUDEDEGREES)
728
	      {
729
		 point.posn.lon = (ch.toDouble() == 180.0) ? 0x7fffffff : (sint32)DEG2SEMI(ch.toDouble());
225 andreas 730
 
731
		 if (history && tpos == first_tpos && plap)	// Add mising information to first lap
732
		    plap->begin.lon = point.posn.lon;
733
		 else if (history && point.posn.lon != 0x7fffffff && plap)
734
		    plap->end.lat = point.posn.lon;
735
 
224 andreas 736
		 tk = 0;
737
	      }
738
	   }
232 andreas 739
	   else if (subCon.toLower() == QString("heartratebpm"))
224 andreas 740
	   {
741
	      if (tk == FLD_VALUE)
742
	      {
743
		 point.heart_rate = (unsigned char)ch.toInt();
744
		 tk = 0;
745
	      }
746
	   }
747
	}
748
 
749
	return TRUE;
750
}
751
 
752
/*
753
 * The following function reads a Garmin HST file, parses the XML
754
 * content and creates the gmn files. If there already exists a file,
755
 * it's not overwritten.
756
 */
757
int gmn_import::import ()
758
{
759
QXmlSimpleReader reader;
760
 
761
	if (!qfstat)
762
	   return 1;
763
 
764
	QXmlInputSource source (&file);
765
	reader.setContentHandler (this);
766
	reader.parse (source);
767
	return 0;
768
}
769
 
770
QString gmn_import::getKey (int pos)
771
{
772
int i = 0;
773
 
774
	while (keys[i].id > 0)
775
	{
776
	   if (keys[i].id == pos)
777
	      return keys[i].name;
778
 
779
	   i++;
780
	}
781
 
782
	return QString::null;
783
}
784
 
785
QString gmn_import::getError (int err)
786
{
787
	if (err > eMax || err < 1)
788
	   return 0;
789
 
790
	return getKey (ERR_FIRST + err);
791
}
792
 
793
QString gmn_import::getError ()
794
{
795
	return getKey (ERR_FIRST + __error);
796
}
797