Added GeoJSON and DEM files info.
[GPXSee.git] / src / GUI / gui.cpp
blob929157ef993b6c2d9a4b82270795e01dbe8994e7
1 #include "common/config.h"
2 #include <QApplication>
3 #include <QSplitter>
4 #include <QVBoxLayout>
5 #include <QMenuBar>
6 #include <QStatusBar>
7 #include <QMessageBox>
8 #include <QFileDialog>
9 #include <QPrintDialog>
10 #include <QPainter>
11 #include <QPaintEngine>
12 #include <QPaintDevice>
13 #include <QKeyEvent>
14 #include <QSignalMapper>
15 #include <QMenu>
16 #include <QToolBar>
17 #include <QTabWidget>
18 #include <QActionGroup>
19 #include <QAction>
20 #include <QLabel>
21 #include <QSettings>
22 #include <QLocale>
23 #include <QMimeData>
24 #include <QUrl>
25 #include <QPixmapCache>
26 #ifdef ENABLE_HIDPI
27 #include <QWindow>
28 #include <QScreen>
29 #endif // ENABLE_HIDPI
30 #include <QStyle>
31 #include "common/programpaths.h"
32 #include "data/data.h"
33 #include "data/poi.h"
34 #include "map/maplist.h"
35 #include "map/emptymap.h"
36 #include "map/downloader.h"
37 #include "icons.h"
38 #include "keys.h"
39 #include "settings.h"
40 #include "elevationgraph.h"
41 #include "speedgraph.h"
42 #include "heartrategraph.h"
43 #include "temperaturegraph.h"
44 #include "cadencegraph.h"
45 #include "powergraph.h"
46 #include "gearratiograph.h"
47 #include "mapview.h"
48 #include "trackinfo.h"
49 #include "filebrowser.h"
50 #include "cpuarch.h"
51 #include "graphtab.h"
52 #include "graphitem.h"
53 #include "pathitem.h"
54 #include "gui.h"
57 #define TOOLBAR_ICON_SIZE 22
59 GUI::GUI()
61 loadMaps();
62 loadPOIs();
64 createMapView();
65 createGraphTabs();
66 createStatusBar();
67 createActions();
68 createMenus();
69 createToolBars();
71 createBrowser();
73 _splitter = new QSplitter();
74 _splitter->setOrientation(Qt::Vertical);
75 _splitter->setChildrenCollapsible(false);
76 _splitter->addWidget(_mapView);
77 _splitter->addWidget(_graphTabWidget);
78 _splitter->setContentsMargins(0, 0, 0, 0);
79 _splitter->setStretchFactor(0, 255);
80 _splitter->setStretchFactor(1, 1);
81 setCentralWidget(_splitter);
83 setWindowIcon(QIcon(APP_ICON));
84 setWindowTitle(APP_NAME);
85 setUnifiedTitleAndToolBarOnMac(true);
86 setAcceptDrops(true);
88 _trackCount = 0;
89 _routeCount = 0;
90 _waypointCount = 0;
91 _trackDistance = 0;
92 _routeDistance = 0;
93 _time = 0;
94 _movingTime = 0;
96 _sliderPos = 0;
98 _dataDir = QDir::homePath();
99 _mapDir = QDir::homePath();
100 _poiDir = QDir::homePath();
102 readSettings();
104 updateGraphTabs();
105 updateMapView();
106 updateStatusBarInfo();
109 void GUI::loadMaps()
111 _ml = new MapList(this);
112 QString mapDir(ProgramPaths::mapDir());
114 if (!mapDir.isNull() && !_ml->loadDir(mapDir))
115 qWarning("%s", qPrintable(_ml->errorString()));
117 _map = new EmptyMap(this);
120 void GUI::loadPOIs()
122 _poi = new POI(this);
123 QString poiDir(ProgramPaths::poiDir());
125 if (!poiDir.isNull() && !_poi->loadDir(poiDir))
126 qWarning("%s", qPrintable(_poi->errorString()));
129 void GUI::createBrowser()
131 _browser = new FileBrowser(this);
132 _browser->setFilter(Data::filter());
135 void GUI::createMapActions()
137 _mapsSignalMapper = new QSignalMapper(this);
138 _mapsActionGroup = new QActionGroup(this);
139 _mapsActionGroup->setExclusive(true);
141 for (int i = 0; i < _ml->maps().count(); i++)
142 createMapAction(_ml->maps().at(i));
144 connect(_mapsSignalMapper, SIGNAL(mapped(int)), this,
145 SLOT(mapChanged(int)));
148 QAction *GUI::createMapAction(const Map *map)
150 QAction *a = new QAction(map->name(), this);
151 a->setMenuRole(QAction::NoRole);
152 a->setCheckable(true);
153 a->setActionGroup(_mapsActionGroup);
155 _mapActions.append(a);
156 _mapsSignalMapper->setMapping(a, _mapActions.size() - 1);
157 connect(a, SIGNAL(triggered()), _mapsSignalMapper, SLOT(map()));
159 return a;
162 void GUI::createPOIFilesActions()
164 _poiFilesSignalMapper = new QSignalMapper(this);
166 for (int i = 0; i < _poi->files().count(); i++)
167 createPOIFileAction(_poi->files().at(i));
169 connect(_poiFilesSignalMapper, SIGNAL(mapped(int)), this,
170 SLOT(poiFileChecked(int)));
173 QAction *GUI::createPOIFileAction(const QString &fileName)
175 QAction *a = new QAction(QFileInfo(fileName).fileName(), this);
176 a->setMenuRole(QAction::NoRole);
177 a->setCheckable(true);
179 _poiFilesActions.append(a);
180 _poiFilesSignalMapper->setMapping(a, _poiFilesActions.size() - 1);
181 connect(a, SIGNAL(triggered()), _poiFilesSignalMapper, SLOT(map()));
183 return a;
186 void GUI::createActions()
188 QActionGroup *ag;
190 // Action Groups
191 _fileActionGroup = new QActionGroup(this);
192 _fileActionGroup->setExclusive(false);
193 _fileActionGroup->setEnabled(false);
195 _navigationActionGroup = new QActionGroup(this);
196 _navigationActionGroup->setEnabled(false);
198 // General actions
199 _exitAction = new QAction(QIcon(QUIT_ICON), tr("Quit"), this);
200 _exitAction->setShortcut(QUIT_SHORTCUT);
201 _exitAction->setMenuRole(QAction::QuitRole);
202 connect(_exitAction, SIGNAL(triggered()), this, SLOT(close()));
203 addAction(_exitAction);
205 // Help & About
206 _pathsAction = new QAction(tr("Paths"), this);
207 _pathsAction->setMenuRole(QAction::NoRole);
208 connect(_pathsAction, SIGNAL(triggered()), this, SLOT(paths()));
209 _keysAction = new QAction(tr("Keyboard controls"), this);
210 _keysAction->setMenuRole(QAction::NoRole);
211 connect(_keysAction, SIGNAL(triggered()), this, SLOT(keys()));
212 _aboutAction = new QAction(QIcon(APP_ICON), tr("About GPXSee"), this);
213 _aboutAction->setMenuRole(QAction::AboutRole);
214 connect(_aboutAction, SIGNAL(triggered()), this, SLOT(about()));
216 // File actions
217 _openFileAction = new QAction(QIcon(OPEN_FILE_ICON), tr("Open..."), this);
218 _openFileAction->setMenuRole(QAction::NoRole);
219 _openFileAction->setShortcut(OPEN_SHORTCUT);
220 connect(_openFileAction, SIGNAL(triggered()), this, SLOT(openFile()));
221 addAction(_openFileAction);
222 _printFileAction = new QAction(QIcon(PRINT_FILE_ICON), tr("Print..."),
223 this);
224 _printFileAction->setMenuRole(QAction::NoRole);
225 _printFileAction->setActionGroup(_fileActionGroup);
226 connect(_printFileAction, SIGNAL(triggered()), this, SLOT(printFile()));
227 addAction(_printFileAction);
228 _exportFileAction = new QAction(QIcon(EXPORT_FILE_ICON),
229 tr("Export to PDF..."), this);
230 _exportFileAction->setMenuRole(QAction::NoRole);
231 _exportFileAction->setShortcut(EXPORT_SHORTCUT);
232 _exportFileAction->setActionGroup(_fileActionGroup);
233 connect(_exportFileAction, SIGNAL(triggered()), this, SLOT(exportFile()));
234 addAction(_exportFileAction);
235 _closeFileAction = new QAction(QIcon(CLOSE_FILE_ICON), tr("Close"), this);
236 _closeFileAction->setMenuRole(QAction::NoRole);
237 _closeFileAction->setShortcut(CLOSE_SHORTCUT);
238 _closeFileAction->setActionGroup(_fileActionGroup);
239 connect(_closeFileAction, SIGNAL(triggered()), this, SLOT(closeAll()));
240 addAction(_closeFileAction);
241 _reloadFileAction = new QAction(QIcon(RELOAD_FILE_ICON), tr("Reload"),
242 this);
243 _reloadFileAction->setMenuRole(QAction::NoRole);
244 _reloadFileAction->setShortcut(RELOAD_SHORTCUT);
245 _reloadFileAction->setActionGroup(_fileActionGroup);
246 connect(_reloadFileAction, SIGNAL(triggered()), this, SLOT(reloadFile()));
247 addAction(_reloadFileAction);
248 _statisticsAction = new QAction(tr("Statistics..."), this);
249 _statisticsAction->setMenuRole(QAction::NoRole);
250 _statisticsAction->setShortcut(STATISTICS_SHORTCUT);
251 _statisticsAction->setActionGroup(_fileActionGroup);
252 connect(_statisticsAction, SIGNAL(triggered()), this, SLOT(statistics()));
253 addAction(_statisticsAction);
255 // POI actions
256 _openPOIAction = new QAction(QIcon(OPEN_FILE_ICON), tr("Load POI file..."),
257 this);
258 _openPOIAction->setMenuRole(QAction::NoRole);
259 connect(_openPOIAction, SIGNAL(triggered()), this, SLOT(openPOIFile()));
260 _closePOIAction = new QAction(QIcon(CLOSE_FILE_ICON), tr("Close POI files"),
261 this);
262 _closePOIAction->setMenuRole(QAction::NoRole);
263 connect(_closePOIAction, SIGNAL(triggered()), this, SLOT(closePOIFiles()));
264 _overlapPOIAction = new QAction(tr("Overlap POIs"), this);
265 _overlapPOIAction->setMenuRole(QAction::NoRole);
266 _overlapPOIAction->setCheckable(true);
267 connect(_overlapPOIAction, SIGNAL(triggered(bool)), _mapView,
268 SLOT(setPOIOverlap(bool)));
269 _showPOILabelsAction = new QAction(tr("Show POI labels"), this);
270 _showPOILabelsAction->setMenuRole(QAction::NoRole);
271 _showPOILabelsAction->setCheckable(true);
272 connect(_showPOILabelsAction, SIGNAL(triggered(bool)), _mapView,
273 SLOT(showPOILabels(bool)));
274 _showPOIAction = new QAction(QIcon(SHOW_POI_ICON), tr("Show POIs"), this);
275 _showPOIAction->setMenuRole(QAction::NoRole);
276 _showPOIAction->setCheckable(true);
277 _showPOIAction->setShortcut(SHOW_POI_SHORTCUT);
278 connect(_showPOIAction, SIGNAL(triggered(bool)), _mapView,
279 SLOT(showPOI(bool)));
280 addAction(_showPOIAction);
281 createPOIFilesActions();
283 // Map actions
284 _showMapAction = new QAction(QIcon(SHOW_MAP_ICON), tr("Show map"),
285 this);
286 _showMapAction->setMenuRole(QAction::NoRole);
287 _showMapAction->setCheckable(true);
288 _showMapAction->setShortcut(SHOW_MAP_SHORTCUT);
289 connect(_showMapAction, SIGNAL(triggered(bool)), _mapView,
290 SLOT(showMap(bool)));
291 addAction(_showMapAction);
292 _loadMapAction = new QAction(QIcon(OPEN_FILE_ICON), tr("Load map..."),
293 this);
294 _loadMapAction->setMenuRole(QAction::NoRole);
295 connect(_loadMapAction, SIGNAL(triggered()), this, SLOT(loadMap()));
296 _clearMapCacheAction = new QAction(tr("Clear tile cache"), this);
297 _clearMapCacheAction->setMenuRole(QAction::NoRole);
298 connect(_clearMapCacheAction, SIGNAL(triggered()), _mapView,
299 SLOT(clearMapCache()));
300 createMapActions();
301 _nextMapAction = new QAction(tr("Next map"), this);
302 _nextMapAction->setMenuRole(QAction::NoRole);
303 _nextMapAction->setShortcut(NEXT_MAP_SHORTCUT);
304 connect(_nextMapAction, SIGNAL(triggered()), this, SLOT(nextMap()));
305 addAction(_nextMapAction);
306 _prevMapAction = new QAction(tr("Next map"), this);
307 _prevMapAction->setMenuRole(QAction::NoRole);
308 _prevMapAction->setShortcut(PREV_MAP_SHORTCUT);
309 connect(_prevMapAction, SIGNAL(triggered()), this, SLOT(prevMap()));
310 addAction(_prevMapAction);
311 if (_ml->maps().isEmpty()) {
312 _showMapAction->setEnabled(false);
313 _clearMapCacheAction->setEnabled(false);
316 // Data actions
317 _showTracksAction = new QAction(tr("Show tracks"), this);
318 _showTracksAction->setMenuRole(QAction::NoRole);
319 _showTracksAction->setCheckable(true);
320 connect(_showTracksAction, SIGNAL(triggered(bool)), this,
321 SLOT(showTracks(bool)));
322 _showRoutesAction = new QAction(tr("Show routes"), this);
323 _showRoutesAction->setMenuRole(QAction::NoRole);
324 _showRoutesAction->setCheckable(true);
325 connect(_showRoutesAction, SIGNAL(triggered(bool)), this,
326 SLOT(showRoutes(bool)));
327 _showWaypointsAction = new QAction(tr("Show waypoints"), this);
328 _showWaypointsAction->setMenuRole(QAction::NoRole);
329 _showWaypointsAction->setCheckable(true);
330 connect(_showWaypointsAction, SIGNAL(triggered(bool)), _mapView,
331 SLOT(showWaypoints(bool)));
332 _showWaypointLabelsAction = new QAction(tr("Waypoint labels"), this);
333 _showWaypointLabelsAction->setMenuRole(QAction::NoRole);
334 _showWaypointLabelsAction->setCheckable(true);
335 connect(_showWaypointLabelsAction, SIGNAL(triggered(bool)), _mapView,
336 SLOT(showWaypointLabels(bool)));
337 _showRouteWaypointsAction = new QAction(tr("Route waypoints"), this);
338 _showRouteWaypointsAction->setMenuRole(QAction::NoRole);
339 _showRouteWaypointsAction->setCheckable(true);
340 connect(_showRouteWaypointsAction, SIGNAL(triggered(bool)), _mapView,
341 SLOT(showRouteWaypoints(bool)));
343 // Graph actions
344 _showGraphsAction = new QAction(QIcon(SHOW_GRAPHS_ICON), tr("Show graphs"),
345 this);
346 _showGraphsAction->setMenuRole(QAction::NoRole);
347 _showGraphsAction->setCheckable(true);
348 _showGraphsAction->setShortcut(SHOW_GRAPHS_SHORTCUT);
349 connect(_showGraphsAction, SIGNAL(triggered(bool)), this,
350 SLOT(showGraphs(bool)));
351 addAction(_showGraphsAction);
352 ag = new QActionGroup(this);
353 ag->setExclusive(true);
354 _distanceGraphAction = new QAction(tr("Distance"), this);
355 _distanceGraphAction->setMenuRole(QAction::NoRole);
356 _distanceGraphAction->setCheckable(true);
357 _distanceGraphAction->setActionGroup(ag);
358 connect(_distanceGraphAction, SIGNAL(triggered()), this,
359 SLOT(setDistanceGraph()));
360 addAction(_distanceGraphAction);
361 _timeGraphAction = new QAction(tr("Time"), this);
362 _timeGraphAction->setMenuRole(QAction::NoRole);
363 _timeGraphAction->setCheckable(true);
364 _timeGraphAction->setActionGroup(ag);
365 connect(_timeGraphAction, SIGNAL(triggered()), this,
366 SLOT(setTimeGraph()));
367 addAction(_timeGraphAction);
368 _showGraphGridAction = new QAction(tr("Show grid"), this);
369 _showGraphGridAction->setMenuRole(QAction::NoRole);
370 _showGraphGridAction->setCheckable(true);
371 connect(_showGraphGridAction, SIGNAL(triggered(bool)), this,
372 SLOT(showGraphGrids(bool)));
373 _showGraphSliderInfoAction = new QAction(tr("Show slider info"), this);
374 _showGraphSliderInfoAction->setMenuRole(QAction::NoRole);
375 _showGraphSliderInfoAction->setCheckable(true);
376 connect(_showGraphSliderInfoAction, SIGNAL(triggered(bool)), this,
377 SLOT(showGraphSliderInfo(bool)));
379 // Settings actions
380 _showToolbarsAction = new QAction(tr("Show toolbars"), this);
381 _showToolbarsAction->setMenuRole(QAction::NoRole);
382 _showToolbarsAction->setCheckable(true);
383 connect(_showToolbarsAction, SIGNAL(triggered(bool)), this,
384 SLOT(showToolbars(bool)));
385 ag = new QActionGroup(this);
386 ag->setExclusive(true);
387 _totalTimeAction = new QAction(tr("Total time"), this);
388 _totalTimeAction->setMenuRole(QAction::NoRole);
389 _totalTimeAction->setCheckable(true);
390 _totalTimeAction->setActionGroup(ag);
391 connect(_totalTimeAction, SIGNAL(triggered()), this,
392 SLOT(setTotalTime()));
393 _movingTimeAction = new QAction(tr("Moving time"), this);
394 _movingTimeAction->setMenuRole(QAction::NoRole);
395 _movingTimeAction->setCheckable(true);
396 _movingTimeAction->setActionGroup(ag);
397 connect(_movingTimeAction, SIGNAL(triggered()), this,
398 SLOT(setMovingTime()));
399 ag = new QActionGroup(this);
400 ag->setExclusive(true);
401 _metricUnitsAction = new QAction(tr("Metric"), this);
402 _metricUnitsAction->setMenuRole(QAction::NoRole);
403 _metricUnitsAction->setCheckable(true);
404 _metricUnitsAction->setActionGroup(ag);
405 connect(_metricUnitsAction, SIGNAL(triggered()), this,
406 SLOT(setMetricUnits()));
407 _imperialUnitsAction = new QAction(tr("Imperial"), this);
408 _imperialUnitsAction->setMenuRole(QAction::NoRole);
409 _imperialUnitsAction->setCheckable(true);
410 _imperialUnitsAction->setActionGroup(ag);
411 connect(_imperialUnitsAction, SIGNAL(triggered()), this,
412 SLOT(setImperialUnits()));
413 _nauticalUnitsAction = new QAction(tr("Nautical"), this);
414 _nauticalUnitsAction->setMenuRole(QAction::NoRole);
415 _nauticalUnitsAction->setCheckable(true);
416 _nauticalUnitsAction->setActionGroup(ag);
417 connect(_nauticalUnitsAction, SIGNAL(triggered()), this,
418 SLOT(setNauticalUnits()));
419 ag = new QActionGroup(this);
420 ag->setExclusive(true);
421 _decimalDegreesAction = new QAction(tr("Decimal degrees (DD)"), this);
422 _decimalDegreesAction->setMenuRole(QAction::NoRole);
423 _decimalDegreesAction->setCheckable(true);
424 _decimalDegreesAction->setActionGroup(ag);
425 connect(_decimalDegreesAction, SIGNAL(triggered()), this,
426 SLOT(setDecimalDegrees()));
427 _degreesMinutesAction = new QAction(tr("Degrees and decimal minutes (DMM)"),
428 this);
429 _degreesMinutesAction->setMenuRole(QAction::NoRole);
430 _degreesMinutesAction->setCheckable(true);
431 _degreesMinutesAction->setActionGroup(ag);
432 connect(_degreesMinutesAction, SIGNAL(triggered()), this,
433 SLOT(setDegreesMinutes()));
434 _DMSAction = new QAction(tr("Degrees, minutes, seconds (DMS)"), this);
435 _DMSAction->setMenuRole(QAction::NoRole);
436 _DMSAction->setCheckable(true);
437 _DMSAction->setActionGroup(ag);
438 connect(_DMSAction, SIGNAL(triggered()), this, SLOT(setDMS()));
439 _fullscreenAction = new QAction(QIcon(FULLSCREEN_ICON),
440 tr("Fullscreen mode"), this);
441 _fullscreenAction->setMenuRole(QAction::NoRole);
442 _fullscreenAction->setCheckable(true);
443 _fullscreenAction->setShortcut(FULLSCREEN_SHORTCUT);
444 connect(_fullscreenAction, SIGNAL(triggered(bool)), this,
445 SLOT(showFullscreen(bool)));
446 addAction(_fullscreenAction);
447 _openOptionsAction = new QAction(tr("Options..."), this);
448 _openOptionsAction->setMenuRole(QAction::PreferencesRole);
449 connect(_openOptionsAction, SIGNAL(triggered()), this,
450 SLOT(openOptions()));
452 // Navigation actions
453 _nextAction = new QAction(QIcon(NEXT_FILE_ICON), tr("Next"), this);
454 _nextAction->setActionGroup(_navigationActionGroup);
455 _nextAction->setMenuRole(QAction::NoRole);
456 connect(_nextAction, SIGNAL(triggered()), this, SLOT(next()));
457 _prevAction = new QAction(QIcon(PREV_FILE_ICON), tr("Previous"), this);
458 _prevAction->setMenuRole(QAction::NoRole);
459 _prevAction->setActionGroup(_navigationActionGroup);
460 connect(_prevAction, SIGNAL(triggered()), this, SLOT(prev()));
461 _lastAction = new QAction(QIcon(LAST_FILE_ICON), tr("Last"), this);
462 _lastAction->setMenuRole(QAction::NoRole);
463 _lastAction->setActionGroup(_navigationActionGroup);
464 connect(_lastAction, SIGNAL(triggered()), this, SLOT(last()));
465 _firstAction = new QAction(QIcon(FIRST_FILE_ICON), tr("First"), this);
466 _firstAction->setMenuRole(QAction::NoRole);
467 _firstAction->setActionGroup(_navigationActionGroup);
468 connect(_firstAction, SIGNAL(triggered()), this, SLOT(first()));
471 void GUI::createMenus()
473 QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
474 fileMenu->addAction(_openFileAction);
475 fileMenu->addSeparator();
476 fileMenu->addAction(_printFileAction);
477 fileMenu->addAction(_exportFileAction);
478 fileMenu->addSeparator();
479 fileMenu->addAction(_statisticsAction);
480 fileMenu->addSeparator();
481 fileMenu->addAction(_reloadFileAction);
482 fileMenu->addAction(_closeFileAction);
483 #ifndef Q_OS_MAC
484 fileMenu->addSeparator();
485 fileMenu->addAction(_exitAction);
486 #endif // Q_OS_MAC
488 _mapMenu = menuBar()->addMenu(tr("&Map"));
489 _mapMenu->addActions(_mapActions);
490 _mapsEnd = _mapMenu->addSeparator();
491 _mapMenu->addAction(_loadMapAction);
492 _mapMenu->addAction(_clearMapCacheAction);
493 _mapMenu->addSeparator();
494 _mapMenu->addAction(_showMapAction);
496 QMenu *graphMenu = menuBar()->addMenu(tr("&Graph"));
497 graphMenu->addAction(_distanceGraphAction);
498 graphMenu->addAction(_timeGraphAction);
499 graphMenu->addSeparator();
500 graphMenu->addAction(_showGraphGridAction);
501 graphMenu->addAction(_showGraphSliderInfoAction);
502 graphMenu->addSeparator();
503 graphMenu->addAction(_showGraphsAction);
505 QMenu *poiMenu = menuBar()->addMenu(tr("&POI"));
506 _poiFilesMenu = poiMenu->addMenu(tr("POI files"));
507 _poiFilesMenu->addActions(_poiFilesActions);
508 poiMenu->addSeparator();
509 poiMenu->addAction(_openPOIAction);
510 poiMenu->addAction(_closePOIAction);
511 poiMenu->addSeparator();
512 poiMenu->addAction(_showPOILabelsAction);
513 poiMenu->addAction(_overlapPOIAction);
514 poiMenu->addSeparator();
515 poiMenu->addAction(_showPOIAction);
517 QMenu *dataMenu = menuBar()->addMenu(tr("&Data"));
518 QMenu *displayMenu = dataMenu->addMenu(tr("Display"));
519 displayMenu->addAction(_showWaypointLabelsAction);
520 displayMenu->addAction(_showRouteWaypointsAction);
521 dataMenu->addSeparator();
522 dataMenu->addAction(_showTracksAction);
523 dataMenu->addAction(_showRoutesAction);
524 dataMenu->addAction(_showWaypointsAction);
526 QMenu *settingsMenu = menuBar()->addMenu(tr("&Settings"));
527 QMenu *timeMenu = settingsMenu->addMenu(tr("Time"));
528 timeMenu->addAction(_totalTimeAction);
529 timeMenu->addAction(_movingTimeAction);
530 QMenu *unitsMenu = settingsMenu->addMenu(tr("Units"));
531 unitsMenu->addAction(_metricUnitsAction);
532 unitsMenu->addAction(_imperialUnitsAction);
533 unitsMenu->addAction(_nauticalUnitsAction);
534 QMenu *coordinatesMenu = settingsMenu->addMenu(tr("Coordinates format"));
535 coordinatesMenu->addAction(_decimalDegreesAction);
536 coordinatesMenu->addAction(_degreesMinutesAction);
537 coordinatesMenu->addAction(_DMSAction);
538 settingsMenu->addSeparator();
539 settingsMenu->addAction(_showToolbarsAction);
540 settingsMenu->addAction(_fullscreenAction);
541 settingsMenu->addSeparator();
542 settingsMenu->addAction(_openOptionsAction);
544 QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
545 helpMenu->addAction(_pathsAction);
546 helpMenu->addAction(_keysAction);
547 helpMenu->addSeparator();
548 helpMenu->addAction(_aboutAction);
551 void GUI::createToolBars()
553 int is = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
554 QSize iconSize(qMin(is, TOOLBAR_ICON_SIZE), qMin(is, TOOLBAR_ICON_SIZE));
556 #ifdef Q_OS_MAC
557 setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
558 #endif // Q_OS_MAC
560 _fileToolBar = addToolBar(tr("File"));
561 _fileToolBar->setIconSize(iconSize);
562 _fileToolBar->addAction(_openFileAction);
563 _fileToolBar->addAction(_reloadFileAction);
564 _fileToolBar->addAction(_closeFileAction);
565 _fileToolBar->addAction(_printFileAction);
567 _showToolBar = addToolBar(tr("Show"));
568 _showToolBar->setIconSize(iconSize);
569 _showToolBar->addAction(_showPOIAction);
570 _showToolBar->addAction(_showMapAction);
571 _showToolBar->addAction(_showGraphsAction);
573 _navigationToolBar = addToolBar(tr("Navigation"));
574 _navigationToolBar->setIconSize(iconSize);
575 _navigationToolBar->addAction(_firstAction);
576 _navigationToolBar->addAction(_prevAction);
577 _navigationToolBar->addAction(_nextAction);
578 _navigationToolBar->addAction(_lastAction);
581 void GUI::createMapView()
583 _mapView = new MapView(_map, _poi, this);
584 _mapView->setSizePolicy(QSizePolicy(QSizePolicy::Ignored,
585 QSizePolicy::Expanding));
586 _mapView->setMinimumHeight(200);
587 #ifdef Q_OS_WIN32
588 _mapView->setFrameShape(QFrame::NoFrame);
589 #endif // Q_OS_WIN32
592 void GUI::createGraphTabs()
594 _graphTabWidget = new QTabWidget();
595 connect(_graphTabWidget, SIGNAL(currentChanged(int)), this,
596 SLOT(graphChanged(int)));
598 _graphTabWidget->setSizePolicy(QSizePolicy(QSizePolicy::Ignored,
599 QSizePolicy::Preferred));
600 _graphTabWidget->setMinimumHeight(200);
601 #ifdef Q_OS_WIN32
602 _graphTabWidget->setDocumentMode(true);
603 #endif // Q_OS_WIN32
605 _tabs.append(new ElevationGraph(_graphTabWidget));
606 _tabs.append(new SpeedGraph(_graphTabWidget));
607 _tabs.append(new HeartRateGraph(_graphTabWidget));
608 _tabs.append(new CadenceGraph(_graphTabWidget));
609 _tabs.append(new PowerGraph(_graphTabWidget));
610 _tabs.append(new TemperatureGraph(_graphTabWidget));
611 _tabs.append(new GearRatioGraph(_graphTabWidget));
613 for (int i = 0; i < _tabs.count(); i++)
614 connect(_tabs.at(i), SIGNAL(sliderPositionChanged(qreal)), this,
615 SLOT(sliderPositionChanged(qreal)));
618 void GUI::createStatusBar()
620 _fileNameLabel = new QLabel();
621 _distanceLabel = new QLabel();
622 _timeLabel = new QLabel();
623 _distanceLabel->setAlignment(Qt::AlignHCenter);
624 _timeLabel->setAlignment(Qt::AlignHCenter);
626 statusBar()->addPermanentWidget(_fileNameLabel, 8);
627 statusBar()->addPermanentWidget(_distanceLabel, 1);
628 statusBar()->addPermanentWidget(_timeLabel, 1);
629 statusBar()->setSizeGripEnabled(false);
632 void GUI::about()
634 QMessageBox msgBox(this);
635 QUrl homepage(APP_HOMEPAGE);
637 msgBox.setWindowTitle(tr("About GPXSee"));
638 msgBox.setText("<h2>" + QString(APP_NAME) + "</h2><p><p>" + tr("Version %1")
639 .arg(QString(APP_VERSION) + " (" + CPU_ARCH + ", Qt " + QT_VERSION_STR
640 + ")") + "</p>");
641 msgBox.setInformativeText("<table width=\"300\"><tr><td>"
642 + tr("GPXSee is distributed under the terms of the GNU General Public "
643 "License version 3. For more info about GPXSee visit the project "
644 "homepage at %1.").arg("<a href=\"" + homepage.toString() + "\">"
645 + homepage.toString(QUrl::RemoveScheme).mid(2) + "</a>")
646 + "</td></tr></table>");
648 QIcon icon = msgBox.windowIcon();
649 QSize size = icon.actualSize(QSize(64, 64));
650 msgBox.setIconPixmap(icon.pixmap(size));
652 msgBox.exec();
655 void GUI::keys()
657 QMessageBox msgBox(this);
659 msgBox.setWindowTitle(tr("Keyboard controls"));
660 msgBox.setText("<h3>" + tr("Keyboard controls") + "</h3>");
661 msgBox.setInformativeText(
662 "<style>td {padding-right: 1.5em;}</style><div><table><tr><td>"
663 + tr("Next file") + "</td><td><i>" + QKeySequence(NEXT_KEY).toString()
664 + "</i></td></tr><tr><td>" + tr("Previous file")
665 + "</td><td><i>" + QKeySequence(PREV_KEY).toString()
666 + "</i></td></tr><tr><td>" + tr("First file") + "</td><td><i>"
667 + QKeySequence(FIRST_KEY).toString() + "</i></td></tr><tr><td>"
668 + tr("Last file") + "</td><td><i>" + QKeySequence(LAST_KEY).toString()
669 + "</i></td></tr><tr><td>" + tr("Append file")
670 + "</td><td><i>" + QKeySequence(MODIFIER).toString() + tr("Next/Previous")
671 + "</i></td></tr><tr><td></td><td></td></tr><tr><td>"
672 + tr("Toggle graph type") + "</td><td><i>"
673 + QKeySequence(TOGGLE_GRAPH_TYPE_KEY).toString() + "</i></td></tr><tr><td>"
674 + tr("Toggle time type") + "</td><td><i>"
675 + QKeySequence(TOGGLE_TIME_TYPE_KEY).toString()
676 + "<tr><td></td><td></td></tr><tr><td>" + tr("Next map")
677 + "</td><td><i>" + NEXT_MAP_SHORTCUT.toString() + "</i></td></tr><tr><td>"
678 + tr("Previous map") + "</td><td><i>" + PREV_MAP_SHORTCUT.toString()
679 + "</i></td></tr><tr><td></td><td></td></tr><tr><td>" + tr("Zoom in")
680 + "</td><td><i>" + QKeySequence(ZOOM_IN).toString()
681 + "</i></td></tr><tr><td>" + tr("Zoom out") + "</td><td><i>"
682 + QKeySequence(ZOOM_OUT).toString() + "</i></td></tr><tr><td>"
683 + tr("Digital zoom") + "</td><td><i>" + QKeySequence(MODIFIER).toString()
684 + tr("Zoom") + "</i></td></tr></table></div>");
686 msgBox.exec();
689 void GUI::paths()
691 QMessageBox msgBox(this);
693 msgBox.setWindowTitle(tr("Paths"));
694 msgBox.setText("<h3>" + tr("Paths") + "</h3>");
695 msgBox.setInformativeText(
696 "<style>td {white-space: pre; padding-right: 1em;}</style><table><tr><td>"
697 + tr("Map directory:") + "</td><td><code>"
698 + QDir::cleanPath(ProgramPaths::mapDir(true)) + "</code></td></tr><tr><td>"
699 + tr("POI directory:") + "</td><td><code>"
700 + QDir::cleanPath(ProgramPaths::poiDir(true)) + "</code></td></tr><tr><td>"
701 + tr("GCS/PCS directory:") + "</td><td><code>"
702 + QDir::cleanPath(ProgramPaths::csvDir(true)) + "</code></td></tr><tr><td>"
703 + tr("DEM directory:") + "</td><td><code>"
704 + QDir::cleanPath(ProgramPaths::demDir(true)) + "</code></td></tr><tr><td>"
705 + tr("Tile cache directory:") + "</td><td><code>"
706 + QDir::cleanPath(ProgramPaths::tilesDir()) + "</code></td></tr></table>"
709 msgBox.exec();
712 void GUI::openFile()
714 QStringList files = QFileDialog::getOpenFileNames(this, tr("Open file"),
715 _dataDir, Data::formats());
716 QStringList list = files;
718 for (QStringList::Iterator it = list.begin(); it != list.end(); it++)
719 openFile(*it);
720 if (!list.isEmpty())
721 _dataDir = QFileInfo(list.first()).path();
724 bool GUI::openFile(const QString &fileName)
726 if (fileName.isEmpty() || _files.contains(fileName))
727 return false;
729 if (loadFile(fileName)) {
730 _files.append(fileName);
731 _browser->setCurrent(fileName);
732 _fileActionGroup->setEnabled(true);
733 _navigationActionGroup->setEnabled(true);
735 updateNavigationActions();
736 updateStatusBarInfo();
737 updateWindowTitle();
739 return true;
740 } else {
741 if (_files.isEmpty())
742 _fileActionGroup->setEnabled(false);
744 return false;
748 bool GUI::loadFile(const QString &fileName)
750 Data data(fileName);
751 QList<QList<GraphItem*> > graphs;
752 QList<PathItem*> paths;
754 if (data.isValid()) {
755 for (int i = 0; i < data.tracks().count(); i++) {
756 _trackDistance += data.tracks().at(i)->distance();
757 _time += data.tracks().at(i)->time();
758 _movingTime += data.tracks().at(i)->movingTime();
759 const QDate &date = data.tracks().at(i)->date().date();
760 if (_dateRange.first.isNull() || _dateRange.first > date)
761 _dateRange.first = date;
762 if (_dateRange.second.isNull() || _dateRange.second < date)
763 _dateRange.second = date;
765 _trackCount += data.tracks().count();
767 for (int i = 0; i < data.routes().count(); i++)
768 _routeDistance += data.routes().at(i)->distance();
769 _routeCount += data.routes().count();
771 _waypointCount += data.waypoints().count();
773 if (_pathName.isNull()) {
774 if (data.tracks().count() == 1 && !data.routes().count())
775 _pathName = data.tracks().first()->name();
776 else if (data.routes().count() == 1 && !data.tracks().count())
777 _pathName = data.routes().first()->name();
778 } else
779 _pathName = QString();
781 for (int i = 0; i < _tabs.count(); i++)
782 graphs.append(_tabs.at(i)->loadData(data));
783 if (updateGraphTabs() | updateMapView())
784 _splitter->refresh();
785 paths = _mapView->loadData(data);
787 for (int i = 0; i < paths.count(); i++) {
788 const PathItem *pi = paths.at(i);
789 for (int j = 0; j < graphs.count(); j++) {
790 const GraphItem *gi = graphs.at(j).at(i);
791 if (!gi)
792 continue;
793 connect(gi, SIGNAL(sliderPositionChanged(qreal)), pi,
794 SLOT(moveMarker(qreal)));
795 connect(pi, SIGNAL(selected(bool)), gi, SLOT(hover(bool)));
796 connect(gi, SIGNAL(selected(bool)), pi, SLOT(hover(bool)));
800 return true;
801 } else {
802 updateNavigationActions();
803 updateStatusBarInfo();
804 updateWindowTitle();
805 updateGraphTabs();
806 updateMapView();
808 QString error = tr("Error loading data file:") + "\n\n"
809 + fileName + "\n\n" + data.errorString();
810 if (data.errorLine())
811 error.append("\n" + tr("Line: %1").arg(data.errorLine()));
812 QMessageBox::critical(this, APP_NAME, error);
813 return false;
817 void GUI::openPOIFile()
819 QStringList files = QFileDialog::getOpenFileNames(this, tr("Open POI file"),
820 _poiDir, Data::formats());
821 QStringList list = files;
823 for (QStringList::Iterator it = list.begin(); it != list.end(); it++)
824 openPOIFile(*it);
825 if (!list.isEmpty())
826 _poiDir = QFileInfo(list.first()).path();
829 bool GUI::openPOIFile(const QString &fileName)
831 if (fileName.isEmpty() || _poi->files().contains(fileName))
832 return false;
834 if (_poi->loadFile(fileName)) {
835 _mapView->showPOI(true);
836 _showPOIAction->setChecked(true);
837 QAction *action = createPOIFileAction(fileName);
838 action->setChecked(true);
839 _poiFilesMenu->addAction(action);
841 return true;
842 } else {
843 QString error = tr("Error loading POI file:") + "\n\n"
844 + fileName + "\n\n" + _poi->errorString();
845 if (_poi->errorLine())
846 error.append("\n" + tr("Line: %1").arg(_poi->errorLine()));
847 QMessageBox::critical(this, APP_NAME, error);
849 return false;
853 void GUI::closePOIFiles()
855 _poiFilesMenu->clear();
857 for (int i = 0; i < _poiFilesActions.count(); i++)
858 delete _poiFilesActions[i];
859 _poiFilesActions.clear();
861 _poi->clear();
864 void GUI::openOptions()
866 #define SET_VIEW_OPTION(option, action) \
867 if (options.option != _options.option) \
868 _mapView->action(options.option)
869 #define SET_TAB_OPTION(option, action) \
870 if (options.option != _options.option) \
871 for (int i = 0; i < _tabs.count(); i++) \
872 _tabs.at(i)->action(options.option)
873 #define SET_TRACK_OPTION(option, action) \
874 if (options.option != _options.option) { \
875 Track::action(options.option); \
876 reload = true; \
878 #define SET_DATA_OPTION(option, action) \
879 if (options.option != _options.option) { \
880 Data::action(options.option); \
881 reload = true; \
884 Options options(_options);
885 bool reload = false;
887 OptionsDialog dialog(&options, this);
888 if (dialog.exec() != QDialog::Accepted)
889 return;
891 SET_VIEW_OPTION(palette, setPalette);
892 SET_VIEW_OPTION(mapOpacity, setMapOpacity);
893 SET_VIEW_OPTION(backgroundColor, setBackgroundColor);
894 SET_VIEW_OPTION(trackWidth, setTrackWidth);
895 SET_VIEW_OPTION(routeWidth, setRouteWidth);
896 SET_VIEW_OPTION(trackStyle, setTrackStyle);
897 SET_VIEW_OPTION(routeStyle, setRouteStyle);
898 SET_VIEW_OPTION(waypointSize, setWaypointSize);
899 SET_VIEW_OPTION(waypointColor, setWaypointColor);
900 SET_VIEW_OPTION(poiSize, setPOISize);
901 SET_VIEW_OPTION(poiColor, setPOIColor);
902 SET_VIEW_OPTION(pathAntiAliasing, useAntiAliasing);
903 SET_VIEW_OPTION(useOpenGL, useOpenGL);
904 SET_VIEW_OPTION(sliderColor, setMarkerColor);
906 SET_TAB_OPTION(palette, setPalette);
907 SET_TAB_OPTION(graphWidth, setGraphWidth);
908 SET_TAB_OPTION(graphAntiAliasing, useAntiAliasing);
909 SET_TAB_OPTION(useOpenGL, useOpenGL);
910 SET_TAB_OPTION(sliderColor, setSliderColor);
912 SET_TRACK_OPTION(elevationFilter, setElevationFilter);
913 SET_TRACK_OPTION(speedFilter, setSpeedFilter);
914 SET_TRACK_OPTION(heartRateFilter, setHeartRateFilter);
915 SET_TRACK_OPTION(cadenceFilter, setCadenceFilter);
916 SET_TRACK_OPTION(powerFilter, setPowerFilter);
917 SET_TRACK_OPTION(outlierEliminate, setOutlierElimination);
918 SET_TRACK_OPTION(pauseSpeed, setPauseSpeed);
919 SET_TRACK_OPTION(pauseInterval, setPauseInterval);
920 SET_TRACK_OPTION(useReportedSpeed, useReportedSpeed);
922 SET_DATA_OPTION(dataUseDEM, useDEM);
924 if (options.poiRadius != _options.poiRadius)
925 _poi->setRadius(options.poiRadius);
926 if (options.poiUseDEM != _options.poiUseDEM)
927 _poi->useDEM(options.poiUseDEM);
929 if (options.pixmapCache != _options.pixmapCache)
930 QPixmapCache::setCacheLimit(options.pixmapCache * 1024);
932 if (options.connectionTimeout != _options.connectionTimeout)
933 Downloader::setTimeout(options.connectionTimeout);
934 #ifdef ENABLE_HTTP2
935 if (options.enableHTTP2 != _options.enableHTTP2)
936 Downloader::enableHTTP2(options.enableHTTP2);
937 #endif // ENABLE_HTTP2
939 #ifdef ENABLE_HIDPI
940 if (options.hidpiMap != _options.hidpiMap)
941 _mapView->setDevicePixelRatio(devicePixelRatioF(),
942 options.hidpiMap ? devicePixelRatioF() : 1.0);
943 #endif // ENABLE_HIDPI
945 if (reload)
946 reloadFile();
948 _options = options;
950 updateMapView();
953 void GUI::printFile()
955 QPrinter printer(QPrinter::HighResolution);
956 QPrintDialog dialog(&printer, this);
958 if (dialog.exec() == QDialog::Accepted)
959 plot(&printer);
962 void GUI::exportFile()
964 ExportDialog dialog(&_export, this);
965 if (dialog.exec() != QDialog::Accepted)
966 return;
968 QPrinter printer(QPrinter::HighResolution);
969 printer.setOutputFormat(QPrinter::PdfFormat);
970 printer.setCreator(QString(APP_NAME) + QString(" ")
971 + QString(APP_VERSION));
972 printer.setResolution(_export.resolution);
973 printer.setOrientation(_export.orientation);
974 printer.setOutputFileName(_export.fileName);
975 printer.setPaperSize(_export.paperSize);
976 printer.setPageMargins(_export.margins.left(), _export.margins.top(),
977 _export.margins.right(), _export.margins.bottom(), QPrinter::Millimeter);
979 plot(&printer);
982 void GUI::statistics()
984 QLocale l(QLocale::system());
986 #ifdef Q_OS_WIN32
987 QString text = "<style>td {white-space: pre; padding-right: 4em;}"
988 "th {text-align: left; padding-top: 0.5em;}</style><table>";
989 #else // Q_OS_WIN32
990 QString text = "<style>td {white-space: pre; padding-right: 2em;}"
991 "th {text-align: left; padding-top: 0.5em;}</style><table>";
992 #endif // Q_OS_WIN32
994 if (_showTracksAction->isChecked() && _trackCount > 1)
995 text.append("<tr><td>" + tr("Tracks") + ":</td><td>"
996 + l.toString(_trackCount) + "</td></tr>");
997 if (_showRoutesAction->isChecked() && _routeCount > 1)
998 text.append("<tr><td>" + tr("Routes") + ":</td><td>"
999 + l.toString(_routeCount) + "</td></tr>");
1000 if (_showWaypointsAction->isChecked() && _waypointCount > 1)
1001 text.append("<tr><td>" + tr("Waypoints") + ":</td><td>"
1002 + l.toString(_waypointCount) + "</td></tr>");
1004 if (_dateRange.first.isValid()) {
1005 if (_dateRange.first == _dateRange.second) {
1006 QString format = l.dateFormat(QLocale::LongFormat);
1007 text.append("<tr><td>" + tr("Date") + ":</td><td>"
1008 + _dateRange.first.toString(format) + "</td></tr>");
1009 } else {
1010 QString format = l.dateFormat(QLocale::ShortFormat);
1011 text.append("<tr><td>" + tr("Date") + ":</td><td>"
1012 + QString("%1 - %2").arg(_dateRange.first.toString(format),
1013 _dateRange.second.toString(format)) + "</td></tr>");
1017 if (distance() > 0)
1018 text.append("<tr><td>" + tr("Distance") + ":</td><td>"
1019 + Format::distance(distance(), units()) + "</td></tr>");
1020 if (time() > 0) {
1021 text.append("<tr><td>" + tr("Time") + ":</td><td>"
1022 + Format::timeSpan(time()) + "</td></tr>");
1023 text.append("<tr><td>" + tr("Moving time") + ":</td><td>"
1024 + Format::timeSpan(movingTime()) + "</td></tr>");
1027 for (int i = 0; i < _tabs.count(); i++) {
1028 const GraphTab *tab = _tabs.at(i);
1029 if (tab->isEmpty())
1030 continue;
1032 text.append("<tr><th colspan=\"2\">" + tab->label() + "</th></tr>");
1033 for (int j = 0; j < tab->info().size(); j++) {
1034 const KV &kv = tab->info().at(j);
1035 text.append("<tr><td>" + kv.key() + ":</td><td>" + kv.value()
1036 + "</td></tr>");
1040 text.append("</table>");
1043 QMessageBox msgBox(this);
1044 msgBox.setWindowTitle(tr("Statistics"));
1045 msgBox.setText("<h3>" + tr("Statistics") + "</h3>");
1046 msgBox.setInformativeText(text);
1047 msgBox.exec();
1050 void GUI::plot(QPrinter *printer)
1052 QLocale l(QLocale::system());
1053 QPainter p(printer);
1054 TrackInfo info;
1055 qreal ih, gh, mh, ratio;
1058 if (!_pathName.isNull() && _options.printName)
1059 info.insert(tr("Name"), _pathName);
1061 if (_options.printItemCount) {
1062 if (_showTracksAction->isChecked() && _trackCount > 1)
1063 info.insert(tr("Tracks"), l.toString(_trackCount));
1064 if (_showRoutesAction->isChecked() && _routeCount > 1)
1065 info.insert(tr("Routes"), l.toString(_routeCount));
1066 if (_showWaypointsAction->isChecked() && _waypointCount > 1)
1067 info.insert(tr("Waypoints"), l.toString(_waypointCount));
1070 if (_dateRange.first.isValid() && _options.printDate) {
1071 if (_dateRange.first == _dateRange.second) {
1072 QString format = l.dateFormat(QLocale::LongFormat);
1073 info.insert(tr("Date"), _dateRange.first.toString(format));
1074 } else {
1075 QString format = l.dateFormat(QLocale::ShortFormat);
1076 info.insert(tr("Date"), QString("%1 - %2")
1077 .arg(_dateRange.first.toString(format),
1078 _dateRange.second.toString(format)));
1082 if (distance() > 0 && _options.printDistance)
1083 info.insert(tr("Distance"), Format::distance(distance(), units()));
1084 if (time() > 0 && _options.printTime)
1085 info.insert(tr("Time"), Format::timeSpan(time()));
1086 if (movingTime() > 0 && _options.printMovingTime)
1087 info.insert(tr("Moving time"), Format::timeSpan(movingTime()));
1089 qreal fsr = 1085.0 / (qMax(printer->width(), printer->height())
1090 / (qreal)printer->resolution());
1091 ratio = p.paintEngine()->paintDevice()->logicalDpiX() / fsr;
1092 if (info.isEmpty()) {
1093 ih = 0;
1094 mh = 0;
1095 } else {
1096 ih = info.contentSize().height() * ratio;
1097 mh = ih / 2;
1098 info.plot(&p, QRectF(0, 0, printer->width(), ih), ratio);
1100 if (_graphTabWidget->isVisible() && !_options.separateGraphPage) {
1101 qreal r = (((qreal)(printer)->width()) / (qreal)(printer->height()));
1102 gh = (printer->width() > printer->height())
1103 ? 0.15 * r * (printer->height() - ih - 2*mh)
1104 : 0.15 * (printer->height() - ih - 2*mh);
1105 GraphTab *gt = static_cast<GraphTab*>(_graphTabWidget->currentWidget());
1106 gt->plot(&p, QRectF(0, printer->height() - gh, printer->width(), gh),
1107 ratio);
1108 } else
1109 gh = 0;
1110 _mapView->plot(&p, QRectF(0, ih + mh, printer->width(), printer->height()
1111 - (ih + 2*mh + gh)), ratio, _options.hiresPrint);
1113 if (_graphTabWidget->isVisible() && _options.separateGraphPage) {
1114 printer->newPage();
1116 int cnt = 0;
1117 for (int i = 0; i < _tabs.size(); i++)
1118 if (!_tabs.at(i)->isEmpty())
1119 cnt++;
1121 qreal sp = ratio * 20;
1122 gh = qMin((printer->height() - ((cnt - 1) * sp))/(qreal)cnt,
1123 0.20 * printer->height());
1125 qreal y = 0;
1126 for (int i = 0; i < _tabs.size(); i++) {
1127 if (!_tabs.at(i)->isEmpty()) {
1128 _tabs.at(i)->plot(&p, QRectF(0, y, printer->width(), gh),
1129 ratio);
1130 y += gh + sp;
1136 void GUI::reloadFile()
1138 _trackCount = 0;
1139 _routeCount = 0;
1140 _waypointCount = 0;
1141 _trackDistance = 0;
1142 _routeDistance = 0;
1143 _time = 0;
1144 _movingTime = 0;
1145 _dateRange = DateRange(QDate(), QDate());
1146 _pathName = QString();
1148 for (int i = 0; i < _tabs.count(); i++)
1149 _tabs.at(i)->clear();
1150 _mapView->clear();
1152 _sliderPos = 0;
1154 for (int i = 0; i < _files.size(); i++) {
1155 if (!loadFile(_files.at(i))) {
1156 _files.removeAt(i);
1157 i--;
1161 updateStatusBarInfo();
1162 updateWindowTitle();
1163 if (_files.isEmpty())
1164 _fileActionGroup->setEnabled(false);
1165 else
1166 _browser->setCurrent(_files.last());
1169 void GUI::closeFiles()
1171 _trackCount = 0;
1172 _routeCount = 0;
1173 _waypointCount = 0;
1174 _trackDistance = 0;
1175 _routeDistance = 0;
1176 _time = 0;
1177 _movingTime = 0;
1178 _dateRange = DateRange(QDate(), QDate());
1179 _pathName = QString();
1181 _sliderPos = 0;
1183 for (int i = 0; i < _tabs.count(); i++)
1184 _tabs.at(i)->clear();
1185 _mapView->clear();
1187 _files.clear();
1190 void GUI::closeAll()
1192 closeFiles();
1194 _fileActionGroup->setEnabled(false);
1195 updateStatusBarInfo();
1196 updateWindowTitle();
1197 updateGraphTabs();
1198 updateMapView();
1201 void GUI::showGraphs(bool show)
1203 _graphTabWidget->setHidden(!show);
1206 void GUI::showToolbars(bool show)
1208 if (show) {
1209 addToolBar(_fileToolBar);
1210 addToolBar(_showToolBar);
1211 addToolBar(_navigationToolBar);
1212 _fileToolBar->show();
1213 _showToolBar->show();
1214 _navigationToolBar->show();
1215 } else {
1216 removeToolBar(_fileToolBar);
1217 removeToolBar(_showToolBar);
1218 removeToolBar(_navigationToolBar);
1222 void GUI::showFullscreen(bool show)
1224 if (show) {
1225 _frameStyle = _mapView->frameStyle();
1226 _showGraphs = _showGraphsAction->isChecked();
1228 statusBar()->hide();
1229 menuBar()->hide();
1230 showToolbars(false);
1231 showGraphs(false);
1232 _showGraphsAction->setChecked(false);
1233 _mapView->setFrameStyle(QFrame::NoFrame);
1235 showFullScreen();
1236 } else {
1237 statusBar()->show();
1238 menuBar()->show();
1239 if (_showToolbarsAction->isChecked())
1240 showToolbars(true);
1241 _showGraphsAction->setChecked(_showGraphs);
1242 if (_showGraphsAction->isEnabled())
1243 showGraphs(_showGraphs);
1244 _mapView->setFrameStyle(_frameStyle);
1246 showNormal();
1250 void GUI::showTracks(bool show)
1252 _mapView->showTracks(show);
1254 for (int i = 0; i < _tabs.size(); i++)
1255 _tabs.at(i)->showTracks(show);
1257 updateStatusBarInfo();
1258 updateGraphTabs();
1261 void GUI::showRoutes(bool show)
1263 _mapView->showRoutes(show);
1265 for (int i = 0; i < _tabs.size(); i++)
1266 _tabs.at(i)->showRoutes(show);
1268 updateStatusBarInfo();
1269 updateGraphTabs();
1272 void GUI::showGraphGrids(bool show)
1274 for (int i = 0; i < _tabs.size(); i++)
1275 _tabs.at(i)->showGrid(show);
1278 void GUI::showGraphSliderInfo(bool show)
1280 for (int i = 0; i < _tabs.size(); i++)
1281 _tabs.at(i)->showSliderInfo(show);
1284 void GUI::loadMap()
1286 QStringList files = QFileDialog::getOpenFileNames(this, tr("Open map file"),
1287 _mapDir, MapList::formats());
1288 QStringList list = files;
1290 for (QStringList::Iterator it = list.begin(); it != list.end(); it++)
1291 loadMap(*it);
1292 if (!list.isEmpty())
1293 _mapDir = QFileInfo(list.first()).path();
1296 bool GUI::loadMap(const QString &fileName)
1298 if (fileName.isEmpty())
1299 return false;
1301 if (_ml->loadFile(fileName)) {
1302 QAction *a = createMapAction(_ml->maps().last());
1303 _mapMenu->insertAction(_mapsEnd, a);
1304 _showMapAction->setEnabled(true);
1305 _clearMapCacheAction->setEnabled(true);
1306 a->trigger();
1307 return true;
1308 } else {
1309 QString error = tr("Error loading map:") + "\n\n"
1310 + fileName + "\n\n" + _ml->errorString();
1311 QMessageBox::critical(this, APP_NAME, error);
1313 return false;
1317 void GUI::updateStatusBarInfo()
1319 if (_files.count() == 0)
1320 _fileNameLabel->setText(tr("No files loaded"));
1321 else if (_files.count() == 1)
1322 _fileNameLabel->setText(_files.at(0));
1323 else
1324 _fileNameLabel->setText(tr("%n files", "", _files.count()));
1326 if (distance() > 0)
1327 _distanceLabel->setText(Format::distance(distance(), units()));
1328 else
1329 _distanceLabel->clear();
1331 if (time() > 0) {
1332 if (_movingTimeAction->isChecked()) {
1333 _timeLabel->setText(Format::timeSpan(movingTime())
1334 + "<sub>M</sub>");
1335 _timeLabel->setToolTip(Format::timeSpan(time()));
1336 } else {
1337 _timeLabel->setText(Format::timeSpan(time()));
1338 _timeLabel->setToolTip(Format::timeSpan(movingTime())
1339 + "<sub>M</sub>");
1341 } else {
1342 _timeLabel->clear();
1343 _timeLabel->setToolTip(QString());
1347 void GUI::updateWindowTitle()
1349 if (_files.count() == 1)
1350 setWindowTitle(QFileInfo(_files.at(0)).fileName() + " - " + APP_NAME);
1351 else
1352 setWindowTitle(APP_NAME);
1355 void GUI::mapChanged(int index)
1357 _map = _ml->maps().at(index);
1358 _mapView->setMap(_map);
1361 void GUI::nextMap()
1363 if (_ml->maps().count() < 2)
1364 return;
1366 int next = (_ml->maps().indexOf(_map) + 1) % _ml->maps().count();
1367 _mapActions.at(next)->setChecked(true);
1368 mapChanged(next);
1371 void GUI::prevMap()
1373 if (_ml->maps().count() < 2)
1374 return;
1376 int prev = (_ml->maps().indexOf(_map) + _ml->maps().count() - 1)
1377 % _ml->maps().count();
1378 _mapActions.at(prev)->setChecked(true);
1379 mapChanged(prev);
1382 void GUI::poiFileChecked(int index)
1384 _poi->enableFile(_poi->files().at(index),
1385 _poiFilesActions.at(index)->isChecked());
1388 void GUI::sliderPositionChanged(qreal pos)
1390 _sliderPos = pos;
1393 void GUI::graphChanged(int index)
1395 if (index < 0)
1396 return;
1398 GraphTab *gt = static_cast<GraphTab*>(_graphTabWidget->widget(index));
1399 gt->setSliderPosition(_sliderPos);
1402 void GUI::updateNavigationActions()
1404 if (_browser->isLast()) {
1405 _nextAction->setEnabled(false);
1406 _lastAction->setEnabled(false);
1407 } else {
1408 _nextAction->setEnabled(true);
1409 _lastAction->setEnabled(true);
1412 if (_browser->isFirst()) {
1413 _prevAction->setEnabled(false);
1414 _firstAction->setEnabled(false);
1415 } else {
1416 _prevAction->setEnabled(true);
1417 _firstAction->setEnabled(true);
1421 bool GUI::updateGraphTabs()
1423 int index;
1424 GraphTab *tab;
1425 bool hidden = _graphTabWidget->isHidden();
1427 for (int i = 0; i < _tabs.size(); i++) {
1428 tab = _tabs.at(i);
1429 if (tab->isEmpty() && (index = _graphTabWidget->indexOf(tab)) >= 0)
1430 _graphTabWidget->removeTab(index);
1433 for (int i = 0; i < _tabs.size(); i++) {
1434 tab = _tabs.at(i);
1435 if (!tab->isEmpty() && _graphTabWidget->indexOf(tab) < 0)
1436 _graphTabWidget->insertTab(i, tab, _tabs.at(i)->label());
1439 if (_graphTabWidget->count() &&
1440 ((_showTracksAction->isChecked() && _trackCount)
1441 || (_showRoutesAction->isChecked() && _routeCount))) {
1442 if (_showGraphsAction->isChecked())
1443 _graphTabWidget->setHidden(false);
1444 _showGraphsAction->setEnabled(true);
1445 } else {
1446 _graphTabWidget->setHidden(true);
1447 _showGraphsAction->setEnabled(false);
1450 return (hidden != _graphTabWidget->isHidden());
1453 bool GUI::updateMapView()
1455 bool hidden = _mapView->isHidden();
1457 if (_options.alwaysShowMap)
1458 _mapView->setHidden(false);
1459 else
1460 _mapView->setHidden(!(_trackCount + _routeCount + _waypointCount));
1462 return (hidden != _mapView->isHidden());
1465 void GUI::setTimeType(TimeType type)
1467 for (int i = 0; i <_tabs.count(); i++)
1468 _tabs.at(i)->setTimeType(type);
1470 updateStatusBarInfo();
1473 void GUI::setUnits(Units units)
1475 _export.units = units;
1476 _options.units = units;
1478 _mapView->setUnits(units);
1479 for (int i = 0; i <_tabs.count(); i++)
1480 _tabs.at(i)->setUnits(units);
1481 updateStatusBarInfo();
1484 void GUI::setCoordinatesFormat(CoordinatesFormat format)
1486 _mapView->setCoordinatesFormat(format);
1489 void GUI::setGraphType(GraphType type)
1491 _sliderPos = 0;
1493 for (int i = 0; i <_tabs.count(); i++) {
1494 _tabs.at(i)->setGraphType(type);
1495 _tabs.at(i)->setSliderPosition(0);
1499 void GUI::next()
1501 QString file = _browser->next();
1502 if (file.isNull())
1503 return;
1505 closeFiles();
1506 openFile(file);
1509 void GUI::prev()
1511 QString file = _browser->prev();
1512 if (file.isNull())
1513 return;
1515 closeFiles();
1516 openFile(file);
1519 void GUI::last()
1521 QString file = _browser->last();
1522 if (file.isNull())
1523 return;
1525 closeFiles();
1526 openFile(file);
1529 void GUI::first()
1531 QString file = _browser->first();
1532 if (file.isNull())
1533 return;
1535 closeFiles();
1536 openFile(file);
1539 void GUI::keyPressEvent(QKeyEvent *event)
1541 QString file;
1543 switch (event->key()) {
1544 case PREV_KEY:
1545 file = _browser->prev();
1546 break;
1547 case NEXT_KEY:
1548 file = _browser->next();
1549 break;
1550 case FIRST_KEY:
1551 file = _browser->first();
1552 break;
1553 case LAST_KEY:
1554 file = _browser->last();
1555 break;
1557 case TOGGLE_GRAPH_TYPE_KEY:
1558 if (_timeGraphAction->isChecked())
1559 _distanceGraphAction->trigger();
1560 else
1561 _timeGraphAction->trigger();
1562 break;
1563 case TOGGLE_TIME_TYPE_KEY:
1564 if (_movingTimeAction->isChecked())
1565 _totalTimeAction->trigger();
1566 else
1567 _movingTimeAction->trigger();
1568 break;
1570 case Qt::Key_Escape:
1571 if (_fullscreenAction->isChecked()) {
1572 _fullscreenAction->setChecked(false);
1573 showFullscreen(false);
1574 return;
1576 break;
1579 if (!file.isNull()) {
1580 if (!(event->modifiers() & MODIFIER))
1581 closeFiles();
1582 openFile(file);
1583 return;
1586 QMainWindow::keyPressEvent(event);
1589 void GUI::closeEvent(QCloseEvent *event)
1591 writeSettings();
1592 event->accept();
1595 void GUI::dragEnterEvent(QDragEnterEvent *event)
1597 if (!event->mimeData()->hasUrls())
1598 return;
1599 if (event->proposedAction() != Qt::CopyAction)
1600 return;
1602 QList<QUrl> urls = event->mimeData()->urls();
1603 for (int i = 0; i < urls.size(); i++)
1604 if (!urls.at(i).isLocalFile())
1605 return;
1607 event->acceptProposedAction();
1610 void GUI::dropEvent(QDropEvent *event)
1612 QList<QUrl> urls = event->mimeData()->urls();
1613 for (int i = 0; i < urls.size(); i++)
1614 openFile(urls.at(i).toLocalFile());
1617 void GUI::writeSettings()
1619 QSettings settings(qApp->applicationName(), qApp->applicationName());
1620 settings.clear();
1622 settings.beginGroup(WINDOW_SETTINGS_GROUP);
1623 if (size() != WINDOW_SIZE_DEFAULT)
1624 settings.setValue(WINDOW_SIZE_SETTING, size());
1625 if (pos() != WINDOW_POS_DEFAULT)
1626 settings.setValue(WINDOW_POS_SETTING, pos());
1627 settings.endGroup();
1629 settings.beginGroup(SETTINGS_SETTINGS_GROUP);
1630 if ((_movingTimeAction->isChecked() ? Moving : Total) !=
1631 TIME_TYPE_DEFAULT)
1632 settings.setValue(TIME_TYPE_SETTING, _movingTimeAction->isChecked()
1633 ? Moving : Total);
1634 Units units = _imperialUnitsAction->isChecked() ? Imperial
1635 : _nauticalUnitsAction->isChecked() ? Nautical : Metric;
1636 if (units != UNITS_DEFAULT)
1637 settings.setValue(UNITS_SETTING, units);
1638 CoordinatesFormat format = _DMSAction->isChecked() ? DMS
1639 : _degreesMinutesAction->isChecked() ? DegreesMinutes : DecimalDegrees;
1640 if (format != COORDINATES_DEFAULT)
1641 settings.setValue(COORDINATES_SETTING, format);
1642 if (_showToolbarsAction->isChecked() != SHOW_TOOLBARS_DEFAULT)
1643 settings.setValue(SHOW_TOOLBARS_SETTING,
1644 _showToolbarsAction->isChecked());
1645 settings.endGroup();
1647 settings.beginGroup(MAP_SETTINGS_GROUP);
1648 settings.setValue(CURRENT_MAP_SETTING, _map->name());
1649 if (_showMapAction->isChecked() != SHOW_MAP_DEFAULT)
1650 settings.setValue(SHOW_MAP_SETTING, _showMapAction->isChecked());
1651 settings.endGroup();
1653 settings.beginGroup(GRAPH_SETTINGS_GROUP);
1654 if (_showGraphsAction->isChecked() != SHOW_GRAPHS_DEFAULT)
1655 settings.setValue(SHOW_GRAPHS_SETTING, _showGraphsAction->isChecked());
1656 if ((_timeGraphAction->isChecked() ? Time : Distance) != GRAPH_TYPE_DEFAULT)
1657 settings.setValue(GRAPH_TYPE_SETTING, _timeGraphAction->isChecked()
1658 ? Time : Distance);
1659 if (_showGraphGridAction->isChecked() != SHOW_GRAPH_GRIDS_DEFAULT)
1660 settings.setValue(SHOW_GRAPH_GRIDS_SETTING,
1661 _showGraphGridAction->isChecked());
1662 if (_showGraphSliderInfoAction->isChecked()
1663 != SHOW_GRAPH_SLIDER_INFO_DEFAULT)
1664 settings.setValue(SHOW_GRAPH_SLIDER_INFO_SETTING,
1665 _showGraphSliderInfoAction->isChecked());
1666 settings.endGroup();
1668 settings.beginGroup(POI_SETTINGS_GROUP);
1669 if (_showPOIAction->isChecked() != SHOW_POI_DEFAULT)
1670 settings.setValue(SHOW_POI_SETTING, _showPOIAction->isChecked());
1671 if (_overlapPOIAction->isChecked() != OVERLAP_POI_DEFAULT)
1672 settings.setValue(OVERLAP_POI_SETTING, _overlapPOIAction->isChecked());
1674 int j = 0;
1675 for (int i = 0; i < _poiFilesActions.count(); i++) {
1676 if (!_poiFilesActions.at(i)->isChecked()) {
1677 if (j == 0)
1678 settings.beginWriteArray(DISABLED_POI_FILE_SETTINGS_PREFIX);
1679 settings.setArrayIndex(j++);
1680 settings.setValue(DISABLED_POI_FILE_SETTING, _poi->files().at(i));
1683 if (j != 0)
1684 settings.endArray();
1685 settings.endGroup();
1687 settings.beginGroup(DATA_SETTINGS_GROUP);
1688 if (_showTracksAction->isChecked() != SHOW_TRACKS_DEFAULT)
1689 settings.setValue(SHOW_TRACKS_SETTING, _showTracksAction->isChecked());
1690 if (_showRoutesAction->isChecked() != SHOW_ROUTES_DEFAULT)
1691 settings.setValue(SHOW_ROUTES_SETTING, _showRoutesAction->isChecked());
1692 if (_showWaypointsAction->isChecked() != SHOW_WAYPOINTS_DEFAULT)
1693 settings.setValue(SHOW_WAYPOINTS_SETTING,
1694 _showWaypointsAction->isChecked());
1695 if (_showWaypointLabelsAction->isChecked() != SHOW_WAYPOINT_LABELS_DEFAULT)
1696 settings.setValue(SHOW_WAYPOINT_LABELS_SETTING,
1697 _showWaypointLabelsAction->isChecked());
1698 if (_showRouteWaypointsAction->isChecked() != SHOW_ROUTE_WAYPOINTS_DEFAULT)
1699 settings.setValue(SHOW_ROUTE_WAYPOINTS_SETTING,
1700 _showRouteWaypointsAction->isChecked());
1701 settings.endGroup();
1703 settings.beginGroup(EXPORT_SETTINGS_GROUP);
1704 if (_export.orientation != PAPER_ORIENTATION_DEFAULT)
1705 settings.setValue(PAPER_ORIENTATION_SETTING, _export.orientation);
1706 if (_export.resolution != RESOLUTION_DEFAULT)
1707 settings.setValue(RESOLUTION_SETTING, _export.resolution);
1708 if (_export.paperSize != PAPER_SIZE_DEFAULT)
1709 settings.setValue(PAPER_SIZE_SETTING, _export.paperSize);
1710 if (_export.margins.left() != MARGIN_LEFT_DEFAULT)
1711 settings.setValue(MARGIN_LEFT_SETTING, _export.margins.left());
1712 if (_export.margins.top() != MARGIN_TOP_DEFAULT)
1713 settings.setValue(MARGIN_TOP_SETTING, _export.margins.top());
1714 if (_export.margins.right() != MARGIN_RIGHT_DEFAULT)
1715 settings.setValue(MARGIN_RIGHT_SETTING, _export.margins.right());
1716 if (_export.margins.bottom() != MARGIN_BOTTOM_DEFAULT)
1717 settings.setValue(MARGIN_BOTTOM_SETTING, _export.margins.bottom());
1718 if (_export.fileName != EXPORT_FILENAME_DEFAULT)
1719 settings.setValue(EXPORT_FILENAME_SETTING, _export.fileName);
1720 settings.endGroup();
1722 settings.beginGroup(OPTIONS_SETTINGS_GROUP);
1723 if (_options.palette.color() != PALETTE_COLOR_DEFAULT)
1724 settings.setValue(PALETTE_COLOR_SETTING, _options.palette.color());
1725 if (_options.palette.shift() != PALETTE_SHIFT_DEFAULT)
1726 settings.setValue(PALETTE_SHIFT_SETTING, _options.palette.shift());
1727 if (_options.mapOpacity != MAP_OPACITY_DEFAULT)
1728 settings.setValue(MAP_OPACITY_SETTING, _options.mapOpacity);
1729 if (_options.backgroundColor != BACKGROUND_COLOR_DEFAULT)
1730 settings.setValue(BACKGROUND_COLOR_SETTING, _options.backgroundColor);
1731 if (_options.trackWidth != TRACK_WIDTH_DEFAULT)
1732 settings.setValue(TRACK_WIDTH_SETTING, _options.trackWidth);
1733 if (_options.routeWidth != ROUTE_WIDTH_DEFAULT)
1734 settings.setValue(ROUTE_WIDTH_SETTING, _options.routeWidth);
1735 if (_options.trackStyle != TRACK_STYLE_DEFAULT)
1736 settings.setValue(TRACK_STYLE_SETTING, (int)_options.trackStyle);
1737 if (_options.routeStyle != ROUTE_STYLE_DEFAULT)
1738 settings.setValue(ROUTE_STYLE_SETTING, (int)_options.routeStyle);
1739 if (_options.waypointSize != WAYPOINT_SIZE_DEFAULT)
1740 settings.setValue(WAYPOINT_SIZE_SETTING, _options.waypointSize);
1741 if (_options.waypointColor != WAYPOINT_COLOR_DEFAULT)
1742 settings.setValue(WAYPOINT_COLOR_SETTING, _options.waypointColor);
1743 if (_options.poiSize != POI_SIZE_DEFAULT)
1744 settings.setValue(POI_SIZE_SETTING, _options.poiSize);
1745 if (_options.poiColor != POI_COLOR_DEFAULT)
1746 settings.setValue(POI_COLOR_SETTING, _options.poiColor);
1747 if (_options.graphWidth != GRAPH_WIDTH_DEFAULT)
1748 settings.setValue(GRAPH_WIDTH_SETTING, _options.graphWidth);
1749 if (_options.pathAntiAliasing != PATH_AA_DEFAULT)
1750 settings.setValue(PATH_AA_SETTING, _options.pathAntiAliasing);
1751 if (_options.graphAntiAliasing != GRAPH_AA_DEFAULT)
1752 settings.setValue(GRAPH_AA_SETTING, _options.graphAntiAliasing);
1753 if (_options.elevationFilter != ELEVATION_FILTER_DEFAULT)
1754 settings.setValue(ELEVATION_FILTER_SETTING, _options.elevationFilter);
1755 if (_options.speedFilter != SPEED_FILTER_DEFAULT)
1756 settings.setValue(SPEED_FILTER_SETTING, _options.speedFilter);
1757 if (_options.heartRateFilter != HEARTRATE_FILTER_DEFAULT)
1758 settings.setValue(HEARTRATE_FILTER_SETTING, _options.heartRateFilter);
1759 if (_options.cadenceFilter != CADENCE_FILTER_DEFAULT)
1760 settings.setValue(CADENCE_FILTER_SETTING, _options.cadenceFilter);
1761 if (_options.powerFilter != POWER_FILTER_DEFAULT)
1762 settings.setValue(POWER_FILTER_SETTING, _options.powerFilter);
1763 if (_options.outlierEliminate != OUTLIER_ELIMINATE_DEFAULT)
1764 settings.setValue(OUTLIER_ELIMINATE_SETTING, _options.outlierEliminate);
1765 if (_options.pauseSpeed != PAUSE_SPEED_DEFAULT)
1766 settings.setValue(PAUSE_SPEED_SETTING, _options.pauseSpeed);
1767 if (_options.pauseInterval != PAUSE_INTERVAL_DEFAULT)
1768 settings.setValue(PAUSE_INTERVAL_SETTING, _options.pauseInterval);
1769 if (_options.useReportedSpeed != USE_REPORTED_SPEED_DEFAULT)
1770 settings.setValue(USE_REPORTED_SPEED_SETTING, _options.useReportedSpeed);
1771 if (_options.dataUseDEM != DATA_USE_DEM_DEFAULT)
1772 settings.setValue(DATA_USE_DEM_SETTING, _options.dataUseDEM);
1773 if (_options.poiRadius != POI_RADIUS_DEFAULT)
1774 settings.setValue(POI_RADIUS_SETTING, _options.poiRadius);
1775 if (_options.poiUseDEM != POI_USE_DEM_DEFAULT)
1776 settings.setValue(POI_USE_DEM_SETTING, _options.poiUseDEM);
1777 if (_options.useOpenGL != USE_OPENGL_DEFAULT)
1778 settings.setValue(USE_OPENGL_SETTING, _options.useOpenGL);
1779 #ifdef ENABLE_HTTP2
1780 if (_options.enableHTTP2 != ENABLE_HTTP2_DEFAULT)
1781 settings.setValue(ENABLE_HTTP2_SETTING, _options.enableHTTP2);
1782 #endif // ENABLE_HTTP2
1783 if (_options.pixmapCache != PIXMAP_CACHE_DEFAULT)
1784 settings.setValue(PIXMAP_CACHE_SETTING, _options.pixmapCache);
1785 if (_options.connectionTimeout != CONNECTION_TIMEOUT_DEFAULT)
1786 settings.setValue(CONNECTION_TIMEOUT_SETTING, _options.connectionTimeout);
1787 if (_options.hiresPrint != HIRES_PRINT_DEFAULT)
1788 settings.setValue(HIRES_PRINT_SETTING, _options.hiresPrint);
1789 if (_options.printName != PRINT_NAME_DEFAULT)
1790 settings.setValue(PRINT_NAME_SETTING, _options.printName);
1791 if (_options.printDate != PRINT_DATE_DEFAULT)
1792 settings.setValue(PRINT_DATE_SETTING, _options.printDate);
1793 if (_options.printDistance != PRINT_DISTANCE_DEFAULT)
1794 settings.setValue(PRINT_DISTANCE_SETTING, _options.printDistance);
1795 if (_options.printTime != PRINT_TIME_DEFAULT)
1796 settings.setValue(PRINT_TIME_SETTING, _options.printTime);
1797 if (_options.printMovingTime != PRINT_MOVING_TIME_DEFAULT)
1798 settings.setValue(PRINT_MOVING_TIME_SETTING, _options.printMovingTime);
1799 if (_options.printItemCount != PRINT_ITEM_COUNT_DEFAULT)
1800 settings.setValue(PRINT_ITEM_COUNT_SETTING, _options.printItemCount);
1801 if (_options.separateGraphPage != SEPARATE_GRAPH_PAGE_DEFAULT)
1802 settings.setValue(SEPARATE_GRAPH_PAGE_SETTING,
1803 _options.separateGraphPage);
1804 if (_options.sliderColor != SLIDER_COLOR_DEFAULT)
1805 settings.setValue(SLIDER_COLOR_SETTING, _options.sliderColor);
1806 if (_options.alwaysShowMap != ALWAYS_SHOW_MAP_DEFAULT)
1807 settings.setValue(ALWAYS_SHOW_MAP_SETTING, _options.alwaysShowMap);
1808 #ifdef ENABLE_HIDPI
1809 if (_options.hidpiMap != HIDPI_MAP_DEFAULT)
1810 settings.setValue(HIDPI_MAP_SETTING, _options.hidpiMap);
1811 #endif // ENABLE_HIDPI
1812 settings.endGroup();
1815 void GUI::readSettings()
1817 int value;
1818 QSettings settings(qApp->applicationName(), qApp->applicationName());
1820 settings.beginGroup(WINDOW_SETTINGS_GROUP);
1821 resize(settings.value(WINDOW_SIZE_SETTING, WINDOW_SIZE_DEFAULT).toSize());
1822 move(settings.value(WINDOW_POS_SETTING, WINDOW_POS_DEFAULT).toPoint());
1823 settings.endGroup();
1825 settings.beginGroup(SETTINGS_SETTINGS_GROUP);
1826 if (settings.value(TIME_TYPE_SETTING, TIME_TYPE_DEFAULT).toInt()
1827 == Moving)
1828 _movingTimeAction->trigger();
1829 else
1830 _totalTimeAction->trigger();
1832 value = settings.value(UNITS_SETTING, UNITS_DEFAULT).toInt();
1833 if (value == Imperial)
1834 _imperialUnitsAction->trigger();
1835 else if (value == Nautical)
1836 _nauticalUnitsAction->trigger();
1837 else
1838 _metricUnitsAction->trigger();
1840 value = settings.value(COORDINATES_SETTING, COORDINATES_DEFAULT).toInt();
1841 if (value == DMS)
1842 _DMSAction->trigger();
1843 else if (value == DegreesMinutes)
1844 _degreesMinutesAction->trigger();
1845 else
1846 _decimalDegreesAction->trigger();
1848 if (!settings.value(SHOW_TOOLBARS_SETTING, SHOW_TOOLBARS_DEFAULT).toBool())
1849 showToolbars(false);
1850 else
1851 _showToolbarsAction->setChecked(true);
1852 settings.endGroup();
1854 settings.beginGroup(MAP_SETTINGS_GROUP);
1855 if (settings.value(SHOW_MAP_SETTING, SHOW_MAP_DEFAULT).toBool())
1856 _showMapAction->setChecked(true);
1857 else
1858 _mapView->showMap(false);
1859 if (_ml->maps().count()) {
1860 int index = mapIndex(settings.value(CURRENT_MAP_SETTING).toString());
1861 _mapActions.at(index)->trigger();
1863 settings.endGroup();
1865 settings.beginGroup(GRAPH_SETTINGS_GROUP);
1866 if (!settings.value(SHOW_GRAPHS_SETTING, SHOW_GRAPHS_DEFAULT).toBool())
1867 showGraphs(false);
1868 else
1869 _showGraphsAction->setChecked(true);
1870 if (settings.value(GRAPH_TYPE_SETTING, GRAPH_TYPE_DEFAULT).toInt()
1871 == Time) {
1872 setTimeGraph();
1873 _timeGraphAction->setChecked(true);
1874 } else
1875 _distanceGraphAction->setChecked(true);
1876 if (!settings.value(SHOW_GRAPH_GRIDS_SETTING, SHOW_GRAPH_GRIDS_DEFAULT)
1877 .toBool())
1878 showGraphGrids(false);
1879 else
1880 _showGraphGridAction->setChecked(true);
1881 if (!settings.value(SHOW_GRAPH_SLIDER_INFO_SETTING,
1882 SHOW_GRAPH_SLIDER_INFO_DEFAULT).toBool())
1883 showGraphSliderInfo(false);
1884 else
1885 _showGraphSliderInfoAction->setChecked(true);
1886 settings.endGroup();
1888 settings.beginGroup(POI_SETTINGS_GROUP);
1889 if (!settings.value(OVERLAP_POI_SETTING, OVERLAP_POI_DEFAULT).toBool())
1890 _mapView->setPOIOverlap(false);
1891 else
1892 _overlapPOIAction->setChecked(true);
1893 if (!settings.value(LABELS_POI_SETTING, LABELS_POI_DEFAULT).toBool())
1894 _mapView->showPOILabels(false);
1895 else
1896 _showPOILabelsAction->setChecked(true);
1897 if (settings.value(SHOW_POI_SETTING, SHOW_POI_DEFAULT).toBool())
1898 _showPOIAction->setChecked(true);
1899 else
1900 _mapView->showPOI(false);
1901 for (int i = 0; i < _poiFilesActions.count(); i++)
1902 _poiFilesActions.at(i)->setChecked(true);
1903 int size = settings.beginReadArray(DISABLED_POI_FILE_SETTINGS_PREFIX);
1904 for (int i = 0; i < size; i++) {
1905 settings.setArrayIndex(i);
1906 int index = _poi->files().indexOf(settings.value(
1907 DISABLED_POI_FILE_SETTING).toString());
1908 if (index >= 0) {
1909 _poi->enableFile(_poi->files().at(index), false);
1910 _poiFilesActions.at(index)->setChecked(false);
1913 settings.endArray();
1914 settings.endGroup();
1916 settings.beginGroup(DATA_SETTINGS_GROUP);
1917 if (!settings.value(SHOW_TRACKS_SETTING, SHOW_TRACKS_DEFAULT).toBool()) {
1918 _mapView->showTracks(false);
1919 for (int i = 0; i < _tabs.count(); i++)
1920 _tabs.at(i)->showTracks(false);
1921 } else
1922 _showTracksAction->setChecked(true);
1923 if (!settings.value(SHOW_ROUTES_SETTING, SHOW_ROUTES_DEFAULT).toBool()) {
1924 _mapView->showRoutes(false);
1925 for (int i = 0; i < _tabs.count(); i++)
1926 _tabs.at(i)->showRoutes(false);
1927 } else
1928 _showRoutesAction->setChecked(true);
1929 if (!settings.value(SHOW_WAYPOINTS_SETTING, SHOW_WAYPOINTS_DEFAULT)
1930 .toBool())
1931 _mapView->showWaypoints(false);
1932 else
1933 _showWaypointsAction->setChecked(true);
1934 if (!settings.value(SHOW_WAYPOINT_LABELS_SETTING,
1935 SHOW_WAYPOINT_LABELS_DEFAULT).toBool())
1936 _mapView->showWaypointLabels(false);
1937 else
1938 _showWaypointLabelsAction->setChecked(true);
1939 if (!settings.value(SHOW_ROUTE_WAYPOINTS_SETTING,
1940 SHOW_ROUTE_WAYPOINTS_SETTING).toBool())
1941 _mapView->showRouteWaypoints(false);
1942 else
1943 _showRouteWaypointsAction->setChecked(true);
1944 settings.endGroup();
1946 settings.beginGroup(EXPORT_SETTINGS_GROUP);
1947 _export.orientation = (QPrinter::Orientation) settings.value(
1948 PAPER_ORIENTATION_SETTING, PAPER_ORIENTATION_DEFAULT).toInt();
1949 _export.resolution = settings.value(RESOLUTION_SETTING, RESOLUTION_DEFAULT)
1950 .toInt();
1951 _export.paperSize = (QPrinter::PaperSize) settings.value(PAPER_SIZE_SETTING,
1952 PAPER_SIZE_DEFAULT).toInt();
1953 qreal ml = settings.value(MARGIN_LEFT_SETTING, MARGIN_LEFT_DEFAULT)
1954 .toReal();
1955 qreal mt = settings.value(MARGIN_TOP_SETTING, MARGIN_TOP_DEFAULT).toReal();
1956 qreal mr = settings.value(MARGIN_RIGHT_SETTING, MARGIN_RIGHT_DEFAULT)
1957 .toReal();
1958 qreal mb = settings.value(MARGIN_BOTTOM_SETTING, MARGIN_BOTTOM_DEFAULT)
1959 .toReal();
1960 _export.margins = MarginsF(ml, mt, mr, mb);
1961 _export.fileName = settings.value(EXPORT_FILENAME_SETTING,
1962 EXPORT_FILENAME_DEFAULT).toString();
1963 settings.endGroup();
1965 settings.beginGroup(OPTIONS_SETTINGS_GROUP);
1966 QColor pc = settings.value(PALETTE_COLOR_SETTING, PALETTE_COLOR_DEFAULT)
1967 .value<QColor>();
1968 qreal ps = settings.value(PALETTE_SHIFT_SETTING, PALETTE_SHIFT_DEFAULT)
1969 .toDouble();
1970 _options.palette = Palette(pc, ps);
1971 _options.mapOpacity = settings.value(MAP_OPACITY_SETTING,
1972 MAP_OPACITY_DEFAULT).toInt();
1973 _options.backgroundColor = settings.value(BACKGROUND_COLOR_SETTING,
1974 BACKGROUND_COLOR_DEFAULT).value<QColor>();
1975 _options.trackWidth = settings.value(TRACK_WIDTH_SETTING,
1976 TRACK_WIDTH_DEFAULT).toInt();
1977 _options.routeWidth = settings.value(ROUTE_WIDTH_SETTING,
1978 ROUTE_WIDTH_DEFAULT).toInt();
1979 _options.trackStyle = (Qt::PenStyle) settings.value(TRACK_STYLE_SETTING,
1980 (int)TRACK_STYLE_DEFAULT).toInt();
1981 _options.routeStyle = (Qt::PenStyle) settings.value(ROUTE_STYLE_SETTING,
1982 (int)ROUTE_STYLE_DEFAULT).toInt();
1983 _options.pathAntiAliasing = settings.value(PATH_AA_SETTING, PATH_AA_DEFAULT)
1984 .toBool();
1985 _options.waypointSize = settings.value(WAYPOINT_SIZE_SETTING,
1986 WAYPOINT_SIZE_DEFAULT).toInt();
1987 _options.waypointColor = settings.value(WAYPOINT_COLOR_SETTING,
1988 WAYPOINT_COLOR_DEFAULT).value<QColor>();
1989 _options.poiSize = settings.value(POI_SIZE_SETTING, POI_SIZE_DEFAULT)
1990 .toInt();
1991 _options.poiColor = settings.value(POI_COLOR_SETTING, POI_COLOR_DEFAULT)
1992 .value<QColor>();
1993 _options.graphWidth = settings.value(GRAPH_WIDTH_SETTING,
1994 GRAPH_WIDTH_DEFAULT).toInt();
1995 _options.graphAntiAliasing = settings.value(GRAPH_AA_SETTING,
1996 GRAPH_AA_DEFAULT).toBool();
1997 _options.elevationFilter = settings.value(ELEVATION_FILTER_SETTING,
1998 ELEVATION_FILTER_DEFAULT).toInt();
1999 _options.speedFilter = settings.value(SPEED_FILTER_SETTING,
2000 SPEED_FILTER_DEFAULT).toInt();
2001 _options.heartRateFilter = settings.value(HEARTRATE_FILTER_SETTING,
2002 HEARTRATE_FILTER_DEFAULT).toInt();
2003 _options.cadenceFilter = settings.value(CADENCE_FILTER_SETTING,
2004 CADENCE_FILTER_DEFAULT).toInt();
2005 _options.powerFilter = settings.value(POWER_FILTER_SETTING,
2006 POWER_FILTER_DEFAULT).toInt();
2007 _options.outlierEliminate = settings.value(OUTLIER_ELIMINATE_SETTING,
2008 OUTLIER_ELIMINATE_DEFAULT).toBool();
2009 _options.pauseSpeed = settings.value(PAUSE_SPEED_SETTING,
2010 PAUSE_SPEED_DEFAULT).toFloat();
2011 _options.useReportedSpeed = settings.value(USE_REPORTED_SPEED_SETTING,
2012 USE_REPORTED_SPEED_DEFAULT).toBool();
2013 _options.dataUseDEM = settings.value(DATA_USE_DEM_SETTING,
2014 DATA_USE_DEM_DEFAULT).toBool();
2015 _options.pauseInterval = settings.value(PAUSE_INTERVAL_SETTING,
2016 PAUSE_INTERVAL_DEFAULT).toInt();
2017 _options.poiRadius = settings.value(POI_RADIUS_SETTING, POI_RADIUS_DEFAULT)
2018 .toInt();
2019 _options.poiUseDEM = settings.value(POI_USE_DEM_SETTING,
2020 POI_USE_DEM_DEFAULT).toBool();
2021 _options.useOpenGL = settings.value(USE_OPENGL_SETTING, USE_OPENGL_DEFAULT)
2022 .toBool();
2023 #ifdef ENABLE_HTTP2
2024 _options.enableHTTP2 = settings.value(ENABLE_HTTP2_SETTING,
2025 ENABLE_HTTP2_DEFAULT).toBool();
2026 #endif // ENABLE_HTTP2
2027 _options.pixmapCache = settings.value(PIXMAP_CACHE_SETTING,
2028 PIXMAP_CACHE_DEFAULT).toInt();
2029 _options.connectionTimeout = settings.value(CONNECTION_TIMEOUT_SETTING,
2030 CONNECTION_TIMEOUT_DEFAULT).toInt();
2031 _options.hiresPrint = settings.value(HIRES_PRINT_SETTING,
2032 HIRES_PRINT_DEFAULT).toBool();
2033 _options.printName = settings.value(PRINT_NAME_SETTING, PRINT_NAME_DEFAULT)
2034 .toBool();
2035 _options.printDate = settings.value(PRINT_DATE_SETTING, PRINT_DATE_DEFAULT)
2036 .toBool();
2037 _options.printDistance = settings.value(PRINT_DISTANCE_SETTING,
2038 PRINT_DISTANCE_DEFAULT).toBool();
2039 _options.printTime = settings.value(PRINT_TIME_SETTING, PRINT_TIME_DEFAULT)
2040 .toBool();
2041 _options.printMovingTime = settings.value(PRINT_MOVING_TIME_SETTING,
2042 PRINT_MOVING_TIME_DEFAULT).toBool();
2043 _options.printItemCount = settings.value(PRINT_ITEM_COUNT_SETTING,
2044 PRINT_ITEM_COUNT_DEFAULT).toBool();
2045 _options.separateGraphPage = settings.value(SEPARATE_GRAPH_PAGE_SETTING,
2046 SEPARATE_GRAPH_PAGE_DEFAULT).toBool();
2047 _options.sliderColor = settings.value(SLIDER_COLOR_SETTING,
2048 SLIDER_COLOR_DEFAULT).value<QColor>();
2049 _options.alwaysShowMap = settings.value(ALWAYS_SHOW_MAP_SETTING,
2050 ALWAYS_SHOW_MAP_DEFAULT).toBool();
2051 #ifdef ENABLE_HIDPI
2052 _options.hidpiMap = settings.value(HIDPI_MAP_SETTING, HIDPI_MAP_SETTING)
2053 .toBool();
2054 #endif // ENABLE_HIDPI
2056 _mapView->setPalette(_options.palette);
2057 _mapView->setMapOpacity(_options.mapOpacity);
2058 _mapView->setBackgroundColor(_options.backgroundColor);
2059 _mapView->setTrackWidth(_options.trackWidth);
2060 _mapView->setRouteWidth(_options.routeWidth);
2061 _mapView->setTrackStyle(_options.trackStyle);
2062 _mapView->setRouteStyle(_options.routeStyle);
2063 _mapView->setWaypointSize(_options.waypointSize);
2064 _mapView->setWaypointColor(_options.waypointColor);
2065 _mapView->setPOISize(_options.poiSize);
2066 _mapView->setPOIColor(_options.poiColor);
2067 _mapView->setRenderHint(QPainter::Antialiasing, _options.pathAntiAliasing);
2068 _mapView->setMarkerColor(_options.sliderColor);
2069 if (_options.useOpenGL)
2070 _mapView->useOpenGL(true);
2071 #ifdef ENABLE_HIDPI
2072 _mapView->setDevicePixelRatio(devicePixelRatioF(),
2073 _options.hidpiMap ? devicePixelRatioF() : 1.0);
2074 #endif // ENABLE_HIDPI
2076 for (int i = 0; i < _tabs.count(); i++) {
2077 _tabs.at(i)->setPalette(_options.palette);
2078 _tabs.at(i)->setGraphWidth(_options.graphWidth);
2079 _tabs.at(i)->setRenderHint(QPainter::Antialiasing,
2080 _options.graphAntiAliasing);
2081 _tabs.at(i)->setSliderColor(_options.sliderColor);
2082 if (_options.useOpenGL)
2083 _tabs.at(i)->useOpenGL(true);
2086 Track::setElevationFilter(_options.elevationFilter);
2087 Track::setSpeedFilter(_options.speedFilter);
2088 Track::setHeartRateFilter(_options.heartRateFilter);
2089 Track::setCadenceFilter(_options.cadenceFilter);
2090 Track::setPowerFilter(_options.powerFilter);
2091 Track::setOutlierElimination(_options.outlierEliminate);
2092 Track::setPauseSpeed(_options.pauseSpeed);
2093 Track::setPauseInterval(_options.pauseInterval);
2094 Track::useReportedSpeed(_options.useReportedSpeed);
2095 Data::useDEM(_options.dataUseDEM);
2097 _poi->setRadius(_options.poiRadius);
2098 _poi->useDEM(_options.poiUseDEM);
2100 QPixmapCache::setCacheLimit(_options.pixmapCache * 1024);
2102 settings.endGroup();
2105 int GUI::mapIndex(const QString &name)
2107 for (int i = 0; i < _ml->maps().count(); i++)
2108 if (_ml->maps().at(i)->name() == name)
2109 return i;
2111 return 0;
2114 Units GUI::units() const
2116 return _imperialUnitsAction->isChecked() ? Imperial
2117 : _nauticalUnitsAction->isChecked() ? Nautical : Metric;
2120 qreal GUI::distance() const
2122 qreal dist = 0;
2124 if (_showTracksAction->isChecked())
2125 dist += _trackDistance;
2126 if (_showRoutesAction->isChecked())
2127 dist += _routeDistance;
2129 return dist;
2132 qreal GUI::time() const
2134 return (_showTracksAction->isChecked()) ? _time : 0;
2137 qreal GUI::movingTime() const
2139 return (_showTracksAction->isChecked()) ? _movingTime : 0;
2142 void GUI::show()
2144 QMainWindow::show();
2146 #ifdef ENABLE_HIDPI
2147 QWindow *w = windowHandle();
2148 connect(w->screen(), SIGNAL(logicalDotsPerInchChanged(qreal)), this,
2149 SLOT(logicalDotsPerInchChanged(qreal)));
2150 connect(w, SIGNAL(screenChanged(QScreen*)), this,
2151 SLOT(screenChanged(QScreen*)));
2152 #endif // ENABLE_HIDPI
2155 void GUI::screenChanged(QScreen *screen)
2157 #ifdef ENABLE_HIDPI
2158 _mapView->setDevicePixelRatio(devicePixelRatioF(),
2159 _options.hidpiMap ? devicePixelRatioF() : 1.0);
2161 disconnect(SIGNAL(logicalDotsPerInchChanged(qreal)), this,
2162 SLOT(logicalDotsPerInchChanged(qreal)));
2163 connect(screen, SIGNAL(logicalDotsPerInchChanged(qreal)), this,
2164 SLOT(logicalDotsPerInchChanged(qreal)));
2165 #else // ENABLE_HIDPI
2166 Q_UNUSED(screen);
2167 #endif // ENABLE_HIDPI
2170 void GUI::logicalDotsPerInchChanged(qreal dpi)
2172 Q_UNUSED(dpi)
2174 #ifdef ENABLE_HIDPI
2175 _mapView->setDevicePixelRatio(devicePixelRatioF(),
2176 _options.hidpiMap ? devicePixelRatioF() : 1.0);
2177 #endif // ENBLE_HIDPI