1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-06 07:32:51 +02:00

Compare commits

...

132 Commits
9.1 ... 9.5

Author SHA1 Message Date
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
0935ce45b6 Localization update/fix 2021-06-29 23:11:56 +02:00
442fc24776 Merge branch 'origin/master' into Weblate. 2021-06-29 21:34:57 +02:00
2f6556dbb3 Remove the forced combobox style causing huge performance drawback 2021-06-29 21:34:00 +02:00
a54bfbadab Merge branch 'origin/master' into Weblate. 2021-06-29 21:33:12 +02:00
e9220d5526 Worldfiles OS X desktop integration 2021-06-29 21:32:27 +02:00
e90959ff34 Translated using Weblate (Polish)
Currently translated at 100.0% (399 of 399 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/pl/
2021-06-29 13:33:17 +02:00
17ed28ebf7 Cosmetics 2021-06-28 23:48:02 +02:00
e9cd0963dc Finalize the projection combo box redesign 2021-06-28 23:47:20 +02:00
fa0f7f95d2 Improve map projections combo box creation time
(but make the combo box less user-friendly)
2021-06-27 22:19:19 +02:00
0dcfeeead1 Fixed error handling 2021-06-27 21:27:02 +02:00
af9ba34521 WLD files windows integration 2021-06-27 20:57:54 +02:00
8e26ed5a50 wld files association (linux) 2021-06-27 17:30:18 +02:00
141f88e46e Merge branch 'origin/master' into Weblate. 2021-06-27 16:36:05 +02:00
c84b677938 Czech translation update 2021-06-27 16:36:21 +02:00
31bd85bcc8 Version++ 2021-06-27 16:24:40 +02:00
c0c7e9046a Code cleanup 2021-06-27 16:00:27 +02:00
f5ea667f34 Improved error handling 2021-06-27 16:00:08 +02:00
04b8d015cc Merge branch 'origin/master' into Weblate. 2021-06-27 16:00:06 +02:00
3db2828874 Translated using Weblate (Polish)
Currently translated at 99.4% (397 of 399 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/pl/
2021-06-25 00:09:57 +02:00
1a3660ba2f Cosmetics 2021-06-22 07:42:48 +02:00
a8b76f350d Merge branch 'origin/master' into Weblate. 2021-06-22 07:42:37 +02:00
e49351a7c9 Merge branch 'origin/master' into Weblate. 2021-06-21 23:35:43 +02:00
057c625283 Improve WKT parsing compatability 2021-06-21 23:35:31 +02:00
47d9eea1af Use propper basename in extension replace 2021-06-21 23:34:29 +02:00
c60aa8876b Translated using Weblate (Hungarian)
Currently translated at 100.0% (399 of 399 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2021-06-19 12:32:46 +02:00
31db5f2140 Translated using Weblate (Russian)
Currently translated at 100.0% (399 of 399 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2021-06-19 12:32:46 +02:00
9ff94f3b24 Translated using Weblate (Finnish)
Currently translated at 98.4% (393 of 399 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2021-06-19 12:32:46 +02:00
334e0c3b37 Translated using Weblate (Swedish)
Currently translated at 100.0% (399 of 399 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2021-06-18 07:40:13 +02:00
3244dd675d Fixed QT6 build 2021-06-17 22:40:37 +02:00
6f093b2148 Localization update 2021-06-17 22:15:13 +02:00
319f1180f1 Cosmetics 2021-06-17 22:13:31 +02:00
ec5a1c7851 Added support for world file maps 2021-06-17 21:58:25 +02:00
4ada19b4bf Reverted all the crazy changes done by user "caspertone2003" using weblate 2021-06-07 00:39:34 +02:00
1777e708d3 Translated using Weblate (Spanish)
Currently translated at 100.0% (398 of 398 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/es/
2021-06-07 00:31:02 +02:00
fd590c83d1 Merge branch 'origin/master' into Weblate. 2021-06-06 16:56:54 +02:00
811d41c26f Always check whether the file is at the end 2021-06-06 16:56:26 +02:00
8887e5d7a7 Merge branch 'origin/master' into Weblate. 2021-06-06 08:06:32 +02:00
8ac739c50a Translated using Weblate (Spanish)
Currently translated at 100.0% (398 of 398 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/es/
2021-06-06 08:06:31 +02:00
d291320832 Allow "quoted" CSV files not ending with CRLF 2021-06-06 08:04:21 +02:00
14c90e3eb0 Merge branch 'origin/master' into Weblate. 2021-06-04 21:08:21 +02:00
7163441cb5 Fixed pixel align issue 2021-06-04 21:04:09 +02:00
1cb478e707 Merge branch 'origin/master' into Weblate. 2021-05-31 22:38:14 +02:00
8589716a59 A little bit more sane bitmask 2021-05-31 22:37:55 +02:00
9973236912 Merge branch 'origin/master' into Weblate. 2021-05-29 23:15:08 +02:00
aff4dc9408 Fixed lat/lon error checks 2021-05-29 23:14:26 +02:00
c173a0372f Merge branch 'origin/master' into Weblate. 2021-05-29 13:10:02 +02:00
c7ef24ff30 Added TomTom OV2 and ITN support info 2021-05-29 13:09:58 +02:00
ee36404613 Merge branch 'origin/master' into Weblate. 2021-05-29 00:27:39 +02:00
89044d215b Merge branch 'origin/master' into Weblate. 2021-05-29 00:19:58 +02:00
28333ffc28 Merge branch 'origin/master' into Weblate. 2021-05-28 07:20:28 +02:00
190a4a437a Merge branch 'origin/master' into Weblate. 2021-05-27 23:22:46 +02:00
11c9fd6d48 Merge branch 'origin/master' into Weblate. 2021-05-27 22:08:59 +02:00
a74495a5e2 Translated using Weblate (Polish)
Currently translated at 100.0% (398 of 398 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/pl/
2021-05-26 18:34:17 +02:00
162 changed files with 8822 additions and 5795 deletions

View File

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

View File

@ -7,13 +7,23 @@ os:
dist: focal
osx_image: xcode12
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
cache:
directories:
- $HOME/Library/Caches/Homebrew
install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install qt; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install qtbase5-dev qtbase5-private-dev libqt5opengl5-dev qttools5-dev-tools; fi
before_cache:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew cleanup; fi
addons:
homebrew:
packages:
- qt
apt:
packages:
- qtbase5-dev
- qtbase5-private-dev
- libqt5opengl5-dev
- qttools5-dev-tools
script:
- 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.
## Features
* Opens GPX, TCX, FIT, KML, NMEA, IGC, CUP, SIGMA SLF, Suunto SML, LOC, GeoJSON, OziExplorer (PLT, RTE, WPT), Garmin GPI&CSV 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).
* 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.
* Support for DEM files (SRTM HGT).
* Support for multiple tracks in one view.

View File

@ -3,7 +3,7 @@ unix:!macx {
} else {
TARGET = GPXSee
}
VERSION = 9.1
VERSION = 9.5
QT += core \
gui \
@ -19,6 +19,8 @@ CONFIG += object_parallel_to_source
INCLUDEPATH += ./src
HEADERS += src/common/config.h \
src/GUI/axislabelitem.h \
src/GUI/dirselectwidget.h \
src/GUI/flowlayout.h \
src/GUI/graphicsscene.h \
src/GUI/mapaction.h \
src/GUI/mapitem.h \
@ -27,6 +29,7 @@ HEADERS += src/common/config.h \
src/GUI/planeitem.h \
src/GUI/poiaction.h \
src/GUI/popup.h \
src/GUI/thumbnail.h \
src/common/garmin.h \
src/common/coordinates.h \
src/common/range.h \
@ -92,6 +95,7 @@ HEADERS += src/common/config.h \
src/GUI/areaitem.h \
src/data/itnparser.h \
src/data/link.h \
src/data/onmoveparsers.h \
src/data/ov2parser.h \
src/map/IMG/bitmapline.h \
src/map/IMG/bitstream.h \
@ -107,6 +111,7 @@ HEADERS += src/common/config.h \
src/map/IMG/rastertile.h \
src/map/IMG/shield.h \
src/map/mapsforge/style.h \
src/map/prjfile.h \
src/map/textpathitem.h \
src/map/textpointitem.h \
src/map/mapsforge/mapdata.h \
@ -149,6 +154,7 @@ HEADERS += src/common/config.h \
src/map/ct.h \
src/map/mapsource.h \
src/map/tileloader.h \
src/map/wldfile.h \
src/map/wmtsmap.h \
src/map/wmts.h \
src/map/wmsmap.h \
@ -207,7 +213,7 @@ HEADERS += src/common/config.h \
src/map/IMG/subdiv.h \
src/map/IMG/style.h \
src/map/IMG/netfile.h \
src/GUI/limitedcombobox.h \
src/GUI/projectioncombobox.h \
src/GUI/pathtickitem.h \
src/map/textitem.h \
src/map/IMG/label.h \
@ -221,14 +227,18 @@ HEADERS += src/common/config.h \
src/data/geojsonparser.h \
src/GUI/timezoneinfo.h \
src/map/aqmmap.h \
src/map/mapsforgemap.h
src/map/mapsforgemap.h \
src/map/worldfilemap.h
SOURCES += src/main.cpp \
src/GUI/axislabelitem.cpp \
src/GUI/dirselectwidget.cpp \
src/GUI/flowlayout.cpp \
src/GUI/mapitem.cpp \
src/GUI/marginswidget.cpp \
src/GUI/markerinfoitem.cpp \
src/GUI/popup.cpp \
src/GUI/thumbnail.cpp \
src/common/coordinates.cpp \
src/common/rectc.cpp \
src/common/range.cpp \
@ -256,7 +266,6 @@ SOURCES += src/main.cpp \
src/GUI/fileselectwidget.cpp \
src/GUI/temperaturegraph.cpp \
src/GUI/trackitem.cpp \
src/GUI/tooltip.cpp \
src/GUI/routeitem.cpp \
src/GUI/graphitem.cpp \
src/GUI/pathitem.cpp \
@ -281,6 +290,7 @@ SOURCES += src/main.cpp \
src/GUI/areaitem.cpp \
src/data/address.cpp \
src/data/itnparser.cpp \
src/data/onmoveparsers.cpp \
src/data/ov2parser.cpp \
src/data/waypoint.cpp \
src/map/IMG/bitmapline.cpp \
@ -295,6 +305,7 @@ SOURCES += src/main.cpp \
src/map/IMG/mapdata.cpp \
src/map/IMG/rastertile.cpp \
src/map/mapsforge/style.cpp \
src/map/prjfile.cpp \
src/map/textpathitem.cpp \
src/map/textpointitem.cpp \
src/map/mapsforge/mapdata.cpp \
@ -332,6 +343,7 @@ SOURCES += src/main.cpp \
src/map/linearunits.cpp \
src/map/mapsource.cpp \
src/map/tileloader.cpp \
src/map/wldfile.cpp \
src/map/wmtsmap.cpp \
src/map/wmts.cpp \
src/map/wmsmap.cpp \
@ -389,7 +401,9 @@ SOURCES += src/main.cpp \
src/GUI/pngexportdialog.cpp \
src/data/geojsonparser.cpp \
src/map/aqmmap.cpp \
src/map/mapsforgemap.cpp
src/map/mapsforgemap.cpp \
src/map/worldfilemap.cpp \
src/GUI/projectioncombobox.cpp
DEFINES += APP_VERSION=\\\"$$VERSION\\\" \
QT_NO_DEPRECATED_WARNINGS
@ -463,7 +477,10 @@ macx {
icons/formats/aqm.icns \
icons/formats/sqlt.icns \
icons/formats/ov2.icns \
icons/formats/itn.icns
icons/formats/itn.icns \
icons/formats/wld.icns \
icons/formats/omd.icns \
icons/formats/ghp.icns
QMAKE_BUNDLE_DATA += locale maps icons csv
}
@ -494,7 +511,10 @@ win32 {
icons/formats/aqm.ico \
icons/formats/sqlt.ico \
icons/formats/ov2.ico \
icons/formats/itn.ico
icons/formats/itn.ico \
icons/formats/wld.ico \
icons/formats/omd.ico \
icons/formats/ghp.ico
DEFINES += _USE_MATH_DEFINES \
NOGDI
}

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

@ -24,3 +24,6 @@ aqm:#32a89e
sqlt:#303030
ov2:#a8c920
itn:#b8540d
wld:#c74c8f
omd:#ed09cb
ghp:#ed09cb

BIN
icons/formats/wld.icns Normal file

Binary file not shown.

BIN
icons/formats/wld.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

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

View File

@ -526,6 +526,58 @@
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>wld</string>
<string>jgw</string>
<string>gfw</string>
<string>pgw</string>
<string>tfw</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/vnd.esri.wld</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>icons/wld.icns</string>
<key>CFBundleTypeName</key>
<string>ESRI World File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</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>
<key>UTImportedTypeDeclarations</key>
@ -1187,6 +1239,73 @@
<string>application/vnd.tomtom.itn</string>
</dict>
</dict>
<dict>
<key>UTTypeIdentifier</key>
<string>com.esri.wld</string>
<key>UTTypeReferenceURL</key>
<string>http://webhelp.esri.com/arcims/9.3/General/topics/author_world_files.htm</string>
<key>UTTypeDescription</key>
<string>ESRI World File</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>wld</string>
<string>jgw</string>
<string>gfw</string>
<string>pgw</string>
<string>tfw</string>
</array>
<key>public.mime-type</key>
<string>application/vnd.esri.wld</string>
</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>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>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>
<key>UTExportedTypeDeclarations</key>

View File

@ -14,14 +14,14 @@
<ul>
<li>Opens GPX, TCX, FIT, KML, IGC, NMEA, SIGMA SLF, Suunto SML, LOC,
OziExplorer (PLT, WPT, RTE), GeoJSON, SeeYou CUP,
Garmin GPI &amp; CSV, TomTom OV2 &amp; ITN and geotagged JPEG
files.</li>
Garmin GPI &amp; CSV, TomTom OV2 &amp; ITN, ONmove OMD/GHP
and geotagged JPEG files.</li>
<li>User-definable online maps (OpenStreetMap/Google tiles, WMTS,
WMS, TMS, QuadTiles).</li>
<li>Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases,
TwoNav RMaps, Garmin IMG &amp; JNX maps, GeoTIFF images,
BSB nautical charts, KMZ maps, AlpineQuest maps,
Mapsforge maps).</li>
Mapsforge maps), ESRI world files.</li>
<li>Elevation, speed, heart rate, cadence, power, temperature and
gear ratio graphs.</li>
<li>Support for multiple tracks in one view.</li>
@ -94,5 +94,8 @@
<mimetype>application/vnd.mapsforge.map</mimetype>
<mimetype>application/vnd.tomtom.ov2</mimetype>
<mimetype>application/vnd.tomtom.itn</mimetype>
<mimetype>application/vnd.esri.wld</mimetype>
<mimetype>application/vnd.onmove.omd</mimetype>
<mimetype>application/vnd.onmove.ghp</mimetype>
</mimetypes>
</component>

View File

@ -15,4 +15,4 @@ Icon=gpxsee
Terminal=false
Type=Application
Categories=Graphics;Viewer;Education;Geography;Maps;Sports;Qt
MimeType=application/gpx+xml;application/vnd.garmin.tcx+xml;application/vnd.ant.fit;application/vnd.google-earth.kml+xml;application/vnd.fai.igc;application/vnd.nmea.nmea;application/vnd.oziexplorer.plt;application/vnd.oziexplorer.rte;application/vnd.oziexplorer.wpt;application/vnd.groundspeak.loc+xml;application/vnd.sigma.slf+xml;application/geo+json;application/vnd.naviter.seeyou.cup;application/vnd.garmin.gpi;application/vnd.suunto.sml+xml;image/jpeg;text/csv;application/vnd.garmin.img;application/vnd.garmin.jnx;application/vnd.garmin.gmap+xml;image/vnd.maptech.kap;application/vnd.oziexplorer.map;application/vnd.mapbox.mbtiles;application/vnd.twonav.rmap;application/vnd.trekbuddy.tba;application/vnd.gpxsee.map+xml;application/x-tar;image/tiff;application/vnd.google-earth.kmz;application/vnd.alpinequest.aqm;application/vnd.rmaps.sqlite;application/vnd.mapsforge.map;application/vnd.tomtom.ov2;application/vnd.tomtom.itn
MimeType=application/gpx+xml;application/vnd.garmin.tcx+xml;application/vnd.ant.fit;application/vnd.google-earth.kml+xml;application/vnd.fai.igc;application/vnd.nmea.nmea;application/vnd.oziexplorer.plt;application/vnd.oziexplorer.rte;application/vnd.oziexplorer.wpt;application/vnd.groundspeak.loc+xml;application/vnd.sigma.slf+xml;application/geo+json;application/vnd.naviter.seeyou.cup;application/vnd.garmin.gpi;application/vnd.suunto.sml+xml;image/jpeg;text/csv;application/vnd.garmin.img;application/vnd.garmin.jnx;application/vnd.garmin.gmap+xml;image/vnd.maptech.kap;application/vnd.oziexplorer.map;application/vnd.mapbox.mbtiles;application/vnd.twonav.rmap;application/vnd.trekbuddy.tba;application/vnd.gpxsee.map+xml;application/x-tar;image/tiff;application/vnd.google-earth.kmz;application/vnd.alpinequest.aqm;application/vnd.rmaps.sqlite;application/vnd.mapsforge.map;application/vnd.tomtom.ov2;application/vnd.tomtom.itn;application/vnd.esri.wld

View File

@ -9,7 +9,7 @@ Unicode true
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "9.1"
!define VERSION "9.5"
; The file to write
OutFile "GPXSee-${VERSION}.exe"
@ -130,17 +130,24 @@ Section "GPXSee" SEC_APP
!insertmacro FILE_ASSOCIATION_ADD "rmap" "TwoNav Raster Map File" 14
!insertmacro FILE_ASSOCIATION_ADD "tba" "TrekBuddy Atlas" 15
!insertmacro FILE_ASSOCIATION_ADD "aqm" "AlpineQuest Map File" 16
!insertmacro FILE_ASSOCIATION_ADD "sqlitedb" "RMAps SQLite Map File" 17
!insertmacro FILE_ASSOCIATION_ADD "sqlitedb" "RMaps SQLite Map File" 17
!insertmacro FILE_ASSOCIATION_ADD "ov2" "TomTom POI File" 18
!insertmacro FILE_ASSOCIATION_ADD "itn" "TomTom Route File" 19
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 20
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 21
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 21
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 22
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 23
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 24
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 25
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 26
!insertmacro FILE_ASSOCIATION_ADD "itn" "TomTom Route File" 19
!insertmacro FILE_ASSOCIATION_ADD "wld" "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 "pgw" "ESRI World File" 20
!insertmacro FILE_ASSOCIATION_ADD "tfw" "ESRI World File" 20
!insertmacro FILE_ASSOCIATION_ADD "omd" "ONmove Log File" 21
!insertmacro FILE_ASSOCIATION_ADD "ghp" "ONmove Log File" 22
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 23
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 24
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 24
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 25
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 26
!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 ".gpx\OpenWithList" "GPXSee.exe" ""
@ -158,6 +165,8 @@ Section "GPXSee" SEC_APP
WriteRegStr HKCR ".cup\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".gpi\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".sml\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".ov2\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".itn\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".csv\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".json\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".jpg\OpenWithList" "GPXSee.exe" ""
@ -177,9 +186,14 @@ Section "GPXSee" SEC_APP
WriteRegStr HKCR ".kmz\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".aqm\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".sqlitedb\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".ov2\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".itn\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".wld\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".jgw\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".gfw\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".pgw\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)'
SectionEnd
@ -286,8 +300,6 @@ Section "Uninstall"
!insertmacro FILE_ASSOCIATION_REMOVE "cup"
!insertmacro FILE_ASSOCIATION_REMOVE "gpi"
!insertmacro FILE_ASSOCIATION_REMOVE "sml"
!insertmacro FILE_ASSOCIATION_REMOVE "ov2"
!insertmacro FILE_ASSOCIATION_REMOVE "itn"
!insertmacro FILE_ASSOCIATION_REMOVE "img"
!insertmacro FILE_ASSOCIATION_REMOVE "jnx"
!insertmacro FILE_ASSOCIATION_REMOVE "kap"
@ -298,6 +310,15 @@ Section "Uninstall"
!insertmacro FILE_ASSOCIATION_REMOVE "kmz"
!insertmacro FILE_ASSOCIATION_REMOVE "aqm"
!insertmacro FILE_ASSOCIATION_REMOVE "sqlitedb"
!insertmacro FILE_ASSOCIATION_REMOVE "ov2"
!insertmacro FILE_ASSOCIATION_REMOVE "itn"
!insertmacro FILE_ASSOCIATION_REMOVE "wld"
!insertmacro FILE_ASSOCIATION_REMOVE "jgw"
!insertmacro FILE_ASSOCIATION_REMOVE "gfw"
!insertmacro FILE_ASSOCIATION_REMOVE "pgw"
!insertmacro FILE_ASSOCIATION_REMOVE "tfw"
!insertmacro FILE_ASSOCIATION_REMOVE "omd"
!insertmacro FILE_ASSOCIATION_REMOVE "ghp"
DeleteRegValue HKCR ".gpx\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".tcx\OpenWithList" "GPXSee.exe"
@ -314,6 +335,8 @@ Section "Uninstall"
DeleteRegValue HKCR ".cup\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".gpi\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".sml\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".ov2\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".itn\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".csv\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".json\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".jpg\OpenWithList" "GPXSee.exe"
@ -333,8 +356,13 @@ Section "Uninstall"
DeleteRegValue HKCR ".kmz\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".aqm\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".sqlitedb\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".ov2\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".itn\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".wld\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".jgw\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".gfw\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".pgw\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"
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
@ -367,4 +395,4 @@ LangString DESC_LOCALIZATION ${LANG_ENGLISH} \
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_MSVC} $(DESC_MSVC)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_APP} $(DESC_APP)
!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"/>
</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 -->
<mime-type type="application/vnd.garmin.img">
@ -260,4 +274,15 @@
<glob pattern="*.map"/>
</mime-type>
<mime-type type="application/vnd.esri.wld">
<comment>ESRI World File</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text/plain"/>
<glob pattern="*.wld"/>
<glob pattern="*.jgw"/>
<glob pattern="*.gfw"/>
<glob pattern="*.pgw"/>
<glob pattern="*.tfw"/>
</mime-type>
</mime-info>

View File

@ -9,7 +9,7 @@ Unicode true
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "9.1"
!define VERSION "9.5"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"
@ -139,15 +139,22 @@ Section "GPXSee" SEC_APP
!insertmacro FILE_ASSOCIATION_ADD "aqm" "AlpineQuest Map File" 16
!insertmacro FILE_ASSOCIATION_ADD "sqlitedb" "RMaps SQLite Map File" 17
!insertmacro FILE_ASSOCIATION_ADD "ov2" "TomTom POI File" 18
!insertmacro FILE_ASSOCIATION_ADD "itn" "TomTom Route File" 19
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 20
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 21
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 21
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 22
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 23
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 24
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 25
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 26
!insertmacro FILE_ASSOCIATION_ADD "itn" "TomTom Route File" 19
!insertmacro FILE_ASSOCIATION_ADD "wld" "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 "pgw" "ESRI World File" 20
!insertmacro FILE_ASSOCIATION_ADD "tfw" "ESRI World File" 20
!insertmacro FILE_ASSOCIATION_ADD "omd" "ONmove Log File" 21
!insertmacro FILE_ASSOCIATION_ADD "ghp" "ONmove Log File" 22
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 23
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 24
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 24
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 25
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 26
!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 ".gpx\OpenWithList" "GPXSee.exe" ""
@ -186,6 +193,13 @@ Section "GPXSee" SEC_APP
WriteRegStr HKCR ".kmz\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".aqm\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".sqlitedb\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".wld\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".jgw\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".gfw\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".pgw\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)'
@ -321,6 +335,13 @@ Section "Uninstall"
!insertmacro FILE_ASSOCIATION_REMOVE "sqlitedb"
!insertmacro FILE_ASSOCIATION_REMOVE "ov2"
!insertmacro FILE_ASSOCIATION_REMOVE "itn"
!insertmacro FILE_ASSOCIATION_REMOVE "wld"
!insertmacro FILE_ASSOCIATION_REMOVE "jgw"
!insertmacro FILE_ASSOCIATION_REMOVE "gfw"
!insertmacro FILE_ASSOCIATION_REMOVE "pgw"
!insertmacro FILE_ASSOCIATION_REMOVE "tfw"
!insertmacro FILE_ASSOCIATION_REMOVE "omd"
!insertmacro FILE_ASSOCIATION_REMOVE "ghp"
DeleteRegValue HKCR ".gpx\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".tcx\OpenWithList" "GPXSee.exe"
@ -358,6 +379,13 @@ Section "Uninstall"
DeleteRegValue HKCR ".kmz\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".aqm\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".sqlitedb\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".wld\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".jgw\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".gfw\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".pgw\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"
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
@ -390,4 +418,4 @@ LangString DESC_LOCALIZATION ${LANG_ENGLISH} \
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_MSVC} $(DESC_MSVC)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_APP} $(DESC_APP)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_LOCALIZATION} $(DESC_LOCALIZATION)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
!insertmacro MUI_FUNCTION_DESCRIPTION_END

View File

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

View File

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

View File

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

View File

@ -11,7 +11,7 @@ public:
CadenceGraphItem(const Graph &graph, GraphType type, int width,
const QColor &color, QGraphicsItem *parent = 0);
QString info() const;
ToolTip info() const;
};
#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;
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)
+ UNIT_SPACE + su);
return tt.toString();
return tt;
}

View File

@ -18,7 +18,7 @@ public:
qreal max() const {return _max;}
qreal min() const {return _min;}
QString info() const;
ToolTip info() const;
private:
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;
}
QString GearRatioGraphItem::info() const
ToolTip GearRatioGraphItem::info() const
{
ToolTip tt;
QLocale l(QLocale::system());
@ -36,5 +36,5 @@ QString GearRatioGraphItem::info() const
tt.insert(tr("Maximum"), l.toString(max(), '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;}
const QMap<qreal, qreal> &map() const {return _map;}
QString info() const;
ToolTip info() const;
private:
QMap<qreal, qreal> _map;

View File

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

View File

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

View File

@ -31,6 +31,7 @@
#include "map/maplist.h"
#include "map/emptymap.h"
#include "map/downloader.h"
#include "map/crs.h"
#include "icons.h"
#include "keys.h"
#include "settings.h"
@ -95,12 +96,12 @@ GUI::GUI()
_movingTime = 0;
_lastTab = 0;
_dataDir = QDir::homePath();
_mapDir = QDir::homePath();
_poiDir = QDir::homePath();
readSettings();
_dataDir = _options.dataPath;
_mapDir = _options.mapsPath;
_poiDir = _options.poiPath;
updateGraphTabs();
updateStatusBarInfo();
}
@ -123,7 +124,8 @@ TreeNode<MapAction*> GUI::createMapActions()
if (mapDir.isNull())
return TreeNode<MapAction*>();
TreeNode<Map*> maps(MapList::loadMaps(mapDir));
TreeNode<Map*> maps(MapList::loadMaps(mapDir,
CRS::projection(_options.inputProjection)));
return createMapActionsNode(maps);
}
@ -1006,8 +1008,19 @@ void GUI::openOptions()
SET_VIEW_OPTION(pathAntiAliasing, useAntiAliasing);
SET_VIEW_OPTION(useOpenGL, useOpenGL);
SET_VIEW_OPTION(sliderColor, setMarkerColor);
SET_VIEW_OPTION(outputProjection, setOutputProjection);
SET_VIEW_OPTION(inputProjection, setInputProjection);
if (options.hidpiMap != _options.hidpiMap)
_mapView->setDevicePixelRatio(devicePixelRatioF(),
options.hidpiMap ? devicePixelRatioF() : 1.0);
if (options.outputProjection != _options.outputProjection)
_mapView->setOutputProjection(CRS::projection(options.outputProjection));
if (options.inputProjection != _options.inputProjection)
_mapView->setInputProjection(CRS::projection(options.inputProjection));
if (options.timeZone != _options.timeZone) {
_mapView->setTimeZone(options.timeZone.zone());
_dateRange.first = _dateRange.first.toTimeZone(options.timeZone.zone());
_dateRange.second = _dateRange.second.toTimeZone(options.timeZone.zone());
}
SET_TAB_OPTION(palette, setPalette);
SET_TAB_OPTION(graphWidth, setGraphWidth);
@ -1047,15 +1060,12 @@ void GUI::openOptions()
if (options.enableHTTP2 != _options.enableHTTP2)
Downloader::enableHTTP2(options.enableHTTP2);
if (options.hidpiMap != _options.hidpiMap)
_mapView->setDevicePixelRatio(devicePixelRatioF(),
options.hidpiMap ? devicePixelRatioF() : 1.0);
if (options.timeZone != _options.timeZone) {
_mapView->setTimeZone(options.timeZone.zone());
_dateRange.first = _dateRange.first.toTimeZone(options.timeZone.zone());
_dateRange.second = _dateRange.second.toTimeZone(options.timeZone.zone());
}
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)
reloadFiles();
@ -1561,7 +1571,8 @@ bool GUI::loadMapNode(const TreeNode<Map*> &node, MapAction *&action,
bool GUI::loadMap(const QString &fileName, MapAction *&action, bool silent)
{
TreeNode<Map*> maps(MapList::loadMaps(fileName));
TreeNode<Map*> maps(MapList::loadMaps(fileName,
CRS::projection(_options.inputProjection)));
QList<QAction*> existingActions(_mapsActionGroup->actions());
return loadMapNode(maps, action, silent, existingActions);
@ -1631,9 +1642,9 @@ void GUI::loadMapDirNode(const TreeNode<Map *> &node, QList<MapAction*> &actions
actions.append(a);
} else
connect(a, &MapAction::loaded, this, &GUI::mapLoadedDir);
}
_areaCount++;
_areaCount++;
}
} else {
map = a->data().value<Map*>();
if (map->isReady())
@ -1650,7 +1661,8 @@ void GUI::loadMapDir()
return;
QFileInfo fi(dir);
TreeNode<Map*> maps(MapList::loadMaps(dir));
TreeNode<Map*> maps(MapList::loadMaps(dir,
CRS::projection(_options.inputProjection)));
QList<QAction*> existingActions(_mapsActionGroup->actions());
QList<MapAction*> actions;
QMenu *menu = new QMenu(maps.name());
@ -2257,6 +2269,13 @@ void GUI::writeSettings()
settings.setValue(INPUT_PROJECTION_SETTING, _options.inputProjection);
if (_options.hidpiMap != HIDPI_MAP_DEFAULT)
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();
}
@ -2558,8 +2577,14 @@ void GUI::readSettings()
OUTPUT_PROJECTION_DEFAULT).toInt();
_options.inputProjection = settings.value(INPUT_PROJECTION_SETTING,
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();
_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->setMapOpacity(_options.mapOpacity);
@ -2581,8 +2606,8 @@ void GUI::readSettings()
_mapView->useOpenGL(true);
_mapView->setDevicePixelRatio(devicePixelRatioF(),
_options.hidpiMap ? devicePixelRatioF() : 1.0);
_mapView->setOutputProjection(_options.outputProjection);
_mapView->setInputProjection(_options.inputProjection);
_mapView->setOutputProjection(CRS::projection(_options.outputProjection));
_mapView->setInputProjection(CRS::projection(_options.inputProjection));
_mapView->setTimeZone(_options.timeZone.zone());
for (int i = 0; i < _tabs.count(); i++) {

View File

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

View File

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

View File

@ -56,17 +56,25 @@ void InfoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
//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)
{
KV<QString, QString> kv(key, value);
int i;
prepareGeometryChange();
if ((i = _list.indexOf(kv)) < 0)
_list.append(kv);
if ((i = indexOf(key)) < 0)
_list.append(KV<QString, QString>(key, value));
else
_list[i] = kv;
_list[i] = KV<QString, QString>(key, value);
updateBoundingRect();
update();

View File

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

View File

@ -1,39 +0,0 @@
#ifndef LIMITEDCOMBOBOX_H
#define LIMITEDCOMBOBOX_H
#include <QComboBox>
#include <QEvent>
class LimitedComboBox : public QComboBox
{
public:
LimitedComboBox(int limit, QWidget *parent = 0)
: QComboBox(parent), _limit(limit)
{
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
setStyleSheet("combobox-popup: 0;");
}
QSize sizeHint() const
{
return QSize(qMin(_limit, QComboBox::sizeHint().width()),
QComboBox::sizeHint().height());
}
QSize minimumSizeHint() const
{
return QSize(qMin(_limit, QComboBox::minimumSizeHint().width()),
QComboBox::minimumSizeHint().height());
}
bool event(QEvent *e)
{
if (e->type() == QEvent::Polish)
view()->setMinimumWidth(QComboBox::sizeHint().width());
return QComboBox::event(e);
}
private:
int _limit;
};
#endif // LIMITEDCOMBOBOX_H

View File

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

View File

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

View File

@ -1121,37 +1121,19 @@ void MapView::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
reloadMap();
}
void MapView::setOutputProjection(int id)
void MapView::setOutputProjection(const Projection &proj)
{
const PCS *pcs;
const GCS *gcs;
_outputProjection = proj;
Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
if ((pcs = PCS::pcs(id)))
_outputProjection = Projection(pcs);
else if ((gcs = GCS::gcs(id)))
_outputProjection = Projection(gcs);
else
qWarning("%d: Unknown PCS/GCS id", id);
_map->setOutputProjection(_outputProjection);
rescale();
centerOn(_map->ll2xy(center));
}
void MapView::setInputProjection(int id)
void MapView::setInputProjection(const Projection &proj)
{
const PCS *pcs;
const GCS *gcs;
_inputProjection = proj;
Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
if ((pcs = PCS::pcs(id)))
_inputProjection = Projection(pcs);
else if ((gcs = GCS::gcs(id)))
_inputProjection = Projection(gcs);
else
qWarning("%d: Unknown PCS/GCS id", id);
_map->setInputProjection(_inputProjection);
rescale();
centerOn(_map->ll2xy(center));

View File

@ -83,8 +83,8 @@ public:
void setCoordinatesFormat(CoordinatesFormat format);
void setTimeZone(const QTimeZone &zone);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
void setOutputProjection(int id);
void setInputProjection(int id);
void setOutputProjection(const Projection &proj);
void setInputProjection(const Projection &proj);
void clearMapCache();
void fitContentToSize();

View File

@ -13,13 +13,13 @@
#include <QLabel>
#include <QSysInfo>
#include <QButtonGroup>
#include "map/pcs.h"
#include "icons.h"
#include "colorbox.h"
#include "stylecombobox.h"
#include "oddspinbox.h"
#include "percentslider.h"
#include "limitedcombobox.h"
#include "projectioncombobox.h"
#include "dirselectwidget.h"
#include "optionsdialog.h"
@ -46,46 +46,18 @@ void OptionsDialog::automaticPauseDetectionSet(bool set)
QWidget *OptionsDialog::createMapPage()
{
int last = -1;
_outputProjection = new LimitedComboBox(200);
QList<KV<int, QString> > projections(GCS::list() + PCS::list());
std::sort(projections.begin(), projections.end());
for (int i = 0; i < projections.size(); i++) {
const KV<int, QString> &proj = projections.at(i);
// There may be same EPSG codes with different names
if (proj.key() == last)
continue;
else
last = proj.key();
QString text = QString::number(proj.key()) + " - " + proj.value();
_outputProjection->addItem(text, QVariant(proj.key()));
}
_outputProjection = new ProjectionComboBox();
_outputProjection->setCurrentIndex(_outputProjection->findData(
_options.outputProjection));
_inputProjection = new LimitedComboBox(200);
last = -1;
for (int i = 0; i < projections.size(); i++) {
const KV<int, QString> &proj = projections.at(i);
// There may be same EPSG codes with different names
if (proj.key() == last)
continue;
else
last = proj.key();
if (proj.key() == 4326 || proj.key() == 3857) {
QString text = QString::number(proj.key()) + " - " + proj.value();
_inputProjection->addItem(text, QVariant(proj.key()));
}
}
_inputProjection = new ProjectionComboBox();
_inputProjection->setCurrentIndex(_inputProjection->findData(
_options.inputProjection));
QLabel *inInfo = new QLabel(tr("Select the proper projection of"
" JNX and KMZ maps. Both EPSG:3857 and EPSG:4326 projected maps"
" exist and there is no projection info in the map file."));
QLabel *outInfo = new QLabel(tr("Select the desired projection of IMG"
" maps. The projection must be valid for the whole map area."));
QLabel *inInfo = new QLabel(tr("Select the proper projection of maps"
" without a projection definition (JNX, KMZ and world file maps)."));
QLabel *outInfo = new QLabel(tr("Select the desired projection of vector"
" maps (IMG and Mapsforge maps). The projection must be valid for"
" the whole map area."));
QFont f = inInfo->font();
f.setPointSize(f.pointSize() - 1);
inInfo->setWordWrap(true);
@ -568,12 +540,12 @@ QWidget *OptionsDialog::createDataPage()
sourceTab->setLayout(sourceTabLayout);
QTabWidget *filterPage = new QTabWidget();
filterPage->addTab(filterTab, tr("Filtering"));
filterPage->addTab(sourceTab, tr("Sources"));
filterPage->addTab(pauseTab, tr("Pause detection"));
QTabWidget *dataPage = new QTabWidget();
dataPage->addTab(filterTab, tr("Filtering"));
dataPage->addTab(sourceTab, tr("Sources"));
dataPage->addTab(pauseTab, tr("Pause detection"));
return filterPage;
return dataPage;
}
QWidget *OptionsDialog::createPOIPage()
@ -712,8 +684,35 @@ QWidget *OptionsDialog::createSystemPage()
systemTabLayout->addStretch();
systemTab->setLayout(systemTabLayout);
_dataPath = new DirSelectWidget();
_dataPath->setDir(_options.dataPath);
_mapsPath = new DirSelectWidget();
_mapsPath->setDir(_options.mapsPath);
_poiPath = new DirSelectWidget();
_poiPath->setDir(_options.poiPath);
QLabel *info = new QLabel(tr("Select the initial paths of the file open"
" dialogues. Leave the field empty for the system default."));
QFont f = info->font();
f.setPointSize(f.pointSize() - 1);
info->setFont(f);
info->setWordWrap(true);
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->addWidget(info);
pathsTabLayout->addLayout(pathsFormLayout);
pathsTabLayout->addStretch();
pathsTab->setLayout(pathsTabLayout);
QTabWidget *systemPage = new QTabWidget();
systemPage->addTab(systemTab, tr("System"));
systemPage->addTab(pathsTab, tr("Initial paths"));
return systemPage;
}
@ -836,6 +835,9 @@ void OptionsDialog::accept()
_options.enableHTTP2 = _enableHTTP2->isChecked();
_options.pixmapCache = _pixmapCache->value();
_options.connectionTimeout = _connectionTimeout->value();
_options.dataPath = _dataPath->dir();
_options.mapsPath = _mapsPath->dir();
_options.poiPath = _poiPath->dir();
_options.hiresPrint = _hires->isChecked();
_options.printName = _name->isChecked();

View File

@ -15,7 +15,8 @@ class QComboBox;
class QCheckBox;
class QRadioButton;
class PercentSlider;
class LimitedComboBox;
class ProjectionComboBox;
class DirSelectWidget;
struct Options {
@ -65,6 +66,9 @@ struct Options {
bool enableHTTP2;
int pixmapCache;
int connectionTimeout;
QString dataPath;
QString mapsPath;
QString poiPath;
// Print/Export
bool hiresPrint;
bool printName;
@ -121,8 +125,8 @@ private:
ColorBox *_sliderColor;
QCheckBox *_graphAA;
// Map
LimitedComboBox *_outputProjection;
LimitedComboBox *_inputProjection;
ProjectionComboBox *_outputProjection;
ProjectionComboBox *_inputProjection;
QRadioButton *_hidpi;
QRadioButton *_lodpi;
// Data
@ -154,6 +158,9 @@ private:
QSpinBox *_connectionTimeout;
QCheckBox *_useOpenGL;
QCheckBox *_enableHTTP2;
DirSelectWidget *_dataPath;
DirSelectWidget *_mapsPath;
DirSelectWidget *_poiPath;
// Print/Export
QRadioButton *_wysiwyg;
QRadioButton *_hires;

View File

@ -19,7 +19,10 @@ public:
void setDigitalZoom(int zoom) {setScale(pow(2, -zoom));}
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);

View File

@ -6,25 +6,31 @@
#include <QMouseEvent>
#include <QBasicTimer>
#include <QScreen>
#include <QVBoxLayout>
#include <QApplication>
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
#include <QDesktopWidget>
#endif // QT 5.15
#include "tooltip.h"
#include "thumbnail.h"
#include "flowlayout.h"
#include "popup.h"
class PopupLabel : public QLabel
class PopupFrame : public QFrame
{
public:
PopupLabel(const QString &text, QWidget *parent = 0);
~PopupLabel();
PopupFrame(const ToolTip &toolTip, QWidget *parent = 0);
~PopupFrame();
const ToolTip &toolTip() const {return _toolTip;}
bool eventFilter(QObject *o, QEvent *ev);
void place(const QPoint &pos, QWidget *w);
void deleteAfterTimer();
void stopTimer() {_timer.stop();}
static PopupLabel *_instance;
static PopupFrame *_instance;
protected:
void paintEvent(QPaintEvent *event);
@ -32,14 +38,17 @@ protected:
void contextMenuEvent(QContextMenuEvent *) {}
private:
void createLayout(const ToolTip &content);
QBasicTimer _timer;
ToolTip _toolTip;
};
PopupLabel *PopupLabel::_instance = 0;
PopupFrame *PopupFrame::_instance = 0;
PopupLabel::PopupLabel(const QString &text, QWidget *parent)
: QLabel(text, parent, Qt::ToolTip | Qt::BypassGraphicsProxyWidget
| Qt::WindowDoesNotAcceptFocus)
PopupFrame::PopupFrame(const ToolTip &toolTip, QWidget *parent)
: QFrame(parent, Qt::ToolTip | Qt::BypassGraphicsProxyWidget
| Qt::WindowDoesNotAcceptFocus), _toolTip(toolTip)
{
delete _instance;
_instance = this;
@ -48,39 +57,73 @@ PopupLabel::PopupLabel(const QString &text, QWidget *parent)
setBackgroundRole(QPalette::ToolTipBase);
setPalette(QToolTip::palette());
ensurePolished();
setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0,
this));
setFrameStyle(QFrame::NoFrame);
setAlignment(Qt::AlignLeft);
setIndent(1);
setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0,
this) / 255.0);
setTextInteractionFlags(Qt::TextBrowserInteraction);
setOpenExternalLinks(true);
setWordWrap(true);
createLayout(toolTip);
setMouseTracking(true);
qApp->installEventFilter(this);
}
PopupLabel::~PopupLabel()
PopupFrame::~PopupFrame()
{
_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);
QStyleOptionFrame opt;
opt.initFrom(this);
p.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
p.end();
QLabel::paintEvent(event);
QFrame::paintEvent(event);
}
void PopupLabel::timerEvent(QTimerEvent *event)
void PopupFrame::timerEvent(QTimerEvent *event)
{
if (event->timerId() == _timer.timerId()) {
_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);
@ -123,7 +166,7 @@ bool PopupLabel::eventFilter(QObject *o, QEvent *ev)
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)
QRect screen = QApplication::desktop()->screenGeometry(w);
@ -148,31 +191,34 @@ void PopupLabel::place(const QPoint &pos, QWidget *w)
this->move(p);
}
void PopupLabel::deleteAfterTimer()
void PopupFrame::deleteAfterTimer()
{
if (!_timer.isActive())
_timer.start(300, this);
}
void Popup::show(const QPoint &pos, const QString &text, QWidget *w)
void Popup::show(const QPoint &pos, const ToolTip &toolTip, QWidget *w)
{
if (text.isEmpty())
if (toolTip.isEmpty())
return;
if (PopupLabel::_instance) {
PopupLabel::_instance->stopTimer();
PopupLabel::_instance->setText(text);
if (PopupFrame::_instance) {
if (toolTip == PopupFrame::_instance->toolTip())
PopupFrame::_instance->stopTimer();
else {
delete PopupFrame::_instance;
PopupFrame::_instance = new PopupFrame(toolTip);
}
} else
PopupLabel::_instance = new PopupLabel(text);
PopupFrame::_instance = new PopupFrame(toolTip);
PopupLabel::_instance->resize(PopupLabel::_instance->sizeHint());
PopupLabel::_instance->place(pos, w);
PopupLabel::_instance->showNormal();
PopupFrame::_instance->resize(PopupFrame::_instance->sizeHint());
PopupFrame::_instance->place(pos, w);
PopupFrame::_instance->showNormal();
}
void Popup::clear()
{
if (PopupLabel::_instance)
delete PopupLabel::_instance;
if (PopupFrame::_instance)
delete PopupFrame::_instance;
}

View File

@ -2,13 +2,13 @@
#define POPUP_H
class QPoint;
class QString;
class QWidget;
class ToolTip;
class Popup
{
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();
};

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;
QLocale l(QLocale::system());
@ -19,5 +19,5 @@ QString PowerGraphItem::info() const
tt.insert(tr("Average"), l.toString(avg(), 'f', 1)
+ UNIT_SPACE + tr("W"));
return tt.toString();
return tt;
}

View File

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

View File

@ -0,0 +1,22 @@
#include "map/pcs.h"
#include "projectioncombobox.h"
ProjectionComboBox::ProjectionComboBox(QWidget *parent) : QComboBox(parent)
{
setSizeAdjustPolicy(AdjustToMinimumContentsLengthWithIcon);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
int last = -1;
QList<KV<int, QString> > projections(GCS::list() + PCS::list());
std::sort(projections.begin(), projections.end());
for (int i = 0; i < projections.size(); i++) {
const KV<int, QString> &proj = projections.at(i);
// There may be duplicit EPSG codes with different names
if (proj.key() == last)
continue;
else
last = proj.key();
QString text = QString::number(proj.key()) + " - " + proj.value();
addItem(text, QVariant(proj.key()));
}
}

View File

@ -0,0 +1,12 @@
#ifndef PROJECTIONCOMBOBOX_H
#define PROJECTIONCOMBOBOX_H
#include <QComboBox>
class ProjectionComboBox : public QComboBox
{
public:
ProjectionComboBox(QWidget *parent = 0);
};
#endif // PROJECTIONCOMBOBOX_H

View File

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

View File

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

View File

@ -205,5 +205,11 @@
#define INPUT_PROJECTION_DEFAULT 4326
#define HIDPI_MAP_SETTING "HiDPIMap"
#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

View File

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

View File

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

View File

@ -12,7 +12,7 @@ TemperatureGraphItem::TemperatureGraphItem(const Graph &graph, GraphType type,
_avg = GraphItem::avg();
}
QString TemperatureGraphItem::info() const
ToolTip TemperatureGraphItem::info() const
{
ToolTip tt;
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)
+ UNIT_SPACE + su);
return tt.toString();
return tt;
}

View File

@ -15,7 +15,7 @@ public:
qreal min() const {return _min;}
qreal avg() const {return _avg;}
QString info() const;
ToolTip info() const;
private:
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
{
public:
void insert(const QString &key, const QString &value);
void setImages(const QVector<ImageInfo> &images) {_images = images;}
QString toString() const;
const QList<KV<QString, QString> > &list() const {return _list;}
const QVector<ImageInfo> &images() const {return _images;}
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:
QList<KV<QString, QString> > _list;

View File

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

View File

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

View File

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

View File

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

View File

@ -9,8 +9,19 @@ public:
const KEY &key() const {return _key;}
const VALUE &value() const {return _value;}
bool operator==(const KV &other) const {return _key == other._key;}
bool operator<(const KV &other) const {return _key < other._key;}
bool operator==(const KV &other) const
{
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:
KEY _key;

View File

@ -63,5 +63,5 @@ bool CSV::readEntry(QStringList &list)
list.append(field);
return (state == 0);
return (_device->atEnd() && (state == 0 || state == 2));
}

View File

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

View File

@ -16,6 +16,11 @@ public:
bool isValid() const {return _size.isValid() && !_path.isEmpty();}
bool operator==(const ImageInfo &other) const
{
return (_path == other._path);
}
private:
QString _path;
QSize _size;

278
src/data/onmoveparsers.cpp Normal file
View File

@ -0,0 +1,278 @@
#include <QFileInfo>
#include <QDir>
#include <QtEndian>
#include "onmoveparsers.h"
static inline quint16 u16(const char *buffer)
{
return qFromLittleEndian<quint16>(buffer);
}
static inline qint16 s16(const char *buffer)
{
return qFromLittleEndian<qint16>(buffer);
}
static inline qint32 s32(const char *buffer)
{
return qFromLittleEndian<qint32>(buffer);
}
bool OMDParser::readHeaderFile(const QString &omdPath, Header &hdr)
{
QFileInfo fi(omdPath);
QString path = fi.absoluteDir().filePath(fi.baseName() + ".OMH");
QFile file(path);
char buffer[60];
if (!file.open(QIODevice::ReadOnly)) {
qWarning("%s: %s", qPrintable(path), qPrintable(file.errorString()));
return false;
}
if (file.read(buffer, sizeof(buffer)) != sizeof(buffer)) {
qWarning("%s: invalid OMH file", qPrintable(path));
return false;
}
quint8 Y = buffer[14];
quint8 M = buffer[15];
quint8 D = buffer[16];
quint8 h = buffer[17];
quint8 m = buffer[18];
quint16 ascent = u16(buffer + 22);
quint16 descent = u16(buffer + 24);
quint8 avgHr = buffer[12];
quint8 maxHr = buffer[13];
QDateTime date(QDate(Y + 2000, M, D), QTime(h, m), Qt::UTC);
if (!date.isValid()) {
qWarning("%s: invalid date", qPrintable(path));
return false;
}
hdr.date = date;
hdr.hr = avgHr || maxHr;
hdr.elevation = ascent || descent;
return true;
}
bool OMDParser::readF1(const char *chunk, const Header &hdr, Sequence &seq,
SegmentData &segment)
{
if (seq.cnt > 1) {
_errorString = "invalid chunk sequence";
return false;
}
qint32 lat = s32(chunk);
qint32 lon = s32(chunk + 4);
quint16 sec = u16(chunk + 12);
quint8 fia = chunk[14];
qint16 alt = s16(chunk + 15);
if (fia == 3) {
Trackpoint t(Coordinates(lon / 1000000.0, lat / 1000000.0));
if (!t.coordinates().isValid()) {
_errorString = "invalid coordinates";
return false;
}
t.setTimestamp(QDateTime(hdr.date.date(),
hdr.date.time().addSecs(sec), Qt::UTC));
if (hdr.elevation)
t.setElevation(alt);
seq.idx[seq.cnt] = segment.size();
segment.append(t);
} else
seq.idx[seq.cnt] = -1;
seq.cnt++;
return true;
}
bool OMDParser::readF2(const char *chunk, const Header &hdr, Sequence &seq,
SegmentData &segment)
{
if (!seq.cnt) {
_errorString = "invalid chunk sequence";
return false;
}
quint16 speed1 = u16(chunk + 2);
quint8 hr1 = chunk[6];
quint16 speed2 = u16(chunk + 12);
quint8 hr2 = chunk[16];
if (seq.idx[0] >= 0) {
Trackpoint &p0 = segment[seq.idx[0]];
if (hdr.hr)
p0.setHeartRate(hr1);
p0.setSpeed(speed1 / 360.0);
}
if (seq.idx[1] >= 0) {
Trackpoint &p1 = segment[seq.idx[1]];
if (hdr.hr)
p1.setHeartRate(hr2);
p1.setSpeed(speed2 / 360.0);
}
seq.idx[0] = -1;
seq.idx[1] = -1;
seq.cnt = 0;
return true;
}
bool OMDParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Area> &polygons, QVector<Waypoint> &waypoints)
{
Q_UNUSED(routes);
Q_UNUSED(waypoints);
Q_UNUSED(polygons);
SegmentData segment;
Header hdr;
Sequence seq;
char chunk[20];
qint64 size;
// If no header file is found or it is invalid, continue with the default
// header values. The track will have a fictional date and possibly some
// zero-graphs, but it will be still usable.
readHeaderFile(file->fileName(), hdr);
while ((size = file->read(chunk, sizeof(chunk))) == sizeof(chunk)) {
switch ((quint8)chunk[19]) {
case 0xF1:
if (!readF1(chunk, hdr, seq, segment))
return false;
break;
case 0xF2:
if (!readF2(chunk, hdr, seq, segment))
return false;
break;
default:
_errorString = "invalid chunk type";
return false;
}
}
if (size < 0) {
_errorString = "I/O error";
return false;
} else if (size) {
_errorString = "unexpected end of file";
return false;
}
tracks.append(TrackData());
tracks.last().append(segment);
return true;
}
bool GHPParser::readHeaderFile(const QString &ghpPath, Header &hdr)
{
QFileInfo fi(ghpPath);
QString path = fi.absoluteDir().filePath(fi.baseName() + ".GHT");
QFile file(path);
char buffer[96];
if (!file.open(QIODevice::ReadOnly)) {
qWarning("%s: %s", qPrintable(path), qPrintable(file.errorString()));
return false;
}
if (file.read(buffer, sizeof(buffer)) != sizeof(buffer)) {
qWarning("%s: invalid GHT file", qPrintable(path));
return false;
}
quint8 Y = buffer[0];
quint8 M = buffer[1];
quint8 D = buffer[2];
quint8 h = buffer[3];
quint8 m = buffer[4];
quint8 s = buffer[5];
quint8 avgHr = buffer[61];
quint8 maxHr = buffer[60];
QDateTime date(QDate(Y + 2000, M, D), QTime(h, m, s), Qt::UTC);
if (!date.isValid()) {
qWarning("%s: invalid date", qPrintable(path));
return false;
}
hdr.date = date;
hdr.hr = avgHr || maxHr;
return true;
}
bool GHPParser::readF0(const char *chunk, const Header &hdr, int &time,
SegmentData &segment)
{
qint32 lat = s32(chunk);
qint32 lon = s32(chunk + 4);
qint16 alt = s16(chunk + 8);
quint16 speed = u16(chunk + 10);
quint8 hr = chunk[12];
quint8 fia = chunk[13];
quint8 ms = chunk[16];
if (fia == 3) {
Trackpoint t(Coordinates(lon / 1000000.0, lat / 1000000.0));
if (!t.coordinates().isValid()) {
_errorString = "invalid coordinates";
return false;
}
t.setTimestamp(QDateTime(hdr.date.date(),
hdr.date.time().addMSecs(time * 100), Qt::UTC));
t.setSpeed(speed / 360.0);
t.setElevation(alt);
if (hdr.hr)
t.setHeartRate(hr);
segment.append(t);
}
time += ms;
return true;
}
bool GHPParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Area> &polygons, QVector<Waypoint> &waypoints)
{
Q_UNUSED(routes);
Q_UNUSED(waypoints);
Q_UNUSED(polygons);
SegmentData segment;
Header hdr;
int time = 0;
char chunk[20];
qint64 size;
// see OMD
readHeaderFile(file->fileName(), hdr);
while ((size = file->read(chunk, sizeof(chunk))) == sizeof(chunk))
if (!readF0(chunk, hdr, time, segment))
return false;
if (size < 0) {
_errorString = "I/O error";
return false;
} else if (size) {
_errorString = "unexpected end of file";
return false;
}
tracks.append(TrackData());
tracks.last().append(segment);
return true;
}

67
src/data/onmoveparsers.h Normal file
View File

@ -0,0 +1,67 @@
#ifndef ONMOVEPARSERS_H
#define ONMOVEPARSERS_H
#include "parser.h"
class OMDParser : public Parser
{
public:
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _errorString;}
int errorLine() const {return 0;}
private:
struct Header
{
Header() : date(QDateTime(QDate(1970, 1, 1), QTime(0, 0), Qt::UTC)),
elevation(true), hr(true) {}
QDateTime date;
bool elevation;
bool hr;
};
struct Sequence
{
Sequence() : cnt(0), idx{-1, -1} {}
unsigned cnt;
int idx[2];
};
bool readHeaderFile(const QString &omdPath, Header &hdr);
bool readF1(const char *chunk, const Header &hdr, Sequence &seq,
SegmentData &segment);
bool readF2(const char *chunk, const Header &hdr, Sequence &seq,
SegmentData &segment);
QString _errorString;
};
class GHPParser : public Parser
{
public:
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Area> &polygons, QVector<Waypoint> &waypoints);
QString errorString() const {return _errorString;}
int errorLine() const {return 0;}
private:
struct Header
{
Header() : date(QDateTime(QDate(1970, 1, 1), QTime(0, 0), Qt::UTC)),
hr(true) {}
QDateTime date;
bool hr;
};
bool readHeaderFile(const QString &ghpPath, Header &hdr);
bool readF0(const char *chunk, const Header &hdr, int &time,
SegmentData &segment);
QString _errorString;
};
#endif // ONMOVEPARSERS_H

View File

@ -34,7 +34,7 @@ bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
Q_UNUSED(routes);
Q_UNUSED(polygons);
bool res;
const GCS *gcs = 0;
GCS gcs;
_errorLine = 1;
_errorString.clear();
@ -54,7 +54,8 @@ bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
return false;
}
} else if (_errorLine == 2) {
if (!(gcs = GCS::gcs(QString(line.trimmed())))) {
gcs = GCS::gcs(QString(line.trimmed()));
if (gcs.isNull()) {
_errorString = "Invalid/unknown datum";
return false;
}
@ -80,7 +81,7 @@ bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
return false;
}
Trackpoint tp(gcs->toWGS84(Coordinates(lon, lat)));
Trackpoint tp(gcs.toWGS84(Coordinates(lon, lat)));
if (list.size() >= 4) {
QByteArray field(list.at(3).trimmed());
@ -125,7 +126,7 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
Q_UNUSED(tracks);
Q_UNUSED(polygons);
bool res, record = false;
const GCS *gcs = 0;
GCS gcs;
_errorLine = 1;
_errorString.clear();
@ -141,7 +142,8 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
return false;
}
} else if (_errorLine == 2) {
if (!(gcs = GCS::gcs(QString(line.trimmed())))) {
gcs = GCS::gcs(QString(line.trimmed()));
if (gcs.isNull()) {
_errorString = "Invalid/unknown datum";
return false;
}
@ -181,7 +183,7 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
return false;
}
Waypoint wp(gcs->toWGS84(Coordinates(lon, lat)));
Waypoint wp(gcs.toWGS84(Coordinates(lon, lat)));
QByteArray name(list.at(4).trimmed());
if (!name.isEmpty())
@ -225,7 +227,7 @@ bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
Q_UNUSED(routes);
Q_UNUSED(polygons);
bool res;
const GCS *gcs = 0;
GCS gcs;
_errorLine = 1;
_errorString.clear();
@ -240,7 +242,8 @@ bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
return false;
}
} else if (_errorLine == 2) {
if (!(gcs = GCS::gcs(QString(line.trimmed())))) {
gcs = GCS::gcs(QString(line.trimmed()));
if (gcs.isNull()) {
_errorString = "Invalid/unknown datum";
return false;
}
@ -262,7 +265,7 @@ bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
return false;
}
Waypoint wp(gcs->toWGS84(Coordinates(lon, lat)));
Waypoint wp(gcs.toWGS84(Coordinates(lon, lat)));
QByteArray name(list.at(1).trimmed());
if (!name.isEmpty())

View File

@ -23,13 +23,13 @@ void SMLParser::sample(SegmentData &segment, QMap<QDateTime, Sensors> &map)
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("Latitude")) {
lat = _reader.readElementText().toDouble(&ok);
if (!ok || lat < -90 || lon > 90) {
if (!ok || lat < -90 || lat > 90) {
_reader.raiseError("Invalid Latitude");
return;
}
} else if (_reader.name() == QLatin1String("Longitude")) {
lon = _reader.readElementText().toDouble(&ok);
if (!ok || lat < -180 || lon > 180) {
if (!ok || lon < -180 || lon > 180) {
_reader.raiseError("Invalid Longitude");
return;
}

View File

@ -6,8 +6,6 @@
using namespace IMG;
typedef QMap<QByteArray, VectorTile*> TileMap;
static SubFile::Type tileType(const char str[3])
{
if (!memcmp(str, "TRE", 3))
@ -26,25 +24,25 @@ static SubFile::Type tileType(const char str[3])
return SubFile::Unknown;
}
IMGData::IMGData(const QString &fileName) : _fileName(fileName)
bool IMGData::readSubFileBlocks(QFile &file, quint64 offset, SubFile *subFile)
{
#define CHECK(condition) \
if (!(condition)) { \
_errorString = "Unsupported or invalid IMG file"; \
qDeleteAll(tileMap); \
return; \
quint16 block;
if (!file.seek(offset + 0x20))
return false;
for (int i = 0; i < 240; i++) {
if (!readValue(file, block))
return false;
if (block == 0xFFFF)
break;
subFile->addBlock(block);
}
QFile file(fileName);
TileMap tileMap;
QByteArray typFile;
return true;
}
if (!file.open(QFile::ReadOnly)) {
_errorString = file.errorString();
return;
}
// Read IMG header
bool IMGData::readIMGHeader(QFile &file)
{
char signature[7], identifier[7];
file.read((char*)&_key, 1) && file.seek(0x10)
&& read(file, signature, sizeof(signature)) && file.seek(0x41)
@ -52,24 +50,35 @@ IMGData::IMGData(const QString &fileName) : _fileName(fileName)
if (memcmp(signature, "DSKIMG", sizeof(signature))
|| memcmp(identifier, "GARMIN", sizeof(identifier))) {
_errorString = "Not a Garmin IMG file";
return;
return false;
}
char d1[20], d2[31];
quint8 e1, e2;
CHECK(file.seek(0x49) && read(file, d1, sizeof(d1)) && file.seek(0x61)
if (!(file.seek(0x49) && read(file, d1, sizeof(d1)) && file.seek(0x61)
&& readValue(file, e1) && readValue(file, e2) && file.seek(0x65)
&& read(file, d2, sizeof(d2)));
&& read(file, d2, sizeof(d2)))) {
_errorString = "Error reading IMG header";
return false;
}
QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2)));
_name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed();
_blockBits = e1 + e2;
// Read the FAT table
return true;
}
bool IMGData::readFAT(QFile &file, TileMap &tileMap)
{
QByteArray typFile;
quint8 flag;
quint64 offset = 0x200;
// Skip unused FAT blocks if any
while (true) {
CHECK(file.seek(offset) && readValue(file, flag));
if (!(file.seek(offset) && readValue(file, flag)))
return false;
if (flag)
break;
offset += 512;
@ -79,17 +88,18 @@ IMGData::IMGData(const QString &fileName) : _fileName(fileName)
char name[8], type[3];
quint32 size;
quint16 part;
CHECK(file.seek(offset + 12) && readValue(file, size));
if (!(file.seek(offset + 12) && readValue(file, size)))
return false;
offset += 512;
int cnt = (size - offset) / 512;
// Read FAT blocks describing the IMG sub-files
for (int i = 0; i < cnt; i++) {
quint16 block;
CHECK(file.seek(offset) && readValue(file, flag)
if (!(file.seek(offset) && readValue(file, flag)
&& read(file, name, sizeof(name))
&& read(file, type, sizeof(type)) && readValue(file, size)
&& readValue(file, part));
&& readValue(file, part)))
return false;
SubFile::Type tt = tileType(type);
QByteArray fn(name, sizeof(name));
@ -104,15 +114,8 @@ IMGData::IMGData(const QString &fileName) : _fileName(fileName)
SubFile *subFile = part ? tile->file(tt)
: tile->addFile(this, tt);
CHECK(subFile);
CHECK(file.seek(offset + 0x20));
for (int i = 0; i < 240; i++) {
CHECK(readValue(file, block));
if (block == 0xFFFF)
break;
subFile->addBlock(block);
}
if (!(subFile && readSubFileBlocks(file, offset, subFile)))
return false;
} else if (tt == SubFile::TYP) {
SubFile *typ = 0;
if (typFile.isNull()) {
@ -122,28 +125,26 @@ IMGData::IMGData(const QString &fileName) : _fileName(fileName)
} else if (fn == typFile)
typ = _typ;
if (typ) {
CHECK(file.seek(offset + 0x20));
for (int i = 0; i < 240; i++) {
CHECK(readValue(file, block));
if (block == 0xFFFF)
break;
typ->addBlock(block);
}
}
if (typ && !readSubFileBlocks(file, offset, typ))
return false;
}
offset += 512;
}
// Create tile tree
return true;
}
bool IMGData::createTileTree(const TileMap &tileMap)
{
int minMapZoom = 24;
for (TileMap::const_iterator it = tileMap.constBegin();
it != tileMap.constEnd(); ++it) {
VectorTile *tile = it.value();
if (!tile->init()) {
qWarning("%s: %s: Invalid map tile", qPrintable(file.fileName()),
qWarning("%s: %s: Invalid map tile", qPrintable(_fileName),
qPrintable(it.key()));
delete tile;
continue;
@ -177,10 +178,32 @@ IMGData::IMGData(const QString &fileName) : _fileName(fileName)
if (!_baseMap)
_zooms.setMin(_zooms.min() - 2);
if (!_tileTree.Count())
return (_tileTree.Count() > 0);
}
IMGData::IMGData(const QString &fileName) : _fileName(fileName)
{
QFile file(fileName);
TileMap tileMap;
if (!file.open(QFile::ReadOnly)) {
_errorString = file.errorString();
return;
}
if (!readIMGHeader(file))
return;
if (!readFAT(file, tileMap)) {
_errorString = "Error reading FAT data";
qDeleteAll(tileMap);
return;
}
if (!createTileTree(tileMap)) {
_errorString = "No usable map tile found";
else
_valid = true;
return;
}
_valid = true;
}
qint64 IMGData::read(QFile &file, char *data, qint64 maxSize) const

View File

@ -18,8 +18,14 @@ public:
bool readBlock(QFile &file, int blockNum, char *data) const;
private:
typedef QMap<QByteArray, VectorTile*> TileMap;
qint64 read(QFile &file, char *data, qint64 maxSize) const;
template<class T> bool readValue(QFile &file, T &val) const;
bool readSubFileBlocks(QFile &file, quint64 offset, SubFile *subFile);
bool readFAT(QFile &file, TileMap &tileMap);
bool readIMGHeader(QFile &file);
bool createTileTree(const TileMap &tileMap);
QString _fileName;
quint8 _key;

View File

@ -57,6 +57,12 @@ static QString capitalized(const QString &str)
return ret;
}
static QByteArray ft2m(const QByteArray &str)
{
bool ok;
int number = str.toInt(&ok);
return ok ? QByteArray::number(qRound(number * 0.3048)) : str;
}
LBLFile::~LBLFile()
{
@ -130,13 +136,15 @@ void LBLFile::clear()
_rasters = 0;
}
Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize) const
Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize,
bool convert) const
{
Shield::Type shieldType = Shield::None;
QByteArray label, shieldLabel;
QByteArray *bap = &label;
Charset curCharSet = Normal;
quint8 b1, b2, b3;
int split = -1;
if (!seek(hdl, offset))
return Label();
@ -149,6 +157,10 @@ Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize) const
for (int cpt = 0; cpt < 4; cpt++) {
if (c[cpt] > 0x2f || (curCharSet == Normal && c[cpt] == 0x1d)) {
if (split >= 0)
label = label.left(split) + ft2m(label.mid(split));
else if (convert)
label = ft2m(label);
QString text(QString::fromLatin1(label));
return Label(capitalize && isAllUpperCase(text)
? capitalized(text) : text, Shield(shieldType, shieldLabel));
@ -159,7 +171,16 @@ Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize) const
curCharSet = Symbol;
else if (c[cpt] == 0x1b)
curCharSet = Special;
else if (c[cpt] >= 0x2a && c[cpt] <= 0x2f) {
else if (c[cpt] >= 0x1e && c[cpt] <= 0x1f) {
if (bap == &shieldLabel)
bap = &label;
else {
if (!bap->isEmpty())
bap->append('\n');
if (c[cpt] == 0x1f && split < 0)
split = bap->size();
}
} else if (c[cpt] >= 0x2a && c[cpt] <= 0x2f) {
shieldType = static_cast<Shield::Type>(c[cpt] - 0x29);
bap = &shieldLabel;
} else if (bap == &shieldLabel
@ -181,11 +202,13 @@ Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize) const
}
}
Label LBLFile::str2label(const QVector<quint8> &str, bool capitalize) const
Label LBLFile::str2label(const QVector<quint8> &str, bool capitalize,
bool convert) const
{
Shield::Type shieldType = Shield::None;
QByteArray label, shieldLabel;
QByteArray *bap = &label;
int split = -1;
for (int i = 0; i < str.size(); i++) {
const quint8 &c = str.at(i);
@ -198,8 +221,12 @@ Label LBLFile::str2label(const QVector<quint8> &str, bool capitalize) const
else if ((c >= 0x1e && c <= 0x1f)) {
if (bap == &shieldLabel)
bap = &label;
else
bap->append(' ');
else {
if (!bap->isEmpty())
bap->append('\n');
if (c == 0x1f && split < 0)
split = bap->size();
}
} else if (c < 0x07) {
shieldType = static_cast<Shield::Type>(c);
bap = &shieldLabel;
@ -209,13 +236,17 @@ Label LBLFile::str2label(const QVector<quint8> &str, bool capitalize) const
bap->append(c);
}
if (split >= 0)
label = label.left(split) + ft2m(label.mid(split));
else if (convert)
label = ft2m(label);
QString text(_codec.toString(label));
return Label(capitalize && isAllUpperCase(text) ? capitalized(text) : text,
Shield(shieldType, _codec.toString(shieldLabel)));
}
Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize,
bool convert) const
{
QVector<quint8> str;
quint8 c;
@ -229,10 +260,11 @@ Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
str.append(c);
} while (c);
return str2label(str, capitalize);
return str2label(str, capitalize, convert);
}
Label LBLFile::labelHuffman(Handle &hdl, quint32 offset, bool capitalize) const
Label LBLFile::labelHuffman(Handle &hdl, quint32 offset, bool capitalize,
bool convert) const
{
QVector<quint8> str;
@ -241,7 +273,7 @@ Label LBLFile::labelHuffman(Handle &hdl, quint32 offset, bool capitalize) const
if (!_huffmanText->decode(this, hdl, str))
return Label();
if (!_table)
return str2label(str, capitalize);
return str2label(str, capitalize, convert);
QVector<quint8> str2;
@ -268,10 +300,11 @@ Label LBLFile::labelHuffman(Handle &hdl, quint32 offset, bool capitalize) const
}
}
return str2label(str2, capitalize);
return str2label(str2, capitalize, convert);
}
Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize) const
Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize,
bool convert) const
{
quint32 labelOffset;
if (poi) {
@ -289,12 +322,12 @@ Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize) con
switch (_encoding) {
case 6:
return label6b(hdl, labelOffset, capitalize);
return label6b(hdl, labelOffset, capitalize, convert);
case 9:
case 10:
return label8b(hdl, labelOffset, capitalize);
return label8b(hdl, labelOffset, capitalize, convert);
case 11:
return labelHuffman(hdl, labelOffset, capitalize);
return labelHuffman(hdl, labelOffset, capitalize, convert);
default:
return Label();
}

View File

@ -32,7 +32,7 @@ public:
void clear();
Label label(Handle &hdl, quint32 offset, bool poi = false,
bool capitalize = true) const;
bool capitalize = true, bool convert = false) const;
quint8 imageIdSize() const {return _imgOffsetIdSize;}
QPixmap image(Handle &hdl, quint32 id) const;
@ -43,10 +43,14 @@ private:
quint32 size;
};
Label str2label(const QVector<quint8> &str, bool capitalize) const;
Label label6b(Handle &hdl, quint32 offset, bool capitalize) const;
Label label8b(Handle &hdl, quint32 offset, bool capitalize) const;
Label labelHuffman(Handle &hdl, quint32 offset, bool capitalize) const;
Label str2label(const QVector<quint8> &str, bool capitalize,
bool convert) const;
Label label6b(Handle &hdl, quint32 offset, bool capitalize,
bool convert) const;
Label label8b(Handle &hdl, quint32 offset, bool capitalize,
bool convert) const;
Label labelHuffman(Handle &hdl, quint32 offset, bool capitalize,
bool convert) const;
bool loadRasterTable(Handle &hdl, quint32 offset, quint32 size,
quint32 recordSize);

View File

@ -411,9 +411,9 @@ void NETFile::clear()
}
bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
const NODFile *nod, Handle &nodHdl, const LBLFile *lbl, Handle &lblHdl,
const NODFile::BlockInfo &blockInfo, quint8 linkId, quint8 lineId,
QList<MapData::Poly> *lines) const
const NODFile *nod, Handle &nodHdl2, Handle &nodHdl, const LBLFile *lbl,
Handle &lblHdl, const NODFile::BlockInfo &blockInfo, quint8 linkId,
quint8 lineId, QList<MapData::Poly> *lines) const
{
MapData::Poly poly;
if (!nod->linkType(nodHdl, blockInfo, linkId, poly.type))
@ -433,24 +433,24 @@ bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
quint16 mask = 0;
quint32 size;
quint8 s68 = (linkInfo.flags >> 0x12) & 1;
quint8 s69 = (linkInfo.flags >> 0x11) & 1;
quint8 s6a = (linkInfo.flags >> 0x13) & 1;
bool firstIsShape = (linkInfo.flags >> 0x12) & 1;
bool singleTopology = (linkInfo.flags >> 0x11) & 1;
bool hasLevels = (linkInfo.flags >> 0x13) & 1;
if (s69 == 0 || s6a == 1) {
if (!singleTopology || hasLevels) {
if (!bs.readVUInt32(size))
return false;
}
if (s69 == 0) {
if (!singleTopology) {
if (!readAdjCounts(bs, ca, mask))
return false;
}
if (!subdiv->level()) {
NODFile::AdjacencyInfo adj(nod, blockInfo, linkId, linkInfo);
NODFile::AdjacencyInfo adj(nodHdl2, blockInfo, linkId, linkInfo);
if (s69 == 1) {
if (s68 == 1) {
if (singleTopology) {
if (firstIsShape) {
if (!readShape(nod, nodHdl, adj, bs, _tp, subdiv, shift, poly))
return false;
} else {
@ -461,7 +461,7 @@ bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
quint16 mask2 = mask + 0xffff;
for (int i = 0; i <= ca.size(); i++) {
quint16 step = (i < ca.size()) ? ca.at(i) & mask2 : 0xFFFF;
bool shape = (i > 0) ? ca.at(i-1) & mask : (s68 == 1);
bool shape = (i > 0) ? ca.at(i-1) & mask : firstIsShape;
if (i == lineId) {
if (shape) {
bool check = (i < ca.size()) ? (ca.at(i) & mask) : false;
@ -482,7 +482,9 @@ bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
}
}
} else {
if (!skipAdjShapes(bs, ca, mask, s68 == 1))
Q_ASSERT(hasLevels);
if (!skipAdjShapes(bs, ca, mask, firstIsShape))
return false;
if (!seekToLevel(bs, subdiv->level()))

View File

@ -30,9 +30,10 @@ public:
bool lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset) const;
bool link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
const NODFile *nod, Handle &nodHdl, const LBLFile *lbl, Handle &lblHdl,
const NODFile::BlockInfo &blockInfo, quint8 linkId, quint8 lineId,
QList<MapData::Poly> *lines) const;
const NODFile *nod, Handle &nodHdl2, Handle &nodHdl, const LBLFile *lbl,
Handle &lblHdl, const NODFile::BlockInfo &blockInfo, quint8 linkId,
quint8 lineId, QList<MapData::Poly> *lines) const;
bool hasLinks() const {return (_linksSize > 0);}
private:
bool linkLabel(Handle &hdl, quint32 offset, quint32 size,

View File

@ -40,13 +40,13 @@ public:
struct AdjacencyInfo
{
AdjacencyInfo(const SubFile *file, const BlockInfo &blockInfo,
quint32 linkId, const LinkInfo &linkInfo) : extHdl(file),
AdjacencyInfo(Handle &hdl, const BlockInfo &blockInfo,
quint32 linkId, const LinkInfo &linkInfo) : extHdl(hdl),
blockInfo(blockInfo), nodeOffset(linkInfo.nodeOffset),
linkOffset(linkInfo.linkOffset), linkId(linkId)
{}
Handle extHdl;
Handle &extHdl;
BlockInfo blockInfo;
NodeInfo nodeInfo;
quint32 nodeOffset;

View File

@ -1,5 +1,6 @@
#include <QFont>
#include <QPainter>
#include <QCache>
#include "map/imgmap.h"
#include "map/textpathitem.h"
#include "map/textpointitem.h"
@ -20,34 +21,6 @@ static const QColor shieldBgColor1("#dd3e3e");
static const QColor shieldBgColor2("#379947");
static const QColor shieldBgColor3("#4a7fc1");
static QString convertUnits(const QString &str)
{
bool ok;
int number = str.toInt(&ok);
return ok ? QString::number(qRound(number * 0.3048)) : str;
}
static int minPOIZoom(Style::POIClass cl)
{
switch (cl) {
case Style::Food:
case Style::Shopping:
case Style::Services:
return 26;
case Style::Accommodation:
case Style::Recreation:
return 25;
case Style::ManmadePlaces:
case Style::NaturePlaces:
case Style::Transport:
case Style::Community:
case Style::Elementary:
return 23;
default:
return 0;
}
}
static QFont pixelSizeFont(int pixelSize)
{
QFont f;
@ -216,6 +189,8 @@ void RasterTile::ll2xy(QList<MapData::Point> &points)
void RasterTile::drawPolygons(QPainter *painter)
{
QCache<const LBLFile *, SubFile::Handle> hc(16);
for (int n = 0; n < _style->drawOrder().size(); n++) {
for (int i = 0; i < _polygons.size(); i++) {
const MapData::Poly &poly = _polygons.at(i);
@ -226,12 +201,19 @@ void RasterTile::drawPolygons(QPainter *painter)
RectC r(poly.raster.rect());
QPointF tl(_map->ll2xy(r.topLeft()));
QPointF br(_map->ll2xy(r.bottomRight()));
QSize size(QRectF(tl, br).toRect().size());
QSizeF size(QRectF(tl, br).size());
SubFile::Handle hdl(poly.raster.lbl());
QPixmap pm(poly.raster.lbl()->image(hdl, poly.raster.id()));
qreal sx = (qreal)size.width() / (qreal)pm.width();
qreal sy = (qreal)size.height() / (qreal)pm.height();
bool insert = false;
SubFile::Handle *hdl = hc.object(poly.raster.lbl());
if (!hdl) {
hdl = new SubFile::Handle(poly.raster.lbl());
insert = true;
}
QPixmap pm(poly.raster.lbl()->image(*hdl, poly.raster.id()));
if (insert)
hc.insert(poly.raster.lbl(), hdl);
qreal sx = size.width() / (qreal)pm.width();
qreal sy = size.height() / (qreal)pm.height();
painter->save();
painter->scale(sx, sy);
@ -361,9 +343,6 @@ void RasterTile::processStreetNames(const QRect &tileRect,
|| style.textFontSize() == Style::None)
continue;
if (Style::isContourLine(poly.type))
poly.label.setText(convertUnits(poly.label.text()));
const QFont *fnt = font(style.textFontSize(), Style::Small);
const QColor *color = style.textColor().isValid()
? &style.textColor() : 0;
@ -450,9 +429,6 @@ void RasterTile::processPoints(QList<TextItem*> &textItems)
const Style::Point &style = _style->point(point.type);
bool poi = Style::isPOI(point.type);
if (poi && _zoom < minPOIZoom(Style::poiClass(point.type)))
continue;
const QString *label = point.label.text().isEmpty()
? 0 : &(point.label.text());
const QImage *img = style.img().isNull() ? 0 : &style.img();
@ -464,14 +440,6 @@ void RasterTile::processPoints(QList<TextItem*> &textItems)
if ((!label || !fnt) && !img)
continue;
if (Style::isSpot(point.type))
point.label.setText(convertUnits(point.label.text()));
if (Style::isSummit(point.type) && !point.label.text().isEmpty()) {
QStringList list = point.label.text().split(" ");
list.last() = convertUnits(list.last());
point.label = list.join(" ");
}
TextPointItem *item = new TextPointItem(QPoint(point.coordinates.lon(),
point.coordinates.lat()), label, fnt, img, color, &haloColor);
if (item->isValid() && !item->collides(textItems))

View File

@ -10,7 +10,7 @@
using namespace IMG;
#define MASK(bits) ((2U << ((bits) - 1U)) - 1U)
#define MASK(bits) ((1U << (bits)) - 1U)
static quint64 pointId(const QPoint &pos, quint32 type, quint32 labelPtr)
{
@ -237,9 +237,11 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
quint32 lblOff;
if (net && net->lblOffset(netHdl, labelPtr & 0x3FFFFF, lblOff)
&& lblOff)
poly.label = lbl->label(lblHdl, lblOff);
poly.label = lbl->label(lblHdl, lblOff, false, true,
Style::isContourLine(poly.type));
} else
poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, false,
true, Style::isContourLine(poly.type));
}
polys->append(poly);
@ -351,7 +353,8 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
return false;
if (lbl && (labelPtr & 0x3FFFFF))
poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, false, true,
Style::isContourLine(poly.type));
polys->append(poly);
}
@ -396,7 +399,7 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
if (lbl && (labelPtr & 0x3FFFFF))
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF,
labelPtr & 0x400000, !(Style::isCountry(point.type)
|| Style::isState(point.type)));
|| Style::isState(point.type)), Style::isSpot(point.type));
points->append(point);
}
@ -446,7 +449,7 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv,
point.coordinates = Coordinates(toWGS24(pos.x()), toWGS24(pos.y()));
point.id = pointId(pos, point.type, labelPtr & 0x3FFFFF);
if (lbl && (labelPtr & 0x3FFFFF))
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, false);
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
points->append(point);
}
@ -456,7 +459,8 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv,
bool RGNFile::links(Handle &hdl, const SubDiv *subdiv, quint32 shift,
const NETFile *net, Handle &netHdl, const NODFile *nod, Handle &nodHdl,
const LBLFile *lbl, Handle &lblHdl, QList<MapData::Poly> *lines) const
Handle &nodHdl2, const LBLFile *lbl, Handle &lblHdl,
QList<MapData::Poly> *lines) const
{
quint32 size, blockIndexId;
quint8 flags;
@ -522,7 +526,7 @@ bool RGNFile::links(Handle &hdl, const SubDiv *subdiv, quint32 shift,
lineId = 0;
}
net->link(subdiv, shift, netHdl, nod, nodHdl, lbl, lblHdl,
net->link(subdiv, shift, netHdl, nod, nodHdl, nodHdl2, lbl, lblHdl,
blockInfo, linkId, lineId, lines);
}

View File

@ -51,7 +51,8 @@ public:
Handle &lblHdl, QList<MapData::Point> *points) const;
bool links(Handle &hdl, const SubDiv *subdiv, quint32 shift,
const NETFile *net, Handle &netHdl, const NODFile *nod, Handle &nodHdl,
const LBLFile *lbl, Handle &lblHdl, QList<MapData::Poly> *lines) const;
Handle &nodHdl2, const LBLFile *lbl, Handle &lblHdl,
QList<MapData::Poly> *lines) const;
bool subdivInit(Handle &hdl, SubDiv *subdiv) const;

View File

@ -1126,39 +1126,6 @@ const Style::Point &Style::point(quint32 type) const
return (it == _points.constEnd()) ? null : *it;
}
Style::POIClass Style::poiClass(quint32 type)
{
if ((type >= 0x2a00 && type < 0x2b00) || type == 0x2c0a || type == 0x2d02
|| (type & 0xffff00) == TYPE(0x10b))
return Food;
else if ((type >= 0x2b00 && type < 0x2c00)
|| (type & 0xffff00) == TYPE(0x10c))
return Accommodation;
else if ((type >= 0x2c00 && type < 0x2e00)
|| (type & 0xffff00) == TYPE(0x10d) || (type & 0xffff00) == TYPE(0x10e))
return Recreation;
else if ((type >= 0x2e00 && type < 0x2f00)
|| (type & 0xffff00) == TYPE(0x10f))
return Shopping;
else if ((type >= 0x2f00 && type < 0x2f0f) || type == 0x2f17
|| (type >= 0x11001 && type < 0x1100f))
return Transport;
else if ((type >= 0x2f0f && type < 0x3000)
|| (type >= 0x1100f && type < 0x11100))
return Services;
else if ((type >= 0x3000 && type < 0x3100)
|| (type & 0xffff00) == TYPE(0x111))
return Community;
else if (type >= 0x4000 && type < 0x6000)
return Elementary;
else if (type >= 0x6400 && type < 0x6500)
return ManmadePlaces;
else if (type >= 0x6500 && type < 0x6700)
return NaturePlaces;
else
return Unknown;
}
#ifndef QT_NO_DEBUG
static QString penColor(const QPen &pen)
{

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