Subversion Repositories public

Rev

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

Rev Author Line No. Line
88 andreas 1
/***************************************************************************
2
 *   Copyright (C) 2007 by Andreas Theofilu                               *
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
 
20
 
21
#include "managefile.h"
22
#include "sportwatcherwidget.h"
23
#include "settingswidget.h"
96 andreas 24
#include "progresswidget.h"
25
 
88 andreas 26
 #include <iostream.h>
27
#include <kfiledialog.h>
28
#include <kmessagebox.h>
29
#include <ksimpleconfig.h>
30
#include <klocale.h>
31
#include <klistview.h>
32
#include <qstring.h>
33
#include <qdatetime.h>
34
 
35
sportwatcherWidget::sportwatcherWidget(QWidget* parent, const char* name, WFlags fl)
36
: sportwatcherWidgetBase(parent,name,fl)
37
{
38
	mama = parent;
39
	gmn = 0;
40
	min_hr = max_hr = avg_hr = 0;
41
	min_height = max_height = 0.0;
42
	max_time = 0;
43
	index = 0;
44
	// Load the config parameters
45
	KSimpleConfig *cfg = new KSimpleConfig(QString("sportwatcher.rc"), true);
46
	cfg->setGroup(QString("SportWatcher"));
47
	lower1 = cfg->readNumEntry("lower1");
48
	lower2 = cfg->readNumEntry("lower2");
49
	lower3 = cfg->readNumEntry("lower3");
50
	upper1 = cfg->readNumEntry("upper1");
51
	upper2 = cfg->readNumEntry("upper2");
52
	upper3 = cfg->readNumEntry("upper3");
53
	MaxHr = cfg->readNumEntry("maxHr");
54
	restHr = cfg->readNumEntry("restHr");
55
	vo2max = cfg->readNumEntry("vo2max");
56
	weight = cfg->readNumEntry("weight");
57
	sampleTime = cfg->readNumEntry("seconds");
58
	Device = cfg->readEntry("Device", "/dev/ttyUSB0");
59
	Data = cfg->readEntry("Data");
60
	HRM = cfg->readEntry("HRM");
61
	delete cfg;
62
	// Fill the activities
63
	getActivities();
64
}
65
 
66
sportwatcherWidget::~sportwatcherWidget()
67
{
68
	if (gmn)
69
	   garmin_free_data (gmn);
70
 
71
	if (index)
72
	{
73
	INDEX *n, *akt = index;
74
 
75
	   while (akt)
76
	   {
77
	      n = akt;
78
	      akt = akt->next;
79
	      delete n;
80
	   }
81
	}
82
}
83
 
84
/*
85
 * Search for a directory named .sportwatcher in the home directory of
86
 * the user and search for *.gmn files. Open the files and read the header
87
 * to find the basic data of activities. Then add the information into
88
 * the activities KListView.
89
 */
90
void sportwatcherWidget::getActivities()
91
{
92
QString path, txt;
93
QDir mdir, dir = QDir::home();
94
QFileInfo *entries;
95
QStringList years, months;
96
QListViewItem *running, *biking, *other;
97
QListViewItem *el;
98
int anz;
99
RUN_NODE *rn;
100
LAP *lap;
101
 
102
	if (Data.isEmpty())
103
	{
104
	   path = dir.path();
105
	   path.append("/.sportwatcher");
106
	}
107
	else
108
	   path = Data;
109
 
110
	dir.setPath(path);
111
 
112
	if (!dir.exists())
113
	{
114
	   dir.mkdir(path);
115
	   return;
116
	}
117
 
118
	liActivities->setRootIsDecorated(true);
119
	liActivities->setSortColumn(-1);
120
	other = new QListViewItem(liActivities, i18n("Others"));
121
	biking = new QListViewItem(liActivities, i18n("Biking"));
122
	running = new QListViewItem(liActivities, i18n("Running"));
123
	liActivities->insertItem(other);
124
	liActivities->insertItem(biking);
125
	liActivities->insertItem(running);
126
 
127
	dir.cd(path);
128
	dir.setFilter(QDir::Dirs | QDir::NoSymLinks);
129
	dir.setSorting(QDir::Name);
130
	const QFileInfoList *list = dir.entryInfoList();
131
 
132
	if (!list)
133
	   return;
134
 
135
	QFileInfoListIterator it(*list);
136
 
137
	while ((entries = it.current()) != 0)		// Years
138
	{
139
	   if (entries->fileName() == QString(".") || entries->fileName() == QString(".."))
140
	   {
141
	      ++it;
142
	      continue;
143
	   }
144
 
145
	   years += entries->absFilePath();
146
	   ++it;
147
	}
148
 
149
	for (QStringList::Iterator strit = years.begin(); strit != years.end(); ++strit)
150
	{
151
	   if (months.count() > 0)
152
	      months.clear();
153
 
154
	   dir.setPath(*strit);
155
	   list = dir.entryInfoList();
156
	   list = dir.entryInfoList();
157
 
158
	   if (!list)
159
	      continue;
160
 
161
	   it = QFileInfoListIterator (*list);
162
 
163
	   while ((entries = it.current()) != 0)	// Months
164
	   {
165
	      if (entries->fileName() == QString(".") || entries->fileName() == QString(".."))
166
	      {
167
		 ++it;
168
		 continue;
169
	      }
170
 
171
	      months += entries->absFilePath();
172
	      ++it;
173
	   }
174
 
175
	   for (QStringList::Iterator strit1 = months.begin(); strit1 != months.end(); ++strit1)
176
	   {
177
	      mdir.setPath(*strit1);
178
	      mdir.cd(*strit1);
179
	      mdir.setFilter(QDir::Files | QDir::NoSymLinks);
180
	      mdir.setNameFilter(QString("*.gmn"));
181
	      list = mdir.entryInfoList();
182
 
183
	      if (!list)
184
		 continue;
185
 
186
	      it = QFileInfoListIterator (*list);
187
	      anz = 0;
188
 
189
	      while ((entries = it.current()) != 0)		// Files
190
	      {
191
		 files += entries->absFilePath();
192
		 ++it;
193
	      }
194
	   }
195
	}
196
 
197
	INDEX *akt, *n;
198
	// Open every file and read its head
199
	for (QStringList::Iterator strfl = files.begin(); strfl != files.end(); ++strfl)
200
	{
201
	   spw.destroy();
202
 
203
	   if (spw.setFileName(*strfl) == -1)
204
	      return;
205
 
206
	   if (gmn)
207
	      garmin_free_data (gmn);
208
 
209
	   gmn = spw.readFile();
210
	   ds.destroy();
211
	   ds.garmin_print_data(gmn);
212
	   rn = ds.getRunNode();
213
 
214
	   lap = ds.getLap(rn->run->first_lap_index);
215
	   const QDateTime *qt = garmin_dtime (lap->start_time);
216
	   QString idx = qt->toString("dd.MM.yyyy hh:mm.ss");
217
 
218
	   if (!index)
219
	   {
220
	      index = new INDEX;
221
	      index->path = *strfl;
222
	      index->activ = idx;
223
	      index->next = 0;
224
	   }
225
	   else
226
	   {
227
	      n = new INDEX;
228
	      n->path = *strfl;
229
	      n->activ = idx;
230
	      n->next = 0;
231
	      akt = index;
232
 
233
	      while (akt->next)
234
		 akt = akt->next;
235
 
236
	      akt->next = n;
237
	   }
238
 
239
	   switch (rn->run->sport_type)
240
	   {
241
	      case D1000_running:
242
		 el = new QListViewItem(running, idx);
243
		 running->insertItem(el);
244
	      break;
245
 
246
	      case D1000_biking:
247
		 el = new QListViewItem(biking, idx);
248
		 biking->insertItem(el);
249
	      break;
250
 
251
	      case D1000_other:
252
		 el = new QListViewItem(other, idx);
253
		 other->insertItem(el);
254
	      break;
255
 
256
	      default:
257
		 el = new QListViewItem(other, idx);
258
		 other->insertItem(el);
259
	   }
260
 
261
	   delete qt;
262
	}
263
 
264
	running->setOpen(true);
265
 
266
	if (gmn)
267
	   garmin_free_data (gmn);
268
 
269
	gmn = 0;
270
}
271
 
272
/*$SPECIALIZATION$*/
273
void sportwatcherWidget::btFullscreenSlot()
274
{
275
}
276
 
277
void sportwatcherWidget::btGlasMinusSlot()
278
{
279
}
280
 
281
void sportwatcherWidget::btGlasPlusSlot()
282
{
283
}
284
 
285
void sportwatcherWidget::btHandSlot()
286
{
287
}
288
 
289
void sportwatcherWidget::btGlasSlot()
290
{
291
}
292
 
293
void sportwatcherWidget::btFlagSlot()
294
{
295
}
296
 
297
void sportwatcherWidget::liLapsSlot(QListViewItem */* item */)
298
{
299
}
300
 
301
void sportwatcherWidget::liActivitiesSlot(QListViewItem *item)
302
{
303
INDEX *akt;
304
 
305
	if (!item)
306
	   return;
307
 
308
	akt = index;
309
 
310
	while (akt)
311
	{
312
	   if (akt->activ == item->text(0))
313
	   {
314
	      spw.destroy();
315
 
316
              if (spw.setFileName(akt->path.ascii()) == -1)
317
		 return;
318
 
319
	      if (gmn)
320
		 garmin_free_data (gmn);
321
 
322
	      gmn = spw.readFile();
323
	      showLaps();
324
	      showCurves();
325
	      return;
326
	   }
327
 
328
	   akt = akt->next;
329
	}
330
}
331
 
332
void sportwatcherWidget::helpAbout()
333
{
334
}
335
 
336
void sportwatcherWidget::helpContents()
337
{
338
}
339
 
340
void sportwatcherWidget::helpIndex()
341
{
342
}
343
 
344
void sportwatcherWidget::fileExit()
345
{
346
	if (mama)
347
	   mama->close();
348
}
349
 
350
void sportwatcherWidget::filePrint()
351
{
352
}
353
 
354
void sportwatcherWidget::fileSaveAs()
355
{
356
}
357
 
358
void sportwatcherWidget::fileSave()
359
{
360
}
361
 
362
void sportwatcherWidget::fileOpen()
363
{
364
QString fname = KFileDialog::getOpenFileName(Data, QString("*.gmn"), this, QString("SportWatcher"));
365
 
366
        if (fname.isEmpty())
367
           return;
368
 
369
	spw.destroy();
370
 
371
        if (spw.setFileName(fname.ascii()) == -1)
372
	   return;
373
 
374
	if (gmn)
375
	   garmin_free_data (gmn);
376
 
377
	gmn = spw.readFile();
378
	showLaps();
379
	showCurves();
380
}
381
 
382
void sportwatcherWidget::fileNew()
383
{
96 andreas 384
progressWidget *dlg = new progressWidget(this, "progressWidgetBase", TRUE);
385
 
386
	dlg->exec();
387
	delete dlg;
88 andreas 388
}
389
 
390
/*
391
 * This function is called, when the user clicks at the menu point
392
 * "Save Heart Rate".
393
 * First, a file dialog box is displayed, where the user can choose a
394
 * directory and a file name to save the heart rate.
395
 * If the file could successfully be created, the heart rate is saved
396
 * in the "HRM"-format. This is the native format polar uses to store
397
 * heart rate data. I've choosen this format, because it's popular and
398
 * used by many other software too.
399
 */
400
void sportwatcherWidget::extrasSaveHR()
401
{
402
QString fname, str1, str2;
403
QFile fdfile;
404
QDateTime *qt, *oldqt;
405
QDate dat;
406
QTime t;
407
QDir dir = QDir::home();
408
char hv0[256];
409
RUN_NODE *rn;
410
LAP *lap, *alap;
411
POINT *point;
412
int samples, smp, seconds, anz, nsec, samsec;
413
int avgHeart, minHeart, maxHeart, aktHeart;
414
int secRange1, secRange2, secRange3, secAbove, secBeyond;
415
 
416
	if (!gmn)
417
	{
418
	   KMessageBox::information(this, i18n("There is no activity open"));
419
	   return;
420
	}
421
 
422
	if (HRM.isEmpty())
423
	   str1 = dir.path();
424
	else
425
	   str1 = HRM;
426
 
427
	str1 +=  "/" + StartTime.toString("yyyyMMddThhmmss.zzz.hrm");
428
	fname = KFileDialog::getSaveFileName(str1, QString("*.hrm"), this, QString("SportWatcher"));
429
 
430
	if (fname.isEmpty())
431
	   return;
432
 
433
	fdfile.setName(fname);
434
 
435
	if (fdfile.exists())
436
	{
437
	   if (KMessageBox::questionYesNo(this, i18n("Do you really want to overwrite this file?")) == KMessageBox::No)
438
	      return;
439
	}
440
 
441
	if (!fdfile.open(IO_ReadWrite | IO_Truncate))
442
	{
443
	   KMessageBox::error(this, i18n("Error creating a file!\nPlease check permissions."));
444
	   return;
445
	}
446
 
447
	rn = ds.getRunNode();
448
	lap = ds.getLap(rn->run->first_lap_index);
449
	t = StartTime.time();
450
	dat = StartTime.date();
451
 
452
	if ((point = ds.getPoint(lap->start_time)) == 0)
453
	{
454
	   fdfile.close();
455
	   return;
456
	}
457
 
458
	strcpy (hv0, "[Params]\n");
459
	write(fdfile.handle(), &hv0[0], strlen(hv0));
460
	str1 = dat.toString("yyyyMMdd");
461
	str2 = t.toString("hh:mm:ss.z");
462
	sprintf(hv0, "Version=106\nMonitor=11\nSMode=000000000\nDate=%s\nStartTime=%s\n",
463
		str1.ascii(), str2.ascii());
464
	write(fdfile.handle(), &hv0[0], strlen(hv0));
465
	t.setHMS(0, 0, 0);
466
	t = t.addSecs(max_time);
467
	str2 = t.toString("hh:mm:ss.z");
468
 
469
	switch (sampleTime)
470
	{
471
	   case 0: samsec = 5; break;
472
	   case 1: samsec = 15; break;
473
	   case 2: samsec = 30; break;
474
	   case 3: samsec = 60; break;
475
	   default:
476
	      samsec = 15;
477
	}
478
 
479
	sprintf(hv0, "Length=%s\nInterval=%d\nUpper1=%d\nLower1=%d\nUpper2=%d\n",
480
	   str2.ascii(), samsec, upper1, lower1, upper2);
481
	write(fdfile.handle(), &hv0[0], strlen(hv0));
482
	sprintf(hv0, "Lower2=%d\nUpper3=%d\nLower3=%d\nTimer1=00:00:00.0\n",
483
		lower2, upper3, lower3);
484
	write(fdfile.handle(), &hv0[0], strlen(hv0));
485
	strcpy(hv0, "Timer2=00:00:00.0\nTimer3=00:00:00.0\nActiveLimit=0\n");
486
	write(fdfile.handle(), &hv0[0], strlen(hv0));
487
	sprintf(hv0, "MaxHR=%d\nRestHR=%d\nStartDelay=0\nVO2max=%d\nWeight=%d\n\n",
488
		MaxHr, restHr, vo2max, weight);
489
	write(fdfile.handle(), &hv0[0], strlen(hv0));
490
 
491
	// Write the intervall times. One block for every lap
492
	secRange1 = secRange2 = secRange3 = secAbove = secBeyond = 0;
493
	strcpy(hv0, "[IntTimes]\n");
494
	write(fdfile.handle(), &hv0[0], strlen(hv0));
495
	t.setHMS(0, 0, 0);
496
 
497
	for (unsigned int i = rn->run->first_lap_index; i < rn->run->last_lap_index; i++)
498
	{
499
	   alap = ds.getLap(i);
500
	   point = ds.getPoint(alap->start_time);
501
	   oldqt = garmin_dtime(point->time);
502
	   avgHeart = minHeart = maxHeart = aktHeart = 0;
503
	   anz = 0;
504
	   unsigned long lastTime = point->time;
505
	   int totSec = 0;
506
 
507
	   while (point)
508
	   {
509
	      if (point->time > (alap->start_time + (alap->total_time / 100)))
510
		 break;
511
 
512
	      if (point->heart_rate > 0)
513
	      {
514
		 avgHeart += point->heart_rate;
515
		 nsec = point->time - lastTime;
516
		 totSec += nsec;
517
 
518
		 if (minHeart == 0 || minHeart > point->heart_rate)
519
		    minHeart = point->heart_rate;
520
 
521
		 if (maxHeart < point->heart_rate)
522
		    maxHeart = point->heart_rate;
523
 
524
		 if (aktHeart == 0 && totSec >= samsec)
525
		    aktHeart = avgHeart / (anz + 1);
526
 
527
		 if (point->heart_rate < lower1)
528
		    secBeyond += nsec;
529
		 else if (point->heart_rate < lower2)
530
		    secRange1 += nsec;
531
		 else if (point->heart_rate < lower3)
532
		    secRange2 += nsec;
533
		 else if (point->heart_rate < upper3)
534
		    secRange3 += nsec;
535
		 else
536
		    secAbove += nsec;
537
 
538
		 lastTime = point->time;
539
		 anz++;
540
	      }
541
 
542
	      point = ds.getPoint(point->time+1);
543
	   }
544
 
545
	   t = t.addSecs(alap->total_time / 100);
546
	   str1 = t.toString("hh:mm:ss.z");
547
	   sprintf(hv0, "%s\t %d\t %d\t %d\t %d\n",
548
	      str1.ascii(), aktHeart, minHeart, avgHeart / anz, maxHeart);
549
	   write(fdfile.handle(), &hv0[0], strlen(hv0));
550
	   strcpy(hv0, "32\t 0\t 0\t 0\t 0\t 0\n");
551
	   write(fdfile.handle(), &hv0[0], strlen(hv0));
552
	   strcpy(hv0, "0\t 0\t 0\t 0\t 0\n");
553
	   write(fdfile.handle(), &hv0[0], strlen(hv0));
554
	   sprintf(hv0, "0\t %d\t 0\t 0\t 0\t 0\n", (int)alap->total_distance);
555
	   write(fdfile.handle(), &hv0[0], strlen(hv0));
556
	   strcpy(hv0, "0\t 0\t 0\t 0\t 0\t 0\n");
557
	   write(fdfile.handle(), &hv0[0], strlen(hv0));
558
	}
559
 
560
	strcpy(hv0, "\n[IntNotes]\n\n[ExtraData]\n\n");
561
	write(fdfile.handle(), &hv0[0], strlen(hv0));
562
 
563
	strcpy(hv0, "[Summary-123]\n");
564
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// Time limits 1
565
	smp = max_time - secBeyond - secRange1 - secRange2 - secRange3 - secAbove;
566
	sprintf(hv0, "%u\t %u\t %u\t %u\t %u\n",
567
		max_time, secRange1, secRange2 + secRange3,
568
		secAbove + secBeyond, smp);
569
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// limits 1
570
	sprintf(hv0, "%d\t %d\t %d\t %d\n",
571
		MaxHr, upper1, lower1, restHr);
572
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// Time limits 1
573
	sprintf(hv0, "%u\t %u\t %u\t %u\t %u\n",
574
		max_time, secRange2, secRange1 + secRange3,
575
		secAbove + secBeyond, smp);
576
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// limits 2
577
	sprintf(hv0, "%d\t %d\t %d\t %d\n",
578
		MaxHr, upper2, lower2, restHr);
579
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// Time limits 2
580
	sprintf(hv0, "%u\t %u\t %u\t %u\t %u\n",
581
		max_time, secRange3, secRange1 + secRange2,
582
		secAbove + secBeyond, smp);
583
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// limits 3
584
	sprintf(hv0, "%d\t %d\t %d\t %d\n",
585
		MaxHr, upper3, lower3, restHr);
586
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// Time limits 3
587
	samples = max_time / samsec;
588
	sprintf(hv0, "0\t %u\n\n", samples);	// samples
589
	write(fdfile.handle(), &hv0[0], strlen(hv0));
590
 
591
	strcpy(hv0, "[Summary-TH]\n");
592
	write(fdfile.handle(), &hv0[0], strlen(hv0));
593
	sprintf(hv0, "%u\t 0\t %u\t %d\t %d\t 0\n", max_time, max_time - max_hr - restHr, max_hr, restHr);
594
	write(fdfile.handle(), &hv0[0], strlen(hv0));
595
	sprintf(hv0, "%d\t %d\t %d\t %d\n", MaxHr, upper3, lower1, restHr);
596
	write(fdfile.handle(), &hv0[0], strlen(hv0));
597
	sprintf(hv0, "0\t %u\n\n", samples);	// samples
598
	write(fdfile.handle(), &hv0[0], strlen(hv0));
599
 
600
	sprintf(hv0, "[HRZones]\n%d\n%d\n%d\n%d\n%d\n%d\n0\n0\n0\n0\n0\n\n",
601
		MaxHr, upper3, upper2, upper1, lower1, restHr);
602
	write(fdfile.handle(), &hv0[0], strlen(hv0));
603
 
604
	strcpy(hv0, "[HRData]\n");
605
	write(fdfile.handle(), &hv0[0], strlen(hv0));
606
 
607
	smp = 0;		// average heart rate of 15 seconds
608
	seconds = 0;
609
	anz = 0;
610
	nsec = samsec;
611
	oldqt = garmin_dtime(lap->start_time);
612
	qt = 0;
613
	point = ds.getPoint(lap->start_time);
614
 
615
	while (point)
616
	{
617
	   if (seconds >= nsec)
618
	   {
619
	      if (anz > 0)
620
	      {
621
		 sprintf(hv0, "%d\n", smp / anz);
622
		 write(fdfile.handle(), &hv0[0], strlen(hv0));
623
	      }
624
 
625
	      if (smp > 0 && seconds >= (nsec + samsec))
626
	      {
627
		 if (anz <= 0)
628
		    anz = 0;
629
 
630
		 for (int x = nsec; x < seconds; x += samsec)
631
		 {
632
		    sprintf(hv0, "%d\n", smp / anz);
633
		    write(fdfile.handle(), &hv0[0], strlen(hv0));
634
		    nsec += samsec;
635
		 }
636
	      }
637
 
638
	      anz = 0;
639
	      smp = 0;
640
	      nsec += samsec;
641
	   }
642
 
643
	   qt = garmin_dtime (point->time);
644
	   seconds += oldqt->secsTo(*qt);
645
 
646
	   if (point->heart_rate > 0)
647
	   {
648
	      smp += point->heart_rate;
649
	      anz++;
650
	   }
651
 
652
	   delete oldqt;
653
	   oldqt = qt;
654
	   point = ds.getPoint(point->time + 1);
655
	}
656
 
657
	fdfile.close();
658
	KMessageBox::information(this, i18n("File successfully written."));
659
}
660
 
661
void sportwatcherWidget::extrasSettings()
662
{
663
settingsWidget *dlg = new settingsWidget(this, "settingsWidgetBase", TRUE, 0);
664
 
665
	if (dlg->exec() == QDialog::Accepted)
666
	{
667
	   KSimpleConfig *cfg = new KSimpleConfig(QString("sportwatcher.rc"), true);
668
	   cfg->setGroup(QString("SportWatcher"));
669
	   lower1 = cfg->readNumEntry("lower1");
670
	   lower2 = cfg->readNumEntry("lower2");
671
	   lower3 = cfg->readNumEntry("lower3");
672
	   upper1 = cfg->readNumEntry("upper1");
673
	   upper2 = cfg->readNumEntry("upper2");
674
	   upper3 = cfg->readNumEntry("upper3");
675
	   MaxHr = cfg->readNumEntry("maxHr");
676
	   restHr = cfg->readNumEntry("restHr");
677
	   vo2max = cfg->readNumEntry("vo2max");
678
	   weight = cfg->readNumEntry("weight");
679
	   sampleTime = cfg->readNumEntry("seconds");
680
	   Device = cfg->readEntry("Device");
681
	   Data = cfg->readEntry("Data");
682
	   HRM = cfg->readEntry("HRM");
683
	   delete cfg;
684
	}
685
 
686
	delete dlg;
687
}
688
 
689
/*
690
 * Functions to fill in the boxes of the main mask.
691
 */
692
void sportwatcherWidget::showLaps()
693
{
694
QString qs_name, qs_distance, qs_etime, qs_avgpace, qs_avgspeed, qs_maxspeed;
695
QString qs_calories, qs_avghr, qs_maxhr, qs_avgcadence, qs_ascent, qs_descent;
696
QDateTime dt;
697
QTime t, st;
698
QDateTime *qt;
699
LAP *lap;
700
POINT *point;
701
RUN_NODE *rakt, *rn;
702
int laps, i, anz, men;
703
double alt_asc, alt_dsc;
704
 
705
	if (!gmn)
706
	{
707
	   KMessageBox::error(0, i18n("No data were loaded!"));
708
	   return;
709
	}
710
 
711
	if (gmn->type == data_Dnil)
712
	{
713
	   KMessageBox::error(0, i18n("No data found!"));
714
	   return;
715
	}
716
 
717
	if (gmn->type != data_Dlist)     /* List of data */
718
	{
719
	   KMessageBox::error(0, QString("Found unexpected data type %1!").arg(gmn->type));
720
	   return;
721
	}
722
 
723
	ds.destroy();
724
	min_hr = max_hr = 0;
725
	min_height = max_height = 0.0;
726
	liLaps->clear();
727
	ds.garmin_print_data(gmn);
728
	rn = ds.getRunNode();
729
	rakt = rn;
730
	liLaps->setRootIsDecorated(true);
731
	liLaps->setColumnAlignment(1, Qt::AlignRight);
732
	liLaps->setColumnAlignment(2, Qt::AlignRight);
733
	liLaps->setColumnAlignment(3, Qt::AlignRight);
734
	liLaps->setColumnAlignment(4, Qt::AlignRight);
735
	liLaps->setColumnAlignment(5, Qt::AlignRight);
736
	liLaps->setColumnAlignment(6, Qt::AlignRight);
737
	liLaps->setColumnAlignment(7, Qt::AlignRight);
738
	liLaps->setColumnAlignment(8, Qt::AlignRight);
739
	liLaps->setColumnAlignment(9, Qt::AlignRight);
740
	liLaps->setColumnAlignment(10, Qt::AlignRight);
741
	liLaps->setColumnAlignment(11, Qt::AlignRight);
742
 
743
	qs_name = qs_distance = qs_etime = qs_avgpace = qs_avgspeed = qs_maxspeed = QString("");
744
	qs_calories = qs_avghr = qs_maxhr = qs_avgcadence = qs_ascent = qs_descent = QString("");
745
	men = 0;
746
 
747
	while (rakt)
748
	{
749
	   if (rakt->run->type == data_D1000 || rakt->run->type == data_D1009 ||
750
	   	rakt->run->type == data_D1010)
751
	   {
752
	   int lt, cal, ahr, mhr;
753
	   double distance, speed, mspeed;
754
	   QDate dat;
755
 
756
	      switch (rakt->run->sport_type)
757
	      {
758
		 case D1000_running: qs_name = QString("Running: "); break;
759
		 case D1000_biking:  qs_name = QString("Biking: "); break;
760
		 case D1000_other:   qs_name = QString("Other: "); break;
761
		 default:
762
		    qs_name = QString("Unknown: ");
763
	      }
764
 
765
	      lap = ds.getLap(rakt->run->first_lap_index);
766
	      qt = garmin_dtime (lap->start_time);
767
	      StartTime = *qt;
768
	      st = qt->time();
769
	      dat = qt->date();
770
	      delete qt;
771
	      lap = ds.getLap(rakt->run->last_lap_index);
772
	      qt = garmin_dtime (lap->start_time);
773
	      t = qt->addSecs(lap->total_time / 100).time();
774
	      lt = st.secsTo(t);
775
	      t.setHMS(0, 0, 0);
776
	      t = t.addSecs(lt);
777
	      qt->setDate(dat);
778
	      qt->setTime(t);
779
	      qs_name.append(dat.toString("dd.MM.yyyy"));
780
	      qs_name.append(" ");
781
	      qs_name.append(st.toString("hh:mm:ss"));
782
	      max_time = lt;
783
	      qs_etime = QString(qt->toString("hh:mm:ss.zzz"));
784
 
785
	      distance = 0.0;
786
	      cal = 0;
787
	      mspeed = 0;
788
	      ahr = mhr = 0;
789
	      anz = 0;
790
 
791
	      for (i = rakt->run->first_lap_index; (unsigned int)i <= rakt->run->last_lap_index; i++)
792
	      {
793
		 if ((lap = ds.getLap(i)) == NULL)
794
		    continue;
795
 
796
		 distance += lap->total_distance;
797
		 cal += lap->calories;
798
		 ahr += lap->avg_heart_rate;
799
		 anz++;
800
 
801
		 if (lap->max_speed > mspeed)
802
		    mspeed = lap->max_speed;
803
 
804
		 if (lap->max_heart_rate > mhr)
805
		    mhr = lap->max_heart_rate;
806
	      }
807
 
808
	      qs_distance.sprintf("%.2f m", distance);
809
 
810
	      if (distance > 0)
811
	      {
812
		 QTime tt = qt->time();
813
		 long secs = (double)(tt.hour() * 3600 + tt.minute() * 60 + tt.second()) / 100.0 * (1000.0 / distance * 100.0);
814
		 int h = secs / 3600;
815
		 int m = (secs - (h * 3600)) / 60;
816
		 int s = secs - ((h * 3600) + (m * 60));
817
		 t = QTime(h, m, s, 0);
818
		 qs_avgpace = t.toString("  hh:mm:ss");
819
		 qs_avgpace.append(QString(" /km"));
820
	      }
821
 
822
	      speed = distance / lt * 3.6;
823
	      qs_avgspeed.sprintf("%.2f km/h", speed);
824
	      qs_maxspeed.sprintf("%.2f km/h", mspeed * 3.6);
825
	      qs_calories.sprintf("%d", cal);
826
	      qs_avghr.sprintf("%d bpm", ahr / anz);
827
	      qs_maxhr.sprintf("%d bpm", mhr);
828
 
829
	      QListViewItem *element = new QListViewItem(liLaps, qs_name, qs_distance,
830
		qs_etime, qs_avgpace, qs_avgspeed, qs_maxspeed, qs_calories, qs_avghr);
831
	      element->setText(8, qs_maxhr);
832
	      element->setText(9, qs_avgcadence);
833
	      element->setText(10, qs_ascent);
834
	      element->setText(11, qs_descent);
835
	      element->sortChildItems(0, false);
836
	      element->setOpen(true);
837
	      liLaps->insertItem(element);
838
	      delete qt;
839
	      /* Get the laps. */
840
	      laps = 1;
841
 
842
	      for (i = rakt->run->first_lap_index; (unsigned int)i <= rakt->run->last_lap_index; i++)
843
	      {
844
		 if ((lap = ds.getLap(i)) == NULL)
845
		    continue;
846
 
847
		 qt = garmin_dtime (lap->start_time);
848
		 qs_name.sprintf("Lap %03d - ", laps);
849
		 qs_name.append(qt->toString("hh:mm:ss"));
850
		 qs_distance.sprintf("%.2f m", lap->total_distance);
851
		 t = QTime(0, 0, 0, 0);
852
		 t = t.addMSecs(lap->total_time * 10);
853
		 qs_etime = t.toString("hh:mm:ss.zzz");
854
		 qs_avgspeed.sprintf("%.2f km/h", lap->total_distance / (lap->total_time / 100.0) * 3.6);
855
		 qs_maxspeed.sprintf("%.2f km/h", lap->max_speed * 3.6);
856
		 qs_calories.sprintf("%d", lap->calories);
857
 
858
		 if (lap->total_distance > 0 && lap->total_time != 0)
859
		 {
860
		    long secs = (double)lap->total_time / 10000.0 * (1000.0 / lap->total_distance * 100.0);
861
		    int h = secs / 3600;
862
		    int m = (secs - (h * 3600)) / 60;
863
		    int s = secs - ((h * 3600) + (m * 60));
864
		    t = QTime(h, m, s, 0);
865
		    qs_avgpace = t.toString("hh:mm:ss");
866
		    qs_avgpace.append(QString(" /km"));
867
		 }
868
 
869
		 qs_avghr.sprintf("%d bpm", lap->avg_heart_rate);
870
		 qs_maxhr.sprintf("%d bpm", lap->max_heart_rate);
871
 
872
		 anz = 0;
873
		 alt_asc = alt_dsc = 0;
874
 
875
		 if ((point = ds.getPoint(lap->start_time)) != 0)
876
		 {
877
		    if (point->alt < 20000)
878
		       alt_dsc = alt_asc = point->alt;
879
		    else
880
		       alt_dsc = alt_asc = 0;
881
 
882
		    while (point)
883
		    {
884
		       if (point->time > (lap->start_time + (lap->total_time / 100)))
885
			 break;
886
 
887
		       if (point->alt > alt_asc && point->alt < 20000)
888
		       {
889
			  alt_asc = point->alt;
890
 
891
			  if (alt_dsc == 0)
892
			     alt_dsc = point->alt;
893
		       }
894
 
895
		       if (point->alt < alt_dsc)
896
			  alt_dsc = point->alt;
897
 
898
		       // save the min and max values. We need this information to
899
		       // build the graphics.
900
		       if (point->heart_rate > max_hr)
901
			  max_hr = point->heart_rate;
902
 
903
		       if ((min_hr == 0 && point->heart_rate > 0) || (point->heart_rate > 0 && point->heart_rate < min_hr))
904
			  min_hr = point->heart_rate;
905
 
906
		       if (point->alt < 20000 && max_height < point->alt)
907
			  max_height = point->alt;
908
 
909
		       if (point->alt < 20000 && (min_height == 0.0 || min_height > point->alt))
910
			  min_height = point->alt;
911
 
912
		       if (point->heart_rate > 0)
913
		       {
914
			  avg_hr += point->heart_rate;
915
			  men++;
916
		       }
917
 
918
		       point = ds.getPoint(point->time + 1);
919
		    }
920
 
921
		    qs_ascent.sprintf("%.2f m", alt_asc);
922
		    qs_descent.sprintf("%.2f m", alt_dsc);
923
		 }
924
 
925
		 if (lap->avg_cadence != 0xff)
926
		    qs_avgcadence.sprintf("%d", lap->avg_cadence);
927
 
928
		 QListViewItem *edetail = new QListViewItem(element, qs_name, qs_distance,
929
			qs_etime, qs_avgpace, qs_avgspeed, qs_maxspeed, qs_calories, qs_avghr);
930
		 edetail->setText(8, qs_maxhr);
931
		 edetail->setText(9, qs_avgcadence);
932
		 edetail->setText(10, qs_ascent);
933
		 edetail->setText(11, qs_descent);
934
		 liLaps->clearSelection();
935
		 element->insertItem(edetail);
936
		 delete qt;
937
		 laps++;
938
	      }
939
	   }
940
 
941
	   rakt = rakt->next;
942
	}
943
 
944
	if (men > 0)
945
	   avg_hr /= men;
946
}
947
 
948
void sportwatcherWidget::showCurves()
949
{
950
QPainter paint;
951
int width, height;
952
int i;
953
int lineHeight, margin_left, margin_right, margin_bottom;
954
int x1, y1, x2, y2;		// Coordinates
955
bool meter;
956
double maxHeight, minHeight;
957
int maxHr, minHr, rh;
958
POINT *point;
959
double w_tick, h_tick;		// Number of pixels one "tick" has;
960
				// This depends on the width and height
961
				// of the image.
962
	// First we draw a grid based on the min and max
963
	// values detected in the function showLap(). In case
964
	// all values are 0, we exit here.
965
	if (min_hr == 0 && max_hr == 0 && min_height == 0.0 && max_height == 0.0)
966
	   return;
967
 
968
	width = imgProfile->width() - 4;
969
	height = imgProfile->height() - 4;
970
	pmProfile.resize(width + 2, height + 4);
971
	paint.begin(&pmProfile);
972
 
973
	// we need a somewhat bigger area to draw our curves than
974
	// we have with the real min and max values.
975
	if (max_height > 0.0)
976
	{
977
	double add = (max_height - min_height) / 100.0 * 5.0;	// Perzent
978
 
979
	   maxHeight = max_height + add;
980
	   minHeight = min_height - add;
981
 
982
	   if (minHeight < 0.0)		// make sure, we are not too deep
983
	      minHeight = 0.0;
984
	}
985
 
986
	if (max_hr > 0)
987
	{
988
	   maxHr = max_hr + 10;
989
	   minHr = min_hr - 10;
990
 
991
	   if (minHr < 0)
992
	      minHr = 0;
993
	}
994
 
995
	// Define colors
996
	QColor background(220, 220, 220);
997
	QColor mark(255, 255, 255);
998
	QColor frame(0, 0, 0);
999
	QColor barcol(151, 190, 13);
1000
	QColor barcol2(190, 151, 13);
1001
	QColor red(220, 128, 128);
1002
	QColor blue(0, 0, 240);
1003
	QFont fntNormal("Helvetica");
1004
//	QFont fntBold("Helvetica", 10, QFont::Bold);
1005
	fntNormal.setPixelSize(10);
1006
	fntNormal.setStyleHint(QFont::Helvetica);
1007
//	fntBold.setPixelSize(10);
1008
//	fntBold.setStyleHint(QFont::Helvetica);
1009
	// Calculate ticks
1010
	margin_left = 52;
1011
	margin_right = 40;
1012
	margin_bottom = 12;
1013
	lineHeight = 10;
1014
	rh = height - margin_bottom - 1;
1015
 
1016
	w_tick = (double)(width - (margin_left + margin_right)) / max_time;	// 1 tick = 1 second
1017
 
1018
	if ((maxHeight - minHeight) > (double)(maxHr - minHr))
1019
	{
1020
	   h_tick = (double)rh / (maxHeight - minHeight);		// 1 tick = 1 meter
1021
	   meter = true;
1022
	}
1023
	else
1024
	{
1025
	   h_tick = (double)rh / ((double)maxHr - (double)minHr);	// 1 tick = 1 bpm
1026
	   meter = false;
1027
	}
1028
 
1029
	// Fill background with background colors
1030
	paint.fillRect(0, 0, width + 4, height + 4, background);
1031
	// Draw a grid with markers at every 10 minutes
1032
	paint.setPen(QPen(frame, 1, QPen::SolidLine));
1033
	// Bottom border line
1034
	x1 = margin_left;
1035
	y1 = height - margin_bottom;
1036
	x2 = width - margin_right;
1037
	y2 = y1;
1038
	paint.drawLine(x1, y1, x2, y2);
1039
	// Left border line
1040
	x1 = x2 = margin_left;
1041
	y1 = 2;
1042
	y2 = height - margin_bottom;
1043
	paint.drawLine(x1, y1, x2, y2);
1044
	// right border line
1045
	x1 = x2 = width - margin_right;
1046
	paint.drawLine(x1, y1, x2, y2);
1047
	// Grid vertical
1048
	paint.setPen(QPen(frame, 1, QPen::SolidLine));
1049
	paint.setFont(fntNormal);
1050
	paint.drawText(margin_left - 20, height - lineHeight, 40, lineHeight, Qt::AlignCenter, QString("00:00"));
1051
	paint.save();
1052
	paint.rotate(270);
1053
	paint.setPen(QPen(barcol, 1, QPen::SolidLine));
1054
	paint.drawText((height + 4) * -1, 3, height - 2, lineHeight, Qt::AlignCenter, i18n("Elevation (m)"));
1055
	paint.setPen(QPen(blue, 1, QPen::SolidLine));
1056
	paint.drawText((height + 4) * -1, width - 1 - lineHeight, height - 2, lineHeight, Qt::AlignCenter, i18n("Heart Rate (bpm)"));
1057
	paint.restore();
1058
	paint.setPen(QPen(mark, 1, QPen::SolidLine));
1059
	// Draw the time scale
1060
	for (i = 0; (unsigned int)i < max_time; i++)
1061
	{
1062
	   if (i > 0 && !(i % 600))	// every 10 minutes
1063
	   {
1064
	      x1 = x2 = margin_left + w_tick * i;
1065
 
1066
	      if (x1 == (width - margin_right))
1067
		 continue;
1068
 
1069
	      y1 = 2;
1070
	      y2 = height - margin_bottom;
1071
	      paint.drawLine(x1, y1, x2, y2);
1072
	      QTime tm(0, 0, 0);
1073
	      tm = tm.addSecs(i);
1074
	      paint.setPen(QPen(frame, 1, QPen::SolidLine));
1075
	      paint.drawText(x1 - 25, height - lineHeight, 50, lineHeight, Qt::AlignCenter, tm.toString((i >= 3600) ? "hh:mm:ss" : "mm:ss"));
1076
	      paint.setPen(QPen(mark, 1, QPen::SolidLine));
1077
	   }
1078
	}
1079
 
1080
	QTime tm(0, 0, 0);
1081
	QString qs;
1082
	tm = tm.addSecs(max_time);
1083
	paint.setPen(QPen(frame, 1, QPen::SolidLine));
1084
	paint.drawText(width - margin_right - 25, height - lineHeight, 50, lineHeight, Qt::AlignCenter, tm.toString((max_time >= 3600) ? "hh:mm:ss" : "mm:ss"));
1085
 
1086
	if (max_height > 0.0)
1087
	{
1088
	   paint.setPen(QPen(barcol, 1, QPen::SolidLine));
1089
	   paint.drawText(12, height - margin_bottom - lineHeight / 2, margin_left - 14, lineHeight, Qt::AlignRight, qs.sprintf("%.0f", minHeight));
1090
	}
1091
 
1092
	if (max_hr > 0)
1093
	{
1094
	   paint.setPen(QPen(blue, 1, QPen::SolidLine));
1095
	   paint.drawText(width - margin_right + 2, height - margin_bottom - lineHeight / 2, margin_right - 14, lineHeight, Qt::AlignLeft, qs.sprintf("%d", minHr));
1096
	}
1097
 
1098
	paint.setPen(QPen(mark, 1, QPen::SolidLine));
1099
 
1100
	// Grid horizontal
1101
	int factor = (meter) ? (maxHeight - minHeight) / (rh / 12) : (maxHr - minHr) / (rh / 12);
1102
	int target = (meter) ? (int)(maxHeight - minHeight) : (maxHr - minHr);
1103
	int oldy = height;
1104
 
1105
	for (i = 0; i < target; i++)
1106
	{
1107
	   if (i > 0 && !(i % factor))
1108
	   {
1109
	      x1 = margin_left + 1;
1110
	      x2 = width - margin_right - 1;
1111
	      y1 = y2 = rh - h_tick * i;
1112
 
1113
	      if (y1 < 12)
1114
		 break;
1115
 
1116
	      paint.drawLine(x1, y1, x2, y2);
1117
 
1118
	      if (y1 < (oldy - lineHeight))
1119
	      {
1120
		 if (meter)
1121
		 {
1122
		    paint.setPen(QPen(barcol, 1, QPen::SolidLine));
1123
		    paint.drawText(12, y1 - lineHeight / 2, margin_left - 14, lineHeight, Qt::AlignRight, qs.sprintf("%.0f", minHeight + i));
1124
 
1125
		    if (maxHr > 0)
1126
		    {
1127
		       double hrscale = (double)(maxHr - minHr) / (double)target;
1128
		       paint.setPen(QPen(blue, 1, QPen::SolidLine));
1129
		       paint.drawText(width - margin_right + 2, y1 - lineHeight / 2, margin_right - 14, lineHeight, Qt::AlignLeft, qs.sprintf("%d", (int)((double)minHr + hrscale * (double)i)));
1130
		    }
1131
		 }
1132
		 else
1133
		 {
1134
		    paint.setPen(QPen(blue, 1, QPen::SolidLine));
1135
		    paint.drawText(width - margin_right + 2, y1 - lineHeight / 2, margin_right - 14, lineHeight, Qt::AlignLeft, qs.sprintf("%d", minHr + i));
1136
 
1137
		    if (max_height > 0)
1138
		    {
1139
		       double hrscale = (maxHeight - minHeight) / (double)target;
1140
		       paint.setPen(QPen(barcol, 1, QPen::SolidLine));
1141
		       paint.drawText(12, y1 - lineHeight / 2, margin_left - 14, lineHeight, Qt::AlignRight, qs.sprintf("%.0f", minHeight + hrscale * (double)i));
1142
		    }
1143
		}
1144
 
1145
		 paint.setPen(QPen(mark, 1, QPen::SolidLine));
1146
		 oldy = y1;
1147
	      }
1148
	   }
1149
	}
1150
 
1151
	// To make out graphics mor beautiful, we draw lines for the
1152
	// heart rate limits and the average heart rate.
1153
	if (max_hr > 0)
1154
	{
1155
	int ay1, ay2, ay3, ay4, ay5;
1156
 
1157
	   x1 = margin_left + 1;
1158
	   x2 = width - margin_right - 1;
1159
 
1160
	   if (meter)
1161
	   {
1162
	      double hrscale = rh / (double)(maxHr - minHr);
1163
	      ay1 = (double)rh - (double)(lower1 - minHr) * hrscale;
1164
	      ay2 = (double)rh - (double)(lower2 - minHr) * hrscale;
1165
	      ay3 = (double)rh - (double)(lower3 - minHr) * hrscale;
1166
	      ay4 = (double)rh - (double)(upper3 - minHr) * hrscale;
1167
	      ay5 = (double)rh - (double)(avg_hr - minHr) * hrscale;
1168
	   }
1169
	   else
1170
	   {
1171
	      ay1 = (double)rh - (double)(lower1 - minHr) * h_tick;
1172
	      ay2 = (double)rh - (double)(lower2 - minHr) * h_tick;
1173
	      ay3 = (double)rh - (double)(lower3 - minHr) * h_tick;
1174
	      ay4 = (double)rh - (double)(upper3 - minHr) * h_tick;
1175
	      ay5 = (double)rh - (double)(avg_hr - minHr) * h_tick;
1176
	   }
1177
 
1178
	   paint.setPen(QPen(barcol2, 1, QPen::DashLine));	// color for limits
1179
 
1180
	   if (lower1 > minHr && lower1 < maxHr)
1181
	      paint.drawLine(x1, ay1, x2, ay1);
1182
 
1183
	   if (lower2 > minHr && lower2 < maxHr)
1184
	      paint.drawLine(x1, ay2, x2, ay2);
1185
 
1186
	   if (lower3 > minHr && lower3 < maxHr)
1187
	      paint.drawLine(x1, ay3, x2, ay3);
1188
 
1189
	   if (upper3 > minHr && upper3 < maxHr)
1190
	      paint.drawLine(x1, ay4, x2, ay4);
1191
 
1192
	   paint.setPen(QPen(red, 1, QPen::DashDotLine));	// color for average heart rate
1193
 
1194
	   if (avg_hr > minHr && avg_hr < maxHr)
1195
	      paint.drawLine(x1, ay5, x2, ay5);
1196
	}
1197
 
1198
	// Now we have a grid and we've done the scaling.
1199
	// This is the point where we draw the curves itself.
1200
	// We use different colors to draw the lines.
1201
	i = 0;
1202
	x1 = x2 = y1 = y2 = 0;
1203
	QDateTime *qt;
1204
	QTime zeit = StartTime.time();
1205
	int secs, hy1, hy2, hx1, hx2;
1206
	hy1 = hy2 = hx1 = hx2 = 0;
1207
 
1208
	while ((point = ds.getPoint(i)) != 0)
1209
	{
1210
	   // calculate the y position based on the time
1211
	   qt = garmin_dtime(point->time);
1212
	   secs = zeit.secsTo(qt->time());
1213
	   delete qt;
1214
	   x2 = secs * w_tick + margin_left + 1;
1215
	   hx2 = x2;
1216
 
1217
	   if (x1 == 0)
1218
	      x1 = x2;
1219
 
1220
	   if (hx1 == 0)
1221
	      hx1 = hx2;
1222
 
1223
	   if (point->alt < 20000 && point->alt > 0.0)
1224
	   {
1225
	      if (meter)
1226
		 y2 = (double)rh - (point->alt - minHeight) * h_tick;
1227
	      else
1228
	      {
1229
		 double hrscale = rh / (maxHeight - minHeight);
1230
		 y2 = (double)rh - (point->alt - minHeight) * hrscale;
1231
	      }
1232
 
1233
	      if (y1 == 0)
1234
		 y1 = y2;
1235
 
1236
	      paint.setPen(QPen(barcol, 1, QPen::SolidLine));
1237
	      paint.drawLine(x1, y1, x2, y2);
1238
	      y1 = y2;
1239
	      x1 = x2;
1240
	   }
1241
 
1242
	   if (point->heart_rate > 0)
1243
	   {
1244
	      if (meter)
1245
	      {
1246
		 double hrscale = rh / (double)(maxHr - minHr);
1247
		 hy2 = (double)rh - (double)(point->heart_rate - minHr) * hrscale;
1248
	      }
1249
	      else
1250
		 hy2 = (double)rh - (double)(point->heart_rate - minHr) * h_tick;
1251
 
1252
	      if (hy1 == 0)
1253
		 hy1 = hy2;
1254
 
1255
	      paint.setPen(QPen(blue, 1, QPen::SolidLine));
1256
	      paint.drawLine(hx1, hy1, hx2, hy2);
1257
	      hy1 = hy2;
1258
	      hx1 = hx2;
1259
	   }
1260
 
1261
	   i++;
1262
	}
1263
 
1264
	paint.end();
1265
	imgProfile->setPixmap(pmProfile);
1266
 
1267
//	if (bProfile)
1268
//	   bitBlt(imgProfile, 0, 0, &pmProfile);
1269
}
1270
 
1271
void sportwatcherWidget::resizeEvent(QResizeEvent */* *e */)
1272
{
1273
	showCurves();
1274
}
1275
 
1276
void sportwatcherWidget::paintEvent(QPaintEvent */* *e */)
1277
{
1278
	showCurves();
1279
}
1280
 
1281
 
1282
/*
1283
 * Private functions to help decode the data
1284
 */
1285
QDateTime *sportwatcherWidget::garmin_dtime (uint32 t)
1286
{
1287
time_t     tval;
1288
struct tm  tmval;
1289
QTime ti;
1290
QDate dt;
1291
QDateTime *qt;
1292
 
1293
	if (t == 0)
1294
	   return new QDateTime(QDate(1900, 1, 1), QTime(0, 0, 0, 0));
1295
 
1296
	tval = t + TIME_OFFSET;
1297
	localtime_r (&tval, &tmval);
1298
	qt = new QDateTime();
1299
	qt->setDate(QDate(tmval.tm_year+1900, tmval.tm_mon+1, tmval.tm_mday));
1300
	qt->setTime(QTime(tmval.tm_hour, tmval.tm_min, tmval.tm_sec, 0));
1301
	/* OK.  Done. */
1302
	return qt;
1303
}
1304
 
1305
 
1306
#include "sportwatcherwidget.moc"
1307