Subversion Repositories public

Rev

Rev 232 | 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,
313 andreas 252
                                    const QXmlAttributes& att)
224 andreas 253
{
254
int i = CON_FIRST;
313 andreas 255
int index;
224 andreas 256
 
257
	while (i <= CON_LAST)
258
	{
232 andreas 259
	   if (qName.toLower() == getKey(i).toLower())
224 andreas 260
	   {
232 andreas 261
	      if (qName.toLower() == QString("course") || qName.toLower() == QString("activity"))
224 andreas 262
	      {
263
		 memset (&run, 0, sizeof (D1009));
225 andreas 264
 
265
		 if (i == CON_ACTIVITY)
266
		 {
232 andreas 267
		    con = "activity";
225 andreas 268
		    history = true;
269
		 }
270
		 else
232 andreas 271
		    con = "course";
225 andreas 272
 
224 andreas 273
		 run.track_index = 0;
274
		 run.first_lap_index = 0;
313 andreas 275
		 // Find sport type, if there is one
276
		 if ((index = att.index(QString("Sport"))) != -1)
277
		 {
278
		    if (att.value(index).toAscii().toLower() == QString("Running").toLower())
279
				run.sport_type = D1000_running;
280
			else if (att.value(index).toAscii().toLower() == QString("Biking").toLower())
281
				run.sport_type = D1000_biking;
282
			else if (att.value(index).toAscii().toLower() == QString("Other").toLower())
283
				run.sport_type = D1000_other;
284
			else
285
				run.sport_type = D1000_other;
286
		 }
287
		 else
288
			run.sport_type = D1000_other;		// Other
289
 
224 andreas 290
		 tk = i;
291
	      }
292
 
232 andreas 293
	      if (qName.toLower() == QString("lap"))
224 andreas 294
	      {
295
		 memset (&lap, 0, sizeof (D1015));
296
		 lap.index = lpos;
297
		 lap.begin.lat = 0x7fffffff;
298
		 lap.begin.lon = 0x7fffffff;
299
		 lap.end.lat = 0x7fffffff;
300
		 lap.end.lon = 0x7fffffff;
232 andreas 301
		 con = "lap";
224 andreas 302
		 lpos++;
303
		 tk = i;
304
	      }
305
 
232 andreas 306
	      if (con == QString("lap") && qName.toLower() == QString("BeginPosition").toLower())
307
		 subCon = qName.toLower();
308
	      else if (con == QString("lap") && qName.toLower() == QString("EndPosition").toLower())
309
		 subCon = qName.toLower();
310
	      else if (con == QString("lap") && qName.toLower() == QString("AverageHeartRateBpm").toLower())
311
		 subCon = qName.toLower();
312
	      else if (con == QString("lap") && qName.toLower() == QString("MaximumHeartRateBpm").toLower())
313
		 subCon = qName.toLower();
224 andreas 314
 
232 andreas 315
	      if (history && qName.toLower() == QString("track") && con.toLower() == QString("lap"))
225 andreas 316
	      {
317
		 first_tpos = tpos + 1;
318
		 endElement (QString::null, QString::null, QString("Lap"));
319
		 indent++;
232 andreas 320
		 con = "lap";
225 andreas 321
		 fakeLap = true;
322
	      }
323
 
232 andreas 324
	      if (qName.toLower() == QString("trackpoint"))
224 andreas 325
	      {
326
		 memset (&point, 0, sizeof (D304));
327
		 point.alt = 1.0e24;
328
		 point.posn.lat = 0x7fffffff;
329
		 point.posn.lon = 0x7fffffff;
232 andreas 330
		 con = "trackpoint";
224 andreas 331
		 tpos++;
332
		 tk = i;
333
	      }
334
 
232 andreas 335
	      if (con == QString("trackpoint") && qName.toLower() == QString("position"))
336
		 subCon = qName.toLower();
337
	      else if (con == QString("trackpoint") && qName.toLower() == QString("heartratebpm"))
338
		 subCon = qName.toLower();
224 andreas 339
	   }
340
 
341
	   i++;
342
	}
343
 
344
	i = FLD_FIRST;
345
 
346
	while (i <= FLD_LAST)
347
	{
232 andreas 348
	   if (qName.toLower() == getKey(i).toLower())
224 andreas 349
	      tk = i;
350
 
351
	   i++;
352
	}
353
 
354
	indent++;
355
	return TRUE;
356
}
357
 
358
/*
359
 * This is called every time an element is closed.
360
 */
361
bool gmn_import::endElement( const QString&, const QString&, const QString& qName)
362
{
225 andreas 363
	if (!fakeLap)
364
	   indent--;
224 andreas 365
 
232 andreas 366
	if (qName.toLower() == QString("lap"))
224 andreas 367
	{
368
	   garmin_data *gdt;
369
	   garmin_list *l;
370
 
225 andreas 371
	   if (!fakeLap)
232 andreas 372
	      con.clear();
224 andreas 373
 
225 andreas 374
	   if (history && fakeLap)
375
	   {
376
	      fakeLap = false;
377
	      return TRUE;
378
	   }
379
 
224 andreas 380
	   if (!gmn)		/* allocating space for first structure */
381
	   {
382
	      if ((gmn = garmin_alloc_data (data_Dlist)) == NULL)
383
	      {
384
		 __error = 3;
385
		 return FALSE;
386
	      }
387
 
388
	      list = (garmin_list *)gmn->data;
389
	      /*
390
	       * This is the first data structure. It contains the total
391
	       * number of laps and the name of the course, if it was
392
	       * named.
393
	       */
394
	      if ((gdt = garmin_alloc_data (data_D1009)) == NULL)
395
	      {
396
		 __error = 6;
397
		 return FALSE;
398
	      }
399
 
400
	      memmove (gdt->data, &run, sizeof (D1009));
401
	      prun = (D1009 *)gdt->data;
402
 
403
	      if (ds)
404
		 ds->garmin_print_data (gdt);
405
 
406
	      if ((l = garmin_list_append (list, gdt)) == NULL)
407
	      {
408
		 __error = 7;
409
		 return FALSE;
410
	      }
411
 
412
	      list = l;
413
	   }
414
 
415
	   if (!list_lap)
416
	   {
417
	      if ((gmn_lap = garmin_alloc_data (data_Dlist)) == NULL)
418
	      {
419
		 __error = 3;
420
		 return FALSE;
421
	      }
422
 
423
	      list_lap = (garmin_list *)gmn_lap->data;
424
 
425
	      if (garmin_list_append (list, gmn_lap) == NULL)
426
	      {
427
		 __error = 7;
428
		 return FALSE;
429
	      }
430
 
431
	      list = list_lap;
432
	   }
433
	   else
434
	      list = list_lap;
435
 
436
	   if ((gdt = garmin_alloc_data (data_D1015)) == NULL)
437
	   {
438
	      __error = 4;
439
	      return FALSE;
440
	   }
441
 
442
	   memmove (gdt->data, &lap, sizeof (D1015));
225 andreas 443
	   plap = (D1015 *)gdt->data;
224 andreas 444
 
445
	   if (ds)
446
	      ds->garmin_print_data (gdt);
447
 
448
	   if ((l = garmin_list_append (list, gdt)) == NULL)
449
	   {
450
	      __error = 7;
451
	      return FALSE;
452
	   }
453
 
454
	   list = l;
455
	}
456
 
232 andreas 457
	if (history && qName.toLower() == QString("track"))
225 andreas 458
	   first_tpos = 0;
459
 
232 andreas 460
	if (qName.toLower() == QString("trackpoint"))
224 andreas 461
	{
462
	   garmin_data *gdt;
463
	   garmin_list *l;
464
 
232 andreas 465
	   con.clear();
224 andreas 466
 
467
	   if (!gmn)		/* allocating space for first structure */
468
	   {
469
	      if ((gmn = garmin_alloc_data (data_Dlist)) == NULL)
470
	      {
471
		 __error = 3;
472
		 return FALSE;
473
	      }
474
 
475
	      list = (garmin_list *)gmn->data;
476
	      /*
477
	       * This is the first data structure. It contains the total
478
	       * number of laps and the name of the course, if it was
479
	       * named.
480
	       */
481
	      if ((gdt = garmin_alloc_data (data_D1009)) == NULL)
482
	      {
483
		 __error = 6;
484
		 return FALSE;
485
	      }
486
 
487
	      memmove (gdt->data, &run, sizeof (D1009));
488
	      prun = (D1009 *)gdt->data;
489
 
490
	      if (ds)
491
		 ds->garmin_print_data (gdt);
492
 
493
	      if ((l = garmin_list_append (list, gdt)) == NULL)
494
	      {
495
		 __error = 7;
496
		 return FALSE;
497
	      }
498
 
499
	      list = l;
500
	   }
501
 
502
	   if (!list_track)
503
	   {
504
	      if ((gmn_track = garmin_alloc_data (data_Dlist)) == NULL)
505
	      {
506
		 __error = 3;
507
		 return FALSE;
508
	      }
509
 
510
	      list_track = (garmin_list *)gmn_track->data;
511
 
512
	      if (garmin_list_append (list, gmn_track) == NULL)
513
	      {
514
		 __error = 7;
515
		 return FALSE;
516
	      }
517
 
518
	      list = list_track;
519
	   }
520
	   else
521
	      list = list_track;
522
 
523
	   if ((gdt = garmin_alloc_data (data_D304)) == NULL)
524
	   {
525
	      __error = 5;
526
	      return FALSE;
527
	   }
528
 
529
	   memmove (gdt->data, &point, sizeof (D304));
530
 
531
	   if (ds)
532
	      ds->garmin_print_data (gdt);
533
 
534
	   if ((l = garmin_list_append (list, gdt)) == NULL)
535
	   {
536
	      __error = 7;
537
	      return FALSE;
538
	   }
539
 
540
	   list = l;
541
	}
542
 
232 andreas 543
	if (qName.toLower() == QString("course") || qName.toLower() == QString("activity"))
224 andreas 544
	{
232 andreas 545
	   con.clear();
224 andreas 546
	   run.track_index = tpos - 1;
547
	   run.last_lap_index = lpos - 1;
548
	   memmove (prun, &run, sizeof (D1009));
225 andreas 549
	   history = false;
224 andreas 550
	}
551
 
232 andreas 552
	if (qName.toLower() == QString("beginposition") || qName.toLower() == QString("endposition") ||
553
	    qName.toLower() == QString("averageheartratebpm") || qName.toLower() == QString("maximumheartratebpm"))
554
	   subCon.clear();
224 andreas 555
 
232 andreas 556
	if (qName.toLower() == QString("heartratebpm") || qName.toLower() == QString("position"))
557
	   subCon.clear();
224 andreas 558
 
559
	if (indent < 0)
560
	{
561
	   __error = 2;
562
	   return FALSE;
563
	}
564
 
565
	return TRUE;
566
}
567
 
568
/*
569
 * The reader calls this function when it has parsed a chunk of character data
570
 * - either normal character data or character data inside a CDATA section.
571
 */
572
bool gmn_import::characters (const QString& ch)
573
{
574
	if (con == QString("course"))
575
	{
576
	   if (tk == FLD_NAME)
577
	   {
232 andreas 578
	      strncpy (run.workout.name, ch.toAscii(), 15);
224 andreas 579
	      run.workout.name[15] = 0;
580
	      tk = 0;
581
	   }
582
	}
583
 
225 andreas 584
	if (history && con == QString("activity"))
585
	{
586
	   if (tk == FLD_ID)
587
	   {
232 andreas 588
	      strncpy (run.workout.name, ch.toAscii(), 15);
225 andreas 589
	      run.workout.name[15] = 0;
590
	      tk = 0;
591
	   }
592
	}
593
 
224 andreas 594
	if (con == QString("lap"))
595
	{
596
	   if (tk == FLD_DISTANCEMETERS)
597
	   {
598
	      lap.total_dist = (float32)ch.toFloat();
599
	      tk = 0;
600
	   }
601
 
602
	   if (tk == FLD_INTENSITY)
603
	   {
232 andreas 604
	      lap.intensity = (ch.toLower() == QString("activ")) ? 0 : 1;
224 andreas 605
	      tk = 0;
606
	   }
607
 
608
	   if (tk == FLD_STARTTIME)
609
	   {
610
	      lap.start_time = garmin_time (ch);
611
	      tk = 0;
612
	   }
613
 
614
	   if (tk == FLD_TOTALTIMESECONDS)
615
	   {
616
	      lap.total_time = (uint32)(ch.toDouble() * 100.0);
617
	      tk = 0;
618
	   }
619
 
620
	   if (tk == FLD_CADENCE)
621
	   {
622
	      lap.avg_cadence = (uint8)ch.toUInt();
623
	      tk = 0;
624
	   }
625
 
626
	   if (tk == FLD_CALORIES)
627
	   {
628
	      lap.calories = (uint16)ch.toUInt();
629
	      tk = 0;
630
	   }
631
 
632
	   if (tk == FLD_MAXSPEED)
633
	   {
634
	      lap.max_speed = (float32)ch.toFloat();
635
	      tk = 0;
636
	   }
637
 
225 andreas 638
	   if (tk == FLD_TRIGGERMETHOD)
639
	   {
232 andreas 640
	      if (ch.toLower() == QString("manual"))
225 andreas 641
		 lap.trigger_method = D1011_manual;
232 andreas 642
	      else if (ch.toLower() == QString("distance"))
225 andreas 643
		 lap.trigger_method = D1011_distance;
232 andreas 644
	      else if (ch.toLower() == QString("location"))
225 andreas 645
		 lap.trigger_method = D1011_location;
232 andreas 646
	      else if (ch.toLower() == QString("time"))
225 andreas 647
		 lap.trigger_method = D1011_time;
232 andreas 648
	      else if (ch.toLower() == QString("HeartRate"))
225 andreas 649
		 lap.trigger_method = D1011_heart_rate;
650
	   }
651
 
232 andreas 652
	   if (subCon.toLower() == QString("BeginPosition").toLower())
224 andreas 653
	   {
654
	      if (tk == FLD_LATITUDEDEGREES)
655
	      {
656
		 lap.begin.lat = (ch.toDouble() == 180.0) ? 0x7fffffff : (sint32)DEG2SEMI(ch.toDouble());
657
		 tk = 0;
658
	      }
659
 
660
	      if (tk == FLD_LONGITUDEDEGREES)
661
	      {
662
		 lap.begin.lon = (ch.toDouble() == 180.0) ? 0x7fffffff : (sint32)DEG2SEMI(ch.toDouble());
663
		 tk = 0;
664
	      }
665
	   }
232 andreas 666
	   else if (subCon.toLower() == QString("EndPosition").toLower())
224 andreas 667
	   {
668
	      if (tk == FLD_LATITUDEDEGREES)
669
	      {
670
		 lap.end.lat = (ch.toDouble() == 180.0) ? 0x7fffffff : (sint32)DEG2SEMI(ch.toDouble());
671
		 tk = 0;
672
	      }
673
 
674
	      if (tk == FLD_LONGITUDEDEGREES)
675
	      {
676
		 lap.end.lon = (ch.toDouble() == 180.0) ? 0x7fffffff : (sint32)DEG2SEMI(ch.toDouble());
677
		 tk = 0;
678
	      }
679
	   }
232 andreas 680
	   else if (subCon.toLower() == QString("AverageHeartRateBpm").toLower())
224 andreas 681
	   {
682
	      if (tk == FLD_VALUE)
683
	      {
684
		 lap.avg_heart_rate = (uint8)ch.toInt();
685
		 tk = 0;
686
	      }
687
	   }
232 andreas 688
	   else if (subCon.toLower() == QString("MaximumHeartRateBpm").toLower())
224 andreas 689
	   {
690
	      if (tk == FLD_VALUE)
691
	      {
692
		 lap.max_heart_rate = (uint8)ch.toInt();
693
		 tk = 0;
694
	      }
695
	   }
696
	}
697
 
698
	if (con == QString("trackpoint"))
699
	{
700
	   if (tk == FLD_TIME)
701
	   {
702
	      point.time = garmin_time (ch);
225 andreas 703
 
704
	      if (history && first_tpos == tpos && plap)
705
		 plap->start_time = point.time;
706
 
224 andreas 707
	      tk = 0;
708
	   }
709
 
710
	   if (tk == FLD_ALTITUDEMETERS)
711
	   {
712
	      point.alt = (ch.toFloat() >= 1.0e24) ? 1.0e24 : (float32)ch.toFloat();
713
	      tk = 0;
714
	   }
715
 
716
	   if (tk == FLD_DISTANCEMETERS)
717
	   {
718
	      point.distance = (ch.toFloat() >= 1.0e24) ? 1.0e24 : (float32)ch.toFloat();
719
	      tk = 0;
720
	   }
721
 
722
	   if (tk == FLD_SENSORSTATE)
723
	   {
232 andreas 724
	      point.sensor = (ch.toLower() == QString("absent")) ? false : true;
224 andreas 725
	      tk = 0;
726
	   }
727
 
232 andreas 728
	   if (subCon.toLower() == QString("position"))
224 andreas 729
	   {
730
	      if (tk == FLD_LATITUDEDEGREES)
731
	      {
732
		 point.posn.lat = (ch.toDouble() == 180.0) ? 0x7fffffff : (sint32)DEG2SEMI(ch.toDouble());
225 andreas 733
 
734
		 if (history && tpos == first_tpos && plap)	// Add mising information to first lap
735
		    plap->begin.lat = point.posn.lat;
736
		 else if (history && point.posn.lat != 0x7fffffff && plap)
737
		    plap->end.lat = point.posn.lat;
738
 
224 andreas 739
		 tk = 0;
740
	      }
741
 
742
	      if (tk == FLD_LONGITUDEDEGREES)
743
	      {
744
		 point.posn.lon = (ch.toDouble() == 180.0) ? 0x7fffffff : (sint32)DEG2SEMI(ch.toDouble());
225 andreas 745
 
746
		 if (history && tpos == first_tpos && plap)	// Add mising information to first lap
747
		    plap->begin.lon = point.posn.lon;
748
		 else if (history && point.posn.lon != 0x7fffffff && plap)
749
		    plap->end.lat = point.posn.lon;
750
 
224 andreas 751
		 tk = 0;
752
	      }
753
	   }
232 andreas 754
	   else if (subCon.toLower() == QString("heartratebpm"))
224 andreas 755
	   {
756
	      if (tk == FLD_VALUE)
757
	      {
758
		 point.heart_rate = (unsigned char)ch.toInt();
759
		 tk = 0;
760
	      }
761
	   }
762
	}
763
 
764
	return TRUE;
765
}
766
 
767
/*
768
 * The following function reads a Garmin HST file, parses the XML
769
 * content and creates the gmn files. If there already exists a file,
770
 * it's not overwritten.
771
 */
772
int gmn_import::import ()
773
{
774
QXmlSimpleReader reader;
775
 
776
	if (!qfstat)
777
	   return 1;
778
 
779
	QXmlInputSource source (&file);
780
	reader.setContentHandler (this);
781
	reader.parse (source);
782
	return 0;
783
}
784
 
785
QString gmn_import::getKey (int pos)
786
{
787
int i = 0;
788
 
789
	while (keys[i].id > 0)
790
	{
791
	   if (keys[i].id == pos)
792
	      return keys[i].name;
793
 
794
	   i++;
795
	}
796
 
797
	return QString::null;
798
}
799
 
800
QString gmn_import::getError (int err)
801
{
802
	if (err > eMax || err < 1)
803
	   return 0;
804
 
805
	return getKey (ERR_FIRST + err);
806
}
807
 
808
QString gmn_import::getError ()
809
{
810
	return getKey (ERR_FIRST + __error);
811
}
812