Subversion Repositories public

Rev

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

Rev Author Line No. Line
88 andreas 1
/***************************************************************************
119 andreas 2
 *   Copyright (C) 2007, 2008 by Andreas Theofilu                          *
3
 *   andreas@theosys.at                                                    *
88 andreas 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
 
119 andreas 20
#include "config.h"
88 andreas 21
#include "managefile.h"
22
#include "sportwatcherwidget.h"
23
#include "settingswidget.h"
96 andreas 24
#include "progresswidget.h"
152 andreas 25
#include "wmsbase.h"
151 andreas 26
// #undef GDAL
27
#include <string.h>
96 andreas 28
 
137 andreas 29
#include <iostream>
88 andreas 30
#include <kfiledialog.h>
31
#include <kmessagebox.h>
32
#include <ksimpleconfig.h>
33
#include <klocale.h>
34
#include <klistview.h>
100 andreas 35
#include <kaboutdialog.h>
36
#include <kaboutdata.h>
128 andreas 37
#include <kglobalsettings.h>
88 andreas 38
#include <qstring.h>
39
#include <qdatetime.h>
109 andreas 40
#include <qtoolbutton.h>
132 andreas 41
#include <qcursor.h>
151 andreas 42
#include <qcstring.h>
43
 
137 andreas 44
#include "copy.h"
88 andreas 45
 
151 andreas 46
// #define DEBUG	1
47
 
137 andreas 48
using std::cout;
49
using std::endl;
50
 
51
 
104 andreas 52
typedef struct
53
{
54
	double lon;
55
	double lat;
56
} posn_type;
57
 
88 andreas 58
sportwatcherWidget::sportwatcherWidget(QWidget* parent, const char* name, WFlags fl)
59
: sportwatcherWidgetBase(parent,name,fl)
60
{
61
	mama = parent;
62
	gmn = 0;
63
	min_hr = max_hr = avg_hr = 0;
64
	min_height = max_height = 0.0;
65
	max_time = 0;
66
	index = 0;
104 andreas 67
	zfactor = 0;
132 andreas 68
	mapLap = 0;
69
	mapPan = QRect(0, 0, 0, 0);
70
	stateHand = stateFlag = stateGlas = false;
71
	oldTransX = oldTransY = 0.0;
72
	lmbPressed = 0;
73
 
88 andreas 74
	// Load the config parameters
75
	KSimpleConfig *cfg = new KSimpleConfig(QString("sportwatcher.rc"), true);
76
	cfg->setGroup(QString("SportWatcher"));
143 andreas 77
	lower1 = cfg->readNumEntry("lower1", 0);
78
	lower2 = cfg->readNumEntry("lower2", 0);
79
	lower3 = cfg->readNumEntry("lower3", 0);
80
	upper1 = cfg->readNumEntry("upper1", 0);
81
	upper2 = cfg->readNumEntry("upper2", 0);
82
	upper3 = cfg->readNumEntry("upper3", 0);
83
	MaxHr = cfg->readNumEntry("maxHr", 180);
84
	restHr = cfg->readNumEntry("restHr", 60);
85
	vo2max = cfg->readNumEntry("vo2max", 50);
86
	weight = cfg->readNumEntry("weight", 70);
87
	sampleTime = cfg->readNumEntry("seconds", 15);
149 andreas 88
	Serial = cfg->readBoolEntry("Serial", false);
88 andreas 89
	Device = cfg->readEntry("Device", "/dev/ttyUSB0");
143 andreas 90
	Data = cfg->readEntry("Data", QDir::home().absPath() + "/.sportwatcher");
91
	HRM = cfg->readEntry("HRM", QDir::home().absPath() + "/polar");
151 andreas 92
	MAP = cfg->readEntry("MAP", QDir::home().absPath() + "/.sportwatcher/track.wms");
149 andreas 93
	Units = cfg->readNumEntry("Units", 0);
88 andreas 94
	delete cfg;
132 andreas 95
	// Set some widget settings
96
	btHand->setToggleButton(true);
97
	btGlas->setToggleButton(true);
88 andreas 98
	// Fill the activities
99
	getActivities();
151 andreas 100
#ifdef GDAL
101
	// Initialize the GDAL
102
	GDALAllRegister();
103
 
104
	if (QFile(MAP).exists())
105
	{
106
	   poDataset = (GDALDataset *)GDALOpen (MAP.ascii(), GA_ReadOnly);
107
 
108
	   if (poDataset == NULL)
109
	      KMessageBox::error(this, i18n("Error opening or initializing the MAP-Database!\nThere will be no map available."));
110
 
111
	   GDALClose (poDataset);
112
	}
113
 
114
	poDataset = 0;
115
#endif
88 andreas 116
}
117
 
118
sportwatcherWidget::~sportwatcherWidget()
119
{
104 andreas 120
	destroy();
88 andreas 121
}
122
 
100 andreas 123
void sportwatcherWidget::destroy()
124
{
125
	if (gmn)
126
	   garmin_free_data (gmn);
127
 
128
	if (index)
129
	{
130
	INDEX *n, *akt = index;
131
 
132
	   while (akt)
133
	   {
134
	      n = akt;
135
	      akt = akt->next;
136
	      delete n;
137
	   }
138
	}
139
 
140
	index = 0;
141
	gmn = 0;
132 andreas 142
	oldTransX = oldTransY = 0.0;
100 andreas 143
}
144
 
132 andreas 145
bool sportwatcherWidget::findIndex(const QString &key)
146
{
147
INDEX *akt = index;
148
 
149
	while (akt)
150
	{
151
	   if (akt->path == key || akt->activ == key)
152
	      return true;
153
 
154
	   akt = akt->next;
155
	}
156
 
157
	return false;
158
}
159
 
88 andreas 160
/*
161
 * Search for a directory named .sportwatcher in the home directory of
162
 * the user and search for *.gmn files. Open the files and read the header
163
 * to find the basic data of activities. Then add the information into
164
 * the activities KListView.
165
 */
166
void sportwatcherWidget::getActivities()
167
{
168
QString path, txt;
132 andreas 169
QDir mdir, dir = QDir::homeDirPath();
88 andreas 170
QFileInfo *entries;
171
QStringList years, months;
128 andreas 172
KListViewItem *running, *biking, *other;
173
KListViewItem *el;
88 andreas 174
int anz;
175
RUN_NODE *rn;
176
LAP *lap;
177
 
178
	if (Data.isEmpty())
179
	{
128 andreas 180
	   path = dir.homeDirPath();
88 andreas 181
	   path.append("/.sportwatcher");
182
	}
183
	else
184
	   path = Data;
185
 
186
	dir.setPath(path);
132 andreas 187
	dir.refresh();
88 andreas 188
 
189
	if (!dir.exists())
190
	{
191
	   dir.mkdir(path);
192
	   return;
193
	}
194
 
132 andreas 195
	destroy();
100 andreas 196
	liActivities->clear();
88 andreas 197
	liActivities->setRootIsDecorated(true);
198
	liActivities->setSortColumn(-1);
128 andreas 199
	other = new KListViewItem(liActivities, i18n("Others"));
200
	biking = new KListViewItem(liActivities, i18n("Biking"));
201
	running = new KListViewItem(liActivities, i18n("Running"));
202
 
203
	other->setPixmap(0, QPixmap::fromMimeSource(QString("history.png")));
204
	biking->setPixmap(0, QPixmap::fromMimeSource(QString("history.png")));
205
	running->setPixmap(0, QPixmap::fromMimeSource(QString("history.png")));
206
 
88 andreas 207
	liActivities->insertItem(other);
208
	liActivities->insertItem(biking);
209
	liActivities->insertItem(running);
210
 
211
	dir.cd(path);
212
	dir.setFilter(QDir::Dirs | QDir::NoSymLinks);
213
	dir.setSorting(QDir::Name);
132 andreas 214
	dir.refresh();
128 andreas 215
	QFileInfoList *list = (QFileInfoList *)dir.entryInfoList();
88 andreas 216
 
217
	if (!list)
218
	   return;
219
 
220
	QFileInfoListIterator it(*list);
221
 
222
	while ((entries = it.current()) != 0)		// Years
223
	{
224
	   if (entries->fileName() == QString(".") || entries->fileName() == QString(".."))
225
	   {
226
	      ++it;
227
	      continue;
228
	   }
229
 
230
	   years += entries->absFilePath();
231
	   ++it;
232
	}
233
 
234
	for (QStringList::Iterator strit = years.begin(); strit != years.end(); ++strit)
235
	{
236
	   if (months.count() > 0)
237
	      months.clear();
238
 
239
	   dir.setPath(*strit);
132 andreas 240
	   dir.refresh();
128 andreas 241
	   list = (QFileInfoList *)dir.entryInfoList();
88 andreas 242
 
243
	   if (!list)
244
	      continue;
245
 
246
	   it = QFileInfoListIterator (*list);
247
 
248
	   while ((entries = it.current()) != 0)	// Months
249
	   {
250
	      if (entries->fileName() == QString(".") || entries->fileName() == QString(".."))
251
	      {
252
		 ++it;
253
		 continue;
254
	      }
255
 
256
	      months += entries->absFilePath();
257
	      ++it;
258
	   }
259
 
260
	   for (QStringList::Iterator strit1 = months.begin(); strit1 != months.end(); ++strit1)
261
	   {
262
	      mdir.setPath(*strit1);
263
	      mdir.cd(*strit1);
264
	      mdir.setFilter(QDir::Files | QDir::NoSymLinks);
265
	      mdir.setNameFilter(QString("*.gmn"));
132 andreas 266
	      mdir.refresh();
128 andreas 267
	      list = (QFileInfoList *)mdir.entryInfoList();
88 andreas 268
 
269
	      if (!list)
270
		 continue;
271
 
272
	      it = QFileInfoListIterator (*list);
273
	      anz = 0;
274
 
275
	      while ((entries = it.current()) != 0)		// Files
276
	      {
277
		 files += entries->absFilePath();
278
		 ++it;
279
	      }
280
	   }
281
	}
282
 
283
	INDEX *akt, *n;
284
	// Open every file and read its head
285
	for (QStringList::Iterator strfl = files.begin(); strfl != files.end(); ++strfl)
286
	{
132 andreas 287
	   if (findIndex(*strfl))	// avoid duplicate entries
288
	      continue;
289
 
88 andreas 290
	   spw.destroy();
291
 
292
	   if (spw.setFileName(*strfl) == -1)
293
	      return;
294
 
295
	   if (gmn)
296
	      garmin_free_data (gmn);
297
 
298
	   gmn = spw.readFile();
299
	   ds.destroy();
300
	   ds.garmin_print_data(gmn);
301
	   rn = ds.getRunNode();
302
 
303
	   lap = ds.getLap(rn->run->first_lap_index);
304
	   const QDateTime *qt = garmin_dtime (lap->start_time);
305
	   QString idx = qt->toString("dd.MM.yyyy hh:mm.ss");
306
 
307
	   if (!index)
308
	   {
309
	      index = new INDEX;
310
	      index->path = *strfl;
311
	      index->activ = idx;
312
	      index->next = 0;
313
	   }
314
	   else
315
	   {
316
	      n = new INDEX;
317
	      n->path = *strfl;
318
	      n->activ = idx;
319
	      n->next = 0;
320
	      akt = index;
321
 
322
	      while (akt->next)
323
		 akt = akt->next;
324
 
325
	      akt->next = n;
326
	   }
327
 
328
	   switch (rn->run->sport_type)
329
	   {
330
	      case D1000_running:
128 andreas 331
		 el = new KListViewItem(running, idx);
332
		 el->setPixmap(0, QPixmap::fromMimeSource(QString("run.png")));
88 andreas 333
		 running->insertItem(el);
334
	      break;
335
 
336
	      case D1000_biking:
128 andreas 337
		 el = new KListViewItem(biking, idx);
338
		 el->setPixmap(0, QPixmap::fromMimeSource(QString("bike.png")));
88 andreas 339
		 biking->insertItem(el);
340
	      break;
341
 
342
	      case D1000_other:
128 andreas 343
		 el = new KListViewItem(other, idx);
344
		 el->setPixmap(0, QPixmap::fromMimeSource(QString("other.png")));
88 andreas 345
		 other->insertItem(el);
346
	      break;
347
 
348
	      default:
128 andreas 349
		 el = new KListViewItem(other, idx);
350
		 el->setPixmap(0, QPixmap::fromMimeSource(QString("other.png")));
88 andreas 351
		 other->insertItem(el);
352
	   }
353
 
354
	   delete qt;
355
	}
356
 
357
	running->setOpen(true);
358
 
359
	if (gmn)
360
	   garmin_free_data (gmn);
361
 
362
	gmn = 0;
363
}
364
 
365
/*$SPECIALIZATION$*/
366
void sportwatcherWidget::btFullscreenSlot()
367
{
132 andreas 368
	oldTransX = oldTransY = 0.0;
369
	mapPan.setCoords(0, 0, 0, 0);
104 andreas 370
	showTrack(0);
88 andreas 371
}
372
 
373
void sportwatcherWidget::btGlasMinusSlot()
374
{
132 andreas 375
bool sh = stateHand;
376
 
377
	stateHand = false;
104 andreas 378
	showTrack(zfactor - 1000);
132 andreas 379
	stateHand = sh;
88 andreas 380
}
381
 
382
void sportwatcherWidget::btGlasPlusSlot()
383
{
132 andreas 384
bool sh = stateHand;
385
 
386
	stateHand = false;
104 andreas 387
	showTrack(zfactor + 1000);
132 andreas 388
	stateHand = sh;
88 andreas 389
}
390
 
391
void sportwatcherWidget::btHandSlot()
392
{
132 andreas 393
QCursor cs;
394
 
395
	if (stateGlas)
396
	{
397
	   stateGlas = false;
398
	   btGlas->toggle();
399
	}
400
 
401
	stateHand = (stateHand) ? false : true;
402
 
403
	if (stateHand)
404
	   cs.setShape(QCursor::PointingHandCursor);
405
	else
406
	   cs.setShape(QCursor::ArrowCursor);
407
 
408
	imgMap->setCursor(cs);
88 andreas 409
}
410
 
411
void sportwatcherWidget::btGlasSlot()
412
{
132 andreas 413
QCursor cs;
414
 
415
	if (stateHand)
416
	{
417
	   stateHand = false;
418
	   btHand->toggle();
419
	}
420
 
421
	stateGlas = (stateGlas) ? false : true;
422
 
423
	if (stateGlas)
424
	   cs.setShape(QCursor::ForbiddenCursor);
425
	else
426
	   cs.setShape(QCursor::ArrowCursor);
427
 
428
	imgMap->setCursor(cs);
88 andreas 429
}
430
 
431
void sportwatcherWidget::btFlagSlot()
432
{
433
}
434
 
132 andreas 435
void sportwatcherWidget::liLapsSlot(QListViewItem *item)
88 andreas 436
{
132 andreas 437
QString sl;
438
int l;
439
int idx;
440
RUN_NODE *rn;
441
LAP *lap;
442
 
443
	if (!item)
444
	   return;
445
 
446
	sl = item->text(0).mid(4, 3);
447
	l = sl.toInt();
448
 
449
	if (l <= 0)
450
	{
451
	   showTrack(zfactor, mapPan, 0);
148 andreas 452
	   showCurves(0);
132 andreas 453
	   return;
454
	}
455
 
456
	rn = ds.getRunNode();
457
	idx = rn->run->first_lap_index;
458
	lap = ds.getLap(idx + l - 1);
459
	showTrack(zfactor, mapPan, lap);
148 andreas 460
	showCurves(lap);
88 andreas 461
}
462
 
463
void sportwatcherWidget::liActivitiesSlot(QListViewItem *item)
464
{
465
INDEX *akt;
466
 
467
	if (!item)
468
	   return;
469
 
470
	akt = index;
471
 
472
	while (akt)
473
	{
474
	   if (akt->activ == item->text(0))
475
	   {
476
	      spw.destroy();
477
 
478
              if (spw.setFileName(akt->path.ascii()) == -1)
479
		 return;
480
 
481
	      if (gmn)
482
		 garmin_free_data (gmn);
483
 
484
	      gmn = spw.readFile();
104 andreas 485
	      zfactor = 0;
88 andreas 486
	      showLaps();
100 andreas 487
	      showTrack();
88 andreas 488
	      showCurves();
489
	      return;
490
	   }
491
 
492
	   akt = akt->next;
493
	}
494
}
495
 
496
void sportwatcherWidget::helpAbout()
497
{
119 andreas 498
KAboutData about("SportWatcher", "SportWatcher", VERSION);
100 andreas 499
QString ab = ("About");
500
QString liz = ("License");
501
 
502
	KAboutDialog *info = new KAboutDialog(KAboutDialog::AbtProduct|KAboutDialog::AbtTabbed,
137 andreas 503
		QString("SportWatcher"), KAboutDialog::Close, KAboutDialog::Close, 0,
100 andreas 504
		i18n("About"), false, false, QString::null, QString::null, QString::null);
119 andreas 505
	info->setProduct("SportWatcher", QString("Version %1").arg(VERSION), "Andreas Theofilu", "2007, 2008");
100 andreas 506
	KAboutContainer *infoAppl = info->addContainerPage(ab, AlignCenter, AlignCenter);
119 andreas 507
	infoAppl->addTitle(QString("SportWatcher"), AlignCenter, false, false);
137 andreas 508
//	infoAppl->addTitle(QString("(C) 2007, 2008, Andreas Theofilu <andreas@theosys.at>"));
509
	infoAppl->addPerson(QString("Andreas Theofilu"), QString("andreas@theosys.at"), QString("http://www.theosys.at"), NULL);
510
	infoAppl->addTitle(I18N_NOOP("\nRead out the data of a Garmin GPS device over USB, and visualize them on screen"));
511
	about.setLicense(KAboutData::License_Custom);
512
	about.setLicenseText(I18N_NOOP(gpl3));
100 andreas 513
	info->addLicensePage(liz, about.license(), 10);
137 andreas 514
	info->setGeometry(0, 0, 800, 400);
100 andreas 515
	info->centerOnScreen(info, 0);
516
	info->exec();
517
	delete info;
88 andreas 518
}
519
 
520
void sportwatcherWidget::helpContents()
521
{
522
}
523
 
524
void sportwatcherWidget::helpIndex()
525
{
526
}
527
 
528
void sportwatcherWidget::fileExit()
529
{
530
	if (mama)
531
	   mama->close();
532
}
533
 
534
void sportwatcherWidget::filePrint()
535
{
536
}
537
 
104 andreas 538
/*
539
 * This function allows the user to choose a file name, where we save the
540
 * actual lap in Garmins own TCX format. This format is simply a XML-file.
541
 * For details about the schema of this file look at
542
 * http://developer.garmin.com/schemas/tcx/v2/
543
 */
88 andreas 544
void sportwatcherWidget::fileSaveAs()
545
{
104 andreas 546
QString fname;
547
QFile fn;
548
QString buffer;
549
RUN_NODE *rn, *rakt;
550
LAP *lap;
551
POINT *point;
552
int indent, i;
553
QDateTime *qt;
554
 
555
	if (!gmn)
556
	{
557
	   KMessageBox::error(this, i18n("Currently no activity is selected!"));
558
	   return;
559
	}
560
 
561
	fname = KFileDialog::getSaveFileName(0, QString("*.tcx"), this, QString("SportWatcher"));
562
 
563
	if (fname.isEmpty())
564
	   return;
565
 
566
	fn.setName(fname);
567
 
568
	if (fn.exists())
569
	{
570
	   if (KMessageBox::questionYesNo(this, i18n("Do you really want to overwrite this file?")) == KMessageBox::No)
571
	      return;
572
	}
573
 
574
	rn = ds.getRunNode();
575
	lap = ds.getLap(rn->run->first_lap_index);
576
 
577
	if ((point = ds.getPoint(lap->start_time)) == 0)
578
	{
579
	   KMessageBox::error(this, i18n("No data to save!"));
580
	   return;
581
	}
582
 
583
	if (!fn.open(IO_ReadWrite | IO_Truncate))
584
	{
585
	   KMessageBox::error(this, i18n("Error creating file " + QString(fname) + "!\nPlease check permissions"));
586
	   return;
587
	}
588
 
589
	buffer = QString("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n");
590
	buffer.append("<TrainingCenterDatabase xmlns=\"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2\" ");
591
	buffer.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
592
	buffer.append("xsi:schemaLocation=\"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 ");
593
	buffer.append("http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd\">\n\n");
594
	writeTag (fn, buffer, indent);
595
	buffer = QString("<folders/>\n\n");
596
	writeTag (fn, buffer, indent);
597
 
598
	// Open a course
599
	QFileInfo finfo(fname);
600
	buffer = QString("<Courses>\n   <Course>\n      <name>%1</name>\n").arg(finfo.baseName(true));
601
	writeTag (fn, buffer, indent);
602
	indent = 2;
603
 
604
	rakt = rn;
605
 
606
	while (rakt)
607
	{
608
	   if (rakt->run->type != data_D1000 && rakt->run->type != data_D1009 &&
609
	   	rakt->run->type != data_D1010)
610
	   {
611
	      rakt = rakt->next;
612
	      continue;
613
	   }
614
 
615
	   for (i = rakt->run->first_lap_index; (unsigned int)i <= rakt->run->last_lap_index; i++)
616
	   {
617
	      if ((lap = ds.getLap(i)) == NULL)
618
		 continue;
619
 
620
	      // Write the information of the lap
621
	      writeTag (fn, QString("<Lap>\n"), indent);
622
	      indent++;
623
	      buffer.sprintf("<TotalTimeSeconds>%f</TotalTimeSeconds>\n", (double)lap->total_time / 100.0);
624
	      writeTag (fn, buffer, indent);
625
	      buffer.sprintf("<DistanceMeters>%f</DistanceMeters>\n", lap->total_distance);
626
	      writeTag (fn, buffer, indent);
627
 
628
	      writeTag (fn, QString("<BeginPosition>\n"), indent);
629
	      indent++;
630
	      buffer.sprintf("<LatitudeDegrees>%f</LatitudeDegrees>\n", SEMI2DEG(lap->begin.lat));
631
	      writeTag (fn, buffer, indent);
632
	      buffer.sprintf("<LongitudeDegrees>%f</LongitudeDegrees>\n", SEMI2DEG(lap->begin.lon));
633
	      writeTag (fn, buffer, indent);
634
	      indent--;
635
	      writeTag (fn, QString("</BeginPosition>\n"), indent);
636
 
637
	      writeTag (fn, QString("<EndPosition>\n"), indent);
638
	      indent++;
639
	      buffer.sprintf("<LatitudeDegrees>%f</LatitudeDegrees>\n", SEMI2DEG(lap->end.lat));
640
	      writeTag (fn, buffer, indent);
641
	      buffer.sprintf("<LongitudeDegrees>%f</LongitudeDegrees>\n", SEMI2DEG(lap->end.lon));
642
	      writeTag (fn, buffer, indent);
643
	      indent--;
644
	      writeTag (fn, QString("</EndPosition>\n"), indent);
645
 
646
	      writeTag (fn, QString("<AverageHeartRateBpm xsi:type=\"HeartRateInBeatsPerMinute_t\">\n"), indent);
647
	      indent++;
648
	      buffer.sprintf("<Value>%d</Value>\n", lap->avg_heart_rate);
649
	      writeTag (fn, buffer, indent);
650
	      indent--;
651
	      writeTag (fn, QString("</AverageHeartRateBpm>\n"), indent);
652
 
653
	      writeTag (fn, QString("<MaximumHeartRateBpm xsi:type=\"HeartRateInBeatsPerMinute_t\">\n"), indent);
654
	      indent++;
655
	      buffer.sprintf("<Value>%d</Value>\n", lap->avg_heart_rate);
656
	      writeTag (fn, buffer, indent);
657
	      indent--;
658
	      writeTag (fn, QString("</MaximumHeartRateBpm>\n"), indent);
659
 
660
	      buffer = QString("<Intensity>%1</Intensity>\n").arg((!lap->intensity) ? "Active" : "");
661
	      writeTag (fn, buffer, indent);
662
	      indent--;
663
	      writeTag (fn, QString("</Lap>\n"), indent);
664
 
665
	      point = ds.getPoint(lap->start_time);
666
	      writeTag (fn, QString("<Track>\n"), indent);
667
	      indent++;
668
 
669
	      while (point)
670
	      {
671
		 if (point->time > (lap->start_time + (lap->total_time / 100)))
672
		    break;
673
 
674
		 writeTag (fn, QString("<Trackpoint>\n"), indent);
675
		 indent++;
676
		 qt = garmin_dtime(point->time);
677
		 buffer = QString("<Time>%1</Time>\n").arg(qt->toString("yyyy-MM-ddThh:mm:ssZ"));
678
		 writeTag (fn, buffer, indent);
679
		 delete qt;
680
		 writeTag (fn, QString("<Position>\n"), indent);
681
		 indent++;
682
		 buffer.sprintf("<LatitudeDegrees>%f</LatitudeDegrees>\n", SEMI2DEG(point->posn.lat));
683
		 writeTag (fn, buffer, indent);
684
		 buffer.sprintf("<LongitudeDegrees>%f</LongitudeDegrees>\n", SEMI2DEG(point->posn.lon));
685
		 writeTag (fn, buffer, indent);
686
		 indent--;
687
		 writeTag (fn, QString("</Position>\n"), indent);
688
 
689
		 if (point->alt < 20000.0)
690
		 {
691
		    buffer.sprintf("<AltitudeMeters>%f</AltitudeMeters>\n", point->alt);
692
		    writeTag (fn, buffer, indent);
693
		 }
694
 
695
		 buffer.sprintf("<DistanceMeters>%f</DistanceMeters>\n", point->distance);
696
		 writeTag (fn, buffer, indent);
697
 
698
		 if (point->heart_rate > 0 && point->heart_rate < 250)
699
		 {
700
		    writeTag (fn, QString("<HeartRateBpm xsi:type=\"HeartRateInBeatsPerMinute_t\">\n"), indent);
701
		    indent++;
702
		    buffer.sprintf("<Value>%d</Value>\n", point->heart_rate);
703
		    writeTag (fn, buffer, indent);
704
		    indent--;
705
		    writeTag (fn, QString("</HeartRateBpm>\n"), indent);
706
		 }
707
 
708
		 buffer.sprintf("<SensorState>%s</SensorState>\n", (!point->sensor) ? "Absent" : "");
709
		 writeTag (fn, buffer, indent);
710
		 indent--;
711
		 writeTag (fn, QString("</Trackpoint>\n"), indent);
712
		 point = ds.getPoint(point->time + 1);
713
	      }
714
 
715
	      indent--;
716
	      writeTag (fn, QString("</Track>\n"), indent);
717
	   }
718
 
719
	   indent--;
720
	   writeTag (fn, QString("</Course>\n"), indent);
721
	   indent--;
722
	   writeTag (fn, QString("</Courses>\n"), indent);
723
	   rakt = rakt->next;
724
	}
725
 
726
	// Write information about device
727
	// Here my personal signature is written :-)
728
	writeTag (fn, QString("<Author xsi:type=\"Application_t\">\n"), indent);
729
	indent++;
730
	writeTag (fn, QString("<Name>SportWatcher</Name>\n"), indent);
731
	writeTag (fn, QString("<Build>\n"), indent);
732
	indent++;
733
	writeTag (fn, QString("<Version>\n"), indent);
734
	indent++;
735
	writeTag (fn, QString("<VersionMajor>0</VersionMajor>\n"), indent);
736
	writeTag (fn, QString("<VersionMinor>1</VersionMinor>\n"), indent);
737
	writeTag (fn, QString("<BuildMajor>0</BuildMajor>\n"), indent);
738
	writeTag (fn, QString("<BuildMinor>0</BuildMinor>\n"), indent);
739
	indent--;
740
	writeTag (fn, QString("</Version>\n"), indent);
741
	writeTag (fn, QString("<Type>Beta</Type>\n"), indent);
742
	writeTag (fn, QString("<Time>Jan 31 2008, 00:00:00</Time>\n"), indent);
743
	writeTag (fn, QString("<Builder>theosys</Builder>\n"), indent);
744
	indent--;
745
	writeTag (fn, QString("</Build>\n"), indent);
746
	writeTag (fn, QString("<LangID>EN</LangID>\n"), indent);
747
	writeTag (fn, QString("<PartNumber>000-00000-00</PartNumber>\n"), indent);
748
	indent--;
749
	writeTag (fn, QString("</Author>\n"), indent);
750
	writeTag (fn, QString("</TrainingCenterDatabase>\n"), indent);
751
 
752
	fn.close();
753
	KMessageBox::information(this, i18n("File ") + fname + i18n(" was written successfully."));
88 andreas 754
}
755
 
756
void sportwatcherWidget::fileSave()
757
{
758
}
759
 
760
void sportwatcherWidget::fileOpen()
761
{
762
QString fname = KFileDialog::getOpenFileName(Data, QString("*.gmn"), this, QString("SportWatcher"));
137 andreas 763
int m;
88 andreas 764
 
765
        if (fname.isEmpty())
766
           return;
767
 
768
	spw.destroy();
769
 
770
        if (spw.setFileName(fname.ascii()) == -1)
771
	   return;
772
 
773
	if (gmn)
774
	   garmin_free_data (gmn);
775
 
776
	gmn = spw.readFile();
104 andreas 777
	zfactor = 0;
137 andreas 778
 
779
	if ((m = garmin_count_error()) > 0)
780
	{
781
	int i, key = -1;
782
 
783
	   for (i = 0; i < m; i++)
784
	      KMessageBox::error(this, QString(garmin_get_next_error(&key)));
785
 
786
	   garmin_clear_errors();
787
	   return;
788
	}
789
 
88 andreas 790
	showLaps();
100 andreas 791
	showTrack();
88 andreas 792
	showCurves();
793
}
794
 
795
void sportwatcherWidget::fileNew()
796
{
132 andreas 797
progressWidget *dlg = new progressWidget(this, "progressWidgetBase");
96 andreas 798
 
100 andreas 799
	dlg->show();
137 andreas 800
 
801
	if (!dlg->Download())
802
	{
803
	int m, key;
804
 
805
	   key = -1;
806
 
807
	   for (m = 0; m < garmin_count_error(); m++)
808
	      KMessageBox::error(this, QString(garmin_get_next_error(&key)));
809
	}
810
	else
811
	   getActivities();
812
 
813
	garmin_clear_errors();
96 andreas 814
	delete dlg;
88 andreas 815
}
816
 
817
/*
818
 * This function is called, when the user clicks at the menu point
819
 * "Save Heart Rate".
820
 * First, a file dialog box is displayed, where the user can choose a
821
 * directory and a file name to save the heart rate.
822
 * If the file could successfully be created, the heart rate is saved
137 andreas 823
 * in the "HRM"-format. This is the native format Polar uses to store
88 andreas 824
 * heart rate data. I've choosen this format, because it's popular and
825
 * used by many other software too.
826
 */
827
void sportwatcherWidget::extrasSaveHR()
828
{
829
QString fname, str1, str2;
830
QFile fdfile;
831
QDateTime *qt, *oldqt;
832
QDate dat;
833
QTime t;
834
QDir dir = QDir::home();
835
char hv0[256];
836
RUN_NODE *rn;
837
LAP *lap, *alap;
838
POINT *point;
839
int samples, smp, seconds, anz, nsec, samsec;
840
int avgHeart, minHeart, maxHeart, aktHeart;
841
int secRange1, secRange2, secRange3, secAbove, secBeyond;
842
 
843
	if (!gmn)
844
	{
845
	   KMessageBox::information(this, i18n("There is no activity open"));
846
	   return;
847
	}
848
 
849
	if (HRM.isEmpty())
850
	   str1 = dir.path();
851
	else
852
	   str1 = HRM;
853
 
854
	str1 +=  "/" + StartTime.toString("yyyyMMddThhmmss.zzz.hrm");
855
	fname = KFileDialog::getSaveFileName(str1, QString("*.hrm"), this, QString("SportWatcher"));
856
 
857
	if (fname.isEmpty())
858
	   return;
859
 
860
	fdfile.setName(fname);
861
 
862
	if (fdfile.exists())
863
	{
864
	   if (KMessageBox::questionYesNo(this, i18n("Do you really want to overwrite this file?")) == KMessageBox::No)
865
	      return;
866
	}
867
 
868
	if (!fdfile.open(IO_ReadWrite | IO_Truncate))
869
	{
870
	   KMessageBox::error(this, i18n("Error creating a file!\nPlease check permissions."));
871
	   return;
872
	}
873
 
874
	rn = ds.getRunNode();
875
	lap = ds.getLap(rn->run->first_lap_index);
876
	t = StartTime.time();
877
	dat = StartTime.date();
878
 
879
	if ((point = ds.getPoint(lap->start_time)) == 0)
880
	{
881
	   fdfile.close();
882
	   return;
883
	}
884
 
885
	strcpy (hv0, "[Params]\n");
886
	write(fdfile.handle(), &hv0[0], strlen(hv0));
887
	str1 = dat.toString("yyyyMMdd");
888
	str2 = t.toString("hh:mm:ss.z");
889
	sprintf(hv0, "Version=106\nMonitor=11\nSMode=000000000\nDate=%s\nStartTime=%s\n",
890
		str1.ascii(), str2.ascii());
891
	write(fdfile.handle(), &hv0[0], strlen(hv0));
892
	t.setHMS(0, 0, 0);
893
	t = t.addSecs(max_time);
894
	str2 = t.toString("hh:mm:ss.z");
895
 
896
	switch (sampleTime)
897
	{
898
	   case 0: samsec = 5; break;
899
	   case 1: samsec = 15; break;
900
	   case 2: samsec = 30; break;
901
	   case 3: samsec = 60; break;
902
	   default:
903
	      samsec = 15;
904
	}
905
 
906
	sprintf(hv0, "Length=%s\nInterval=%d\nUpper1=%d\nLower1=%d\nUpper2=%d\n",
907
	   str2.ascii(), samsec, upper1, lower1, upper2);
908
	write(fdfile.handle(), &hv0[0], strlen(hv0));
909
	sprintf(hv0, "Lower2=%d\nUpper3=%d\nLower3=%d\nTimer1=00:00:00.0\n",
910
		lower2, upper3, lower3);
911
	write(fdfile.handle(), &hv0[0], strlen(hv0));
912
	strcpy(hv0, "Timer2=00:00:00.0\nTimer3=00:00:00.0\nActiveLimit=0\n");
913
	write(fdfile.handle(), &hv0[0], strlen(hv0));
914
	sprintf(hv0, "MaxHR=%d\nRestHR=%d\nStartDelay=0\nVO2max=%d\nWeight=%d\n\n",
915
		MaxHr, restHr, vo2max, weight);
916
	write(fdfile.handle(), &hv0[0], strlen(hv0));
917
 
918
	// Write the intervall times. One block for every lap
919
	secRange1 = secRange2 = secRange3 = secAbove = secBeyond = 0;
920
	strcpy(hv0, "[IntTimes]\n");
921
	write(fdfile.handle(), &hv0[0], strlen(hv0));
922
	t.setHMS(0, 0, 0);
923
 
924
	for (unsigned int i = rn->run->first_lap_index; i < rn->run->last_lap_index; i++)
925
	{
926
	   alap = ds.getLap(i);
927
	   point = ds.getPoint(alap->start_time);
928
	   oldqt = garmin_dtime(point->time);
929
	   avgHeart = minHeart = maxHeart = aktHeart = 0;
930
	   anz = 0;
931
	   unsigned long lastTime = point->time;
932
	   int totSec = 0;
933
 
934
	   while (point)
935
	   {
936
	      if (point->time > (alap->start_time + (alap->total_time / 100)))
937
		 break;
938
 
939
	      if (point->heart_rate > 0)
940
	      {
941
		 avgHeart += point->heart_rate;
942
		 nsec = point->time - lastTime;
943
		 totSec += nsec;
944
 
945
		 if (minHeart == 0 || minHeart > point->heart_rate)
946
		    minHeart = point->heart_rate;
947
 
948
		 if (maxHeart < point->heart_rate)
949
		    maxHeart = point->heart_rate;
950
 
951
		 if (aktHeart == 0 && totSec >= samsec)
952
		    aktHeart = avgHeart / (anz + 1);
953
 
954
		 if (point->heart_rate < lower1)
955
		    secBeyond += nsec;
956
		 else if (point->heart_rate < lower2)
957
		    secRange1 += nsec;
958
		 else if (point->heart_rate < lower3)
959
		    secRange2 += nsec;
960
		 else if (point->heart_rate < upper3)
961
		    secRange3 += nsec;
962
		 else
963
		    secAbove += nsec;
964
 
965
		 lastTime = point->time;
966
		 anz++;
967
	      }
968
 
969
	      point = ds.getPoint(point->time+1);
970
	   }
971
 
972
	   t = t.addSecs(alap->total_time / 100);
973
	   str1 = t.toString("hh:mm:ss.z");
974
	   sprintf(hv0, "%s\t %d\t %d\t %d\t %d\n",
975
	      str1.ascii(), aktHeart, minHeart, avgHeart / anz, maxHeart);
976
	   write(fdfile.handle(), &hv0[0], strlen(hv0));
977
	   strcpy(hv0, "32\t 0\t 0\t 0\t 0\t 0\n");
978
	   write(fdfile.handle(), &hv0[0], strlen(hv0));
979
	   strcpy(hv0, "0\t 0\t 0\t 0\t 0\n");
980
	   write(fdfile.handle(), &hv0[0], strlen(hv0));
981
	   sprintf(hv0, "0\t %d\t 0\t 0\t 0\t 0\n", (int)alap->total_distance);
982
	   write(fdfile.handle(), &hv0[0], strlen(hv0));
983
	   strcpy(hv0, "0\t 0\t 0\t 0\t 0\t 0\n");
984
	   write(fdfile.handle(), &hv0[0], strlen(hv0));
985
	}
986
 
987
	strcpy(hv0, "\n[IntNotes]\n\n[ExtraData]\n\n");
988
	write(fdfile.handle(), &hv0[0], strlen(hv0));
989
 
990
	strcpy(hv0, "[Summary-123]\n");
991
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// Time limits 1
992
	smp = max_time - secBeyond - secRange1 - secRange2 - secRange3 - secAbove;
993
	sprintf(hv0, "%u\t %u\t %u\t %u\t %u\n",
994
		max_time, secRange1, secRange2 + secRange3,
995
		secAbove + secBeyond, smp);
996
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// limits 1
997
	sprintf(hv0, "%d\t %d\t %d\t %d\n",
998
		MaxHr, upper1, lower1, restHr);
999
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// Time limits 1
1000
	sprintf(hv0, "%u\t %u\t %u\t %u\t %u\n",
1001
		max_time, secRange2, secRange1 + secRange3,
1002
		secAbove + secBeyond, smp);
1003
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// limits 2
1004
	sprintf(hv0, "%d\t %d\t %d\t %d\n",
1005
		MaxHr, upper2, lower2, restHr);
1006
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// Time limits 2
1007
	sprintf(hv0, "%u\t %u\t %u\t %u\t %u\n",
1008
		max_time, secRange3, secRange1 + secRange2,
1009
		secAbove + secBeyond, smp);
1010
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// limits 3
1011
	sprintf(hv0, "%d\t %d\t %d\t %d\n",
1012
		MaxHr, upper3, lower3, restHr);
1013
	write(fdfile.handle(), &hv0[0], strlen(hv0));	// Time limits 3
1014
	samples = max_time / samsec;
1015
	sprintf(hv0, "0\t %u\n\n", samples);	// samples
1016
	write(fdfile.handle(), &hv0[0], strlen(hv0));
1017
 
1018
	strcpy(hv0, "[Summary-TH]\n");
1019
	write(fdfile.handle(), &hv0[0], strlen(hv0));
1020
	sprintf(hv0, "%u\t 0\t %u\t %d\t %d\t 0\n", max_time, max_time - max_hr - restHr, max_hr, restHr);
1021
	write(fdfile.handle(), &hv0[0], strlen(hv0));
1022
	sprintf(hv0, "%d\t %d\t %d\t %d\n", MaxHr, upper3, lower1, restHr);
1023
	write(fdfile.handle(), &hv0[0], strlen(hv0));
1024
	sprintf(hv0, "0\t %u\n\n", samples);	// samples
1025
	write(fdfile.handle(), &hv0[0], strlen(hv0));
1026
 
1027
	sprintf(hv0, "[HRZones]\n%d\n%d\n%d\n%d\n%d\n%d\n0\n0\n0\n0\n0\n\n",
1028
		MaxHr, upper3, upper2, upper1, lower1, restHr);
1029
	write(fdfile.handle(), &hv0[0], strlen(hv0));
1030
 
1031
	strcpy(hv0, "[HRData]\n");
1032
	write(fdfile.handle(), &hv0[0], strlen(hv0));
1033
 
1034
	smp = 0;		// average heart rate of 15 seconds
1035
	seconds = 0;
1036
	anz = 0;
1037
	nsec = samsec;
1038
	oldqt = garmin_dtime(lap->start_time);
1039
	qt = 0;
1040
	point = ds.getPoint(lap->start_time);
1041
 
1042
	while (point)
1043
	{
1044
	   if (seconds >= nsec)
1045
	   {
1046
	      if (anz > 0)
1047
	      {
1048
		 sprintf(hv0, "%d\n", smp / anz);
1049
		 write(fdfile.handle(), &hv0[0], strlen(hv0));
1050
	      }
1051
 
1052
	      if (smp > 0 && seconds >= (nsec + samsec))
1053
	      {
1054
		 if (anz <= 0)
1055
		    anz = 0;
1056
 
1057
		 for (int x = nsec; x < seconds; x += samsec)
1058
		 {
1059
		    sprintf(hv0, "%d\n", smp / anz);
1060
		    write(fdfile.handle(), &hv0[0], strlen(hv0));
1061
		    nsec += samsec;
1062
		 }
1063
	      }
1064
 
1065
	      anz = 0;
1066
	      smp = 0;
1067
	      nsec += samsec;
1068
	   }
1069
 
1070
	   qt = garmin_dtime (point->time);
1071
	   seconds += oldqt->secsTo(*qt);
1072
 
1073
	   if (point->heart_rate > 0)
1074
	   {
1075
	      smp += point->heart_rate;
1076
	      anz++;
1077
	   }
1078
 
1079
	   delete oldqt;
1080
	   oldqt = qt;
1081
	   point = ds.getPoint(point->time + 1);
1082
	}
1083
 
1084
	fdfile.close();
1085
	KMessageBox::information(this, i18n("File successfully written."));
1086
}
1087
 
1088
void sportwatcherWidget::extrasSettings()
1089
{
1090
settingsWidget *dlg = new settingsWidget(this, "settingsWidgetBase", TRUE, 0);
1091
 
1092
	if (dlg->exec() == QDialog::Accepted)
1093
	{
1094
	   KSimpleConfig *cfg = new KSimpleConfig(QString("sportwatcher.rc"), true);
1095
	   cfg->setGroup(QString("SportWatcher"));
1096
	   lower1 = cfg->readNumEntry("lower1");
1097
	   lower2 = cfg->readNumEntry("lower2");
1098
	   lower3 = cfg->readNumEntry("lower3");
1099
	   upper1 = cfg->readNumEntry("upper1");
1100
	   upper2 = cfg->readNumEntry("upper2");
1101
	   upper3 = cfg->readNumEntry("upper3");
1102
	   MaxHr = cfg->readNumEntry("maxHr");
1103
	   restHr = cfg->readNumEntry("restHr");
1104
	   vo2max = cfg->readNumEntry("vo2max");
1105
	   weight = cfg->readNumEntry("weight");
1106
	   sampleTime = cfg->readNumEntry("seconds");
149 andreas 1107
	   Serial = cfg->readBoolEntry("Serial");
88 andreas 1108
	   Device = cfg->readEntry("Device");
1109
	   Data = cfg->readEntry("Data");
1110
	   HRM = cfg->readEntry("HRM");
151 andreas 1111
	   MAP = cfg->readEntry("MAP");
149 andreas 1112
	   Units = cfg->readNumEntry("Units");
88 andreas 1113
	   delete cfg;
1114
	}
1115
 
1116
	delete dlg;
152 andreas 1117
}
151 andreas 1118
 
152 andreas 1119
void sportwatcherWidget::extrasWMSSettings()
1120
{
1121
wmsbase *dlg = new wmsbase(this, "wmswidgetbase", TRUE, 0);
151 andreas 1122
 
152 andreas 1123
	dlg->exec();
1124
	delete dlg;
88 andreas 1125
}
1126
 
1127
/*
1128
 * Functions to fill in the boxes of the main mask.
1129
 */
1130
void sportwatcherWidget::showLaps()
1131
{
1132
QString qs_name, qs_distance, qs_etime, qs_avgpace, qs_avgspeed, qs_maxspeed;
1133
QString qs_calories, qs_avghr, qs_maxhr, qs_avgcadence, qs_ascent, qs_descent;
1134
QDateTime dt;
1135
QTime t, st;
1136
QDateTime *qt;
1137
LAP *lap;
1138
POINT *point;
1139
RUN_NODE *rakt, *rn;
149 andreas 1140
int laps, i, anz, men, cad;
1141
double alt_asc, alt_dsc, sum_asc, sum_dsc, old_asc, old_dsc;
88 andreas 1142
 
1143
	if (!gmn)
1144
	{
1145
	   KMessageBox::error(0, i18n("No data were loaded!"));
1146
	   return;
1147
	}
1148
 
1149
	if (gmn->type == data_Dnil)
1150
	{
1151
	   KMessageBox::error(0, i18n("No data found!"));
1152
	   return;
1153
	}
1154
 
1155
	if (gmn->type != data_Dlist)     /* List of data */
1156
	{
1157
	   KMessageBox::error(0, QString("Found unexpected data type %1!").arg(gmn->type));
1158
	   return;
1159
	}
1160
 
1161
	ds.destroy();
1162
	min_hr = max_hr = 0;
1163
	min_height = max_height = 0.0;
1164
	liLaps->clear();
100 andreas 1165
	liLaps->setAllColumnsShowFocus(true);
88 andreas 1166
	ds.garmin_print_data(gmn);
1167
	rn = ds.getRunNode();
1168
	rakt = rn;
1169
	liLaps->setRootIsDecorated(true);
128 andreas 1170
	liLaps->setAlternateBackground(KGlobalSettings::alternateBackgroundColor());
88 andreas 1171
	liLaps->setColumnAlignment(1, Qt::AlignRight);
1172
	liLaps->setColumnAlignment(2, Qt::AlignRight);
1173
	liLaps->setColumnAlignment(3, Qt::AlignRight);
1174
	liLaps->setColumnAlignment(4, Qt::AlignRight);
1175
	liLaps->setColumnAlignment(5, Qt::AlignRight);
1176
	liLaps->setColumnAlignment(6, Qt::AlignRight);
1177
	liLaps->setColumnAlignment(7, Qt::AlignRight);
1178
	liLaps->setColumnAlignment(8, Qt::AlignRight);
1179
	liLaps->setColumnAlignment(9, Qt::AlignRight);
1180
	liLaps->setColumnAlignment(10, Qt::AlignRight);
1181
	liLaps->setColumnAlignment(11, Qt::AlignRight);
1182
 
1183
	qs_name = qs_distance = qs_etime = qs_avgpace = qs_avgspeed = qs_maxspeed = QString("");
1184
	qs_calories = qs_avghr = qs_maxhr = qs_avgcadence = qs_ascent = qs_descent = QString("");
1185
	men = 0;
149 andreas 1186
	cad = 0;
88 andreas 1187
 
1188
	while (rakt)
1189
	{
1190
	   if (rakt->run->type == data_D1000 || rakt->run->type == data_D1009 ||
1191
	   	rakt->run->type == data_D1010)
1192
	   {
1193
	   int lt, cal, ahr, mhr;
1194
	   double distance, speed, mspeed;
1195
	   QDate dat;
1196
 
1197
	      switch (rakt->run->sport_type)
1198
	      {
1199
		 case D1000_running: qs_name = QString("Running: "); break;
1200
		 case D1000_biking:  qs_name = QString("Biking: "); break;
1201
		 case D1000_other:   qs_name = QString("Other: "); break;
1202
		 default:
1203
		    qs_name = QString("Unknown: ");
1204
	      }
1205
 
1206
	      lap = ds.getLap(rakt->run->first_lap_index);
1207
	      qt = garmin_dtime (lap->start_time);
1208
	      StartTime = *qt;
1209
	      st = qt->time();
1210
	      dat = qt->date();
1211
	      delete qt;
1212
	      lap = ds.getLap(rakt->run->last_lap_index);
1213
	      qt = garmin_dtime (lap->start_time);
1214
	      t = qt->addSecs(lap->total_time / 100).time();
1215
	      lt = st.secsTo(t);
1216
	      t.setHMS(0, 0, 0);
1217
	      t = t.addSecs(lt);
1218
	      qt->setDate(dat);
1219
	      qt->setTime(t);
1220
	      qs_name.append(dat.toString("dd.MM.yyyy"));
1221
	      qs_name.append(" ");
1222
	      qs_name.append(st.toString("hh:mm:ss"));
1223
	      max_time = lt;
1224
	      qs_etime = QString(qt->toString("hh:mm:ss.zzz"));
1225
 
1226
	      distance = 0.0;
1227
	      cal = 0;
1228
	      mspeed = 0;
1229
	      ahr = mhr = 0;
1230
	      anz = 0;
149 andreas 1231
	      cad = 0;
1232
	      sum_asc = sum_dsc = old_asc = old_dsc = 0;
88 andreas 1233
 
1234
	      for (i = rakt->run->first_lap_index; (unsigned int)i <= rakt->run->last_lap_index; i++)
1235
	      {
1236
		 if ((lap = ds.getLap(i)) == NULL)
1237
		    continue;
1238
 
1239
		 distance += lap->total_distance;
1240
		 cal += lap->calories;
149 andreas 1241
 
1242
		 if (lap->avg_cadence != 0xff)
1243
		    cad += lap->avg_cadence;
1244
 
88 andreas 1245
		 ahr += lap->avg_heart_rate;
1246
		 anz++;
1247
 
1248
		 if (lap->max_speed > mspeed)
1249
		    mspeed = lap->max_speed;
1250
 
1251
		 if (lap->max_heart_rate > mhr)
1252
		    mhr = lap->max_heart_rate;
1253
	      }
1254
 
149 andreas 1255
	      if (Units == 1)		// Statute?
1256
		 qs_distance.sprintf("%.2f ft", distance / 0.304);
1257
	      else
1258
	         qs_distance.sprintf("%.2f m", distance);
1259
 
104 andreas 1260
	      total_distance = distance;
88 andreas 1261
 
1262
	      if (distance > 0)
1263
	      {
1264
		 QTime tt = qt->time();
1265
		 long secs = (double)(tt.hour() * 3600 + tt.minute() * 60 + tt.second()) / 100.0 * (1000.0 / distance * 100.0);
1266
		 int h = secs / 3600;
1267
		 int m = (secs - (h * 3600)) / 60;
1268
		 int s = secs - ((h * 3600) + (m * 60));
1269
		 t = QTime(h, m, s, 0);
1270
		 qs_avgpace = t.toString("  hh:mm:ss");
149 andreas 1271
//		 qs_avgpace.append(QString(" /lap"));
88 andreas 1272
	      }
1273
 
149 andreas 1274
	      if (Units == 1)		// Statute?
1275
		 speed = distance / lt;
1276
	      else
1277
		 speed = distance / lt * 3.6;
1278
 
1279
	      qs_avgspeed.sprintf("%.2f %s", speed, (Units == 1) ? "mi/h" : "km/h");
1280
	      qs_maxspeed.sprintf("%.2f %s", (Units == 1) ? mspeed : mspeed * 3.6, (Units == 1) ? "mi/h" : "km/h");
88 andreas 1281
	      qs_calories.sprintf("%d", cal);
1282
	      qs_avghr.sprintf("%d bpm", ahr / anz);
1283
	      qs_maxhr.sprintf("%d bpm", mhr);
1284
 
149 andreas 1285
	      if (cad > 0)
1286
		 qs_avgcadence.sprintf("%d", cad / anz);
1287
 
128 andreas 1288
	      KListViewItem *element = new KListViewItem(liLaps, qs_name, qs_distance,
88 andreas 1289
		qs_etime, qs_avgpace, qs_avgspeed, qs_maxspeed, qs_calories, qs_avghr);
1290
	      element->setText(8, qs_maxhr);
1291
	      element->setText(9, qs_avgcadence);
1292
	      element->setText(10, qs_ascent);
1293
	      element->setText(11, qs_descent);
1294
	      element->sortChildItems(0, false);
1295
	      element->setOpen(true);
128 andreas 1296
	      element->setPixmap(0, QPixmap::fromMimeSource(QString("activity.png")));
88 andreas 1297
	      liLaps->insertItem(element);
1298
	      delete qt;
1299
	      /* Get the laps. */
1300
	      laps = 1;
1301
 
1302
	      for (i = rakt->run->first_lap_index; (unsigned int)i <= rakt->run->last_lap_index; i++)
1303
	      {
149 andreas 1304
		 double spd;
1305
		 char *un;
1306
 
88 andreas 1307
		 if ((lap = ds.getLap(i)) == NULL)
1308
		    continue;
1309
 
1310
		 qt = garmin_dtime (lap->start_time);
1311
		 qs_name.sprintf("Lap %03d - ", laps);
1312
		 qs_name.append(qt->toString("hh:mm:ss"));
149 andreas 1313
		 qs_distance.sprintf("%.2f %s", (Units == 1) ? lap->total_distance / 0.304 : lap->total_distance, (Units == 1) ? "ft" : "m");
88 andreas 1314
		 t = QTime(0, 0, 0, 0);
1315
		 t = t.addMSecs(lap->total_time * 10);
1316
		 qs_etime = t.toString("hh:mm:ss.zzz");
149 andreas 1317
		 spd = lap->total_distance / (lap->total_time / 100.0);
1318
 
1319
		 if (Units == 0)
1320
		 {
1321
		    un = (char *)"km/h";
1322
		    spd *= 3.6;
1323
		 }
1324
		 else
1325
		    un = (char *)"mi/h";
1326
 
1327
		 qs_avgspeed.sprintf("%.2f %s", spd, un);
1328
		 qs_maxspeed.sprintf("%.2f %s", (Units == 1) ? lap->max_speed : lap->max_speed * 3.6, un);
88 andreas 1329
		 qs_calories.sprintf("%d", lap->calories);
1330
 
1331
		 if (lap->total_distance > 0 && lap->total_time != 0)
1332
		 {
1333
		    long secs = (double)lap->total_time / 10000.0 * (1000.0 / lap->total_distance * 100.0);
1334
		    int h = secs / 3600;
1335
		    int m = (secs - (h * 3600)) / 60;
1336
		    int s = secs - ((h * 3600) + (m * 60));
1337
		    t = QTime(h, m, s, 0);
1338
		    qs_avgpace = t.toString("hh:mm:ss");
149 andreas 1339
//		    qs_avgpace.append(QString(" /lap"));
88 andreas 1340
		 }
1341
 
1342
		 qs_avghr.sprintf("%d bpm", lap->avg_heart_rate);
1343
		 qs_maxhr.sprintf("%d bpm", lap->max_heart_rate);
1344
 
1345
		 anz = 0;
1346
		 alt_asc = alt_dsc = 0;
1347
 
1348
		 if ((point = ds.getPoint(lap->start_time)) != 0)
1349
		 {
1350
		    if (point->alt < 20000)
149 andreas 1351
		    {
88 andreas 1352
		       alt_dsc = alt_asc = point->alt;
149 andreas 1353
 
1354
		       if (old_asc == 0)
1355
			  old_asc = alt_asc;
1356
 
1357
		       if (old_dsc == 0)
1358
			  old_dsc = alt_dsc;
1359
		    }
88 andreas 1360
		    else
1361
		       alt_dsc = alt_asc = 0;
1362
 
1363
		    while (point)
1364
		    {
1365
		       if (point->time > (lap->start_time + (lap->total_time / 100)))
1366
			 break;
1367
 
1368
		       if (point->alt > alt_asc && point->alt < 20000)
1369
		       {
1370
			  alt_asc = point->alt;
1371
 
1372
			  if (alt_dsc == 0)
1373
			     alt_dsc = point->alt;
1374
		       }
1375
 
1376
		       if (point->alt < alt_dsc)
1377
			  alt_dsc = point->alt;
1378
 
1379
		       // save the min and max values. We need this information to
1380
		       // build the graphics.
1381
		       if (point->heart_rate > max_hr)
1382
			  max_hr = point->heart_rate;
1383
 
1384
		       if ((min_hr == 0 && point->heart_rate > 0) || (point->heart_rate > 0 && point->heart_rate < min_hr))
1385
			  min_hr = point->heart_rate;
1386
 
1387
		       if (point->alt < 20000 && max_height < point->alt)
1388
			  max_height = point->alt;
1389
 
1390
		       if (point->alt < 20000 && (min_height == 0.0 || min_height > point->alt))
1391
			  min_height = point->alt;
1392
 
1393
		       if (point->heart_rate > 0)
1394
		       {
1395
			  avg_hr += point->heart_rate;
1396
			  men++;
1397
		       }
1398
 
1399
		       point = ds.getPoint(point->time + 1);
1400
		    }
1401
 
149 andreas 1402
		    if (old_asc < alt_asc)
1403
		       sum_asc += (alt_asc - old_asc);
1404
 
1405
		    if (old_dsc > alt_dsc)
1406
		       sum_dsc += (old_dsc - alt_dsc);
1407
 
1408
		    old_asc = alt_asc;
1409
		    old_dsc = alt_dsc;
1410
		    qs_ascent.sprintf("%.2f %s", (Units == 1) ? (alt_asc / 0.304) : alt_asc, (Units == 1) ? "ft" : "m");
1411
		    qs_descent.sprintf("%.2f %s", (Units == 1) ? (alt_dsc / 0.304) : alt_dsc, (Units == 1) ? "ft" : "m");
88 andreas 1412
		 }
1413
 
1414
		 if (lap->avg_cadence != 0xff)
1415
		    qs_avgcadence.sprintf("%d", lap->avg_cadence);
1416
 
128 andreas 1417
		 KListViewItem *edetail = new KListViewItem(element, qs_name, qs_distance,
88 andreas 1418
			qs_etime, qs_avgpace, qs_avgspeed, qs_maxspeed, qs_calories, qs_avghr);
1419
		 edetail->setText(8, qs_maxhr);
1420
		 edetail->setText(9, qs_avgcadence);
1421
		 edetail->setText(10, qs_ascent);
1422
		 edetail->setText(11, qs_descent);
128 andreas 1423
		 edetail->setPixmap(0, QPixmap::fromMimeSource(QString("history.png")));
1424
 
1425
		 switch (rakt->run->sport_type)
1426
		 {
1427
		    case D1000_running: edetail->setPixmap(0, QPixmap::fromMimeSource(QString("run.png"))); break;
1428
		    case D1000_biking:  edetail->setPixmap(0, QPixmap::fromMimeSource(QString("bike.png"))); break;
1429
		    case D1000_other:   edetail->setPixmap(0, QPixmap::fromMimeSource(QString("other.png"))); break;
1430
		    default:
1431
		       edetail->setPixmap(0, QPixmap::fromMimeSource(QString("other.png")));
1432
		 }
1433
 
88 andreas 1434
		 liLaps->clearSelection();
1435
		 element->insertItem(edetail);
1436
		 delete qt;
1437
		 laps++;
1438
	      }
149 andreas 1439
 
1440
	      qs_ascent.sprintf("%.2f %s", (Units == 1) ? sum_asc / 0.304 : sum_asc, (Units == 1) ? "ft" : "m");
1441
	      qs_descent.sprintf("%.2f %s", (Units == 1) ? sum_dsc / 0.304 : sum_dsc, (Units == 1) ? "ft" : "m");
1442
      	      element->setText(10, qs_ascent);
1443
	      element->setText(11, qs_descent);
88 andreas 1444
	   }
1445
 
1446
	   rakt = rakt->next;
1447
	}
1448
 
1449
	if (men > 0)
1450
	   avg_hr /= men;
1451
}
1452
 
100 andreas 1453
void sportwatcherWidget::showTrack()
1454
{
132 andreas 1455
	showTrack(0, QRect(0, 0, 0, 0), 0);
104 andreas 1456
}
1457
 
1458
void sportwatcherWidget::showTrack(int zoom)
1459
{
132 andreas 1460
	showTrack(zoom, mapPan, mapLap);
1461
}
1462
 
1463
void sportwatcherWidget::showTrack(int zoom, const QRect &pan, LAP *lap)
1464
{
100 andreas 1465
int width, height;
1466
double x1, y1, x2, y2;
132 andreas 1467
int a, top, left, panX, panY;
1468
uint32 i;
109 andreas 1469
double coordW, coordH, tick;
128 andreas 1470
double meterW, dist;
100 andreas 1471
QPainter paint;
152 andreas 1472
posn_type posNW, posSE, posLXY, posRXY;
100 andreas 1473
POINT *point;
152 andreas 1474
bool Fgeo = false;
151 andreas 1475
#ifdef GDAL
1476
GDALDataset *poDataset;
1477
//double adfGeoTransform[6];
1478
GDALRasterBand *poBand;
1479
unsigned char *pafScanline;
1480
unsigned char *pafScanlineRed;
1481
unsigned char *pafScanlineGreen;
1482
unsigned char *pafScanlineBlue;
1483
int nXSize, nYSize;
1484
#endif
100 andreas 1485
 
109 andreas 1486
	if (!gmn)
1487
	   return;
1488
 
104 andreas 1489
	if (zoom != zfactor)
1490
	   zfactor = zoom;
1491
 
132 andreas 1492
	if (mapLap != lap)
1493
	   mapLap = lap;
1494
 
148 andreas 1495
	width = imgMap->width() - 2;
1496
	height = imgMap->height();
100 andreas 1497
	pmMap.resize(width, height);
1498
	paint.begin(&pmMap);
1499
 
132 andreas 1500
	panX = panY = 0;
1501
 
1502
	if (stateHand && mapPan != pan)
1503
	{
1504
	   mapPan = pan;
1505
	   panX = mapPan.right() - mapPan.left();
1506
	   panY = mapPan.bottom() - mapPan.top();
1507
	   oldTransX += (double)panX;
1508
	   oldTransY += (double)panY;
1509
	}
1510
 
104 andreas 1511
	memset(&posNW, 0, sizeof(posn_type));
1512
	memset(&posSE, 0, sizeof(posn_type));
100 andreas 1513
 
1514
	posSE.lat = 9999.0;
1515
	posNW.lon = 9999.0;
1516
 
1517
	/*
1518
	 * Find out the corners of our track (NW, NE, SE, SW)
1519
	 */
132 andreas 1520
	if (mapLap)
1521
	   i = mapLap->start_time;
1522
	else
1523
	   i = 0;
100 andreas 1524
 
1525
	while ((point = ds.getPoint(i)) != 0)
1526
	{
132 andreas 1527
	   if (mapLap && point->time > (mapLap->start_time + (mapLap->total_time / 100)))
1528
	      break;
1529
 
100 andreas 1530
	   if (point->posn.lat == 0x7fffffff || point->posn.lon == 0x7fffffff)
1531
	   {
132 andreas 1532
	      i = point->time + 1;
100 andreas 1533
	      continue;
1534
	   }
1535
 
1536
	   if (SEMI2DEG(point->posn.lat) > posNW.lat)
1537
	      posNW.lat = SEMI2DEG(point->posn.lat);
1538
 
1539
	   if (SEMI2DEG(point->posn.lat) < posSE.lat)
1540
	      posSE.lat = SEMI2DEG(point->posn.lat);
1541
 
1542
	   if (SEMI2DEG(point->posn.lon) < posNW.lon)
1543
	      posNW.lon = SEMI2DEG(point->posn.lon);
1544
 
1545
	   if (SEMI2DEG(point->posn.lon) > posSE.lon)
1546
	      posSE.lon = SEMI2DEG(point->posn.lon);
1547
 
132 andreas 1548
	   i = point->time + 1;
100 andreas 1549
	}
104 andreas 1550
 
1551
	coordW = (posNW.lon > posSE.lon) ? posNW.lon - posSE.lon : posSE.lon - posNW.lon;
1552
	coordH = (posNW.lat > posSE.lat) ? posNW.lat - posSE.lat : posSE.lat - posNW.lat;
109 andreas 1553
	meterW = ds.earth_distance(posNW.lat, posNW.lon, posNW.lat, posSE.lon);
104 andreas 1554
 
1555
	// define the ticks to translate the GPS coordinates into pixels.
1556
	// The track should be centered and we have to calculate the
1557
	// rectangular within we draw the track.
152 andreas 1558
	if (coordW < coordH)
100 andreas 1559
	{
152 andreas 1560
	   tick = (double)width / coordW + (double)zoom;
1561
 
1562
	   if ((tick * coordH) > height)
109 andreas 1563
	      tick = (double)height / coordH + (double)zoom;
100 andreas 1564
	}
1565
	else
1566
	{
152 andreas 1567
	   tick = (double)height / coordH + (double)zoom;
1568
 
1569
	   if ((tick * coordW) > width)
109 andreas 1570
	      tick = (double)width / coordW + (double)zoom;
100 andreas 1571
	}
104 andreas 1572
 
152 andreas 1573
	left = (width - tick * coordW) / 2;
1574
	top = (height - tick * coordH) / 2;
1575
 
132 andreas 1576
	a = tick * coordW;
1577
	dist = meterW / a;
151 andreas 1578
#ifdef GDAL
146 andreas 1579
	/*
1580
	 * If we have a map file, we try to read it and if successfull,
1581
	 * we should get a map painted.
1582
	 */
152 andreas 1583
	if (!MAP.isEmpty() && coordW != 9999 && coordH != 9999)
146 andreas 1584
	{
152 andreas 1585
	   posLXY.lon = posNW.lon - (left + oldTransX) / tick;
1586
	   posLXY.lat = posNW.lat + (top + oldTransY) / tick;
1587
	   posRXY.lon = posSE.lon + (width - left - a - oldTransX) / tick;
1588
	   posRXY.lat = posSE.lat - (height - top - (tick * coordH) - oldTransY) / tick;
1589
 
1590
	   if (writeWMSTag(posLXY.lon, posLXY.lat, posRXY.lon, posRXY.lat, width, height))
151 andreas 1591
	   {
1592
	      if ((poDataset = (GDALDataset *)GDALOpen (MAP.ascii(), GA_ReadOnly)) != NULL)
1593
	      {
1594
		 QPixmap bild;
1595
		 int nRasterCount = poDataset->GetRasterCount();
1596
		 int nXBlock, nYBlock;
152 andreas 1597
		 GDALColorTable *pCT, *pCTb, *pCTr, *pCTg;
146 andreas 1598
 
151 andreas 1599
		 int             bGotMin, bGotMax;
1600
		 int		 tTypeLen, tColor, tColorEntrys;
1601
		 GDALDataType    tRasterType;
1602
		 double          adfMinMax[2];
1603
 
152 andreas 1604
		 pafScanlineRed = pafScanlineGreen = pafScanlineBlue = 0;
1605
 
151 andreas 1606
		 for (a = 1; a <= nRasterCount; a++)
1607
		 {
1608
		    poBand = poDataset->GetRasterBand (a);
1609
		    poBand->GetBlockSize (&nXBlock, &nYBlock);
1610
		    nXSize = poBand->GetXSize();
1611
		    nYSize = poBand->GetYSize();
1612
		    tRasterType = poBand->GetRasterDataType ();
1613
		    tTypeLen = GDALGetDataTypeSize (tRasterType) / 8;	// We need Bytes not Bits!
1614
		    tColor = poBand->GetColorInterpretation ();
1615
 
1616
		    adfMinMax[0] = poBand->GetMinimum (&bGotMin);
1617
		    adfMinMax[1] = poBand->GetMaximum (&bGotMax);
1618
 
1619
		    if (!(bGotMin && bGotMax))
1620
		       GDALComputeRasterMinMax ((GDALRasterBandH)poBand, TRUE, adfMinMax);
1621
 
152 andreas 1622
		    if ((pCT = poBand->GetColorTable()) != NULL)
151 andreas 1623
		       tColorEntrys = poBand->GetColorTable()->GetColorEntryCount();
1624
 
1625
		    switch (a)
1626
		    {
152 andreas 1627
		       case 1: pafScanlineRed   = new unsigned char[tTypeLen * nXSize * nYSize]; pafScanline = pafScanlineRed; pCTr = pCT; break;
1628
		       case 2: pafScanlineGreen = new unsigned char[tTypeLen * nXSize * nYSize]; pafScanline = pafScanlineGreen; pCTg = pCT; break;
1629
		       case 3: pafScanlineBlue  = new unsigned char[tTypeLen * nXSize * nYSize]; pafScanline = pafScanlineBlue; pCTb = pCT; break;
151 andreas 1630
		    }
1631
 
152 andreas 1632
		    memset (pafScanline, 0, tTypeLen * nXSize * nYSize);
151 andreas 1633
 
152 andreas 1634
		    if (poBand->RasterIO (GF_Read, 0, 0, nXSize, nYSize, pafScanline, nXSize, nYSize, tRasterType, 0, 0) == CE_Failure)
1635
		    {
151 andreas 1636
		       KMessageBox::error(this, i18n("Error reading a raster band!"));
152 andreas 1637
		       Fgeo = false;
1638
		       break;
1639
		    }
1640
		    else
1641
		       Fgeo = true;
151 andreas 1642
		 }
1643
 
152 andreas 1644
		 if (Fgeo)
1645
		 {
1646
		 unsigned char *pCombinedBytes = new unsigned char[(tTypeLen * nXSize * nYSize * nRasterCount)];
1647
		 unsigned char *ptr_dest, *ptr_src;
1648
		 int j;
151 andreas 1649
 
152 andreas 1650
		    for (a = 0, j = 0; a < (nXSize * nYSize * nRasterCount); a += nRasterCount, j++)
151 andreas 1651
		    {
152 andreas 1652
		       int k = a;
1653
 
1654
		       for (int m = nRasterCount - 1; m >= 0; m--, k++)
1655
		       {
1656
		       unsigned char *pBytes;
1657
 
1658
			  switch (m)
1659
			  {
1660
			     case 2: pBytes = pafScanlineBlue; pCT = pCTb; break;
1661
			     case 1: pBytes = pafScanlineGreen; pCT = pCTg; break;
1662
			     default: pBytes = pafScanlineRed; pCT = pCTr;
1663
			  }
1664
 
1665
			  ptr_dest = pCombinedBytes + k;
1666
			  unsigned char b = pBytes[j];
1667
 
1668
			  if (pCT != NULL)
1669
			  {
1670
			     GDALColorEntry ce;
1671
			     unsigned int c = (unsigned int)b;
1672
			     c = pCT->GetColorEntryAsRGB (c, &ce);
1673
 
1674
			     if  (m == 0) c = ce.c1;
1675
			     if  (m == 1) c = ce.c2;
1676
			     if  (m == 2) c = ce.c3;
1677
 
1678
			     b = (unsigned char)c;
1679
			  }
1680
 
1681
			  ptr_src = &b;
1682
			  memcpy (ptr_dest, ptr_src, 1);
1683
		       }
151 andreas 1684
		    }
152 andreas 1685
 
1686
		    x1 = y1 = 0;
1687
 
1688
		    for (a = 0; a < (nXSize * nYSize * nRasterCount); a += 3)
1689
		    {
1690
		       paint.setPen (QPen(QColor((int)pCombinedBytes[a+2], (int)pCombinedBytes[a+1], (int)pCombinedBytes[a]), QPen::SolidLine));
1691
		       paint.drawPoint(x1, y1);
1692
		       x1++;
1693
 
1694
		       if (x1 >= nXSize)
1695
		       {
1696
			  x1 = 0;
1697
			  y1++;
1698
		       }
1699
		    }
1700
 
1701
		    delete pCombinedBytes;
151 andreas 1702
		 }
1703
 
152 andreas 1704
		 if (pafScanlineRed)
1705
		    delete pafScanlineRed;
151 andreas 1706
 
152 andreas 1707
		 if (pafScanlineGreen)
1708
		    delete pafScanlineGreen;
1709
 
1710
		 if (pafScanlineBlue)
1711
		    delete pafScanlineBlue;
1712
 
1713
		 GDALClose (poDataset);
1714
		 poDataset = 0;
151 andreas 1715
	      }
1716
	      else
1717
		 KMessageBox::error(this, i18n("Error opening WMS file!"));
1718
	   }
146 andreas 1719
	}
151 andreas 1720
#endif
100 andreas 1721
	// Colors and fonts
1722
	QColor background(220, 220, 220);
104 andreas 1723
	QColor red(255, 0, 0);
100 andreas 1724
	QColor black(0, 0, 0);
1725
	QColor yellow(255, 255, 0);
1726
	QFont fntNormal("Helvetica");
1727
	fntNormal.setPixelSize(10);
1728
	fntNormal.setStyleHint(QFont::Helvetica);
104 andreas 1729
	QPen dot(red, 4, QPen::SolidLine);
100 andreas 1730
	QPen line(black, 1, QPen::SolidLine);
1731
	QPen yline(yellow, 3, QPen::SolidLine);
1732
	// Fill background with background colors
152 andreas 1733
	if (!Fgeo)
1734
	   paint.fillRect(0, 0, width+2, height+2, background);
1735
 
109 andreas 1736
	paint.setPen(line);
1737
	paint.drawLine(10, height - 9, 10, height - 4);
1738
	paint.drawLine(10, height - 4, 10 + (1000 / dist), height - 4);
1739
	paint.drawLine(10 + (1000 / dist), height - 9, 10 + (1000 / dist), height - 4);
1740
	paint.setFont(fntNormal);
1741
	paint.drawText(10, height - 10, QString("1000 m"));
1742
 
100 andreas 1743
	// Draw track
132 andreas 1744
	if (mapLap)
1745
	   i = mapLap->start_time;
1746
	else
1747
	   i = 0;
1748
 
100 andreas 1749
	x1 = y1 = 0.0;
104 andreas 1750
 
100 andreas 1751
	while ((point = ds.getPoint(i)) != 0)
1752
	{
132 andreas 1753
	   if (mapLap && point->time > (mapLap->start_time + (mapLap->total_time / 100)))
1754
	      break;
1755
 
100 andreas 1756
	   if (point->posn.lat == 0x7fffffff || point->posn.lon == 0x7fffffff)
1757
	   {
132 andreas 1758
	      i = point->time + 1;
100 andreas 1759
	      continue;
1760
	   }
1761
 
132 andreas 1762
	   x2 = (left + ((posNW.lon - SEMI2DEG(point->posn.lon)) * tick * -1)) + oldTransX;
1763
	   y2 = (top + ((posNW.lat - SEMI2DEG(point->posn.lat)) * tick)) + oldTransY;
100 andreas 1764
 
1765
	   if (x1 == 0.0 && y1 == 0.0)
1766
	   {
1767
	      x1 = x2;
1768
	      y1 = y2;
1769
	   }
104 andreas 1770
 
100 andreas 1771
	   paint.setPen(yline);
104 andreas 1772
	   paint.drawLine(x1, y1, x2, y2);
1773
 
1774
	   if ((point->distance - dist) >= 1000.0)	// a dot at every 1000 meters
1775
	   {
1776
	      paint.setPen(dot);
1777
	      paint.drawEllipse(x2-1, y2-1, 2, 2);
1778
	      dist = (int)(point->distance / 1000) * 1000.0;
1779
	   }
1780
 
100 andreas 1781
	   paint.setPen(line);
1782
	   paint.drawLine(x1, y1, x2, y2);
1783
	   x1 = x2;
1784
	   y1 = y2;
132 andreas 1785
	   i = point->time + 1;
100 andreas 1786
	}
1787
 
1788
	paint.end();
1789
	imgMap->setPixmap(pmMap);
1790
}
1791
 
88 andreas 1792
void sportwatcherWidget::showCurves()
1793
{
148 andreas 1794
	showCurves (mapLap);
1795
}
1796
 
1797
void sportwatcherWidget::showCurves(LAP *lap)
1798
{
88 andreas 1799
QPainter paint;
1800
int width, height;
148 andreas 1801
int i, secs;
88 andreas 1802
int lineHeight, margin_left, margin_right, margin_bottom;
1803
int x1, y1, x2, y2;		// Coordinates
1804
bool meter;
1805
double maxHeight, minHeight;
1806
int maxHr, minHr, rh;
1807
POINT *point;
148 andreas 1808
RUN_NODE *rn;
1809
LAP *lp;
88 andreas 1810
double w_tick, h_tick;		// Number of pixels one "tick" has;
1811
				// This depends on the width and height
1812
				// of the image.
1813
	// First we draw a grid based on the min and max
1814
	// values detected in the function showLap(). In case
1815
	// all values are 0, we exit here.
1816
	if (min_hr == 0 && max_hr == 0 && min_height == 0.0 && max_height == 0.0)
1817
	   return;
1818
 
148 andreas 1819
	width = imgProfile->width() - 2;
1820
	height = imgProfile->height();
1821
	pmProfile.resize(width, height);
88 andreas 1822
	paint.begin(&pmProfile);
1823
 
1824
	// we need a somewhat bigger area to draw our curves than
1825
	// we have with the real min and max values.
1826
	if (max_height > 0.0)
1827
	{
148 andreas 1828
	double add = (max_height - min_height) / 100.0 * 5.0;	// Percent
88 andreas 1829
 
1830
	   maxHeight = max_height + add;
1831
	   minHeight = min_height - add;
1832
 
1833
	   if (minHeight < 0.0)		// make sure, we are not too deep
1834
	      minHeight = 0.0;
1835
	}
1836
 
1837
	if (max_hr > 0)
1838
	{
1839
	   maxHr = max_hr + 10;
1840
	   minHr = min_hr - 10;
1841
 
1842
	   if (minHr < 0)
1843
	      minHr = 0;
1844
	}
1845
 
1846
	// Define colors
148 andreas 1847
	QColor background(220, 220, 220);	// Background of graphic
1848
	QColor mark(255, 255, 255);		// Lines inside curve area
1849
	QColor hlight(180, 180, 180);		// area of current lap
1850
//	hlight.setAlpha(128);			// 50% transparent
1851
	QColor frame(0, 0, 0);			// Text and borders
1852
	QColor barcol(151, 190, 13);		// heart rate
1853
	QColor barcol2(190, 151, 13);		// height over NN
88 andreas 1854
	QColor red(220, 128, 128);
1855
	QColor blue(0, 0, 240);
1856
	QFont fntNormal("Helvetica");
1857
//	QFont fntBold("Helvetica", 10, QFont::Bold);
1858
	fntNormal.setPixelSize(10);
1859
	fntNormal.setStyleHint(QFont::Helvetica);
1860
//	fntBold.setPixelSize(10);
1861
//	fntBold.setStyleHint(QFont::Helvetica);
1862
	// Calculate ticks
1863
	margin_left = 52;
1864
	margin_right = 40;
1865
	margin_bottom = 12;
1866
	lineHeight = 10;
1867
	rh = height - margin_bottom - 1;
1868
 
1869
	w_tick = (double)(width - (margin_left + margin_right)) / max_time;	// 1 tick = 1 second
1870
 
1871
	if ((maxHeight - minHeight) > (double)(maxHr - minHr))
1872
	{
1873
	   h_tick = (double)rh / (maxHeight - minHeight);		// 1 tick = 1 meter
1874
	   meter = true;
1875
	}
1876
	else
1877
	{
1878
	   h_tick = (double)rh / ((double)maxHr - (double)minHr);	// 1 tick = 1 bpm
1879
	   meter = false;
1880
	}
1881
 
1882
	// Fill background with background colors
1883
	paint.fillRect(0, 0, width + 4, height + 4, background);
1884
	// Draw a grid with markers at every 10 minutes
1885
	paint.setPen(QPen(frame, 1, QPen::SolidLine));
1886
	// Bottom border line
1887
	x1 = margin_left;
1888
	y1 = height - margin_bottom;
1889
	x2 = width - margin_right;
1890
	y2 = y1;
1891
	paint.drawLine(x1, y1, x2, y2);
1892
	// Left border line
1893
	x1 = x2 = margin_left;
1894
	y1 = 2;
1895
	y2 = height - margin_bottom;
1896
	paint.drawLine(x1, y1, x2, y2);
1897
	// right border line
1898
	x1 = x2 = width - margin_right;
1899
	paint.drawLine(x1, y1, x2, y2);
148 andreas 1900
 
1901
	// Draw some darker lines to show the laps, if we have one
1902
	// and, in case we have a given lap, we fill the area.
1903
	QDateTime *qt;
1904
	QTime zeit = StartTime.time();
1905
	rn = ds.getRunNode();
1906
	paint.setPen(QPen(hlight, 1, QPen::SolidLine));
1907
 
1908
	for (i = rn->run->first_lap_index; (unsigned int)i <= rn->run->last_lap_index; i++)
1909
	{
1910
	   if ((lp = ds.getLap(i)) == NULL)
1911
	      continue;
1912
 
1913
	   qt = garmin_dtime(lp->start_time);
1914
	   secs = zeit.secsTo(qt->time());
1915
	   delete qt;
1916
	   x1 = secs * w_tick + margin_left + 1;
1917
 
1918
	   if (lap && lp->start_time == lap->start_time)
1919
	      paint.fillRect(x1, 2, (int)((double)lap->total_time / 100.0 * w_tick), height - margin_bottom - 2, hlight);
1920
	   else
1921
	      paint.drawLine(x1, 2, x1, height - margin_bottom);
1922
	}
1923
 
88 andreas 1924
	// Grid vertical
1925
	paint.setPen(QPen(frame, 1, QPen::SolidLine));
1926
	paint.setFont(fntNormal);
1927
	paint.drawText(margin_left - 20, height - lineHeight, 40, lineHeight, Qt::AlignCenter, QString("00:00"));
1928
	paint.save();
1929
	paint.rotate(270);
1930
	paint.setPen(QPen(barcol, 1, QPen::SolidLine));
149 andreas 1931
	paint.drawText((height + 4) * -1, 3, height - 2, lineHeight, Qt::AlignCenter, i18n((Units == 1) ? "Elevation (ft)" : "Elevation (m)"));
88 andreas 1932
	paint.setPen(QPen(blue, 1, QPen::SolidLine));
1933
	paint.drawText((height + 4) * -1, width - 1 - lineHeight, height - 2, lineHeight, Qt::AlignCenter, i18n("Heart Rate (bpm)"));
1934
	paint.restore();
1935
	paint.setPen(QPen(mark, 1, QPen::SolidLine));
1936
	// Draw the time scale
1937
	for (i = 0; (unsigned int)i < max_time; i++)
1938
	{
1939
	   if (i > 0 && !(i % 600))	// every 10 minutes
1940
	   {
1941
	      x1 = x2 = margin_left + w_tick * i;
1942
 
1943
	      if (x1 == (width - margin_right))
1944
		 continue;
1945
 
1946
	      y1 = 2;
1947
	      y2 = height - margin_bottom;
1948
	      paint.drawLine(x1, y1, x2, y2);
1949
	      QTime tm(0, 0, 0);
1950
	      tm = tm.addSecs(i);
1951
	      paint.setPen(QPen(frame, 1, QPen::SolidLine));
1952
	      paint.drawText(x1 - 25, height - lineHeight, 50, lineHeight, Qt::AlignCenter, tm.toString((i >= 3600) ? "hh:mm:ss" : "mm:ss"));
1953
	      paint.setPen(QPen(mark, 1, QPen::SolidLine));
1954
	   }
1955
	}
1956
 
1957
	QTime tm(0, 0, 0);
1958
	QString qs;
1959
	tm = tm.addSecs(max_time);
1960
	paint.setPen(QPen(frame, 1, QPen::SolidLine));
1961
	paint.drawText(width - margin_right - 25, height - lineHeight, 50, lineHeight, Qt::AlignCenter, tm.toString((max_time >= 3600) ? "hh:mm:ss" : "mm:ss"));
1962
 
1963
	if (max_height > 0.0)
1964
	{
1965
	   paint.setPen(QPen(barcol, 1, QPen::SolidLine));
149 andreas 1966
	   paint.drawText(12, height - margin_bottom - lineHeight / 2, margin_left - 14, lineHeight, Qt::AlignRight, qs.sprintf("%.0f", (Units == 1) ? minHeight / 0.304 : minHeight));
88 andreas 1967
	}
1968
 
1969
	if (max_hr > 0)
1970
	{
1971
	   paint.setPen(QPen(blue, 1, QPen::SolidLine));
1972
	   paint.drawText(width - margin_right + 2, height - margin_bottom - lineHeight / 2, margin_right - 14, lineHeight, Qt::AlignLeft, qs.sprintf("%d", minHr));
1973
	}
1974
 
1975
	paint.setPen(QPen(mark, 1, QPen::SolidLine));
1976
 
1977
	// Grid horizontal
1978
	int factor = (meter) ? (maxHeight - minHeight) / (rh / 12) : (maxHr - minHr) / (rh / 12);
1979
	int target = (meter) ? (int)(maxHeight - minHeight) : (maxHr - minHr);
1980
	int oldy = height;
1981
 
1982
	for (i = 0; i < target; i++)
1983
	{
1984
	   if (i > 0 && !(i % factor))
1985
	   {
1986
	      x1 = margin_left + 1;
1987
	      x2 = width - margin_right - 1;
1988
	      y1 = y2 = rh - h_tick * i;
1989
 
1990
	      if (y1 < 12)
1991
		 break;
1992
 
1993
	      paint.drawLine(x1, y1, x2, y2);
1994
 
1995
	      if (y1 < (oldy - lineHeight))
1996
	      {
1997
		 if (meter)
1998
		 {
1999
		    paint.setPen(QPen(barcol, 1, QPen::SolidLine));
149 andreas 2000
		    paint.drawText(12, y1 - lineHeight / 2, margin_left - 14, lineHeight, Qt::AlignRight, qs.sprintf("%.0f", (Units == 1) ? (minHeight + i) / 0.304 : minHeight + i));
88 andreas 2001
 
2002
		    if (maxHr > 0)
2003
		    {
2004
		       double hrscale = (double)(maxHr - minHr) / (double)target;
2005
		       paint.setPen(QPen(blue, 1, QPen::SolidLine));
2006
		       paint.drawText(width - margin_right + 2, y1 - lineHeight / 2, margin_right - 14, lineHeight, Qt::AlignLeft, qs.sprintf("%d", (int)((double)minHr + hrscale * (double)i)));
2007
		    }
2008
		 }
2009
		 else
2010
		 {
2011
		    paint.setPen(QPen(blue, 1, QPen::SolidLine));
2012
		    paint.drawText(width - margin_right + 2, y1 - lineHeight / 2, margin_right - 14, lineHeight, Qt::AlignLeft, qs.sprintf("%d", minHr + i));
2013
 
2014
		    if (max_height > 0)
2015
		    {
2016
		       double hrscale = (maxHeight - minHeight) / (double)target;
2017
		       paint.setPen(QPen(barcol, 1, QPen::SolidLine));
2018
		       paint.drawText(12, y1 - lineHeight / 2, margin_left - 14, lineHeight, Qt::AlignRight, qs.sprintf("%.0f", minHeight + hrscale * (double)i));
2019
		    }
2020
		}
2021
 
2022
		 paint.setPen(QPen(mark, 1, QPen::SolidLine));
2023
		 oldy = y1;
2024
	      }
2025
	   }
2026
	}
2027
 
148 andreas 2028
	// To make out graphics more beautiful, we draw lines for the
88 andreas 2029
	// heart rate limits and the average heart rate.
2030
	if (max_hr > 0)
2031
	{
2032
	int ay1, ay2, ay3, ay4, ay5;
2033
 
2034
	   x1 = margin_left + 1;
2035
	   x2 = width - margin_right - 1;
2036
 
2037
	   if (meter)
2038
	   {
2039
	      double hrscale = rh / (double)(maxHr - minHr);
2040
	      ay1 = (double)rh - (double)(lower1 - minHr) * hrscale;
2041
	      ay2 = (double)rh - (double)(lower2 - minHr) * hrscale;
2042
	      ay3 = (double)rh - (double)(lower3 - minHr) * hrscale;
2043
	      ay4 = (double)rh - (double)(upper3 - minHr) * hrscale;
2044
	      ay5 = (double)rh - (double)(avg_hr - minHr) * hrscale;
2045
	   }
2046
	   else
2047
	   {
2048
	      ay1 = (double)rh - (double)(lower1 - minHr) * h_tick;
2049
	      ay2 = (double)rh - (double)(lower2 - minHr) * h_tick;
2050
	      ay3 = (double)rh - (double)(lower3 - minHr) * h_tick;
2051
	      ay4 = (double)rh - (double)(upper3 - minHr) * h_tick;
2052
	      ay5 = (double)rh - (double)(avg_hr - minHr) * h_tick;
2053
	   }
2054
 
2055
	   paint.setPen(QPen(barcol2, 1, QPen::DashLine));	// color for limits
2056
 
2057
	   if (lower1 > minHr && lower1 < maxHr)
2058
	      paint.drawLine(x1, ay1, x2, ay1);
2059
 
2060
	   if (lower2 > minHr && lower2 < maxHr)
2061
	      paint.drawLine(x1, ay2, x2, ay2);
2062
 
2063
	   if (lower3 > minHr && lower3 < maxHr)
2064
	      paint.drawLine(x1, ay3, x2, ay3);
2065
 
2066
	   if (upper3 > minHr && upper3 < maxHr)
2067
	      paint.drawLine(x1, ay4, x2, ay4);
2068
 
2069
	   paint.setPen(QPen(red, 1, QPen::DashDotLine));	// color for average heart rate
2070
 
2071
	   if (avg_hr > minHr && avg_hr < maxHr)
2072
	      paint.drawLine(x1, ay5, x2, ay5);
2073
	}
2074
 
2075
	// Now we have a grid and we've done the scaling.
2076
	// This is the point where we draw the curves itself.
2077
	// We use different colors to draw the lines.
2078
	i = 0;
2079
	x1 = x2 = y1 = y2 = 0;
148 andreas 2080
	int hy1, hy2, hx1, hx2;
88 andreas 2081
	hy1 = hy2 = hx1 = hx2 = 0;
2082
 
2083
	while ((point = ds.getPoint(i)) != 0)
2084
	{
2085
	   // calculate the y position based on the time
2086
	   qt = garmin_dtime(point->time);
2087
	   secs = zeit.secsTo(qt->time());
2088
	   delete qt;
2089
	   x2 = secs * w_tick + margin_left + 1;
2090
	   hx2 = x2;
2091
 
2092
	   if (x1 == 0)
2093
	      x1 = x2;
2094
 
2095
	   if (hx1 == 0)
2096
	      hx1 = hx2;
2097
 
2098
	   if (point->alt < 20000 && point->alt > 0.0)
2099
	   {
2100
	      if (meter)
2101
		 y2 = (double)rh - (point->alt - minHeight) * h_tick;
2102
	      else
2103
	      {
2104
		 double hrscale = rh / (maxHeight - minHeight);
2105
		 y2 = (double)rh - (point->alt - minHeight) * hrscale;
2106
	      }
2107
 
2108
	      if (y1 == 0)
2109
		 y1 = y2;
2110
 
2111
	      paint.setPen(QPen(barcol, 1, QPen::SolidLine));
2112
	      paint.drawLine(x1, y1, x2, y2);
2113
	      y1 = y2;
2114
	      x1 = x2;
2115
	   }
2116
 
2117
	   if (point->heart_rate > 0)
2118
	   {
2119
	      if (meter)
2120
	      {
2121
		 double hrscale = rh / (double)(maxHr - minHr);
2122
		 hy2 = (double)rh - (double)(point->heart_rate - minHr) * hrscale;
2123
	      }
2124
	      else
2125
		 hy2 = (double)rh - (double)(point->heart_rate - minHr) * h_tick;
2126
 
2127
	      if (hy1 == 0)
2128
		 hy1 = hy2;
2129
 
2130
	      paint.setPen(QPen(blue, 1, QPen::SolidLine));
2131
	      paint.drawLine(hx1, hy1, hx2, hy2);
2132
	      hy1 = hy2;
2133
	      hx1 = hx2;
2134
	   }
2135
 
2136
	   i++;
2137
	}
2138
 
2139
	paint.end();
2140
	imgProfile->setPixmap(pmProfile);
2141
 
2142
//	if (bProfile)
2143
//	   bitBlt(imgProfile, 0, 0, &pmProfile);
2144
}
2145
 
2146
void sportwatcherWidget::resizeEvent(QResizeEvent */* *e */)
2147
{
132 andreas 2148
	showTrack(zfactor);
88 andreas 2149
	showCurves();
2150
}
2151
 
2152
void sportwatcherWidget::paintEvent(QPaintEvent */* *e */)
2153
{
132 andreas 2154
	showTrack(zfactor);
88 andreas 2155
	showCurves();
2156
}
2157
 
132 andreas 2158
void sportwatcherWidget::mouseMoveEvent(QMouseEvent *e)
2159
{
2160
QPoint pos(0, 0);
2161
QPoint ev = imgMap->mapFrom(this, e->pos());
2162
static QRect coord;
88 andreas 2163
 
132 andreas 2164
	if (!stateHand)
2165
	   return;
2166
 
2167
	if (ev.x() >= pos.x() &&
2168
	    ev.y() >= pos.y() &&
2169
	    ev.x() <= (pos.x() + imgMap->geometry().width()) &&
2170
	    ev.y() <= (pos.y() + imgMap->geometry().height()))
2171
	{
2172
	   if (lmbPressed == 1)
2173
	   {
2174
	      coord.setCoords(ev.x(), ev.y(), 0, 0);
2175
	      lmbPressed = 0;
2176
	   }
2177
	   else
2178
	   {
2179
	      coord.setRight(ev.x());
2180
	      coord.setBottom(ev.y());
2181
	   }
2182
 
2183
	   if (lmbPressed == 2)
2184
	   {
2185
	      showTrack(zfactor, coord, mapLap);
2186
	      lmbPressed = 0;
2187
	   }
2188
	}
2189
}
2190
 
2191
void sportwatcherWidget::mousePressEvent(QMouseEvent *e)
2192
{
2193
	if (stateHand && e->button() == QMouseEvent::LeftButton)
2194
	   lmbPressed = 1;	// Left Mouse Button is pressed
2195
	else if (stateHand)
2196
	   lmbPressed = 0;	// Wrong button is pressed
2197
 
2198
	if (stateGlas)
2199
	{
2200
	   if (e->button() == QMouseEvent::LeftButton)
2201
	      btGlasPlusSlot();
2202
	   else if (e->button() == QMouseEvent::RightButton)
2203
	      btGlasMinusSlot();
2204
	}
2205
}
2206
 
2207
void sportwatcherWidget::mouseReleaseEvent(QMouseEvent *e)
2208
{
2209
	if (stateHand && e->button() == QMouseEvent::LeftButton)
2210
	{
2211
	   lmbPressed = 2;	// Left Mouse Button was released
2212
	   mouseMoveEvent(e);
2213
	}
2214
}
2215
 
88 andreas 2216
/*
2217
 * Private functions to help decode the data
2218
 */
2219
QDateTime *sportwatcherWidget::garmin_dtime (uint32 t)
2220
{
2221
time_t     tval;
2222
struct tm  tmval;
2223
QTime ti;
2224
QDate dt;
2225
QDateTime *qt;
2226
 
2227
	if (t == 0)
2228
	   return new QDateTime(QDate(1900, 1, 1), QTime(0, 0, 0, 0));
2229
 
2230
	tval = t + TIME_OFFSET;
2231
	localtime_r (&tval, &tmval);
2232
	qt = new QDateTime();
2233
	qt->setDate(QDate(tmval.tm_year+1900, tmval.tm_mon+1, tmval.tm_mday));
2234
	qt->setTime(QTime(tmval.tm_hour, tmval.tm_min, tmval.tm_sec, 0));
2235
	/* OK.  Done. */
2236
	return qt;
2237
}
2238
 
104 andreas 2239
bool sportwatcherWidget::writeTag(const QFile &fn, const QString &str, int indent)
2240
{
2241
QString qs;
2242
char *p = new char[str.length()+100];
2243
QCString qcs;
2244
int i;
88 andreas 2245
 
104 andreas 2246
	qs.fill(' ', indent * 3);
2247
	qs.append(str);
2248
	qcs = qs.utf8();
2249
	qstrcpy(p, qcs);
2250
	i = strlen(p);
2251
 
2252
	if (write(fn.handle(), p, i) != i)
2253
	{
2254
	   delete p;
2255
	   return false;
2256
	}
2257
 
2258
	delete p;
2259
	return true;
2260
}
2261
 
151 andreas 2262
#ifdef GDAL
2263
bool sportwatcherWidget::writeWMSTag(double llat, double llon, double rlat, double rlon, int width, int height)
2264
{
2265
QFile fl(MAP);
152 andreas 2266
QString xml, s, srs, crs, styles, bSize, ext;
2267
QDir dir = QDir::home();
2268
QString path = dir.absPath();
2269
int item;
2270
bool flag;
151 andreas 2271
 
2272
	if (!fl.open(IO_ReadWrite | IO_Truncate))
2273
	{
2274
	   KMessageBox::error (this, i18n("Error opening or creating the WMS tag file!\nPlease check file name and/or permissions."));
2275
	   return false;
2276
	}
2277
 
152 andreas 2278
	KSimpleConfig *cfg = new KSimpleConfig(QString("sportwatcher.rc"));
2279
	cfg->setGroup(QString("WMS"));
2280
	styles = cfg->readEntry("Styles");
2281
 
151 andreas 2282
	xml = "<GDAL_WMS>\n";
2283
	xml += "   <Service name=\"WMS\">\n";
2284
	xml += "      <Version>1.1.1</Version>\n";
152 andreas 2285
	xml += "      <ServerURL>" + cfg->readEntry("ServerURL", "http://onearth.jpl.nasa.gov/wms.cgi") + "?</serverURL>\n";
2286
	item = cfg->readNumEntry("SRS", 0);
2287
 
2288
	switch (item)
2289
	{
2290
	   case 0: srs = QString("EPSG:4326"); break;
2291
	   default: srs = QString("EPSG:4326");
2292
	}
2293
 
2294
	xml += "      <SRS>" + srs + "</SRS>\n";
2295
	item = cfg->readNumEntry("CRS", 0);
2296
 
2297
	switch (item)
2298
	{
2299
	   case 0: crs = QString("CRS:83"); break;
2300
	   default: crs = QString("CRS:83"); break;
2301
	}
2302
 
2303
	xml += "      <CRS>" + crs + "</CRS>\n";
2304
	item = cfg->readNumEntry("Image", 2);
2305
	xml += "      <ImageFormat>image/";
2306
 
2307
	switch (item)
2308
	{
2309
	   case 0: xml += "gif"; ext = QString(".gif"); break;
2310
	   case 1: xml += "jpeg"; ext = QString(".jpg"); break;
2311
	   case 2: xml += "png"; ext = QString(".png"); break;
2312
	   case 3: xml += "tiff"; ext = QString(".tif"); break;
2313
	   default: xml += "png"; ext = QString(".png");
2314
	}
2315
 
2316
	xml += "</ImageFormat>\n";
2317
 
2318
	xml += "      <Layers>" + cfg->readEntry("Layer") + "</Layers>\n";
2319
 
2320
	if (!styles.isEmpty())
2321
	   xml += "      <Styles>" + styles + "</Styles>\n";
2322
 
151 andreas 2323
	xml += "      <BBoxOrder>xyXY</BBoxOrder>\n";
2324
	xml += "   </Service>\n";
2325
	xml += "   <DataWindow>\n";
2326
	s.sprintf ("%f", llat);
2327
	xml += "      <UpperLeftX>" + s + "</UpperLeftX>\n";
2328
	s.sprintf ("%f", llon);
2329
	xml += "      <UpperLeftY>" + s + "</UpperLeftY>\n";
2330
	s.sprintf ("%f", rlat);
2331
	xml += "      <LowerRightX>" + s + "</LowerRightX>\n";
2332
	s.sprintf ("%f", rlon);
2333
	xml += "      <LowerRightY>" + s + "</LowerRightY>\n";
2334
	s.sprintf ("%d", width);
2335
	xml += "      <SizeX>" + s + "</SizeX>\n";
2336
	s.sprintf ("%d", height);
2337
	xml += "      <SizeY>" + s + "</SizeY>\n";
2338
	xml += "   </DataWindow>\n";
2339
	xml += "   <Projection>EPSG:4326</Projection>\n";
152 andreas 2340
	xml += "   <BandsCount>" + cfg->readEntry("Bands", "3") + "</BandsCount>\n";
2341
	item = cfg->readNumEntry("Tile", 2);
2342
 
2343
	switch (item)
2344
	{
2345
	   case 0: bSize = QString("64"); break;
2346
	   case 1: bSize = QString("128"); break;
2347
	   case 2: bSize = QString("256"); break;
2348
	   case 3: bSize = QString("512"); break;
2349
	   case 4: bSize = QString("1024"); break;
2350
	   default: bSize = QString("256");
2351
	}
2352
 
2353
	xml += "   <BlockSizeX>" + bSize + "</BlockSizeX>\n";
2354
	xml += "   <BlockSizeY>" + bSize + "</BlockSizeY>\n";
2355
	xml += "   <OverviewCount>" + cfg->readEntry("Overview", "10") + "</OverviewCount>\n";
151 andreas 2356
	xml += "   <Cache>\n";
152 andreas 2357
	xml += "      <Path>" + path + "/.gdalwmscache" + "</Path>\n";
2358
	xml += "      <Depth>" + cfg->readEntry("Depth", "2") + "</Depth>\n";
2359
	xml += "      <Extension>" + ext + "</Extension>\n";
151 andreas 2360
	xml += "   </Cache>\n";
152 andreas 2361
	QString off((cfg->readBoolEntry("Offline", false)) ? "true" : "false");
2362
	QString adv((cfg->readBoolEntry("Advice", false)) ? "true" : "false");
2363
	QString ver((cfg->readBoolEntry("Verify", true)) ? "true" : "false");
2364
	xml += "   <OfflineMode>" + off + "</OfflineMode>\n";
2365
	xml += "   <AdviseRead>" + adv + "</AdviseRead>\n";
2366
	xml += "   <VerifyAdviseRead>" + ver + "</VerifyAdviseRead>\n";
151 andreas 2367
	xml += "</GDAL_WMS>\n";
2368
 
2369
	write (fl.handle(), xml.ascii(), strlen (xml.ascii()));
2370
	fl.close();
152 andreas 2371
	delete cfg;
151 andreas 2372
	return true;
2373
}
2374
 
2375
void sportwatcherWidget::fillBMPHeader (BMP_HEADER *bmpH, BMP_INFO *bmpI, int nXSize, int nYSize, int nRasterCount)
2376
{
2377
//	bmpH->bfType = 19778;
2378
	bmpH->bfSize = sizeof(BMP_HEADER) + sizeof(BMP_INFO) + (nXSize * nYSize * nRasterCount);
2379
	bmpH->bfReserved = 0;
2380
	bmpH->bfOffBits = (sizeof(BMP_HEADER) + sizeof(BMP_INFO)) * 8;
2381
//fprintf(stderr, "Size: %d, Res: %d, Off: %d\n",
2382
//		bmpH->bfSize, bmpH->bfReserved, bmpH->bfOffBits);
2383
	bmpI->biSize = sizeof(BMP_INFO);
2384
	bmpI->biWidth = nXSize;
2385
	bmpI->biHeight = nYSize;
2386
	bmpI->biPlanes = 1;
2387
	bmpI->biBitCount = 24;
2388
	bmpI->biCompression = 0;
2389
	bmpI->biSizeImage = nXSize * nYSize * nRasterCount;
2390
	bmpI->biXPelsPerMeter = 0;
2391
	bmpI->biYPelsPerMeter = 0;
2392
	bmpI->biClrUsed = 0;
2393
	bmpI->biClrImportant = 0;
2394
}
2395
 
2396
#endif
2397
 
88 andreas 2398
#include "sportwatcherwidget.moc"
2399