Subversion Repositories public

Rev

Rev 313 | Details | Compare with Previous | Last modification | View Log | RSS feed

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