1 #include <QApplication>
9 #include <QPrintDialog>
11 #include <QPaintEngine>
12 #include <QPaintDevice>
17 #include <QActionGroup>
24 #include <QPixmapCache>
29 #include <QGeoPositionInfoSource>
30 #include "common/config.h"
31 #include "common/programpaths.h"
32 #include "common/downloader.h"
33 #include "data/data.h"
35 #include "data/demloader.h"
36 #include "map/maplist.h"
37 #include "map/emptymap.h"
42 #include "elevationgraph.h"
43 #include "speedgraph.h"
44 #include "heartrategraph.h"
45 #include "temperaturegraph.h"
46 #include "cadencegraph.h"
47 #include "powergraph.h"
48 #include "gearratiograph.h"
50 #include "trackinfo.h"
51 #include "filebrowser.h"
53 #include "graphitem.h"
55 #include "mapaction.h"
56 #include "poiaction.h"
59 #include "common/util.h"
60 #include "navigationwidget.h"
61 #endif // Q_OS_ANDROID
64 #define MAX_RECENT_FILES 10
65 #define TOOLBAR_ICON_SIZE 22
70 QStringList disabledPOIs
, recentFiles
;
73 _dem
= new DEMLoader(ProgramPaths::demDir(true), this);
74 connect(_dem
, &DEMLoader::finished
, this, &GUI::demLoaded
);
85 #endif // Q_OS_ANDROID
88 _splitter
= new QSplitter();
89 _splitter
->setOrientation(Qt::Vertical
);
90 _splitter
->setChildrenCollapsible(false);
91 _splitter
->addWidget(_mapView
);
92 _splitter
->addWidget(_graphTabWidget
);
93 _splitter
->setContentsMargins(0, 0, 0, 0);
94 _splitter
->setStretchFactor(0, 255);
95 _splitter
->setStretchFactor(1, 1);
97 setCentralWidget(_splitter
);
99 setWindowIcon(QIcon(APP_ICON
));
100 setWindowTitle(APP_NAME
);
101 setUnifiedTitleAndToolBarOnMac(true);
102 setAcceptDrops(true);
114 readSettings(activeMap
, disabledPOIs
, recentFiles
);
116 loadInitialMaps(activeMap
);
117 loadInitialPOIs(disabledPOIs
);
119 loadRecentFiles(recentFiles
);
120 #endif // Q_OS_ANDROID
123 updateStatusBarInfo();
126 void GUI::createBrowser()
128 _browser
= new FileBrowser(this);
129 _browser
->setFilter(Data::filter());
130 connect(_browser
, &FileBrowser::listChanged
, this,
131 &GUI::updateNavigationActions
);
134 TreeNode
<MapAction
*> GUI::createMapActionsNode(const TreeNode
<Map
*> &node
)
136 TreeNode
<MapAction
*> tree(node
.name());
138 for (int i
= 0; i
< node
.childs().size(); i
++)
139 tree
.addChild(createMapActionsNode(node
.childs().at(i
)));
141 for (int i
= 0; i
< node
.items().size(); i
++) {
142 Map
*map
= node
.items().at(i
);
143 if (map
->isValid()) {
144 MapAction
*a
= new MapAction(map
, _mapsActionGroup
);
145 connect(a
, &MapAction::loaded
, this, &GUI::mapInitialized
);
154 void GUI::mapInitialized()
156 MapAction
*action
= static_cast<MapAction
*>(QObject::sender());
157 Map
*map
= action
->data().value
<Map
*>();
159 if (map
->isValid()) {
160 if (!_mapsActionGroup
->checkedAction())
162 _showMapAction
->setEnabled(true);
163 _clearMapCacheAction
->setEnabled(true);
165 qWarning("%s: %s", qPrintable(map
->path()), qPrintable(map
->errorString()));
166 action
->deleteLater();
170 TreeNode
<POIAction
*> GUI::createPOIActionsNode(const TreeNode
<QString
> &node
)
172 TreeNode
<POIAction
*> tree(node
.name());
174 for (int i
= 0; i
< node
.childs().size(); i
++)
175 tree
.addChild(createPOIActionsNode(node
.childs().at(i
)));
176 for (int i
= 0; i
< node
.items().size(); i
++)
177 tree
.addItem(new POIAction(node
.items().at(i
), _poisActionGroup
));
182 void GUI::createActions()
187 _fileActionGroup
= new QActionGroup(this);
188 _fileActionGroup
->setExclusive(false);
189 _fileActionGroup
->setEnabled(false);
191 _navigationActionGroup
= new QActionGroup(this);
192 _navigationActionGroup
->setEnabled(false);
195 #if !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID)
196 _exitAction
= new QAction(QIcon::fromTheme(QUIT_NAME
, QIcon(QUIT_ICON
)),
198 _exitAction
->setShortcut(QUIT_SHORTCUT
);
199 _exitAction
->setMenuRole(QAction::QuitRole
);
200 connect(_exitAction
, &QAction::triggered
, this, &GUI::close
);
201 addAction(_exitAction
);
202 #endif // Q_OS_MAC + Q_OS_ANDROID
205 _pathsAction
= new QAction(tr("Paths"), this);
206 _pathsAction
->setMenuRole(QAction::NoRole
);
207 connect(_pathsAction
, &QAction::triggered
, this, &GUI::paths
);
209 _keysAction
= new QAction(tr("Keyboard controls"), this);
210 _keysAction
->setMenuRole(QAction::NoRole
);
211 connect(_keysAction
, &QAction::triggered
, this, &GUI::keys
);
212 #endif // Q_OS_ANDROID
213 _aboutAction
= new QAction(QIcon(APP_ICON
), tr("About GPXSee"), this);
214 _aboutAction
->setMenuRole(QAction::AboutRole
);
215 connect(_aboutAction
, &QAction::triggered
, this, &GUI::about
);
218 _openFileAction
= new QAction(QIcon::fromTheme(OPEN_FILE_NAME
,
219 QIcon(OPEN_FILE_ICON
)), tr("Open..."), this);
220 _openFileAction
->setMenuRole(QAction::NoRole
);
221 _openFileAction
->setShortcut(OPEN_SHORTCUT
);
222 connect(_openFileAction
, &QAction::triggered
, this,
223 QOverload
<>::of(&GUI::openFile
));
224 addAction(_openFileAction
);
225 _openDirAction
= new QAction(QIcon::fromTheme(OPEN_DIR_NAME
,
226 QIcon(OPEN_DIR_ICON
)), tr("Open directory..."), this);
227 _openDirAction
->setMenuRole(QAction::NoRole
);
228 connect(_openDirAction
, &QAction::triggered
, this,
229 QOverload
<>::of(&GUI::openDir
));
230 _printFileAction
= new QAction(QIcon::fromTheme(PRINT_FILE_NAME
,
231 QIcon(PRINT_FILE_ICON
)), tr("Print..."), this);
232 _printFileAction
->setMenuRole(QAction::NoRole
);
233 _printFileAction
->setActionGroup(_fileActionGroup
);
234 connect(_printFileAction
, &QAction::triggered
, this, &GUI::printFile
);
235 addAction(_printFileAction
);
236 _exportPDFFileAction
= new QAction(QIcon::fromTheme(EXPORT_FILE_NAME
,
237 QIcon(EXPORT_FILE_ICON
)), tr("Export to PDF..."), this);
238 _exportPDFFileAction
->setMenuRole(QAction::NoRole
);
239 _exportPDFFileAction
->setShortcut(PDF_EXPORT_SHORTCUT
);
240 _exportPDFFileAction
->setActionGroup(_fileActionGroup
);
241 connect(_exportPDFFileAction
, &QAction::triggered
, this, &GUI::exportPDFFile
);
242 addAction(_exportPDFFileAction
);
243 _exportPNGFileAction
= new QAction(QIcon::fromTheme(EXPORT_FILE_NAME
,
244 QIcon(EXPORT_FILE_ICON
)), tr("Export to PNG..."), this);
245 _exportPNGFileAction
->setMenuRole(QAction::NoRole
);
246 _exportPNGFileAction
->setShortcut(PNG_EXPORT_SHORTCUT
);
247 _exportPNGFileAction
->setActionGroup(_fileActionGroup
);
248 connect(_exportPNGFileAction
, &QAction::triggered
, this, &GUI::exportPNGFile
);
249 addAction(_exportPNGFileAction
);
250 _closeFileAction
= new QAction(QIcon::fromTheme(CLOSE_FILE_NAME
,
251 QIcon(CLOSE_FILE_ICON
)), tr("Close"), this);
252 _closeFileAction
->setMenuRole(QAction::NoRole
);
253 _closeFileAction
->setShortcut(CLOSE_SHORTCUT
);
254 _closeFileAction
->setActionGroup(_fileActionGroup
);
255 connect(_closeFileAction
, &QAction::triggered
, this, &GUI::closeAll
);
256 addAction(_closeFileAction
);
257 _reloadFileAction
= new QAction(QIcon::fromTheme(RELOAD_FILE_NAME
,
258 QIcon(RELOAD_FILE_ICON
)), tr("Reload"), this);
259 _reloadFileAction
->setMenuRole(QAction::NoRole
);
260 _reloadFileAction
->setShortcut(RELOAD_SHORTCUT
);
261 _reloadFileAction
->setActionGroup(_fileActionGroup
);
262 connect(_reloadFileAction
, &QAction::triggered
, this, &GUI::reloadFiles
);
263 addAction(_reloadFileAction
);
264 _statisticsAction
= new QAction(tr("Statistics..."), this);
265 _statisticsAction
->setMenuRole(QAction::NoRole
);
266 _statisticsAction
->setShortcut(STATISTICS_SHORTCUT
);
267 _statisticsAction
->setActionGroup(_fileActionGroup
);
268 connect(_statisticsAction
, &QAction::triggered
, this, &GUI::statistics
);
269 addAction(_statisticsAction
);
271 _recentFilesActionGroup
= new QActionGroup(this);
272 connect(_recentFilesActionGroup
, &QActionGroup::triggered
, this,
273 &GUI::recentFileSelected
);
274 _clearRecentFilesAction
= new QAction(tr("Clear list"), this);
275 _clearRecentFilesAction
->setMenuRole(QAction::NoRole
);
276 connect(_clearRecentFilesAction
, &QAction::triggered
, this,
277 &GUI::clearRecentFiles
);
278 #endif // Q_OS_ANDROID
281 _poisActionGroup
= new QActionGroup(this);
282 _poisActionGroup
->setExclusive(false);
283 connect(_poisActionGroup
, &QActionGroup::triggered
, this,
284 &GUI::poiFileChecked
);
285 _openPOIAction
= new QAction(QIcon::fromTheme(OPEN_FILE_NAME
,
286 QIcon(OPEN_FILE_ICON
)), tr("Load POI file..."), this);
287 _openPOIAction
->setMenuRole(QAction::NoRole
);
288 connect(_openPOIAction
, &QAction::triggered
, this,
289 QOverload
<>::of(&GUI::openPOIFile
));
290 _selectAllPOIAction
= new QAction(tr("Select all files"), this);
291 _selectAllPOIAction
->setMenuRole(QAction::NoRole
);
292 _selectAllPOIAction
->setEnabled(false);
293 connect(_selectAllPOIAction
, &QAction::triggered
, this,
294 &GUI::selectAllPOIs
);
295 _unselectAllPOIAction
= new QAction(tr("Unselect all files"), this);
296 _unselectAllPOIAction
->setMenuRole(QAction::NoRole
);
297 _unselectAllPOIAction
->setEnabled(false);
298 connect(_unselectAllPOIAction
, &QAction::triggered
, this,
299 &GUI::unselectAllPOIs
);
300 _overlapPOIAction
= new QAction(tr("Overlap POIs"), this);
301 _overlapPOIAction
->setMenuRole(QAction::NoRole
);
302 _overlapPOIAction
->setCheckable(true);
303 connect(_overlapPOIAction
, &QAction::triggered
, _mapView
,
304 &MapView::showOverlappedPOIs
);
305 _showPOIIconsAction
= new QAction(tr("Show POI icons"), this);
306 _showPOIIconsAction
->setMenuRole(QAction::NoRole
);
307 _showPOIIconsAction
->setCheckable(true);
308 connect(_showPOIIconsAction
, &QAction::triggered
, _mapView
,
309 &MapView::showPOIIcons
);
310 _showPOILabelsAction
= new QAction(tr("Show POI labels"), this);
311 _showPOILabelsAction
->setMenuRole(QAction::NoRole
);
312 _showPOILabelsAction
->setCheckable(true);
313 connect(_showPOILabelsAction
, &QAction::triggered
, _mapView
,
314 &MapView::showPOILabels
);
315 _showPOIAction
= new QAction(QIcon::fromTheme(SHOW_POI_NAME
,
316 QIcon(SHOW_POI_ICON
)), tr("Show POIs"), this);
317 _showPOIAction
->setMenuRole(QAction::NoRole
);
318 _showPOIAction
->setCheckable(true);
319 _showPOIAction
->setShortcut(SHOW_POI_SHORTCUT
);
320 connect(_showPOIAction
, &QAction::triggered
, _mapView
, &MapView::showPOI
);
321 addAction(_showPOIAction
);
324 _mapsActionGroup
= new QActionGroup(this);
325 _mapsActionGroup
->setExclusive(true);
326 connect(_mapsActionGroup
, &QActionGroup::triggered
, this, &GUI::mapChanged
);
327 _showMapAction
= new QAction(QIcon::fromTheme(SHOW_MAP_NAME
,
328 QIcon(SHOW_MAP_ICON
)), tr("Show map"), this);
329 _showMapAction
->setEnabled(false);
330 _showMapAction
->setMenuRole(QAction::NoRole
);
331 _showMapAction
->setCheckable(true);
332 _showMapAction
->setShortcut(SHOW_MAP_SHORTCUT
);
333 connect(_showMapAction
, &QAction::triggered
, _mapView
,
335 addAction(_showMapAction
);
336 _loadMapAction
= new QAction(QIcon::fromTheme(OPEN_FILE_NAME
,
337 QIcon(OPEN_FILE_ICON
)), tr("Load map..."), this);
338 _loadMapAction
->setMenuRole(QAction::NoRole
);
339 connect(_loadMapAction
, &QAction::triggered
, this,
340 QOverload
<>::of(&GUI::loadMap
));
341 _loadMapDirAction
= new QAction(QIcon::fromTheme(OPEN_DIR_NAME
,
342 QIcon(OPEN_DIR_ICON
)), tr("Load map directory..."), this);
343 _loadMapDirAction
->setMenuRole(QAction::NoRole
);
344 connect(_loadMapDirAction
, &QAction::triggered
, this, &GUI::loadMapDir
);
345 _clearMapCacheAction
= new QAction(tr("Clear tile cache"), this);
346 _clearMapCacheAction
->setEnabled(false);
347 _clearMapCacheAction
->setMenuRole(QAction::NoRole
);
348 connect(_clearMapCacheAction
, &QAction::triggered
, this,
349 &GUI::clearMapCache
);
350 _nextMapAction
= new QAction(tr("Next map"), this);
351 _nextMapAction
->setMenuRole(QAction::NoRole
);
352 _nextMapAction
->setShortcut(NEXT_MAP_SHORTCUT
);
353 connect(_nextMapAction
, &QAction::triggered
, this, &GUI::nextMap
);
354 addAction(_nextMapAction
);
355 _prevMapAction
= new QAction(tr("Next map"), this);
356 _prevMapAction
->setMenuRole(QAction::NoRole
);
357 _prevMapAction
->setShortcut(PREV_MAP_SHORTCUT
);
358 connect(_prevMapAction
, &QAction::triggered
, this, &GUI::prevMap
);
359 addAction(_prevMapAction
);
360 _showCoordinatesAction
= new QAction(tr("Show cursor coordinates"), this);
361 _showCoordinatesAction
->setMenuRole(QAction::NoRole
);
362 _showCoordinatesAction
->setCheckable(true);
363 connect(_showCoordinatesAction
, &QAction::triggered
, _mapView
,
364 &MapView::showCursorCoordinates
);
367 _showPositionAction
= new QAction(QIcon::fromTheme(SHOW_POS_NAME
,
368 QIcon(SHOW_POS_ICON
)), tr("Show position"), this);
369 _showPositionAction
->setMenuRole(QAction::NoRole
);
370 _showPositionAction
->setCheckable(true);
371 _showPositionAction
->setEnabled(false);
372 connect(_showPositionAction
, &QAction::triggered
, _mapView
,
373 &MapView::showPosition
);
374 _followPositionAction
= new QAction(tr("Follow position"), this);
375 _followPositionAction
->setMenuRole(QAction::NoRole
);
376 _followPositionAction
->setCheckable(true);
377 connect(_followPositionAction
, &QAction::triggered
, _mapView
,
378 &MapView::followPosition
);
379 _showPositionCoordinatesAction
= new QAction(tr("Show coordinates"),
381 _showPositionCoordinatesAction
->setMenuRole(QAction::NoRole
);
382 _showPositionCoordinatesAction
->setCheckable(true);
383 connect(_showPositionCoordinatesAction
, &QAction::triggered
, _mapView
,
384 &MapView::showPositionCoordinates
);
385 _showMotionInfoAction
= new QAction(tr("Show motion info"), this);
386 _showMotionInfoAction
->setMenuRole(QAction::NoRole
);
387 _showMotionInfoAction
->setCheckable(true);
388 connect(_showMotionInfoAction
, &QAction::triggered
, _mapView
,
389 &MapView::showMotionInfo
);
392 _showTracksAction
= new QAction(tr("Show tracks"), this);
393 _showTracksAction
->setMenuRole(QAction::NoRole
);
394 _showTracksAction
->setCheckable(true);
395 _showTracksAction
->setShortcut(SHOW_TRACKS_SHORTCUT
);
396 connect(_showTracksAction
, &QAction::triggered
, this, &GUI::showTracks
);
397 _showRoutesAction
= new QAction(tr("Show routes"), this);
398 _showRoutesAction
->setMenuRole(QAction::NoRole
);
399 _showRoutesAction
->setCheckable(true);
400 connect(_showRoutesAction
, &QAction::triggered
, this, &GUI::showRoutes
);
401 _showWaypointsAction
= new QAction(tr("Show waypoints"), this);
402 _showWaypointsAction
->setMenuRole(QAction::NoRole
);
403 _showWaypointsAction
->setCheckable(true);
404 connect(_showWaypointsAction
, &QAction::triggered
, this,
405 &GUI::showWaypoints
);
406 _showAreasAction
= new QAction(tr("Show areas"), this);
407 _showAreasAction
->setMenuRole(QAction::NoRole
);
408 _showAreasAction
->setCheckable(true);
409 connect(_showAreasAction
, &QAction::triggered
, this, &GUI::showAreas
);
410 _showWaypointIconsAction
= new QAction(tr("Waypoint icons"), this);
411 _showWaypointIconsAction
->setMenuRole(QAction::NoRole
);
412 _showWaypointIconsAction
->setCheckable(true);
413 connect(_showWaypointIconsAction
, &QAction::triggered
, _mapView
,
414 &MapView::showWaypointIcons
);
415 _showWaypointLabelsAction
= new QAction(tr("Waypoint labels"), this);
416 _showWaypointLabelsAction
->setMenuRole(QAction::NoRole
);
417 _showWaypointLabelsAction
->setCheckable(true);
418 connect(_showWaypointLabelsAction
, &QAction::triggered
, _mapView
,
419 &MapView::showWaypointLabels
);
420 _showRouteWaypointsAction
= new QAction(tr("Route waypoints"), this);
421 _showRouteWaypointsAction
->setMenuRole(QAction::NoRole
);
422 _showRouteWaypointsAction
->setCheckable(true);
423 connect(_showRouteWaypointsAction
, &QAction::triggered
, _mapView
,
424 &MapView::showRouteWaypoints
);
425 _showTicksAction
= new QAction(tr("km/mi markers"), this);
426 _showTicksAction
->setMenuRole(QAction::NoRole
);
427 _showTicksAction
->setCheckable(true);
428 connect(_showTicksAction
, &QAction::triggered
, _mapView
,
429 &MapView::showTicks
);
430 QActionGroup
*markerInfoGroup
= new QActionGroup(this);
431 connect(markerInfoGroup
, &QActionGroup::triggered
, this,
432 &GUI::showPathMarkerInfo
);
433 _hideMarkersAction
= new QAction(tr("Do not show"), this);
434 _hideMarkersAction
->setMenuRole(QAction::NoRole
);
435 _hideMarkersAction
->setCheckable(true);
436 _hideMarkersAction
->setActionGroup(markerInfoGroup
);
437 _showMarkersAction
= new QAction(tr("Marker only"), this);
438 _showMarkersAction
->setMenuRole(QAction::NoRole
);
439 _showMarkersAction
->setCheckable(true);
440 _showMarkersAction
->setActionGroup(markerInfoGroup
);
441 _showMarkerDateAction
= new QAction(tr("Date/time"), this);
442 _showMarkerDateAction
->setMenuRole(QAction::NoRole
);
443 _showMarkerDateAction
->setCheckable(true);
444 _showMarkerDateAction
->setActionGroup(markerInfoGroup
);
445 _showMarkerCoordinatesAction
= new QAction(tr("Coordinates"), this);
446 _showMarkerCoordinatesAction
->setMenuRole(QAction::NoRole
);
447 _showMarkerCoordinatesAction
->setCheckable(true);
448 _showMarkerCoordinatesAction
->setActionGroup(markerInfoGroup
);
449 _useStylesAction
= new QAction(tr("Use styles"), this);
450 _useStylesAction
->setMenuRole(QAction::NoRole
);
451 _useStylesAction
->setCheckable(true);
452 connect(_useStylesAction
, &QAction::triggered
, _mapView
,
453 &MapView::useStyles
);
456 _downloadDEMAction
= new QAction(tr("Download DEM data"), this);
457 _downloadDEMAction
->setMenuRole(QAction::NoRole
);
458 _downloadDEMAction
->setEnabled(false);
459 _downloadDEMAction
->setShortcut(DOWNLOAD_DEM_SHORTCUT
);
460 connect(_downloadDEMAction
, &QAction::triggered
, this, &GUI::downloadDEM
);
461 _showDEMTilesAction
= new QAction(tr("Show local DEM tiles"), this);
462 _showDEMTilesAction
->setMenuRole(QAction::NoRole
);
463 connect(_showDEMTilesAction
, &QAction::triggered
, this, &GUI::showDEMTiles
);
466 _showGraphsAction
= new QAction(QIcon::fromTheme(SHOW_GRAPHS_NAME
,
467 QIcon(SHOW_GRAPHS_ICON
)), tr("Show graphs"), this);
468 _showGraphsAction
->setMenuRole(QAction::NoRole
);
469 _showGraphsAction
->setCheckable(true);
470 _showGraphsAction
->setShortcut(SHOW_GRAPHS_SHORTCUT
);
471 connect(_showGraphsAction
, &QAction::triggered
, this, &GUI::showGraphs
);
472 addAction(_showGraphsAction
);
473 ag
= new QActionGroup(this);
474 ag
->setExclusive(true);
475 _distanceGraphAction
= new QAction(tr("Distance"), this);
476 _distanceGraphAction
->setMenuRole(QAction::NoRole
);
477 _distanceGraphAction
->setCheckable(true);
478 _distanceGraphAction
->setActionGroup(ag
);
479 connect(_distanceGraphAction
, &QAction::triggered
, this,
480 &GUI::setDistanceGraph
);
481 addAction(_distanceGraphAction
);
482 _timeGraphAction
= new QAction(tr("Time"), this);
483 _timeGraphAction
->setMenuRole(QAction::NoRole
);
484 _timeGraphAction
->setCheckable(true);
485 _timeGraphAction
->setActionGroup(ag
);
486 connect(_timeGraphAction
, &QAction::triggered
, this, &GUI::setTimeGraph
);
487 addAction(_timeGraphAction
);
488 _showGraphGridAction
= new QAction(tr("Show grid"), this);
489 _showGraphGridAction
->setMenuRole(QAction::NoRole
);
490 _showGraphGridAction
->setCheckable(true);
491 connect(_showGraphGridAction
, &QAction::triggered
, this,
492 &GUI::showGraphGrids
);
493 _showGraphSliderInfoAction
= new QAction(tr("Show slider info"), this);
494 _showGraphSliderInfoAction
->setMenuRole(QAction::NoRole
);
495 _showGraphSliderInfoAction
->setCheckable(true);
496 connect(_showGraphSliderInfoAction
, &QAction::triggered
, this,
497 &GUI::showGraphSliderInfo
);
499 _showGraphTabsAction
= new QAction(tr("Show tabs"), this);
500 _showGraphTabsAction
->setMenuRole(QAction::NoRole
);
501 _showGraphTabsAction
->setCheckable(true);
502 connect(_showGraphTabsAction
, &QAction::triggered
, this,
503 &GUI::showGraphTabs
);
504 #endif // Q_OS_ANDROID
508 _showToolbarsAction
= new QAction(tr("Show toolbars"), this);
509 _showToolbarsAction
->setMenuRole(QAction::NoRole
);
510 _showToolbarsAction
->setCheckable(true);
511 connect(_showToolbarsAction
, &QAction::triggered
, this, &GUI::showToolbars
);
512 #endif // Q_OS_ANDROID
513 ag
= new QActionGroup(this);
514 ag
->setExclusive(true);
515 _totalTimeAction
= new QAction(tr("Total time"), this);
516 _totalTimeAction
->setMenuRole(QAction::NoRole
);
517 _totalTimeAction
->setCheckable(true);
518 _totalTimeAction
->setActionGroup(ag
);
519 connect(_totalTimeAction
, &QAction::triggered
, this, &GUI::setTotalTime
);
520 _movingTimeAction
= new QAction(tr("Moving time"), this);
521 _movingTimeAction
->setMenuRole(QAction::NoRole
);
522 _movingTimeAction
->setCheckable(true);
523 _movingTimeAction
->setActionGroup(ag
);
524 connect(_movingTimeAction
, &QAction::triggered
, this, &GUI::setMovingTime
);
525 ag
= new QActionGroup(this);
526 ag
->setExclusive(true);
527 _metricUnitsAction
= new QAction(tr("Metric"), this);
528 _metricUnitsAction
->setMenuRole(QAction::NoRole
);
529 _metricUnitsAction
->setCheckable(true);
530 _metricUnitsAction
->setActionGroup(ag
);
531 connect(_metricUnitsAction
, &QAction::triggered
, this, &GUI::setMetricUnits
);
532 _imperialUnitsAction
= new QAction(tr("Imperial"), this);
533 _imperialUnitsAction
->setMenuRole(QAction::NoRole
);
534 _imperialUnitsAction
->setCheckable(true);
535 _imperialUnitsAction
->setActionGroup(ag
);
536 connect(_imperialUnitsAction
, &QAction::triggered
, this,
537 &GUI::setImperialUnits
);
538 _nauticalUnitsAction
= new QAction(tr("Nautical"), this);
539 _nauticalUnitsAction
->setMenuRole(QAction::NoRole
);
540 _nauticalUnitsAction
->setCheckable(true);
541 _nauticalUnitsAction
->setActionGroup(ag
);
542 connect(_nauticalUnitsAction
, &QAction::triggered
, this,
543 &GUI::setNauticalUnits
);
544 ag
= new QActionGroup(this);
545 ag
->setExclusive(true);
546 _decimalDegreesAction
= new QAction(tr("Decimal degrees (DD)"), this);
547 _decimalDegreesAction
->setMenuRole(QAction::NoRole
);
548 _decimalDegreesAction
->setCheckable(true);
549 _decimalDegreesAction
->setActionGroup(ag
);
550 connect(_decimalDegreesAction
, &QAction::triggered
, this,
551 &GUI::setDecimalDegrees
);
552 _degreesMinutesAction
= new QAction(tr("Degrees and decimal minutes (DMM)"),
554 _degreesMinutesAction
->setMenuRole(QAction::NoRole
);
555 _degreesMinutesAction
->setCheckable(true);
556 _degreesMinutesAction
->setActionGroup(ag
);
557 connect(_degreesMinutesAction
, &QAction::triggered
, this,
558 &GUI::setDegreesMinutes
);
559 _dmsAction
= new QAction(tr("Degrees, minutes, seconds (DMS)"), this);
560 _dmsAction
->setMenuRole(QAction::NoRole
);
561 _dmsAction
->setCheckable(true);
562 _dmsAction
->setActionGroup(ag
);
563 connect(_dmsAction
, &QAction::triggered
, this, &GUI::setDMS
);
565 _fullscreenAction
= new QAction(QIcon::fromTheme(FULLSCREEN_NAME
,
566 QIcon(FULLSCREEN_ICON
)), tr("Fullscreen mode"), this);
567 _fullscreenAction
->setMenuRole(QAction::NoRole
);
568 _fullscreenAction
->setCheckable(true);
569 _fullscreenAction
->setShortcut(FULLSCREEN_SHORTCUT
);
570 connect(_fullscreenAction
, &QAction::triggered
, this, &GUI::showFullscreen
);
571 addAction(_fullscreenAction
);
572 #endif // Q_OS_ANDROID
573 _openOptionsAction
= new QAction(tr("Options..."), this);
574 _openOptionsAction
->setMenuRole(QAction::PreferencesRole
);
575 connect(_openOptionsAction
, &QAction::triggered
, this, &GUI::openOptions
);
577 // Navigation actions
579 _nextAction
= new QAction(QIcon::fromTheme(NEXT_FILE_NAME
,
580 QIcon(NEXT_FILE_ICON
)), tr("Next"), this);
581 _nextAction
->setActionGroup(_navigationActionGroup
);
582 _nextAction
->setMenuRole(QAction::NoRole
);
583 connect(_nextAction
, &QAction::triggered
, this, &GUI::next
);
584 _prevAction
= new QAction(QIcon::fromTheme(PREV_FILE_NAME
,
585 QIcon(PREV_FILE_ICON
)), tr("Previous"), this);
586 _prevAction
->setMenuRole(QAction::NoRole
);
587 _prevAction
->setActionGroup(_navigationActionGroup
);
588 connect(_prevAction
, &QAction::triggered
, this, &GUI::prev
);
589 _lastAction
= new QAction(QIcon::fromTheme(LAST_FILE_NAME
,
590 QIcon(LAST_FILE_ICON
)), tr("Last"), this);
591 _lastAction
->setMenuRole(QAction::NoRole
);
592 _lastAction
->setActionGroup(_navigationActionGroup
);
593 connect(_lastAction
, &QAction::triggered
, this, &GUI::last
);
594 _firstAction
= new QAction(QIcon::fromTheme(FIRST_FILE_NAME
,
595 QIcon(FIRST_FILE_ICON
)), tr("First"), this);
596 _firstAction
->setMenuRole(QAction::NoRole
);
597 _firstAction
->setActionGroup(_navigationActionGroup
);
598 connect(_firstAction
, &QAction::triggered
, this, &GUI::first
);
599 #endif // Q_OS_ANDROID
602 void GUI::createMapNodeMenu(const TreeNode
<MapAction
*> &node
, QMenu
*menu
,
605 for (int i
= 0; i
< node
.childs().size(); i
++) {
606 QMenu
*cm
= new QMenu(node
.childs().at(i
).name(), menu
);
607 menu
->insertMenu(action
, cm
);
608 createMapNodeMenu(node
.childs().at(i
), cm
);
611 for (int i
= 0; i
< node
.items().size(); i
++)
612 menu
->insertAction(action
, node
.items().at(i
));
615 void GUI::createPOINodeMenu(const TreeNode
<POIAction
*> &node
, QMenu
*menu
,
618 for (int i
= 0; i
< node
.childs().size(); i
++) {
619 QMenu
*cm
= new QMenu(node
.childs().at(i
).name(), menu
);
620 menu
->insertMenu(action
, cm
);
621 createPOINodeMenu(node
.childs().at(i
), cm
);
624 for (int i
= 0; i
< node
.items().size(); i
++)
625 menu
->insertAction(action
, node
.items().at(i
));
628 void GUI::createMenus()
630 QMenu
*fileMenu
= menuBar()->addMenu(tr("&File"));
631 fileMenu
->addAction(_openFileAction
);
633 _recentFilesMenu
= fileMenu
->addMenu(tr("Open recent"));
634 _recentFilesMenu
->setIcon(QIcon::fromTheme(OPEN_RECENT_NAME
,
635 QIcon(OPEN_RECENT_ICON
)));
636 _recentFilesMenu
->menuAction()->setMenuRole(QAction::NoRole
);
637 _recentFilesMenu
->setEnabled(false);
638 _recentFilesEnd
= _recentFilesMenu
->addSeparator();
639 _recentFilesMenu
->addAction(_clearRecentFilesAction
);
640 #endif // Q_OS_ANDROID
641 fileMenu
->addAction(_openDirAction
);
642 fileMenu
->addSeparator();
644 fileMenu
->addAction(_printFileAction
);
645 #endif // Q_OS_ANDROID
646 fileMenu
->addAction(_exportPDFFileAction
);
647 fileMenu
->addAction(_exportPNGFileAction
);
648 fileMenu
->addSeparator();
649 fileMenu
->addAction(_statisticsAction
);
650 fileMenu
->addSeparator();
651 fileMenu
->addAction(_reloadFileAction
);
652 fileMenu
->addAction(_closeFileAction
);
653 #if !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID)
654 fileMenu
->addSeparator();
655 fileMenu
->addAction(_exitAction
);
656 #endif // Q_OS_MAC + Q_OS_ANDROID
658 _mapMenu
= menuBar()->addMenu(tr("&Map"));
659 _mapsEnd
= _mapMenu
->addSeparator();
660 _mapMenu
->addAction(_loadMapAction
);
661 _mapMenu
->addAction(_loadMapDirAction
);
662 _mapMenu
->addAction(_clearMapCacheAction
);
663 _mapMenu
->addSeparator();
664 _mapMenu
->addAction(_showCoordinatesAction
);
665 _mapMenu
->addSeparator();
666 _mapMenu
->addAction(_showMapAction
);
668 QMenu
*graphMenu
= menuBar()->addMenu(tr("&Graph"));
669 graphMenu
->addAction(_distanceGraphAction
);
670 graphMenu
->addAction(_timeGraphAction
);
671 graphMenu
->addSeparator();
672 graphMenu
->addAction(_showGraphGridAction
);
673 graphMenu
->addAction(_showGraphSliderInfoAction
);
675 graphMenu
->addAction(_showGraphTabsAction
);
676 #endif // Q_OS_ANDROID
677 graphMenu
->addSeparator();
678 graphMenu
->addAction(_showGraphsAction
);
680 QMenu
*dataMenu
= menuBar()->addMenu(tr("&Data"));
681 dataMenu
->addAction(_showWaypointIconsAction
);
682 dataMenu
->addAction(_showWaypointLabelsAction
);
683 dataMenu
->addAction(_showRouteWaypointsAction
);
684 dataMenu
->addAction(_showTicksAction
);
685 QMenu
*markerMenu
= dataMenu
->addMenu(tr("Position info"));
686 markerMenu
->menuAction()->setMenuRole(QAction::NoRole
);
687 markerMenu
->addAction(_hideMarkersAction
);
688 markerMenu
->addAction(_showMarkersAction
);
689 markerMenu
->addAction(_showMarkerDateAction
);
690 markerMenu
->addAction(_showMarkerCoordinatesAction
);
691 dataMenu
->addSeparator();
692 dataMenu
->addAction(_useStylesAction
);
693 dataMenu
->addSeparator();
694 dataMenu
->addAction(_showTracksAction
);
695 dataMenu
->addAction(_showRoutesAction
);
696 dataMenu
->addAction(_showAreasAction
);
697 dataMenu
->addAction(_showWaypointsAction
);
699 _poiMenu
= menuBar()->addMenu(tr("&POI"));
700 _poisEnd
= _poiMenu
->addSeparator();
701 _poiMenu
->addAction(_openPOIAction
);
702 _poiMenu
->addAction(_selectAllPOIAction
);
703 _poiMenu
->addAction(_unselectAllPOIAction
);
704 _poiMenu
->addSeparator();
705 _poiMenu
->addAction(_showPOIIconsAction
);
706 _poiMenu
->addAction(_showPOILabelsAction
);
707 _poiMenu
->addAction(_overlapPOIAction
);
708 _poiMenu
->addSeparator();
709 _poiMenu
->addAction(_showPOIAction
);
711 QMenu
*demMenu
= menuBar()->addMenu(tr("DEM"));
712 demMenu
->addAction(_showDEMTilesAction
);
713 demMenu
->addAction(_downloadDEMAction
);
715 QMenu
*positionMenu
= menuBar()->addMenu(tr("Position"));
716 positionMenu
->addAction(_showPositionCoordinatesAction
);
717 positionMenu
->addAction(_showMotionInfoAction
);
718 positionMenu
->addAction(_followPositionAction
);
719 positionMenu
->addSeparator();
720 positionMenu
->addAction(_showPositionAction
);
722 QMenu
*settingsMenu
= menuBar()->addMenu(tr("&Settings"));
723 QMenu
*timeMenu
= settingsMenu
->addMenu(tr("Time"));
724 timeMenu
->menuAction()->setMenuRole(QAction::NoRole
);
725 timeMenu
->addAction(_totalTimeAction
);
726 timeMenu
->addAction(_movingTimeAction
);
727 QMenu
*unitsMenu
= settingsMenu
->addMenu(tr("Units"));
728 unitsMenu
->menuAction()->setMenuRole(QAction::NoRole
);
729 unitsMenu
->addAction(_metricUnitsAction
);
730 unitsMenu
->addAction(_imperialUnitsAction
);
731 unitsMenu
->addAction(_nauticalUnitsAction
);
732 QMenu
*coordinatesMenu
= settingsMenu
->addMenu(tr("Coordinates format"));
733 coordinatesMenu
->menuAction()->setMenuRole(QAction::NoRole
);
734 coordinatesMenu
->addAction(_decimalDegreesAction
);
735 coordinatesMenu
->addAction(_degreesMinutesAction
);
736 coordinatesMenu
->addAction(_dmsAction
);
737 settingsMenu
->addSeparator();
739 settingsMenu
->addAction(_showToolbarsAction
);
740 settingsMenu
->addAction(_fullscreenAction
);
741 settingsMenu
->addSeparator();
742 #endif // Q_OS_ANDROID
743 settingsMenu
->addAction(_openOptionsAction
);
745 QMenu
*helpMenu
= menuBar()->addMenu(tr("&Help"));
746 helpMenu
->addAction(_pathsAction
);
748 helpMenu
->addAction(_keysAction
);
749 #endif // Q_OS_ANDROID
750 helpMenu
->addSeparator();
751 helpMenu
->addAction(_aboutAction
);
755 void GUI::createNavigation()
757 _navigation
= new NavigationWidget(_mapView
);
759 connect(_navigation
, &NavigationWidget::next
, this, &GUI::next
);
760 connect(_navigation
, &NavigationWidget::prev
, this, &GUI::prev
);
762 #else // Q_OS_ANDROID
763 void GUI::createToolBars()
765 int is
= style()->pixelMetric(QStyle::PM_ToolBarIconSize
);
766 QSize
iconSize(qMin(is
, TOOLBAR_ICON_SIZE
), qMin(is
, TOOLBAR_ICON_SIZE
));
769 setToolButtonStyle(Qt::ToolButtonTextUnderIcon
);
772 _fileToolBar
= addToolBar(tr("File"));
773 _fileToolBar
->setObjectName("File");
774 _fileToolBar
->setIconSize(iconSize
);
775 _fileToolBar
->addAction(_openFileAction
);
776 _fileToolBar
->addAction(_reloadFileAction
);
777 _fileToolBar
->addAction(_closeFileAction
);
779 _fileToolBar
->addAction(_printFileAction
);
782 _showToolBar
= addToolBar(tr("Show"));
783 _showToolBar
->setObjectName("Show");
784 _showToolBar
->setIconSize(iconSize
);
785 _showToolBar
->addAction(_showPOIAction
);
786 _showToolBar
->addAction(_showMapAction
);
787 _showToolBar
->addAction(_showGraphsAction
);
788 _showToolBar
->addAction(_showPositionAction
);
790 _navigationToolBar
= addToolBar(tr("Navigation"));
791 _navigationToolBar
->setObjectName("Navigation");
792 _navigationToolBar
->setIconSize(iconSize
);
793 _navigationToolBar
->addAction(_firstAction
);
794 _navigationToolBar
->addAction(_prevAction
);
795 _navigationToolBar
->addAction(_nextAction
);
796 _navigationToolBar
->addAction(_lastAction
);
798 #endif // Q_OS_ANDROID
800 void GUI::createMapView()
802 _map
= new EmptyMap(this);
803 _mapView
= new MapView(_map
, _poi
, this);
804 _mapView
->setSizePolicy(QSizePolicy(QSizePolicy::Ignored
,
805 QSizePolicy::Expanding
));
807 _mapView
->setMinimumHeight(100);
808 #else // Q_OS_ANDROID
809 _mapView
->setMinimumHeight(200);
810 #endif // Q_OS_ANDROID
812 _mapView
->setFrameShape(QFrame::NoFrame
);
816 void GUI::createGraphTabs()
818 _graphTabWidget
= new QTabWidget();
819 _graphTabWidget
->setSizePolicy(QSizePolicy(QSizePolicy::Ignored
,
820 QSizePolicy::Preferred
));
821 _graphTabWidget
->setMinimumHeight(200);
823 _graphTabWidget
->setDocumentMode(true);
826 connect(_graphTabWidget
, &QTabWidget::currentChanged
, this,
829 _tabs
.append(new ElevationGraph(_graphTabWidget
));
830 _tabs
.append(new SpeedGraph(_graphTabWidget
));
831 _tabs
.append(new HeartRateGraph(_graphTabWidget
));
832 _tabs
.append(new CadenceGraph(_graphTabWidget
));
833 _tabs
.append(new PowerGraph(_graphTabWidget
));
834 _tabs
.append(new TemperatureGraph(_graphTabWidget
));
835 _tabs
.append(new GearRatioGraph(_graphTabWidget
));
837 for (int i
= 0; i
< _tabs
.size(); i
++)
838 connect(_tabs
.at(i
), &GraphTab::sliderPositionChanged
, _mapView
,
839 &MapView::setMarkerPosition
);
842 void GUI::createStatusBar()
844 _fileNameLabel
= new QLabel();
845 _distanceLabel
= new QLabel();
846 _timeLabel
= new QLabel();
847 _distanceLabel
->setAlignment(Qt::AlignHCenter
);
848 _timeLabel
->setAlignment(Qt::AlignHCenter
);
850 statusBar()->addPermanentWidget(_fileNameLabel
, 8);
851 statusBar()->addPermanentWidget(_distanceLabel
, 1);
852 statusBar()->addPermanentWidget(_timeLabel
, 1);
853 statusBar()->setSizeGripEnabled(false);
858 QMessageBox
msgBox(this);
859 QUrl
homepage(APP_HOMEPAGE
);
861 msgBox
.setWindowTitle(tr("About GPXSee"));
863 msgBox
.setText("<h2>" + QString(APP_NAME
) + "</h2><p>" + tr("Version %1")
864 .arg(QString(APP_VERSION
) + " (" + QSysInfo::buildCpuArchitecture()
865 + ", Qt " + QT_VERSION_STR
+ ")") + "</p><p>"
866 + tr("GPXSee is distributed under the terms of the GNU General Public "
867 "License version 3. For more info about GPXSee visit the project "
868 "homepage at %1.").arg("<a href=\"" + homepage
.toString() + "\">"
869 + homepage
.toString(QUrl::RemoveScheme
).mid(2) + "</a>") + "</p>");
870 #else // Q_OS_ANDROID
871 msgBox
.setText("<h2>" + QString(APP_NAME
) + "</h2><p>" + tr("Version %1")
872 .arg(QString(APP_VERSION
) + " (" + QSysInfo::buildCpuArchitecture()
873 + ", Qt " + QT_VERSION_STR
+ ")") + "</p>");
874 msgBox
.setInformativeText("<table width=\"300\"><tr><td>"
875 + tr("GPXSee is distributed under the terms of the GNU General Public "
876 "License version 3. For more info about GPXSee visit the project "
877 "homepage at %1.").arg("<a href=\"" + homepage
.toString() + "\">"
878 + homepage
.toString(QUrl::RemoveScheme
).mid(2) + "</a>")
879 + "</td></tr></table>");
881 QIcon icon
= msgBox
.windowIcon();
882 QSize size
= icon
.actualSize(QSize(64, 64));
883 msgBox
.setIconPixmap(icon
.pixmap(size
));
884 #endif // Q_OS_ANDROID
892 QMessageBox
msgBox(this);
894 msgBox
.setWindowTitle(tr("Keyboard controls"));
895 msgBox
.setText("<h3>" + tr("Keyboard controls") + "</h3>");
896 msgBox
.setInformativeText(
897 "<style>td {padding-right: 1.5em;}</style><div><table><tr><td>"
898 + tr("Next file") + "</td><td><i>" + QKeySequence(NEXT_KEY
).toString()
899 + "</i></td></tr><tr><td>" + tr("Previous file")
900 + "</td><td><i>" + QKeySequence(PREV_KEY
).toString()
901 + "</i></td></tr><tr><td>" + tr("First file") + "</td><td><i>"
902 + QKeySequence(FIRST_KEY
).toString() + "</i></td></tr><tr><td>"
903 + tr("Last file") + "</td><td><i>" + QKeySequence(LAST_KEY
).toString()
904 + "</i></td></tr><tr><td>" + tr("Append file")
905 + "</td><td><i>" + QKeySequence(MODIFIER
).toString() + tr("Next/Previous")
906 + "</i></td></tr><tr><td></td><td></td></tr><tr><td>"
907 + tr("Toggle graph type") + "</td><td><i>"
908 + QKeySequence(TOGGLE_GRAPH_TYPE_KEY
).toString() + "</i></td></tr><tr><td>"
909 + tr("Toggle time type") + "</td><td><i>"
910 + QKeySequence(TOGGLE_TIME_TYPE_KEY
).toString() + "</i></td></tr><tr><td>"
911 + tr("Toggle position info") + "</td><td><i>"
912 + QKeySequence(TOGGLE_MARKER_INFO_KEY
).toString() + "</i></td></tr>"
913 + "<tr><td></td><td></td></tr><tr><td>" + tr("Next map")
914 + "</td><td><i>" + NEXT_MAP_SHORTCUT
.toString() + "</i></td></tr><tr><td>"
915 + tr("Previous map") + "</td><td><i>" + PREV_MAP_SHORTCUT
.toString()
916 + "</i></td></tr><tr><td></td><td></td></tr><tr><td>" + tr("Zoom in")
917 + "</td><td><i>" + QKeySequence(ZOOM_IN
).toString()
918 + "</i></td></tr><tr><td>" + tr("Zoom out") + "</td><td><i>"
919 + QKeySequence(ZOOM_OUT
).toString() + "</i></td></tr><tr><td>"
920 + tr("Digital zoom") + "</td><td><i>" + QKeySequence(MODIFIER
).toString()
921 + tr("Zoom") + "</i></td></tr><tr><td></td><td></td></tr><tr><td>"
922 + tr("Copy coordinates") + "</td><td><i>"
923 + QKeySequence(MODIFIER
).toString() + tr("Left Click")
924 + "</i></td></tr></table></div>");
928 #endif // Q_OS_ANDROID
932 QMessageBox
msgBox(this);
934 msgBox
.setWindowTitle(tr("Paths"));
937 + "<small><b>" + tr("Map directory:") + "</b><br>"
938 + QDir::cleanPath(ProgramPaths::mapDir(true)) + "<br><br><b>"
939 + tr("POI directory:") + "</b><br>"
940 + QDir::cleanPath(ProgramPaths::poiDir(true)) + "<br><br><b>"
941 + tr("CRS directory:") + "</b><br>"
942 + QDir::cleanPath(ProgramPaths::crsDir(true)) + "<br><br><b>"
943 + tr("DEM directory:") + "</b><br>"
944 + QDir::cleanPath(ProgramPaths::demDir(true)) + "<br><br><b>"
945 + tr("Styles directory:") + "</b><br>"
946 + QDir::cleanPath(ProgramPaths::styleDir(true)) + "<br><br><b>"
947 + tr("Symbols directory:") + "</b><br>"
948 + QDir::cleanPath(ProgramPaths::symbolsDir(true)) + "<br><br><b>"
949 + tr("Tile cache directory:") + "</b><br>"
950 + QDir::cleanPath(ProgramPaths::tilesDir()) + "</small>");
951 #else // Q_OS_ANDROID
952 msgBox
.setText("<h3>" + tr("Paths") + "</h3>");
953 msgBox
.setInformativeText(
954 "<style>td {white-space: pre; padding-right: 1em;}</style><table><tr><td>"
955 + tr("Map directory:") + "</td><td><code>"
956 + QDir::cleanPath(ProgramPaths::mapDir(true)) + "</code></td></tr><tr><td>"
957 + tr("POI directory:") + "</td><td><code>"
958 + QDir::cleanPath(ProgramPaths::poiDir(true)) + "</code></td></tr><tr><td>"
959 + tr("CRS directory:") + "</td><td><code>"
960 + QDir::cleanPath(ProgramPaths::crsDir(true)) + "</code></td></tr><tr><td>"
961 + tr("DEM directory:") + "</td><td><code>"
962 + QDir::cleanPath(ProgramPaths::demDir(true)) + "</code></td></tr><tr><td>"
963 + tr("Styles directory:") + "</td><td><code>"
964 + QDir::cleanPath(ProgramPaths::styleDir(true)) + "</code></td></tr><tr><td>"
965 + tr("Symbols directory:") + "</td><td><code>"
966 + QDir::cleanPath(ProgramPaths::symbolsDir(true)) + "</code></td></tr><tr><td>"
967 + tr("Tile cache directory:") + "</td><td><code>"
968 + QDir::cleanPath(ProgramPaths::tilesDir()) + "</code></td></tr></table>"
970 #endif // Q_OS_ANDROID
978 QStringList
files(QFileDialog::getOpenFileNames(this, tr("Open file"),
980 #else // Q_OS_ANDROID
981 QStringList
files(QFileDialog::getOpenFileNames(this, tr("Open file"),
982 _dataDir
, Data::formats()));
983 #endif // Q_OS_ANDROID
984 int showError
= (files
.size() > 1) ? 2 : 1;
986 for (int i
= 0; i
< files
.size(); i
++)
987 openFile(files
.at(i
), true, showError
);
988 if (!files
.isEmpty())
989 _dataDir
= QFileInfo(files
.last()).path();
993 void GUI::openDir(const QString
&path
, int &showError
)
996 md
.setFilter(QDir::Files
| QDir::Dirs
| QDir::NoDotAndDotDot
);
997 md
.setSorting(QDir::DirsLast
);
998 QFileInfoList ml
= md
.entryInfoList();
1000 for (int i
= 0; i
< ml
.size(); i
++) {
1001 const QFileInfo
&fi
= ml
.at(i
);
1004 openDir(fi
.absoluteFilePath(), showError
);
1006 openFile(fi
.absoluteFilePath(), true, showError
);
1009 #endif // Q_OS_ANDROID
1013 QString
dir(QFileDialog::getExistingDirectory(this, tr("Open directory"),
1016 if (!dir
.isEmpty()) {
1019 _browser
->setCurrentDir(dir
);
1020 openFile(_browser
->current(), true, showError
);
1021 #else // Q_OS_ANDROID
1023 openDir(dir
, showError
);
1025 #endif // Q_OS_ANDROID
1029 bool GUI::openFile(const QString
&fileName
, bool tryUnknown
, int &showError
)
1031 QFileInfo
fi(fileName
);
1032 QString
canonicalFileName(fi
.canonicalFilePath());
1034 if (_files
.contains(canonicalFileName
))
1037 if (!loadFile(fileName
, tryUnknown
, showError
))
1040 _files
.append(canonicalFileName
);
1041 #ifndef Q_OS_ANDROID
1042 _browser
->setCurrent(fileName
);
1043 #endif // Q_OS_ANDROID
1044 _fileActionGroup
->setEnabled(true);
1045 // Explicitly enable the reload action as it may be disabled by loadMapDir()
1046 _reloadFileAction
->setEnabled(true);
1047 _navigationActionGroup
->setEnabled(true);
1049 updateNavigationActions();
1050 updateStatusBarInfo();
1051 updateWindowTitle();
1052 #ifndef Q_OS_ANDROID
1053 updateRecentFiles(canonicalFileName
);
1054 #endif // Q_OS_ANDROID
1059 bool GUI::loadFile(const QString
&fileName
, bool tryUnknown
, int &showError
)
1061 Data
data(fileName
, tryUnknown
);
1063 if (data
.isValid()) {
1067 updateNavigationActions();
1068 updateStatusBarInfo();
1069 updateWindowTitle();
1071 updateDEMDownloadAction();
1072 if (_files
.isEmpty())
1073 _fileActionGroup
->setEnabled(false);
1076 QString error
= tr("Error loading data file:") + "\n"
1077 + Util::displayName(fileName
) + ": " + data
.errorString();
1078 if (data
.errorLine())
1079 error
.append("\n" + tr("Line: %1").arg(data
.errorLine()));
1081 if (showError
> 1) {
1082 QMessageBox
message(QMessageBox::Critical
, APP_NAME
, error
,
1083 QMessageBox::Ok
, this);
1084 QCheckBox
checkBox(tr("Don't show again"));
1085 message
.setCheckBox(&checkBox
);
1087 if (checkBox
.isChecked())
1090 QMessageBox::critical(this, APP_NAME
, error
);
1097 void GUI::loadData(const Data
&data
)
1099 QList
<QList
<GraphItem
*> > graphs
;
1100 QList
<PathItem
*> paths
;
1102 for (int i
= 0; i
< data
.tracks().count(); i
++) {
1103 const Track
&track
= data
.tracks().at(i
);
1104 _trackDistance
+= track
.distance();
1105 _time
+= track
.time();
1106 _movingTime
+= track
.movingTime();
1107 const QDateTime date
= track
.date().toTimeZone(_options
.timeZone
.zone());
1108 if (_dateRange
.first
.isNull() || _dateRange
.first
> date
)
1109 _dateRange
.first
= date
;
1110 if (_dateRange
.second
.isNull() || _dateRange
.second
< date
)
1111 _dateRange
.second
= date
;
1113 _trackCount
+= data
.tracks().count();
1115 for (int i
= 0; i
< data
.routes().count(); i
++)
1116 _routeDistance
+= data
.routes().at(i
).distance();
1117 _routeCount
+= data
.routes().count();
1119 _waypointCount
+= data
.waypoints().count();
1120 _areaCount
+= data
.areas().count();
1122 if (_pathName
.isNull()) {
1123 if (data
.tracks().count() == 1 && !data
.routes().count())
1124 _pathName
= data
.tracks().first().name();
1125 else if (data
.routes().count() == 1 && !data
.tracks().count())
1126 _pathName
= data
.routes().first().name();
1128 _pathName
= QString();
1130 for (int i
= 0; i
< _tabs
.count(); i
++)
1131 graphs
.append(_tabs
.at(i
)->loadData(data
));
1132 if (updateGraphTabs())
1133 _splitter
->refresh();
1134 paths
= _mapView
->loadData(data
);
1136 GraphTab
*gt
= static_cast<GraphTab
*>(_graphTabWidget
->currentWidget());
1138 for (int i
= 0; i
< paths
.count(); i
++) {
1139 PathItem
*pi
= paths
.at(i
);
1143 for (int j
= 0; j
< graphs
.count(); j
++)
1144 pi
->addGraph(graphs
.at(j
).at(i
));
1147 pi
->setGraph(_tabs
.indexOf(gt
));
1148 pi
->setMarkerPosition(gt
->sliderPosition());
1152 updateDEMDownloadAction();
1155 void GUI::openPOIFile()
1158 QStringList
files(QFileDialog::getOpenFileNames(this, tr("Open POI file"),
1160 #else // Q_OS_ANDROID
1161 QStringList
files(QFileDialog::getOpenFileNames(this, tr("Open POI file"),
1162 _poiDir
, Data::formats()));
1163 #endif // Q_OS_ANDROID
1165 for (int i
= 0; i
< files
.size(); i
++)
1166 openPOIFile(files
.at(i
));
1167 if (!files
.isEmpty())
1168 _poiDir
= QFileInfo(files
.last()).path();
1171 bool GUI::openPOIFile(const QString
&fileName
)
1173 if (_poi
->isLoaded(fileName
))
1176 if (_poi
->loadFile(fileName
)) {
1177 _mapView
->showPOI(true);
1178 _showPOIAction
->setChecked(true);
1179 QAction
*action
= new POIAction(fileName
, _poisActionGroup
);
1180 action
->setChecked(true);
1181 _poiMenu
->insertAction(_poisEnd
, action
);
1183 _selectAllPOIAction
->setEnabled(true);
1184 _unselectAllPOIAction
->setEnabled(true);
1188 QString error
= tr("Error loading POI file:") + "\n"
1189 + Util::displayName(fileName
) + ": " + _poi
->errorString();
1190 if (_poi
->errorLine())
1191 error
.append("\n" + tr("Line: %1").arg(_poi
->errorLine()));
1192 QMessageBox::critical(this, APP_NAME
, error
);
1198 void GUI::openOptions()
1200 Options
options(_options
);
1201 OptionsDialog
dialog(options
, _units
, this);
1203 if (dialog
.exec() != QDialog::Accepted
)
1206 updateOptions(options
);
1209 void GUI::printFile()
1211 QPrinter
printer(QPrinter::HighResolution
);
1212 QPrintDialog
dialog(&printer
, this);
1214 if (dialog
.exec() == QDialog::Accepted
)
1218 void GUI::exportPDFFile()
1220 PDFExportDialog
dialog(_pdfExport
, _units
, this);
1221 if (dialog
.exec() != QDialog::Accepted
)
1224 QPrinter
printer(QPrinter::HighResolution
);
1225 printer
.setOutputFormat(QPrinter::PdfFormat
);
1226 printer
.setCreator(QString(APP_NAME
) + QString(" ")
1227 + QString(APP_VERSION
));
1228 printer
.setResolution(_pdfExport
.resolution
);
1229 printer
.setPageLayout(QPageLayout(QPageSize(_pdfExport
.paperSize
),
1230 _pdfExport
.orientation
, _pdfExport
.margins
, QPageLayout::Millimeter
));
1231 printer
.setOutputFileName(_pdfExport
.fileName
);
1236 void GUI::exportPNGFile()
1238 PNGExportDialog
dialog(_pngExport
, this);
1239 if (dialog
.exec() != QDialog::Accepted
)
1242 QImage
img(_pngExport
.size
, QImage::Format_ARGB32_Premultiplied
);
1244 QRectF
rect(0, 0, img
.width(), img
.height());
1245 QRectF
contentRect(rect
.adjusted(_pngExport
.margins
.left(),
1246 _pngExport
.margins
.top(), -_pngExport
.margins
.right(),
1247 -_pngExport
.margins
.bottom()));
1249 if (_pngExport
.antialiasing
)
1250 p
.setRenderHint(QPainter::Antialiasing
);
1251 p
.fillRect(rect
, Qt::white
);
1252 plotMainPage(&p
, contentRect
, 1.0, true);
1253 img
.save(_pngExport
.fileName
, "png");
1255 if (!_tabs
.isEmpty() && _options
.separateGraphPage
) {
1256 QImage
img2(_pngExport
.size
.width(), (int)graphPlotHeight(rect
, 1)
1257 + _pngExport
.margins
.bottom(), QImage::Format_ARGB32_Premultiplied
);
1259 QRectF
rect2(0, 0, img2
.width(), img2
.height());
1261 if (_pngExport
.antialiasing
)
1262 p2
.setRenderHint(QPainter::Antialiasing
);
1263 p2
.fillRect(rect2
, Qt::white
);
1264 plotGraphsPage(&p2
, contentRect
, 1);
1266 QFileInfo
fi(_pngExport
.fileName
);
1267 img2
.save(fi
.absolutePath() + "/" + fi
.baseName() + "-graphs."
1268 + fi
.suffix(), "png");
1272 void GUI::statistics()
1274 QLocale
l(QLocale::system());
1275 QMessageBox
msgBox(this);
1279 if (_showTracksAction
->isChecked() && _trackCount
> 1)
1280 text
.append("<b>" + tr("Tracks") + ":</b> "
1281 + l
.toString(_trackCount
) + "<br>");
1282 if (_showRoutesAction
->isChecked() && _routeCount
> 1)
1283 text
.append("<b>" + tr("Routes") + ":</b> "
1284 + l
.toString(_routeCount
) + "<br>");
1285 if (_showWaypointsAction
->isChecked() && _waypointCount
> 1)
1286 text
.append("<b>" + tr("Waypoints") + ":</b> "
1287 + l
.toString(_waypointCount
) + "<br>");
1288 if (_showAreasAction
->isChecked() && _areaCount
> 1)
1289 text
.append("<b>" + tr("Areas") + ":</b> "
1290 + l
.toString(_areaCount
) + "<br>");
1292 if (_dateRange
.first
.isValid()) {
1293 QString format
= l
.dateFormat(QLocale::ShortFormat
);
1294 if (_dateRange
.first
== _dateRange
.second
)
1295 text
.append("<b>" + tr("Date") + ":</b> "
1296 + _dateRange
.first
.toString(format
) + "<br>");
1298 text
.append("<b>" + tr("Date") + ":</b> "
1299 + QString("%1 - %2").arg(_dateRange
.first
.toString(format
),
1300 _dateRange
.second
.toString(format
)) + "<br>");
1304 text
.append("<b>" + tr("Distance") + ":</b> "
1305 + Format::distance(distance(), units()) + "<br>");
1307 text
.append("<b>" + tr("Time") + ":</b> "
1308 + Format::timeSpan(time()) + "<br>");
1309 text
.append("<b>" + tr("Moving time") + ":</b> "
1310 + Format::timeSpan(movingTime()) + "<br>");
1312 text
.append("<br>");
1314 for (int i
= 0; i
< _tabs
.count(); i
++) {
1315 const GraphTab
*tab
= _tabs
.at(i
);
1319 text
.append("<i>" + tab
->label() + "</i><br>");
1320 for (int j
= 0; j
< tab
->info().size(); j
++) {
1321 const KV
<QString
, QString
> &kv
= tab
->info().at(j
);
1322 text
.append("<b>" + kv
.key() + ":</b> " + kv
.value());
1323 if (j
!= tab
->info().size() - 1)
1326 if (i
!= _tabs
.count() - 1)
1327 text
.append("<br><br>");
1330 msgBox
.setWindowTitle(tr("Statistics"));
1331 msgBox
.setText(text
);
1333 #else // Q_OS_ANDROID
1336 text
= "<style>td {white-space: pre; padding-right: 4em;}"
1337 "th {text-align: left; padding-top: 0.5em;}</style><table>";
1339 text
= "<style>td {white-space: pre; padding-right: 2em;}"
1340 "th {text-align: left; padding-top: 0.5em;}</style><table>";
1341 #endif // Q_OS_WIN32
1343 if (_showTracksAction
->isChecked() && _trackCount
> 1)
1344 text
.append("<tr><td>" + tr("Tracks") + ":</td><td>"
1345 + l
.toString(_trackCount
) + "</td></tr>");
1346 if (_showRoutesAction
->isChecked() && _routeCount
> 1)
1347 text
.append("<tr><td>" + tr("Routes") + ":</td><td>"
1348 + l
.toString(_routeCount
) + "</td></tr>");
1349 if (_showWaypointsAction
->isChecked() && _waypointCount
> 1)
1350 text
.append("<tr><td>" + tr("Waypoints") + ":</td><td>"
1351 + l
.toString(_waypointCount
) + "</td></tr>");
1352 if (_showAreasAction
->isChecked() && _areaCount
> 1)
1353 text
.append("<tr><td>" + tr("Areas") + ":</td><td>"
1354 + l
.toString(_areaCount
) + "</td></tr>");
1356 if (_dateRange
.first
.isValid()) {
1357 if (_dateRange
.first
== _dateRange
.second
) {
1358 QString format
= l
.dateFormat(QLocale::LongFormat
);
1359 text
.append("<tr><td>" + tr("Date") + ":</td><td>"
1360 + _dateRange
.first
.toString(format
) + "</td></tr>");
1362 QString format
= l
.dateFormat(QLocale::ShortFormat
);
1363 text
.append("<tr><td>" + tr("Date") + ":</td><td>"
1364 + QString("%1 - %2").arg(_dateRange
.first
.toString(format
),
1365 _dateRange
.second
.toString(format
)) + "</td></tr>");
1370 text
.append("<tr><td>" + tr("Distance") + ":</td><td>"
1371 + Format::distance(distance(), units()) + "</td></tr>");
1373 text
.append("<tr><td>" + tr("Time") + ":</td><td>"
1374 + Format::timeSpan(time()) + "</td></tr>");
1375 text
.append("<tr><td>" + tr("Moving time") + ":</td><td>"
1376 + Format::timeSpan(movingTime()) + "</td></tr>");
1379 for (int i
= 0; i
< _tabs
.count(); i
++) {
1380 const GraphTab
*tab
= _tabs
.at(i
);
1384 text
.append("<tr><th colspan=\"2\">" + tab
->label() + "</th></tr>");
1385 for (int j
= 0; j
< tab
->info().size(); j
++) {
1386 const KV
<QString
, QString
> &kv
= tab
->info().at(j
);
1387 text
.append("<tr><td>" + kv
.key() + ":</td><td>" + kv
.value()
1392 text
.append("</table>");
1394 msgBox
.setWindowTitle(tr("Statistics"));
1395 msgBox
.setText("<h3>" + tr("Statistics") + "</h3>");
1396 msgBox
.setInformativeText(text
);
1397 #endif // Q_OS_ANDROID
1402 void GUI::plotMainPage(QPainter
*painter
, const QRectF
&rect
, qreal ratio
,
1405 QLocale
l(QLocale::system());
1411 if (!_pathName
.isNull() && _options
.printName
)
1412 info
.insert(tr("Name"), _pathName
);
1414 if (_options
.printItemCount
) {
1415 if (_showTracksAction
->isChecked() && _trackCount
> 1)
1416 info
.insert(tr("Tracks"), l
.toString(_trackCount
));
1417 if (_showRoutesAction
->isChecked() && _routeCount
> 1)
1418 info
.insert(tr("Routes"), l
.toString(_routeCount
));
1419 if (_showWaypointsAction
->isChecked() && _waypointCount
> 1)
1420 info
.insert(tr("Waypoints"), l
.toString(_waypointCount
));
1421 if (_showAreasAction
->isChecked() && _areaCount
> 1)
1422 info
.insert(tr("Areas"), l
.toString(_areaCount
));
1425 if (_dateRange
.first
.isValid() && _options
.printDate
) {
1426 if (_dateRange
.first
== _dateRange
.second
) {
1427 QString format
= l
.dateFormat(QLocale::LongFormat
);
1428 info
.insert(tr("Date"), _dateRange
.first
.toString(format
));
1430 QString format
= l
.dateFormat(QLocale::ShortFormat
);
1431 info
.insert(tr("Date"), QString("%1 - %2")
1432 .arg(_dateRange
.first
.toString(format
),
1433 _dateRange
.second
.toString(format
)));
1437 if (distance() > 0 && _options
.printDistance
)
1438 info
.insert(tr("Distance"), Format::distance(distance(), units()));
1439 if (time() > 0 && _options
.printTime
)
1440 info
.insert(tr("Time"), Format::timeSpan(time()));
1441 if (movingTime() > 0 && _options
.printMovingTime
)
1442 info
.insert(tr("Moving time"), Format::timeSpan(movingTime()));
1444 if (info
.isEmpty()) {
1448 ih
= info
.contentSize().height() * ratio
;
1450 info
.plot(painter
, QRectF(rect
.x(), rect
.y(), rect
.width(), ih
), ratio
);
1452 if (_graphTabWidget
->isVisible() && !_options
.separateGraphPage
) {
1453 qreal r
= rect
.width() / rect
.height();
1454 gh
= (rect
.width() > rect
.height())
1455 ? 0.15 * r
* (rect
.height() - ih
- 2*mh
)
1456 : 0.15 * (rect
.height() - ih
- 2*mh
);
1460 GraphTab
*gt
= static_cast<GraphTab
*>(_graphTabWidget
->currentWidget());
1461 gt
->plot(painter
, QRectF(rect
.x(), rect
.y() + rect
.height() - gh
,
1462 rect
.width(), gh
), ratio
);
1468 MapView::PlotFlags flags
;
1469 if (_options
.hiresPrint
)
1470 flags
|= MapView::HiRes
;
1472 flags
|= MapView::Expand
;
1474 _mapView
->plot(painter
, QRectF(rect
.x(), rect
.y() + ih
+ mh
, rect
.width(),
1475 rect
.height() - (ih
+ sc
*mh
+ gh
)), ratio
, flags
);
1478 void GUI::plotGraphsPage(QPainter
*painter
, const QRectF
&rect
, qreal ratio
)
1481 for (int i
= 0; i
< _tabs
.size(); i
++)
1482 if (!_tabs
.at(i
)->isEmpty())
1485 qreal sp
= ratio
* 20;
1486 qreal gh
= qMin((rect
.height() - ((cnt
- 1) * sp
))/(qreal
)cnt
,
1487 0.20 * rect
.height());
1490 for (int i
= 0; i
< _tabs
.size(); i
++) {
1491 if (!_tabs
.at(i
)->isEmpty()) {
1492 _tabs
.at(i
)->plot(painter
, QRectF(rect
.x(), rect
.y() + y
,
1493 rect
.width(), gh
), ratio
);
1499 qreal
GUI::graphPlotHeight(const QRectF
&rect
, qreal ratio
)
1502 for (int i
= 0; i
< _tabs
.size(); i
++)
1503 if (!_tabs
.at(i
)->isEmpty())
1506 qreal sp
= ratio
* 20;
1507 qreal gh
= qMin((rect
.height() - ((cnt
- 1) * sp
))/(qreal
)cnt
,
1508 0.20 * rect
.height());
1510 return cnt
* gh
+ (cnt
- 1) * sp
;
1513 void GUI::plot(QPrinter
*printer
)
1515 QPainter
p(printer
);
1516 qreal fsr
= 1085.0 / (qMax(printer
->width(), printer
->height())
1517 / (qreal
)printer
->resolution());
1518 qreal ratio
= p
.paintEngine()->paintDevice()->logicalDpiX() / fsr
;
1519 QRectF
rect(0, 0, printer
->width(), printer
->height());
1521 plotMainPage(&p
, rect
, ratio
);
1523 if (!_tabs
.isEmpty() && _options
.separateGraphPage
) {
1525 plotGraphsPage(&p
, rect
, ratio
);
1529 void GUI::reloadFiles()
1539 _dateRange
= DateTimeRange(QDateTime(), QDateTime());
1540 _pathName
= QString();
1542 for (int i
= 0; i
< _tabs
.count(); i
++)
1543 _tabs
.at(i
)->clear();
1547 for (int i
= 0; i
< _files
.size(); i
++) {
1548 if (!loadFile(_files
.at(i
), true, showError
)) {
1554 updateStatusBarInfo();
1555 updateWindowTitle();
1556 if (_files
.isEmpty())
1557 _fileActionGroup
->setEnabled(false);
1558 #ifndef Q_OS_ANDROID
1560 _browser
->setCurrent(_files
.last());
1561 #endif // Q_OS_ANDROID
1562 updateDEMDownloadAction();
1565 void GUI::closeFiles()
1575 _dateRange
= DateTimeRange(QDateTime(), QDateTime());
1576 _pathName
= QString();
1578 for (int i
= 0; i
< _tabs
.count(); i
++)
1579 _tabs
.at(i
)->clear();
1587 void GUI::closeAll()
1591 _fileActionGroup
->setEnabled(false);
1592 updateStatusBarInfo();
1593 updateWindowTitle();
1595 updateDEMDownloadAction();
1598 _browser
->setCurrentDir(QString());
1599 #endif // Q_OS_ANDROID
1602 void GUI::showGraphs(bool show
)
1604 _graphTabWidget
->setHidden(!show
);
1608 void GUI::showGraphTabs(bool show
)
1610 _graphTabWidget
->tabBar()->setVisible(show
);
1612 #else // Q_OS_ANDROID
1613 void GUI::showToolbars(bool show
)
1616 Q_ASSERT(!_windowStates
.isEmpty());
1617 restoreState(_windowStates
.last());
1618 _windowStates
.removeLast();
1620 _windowStates
.append(saveState());
1621 removeToolBar(_fileToolBar
);
1622 removeToolBar(_showToolBar
);
1623 removeToolBar(_navigationToolBar
);
1627 void GUI::showFullscreen(bool show
)
1630 _windowGeometries
.append(saveGeometry());
1631 _frameStyle
= _mapView
->frameStyle();
1632 statusBar()->hide();
1634 showToolbars(false);
1635 _mapView
->setFrameStyle(QFrame::NoFrame
);
1636 _graphTabWidget
->tabBar()->hide();
1638 _graphTabWidget
->setDocumentMode(true);
1642 Q_ASSERT(!_windowGeometries
.isEmpty());
1643 _windowGeometries
.removeLast();
1644 statusBar()->show();
1647 _mapView
->setFrameStyle(_frameStyle
);
1648 _graphTabWidget
->tabBar()->show();
1650 _graphTabWidget
->setDocumentMode(false);
1655 #endif // Q_OS_ANDROID
1657 void GUI::showTracks(bool show
)
1659 _mapView
->showTracks(show
);
1661 for (int i
= 0; i
< _tabs
.size(); i
++)
1662 _tabs
.at(i
)->showTracks(show
);
1664 updateStatusBarInfo();
1666 updateDEMDownloadAction();
1669 void GUI::showRoutes(bool show
)
1671 _mapView
->showRoutes(show
);
1673 for (int i
= 0; i
< _tabs
.size(); i
++)
1674 _tabs
.at(i
)->showRoutes(show
);
1676 updateStatusBarInfo();
1678 updateDEMDownloadAction();
1681 void GUI::showWaypoints(bool show
)
1683 _mapView
->showWaypoints(show
);
1684 updateDEMDownloadAction();
1687 void GUI::showAreas(bool show
)
1689 _mapView
->showAreas(show
);
1690 updateDEMDownloadAction();
1693 void GUI::showGraphGrids(bool show
)
1695 for (int i
= 0; i
< _tabs
.size(); i
++)
1696 _tabs
.at(i
)->showGrid(show
);
1699 void GUI::showGraphSliderInfo(bool show
)
1701 for (int i
= 0; i
< _tabs
.size(); i
++)
1702 _tabs
.at(i
)->showSliderInfo(show
);
1705 void GUI::showPathMarkerInfo(QAction
*action
)
1707 if (action
== _showMarkersAction
) {
1708 _mapView
->showMarkers(true);
1709 _mapView
->showMarkerInfo(MarkerInfoItem::None
);
1710 } else if (action
== _showMarkerDateAction
) {
1711 _mapView
->showMarkers(true);
1712 _mapView
->showMarkerInfo(MarkerInfoItem::Date
);
1713 } else if (action
== _showMarkerCoordinatesAction
) {
1714 _mapView
->showMarkers(true);
1715 _mapView
->showMarkerInfo(MarkerInfoItem::Position
);
1717 _mapView
->showMarkers(false);
1718 _mapView
->showMarkerInfo(MarkerInfoItem::None
);
1725 QStringList
files(QFileDialog::getOpenFileNames(this, tr("Open map file"),
1727 #else // Q_OS_ANDROID
1728 QStringList
files(QFileDialog::getOpenFileNames(this, tr("Open map file"),
1729 _mapDir
, MapList::formats()));
1730 #endif // Q_OS_ANDROID
1731 MapAction
*a
, *lastReady
= 0;
1732 int showError
= (files
.size() > 1) ? 2 : 1;
1734 for (int i
= 0; i
< files
.size(); i
++) {
1735 if (loadMap(files
.at(i
), a
, showError
) && a
)
1738 if (!files
.isEmpty())
1739 _mapDir
= QFileInfo(files
.last()).path();
1741 lastReady
->trigger();
1744 static MapAction
*findMapAction(const QList
<QAction
*> &mapActions
,
1747 for (int i
= 0; i
< mapActions
.count(); i
++) {
1748 const Map
*m
= mapActions
.at(i
)->data().value
<Map
*>();
1749 if (map
->path() == m
->path())
1750 return static_cast<MapAction
*>(mapActions
.at(i
));
1756 bool GUI::loadMapNode(const TreeNode
<Map
*> &node
, MapAction
*&action
,
1757 const QList
<QAction
*> &existingActions
, int &showError
)
1763 for (int i
= 0; i
< node
.childs().size(); i
++)
1764 valid
= loadMapNode(node
.childs().at(i
), action
, existingActions
,
1767 for (int i
= 0; i
< node
.items().size(); i
++) {
1768 Map
*map
= node
.items().at(i
);
1771 if (!(a
= findMapAction(existingActions
, map
))) {
1772 if (!map
->isValid()) {
1774 QString error
= tr("Error loading map:") + "\n"
1775 + Util::displayName(map
->path()) + ": " + map
->errorString();
1777 if (showError
> 1) {
1778 QMessageBox
message(QMessageBox::Critical
, APP_NAME
,
1779 error
, QMessageBox::Ok
, this);
1780 QCheckBox
checkBox(tr("Don't show again"));
1781 message
.setCheckBox(&checkBox
);
1783 if (checkBox
.isChecked())
1786 QMessageBox::critical(this, APP_NAME
, error
);
1792 a
= new MapAction(map
, _mapsActionGroup
);
1793 _mapMenu
->insertAction(_mapsEnd
, a
);
1795 if (map
->isReady()) {
1797 _showMapAction
->setEnabled(true);
1798 _clearMapCacheAction
->setEnabled(true);
1800 connect(a
, &MapAction::loaded
, this, &GUI::mapLoaded
);
1804 map
= a
->data().value
<Map
*>();
1813 bool GUI::loadMap(const QString
&fileName
, MapAction
*&action
, int &showError
)
1815 TreeNode
<Map
*> maps(MapList::loadMaps(fileName
, _mapView
->inputProjection()));
1816 QList
<QAction
*> existingActions(_mapsActionGroup
->actions());
1818 return loadMapNode(maps
, action
, existingActions
, showError
);
1821 void GUI::mapLoaded()
1823 MapAction
*action
= static_cast<MapAction
*>(QObject::sender());
1824 Map
*map
= action
->data().value
<Map
*>();
1826 if (map
->isValid()) {
1828 _showMapAction
->setEnabled(true);
1829 _clearMapCacheAction
->setEnabled(true);
1831 QString error
= tr("Error loading map:") + "\n"
1832 + Util::displayName(map
->path()) + ": " + map
->errorString();
1833 QMessageBox::critical(this, APP_NAME
, error
);
1834 action
->deleteLater();
1838 void GUI::mapLoadedDir()
1840 MapAction
*action
= static_cast<MapAction
*>(QObject::sender());
1841 Map
*map
= action
->data().value
<Map
*>();
1843 if (map
->isValid()) {
1844 _showMapAction
->setEnabled(true);
1845 _clearMapCacheAction
->setEnabled(true);
1846 QList
<MapAction
*> actions
;
1847 actions
.append(action
);
1848 _mapView
->loadMaps(actions
);
1850 QString error
= tr("Error loading map:") + "\n"
1851 + Util::displayName(map
->path()) + ": " + map
->errorString();
1852 QMessageBox::critical(this, APP_NAME
, error
);
1853 action
->deleteLater();
1857 void GUI::loadMapDirNode(const TreeNode
<Map
*> &node
, QList
<MapAction
*> &actions
,
1858 QMenu
*menu
, const QList
<QAction
*> &existingActions
, int &showError
)
1860 for (int i
= 0; i
< node
.childs().size(); i
++) {
1861 QMenu
*cm
= new QMenu(node
.childs().at(i
).name(), menu
);
1863 loadMapDirNode(node
.childs().at(i
), actions
, cm
, existingActions
,
1867 for (int i
= 0; i
< node
.items().size(); i
++) {
1868 Map
*map
= node
.items().at(i
);
1871 if (!(a
= findMapAction(existingActions
, map
))) {
1872 if (!map
->isValid()) {
1874 QString error
= tr("Error loading map:") + "\n"
1875 + Util::displayName(map
->path()) + ": " + map
->errorString();
1877 if (showError
> 1) {
1878 QMessageBox
message(QMessageBox::Critical
, APP_NAME
,
1879 error
, QMessageBox::Ok
, this);
1880 QCheckBox
checkBox(tr("Don't show again"));
1881 message
.setCheckBox(&checkBox
);
1883 if (checkBox
.isChecked())
1886 QMessageBox::critical(this, APP_NAME
, error
);
1891 a
= new MapAction(map
, _mapsActionGroup
);
1894 if (map
->isReady()) {
1895 _showMapAction
->setEnabled(true);
1896 _clearMapCacheAction
->setEnabled(true);
1899 connect(a
, &MapAction::loaded
, this, &GUI::mapLoadedDir
);
1904 map
= a
->data().value
<Map
*>();
1911 void GUI::loadMapDir()
1913 QString
dir(QFileDialog::getExistingDirectory(this,
1914 tr("Select map directory"), _mapDir
, QFileDialog::ShowDirsOnly
));
1919 TreeNode
<Map
*> maps(MapList::loadMaps(dir
, _mapView
->inputProjection()));
1920 QList
<QAction
*> existingActions(_mapsActionGroup
->actions());
1921 QList
<MapAction
*> actions
;
1922 QMenu
*menu
= new QMenu(maps
.name());
1923 int showError
= (maps
.items().size() > 1 || !maps
.childs().isEmpty())
1926 loadMapDirNode(maps
, actions
, menu
, existingActions
, showError
);
1928 _mapView
->loadMaps(actions
);
1930 if (menu
->isEmpty())
1933 _mapMenu
->insertMenu(_mapsEnd
, menu
);
1935 _mapDir
= fi
.absolutePath();
1936 _fileActionGroup
->setEnabled(true);
1937 _reloadFileAction
->setEnabled(false);
1940 void GUI::clearMapCache()
1942 if (QMessageBox::question(this, APP_NAME
,
1943 tr("Clear \"%1\" tile cache?").arg(_map
->name())) == QMessageBox::Yes
)
1944 _mapView
->clearMapCache();
1947 void GUI::downloadDEM()
1949 RectC
br(_mapView
->boundingRect());
1950 _demRects
.append(br
);
1952 if (!_dem
->loadTiles(br
) && _demRects
.size() == 1)
1956 void GUI::demLoaded()
1958 for (int i
= 0; i
< _demRects
.size(); i
++) {
1959 if (!_dem
->checkTiles(_demRects
.at(i
))) {
1960 QMessageBox::warning(this, APP_NAME
,
1961 tr("Could not download all required DEM files."));
1971 void GUI::showDEMTiles()
1973 QList
<Area
> tiles(DEM::tiles());
1975 if (tiles
.isEmpty()) {
1976 QMessageBox::information(this, APP_NAME
, tr("No local DEM tiles found."));
1978 _mapView
->loadDEMs(tiles
);
1980 _areaCount
+= tiles
.size();
1982 _fileActionGroup
->setEnabled(true);
1983 _reloadFileAction
->setEnabled(false);
1987 void GUI::updateStatusBarInfo()
1989 if (_files
.count() == 0)
1990 _fileNameLabel
->setText(tr("No files loaded"));
1991 else if (_files
.count() == 1)
1992 _fileNameLabel
->setText(Util::displayName(_files
.at(0)));
1994 _fileNameLabel
->setText(tr("%n files", "", _files
.count()));
1997 _distanceLabel
->setText(Format::distance(distance(), units()));
1999 _distanceLabel
->clear();
2002 if (_movingTimeAction
->isChecked()) {
2003 _timeLabel
->setText(Format::timeSpan(movingTime())
2005 _timeLabel
->setToolTip(Format::timeSpan(time()));
2007 _timeLabel
->setText(Format::timeSpan(time()));
2008 _timeLabel
->setToolTip(Format::timeSpan(movingTime())
2012 _timeLabel
->clear();
2013 _timeLabel
->setToolTip(QString());
2017 statusBar()->setVisible(!_files
.isEmpty());
2018 #endif // Q_OS_ANDROID
2021 void GUI::updateWindowTitle()
2023 if (_files
.count() == 1)
2024 setWindowTitle(QFileInfo(_files
.at(0)).fileName() + " - " + APP_NAME
);
2026 setWindowTitle(APP_NAME
);
2029 #ifndef Q_OS_ANDROID
2030 void GUI::updateRecentFiles(const QString
&fileName
)
2034 QList
<QAction
*> actions(_recentFilesActionGroup
->actions());
2035 for (int i
= 0; i
< actions
.size(); i
++) {
2036 if (actions
.at(i
)->text() == fileName
) {
2044 else if (actions
.size() == MAX_RECENT_FILES
)
2045 delete actions
.last();
2047 actions
= _recentFilesActionGroup
->actions();
2048 QAction
*before
= actions
.size() ? actions
.last() : _recentFilesEnd
;
2049 _recentFilesMenu
->insertAction(before
,
2050 new QAction(fileName
, _recentFilesActionGroup
));
2051 _recentFilesMenu
->setEnabled(true);
2054 void GUI::clearRecentFiles()
2056 QList
<QAction
*> actions(_recentFilesActionGroup
->actions());
2058 for (int i
= 0; i
< actions
.size(); i
++)
2059 delete actions
.at(i
);
2061 _recentFilesMenu
->setEnabled(false);
2064 void GUI::recentFileSelected(QAction
*action
)
2067 openFile(action
->text(), true, showError
);
2069 #endif // Q_OS_ANDROID
2071 void GUI::mapChanged(QAction
*action
)
2073 _map
= action
->data().value
<Map
*>();
2074 _mapView
->setMap(_map
);
2079 QAction
*checked
= _mapsActionGroup
->checkedAction();
2083 QList
<QAction
*> maps(_mapsActionGroup
->actions());
2084 for (int i
= 1; i
< maps
.size(); i
++) {
2085 int next
= (maps
.indexOf(checked
) + i
) % maps
.count();
2086 if (maps
.at(next
)->isEnabled()) {
2087 maps
.at(next
)->trigger();
2095 QAction
*checked
= _mapsActionGroup
->checkedAction();
2099 QList
<QAction
*> maps(_mapsActionGroup
->actions());
2100 for (int i
= 1; i
< maps
.size(); i
++) {
2101 int prev
= (maps
.indexOf(checked
) + maps
.count() - i
) % maps
.count();
2102 if (maps
.at(prev
)->isEnabled()) {
2103 maps
.at(prev
)->trigger();
2109 void GUI::poiFileChecked(QAction
*action
)
2111 _poi
->enableFile(action
->data().value
<QString
>(), action
->isChecked());
2114 void GUI::selectAllPOIs()
2116 QList
<QAction
*> actions(_poisActionGroup
->actions());
2117 for (int i
= 0; i
< actions
.size(); i
++) {
2118 POIAction
*a
= static_cast<POIAction
*>(actions
.at(i
));
2119 if (_poi
->enableFile(a
->data().toString(), true))
2120 a
->setChecked(true);
2124 void GUI::unselectAllPOIs()
2126 QList
<QAction
*> actions(_poisActionGroup
->actions());
2127 for (int i
= 0; i
< actions
.size(); i
++) {
2128 POIAction
*a
= static_cast<POIAction
*>(actions
.at(i
));
2129 if (_poi
->enableFile(a
->data().toString(), false))
2130 a
->setChecked(false);
2134 void GUI::graphChanged(int index
)
2139 GraphTab
*gt
= static_cast<GraphTab
*>(_graphTabWidget
->widget(index
));
2141 _mapView
->setGraph(_tabs
.indexOf(gt
));
2144 gt
->setSliderPosition(_lastTab
->sliderPosition());
2148 void GUI::updateNavigationActions()
2151 _navigation
->enableNext(!_browser
->isLast()
2152 && !_browser
->current().isNull());
2153 _navigation
->enablePrev(!_browser
->isFirst()
2154 && !_browser
->current().isNull());
2155 #else // Q_OS_ANDROID
2156 _lastAction
->setEnabled(!_browser
->isLast());
2157 _nextAction
->setEnabled(!_browser
->isLast());
2158 _firstAction
->setEnabled(!_browser
->isFirst());
2159 _prevAction
->setEnabled(!_browser
->isFirst());
2160 #endif // Q_OS_ANDROID
2163 bool GUI::updateGraphTabs()
2167 bool hidden
= _graphTabWidget
->isHidden();
2169 for (int i
= 0; i
< _tabs
.size(); i
++) {
2171 if (tab
->isEmpty() && (index
= _graphTabWidget
->indexOf(tab
)) >= 0)
2172 _graphTabWidget
->removeTab(index
);
2175 for (int i
= 0; i
< _tabs
.size(); i
++) {
2177 if (!tab
->isEmpty() && _graphTabWidget
->indexOf(tab
) < 0)
2178 _graphTabWidget
->insertTab(i
, tab
, _tabs
.at(i
)->label());
2181 if (_graphTabWidget
->count() &&
2182 ((_showTracksAction
->isChecked() && _trackCount
)
2183 || (_showRoutesAction
->isChecked() && _routeCount
))) {
2184 if (_showGraphsAction
->isChecked())
2185 _graphTabWidget
->setHidden(false);
2186 _showGraphsAction
->setEnabled(true);
2188 _graphTabWidget
->setHidden(true);
2189 _showGraphsAction
->setEnabled(false);
2192 return (hidden
!= _graphTabWidget
->isHidden());
2195 void GUI::updateDEMDownloadAction()
2197 _downloadDEMAction
->setEnabled(!_dem
->url().isEmpty()
2198 && !_dem
->checkTiles(_mapView
->boundingRect()));
2201 void GUI::setTimeType(TimeType type
)
2203 for (int i
= 0; i
<_tabs
.count(); i
++)
2204 _tabs
.at(i
)->setTimeType(type
);
2206 updateStatusBarInfo();
2209 void GUI::setUnits(Units units
)
2213 _mapView
->setUnits(units
);
2214 for (int i
= 0; i
<_tabs
.count(); i
++)
2215 _tabs
.at(i
)->setUnits(units
);
2216 updateStatusBarInfo();
2219 void GUI::setCoordinatesFormat(CoordinatesFormat format
)
2221 _mapView
->setCoordinatesFormat(format
);
2224 void GUI::setGraphType(GraphType type
)
2226 for (int i
= 0; i
<_tabs
.count(); i
++)
2227 _tabs
.at(i
)->setGraphType(type
);
2233 QString file
= _browser
->next();
2238 openFile(file
, true, showError
);
2244 QString file
= _browser
->prev();
2249 openFile(file
, true, showError
);
2255 QString file
= _browser
->last();
2260 openFile(file
, true, showError
);
2266 QString file
= _browser
->first();
2271 openFile(file
, true, showError
);
2274 #ifndef Q_OS_ANDROID
2275 void GUI::keyPressEvent(QKeyEvent
*event
)
2280 switch (event
->key()) {
2282 file
= _browser
->prev();
2285 file
= _browser
->next();
2288 file
= _browser
->first();
2291 file
= _browser
->last();
2294 case TOGGLE_GRAPH_TYPE_KEY
:
2295 if (_timeGraphAction
->isChecked())
2296 _distanceGraphAction
->trigger();
2298 _timeGraphAction
->trigger();
2300 case TOGGLE_TIME_TYPE_KEY
:
2301 if (_movingTimeAction
->isChecked())
2302 _totalTimeAction
->trigger();
2304 _movingTimeAction
->trigger();
2306 case TOGGLE_MARKER_INFO_KEY
:
2307 if (_showMarkerDateAction
->isChecked())
2308 _showMarkerCoordinatesAction
->trigger();
2309 else if (_showMarkerCoordinatesAction
->isChecked())
2310 _showMarkerDateAction
->trigger();
2312 case Qt::Key_Escape
:
2313 if (_fullscreenAction
->isChecked()) {
2314 _fullscreenAction
->setChecked(false);
2315 showFullscreen(false);
2321 if (!file
.isNull()) {
2322 if (!(event
->modifiers() & MODIFIER
))
2324 openFile(file
, true, showError
);
2328 QMainWindow::keyPressEvent(event
);
2330 #endif // Q_OS_ANDROID
2332 void GUI::closeEvent(QCloseEvent
*event
)
2335 QMainWindow::closeEvent(event
);
2338 void GUI::dragEnterEvent(QDragEnterEvent
*event
)
2340 if (!event
->mimeData()->hasUrls())
2342 if (event
->proposedAction() != Qt::CopyAction
)
2345 QList
<QUrl
> urls
= event
->mimeData()->urls();
2346 for (int i
= 0; i
< urls
.size(); i
++)
2347 if (!urls
.at(i
).isLocalFile())
2350 event
->acceptProposedAction();
2353 void GUI::dropEvent(QDropEvent
*event
)
2355 MapAction
*lastReady
= 0;
2356 QList
<QUrl
> urls(event
->mimeData()->urls());
2358 int showError
= (urls
.size() > 1) ? 2 : 1;
2360 for (int i
= 0; i
< urls
.size(); i
++) {
2361 QString
file(urls
.at(i
).toLocalFile());
2363 if (!openFile(file
, false, silent
)) {
2365 if (!loadMap(file
, a
, silent
))
2366 openFile(file
, true, showError
);
2375 lastReady
->trigger();
2377 event
->acceptProposedAction();
2380 QGeoPositionInfoSource
*GUI::positionSource(const Options
&options
)
2382 QGeoPositionInfoSource
*source
;
2384 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
2385 source
= QGeoPositionInfoSource::createSource(options
.plugin
, this);
2387 source
= QGeoPositionInfoSource::createSource(options
.plugin
,
2388 options
.pluginParams
.value(options
.plugin
), this);
2391 source
->setPreferredPositioningMethods(
2392 QGeoPositionInfoSource::SatellitePositioningMethods
);
2397 void GUI::writeSettings()
2399 #define WRITE(name, value) \
2400 Settings::name.write(settings, value);
2402 QSettings
settings(qApp
->applicationName(), qApp
->applicationName());
2406 #ifndef Q_OS_ANDROID
2407 settings
.beginGroup(SETTINGS_WINDOW
);
2408 if (!_windowStates
.isEmpty() && !_windowGeometries
.isEmpty()) {
2409 WRITE(windowState
, _windowStates
.first());
2410 WRITE(windowGeometry
, _windowGeometries
.first());
2412 WRITE(windowState
, saveState());
2413 WRITE(windowGeometry
, saveGeometry());
2415 settings
.endGroup();
2416 #endif // Q_OS_ANDROID
2419 settings
.beginGroup(SETTINGS_SETTINGS
);
2420 WRITE(timeType
, _movingTimeAction
->isChecked() ? Moving
: Total
);
2421 WRITE(units
, _imperialUnitsAction
->isChecked()
2422 ? Imperial
: _nauticalUnitsAction
->isChecked()
2423 ? Nautical
: Metric
);
2424 WRITE(coordinatesFormat
, _dmsAction
->isChecked()
2425 ? DMS
: _degreesMinutesAction
->isChecked()
2426 ? DegreesMinutes
: DecimalDegrees
);
2427 #ifndef Q_OS_ANDROID
2428 WRITE(showToolbars
, _showToolbarsAction
->isChecked());
2429 #endif // Q_OS_ANDROID
2430 settings
.endGroup();
2433 #ifndef Q_OS_ANDROID
2434 QList
<QAction
*> recentActions(_recentFilesActionGroup
->actions());
2436 for (int i
= 0; i
< recentActions
.size(); i
++)
2437 recent
.append(recentActions
.at(i
)->text());
2439 settings
.beginGroup(SETTINGS_FILE
);
2440 WRITE(recentDataFiles
, recent
);
2441 settings
.endGroup();
2442 #endif // Q_OS_ANDROID
2445 settings
.beginGroup(SETTINGS_MAP
);
2446 WRITE(activeMap
, _map
->name());
2447 WRITE(showMap
, _showMapAction
->isChecked());
2448 WRITE(cursorCoordinates
, _showCoordinatesAction
->isChecked());
2449 settings
.endGroup();
2452 settings
.beginGroup(SETTINGS_GRAPH
);
2453 WRITE(showGraphs
, _showGraphsAction
->isChecked());
2454 WRITE(graphType
, _timeGraphAction
->isChecked() ? Time
: Distance
);
2455 WRITE(showGrid
, _showGraphGridAction
->isChecked());
2456 WRITE(sliderInfo
, _showGraphSliderInfoAction
->isChecked());
2458 WRITE(showGraphTabs
, _showGraphTabsAction
->isChecked());
2459 #endif // Q_OS_ANDROID
2460 settings
.endGroup();
2463 QList
<QAction
*> disabledActions(_poisActionGroup
->actions());
2464 QStringList disabled
;
2465 for (int i
= 0; i
< disabledActions
.size(); i
++)
2466 if (!disabledActions
.at(i
)->isChecked())
2467 disabled
.append(disabledActions
.at(i
)->data().toString());
2469 settings
.beginGroup(SETTINGS_POI
);
2470 WRITE(showPoi
, _showPOIAction
->isChecked());
2471 WRITE(poiOverlap
, _overlapPOIAction
->isChecked());
2472 WRITE(poiLabels
, _showPOILabelsAction
->isChecked());
2473 WRITE(poiIcons
, _showPOIIconsAction
->isChecked());
2474 WRITE(disabledPoiFiles
, disabled
);
2475 settings
.endGroup();
2478 MarkerInfoItem::Type mi
;
2479 if (_showMarkerDateAction
->isChecked())
2480 mi
= MarkerInfoItem::Date
;
2481 else if (_showMarkerCoordinatesAction
->isChecked())
2482 mi
= MarkerInfoItem::Position
;
2484 mi
= MarkerInfoItem::None
;
2486 settings
.beginGroup(SETTINGS_DATA
);
2487 WRITE(tracks
, _showTracksAction
->isChecked());
2488 WRITE(routes
, _showRoutesAction
->isChecked());
2489 WRITE(waypoints
, _showWaypointsAction
->isChecked());
2490 WRITE(areas
, _showAreasAction
->isChecked());
2491 WRITE(waypointIcons
, _showWaypointIconsAction
->isChecked());
2492 WRITE(waypointLabels
, _showWaypointLabelsAction
->isChecked());
2493 WRITE(routeWaypoints
, _showRouteWaypointsAction
->isChecked());
2494 WRITE(pathTicks
, _showTicksAction
->isChecked());
2495 WRITE(positionMarkers
, _showMarkersAction
->isChecked()
2496 || _showMarkerDateAction
->isChecked()
2497 || _showMarkerCoordinatesAction
->isChecked());
2498 WRITE(markerInfo
, mi
);
2499 WRITE(useStyles
, _useStylesAction
->isChecked());
2500 settings
.endGroup();
2503 settings
.beginGroup(SETTINGS_POSITION
);
2504 WRITE(showPosition
, _showPositionAction
->isChecked());
2505 WRITE(followPosition
, _followPositionAction
->isChecked());
2506 WRITE(positionCoordinates
, _showPositionCoordinatesAction
->isChecked());
2507 WRITE(motionInfo
, _showMotionInfoAction
->isChecked());
2508 settings
.endGroup();
2511 settings
.beginGroup(SETTINGS_PDF_EXPORT
);
2512 WRITE(pdfOrientation
, _pdfExport
.orientation
);
2513 WRITE(pdfResolution
, _pdfExport
.resolution
);
2514 WRITE(pdfSize
, _pdfExport
.paperSize
);
2515 WRITE(pdfMarginLeft
, _pdfExport
.margins
.left());
2516 WRITE(pdfMarginTop
, _pdfExport
.margins
.top());
2517 WRITE(pdfMarginRight
, _pdfExport
.margins
.right());
2518 WRITE(pdfMarginBottom
, _pdfExport
.margins
.bottom());
2519 WRITE(pdfFileName
, _pdfExport
.fileName
);
2520 settings
.endGroup();
2523 settings
.beginGroup(SETTINGS_PNG_EXPORT
);
2524 WRITE(pngWidth
, _pngExport
.size
.width());
2525 WRITE(pngHeight
, _pngExport
.size
.height());
2526 WRITE(pngMarginLeft
, _pngExport
.margins
.left());
2527 WRITE(pngMarginTop
, _pngExport
.margins
.top());
2528 WRITE(pngMarginRight
, _pngExport
.margins
.right());
2529 WRITE(pngMarginBottom
, _pngExport
.margins
.bottom());
2530 WRITE(pngAntialiasing
, _pngExport
.antialiasing
);
2531 WRITE(pngFileName
, _pngExport
.fileName
);
2532 settings
.endGroup();
2535 settings
.beginGroup(SETTINGS_OPTIONS
);
2536 WRITE(paletteColor
, _options
.palette
.color());
2537 WRITE(paletteShift
, _options
.palette
.shift());
2538 WRITE(mapOpacity
, _options
.mapOpacity
);
2539 WRITE(backgroundColor
, _options
.backgroundColor
);
2540 WRITE(crosshairColor
, _options
.crosshairColor
);
2541 WRITE(infoColor
, _options
.infoColor
);
2542 WRITE(infoBackground
, _options
.infoBackground
);
2543 WRITE(trackWidth
, _options
.trackWidth
);
2544 WRITE(routeWidth
, _options
.routeWidth
);
2545 WRITE(areaWidth
, _options
.areaWidth
);
2546 WRITE(trackStyle
, (int)_options
.trackStyle
);
2547 WRITE(routeStyle
, (int)_options
.routeStyle
);
2548 WRITE(areaStyle
, (int)_options
.areaStyle
);
2549 WRITE(areaOpacity
, _options
.areaOpacity
);
2550 WRITE(waypointSize
, _options
.waypointSize
);
2551 WRITE(waypointColor
, _options
.waypointColor
);
2552 WRITE(poiSize
, _options
.poiSize
);
2553 WRITE(poiColor
, _options
.poiColor
);
2554 WRITE(graphWidth
, _options
.graphWidth
);
2555 WRITE(pathAntiAliasing
, _options
.pathAntiAliasing
);
2556 WRITE(graphAntiAliasing
, _options
.graphAntiAliasing
);
2557 WRITE(elevationFilter
, _options
.elevationFilter
);
2558 WRITE(speedFilter
, _options
.speedFilter
);
2559 WRITE(heartRateFilter
, _options
.heartRateFilter
);
2560 WRITE(cadenceFilter
, _options
.cadenceFilter
);
2561 WRITE(powerFilter
, _options
.powerFilter
);
2562 WRITE(outlierEliminate
, _options
.outlierEliminate
);
2563 WRITE(automaticPause
, _options
.automaticPause
);
2564 WRITE(pauseSpeed
, _options
.pauseSpeed
);
2565 WRITE(pauseInterval
, _options
.pauseInterval
);
2566 WRITE(useReportedSpeed
, _options
.useReportedSpeed
);
2567 WRITE(dataUseDEM
, _options
.dataUseDEM
);
2568 WRITE(secondaryElevation
, _options
.showSecondaryElevation
);
2569 WRITE(secondarySpeed
, _options
.showSecondarySpeed
);
2570 WRITE(timeZone
, QVariant::fromValue(_options
.timeZone
));
2571 WRITE(useSegments
, _options
.useSegments
);
2572 WRITE(poiRadius
, _options
.poiRadius
);
2573 WRITE(demURL
, _options
.demURL
);
2574 WRITE(demAuthentication
, _options
.demAuthorization
);
2575 WRITE(demUsername
, _options
.demUsername
);
2576 WRITE(demPassword
, _options
.demPassword
);
2577 WRITE(positionPlugin(), _options
.plugin
);
2578 WRITE(positionPluginParameters
, _options
.pluginParams
);
2579 WRITE(useOpenGL
, _options
.useOpenGL
);
2580 WRITE(enableHTTP2
, _options
.enableHTTP2
);
2581 WRITE(pixmapCache
, _options
.pixmapCache
);
2582 WRITE(demCache
, _options
.demCache
);
2583 WRITE(connectionTimeout
, _options
.connectionTimeout
);
2584 WRITE(hiresPrint
, _options
.hiresPrint
);
2585 WRITE(printName
, _options
.printName
);
2586 WRITE(printDate
, _options
.printDate
);
2587 WRITE(printDistance
, _options
.printDistance
);
2588 WRITE(printTime
, _options
.printTime
);
2589 WRITE(printMovingTime
, _options
.printMovingTime
);
2590 WRITE(printItemCount
, _options
.printItemCount
);
2591 WRITE(separateGraphPage
, _options
.separateGraphPage
);
2592 WRITE(sliderColor
, _options
.sliderColor
);
2593 WRITE(outputProjection
, _options
.outputProjection
);
2594 WRITE(inputProjection
, _options
.inputProjection
);
2595 WRITE(hidpiMap
, _options
.hidpiMap
);
2596 WRITE(dataPath
, _options
.dataPath
);
2597 WRITE(mapsPath
, _options
.mapsPath
);
2598 WRITE(poiPath
, _options
.poiPath
);
2599 settings
.endGroup();
2602 void GUI::readSettings(QString
&activeMap
, QStringList
&disabledPOIs
,
2603 QStringList
&recentFiles
)
2605 #define READ(name) \
2606 (Settings::name.read(settings))
2608 QSettings
settings(qApp
->applicationName(), qApp
->applicationName());
2610 #ifndef Q_OS_ANDROID
2611 settings
.beginGroup(SETTINGS_WINDOW
);
2612 restoreGeometry(READ(windowGeometry
).toByteArray());
2613 restoreState(READ(windowState
).toByteArray());
2614 settings
.endGroup();
2615 #endif // Q_OS_ANDROID
2618 settings
.beginGroup(SETTINGS_SETTINGS
);
2619 TimeType tt
= (TimeType
)READ(timeType
).toInt();
2621 _movingTimeAction
->setChecked(true);
2623 _totalTimeAction
->setChecked(true);
2626 Units u
= (Units
)READ(units
).toInt();
2628 _imperialUnitsAction
->setChecked(true);
2629 else if (u
== Nautical
)
2630 _nauticalUnitsAction
->setChecked(true);
2632 _metricUnitsAction
->setChecked(true);
2635 CoordinatesFormat cf
= (CoordinatesFormat
)READ(coordinatesFormat
).toInt();
2637 _dmsAction
->setChecked(true);
2638 else if (cf
== DegreesMinutes
)
2639 _degreesMinutesAction
->setChecked(true);
2641 _decimalDegreesAction
->setChecked(true);
2642 setCoordinatesFormat(cf
);
2644 #ifndef Q_OS_ANDROID
2645 if (READ(showToolbars
).toBool())
2646 _showToolbarsAction
->setChecked(true);
2648 showToolbars(false);
2649 #endif // Q_OS_ANDROID
2650 settings
.endGroup();
2653 #ifndef Q_OS_ANDROID
2654 settings
.beginGroup(SETTINGS_FILE
);
2655 recentFiles
= READ(recentDataFiles
);
2656 settings
.endGroup();
2657 #else // Q_OS_ANDROID
2658 Q_UNUSED(recentFiles
);
2659 #endif // Q_OS_ANDROID
2662 settings
.beginGroup(SETTINGS_MAP
);
2663 if (READ(showMap
).toBool()) {
2664 _showMapAction
->setChecked(true);
2665 _mapView
->showMap(true);
2667 if (READ(cursorCoordinates
).toBool()) {
2668 _showCoordinatesAction
->setChecked(true);
2669 _mapView
->showCursorCoordinates(true);
2671 activeMap
= READ(activeMap
).toString();
2672 settings
.endGroup();
2675 settings
.beginGroup(SETTINGS_GRAPH
);
2676 if (READ(showGraphs
).toBool())
2677 _showGraphsAction
->setChecked(true);
2681 GraphType gt
= (GraphType
)READ(graphType
).toInt();
2683 _timeGraphAction
->setChecked(true);
2685 _distanceGraphAction
->setChecked(true);
2688 if (READ(showGrid
).toBool())
2689 _showGraphGridAction
->setChecked(true);
2691 showGraphGrids(false);
2693 if (READ(sliderInfo
).toBool())
2694 _showGraphSliderInfoAction
->setChecked(true);
2696 showGraphSliderInfo(false);
2699 if (READ(showGraphTabs
).toBool())
2700 _showGraphTabsAction
->setChecked(true);
2702 showGraphTabs(false);
2703 #endif // Q_OS_ANDROID
2704 settings
.endGroup();
2707 settings
.beginGroup(SETTINGS_POI
);
2708 if (READ(poiOverlap
).toBool()) {
2709 _overlapPOIAction
->setChecked(true);
2710 _mapView
->showOverlappedPOIs(true);
2712 if (READ(poiIcons
).toBool()) {
2713 _showPOIIconsAction
->setChecked(true);
2714 _mapView
->showPOIIcons(true);
2716 if (READ(poiLabels
).toBool()) {
2717 _showPOILabelsAction
->setChecked(true);
2718 _mapView
->showPOILabels(true);
2720 if (READ(showPoi
).toBool()) {
2721 _showPOIAction
->setChecked(true);
2722 _mapView
->showPOI(true);
2724 disabledPOIs
= READ(disabledPoiFiles
);
2725 settings
.endGroup();
2728 settings
.beginGroup(SETTINGS_DATA
);
2729 if (READ(tracks
).toBool()) {
2730 _showTracksAction
->setChecked(true);
2731 _mapView
->showTracks(true);
2732 for (int i
= 0; i
< _tabs
.count(); i
++)
2733 _tabs
.at(i
)->showTracks(true);
2735 if (READ(routes
).toBool()) {
2736 _showRoutesAction
->setChecked(true);
2737 _mapView
->showRoutes(true);
2738 for (int i
= 0; i
< _tabs
.count(); i
++)
2739 _tabs
.at(i
)->showRoutes(true);
2741 if (READ(waypoints
).toBool()) {
2742 _showWaypointsAction
->setChecked(true);
2743 _mapView
->showWaypoints(true);
2745 if (READ(areas
).toBool()) {
2746 _showAreasAction
->setChecked(true);
2747 _mapView
->showAreas(true);
2749 if (READ(waypointIcons
).toBool()) {
2750 _showWaypointIconsAction
->setChecked(true);
2751 _mapView
->showWaypointIcons(true);
2753 if (READ(waypointLabels
).toBool()) {
2754 _showWaypointLabelsAction
->setChecked(true);
2755 _mapView
->showWaypointLabels(true);
2757 if (READ(routeWaypoints
).toBool()) {
2758 _showRouteWaypointsAction
->setChecked(true);
2759 _mapView
->showRouteWaypoints(true);
2761 if (READ(pathTicks
).toBool()) {
2762 _showTicksAction
->setChecked(true);
2763 _mapView
->showTicks(true);
2765 if (READ(useStyles
).toBool()) {
2766 _useStylesAction
->setChecked(true);
2767 _mapView
->useStyles(true);
2769 if (READ(positionMarkers
).toBool()) {
2770 MarkerInfoItem::Type mt
= (MarkerInfoItem::Type
)READ(markerInfo
).toInt();
2771 if (mt
== MarkerInfoItem::Position
)
2772 _showMarkerCoordinatesAction
->setChecked(true);
2773 else if (mt
== MarkerInfoItem::Date
)
2774 _showMarkerDateAction
->setChecked(true);
2776 _showMarkersAction
->setChecked(true);
2778 _mapView
->showMarkers(true);
2779 _mapView
->showMarkerInfo(mt
);
2781 _hideMarkersAction
->setChecked(true);
2782 settings
.endGroup();
2785 settings
.beginGroup(SETTINGS_POSITION
);
2786 if (READ(showPosition
).toBool()) {
2787 _showPositionAction
->setChecked(true);
2788 _mapView
->showPosition(true);
2790 if (READ(followPosition
).toBool()) {
2791 _followPositionAction
->setChecked(true);
2792 _mapView
->followPosition(true);
2794 if (READ(positionCoordinates
).toBool()) {
2795 _showPositionCoordinatesAction
->setChecked(true);
2796 _mapView
->showPositionCoordinates(true);
2798 if (READ(motionInfo
).toBool()) {
2799 _showMotionInfoAction
->setChecked(true);
2800 _mapView
->showMotionInfo(true);
2802 settings
.endGroup();
2805 settings
.beginGroup(SETTINGS_PDF_EXPORT
);
2806 _pdfExport
.orientation
= (QPageLayout::Orientation
)READ(pdfOrientation
)
2808 _pdfExport
.resolution
= READ(pdfResolution
).toInt();
2809 _pdfExport
.paperSize
= (QPageSize::PageSizeId
)READ(pdfSize
).toInt();
2810 _pdfExport
.margins
= QMarginsF(READ(pdfMarginLeft
).toReal(),
2811 READ(pdfMarginTop
).toReal(), READ(pdfMarginRight
).toReal(),
2812 READ(pdfMarginBottom
).toReal());
2813 _pdfExport
.fileName
= READ(pdfFileName
).toString();
2814 settings
.endGroup();
2817 settings
.beginGroup(SETTINGS_PNG_EXPORT
);
2818 _pngExport
.size
= QSize(READ(pngWidth
).toInt(), READ(pngHeight
).toInt());
2819 _pngExport
.margins
= QMargins(READ(pngMarginLeft
).toInt(),
2820 READ(pngMarginTop
).toInt(), READ(pngMarginRight
).toInt(),
2821 READ(pngMarginBottom
).toInt());
2822 _pngExport
.antialiasing
= READ(pngAntialiasing
).toBool();
2823 _pngExport
.fileName
= READ(pngFileName
).toString();
2824 settings
.endGroup();
2827 settings
.beginGroup(SETTINGS_OPTIONS
);
2828 _options
.palette
= Palette(READ(paletteColor
).value
<QColor
>(),
2829 READ(paletteShift
).toDouble());
2830 _options
.mapOpacity
= READ(mapOpacity
).toInt();
2831 _options
.backgroundColor
= READ(backgroundColor
).value
<QColor
>();
2832 _options
.crosshairColor
= READ(crosshairColor
).value
<QColor
>();
2833 _options
.infoColor
= READ(infoColor
).value
<QColor
>();
2834 _options
.infoBackground
= READ(infoBackground
).toBool();
2835 _options
.trackWidth
= READ(trackWidth
).toInt();
2836 _options
.routeWidth
= READ(routeWidth
).toInt();
2837 _options
.areaWidth
= READ(areaWidth
).toInt();
2838 _options
.trackStyle
= (Qt::PenStyle
)READ(trackStyle
).toInt();
2839 _options
.routeStyle
= (Qt::PenStyle
)READ(routeStyle
).toInt();
2840 _options
.areaStyle
= (Qt::PenStyle
)READ(areaStyle
).toInt();
2841 _options
.areaOpacity
= READ(areaOpacity
).toInt();
2842 _options
.pathAntiAliasing
= READ(pathAntiAliasing
).toBool();
2843 _options
.waypointSize
= READ(waypointSize
).toInt();
2844 _options
.waypointColor
= READ(waypointColor
).value
<QColor
>();
2845 _options
.poiSize
= READ(poiSize
).toInt();
2846 _options
.poiColor
= READ(poiColor
).value
<QColor
>();
2847 _options
.graphWidth
= READ(graphWidth
).toInt();
2848 _options
.graphAntiAliasing
= READ(graphAntiAliasing
).toBool();
2849 _options
.elevationFilter
= READ(elevationFilter
).toInt();
2850 _options
.speedFilter
= READ(speedFilter
).toInt();
2851 _options
.heartRateFilter
= READ(heartRateFilter
).toInt();
2852 _options
.cadenceFilter
= READ(cadenceFilter
).toInt();
2853 _options
.powerFilter
= READ(powerFilter
).toInt();
2854 _options
.outlierEliminate
= READ(outlierEliminate
).toBool();
2855 _options
.pauseSpeed
= READ(pauseSpeed
).toFloat();
2856 _options
.automaticPause
= READ(automaticPause
).toBool();
2857 _options
.pauseInterval
= READ(pauseInterval
).toInt();
2858 _options
.useReportedSpeed
= READ(useReportedSpeed
).toBool();
2859 _options
.dataUseDEM
= READ(dataUseDEM
).toBool();
2860 _options
.showSecondaryElevation
= READ(secondaryElevation
).toBool();
2861 _options
.showSecondarySpeed
= READ(secondarySpeed
).toBool();
2862 _options
.timeZone
= READ(timeZone
).value
<TimeZoneInfo
>();
2863 _options
.useSegments
= READ(useSegments
).toBool();
2864 _options
.poiRadius
= READ(poiRadius
).toInt();
2865 _options
.demURL
= READ(demURL
).toString();
2866 _options
.demAuthorization
= READ(demAuthentication
).toBool();
2867 _options
.demUsername
= READ(demUsername
).toString();
2868 _options
.demPassword
= READ(demPassword
).toString();
2869 _options
.plugin
= READ(positionPlugin()).toString();
2870 _options
.pluginParams
= READ(positionPluginParameters
);
2871 _options
.useOpenGL
= READ(useOpenGL
).toBool();
2872 _options
.enableHTTP2
= READ(enableHTTP2
).toBool();
2873 _options
.pixmapCache
= READ(pixmapCache
).toInt();
2874 _options
.demCache
= READ(demCache
).toInt();
2875 _options
.connectionTimeout
= READ(connectionTimeout
).toInt();
2876 _options
.hiresPrint
= READ(hiresPrint
).toBool();
2877 _options
.printName
= READ(printName
).toBool();
2878 _options
.printDate
= READ(printDate
).toBool();
2879 _options
.printDistance
= READ(printDistance
).toBool();
2880 _options
.printTime
= READ(printTime
).toBool();
2881 _options
.printMovingTime
= READ(printMovingTime
).toBool();
2882 _options
.printItemCount
= READ(printItemCount
).toBool();
2883 _options
.separateGraphPage
= READ(separateGraphPage
).toBool();
2884 _options
.sliderColor
= READ(sliderColor
).value
<QColor
>();
2885 _options
.outputProjection
= READ(outputProjection
).toInt();
2886 _options
.inputProjection
= READ(inputProjection
).toInt();
2887 _options
.hidpiMap
= READ(hidpiMap
).toBool();
2888 _options
.dataPath
= READ(dataPath
).toString();
2889 _options
.mapsPath
= READ(mapsPath
).toString();
2890 _options
.poiPath
= READ(poiPath
).toString();
2891 settings
.endGroup();
2896 void GUI::loadOptions()
2898 _positionSource
= positionSource(_options
);
2899 _showPositionAction
->setEnabled(_positionSource
!= 0);
2901 _mapView
->setPalette(_options
.palette
);
2902 _mapView
->setMapOpacity(_options
.mapOpacity
);
2903 _mapView
->setBackgroundColor(_options
.backgroundColor
);
2904 _mapView
->setCrosshairColor(_options
.crosshairColor
);
2905 _mapView
->setInfoColor(_options
.infoColor
);
2906 _mapView
->drawInfoBackground(_options
.infoBackground
);
2907 _mapView
->setTrackWidth(_options
.trackWidth
);
2908 _mapView
->setRouteWidth(_options
.routeWidth
);
2909 _mapView
->setAreaWidth(_options
.areaWidth
);
2910 _mapView
->setTrackStyle(_options
.trackStyle
);
2911 _mapView
->setRouteStyle(_options
.routeStyle
);
2912 _mapView
->setAreaStyle(_options
.areaStyle
);
2913 _mapView
->setAreaOpacity(_options
.areaOpacity
);
2914 _mapView
->setWaypointSize(_options
.waypointSize
);
2915 _mapView
->setWaypointColor(_options
.waypointColor
);
2916 _mapView
->setPOISize(_options
.poiSize
);
2917 _mapView
->setPOIColor(_options
.poiColor
);
2918 _mapView
->setRenderHint(QPainter::Antialiasing
, _options
.pathAntiAliasing
);
2919 _mapView
->setMarkerColor(_options
.sliderColor
);
2920 _mapView
->useOpenGL(_options
.useOpenGL
);
2921 _mapView
->setMapConfig(CRS::projection(_options
.inputProjection
),
2922 CRS::projection(4326, _options
.outputProjection
), _options
.hidpiMap
);
2923 _mapView
->setTimeZone(_options
.timeZone
.zone());
2924 _mapView
->setPositionSource(_positionSource
);
2926 for (int i
= 0; i
< _tabs
.count(); i
++) {
2927 _tabs
.at(i
)->setPalette(_options
.palette
);
2928 _tabs
.at(i
)->setGraphWidth(_options
.graphWidth
);
2929 _tabs
.at(i
)->setRenderHint(QPainter::Antialiasing
,
2930 _options
.graphAntiAliasing
);
2931 _tabs
.at(i
)->setSliderColor(_options
.sliderColor
);
2932 if (_options
.useOpenGL
)
2933 _tabs
.at(i
)->useOpenGL(true);
2936 Track::setElevationFilter(_options
.elevationFilter
);
2937 Track::setSpeedFilter(_options
.speedFilter
);
2938 Track::setHeartRateFilter(_options
.heartRateFilter
);
2939 Track::setCadenceFilter(_options
.cadenceFilter
);
2940 Track::setPowerFilter(_options
.powerFilter
);
2941 Track::setOutlierElimination(_options
.outlierEliminate
);
2942 Track::setAutomaticPause(_options
.automaticPause
);
2943 Track::setPauseSpeed(_options
.pauseSpeed
);
2944 Track::setPauseInterval(_options
.pauseInterval
);
2945 Track::useReportedSpeed(_options
.useReportedSpeed
);
2946 Track::useDEM(_options
.dataUseDEM
);
2947 Track::showSecondaryElevation(_options
.showSecondaryElevation
);
2948 Track::showSecondarySpeed(_options
.showSecondarySpeed
);
2949 Track::useSegments(_options
.useSegments
);
2950 Route::useDEM(_options
.dataUseDEM
);
2951 Route::showSecondaryElevation(_options
.showSecondaryElevation
);
2952 Waypoint::useDEM(_options
.dataUseDEM
);
2953 Waypoint::showSecondaryElevation(_options
.showSecondaryElevation
);
2955 Downloader::enableHTTP2(_options
.enableHTTP2
);
2956 Downloader::setTimeout(_options
.connectionTimeout
);
2958 QPixmapCache::setCacheLimit(_options
.pixmapCache
* 1024);
2959 DEM::setCacheSize(_options
.demCache
* 1024);
2961 _poi
->setRadius(_options
.poiRadius
);
2963 _dem
->setUrl(_options
.demURL
);
2964 if (_options
.demAuthorization
)
2965 _dem
->setAuthorization(Authorization(_options
.demUsername
,
2966 _options
.demPassword
));
2968 _dataDir
= _options
.dataPath
;
2969 _mapDir
= _options
.mapsPath
;
2970 _poiDir
= _options
.poiPath
;
2973 void GUI::updateOptions(const Options
&options
)
2975 #define SET_VIEW_OPTION(option, action) \
2976 if (options.option != _options.option) \
2977 _mapView->action(options.option)
2978 #define SET_TAB_OPTION(option, action) \
2979 if (options.option != _options.option) \
2980 for (int i = 0; i < _tabs.count(); i++) \
2981 _tabs.at(i)->action(options.option)
2982 #define SET_TRACK_OPTION(option, action) \
2983 if (options.option != _options.option) { \
2984 Track::action(options.option); \
2987 #define SET_ROUTE_OPTION(option, action) \
2988 if (options.option != _options.option) { \
2989 Route::action(options.option); \
2992 #define SET_WAYPOINT_OPTION(option, action) \
2993 if (options.option != _options.option) { \
2994 Waypoint::action(options.option); \
2998 bool reload
= false;
3000 SET_VIEW_OPTION(palette
, setPalette
);
3001 SET_VIEW_OPTION(mapOpacity
, setMapOpacity
);
3002 SET_VIEW_OPTION(backgroundColor
, setBackgroundColor
);
3003 SET_VIEW_OPTION(trackWidth
, setTrackWidth
);
3004 SET_VIEW_OPTION(routeWidth
, setRouteWidth
);
3005 SET_VIEW_OPTION(areaWidth
, setAreaWidth
);
3006 SET_VIEW_OPTION(trackStyle
, setTrackStyle
);
3007 SET_VIEW_OPTION(routeStyle
, setRouteStyle
);
3008 SET_VIEW_OPTION(areaStyle
, setAreaStyle
);
3009 SET_VIEW_OPTION(areaOpacity
, setAreaOpacity
);
3010 SET_VIEW_OPTION(waypointSize
, setWaypointSize
);
3011 SET_VIEW_OPTION(waypointColor
, setWaypointColor
);
3012 SET_VIEW_OPTION(poiSize
, setPOISize
);
3013 SET_VIEW_OPTION(poiColor
, setPOIColor
);
3014 SET_VIEW_OPTION(pathAntiAliasing
, useAntiAliasing
);
3015 SET_VIEW_OPTION(useOpenGL
, useOpenGL
);
3016 SET_VIEW_OPTION(sliderColor
, setMarkerColor
);
3017 SET_VIEW_OPTION(crosshairColor
, setCrosshairColor
);
3018 SET_VIEW_OPTION(infoColor
, setInfoColor
);
3019 SET_VIEW_OPTION(infoBackground
, drawInfoBackground
);
3021 if (options
.plugin
!= _options
.plugin
3022 || options
.pluginParams
.value(options
.plugin
)
3023 != _options
.pluginParams
.value(_options
.plugin
)) {
3024 QGeoPositionInfoSource
*source
= positionSource(options
);
3025 _showPositionAction
->setEnabled(source
!= 0);
3026 _mapView
->setPositionSource(source
);
3027 delete _positionSource
;
3028 _positionSource
= source
;
3031 if (options
.hidpiMap
!= _options
.hidpiMap
3032 || options
.outputProjection
!= _options
.outputProjection
3033 || options
.inputProjection
!= _options
.inputProjection
)
3034 _mapView
->setMapConfig(CRS::projection(options
.inputProjection
),
3035 CRS::projection(4326, options
.outputProjection
), options
.hidpiMap
);
3037 if (options
.timeZone
!= _options
.timeZone
) {
3038 _mapView
->setTimeZone(options
.timeZone
.zone());
3039 _dateRange
.first
= _dateRange
.first
.toTimeZone(options
.timeZone
.zone());
3040 _dateRange
.second
= _dateRange
.second
.toTimeZone(options
.timeZone
.zone());
3043 SET_TAB_OPTION(palette
, setPalette
);
3044 SET_TAB_OPTION(graphWidth
, setGraphWidth
);
3045 SET_TAB_OPTION(graphAntiAliasing
, useAntiAliasing
);
3046 SET_TAB_OPTION(useOpenGL
, useOpenGL
);
3047 SET_TAB_OPTION(sliderColor
, setSliderColor
);
3049 SET_TRACK_OPTION(elevationFilter
, setElevationFilter
);
3050 SET_TRACK_OPTION(speedFilter
, setSpeedFilter
);
3051 SET_TRACK_OPTION(heartRateFilter
, setHeartRateFilter
);
3052 SET_TRACK_OPTION(cadenceFilter
, setCadenceFilter
);
3053 SET_TRACK_OPTION(powerFilter
, setPowerFilter
);
3054 SET_TRACK_OPTION(outlierEliminate
, setOutlierElimination
);
3055 SET_TRACK_OPTION(automaticPause
, setAutomaticPause
);
3056 SET_TRACK_OPTION(pauseSpeed
, setPauseSpeed
);
3057 SET_TRACK_OPTION(pauseInterval
, setPauseInterval
);
3058 SET_TRACK_OPTION(useReportedSpeed
, useReportedSpeed
);
3059 SET_TRACK_OPTION(dataUseDEM
, useDEM
);
3060 SET_TRACK_OPTION(showSecondaryElevation
, showSecondaryElevation
);
3061 SET_TRACK_OPTION(showSecondarySpeed
, showSecondarySpeed
);
3062 SET_TRACK_OPTION(useSegments
, useSegments
);
3064 SET_ROUTE_OPTION(dataUseDEM
, useDEM
);
3065 SET_ROUTE_OPTION(showSecondaryElevation
, showSecondaryElevation
);
3067 SET_WAYPOINT_OPTION(dataUseDEM
, useDEM
);
3068 SET_WAYPOINT_OPTION(showSecondaryElevation
, showSecondaryElevation
);
3070 if (options
.poiRadius
!= _options
.poiRadius
)
3071 _poi
->setRadius(options
.poiRadius
);
3073 if (options
.demURL
!= _options
.demURL
)
3074 _dem
->setUrl(options
.demURL
);
3075 if (options
.demAuthorization
!= _options
.demAuthorization
3076 || options
.demUsername
!= _options
.demUsername
3077 || options
.demPassword
!= _options
.demPassword
)
3078 _dem
->setAuthorization(options
.demAuthorization
3079 ? Authorization(options
.demUsername
, options
.demPassword
)
3082 if (options
.pixmapCache
!= _options
.pixmapCache
)
3083 QPixmapCache::setCacheLimit(options
.pixmapCache
* 1024);
3084 if (options
.demCache
!= _options
.demCache
)
3085 DEM::setCacheSize(options
.demCache
* 1024);
3087 if (options
.connectionTimeout
!= _options
.connectionTimeout
)
3088 Downloader::setTimeout(options
.connectionTimeout
);
3089 if (options
.enableHTTP2
!= _options
.enableHTTP2
)
3090 Downloader::enableHTTP2(options
.enableHTTP2
);
3092 if (options
.dataPath
!= _options
.dataPath
)
3093 _dataDir
= options
.dataPath
;
3094 if (options
.mapsPath
!= _options
.mapsPath
)
3095 _mapDir
= options
.mapsPath
;
3096 if (options
.poiPath
!= _options
.poiPath
)
3097 _poiDir
= options
.poiPath
;
3104 updateDEMDownloadAction();
3107 void GUI::loadInitialMaps(const QString
&selected
)
3110 QString
mapDir(ProgramPaths::mapDir());
3111 if (mapDir
.isNull())
3114 TreeNode
<Map
*> maps(MapList::loadMaps(mapDir
, _mapView
->inputProjection()));
3115 createMapNodeMenu(createMapActionsNode(maps
), _mapMenu
, _mapsEnd
);
3117 // Select the active map according to the user settings
3118 QAction
*ma
= mapAction(selected
);
3121 _showMapAction
->setEnabled(true);
3122 _clearMapCacheAction
->setEnabled(true);
3126 void GUI::loadInitialPOIs(const QStringList
&disabled
)
3128 // Load the POI files
3129 QString
poiDir(ProgramPaths::poiDir());
3130 if (poiDir
.isNull())
3133 TreeNode
<QString
> poiFiles(_poi
->loadDir(poiDir
));
3134 createPOINodeMenu(createPOIActionsNode(poiFiles
), _poiMenu
, _poisEnd
);
3136 // Enable/disable the files according to the user settings
3137 QList
<QAction
*> poiActions(_poisActionGroup
->actions());
3138 for (int i
= 0; i
< poiActions
.count(); i
++)
3139 poiActions
.at(i
)->setChecked(true);
3140 for (int i
= 0; i
< disabled
.size(); i
++) {
3141 const QString
&file
= disabled
.at(i
);
3142 if (_poi
->enableFile(file
, false)) {
3143 for (int j
= 0; j
< poiActions
.size(); j
++)
3144 if (poiActions
.at(j
)->data().toString() == file
)
3145 poiActions
.at(j
)->setChecked(false);
3149 _selectAllPOIAction
->setEnabled(!poiActions
.isEmpty());
3150 _unselectAllPOIAction
->setEnabled(!poiActions
.isEmpty());
3153 #ifndef Q_OS_ANDROID
3154 void GUI::loadRecentFiles(const QStringList
&files
)
3156 QAction
*before
= _recentFilesEnd
;
3158 for (int i
= 0; i
< files
.size(); i
++) {
3159 QAction
*a
= new QAction(files
.at(i
), _recentFilesActionGroup
);
3160 _recentFilesMenu
->insertAction(before
, a
);
3164 if (!files
.isEmpty())
3165 _recentFilesMenu
->setEnabled(true);
3167 #endif // Q_OS_ANDROID
3169 QAction
*GUI::mapAction(const QString
&name
)
3171 QList
<QAction
*> maps(_mapsActionGroup
->actions());
3174 for (int i
= 0; i
< maps
.count(); i
++) {
3175 Map
*map
= maps
.at(i
)->data().value
<Map
*>();
3176 if (map
->name() == name
&& map
->isReady())
3181 for (int i
= 0; i
< maps
.count(); i
++) {
3182 Map
*map
= maps
.at(i
)->data().value
<Map
*>();
3190 Units
GUI::units() const
3192 return _imperialUnitsAction
->isChecked() ? Imperial
3193 : _nauticalUnitsAction
->isChecked() ? Nautical
: Metric
;
3196 qreal
GUI::distance() const
3200 if (_showTracksAction
->isChecked())
3201 dist
+= _trackDistance
;
3202 if (_showRoutesAction
->isChecked())
3203 dist
+= _routeDistance
;
3208 qreal
GUI::time() const
3210 return (_showTracksAction
->isChecked()) ? _time
: 0;
3213 qreal
GUI::movingTime() const
3215 return (_showTracksAction
->isChecked()) ? _movingTime
: 0;
3220 QMainWindow::show();
3222 QWindow
*w
= windowHandle();
3223 connect(w
->screen(), &QScreen::logicalDotsPerInchChanged
, this,
3224 &GUI::logicalDotsPerInchChanged
);
3225 connect(w
, &QWindow::screenChanged
, this, &GUI::screenChanged
);
3227 _mapView
->fitContentToSize();
3230 void GUI::screenChanged(QScreen
*screen
)
3232 _mapView
->setDevicePixelRatio(devicePixelRatioF());
3234 disconnect(SIGNAL(logicalDotsPerInchChanged(qreal
)), this,
3235 SLOT(logicalDotsPerInchChanged(qreal
)));
3236 connect(screen
, &QScreen::logicalDotsPerInchChanged
, this,
3237 &GUI::logicalDotsPerInchChanged
);
3240 void GUI::logicalDotsPerInchChanged(qreal dpi
)
3244 _mapView
->setDevicePixelRatio(devicePixelRatioF());