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"
57 #include "navigationwidget.h"
61 #define MAX_RECENT_FILES 10
62 #define TOOLBAR_ICON_SIZE 22
67 QStringList disabledPOIs
, recentFiles
;
70 _dem
= new DEMLoader(ProgramPaths::demDir(true), this);
71 connect(_dem
, &DEMLoader::finished
, this, &GUI::demLoaded
);
82 #endif // Q_OS_ANDROID
85 _splitter
= new QSplitter();
86 _splitter
->setOrientation(Qt::Vertical
);
87 _splitter
->setChildrenCollapsible(false);
88 _splitter
->addWidget(_mapView
);
89 _splitter
->addWidget(_graphTabWidget
);
90 _splitter
->setContentsMargins(0, 0, 0, 0);
91 _splitter
->setStretchFactor(0, 255);
92 _splitter
->setStretchFactor(1, 1);
94 setCentralWidget(_splitter
);
96 setWindowIcon(QIcon(APP_ICON
));
97 setWindowTitle(APP_NAME
);
98 setUnifiedTitleAndToolBarOnMac(true);
111 readSettings(activeMap
, disabledPOIs
, recentFiles
);
113 loadInitialMaps(activeMap
);
114 loadInitialPOIs(disabledPOIs
);
116 loadRecentFiles(recentFiles
);
117 #endif // Q_OS_ANDROID
120 updateStatusBarInfo();
123 void GUI::createBrowser()
125 _browser
= new FileBrowser(this);
126 _browser
->setFilter(Data::filter());
127 connect(_browser
, &FileBrowser::listChanged
, this,
128 &GUI::updateNavigationActions
);
131 TreeNode
<MapAction
*> GUI::createMapActionsNode(const TreeNode
<Map
*> &node
)
133 TreeNode
<MapAction
*> tree(node
.name());
135 for (int i
= 0; i
< node
.childs().size(); i
++)
136 tree
.addChild(createMapActionsNode(node
.childs().at(i
)));
138 for (int i
= 0; i
< node
.items().size(); i
++) {
139 Map
*map
= node
.items().at(i
);
140 if (map
->isValid()) {
141 MapAction
*a
= new MapAction(map
, _mapsActionGroup
);
142 connect(a
, &MapAction::loaded
, this, &GUI::mapInitialized
);
151 void GUI::mapInitialized()
153 MapAction
*action
= static_cast<MapAction
*>(QObject::sender());
154 Map
*map
= action
->data().value
<Map
*>();
156 if (map
->isValid()) {
157 if (!_mapsActionGroup
->checkedAction())
159 _showMapAction
->setEnabled(true);
160 _clearMapCacheAction
->setEnabled(true);
162 qWarning("%s: %s", qPrintable(map
->path()), qPrintable(map
->errorString()));
163 action
->deleteLater();
167 TreeNode
<POIAction
*> GUI::createPOIActionsNode(const TreeNode
<QString
> &node
)
169 TreeNode
<POIAction
*> tree(node
.name());
171 for (int i
= 0; i
< node
.childs().size(); i
++)
172 tree
.addChild(createPOIActionsNode(node
.childs().at(i
)));
173 for (int i
= 0; i
< node
.items().size(); i
++)
174 tree
.addItem(new POIAction(node
.items().at(i
), _poisActionGroup
));
179 void GUI::createActions()
184 _fileActionGroup
= new QActionGroup(this);
185 _fileActionGroup
->setExclusive(false);
186 _fileActionGroup
->setEnabled(false);
188 _navigationActionGroup
= new QActionGroup(this);
189 _navigationActionGroup
->setEnabled(false);
192 #if !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID)
193 _exitAction
= new QAction(QIcon::fromTheme(QUIT_NAME
, QIcon(QUIT_ICON
)),
195 _exitAction
->setShortcut(QUIT_SHORTCUT
);
196 _exitAction
->setMenuRole(QAction::QuitRole
);
197 connect(_exitAction
, &QAction::triggered
, this, &GUI::close
);
198 addAction(_exitAction
);
199 #endif // Q_OS_MAC + Q_OS_ANDROID
202 _pathsAction
= new QAction(tr("Paths"), this);
203 _pathsAction
->setMenuRole(QAction::NoRole
);
204 connect(_pathsAction
, &QAction::triggered
, this, &GUI::paths
);
206 _keysAction
= new QAction(tr("Keyboard controls"), this);
207 _keysAction
->setMenuRole(QAction::NoRole
);
208 connect(_keysAction
, &QAction::triggered
, this, &GUI::keys
);
209 #endif // Q_OS_ANDROID
210 _aboutAction
= new QAction(QIcon(APP_ICON
), tr("About GPXSee"), this);
211 _aboutAction
->setMenuRole(QAction::AboutRole
);
212 connect(_aboutAction
, &QAction::triggered
, this, &GUI::about
);
215 _openFileAction
= new QAction(QIcon::fromTheme(OPEN_FILE_NAME
,
216 QIcon(OPEN_FILE_ICON
)), tr("Open..."), this);
217 _openFileAction
->setMenuRole(QAction::NoRole
);
218 _openFileAction
->setShortcut(OPEN_SHORTCUT
);
219 connect(_openFileAction
, &QAction::triggered
, this,
220 QOverload
<>::of(&GUI::openFile
));
221 addAction(_openFileAction
);
222 _openDirAction
= new QAction(QIcon::fromTheme(OPEN_DIR_NAME
,
223 QIcon(OPEN_DIR_ICON
)), tr("Open directory..."), this);
224 _openDirAction
->setMenuRole(QAction::NoRole
);
225 connect(_openDirAction
, &QAction::triggered
, this,
226 QOverload
<>::of(&GUI::openDir
));
227 _printFileAction
= new QAction(QIcon::fromTheme(PRINT_FILE_NAME
,
228 QIcon(PRINT_FILE_ICON
)), tr("Print..."), this);
229 _printFileAction
->setMenuRole(QAction::NoRole
);
230 _printFileAction
->setActionGroup(_fileActionGroup
);
231 connect(_printFileAction
, &QAction::triggered
, this, &GUI::printFile
);
232 addAction(_printFileAction
);
233 _exportPDFFileAction
= new QAction(QIcon::fromTheme(EXPORT_FILE_NAME
,
234 QIcon(EXPORT_FILE_ICON
)), tr("Export to PDF..."), this);
235 _exportPDFFileAction
->setMenuRole(QAction::NoRole
);
236 _exportPDFFileAction
->setShortcut(PDF_EXPORT_SHORTCUT
);
237 _exportPDFFileAction
->setActionGroup(_fileActionGroup
);
238 connect(_exportPDFFileAction
, &QAction::triggered
, this, &GUI::exportPDFFile
);
239 addAction(_exportPDFFileAction
);
240 _exportPNGFileAction
= new QAction(QIcon::fromTheme(EXPORT_FILE_NAME
,
241 QIcon(EXPORT_FILE_ICON
)), tr("Export to PNG..."), this);
242 _exportPNGFileAction
->setMenuRole(QAction::NoRole
);
243 _exportPNGFileAction
->setShortcut(PNG_EXPORT_SHORTCUT
);
244 _exportPNGFileAction
->setActionGroup(_fileActionGroup
);
245 connect(_exportPNGFileAction
, &QAction::triggered
, this, &GUI::exportPNGFile
);
246 addAction(_exportPNGFileAction
);
247 _closeFileAction
= new QAction(QIcon::fromTheme(CLOSE_FILE_NAME
,
248 QIcon(CLOSE_FILE_ICON
)), tr("Close"), this);
249 _closeFileAction
->setMenuRole(QAction::NoRole
);
250 _closeFileAction
->setShortcut(CLOSE_SHORTCUT
);
251 _closeFileAction
->setActionGroup(_fileActionGroup
);
252 connect(_closeFileAction
, &QAction::triggered
, this, &GUI::closeAll
);
253 addAction(_closeFileAction
);
254 _reloadFileAction
= new QAction(QIcon::fromTheme(RELOAD_FILE_NAME
,
255 QIcon(RELOAD_FILE_ICON
)), tr("Reload"), this);
256 _reloadFileAction
->setMenuRole(QAction::NoRole
);
257 _reloadFileAction
->setShortcut(RELOAD_SHORTCUT
);
258 _reloadFileAction
->setActionGroup(_fileActionGroup
);
259 connect(_reloadFileAction
, &QAction::triggered
, this, &GUI::reloadFiles
);
260 addAction(_reloadFileAction
);
261 _statisticsAction
= new QAction(tr("Statistics..."), this);
262 _statisticsAction
->setMenuRole(QAction::NoRole
);
263 _statisticsAction
->setShortcut(STATISTICS_SHORTCUT
);
264 _statisticsAction
->setActionGroup(_fileActionGroup
);
265 connect(_statisticsAction
, &QAction::triggered
, this, &GUI::statistics
);
266 addAction(_statisticsAction
);
268 _recentFilesActionGroup
= new QActionGroup(this);
269 connect(_recentFilesActionGroup
, &QActionGroup::triggered
, this,
270 &GUI::recentFileSelected
);
271 _clearRecentFilesAction
= new QAction(tr("Clear list"), this);
272 _clearRecentFilesAction
->setMenuRole(QAction::NoRole
);
273 connect(_clearRecentFilesAction
, &QAction::triggered
, this,
274 &GUI::clearRecentFiles
);
275 #endif // Q_OS_ANDROID
278 _poisActionGroup
= new QActionGroup(this);
279 _poisActionGroup
->setExclusive(false);
280 connect(_poisActionGroup
, &QActionGroup::triggered
, this,
281 &GUI::poiFileChecked
);
282 _openPOIAction
= new QAction(QIcon::fromTheme(OPEN_FILE_NAME
,
283 QIcon(OPEN_FILE_ICON
)), tr("Load POI file..."), this);
284 _openPOIAction
->setMenuRole(QAction::NoRole
);
285 connect(_openPOIAction
, &QAction::triggered
, this,
286 QOverload
<>::of(&GUI::openPOIFile
));
287 _selectAllPOIAction
= new QAction(tr("Select all files"), this);
288 _selectAllPOIAction
->setMenuRole(QAction::NoRole
);
289 _selectAllPOIAction
->setEnabled(false);
290 connect(_selectAllPOIAction
, &QAction::triggered
, this,
291 &GUI::selectAllPOIs
);
292 _unselectAllPOIAction
= new QAction(tr("Unselect all files"), this);
293 _unselectAllPOIAction
->setMenuRole(QAction::NoRole
);
294 _unselectAllPOIAction
->setEnabled(false);
295 connect(_unselectAllPOIAction
, &QAction::triggered
, this,
296 &GUI::unselectAllPOIs
);
297 _overlapPOIAction
= new QAction(tr("Overlap POIs"), this);
298 _overlapPOIAction
->setMenuRole(QAction::NoRole
);
299 _overlapPOIAction
->setCheckable(true);
300 connect(_overlapPOIAction
, &QAction::triggered
, _mapView
,
301 &MapView::showOverlappedPOIs
);
302 _showPOIIconsAction
= new QAction(tr("Show POI icons"), this);
303 _showPOIIconsAction
->setMenuRole(QAction::NoRole
);
304 _showPOIIconsAction
->setCheckable(true);
305 connect(_showPOIIconsAction
, &QAction::triggered
, _mapView
,
306 &MapView::showPOIIcons
);
307 _showPOILabelsAction
= new QAction(tr("Show POI labels"), this);
308 _showPOILabelsAction
->setMenuRole(QAction::NoRole
);
309 _showPOILabelsAction
->setCheckable(true);
310 connect(_showPOILabelsAction
, &QAction::triggered
, _mapView
,
311 &MapView::showPOILabels
);
312 _showPOIAction
= new QAction(QIcon::fromTheme(SHOW_POI_NAME
,
313 QIcon(SHOW_POI_ICON
)), tr("Show POIs"), this);
314 _showPOIAction
->setMenuRole(QAction::NoRole
);
315 _showPOIAction
->setCheckable(true);
316 _showPOIAction
->setShortcut(SHOW_POI_SHORTCUT
);
317 connect(_showPOIAction
, &QAction::triggered
, _mapView
, &MapView::showPOI
);
318 addAction(_showPOIAction
);
321 _mapsActionGroup
= new QActionGroup(this);
322 _mapsActionGroup
->setExclusive(true);
323 connect(_mapsActionGroup
, &QActionGroup::triggered
, this, &GUI::mapChanged
);
324 _showMapAction
= new QAction(QIcon::fromTheme(SHOW_MAP_NAME
,
325 QIcon(SHOW_MAP_ICON
)), tr("Show map"), this);
326 _showMapAction
->setEnabled(false);
327 _showMapAction
->setMenuRole(QAction::NoRole
);
328 _showMapAction
->setCheckable(true);
329 _showMapAction
->setShortcut(SHOW_MAP_SHORTCUT
);
330 connect(_showMapAction
, &QAction::triggered
, _mapView
,
332 addAction(_showMapAction
);
333 _loadMapAction
= new QAction(QIcon::fromTheme(OPEN_FILE_NAME
,
334 QIcon(OPEN_FILE_ICON
)), tr("Load map..."), this);
335 _loadMapAction
->setMenuRole(QAction::NoRole
);
336 connect(_loadMapAction
, &QAction::triggered
, this,
337 QOverload
<>::of(&GUI::loadMap
));
338 _loadMapDirAction
= new QAction(QIcon::fromTheme(OPEN_DIR_NAME
,
339 QIcon(OPEN_DIR_ICON
)), tr("Load map directory..."), this);
340 _loadMapDirAction
->setMenuRole(QAction::NoRole
);
341 connect(_loadMapDirAction
, &QAction::triggered
, this, &GUI::loadMapDir
);
342 _clearMapCacheAction
= new QAction(tr("Clear tile cache"), this);
343 _clearMapCacheAction
->setEnabled(false);
344 _clearMapCacheAction
->setMenuRole(QAction::NoRole
);
345 connect(_clearMapCacheAction
, &QAction::triggered
, this,
346 &GUI::clearMapCache
);
347 _nextMapAction
= new QAction(tr("Next map"), this);
348 _nextMapAction
->setMenuRole(QAction::NoRole
);
349 _nextMapAction
->setShortcut(NEXT_MAP_SHORTCUT
);
350 connect(_nextMapAction
, &QAction::triggered
, this, &GUI::nextMap
);
351 addAction(_nextMapAction
);
352 _prevMapAction
= new QAction(tr("Next map"), this);
353 _prevMapAction
->setMenuRole(QAction::NoRole
);
354 _prevMapAction
->setShortcut(PREV_MAP_SHORTCUT
);
355 connect(_prevMapAction
, &QAction::triggered
, this, &GUI::prevMap
);
356 addAction(_prevMapAction
);
357 _showCoordinatesAction
= new QAction(tr("Show cursor coordinates"), this);
358 _showCoordinatesAction
->setMenuRole(QAction::NoRole
);
359 _showCoordinatesAction
->setCheckable(true);
360 connect(_showCoordinatesAction
, &QAction::triggered
, _mapView
,
361 &MapView::showCursorCoordinates
);
364 _showPositionAction
= new QAction(QIcon::fromTheme(SHOW_POS_NAME
,
365 QIcon(SHOW_POS_ICON
)), tr("Show position"), this);
366 _showPositionAction
->setMenuRole(QAction::NoRole
);
367 _showPositionAction
->setCheckable(true);
368 _showPositionAction
->setEnabled(false);
369 connect(_showPositionAction
, &QAction::triggered
, _mapView
,
370 &MapView::showPosition
);
371 _followPositionAction
= new QAction(tr("Follow position"), this);
372 _followPositionAction
->setMenuRole(QAction::NoRole
);
373 _followPositionAction
->setCheckable(true);
374 connect(_followPositionAction
, &QAction::triggered
, _mapView
,
375 &MapView::followPosition
);
376 _showPositionCoordinatesAction
= new QAction(tr("Show coordinates"),
378 _showPositionCoordinatesAction
->setMenuRole(QAction::NoRole
);
379 _showPositionCoordinatesAction
->setCheckable(true);
380 connect(_showPositionCoordinatesAction
, &QAction::triggered
, _mapView
,
381 &MapView::showPositionCoordinates
);
382 _showMotionInfoAction
= new QAction(tr("Show motion info"), this);
383 _showMotionInfoAction
->setMenuRole(QAction::NoRole
);
384 _showMotionInfoAction
->setCheckable(true);
385 connect(_showMotionInfoAction
, &QAction::triggered
, _mapView
,
386 &MapView::showMotionInfo
);
389 _showTracksAction
= new QAction(tr("Show tracks"), this);
390 _showTracksAction
->setMenuRole(QAction::NoRole
);
391 _showTracksAction
->setCheckable(true);
392 _showTracksAction
->setShortcut(SHOW_TRACKS_SHORTCUT
);
393 connect(_showTracksAction
, &QAction::triggered
, this, &GUI::showTracks
);
394 _showRoutesAction
= new QAction(tr("Show routes"), this);
395 _showRoutesAction
->setMenuRole(QAction::NoRole
);
396 _showRoutesAction
->setCheckable(true);
397 connect(_showRoutesAction
, &QAction::triggered
, this, &GUI::showRoutes
);
398 _showWaypointsAction
= new QAction(tr("Show waypoints"), this);
399 _showWaypointsAction
->setMenuRole(QAction::NoRole
);
400 _showWaypointsAction
->setCheckable(true);
401 connect(_showWaypointsAction
, &QAction::triggered
, this,
402 &GUI::showWaypoints
);
403 _showAreasAction
= new QAction(tr("Show areas"), this);
404 _showAreasAction
->setMenuRole(QAction::NoRole
);
405 _showAreasAction
->setCheckable(true);
406 connect(_showAreasAction
, &QAction::triggered
, this, &GUI::showAreas
);
407 _showWaypointIconsAction
= new QAction(tr("Waypoint icons"), this);
408 _showWaypointIconsAction
->setMenuRole(QAction::NoRole
);
409 _showWaypointIconsAction
->setCheckable(true);
410 connect(_showWaypointIconsAction
, &QAction::triggered
, _mapView
,
411 &MapView::showWaypointIcons
);
412 _showWaypointLabelsAction
= new QAction(tr("Waypoint labels"), this);
413 _showWaypointLabelsAction
->setMenuRole(QAction::NoRole
);
414 _showWaypointLabelsAction
->setCheckable(true);
415 connect(_showWaypointLabelsAction
, &QAction::triggered
, _mapView
,
416 &MapView::showWaypointLabels
);
417 _showRouteWaypointsAction
= new QAction(tr("Route waypoints"), this);
418 _showRouteWaypointsAction
->setMenuRole(QAction::NoRole
);
419 _showRouteWaypointsAction
->setCheckable(true);
420 connect(_showRouteWaypointsAction
, &QAction::triggered
, _mapView
,
421 &MapView::showRouteWaypoints
);
422 _showTicksAction
= new QAction(tr("km/mi markers"), this);
423 _showTicksAction
->setMenuRole(QAction::NoRole
);
424 _showTicksAction
->setCheckable(true);
425 connect(_showTicksAction
, &QAction::triggered
, _mapView
,
426 &MapView::showTicks
);
427 QActionGroup
*markerInfoGroup
= new QActionGroup(this);
428 connect(markerInfoGroup
, &QActionGroup::triggered
, this,
429 &GUI::showPathMarkerInfo
);
430 _hideMarkersAction
= new QAction(tr("Do not show"), this);
431 _hideMarkersAction
->setMenuRole(QAction::NoRole
);
432 _hideMarkersAction
->setCheckable(true);
433 _hideMarkersAction
->setActionGroup(markerInfoGroup
);
434 _showMarkersAction
= new QAction(tr("Marker only"), this);
435 _showMarkersAction
->setMenuRole(QAction::NoRole
);
436 _showMarkersAction
->setCheckable(true);
437 _showMarkersAction
->setActionGroup(markerInfoGroup
);
438 _showMarkerDateAction
= new QAction(tr("Date/time"), this);
439 _showMarkerDateAction
->setMenuRole(QAction::NoRole
);
440 _showMarkerDateAction
->setCheckable(true);
441 _showMarkerDateAction
->setActionGroup(markerInfoGroup
);
442 _showMarkerCoordinatesAction
= new QAction(tr("Coordinates"), this);
443 _showMarkerCoordinatesAction
->setMenuRole(QAction::NoRole
);
444 _showMarkerCoordinatesAction
->setCheckable(true);
445 _showMarkerCoordinatesAction
->setActionGroup(markerInfoGroup
);
446 _useStylesAction
= new QAction(tr("Use styles"), this);
447 _useStylesAction
->setMenuRole(QAction::NoRole
);
448 _useStylesAction
->setCheckable(true);
449 connect(_useStylesAction
, &QAction::triggered
, _mapView
,
450 &MapView::useStyles
);
453 _downloadDEMAction
= new QAction(tr("Download DEM data"), this);
454 _downloadDEMAction
->setMenuRole(QAction::NoRole
);
455 _downloadDEMAction
->setEnabled(false);
456 _downloadDEMAction
->setShortcut(DOWNLOAD_DEM_SHORTCUT
);
457 connect(_downloadDEMAction
, &QAction::triggered
, this, &GUI::downloadDEM
);
458 _showDEMTilesAction
= new QAction(tr("Show local DEM tiles"), this);
459 _showDEMTilesAction
->setMenuRole(QAction::NoRole
);
460 connect(_showDEMTilesAction
, &QAction::triggered
, this, &GUI::showDEMTiles
);
463 _showGraphsAction
= new QAction(QIcon::fromTheme(SHOW_GRAPHS_NAME
,
464 QIcon(SHOW_GRAPHS_ICON
)), tr("Show graphs"), this);
465 _showGraphsAction
->setMenuRole(QAction::NoRole
);
466 _showGraphsAction
->setCheckable(true);
467 _showGraphsAction
->setShortcut(SHOW_GRAPHS_SHORTCUT
);
468 connect(_showGraphsAction
, &QAction::triggered
, this, &GUI::showGraphs
);
469 addAction(_showGraphsAction
);
470 ag
= new QActionGroup(this);
471 ag
->setExclusive(true);
472 _distanceGraphAction
= new QAction(tr("Distance"), this);
473 _distanceGraphAction
->setMenuRole(QAction::NoRole
);
474 _distanceGraphAction
->setCheckable(true);
475 _distanceGraphAction
->setActionGroup(ag
);
476 connect(_distanceGraphAction
, &QAction::triggered
, this,
477 &GUI::setDistanceGraph
);
478 addAction(_distanceGraphAction
);
479 _timeGraphAction
= new QAction(tr("Time"), this);
480 _timeGraphAction
->setMenuRole(QAction::NoRole
);
481 _timeGraphAction
->setCheckable(true);
482 _timeGraphAction
->setActionGroup(ag
);
483 connect(_timeGraphAction
, &QAction::triggered
, this, &GUI::setTimeGraph
);
484 addAction(_timeGraphAction
);
485 _showGraphGridAction
= new QAction(tr("Show grid"), this);
486 _showGraphGridAction
->setMenuRole(QAction::NoRole
);
487 _showGraphGridAction
->setCheckable(true);
488 connect(_showGraphGridAction
, &QAction::triggered
, this,
489 &GUI::showGraphGrids
);
490 _showGraphSliderInfoAction
= new QAction(tr("Show slider info"), this);
491 _showGraphSliderInfoAction
->setMenuRole(QAction::NoRole
);
492 _showGraphSliderInfoAction
->setCheckable(true);
493 connect(_showGraphSliderInfoAction
, &QAction::triggered
, this,
494 &GUI::showGraphSliderInfo
);
496 _showGraphTabsAction
= new QAction(tr("Show tabs"), this);
497 _showGraphTabsAction
->setMenuRole(QAction::NoRole
);
498 _showGraphTabsAction
->setCheckable(true);
499 connect(_showGraphTabsAction
, &QAction::triggered
, this,
500 &GUI::showGraphTabs
);
501 #endif // Q_OS_ANDROID
505 _showToolbarsAction
= new QAction(tr("Show toolbars"), this);
506 _showToolbarsAction
->setMenuRole(QAction::NoRole
);
507 _showToolbarsAction
->setCheckable(true);
508 connect(_showToolbarsAction
, &QAction::triggered
, this, &GUI::showToolbars
);
509 #endif // Q_OS_ANDROID
510 ag
= new QActionGroup(this);
511 ag
->setExclusive(true);
512 _totalTimeAction
= new QAction(tr("Total time"), this);
513 _totalTimeAction
->setMenuRole(QAction::NoRole
);
514 _totalTimeAction
->setCheckable(true);
515 _totalTimeAction
->setActionGroup(ag
);
516 connect(_totalTimeAction
, &QAction::triggered
, this, &GUI::setTotalTime
);
517 _movingTimeAction
= new QAction(tr("Moving time"), this);
518 _movingTimeAction
->setMenuRole(QAction::NoRole
);
519 _movingTimeAction
->setCheckable(true);
520 _movingTimeAction
->setActionGroup(ag
);
521 connect(_movingTimeAction
, &QAction::triggered
, this, &GUI::setMovingTime
);
522 ag
= new QActionGroup(this);
523 ag
->setExclusive(true);
524 _metricUnitsAction
= new QAction(tr("Metric"), this);
525 _metricUnitsAction
->setMenuRole(QAction::NoRole
);
526 _metricUnitsAction
->setCheckable(true);
527 _metricUnitsAction
->setActionGroup(ag
);
528 connect(_metricUnitsAction
, &QAction::triggered
, this, &GUI::setMetricUnits
);
529 _imperialUnitsAction
= new QAction(tr("Imperial"), this);
530 _imperialUnitsAction
->setMenuRole(QAction::NoRole
);
531 _imperialUnitsAction
->setCheckable(true);
532 _imperialUnitsAction
->setActionGroup(ag
);
533 connect(_imperialUnitsAction
, &QAction::triggered
, this,
534 &GUI::setImperialUnits
);
535 _nauticalUnitsAction
= new QAction(tr("Nautical"), this);
536 _nauticalUnitsAction
->setMenuRole(QAction::NoRole
);
537 _nauticalUnitsAction
->setCheckable(true);
538 _nauticalUnitsAction
->setActionGroup(ag
);
539 connect(_nauticalUnitsAction
, &QAction::triggered
, this,
540 &GUI::setNauticalUnits
);
541 ag
= new QActionGroup(this);
542 ag
->setExclusive(true);
543 _decimalDegreesAction
= new QAction(tr("Decimal degrees (DD)"), this);
544 _decimalDegreesAction
->setMenuRole(QAction::NoRole
);
545 _decimalDegreesAction
->setCheckable(true);
546 _decimalDegreesAction
->setActionGroup(ag
);
547 connect(_decimalDegreesAction
, &QAction::triggered
, this,
548 &GUI::setDecimalDegrees
);
549 _degreesMinutesAction
= new QAction(tr("Degrees and decimal minutes (DMM)"),
551 _degreesMinutesAction
->setMenuRole(QAction::NoRole
);
552 _degreesMinutesAction
->setCheckable(true);
553 _degreesMinutesAction
->setActionGroup(ag
);
554 connect(_degreesMinutesAction
, &QAction::triggered
, this,
555 &GUI::setDegreesMinutes
);
556 _dmsAction
= new QAction(tr("Degrees, minutes, seconds (DMS)"), this);
557 _dmsAction
->setMenuRole(QAction::NoRole
);
558 _dmsAction
->setCheckable(true);
559 _dmsAction
->setActionGroup(ag
);
560 connect(_dmsAction
, &QAction::triggered
, this, &GUI::setDMS
);
562 _fullscreenAction
= new QAction(QIcon::fromTheme(FULLSCREEN_NAME
,
563 QIcon(FULLSCREEN_ICON
)), tr("Fullscreen mode"), this);
564 _fullscreenAction
->setMenuRole(QAction::NoRole
);
565 _fullscreenAction
->setCheckable(true);
566 _fullscreenAction
->setShortcut(FULLSCREEN_SHORTCUT
);
567 connect(_fullscreenAction
, &QAction::triggered
, this, &GUI::showFullscreen
);
568 addAction(_fullscreenAction
);
569 #endif // Q_OS_ANDROID
570 _openOptionsAction
= new QAction(tr("Options..."), this);
571 _openOptionsAction
->setMenuRole(QAction::PreferencesRole
);
572 connect(_openOptionsAction
, &QAction::triggered
, this, &GUI::openOptions
);
574 // Navigation actions
576 _nextAction
= new QAction(QIcon::fromTheme(NEXT_FILE_NAME
,
577 QIcon(NEXT_FILE_ICON
)), tr("Next"), this);
578 _nextAction
->setActionGroup(_navigationActionGroup
);
579 _nextAction
->setMenuRole(QAction::NoRole
);
580 connect(_nextAction
, &QAction::triggered
, this, &GUI::next
);
581 _prevAction
= new QAction(QIcon::fromTheme(PREV_FILE_NAME
,
582 QIcon(PREV_FILE_ICON
)), tr("Previous"), this);
583 _prevAction
->setMenuRole(QAction::NoRole
);
584 _prevAction
->setActionGroup(_navigationActionGroup
);
585 connect(_prevAction
, &QAction::triggered
, this, &GUI::prev
);
586 _lastAction
= new QAction(QIcon::fromTheme(LAST_FILE_NAME
,
587 QIcon(LAST_FILE_ICON
)), tr("Last"), this);
588 _lastAction
->setMenuRole(QAction::NoRole
);
589 _lastAction
->setActionGroup(_navigationActionGroup
);
590 connect(_lastAction
, &QAction::triggered
, this, &GUI::last
);
591 _firstAction
= new QAction(QIcon::fromTheme(FIRST_FILE_NAME
,
592 QIcon(FIRST_FILE_ICON
)), tr("First"), this);
593 _firstAction
->setMenuRole(QAction::NoRole
);
594 _firstAction
->setActionGroup(_navigationActionGroup
);
595 connect(_firstAction
, &QAction::triggered
, this, &GUI::first
);
596 #endif // Q_OS_ANDROID
599 void GUI::createMapNodeMenu(const TreeNode
<MapAction
*> &node
, QMenu
*menu
,
602 for (int i
= 0; i
< node
.childs().size(); i
++) {
603 QMenu
*cm
= new QMenu(node
.childs().at(i
).name(), menu
);
604 menu
->insertMenu(action
, cm
);
605 createMapNodeMenu(node
.childs().at(i
), cm
);
608 for (int i
= 0; i
< node
.items().size(); i
++)
609 menu
->insertAction(action
, node
.items().at(i
));
612 void GUI::createPOINodeMenu(const TreeNode
<POIAction
*> &node
, QMenu
*menu
,
615 for (int i
= 0; i
< node
.childs().size(); i
++) {
616 QMenu
*cm
= new QMenu(node
.childs().at(i
).name(), menu
);
617 menu
->insertMenu(action
, cm
);
618 createPOINodeMenu(node
.childs().at(i
), cm
);
621 for (int i
= 0; i
< node
.items().size(); i
++)
622 menu
->insertAction(action
, node
.items().at(i
));
625 void GUI::createMenus()
627 QMenu
*fileMenu
= menuBar()->addMenu(tr("&File"));
628 fileMenu
->addAction(_openFileAction
);
630 _recentFilesMenu
= fileMenu
->addMenu(tr("Open recent"));
631 _recentFilesMenu
->setIcon(QIcon::fromTheme(OPEN_RECENT_NAME
,
632 QIcon(OPEN_RECENT_ICON
)));
633 _recentFilesMenu
->menuAction()->setMenuRole(QAction::NoRole
);
634 _recentFilesMenu
->setEnabled(false);
635 _recentFilesEnd
= _recentFilesMenu
->addSeparator();
636 _recentFilesMenu
->addAction(_clearRecentFilesAction
);
637 #endif // Q_OS_ANDROID
638 fileMenu
->addAction(_openDirAction
);
639 fileMenu
->addSeparator();
641 fileMenu
->addAction(_printFileAction
);
642 #endif // Q_OS_ANDROID
643 fileMenu
->addAction(_exportPDFFileAction
);
644 fileMenu
->addAction(_exportPNGFileAction
);
645 fileMenu
->addSeparator();
646 fileMenu
->addAction(_statisticsAction
);
647 fileMenu
->addSeparator();
648 fileMenu
->addAction(_reloadFileAction
);
649 fileMenu
->addAction(_closeFileAction
);
650 #if !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID)
651 fileMenu
->addSeparator();
652 fileMenu
->addAction(_exitAction
);
653 #endif // Q_OS_MAC + Q_OS_ANDROID
655 _mapMenu
= menuBar()->addMenu(tr("&Map"));
656 _mapsEnd
= _mapMenu
->addSeparator();
657 _mapMenu
->addAction(_loadMapAction
);
658 _mapMenu
->addAction(_loadMapDirAction
);
659 _mapMenu
->addAction(_clearMapCacheAction
);
660 _mapMenu
->addSeparator();
661 _mapMenu
->addAction(_showCoordinatesAction
);
662 _mapMenu
->addSeparator();
663 _mapMenu
->addAction(_showMapAction
);
665 QMenu
*graphMenu
= menuBar()->addMenu(tr("&Graph"));
666 graphMenu
->addAction(_distanceGraphAction
);
667 graphMenu
->addAction(_timeGraphAction
);
668 graphMenu
->addSeparator();
669 graphMenu
->addAction(_showGraphGridAction
);
670 graphMenu
->addAction(_showGraphSliderInfoAction
);
672 graphMenu
->addAction(_showGraphTabsAction
);
673 #endif // Q_OS_ANDROID
674 graphMenu
->addSeparator();
675 graphMenu
->addAction(_showGraphsAction
);
677 QMenu
*dataMenu
= menuBar()->addMenu(tr("&Data"));
678 dataMenu
->addAction(_showWaypointIconsAction
);
679 dataMenu
->addAction(_showWaypointLabelsAction
);
680 dataMenu
->addAction(_showRouteWaypointsAction
);
681 dataMenu
->addAction(_showTicksAction
);
682 QMenu
*markerMenu
= dataMenu
->addMenu(tr("Position info"));
683 markerMenu
->menuAction()->setMenuRole(QAction::NoRole
);
684 markerMenu
->addAction(_hideMarkersAction
);
685 markerMenu
->addAction(_showMarkersAction
);
686 markerMenu
->addAction(_showMarkerDateAction
);
687 markerMenu
->addAction(_showMarkerCoordinatesAction
);
688 dataMenu
->addSeparator();
689 dataMenu
->addAction(_useStylesAction
);
690 dataMenu
->addSeparator();
691 dataMenu
->addAction(_showTracksAction
);
692 dataMenu
->addAction(_showRoutesAction
);
693 dataMenu
->addAction(_showAreasAction
);
694 dataMenu
->addAction(_showWaypointsAction
);
696 _poiMenu
= menuBar()->addMenu(tr("&POI"));
697 _poisEnd
= _poiMenu
->addSeparator();
698 _poiMenu
->addAction(_openPOIAction
);
699 _poiMenu
->addAction(_selectAllPOIAction
);
700 _poiMenu
->addAction(_unselectAllPOIAction
);
701 _poiMenu
->addSeparator();
702 _poiMenu
->addAction(_showPOIIconsAction
);
703 _poiMenu
->addAction(_showPOILabelsAction
);
704 _poiMenu
->addAction(_overlapPOIAction
);
705 _poiMenu
->addSeparator();
706 _poiMenu
->addAction(_showPOIAction
);
708 QMenu
*demMenu
= menuBar()->addMenu(tr("DEM"));
709 demMenu
->addAction(_showDEMTilesAction
);
710 demMenu
->addAction(_downloadDEMAction
);
712 QMenu
*positionMenu
= menuBar()->addMenu(tr("Position"));
713 positionMenu
->addAction(_showPositionCoordinatesAction
);
714 positionMenu
->addAction(_showMotionInfoAction
);
715 positionMenu
->addAction(_followPositionAction
);
716 positionMenu
->addSeparator();
717 positionMenu
->addAction(_showPositionAction
);
719 QMenu
*settingsMenu
= menuBar()->addMenu(tr("&Settings"));
720 QMenu
*timeMenu
= settingsMenu
->addMenu(tr("Time"));
721 timeMenu
->menuAction()->setMenuRole(QAction::NoRole
);
722 timeMenu
->addAction(_totalTimeAction
);
723 timeMenu
->addAction(_movingTimeAction
);
724 QMenu
*unitsMenu
= settingsMenu
->addMenu(tr("Units"));
725 unitsMenu
->menuAction()->setMenuRole(QAction::NoRole
);
726 unitsMenu
->addAction(_metricUnitsAction
);
727 unitsMenu
->addAction(_imperialUnitsAction
);
728 unitsMenu
->addAction(_nauticalUnitsAction
);
729 QMenu
*coordinatesMenu
= settingsMenu
->addMenu(tr("Coordinates format"));
730 coordinatesMenu
->menuAction()->setMenuRole(QAction::NoRole
);
731 coordinatesMenu
->addAction(_decimalDegreesAction
);
732 coordinatesMenu
->addAction(_degreesMinutesAction
);
733 coordinatesMenu
->addAction(_dmsAction
);
734 settingsMenu
->addSeparator();
736 settingsMenu
->addAction(_showToolbarsAction
);
737 settingsMenu
->addAction(_fullscreenAction
);
738 settingsMenu
->addSeparator();
739 #endif // Q_OS_ANDROID
740 settingsMenu
->addAction(_openOptionsAction
);
742 QMenu
*helpMenu
= menuBar()->addMenu(tr("&Help"));
743 helpMenu
->addAction(_pathsAction
);
745 helpMenu
->addAction(_keysAction
);
746 #endif // Q_OS_ANDROID
747 helpMenu
->addSeparator();
748 helpMenu
->addAction(_aboutAction
);
752 void GUI::createNavigation()
754 _navigation
= new NavigationWidget(_mapView
);
756 connect(_navigation
, &NavigationWidget::next
, this, &GUI::next
);
757 connect(_navigation
, &NavigationWidget::prev
, this, &GUI::prev
);
759 #else // Q_OS_ANDROID
760 void GUI::createToolBars()
762 int is
= style()->pixelMetric(QStyle::PM_ToolBarIconSize
);
763 QSize
iconSize(qMin(is
, TOOLBAR_ICON_SIZE
), qMin(is
, TOOLBAR_ICON_SIZE
));
766 setToolButtonStyle(Qt::ToolButtonTextUnderIcon
);
769 _fileToolBar
= addToolBar(tr("File"));
770 _fileToolBar
->setObjectName("File");
771 _fileToolBar
->setIconSize(iconSize
);
772 _fileToolBar
->addAction(_openFileAction
);
773 _fileToolBar
->addAction(_reloadFileAction
);
774 _fileToolBar
->addAction(_closeFileAction
);
776 _fileToolBar
->addAction(_printFileAction
);
779 _showToolBar
= addToolBar(tr("Show"));
780 _showToolBar
->setObjectName("Show");
781 _showToolBar
->setIconSize(iconSize
);
782 _showToolBar
->addAction(_showPOIAction
);
783 _showToolBar
->addAction(_showMapAction
);
784 _showToolBar
->addAction(_showGraphsAction
);
785 _showToolBar
->addAction(_showPositionAction
);
787 _navigationToolBar
= addToolBar(tr("Navigation"));
788 _navigationToolBar
->setObjectName("Navigation");
789 _navigationToolBar
->setIconSize(iconSize
);
790 _navigationToolBar
->addAction(_firstAction
);
791 _navigationToolBar
->addAction(_prevAction
);
792 _navigationToolBar
->addAction(_nextAction
);
793 _navigationToolBar
->addAction(_lastAction
);
795 #endif // Q_OS_ANDROID
797 void GUI::createMapView()
799 _map
= new EmptyMap(this);
800 _mapView
= new MapView(_map
, _poi
, this);
801 _mapView
->setSizePolicy(QSizePolicy(QSizePolicy::Ignored
,
802 QSizePolicy::Expanding
));
804 _mapView
->setMinimumHeight(100);
805 #else // Q_OS_ANDROID
806 _mapView
->setMinimumHeight(200);
807 #endif // Q_OS_ANDROID
809 _mapView
->setFrameShape(QFrame::NoFrame
);
813 void GUI::createGraphTabs()
815 _graphTabWidget
= new QTabWidget();
816 _graphTabWidget
->setSizePolicy(QSizePolicy(QSizePolicy::Ignored
,
817 QSizePolicy::Preferred
));
818 _graphTabWidget
->setMinimumHeight(200);
820 _graphTabWidget
->setDocumentMode(true);
823 connect(_graphTabWidget
, &QTabWidget::currentChanged
, this,
826 _tabs
.append(new ElevationGraph(_graphTabWidget
));
827 _tabs
.append(new SpeedGraph(_graphTabWidget
));
828 _tabs
.append(new HeartRateGraph(_graphTabWidget
));
829 _tabs
.append(new CadenceGraph(_graphTabWidget
));
830 _tabs
.append(new PowerGraph(_graphTabWidget
));
831 _tabs
.append(new TemperatureGraph(_graphTabWidget
));
832 _tabs
.append(new GearRatioGraph(_graphTabWidget
));
834 for (int i
= 0; i
< _tabs
.size(); i
++)
835 connect(_tabs
.at(i
), &GraphTab::sliderPositionChanged
, _mapView
,
836 &MapView::setMarkerPosition
);
839 void GUI::createStatusBar()
841 _fileNameLabel
= new QLabel();
842 _distanceLabel
= new QLabel();
843 _timeLabel
= new QLabel();
844 _distanceLabel
->setAlignment(Qt::AlignHCenter
);
845 _timeLabel
->setAlignment(Qt::AlignHCenter
);
847 statusBar()->addPermanentWidget(_fileNameLabel
, 8);
848 statusBar()->addPermanentWidget(_distanceLabel
, 1);
849 statusBar()->addPermanentWidget(_timeLabel
, 1);
850 statusBar()->setSizeGripEnabled(false);
855 QMessageBox
msgBox(this);
856 QUrl
homepage(APP_HOMEPAGE
);
858 msgBox
.setWindowTitle(tr("About GPXSee"));
860 msgBox
.setText("<h2>" + QString(APP_NAME
) + "</h2><p>" + tr("Version %1")
861 .arg(QString(APP_VERSION
) + " (" + QSysInfo::buildCpuArchitecture()
862 + ", Qt " + QT_VERSION_STR
+ ")") + "</p><p>"
863 + tr("GPXSee is distributed under the terms of the GNU General Public "
864 "License version 3. For more info about GPXSee visit the project "
865 "homepage at %1.").arg("<a href=\"" + homepage
.toString() + "\">"
866 + homepage
.toString(QUrl::RemoveScheme
).mid(2) + "</a>") + "</p>");
867 #else // Q_OS_ANDROID
868 msgBox
.setText("<h2>" + QString(APP_NAME
) + "</h2><p>" + tr("Version %1")
869 .arg(QString(APP_VERSION
) + " (" + QSysInfo::buildCpuArchitecture()
870 + ", Qt " + QT_VERSION_STR
+ ")") + "</p>");
871 msgBox
.setInformativeText("<table width=\"300\"><tr><td>"
872 + tr("GPXSee is distributed under the terms of the GNU General Public "
873 "License version 3. For more info about GPXSee visit the project "
874 "homepage at %1.").arg("<a href=\"" + homepage
.toString() + "\">"
875 + homepage
.toString(QUrl::RemoveScheme
).mid(2) + "</a>")
876 + "</td></tr></table>");
878 QIcon icon
= msgBox
.windowIcon();
879 QSize size
= icon
.actualSize(QSize(64, 64));
880 msgBox
.setIconPixmap(icon
.pixmap(size
));
881 #endif // Q_OS_ANDROID
889 QMessageBox
msgBox(this);
891 msgBox
.setWindowTitle(tr("Keyboard controls"));
892 msgBox
.setText("<h3>" + tr("Keyboard controls") + "</h3>");
893 msgBox
.setInformativeText(
894 "<style>td {padding-right: 1.5em;}</style><div><table><tr><td>"
895 + tr("Next file") + "</td><td><i>" + QKeySequence(NEXT_KEY
).toString()
896 + "</i></td></tr><tr><td>" + tr("Previous file")
897 + "</td><td><i>" + QKeySequence(PREV_KEY
).toString()
898 + "</i></td></tr><tr><td>" + tr("First file") + "</td><td><i>"
899 + QKeySequence(FIRST_KEY
).toString() + "</i></td></tr><tr><td>"
900 + tr("Last file") + "</td><td><i>" + QKeySequence(LAST_KEY
).toString()
901 + "</i></td></tr><tr><td>" + tr("Append file")
902 + "</td><td><i>" + QKeySequence(MODIFIER
).toString() + tr("Next/Previous")
903 + "</i></td></tr><tr><td></td><td></td></tr><tr><td>"
904 + tr("Toggle graph type") + "</td><td><i>"
905 + QKeySequence(TOGGLE_GRAPH_TYPE_KEY
).toString() + "</i></td></tr><tr><td>"
906 + tr("Toggle time type") + "</td><td><i>"
907 + QKeySequence(TOGGLE_TIME_TYPE_KEY
).toString() + "</i></td></tr><tr><td>"
908 + tr("Toggle position info") + "</td><td><i>"
909 + QKeySequence(TOGGLE_MARKER_INFO_KEY
).toString() + "</i></td></tr>"
910 + "<tr><td></td><td></td></tr><tr><td>" + tr("Next map")
911 + "</td><td><i>" + NEXT_MAP_SHORTCUT
.toString() + "</i></td></tr><tr><td>"
912 + tr("Previous map") + "</td><td><i>" + PREV_MAP_SHORTCUT
.toString()
913 + "</i></td></tr><tr><td></td><td></td></tr><tr><td>" + tr("Zoom in")
914 + "</td><td><i>" + QKeySequence(ZOOM_IN
).toString()
915 + "</i></td></tr><tr><td>" + tr("Zoom out") + "</td><td><i>"
916 + QKeySequence(ZOOM_OUT
).toString() + "</i></td></tr><tr><td>"
917 + tr("Digital zoom") + "</td><td><i>" + QKeySequence(MODIFIER
).toString()
918 + tr("Zoom") + "</i></td></tr><tr><td></td><td></td></tr><tr><td>"
919 + tr("Copy coordinates") + "</td><td><i>"
920 + QKeySequence(MODIFIER
).toString() + tr("Left Click")
921 + "</i></td></tr></table></div>");
925 #endif // Q_OS_ANDROID
929 QMessageBox
msgBox(this);
931 msgBox
.setWindowTitle(tr("Paths"));
934 + "<small><b>" + tr("Map directory:") + "</b><br>"
935 + QDir::cleanPath(ProgramPaths::mapDir(true)) + "<br><br><b>"
936 + tr("POI directory:") + "</b><br>"
937 + QDir::cleanPath(ProgramPaths::poiDir(true)) + "<br><br><b>"
938 + tr("CRS directory:") + "</b><br>"
939 + QDir::cleanPath(ProgramPaths::crsDir(true)) + "<br><br><b>"
940 + tr("DEM directory:") + "</b><br>"
941 + QDir::cleanPath(ProgramPaths::demDir(true)) + "<br><br><b>"
942 + tr("Styles directory:") + "</b><br>"
943 + QDir::cleanPath(ProgramPaths::styleDir(true)) + "<br><br><b>"
944 + tr("Symbols directory:") + "</b><br>"
945 + QDir::cleanPath(ProgramPaths::symbolsDir(true)) + "<br><br><b>"
946 + tr("Tile cache directory:") + "</b><br>"
947 + QDir::cleanPath(ProgramPaths::tilesDir()) + "</small>");
948 #else // Q_OS_ANDROID
949 msgBox
.setText("<h3>" + tr("Paths") + "</h3>");
950 msgBox
.setInformativeText(
951 "<style>td {white-space: pre; padding-right: 1em;}</style><table><tr><td>"
952 + tr("Map directory:") + "</td><td><code>"
953 + QDir::cleanPath(ProgramPaths::mapDir(true)) + "</code></td></tr><tr><td>"
954 + tr("POI directory:") + "</td><td><code>"
955 + QDir::cleanPath(ProgramPaths::poiDir(true)) + "</code></td></tr><tr><td>"
956 + tr("CRS directory:") + "</td><td><code>"
957 + QDir::cleanPath(ProgramPaths::crsDir(true)) + "</code></td></tr><tr><td>"
958 + tr("DEM directory:") + "</td><td><code>"
959 + QDir::cleanPath(ProgramPaths::demDir(true)) + "</code></td></tr><tr><td>"
960 + tr("Styles directory:") + "</td><td><code>"
961 + QDir::cleanPath(ProgramPaths::styleDir(true)) + "</code></td></tr><tr><td>"
962 + tr("Symbols directory:") + "</td><td><code>"
963 + QDir::cleanPath(ProgramPaths::symbolsDir(true)) + "</code></td></tr><tr><td>"
964 + tr("Tile cache directory:") + "</td><td><code>"
965 + QDir::cleanPath(ProgramPaths::tilesDir()) + "</code></td></tr></table>"
967 #endif // Q_OS_ANDROID
975 QStringList
files(QFileDialog::getOpenFileNames(this, tr("Open file"),
977 #else // Q_OS_ANDROID
978 QStringList
files(QFileDialog::getOpenFileNames(this, tr("Open file"),
979 _dataDir
, Data::formats()));
980 #endif // Q_OS_ANDROID
981 int showError
= (files
.size() > 1) ? 2 : 1;
983 for (int i
= 0; i
< files
.size(); i
++)
984 openFile(files
.at(i
), true, showError
);
985 if (!files
.isEmpty())
986 _dataDir
= QFileInfo(files
.last()).path();
990 void GUI::openDir(const QString
&path
, int &showError
)
993 md
.setFilter(QDir::Files
| QDir::Dirs
| QDir::NoDotAndDotDot
);
994 md
.setSorting(QDir::DirsLast
);
995 QFileInfoList ml
= md
.entryInfoList();
997 for (int i
= 0; i
< ml
.size(); i
++) {
998 const QFileInfo
&fi
= ml
.at(i
);
1001 openDir(fi
.absoluteFilePath(), showError
);
1003 openFile(fi
.absoluteFilePath(), true, showError
);
1006 #endif // Q_OS_ANDROID
1010 QString
dir(QFileDialog::getExistingDirectory(this, tr("Open directory"),
1013 if (!dir
.isEmpty()) {
1016 _browser
->setCurrentDir(dir
);
1017 openFile(_browser
->current(), true, showError
);
1018 #else // Q_OS_ANDROID
1020 openDir(dir
, showError
);
1022 #endif // Q_OS_ANDROID
1026 bool GUI::openFile(const QString
&fileName
, bool tryUnknown
, int &showError
)
1028 if (_files
.contains(fileName
))
1031 if (!loadFile(fileName
, tryUnknown
, showError
))
1034 _files
.append(fileName
);
1035 #ifndef Q_OS_ANDROID
1036 _browser
->setCurrent(fileName
);
1037 #endif // Q_OS_ANDROID
1038 _fileActionGroup
->setEnabled(true);
1039 // Explicitly enable the reload action as it may be disabled by loadMapDir()
1040 _reloadFileAction
->setEnabled(true);
1041 _navigationActionGroup
->setEnabled(true);
1043 updateNavigationActions();
1044 updateStatusBarInfo();
1045 updateWindowTitle();
1046 #ifndef Q_OS_ANDROID
1047 updateRecentFiles(fileName
);
1048 #endif // Q_OS_ANDROID
1053 bool GUI::loadFile(const QString
&fileName
, bool tryUnknown
, int &showError
)
1055 Data
data(fileName
, tryUnknown
);
1057 if (data
.isValid()) {
1061 updateNavigationActions();
1062 updateStatusBarInfo();
1063 updateWindowTitle();
1065 updateDEMDownloadAction();
1066 if (_files
.isEmpty())
1067 _fileActionGroup
->setEnabled(false);
1070 QString error
= tr("Error loading data file:") + "\n"
1071 + Util::displayName(fileName
) + ": " + data
.errorString();
1072 if (data
.errorLine())
1073 error
.append("\n" + tr("Line: %1").arg(data
.errorLine()));
1075 if (showError
> 1) {
1076 QMessageBox
message(QMessageBox::Critical
, APP_NAME
, error
,
1077 QMessageBox::Ok
, this);
1078 QCheckBox
checkBox(tr("Don't show again"));
1079 message
.setCheckBox(&checkBox
);
1081 if (checkBox
.isChecked())
1084 QMessageBox::critical(this, APP_NAME
, error
);
1091 void GUI::loadData(const Data
&data
)
1093 QList
<QList
<GraphItem
*> > graphs
;
1094 QList
<PathItem
*> paths
;
1096 for (int i
= 0; i
< data
.tracks().count(); i
++) {
1097 const Track
&track
= data
.tracks().at(i
);
1098 _trackDistance
+= track
.distance();
1099 _time
+= track
.time();
1100 _movingTime
+= track
.movingTime();
1101 const QDateTime date
= track
.date().toTimeZone(_options
.timeZone
.zone());
1102 if (_dateRange
.first
.isNull() || _dateRange
.first
> date
)
1103 _dateRange
.first
= date
;
1104 if (_dateRange
.second
.isNull() || _dateRange
.second
< date
)
1105 _dateRange
.second
= date
;
1107 _trackCount
+= data
.tracks().count();
1109 for (int i
= 0; i
< data
.routes().count(); i
++)
1110 _routeDistance
+= data
.routes().at(i
).distance();
1111 _routeCount
+= data
.routes().count();
1113 _waypointCount
+= data
.waypoints().count();
1114 _areaCount
+= data
.areas().count();
1116 if (_pathName
.isNull()) {
1117 if (data
.tracks().count() == 1 && !data
.routes().count())
1118 _pathName
= data
.tracks().first().name();
1119 else if (data
.routes().count() == 1 && !data
.tracks().count())
1120 _pathName
= data
.routes().first().name();
1122 _pathName
= QString();
1124 for (int i
= 0; i
< _tabs
.count(); i
++)
1125 graphs
.append(_tabs
.at(i
)->loadData(data
));
1126 if (updateGraphTabs())
1127 _splitter
->refresh();
1128 paths
= _mapView
->loadData(data
);
1130 GraphTab
*gt
= static_cast<GraphTab
*>(_graphTabWidget
->currentWidget());
1132 for (int i
= 0; i
< paths
.count(); i
++) {
1133 PathItem
*pi
= paths
.at(i
);
1137 for (int j
= 0; j
< graphs
.count(); j
++)
1138 pi
->addGraph(graphs
.at(j
).at(i
));
1141 pi
->setGraph(_tabs
.indexOf(gt
));
1142 pi
->setMarkerPosition(gt
->sliderPosition());
1146 updateDEMDownloadAction();
1149 void GUI::openPOIFile()
1152 QStringList
files(QFileDialog::getOpenFileNames(this, tr("Open POI file"),
1154 #else // Q_OS_ANDROID
1155 QStringList
files(QFileDialog::getOpenFileNames(this, tr("Open POI file"),
1156 _poiDir
, Data::formats()));
1157 #endif // Q_OS_ANDROID
1159 for (int i
= 0; i
< files
.size(); i
++)
1160 openPOIFile(files
.at(i
));
1161 if (!files
.isEmpty())
1162 _poiDir
= QFileInfo(files
.last()).path();
1165 bool GUI::openPOIFile(const QString
&fileName
)
1167 if (_poi
->isLoaded(fileName
))
1170 if (_poi
->loadFile(fileName
)) {
1171 _mapView
->showPOI(true);
1172 _showPOIAction
->setChecked(true);
1173 QAction
*action
= new POIAction(fileName
, _poisActionGroup
);
1174 action
->setChecked(true);
1175 _poiMenu
->insertAction(_poisEnd
, action
);
1177 _selectAllPOIAction
->setEnabled(true);
1178 _unselectAllPOIAction
->setEnabled(true);
1182 QString error
= tr("Error loading POI file:") + "\n"
1183 + Util::displayName(fileName
) + ": " + _poi
->errorString();
1184 if (_poi
->errorLine())
1185 error
.append("\n" + tr("Line: %1").arg(_poi
->errorLine()));
1186 QMessageBox::critical(this, APP_NAME
, error
);
1192 void GUI::openOptions()
1194 Options
options(_options
);
1195 OptionsDialog
dialog(options
, _units
, this);
1197 if (dialog
.exec() != QDialog::Accepted
)
1200 updateOptions(options
);
1203 void GUI::printFile()
1205 QPrinter
printer(QPrinter::HighResolution
);
1206 QPrintDialog
dialog(&printer
, this);
1208 if (dialog
.exec() == QDialog::Accepted
)
1212 void GUI::exportPDFFile()
1214 PDFExportDialog
dialog(_pdfExport
, _units
, this);
1215 if (dialog
.exec() != QDialog::Accepted
)
1218 QPrinter
printer(QPrinter::HighResolution
);
1219 printer
.setOutputFormat(QPrinter::PdfFormat
);
1220 printer
.setCreator(QString(APP_NAME
) + QString(" ")
1221 + QString(APP_VERSION
));
1222 printer
.setResolution(_pdfExport
.resolution
);
1223 printer
.setPageLayout(QPageLayout(QPageSize(_pdfExport
.paperSize
),
1224 _pdfExport
.orientation
, _pdfExport
.margins
, QPageLayout::Millimeter
));
1225 printer
.setOutputFileName(_pdfExport
.fileName
);
1230 void GUI::exportPNGFile()
1232 PNGExportDialog
dialog(_pngExport
, this);
1233 if (dialog
.exec() != QDialog::Accepted
)
1236 QImage
img(_pngExport
.size
, QImage::Format_ARGB32_Premultiplied
);
1238 QRectF
rect(0, 0, img
.width(), img
.height());
1239 QRectF
contentRect(rect
.adjusted(_pngExport
.margins
.left(),
1240 _pngExport
.margins
.top(), -_pngExport
.margins
.right(),
1241 -_pngExport
.margins
.bottom()));
1243 if (_pngExport
.antialiasing
)
1244 p
.setRenderHint(QPainter::Antialiasing
);
1245 p
.fillRect(rect
, Qt::white
);
1246 plotMainPage(&p
, contentRect
, 1.0, true);
1247 img
.save(_pngExport
.fileName
, "png");
1249 if (!_tabs
.isEmpty() && _options
.separateGraphPage
) {
1250 QImage
img2(_pngExport
.size
.width(), (int)graphPlotHeight(rect
, 1)
1251 + _pngExport
.margins
.bottom(), QImage::Format_ARGB32_Premultiplied
);
1253 QRectF
rect2(0, 0, img2
.width(), img2
.height());
1255 if (_pngExport
.antialiasing
)
1256 p2
.setRenderHint(QPainter::Antialiasing
);
1257 p2
.fillRect(rect2
, Qt::white
);
1258 plotGraphsPage(&p2
, contentRect
, 1);
1260 QFileInfo
fi(_pngExport
.fileName
);
1261 img2
.save(fi
.absolutePath() + "/" + fi
.baseName() + "-graphs."
1262 + fi
.suffix(), "png");
1266 void GUI::statistics()
1268 QLocale
l(QLocale::system());
1269 QMessageBox
msgBox(this);
1273 if (_showTracksAction
->isChecked() && _trackCount
> 1)
1274 text
.append("<b>" + tr("Tracks") + ":</b> "
1275 + l
.toString(_trackCount
) + "<br>");
1276 if (_showRoutesAction
->isChecked() && _routeCount
> 1)
1277 text
.append("<b>" + tr("Routes") + ":</b> "
1278 + l
.toString(_routeCount
) + "<br>");
1279 if (_showWaypointsAction
->isChecked() && _waypointCount
> 1)
1280 text
.append("<b>" + tr("Waypoints") + ":</b> "
1281 + l
.toString(_waypointCount
) + "<br>");
1282 if (_showAreasAction
->isChecked() && _areaCount
> 1)
1283 text
.append("<b>" + tr("Areas") + ":</b> "
1284 + l
.toString(_areaCount
) + "<br>");
1286 if (_dateRange
.first
.isValid()) {
1287 QString format
= l
.dateFormat(QLocale::ShortFormat
);
1288 if (_dateRange
.first
== _dateRange
.second
)
1289 text
.append("<b>" + tr("Date") + ":</b> "
1290 + _dateRange
.first
.toString(format
) + "<br>");
1292 text
.append("<b>" + tr("Date") + ":</b> "
1293 + QString("%1 - %2").arg(_dateRange
.first
.toString(format
),
1294 _dateRange
.second
.toString(format
)) + "<br>");
1298 text
.append("<b>" + tr("Distance") + ":</b> "
1299 + Format::distance(distance(), units()) + "<br>");
1301 text
.append("<b>" + tr("Time") + ":</b> "
1302 + Format::timeSpan(time()) + "<br>");
1303 text
.append("<b>" + tr("Moving time") + ":</b> "
1304 + Format::timeSpan(movingTime()) + "<br>");
1306 text
.append("<br>");
1308 for (int i
= 0; i
< _tabs
.count(); i
++) {
1309 const GraphTab
*tab
= _tabs
.at(i
);
1313 text
.append("<i>" + tab
->label() + "</i><br>");
1314 for (int j
= 0; j
< tab
->info().size(); j
++) {
1315 const KV
<QString
, QString
> &kv
= tab
->info().at(j
);
1316 text
.append("<b>" + kv
.key() + ":</b> " + kv
.value());
1317 if (j
!= tab
->info().size() - 1)
1320 if (i
!= _tabs
.count() - 1)
1321 text
.append("<br><br>");
1324 msgBox
.setWindowTitle(tr("Statistics"));
1325 msgBox
.setText(text
);
1327 #else // Q_OS_ANDROID
1330 text
= "<style>td {white-space: pre; padding-right: 4em;}"
1331 "th {text-align: left; padding-top: 0.5em;}</style><table>";
1333 text
= "<style>td {white-space: pre; padding-right: 2em;}"
1334 "th {text-align: left; padding-top: 0.5em;}</style><table>";
1335 #endif // Q_OS_WIN32
1337 if (_showTracksAction
->isChecked() && _trackCount
> 1)
1338 text
.append("<tr><td>" + tr("Tracks") + ":</td><td>"
1339 + l
.toString(_trackCount
) + "</td></tr>");
1340 if (_showRoutesAction
->isChecked() && _routeCount
> 1)
1341 text
.append("<tr><td>" + tr("Routes") + ":</td><td>"
1342 + l
.toString(_routeCount
) + "</td></tr>");
1343 if (_showWaypointsAction
->isChecked() && _waypointCount
> 1)
1344 text
.append("<tr><td>" + tr("Waypoints") + ":</td><td>"
1345 + l
.toString(_waypointCount
) + "</td></tr>");
1346 if (_showAreasAction
->isChecked() && _areaCount
> 1)
1347 text
.append("<tr><td>" + tr("Areas") + ":</td><td>"
1348 + l
.toString(_areaCount
) + "</td></tr>");
1350 if (_dateRange
.first
.isValid()) {
1351 if (_dateRange
.first
== _dateRange
.second
) {
1352 QString format
= l
.dateFormat(QLocale::LongFormat
);
1353 text
.append("<tr><td>" + tr("Date") + ":</td><td>"
1354 + _dateRange
.first
.toString(format
) + "</td></tr>");
1356 QString format
= l
.dateFormat(QLocale::ShortFormat
);
1357 text
.append("<tr><td>" + tr("Date") + ":</td><td>"
1358 + QString("%1 - %2").arg(_dateRange
.first
.toString(format
),
1359 _dateRange
.second
.toString(format
)) + "</td></tr>");
1364 text
.append("<tr><td>" + tr("Distance") + ":</td><td>"
1365 + Format::distance(distance(), units()) + "</td></tr>");
1367 text
.append("<tr><td>" + tr("Time") + ":</td><td>"
1368 + Format::timeSpan(time()) + "</td></tr>");
1369 text
.append("<tr><td>" + tr("Moving time") + ":</td><td>"
1370 + Format::timeSpan(movingTime()) + "</td></tr>");
1373 for (int i
= 0; i
< _tabs
.count(); i
++) {
1374 const GraphTab
*tab
= _tabs
.at(i
);
1378 text
.append("<tr><th colspan=\"2\">" + tab
->label() + "</th></tr>");
1379 for (int j
= 0; j
< tab
->info().size(); j
++) {
1380 const KV
<QString
, QString
> &kv
= tab
->info().at(j
);
1381 text
.append("<tr><td>" + kv
.key() + ":</td><td>" + kv
.value()
1386 text
.append("</table>");
1388 msgBox
.setWindowTitle(tr("Statistics"));
1389 msgBox
.setText("<h3>" + tr("Statistics") + "</h3>");
1390 msgBox
.setInformativeText(text
);
1391 #endif // Q_OS_ANDROID
1396 void GUI::plotMainPage(QPainter
*painter
, const QRectF
&rect
, qreal ratio
,
1399 QLocale
l(QLocale::system());
1405 if (!_pathName
.isNull() && _options
.printName
)
1406 info
.insert(tr("Name"), _pathName
);
1408 if (_options
.printItemCount
) {
1409 if (_showTracksAction
->isChecked() && _trackCount
> 1)
1410 info
.insert(tr("Tracks"), l
.toString(_trackCount
));
1411 if (_showRoutesAction
->isChecked() && _routeCount
> 1)
1412 info
.insert(tr("Routes"), l
.toString(_routeCount
));
1413 if (_showWaypointsAction
->isChecked() && _waypointCount
> 1)
1414 info
.insert(tr("Waypoints"), l
.toString(_waypointCount
));
1415 if (_showAreasAction
->isChecked() && _areaCount
> 1)
1416 info
.insert(tr("Areas"), l
.toString(_areaCount
));
1419 if (_dateRange
.first
.isValid() && _options
.printDate
) {
1420 if (_dateRange
.first
== _dateRange
.second
) {
1421 QString format
= l
.dateFormat(QLocale::LongFormat
);
1422 info
.insert(tr("Date"), _dateRange
.first
.toString(format
));
1424 QString format
= l
.dateFormat(QLocale::ShortFormat
);
1425 info
.insert(tr("Date"), QString("%1 - %2")
1426 .arg(_dateRange
.first
.toString(format
),
1427 _dateRange
.second
.toString(format
)));
1431 if (distance() > 0 && _options
.printDistance
)
1432 info
.insert(tr("Distance"), Format::distance(distance(), units()));
1433 if (time() > 0 && _options
.printTime
)
1434 info
.insert(tr("Time"), Format::timeSpan(time()));
1435 if (movingTime() > 0 && _options
.printMovingTime
)
1436 info
.insert(tr("Moving time"), Format::timeSpan(movingTime()));
1438 if (info
.isEmpty()) {
1442 ih
= info
.contentSize().height() * ratio
;
1444 info
.plot(painter
, QRectF(rect
.x(), rect
.y(), rect
.width(), ih
), ratio
);
1446 if (_graphTabWidget
->isVisible() && !_options
.separateGraphPage
) {
1447 qreal r
= rect
.width() / rect
.height();
1448 gh
= (rect
.width() > rect
.height())
1449 ? 0.15 * r
* (rect
.height() - ih
- 2*mh
)
1450 : 0.15 * (rect
.height() - ih
- 2*mh
);
1454 GraphTab
*gt
= static_cast<GraphTab
*>(_graphTabWidget
->currentWidget());
1455 gt
->plot(painter
, QRectF(rect
.x(), rect
.y() + rect
.height() - gh
,
1456 rect
.width(), gh
), ratio
);
1462 MapView::PlotFlags flags
;
1463 if (_options
.hiresPrint
)
1464 flags
|= MapView::HiRes
;
1466 flags
|= MapView::Expand
;
1468 _mapView
->plot(painter
, QRectF(rect
.x(), rect
.y() + ih
+ mh
, rect
.width(),
1469 rect
.height() - (ih
+ sc
*mh
+ gh
)), ratio
, flags
);
1472 void GUI::plotGraphsPage(QPainter
*painter
, const QRectF
&rect
, qreal ratio
)
1475 for (int i
= 0; i
< _tabs
.size(); i
++)
1476 if (!_tabs
.at(i
)->isEmpty())
1479 qreal sp
= ratio
* 20;
1480 qreal gh
= qMin((rect
.height() - ((cnt
- 1) * sp
))/(qreal
)cnt
,
1481 0.20 * rect
.height());
1484 for (int i
= 0; i
< _tabs
.size(); i
++) {
1485 if (!_tabs
.at(i
)->isEmpty()) {
1486 _tabs
.at(i
)->plot(painter
, QRectF(rect
.x(), rect
.y() + y
,
1487 rect
.width(), gh
), ratio
);
1493 qreal
GUI::graphPlotHeight(const QRectF
&rect
, qreal ratio
)
1496 for (int i
= 0; i
< _tabs
.size(); i
++)
1497 if (!_tabs
.at(i
)->isEmpty())
1500 qreal sp
= ratio
* 20;
1501 qreal gh
= qMin((rect
.height() - ((cnt
- 1) * sp
))/(qreal
)cnt
,
1502 0.20 * rect
.height());
1504 return cnt
* gh
+ (cnt
- 1) * sp
;
1507 void GUI::plot(QPrinter
*printer
)
1509 QPainter
p(printer
);
1510 qreal fsr
= 1085.0 / (qMax(printer
->width(), printer
->height())
1511 / (qreal
)printer
->resolution());
1512 qreal ratio
= p
.paintEngine()->paintDevice()->logicalDpiX() / fsr
;
1513 QRectF
rect(0, 0, printer
->width(), printer
->height());
1515 plotMainPage(&p
, rect
, ratio
);
1517 if (!_tabs
.isEmpty() && _options
.separateGraphPage
) {
1519 plotGraphsPage(&p
, rect
, ratio
);
1523 void GUI::reloadFiles()
1533 _dateRange
= DateTimeRange(QDateTime(), QDateTime());
1534 _pathName
= QString();
1536 for (int i
= 0; i
< _tabs
.count(); i
++)
1537 _tabs
.at(i
)->clear();
1541 for (int i
= 0; i
< _files
.size(); i
++) {
1542 if (!loadFile(_files
.at(i
), true, showError
)) {
1548 updateStatusBarInfo();
1549 updateWindowTitle();
1550 if (_files
.isEmpty())
1551 _fileActionGroup
->setEnabled(false);
1552 #ifndef Q_OS_ANDROID
1554 _browser
->setCurrent(_files
.last());
1555 #endif // Q_OS_ANDROID
1556 updateDEMDownloadAction();
1559 void GUI::closeFiles()
1569 _dateRange
= DateTimeRange(QDateTime(), QDateTime());
1570 _pathName
= QString();
1572 for (int i
= 0; i
< _tabs
.count(); i
++)
1573 _tabs
.at(i
)->clear();
1581 void GUI::closeAll()
1585 _fileActionGroup
->setEnabled(false);
1586 updateStatusBarInfo();
1587 updateWindowTitle();
1589 updateDEMDownloadAction();
1592 _browser
->setCurrentDir(QString());
1593 #endif // Q_OS_ANDROID
1596 void GUI::showGraphs(bool show
)
1598 _graphTabWidget
->setHidden(!show
);
1602 void GUI::showGraphTabs(bool show
)
1604 _graphTabWidget
->tabBar()->setVisible(show
);
1606 #else // Q_OS_ANDROID
1607 void GUI::showToolbars(bool show
)
1610 Q_ASSERT(!_windowStates
.isEmpty());
1611 restoreState(_windowStates
.last());
1612 _windowStates
.removeLast();
1614 _windowStates
.append(saveState());
1615 removeToolBar(_fileToolBar
);
1616 removeToolBar(_showToolBar
);
1617 removeToolBar(_navigationToolBar
);
1621 void GUI::showFullscreen(bool show
)
1624 _windowGeometries
.append(saveGeometry());
1625 _frameStyle
= _mapView
->frameStyle();
1626 statusBar()->hide();
1628 showToolbars(false);
1629 _mapView
->setFrameStyle(QFrame::NoFrame
);
1630 _graphTabWidget
->tabBar()->hide();
1632 _graphTabWidget
->setDocumentMode(true);
1636 Q_ASSERT(!_windowGeometries
.isEmpty());
1637 _windowGeometries
.removeLast();
1638 statusBar()->show();
1641 _mapView
->setFrameStyle(_frameStyle
);
1642 _graphTabWidget
->tabBar()->show();
1644 _graphTabWidget
->setDocumentMode(false);
1649 #endif // Q_OS_ANDROID
1651 void GUI::showTracks(bool show
)
1653 _mapView
->showTracks(show
);
1655 for (int i
= 0; i
< _tabs
.size(); i
++)
1656 _tabs
.at(i
)->showTracks(show
);
1658 updateStatusBarInfo();
1660 updateDEMDownloadAction();
1663 void GUI::showRoutes(bool show
)
1665 _mapView
->showRoutes(show
);
1667 for (int i
= 0; i
< _tabs
.size(); i
++)
1668 _tabs
.at(i
)->showRoutes(show
);
1670 updateStatusBarInfo();
1672 updateDEMDownloadAction();
1675 void GUI::showWaypoints(bool show
)
1677 _mapView
->showWaypoints(show
);
1678 updateDEMDownloadAction();
1681 void GUI::showAreas(bool show
)
1683 _mapView
->showAreas(show
);
1684 updateDEMDownloadAction();
1687 void GUI::showGraphGrids(bool show
)
1689 for (int i
= 0; i
< _tabs
.size(); i
++)
1690 _tabs
.at(i
)->showGrid(show
);
1693 void GUI::showGraphSliderInfo(bool show
)
1695 for (int i
= 0; i
< _tabs
.size(); i
++)
1696 _tabs
.at(i
)->showSliderInfo(show
);
1699 void GUI::showPathMarkerInfo(QAction
*action
)
1701 if (action
== _showMarkersAction
) {
1702 _mapView
->showMarkers(true);
1703 _mapView
->showMarkerInfo(MarkerInfoItem::None
);
1704 } else if (action
== _showMarkerDateAction
) {
1705 _mapView
->showMarkers(true);
1706 _mapView
->showMarkerInfo(MarkerInfoItem::Date
);
1707 } else if (action
== _showMarkerCoordinatesAction
) {
1708 _mapView
->showMarkers(true);
1709 _mapView
->showMarkerInfo(MarkerInfoItem::Position
);
1711 _mapView
->showMarkers(false);
1712 _mapView
->showMarkerInfo(MarkerInfoItem::None
);
1719 QStringList
files(QFileDialog::getOpenFileNames(this, tr("Open map file"),
1721 #else // Q_OS_ANDROID
1722 QStringList
files(QFileDialog::getOpenFileNames(this, tr("Open map file"),
1723 _mapDir
, MapList::formats()));
1724 #endif // Q_OS_ANDROID
1725 MapAction
*a
, *lastReady
= 0;
1726 int showError
= (files
.size() > 1) ? 2 : 1;
1728 for (int i
= 0; i
< files
.size(); i
++) {
1729 if (loadMap(files
.at(i
), a
, showError
) && a
)
1732 if (!files
.isEmpty())
1733 _mapDir
= QFileInfo(files
.last()).path();
1735 lastReady
->trigger();
1738 static MapAction
*findMapAction(const QList
<QAction
*> &mapActions
,
1741 for (int i
= 0; i
< mapActions
.count(); i
++) {
1742 const Map
*m
= mapActions
.at(i
)->data().value
<Map
*>();
1743 if (map
->path() == m
->path())
1744 return static_cast<MapAction
*>(mapActions
.at(i
));
1750 bool GUI::loadMapNode(const TreeNode
<Map
*> &node
, MapAction
*&action
,
1751 const QList
<QAction
*> &existingActions
, int &showError
)
1757 for (int i
= 0; i
< node
.childs().size(); i
++)
1758 valid
= loadMapNode(node
.childs().at(i
), action
, existingActions
,
1761 for (int i
= 0; i
< node
.items().size(); i
++) {
1762 Map
*map
= node
.items().at(i
);
1765 if (!(a
= findMapAction(existingActions
, map
))) {
1766 if (!map
->isValid()) {
1768 QString error
= tr("Error loading map:") + "\n"
1769 + Util::displayName(map
->path()) + ": " + map
->errorString();
1771 if (showError
> 1) {
1772 QMessageBox
message(QMessageBox::Critical
, APP_NAME
,
1773 error
, QMessageBox::Ok
, this);
1774 QCheckBox
checkBox(tr("Don't show again"));
1775 message
.setCheckBox(&checkBox
);
1777 if (checkBox
.isChecked())
1780 QMessageBox::critical(this, APP_NAME
, error
);
1786 a
= new MapAction(map
, _mapsActionGroup
);
1787 _mapMenu
->insertAction(_mapsEnd
, a
);
1789 if (map
->isReady()) {
1791 _showMapAction
->setEnabled(true);
1792 _clearMapCacheAction
->setEnabled(true);
1794 connect(a
, &MapAction::loaded
, this, &GUI::mapLoaded
);
1798 map
= a
->data().value
<Map
*>();
1807 bool GUI::loadMap(const QString
&fileName
, MapAction
*&action
, int &showError
)
1809 TreeNode
<Map
*> maps(MapList::loadMaps(fileName
, _mapView
->inputProjection()));
1810 QList
<QAction
*> existingActions(_mapsActionGroup
->actions());
1812 return loadMapNode(maps
, action
, existingActions
, showError
);
1815 void GUI::mapLoaded()
1817 MapAction
*action
= static_cast<MapAction
*>(QObject::sender());
1818 Map
*map
= action
->data().value
<Map
*>();
1820 if (map
->isValid()) {
1822 _showMapAction
->setEnabled(true);
1823 _clearMapCacheAction
->setEnabled(true);
1825 QString error
= tr("Error loading map:") + "\n"
1826 + Util::displayName(map
->path()) + ": " + map
->errorString();
1827 QMessageBox::critical(this, APP_NAME
, error
);
1828 action
->deleteLater();
1832 void GUI::mapLoadedDir()
1834 MapAction
*action
= static_cast<MapAction
*>(QObject::sender());
1835 Map
*map
= action
->data().value
<Map
*>();
1837 if (map
->isValid()) {
1838 _showMapAction
->setEnabled(true);
1839 _clearMapCacheAction
->setEnabled(true);
1840 QList
<MapAction
*> actions
;
1841 actions
.append(action
);
1842 _mapView
->loadMaps(actions
);
1844 QString error
= tr("Error loading map:") + "\n"
1845 + Util::displayName(map
->path()) + ": " + map
->errorString();
1846 QMessageBox::critical(this, APP_NAME
, error
);
1847 action
->deleteLater();
1851 void GUI::loadMapDirNode(const TreeNode
<Map
*> &node
, QList
<MapAction
*> &actions
,
1852 QMenu
*menu
, const QList
<QAction
*> &existingActions
, int &showError
)
1854 for (int i
= 0; i
< node
.childs().size(); i
++) {
1855 QMenu
*cm
= new QMenu(node
.childs().at(i
).name(), menu
);
1857 loadMapDirNode(node
.childs().at(i
), actions
, cm
, existingActions
,
1861 for (int i
= 0; i
< node
.items().size(); i
++) {
1862 Map
*map
= node
.items().at(i
);
1865 if (!(a
= findMapAction(existingActions
, map
))) {
1866 if (!map
->isValid()) {
1868 QString error
= tr("Error loading map:") + "\n"
1869 + Util::displayName(map
->path()) + ": " + map
->errorString();
1871 if (showError
> 1) {
1872 QMessageBox
message(QMessageBox::Critical
, APP_NAME
,
1873 error
, QMessageBox::Ok
, this);
1874 QCheckBox
checkBox(tr("Don't show again"));
1875 message
.setCheckBox(&checkBox
);
1877 if (checkBox
.isChecked())
1880 QMessageBox::critical(this, APP_NAME
, error
);
1885 a
= new MapAction(map
, _mapsActionGroup
);
1888 if (map
->isReady()) {
1889 _showMapAction
->setEnabled(true);
1890 _clearMapCacheAction
->setEnabled(true);
1893 connect(a
, &MapAction::loaded
, this, &GUI::mapLoadedDir
);
1898 map
= a
->data().value
<Map
*>();
1905 void GUI::loadMapDir()
1907 QString
dir(QFileDialog::getExistingDirectory(this,
1908 tr("Select map directory"), _mapDir
, QFileDialog::ShowDirsOnly
));
1913 TreeNode
<Map
*> maps(MapList::loadMaps(dir
, _mapView
->inputProjection()));
1914 QList
<QAction
*> existingActions(_mapsActionGroup
->actions());
1915 QList
<MapAction
*> actions
;
1916 QMenu
*menu
= new QMenu(maps
.name());
1917 int showError
= (maps
.items().size() > 1 || !maps
.childs().isEmpty())
1920 loadMapDirNode(maps
, actions
, menu
, existingActions
, showError
);
1922 _mapView
->loadMaps(actions
);
1924 if (menu
->isEmpty())
1927 _mapMenu
->insertMenu(_mapsEnd
, menu
);
1929 _mapDir
= fi
.absolutePath();
1930 _fileActionGroup
->setEnabled(true);
1931 _reloadFileAction
->setEnabled(false);
1934 void GUI::clearMapCache()
1936 if (QMessageBox::question(this, APP_NAME
,
1937 tr("Clear \"%1\" tile cache?").arg(_map
->name())) == QMessageBox::Yes
)
1938 _mapView
->clearMapCache();
1941 void GUI::downloadDEM()
1943 RectC
br(_mapView
->boundingRect());
1944 _demRects
.append(br
);
1946 if (!_dem
->loadTiles(br
) && _demRects
.size() == 1)
1950 void GUI::demLoaded()
1952 for (int i
= 0; i
< _demRects
.size(); i
++) {
1953 if (!_dem
->checkTiles(_demRects
.at(i
))) {
1954 QMessageBox::warning(this, APP_NAME
,
1955 tr("Could not download all required DEM files."));
1965 void GUI::showDEMTiles()
1967 QList
<Area
> tiles(DEM::tiles());
1969 if (tiles
.isEmpty()) {
1970 QMessageBox::information(this, APP_NAME
, tr("No local DEM tiles found."));
1972 _mapView
->loadDEMs(tiles
);
1974 _areaCount
+= tiles
.size();
1976 _fileActionGroup
->setEnabled(true);
1977 _reloadFileAction
->setEnabled(false);
1981 void GUI::updateStatusBarInfo()
1983 if (_files
.count() == 0)
1984 _fileNameLabel
->setText(tr("No files loaded"));
1985 else if (_files
.count() == 1)
1986 _fileNameLabel
->setText(Util::displayName(_files
.at(0)));
1988 _fileNameLabel
->setText(tr("%n files", "", _files
.count()));
1991 _distanceLabel
->setText(Format::distance(distance(), units()));
1993 _distanceLabel
->clear();
1996 if (_movingTimeAction
->isChecked()) {
1997 _timeLabel
->setText(Format::timeSpan(movingTime())
1999 _timeLabel
->setToolTip(Format::timeSpan(time()));
2001 _timeLabel
->setText(Format::timeSpan(time()));
2002 _timeLabel
->setToolTip(Format::timeSpan(movingTime())
2006 _timeLabel
->clear();
2007 _timeLabel
->setToolTip(QString());
2011 statusBar()->setVisible(!_files
.isEmpty());
2012 #endif // Q_OS_ANDROID
2015 void GUI::updateWindowTitle()
2017 if (_files
.count() == 1)
2018 setWindowTitle(QFileInfo(_files
.at(0)).fileName() + " - " + APP_NAME
);
2020 setWindowTitle(APP_NAME
);
2023 #ifndef Q_OS_ANDROID
2024 void GUI::updateRecentFiles(const QString
&fileName
)
2028 QList
<QAction
*> actions(_recentFilesActionGroup
->actions());
2029 for (int i
= 0; i
< actions
.size(); i
++) {
2030 if (actions
.at(i
)->text() == fileName
) {
2038 else if (actions
.size() == MAX_RECENT_FILES
)
2039 delete actions
.last();
2041 actions
= _recentFilesActionGroup
->actions();
2042 QAction
*before
= actions
.size() ? actions
.last() : _recentFilesEnd
;
2043 _recentFilesMenu
->insertAction(before
,
2044 new QAction(fileName
, _recentFilesActionGroup
));
2045 _recentFilesMenu
->setEnabled(true);
2048 void GUI::clearRecentFiles()
2050 QList
<QAction
*> actions(_recentFilesActionGroup
->actions());
2052 for (int i
= 0; i
< actions
.size(); i
++)
2053 delete actions
.at(i
);
2055 _recentFilesMenu
->setEnabled(false);
2058 void GUI::recentFileSelected(QAction
*action
)
2061 openFile(action
->text(), true, showError
);
2063 #endif // Q_OS_ANDROID
2065 void GUI::mapChanged(QAction
*action
)
2067 _map
= action
->data().value
<Map
*>();
2068 _mapView
->setMap(_map
);
2073 QAction
*checked
= _mapsActionGroup
->checkedAction();
2077 QList
<QAction
*> maps(_mapsActionGroup
->actions());
2078 for (int i
= 1; i
< maps
.size(); i
++) {
2079 int next
= (maps
.indexOf(checked
) + i
) % maps
.count();
2080 if (maps
.at(next
)->isEnabled()) {
2081 maps
.at(next
)->trigger();
2089 QAction
*checked
= _mapsActionGroup
->checkedAction();
2093 QList
<QAction
*> maps(_mapsActionGroup
->actions());
2094 for (int i
= 1; i
< maps
.size(); i
++) {
2095 int prev
= (maps
.indexOf(checked
) + maps
.count() - i
) % maps
.count();
2096 if (maps
.at(prev
)->isEnabled()) {
2097 maps
.at(prev
)->trigger();
2103 void GUI::poiFileChecked(QAction
*action
)
2105 _poi
->enableFile(action
->data().value
<QString
>(), action
->isChecked());
2108 void GUI::selectAllPOIs()
2110 QList
<QAction
*> actions(_poisActionGroup
->actions());
2111 for (int i
= 0; i
< actions
.size(); i
++) {
2112 POIAction
*a
= static_cast<POIAction
*>(actions
.at(i
));
2113 if (_poi
->enableFile(a
->data().toString(), true))
2114 a
->setChecked(true);
2118 void GUI::unselectAllPOIs()
2120 QList
<QAction
*> actions(_poisActionGroup
->actions());
2121 for (int i
= 0; i
< actions
.size(); i
++) {
2122 POIAction
*a
= static_cast<POIAction
*>(actions
.at(i
));
2123 if (_poi
->enableFile(a
->data().toString(), false))
2124 a
->setChecked(false);
2128 void GUI::graphChanged(int index
)
2133 GraphTab
*gt
= static_cast<GraphTab
*>(_graphTabWidget
->widget(index
));
2135 _mapView
->setGraph(_tabs
.indexOf(gt
));
2138 gt
->setSliderPosition(_lastTab
->sliderPosition());
2142 void GUI::updateNavigationActions()
2145 _navigation
->enableNext(!_browser
->isLast()
2146 && !_browser
->current().isNull());
2147 _navigation
->enablePrev(!_browser
->isFirst()
2148 && !_browser
->current().isNull());
2149 #else // Q_OS_ANDROID
2150 _lastAction
->setEnabled(!_browser
->isLast());
2151 _nextAction
->setEnabled(!_browser
->isLast());
2152 _firstAction
->setEnabled(!_browser
->isFirst());
2153 _prevAction
->setEnabled(!_browser
->isFirst());
2154 #endif // Q_OS_ANDROID
2157 bool GUI::updateGraphTabs()
2161 bool hidden
= _graphTabWidget
->isHidden();
2163 for (int i
= 0; i
< _tabs
.size(); i
++) {
2165 if (tab
->isEmpty() && (index
= _graphTabWidget
->indexOf(tab
)) >= 0)
2166 _graphTabWidget
->removeTab(index
);
2169 for (int i
= 0; i
< _tabs
.size(); i
++) {
2171 if (!tab
->isEmpty() && _graphTabWidget
->indexOf(tab
) < 0)
2172 _graphTabWidget
->insertTab(i
, tab
, _tabs
.at(i
)->label());
2175 if (_graphTabWidget
->count() &&
2176 ((_showTracksAction
->isChecked() && _trackCount
)
2177 || (_showRoutesAction
->isChecked() && _routeCount
))) {
2178 if (_showGraphsAction
->isChecked())
2179 _graphTabWidget
->setHidden(false);
2180 _showGraphsAction
->setEnabled(true);
2182 _graphTabWidget
->setHidden(true);
2183 _showGraphsAction
->setEnabled(false);
2186 return (hidden
!= _graphTabWidget
->isHidden());
2189 void GUI::updateDEMDownloadAction()
2191 _downloadDEMAction
->setEnabled(!_dem
->url().isEmpty()
2192 && !_dem
->checkTiles(_mapView
->boundingRect()));
2195 void GUI::setTimeType(TimeType type
)
2197 for (int i
= 0; i
<_tabs
.count(); i
++)
2198 _tabs
.at(i
)->setTimeType(type
);
2200 updateStatusBarInfo();
2203 void GUI::setUnits(Units units
)
2207 _mapView
->setUnits(units
);
2208 for (int i
= 0; i
<_tabs
.count(); i
++)
2209 _tabs
.at(i
)->setUnits(units
);
2210 updateStatusBarInfo();
2213 void GUI::setCoordinatesFormat(CoordinatesFormat format
)
2215 _mapView
->setCoordinatesFormat(format
);
2218 void GUI::setGraphType(GraphType type
)
2220 for (int i
= 0; i
<_tabs
.count(); i
++)
2221 _tabs
.at(i
)->setGraphType(type
);
2227 QString file
= _browser
->next();
2232 openFile(file
, true, showError
);
2238 QString file
= _browser
->prev();
2243 openFile(file
, true, showError
);
2249 QString file
= _browser
->last();
2254 openFile(file
, true, showError
);
2260 QString file
= _browser
->first();
2265 openFile(file
, true, showError
);
2268 #ifndef Q_OS_ANDROID
2269 void GUI::keyPressEvent(QKeyEvent
*event
)
2274 switch (event
->key()) {
2276 file
= _browser
->prev();
2279 file
= _browser
->next();
2282 file
= _browser
->first();
2285 file
= _browser
->last();
2288 case TOGGLE_GRAPH_TYPE_KEY
:
2289 if (_timeGraphAction
->isChecked())
2290 _distanceGraphAction
->trigger();
2292 _timeGraphAction
->trigger();
2294 case TOGGLE_TIME_TYPE_KEY
:
2295 if (_movingTimeAction
->isChecked())
2296 _totalTimeAction
->trigger();
2298 _movingTimeAction
->trigger();
2300 case TOGGLE_MARKER_INFO_KEY
:
2301 if (_showMarkerDateAction
->isChecked())
2302 _showMarkerCoordinatesAction
->trigger();
2303 else if (_showMarkerCoordinatesAction
->isChecked())
2304 _showMarkerDateAction
->trigger();
2306 case Qt::Key_Escape
:
2307 if (_fullscreenAction
->isChecked()) {
2308 _fullscreenAction
->setChecked(false);
2309 showFullscreen(false);
2315 if (!file
.isNull()) {
2316 if (!(event
->modifiers() & MODIFIER
))
2318 openFile(file
, true, showError
);
2322 QMainWindow::keyPressEvent(event
);
2324 #endif // Q_OS_ANDROID
2326 void GUI::closeEvent(QCloseEvent
*event
)
2329 QMainWindow::closeEvent(event
);
2332 void GUI::dragEnterEvent(QDragEnterEvent
*event
)
2334 if (!event
->mimeData()->hasUrls())
2336 if (event
->proposedAction() != Qt::CopyAction
)
2339 QList
<QUrl
> urls
= event
->mimeData()->urls();
2340 for (int i
= 0; i
< urls
.size(); i
++)
2341 if (!urls
.at(i
).isLocalFile())
2344 event
->acceptProposedAction();
2347 void GUI::dropEvent(QDropEvent
*event
)
2349 MapAction
*lastReady
= 0;
2350 QList
<QUrl
> urls(event
->mimeData()->urls());
2352 int showError
= (urls
.size() > 1) ? 2 : 1;
2354 for (int i
= 0; i
< urls
.size(); i
++) {
2355 QString
file(urls
.at(i
).toLocalFile());
2357 if (!openFile(file
, false, silent
)) {
2359 if (!loadMap(file
, a
, silent
))
2360 openFile(file
, true, showError
);
2369 lastReady
->trigger();
2371 event
->acceptProposedAction();
2374 QGeoPositionInfoSource
*GUI::positionSource(const Options
&options
)
2376 QGeoPositionInfoSource
*source
;
2378 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
2379 source
= QGeoPositionInfoSource::createSource(options
.plugin
, this);
2381 source
= QGeoPositionInfoSource::createSource(options
.plugin
,
2382 options
.pluginParams
.value(options
.plugin
), this);
2385 source
->setPreferredPositioningMethods(
2386 QGeoPositionInfoSource::SatellitePositioningMethods
);
2391 void GUI::writeSettings()
2393 #define WRITE(name, value) \
2394 Settings::name.write(settings, value);
2396 QSettings
settings(qApp
->applicationName(), qApp
->applicationName());
2400 #ifndef Q_OS_ANDROID
2401 settings
.beginGroup(SETTINGS_WINDOW
);
2402 if (!_windowStates
.isEmpty() && !_windowGeometries
.isEmpty()) {
2403 WRITE(windowState
, _windowStates
.first());
2404 WRITE(windowGeometry
, _windowGeometries
.first());
2406 WRITE(windowState
, saveState());
2407 WRITE(windowGeometry
, saveGeometry());
2409 settings
.endGroup();
2410 #endif // Q_OS_ANDROID
2413 settings
.beginGroup(SETTINGS_SETTINGS
);
2414 WRITE(timeType
, _movingTimeAction
->isChecked() ? Moving
: Total
);
2415 WRITE(units
, _imperialUnitsAction
->isChecked()
2416 ? Imperial
: _nauticalUnitsAction
->isChecked()
2417 ? Nautical
: Metric
);
2418 WRITE(coordinatesFormat
, _dmsAction
->isChecked()
2419 ? DMS
: _degreesMinutesAction
->isChecked()
2420 ? DegreesMinutes
: DecimalDegrees
);
2421 #ifndef Q_OS_ANDROID
2422 WRITE(showToolbars
, _showToolbarsAction
->isChecked());
2423 #endif // Q_OS_ANDROID
2424 settings
.endGroup();
2427 #ifndef Q_OS_ANDROID
2428 QList
<QAction
*> recentActions(_recentFilesActionGroup
->actions());
2430 for (int i
= 0; i
< recentActions
.size(); i
++)
2431 recent
.append(recentActions
.at(i
)->text());
2433 settings
.beginGroup(SETTINGS_FILE
);
2434 WRITE(recentDataFiles
, recent
);
2435 settings
.endGroup();
2436 #endif // Q_OS_ANDROID
2439 settings
.beginGroup(SETTINGS_MAP
);
2440 WRITE(activeMap
, _map
->name());
2441 WRITE(showMap
, _showMapAction
->isChecked());
2442 WRITE(cursorCoordinates
, _showCoordinatesAction
->isChecked());
2443 settings
.endGroup();
2446 settings
.beginGroup(SETTINGS_GRAPH
);
2447 WRITE(showGraphs
, _showGraphsAction
->isChecked());
2448 WRITE(graphType
, _timeGraphAction
->isChecked() ? Time
: Distance
);
2449 WRITE(showGrid
, _showGraphGridAction
->isChecked());
2450 WRITE(sliderInfo
, _showGraphSliderInfoAction
->isChecked());
2452 WRITE(showGraphTabs
, _showGraphTabsAction
->isChecked());
2453 #endif // Q_OS_ANDROID
2454 settings
.endGroup();
2457 QList
<QAction
*> disabledActions(_poisActionGroup
->actions());
2458 QStringList disabled
;
2459 for (int i
= 0; i
< disabledActions
.size(); i
++)
2460 if (!disabledActions
.at(i
)->isChecked())
2461 disabled
.append(disabledActions
.at(i
)->data().toString());
2463 settings
.beginGroup(SETTINGS_POI
);
2464 WRITE(showPoi
, _showPOIAction
->isChecked());
2465 WRITE(poiOverlap
, _overlapPOIAction
->isChecked());
2466 WRITE(poiLabels
, _showPOILabelsAction
->isChecked());
2467 WRITE(poiIcons
, _showPOIIconsAction
->isChecked());
2468 WRITE(disabledPoiFiles
, disabled
);
2469 settings
.endGroup();
2472 MarkerInfoItem::Type mi
;
2473 if (_showMarkerDateAction
->isChecked())
2474 mi
= MarkerInfoItem::Date
;
2475 else if (_showMarkerCoordinatesAction
->isChecked())
2476 mi
= MarkerInfoItem::Position
;
2478 mi
= MarkerInfoItem::None
;
2480 settings
.beginGroup(SETTINGS_DATA
);
2481 WRITE(tracks
, _showTracksAction
->isChecked());
2482 WRITE(routes
, _showRoutesAction
->isChecked());
2483 WRITE(waypoints
, _showWaypointsAction
->isChecked());
2484 WRITE(areas
, _showAreasAction
->isChecked());
2485 WRITE(waypointIcons
, _showWaypointIconsAction
->isChecked());
2486 WRITE(waypointLabels
, _showWaypointLabelsAction
->isChecked());
2487 WRITE(routeWaypoints
, _showRouteWaypointsAction
->isChecked());
2488 WRITE(pathTicks
, _showTicksAction
->isChecked());
2489 WRITE(positionMarkers
, _showMarkersAction
->isChecked()
2490 || _showMarkerDateAction
->isChecked()
2491 || _showMarkerCoordinatesAction
->isChecked());
2492 WRITE(markerInfo
, mi
);
2493 WRITE(useStyles
, _useStylesAction
->isChecked());
2494 settings
.endGroup();
2497 settings
.beginGroup(SETTINGS_POSITION
);
2498 WRITE(showPosition
, _showPositionAction
->isChecked());
2499 WRITE(followPosition
, _followPositionAction
->isChecked());
2500 WRITE(positionCoordinates
, _showPositionCoordinatesAction
->isChecked());
2501 WRITE(motionInfo
, _showMotionInfoAction
->isChecked());
2502 settings
.endGroup();
2505 settings
.beginGroup(SETTINGS_PDF_EXPORT
);
2506 WRITE(pdfOrientation
, _pdfExport
.orientation
);
2507 WRITE(pdfResolution
, _pdfExport
.resolution
);
2508 WRITE(pdfSize
, _pdfExport
.paperSize
);
2509 WRITE(pdfMarginLeft
, _pdfExport
.margins
.left());
2510 WRITE(pdfMarginTop
, _pdfExport
.margins
.top());
2511 WRITE(pdfMarginRight
, _pdfExport
.margins
.right());
2512 WRITE(pdfMarginBottom
, _pdfExport
.margins
.bottom());
2513 WRITE(pdfFileName
, _pdfExport
.fileName
);
2514 settings
.endGroup();
2517 settings
.beginGroup(SETTINGS_PNG_EXPORT
);
2518 WRITE(pngWidth
, _pngExport
.size
.width());
2519 WRITE(pngHeight
, _pngExport
.size
.height());
2520 WRITE(pngMarginLeft
, _pngExport
.margins
.left());
2521 WRITE(pngMarginTop
, _pngExport
.margins
.top());
2522 WRITE(pngMarginRight
, _pngExport
.margins
.right());
2523 WRITE(pngMarginBottom
, _pngExport
.margins
.bottom());
2524 WRITE(pngAntialiasing
, _pngExport
.antialiasing
);
2525 WRITE(pngFileName
, _pngExport
.fileName
);
2526 settings
.endGroup();
2529 settings
.beginGroup(SETTINGS_OPTIONS
);
2530 WRITE(paletteColor
, _options
.palette
.color());
2531 WRITE(paletteShift
, _options
.palette
.shift());
2532 WRITE(mapOpacity
, _options
.mapOpacity
);
2533 WRITE(backgroundColor
, _options
.backgroundColor
);
2534 WRITE(crosshairColor
, _options
.crosshairColor
);
2535 WRITE(infoColor
, _options
.infoColor
);
2536 WRITE(infoBackground
, _options
.infoBackground
);
2537 WRITE(trackWidth
, _options
.trackWidth
);
2538 WRITE(routeWidth
, _options
.routeWidth
);
2539 WRITE(areaWidth
, _options
.areaWidth
);
2540 WRITE(trackStyle
, (int)_options
.trackStyle
);
2541 WRITE(routeStyle
, (int)_options
.routeStyle
);
2542 WRITE(areaStyle
, (int)_options
.areaStyle
);
2543 WRITE(areaOpacity
, _options
.areaOpacity
);
2544 WRITE(waypointSize
, _options
.waypointSize
);
2545 WRITE(waypointColor
, _options
.waypointColor
);
2546 WRITE(poiSize
, _options
.poiSize
);
2547 WRITE(poiColor
, _options
.poiColor
);
2548 WRITE(graphWidth
, _options
.graphWidth
);
2549 WRITE(pathAntiAliasing
, _options
.pathAntiAliasing
);
2550 WRITE(graphAntiAliasing
, _options
.graphAntiAliasing
);
2551 WRITE(elevationFilter
, _options
.elevationFilter
);
2552 WRITE(speedFilter
, _options
.speedFilter
);
2553 WRITE(heartRateFilter
, _options
.heartRateFilter
);
2554 WRITE(cadenceFilter
, _options
.cadenceFilter
);
2555 WRITE(powerFilter
, _options
.powerFilter
);
2556 WRITE(outlierEliminate
, _options
.outlierEliminate
);
2557 WRITE(automaticPause
, _options
.automaticPause
);
2558 WRITE(pauseSpeed
, _options
.pauseSpeed
);
2559 WRITE(pauseInterval
, _options
.pauseInterval
);
2560 WRITE(useReportedSpeed
, _options
.useReportedSpeed
);
2561 WRITE(dataUseDEM
, _options
.dataUseDEM
);
2562 WRITE(secondaryElevation
, _options
.showSecondaryElevation
);
2563 WRITE(secondarySpeed
, _options
.showSecondarySpeed
);
2564 WRITE(timeZone
, QVariant::fromValue(_options
.timeZone
));
2565 WRITE(useSegments
, _options
.useSegments
);
2566 WRITE(poiRadius
, _options
.poiRadius
);
2567 WRITE(demURL
, _options
.demURL
);
2568 WRITE(demAuthentication
, _options
.demAuthorization
);
2569 WRITE(demUsername
, _options
.demUsername
);
2570 WRITE(demPassword
, _options
.demPassword
);
2571 WRITE(positionPlugin(), _options
.plugin
);
2572 WRITE(positionPluginParameters
, _options
.pluginParams
);
2573 WRITE(useOpenGL
, _options
.useOpenGL
);
2574 WRITE(enableHTTP2
, _options
.enableHTTP2
);
2575 WRITE(pixmapCache
, _options
.pixmapCache
);
2576 WRITE(demCache
, _options
.demCache
);
2577 WRITE(connectionTimeout
, _options
.connectionTimeout
);
2578 WRITE(hiresPrint
, _options
.hiresPrint
);
2579 WRITE(printName
, _options
.printName
);
2580 WRITE(printDate
, _options
.printDate
);
2581 WRITE(printDistance
, _options
.printDistance
);
2582 WRITE(printTime
, _options
.printTime
);
2583 WRITE(printMovingTime
, _options
.printMovingTime
);
2584 WRITE(printItemCount
, _options
.printItemCount
);
2585 WRITE(separateGraphPage
, _options
.separateGraphPage
);
2586 WRITE(sliderColor
, _options
.sliderColor
);
2587 WRITE(outputProjection
, _options
.outputProjection
);
2588 WRITE(inputProjection
, _options
.inputProjection
);
2589 WRITE(hidpiMap
, _options
.hidpiMap
);
2590 WRITE(dataPath
, _options
.dataPath
);
2591 WRITE(mapsPath
, _options
.mapsPath
);
2592 WRITE(poiPath
, _options
.poiPath
);
2593 settings
.endGroup();
2596 void GUI::readSettings(QString
&activeMap
, QStringList
&disabledPOIs
,
2597 QStringList
&recentFiles
)
2599 #define READ(name) \
2600 (Settings::name.read(settings))
2602 QSettings
settings(qApp
->applicationName(), qApp
->applicationName());
2604 #ifndef Q_OS_ANDROID
2605 settings
.beginGroup(SETTINGS_WINDOW
);
2606 restoreGeometry(READ(windowGeometry
).toByteArray());
2607 restoreState(READ(windowState
).toByteArray());
2608 settings
.endGroup();
2609 #endif // Q_OS_ANDROID
2612 settings
.beginGroup(SETTINGS_SETTINGS
);
2613 TimeType tt
= (TimeType
)READ(timeType
).toInt();
2615 _movingTimeAction
->setChecked(true);
2617 _totalTimeAction
->setChecked(true);
2620 Units u
= (Units
)READ(units
).toInt();
2622 _imperialUnitsAction
->setChecked(true);
2623 else if (u
== Nautical
)
2624 _nauticalUnitsAction
->setChecked(true);
2626 _metricUnitsAction
->setChecked(true);
2629 CoordinatesFormat cf
= (CoordinatesFormat
)READ(coordinatesFormat
).toInt();
2631 _dmsAction
->setChecked(true);
2632 else if (cf
== DegreesMinutes
)
2633 _degreesMinutesAction
->setChecked(true);
2635 _decimalDegreesAction
->setChecked(true);
2636 setCoordinatesFormat(cf
);
2638 #ifndef Q_OS_ANDROID
2639 if (READ(showToolbars
).toBool())
2640 _showToolbarsAction
->setChecked(true);
2642 showToolbars(false);
2643 #endif // Q_OS_ANDROID
2644 settings
.endGroup();
2647 #ifndef Q_OS_ANDROID
2648 settings
.beginGroup(SETTINGS_FILE
);
2649 recentFiles
= READ(recentDataFiles
);
2650 settings
.endGroup();
2651 #else // Q_OS_ANDROID
2652 Q_UNUSED(recentFiles
);
2653 #endif // Q_OS_ANDROID
2656 settings
.beginGroup(SETTINGS_MAP
);
2657 if (READ(showMap
).toBool()) {
2658 _showMapAction
->setChecked(true);
2659 _mapView
->showMap(true);
2661 if (READ(cursorCoordinates
).toBool()) {
2662 _showCoordinatesAction
->setChecked(true);
2663 _mapView
->showCursorCoordinates(true);
2665 activeMap
= READ(activeMap
).toString();
2666 settings
.endGroup();
2669 settings
.beginGroup(SETTINGS_GRAPH
);
2670 if (READ(showGraphs
).toBool())
2671 _showGraphsAction
->setChecked(true);
2675 GraphType gt
= (GraphType
)READ(graphType
).toInt();
2677 _timeGraphAction
->setChecked(true);
2679 _distanceGraphAction
->setChecked(true);
2682 if (READ(showGrid
).toBool())
2683 _showGraphGridAction
->setChecked(true);
2685 showGraphGrids(false);
2687 if (READ(sliderInfo
).toBool())
2688 _showGraphSliderInfoAction
->setChecked(true);
2690 showGraphSliderInfo(false);
2693 if (READ(showGraphTabs
).toBool())
2694 _showGraphTabsAction
->setChecked(true);
2696 showGraphTabs(false);
2697 #endif // Q_OS_ANDROID
2698 settings
.endGroup();
2701 settings
.beginGroup(SETTINGS_POI
);
2702 if (READ(poiOverlap
).toBool()) {
2703 _overlapPOIAction
->setChecked(true);
2704 _mapView
->showOverlappedPOIs(true);
2706 if (READ(poiIcons
).toBool()) {
2707 _showPOIIconsAction
->setChecked(true);
2708 _mapView
->showPOIIcons(true);
2710 if (READ(poiLabels
).toBool()) {
2711 _showPOILabelsAction
->setChecked(true);
2712 _mapView
->showPOILabels(true);
2714 if (READ(showPoi
).toBool()) {
2715 _showPOIAction
->setChecked(true);
2716 _mapView
->showPOI(true);
2718 disabledPOIs
= READ(disabledPoiFiles
);
2719 settings
.endGroup();
2722 settings
.beginGroup(SETTINGS_DATA
);
2723 if (READ(tracks
).toBool()) {
2724 _showTracksAction
->setChecked(true);
2725 _mapView
->showTracks(true);
2726 for (int i
= 0; i
< _tabs
.count(); i
++)
2727 _tabs
.at(i
)->showTracks(true);
2729 if (READ(routes
).toBool()) {
2730 _showRoutesAction
->setChecked(true);
2731 _mapView
->showRoutes(true);
2732 for (int i
= 0; i
< _tabs
.count(); i
++)
2733 _tabs
.at(i
)->showRoutes(true);
2735 if (READ(waypoints
).toBool()) {
2736 _showWaypointsAction
->setChecked(true);
2737 _mapView
->showWaypoints(true);
2739 if (READ(areas
).toBool()) {
2740 _showAreasAction
->setChecked(true);
2741 _mapView
->showAreas(true);
2743 if (READ(waypointIcons
).toBool()) {
2744 _showWaypointIconsAction
->setChecked(true);
2745 _mapView
->showWaypointIcons(true);
2747 if (READ(waypointLabels
).toBool()) {
2748 _showWaypointLabelsAction
->setChecked(true);
2749 _mapView
->showWaypointLabels(true);
2751 if (READ(routeWaypoints
).toBool()) {
2752 _showRouteWaypointsAction
->setChecked(true);
2753 _mapView
->showRouteWaypoints(true);
2755 if (READ(pathTicks
).toBool()) {
2756 _showTicksAction
->setChecked(true);
2757 _mapView
->showTicks(true);
2759 if (READ(useStyles
).toBool()) {
2760 _useStylesAction
->setChecked(true);
2761 _mapView
->useStyles(true);
2763 if (READ(positionMarkers
).toBool()) {
2764 MarkerInfoItem::Type mt
= (MarkerInfoItem::Type
)READ(markerInfo
).toInt();
2765 if (mt
== MarkerInfoItem::Position
)
2766 _showMarkerCoordinatesAction
->setChecked(true);
2767 else if (mt
== MarkerInfoItem::Date
)
2768 _showMarkerDateAction
->setChecked(true);
2770 _showMarkersAction
->setChecked(true);
2772 _mapView
->showMarkers(true);
2773 _mapView
->showMarkerInfo(mt
);
2775 _hideMarkersAction
->setChecked(true);
2776 settings
.endGroup();
2779 settings
.beginGroup(SETTINGS_POSITION
);
2780 if (READ(showPosition
).toBool()) {
2781 _showPositionAction
->setChecked(true);
2782 _mapView
->showPosition(true);
2784 if (READ(followPosition
).toBool()) {
2785 _followPositionAction
->setChecked(true);
2786 _mapView
->followPosition(true);
2788 if (READ(positionCoordinates
).toBool()) {
2789 _showPositionCoordinatesAction
->setChecked(true);
2790 _mapView
->showPositionCoordinates(true);
2792 if (READ(motionInfo
).toBool()) {
2793 _showMotionInfoAction
->setChecked(true);
2794 _mapView
->showMotionInfo(true);
2796 settings
.endGroup();
2799 settings
.beginGroup(SETTINGS_PDF_EXPORT
);
2800 _pdfExport
.orientation
= (QPageLayout::Orientation
)READ(pdfOrientation
)
2802 _pdfExport
.resolution
= READ(pdfResolution
).toInt();
2803 _pdfExport
.paperSize
= (QPageSize::PageSizeId
)READ(pdfSize
).toInt();
2804 _pdfExport
.margins
= QMarginsF(READ(pdfMarginLeft
).toReal(),
2805 READ(pdfMarginTop
).toReal(), READ(pdfMarginRight
).toReal(),
2806 READ(pdfMarginBottom
).toReal());
2807 _pdfExport
.fileName
= READ(pdfFileName
).toString();
2808 settings
.endGroup();
2811 settings
.beginGroup(SETTINGS_PNG_EXPORT
);
2812 _pngExport
.size
= QSize(READ(pngWidth
).toInt(), READ(pngHeight
).toInt());
2813 _pngExport
.margins
= QMargins(READ(pngMarginLeft
).toInt(),
2814 READ(pngMarginTop
).toInt(), READ(pngMarginRight
).toInt(),
2815 READ(pngMarginBottom
).toInt());
2816 _pngExport
.antialiasing
= READ(pngAntialiasing
).toBool();
2817 _pngExport
.fileName
= READ(pngFileName
).toString();
2818 settings
.endGroup();
2821 settings
.beginGroup(SETTINGS_OPTIONS
);
2822 _options
.palette
= Palette(READ(paletteColor
).value
<QColor
>(),
2823 READ(paletteShift
).toDouble());
2824 _options
.mapOpacity
= READ(mapOpacity
).toInt();
2825 _options
.backgroundColor
= READ(backgroundColor
).value
<QColor
>();
2826 _options
.crosshairColor
= READ(crosshairColor
).value
<QColor
>();
2827 _options
.infoColor
= READ(infoColor
).value
<QColor
>();
2828 _options
.infoBackground
= READ(infoBackground
).toBool();
2829 _options
.trackWidth
= READ(trackWidth
).toInt();
2830 _options
.routeWidth
= READ(routeWidth
).toInt();
2831 _options
.areaWidth
= READ(areaWidth
).toInt();
2832 _options
.trackStyle
= (Qt::PenStyle
)READ(trackStyle
).toInt();
2833 _options
.routeStyle
= (Qt::PenStyle
)READ(routeStyle
).toInt();
2834 _options
.areaStyle
= (Qt::PenStyle
)READ(areaStyle
).toInt();
2835 _options
.areaOpacity
= READ(areaOpacity
).toInt();
2836 _options
.pathAntiAliasing
= READ(pathAntiAliasing
).toBool();
2837 _options
.waypointSize
= READ(waypointSize
).toInt();
2838 _options
.waypointColor
= READ(waypointColor
).value
<QColor
>();
2839 _options
.poiSize
= READ(poiSize
).toInt();
2840 _options
.poiColor
= READ(poiColor
).value
<QColor
>();
2841 _options
.graphWidth
= READ(graphWidth
).toInt();
2842 _options
.graphAntiAliasing
= READ(graphAntiAliasing
).toBool();
2843 _options
.elevationFilter
= READ(elevationFilter
).toInt();
2844 _options
.speedFilter
= READ(speedFilter
).toInt();
2845 _options
.heartRateFilter
= READ(heartRateFilter
).toInt();
2846 _options
.cadenceFilter
= READ(cadenceFilter
).toInt();
2847 _options
.powerFilter
= READ(powerFilter
).toInt();
2848 _options
.outlierEliminate
= READ(outlierEliminate
).toBool();
2849 _options
.pauseSpeed
= READ(pauseSpeed
).toFloat();
2850 _options
.automaticPause
= READ(automaticPause
).toBool();
2851 _options
.pauseInterval
= READ(pauseInterval
).toInt();
2852 _options
.useReportedSpeed
= READ(useReportedSpeed
).toBool();
2853 _options
.dataUseDEM
= READ(dataUseDEM
).toBool();
2854 _options
.showSecondaryElevation
= READ(secondaryElevation
).toBool();
2855 _options
.showSecondarySpeed
= READ(secondarySpeed
).toBool();
2856 _options
.timeZone
= READ(timeZone
).value
<TimeZoneInfo
>();
2857 _options
.useSegments
= READ(useSegments
).toBool();
2858 _options
.poiRadius
= READ(poiRadius
).toInt();
2859 _options
.demURL
= READ(demURL
).toString();
2860 _options
.demAuthorization
= READ(demAuthentication
).toBool();
2861 _options
.demUsername
= READ(demUsername
).toString();
2862 _options
.demPassword
= READ(demPassword
).toString();
2863 _options
.plugin
= READ(positionPlugin()).toString();
2864 _options
.pluginParams
= READ(positionPluginParameters
);
2865 _options
.useOpenGL
= READ(useOpenGL
).toBool();
2866 _options
.enableHTTP2
= READ(enableHTTP2
).toBool();
2867 _options
.pixmapCache
= READ(pixmapCache
).toInt();
2868 _options
.demCache
= READ(demCache
).toInt();
2869 _options
.connectionTimeout
= READ(connectionTimeout
).toInt();
2870 _options
.hiresPrint
= READ(hiresPrint
).toBool();
2871 _options
.printName
= READ(printName
).toBool();
2872 _options
.printDate
= READ(printDate
).toBool();
2873 _options
.printDistance
= READ(printDistance
).toBool();
2874 _options
.printTime
= READ(printTime
).toBool();
2875 _options
.printMovingTime
= READ(printMovingTime
).toBool();
2876 _options
.printItemCount
= READ(printItemCount
).toBool();
2877 _options
.separateGraphPage
= READ(separateGraphPage
).toBool();
2878 _options
.sliderColor
= READ(sliderColor
).value
<QColor
>();
2879 _options
.outputProjection
= READ(outputProjection
).toInt();
2880 _options
.inputProjection
= READ(inputProjection
).toInt();
2881 _options
.hidpiMap
= READ(hidpiMap
).toBool();
2882 _options
.dataPath
= READ(dataPath
).toString();
2883 _options
.mapsPath
= READ(mapsPath
).toString();
2884 _options
.poiPath
= READ(poiPath
).toString();
2885 settings
.endGroup();
2890 void GUI::loadOptions()
2892 _positionSource
= positionSource(_options
);
2893 _showPositionAction
->setEnabled(_positionSource
!= 0);
2895 _mapView
->setPalette(_options
.palette
);
2896 _mapView
->setMapOpacity(_options
.mapOpacity
);
2897 _mapView
->setBackgroundColor(_options
.backgroundColor
);
2898 _mapView
->setCrosshairColor(_options
.crosshairColor
);
2899 _mapView
->setInfoColor(_options
.infoColor
);
2900 _mapView
->drawInfoBackground(_options
.infoBackground
);
2901 _mapView
->setTrackWidth(_options
.trackWidth
);
2902 _mapView
->setRouteWidth(_options
.routeWidth
);
2903 _mapView
->setAreaWidth(_options
.areaWidth
);
2904 _mapView
->setTrackStyle(_options
.trackStyle
);
2905 _mapView
->setRouteStyle(_options
.routeStyle
);
2906 _mapView
->setAreaStyle(_options
.areaStyle
);
2907 _mapView
->setAreaOpacity(_options
.areaOpacity
);
2908 _mapView
->setWaypointSize(_options
.waypointSize
);
2909 _mapView
->setWaypointColor(_options
.waypointColor
);
2910 _mapView
->setPOISize(_options
.poiSize
);
2911 _mapView
->setPOIColor(_options
.poiColor
);
2912 _mapView
->setRenderHint(QPainter::Antialiasing
, _options
.pathAntiAliasing
);
2913 _mapView
->setMarkerColor(_options
.sliderColor
);
2914 _mapView
->useOpenGL(_options
.useOpenGL
);
2915 _mapView
->setMapConfig(CRS::projection(_options
.inputProjection
),
2916 CRS::projection(4326, _options
.outputProjection
), _options
.hidpiMap
);
2917 _mapView
->setTimeZone(_options
.timeZone
.zone());
2918 _mapView
->setPositionSource(_positionSource
);
2920 for (int i
= 0; i
< _tabs
.count(); i
++) {
2921 _tabs
.at(i
)->setPalette(_options
.palette
);
2922 _tabs
.at(i
)->setGraphWidth(_options
.graphWidth
);
2923 _tabs
.at(i
)->setRenderHint(QPainter::Antialiasing
,
2924 _options
.graphAntiAliasing
);
2925 _tabs
.at(i
)->setSliderColor(_options
.sliderColor
);
2926 if (_options
.useOpenGL
)
2927 _tabs
.at(i
)->useOpenGL(true);
2930 Track::setElevationFilter(_options
.elevationFilter
);
2931 Track::setSpeedFilter(_options
.speedFilter
);
2932 Track::setHeartRateFilter(_options
.heartRateFilter
);
2933 Track::setCadenceFilter(_options
.cadenceFilter
);
2934 Track::setPowerFilter(_options
.powerFilter
);
2935 Track::setOutlierElimination(_options
.outlierEliminate
);
2936 Track::setAutomaticPause(_options
.automaticPause
);
2937 Track::setPauseSpeed(_options
.pauseSpeed
);
2938 Track::setPauseInterval(_options
.pauseInterval
);
2939 Track::useReportedSpeed(_options
.useReportedSpeed
);
2940 Track::useDEM(_options
.dataUseDEM
);
2941 Track::showSecondaryElevation(_options
.showSecondaryElevation
);
2942 Track::showSecondarySpeed(_options
.showSecondarySpeed
);
2943 Track::useSegments(_options
.useSegments
);
2944 Route::useDEM(_options
.dataUseDEM
);
2945 Route::showSecondaryElevation(_options
.showSecondaryElevation
);
2946 Waypoint::useDEM(_options
.dataUseDEM
);
2947 Waypoint::showSecondaryElevation(_options
.showSecondaryElevation
);
2949 Downloader::enableHTTP2(_options
.enableHTTP2
);
2950 Downloader::setTimeout(_options
.connectionTimeout
);
2952 QPixmapCache::setCacheLimit(_options
.pixmapCache
* 1024);
2953 DEM::setCacheSize(_options
.demCache
* 1024);
2955 _poi
->setRadius(_options
.poiRadius
);
2957 _dem
->setUrl(_options
.demURL
);
2958 if (_options
.demAuthorization
)
2959 _dem
->setAuthorization(Authorization(_options
.demUsername
,
2960 _options
.demPassword
));
2962 _dataDir
= _options
.dataPath
;
2963 _mapDir
= _options
.mapsPath
;
2964 _poiDir
= _options
.poiPath
;
2967 void GUI::updateOptions(const Options
&options
)
2969 #define SET_VIEW_OPTION(option, action) \
2970 if (options.option != _options.option) \
2971 _mapView->action(options.option)
2972 #define SET_TAB_OPTION(option, action) \
2973 if (options.option != _options.option) \
2974 for (int i = 0; i < _tabs.count(); i++) \
2975 _tabs.at(i)->action(options.option)
2976 #define SET_TRACK_OPTION(option, action) \
2977 if (options.option != _options.option) { \
2978 Track::action(options.option); \
2981 #define SET_ROUTE_OPTION(option, action) \
2982 if (options.option != _options.option) { \
2983 Route::action(options.option); \
2986 #define SET_WAYPOINT_OPTION(option, action) \
2987 if (options.option != _options.option) { \
2988 Waypoint::action(options.option); \
2992 bool reload
= false;
2994 SET_VIEW_OPTION(palette
, setPalette
);
2995 SET_VIEW_OPTION(mapOpacity
, setMapOpacity
);
2996 SET_VIEW_OPTION(backgroundColor
, setBackgroundColor
);
2997 SET_VIEW_OPTION(trackWidth
, setTrackWidth
);
2998 SET_VIEW_OPTION(routeWidth
, setRouteWidth
);
2999 SET_VIEW_OPTION(areaWidth
, setAreaWidth
);
3000 SET_VIEW_OPTION(trackStyle
, setTrackStyle
);
3001 SET_VIEW_OPTION(routeStyle
, setRouteStyle
);
3002 SET_VIEW_OPTION(areaStyle
, setAreaStyle
);
3003 SET_VIEW_OPTION(areaOpacity
, setAreaOpacity
);
3004 SET_VIEW_OPTION(waypointSize
, setWaypointSize
);
3005 SET_VIEW_OPTION(waypointColor
, setWaypointColor
);
3006 SET_VIEW_OPTION(poiSize
, setPOISize
);
3007 SET_VIEW_OPTION(poiColor
, setPOIColor
);
3008 SET_VIEW_OPTION(pathAntiAliasing
, useAntiAliasing
);
3009 SET_VIEW_OPTION(useOpenGL
, useOpenGL
);
3010 SET_VIEW_OPTION(sliderColor
, setMarkerColor
);
3011 SET_VIEW_OPTION(crosshairColor
, setCrosshairColor
);
3012 SET_VIEW_OPTION(infoColor
, setInfoColor
);
3013 SET_VIEW_OPTION(infoBackground
, drawInfoBackground
);
3015 if (options
.plugin
!= _options
.plugin
3016 || options
.pluginParams
.value(options
.plugin
)
3017 != _options
.pluginParams
.value(_options
.plugin
)) {
3018 QGeoPositionInfoSource
*source
= positionSource(options
);
3019 _showPositionAction
->setEnabled(source
!= 0);
3020 _mapView
->setPositionSource(source
);
3021 delete _positionSource
;
3022 _positionSource
= source
;
3025 if (options
.hidpiMap
!= _options
.hidpiMap
3026 || options
.outputProjection
!= _options
.outputProjection
3027 || options
.inputProjection
!= _options
.inputProjection
)
3028 _mapView
->setMapConfig(CRS::projection(options
.inputProjection
),
3029 CRS::projection(4326, options
.outputProjection
), options
.hidpiMap
);
3031 if (options
.timeZone
!= _options
.timeZone
) {
3032 _mapView
->setTimeZone(options
.timeZone
.zone());
3033 _dateRange
.first
= _dateRange
.first
.toTimeZone(options
.timeZone
.zone());
3034 _dateRange
.second
= _dateRange
.second
.toTimeZone(options
.timeZone
.zone());
3037 SET_TAB_OPTION(palette
, setPalette
);
3038 SET_TAB_OPTION(graphWidth
, setGraphWidth
);
3039 SET_TAB_OPTION(graphAntiAliasing
, useAntiAliasing
);
3040 SET_TAB_OPTION(useOpenGL
, useOpenGL
);
3041 SET_TAB_OPTION(sliderColor
, setSliderColor
);
3043 SET_TRACK_OPTION(elevationFilter
, setElevationFilter
);
3044 SET_TRACK_OPTION(speedFilter
, setSpeedFilter
);
3045 SET_TRACK_OPTION(heartRateFilter
, setHeartRateFilter
);
3046 SET_TRACK_OPTION(cadenceFilter
, setCadenceFilter
);
3047 SET_TRACK_OPTION(powerFilter
, setPowerFilter
);
3048 SET_TRACK_OPTION(outlierEliminate
, setOutlierElimination
);
3049 SET_TRACK_OPTION(automaticPause
, setAutomaticPause
);
3050 SET_TRACK_OPTION(pauseSpeed
, setPauseSpeed
);
3051 SET_TRACK_OPTION(pauseInterval
, setPauseInterval
);
3052 SET_TRACK_OPTION(useReportedSpeed
, useReportedSpeed
);
3053 SET_TRACK_OPTION(dataUseDEM
, useDEM
);
3054 SET_TRACK_OPTION(showSecondaryElevation
, showSecondaryElevation
);
3055 SET_TRACK_OPTION(showSecondarySpeed
, showSecondarySpeed
);
3056 SET_TRACK_OPTION(useSegments
, useSegments
);
3058 SET_ROUTE_OPTION(dataUseDEM
, useDEM
);
3059 SET_ROUTE_OPTION(showSecondaryElevation
, showSecondaryElevation
);
3061 SET_WAYPOINT_OPTION(dataUseDEM
, useDEM
);
3062 SET_WAYPOINT_OPTION(showSecondaryElevation
, showSecondaryElevation
);
3064 if (options
.poiRadius
!= _options
.poiRadius
)
3065 _poi
->setRadius(options
.poiRadius
);
3067 if (options
.demURL
!= _options
.demURL
)
3068 _dem
->setUrl(options
.demURL
);
3069 if (options
.demAuthorization
!= _options
.demAuthorization
3070 || options
.demUsername
!= _options
.demUsername
3071 || options
.demPassword
!= _options
.demPassword
)
3072 _dem
->setAuthorization(options
.demAuthorization
3073 ? Authorization(options
.demUsername
, options
.demPassword
)
3076 if (options
.pixmapCache
!= _options
.pixmapCache
)
3077 QPixmapCache::setCacheLimit(options
.pixmapCache
* 1024);
3078 if (options
.demCache
!= _options
.demCache
)
3079 DEM::setCacheSize(options
.demCache
* 1024);
3081 if (options
.connectionTimeout
!= _options
.connectionTimeout
)
3082 Downloader::setTimeout(options
.connectionTimeout
);
3083 if (options
.enableHTTP2
!= _options
.enableHTTP2
)
3084 Downloader::enableHTTP2(options
.enableHTTP2
);
3086 if (options
.dataPath
!= _options
.dataPath
)
3087 _dataDir
= options
.dataPath
;
3088 if (options
.mapsPath
!= _options
.mapsPath
)
3089 _mapDir
= options
.mapsPath
;
3090 if (options
.poiPath
!= _options
.poiPath
)
3091 _poiDir
= options
.poiPath
;
3098 updateDEMDownloadAction();
3101 void GUI::loadInitialMaps(const QString
&selected
)
3104 QString
mapDir(ProgramPaths::mapDir());
3105 if (mapDir
.isNull())
3108 TreeNode
<Map
*> maps(MapList::loadMaps(mapDir
, _mapView
->inputProjection()));
3109 createMapNodeMenu(createMapActionsNode(maps
), _mapMenu
, _mapsEnd
);
3111 // Select the active map according to the user settings
3112 QAction
*ma
= mapAction(selected
);
3115 _showMapAction
->setEnabled(true);
3116 _clearMapCacheAction
->setEnabled(true);
3120 void GUI::loadInitialPOIs(const QStringList
&disabled
)
3122 // Load the POI files
3123 QString
poiDir(ProgramPaths::poiDir());
3124 if (poiDir
.isNull())
3127 TreeNode
<QString
> poiFiles(_poi
->loadDir(poiDir
));
3128 createPOINodeMenu(createPOIActionsNode(poiFiles
), _poiMenu
, _poisEnd
);
3130 // Enable/disable the files according to the user settings
3131 QList
<QAction
*> poiActions(_poisActionGroup
->actions());
3132 for (int i
= 0; i
< poiActions
.count(); i
++)
3133 poiActions
.at(i
)->setChecked(true);
3134 for (int i
= 0; i
< disabled
.size(); i
++) {
3135 const QString
&file
= disabled
.at(i
);
3136 if (_poi
->enableFile(file
, false)) {
3137 for (int j
= 0; j
< poiActions
.size(); j
++)
3138 if (poiActions
.at(j
)->data().toString() == file
)
3139 poiActions
.at(j
)->setChecked(false);
3143 _selectAllPOIAction
->setEnabled(!poiActions
.isEmpty());
3144 _unselectAllPOIAction
->setEnabled(!poiActions
.isEmpty());
3147 #ifndef Q_OS_ANDROID
3148 void GUI::loadRecentFiles(const QStringList
&files
)
3150 QAction
*before
= _recentFilesEnd
;
3152 for (int i
= 0; i
< files
.size(); i
++) {
3153 QAction
*a
= new QAction(files
.at(i
), _recentFilesActionGroup
);
3154 _recentFilesMenu
->insertAction(before
, a
);
3158 if (!files
.isEmpty())
3159 _recentFilesMenu
->setEnabled(true);
3161 #endif // Q_OS_ANDROID
3163 QAction
*GUI::mapAction(const QString
&name
)
3165 QList
<QAction
*> maps(_mapsActionGroup
->actions());
3168 for (int i
= 0; i
< maps
.count(); i
++) {
3169 Map
*map
= maps
.at(i
)->data().value
<Map
*>();
3170 if (map
->name() == name
&& map
->isReady())
3175 for (int i
= 0; i
< maps
.count(); i
++) {
3176 Map
*map
= maps
.at(i
)->data().value
<Map
*>();
3184 Units
GUI::units() const
3186 return _imperialUnitsAction
->isChecked() ? Imperial
3187 : _nauticalUnitsAction
->isChecked() ? Nautical
: Metric
;
3190 qreal
GUI::distance() const
3194 if (_showTracksAction
->isChecked())
3195 dist
+= _trackDistance
;
3196 if (_showRoutesAction
->isChecked())
3197 dist
+= _routeDistance
;
3202 qreal
GUI::time() const
3204 return (_showTracksAction
->isChecked()) ? _time
: 0;
3207 qreal
GUI::movingTime() const
3209 return (_showTracksAction
->isChecked()) ? _movingTime
: 0;
3214 QMainWindow::show();
3216 QWindow
*w
= windowHandle();
3217 connect(w
->screen(), &QScreen::logicalDotsPerInchChanged
, this,
3218 &GUI::logicalDotsPerInchChanged
);
3219 connect(w
, &QWindow::screenChanged
, this, &GUI::screenChanged
);
3221 _mapView
->fitContentToSize();
3224 void GUI::screenChanged(QScreen
*screen
)
3226 _mapView
->setDevicePixelRatio(devicePixelRatioF());
3228 disconnect(SIGNAL(logicalDotsPerInchChanged(qreal
)), this,
3229 SLOT(logicalDotsPerInchChanged(qreal
)));
3230 connect(screen
, &QScreen::logicalDotsPerInchChanged
, this,
3231 &GUI::logicalDotsPerInchChanged
);
3234 void GUI::logicalDotsPerInchChanged(qreal dpi
)
3238 _mapView
->setDevicePixelRatio(devicePixelRatioF());