1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-09 00:34:27 +02:00

Compare commits

..

153 Commits
9.2 ... 9.7

Author SHA1 Message Date
2a7507ff25 Fixed form layout issue on OS X 2021-09-26 11:33:50 +02:00
134129e798 Fixed broken map/POI sub-menu entry insertion 2021-09-25 22:47:43 +02:00
a8c10226eb Merge branch 'origin/master' into Weblate. 2021-09-25 19:25:30 +02:00
8c470ccabd Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (418 of 418 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/zh_Hans/
2021-09-25 19:25:29 +02:00
a22011ba99 Translated using Weblate (Hungarian)
Currently translated at 100.0% (418 of 418 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2021-09-25 19:25:29 +02:00
5fed1612bd Translated using Weblate (Swedish)
Currently translated at 100.0% (418 of 418 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2021-09-25 19:25:29 +02:00
9cf4d8af6c Translated using Weblate (French)
Currently translated at 100.0% (418 of 418 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fr/
2021-09-25 19:25:28 +02:00
6358fa703b Translated using Weblate (Finnish)
Currently translated at 98.0% (410 of 418 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2021-09-25 19:25:28 +02:00
72672404e7 German translation update 2021-09-25 19:25:13 +02:00
348a9b120f Czech translation update 2021-09-25 19:24:52 +02:00
b7343b1535 Merge branch 'origin/master' into Weblate. 2021-09-24 20:16:16 +02:00
0a57fa9fff Translated using Weblate (Turkish)
Currently translated at 100.0% (418 of 418 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2021-09-24 20:16:15 +02:00
9f98220d67 Chinese localization update 2021-09-24 20:15:59 +02:00
446a68abcb Added Chinese localization 2021-09-24 20:14:59 +02:00
43738523a6 Merge branch 'origin/master' into Weblate. 2021-09-24 19:51:11 +02:00
ac0a75b5f2 Translated using Weblate (Hungarian)
Currently translated at 100.0% (417 of 417 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2021-09-24 19:51:11 +02:00
c9ec1e8b52 Translated using Weblate (Turkish)
Currently translated at 100.0% (417 of 417 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2021-09-24 19:51:11 +02:00
24f7201fc7 Translated using Weblate (Swedish)
Currently translated at 100.0% (417 of 417 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2021-09-24 19:51:11 +02:00
70ee59d0e1 Localization update 2021-09-24 19:50:54 +02:00
91bc1f4546 Make it clear that only the selected map's cache will be dropped 2021-09-24 19:49:15 +02:00
28a71cbc39 Improved DEM coverage UX 2021-09-24 19:47:56 +02:00
8e2ff85aaa Added support for location files 2021-09-24 19:45:17 +02:00
c5212129ab Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (417 of 417 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/zh_Hans/
2021-09-24 18:05:44 +02:00
8fea000adf Added Chinese translation stub 2021-09-23 22:50:38 +02:00
34d57270de Localization update 2021-09-23 22:46:21 +02:00
7920f0f245 Added DEM data overview 2021-09-23 22:44:21 +02:00
c43b4060ca Removed obsolete include 2021-09-23 22:42:57 +02:00
c77cf70f9f Multiple settings handling fixes and enhancements 2021-09-22 20:29:48 +02:00
db45d3c659 Version++ 2021-09-21 22:09:26 +02:00
45dbb105c5 Enable DEM fetching for a single point 2021-09-21 22:07:22 +02:00
d7dc185ecf Only show the password on explicit user request 2021-09-20 21:58:08 +02:00
e47cbc9af3 Added missing namespace 2021-09-20 21:43:17 +02:00
f5078074cf Updated paths according to the recent project structure change 2021-09-17 23:55:42 +02:00
11c83b405f Project structure cleanup 2021-09-17 23:45:12 +02:00
499461ff76 Code cleanup 2021-09-17 23:22:32 +02:00
fd65882907 Do not render tiles that will not be shown due to zoom in/out 2021-09-16 22:54:09 +02:00
d0dc3661e4 Added UTTypeIconFile entries 2021-09-13 23:36:17 +02:00
0c434106af Merge remote-tracking branch 'weblate/master' 2021-09-04 10:03:35 +02:00
b938e24d65 Do not check for insane numbers of DEM tiles 2021-09-04 10:02:24 +02:00
1d65e32335 Translated using Weblate (Esperanto)
Currently translated at 94.9% (395 of 416 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/eo/
2021-09-03 11:37:11 +02:00
6be33a1fc1 Translated using Weblate (Russian)
Currently translated at 100.0% (416 of 416 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2021-09-03 11:37:11 +02:00
660fdde8c2 Translated using Weblate (Finnish)
Currently translated at 98.5% (410 of 416 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2021-09-03 11:37:11 +02:00
d50ab8607e Added some more shortcuts 2021-09-02 12:55:32 +02:00
3709a3feb5 Do not show the "Print" button in the toolbar on OS X
(As we are using buttons with text on OS X, the space is very limited)
2021-09-02 12:47:29 +02:00
a073c93e0d Removed debug stuff 2021-09-02 12:30:07 +02:00
f934df59e4 Some more options dialog polishing on OS X 2021-09-02 12:27:20 +02:00
394fcf6d4d Merge remote-tracking branch 'weblate/master' 2021-09-02 04:18:35 +02:00
0e1584ea24 Translated using Weblate (German)
Currently translated at 100.0% (416 of 416 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/de/
2021-09-02 04:17:13 +02:00
c592be7cfd Use the static exists() functions that are faster according to the docs 2021-09-01 20:14:06 +02:00
c84d7871fb Merge remote-tracking branch 'weblate/master' 2021-09-01 13:27:51 +02:00
34669b68f5 Code cleanup 2021-09-01 13:27:30 +02:00
849eaa57cc Merge branch 'origin/master' into Weblate. 2021-09-01 13:11:29 +02:00
7f6ac2e4c3 Improved DEM downloads handling logic 2021-09-01 13:08:34 +02:00
5407fe35e6 Merge branch 'origin/master' into Weblate. 2021-08-31 23:40:53 +02:00
133aac3bd4 Windows/Linux optionsdialog polishing 2021-08-31 22:55:32 +02:00
a5cd05233c Merge branch 'origin/master' into Weblate. 2021-08-31 18:45:31 +02:00
22b691252f Fixed widget margins 2021-08-31 18:43:55 +02:00
988ea7d952 Czech translation update 2021-08-31 18:43:32 +02:00
c253669017 Merge branch 'origin/master' into Weblate. 2021-08-31 18:28:00 +02:00
37d8aadfed Translated using Weblate (Hungarian)
Currently translated at 100.0% (417 of 417 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2021-08-31 18:27:59 +02:00
ae204e9ddf Translated using Weblate (Turkish)
Currently translated at 100.0% (417 of 417 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2021-08-31 18:27:59 +02:00
07410ad7d5 Translated using Weblate (Russian)
Currently translated at 98.8% (412 of 417 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2021-08-31 18:27:59 +02:00
98b56485bd Localization update 2021-08-31 18:27:42 +02:00
302fe4d8e1 Improved Options UI on OS X 2021-08-31 18:25:30 +02:00
045dab6cdd Silenced QT6 warning 2021-08-31 18:23:10 +02:00
da522cd2ba Use the latest OS X image 2021-08-31 18:10:26 +02:00
38322f09a6 Translated using Weblate (Swedish)
Currently translated at 100.0% (417 of 417 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2021-08-31 07:28:09 +02:00
7803340c0e Localization update 2021-08-30 20:33:39 +02:00
2232b011a1 Added support for downloading DEM tiles 2021-08-30 20:31:33 +02:00
94a0158243 Properly handle connection timeouts
(count timeout from last received data chunk, not for the whole download)
2021-08-29 20:28:08 +02:00
018d0ba085 Redesigned HTTP downloader
- Save the data as they come rather than at once
- + some related refactoring
2021-08-26 22:22:18 +02:00
d5a472ddc0 Cosmetics 2021-08-25 00:34:31 +02:00
09a6d8655e Code cleanup 2021-08-23 22:27:36 +02:00
1d2b93466f Fixed shifted file association 2021-08-22 19:07:38 +02:00
9979a8b233 Added ONmove OMD/GHP support info 2021-08-22 17:29:42 +02:00
ef6f3a0516 Translated using Weblate (Ukrainian)
Currently translated at 95.3% (388 of 407 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/uk/
2021-08-22 16:58:45 +02:00
4f81e120b7 Translated using Weblate (German)
Currently translated at 100.0% (407 of 407 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/de/
2021-08-22 16:58:45 +02:00
ed68cbd891 Translated using Weblate (Czech)
Currently translated at 100.0% (407 of 407 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/cs/
2021-08-22 15:24:16 +02:00
a4c7449772 Translated using Weblate (Esperanto)
Currently translated at 95.5% (389 of 407 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/eo/
2021-08-21 17:35:10 +02:00
60d82c9b7b Translated using Weblate (Russian)
Currently translated at 100.0% (407 of 407 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2021-08-21 17:35:09 +02:00
fe288a4fea Translated using Weblate (Finnish)
Currently translated at 99.2% (404 of 407 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2021-08-21 17:35:09 +02:00
9f95ded407 Translated using Weblate (Hungarian)
Currently translated at 100.0% (407 of 407 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2021-08-21 10:35:40 +02:00
1241b71475 Translated using Weblate (Turkish)
Currently translated at 100.0% (407 of 407 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2021-08-21 10:35:40 +02:00
48a7ecb83e Translated using Weblate (Swedish)
Currently translated at 100.0% (407 of 407 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2021-08-21 10:35:40 +02:00
62a60723be Added GHP OS X desktop integration 2021-08-19 23:41:01 +02:00
b7ee1ac660 Localization update 2021-08-19 19:47:26 +02:00
9f6ced0342 Added GHP Linux & Windows desktop integration 2021-08-19 19:45:53 +02:00
814eceb82c Added support for ONmove 7xx series GHP files 2021-08-19 19:35:26 +02:00
445598cd52 Localization update 2021-08-19 00:01:29 +02:00
eab43332ee Version++ 2021-08-18 23:30:38 +02:00
94571ccfc6 OMD OS X desktop integration 2021-08-18 23:28:11 +02:00
accea5d9da OMD Windows & Linux desktop integration 2021-08-18 22:30:02 +02:00
8d8a31eef9 Cosmetics 2021-08-18 21:33:07 +02:00
221d1b3fdb Added support for OnMove OMD files 2021-08-18 21:29:28 +02:00
ab062cc3ff Improved handling of labels with separators 2021-08-16 09:00:36 +02:00
78e8b03d66 Code cleanup 2021-08-10 20:44:16 +02:00
82d2ac0871 Fixed layout centering 2021-08-08 11:07:53 +02:00
0b3e35db72 Fixed some possible corner case 2021-08-05 00:02:47 +02:00
0c4e5b0017 A more human yaml syntax 2021-08-04 23:51:24 +02:00
933f2c3837 Rotate JPEG thumbnails acording to EXIF data
fixes #385
2021-08-04 08:57:42 +02:00
6e4cc406ab Version++ 2021-07-31 08:25:30 +02:00
21ce65146a Cache homebrew packages between builds 2021-07-30 23:41:50 +02:00
c99adfd6d2 Use the apt addon instead of manual packages install 2021-07-30 08:56:49 +02:00
c537f1ba6c Use travis-ci homebrew addon instead of manual package installation 2021-07-30 08:44:18 +02:00
4e36d8633c Translated using Weblate (Turkish)
Currently translated at 100.0% (406 of 406 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2021-07-29 23:00:36 +02:00
8beeeb7526 Merge branch 'origin/master' into Weblate. 2021-07-27 21:54:33 +02:00
69cc6ccb75 Render symbols/labels for not rendered areas 2021-07-27 21:53:24 +02:00
f042f11eed Fixed rule evaluation logic 2021-07-27 21:52:37 +02:00
f72835f05e Translated using Weblate (Finnish)
Currently translated at 99.2% (403 of 406 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2021-07-24 20:18:47 +02:00
c8779b4592 Translated using Weblate (Esperanto)
Currently translated at 95.5% (388 of 406 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/eo/
2021-07-24 20:18:47 +02:00
4b30e665cc Translated using Weblate (Russian)
Currently translated at 100.0% (406 of 406 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2021-07-24 20:18:47 +02:00
ac45ccaab6 Translated using Weblate (Ukrainian)
Currently translated at 95.3% (387 of 406 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/uk/
2021-07-24 20:18:46 +02:00
6d2182eb46 Translated using Weblate (French)
Currently translated at 100.0% (406 of 406 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fr/
2021-07-24 07:30:18 +02:00
50aea76bf7 Merge branch 'origin/master' into Weblate. 2021-07-22 00:34:45 +02:00
7676a21fc3 Some more file open logic fix/improvement 2021-07-22 00:32:36 +02:00
dc6a57338e Code cleanup 2021-07-22 00:31:57 +02:00
fa3fac5314 Merge branch 'origin/master' into Weblate. 2021-07-21 02:07:49 +02:00
a53fedf838 Yet another unnecessary file open remove 2021-07-21 02:06:35 +02:00
4d284ad0e5 Merge branch 'origin/master' into Weblate. 2021-07-19 22:52:50 +02:00
3f3ccb6856 Cache the open file descriptors between successive raster loads 2021-07-19 22:51:00 +02:00
2ea16eaaab Do not open/close the data files when not accessing them 2021-07-19 22:47:44 +02:00
effb0bb654 Translated using Weblate (Russian)
Currently translated at 99.5% (404 of 406 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2021-07-19 08:46:45 +02:00
8bd08b31a3 Give the flags human readable names 2021-07-18 22:32:49 +02:00
7a9d941e60 German translation 2021-07-16 21:35:58 +02:00
5c341c8339 Updated Czech translation 2021-07-16 21:08:03 +02:00
abddd8f9f1 Merge branch 'origin/master' into Weblate. 2021-07-13 19:58:30 +02:00
29f9fb7a68 Some more error checking 2021-07-13 19:58:12 +02:00
1387e9f12e Merge branch 'origin/master' into Weblate. 2021-07-13 19:43:50 +02:00
b04ac5fae3 Some more style error checks 2021-07-13 19:43:29 +02:00
9754e52f2d Merge branch 'origin/master' into Weblate. 2021-07-13 17:33:10 +02:00
ced95a9b3d Translated using Weblate (Hungarian)
Currently translated at 100.0% (406 of 406 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2021-07-13 17:33:10 +02:00
c5e1872c2e Fixed "float font sizes causing crash on style load" issue 2021-07-13 17:31:37 +02:00
52a88d39df Merge branch 'origin/master' into Weblate. 2021-07-13 08:53:18 +02:00
199806a107 Change the open path on options change 2021-07-13 08:52:41 +02:00
50dfa34dbc Merge branch 'origin/master' into Weblate. 2021-07-12 20:25:26 +02:00
eaaa1b0506 Translated using Weblate (Norwegian Bokmål)
Currently translated at 96.7% (393 of 406 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/nb_NO/
2021-07-12 20:25:26 +02:00
15f194a848 Version++ 2021-07-12 20:25:06 +02:00
56e60e32a7 Translated using Weblate (Swedish)
Currently translated at 100.0% (406 of 406 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2021-07-12 13:43:31 +02:00
762180542f Merge branch 'origin/master' into Weblate. 2021-07-12 12:09:03 +02:00
e48c5bf740 Localization update 2021-07-12 12:08:56 +02:00
b36aa057e8 Added missing placeholder text 2021-07-12 12:07:09 +02:00
62d37df40c Merge branch 'origin/master' into Weblate. 2021-07-12 11:50:04 +02:00
d51b16b398 Added missing class forward declarations 2021-07-12 11:49:36 +02:00
6234216862 Merge branch 'origin/master' into Weblate. 2021-07-12 00:21:53 +02:00
5b3b7128f6 Added initial open file paths configuration 2021-07-12 00:21:21 +02:00
f1dd54457d Merge branch 'origin/master' into Weblate. 2021-07-11 12:55:10 +02:00
3644ed3b1f Do not count errored maps as areas 2021-07-11 12:54:45 +02:00
655d4ea362 Merge branch 'origin/master' into Weblate. 2021-07-09 07:57:21 +02:00
3d7e64a470 Removed the artificial POI zoom level limits 2021-07-09 07:56:35 +02:00
c667972498 Translated using Weblate (Finnish)
Currently translated at 99.7% (398 of 399 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2021-07-04 22:33:33 +02:00
34e3e04e03 Improved error handling/reporting.
+ refactoring
2021-07-01 22:18:45 +02:00
f4d0c7f032 Remove all the remaining obscure micro-optimizations 2021-07-01 08:54:48 +02:00
f77e428eeb Added world files support info 2021-06-30 08:11:01 +02:00
172 changed files with 11889 additions and 6117 deletions

View File

@ -1,4 +1,4 @@
version: 9.2.{build} version: 9.7.{build}
configuration: configuration:
- Release - Release
@ -30,43 +30,29 @@ environment:
NSISDEF: /DQT6 NSISDEF: /DQT6
install: install:
- cmd: >- - cmd: |-
set PATH=%QTDIR%\bin;%NSISDIR%;%PATH% set PATH=%QTDIR%\bin;%NSISDIR%;%PATH%
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\"%VCVARS% call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\"%VCVARS%
build_script: build_script:
- cmd: >- - cmd: |-
lrelease gpxsee.pro lrelease gpxsee.pro
qmake gpxsee.pro qmake gpxsee.pro
nmake release nmake release
md installer md installer
copy release\GPXSee.exe installer copy release\GPXSee.exe installer
windeployqt --release installer\GPXSee.exe windeployqt --release installer\GPXSee.exe
copy pkg\%NSI% installer copy pkg\%NSI% installer
copy pkg\macros.nsh installer copy pkg\macros.nsh installer
xcopy pkg\csv installer\csv /i xcopy pkg\csv installer\csv /i
xcopy pkg\maps installer\maps /i xcopy pkg\maps installer\maps /i
xcopy lang\*.qm installer\translations\ /sy xcopy lang\*.qm installer\translations\ /sy
copy licence.txt installer copy licence.txt installer
copy %OPENSSLDIR%\%LIBCRYPTO% installer copy %OPENSSLDIR%\%LIBCRYPTO% installer
copy %OPENSSLDIR%\%LIBSSL% installer copy %OPENSSLDIR%\%LIBSSL% installer
makensis.exe %NSISDEF% installer\%NSI% makensis.exe %NSISDEF% installer\%NSI%
artifacts: artifacts:
- path: installer\GPXSee-*.exe - path: installer\GPXSee-*.exe

View File

@ -5,15 +5,25 @@ os:
- osx - osx
dist: focal dist: focal
osx_image: xcode12 osx_image: xcode12.5
before_install: cache:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update; fi directories:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi - $HOME/Library/Caches/Homebrew
install: before_cache:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install qt; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew cleanup; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install qtbase5-dev qtbase5-private-dev libqt5opengl5-dev qttools5-dev-tools; fi
addons:
homebrew:
packages:
- qt
apt:
packages:
- qtbase5-dev
- qtbase5-private-dev
- libqt5opengl5-dev
- qttools5-dev-tools
script: script:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then PATH=/usr/local/opt/qt/bin/:${PATH}; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then PATH=/usr/local/opt/qt/bin/:${PATH}; fi

View File

@ -2,9 +2,9 @@
GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common GPS log file formats. GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common GPS log file formats.
## Features ## Features
* Opens GPX, TCX, FIT, KML, NMEA, IGC, CUP, SIGMA SLF, Suunto SML, LOC, GeoJSON, OziExplorer (PLT, RTE, WPT), Garmin GPI&CSV, TomTom OV2&ITN and geotagged JPEG files. * Opens GPX, TCX, FIT, KML, NMEA, IGC, CUP, SIGMA SLF, Suunto SML, LOC, GeoJSON, OziExplorer (PLT, RTE, WPT), Garmin GPI&CSV, TomTom OV2&ITN, ONmove OMD/GHP and geotagged JPEG files.
* User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS, QuadTiles). * User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS, QuadTiles).
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, Garmin IMG/GMAP & JNX maps, TwoNav RMaps, GeoTIFF images, BSB charts, KMZ maps, AlpineQuest maps, Locus/OsmAnd/RMaps SQLite maps, Mapsforge vector maps). * Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, Garmin IMG/GMAP & JNX maps, TwoNav RMaps, GeoTIFF images, BSB charts, KMZ maps, AlpineQuest maps, Locus/OsmAnd/RMaps SQLite maps, Mapsforge vector maps, ESRI World-File georeferenced images).
* Elevation, speed, heart rate, cadence, power, temperature and gear ratio/shifts graphs. * Elevation, speed, heart rate, cadence, power, temperature and gear ratio/shifts graphs.
* Support for DEM files (SRTM HGT). * Support for DEM files (SRTM HGT).
* Support for multiple tracks in one view. * Support for multiple tracks in one view.
@ -50,9 +50,9 @@ licenses:
* [Oxygen icons](icons/GUI) - LGPLv3 * [Oxygen icons](icons/GUI) - LGPLv3
* [Mapbox Maki icons](icons/POI) - CC0 * [Mapbox Maki icons](icons/POI) - CC0
* [RTree implementation](src/common/rtree.h) - Public domain * [RTree implementation](src/common/rtree.h) - Public domain
* [Albers](src/map/albersequal.cpp), [Geocentric](src/map/geocentric.cpp), [LCC](src/map/lambertconic.cpp), * [Albers](src/map/proj/albersequal.cpp), [Geocentric](src/map/geocentric.cpp), [LCC](src/map/proj/lambertconic.cpp),
[Mercator](src/map/mercator.cpp), [Polar Stereographic](src/map/polarstereographic.cpp), [Mercator](src/map/proj/mercator.cpp), [Polar Stereographic](src/map/proj/polarstereographic.cpp),
[Polyconic](src/map/polyconic.cpp) and [Transverse Mercator](src/map/transversemercator.cpp) [Polyconic](src/map/proj/polyconic.cpp) and [Transverse Mercator](src/map/proj/transversemercator.cpp)
projections - NIMA Source Code Disclaimer projections - NIMA Source Code Disclaimer
* [Projection parameters CSV files](pkg/csv) - BSD/EPSG/Public domain * [Projection parameters CSV files](pkg/csv) - BSD/EPSG/Public domain
* [Mapsforge render theme](data/default.xml) and its [icons](icons/mapsforge) - LGPLv3 * [Mapsforge render theme](data/default.xml) and its [icons](icons/mapsforge) - LGPLv3

View File

@ -3,7 +3,7 @@ unix:!macx {
} else { } else {
TARGET = GPXSee TARGET = GPXSee
} }
VERSION = 9.2 VERSION = 9.7
QT += core \ QT += core \
gui \ gui \
@ -18,15 +18,6 @@ greaterThan(QT_MAJOR_VERSION, 5) {QT += openglwidgets}
CONFIG += object_parallel_to_source CONFIG += object_parallel_to_source
INCLUDEPATH += ./src INCLUDEPATH += ./src
HEADERS += src/common/config.h \ HEADERS += src/common/config.h \
src/GUI/axislabelitem.h \
src/GUI/graphicsscene.h \
src/GUI/mapaction.h \
src/GUI/mapitem.h \
src/GUI/marginswidget.h \
src/GUI/markerinfoitem.h \
src/GUI/planeitem.h \
src/GUI/poiaction.h \
src/GUI/popup.h \
src/common/garmin.h \ src/common/garmin.h \
src/common/coordinates.h \ src/common/coordinates.h \
src/common/range.h \ src/common/range.h \
@ -40,6 +31,22 @@ HEADERS += src/common/config.h \
src/common/greatcircle.h \ src/common/greatcircle.h \
src/common/programpaths.h \ src/common/programpaths.h \
src/common/tifffile.h \ src/common/tifffile.h \
src/common/downloader.h \
src/common/polygon.h \
src/GUI/authenticationwidget.h \
src/GUI/axislabelitem.h \
src/GUI/dirselectwidget.h \
src/GUI/flowlayout.h \
src/GUI/graphicsscene.h \
src/GUI/infolabel.h \
src/GUI/mapaction.h \
src/GUI/mapitem.h \
src/GUI/marginswidget.h \
src/GUI/markerinfoitem.h \
src/GUI/planeitem.h \
src/GUI/poiaction.h \
src/GUI/popup.h \
src/GUI/thumbnail.h \
src/GUI/app.h \ src/GUI/app.h \
src/GUI/icons.h \ src/GUI/icons.h \
src/GUI/gui.h \ src/GUI/gui.h \
@ -90,9 +97,24 @@ HEADERS += src/common/config.h \
src/GUI/mapview.h \ src/GUI/mapview.h \
src/GUI/font.h \ src/GUI/font.h \
src/GUI/areaitem.h \ src/GUI/areaitem.h \
src/data/itnparser.h \ src/GUI/coordinatesitem.h \
src/data/link.h \ src/GUI/projectioncombobox.h \
src/data/ov2parser.h \ src/GUI/pathtickitem.h \
src/GUI/pdfexportdialog.h \
src/GUI/pngexportdialog.h \
src/GUI/timezoneinfo.h \
src/GUI/passwordedit.h \
src/map/proj/polyconic.h \
src/map/proj/webmercator.h \
src/map/proj/transversemercator.h \
src/map/proj/latlon.h \
src/map/proj/lambertconic.h \
src/map/proj/lambertazimuthal.h \
src/map/proj/albersequal.h \
src/map/proj/mercator.h \
src/map/proj/krovak.h \
src/map/proj/polarstereographic.h \
src/map/proj/obliquestereographic.h \
src/map/IMG/bitmapline.h \ src/map/IMG/bitmapline.h \
src/map/IMG/bitstream.h \ src/map/IMG/bitstream.h \
src/map/IMG/deltastream.h \ src/map/IMG/deltastream.h \
@ -106,32 +128,34 @@ HEADERS += src/common/config.h \
src/map/IMG/raster.h \ src/map/IMG/raster.h \
src/map/IMG/rastertile.h \ src/map/IMG/rastertile.h \
src/map/IMG/shield.h \ src/map/IMG/shield.h \
src/map/IMG/imgdata.h \
src/map/IMG/subfile.h \
src/map/IMG/trefile.h \
src/map/IMG/rgnfile.h \
src/map/IMG/lblfile.h \
src/map/IMG/vectortile.h \
src/map/IMG/subdiv.h \
src/map/IMG/style.h \
src/map/IMG/netfile.h \
src/map/IMG/label.h \
src/map/mapsforge/style.h \ src/map/mapsforge/style.h \
src/map/prjfile.h \
src/map/textpathitem.h \
src/map/textpointitem.h \
src/map/mapsforge/mapdata.h \ src/map/mapsforge/mapdata.h \
src/map/mapsforge/rastertile.h \ src/map/mapsforge/rastertile.h \
src/map/mapsforge/subfile.h \ src/map/mapsforge/subfile.h \
src/map/textpathitem.h \
src/map/textpointitem.h \
src/map/prjfile.h \
src/map/bsbmap.h \ src/map/bsbmap.h \
src/map/invalidmap.h \ src/map/invalidmap.h \
src/map/kmzmap.h \ src/map/kmzmap.h \
src/map/polyconic.h \
src/map/projection.h \ src/map/projection.h \
src/map/ellipsoid.h \ src/map/ellipsoid.h \
src/map/datum.h \ src/map/datum.h \
src/map/sqlitemap.h \ src/map/sqlitemap.h \
src/map/webmercator.h \
src/map/transversemercator.h \
src/map/latlon.h \
src/map/utm.h \ src/map/utm.h \
src/map/lambertconic.h \
src/map/lambertazimuthal.h \
src/map/albersequal.h \
src/map/map.h \ src/map/map.h \
src/map/maplist.h \ src/map/maplist.h \
src/map/onlinemap.h \ src/map/onlinemap.h \
src/map/downloader.h \
src/map/tile.h \ src/map/tile.h \
src/map/emptymap.h \ src/map/emptymap.h \
src/map/ozimap.h \ src/map/ozimap.h \
@ -160,14 +184,23 @@ HEADERS += src/common/config.h \
src/map/pointd.h \ src/map/pointd.h \
src/map/rectd.h \ src/map/rectd.h \
src/map/geocentric.h \ src/map/geocentric.h \
src/map/mercator.h \
src/map/jnxmap.h \ src/map/jnxmap.h \
src/map/krovak.h \
src/map/geotiffmap.h \ src/map/geotiffmap.h \
src/map/image.h \ src/map/image.h \
src/map/mbtilesmap.h \ src/map/mbtilesmap.h \
src/map/osm.h \ src/map/osm.h \
src/map/polarstereographic.h \ src/map/rmap.h \
src/map/calibrationpoint.h \
src/map/color.h \
src/map/textitem.h \
src/map/aqmmap.h \
src/map/mapsforgemap.h \
src/map/worldfilemap.h \
src/map/imgmap.h \
src/data/itnparser.h \
src/data/link.h \
src/data/onmoveparsers.h \
src/data/ov2parser.h \
src/data/graph.h \ src/data/graph.h \
src/data/poi.h \ src/data/poi.h \
src/data/waypoint.h \ src/data/waypoint.h \
@ -190,48 +223,18 @@ HEADERS += src/common/config.h \
src/data/locparser.h \ src/data/locparser.h \
src/data/slfparser.h \ src/data/slfparser.h \
src/data/dem.h \ src/data/dem.h \
src/common/polygon.h \ src/data/demloader.h \
src/data/area.h \ src/data/area.h \
src/map/obliquestereographic.h \
src/GUI/coordinatesitem.h \
src/map/rmap.h \
src/map/calibrationpoint.h \
src/map/color.h \
src/data/exifparser.h \ src/data/exifparser.h \
src/data/imageinfo.h \ src/data/imageinfo.h \
src/map/imgmap.h \
src/map/IMG/imgdata.h \
src/map/IMG/subfile.h \
src/map/IMG/trefile.h \
src/map/IMG/rgnfile.h \
src/map/IMG/lblfile.h \
src/map/IMG/vectortile.h \
src/map/IMG/subdiv.h \
src/map/IMG/style.h \
src/map/IMG/netfile.h \
src/GUI/projectioncombobox.h \
src/GUI/pathtickitem.h \
src/map/textitem.h \
src/map/IMG/label.h \
src/data/csv.h \ src/data/csv.h \
src/data/cupparser.h \ src/data/cupparser.h \
src/data/gpiparser.h \ src/data/gpiparser.h \
src/data/address.h \ src/data/address.h \
src/data/smlparser.h \ src/data/smlparser.h \
src/GUI/pdfexportdialog.h \ src/data/geojsonparser.h
src/GUI/pngexportdialog.h \
src/data/geojsonparser.h \
src/GUI/timezoneinfo.h \
src/map/aqmmap.h \
src/map/mapsforgemap.h \
src/map/worldfilemap.h
SOURCES += src/main.cpp \ SOURCES += src/main.cpp \
src/GUI/axislabelitem.cpp \
src/GUI/mapitem.cpp \
src/GUI/marginswidget.cpp \
src/GUI/markerinfoitem.cpp \
src/GUI/popup.cpp \
src/common/coordinates.cpp \ src/common/coordinates.cpp \
src/common/rectc.cpp \ src/common/rectc.cpp \
src/common/range.cpp \ src/common/range.cpp \
@ -240,6 +243,17 @@ SOURCES += src/main.cpp \
src/common/greatcircle.cpp \ src/common/greatcircle.cpp \
src/common/programpaths.cpp \ src/common/programpaths.cpp \
src/common/tifffile.cpp \ src/common/tifffile.cpp \
src/common/downloader.cpp \
src/GUI/authenticationwidget.cpp \
src/GUI/axislabelitem.cpp \
src/GUI/dirselectwidget.cpp \
src/GUI/flowlayout.cpp \
src/GUI/infolabel.cpp \
src/GUI/mapitem.cpp \
src/GUI/marginswidget.cpp \
src/GUI/markerinfoitem.cpp \
src/GUI/popup.cpp \
src/GUI/thumbnail.cpp \
src/GUI/app.cpp \ src/GUI/app.cpp \
src/GUI/gui.cpp \ src/GUI/gui.cpp \
src/GUI/axisitem.cpp \ src/GUI/axisitem.cpp \
@ -259,7 +273,6 @@ SOURCES += src/main.cpp \
src/GUI/fileselectwidget.cpp \ src/GUI/fileselectwidget.cpp \
src/GUI/temperaturegraph.cpp \ src/GUI/temperaturegraph.cpp \
src/GUI/trackitem.cpp \ src/GUI/trackitem.cpp \
src/GUI/tooltip.cpp \
src/GUI/routeitem.cpp \ src/GUI/routeitem.cpp \
src/GUI/graphitem.cpp \ src/GUI/graphitem.cpp \
src/GUI/pathitem.cpp \ src/GUI/pathitem.cpp \
@ -282,10 +295,23 @@ SOURCES += src/main.cpp \
src/GUI/gearratiographitem.cpp \ src/GUI/gearratiographitem.cpp \
src/GUI/mapview.cpp \ src/GUI/mapview.cpp \
src/GUI/areaitem.cpp \ src/GUI/areaitem.cpp \
src/data/address.cpp \ src/GUI/coordinatesitem.cpp \
src/data/itnparser.cpp \ src/GUI/pathtickitem.cpp \
src/data/ov2parser.cpp \ src/GUI/graphicsscene.cpp \
src/data/waypoint.cpp \ src/GUI/pdfexportdialog.cpp \
src/GUI/pngexportdialog.cpp \
src/GUI/projectioncombobox.cpp \
src/GUI/passwordedit.cpp \
src/map/proj/polyconic.cpp \
src/map/proj/webmercator.cpp \
src/map/proj/transversemercator.cpp \
src/map/proj/lambertconic.cpp \
src/map/proj/albersequal.cpp \
src/map/proj/lambertazimuthal.cpp \
src/map/proj/mercator.cpp \
src/map/proj/krovak.cpp \
src/map/proj/polarstereographic.cpp \
src/map/proj/obliquestereographic.cpp \
src/map/IMG/bitmapline.cpp \ src/map/IMG/bitmapline.cpp \
src/map/IMG/bitstream.cpp \ src/map/IMG/bitstream.cpp \
src/map/IMG/deltastream.cpp \ src/map/IMG/deltastream.cpp \
@ -297,21 +323,28 @@ SOURCES += src/main.cpp \
src/map/IMG/nodfile.cpp \ src/map/IMG/nodfile.cpp \
src/map/IMG/mapdata.cpp \ src/map/IMG/mapdata.cpp \
src/map/IMG/rastertile.cpp \ src/map/IMG/rastertile.cpp \
src/map/IMG/imgdata.cpp \
src/map/IMG/subfile.cpp \
src/map/IMG/trefile.cpp \
src/map/IMG/rgnfile.cpp \
src/map/IMG/lblfile.cpp \
src/map/IMG/vectortile.cpp \
src/map/IMG/style.cpp \
src/map/IMG/netfile.cpp \
src/map/mapsforge/style.cpp \ src/map/mapsforge/style.cpp \
src/map/prjfile.cpp \
src/map/textpathitem.cpp \
src/map/textpointitem.cpp \
src/map/mapsforge/mapdata.cpp \ src/map/mapsforge/mapdata.cpp \
src/map/mapsforge/rastertile.cpp \ src/map/mapsforge/rastertile.cpp \
src/map/mapsforge/subfile.cpp \ src/map/mapsforge/subfile.cpp \
src/map/imgmap.cpp \
src/map/prjfile.cpp \
src/map/textpathitem.cpp \
src/map/textpointitem.cpp \
src/map/bsbmap.cpp \ src/map/bsbmap.cpp \
src/map/kmzmap.cpp \ src/map/kmzmap.cpp \
src/map/maplist.cpp \ src/map/maplist.cpp \
src/map/onlinemap.cpp \ src/map/onlinemap.cpp \
src/map/downloader.cpp \
src/map/emptymap.cpp \ src/map/emptymap.cpp \
src/map/ozimap.cpp \ src/map/ozimap.cpp \
src/map/polyconic.cpp \
src/map/sqlitemap.cpp \ src/map/sqlitemap.cpp \
src/map/tar.cpp \ src/map/tar.cpp \
src/map/atlas.cpp \ src/map/atlas.cpp \
@ -319,12 +352,7 @@ SOURCES += src/main.cpp \
src/map/matrix.cpp \ src/map/matrix.cpp \
src/map/ellipsoid.cpp \ src/map/ellipsoid.cpp \
src/map/datum.cpp \ src/map/datum.cpp \
src/map/webmercator.cpp \
src/map/transversemercator.cpp \
src/map/utm.cpp \ src/map/utm.cpp \
src/map/lambertconic.cpp \
src/map/albersequal.cpp \
src/map/lambertazimuthal.cpp \
src/map/geotiff.cpp \ src/map/geotiff.cpp \
src/map/pcs.cpp \ src/map/pcs.cpp \
src/map/transform.cpp \ src/map/transform.cpp \
@ -344,16 +372,23 @@ SOURCES += src/main.cpp \
src/map/crs.cpp \ src/map/crs.cpp \
src/map/coordinatesystem.cpp \ src/map/coordinatesystem.cpp \
src/map/geocentric.cpp \ src/map/geocentric.cpp \
src/map/mercator.cpp \
src/map/jnxmap.cpp \ src/map/jnxmap.cpp \
src/map/krovak.cpp \
src/map/map.cpp \ src/map/map.cpp \
src/map/geotiffmap.cpp \ src/map/geotiffmap.cpp \
src/map/image.cpp \ src/map/image.cpp \
src/map/mbtilesmap.cpp \ src/map/mbtilesmap.cpp \
src/map/osm.cpp \ src/map/osm.cpp \
src/map/polarstereographic.cpp \
src/map/rectd.cpp \ src/map/rectd.cpp \
src/map/rmap.cpp \
src/map/textitem.cpp \
src/map/aqmmap.cpp \
src/map/mapsforgemap.cpp \
src/map/worldfilemap.cpp \
src/data/address.cpp \
src/data/itnparser.cpp \
src/data/onmoveparsers.cpp \
src/data/ov2parser.cpp \
src/data/waypoint.cpp \
src/data/data.cpp \ src/data/data.cpp \
src/data/poi.cpp \ src/data/poi.cpp \
src/data/track.cpp \ src/data/track.cpp \
@ -370,33 +405,13 @@ SOURCES += src/main.cpp \
src/data/locparser.cpp \ src/data/locparser.cpp \
src/data/slfparser.cpp \ src/data/slfparser.cpp \
src/data/dem.cpp \ src/data/dem.cpp \
src/map/obliquestereographic.cpp \ src/data/demloader.cpp \
src/GUI/coordinatesitem.cpp \
src/map/rmap.cpp \
src/data/exifparser.cpp \ src/data/exifparser.cpp \
src/map/imgmap.cpp \
src/map/IMG/imgdata.cpp \
src/map/IMG/subfile.cpp \
src/map/IMG/trefile.cpp \
src/map/IMG/rgnfile.cpp \
src/map/IMG/lblfile.cpp \
src/map/IMG/vectortile.cpp \
src/map/IMG/style.cpp \
src/map/IMG/netfile.cpp \
src/GUI/pathtickitem.cpp \
src/map/textitem.cpp \
src/data/csv.cpp \ src/data/csv.cpp \
src/data/cupparser.cpp \ src/data/cupparser.cpp \
src/GUI/graphicsscene.cpp \
src/data/gpiparser.cpp \ src/data/gpiparser.cpp \
src/data/smlparser.cpp \ src/data/smlparser.cpp \
src/GUI/pdfexportdialog.cpp \ src/data/geojsonparser.cpp
src/GUI/pngexportdialog.cpp \
src/data/geojsonparser.cpp \
src/map/aqmmap.cpp \
src/map/mapsforgemap.cpp \
src/map/worldfilemap.cpp \
src/GUI/projectioncombobox.cpp
DEFINES += APP_VERSION=\\\"$$VERSION\\\" \ DEFINES += APP_VERSION=\\\"$$VERSION\\\" \
QT_NO_DEPRECATED_WARNINGS QT_NO_DEPRECATED_WARNINGS
@ -418,7 +433,8 @@ TRANSLATIONS = lang/gpxsee_en.ts \
lang/gpxsee_uk.ts \ lang/gpxsee_uk.ts \
lang/gpxsee_hu.ts \ lang/gpxsee_hu.ts \
lang/gpxsee_it.ts \ lang/gpxsee_it.ts \
lang/gpxsee_eo.ts lang/gpxsee_eo.ts \
lang/gpxsee_zh.ts
macx { macx {
ICON = icons/app/gpxsee.icns ICON = icons/app/gpxsee.icns
@ -440,7 +456,8 @@ macx {
lang/gpxsee_uk.qm \ lang/gpxsee_uk.qm \
lang/gpxsee_hu.qm \ lang/gpxsee_hu.qm \
lang/gpxsee_it.qm \ lang/gpxsee_it.qm \
lang/gpxsee_eo.qm lang/gpxsee_eo.qm \
lang/gpxsee_zh.qm
csv.path = Contents/Resources csv.path = Contents/Resources
csv.files = pkg/csv csv.files = pkg/csv
maps.path = Contents/Resources maps.path = Contents/Resources
@ -471,7 +488,9 @@ macx {
icons/formats/sqlt.icns \ icons/formats/sqlt.icns \
icons/formats/ov2.icns \ icons/formats/ov2.icns \
icons/formats/itn.icns \ icons/formats/itn.icns \
icons/formats/wld.icns icons/formats/wld.icns \
icons/formats/omd.icns \
icons/formats/ghp.icns
QMAKE_BUNDLE_DATA += locale maps icons csv QMAKE_BUNDLE_DATA += locale maps icons csv
} }
@ -503,7 +522,9 @@ win32 {
icons/formats/sqlt.ico \ icons/formats/sqlt.ico \
icons/formats/ov2.ico \ icons/formats/ov2.ico \
icons/formats/itn.ico \ icons/formats/itn.ico \
icons/formats/wld.ico icons/formats/wld.ico \
icons/formats/omd.ico \
icons/formats/ghp.ico
DEFINES += _USE_MATH_DEFINES \ DEFINES += _USE_MATH_DEFINES \
NOGDI NOGDI
} }

View File

@ -43,8 +43,14 @@
<file alias="view-filter@2x.png">icons/GUI/view-filter@2x.png</file> <file alias="view-filter@2x.png">icons/GUI/view-filter@2x.png</file>
<file alias="applications-internet_32.png">icons/GUI/applications-internet_32.png</file> <file alias="applications-internet_32.png">icons/GUI/applications-internet_32.png</file>
<file alias="applications-internet_32@2x.png">icons/GUI/applications-internet_32@2x.png</file> <file alias="applications-internet_32@2x.png">icons/GUI/applications-internet_32@2x.png</file>
<file alias="view-grid.png">icons/GUI/view-grid.png</file>
<file alias="view-grid@2x.png">icons/GUI/view-grid@2x.png</file>
<file alias="document-decrypt.png">icons/GUI/document-decrypt.png</file>
<file alias="document-decrypt@2x.png">icons/GUI/document-decrypt.png</file>
<file alias="document-encrypt.png">icons/GUI/document-encrypt.png</file>
<file alias="document-encrypt@2x.png">icons/GUI/document-encrypt.png</file>
</qresource> </qresource>
<!-- POI icons for default IMG map style --> <!-- POI icons for default IMG map style -->
<qresource prefix="/POI"> <qresource prefix="/POI">
<file alias="airfield-11.png">icons/POI/airfield-11.png</file> <file alias="airfield-11.png">icons/POI/airfield-11.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
icons/GUI/view-grid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
icons/GUI/view-grid@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
icons/formats/ghp.icns Normal file

Binary file not shown.

BIN
icons/formats/ghp.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

BIN
icons/formats/omd.icns Normal file

Binary file not shown.

BIN
icons/formats/omd.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

View File

@ -25,3 +25,5 @@ sqlt:#303030
ov2:#a8c920 ov2:#a8c920
itn:#b8540d itn:#b8540d
wld:#c74c8f wld:#c74c8f
omd:#ed09cb
ghp:#ed09cb

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2265
lang/gpxsee_zh.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@ -546,6 +546,38 @@
<key>CFBundleTypeRole</key> <key>CFBundleTypeRole</key>
<string>Viewer</string> <string>Viewer</string>
</dict> </dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>omd</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/vnd.onmove.omd</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>icons/omd.icns</string>
<key>CFBundleTypeName</key>
<string>ONmove Log File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>ghp</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/vnd.onmove.ghp</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>icons/ghp.icns</string>
<key>CFBundleTypeName</key>
<string>ONmove Log File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array> </array>
<key>UTImportedTypeDeclarations</key> <key>UTImportedTypeDeclarations</key>
@ -557,6 +589,8 @@
<string>http://www.topografix.com/GPX/1/1</string> <string>http://www.topografix.com/GPX/1/1</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>GPS Exchange Format</string> <string>GPS Exchange Format</string>
<key>UTTypeIconFile</key>
<string>icons/gpx.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.xml</string> <string>public.xml</string>
@ -578,6 +612,8 @@
<string>http://www8.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd</string> <string>http://www8.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>Training Center XML</string> <string>Training Center XML</string>
<key>UTTypeIconFile</key>
<string>icons/tcx.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.xml</string> <string>public.xml</string>
@ -599,6 +635,8 @@
<string>https://developers.google.com/kml/documentation/kmlreference</string> <string>https://developers.google.com/kml/documentation/kmlreference</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>Keyhole Markup Language</string> <string>Keyhole Markup Language</string>
<key>UTTypeIconFile</key>
<string>icons/kml.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.xml</string> <string>public.xml</string>
@ -620,6 +658,8 @@
<string>https://developers.google.com/kml/documentation/kmlreference</string> <string>https://developers.google.com/kml/documentation/kmlreference</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>KML geographic compressed data</string> <string>KML geographic compressed data</string>
<key>UTTypeIconFile</key>
<string>icons/kml.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.archive</string> <string>public.archive</string>
@ -641,6 +681,8 @@
<string>https://www.geocaching.com</string> <string>https://www.geocaching.com</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>Geocaching.com Waypoint File</string> <string>Geocaching.com Waypoint File</string>
<key>UTTypeIconFile</key>
<string>icons/loc.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.xml</string> <string>public.xml</string>
@ -662,6 +704,8 @@
<string>https://www.sigmasport.com</string> <string>https://www.sigmasport.com</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>Sigma Log Format</string> <string>Sigma Log Format</string>
<key>UTTypeIconFile</key>
<string>icons/slf.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.xml</string> <string>public.xml</string>
@ -683,6 +727,8 @@
<string>https://www.thisisant.com/resources/fit</string> <string>https://www.thisisant.com/resources/fit</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>Flexible and Interoperable Data Transfer</string> <string>Flexible and Interoperable Data Transfer</string>
<key>UTTypeIconFile</key>
<string>icons/fit.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -704,6 +750,8 @@
<string>http://www.fai.org/gnss-recording-devices/igc-approved-flight-recorders</string> <string>http://www.fai.org/gnss-recording-devices/igc-approved-flight-recorders</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>Flight Recorder Data Format</string> <string>Flight Recorder Data Format</string>
<key>UTTypeIconFile</key>
<string>icons/igc.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -725,6 +773,8 @@
<string>http://www.nmea.org/content/nmea_standards/nmea_0183_v_410.asp</string> <string>http://www.nmea.org/content/nmea_standards/nmea_0183_v_410.asp</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>NMEA 0183 data</string> <string>NMEA 0183 data</string>
<key>UTTypeIconFile</key>
<string>icons/nmea.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -746,6 +796,8 @@
<string>http://www.oziexplorer3.com/eng/help/fileformats.html</string> <string>http://www.oziexplorer3.com/eng/help/fileformats.html</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>OziExplorer Track Point File</string> <string>OziExplorer Track Point File</string>
<key>UTTypeIconFile</key>
<string>icons/plt.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -762,11 +814,13 @@
</dict> </dict>
<dict> <dict>
<key>UTTypeIdentifier</key> <key>UTTypeIdentifier</key>
<string>com.oziexplorer3.plt</string> <string>com.oziexplorer3.rte</string>
<key>UTTypeReferenceURL</key> <key>UTTypeReferenceURL</key>
<string>http://www.oziexplorer3.com/eng/help/fileformats.html</string> <string>http://www.oziexplorer3.com/eng/help/fileformats.html</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>OziExplorer Route File</string> <string>OziExplorer Route File</string>
<key>UTTypeIconFile</key>
<string>icons/rte.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -783,11 +837,13 @@
</dict> </dict>
<dict> <dict>
<key>UTTypeIdentifier</key> <key>UTTypeIdentifier</key>
<string>com.oziexplorer3.plt</string> <string>com.oziexplorer3.wpt</string>
<key>UTTypeReferenceURL</key> <key>UTTypeReferenceURL</key>
<string>http://www.oziexplorer3.com/eng/help/fileformats.html</string> <string>http://www.oziexplorer3.com/eng/help/fileformats.html</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>OziExplorer Waypoint File</string> <string>OziExplorer Waypoint File</string>
<key>UTTypeIconFile</key>
<string>icons/wpt.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -809,6 +865,8 @@
<string>http://www.geojson.org</string> <string>http://www.geojson.org</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>GeoJSON</string> <string>GeoJSON</string>
<key>UTTypeIconFile</key>
<string>icons/json.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.json</string> <string>public.json</string>
@ -830,6 +888,8 @@
<string>http://www.naviter.com</string> <string>http://www.naviter.com</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>SeeYou CUP File</string> <string>SeeYou CUP File</string>
<key>UTTypeIconFile</key>
<string>icons/cup.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -851,6 +911,8 @@
<string>http://www.garmin.com</string> <string>http://www.garmin.com</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>Garmin POI File</string> <string>Garmin POI File</string>
<key>UTTypeIconFile</key>
<string>icons/gpi.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -872,6 +934,8 @@
<string>https://www.suunto.com</string> <string>https://www.suunto.com</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>Suunto Markup Language</string> <string>Suunto Markup Language</string>
<key>UTTypeIconFile</key>
<string>icons/sml.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.xml</string> <string>public.xml</string>
@ -937,6 +1001,8 @@
<string>https://sourceforge.net/projects/garmin-img/</string> <string>https://sourceforge.net/projects/garmin-img/</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>Garmin IMG map</string> <string>Garmin IMG map</string>
<key>UTTypeIconFile</key>
<string>icons/img.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -958,6 +1024,8 @@
<string>http://whiter.brinkster.net/en/JNX.shtml</string> <string>http://whiter.brinkster.net/en/JNX.shtml</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>Garmin JNX Map</string> <string>Garmin JNX Map</string>
<key>UTTypeIconFile</key>
<string>icons/jnx.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -979,6 +1047,8 @@
<string>https://sourceforge.net/projects/garmin-img/</string> <string>https://sourceforge.net/projects/garmin-img/</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>Garmin Map Product File</string> <string>Garmin Map Product File</string>
<key>UTTypeIconFile</key>
<string>icons/img.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.xml</string> <string>public.xml</string>
@ -1000,6 +1070,8 @@
<string>http://libbsb.sourceforge.net/bsb_file_format.html</string> <string>http://libbsb.sourceforge.net/bsb_file_format.html</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>BSB Nautical Charts</string> <string>BSB Nautical Charts</string>
<key>UTTypeIconFile</key>
<string>icons/kap.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.image</string> <string>public.image</string>
@ -1022,6 +1094,8 @@
<string>https://www.oziexplorer3.com/eng/help/map_file_format.html</string> <string>https://www.oziexplorer3.com/eng/help/map_file_format.html</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>OziExplorer Map File</string> <string>OziExplorer Map File</string>
<key>UTTypeIconFile</key>
<string>icons/map.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -1043,6 +1117,8 @@
<string>https://github.com/mapbox/mbtiles-spec</string> <string>https://github.com/mapbox/mbtiles-spec</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>MBTiles Map File</string> <string>MBTiles Map File</string>
<key>UTTypeIconFile</key>
<string>icons/mbts.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -1064,6 +1140,8 @@
<string>https://wiki.openstreetmap.org/wiki/TwoNav_RMAP</string> <string>https://wiki.openstreetmap.org/wiki/TwoNav_RMAP</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>TwoNav Raster Map File</string> <string>TwoNav Raster Map File</string>
<key>UTTypeIconFile</key>
<string>icons/rmap.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -1086,6 +1164,8 @@
<string>https://github.com/kruhc/trekbuddy</string> <string>https://github.com/kruhc/trekbuddy</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>TrekBuddy Atlas</string> <string>TrekBuddy Atlas</string>
<key>UTTypeIconFile</key>
<string>icons/tba.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -1107,6 +1187,8 @@
<string>https://svn.code.sf.net/p/mobac/code/trunk/MOBAC</string> <string>https://svn.code.sf.net/p/mobac/code/trunk/MOBAC</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>AlpineQuest Map File</string> <string>AlpineQuest Map File</string>
<key>UTTypeIconFile</key>
<string>icons/aqm.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -1128,6 +1210,8 @@
<string>https://svn.code.sf.net/p/mobac/code/trunk/MOBAC</string> <string>https://svn.code.sf.net/p/mobac/code/trunk/MOBAC</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>RMaps SQLite Map File</string> <string>RMaps SQLite Map File</string>
<key>UTTypeIconFile</key>
<string>icons/sqlt.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -1172,6 +1256,8 @@
<string>https://www.tomtom.com/lib/doc/ttnavsdk3_manual.pdf</string> <string>https://www.tomtom.com/lib/doc/ttnavsdk3_manual.pdf</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>TomTom POI File</string> <string>TomTom POI File</string>
<key>UTTypeIconFile</key>
<string>icons/ov2.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -1193,6 +1279,8 @@
<string>https://www.tomtom.com/lib/doc/ttnavsdk3_manual.pdf</string> <string>https://www.tomtom.com/lib/doc/ttnavsdk3_manual.pdf</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>TomTom Route File</string> <string>TomTom Route File</string>
<key>UTTypeIconFile</key>
<string>icons/itn.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -1214,6 +1302,8 @@
<string>http://webhelp.esri.com/arcims/9.3/General/topics/author_world_files.htm</string> <string>http://webhelp.esri.com/arcims/9.3/General/topics/author_world_files.htm</string>
<key>UTTypeDescription</key> <key>UTTypeDescription</key>
<string>ESRI World File</string> <string>ESRI World File</string>
<key>UTTypeIconFile</key>
<string>icons/wld.icns</string>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
@ -1232,6 +1322,52 @@
<string>application/vnd.esri.wld</string> <string>application/vnd.esri.wld</string>
</dict> </dict>
</dict> </dict>
<dict>
<key>UTTypeIdentifier</key>
<string>com.geonaute.omd</string>
<key>UTTypeReferenceURL</key>
<string>https://github.com/ColinPitrat/kalenji-gps-watch-reader</string>
<key>UTTypeDescription</key>
<string>ONmove Log File</string>
<key>UTTypeIconFile</key>
<string>icons/omd.icns</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>omd</string>
</array>
<key>public.mime-type</key>
<string>application/vnd.onmove.omd</string>
</dict>
</dict>
<dict>
<key>UTTypeIdentifier</key>
<string>com.geonaute.ghp</string>
<key>UTTypeReferenceURL</key>
<string>https://github.com/ColinPitrat/kalenji-gps-watch-reader</string>
<key>UTTypeDescription</key>
<string>ONmove Log File</string>
<key>UTTypeIconFile</key>
<string>icons/ghp.icns</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>ghp</string>
</array>
<key>public.mime-type</key>
<string>application/vnd.onmove.ghp</string>
</dict>
</dict>
</array> </array>
<key>UTExportedTypeDeclarations</key> <key>UTExportedTypeDeclarations</key>

View File

@ -14,8 +14,8 @@
<ul> <ul>
<li>Opens GPX, TCX, FIT, KML, IGC, NMEA, SIGMA SLF, Suunto SML, LOC, <li>Opens GPX, TCX, FIT, KML, IGC, NMEA, SIGMA SLF, Suunto SML, LOC,
OziExplorer (PLT, WPT, RTE), GeoJSON, SeeYou CUP, OziExplorer (PLT, WPT, RTE), GeoJSON, SeeYou CUP,
Garmin GPI &amp; CSV, TomTom OV2 &amp; ITN and geotagged JPEG Garmin GPI &amp; CSV, TomTom OV2 &amp; ITN, ONmove OMD/GHP
files.</li> and geotagged JPEG files.</li>
<li>User-definable online maps (OpenStreetMap/Google tiles, WMTS, <li>User-definable online maps (OpenStreetMap/Google tiles, WMTS,
WMS, TMS, QuadTiles).</li> WMS, TMS, QuadTiles).</li>
<li>Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, <li>Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases,
@ -95,5 +95,7 @@
<mimetype>application/vnd.tomtom.ov2</mimetype> <mimetype>application/vnd.tomtom.ov2</mimetype>
<mimetype>application/vnd.tomtom.itn</mimetype> <mimetype>application/vnd.tomtom.itn</mimetype>
<mimetype>application/vnd.esri.wld</mimetype> <mimetype>application/vnd.esri.wld</mimetype>
<mimetype>application/vnd.onmove.omd</mimetype>
<mimetype>application/vnd.onmove.ghp</mimetype>
</mimetypes> </mimetypes>
</component> </component>

View File

@ -9,7 +9,7 @@ Unicode true
; The name of the installer ; The name of the installer
Name "GPXSee" Name "GPXSee"
; Program version ; Program version
!define VERSION "9.2" !define VERSION "9.7"
; The file to write ; The file to write
OutFile "GPXSee-${VERSION}.exe" OutFile "GPXSee-${VERSION}.exe"
@ -137,15 +137,17 @@ Section "GPXSee" SEC_APP
!insertmacro FILE_ASSOCIATION_ADD "jgw" "ESRI World File" 20 !insertmacro FILE_ASSOCIATION_ADD "jgw" "ESRI World File" 20
!insertmacro FILE_ASSOCIATION_ADD "gfw" "ESRI World File" 20 !insertmacro FILE_ASSOCIATION_ADD "gfw" "ESRI World File" 20
!insertmacro FILE_ASSOCIATION_ADD "pgw" "ESRI World File" 20 !insertmacro FILE_ASSOCIATION_ADD "pgw" "ESRI World File" 20
!insertmacro FILE_ASSOCIATION_ADD "tfw" "ESRI World File" 20 !insertmacro FILE_ASSOCIATION_ADD "tfw" "ESRI World File" 20
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 21 !insertmacro FILE_ASSOCIATION_ADD "omd" "ONmove Log File" 21
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 22 !insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 22
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 22 !insertmacro FILE_ASSOCIATION_ADD "ghp" "ONmove Log File" 23
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 23 !insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 24
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 24 !insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 24
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 25 !insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 25
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 26 !insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 26
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 27 !insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 27
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 28
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 29
WriteRegStr HKCR "Applications\GPXSee.exe\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\"" WriteRegStr HKCR "Applications\GPXSee.exe\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
WriteRegStr HKCR ".gpx\OpenWithList" "GPXSee.exe" "" WriteRegStr HKCR ".gpx\OpenWithList" "GPXSee.exe" ""
@ -188,7 +190,9 @@ Section "GPXSee" SEC_APP
WriteRegStr HKCR ".jgw\OpenWithList" "GPXSee.exe" "" WriteRegStr HKCR ".jgw\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".gfw\OpenWithList" "GPXSee.exe" "" WriteRegStr HKCR ".gfw\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".pgw\OpenWithList" "GPXSee.exe" "" WriteRegStr HKCR ".pgw\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".tfw\OpenWithList" "GPXSee.exe" "" WriteRegStr HKCR ".tfw\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".omd\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".ghp\OpenWithList" "GPXSee.exe" ""
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)' System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
@ -243,6 +247,7 @@ Section "ANGLE" SEC_ANGLE
SectionEnd SectionEnd
SectionGroup "Localization" SEC_LOCALIZATION SectionGroup "Localization" SEC_LOCALIZATION
!insertmacro LOCALIZATION "Chinese (Simplified)" "zh"
!insertmacro LOCALIZATION "Czech" "cs" !insertmacro LOCALIZATION "Czech" "cs"
!insertmacro LOCALIZATION "Danish" "da" !insertmacro LOCALIZATION "Danish" "da"
!insertmacro LOCALIZATION "Esperanto" "eo" !insertmacro LOCALIZATION "Esperanto" "eo"
@ -313,6 +318,8 @@ Section "Uninstall"
!insertmacro FILE_ASSOCIATION_REMOVE "gfw" !insertmacro FILE_ASSOCIATION_REMOVE "gfw"
!insertmacro FILE_ASSOCIATION_REMOVE "pgw" !insertmacro FILE_ASSOCIATION_REMOVE "pgw"
!insertmacro FILE_ASSOCIATION_REMOVE "tfw" !insertmacro FILE_ASSOCIATION_REMOVE "tfw"
!insertmacro FILE_ASSOCIATION_REMOVE "omd"
!insertmacro FILE_ASSOCIATION_REMOVE "ghp"
DeleteRegValue HKCR ".gpx\OpenWithList" "GPXSee.exe" DeleteRegValue HKCR ".gpx\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".tcx\OpenWithList" "GPXSee.exe" DeleteRegValue HKCR ".tcx\OpenWithList" "GPXSee.exe"
@ -355,6 +362,8 @@ Section "Uninstall"
DeleteRegValue HKCR ".gfw\OpenWithList" "GPXSee.exe" DeleteRegValue HKCR ".gfw\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".pgw\OpenWithList" "GPXSee.exe" DeleteRegValue HKCR ".pgw\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".tfw\OpenWithList" "GPXSee.exe" DeleteRegValue HKCR ".tfw\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".omd\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".ghp\OpenWithList" "GPXSee.exe"
DeleteRegKey HKCR "Applications\GPXSee.exe" DeleteRegKey HKCR "Applications\GPXSee.exe"
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)' System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
@ -387,4 +396,4 @@ LangString DESC_LOCALIZATION ${LANG_ENGLISH} \
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_MSVC} $(DESC_MSVC) !insertmacro MUI_DESCRIPTION_TEXT ${SEC_MSVC} $(DESC_MSVC)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_APP} $(DESC_APP) !insertmacro MUI_DESCRIPTION_TEXT ${SEC_APP} $(DESC_APP)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_LOCALIZATION} $(DESC_LOCALIZATION) !insertmacro MUI_DESCRIPTION_TEXT ${SEC_LOCALIZATION} $(DESC_LOCALIZATION)
!insertmacro MUI_FUNCTION_DESCRIPTION_END !insertmacro MUI_FUNCTION_DESCRIPTION_END

View File

@ -142,6 +142,20 @@
<glob pattern="*.itn"/> <glob pattern="*.itn"/>
</mime-type> </mime-type>
<mime-type type="application/vnd.onmove.omd">
<comment>ONmove Log File</comment>
<sub-class-of type="application/octet-stream"/>
<generic-icon name="application/octet-stream"/>
<glob pattern="*.omd"/>
</mime-type>
<mime-type type="application/vnd.onmove.ghp">
<comment>ONmove Log File</comment>
<sub-class-of type="application/octet-stream"/>
<generic-icon name="application/octet-stream"/>
<glob pattern="*.ghp"/>
</mime-type>
<!-- Maps --> <!-- Maps -->
<mime-type type="application/vnd.garmin.img"> <mime-type type="application/vnd.garmin.img">

View File

@ -9,7 +9,7 @@ Unicode true
; The name of the installer ; The name of the installer
Name "GPXSee" Name "GPXSee"
; Program version ; Program version
!define VERSION "9.2" !define VERSION "9.7"
; The file to write ; The file to write
OutFile "GPXSee-${VERSION}_x64.exe" OutFile "GPXSee-${VERSION}_x64.exe"
@ -144,15 +144,17 @@ Section "GPXSee" SEC_APP
!insertmacro FILE_ASSOCIATION_ADD "jgw" "ESRI World File" 20 !insertmacro FILE_ASSOCIATION_ADD "jgw" "ESRI World File" 20
!insertmacro FILE_ASSOCIATION_ADD "gfw" "ESRI World File" 20 !insertmacro FILE_ASSOCIATION_ADD "gfw" "ESRI World File" 20
!insertmacro FILE_ASSOCIATION_ADD "pgw" "ESRI World File" 20 !insertmacro FILE_ASSOCIATION_ADD "pgw" "ESRI World File" 20
!insertmacro FILE_ASSOCIATION_ADD "tfw" "ESRI World File" 20 !insertmacro FILE_ASSOCIATION_ADD "tfw" "ESRI World File" 20
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 21 !insertmacro FILE_ASSOCIATION_ADD "omd" "ONmove Log File" 21
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 22 !insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 22
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 22 !insertmacro FILE_ASSOCIATION_ADD "ghp" "ONmove Log File" 23
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 23 !insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 24
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 24 !insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 24
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 25 !insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 25
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 26 !insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 26
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 27 !insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 27
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 28
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 29
WriteRegStr HKCR "Applications\GPXSee.exe\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\"" WriteRegStr HKCR "Applications\GPXSee.exe\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
WriteRegStr HKCR ".gpx\OpenWithList" "GPXSee.exe" "" WriteRegStr HKCR ".gpx\OpenWithList" "GPXSee.exe" ""
@ -196,6 +198,8 @@ Section "GPXSee" SEC_APP
WriteRegStr HKCR ".gfw\OpenWithList" "GPXSee.exe" "" WriteRegStr HKCR ".gfw\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".pgw\OpenWithList" "GPXSee.exe" "" WriteRegStr HKCR ".pgw\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".tfw\OpenWithList" "GPXSee.exe" "" WriteRegStr HKCR ".tfw\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".omd\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".ghp\OpenWithList" "GPXSee.exe" ""
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)' System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
@ -265,6 +269,7 @@ SectionEnd
!endif !endif
SectionGroup "Localization" SEC_LOCALIZATION SectionGroup "Localization" SEC_LOCALIZATION
!insertmacro LOCALIZATION "Chinese (Simplified)" "zh"
!insertmacro LOCALIZATION "Czech" "cs" !insertmacro LOCALIZATION "Czech" "cs"
!insertmacro LOCALIZATION "Danish" "da" !insertmacro LOCALIZATION "Danish" "da"
!insertmacro LOCALIZATION "Esperanto" "eo" !insertmacro LOCALIZATION "Esperanto" "eo"
@ -336,6 +341,8 @@ Section "Uninstall"
!insertmacro FILE_ASSOCIATION_REMOVE "gfw" !insertmacro FILE_ASSOCIATION_REMOVE "gfw"
!insertmacro FILE_ASSOCIATION_REMOVE "pgw" !insertmacro FILE_ASSOCIATION_REMOVE "pgw"
!insertmacro FILE_ASSOCIATION_REMOVE "tfw" !insertmacro FILE_ASSOCIATION_REMOVE "tfw"
!insertmacro FILE_ASSOCIATION_REMOVE "omd"
!insertmacro FILE_ASSOCIATION_REMOVE "ghp"
DeleteRegValue HKCR ".gpx\OpenWithList" "GPXSee.exe" DeleteRegValue HKCR ".gpx\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".tcx\OpenWithList" "GPXSee.exe" DeleteRegValue HKCR ".tcx\OpenWithList" "GPXSee.exe"
@ -378,6 +385,8 @@ Section "Uninstall"
DeleteRegValue HKCR ".gfw\OpenWithList" "GPXSee.exe" DeleteRegValue HKCR ".gfw\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".pgw\OpenWithList" "GPXSee.exe" DeleteRegValue HKCR ".pgw\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".tfw\OpenWithList" "GPXSee.exe" DeleteRegValue HKCR ".tfw\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".omd\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".ghp\OpenWithList" "GPXSee.exe"
DeleteRegKey HKCR "Applications\GPXSee.exe" DeleteRegKey HKCR "Applications\GPXSee.exe"
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)' System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
@ -410,4 +419,4 @@ LangString DESC_LOCALIZATION ${LANG_ENGLISH} \
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_MSVC} $(DESC_MSVC) !insertmacro MUI_DESCRIPTION_TEXT ${SEC_MSVC} $(DESC_MSVC)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_APP} $(DESC_APP) !insertmacro MUI_DESCRIPTION_TEXT ${SEC_APP} $(DESC_APP)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_LOCALIZATION} $(DESC_LOCALIZATION) !insertmacro MUI_DESCRIPTION_TEXT ${SEC_LOCALIZATION} $(DESC_LOCALIZATION)
!insertmacro MUI_FUNCTION_DESCRIPTION_END !insertmacro MUI_FUNCTION_DESCRIPTION_END

View File

@ -5,17 +5,15 @@
#include <QNetworkProxyFactory> #include <QNetworkProxyFactory>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QLibraryInfo> #include <QLibraryInfo>
#include <QSettings>
#include <QSurfaceFormat> #include <QSurfaceFormat>
#include "common/programpaths.h" #include "common/programpaths.h"
#include "common/config.h" #include "common/config.h"
#include "map/downloader.h" #include "common/downloader.h"
#include "map/ellipsoid.h" #include "map/ellipsoid.h"
#include "map/gcs.h" #include "map/gcs.h"
#include "map/pcs.h" #include "map/pcs.h"
#include "data/dem.h" #include "data/dem.h"
#include "gui.h" #include "gui.h"
#include "settings.h"
#include "mapaction.h" #include "mapaction.h"
#include "app.h" #include "app.h"
@ -60,14 +58,6 @@ App::App(int &argc, char **argv) : QApplication(argc, argv)
loadDatums(); loadDatums();
loadPCSs(); loadPCSs();
QSettings settings(qApp->applicationName(), qApp->applicationName());
settings.beginGroup(OPTIONS_SETTINGS_GROUP);
Downloader::enableHTTP2(settings.value(ENABLE_HTTP2_SETTING,
ENABLE_HTTP2_DEFAULT).toBool());
Downloader::setTimeout(settings.value(CONNECTION_TIMEOUT_SETTING,
CONNECTION_TIMEOUT_DEFAULT).toInt());
settings.endGroup();
_gui = new GUI(); _gui = new GUI();
} }

View File

@ -9,7 +9,7 @@
#include "areaitem.h" #include "areaitem.h"
QString AreaItem::info() const ToolTip AreaItem::info() const
{ {
ToolTip tt; ToolTip tt;
@ -19,7 +19,7 @@ QString AreaItem::info() const
tt.insert(qApp->translate("PolygonItem", "Description"), tt.insert(qApp->translate("PolygonItem", "Description"),
_area.description()); _area.description());
return tt.toString(); return tt;
} }
AreaItem::AreaItem(const Area &area, Map *map, GraphicsItem *parent) AreaItem::AreaItem(const Area &area, Map *map, GraphicsItem *parent)

View File

@ -25,7 +25,7 @@ public:
void setStyle(Qt::PenStyle style); void setStyle(Qt::PenStyle style);
void setDigitalZoom(int zoom); void setDigitalZoom(int zoom);
QString info() const; ToolTip info() const;
protected: protected:
void hoverEnterEvent(QGraphicsSceneHoverEvent *event); void hoverEnterEvent(QGraphicsSceneHoverEvent *event);

View File

@ -0,0 +1,20 @@
#include <QFormLayout>
#include "authenticationwidget.h"
AuthenticationWidget::AuthenticationWidget(QWidget *parent) : QWidget(parent)
{
_username = new QLineEdit();
_password = new PasswordEdit();
#ifdef Q_OS_MAC
/* A hack to fix the issue with different field sizes on Mac */
_username->setMinimumWidth(150);
_password->setMinimumWidth(150);
#endif // Q_OS_MAC
QFormLayout *layout = new QFormLayout();
layout->addRow(tr("Username:"), _username);
layout->addRow(tr("Password:"), _password);
layout->setContentsMargins(0, 0, 0, 0);
setLayout(layout);
}

View File

@ -0,0 +1,26 @@
#ifndef AUTHENTICATIONWIDGET_H
#define AUTHENTICATIONWIDGET_H
#include <QWidget>
#include <QLineEdit>
#include "passwordedit.h"
class AuthenticationWidget : public QWidget
{
Q_OBJECT
public:
AuthenticationWidget(QWidget *parent = 0);
QString username() const {return _username->text();}
QString password() const {return _password->text();}
void setUsername(const QString &username) {_username->setText(username);}
void setPassword(const QString &password) {_password->setText(password);}
private:
QLineEdit *_username;
PasswordEdit *_password;
};
#endif // AUTHENTICATIONWIDGET_H

View File

@ -9,7 +9,7 @@ CadenceGraphItem::CadenceGraphItem(const Graph &graph, GraphType type,
{ {
} }
QString CadenceGraphItem::info() const ToolTip CadenceGraphItem::info() const
{ {
ToolTip tt; ToolTip tt;
QLocale l(QLocale::system()); QLocale l(QLocale::system());
@ -19,5 +19,5 @@ QString CadenceGraphItem::info() const
tt.insert(tr("Average"), l.toString(avg(), 'f', 1) tt.insert(tr("Average"), l.toString(avg(), 'f', 1)
+ UNIT_SPACE + tr("rpm")); + UNIT_SPACE + tr("rpm"));
return tt.toString(); return tt;
} }

View File

@ -11,7 +11,7 @@ public:
CadenceGraphItem(const Graph &graph, GraphType type, int width, CadenceGraphItem(const Graph &graph, GraphType type, int width,
const QColor &color, QGraphicsItem *parent = 0); const QColor &color, QGraphicsItem *parent = 0);
QString info() const; ToolTip info() const;
}; };
#endif // CADENCEGRAPHITEM_H #endif // CADENCEGRAPHITEM_H

View File

@ -0,0 +1,43 @@
#include <QPushButton>
#include <QToolButton>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QFileInfo>
#include <QFontMetrics>
#include <QApplication>
#include "dirselectwidget.h"
DirSelectWidget::DirSelectWidget(QWidget *parent) : QWidget(parent)
{
QFontMetrics fm(QApplication::font());
_edit = new QLineEdit();
_edit->setMinimumWidth(fm.averageCharWidth() * (QDir::homePath().length()
+ 12));
_edit->setPlaceholderText(tr("System default"));
#ifdef Q_OS_WIN32
_button = new QPushButton("...");
_button->setMaximumWidth(_button->sizeHint().width() / 2);
#else // Q_OS_WIN32
_button = new QToolButton();
_button->setText("...");
#endif // Q_OS_WIN32
connect(_button, &QToolButton::clicked, this, &DirSelectWidget::browse);
QHBoxLayout *layout = new QHBoxLayout();
layout->setContentsMargins(QMargins());
layout->addWidget(_edit);
layout->addWidget(_button);
setLayout(layout);
QSizePolicy p(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
setSizePolicy(p);
}
void DirSelectWidget::browse()
{
QString dir(QFileDialog::getExistingDirectory(this, tr("Select directory"),
_edit->text()));
if (!dir.isEmpty())
_edit->setText(dir);
}

33
src/GUI/dirselectwidget.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef DIRSELECTWIDGET_H
#define DIRSELECTWIDGET_H
#include <QWidget>
#include <QLineEdit>
class QPushButton;
class QToolButton;
class DirSelectWidget : public QWidget
{
Q_OBJECT
public:
DirSelectWidget(QWidget *parent = 0);
QString dir() const {return _edit->text();}
void setDir(const QString &path) {_edit->setText(path);}
bool checkDir(QString &error) const;
private slots:
void browse();
private:
QLineEdit *_edit;
#ifdef Q_OS_WIN32
QPushButton *_button;
#else // Q_OS_WIN32
QToolButton *_button;
#endif // Q_OS_WIN32
};
#endif // DIRSELECTWIDGET_H

View File

@ -26,7 +26,7 @@ ElevationGraphItem::ElevationGraphItem(const Graph &graph, GraphType type,
} }
} }
QString ElevationGraphItem::info() const ToolTip ElevationGraphItem::info() const
{ {
ToolTip tt; ToolTip tt;
qreal scale = (_units == Metric) ? 1.0 : M2FT; qreal scale = (_units == Metric) ? 1.0 : M2FT;
@ -42,6 +42,5 @@ QString ElevationGraphItem::info() const
tt.insert(tr("Minimum"), l.toString(min() * scale, 'f', 0) tt.insert(tr("Minimum"), l.toString(min() * scale, 'f', 0)
+ UNIT_SPACE + su); + UNIT_SPACE + su);
return tt;
return tt.toString();
} }

View File

@ -18,7 +18,7 @@ public:
qreal max() const {return _max;} qreal max() const {return _max;}
qreal min() const {return _min;} qreal min() const {return _min;}
QString info() const; ToolTip info() const;
private: private:
qreal _ascent, _descent, _min, _max; qreal _ascent, _descent, _min, _max;

181
src/GUI/flowlayout.cpp Normal file
View File

@ -0,0 +1,181 @@
#include <QtWidgets>
#include "flowlayout.h"
struct FlowLayoutItem
{
FlowLayoutItem() : item(0) {}
FlowLayoutItem(QLayoutItem *item, int x, int y) : item(item), pos(x, y) {}
QLayoutItem *item;
QPoint pos;
};
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
: QLayout(parent), _hSpace(hSpacing), _vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
: _hSpace(hSpacing), _vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::~FlowLayout()
{
qDeleteAll(_items);
}
void FlowLayout::addItem(QLayoutItem *item)
{
_items.append(item);
}
int FlowLayout::horizontalSpacing() const
{
return (_hSpace >= 0)
? _hSpace
: smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
}
int FlowLayout::verticalSpacing() const
{
return (_vSpace >= 0)
? _vSpace
: smartSpacing(QStyle::PM_LayoutVerticalSpacing);
}
int FlowLayout::count() const
{
return _items.size();
}
QLayoutItem *FlowLayout::itemAt(int index) const
{
return _items.value(index);
}
QLayoutItem *FlowLayout::takeAt(int index)
{
if (index >= 0 && index < _items.size())
return _items.takeAt(index);
return 0;
}
Qt::Orientations FlowLayout::expandingDirections() const
{
return {};
}
bool FlowLayout::hasHeightForWidth() const
{
return true;
}
int FlowLayout::heightForWidth(int width) const
{
int height = doLayout(QRect(0, 0, width, 0), true);
return height;
}
void FlowLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
doLayout(rect, false);
}
QSize FlowLayout::sizeHint() const
{
return minimumSize();
}
QSize FlowLayout::minimumSize() const
{
QSize size;
for (int i = 0; i < _items.size(); i++)
size = size.expandedTo(_items.at(i)->minimumSize());
const QMargins margins = contentsMargins();
size += QSize(margins.left() + margins.right(), margins.top()
+ margins.bottom());
return size;
}
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
{
int left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
int x = effectiveRect.x();
int y = effectiveRect.y();
int lineHeight = 0;
QVector<QVector<FlowLayoutItem>> rows;
for (int i = 0; i < _items.size(); i++) {
QLayoutItem *item = _items.at(i);
const QWidget *wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton,
QSizePolicy::PushButton, Qt::Horizontal);
int spaceY = verticalSpacing();
if (spaceY == -1)
spaceY = wid->style()->layoutSpacing(QSizePolicy::PushButton,
QSizePolicy::PushButton, Qt::Vertical);
int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x();
y = y + lineHeight + spaceY;
nextX = x + item->sizeHint().width() + spaceX;
lineHeight = 0;
rows.append(QVector<FlowLayoutItem>());
}
if (rows.isEmpty())
rows.append(QVector<FlowLayoutItem>());
rows.last().append(FlowLayoutItem(item, x, y));
x = nextX;
lineHeight = qMax(lineHeight, item->sizeHint().height());
}
if (!testOnly) {
for (int i = 0; i < rows.size(); i++) {
const FlowLayoutItem &li = rows.at(i).last();
int width = li.item->sizeHint().width() + li.pos.x()
- effectiveRect.x();
int offset = (effectiveRect.width() - width) / 2;
int height = 0;
for (int j = 0; j < rows.at(i).size(); j++)
height = qMax(rows.at(i).at(j).item->sizeHint().height(), height);
for (int j = 0; j < rows.at(i).size(); j++) {
QLayoutItem *item = rows.at(i).at(j).item;
const QPoint &p = rows.at(i).at(j).pos;
QSize sh(item->sizeHint());
item->setGeometry(QRect(QPoint(p.x() + offset, p.y() + height
- sh.height()), sh));
}
}
}
return y + lineHeight - rect.y() + bottom;
}
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{
QObject *parent = this->parent();
if (!parent)
return -1;
else if (parent->isWidgetType()) {
QWidget *pw = static_cast<QWidget *>(parent);
return pw->style()->pixelMetric(pm, 0, pw);
} else
return static_cast<QLayout *>(parent)->spacing();
}

38
src/GUI/flowlayout.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef FLOWLAYOUT_H
#define FLOWLAYOUT_H
#include <QLayout>
#include <QRect>
#include <QStyle>
class FlowLayout : public QLayout
{
public:
FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1,
int vSpacing = -1);
FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~FlowLayout();
void addItem(QLayoutItem *item);
int horizontalSpacing() const;
int verticalSpacing() const;
Qt::Orientations expandingDirections() const;
bool hasHeightForWidth() const;
int heightForWidth(int) const;
int count() const;
QLayoutItem *itemAt(int index) const;
QSize minimumSize() const;
void setGeometry(const QRect &rect);
QSize sizeHint() const;
QLayoutItem *takeAt(int index);
private:
int doLayout(const QRect &rect, bool testOnly) const;
int smartSpacing(QStyle::PixelMetric pm) const;
QList<QLayoutItem *> _items;
int _hSpace;
int _vSpace;
};
#endif // FLOWLAYOUT_H

View File

@ -27,7 +27,7 @@ GearRatioGraphItem::GearRatioGraphItem(const Graph &graph, GraphType type,
_top = key; _top = key;
} }
QString GearRatioGraphItem::info() const ToolTip GearRatioGraphItem::info() const
{ {
ToolTip tt; ToolTip tt;
QLocale l(QLocale::system()); QLocale l(QLocale::system());
@ -36,5 +36,5 @@ QString GearRatioGraphItem::info() const
tt.insert(tr("Maximum"), l.toString(max(), 'f', 2)); tt.insert(tr("Maximum"), l.toString(max(), 'f', 2));
tt.insert(tr("Most used"), l.toString(top(), 'f', 2)); tt.insert(tr("Most used"), l.toString(top(), 'f', 2));
return tt.toString(); return tt;
} }

View File

@ -15,7 +15,7 @@ public:
qreal top() const {return _top;} qreal top() const {return _top;}
const QMap<qreal, qreal> &map() const {return _map;} const QMap<qreal, qreal> &map() const {return _map;}
QString info() const; ToolTip info() const;
private: private:
QMap<qreal, qreal> _map; QMap<qreal, qreal> _map;

View File

@ -3,13 +3,14 @@
#include <QGraphicsScene> #include <QGraphicsScene>
#include <QGraphicsItem> #include <QGraphicsItem>
#include "tooltip.h"
class GraphicsItem : public QGraphicsItem class GraphicsItem : public QGraphicsItem
{ {
public: public:
GraphicsItem(QGraphicsItem *parent = 0) : QGraphicsItem(parent) {} GraphicsItem(QGraphicsItem *parent = 0) : QGraphicsItem(parent) {}
virtual QString info() const = 0; virtual ToolTip info() const = 0;
int type() const {return QGraphicsItem::UserType + 1;} int type() const {return QGraphicsItem::UserType + 1;}
}; };

View File

@ -16,7 +16,7 @@ public:
const QColor &color, Qt::PenStyle style, QGraphicsItem *parent = 0); const QColor &color, Qt::PenStyle style, QGraphicsItem *parent = 0);
virtual ~GraphItem() {} virtual ~GraphItem() {}
virtual QString info() const = 0; virtual ToolTip info() const = 0;
QPainterPath shape() const {return _shape;} QPainterPath shape() const {return _shape;}
QRectF boundingRect() const {return _shape.boundingRect();} QRectF boundingRect() const {return _shape.boundingRect();}

View File

@ -26,11 +26,12 @@
#include <QStyle> #include <QStyle>
#include <QTabBar> #include <QTabBar>
#include "common/programpaths.h" #include "common/programpaths.h"
#include "common/downloader.h"
#include "data/data.h" #include "data/data.h"
#include "data/poi.h" #include "data/poi.h"
#include "data/demloader.h"
#include "map/maplist.h" #include "map/maplist.h"
#include "map/emptymap.h" #include "map/emptymap.h"
#include "map/downloader.h"
#include "map/crs.h" #include "map/crs.h"
#include "icons.h" #include "icons.h"
#include "keys.h" #include "keys.h"
@ -58,16 +59,18 @@
GUI::GUI() GUI::GUI()
{ {
TreeNode<MapAction*> mapActions; QString activeMap;
TreeNode<POIAction*> poiActions; QStringList disabledPOIs;
_poi = new POI(this); _poi = new POI(this);
_dem = new DEMLoader(ProgramPaths::demDir(true), this);
connect(_dem, &DEMLoader::finished, this, &GUI::demLoaded);
createMapView(); createMapView();
createGraphTabs(); createGraphTabs();
createStatusBar(); createStatusBar();
createActions(mapActions, poiActions); createActions();
createMenus(mapActions, poiActions); createMenus();
createToolBars(); createToolBars();
createBrowser(); createBrowser();
@ -96,11 +99,10 @@ GUI::GUI()
_movingTime = 0; _movingTime = 0;
_lastTab = 0; _lastTab = 0;
_dataDir = QDir::homePath(); readSettings(activeMap, disabledPOIs);
_mapDir = QDir::homePath();
_poiDir = QDir::homePath();
readSettings(); loadInitialMaps(activeMap);
loadInitialPOIs(disabledPOIs);
updateGraphTabs(); updateGraphTabs();
updateStatusBarInfo(); updateStatusBarInfo();
@ -114,21 +116,6 @@ void GUI::createBrowser()
&GUI::updateNavigationActions); &GUI::updateNavigationActions);
} }
TreeNode<MapAction*> GUI::createMapActions()
{
_mapsActionGroup = new QActionGroup(this);
_mapsActionGroup->setExclusive(true);
connect(_mapsActionGroup, &QActionGroup::triggered, this, &GUI::mapChanged);
QString mapDir(ProgramPaths::mapDir());
if (mapDir.isNull())
return TreeNode<MapAction*>();
TreeNode<Map*> maps(MapList::loadMaps(mapDir,
CRS::projection(_options.inputProjection)));
return createMapActionsNode(maps);
}
TreeNode<MapAction*> GUI::createMapActionsNode(const TreeNode<Map*> &node) TreeNode<MapAction*> GUI::createMapActionsNode(const TreeNode<Map*> &node)
{ {
TreeNode<MapAction*> tree(node.name()); TreeNode<MapAction*> tree(node.name());
@ -168,21 +155,6 @@ void GUI::mapInitialized()
} }
} }
TreeNode<POIAction *> GUI::createPOIActions()
{
_poisActionGroup = new QActionGroup(this);
_poisActionGroup->setExclusive(false);
connect(_poisActionGroup, &QActionGroup::triggered, this,
&GUI::poiFileChecked);
TreeNode<QString> poiFiles;
QString poiDir(ProgramPaths::poiDir());
if (!poiDir.isNull())
poiFiles = _poi->loadDir(poiDir);
return createPOIActionsNode(poiFiles);
}
TreeNode<POIAction *> GUI::createPOIActionsNode(const TreeNode<QString> &node) TreeNode<POIAction *> GUI::createPOIActionsNode(const TreeNode<QString> &node)
{ {
TreeNode<POIAction*> tree(node.name()); TreeNode<POIAction*> tree(node.name());
@ -195,8 +167,7 @@ TreeNode<POIAction *> GUI::createPOIActionsNode(const TreeNode<QString> &node)
return tree; return tree;
} }
void GUI::createActions(TreeNode<MapAction*> &mapActions, void GUI::createActions()
TreeNode<POIAction*> &poiActions)
{ {
QActionGroup *ag; QActionGroup *ag;
@ -274,7 +245,10 @@ void GUI::createActions(TreeNode<MapAction*> &mapActions,
addAction(_statisticsAction); addAction(_statisticsAction);
// POI actions // POI actions
poiActions = createPOIActions(); _poisActionGroup = new QActionGroup(this);
_poisActionGroup->setExclusive(false);
connect(_poisActionGroup, &QActionGroup::triggered, this,
&GUI::poiFileChecked);
_openPOIAction = new QAction(QIcon(OPEN_FILE_ICON), tr("Load POI file..."), _openPOIAction = new QAction(QIcon(OPEN_FILE_ICON), tr("Load POI file..."),
this); this);
_openPOIAction->setMenuRole(QAction::NoRole); _openPOIAction->setMenuRole(QAction::NoRole);
@ -282,12 +256,12 @@ void GUI::createActions(TreeNode<MapAction*> &mapActions,
QOverload<>::of(&GUI::openPOIFile)); QOverload<>::of(&GUI::openPOIFile));
_selectAllPOIAction = new QAction(tr("Select all files"), this); _selectAllPOIAction = new QAction(tr("Select all files"), this);
_selectAllPOIAction->setMenuRole(QAction::NoRole); _selectAllPOIAction->setMenuRole(QAction::NoRole);
_selectAllPOIAction->setEnabled(!_poisActionGroup->actions().isEmpty()); _selectAllPOIAction->setEnabled(false);
connect(_selectAllPOIAction, &QAction::triggered, this, connect(_selectAllPOIAction, &QAction::triggered, this,
&GUI::selectAllPOIs); &GUI::selectAllPOIs);
_unselectAllPOIAction = new QAction(tr("Unselect all files"), this); _unselectAllPOIAction = new QAction(tr("Unselect all files"), this);
_unselectAllPOIAction->setMenuRole(QAction::NoRole); _unselectAllPOIAction->setMenuRole(QAction::NoRole);
_unselectAllPOIAction->setEnabled(_selectAllPOIAction->isEnabled()); _unselectAllPOIAction->setEnabled(false);
connect(_unselectAllPOIAction, &QAction::triggered, this, connect(_unselectAllPOIAction, &QAction::triggered, this,
&GUI::unselectAllPOIs); &GUI::unselectAllPOIs);
_overlapPOIAction = new QAction(tr("Overlap POIs"), this); _overlapPOIAction = new QAction(tr("Overlap POIs"), this);
@ -308,7 +282,9 @@ void GUI::createActions(TreeNode<MapAction*> &mapActions,
addAction(_showPOIAction); addAction(_showPOIAction);
// Map actions // Map actions
mapActions = createMapActions(); _mapsActionGroup = new QActionGroup(this);
_mapsActionGroup->setExclusive(true);
connect(_mapsActionGroup, &QActionGroup::triggered, this, &GUI::mapChanged);
_showMapAction = new QAction(QIcon(SHOW_MAP_ICON), tr("Show map"), _showMapAction = new QAction(QIcon(SHOW_MAP_ICON), tr("Show map"),
this); this);
_showMapAction->setEnabled(false); _showMapAction->setEnabled(false);
@ -352,6 +328,7 @@ void GUI::createActions(TreeNode<MapAction*> &mapActions,
_showTracksAction = new QAction(tr("Show tracks"), this); _showTracksAction = new QAction(tr("Show tracks"), this);
_showTracksAction->setMenuRole(QAction::NoRole); _showTracksAction->setMenuRole(QAction::NoRole);
_showTracksAction->setCheckable(true); _showTracksAction->setCheckable(true);
_showTracksAction->setShortcut(SHOW_TRACKS_SHORTCUT);
connect(_showTracksAction, &QAction::triggered, this, &GUI::showTracks); connect(_showTracksAction, &QAction::triggered, this, &GUI::showTracks);
_showRoutesAction = new QAction(tr("Show routes"), this); _showRoutesAction = new QAction(tr("Show routes"), this);
_showRoutesAction->setMenuRole(QAction::NoRole); _showRoutesAction->setMenuRole(QAction::NoRole);
@ -360,13 +337,12 @@ void GUI::createActions(TreeNode<MapAction*> &mapActions,
_showWaypointsAction = new QAction(tr("Show waypoints"), this); _showWaypointsAction = new QAction(tr("Show waypoints"), this);
_showWaypointsAction->setMenuRole(QAction::NoRole); _showWaypointsAction->setMenuRole(QAction::NoRole);
_showWaypointsAction->setCheckable(true); _showWaypointsAction->setCheckable(true);
connect(_showWaypointsAction, &QAction::triggered, _mapView, connect(_showWaypointsAction, &QAction::triggered, this,
&MapView::showWaypoints); &GUI::showWaypoints);
_showAreasAction = new QAction(tr("Show areas"), this); _showAreasAction = new QAction(tr("Show areas"), this);
_showAreasAction->setMenuRole(QAction::NoRole); _showAreasAction->setMenuRole(QAction::NoRole);
_showAreasAction->setCheckable(true); _showAreasAction->setCheckable(true);
connect(_showAreasAction, &QAction::triggered, _mapView, connect(_showAreasAction, &QAction::triggered, this, &GUI::showAreas);
&MapView::showAreas);
_showWaypointLabelsAction = new QAction(tr("Waypoint labels"), this); _showWaypointLabelsAction = new QAction(tr("Waypoint labels"), this);
_showWaypointLabelsAction->setMenuRole(QAction::NoRole); _showWaypointLabelsAction->setMenuRole(QAction::NoRole);
_showWaypointLabelsAction->setCheckable(true); _showWaypointLabelsAction->setCheckable(true);
@ -402,6 +378,16 @@ void GUI::createActions(TreeNode<MapAction*> &mapActions,
_showMarkerCoordinatesAction->setCheckable(true); _showMarkerCoordinatesAction->setCheckable(true);
_showMarkerCoordinatesAction->setActionGroup(markerInfoGroup); _showMarkerCoordinatesAction->setActionGroup(markerInfoGroup);
// DEM actions
_downloadDEMAction = new QAction(tr("Download DEM data"), this);
_downloadDEMAction->setMenuRole(QAction::NoRole);
_downloadDEMAction->setEnabled(false);
_downloadDEMAction->setShortcut(DOWNLOAD_DEM_SHORTCUT);
connect(_downloadDEMAction, &QAction::triggered, this, &GUI::downloadDEM);
_showDEMTilesAction = new QAction(tr("Show local DEM tiles"));
_showDEMTilesAction->setMenuRole(QAction::NoRole);
connect(_showDEMTilesAction, &QAction::triggered, this, &GUI::showDEMTiles);
// Graph actions // Graph actions
_showGraphsAction = new QAction(QIcon(SHOW_GRAPHS_ICON), tr("Show graphs"), _showGraphsAction = new QAction(QIcon(SHOW_GRAPHS_ICON), tr("Show graphs"),
this); this);
@ -522,32 +508,33 @@ void GUI::createActions(TreeNode<MapAction*> &mapActions,
connect(_firstAction, &QAction::triggered, this, &GUI::first); connect(_firstAction, &QAction::triggered, this, &GUI::first);
} }
void GUI::createMapNodeMenu(const TreeNode<MapAction*> &node, QMenu *menu) void GUI::createMapNodeMenu(const TreeNode<MapAction*> &node, QMenu *menu,
QAction *action)
{ {
for (int i = 0; i < node.childs().size(); i++) { for (int i = 0; i < node.childs().size(); i++) {
QMenu *cm = new QMenu(node.childs().at(i).name(), menu); QMenu *cm = new QMenu(node.childs().at(i).name(), menu);
menu->addMenu(cm); menu->insertMenu(action, cm);
createMapNodeMenu(node.childs().at(i), cm); createMapNodeMenu(node.childs().at(i), cm);
} }
for (int i = 0; i < node.items().size(); i++) for (int i = 0; i < node.items().size(); i++)
menu->addAction(node.items().at(i)); menu->insertAction(action, node.items().at(i));
} }
void GUI::createPOINodeMenu(const TreeNode<POIAction*> &node, QMenu *menu) void GUI::createPOINodeMenu(const TreeNode<POIAction*> &node, QMenu *menu,
QAction *action)
{ {
for (int i = 0; i < node.childs().size(); i++) { for (int i = 0; i < node.childs().size(); i++) {
QMenu *cm = new QMenu(node.childs().at(i).name(), menu); QMenu *cm = new QMenu(node.childs().at(i).name(), menu);
menu->addMenu(cm); menu->insertMenu(action, cm);
createPOINodeMenu(node.childs().at(i), cm); createPOINodeMenu(node.childs().at(i), cm);
} }
for (int i = 0; i < node.items().size(); i++) for (int i = 0; i < node.items().size(); i++)
menu->addAction(node.items().at(i)); menu->insertAction(action, node.items().at(i));
} }
void GUI::createMenus(const TreeNode<MapAction*> &mapActions, void GUI::createMenus()
const TreeNode<POIAction*> &poiActions)
{ {
QMenu *fileMenu = menuBar()->addMenu(tr("&File")); QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(_openFileAction); fileMenu->addAction(_openFileAction);
@ -566,7 +553,6 @@ void GUI::createMenus(const TreeNode<MapAction*> &mapActions,
#endif // Q_OS_MAC #endif // Q_OS_MAC
_mapMenu = menuBar()->addMenu(tr("&Map")); _mapMenu = menuBar()->addMenu(tr("&Map"));
createMapNodeMenu(mapActions, _mapMenu);
_mapsEnd = _mapMenu->addSeparator(); _mapsEnd = _mapMenu->addSeparator();
_mapMenu->addAction(_loadMapAction); _mapMenu->addAction(_loadMapAction);
_mapMenu->addAction(_loadMapDirAction); _mapMenu->addAction(_loadMapDirAction);
@ -585,18 +571,6 @@ void GUI::createMenus(const TreeNode<MapAction*> &mapActions,
graphMenu->addSeparator(); graphMenu->addSeparator();
graphMenu->addAction(_showGraphsAction); graphMenu->addAction(_showGraphsAction);
_poiMenu = menuBar()->addMenu(tr("&POI"));
createPOINodeMenu(poiActions, _poiMenu);
_poisEnd = _poiMenu->addSeparator();
_poiMenu->addAction(_openPOIAction);
_poiMenu->addAction(_selectAllPOIAction);
_poiMenu->addAction(_unselectAllPOIAction);
_poiMenu->addSeparator();
_poiMenu->addAction(_showPOILabelsAction);
_poiMenu->addAction(_overlapPOIAction);
_poiMenu->addSeparator();
_poiMenu->addAction(_showPOIAction);
QMenu *dataMenu = menuBar()->addMenu(tr("&Data")); QMenu *dataMenu = menuBar()->addMenu(tr("&Data"));
dataMenu->addAction(_showWaypointLabelsAction); dataMenu->addAction(_showWaypointLabelsAction);
dataMenu->addAction(_showRouteWaypointsAction); dataMenu->addAction(_showRouteWaypointsAction);
@ -612,6 +586,21 @@ void GUI::createMenus(const TreeNode<MapAction*> &mapActions,
dataMenu->addAction(_showAreasAction); dataMenu->addAction(_showAreasAction);
dataMenu->addAction(_showWaypointsAction); dataMenu->addAction(_showWaypointsAction);
_poiMenu = menuBar()->addMenu(tr("&POI"));
_poisEnd = _poiMenu->addSeparator();
_poiMenu->addAction(_openPOIAction);
_poiMenu->addAction(_selectAllPOIAction);
_poiMenu->addAction(_unselectAllPOIAction);
_poiMenu->addSeparator();
_poiMenu->addAction(_showPOILabelsAction);
_poiMenu->addAction(_overlapPOIAction);
_poiMenu->addSeparator();
_poiMenu->addAction(_showPOIAction);
QMenu *demMenu = menuBar()->addMenu(tr("DEM"));
demMenu->addAction(_showDEMTilesAction);
demMenu->addAction(_downloadDEMAction);
QMenu *settingsMenu = menuBar()->addMenu(tr("&Settings")); QMenu *settingsMenu = menuBar()->addMenu(tr("&Settings"));
QMenu *timeMenu = settingsMenu->addMenu(tr("Time")); QMenu *timeMenu = settingsMenu->addMenu(tr("Time"));
timeMenu->addAction(_totalTimeAction); timeMenu->addAction(_totalTimeAction);
@ -652,7 +641,9 @@ void GUI::createToolBars()
_fileToolBar->addAction(_openFileAction); _fileToolBar->addAction(_openFileAction);
_fileToolBar->addAction(_reloadFileAction); _fileToolBar->addAction(_reloadFileAction);
_fileToolBar->addAction(_closeFileAction); _fileToolBar->addAction(_closeFileAction);
#ifndef Q_OS_MAC
_fileToolBar->addAction(_printFileAction); _fileToolBar->addAction(_printFileAction);
#endif // Q_OS_MAC
_showToolBar = addToolBar(tr("Show")); _showToolBar = addToolBar(tr("Show"));
_showToolBar->setObjectName("Show"); _showToolBar->setObjectName("Show");
@ -854,6 +845,7 @@ bool GUI::loadFile(const QString &fileName, bool silent)
updateStatusBarInfo(); updateStatusBarInfo();
updateWindowTitle(); updateWindowTitle();
updateGraphTabs(); updateGraphTabs();
updateDEMDownloadAction();
QString error = tr("Error loading data file:") + "\n\n" QString error = tr("Error loading data file:") + "\n\n"
+ fileName + "\n\n" + data.errorString(); + fileName + "\n\n" + data.errorString();
@ -919,6 +911,8 @@ void GUI::loadData(const Data &data)
pi->setMarkerPosition(gt->sliderPosition()); pi->setMarkerPosition(gt->sliderPosition());
} }
} }
updateDEMDownloadAction();
} }
void GUI::openPOIFile() void GUI::openPOIFile()
@ -1052,6 +1046,15 @@ void GUI::openOptions()
if (options.poiRadius != _options.poiRadius) if (options.poiRadius != _options.poiRadius)
_poi->setRadius(options.poiRadius); _poi->setRadius(options.poiRadius);
if (options.demURL != _options.demURL)
_dem->setUrl(options.demURL);
if (options.demAuthorization != _options.demAuthorization
|| options.demUsername != _options.demUsername
|| options.demPassword != _options.demPassword)
_dem->setAuthorization(options.demAuthorization
? Authorization(options.demUsername, options.demPassword)
: Authorization());
if (options.pixmapCache != _options.pixmapCache) if (options.pixmapCache != _options.pixmapCache)
QPixmapCache::setCacheLimit(options.pixmapCache * 1024); QPixmapCache::setCacheLimit(options.pixmapCache * 1024);
@ -1060,10 +1063,19 @@ void GUI::openOptions()
if (options.enableHTTP2 != _options.enableHTTP2) if (options.enableHTTP2 != _options.enableHTTP2)
Downloader::enableHTTP2(options.enableHTTP2); Downloader::enableHTTP2(options.enableHTTP2);
if (options.dataPath != _options.dataPath)
_dataDir = options.dataPath;
if (options.mapsPath != _options.mapsPath)
_mapDir = options.mapsPath;
if (options.poiPath != _options.poiPath)
_poiDir = options.poiPath;
if (reload) if (reload)
reloadFiles(); reloadFiles();
_options = options; _options = options;
updateDEMDownloadAction();
} }
void GUI::printFile() void GUI::printFile()
@ -1357,6 +1369,7 @@ void GUI::reloadFiles()
_fileActionGroup->setEnabled(false); _fileActionGroup->setEnabled(false);
else else
_browser->setCurrent(_files.last()); _browser->setCurrent(_files.last());
updateDEMDownloadAction();
} }
void GUI::closeFiles() void GUI::closeFiles()
@ -1389,6 +1402,7 @@ void GUI::closeAll()
updateStatusBarInfo(); updateStatusBarInfo();
updateWindowTitle(); updateWindowTitle();
updateGraphTabs(); updateGraphTabs();
updateDEMDownloadAction();
} }
void GUI::showGraphs(bool show) void GUI::showGraphs(bool show)
@ -1448,6 +1462,7 @@ void GUI::showTracks(bool show)
updateStatusBarInfo(); updateStatusBarInfo();
updateGraphTabs(); updateGraphTabs();
updateDEMDownloadAction();
} }
void GUI::showRoutes(bool show) void GUI::showRoutes(bool show)
@ -1459,6 +1474,19 @@ void GUI::showRoutes(bool show)
updateStatusBarInfo(); updateStatusBarInfo();
updateGraphTabs(); updateGraphTabs();
updateDEMDownloadAction();
}
void GUI::showWaypoints(bool show)
{
_mapView->showWaypoints(show);
updateDEMDownloadAction();
}
void GUI::showAreas(bool show)
{
_mapView->showAreas(show);
updateDEMDownloadAction();
} }
void GUI::showGraphGrids(bool show) void GUI::showGraphGrids(bool show)
@ -1635,9 +1663,9 @@ void GUI::loadMapDirNode(const TreeNode<Map *> &node, QList<MapAction*> &actions
actions.append(a); actions.append(a);
} else } else
connect(a, &MapAction::loaded, this, &GUI::mapLoadedDir); connect(a, &MapAction::loaded, this, &GUI::mapLoadedDir);
}
_areaCount++; _areaCount++;
}
} else { } else {
map = a->data().value<Map*>(); map = a->data().value<Map*>();
if (map->isReady()) if (map->isReady())
@ -1677,10 +1705,50 @@ void GUI::loadMapDir()
void GUI::clearMapCache() void GUI::clearMapCache()
{ {
if (QMessageBox::question(this, APP_NAME, if (QMessageBox::question(this, APP_NAME,
tr("Clear the map tile cache?")) == QMessageBox::Yes) tr("Clear \"%1\" tile cache?").arg(_map->name())) == QMessageBox::Yes)
_mapView->clearMapCache(); _mapView->clearMapCache();
} }
void GUI::downloadDEM()
{
RectC br(_mapView->boundingRect());
_demRects.append(br);
if (!_dem->loadTiles(br) && _demRects.size() == 1)
demLoaded();
}
void GUI::demLoaded()
{
for (int i = 0; i < _demRects.size(); i++) {
if (!_dem->checkTiles(_demRects.at(i))) {
QMessageBox::warning(this, APP_NAME,
tr("Could not download all required DEM files."));
break;
}
}
DEM::clearCache();
_demRects.clear();
reloadFiles();
}
void GUI::showDEMTiles()
{
QList<Area> tiles(DEM::tiles());
if (tiles.isEmpty()) {
QMessageBox::information(this, APP_NAME, tr("No local DEM tiles found."));
} else {
_mapView->loadDEMs(tiles);
_areaCount += tiles.size();
_fileActionGroup->setEnabled(true);
_reloadFileAction->setEnabled(false);
}
}
void GUI::updateStatusBarInfo() void GUI::updateStatusBarInfo()
{ {
if (_files.count() == 0) if (_files.count() == 0)
@ -1836,6 +1904,12 @@ bool GUI::updateGraphTabs()
return (hidden != _graphTabWidget->isHidden()); return (hidden != _graphTabWidget->isHidden());
} }
void GUI::updateDEMDownloadAction()
{
_downloadDEMAction->setEnabled(!_dem->url().isEmpty()
&& !_dem->checkTiles(_mapView->boundingRect()));
}
void GUI::setTimeType(TimeType type) void GUI::setTimeType(TimeType type)
{ {
for (int i = 0; i <_tabs.count(); i++) for (int i = 0; i <_tabs.count(); i++)
@ -2229,6 +2303,14 @@ void GUI::writeSettings()
settings.setValue(USE_SEGMENTS_SETTING, _options.useSegments); settings.setValue(USE_SEGMENTS_SETTING, _options.useSegments);
if (_options.poiRadius != POI_RADIUS_DEFAULT) if (_options.poiRadius != POI_RADIUS_DEFAULT)
settings.setValue(POI_RADIUS_SETTING, _options.poiRadius); settings.setValue(POI_RADIUS_SETTING, _options.poiRadius);
if (_options.demURL != DEM_URL_DEFAULT)
settings.setValue(DEM_URL_SETTING, _options.demURL);
if (_options.demAuthorization != DEM_AUTH_DEFAULT)
settings.setValue(DEM_AUTH_SETTING, _options.demAuthorization);
if (_options.demUsername != DEM_USERNAME_DEFAULT)
settings.setValue(DEM_USERNAME_SETTING, _options.demUsername);
if (_options.demPassword != DEM_PASSWORD_DEFAULT)
settings.setValue(DEM_PASSWORD_SETTING, _options.demPassword);
if (_options.useOpenGL != USE_OPENGL_DEFAULT) if (_options.useOpenGL != USE_OPENGL_DEFAULT)
settings.setValue(USE_OPENGL_SETTING, _options.useOpenGL); settings.setValue(USE_OPENGL_SETTING, _options.useOpenGL);
if (_options.enableHTTP2 != ENABLE_HTTP2_DEFAULT) if (_options.enableHTTP2 != ENABLE_HTTP2_DEFAULT)
@ -2262,10 +2344,17 @@ void GUI::writeSettings()
settings.setValue(INPUT_PROJECTION_SETTING, _options.inputProjection); settings.setValue(INPUT_PROJECTION_SETTING, _options.inputProjection);
if (_options.hidpiMap != HIDPI_MAP_DEFAULT) if (_options.hidpiMap != HIDPI_MAP_DEFAULT)
settings.setValue(HIDPI_MAP_SETTING, _options.hidpiMap); settings.setValue(HIDPI_MAP_SETTING, _options.hidpiMap);
if (_options.dataPath != DATA_PATH_DEFAULT)
settings.setValue(DATA_PATH_SETTING, _options.dataPath);
if (_options.mapsPath != MAPS_PATH_DEFAULT)
settings.setValue(MAPS_PATH_SETTING, _options.mapsPath);
if (_options.poiPath != POI_PATH_DEFAULT)
settings.setValue(POI_PATH_SETTING, _options.poiPath);
settings.endGroup(); settings.endGroup();
} }
void GUI::readSettings() void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
{ {
int value; int value;
QSettings settings(qApp->applicationName(), qApp->applicationName()); QSettings settings(qApp->applicationName(), qApp->applicationName());
@ -2308,17 +2397,12 @@ void GUI::readSettings()
_showMapAction->setChecked(true); _showMapAction->setChecked(true);
else else
_mapView->showMap(false); _mapView->showMap(false);
QAction *ma = mapAction(settings.value(CURRENT_MAP_SETTING).toString());
if (ma) {
ma->trigger();
_showMapAction->setEnabled(true);
_clearMapCacheAction->setEnabled(true);
}
if (settings.value(SHOW_COORDINATES_SETTING, SHOW_COORDINATES_DEFAULT) if (settings.value(SHOW_COORDINATES_SETTING, SHOW_COORDINATES_DEFAULT)
.toBool()) { .toBool()) {
_showCoordinatesAction->setChecked(true); _showCoordinatesAction->setChecked(true);
_mapView->showCoordinates(true); _mapView->showCoordinates(true);
} }
activeMap = settings.value(CURRENT_MAP_SETTING).toString();
settings.endGroup(); settings.endGroup();
settings.beginGroup(GRAPH_SETTINGS_GROUP); settings.beginGroup(GRAPH_SETTINGS_GROUP);
@ -2358,18 +2442,11 @@ void GUI::readSettings()
_showPOIAction->setChecked(true); _showPOIAction->setChecked(true);
else else
_mapView->showPOI(false); _mapView->showPOI(false);
QList<QAction*> poiActions(_poisActionGroup->actions());
for (int i = 0; i < poiActions.count(); i++)
poiActions.at(i)->setChecked(true);
int size = settings.beginReadArray(DISABLED_POI_FILE_SETTINGS_PREFIX); int size = settings.beginReadArray(DISABLED_POI_FILE_SETTINGS_PREFIX);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
settings.setArrayIndex(i); settings.setArrayIndex(i);
QString file(settings.value(DISABLED_POI_FILE_SETTING).toString()); disabledPOIs.append(settings.value(DISABLED_POI_FILE_SETTING).toString());
if (_poi->enableFile(file, false)) {
for (int j = 0; j < poiActions.size(); j++)
if (poiActions.at(j)->data().toString() == file)
poiActions.at(j)->setChecked(false);
}
} }
settings.endArray(); settings.endArray();
settings.endGroup(); settings.endGroup();
@ -2533,6 +2610,13 @@ void GUI::readSettings()
PAUSE_INTERVAL_DEFAULT).toInt(); PAUSE_INTERVAL_DEFAULT).toInt();
_options.poiRadius = settings.value(POI_RADIUS_SETTING, POI_RADIUS_DEFAULT) _options.poiRadius = settings.value(POI_RADIUS_SETTING, POI_RADIUS_DEFAULT)
.toInt(); .toInt();
_options.demURL = settings.value(DEM_URL_SETTING, DEM_URL_DEFAULT).toString();
_options.demAuthorization = settings.value(DEM_AUTH_SETTING,
DEM_AUTH_DEFAULT).toBool();
_options.demUsername = settings.value(DEM_USERNAME_SETTING,
DEM_USERNAME_DEFAULT).toString();
_options.demPassword = settings.value(DEM_PASSWORD_SETTING,
DEM_PASSWORD_DEFAULT).toString();
_options.useOpenGL = settings.value(USE_OPENGL_SETTING, USE_OPENGL_DEFAULT) _options.useOpenGL = settings.value(USE_OPENGL_SETTING, USE_OPENGL_DEFAULT)
.toBool(); .toBool();
_options.enableHTTP2 = settings.value(ENABLE_HTTP2_SETTING, _options.enableHTTP2 = settings.value(ENABLE_HTTP2_SETTING,
@ -2563,8 +2647,14 @@ void GUI::readSettings()
OUTPUT_PROJECTION_DEFAULT).toInt(); OUTPUT_PROJECTION_DEFAULT).toInt();
_options.inputProjection = settings.value(INPUT_PROJECTION_SETTING, _options.inputProjection = settings.value(INPUT_PROJECTION_SETTING,
INPUT_PROJECTION_DEFAULT).toInt(); INPUT_PROJECTION_DEFAULT).toInt();
_options.hidpiMap = settings.value(HIDPI_MAP_SETTING, HIDPI_MAP_SETTING) _options.hidpiMap = settings.value(HIDPI_MAP_SETTING, HIDPI_MAP_DEFAULT)
.toBool(); .toBool();
_options.dataPath = settings.value(DATA_PATH_SETTING, DATA_PATH_DEFAULT)
.toString();
_options.mapsPath = settings.value(MAPS_PATH_SETTING, MAPS_PATH_DEFAULT)
.toString();
_options.poiPath = settings.value(POI_PATH_SETTING, POI_PATH_DEFAULT)
.toString();
_mapView->setPalette(_options.palette); _mapView->setPalette(_options.palette);
_mapView->setMapOpacity(_options.mapOpacity); _mapView->setMapOpacity(_options.mapOpacity);
@ -2619,13 +2709,72 @@ void GUI::readSettings()
Waypoint::useDEM(_options.dataUseDEM); Waypoint::useDEM(_options.dataUseDEM);
Waypoint::showSecondaryElevation(_options.showSecondaryElevation); Waypoint::showSecondaryElevation(_options.showSecondaryElevation);
_poi->setRadius(_options.poiRadius); Downloader::enableHTTP2(_options.enableHTTP2);
Downloader::setTimeout(_options.connectionTimeout);
QPixmapCache::setCacheLimit(_options.pixmapCache * 1024); QPixmapCache::setCacheLimit(_options.pixmapCache * 1024);
_poi->setRadius(_options.poiRadius);
_dem->setUrl(_options.demURL);
if (_options.demAuthorization)
_dem->setAuthorization(Authorization(_options.demUsername,
_options.demPassword));
_dataDir = _options.dataPath;
_mapDir = _options.mapsPath;
_poiDir = _options.poiPath;
settings.endGroup(); settings.endGroup();
} }
void GUI::loadInitialMaps(const QString &selected)
{
// Load the maps
QString mapDir(ProgramPaths::mapDir());
if (mapDir.isNull())
return;
TreeNode<Map*> maps(MapList::loadMaps(mapDir,
CRS::projection(_options.inputProjection)));
createMapNodeMenu(createMapActionsNode(maps), _mapMenu, _mapsEnd);
// Select the active map according to the user settings
QAction *ma = mapAction(selected);
if (ma) {
ma->trigger();
_showMapAction->setEnabled(true);
_clearMapCacheAction->setEnabled(true);
}
}
void GUI::loadInitialPOIs(const QStringList &disabled)
{
// Load the POI files
QString poiDir(ProgramPaths::poiDir());
if (poiDir.isNull())
return;
TreeNode<QString> poiFiles(_poi->loadDir(poiDir));
createPOINodeMenu(createPOIActionsNode(poiFiles), _poiMenu, _poisEnd);
// Enable/disable the files according to the user settings
QList<QAction*> poiActions(_poisActionGroup->actions());
for (int i = 0; i < poiActions.count(); i++)
poiActions.at(i)->setChecked(true);
for (int i = 0; i < disabled.size(); i++) {
const QString &file = disabled.at(i);
if (_poi->enableFile(file, false)) {
for (int j = 0; j < poiActions.size(); j++)
if (poiActions.at(j)->data().toString() == file)
poiActions.at(j)->setChecked(false);
}
}
_selectAllPOIAction->setEnabled(!poiActions.isEmpty());
_unselectAllPOIAction->setEnabled(!poiActions.isEmpty());
}
QAction *GUI::mapAction(const QString &name) QAction *GUI::mapAction(const QString &name)
{ {
QList<QAction *> maps(_mapsActionGroup->actions()); QList<QAction *> maps(_mapsActionGroup->actions());

View File

@ -7,6 +7,7 @@
#include <QDate> #include <QDate>
#include <QPrinter> #include <QPrinter>
#include "common/treenode.h" #include "common/treenode.h"
#include "common/rectc.h"
#include "data/graph.h" #include "data/graph.h"
#include "units.h" #include "units.h"
#include "timetype.h" #include "timetype.h"
@ -32,6 +33,7 @@ class QScreen;
class MapAction; class MapAction;
class POIAction; class POIAction;
class Data; class Data;
class DEMLoader;
class GUI : public QMainWindow class GUI : public QMainWindow
{ {
@ -65,12 +67,16 @@ private slots:
void showFullscreen(bool show); void showFullscreen(bool show);
void showTracks(bool show); void showTracks(bool show);
void showRoutes(bool show); void showRoutes(bool show);
void showAreas(bool show);
void showWaypoints(bool show);
void loadMap(); void loadMap();
void loadMapDir(); void loadMapDir();
void nextMap(); void nextMap();
void prevMap(); void prevMap();
void openOptions(); void openOptions();
void clearMapCache(); void clearMapCache();
void downloadDEM();
void showDEMTiles();
void mapChanged(QAction *action); void mapChanged(QAction *action);
void graphChanged(int); void graphChanged(int);
@ -102,6 +108,8 @@ private slots:
void mapLoadedDir(); void mapLoadedDir();
void mapInitialized(); void mapInitialized();
void demLoaded();
private: private:
typedef QPair<QDateTime, QDateTime> DateTimeRange; typedef QPair<QDateTime, QDateTime> DateTimeRange;
@ -112,16 +120,14 @@ private:
void plotGraphsPage(QPainter *painter, const QRectF &rect, qreal ratio); void plotGraphsPage(QPainter *painter, const QRectF &rect, qreal ratio);
qreal graphPlotHeight(const QRectF &rect, qreal ratio); qreal graphPlotHeight(const QRectF &rect, qreal ratio);
TreeNode<POIAction*> createPOIActions();
TreeNode<POIAction*> createPOIActionsNode(const TreeNode<QString> &node); TreeNode<POIAction*> createPOIActionsNode(const TreeNode<QString> &node);
TreeNode<MapAction*> createMapActions();
TreeNode<MapAction*> createMapActionsNode(const TreeNode<Map*> &node); TreeNode<MapAction*> createMapActionsNode(const TreeNode<Map*> &node);
void createActions(TreeNode<MapAction*> &mapActions, void createMapNodeMenu(const TreeNode<MapAction*> &node, QMenu *menu,
TreeNode<POIAction*> &poiActions); QAction *action = 0);
void createMapNodeMenu(const TreeNode<MapAction*> &node, QMenu *menu); void createPOINodeMenu(const TreeNode<POIAction*> &node, QMenu *menu,
void createPOINodeMenu(const TreeNode<POIAction*> &node, QMenu *menu); QAction *action = 0);
void createMenus(const TreeNode<MapAction*> &mapActions, void createActions();
const TreeNode<POIAction*> &poiActions); void createMenus();
void createToolBars(); void createToolBars();
void createStatusBar(); void createStatusBar();
void createMapView(); void createMapView();
@ -138,6 +144,7 @@ private:
void updateStatusBarInfo(); void updateStatusBarInfo();
void updateWindowTitle(); void updateWindowTitle();
bool updateGraphTabs(); bool updateGraphTabs();
void updateDEMDownloadAction();
TimeType timeType() const; TimeType timeType() const;
Units units() const; Units units() const;
@ -150,9 +157,12 @@ private:
qreal time() const; qreal time() const;
qreal movingTime() const; qreal movingTime() const;
QAction *mapAction(const QString &name); QAction *mapAction(const QString &name);
void readSettings(); void readSettings(QString &activeMap, QStringList &disabledPOIs);
void writeSettings(); void writeSettings();
void loadInitialMaps(const QString &selected);
void loadInitialPOIs(const QStringList &disabled);
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event);
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
void dragEnterEvent(QDragEnterEvent *event); void dragEnterEvent(QDragEnterEvent *event);
@ -224,6 +234,8 @@ private:
QAction *_showTicksAction; QAction *_showTicksAction;
QAction *_showCoordinatesAction; QAction *_showCoordinatesAction;
QAction *_openOptionsAction; QAction *_openOptionsAction;
QAction *_downloadDEMAction;
QAction *_showDEMTilesAction;
QAction *_mapsEnd; QAction *_mapsEnd;
QAction *_poisEnd; QAction *_poisEnd;
@ -239,6 +251,7 @@ private:
POI *_poi; POI *_poi;
Map *_map; Map *_map;
DEMLoader *_dem;
FileBrowser *_browser; FileBrowser *_browser;
QList<QString> _files; QList<QString> _files;
@ -260,6 +273,8 @@ private:
QString _dataDir, _mapDir, _poiDir; QString _dataDir, _mapDir, _poiDir;
Units _units; Units _units;
QList<RectC> _demRects;
}; };
#endif // GUI_H #endif // GUI_H

View File

@ -9,7 +9,7 @@ HeartRateGraphItem::HeartRateGraphItem(const Graph &graph, GraphType type,
{ {
} }
QString HeartRateGraphItem::info() const ToolTip HeartRateGraphItem::info() const
{ {
ToolTip tt; ToolTip tt;
QLocale l(QLocale::system()); QLocale l(QLocale::system());
@ -19,5 +19,5 @@ QString HeartRateGraphItem::info() const
tt.insert(tr("Average"), l.toString(avg(), 'f', 0) tt.insert(tr("Average"), l.toString(avg(), 'f', 0)
+ UNIT_SPACE + tr("bpm")); + UNIT_SPACE + tr("bpm"));
return tt.toString(); return tt;
} }

View File

@ -11,7 +11,7 @@ public:
HeartRateGraphItem(const Graph &graph, GraphType type, int width, HeartRateGraphItem(const Graph &graph, GraphType type, int width,
const QColor &color, QGraphicsItem *parent = 0); const QColor &color, QGraphicsItem *parent = 0);
QString info() const; ToolTip info() const;
}; };
#endif // HEARTRATEGRAPHITEM_H #endif // HEARTRATEGRAPHITEM_H

View File

@ -26,5 +26,9 @@
#define PRINT_EXPORT_ICON ":/document-print_32.png" #define PRINT_EXPORT_ICON ":/document-print_32.png"
#define DATA_ICON ":/view-filter.png" #define DATA_ICON ":/view-filter.png"
#define MAPS_ICON ":/applications-internet_32.png" #define MAPS_ICON ":/applications-internet_32.png"
#define DEM_ICON ":/view-grid.png"
#define SHOW_PWD_ICON ":/document-encrypt.png"
#define HIDE_PWD_ICON ":/document-decrypt.png"
#endif /* ICONS_H */ #endif /* ICONS_H */

View File

@ -56,17 +56,25 @@ void InfoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
//painter->drawRect(boundingRect()); //painter->drawRect(boundingRect());
} }
int InfoItem::indexOf(const QString &key) const
{
for (int i = 0; i < _list.size(); i++)
if (_list.at(i).key() == key)
return i;
return -1;
}
void InfoItem::insert(const QString &key, const QString &value) void InfoItem::insert(const QString &key, const QString &value)
{ {
KV<QString, QString> kv(key, value);
int i; int i;
prepareGeometryChange(); prepareGeometryChange();
if ((i = _list.indexOf(kv)) < 0) if ((i = indexOf(key)) < 0)
_list.append(kv); _list.append(KV<QString, QString>(key, value));
else else
_list[i] = kv; _list[i] = KV<QString, QString>(key, value);
updateBoundingRect(); updateBoundingRect();
update(); update();

View File

@ -22,6 +22,7 @@ public:
private: private:
void updateBoundingRect(); void updateBoundingRect();
int indexOf(const QString &key) const;
QList<KV<QString, QString> > _list; QList<KV<QString, QString> > _list;
QRectF _boundingRect; QRectF _boundingRect;

15
src/GUI/infolabel.cpp Normal file
View File

@ -0,0 +1,15 @@
#include <QtGlobal>
#include "infolabel.h"
InfoLabel::InfoLabel(const QString &text, QWidget *parent)
: QLabel(text, parent)
{
QFont f(font());
#ifdef Q_OS_MAC
f.setPointSize(qMax(10, f.pointSize() - 2));
#else // Q_OS_MAC
f.setPointSize(f.pointSize() - 1);
#endif // Q_OS_MAC
setWordWrap(true);
setFont(f);
}

12
src/GUI/infolabel.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef INFOLABEL_H
#define INFOLABEL_H
#include <QLabel>
class InfoLabel : public QLabel
{
public:
InfoLabel(const QString &text, QWidget *parent = 0);
};
#endif // INFOLABEL_H

View File

@ -28,6 +28,8 @@
#define PREV_MAP_SHORTCUT QKeySequence(QKeySequence::Back) #define PREV_MAP_SHORTCUT QKeySequence(QKeySequence::Back)
#define SHOW_GRAPHS_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_G) #define SHOW_GRAPHS_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_G)
#define STATISTICS_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_S) #define STATISTICS_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_S)
#define DOWNLOAD_DEM_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_D)
#define SHOW_TRACKS_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_T)
#define FULLSCREEN_SHORTCUT (QKeySequence(QKeySequence::FullScreen).isEmpty() \ #define FULLSCREEN_SHORTCUT (QKeySequence(QKeySequence::FullScreen).isEmpty() \
? QKeySequence(Qt::Key_F11) \ ? QKeySequence(Qt::Key_F11) \
: QKeySequence(QKeySequence::FullScreen)) : QKeySequence(QKeySequence::FullScreen))

View File

@ -69,7 +69,7 @@ static QRectF bbox(const RectC &rect, Map *map, int samples = 100)
return prect; return prect;
} }
QString MapItem::info() const ToolTip MapItem::info() const
{ {
ToolTip tt; ToolTip tt;
@ -78,7 +78,7 @@ QString MapItem::info() const
if (!_fileName.isEmpty()) if (!_fileName.isEmpty())
tt.insert(tr("File"), _fileName); tt.insert(tr("File"), _fileName);
return tt.toString(); return tt;
} }
MapItem::MapItem(MapAction *action, Map *map, GraphicsItem *parent) MapItem::MapItem(MapAction *action, Map *map, GraphicsItem *parent)

View File

@ -26,7 +26,7 @@ public:
void setStyle(Qt::PenStyle style); void setStyle(Qt::PenStyle style);
void setDigitalZoom(int zoom); void setDigitalZoom(int zoom);
QString info() const; ToolTip info() const;
signals: signals:
void triggered(); void triggered();

View File

@ -293,6 +293,23 @@ void MapView::loadMaps(const QList<MapAction *> &maps)
centerOn(contentCenter()); centerOn(contentCenter());
} }
void MapView::loadDEMs(const QList<Area> &dems)
{
int zoom = _map->zoom();
for (int i = 0; i < dems.size(); i++)
addArea(dems.at(i));
if (fitMapZoom() != zoom)
rescale();
else
updatePOIVisibility();
updateZValues(_areas);
centerOn(contentCenter());
}
int MapView::fitMapZoom() const int MapView::fitMapZoom() const
{ {
RectC br = _tr | _rr | _wr | _ar; RectC br = _tr | _rr | _wr | _ar;
@ -1147,3 +1164,19 @@ void MapView::fitContentToSize()
centerOn(contentCenter()); centerOn(contentCenter());
} }
RectC MapView::boundingRect() const
{
RectC rect;
if (_showTracks)
rect |= _tr;
if (_showRoutes)
rect |= _rr;
if (_showWaypoints)
rect |= _wr;
if (_showAreas)
rect |= _ar;
return rect;
}

View File

@ -52,6 +52,7 @@ public:
QList<PathItem *> loadData(const Data &data); QList<PathItem *> loadData(const Data &data);
void loadMaps(const QList<MapAction*> &maps); void loadMaps(const QList<MapAction*> &maps);
void loadDEMs(const QList<Area> &dems);
void setPalette(const Palette &palette); void setPalette(const Palette &palette);
void setPOI(POI *poi); void setPOI(POI *poi);
@ -88,6 +89,8 @@ public:
void clearMapCache(); void clearMapCache();
void fitContentToSize(); void fitContentToSize();
RectC boundingRect() const;
public slots: public slots:
void showMap(bool show); void showMap(bool show);
void showPOI(bool show); void showPOI(bool show);

View File

@ -14,11 +14,14 @@
#include <QSysInfo> #include <QSysInfo>
#include <QButtonGroup> #include <QButtonGroup>
#include "icons.h" #include "icons.h"
#include "infolabel.h"
#include "colorbox.h" #include "colorbox.h"
#include "stylecombobox.h" #include "stylecombobox.h"
#include "oddspinbox.h" #include "oddspinbox.h"
#include "percentslider.h" #include "percentslider.h"
#include "projectioncombobox.h" #include "projectioncombobox.h"
#include "dirselectwidget.h"
#include "authenticationwidget.h"
#include "optionsdialog.h" #include "optionsdialog.h"
@ -52,17 +55,11 @@ QWidget *OptionsDialog::createMapPage()
_inputProjection->setCurrentIndex(_inputProjection->findData( _inputProjection->setCurrentIndex(_inputProjection->findData(
_options.inputProjection)); _options.inputProjection));
QLabel *inInfo = new QLabel(tr("Select the proper projection of maps" InfoLabel *inInfo = new InfoLabel(tr("Select the proper projection of maps"
" without a projection definition (JNX, KMZ and world file maps).")); " without a projection definition (JNX, KMZ and world file maps)."));
QLabel *outInfo = new QLabel(tr("Select the desired projection of vector" InfoLabel *outInfo = new InfoLabel(tr("Select the desired projection of"
" maps (IMG and Mapsforge maps). The projection must be valid for" " vector maps (IMG and Mapsforge maps). The projection must be valid for"
" the whole map area.")); " the whole map area."));
QFont f = inInfo->font();
f.setPointSize(f.pointSize() - 1);
inInfo->setWordWrap(true);
outInfo->setWordWrap(true);
inInfo->setFont(f);
outInfo->setFont(f);
_hidpi = new QRadioButton(tr("High-resolution")); _hidpi = new QRadioButton(tr("High-resolution"));
_lodpi = new QRadioButton(tr("Standard")); _lodpi = new QRadioButton(tr("Standard"));
@ -70,14 +67,10 @@ QWidget *OptionsDialog::createMapPage()
_hidpi->setChecked(true); _hidpi->setChecked(true);
else else
_lodpi->setChecked(true); _lodpi->setChecked(true);
QLabel *lhi = new QLabel(tr("Non-HiDPI maps are loaded as HiDPI maps. " InfoLabel *lhi = new InfoLabel(tr("Non-HiDPI maps are loaded as HiDPI maps. "
"The map is sharp but map objects are small/hard to read.")); "The map is sharp but map objects are small/hard to read."));
QLabel *llo = new QLabel(tr("Non-HiDPI maps are loaded such as they are. " InfoLabel *llo = new InfoLabel(tr("Non-HiDPI maps are loaded such as they are. "
"Map objects have the expected size but the map is blurry.")); "Map objects have the expected size but the map is blurry."));
lhi->setWordWrap(true);
llo->setWordWrap(true);
lhi->setFont(f);
llo->setFont(f);
QVBoxLayout *inLayout = new QVBoxLayout(); QVBoxLayout *inLayout = new QVBoxLayout();
inLayout->addWidget(_inputProjection); inLayout->addWidget(_inputProjection);
@ -133,34 +126,12 @@ QWidget *OptionsDialog::createAppearancePage()
_trackWidth->setMinimum(1); _trackWidth->setMinimum(1);
_trackStyle = new StyleComboBox(); _trackStyle = new StyleComboBox();
_trackStyle->setValue(_options.trackStyle); _trackStyle->setValue(_options.trackStyle);
QFormLayout *trackLayout = new QFormLayout();
#ifdef Q_OS_MAC
trackLayout->addRow(tr("Track width:"), _trackWidth);
trackLayout->addRow(tr("Track style:"), _trackStyle);
#else // Q_OS_MAC
trackLayout->addRow(tr("Width:"), _trackWidth);
trackLayout->addRow(tr("Style:"), _trackStyle);
QGroupBox *trackBox = new QGroupBox(tr("Tracks"));
trackBox->setLayout(trackLayout);
#endif // Q_OS_MAC
// Routes // Routes
_routeWidth = new QSpinBox(); _routeWidth = new QSpinBox();
_routeWidth->setValue(_options.routeWidth); _routeWidth->setValue(_options.routeWidth);
_routeWidth->setMinimum(1); _routeWidth->setMinimum(1);
_routeStyle = new StyleComboBox(); _routeStyle = new StyleComboBox();
_routeStyle->setValue(_options.routeStyle); _routeStyle->setValue(_options.routeStyle);
QFormLayout *routeLayout = new QFormLayout();
#ifdef Q_OS_MAC
routeLayout->addRow(tr("Route width:"), _routeWidth);
routeLayout->addRow(tr("Route style:"), _routeStyle);
#else // Q_OS_MAC
routeLayout->addRow(tr("Width:"), _routeWidth);
routeLayout->addRow(tr("Style:"), _routeStyle);
QGroupBox *routeBox = new QGroupBox(tr("Routes"));
routeBox->setLayout(routeLayout);
#endif // Q_OS_MAC
// Areas // Areas
_areaWidth = new QSpinBox(); _areaWidth = new QSpinBox();
_areaWidth->setValue(_options.areaWidth); _areaWidth->setValue(_options.areaWidth);
@ -168,52 +139,64 @@ QWidget *OptionsDialog::createAppearancePage()
_areaStyle->setValue(_options.areaStyle); _areaStyle->setValue(_options.areaStyle);
_areaOpacity = new PercentSlider(); _areaOpacity = new PercentSlider();
_areaOpacity->setValue(_options.areaOpacity); _areaOpacity->setValue(_options.areaOpacity);
QFormLayout *areaLayout = new QFormLayout();
#ifdef Q_OS_MAC
areaLayout->addRow(tr("Area border width:"), _areaWidth);
areaLayout->addRow(tr("Area border style:"), _areaStyle);
areaLayout->addRow(tr("Area fill opacity:"), _areaOpacity);
#else // Q_OS_MAC
areaLayout->addRow(tr("Width:"), _areaWidth);
areaLayout->addRow(tr("Style:"), _areaStyle);
areaLayout->addRow(tr("Fill opacity:"), _areaOpacity);
QGroupBox *areaBox = new QGroupBox(tr("Areas"));
areaBox->setLayout(areaLayout);
#endif // Q_OS_MAC
// Palette & antialiasing // Palette & antialiasing
_baseColor = new ColorBox(); _baseColor = new ColorBox();
_baseColor->setColor(_options.palette.color()); _baseColor->setColor(_options.palette.color());
_colorOffset = new PercentSlider(); _colorOffset = new PercentSlider();
_colorOffset->setValue(_options.palette.shift() * 100); _colorOffset->setValue(_options.palette.shift() * 100);
_pathAA = new QCheckBox(tr("Use anti-aliasing"));
_pathAA->setChecked(_options.pathAntiAliasing);
#ifdef Q_OS_MAC
QWidget *pathTab = new QWidget();
QFormLayout *pathTabLayout = new QFormLayout();
pathTabLayout->addRow(tr("Track width:"), _trackWidth);
pathTabLayout->addRow(tr("Track style:"), _trackStyle);
pathTabLayout->addRow(line());
pathTabLayout->addRow(tr("Route width:"), _routeWidth);
pathTabLayout->addRow(tr("Route style:"), _routeStyle);
pathTabLayout->addRow(line());
pathTabLayout->addRow(tr("Area border width:"), _areaWidth);
pathTabLayout->addRow(tr("Area border style:"), _areaStyle);
pathTabLayout->addRow(tr("Area fill opacity:"), _areaOpacity);
pathTabLayout->addRow(line());
pathTabLayout->addRow(tr("Base color:"), _baseColor);
pathTabLayout->addRow(tr("Palette shift:"), _colorOffset);
pathTabLayout->addRow(line());
pathTabLayout->addWidget(_pathAA);
pathTab->setLayout(pathTabLayout);
#else // Q_OS_MAC
QFormLayout *trackLayout = new QFormLayout();
trackLayout->addRow(tr("Width:"), _trackWidth);
trackLayout->addRow(tr("Style:"), _trackStyle);
QGroupBox *trackBox = new QGroupBox(tr("Tracks"));
trackBox->setLayout(trackLayout);
QFormLayout *routeLayout = new QFormLayout();
routeLayout->addRow(tr("Width:"), _routeWidth);
routeLayout->addRow(tr("Style:"), _routeStyle);
QGroupBox *routeBox = new QGroupBox(tr("Routes"));
routeBox->setLayout(routeLayout);
QFormLayout *areaLayout = new QFormLayout();
areaLayout->addRow(tr("Width:"), _areaWidth);
areaLayout->addRow(tr("Style:"), _areaStyle);
areaLayout->addRow(tr("Fill opacity:"), _areaOpacity);
QGroupBox *areaBox = new QGroupBox(tr("Areas"));
areaBox->setLayout(areaLayout);
QFormLayout *paletteLayout = new QFormLayout(); QFormLayout *paletteLayout = new QFormLayout();
paletteLayout->addRow(tr("Base color:"), _baseColor); paletteLayout->addRow(tr("Base color:"), _baseColor);
paletteLayout->addRow(tr("Palette shift:"), _colorOffset); paletteLayout->addRow(tr("Palette shift:"), _colorOffset);
_pathAA = new QCheckBox(tr("Use anti-aliasing"));
_pathAA->setChecked(_options.pathAntiAliasing);
QFormLayout *pathAALayout = new QFormLayout(); QFormLayout *pathAALayout = new QFormLayout();
pathAALayout->addWidget(_pathAA); pathAALayout->addWidget(_pathAA);
QWidget *pathTab = new QWidget(); QWidget *pathTab = new QWidget();
QVBoxLayout *pathTabLayout = new QVBoxLayout(); QVBoxLayout *pathTabLayout = new QVBoxLayout();
#ifdef Q_OS_MAC
pathTabLayout->addLayout(trackLayout);
pathTabLayout->addWidget(line());
pathTabLayout->addLayout(routeLayout);
pathTabLayout->addWidget(line());
pathTabLayout->addLayout(areaLayout);
pathTabLayout->addWidget(line());
#else // Q_OS_MAC
pathTabLayout->addWidget(trackBox); pathTabLayout->addWidget(trackBox);
pathTabLayout->addWidget(routeBox); pathTabLayout->addWidget(routeBox);
pathTabLayout->addWidget(areaBox); pathTabLayout->addWidget(areaBox);
#endif // Q_OS_MAC
pathTabLayout->addLayout(paletteLayout); pathTabLayout->addLayout(paletteLayout);
pathTabLayout->addLayout(pathAALayout); pathTabLayout->addLayout(pathAALayout);
pathTabLayout->addStretch(); pathTabLayout->addStretch();
pathTab->setLayout(pathTabLayout); pathTab->setLayout(pathTabLayout);
#endif // Q_OS_MAC
// Waypoints // Waypoints
_waypointSize = new QSpinBox(); _waypointSize = new QSpinBox();
@ -221,46 +204,40 @@ QWidget *OptionsDialog::createAppearancePage()
_waypointSize->setValue(_options.waypointSize); _waypointSize->setValue(_options.waypointSize);
_waypointColor = new ColorBox(); _waypointColor = new ColorBox();
_waypointColor->setColor(_options.waypointColor); _waypointColor->setColor(_options.waypointColor);
QFormLayout *waypointLayout = new QFormLayout(); // POI
#ifdef Q_OS_MAC
waypointLayout->addRow(tr("Waypoint color:"), _waypointColor);
waypointLayout->addRow(tr("Waypoint size:"), _waypointSize);
#else // Q_OS_MAC
waypointLayout->addRow(tr("Color:"), _waypointColor);
waypointLayout->addRow(tr("Size:"), _waypointSize);
QGroupBox *waypointBox = new QGroupBox(tr("Waypoints"));
waypointBox->setLayout(waypointLayout);
#endif // Q_OS_MAC
_poiSize = new QSpinBox(); _poiSize = new QSpinBox();
_poiSize->setMinimum(1); _poiSize->setMinimum(1);
_poiSize->setValue(_options.poiSize); _poiSize->setValue(_options.poiSize);
_poiColor = new ColorBox(); _poiColor = new ColorBox();
_poiColor->setColor(_options.poiColor); _poiColor->setColor(_options.poiColor);
QFormLayout *poiLayout = new QFormLayout();
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
poiLayout->addRow(tr("POI color:"), _poiColor); QWidget *pointTab = new QWidget();
poiLayout->addRow(tr("POI size:"), _poiSize); QFormLayout *pointTabLayout = new QFormLayout();
pointTabLayout->addRow(tr("Waypoint color:"), _waypointColor);
pointTabLayout->addRow(tr("Waypoint size:"), _waypointSize);
pointTabLayout->addRow(line());
pointTabLayout->addRow(tr("POI color:"), _poiColor);
pointTabLayout->addRow(tr("POI size:"), _poiSize);
pointTab->setLayout(pointTabLayout);
#else // Q_OS_MAC #else // Q_OS_MAC
QFormLayout *waypointLayout = new QFormLayout();
waypointLayout->addRow(tr("Color:"), _waypointColor);
waypointLayout->addRow(tr("Size:"), _waypointSize);
QGroupBox *waypointBox = new QGroupBox(tr("Waypoints"));
waypointBox->setLayout(waypointLayout);
QFormLayout *poiLayout = new QFormLayout();
poiLayout->addRow(tr("Color:"), _poiColor); poiLayout->addRow(tr("Color:"), _poiColor);
poiLayout->addRow(tr("Size:"), _poiSize); poiLayout->addRow(tr("Size:"), _poiSize);
QGroupBox *poiBox = new QGroupBox(tr("POIs")); QGroupBox *poiBox = new QGroupBox(tr("POIs"));
poiBox->setLayout(poiLayout); poiBox->setLayout(poiLayout);
#endif // Q_OS_MAC
QWidget *pointTab = new QWidget(); QWidget *pointTab = new QWidget();
QVBoxLayout *pointTabLayout = new QVBoxLayout(); QVBoxLayout *pointTabLayout = new QVBoxLayout();
#ifdef Q_OS_MAC
pointTabLayout->addLayout(waypointLayout);
pointTabLayout->addWidget(line());
pointTabLayout->addLayout(poiLayout);
#else // Q_OS_MAC
pointTabLayout->addWidget(waypointBox); pointTabLayout->addWidget(waypointBox);
pointTabLayout->addWidget(poiBox); pointTabLayout->addWidget(poiBox);
#endif // Q_OS_MAC
pointTabLayout->addStretch(); pointTabLayout->addStretch();
pointTab->setLayout(pointTabLayout); pointTab->setLayout(pointTabLayout);
#endif // Q_OS_MAC
// Graphs // Graphs
_sliderColor = new ColorBox(); _sliderColor = new ColorBox();
@ -268,23 +245,29 @@ QWidget *OptionsDialog::createAppearancePage()
_graphWidth = new QSpinBox(); _graphWidth = new QSpinBox();
_graphWidth->setValue(_options.graphWidth); _graphWidth->setValue(_options.graphWidth);
_graphWidth->setMinimum(1); _graphWidth->setMinimum(1);
_graphAA = new QCheckBox(tr("Use anti-aliasing"));
_graphAA->setChecked(_options.graphAntiAliasing);
#ifdef Q_OS_MAC
QWidget *graphTab = new QWidget();
QFormLayout *graphTabLayout = new QFormLayout();
graphTabLayout->addRow(tr("Line width:"), _graphWidth);
graphTabLayout->addRow(tr("Slider color:"), _sliderColor);
graphTabLayout->addWidget(_graphAA);
graphTab->setLayout(graphTabLayout);
#else // Q_OS_MAC
QFormLayout *graphLayout = new QFormLayout(); QFormLayout *graphLayout = new QFormLayout();
graphLayout->addRow(tr("Line width:"), _graphWidth); graphLayout->addRow(tr("Line width:"), _graphWidth);
graphLayout->addRow(tr("Slider color:"), _sliderColor); graphLayout->addRow(tr("Slider color:"), _sliderColor);
_graphAA = new QCheckBox(tr("Use anti-aliasing"));
_graphAA->setChecked(_options.graphAntiAliasing);
QFormLayout *graphAALayout = new QFormLayout(); QFormLayout *graphAALayout = new QFormLayout();
graphAALayout->addWidget(_graphAA); graphAALayout->addWidget(_graphAA);
QWidget *graphTab = new QWidget(); QWidget *graphTab = new QWidget();
QVBoxLayout *graphTabLayout = new QVBoxLayout(); QVBoxLayout *graphTabLayout = new QVBoxLayout();
graphTabLayout->addLayout(graphLayout); graphTabLayout->addLayout(graphLayout);
graphTabLayout->addLayout(graphAALayout); graphTabLayout->addLayout(graphAALayout);
graphTabLayout->addStretch(); graphTabLayout->addStretch();
graphTab->setLayout(graphTabLayout); graphTab->setLayout(graphTabLayout);
#endif // Q_OS_MAC
// Map // Map
_mapOpacity = new PercentSlider(); _mapOpacity = new PercentSlider();
@ -296,14 +279,12 @@ QWidget *OptionsDialog::createAppearancePage()
QFormLayout *mapLayout = new QFormLayout(); QFormLayout *mapLayout = new QFormLayout();
mapLayout->addRow(tr("Background color:"), _backgroundColor); mapLayout->addRow(tr("Background color:"), _backgroundColor);
mapLayout->addRow(tr("Map opacity:"), _mapOpacity); mapLayout->addRow(tr("Map opacity:"), _mapOpacity);
QWidget *mapTab = new QWidget(); QWidget *mapTab = new QWidget();
QVBoxLayout *mapTabLayout = new QVBoxLayout(); QVBoxLayout *mapTabLayout = new QVBoxLayout();
mapTabLayout->addLayout(mapLayout); mapTabLayout->addLayout(mapLayout);
mapTabLayout->addStretch(); mapTabLayout->addStretch();
mapTab->setLayout(mapTabLayout); mapTab->setLayout(mapTabLayout);
QTabWidget *appearancePage = new QTabWidget(); QTabWidget *appearancePage = new QTabWidget();
appearancePage->addTab(pathTab, tr("Paths")); appearancePage->addTab(pathTab, tr("Paths"));
appearancePage->addTab(pointTab, tr("Points")); appearancePage->addTab(pointTab, tr("Points"));
@ -333,36 +314,39 @@ QWidget *OptionsDialog::createDataPage()
_powerFilter->setValue(_options.powerFilter); _powerFilter->setValue(_options.powerFilter);
_powerFilter->setToolTip(filterToolTip); _powerFilter->setToolTip(filterToolTip);
_outlierEliminate = new QCheckBox(tr("Eliminate GPS outliers"));
_outlierEliminate->setChecked(_options.outlierEliminate);
#ifdef Q_OS_MAC
QWidget *filterTab = new QWidget();
QFormLayout *filterTabLayout = new QFormLayout();
filterTabLayout->addWidget(new QLabel(tr("Smoothing")));
filterTabLayout->addRow(tr("Elevation:"), _elevationFilter);
filterTabLayout->addRow(tr("Speed:"), _speedFilter);
filterTabLayout->addRow(tr("Heart rate:"), _heartRateFilter);
filterTabLayout->addRow(tr("Cadence:"), _cadenceFilter);
filterTabLayout->addRow(tr("Power:"), _powerFilter);
filterTabLayout->addWidget(new QWidget());
filterTabLayout->addWidget(_outlierEliminate);
filterTab->setLayout(filterTabLayout);
#else // Q_OS_MAC
QFormLayout *smoothLayout = new QFormLayout(); QFormLayout *smoothLayout = new QFormLayout();
smoothLayout->addRow(tr("Elevation:"), _elevationFilter); smoothLayout->addRow(tr("Elevation:"), _elevationFilter);
smoothLayout->addRow(tr("Speed:"), _speedFilter); smoothLayout->addRow(tr("Speed:"), _speedFilter);
smoothLayout->addRow(tr("Heart rate:"), _heartRateFilter); smoothLayout->addRow(tr("Heart rate:"), _heartRateFilter);
smoothLayout->addRow(tr("Cadence:"), _cadenceFilter); smoothLayout->addRow(tr("Cadence:"), _cadenceFilter);
smoothLayout->addRow(tr("Power:"), _powerFilter); smoothLayout->addRow(tr("Power:"), _powerFilter);
#ifndef Q_OS_MAC
QGroupBox *smoothBox = new QGroupBox(tr("Smoothing"));
smoothBox->setLayout(smoothLayout);
#endif // Q_OS_MAC
_outlierEliminate = new QCheckBox(tr("Eliminate GPS outliers"));
_outlierEliminate->setChecked(_options.outlierEliminate);
QFormLayout *outlierLayout = new QFormLayout();
outlierLayout->addWidget(_outlierEliminate);
QWidget *filterTab = new QWidget(); QWidget *filterTab = new QWidget();
QVBoxLayout *filterTabLayout = new QVBoxLayout(); QVBoxLayout *filterTabLayout = new QVBoxLayout();
#ifdef Q_OS_MAC QGroupBox *smoothBox = new QGroupBox(tr("Smoothing"));
filterTabLayout->addWidget(new QLabel(tr("Smoothing:"))); smoothBox->setLayout(smoothLayout);
filterTabLayout->addLayout(smoothLayout); QFormLayout *outlierLayout = new QFormLayout();
filterTabLayout->addWidget(line()); outlierLayout->addWidget(_outlierEliminate);
#else // Q_OS_MAC
filterTabLayout->addWidget(smoothBox); filterTabLayout->addWidget(smoothBox);
#endif // Q_OS_MAC
filterTabLayout->addLayout(outlierLayout); filterTabLayout->addLayout(outlierLayout);
filterTabLayout->addStretch(); filterTabLayout->addStretch();
filterTab->setLayout(filterTabLayout); filterTab->setLayout(filterTabLayout);
#endif // Q_OS_MAC
_automaticPause = new QRadioButton(tr("Automatic")); _automaticPause = new QRadioButton(tr("Automatic"));
_manualPause = new QRadioButton(tr("Custom")); _manualPause = new QRadioButton(tr("Custom"));
@ -395,26 +379,6 @@ QWidget *OptionsDialog::createDataPage()
connect(_automaticPause, &QRadioButton::toggled, this, connect(_automaticPause, &QRadioButton::toggled, this,
&OptionsDialog::automaticPauseDetectionSet); &OptionsDialog::automaticPauseDetectionSet);
QHBoxLayout *pauseTypeLayout = new QHBoxLayout();
#ifdef Q_OS_MAC
pauseTypeLayout->addStretch();
#endif
pauseTypeLayout->addWidget(_automaticPause);
pauseTypeLayout->addWidget(_manualPause);
pauseTypeLayout->addStretch();
QFormLayout *pauseValuesLayout = new QFormLayout();
pauseValuesLayout->addRow(tr("Minimal speed:"), _pauseSpeed);
pauseValuesLayout->addRow(tr("Minimal duration:"), _pauseInterval);
QVBoxLayout *pauseLayout = new QVBoxLayout();
pauseLayout->addLayout(pauseTypeLayout);
pauseLayout->addLayout(pauseValuesLayout);
QWidget *pauseTab = new QWidget();
pauseTab->setLayout(pauseLayout);
_computedSpeed = new QRadioButton(tr("Computed from distance/time")); _computedSpeed = new QRadioButton(tr("Computed from distance/time"));
_reportedSpeed = new QRadioButton(tr("Recorded by device")); _reportedSpeed = new QRadioButton(tr("Recorded by device"));
if (_options.useReportedSpeed) if (_options.useReportedSpeed)
@ -457,10 +421,9 @@ QWidget *OptionsDialog::createDataPage()
_useSegments = new QCheckBox(tr("Use segments")); _useSegments = new QCheckBox(tr("Use segments"));
_useSegments->setChecked(_options.useSegments); _useSegments->setChecked(_options.useSegments);
QWidget *sourceTab = new QWidget();
QVBoxLayout *sourceTabLayout = new QVBoxLayout();
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
QWidget *sourceTab = new QWidget();
QFormLayout *sourceTabLayout = new QFormLayout();
QButtonGroup *speedGroup = new QButtonGroup(this); QButtonGroup *speedGroup = new QButtonGroup(this);
speedGroup->addButton(_computedSpeed); speedGroup->addButton(_computedSpeed);
speedGroup->addButton(_reportedSpeed); speedGroup->addButton(_reportedSpeed);
@ -468,7 +431,6 @@ QWidget *OptionsDialog::createDataPage()
speedOptions->addWidget(_computedSpeed); speedOptions->addWidget(_computedSpeed);
speedOptions->addWidget(_reportedSpeed); speedOptions->addWidget(_reportedSpeed);
speedOptions->addWidget(_showSecondarySpeed); speedOptions->addWidget(_showSecondarySpeed);
QButtonGroup *elevationGroup = new QButtonGroup(this); QButtonGroup *elevationGroup = new QButtonGroup(this);
elevationGroup->addButton(_dataGPSElevation); elevationGroup->addButton(_dataGPSElevation);
elevationGroup->addButton(_dataDEMElevation); elevationGroup->addButton(_dataDEMElevation);
@ -476,7 +438,6 @@ QWidget *OptionsDialog::createDataPage()
elevationOptions->addWidget(_dataGPSElevation); elevationOptions->addWidget(_dataGPSElevation);
elevationOptions->addWidget(_dataDEMElevation); elevationOptions->addWidget(_dataDEMElevation);
elevationOptions->addWidget(_showSecondaryElevation); elevationOptions->addWidget(_showSecondaryElevation);
QButtonGroup *timeZoneGroup = new QButtonGroup(this); QButtonGroup *timeZoneGroup = new QButtonGroup(this);
timeZoneGroup->addButton(_utcZone); timeZoneGroup->addButton(_utcZone);
timeZoneGroup->addButton(_systemZone); timeZoneGroup->addButton(_systemZone);
@ -486,65 +447,71 @@ QWidget *OptionsDialog::createDataPage()
zoneOptions->addWidget(_systemZone); zoneOptions->addWidget(_systemZone);
zoneOptions->addWidget(_customZone); zoneOptions->addWidget(_customZone);
zoneOptions->addItem(customZoneLayout); zoneOptions->addItem(customZoneLayout);
sourceTabLayout->addRow(tr("Speed:"), speedOptions);
QFormLayout *formLayout = new QFormLayout(); sourceTabLayout->addRow(tr("Elevation:"), elevationOptions);
formLayout->addRow(tr("Speed:"), speedOptions); sourceTabLayout->addRow(tr("Time zone:"), zoneOptions);
formLayout->addRow(tr("Elevation:"), elevationOptions); sourceTabLayout->addRow(line());
sourceTabLayout->addWidget(_useSegments);
formLayout->addRow(tr("Time zone:"), zoneOptions); sourceTab->setLayout(sourceTabLayout);
QFormLayout *segmentsLayout = new QFormLayout();
segmentsLayout->addWidget(_useSegments);
sourceTabLayout->addLayout(formLayout);
sourceTabLayout->addWidget(line());
sourceTabLayout->addLayout(segmentsLayout);
#else // Q_OS_MAC #else // Q_OS_MAC
QWidget *sourceTab = new QWidget();
QVBoxLayout *sourceTabLayout = new QVBoxLayout();
QFormLayout *speedLayout = new QFormLayout(); QFormLayout *speedLayout = new QFormLayout();
QFormLayout *elevationLayout = new QFormLayout(); QFormLayout *elevationLayout = new QFormLayout();
QFormLayout *timeZoneLayout = new QFormLayout(); QFormLayout *timeZoneLayout = new QFormLayout();
QFormLayout *segmentsLayout = new QFormLayout(); QFormLayout *segmentsLayout = new QFormLayout();
speedLayout->addWidget(_computedSpeed); speedLayout->addWidget(_computedSpeed);
speedLayout->addWidget(_reportedSpeed); speedLayout->addWidget(_reportedSpeed);
speedLayout->addWidget(_showSecondarySpeed); speedLayout->addWidget(_showSecondarySpeed);
QGroupBox *speedBox = new QGroupBox(tr("Speed")); QGroupBox *speedBox = new QGroupBox(tr("Speed"));
speedBox->setLayout(speedLayout); speedBox->setLayout(speedLayout);
elevationLayout->addWidget(_dataGPSElevation); elevationLayout->addWidget(_dataGPSElevation);
elevationLayout->addWidget(_dataDEMElevation); elevationLayout->addWidget(_dataDEMElevation);
elevationLayout->addWidget(_showSecondaryElevation); elevationLayout->addWidget(_showSecondaryElevation);
QGroupBox *elevationBox = new QGroupBox(tr("Elevation")); QGroupBox *elevationBox = new QGroupBox(tr("Elevation"));
elevationBox->setLayout(elevationLayout); elevationBox->setLayout(elevationLayout);
timeZoneLayout->addWidget(_utcZone); timeZoneLayout->addWidget(_utcZone);
timeZoneLayout->addWidget(_systemZone); timeZoneLayout->addWidget(_systemZone);
timeZoneLayout->addWidget(_customZone); timeZoneLayout->addWidget(_customZone);
timeZoneLayout->addItem(customZoneLayout); timeZoneLayout->addItem(customZoneLayout);
QGroupBox *timeZoneBox = new QGroupBox(tr("Time zone")); QGroupBox *timeZoneBox = new QGroupBox(tr("Time zone"));
timeZoneBox->setLayout(timeZoneLayout); timeZoneBox->setLayout(timeZoneLayout);
segmentsLayout->addWidget(_useSegments); segmentsLayout->addWidget(_useSegments);
sourceTabLayout->addWidget(speedBox); sourceTabLayout->addWidget(speedBox);
sourceTabLayout->addWidget(elevationBox); sourceTabLayout->addWidget(elevationBox);
sourceTabLayout->addWidget(timeZoneBox); sourceTabLayout->addWidget(timeZoneBox);
sourceTabLayout->addLayout(segmentsLayout); sourceTabLayout->addLayout(segmentsLayout);
#endif // Q_OS_MAC
sourceTabLayout->addStretch(); sourceTabLayout->addStretch();
sourceTab->setLayout(sourceTabLayout); sourceTab->setLayout(sourceTabLayout);
#endif // Q_OS_MAC
QTabWidget *filterPage = new QTabWidget(); QHBoxLayout *pauseTypeLayout = new QHBoxLayout();
filterPage->addTab(filterTab, tr("Filtering")); #ifdef Q_OS_MAC
filterPage->addTab(sourceTab, tr("Sources")); pauseTypeLayout->addStretch();
filterPage->addTab(pauseTab, tr("Pause detection")); #endif
pauseTypeLayout->addWidget(_automaticPause);
pauseTypeLayout->addWidget(_manualPause);
pauseTypeLayout->addStretch();
return filterPage; QFormLayout *pauseValuesLayout = new QFormLayout();
pauseValuesLayout->addRow(tr("Minimal speed:"), _pauseSpeed);
pauseValuesLayout->addRow(tr("Minimal duration:"), _pauseInterval);
QVBoxLayout *pauseLayout = new QVBoxLayout();
pauseLayout->addLayout(pauseTypeLayout);
pauseLayout->addLayout(pauseValuesLayout);
QWidget *pauseTab = new QWidget();
pauseTab->setLayout(pauseLayout);
QTabWidget *dataPage = new QTabWidget();
dataPage->addTab(sourceTab, tr("Sources"));
dataPage->addTab(filterTab, tr("Filtering"));
dataPage->addTab(pauseTab, tr("Pause detection"));
return dataPage;
} }
QWidget *OptionsDialog::createPOIPage() QWidget *OptionsDialog::createPOIPage()
@ -575,6 +542,57 @@ QWidget *OptionsDialog::createPOIPage()
return poiPage; return poiPage;
} }
QWidget *OptionsDialog::createDEMPage()
{
_demURL = new QLineEdit();
_demURL->setMinimumWidth(300);
_demURL->setText(_options.demURL);
_demAuth = new AuthenticationWidget();
_demAuth->setUsername(_options.demUsername);
_demAuth->setPassword(_options.demPassword);
_demAuth->setEnabled(_options.demAuthorization);
QCheckBox *useAuth = new QCheckBox(tr("Use HTTP authentication"));
useAuth->setChecked(_demAuth->isEnabled());
connect(useAuth, &QRadioButton::toggled, _demAuth,
&AuthenticationWidget::setEnabled);
InfoLabel *info = new InfoLabel(
tr("Use $lat and $lon for NYY/SYY and EXXX/WXXX in the URL."));
info->setMinimumWidth(_demURL->minimumWidth());
#ifdef Q_OS_MAC
QFormLayout *sourceLayout = new QFormLayout();
sourceLayout->addRow(tr("URL:"), _demURL);
sourceLayout->addWidget(info);
sourceLayout->addWidget(new QWidget());
sourceLayout->addWidget(useAuth);
sourceLayout->addWidget(_demAuth);
sourceLayout->setAlignment(_demAuth, Qt::AlignLeft);
QWidget *sourceTab = new QWidget();
sourceTab->setLayout(sourceLayout);
#else // Q_OS_MAC
QVBoxLayout *urlValueLayout = new QVBoxLayout();
urlValueLayout->addWidget(_demURL);
urlValueLayout->addWidget(info);
QFormLayout *urlLayout = new QFormLayout();
urlLayout->addRow(tr("URL:"), urlValueLayout);
QVBoxLayout *sourceLayout = new QVBoxLayout();
sourceLayout->addLayout(urlLayout);
sourceLayout->addSpacing(10);
sourceLayout->addWidget(useAuth);
sourceLayout->addWidget(_demAuth);
sourceLayout->addStretch();
QWidget *sourceTab = new QWidget();
sourceTab->setLayout(sourceLayout);
#endif // Q_OS_MAC
QTabWidget *demPage = new QTabWidget();
demPage->addTab(sourceTab, tr("Source"));
return demPage;
}
QWidget *OptionsDialog::createExportPage() QWidget *OptionsDialog::createExportPage()
{ {
_wysiwyg = new QRadioButton(tr("WYSIWYG")); _wysiwyg = new QRadioButton(tr("WYSIWYG"));
@ -583,17 +601,11 @@ QWidget *OptionsDialog::createExportPage()
_hires->setChecked(true); _hires->setChecked(true);
else else
_wysiwyg->setChecked(true); _wysiwyg->setChecked(true);
QLabel *lw = new QLabel(tr("The printed area is approximately the display" InfoLabel *lw = new InfoLabel(tr("The printed area is approximately the "
" area. The map zoom level does not change.")); "display area. The map zoom level does not change."));
QLabel *lh = new QLabel(tr("The zoom level will be changed so that" InfoLabel *lh = new InfoLabel(tr("The zoom level will be changed so that"
" the whole content (tracks/waypoints) fits to the printed area and" " the whole content (tracks/waypoints) fits to the printed area and"
" the map resolution is as close as possible to the print resolution.")); " the map resolution is as close as possible to the print resolution."));
QFont f = lw->font();
f.setPointSize(f.pointSize() - 1);
lw->setWordWrap(true);
lh->setWordWrap(true);
lw->setFont(f);
lh->setFont(f);
QVBoxLayout *modeTabLayout = new QVBoxLayout(); QVBoxLayout *modeTabLayout = new QVBoxLayout();
modeTabLayout->addWidget(_wysiwyg); modeTabLayout->addWidget(_wysiwyg);
@ -668,23 +680,54 @@ QWidget *OptionsDialog::createSystemPage()
_connectionTimeout->setSuffix(UNIT_SPACE + tr("s")); _connectionTimeout->setSuffix(UNIT_SPACE + tr("s"));
_connectionTimeout->setValue(_options.connectionTimeout); _connectionTimeout->setValue(_options.connectionTimeout);
#ifdef Q_OS_MAC
QWidget *systemTab = new QWidget();
QFormLayout *systemTabLayout = new QFormLayout();
systemTabLayout->addRow(tr("Image cache size:"), _pixmapCache);
systemTabLayout->addRow(tr("Connection timeout:"), _connectionTimeout);
systemTabLayout->addWidget(_enableHTTP2);
systemTabLayout->addWidget(_useOpenGL);
systemTab->setLayout(systemTabLayout);
#else // Q_OS_MAC
QFormLayout *formLayout = new QFormLayout(); QFormLayout *formLayout = new QFormLayout();
formLayout->addRow(tr("Image cache size:"), _pixmapCache); formLayout->addRow(tr("Image cache size:"), _pixmapCache);
formLayout->addRow(tr("Connection timeout:"), _connectionTimeout); formLayout->addRow(tr("Connection timeout:"), _connectionTimeout);
QFormLayout *checkboxLayout = new QFormLayout(); QFormLayout *checkboxLayout = new QFormLayout();
checkboxLayout->addWidget(_enableHTTP2); checkboxLayout->addWidget(_enableHTTP2);
checkboxLayout->addWidget(_useOpenGL); checkboxLayout->addWidget(_useOpenGL);
QWidget *systemTab = new QWidget(); QWidget *systemTab = new QWidget();
QVBoxLayout *systemTabLayout = new QVBoxLayout(); QVBoxLayout *systemTabLayout = new QVBoxLayout();
systemTabLayout->addLayout(formLayout); systemTabLayout->addLayout(formLayout);
systemTabLayout->addLayout(checkboxLayout); systemTabLayout->addLayout(checkboxLayout);
systemTabLayout->addStretch(); systemTabLayout->addStretch();
systemTab->setLayout(systemTabLayout); systemTab->setLayout(systemTabLayout);
#endif // Q_OS_MAC
_dataPath = new DirSelectWidget();
_dataPath->setDir(_options.dataPath);
_mapsPath = new DirSelectWidget();
_mapsPath->setDir(_options.mapsPath);
_poiPath = new DirSelectWidget();
_poiPath->setDir(_options.poiPath);
InfoLabel *info = new InfoLabel(tr("Select the initial paths of the file"
" open dialogues. Leave the field empty for the system default."));
QFormLayout *pathsFormLayout = new QFormLayout();
pathsFormLayout->addRow(tr("Data:"), _dataPath);
pathsFormLayout->addRow(tr("Maps:"), _mapsPath);
pathsFormLayout->addRow(tr("POI:"), _poiPath);
QWidget *pathsTab = new QWidget();
QVBoxLayout *pathsTabLayout = new QVBoxLayout();
pathsTabLayout->addLayout(pathsFormLayout);
pathsTabLayout->addWidget(info);
pathsTabLayout->addStretch();
pathsTab->setLayout(pathsTabLayout);
QTabWidget *systemPage = new QTabWidget(); QTabWidget *systemPage = new QTabWidget();
systemPage->addTab(systemTab, tr("System")); systemPage->addTab(systemTab, tr("System"));
systemPage->addTab(pathsTab, tr("Initial paths"));
return systemPage; return systemPage;
} }
@ -697,6 +740,7 @@ OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent)
pages->addWidget(createMapPage()); pages->addWidget(createMapPage());
pages->addWidget(createDataPage()); pages->addWidget(createDataPage());
pages->addWidget(createPOIPage()); pages->addWidget(createPOIPage());
pages->addWidget(createDEMPage());
pages->addWidget(createExportPage()); pages->addWidget(createExportPage());
pages->addWidget(createSystemPage()); pages->addWidget(createSystemPage());
@ -707,6 +751,7 @@ OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent)
new QListWidgetItem(QIcon(MAPS_ICON), tr("Maps"), menu); new QListWidgetItem(QIcon(MAPS_ICON), tr("Maps"), menu);
new QListWidgetItem(QIcon(DATA_ICON), tr("Data"), menu); new QListWidgetItem(QIcon(DATA_ICON), tr("Data"), menu);
new QListWidgetItem(QIcon(POI_ICON), tr("POI"), menu); new QListWidgetItem(QIcon(POI_ICON), tr("POI"), menu);
new QListWidgetItem(QIcon(DEM_ICON), tr("DEM"), menu);
new QListWidgetItem(QIcon(PRINT_EXPORT_ICON), tr("Print & Export"), new QListWidgetItem(QIcon(PRINT_EXPORT_ICON), tr("Print & Export"),
menu); menu);
new QListWidgetItem(QIcon(SYSTEM_ICON), tr("System"), menu); new QListWidgetItem(QIcon(SYSTEM_ICON), tr("System"), menu);
@ -736,6 +781,9 @@ OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent)
QVBoxLayout *layout = new QVBoxLayout; QVBoxLayout *layout = new QVBoxLayout;
layout->addLayout(contentLayout); layout->addLayout(contentLayout);
layout->addWidget(buttonBox); layout->addWidget(buttonBox);
#ifdef Q_OS_MAC
layout->setSizeConstraint(QLayout::SetFixedSize);
#endif // Q_OS_MAC
setLayout(layout); setLayout(layout);
setWindowTitle(tr("Options")); setWindowTitle(tr("Options"));
@ -803,10 +851,18 @@ void OptionsDialog::accept()
if (qAbs(poiRadius - _options.poiRadius) > 0.01) if (qAbs(poiRadius - _options.poiRadius) > 0.01)
_options.poiRadius = poiRadius; _options.poiRadius = poiRadius;
_options.demURL = _demURL->text();
_options.demAuthorization = _demAuth->isEnabled();
_options.demUsername = _demAuth->username();
_options.demPassword = _demAuth->password();
_options.useOpenGL = _useOpenGL->isChecked(); _options.useOpenGL = _useOpenGL->isChecked();
_options.enableHTTP2 = _enableHTTP2->isChecked(); _options.enableHTTP2 = _enableHTTP2->isChecked();
_options.pixmapCache = _pixmapCache->value(); _options.pixmapCache = _pixmapCache->value();
_options.connectionTimeout = _connectionTimeout->value(); _options.connectionTimeout = _connectionTimeout->value();
_options.dataPath = _dataPath->dir();
_options.mapsPath = _mapsPath->dir();
_options.poiPath = _poiPath->dir();
_options.hiresPrint = _hires->isChecked(); _options.hiresPrint = _hires->isChecked();
_options.printName = _name->isChecked(); _options.printName = _name->isChecked();

View File

@ -6,17 +6,19 @@
#include "units.h" #include "units.h"
#include "timezoneinfo.h" #include "timezoneinfo.h"
class ColorBox;
class StyleComboBox;
class OddSpinBox;
class QSpinBox; class QSpinBox;
class QDoubleSpinBox; class QDoubleSpinBox;
class QComboBox; class QComboBox;
class QCheckBox; class QCheckBox;
class QRadioButton; class QRadioButton;
class QLineEdit;
class ColorBox;
class StyleComboBox;
class OddSpinBox;
class PercentSlider; class PercentSlider;
class ProjectionComboBox; class ProjectionComboBox;
class DirSelectWidget;
class AuthenticationWidget;
struct Options { struct Options {
// Appearance // Appearance
@ -60,11 +62,19 @@ struct Options {
bool useSegments; bool useSegments;
// POI // POI
int poiRadius; int poiRadius;
// DEM
QString demURL;
QString demUsername;
QString demPassword;
bool demAuthorization;
// System // System
bool useOpenGL; bool useOpenGL;
bool enableHTTP2; bool enableHTTP2;
int pixmapCache; int pixmapCache;
int connectionTimeout; int connectionTimeout;
QString dataPath;
QString mapsPath;
QString poiPath;
// Print/Export // Print/Export
bool hiresPrint; bool hiresPrint;
bool printName; bool printName;
@ -96,6 +106,7 @@ private:
QWidget *createPOIPage(); QWidget *createPOIPage();
QWidget *createSystemPage(); QWidget *createSystemPage();
QWidget *createExportPage(); QWidget *createExportPage();
QWidget *createDEMPage();
Options &_options; Options &_options;
@ -149,11 +160,17 @@ private:
QCheckBox *_useSegments; QCheckBox *_useSegments;
// POI // POI
QDoubleSpinBox *_poiRadius; QDoubleSpinBox *_poiRadius;
// DEM
QLineEdit *_demURL;
AuthenticationWidget *_demAuth;
// System // System
QSpinBox *_pixmapCache; QSpinBox *_pixmapCache;
QSpinBox *_connectionTimeout; QSpinBox *_connectionTimeout;
QCheckBox *_useOpenGL; QCheckBox *_useOpenGL;
QCheckBox *_enableHTTP2; QCheckBox *_enableHTTP2;
DirSelectWidget *_dataPath;
DirSelectWidget *_mapsPath;
DirSelectWidget *_poiPath;
// Print/Export // Print/Export
QRadioButton *_wysiwyg; QRadioButton *_wysiwyg;
QRadioButton *_hires; QRadioButton *_hires;

24
src/GUI/passwordedit.cpp Normal file
View File

@ -0,0 +1,24 @@
#include <QAction>
#include "icons.h"
#include "passwordedit.h"
PasswordEdit::PasswordEdit(QWidget *parent) : QLineEdit(parent)
{
_show = false;
_action = addAction(QIcon(SHOW_PWD_ICON), QLineEdit::TrailingPosition);
connect(_action, &QAction::triggered, this, &PasswordEdit::showPassword);
setEchoMode(QLineEdit::Password);
}
void PasswordEdit::showPassword()
{
if (_show) {
_action->setIcon(QIcon(SHOW_PWD_ICON));
setEchoMode(QLineEdit::Password);
_show = false;
} else {
_action->setIcon(QIcon(HIDE_PWD_ICON));
setEchoMode(QLineEdit::Normal);
_show = true;
}
}

21
src/GUI/passwordedit.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef PASSWORDEDIT_H
#define PASSWORDEDIT_H
#include <QLineEdit>
class PasswordEdit : public QLineEdit
{
Q_OBJECT
public:
PasswordEdit(QWidget *parent = 0);
private slots:
void showPassword();
private:
QAction *_action;
bool _show;
};
#endif // PASSWORDEDIT_H

View File

@ -19,7 +19,10 @@ public:
void setDigitalZoom(int zoom) {setScale(pow(2, -zoom));} void setDigitalZoom(int zoom) {setScale(pow(2, -zoom));}
int type() const {return parentItem()->type();} int type() const {return parentItem()->type();}
QString info() const {return static_cast<GraphicsItem*>(parentItem())->info();} ToolTip info() const
{
return static_cast<GraphicsItem*>(parentItem())->info();
}
static QRect tickRect(int value); static QRect tickRect(int value);

View File

@ -6,25 +6,31 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <QBasicTimer> #include <QBasicTimer>
#include <QScreen> #include <QScreen>
#include <QVBoxLayout>
#include <QApplication> #include <QApplication>
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
#include <QDesktopWidget> #include <QDesktopWidget>
#endif // QT 5.15 #endif // QT 5.15
#include "tooltip.h"
#include "thumbnail.h"
#include "flowlayout.h"
#include "popup.h" #include "popup.h"
class PopupLabel : public QLabel class PopupFrame : public QFrame
{ {
public: public:
PopupLabel(const QString &text, QWidget *parent = 0); PopupFrame(const ToolTip &toolTip, QWidget *parent = 0);
~PopupLabel(); ~PopupFrame();
const ToolTip &toolTip() const {return _toolTip;}
bool eventFilter(QObject *o, QEvent *ev); bool eventFilter(QObject *o, QEvent *ev);
void place(const QPoint &pos, QWidget *w); void place(const QPoint &pos, QWidget *w);
void deleteAfterTimer(); void deleteAfterTimer();
void stopTimer() {_timer.stop();} void stopTimer() {_timer.stop();}
static PopupLabel *_instance; static PopupFrame *_instance;
protected: protected:
void paintEvent(QPaintEvent *event); void paintEvent(QPaintEvent *event);
@ -32,14 +38,17 @@ protected:
void contextMenuEvent(QContextMenuEvent *) {} void contextMenuEvent(QContextMenuEvent *) {}
private: private:
void createLayout(const ToolTip &content);
QBasicTimer _timer; QBasicTimer _timer;
ToolTip _toolTip;
}; };
PopupLabel *PopupLabel::_instance = 0; PopupFrame *PopupFrame::_instance = 0;
PopupLabel::PopupLabel(const QString &text, QWidget *parent) PopupFrame::PopupFrame(const ToolTip &toolTip, QWidget *parent)
: QLabel(text, parent, Qt::ToolTip | Qt::BypassGraphicsProxyWidget : QFrame(parent, Qt::ToolTip | Qt::BypassGraphicsProxyWidget
| Qt::WindowDoesNotAcceptFocus) | Qt::WindowDoesNotAcceptFocus), _toolTip(toolTip)
{ {
delete _instance; delete _instance;
_instance = this; _instance = this;
@ -48,39 +57,73 @@ PopupLabel::PopupLabel(const QString &text, QWidget *parent)
setBackgroundRole(QPalette::ToolTipBase); setBackgroundRole(QPalette::ToolTipBase);
setPalette(QToolTip::palette()); setPalette(QToolTip::palette());
ensurePolished(); ensurePolished();
setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0,
this));
setFrameStyle(QFrame::NoFrame); setFrameStyle(QFrame::NoFrame);
setAlignment(Qt::AlignLeft);
setIndent(1);
setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0,
this) / 255.0); this) / 255.0);
setTextInteractionFlags(Qt::TextBrowserInteraction); createLayout(toolTip);
setOpenExternalLinks(true);
setWordWrap(true);
setMouseTracking(true); setMouseTracking(true);
qApp->installEventFilter(this); qApp->installEventFilter(this);
} }
PopupLabel::~PopupLabel() PopupFrame::~PopupFrame()
{ {
_instance = 0; _instance = 0;
} }
void PopupLabel::paintEvent(QPaintEvent *event) void PopupFrame::createLayout(const ToolTip &content)
{
QVBoxLayout *layout = new QVBoxLayout();
int margin = 1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0,
this);
layout->setContentsMargins(margin, margin, margin, margin);
layout->setSpacing(0);
if (!content.images().isEmpty()) {
FlowLayout *imagesLayout = new FlowLayout(0, 2, 2);
int size = qMin(960/content.images().size(), 240);
for (int i = 0; i < content.images().size(); i++)
imagesLayout->addWidget(new Thumbnail(content.images().at(i), size));
layout->addLayout(imagesLayout);
}
if (!content.list().isEmpty()) {
QString html = "<table>";
for (int i = 0; i < content.list().count(); i++)
html += "<tr><td align=\"right\"><b>" + content.list().at(i).key()
+ ":&nbsp;</b></td><td>" + content.list().at(i).value()
+ "</td></tr>";
html += "</table>";
QLabel *label = new QLabel(html);
label->setAlignment(Qt::AlignLeft);
label->setIndent(1);
label->setTextInteractionFlags(Qt::TextBrowserInteraction);
label->setOpenExternalLinks(true);
label->setWordWrap(true);
layout->addWidget(label);
}
setLayout(layout);
}
void PopupFrame::paintEvent(QPaintEvent *event)
{ {
QStylePainter p(this); QStylePainter p(this);
QStyleOptionFrame opt; QStyleOptionFrame opt;
opt.initFrom(this); opt.initFrom(this);
p.drawPrimitive(QStyle::PE_PanelTipLabel, opt); p.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
p.end(); p.end();
QLabel::paintEvent(event); QFrame::paintEvent(event);
} }
void PopupLabel::timerEvent(QTimerEvent *event) void PopupFrame::timerEvent(QTimerEvent *event)
{ {
if (event->timerId() == _timer.timerId()) { if (event->timerId() == _timer.timerId()) {
_timer.stop(); _timer.stop();
@ -88,7 +131,7 @@ void PopupLabel::timerEvent(QTimerEvent *event)
} }
} }
bool PopupLabel::eventFilter(QObject *o, QEvent *ev) bool PopupFrame::eventFilter(QObject *o, QEvent *ev)
{ {
Q_UNUSED(o); Q_UNUSED(o);
@ -123,7 +166,7 @@ bool PopupLabel::eventFilter(QObject *o, QEvent *ev)
return false; return false;
} }
void PopupLabel::place(const QPoint &pos, QWidget *w) void PopupFrame::place(const QPoint &pos, QWidget *w)
{ {
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
QRect screen = QApplication::desktop()->screenGeometry(w); QRect screen = QApplication::desktop()->screenGeometry(w);
@ -148,31 +191,34 @@ void PopupLabel::place(const QPoint &pos, QWidget *w)
this->move(p); this->move(p);
} }
void PopupLabel::deleteAfterTimer() void PopupFrame::deleteAfterTimer()
{ {
if (!_timer.isActive()) if (!_timer.isActive())
_timer.start(300, this); _timer.start(300, this);
} }
void Popup::show(const QPoint &pos, const ToolTip &toolTip, QWidget *w)
void Popup::show(const QPoint &pos, const QString &text, QWidget *w)
{ {
if (text.isEmpty()) if (toolTip.isEmpty())
return; return;
if (PopupLabel::_instance) { if (PopupFrame::_instance) {
PopupLabel::_instance->stopTimer(); if (toolTip == PopupFrame::_instance->toolTip())
PopupLabel::_instance->setText(text); PopupFrame::_instance->stopTimer();
else {
delete PopupFrame::_instance;
PopupFrame::_instance = new PopupFrame(toolTip);
}
} else } else
PopupLabel::_instance = new PopupLabel(text); PopupFrame::_instance = new PopupFrame(toolTip);
PopupLabel::_instance->resize(PopupLabel::_instance->sizeHint()); PopupFrame::_instance->resize(PopupFrame::_instance->sizeHint());
PopupLabel::_instance->place(pos, w); PopupFrame::_instance->place(pos, w);
PopupLabel::_instance->showNormal(); PopupFrame::_instance->showNormal();
} }
void Popup::clear() void Popup::clear()
{ {
if (PopupLabel::_instance) if (PopupFrame::_instance)
delete PopupLabel::_instance; delete PopupFrame::_instance;
} }

View File

@ -2,13 +2,13 @@
#define POPUP_H #define POPUP_H
class QPoint; class QPoint;
class QString;
class QWidget; class QWidget;
class ToolTip;
class Popup class Popup
{ {
public: public:
static void show(const QPoint &pos, const QString &text, QWidget *w); static void show(const QPoint &pos, const ToolTip &toolTip, QWidget *w);
static void clear(); static void clear();
}; };

View File

@ -9,7 +9,7 @@ PowerGraphItem::PowerGraphItem(const Graph &graph, GraphType type, int width,
{ {
} }
QString PowerGraphItem::info() const ToolTip PowerGraphItem::info() const
{ {
ToolTip tt; ToolTip tt;
QLocale l(QLocale::system()); QLocale l(QLocale::system());
@ -19,5 +19,5 @@ QString PowerGraphItem::info() const
tt.insert(tr("Average"), l.toString(avg(), 'f', 1) tt.insert(tr("Average"), l.toString(avg(), 'f', 1)
+ UNIT_SPACE + tr("W")); + UNIT_SPACE + tr("W"));
return tt.toString(); return tt;
} }

View File

@ -11,7 +11,7 @@ public:
PowerGraphItem(const Graph &graph, GraphType type, int width, PowerGraphItem(const Graph &graph, GraphType type, int width,
const QColor &color, QGraphicsItem *parent = 0); const QColor &color, QGraphicsItem *parent = 0);
QString info() const; ToolTip info() const;
}; };
#endif // POWERGRAPHITEM_H #endif // POWERGRAPHITEM_H

View File

@ -8,7 +8,7 @@
#include "routeitem.h" #include "routeitem.h"
QString RouteItem::info() const ToolTip RouteItem::info() const
{ {
ToolTip tt; ToolTip tt;
@ -32,7 +32,7 @@ QString RouteItem::info() const
tt.insert(tr("Links"), links); tt.insert(tr("Links"), links);
} }
return tt.toString(); return tt;
} }
RouteItem::RouteItem(const Route &route, Map *map, QGraphicsItem *parent) RouteItem::RouteItem(const Route &route, Map *map, QGraphicsItem *parent)

View File

@ -21,7 +21,7 @@ public:
void showWaypoints(bool show); void showWaypoints(bool show);
void showWaypointLabels(bool show); void showWaypointLabels(bool show);
QString info() const; ToolTip info() const;
QDateTime date() const {return QDateTime();} QDateTime date() const {return QDateTime();}
private: private:

View File

@ -173,6 +173,14 @@
#define USE_SEGMENTS_DEFAULT true #define USE_SEGMENTS_DEFAULT true
#define POI_RADIUS_SETTING "poiRadius" #define POI_RADIUS_SETTING "poiRadius"
#define POI_RADIUS_DEFAULT (int)(IMPERIAL_UNITS() ? MIINM : KMINM) #define POI_RADIUS_DEFAULT (int)(IMPERIAL_UNITS() ? MIINM : KMINM)
#define DEM_URL_SETTING "demURL"
#define DEM_URL_DEFAULT ""
#define DEM_AUTH_SETTING "demAuthentication"
#define DEM_AUTH_DEFAULT false
#define DEM_USERNAME_SETTING "demUsername"
#define DEM_USERNAME_DEFAULT ""
#define DEM_PASSWORD_SETTING "demPassword"
#define DEM_PASSWORD_DEFAULT ""
#define USE_OPENGL_SETTING "useOpenGL" #define USE_OPENGL_SETTING "useOpenGL"
#define USE_OPENGL_DEFAULT false #define USE_OPENGL_DEFAULT false
#define ENABLE_HTTP2_SETTING "enableHTTP2" #define ENABLE_HTTP2_SETTING "enableHTTP2"
@ -205,5 +213,11 @@
#define INPUT_PROJECTION_DEFAULT 4326 #define INPUT_PROJECTION_DEFAULT 4326
#define HIDPI_MAP_SETTING "HiDPIMap" #define HIDPI_MAP_SETTING "HiDPIMap"
#define HIDPI_MAP_DEFAULT true #define HIDPI_MAP_DEFAULT true
#define DATA_PATH_SETTING "dataPath"
#define DATA_PATH_DEFAULT QString()
#define MAPS_PATH_SETTING "mapsPath"
#define MAPS_PATH_DEFAULT QString()
#define POI_PATH_SETTING "poiPath"
#define POI_PATH_DEFAULT QString()
#endif // SETTINGS_H #endif // SETTINGS_H

View File

@ -15,7 +15,7 @@ SpeedGraphItem::SpeedGraphItem(const Graph &graph, GraphType type, int width,
_mavg = graph.last().last().s() / movingTime; _mavg = graph.last().last().s() / movingTime;
} }
QString SpeedGraphItem::info() const ToolTip SpeedGraphItem::info() const
{ {
ToolTip tt; ToolTip tt;
qreal scale = (_units == Imperial) ? MS2MIH : (_units == Nautical) qreal scale = (_units == Imperial) ? MS2MIH : (_units == Nautical)
@ -34,7 +34,7 @@ QString SpeedGraphItem::info() const
? avg() * scale : mavg() * scale, 'f', 1) + UNIT_SPACE + su); ? avg() * scale : mavg() * scale, 'f', 1) + UNIT_SPACE + su);
tt.insert(tr("Pace"), pace + UNIT_SPACE + pu); tt.insert(tr("Pace"), pace + UNIT_SPACE + pu);
return tt.toString(); return tt;
} }
void SpeedGraphItem::setTimeType(TimeType type) void SpeedGraphItem::setTimeType(TimeType type)

View File

@ -17,7 +17,7 @@ public:
qreal mavg() const {return _mavg;} qreal mavg() const {return _mavg;}
qreal max() const {return _max;} qreal max() const {return _max;}
QString info() const; ToolTip info() const;
void setTimeType(TimeType type); void setTimeType(TimeType type);

View File

@ -12,7 +12,7 @@ TemperatureGraphItem::TemperatureGraphItem(const Graph &graph, GraphType type,
_avg = GraphItem::avg(); _avg = GraphItem::avg();
} }
QString TemperatureGraphItem::info() const ToolTip TemperatureGraphItem::info() const
{ {
ToolTip tt; ToolTip tt;
qreal scale = (_units == Metric) ? 1.0 : C2FS; qreal scale = (_units == Metric) ? 1.0 : C2FS;
@ -28,5 +28,5 @@ QString TemperatureGraphItem::info() const
tt.insert(tr("Minimum"), l.toString(min() * scale + offset, 'f', 1) tt.insert(tr("Minimum"), l.toString(min() * scale + offset, 'f', 1)
+ UNIT_SPACE + su); + UNIT_SPACE + su);
return tt.toString(); return tt;
} }

View File

@ -15,7 +15,7 @@ public:
qreal min() const {return _min;} qreal min() const {return _min;}
qreal avg() const {return _avg;} qreal avg() const {return _avg;}
QString info() const; ToolTip info() const;
private: private:
qreal _min, _max, _avg; qreal _min, _max, _avg;

43
src/GUI/thumbnail.cpp Normal file
View File

@ -0,0 +1,43 @@
#include <QImageReader>
#include <QDesktopServices>
#include <QFileInfo>
#include <QMouseEvent>
#include "data/imageinfo.h"
#include "thumbnail.h"
static QSize thumbnailSize(const ImageInfo &img, int limit)
{
int width, height;
if (img.size().width() > img.size().height()) {
width = qMin(img.size().width(), limit);
qreal ratio = img.size().width() / (qreal)img.size().height();
height = (int)(width / ratio);
} else {
height = qMin(img.size().height(), limit);
qreal ratio = img.size().height() / (qreal)img.size().width();
width = (int)(height / ratio);
}
return QSize(width, height);
}
Thumbnail::Thumbnail(const ImageInfo &img, int size, QWidget *parent)
: QLabel(parent)
{
QImageReader reader(img.path());
reader.setAutoTransform(true);
reader.setScaledSize(thumbnailSize(img, size));
setPixmap(QPixmap::fromImage(reader.read()));
setCursor(Qt::PointingHandCursor);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
_path = QFileInfo(img.path()).absoluteFilePath();
}
void Thumbnail::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
QDesktopServices::openUrl(QUrl::fromLocalFile(_path));
}

20
src/GUI/thumbnail.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef THUMBNAIL_H
#define THUMBNAIL_H
#include <QLabel>
class ImageInfo;
class Thumbnail : public QLabel
{
public:
Thumbnail(const ImageInfo &img, int size, QWidget *parent = 0);
protected:
void mousePressEvent(QMouseEvent *event);
private:
QString _path;
};
#endif // THUMBNAIL_H

View File

@ -1,52 +0,0 @@
#include "popup.h"
#include "tooltip.h"
static QSize thumbnailSize(const ImageInfo &img, int limit)
{
int width, height;
if (img.size().width() > img.size().height()) {
width = qMin(img.size().width(), limit);
qreal ratio = img.size().width() / (qreal)img.size().height();
height = (int)(width / ratio);
} else {
height = qMin(img.size().height(), limit);
qreal ratio = img.size().height() / (qreal)img.size().width();
width = (int)(height / ratio);
}
return QSize(width, height);
}
void ToolTip::insert(const QString &key, const QString &value)
{
_list.append(KV<QString, QString>(key, value));
}
QString ToolTip::toString() const
{
QString html;
if (_images.size()) {
html = "<div align=\"center\">";
for (int i = 0; i < _images.size(); i++) {
const ImageInfo &img = _images.at(i);
QSize size(thumbnailSize(img, qMin(960/_images.size(), 240)));
html += QString("<a href=\"file:%0\">"
"<img src=\"%0\" width=\"%1\" height=\"%2\"/></a>")
.arg(img.path(), QString::number(size.width()),
QString::number(size.height()));
}
html += "</div>";
}
if (!_list.isEmpty()) {
html += "<table>";
for (int i = 0; i < _list.count(); i++)
html += "<tr><td align=\"right\"><b>" + _list.at(i).key()
+ ":&nbsp;</b></td><td>" + _list.at(i).value() + "</td></tr>";
html += "</table>";
}
return html;
}

View File

@ -10,9 +10,31 @@
class ToolTip class ToolTip
{ {
public: public:
void insert(const QString &key, const QString &value); const QList<KV<QString, QString> > &list() const {return _list;}
void setImages(const QVector<ImageInfo> &images) {_images = images;} const QVector<ImageInfo> &images() const {return _images;}
QString toString() const;
bool isEmpty() const
{
return _list.isEmpty() && _images.isEmpty();
}
bool operator==(const ToolTip &other) const
{
return (_list == other._list && _images == other._images);
}
bool operator!=(const ToolTip &other) const
{
return (_list != other._list || _images != other._images);
}
void insert(const QString &key, const QString &value)
{
_list.append(KV<QString, QString>(key, value));
}
void setImages(const QVector<ImageInfo> &images)
{
_images = images;
}
private: private:
QList<KV<QString, QString> > _list; QList<KV<QString, QString> > _list;

View File

@ -6,7 +6,7 @@
#include "trackitem.h" #include "trackitem.h"
QString TrackItem::info() const ToolTip TrackItem::info() const
{ {
ToolTip tt; ToolTip tt;
QLocale l; QLocale l;
@ -37,7 +37,7 @@ QString TrackItem::info() const
tt.insert(tr("Links"), links); tt.insert(tr("Links"), links);
} }
return tt.toString(); return tt;
} }
TrackItem::TrackItem(const Track &track, Map *map, QGraphicsItem *parent) TrackItem::TrackItem(const Track &track, Map *map, QGraphicsItem *parent)

View File

@ -15,7 +15,7 @@ class TrackItem : public PathItem
public: public:
TrackItem(const Track &track, Map *map, QGraphicsItem *parent = 0); TrackItem(const Track &track, Map *map, QGraphicsItem *parent = 0);
QString info() const; ToolTip info() const;
QDateTime date() const {return _date;} QDateTime date() const {return _date;}
private: private:

View File

@ -3,7 +3,6 @@
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include <QLabel> #include <QLabel>
#include "font.h" #include "font.h"
#include "tooltip.h"
#include "popup.h" #include "popup.h"
#include "waypointitem.h" #include "waypointitem.h"
@ -18,7 +17,7 @@ Units WaypointItem::_units = Metric;
CoordinatesFormat WaypointItem::_format = DecimalDegrees; CoordinatesFormat WaypointItem::_format = DecimalDegrees;
QTimeZone WaypointItem::_timeZone = QTimeZone::utc(); QTimeZone WaypointItem::_timeZone = QTimeZone::utc();
QString WaypointItem::info() const ToolTip WaypointItem::info() const
{ {
ToolTip tt; ToolTip tt;
QLocale l; QLocale l;
@ -66,7 +65,7 @@ QString WaypointItem::info() const
} }
tt.setImages(_waypoint.images()); tt.setImages(_waypoint.images());
return tt.toString(); return tt;
} }
WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map, WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map,

View File

@ -30,7 +30,7 @@ public:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget); QWidget *widget);
QString info() const; ToolTip info() const;
static void setUnits(Units units) {_units = units;} static void setUnits(Units units) {_units = units;}
static void setCoordinatesFormat(CoordinatesFormat format) static void setCoordinatesFormat(CoordinatesFormat format)

204
src/common/downloader.cpp Normal file
View File

@ -0,0 +1,204 @@
#include <QFile>
#include <QFileInfo>
#include <QNetworkRequest>
#include <QDir>
#include <QTimerEvent>
#include "common/config.h"
#include "downloader.h"
#if defined(Q_OS_LINUX)
#define PLATFORM_STR "Linux"
#elif defined(Q_OS_WIN32)
#define PLATFORM_STR "Windows"
#elif defined(Q_OS_MAC)
#define PLATFORM_STR "OS X"
#else
#define PLATFORM_STR "Unknown"
#endif
#define USER_AGENT \
APP_NAME "/" APP_VERSION " (" PLATFORM_STR "; Qt " QT_VERSION_STR ")"
#define MAX_REDIRECT_LEVEL 5
#define RETRIES 3
#define ATTR_REDIRECT_POLICY QNetworkRequest::RedirectPolicyAttribute
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
#define ATTR_HTTP2_ALLOWED QNetworkRequest::HTTP2AllowedAttribute
#else // QT 5.15
#define ATTR_HTTP2_ALLOWED QNetworkRequest::Http2AllowedAttribute
#endif // QT 5.15
#define TMP_SUFFIX ".download"
static QString tmpName(const QString &origName)
{
return origName + TMP_SUFFIX;
}
static QString origName(const QString &tmpName)
{
return tmpName.left(tmpName.size() - (sizeof(TMP_SUFFIX) - 1));
}
Authorization::Authorization(const QString &username, const QString &password)
{
QString concatenated = username + ":" + password;
QByteArray data = concatenated.toLocal8Bit().toBase64();
_header = "Basic " + data;
}
NetworkTimeout::NetworkTimeout(int timeout, QNetworkReply *reply)
: QObject(reply), _timeout(timeout)
{
connect(reply, &QIODevice::readyRead, this, &NetworkTimeout::reset);
_timer.start(timeout * 1000, this);
}
void NetworkTimeout::reset()
{
_timer.start(_timeout * 1000, this);
}
void NetworkTimeout::timerEvent(QTimerEvent *ev)
{
if (!_timer.isActive() || ev->timerId() != _timer.timerId())
return;
QNetworkReply *reply = static_cast<QNetworkReply*>(parent());
if (reply->isRunning())
reply->close();
_timer.stop();
}
QNetworkAccessManager *Downloader::_manager = 0;
int Downloader::_timeout = 30;
bool Downloader::_http2 = true;
bool Downloader::doDownload(const Download &dl, const Authorization &auth)
{
const QUrl &url = dl.url();
if (!url.isValid() || !(url.scheme() == QLatin1String("http")
|| url.scheme() == QLatin1String("https"))) {
qWarning("%s: Invalid URL", qPrintable(url.toString()));
return false;
}
if (_errorDownloads.value(url) >= RETRIES)
return false;
if (_currentDownloads.contains(url))
return false;
QNetworkRequest request(url);
request.setMaximumRedirectsAllowed(MAX_REDIRECT_LEVEL);
request.setAttribute(ATTR_REDIRECT_POLICY,
QNetworkRequest::NoLessSafeRedirectPolicy);
request.setAttribute(ATTR_HTTP2_ALLOWED, QVariant(_http2));
request.setRawHeader("User-Agent", USER_AGENT);
if (!auth.isNull())
request.setRawHeader("Authorization", auth.header());
QFile *file = new QFile(tmpName(dl.file()));
if (!file->open(QIODevice::WriteOnly)) {
qWarning("%s: %s", qPrintable(file->fileName()),
qPrintable(file->errorString()));
_errorDownloads.insert(url, RETRIES);
return false;
}
Q_ASSERT(_manager);
QNetworkReply *reply = _manager->get(request);
file->setParent(reply);
_currentDownloads.insert(url, file);
if (reply->isRunning()) {
/* Starting with Qt 5.15 this can be replaced by
QNetworkRequest::setTransferTimeout() */
new NetworkTimeout(_timeout, reply);
connect(reply, &QIODevice::readyRead, this, &Downloader::emitReadReady);
connect(reply, &QNetworkReply::finished, this, &Downloader::emitFinished);
} else {
readData(reply);
downloadFinished(reply);
}
return true;
}
void Downloader::emitFinished()
{
downloadFinished(static_cast<QNetworkReply*>(sender()));
}
void Downloader::emitReadReady()
{
readData(static_cast<QNetworkReply*>(sender()));
}
void Downloader::insertError(const QUrl &url, QNetworkReply::NetworkError error)
{
if (error == QNetworkReply::OperationCanceledError)
_errorDownloads.insert(url, _errorDownloads.value(url) + 1);
else
_errorDownloads.insert(url, RETRIES);
}
void Downloader::readData(QNetworkReply *reply)
{
QFile *file = _currentDownloads.value(reply->request().url());
Q_ASSERT(file);
file->write(reply->readAll());
}
void Downloader::downloadFinished(QNetworkReply *reply)
{
QUrl url(reply->request().url());
QNetworkReply::NetworkError error = reply->error();
QFile *file = _currentDownloads.value(reply->request().url());
if (error) {
insertError(url, error);
qWarning("%s: %s", url.toEncoded().constData(),
qPrintable(reply->errorString()));
file->remove();
} else {
file->close();
file->rename(origName(file->fileName()));
}
_currentDownloads.remove(url);
reply->deleteLater();
if (_currentDownloads.isEmpty())
emit finished();
}
bool Downloader::get(const QList<Download> &list,
const Authorization &authorization)
{
bool finishEmitted = false;
for (int i = 0; i < list.count(); i++)
finishEmitted |= doDownload(list.at(i), authorization);
return finishEmitted;
}
void Downloader::enableHTTP2(bool enable)
{
Q_ASSERT(_manager);
_http2 = enable;
_manager->clearConnectionCache();
}
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const Download &download)
{
dbg.nospace() << "Download(" << download.url() << "," << download.file()
<< ")";
return dbg.space();
}
#endif // QT_NO_DEBUG

View File

@ -3,11 +3,12 @@
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
#include <QBasicTimer>
#include <QUrl> #include <QUrl>
#include <QList> #include <QList>
#include <QSet>
#include <QHash> #include <QHash>
class QFile;
class Download class Download
{ {
@ -28,12 +29,30 @@ public:
Authorization() {} Authorization() {}
Authorization(const QString &username, const QString &password); Authorization(const QString &username, const QString &password);
bool isNull() const {return _header.isNull();}
const QByteArray &header() const {return _header;} const QByteArray &header() const {return _header;}
private: private:
QByteArray _header; QByteArray _header;
}; };
class NetworkTimeout : public QObject
{
Q_OBJECT
public:
NetworkTimeout(int timeout, QNetworkReply *reply);
private slots:
void reset();
private:
void timerEvent(QTimerEvent *ev);
QBasicTimer _timer;
int _timeout;
};
class Downloader : public QObject class Downloader : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -55,18 +74,17 @@ signals:
private slots: private slots:
void emitFinished(); void emitFinished();
void downloadFinished(QNetworkReply *reply); void emitReadReady();
private: private:
class Redirect;
class ReplyTimeout; class ReplyTimeout;
void insertError(const QUrl &url, QNetworkReply::NetworkError error); void insertError(const QUrl &url, QNetworkReply::NetworkError error);
bool doDownload(const Download &dl, const QByteArray &authorization, bool doDownload(const Download &dl, const Authorization &auth);
const Redirect *redirect = 0); void downloadFinished(QNetworkReply *reply);
bool saveToDisk(const QString &filename, QIODevice *data); void readData(QNetworkReply *reply);
QSet<QUrl> _currentDownloads; QHash<QUrl, QFile*> _currentDownloads;
QHash<QUrl, int> _errorDownloads; QHash<QUrl, int> _errorDownloads;
static QNetworkAccessManager *_manager; static QNetworkAccessManager *_manager;
@ -74,4 +92,8 @@ private:
static bool _http2; static bool _http2;
}; };
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const Download &download);
#endif // QT_NO_DEBUG
#endif // DOWNLOADER_H #endif // DOWNLOADER_H

View File

@ -5,37 +5,40 @@
#define LS(val, bits) ((qint32)(((quint32)(val))<<(bits))) #define LS(val, bits) ((qint32)(((quint32)(val))<<(bits)))
inline double toWGS32(qint32 v) namespace Garmin
{ {
return ((double)v / (double)(1U<<31)) * 180.0; inline double toWGS32(qint32 v)
} {
return ((double)v / (double)(1U<<31)) * 180.0;
}
inline double toWGS24(qint32 v) inline double toWGS24(qint32 v)
{ {
return toWGS32(LS(v, 8)); return toWGS32(LS(v, 8));
} }
inline quint8 vs(const quint8 b0) inline quint8 vs(const quint8 b0)
{ {
static const quint8 sizes[] = {4, 1, 2, 1, 3, 1, 2, 1}; static const quint8 sizes[] = {4, 1, 2, 1, 3, 1, 2, 1};
return sizes[b0 & 0x07]; return sizes[b0 & 0x07];
} }
inline quint8 bs(const quint8 val) inline quint8 bs(const quint8 val)
{ {
return (val + 7) >> 3; return (val + 7) >> 3;
} }
inline quint8 byteSize(quint32 val) inline quint8 byteSize(quint32 val)
{ {
quint8 ret = 0; quint8 ret = 0;
do { do {
ret++; ret++;
val = val >> 8; val = val >> 8;
} while (val != 0); } while (val != 0);
return ret; return ret;
}
} }
#endif // GARMIN_H #endif // GARMIN_H

View File

@ -9,8 +9,19 @@ public:
const KEY &key() const {return _key;} const KEY &key() const {return _key;}
const VALUE &value() const {return _value;} const VALUE &value() const {return _value;}
bool operator==(const KV &other) const {return _key == other._key;} bool operator==(const KV &other) const
bool operator<(const KV &other) const {return _key < other._key;} {
return (_key == other._key && _value == other._value);
}
bool operator<(const KV &other) const
{
if (_key < other._key)
return true;
else if (_key > other._key)
return false;
else
return _value < other._value;
}
private: private:
KEY _key; KEY _key;

View File

@ -19,6 +19,7 @@
#include "smlparser.h" #include "smlparser.h"
#include "ov2parser.h" #include "ov2parser.h"
#include "itnparser.h" #include "itnparser.h"
#include "onmoveparsers.h"
#include "data.h" #include "data.h"
@ -41,6 +42,8 @@ static GPIParser gpi;
static SMLParser sml; static SMLParser sml;
static OV2Parser ov2; static OV2Parser ov2;
static ITNParser itn; static ITNParser itn;
static OMDParser omd;
static GHPParser ghp;
static QMap<QString, Parser*> parsers() static QMap<QString, Parser*> parsers()
{ {
@ -67,6 +70,8 @@ static QMap<QString, Parser*> parsers()
map.insert("sml", &sml); map.insert("sml", &sml);
map.insert("ov2", &ov2); map.insert("ov2", &ov2);
map.insert("itn", &itn); map.insert("itn", &itn);
map.insert("omd", &omd);
map.insert("ghp", &ghp);
return map; return map;
} }
@ -144,6 +149,7 @@ QString Data::formats()
+ qApp->translate("Data", "KML files") + " (*.kml);;" + qApp->translate("Data", "KML files") + " (*.kml);;"
+ qApp->translate("Data", "LOC files") + " (*.loc);;" + qApp->translate("Data", "LOC files") + " (*.loc);;"
+ qApp->translate("Data", "NMEA files") + " (*.nmea);;" + qApp->translate("Data", "NMEA files") + " (*.nmea);;"
+ qApp->translate("Data", "ONmove files") + " (*.omd *.ghp);;"
+ qApp->translate("Data", "OV2 files") + " (*.ov2);;" + qApp->translate("Data", "OV2 files") + " (*.ov2);;"
+ qApp->translate("Data", "OziExplorer files") + " (*.plt *.rte *.wpt);;" + qApp->translate("Data", "OziExplorer files") + " (*.plt *.rte *.wpt);;"
+ qApp->translate("Data", "SLF files") + " (*.slf);;" + qApp->translate("Data", "SLF files") + " (*.slf);;"

View File

@ -15,8 +15,9 @@
#include <QtMath> #include <QtMath>
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QRegularExpression>
#include <private/qzipreader_p.h> #include <private/qzipreader_p.h>
#include "common/coordinates.h" #include "common/rectc.h"
#include "dem.h" #include "dem.h"
@ -66,19 +67,26 @@ static qreal height(const Coordinates &c, const QByteArray *data)
} }
QString DEM::_dir; QString DEM::Tile::latStr() const
QCache<DEM::Key, QByteArray> DEM::_data;
QString DEM::baseName(const Key &key)
{ {
const char ns = (key.lat() >= 0) ? 'N' : 'S'; const char ns = (_lat >= 0) ? 'N' : 'S';
const char ew = (key.lon() >= 0) ? 'E' : 'W'; return QString("%1%2").arg(ns).arg(qAbs(_lat), 2, 10, QChar('0'));
return QString("%1%2%3%4.hgt").arg(ns)
.arg(qAbs(key.lat()), 2, 10, QChar('0')).arg(ew)
.arg(qAbs(key.lon()), 3, 10, QChar('0'));
} }
QString DEM::Tile::lonStr() const
{
const char ew = (_lon >= 0) ? 'E' : 'W';
return QString("%1%2").arg(ew).arg(qAbs(_lon), 3, 10, QChar('0'));
}
QString DEM::Tile::baseName() const
{
return QString("%1%2.hgt").arg(latStr(), lonStr());
}
QString DEM::_dir;
QCache<DEM::Tile, QByteArray> DEM::_data;
QString DEM::fileName(const QString &baseName) QString DEM::fileName(const QString &baseName)
{ {
return QDir(_dir).absoluteFilePath(baseName); return QDir(_dir).absoluteFilePath(baseName);
@ -89,16 +97,21 @@ void DEM::setDir(const QString &path)
_dir = path; _dir = path;
} }
void DEM::clearCache()
{
_data.clear();
}
qreal DEM::elevation(const Coordinates &c) qreal DEM::elevation(const Coordinates &c)
{ {
if (_dir.isEmpty()) if (_dir.isEmpty())
return NAN; return NAN;
Key k(qFloor(c.lon()), qFloor(c.lat())); Tile tile(qFloor(c.lon()), qFloor(c.lat()));
QByteArray *ba = _data[k]; QByteArray *ba = _data[tile];
if (!ba) { if (!ba) {
QString bn(baseName(k)); QString bn(tile.baseName());
QString fn(fileName(bn)); QString fn(fileName(bn));
QString zn(fn + ".zip"); QString zn(fn + ".zip");
@ -106,22 +119,60 @@ qreal DEM::elevation(const Coordinates &c)
QZipReader zip(zn, QIODevice::ReadOnly); QZipReader zip(zn, QIODevice::ReadOnly);
ba = new QByteArray(zip.fileData(bn)); ba = new QByteArray(zip.fileData(bn));
qreal ele = height(c, ba); qreal ele = height(c, ba);
_data.insert(k, ba); _data.insert(tile, ba);
return ele; return ele;
} else { } else {
QFile file(fn); QFile file(fn);
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
qWarning("%s: %s", qPrintable(file.fileName()), qWarning("%s: %s", qPrintable(file.fileName()),
qPrintable(file.errorString())); qPrintable(file.errorString()));
_data.insert(k, new QByteArray()); _data.insert(tile, new QByteArray());
return NAN; return NAN;
} else { } else {
ba = new QByteArray(file.readAll()); ba = new QByteArray(file.readAll());
qreal ele = height(c, ba); qreal ele = height(c, ba);
_data.insert(k, ba); _data.insert(tile, ba);
return ele; return ele;
} }
} }
} else } else
return height(c, ba); return height(c, ba);
} }
QList<Area> DEM::tiles()
{
QDir dir(_dir);
QFileInfoList files(dir.entryInfoList(QDir::Files | QDir::Readable));
QRegularExpression re("([NS])([0-9]{2})([EW])([0-9]{3})");
QList<Area> list;
for (int i = 0; i < files.size(); i++) {
QString basename(files.at(i).baseName());
QRegularExpressionMatch match(re.match(basename));
if (!match.hasMatch())
continue;
int lat = match.captured(2).toInt();
int lon = match.captured(4).toInt();
if (match.captured(1) == "S")
lat = -lat;
if (match.captured(3) == "W")
lon = -lon;
Area area(RectC(Coordinates(lon, lat + 1), Coordinates(lon + 1, lat)));
area.setName(basename);
area.setDescription(files.at(i).canonicalFilePath());
list.append(area);
}
return list;
}
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const DEM::Tile &tile)
{
dbg.nospace() << "Tile(" << tile.baseName() << ")";
return dbg.space();
}
#endif // QT_NO_DEBUG

View File

@ -5,21 +5,27 @@
#include <QCache> #include <QCache>
#include <QByteArray> #include <QByteArray>
#include "common/config.h" #include "common/config.h"
#include "area.h"
class QString; class QString;
class Coordinates; class Coordinates;
class RectC;
class DEM class DEM
{ {
private: public:
class Key { class Tile {
public: public:
Key(int lon, int lat) : _lon(lon), _lat(lat) {} Tile(int lon, int lat) : _lon(lon), _lat(lat) {}
int lon() const {return _lon;} int lon() const {return _lon;}
int lat() const {return _lat;} int lat() const {return _lat;}
bool operator==(const Key &other) const QString lonStr() const;
QString latStr() const;
QString baseName() const;
bool operator==(const Tile &other) const
{ {
return (_lon == other._lon && _lat == other._lat); return (_lon == other._lon && _lat == other._lat);
} }
@ -28,22 +34,26 @@ private:
int _lon, _lat; int _lon, _lat;
}; };
static QString baseName(const Key &key); static void setDir(const QString &path);
static void clearCache();
static qreal elevation(const Coordinates &c);
static QList<Area> tiles();
private:
static QString fileName(const QString &baseName); static QString fileName(const QString &baseName);
static QString _dir; static QString _dir;
static QCache<Key, QByteArray> _data; static QCache<Tile, QByteArray> _data;
public:
static void setDir(const QString &path);
static qreal elevation(const Coordinates &c);
friend HASH_T qHash(const Key &key);
}; };
inline HASH_T qHash(const DEM::Key &key) inline HASH_T qHash(const DEM::Tile &tile)
{ {
return (qHash(key.lon()) ^ qHash(key.lat())); return (qHash(tile.lon()) ^ qHash(tile.lat()));
} }
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const DEM::Tile &tile);
#endif // QT_NO_DEBUG
#endif // DEM_H #endif // DEM_H

Some files were not shown because too many files have changed in this diff Show More