1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-04 22:59:29 +02:00

Compare commits

...

101 Commits
9.12 ... 10.2

Author SHA1 Message Date
c0e2597dcc Merge branch 'origin/master' into Weblate. 2022-01-20 23:50:24 +01:00
ff0affc8ec Version++ 2022-01-20 23:50:23 +01:00
e38772c9b6 Added default DEM download URL 2022-01-20 23:48:38 +01:00
713876d7a4 Merge branch 'origin/master' into Weblate. 2022-01-18 21:31:18 +01:00
d0e0ea32ab Prefer GPS positioning sources if available 2022-01-18 21:30:50 +01:00
2529ea9932 Translated using Weblate (Esperanto)
Currently translated at 92.7% (407 of 439 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/eo/
2022-01-17 17:52:48 +01:00
025313edb0 Translated using Weblate (Russian)
Currently translated at 100.0% (439 of 439 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2022-01-17 17:52:48 +01:00
86dbc58e8e Translated using Weblate (Finnish)
Currently translated at 97.9% (430 of 439 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2022-01-17 17:52:48 +01:00
3117127a3e Merge branch 'origin/master' into Weblate. 2022-01-14 00:15:44 +01:00
76c2da9b50 Do not buffer the I/O as we are already reading in blocks 2022-01-14 00:13:40 +01:00
39ab3d7a85 Translated using Weblate (French)
Currently translated at 100.0% (439 of 439 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fr/
2022-01-13 09:54:57 +01:00
53b34ff24c Added missing TLS plugins to Qt6 build 2022-01-10 21:54:39 +01:00
00a9adce1e Also ignore invalid dates in waypoint lines 2022-01-04 09:37:26 +01:00
c4e0ff6435 Ignore invalid dates
fixes #416
2022-01-03 23:21:55 +01:00
40616fb868 Do not load icons from the current directory when no symbols dir is set 2022-01-03 23:20:58 +01:00
c062a62014 Do not duplicate the suffixes in the formats list 2022-01-03 23:20:03 +01:00
1000dd3fc1 Added missing TwoNav mime-types 2022-01-02 12:43:34 +01:00
50374fc222 Fixed typo 2022-01-01 22:42:33 +01:00
2cc97f8e36 TRK format Mac integration 2022-01-01 22:39:37 +01:00
44aed958a5 Translation update 2022-01-01 21:21:30 +01:00
cb2dfd9155 Merge branch 'origin/master' into Weblate. 2022-01-01 21:06:53 +01:00
7d98a797f5 Added TRK files Windows association 2022-01-01 21:06:33 +01:00
b17d7eac5f Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (439 of 439 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/zh_Hans/
2021-12-27 11:51:43 +01:00
f24f2abb4d Translated using Weblate (Hungarian)
Currently translated at 100.0% (439 of 439 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2021-12-27 09:11:32 +01:00
d9c66c11e0 Translated using Weblate (Turkish)
Currently translated at 100.0% (439 of 439 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2021-12-27 09:11:32 +01:00
1ed2685802 Translated using Weblate (Swedish)
Currently translated at 100.0% (439 of 439 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2021-12-27 09:11:32 +01:00
0483cdb5db Added missing features info 2021-12-25 13:17:49 +01:00
e4c4961e7a Merge branch 'origin/master' into Weblate. 2021-12-25 13:17:33 +01:00
4fbe7f7571 TwoNav data files Linux desktop integration 2021-12-25 13:01:42 +01:00
87c82ec75f Merge branch 'origin/master' into Weblate. 2021-12-25 13:01:31 +01:00
2655091b95 Localization update 2021-12-25 12:39:43 +01:00
9b5b422aef Added flags icons 2021-12-25 12:31:41 +01:00
c6e7393df7 Merge branch 'origin/master' into Weblate. 2021-12-25 12:31:16 +01:00
a42280dec3 Parse waypoint symbols
+ fixed error handling
2021-12-24 15:09:19 +01:00
4f1c2a7ea3 Merge branch 'origin/master' into Weblate. 2021-12-24 15:09:06 +01:00
93377964d8 Properly sort the file types list 2021-12-24 14:46:37 +01:00
421ab19e7a Demangle waypoint names 2021-12-24 14:40:01 +01:00
01e6053400 Merge branch 'origin/master' into Weblate. 2021-12-24 14:39:46 +01:00
f55e5d639d Fixed build with Qt < 5.14 2021-12-24 14:08:39 +01:00
306fefe8db Merge branch 'origin/master' into Weblate. 2021-12-24 14:08:11 +01:00
cedaeb1185 Version++ 2021-12-24 13:48:08 +01:00
42a39f3eb3 Merge branch 'origin/master' into Weblate. 2021-12-24 13:47:36 +01:00
23400a8c3a Merge branch 'origin/master' into Weblate. 2021-12-24 13:44:22 +01:00
e6fd92266d Translated using Weblate (Finnish)
Currently translated at 97.9% (429 of 438 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2021-12-24 13:44:22 +01:00
321357b74d Added support for TwoNav data files (trk, rte, wpt)
Resolves #411
2021-12-24 13:43:23 +01:00
897e075505 Translated using Weblate (Hungarian)
Currently translated at 100.0% (438 of 438 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2021-12-16 09:54:22 +01:00
932aadee5f Added Korean localization stub 2021-12-14 20:35:19 +01:00
32bf7f0dfa Localization files update 2021-12-14 20:34:43 +01:00
b539eb8ed8 Translated using Weblate (Esperanto)
Currently translated at 92.6% (406 of 438 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/eo/
2021-12-09 10:52:11 +01:00
741e95cb63 Translated using Weblate (Ukrainian)
Currently translated at 90.8% (398 of 438 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/uk/
2021-12-09 10:52:10 +01:00
c161e35379 Translated using Weblate (Russian)
Currently translated at 100.0% (438 of 438 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2021-12-09 10:52:10 +01:00
d09b937e10 Translated using Weblate (Finnish)
Currently translated at 96.8% (424 of 438 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2021-12-09 10:52:10 +01:00
a1d7689879 Translated using Weblate (Russian)
Currently translated at 98.1% (430 of 438 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2021-12-08 08:53:30 +01:00
7ff7303eab Added real-time GPS position info 2021-12-08 08:04:27 +01:00
5789982024 Added missing mimetypes 2021-12-08 01:26:30 +01:00
0861b0a0b4 Merge branch 'origin/master' into Weblate. 2021-12-06 22:59:40 +01:00
0e735d5726 Translated using Weblate (Hungarian)
Currently translated at 100.0% (438 of 438 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2021-12-06 22:59:40 +01:00
308ca9c702 Added missing image validity check
(invalid images cause a divide-by-zero error later in the code)
2021-12-06 22:58:49 +01:00
b1ea38b6ac Merge branch 'origin/master' into Weblate. 2021-12-05 21:30:16 +01:00
428fb934c4 Minor linux CI configuration tweaks 2021-12-05 21:30:08 +01:00
c4066ef66b Merge branch 'origin/master' into Weblate. 2021-12-05 18:14:34 +01:00
f5523b68a9 Fixed build with Qt < 5.14 2021-12-05 18:14:31 +01:00
f692e38711 Merge branch 'origin/master' into Weblate. 2021-12-05 15:55:22 +01:00
2d43768f81 It's qtpositioning, not qtlocation... 2021-12-05 15:55:17 +01:00
bbfd0d8735 Merge branch 'origin/master' into Weblate. 2021-12-05 15:52:56 +01:00
5dd8dd524a Added missing Qt location dev package install 2021-12-05 15:52:46 +01:00
04c989d3b7 Merge branch 'origin/master' into Weblate. 2021-12-05 15:48:26 +01:00
42f35f95a8 Added missing "apt-get update" 2021-12-05 15:48:25 +01:00
7861d8f6d8 Added missing sudo 2021-12-05 15:42:03 +01:00
9dc9cf9991 Merge branch 'origin/master' into Weblate. 2021-12-05 15:41:56 +01:00
355ddda1e6 Merge branch 'origin/master' into Weblate. 2021-12-05 15:40:35 +01:00
901a44d1e4 Translated using Weblate (Turkish)
Currently translated at 100.0% (438 of 438 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2021-12-05 15:40:35 +01:00
5424b64679 Added Linux CI target 2021-12-05 15:40:34 +01:00
e4d68de963 Merge remote-tracking branch 'weblate/master' 2021-12-05 10:37:50 +01:00
ace03b2003 Merge branch 'origin/master' into Weblate. 2021-12-05 10:37:45 +01:00
97029233e9 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (438 of 438 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/zh_Hans/
2021-12-05 10:37:45 +01:00
c9a4506cbb German translation update 2021-12-05 10:37:23 +01:00
851c64c3ec Czech translation update 2021-12-05 10:37:03 +01:00
7fdc182687 Merge branch 'origin/master' into Weblate. 2021-12-05 00:59:08 +01:00
3e0fb14a75 Fixed plugin parameters saving 2021-12-05 00:57:58 +01:00
ae0604793e Translated using Weblate (Chinese (Simplified))
Currently translated at 97.2% (426 of 438 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/zh_Hans/
2021-12-04 23:13:29 +01:00
0432665aeb Translated using Weblate (Swedish)
Currently translated at 100.0% (438 of 438 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2021-12-04 21:44:05 +01:00
b7b6a3fe53 Merge branch 'origin/master' into Weblate. 2021-12-04 15:13:00 +01:00
1e3132c9b3 Localization update 2021-12-04 15:12:59 +01:00
b4925843c8 Merge branch 'origin/master' into Weblate. 2021-12-04 15:06:36 +01:00
fa55c6d93a Added positioning support 2021-12-04 15:05:30 +01:00
682da37ea6 Merge branch 'origin/master' into Weblate. 2021-11-27 10:42:51 +01:00
a4d91ef17a Added workaround for broken FIT files exported by Strava
Fixes #410
2021-11-27 10:41:39 +01:00
7922840b4f Merge branch 'origin/master' into Weblate. 2021-11-16 23:17:39 +01:00
9119ebd2cf Merge branch 'origin/master' into Weblate. 2021-11-16 23:11:16 +01:00
1589fe27e9 Merge branch 'origin/master' into Weblate. 2021-11-16 23:10:42 +01:00
a2e1937e32 Merge branch 'origin/master' into Weblate. 2021-11-16 23:10:10 +01:00
35184abbe7 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (423 of 423 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/zh_Hans/
2021-11-16 23:05:27 +01:00
9253703a69 Translated using Weblate (Esperanto)
Currently translated at 94.3% (399 of 423 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/eo/
2021-11-16 23:05:26 +01:00
edb3395d95 Translated using Weblate (Hungarian)
Currently translated at 100.0% (423 of 423 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2021-11-16 23:05:26 +01:00
39574704b0 Translated using Weblate (Turkish)
Currently translated at 100.0% (423 of 423 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2021-11-16 23:05:26 +01:00
5298110a0e Translated using Weblate (Russian)
Currently translated at 100.0% (423 of 423 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2021-11-16 23:05:26 +01:00
a1a96e1066 Translated using Weblate (Finnish)
Currently translated at 98.1% (415 of 423 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2021-11-16 23:05:25 +01:00
1c2e1fd5c5 Translated using Weblate (Swedish)
Currently translated at 100.0% (423 of 423 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2021-11-15 22:40:54 +01:00
ae6f91a762 Translated using Weblate (German)
Currently translated at 100.0% (423 of 423 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/de/
2021-11-15 21:34:54 +01:00
9a3d81e8de Translated using Weblate (Czech)
Currently translated at 100.0% (423 of 423 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/cs/
2021-11-15 21:34:54 +01:00
65 changed files with 10388 additions and 5392 deletions

View File

@ -1,4 +1,4 @@
version: 9.12.{build}
version: 10.2.{build}
configuration:
- Release

24
.github/workflows/linux.yml vendored Normal file
View File

@ -0,0 +1,24 @@
name: Linux
on:
push:
branches:
- master
jobs:
build:
name: GPXSee
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install qtbase5-dev qtbase5-private-dev qtbase5-dev-tools qt5-qmake qttools5-dev-tools libqt5opengl5-dev qtpositioning5-dev
- name: Create localization
run: lrelease gpxsee.pro
- name: Configure build
run: qmake gpxsee.pro
- name: Build project
run: make -j2

View File

@ -4,8 +4,8 @@ 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, TomTom OV2&ITN, ONmove OMD/GHP and
geotagged JPEG files.
OziExplorer (PLT, RTE, WPT), Garmin GPI&CSV, TomTom OV2&ITN, ONmove OMD/GHP,
TwoNav (TRK, RTE, WPT) and geotagged JPEG files.
* User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS,
QuadTiles).
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases,
@ -20,6 +20,7 @@ GPS log file formats.
* Print/export to PDF/PNG.
* Full-screen mode.
* HiDPI/Retina displays & maps support.
* Real-time GPS position.
* Native GUI for Windows, Mac OS X and Linux.
![GPXSee - Linux](https://a.fsdn.com/con/app/proj/gpxsee/screenshots/linux2.png)

View File

@ -3,7 +3,7 @@ unix:!macx {
} else {
TARGET = GPXSee
}
VERSION = 9.12
VERSION = 10.2
QT += core \
gui \
@ -12,7 +12,8 @@ QT += core \
sql \
concurrent \
widgets \
printsupport
printsupport \
positioning
greaterThan(QT_MAJOR_VERSION, 5) {
QT += openglwidgets \
core5compat
@ -21,6 +22,9 @@ greaterThan(QT_MAJOR_VERSION, 5) {
CONFIG += object_parallel_to_source
INCLUDEPATH += ./src
HEADERS += src/common/config.h \
src/GUI/crosshairitem.h \
src/GUI/motioninfoitem.h \
src/GUI/pluginparameters.h \
src/common/garmin.h \
src/common/coordinates.h \
src/common/range.h \
@ -108,6 +112,7 @@ HEADERS += src/common/config.h \
src/GUI/pngexportdialog.h \
src/GUI/timezoneinfo.h \
src/GUI/passwordedit.h \
src/data/twonavparser.h \
src/map/proj/polyconic.h \
src/map/proj/webmercator.h \
src/map/proj/transversemercator.h \
@ -238,6 +243,9 @@ HEADERS += src/common/config.h \
src/data/geojsonparser.h
SOURCES += src/main.cpp \
src/GUI/crosshairitem.cpp \
src/GUI/motioninfoitem.cpp \
src/GUI/pluginparameters.cpp \
src/common/coordinates.cpp \
src/common/rectc.cpp \
src/common/range.cpp \
@ -305,6 +313,7 @@ SOURCES += src/main.cpp \
src/GUI/pngexportdialog.cpp \
src/GUI/projectioncombobox.cpp \
src/GUI/passwordedit.cpp \
src/data/twonavparser.cpp \
src/map/proj/polyconic.cpp \
src/map/proj/webmercator.cpp \
src/map/proj/transversemercator.cpp \
@ -488,7 +497,8 @@ win32 {
icons/formats/wld.ico \
icons/formats/omd.ico \
icons/formats/ghp.ico \
icons/formats/qct.ico
icons/formats/qct.ico \
icons/formats/trk.ico
DEFINES += _USE_MATH_DEFINES \
NOGDI
}

View File

@ -49,6 +49,10 @@
<file alias="document-decrypt@2x.png">icons/GUI/document-decrypt.png</file>
<file alias="document-encrypt.png">icons/GUI/document-encrypt.png</file>
<file alias="document-encrypt@2x.png">icons/GUI/document-encrypt.png</file>
<file alias="transform-move.png">icons/GUI/transform-move.png</file>
<file alias="transform-move@2x.png">icons/GUI/transform-move@2x.png</file>
<file alias="transform-move_32.png">icons/GUI/transform-move_32.png</file>
<file alias="transform-move_32@2x.png">icons/GUI/transform-move_32@2x.png</file>
</qresource>
<!-- IMG map style -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -28,3 +28,4 @@ wld:#c74c8f
omd:#ed09cb
ghp:#ed09cb
qct:#370642
trk:#cccccc

BIN
icons/formats/trk.icns Normal file

Binary file not shown.

BIN
icons/formats/trk.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 B

BIN
icons/symbols/Flag, Red.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 B

BIN
icons/symbols/Flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 827 B

After

Width:  |  Height:  |  Size: 747 B

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

2365
lang/gpxsee_ko.ts Normal file

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

@ -594,6 +594,22 @@
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>trk</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/vnd.twonav.trk</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>icons/trk.icns</string>
<key>CFBundleTypeName</key>
<string>TwoNav Track File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
<key>UTImportedTypeDeclarations</key>
@ -1407,6 +1423,29 @@
<string>application/vnd.memory-map.qct</string>
</dict>
</dict>
<dict>
<key>UTTypeIdentifier</key>
<string>com.twonav.trk</string>
<key>UTTypeReferenceURL</key>
<string>https://github.com/GPSBabel/gpsbabel/blob/master/deprecated/compegps.cc</string>
<key>UTTypeDescription</key>
<string>TwoNav Track File</string>
<key>UTTypeIconFile</key>
<string>icons/trk.icns</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>trk</string>
</array>
<key>public.mime-type</key>
<string>application/vnd.twonav.trk</string>
</dict>
</dict>
</array>
<key>UTExportedTypeDeclarations</key>

View File

@ -14,8 +14,8 @@
<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, ONmove OMD/GHP
and geotagged JPEG files.</li>
Garmin GPI &amp; CSV, TomTom OV2 &amp; ITN, ONmove OMD/GHP,
TwoNav (TRK, RTE, WPT) 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,
@ -30,6 +30,7 @@
<li>Print/export to PDF &amp; PNG.</li>
<li>Full-screen mode.</li>
<li>HiDPI/Retina displays &amp; maps support.</li>
<li>Real-time GPS position.</li>
</ul>
</description>
@ -98,5 +99,8 @@
<mimetype>application/vnd.onmove.omd</mimetype>
<mimetype>application/vnd.onmove.ghp</mimetype>
<mimetype>application/vnd.memory-map.qct</mimetype>
<mimetype>application/vnd.twonav.trk</mimetype>
<mimetype>application/vnd.twonav.rte</mimetype>
<mimetype>application/vnd.twonav.wpt</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;application/vnd.esri.wld
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;application/vnd.onmove.omd;application/vnd.onmove.ghp;application/vnd.memory-map.qct;application/vnd.twonav.trk;application/vnd.twonav.rte;application/vnd.twonav.wpt

View File

@ -156,6 +156,28 @@
<glob pattern="*.ghp"/>
</mime-type>
<mime-type type="application/vnd.twonav.trk">
<comment>TwoNav Track File</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text/plain"/>
<glob pattern="*.trk"/>
</mime-type>
<mime-type type="application/vnd.twonav.rte">
<comment>TwoNav Route File</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text/plain"/>
<glob pattern="*.rte"/>
</mime-type>
<mime-type type="application/vnd.twonav.wpt">
<comment>TwoNav Waypoint File</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text/plain"/>
<glob pattern="*.wpt"/>
</mime-type>
<!-- Maps -->
<mime-type type="application/vnd.garmin.img">

View File

@ -37,7 +37,7 @@ Unicode true
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "9.12"
!define VERSION "10.2"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"
@ -178,13 +178,14 @@ Section "GPXSee" SEC_APP
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 22
!insertmacro FILE_ASSOCIATION_ADD "ghp" "ONmove Log File" 23
!insertmacro FILE_ASSOCIATION_ADD "qct" "QuickChart Map File" 24
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 25
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 25
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 26
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 27
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 28
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 29
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 30
!insertmacro FILE_ASSOCIATION_ADD "trk" "TwoNav Track File" 25
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 26
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 26
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 27
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 28
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 29
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 30
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 31
WriteRegStr HKCR "Applications\GPXSee.exe\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
WriteRegStr HKCR ".gpx\OpenWithList" "GPXSee.exe" ""
@ -231,6 +232,7 @@ Section "GPXSee" SEC_APP
WriteRegStr HKCR ".omd\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".ghp\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".qct\OpenWithList" "GPXSee.exe" ""
WriteRegStr HKCR ".trk\OpenWithList" "GPXSee.exe" ""
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
@ -252,6 +254,9 @@ Section "QT framework" SEC_QT
File "Qt6Svg.dll"
File "Qt6Widgets.dll"
File "Qt6Core5Compat.dll"
File "Qt6Positioning.dll"
File "Qt6SerialPort.dll"
File /r "tls"
!else
File "Qt5Core.dll"
File "Qt5Gui.dll"
@ -261,12 +266,15 @@ Section "QT framework" SEC_QT
File "Qt5Sql.dll"
File "Qt5Svg.dll"
File "Qt5Concurrent.dll"
File "Qt5Positioning.dll"
File "Qt5SerialPort.dll"
File /r "printsupport"
!endif
File /r "platforms"
File /r "imageformats"
File /r "styles"
File /r "sqldrivers"
File /r "position"
SectionEnd
@ -376,6 +384,7 @@ Section "Uninstall"
!insertmacro FILE_ASSOCIATION_REMOVE "omd"
!insertmacro FILE_ASSOCIATION_REMOVE "ghp"
!insertmacro FILE_ASSOCIATION_REMOVE "qct"
!insertmacro FILE_ASSOCIATION_REMOVE "trk"
DeleteRegValue HKCR ".gpx\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".tcx\OpenWithList" "GPXSee.exe"
@ -421,6 +430,7 @@ Section "Uninstall"
DeleteRegValue HKCR ".omd\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".ghp\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".qct\OpenWithList" "GPXSee.exe"
DeleteRegValue HKCR ".trk\OpenWithList" "GPXSee.exe"
DeleteRegKey HKCR "Applications\GPXSee.exe"
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
@ -453,4 +463,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

@ -7,10 +7,13 @@
CoordinatesItem::CoordinatesItem(QGraphicsItem *parent) : QGraphicsItem(parent)
{
_format = DecimalDegrees;
_units = Metric;
_ele = NAN;
_color = Qt::black;
_bgColor = Qt::white;
_drawBackground = false;
_font.setPixelSize(FONT_SIZE);
_font.setFamily(FONT_FAMILY);
_digitalZoom = 0;
setAcceptHoverEvents(true);
@ -27,24 +30,36 @@ void CoordinatesItem::paint(QPainter *painter,
if (!_c.isValid())
return;
if (_drawBackground) {
painter->setPen(Qt::NoPen);
QColor bc(_bgColor);
bc.setAlpha(196);
painter->setBrush(QBrush(bc));
painter->drawRect(_boundingRect);
painter->setBrush(Qt::NoBrush);
}
QFontMetrics fm(_font);
painter->setFont(_font);
painter->setPen(QPen(Qt::black));
painter->drawText(0, -fm.descent(), Format::coordinates(_c, _format));
painter->setPen(QPen(_color));
painter->drawText(0, -fm.descent(), text());
/*
painter->setPen(Qt::red);
painter->drawRect(boundingRect());
*/
//painter->setPen(Qt::red);
//painter->drawRect(boundingRect());
}
void CoordinatesItem::setCoordinates(const Coordinates &c)
void CoordinatesItem::setCoordinates(const Coordinates &c, qreal elevation)
{
prepareGeometryChange();
_c = c;
_ele = elevation;
updateBoundingRect();
update();
}
void CoordinatesItem::setFormat(const CoordinatesFormat &format)
void CoordinatesItem::setFormat(CoordinatesFormat format)
{
prepareGeometryChange();
@ -52,16 +67,54 @@ void CoordinatesItem::setFormat(const CoordinatesFormat &format)
updateBoundingRect();
}
void CoordinatesItem::setUnits(Units units)
{
prepareGeometryChange();
_units = units;
updateBoundingRect();
}
void CoordinatesItem::setDigitalZoom(qreal zoom)
{
_digitalZoom = zoom;
setScale(pow(2, -_digitalZoom));
}
QString CoordinatesItem::text() const
{
return (std::isnan(_ele))
? Format::coordinates(_c, _format)
: Format::coordinates(_c, _format) + ", " + Format::elevation(_ele, _units);
}
void CoordinatesItem::updateBoundingRect()
{
QFontMetrics fm(_font);
_boundingRect = fm.tightBoundingRect(Format::coordinates(
Coordinates(-180, -90), _format));
_boundingRect.moveBottom(-fm.descent());
QRectF br(fm.tightBoundingRect(text()));
QRectF r1(br);
QRectF r2(br);
r1.moveTop(-fm.ascent());
r2.moveBottom(-fm.descent());
_boundingRect = r1 | r2;
}
void CoordinatesItem::setColor(const QColor &color)
{
_color = color;
update();
}
void CoordinatesItem::setBackgroundColor(const QColor &color)
{
_bgColor = color;
update();
}
void CoordinatesItem::drawBackground(bool draw)
{
_drawBackground = draw;
update();
}

View File

@ -17,18 +17,27 @@ public:
CoordinatesFormat format() const {return _format;}
void setCoordinates(const Coordinates &c);
void setFormat(const CoordinatesFormat &format);
void setCoordinates(const Coordinates &c, qreal elevation = NAN);
void setFormat(CoordinatesFormat format);
void setUnits(Units units);
void setDigitalZoom(qreal zoom);
void setColor(const QColor &color);
void setBackgroundColor(const QColor &color);
void drawBackground(bool draw);
private:
void updateBoundingRect();
QString text() const;
Coordinates _c;
qreal _ele;
CoordinatesFormat _format;
Units _units;
QRectF _boundingRect;
QFont _font;
qreal _digitalZoom;
QColor _color, _bgColor;
bool _drawBackground;
};
#endif // COORDINATESITEM_H

45
src/GUI/crosshairitem.cpp Normal file
View File

@ -0,0 +1,45 @@
#include <QPainter>
#include "crosshairitem.h"
#define SIZE 16
#define WIDTH 2
CrosshairItem::CrosshairItem(QGraphicsItem *parent) : QGraphicsItem(parent)
{
_color = Qt::red;
_digitalZoom = 0;
}
QRectF CrosshairItem::boundingRect() const
{
return QRectF(-SIZE/2, -SIZE/2, SIZE, SIZE);
}
void CrosshairItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setRenderHint(QPainter::Antialiasing, false);
painter->setPen(QPen(_color, WIDTH));
painter->drawLine(-SIZE/2, 0, -SIZE/4, 0);
painter->drawLine(SIZE/4, 0, SIZE/2, 0);
painter->drawLine(0, -SIZE/2, 0, -SIZE/4);
painter->drawLine(0, SIZE/4, 0, SIZE/2);
//painter->drawRect(boundingRect());
}
void CrosshairItem::setDigitalZoom(qreal zoom)
{
_digitalZoom = zoom;
setScale(pow(2, -_digitalZoom));
}
void CrosshairItem::setColor(const QColor &color)
{
_color = color;
update();
}

30
src/GUI/crosshairitem.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef CROSSHAIRITEM_H
#define CROSSHAIRITEM_H
#include <QGraphicsItem>
#include "map/map.h"
class CrosshairItem : public QGraphicsItem
{
public:
CrosshairItem(QGraphicsItem *parent = 0);
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget);
const Coordinates &coordinates() const {return _c;}
const QColor &color() const {return _color;}
void setCoordinates(const Coordinates &c) {_c = c;}
void setMap(Map *map) {setPos(map->ll2xy(_c));}
void setDigitalZoom(qreal zoom);
void setColor(const QColor &color);
private:
Coordinates _c;
QColor _color;
qreal _digitalZoom;
};
#endif // CROSSHAIRITEM_H

View File

@ -25,6 +25,7 @@
#include <QScreen>
#include <QStyle>
#include <QTabBar>
#include <QGeoPositionInfoSource>
#include "common/programpaths.h"
#include "common/downloader.h"
#include "data/data.h"
@ -327,7 +328,32 @@ void GUI::createActions()
_showCoordinatesAction->setMenuRole(QAction::NoRole);
_showCoordinatesAction->setCheckable(true);
connect(_showCoordinatesAction, &QAction::triggered, _mapView,
&MapView::showCoordinates);
&MapView::showCursorCoordinates);
// Position
_showPositionAction = new QAction(QIcon(SHOW_POS_ICON),
tr("Show position"), this);
_showPositionAction->setMenuRole(QAction::NoRole);
_showPositionAction->setCheckable(true);
_showPositionAction->setEnabled(false);
connect(_showPositionAction, &QAction::triggered, _mapView,
&MapView::showPosition);
_followPositionAction = new QAction(tr("Follow position"), this);
_followPositionAction->setMenuRole(QAction::NoRole);
_followPositionAction->setCheckable(true);
connect(_followPositionAction, &QAction::triggered, _mapView,
&MapView::followPosition);
_showPositionCoordinatesAction = new QAction(tr("Show coordinates"),
this);
_showPositionCoordinatesAction->setMenuRole(QAction::NoRole);
_showPositionCoordinatesAction->setCheckable(true);
connect(_showPositionCoordinatesAction, &QAction::triggered, _mapView,
&MapView::showPositionCoordinates);
_showMotionInfo = new QAction(tr("Show motion info"), this);
_showMotionInfo->setMenuRole(QAction::NoRole);
_showMotionInfo->setCheckable(true);
connect(_showMotionInfo, &QAction::triggered, _mapView,
&MapView::showMotionInfo);
// Data actions
_showTracksAction = new QAction(tr("Show tracks"), this);
@ -613,6 +639,13 @@ void GUI::createMenus()
demMenu->addAction(_showDEMTilesAction);
demMenu->addAction(_downloadDEMAction);
QMenu *positionMenu = menuBar()->addMenu(tr("Position"));
positionMenu->addAction(_showPositionCoordinatesAction);
positionMenu->addAction(_showMotionInfo);
positionMenu->addAction(_followPositionAction);
positionMenu->addSeparator();
positionMenu->addAction(_showPositionAction);
QMenu *settingsMenu = menuBar()->addMenu(tr("&Settings"));
QMenu *timeMenu = settingsMenu->addMenu(tr("Time"));
timeMenu->addAction(_totalTimeAction);
@ -663,6 +696,7 @@ void GUI::createToolBars()
_showToolBar->addAction(_showPOIAction);
_showToolBar->addAction(_showMapAction);
_showToolBar->addAction(_showGraphsAction);
_showToolBar->addAction(_showPositionAction);
_navigationToolBar = addToolBar(tr("Navigation"));
_navigationToolBar->setObjectName("Navigation");
@ -676,7 +710,7 @@ void GUI::createToolBars()
void GUI::createMapView()
{
_map = new EmptyMap(this);
_mapView = new MapView(_map, _poi, this);
_mapView = new MapView(_map, _poi, 0, this);
_mapView->setSizePolicy(QSizePolicy(QSizePolicy::Ignored,
QSizePolicy::Expanding));
_mapView->setMinimumHeight(200);
@ -1018,6 +1052,19 @@ void GUI::openOptions()
SET_VIEW_OPTION(pathAntiAliasing, useAntiAliasing);
SET_VIEW_OPTION(useOpenGL, useOpenGL);
SET_VIEW_OPTION(sliderColor, setMarkerColor);
SET_VIEW_OPTION(crosshairColor, setCrosshairColor);
SET_VIEW_OPTION(infoColor, setInfoColor);
SET_VIEW_OPTION(infoBackground, drawInfoBackground);
if (options.plugin != _options.plugin
|| options.pluginParams.value(options.plugin)
!= _options.pluginParams.value(_options.plugin)) {
QGeoPositionInfoSource *source = positionSource(options);
_showPositionAction->setEnabled(source != 0);
_mapView->setPositionSource(source);
delete _positionSource;
_positionSource = source;
}
if (options.hidpiMap != _options.hidpiMap)
_mapView->setDevicePixelRatio(devicePixelRatioF(),
@ -2096,8 +2143,27 @@ void GUI::dropEvent(QDropEvent *event)
event->acceptProposedAction();
}
QGeoPositionInfoSource *GUI::positionSource(const Options &options)
{
QGeoPositionInfoSource *source;
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
source = QGeoPositionInfoSource::createSource(options.plugin, this);
#else // QT 5.14
source = QGeoPositionInfoSource::createSource(options.plugin,
options.pluginParams.value(options.plugin), this);
#endif // QT 5.14
if (source)
source->setPreferredPositioningMethods(
QGeoPositionInfoSource::SatellitePositioningMethods);
return source;
}
void GUI::writeSettings()
{
int index;
QSettings settings(qApp->applicationName(), qApp->applicationName());
settings.clear();
@ -2133,8 +2199,8 @@ void GUI::writeSettings()
settings.setValue(CURRENT_MAP_SETTING, _map->name());
if (_showMapAction->isChecked() != SHOW_MAP_DEFAULT)
settings.setValue(SHOW_MAP_SETTING, _showMapAction->isChecked());
if (_showCoordinatesAction->isChecked() != SHOW_COORDINATES_DEFAULT)
settings.setValue(SHOW_COORDINATES_SETTING,
if (_showCoordinatesAction->isChecked() != SHOW_CURSOR_COORDINATES_DEFAULT)
settings.setValue(SHOW_CURSOR_COORDINATES_SETTING,
_showCoordinatesAction->isChecked());
settings.endGroup();
@ -2165,21 +2231,37 @@ void GUI::writeSettings()
settings.setValue(SHOW_POI_ICONS_SETTING,
_showPOIIconsAction->isChecked());
int j = 0;
index = 0;
QList<QAction*> poiActions(_poisActionGroup->actions());
for (int i = 0; i < poiActions.count(); i++) {
POIAction *a = static_cast<POIAction*>(poiActions.at(i));
if (!a->isChecked()) {
if (j == 0)
if (index == 0)
settings.beginWriteArray(DISABLED_POI_FILE_SETTINGS_PREFIX);
settings.setArrayIndex(j++);
settings.setArrayIndex(index++);
settings.setValue(DISABLED_POI_FILE_SETTING, a->data().toString());
}
}
if (j != 0)
if (index != 0)
settings.endArray();
settings.endGroup();
settings.beginGroup(POSITION_SETTINGS_GROUP);
if (_showPositionAction->isChecked() != SHOW_POSITION_DEFAULT)
settings.setValue(SHOW_POSITION_SETTING,
_showPositionAction->isChecked());
if (_followPositionAction->isChecked() != FOLLOW_POSITION_DEFAULT)
settings.setValue(FOLLOW_POSITION_SETTING,
_followPositionAction->isChecked());
if (_showPositionCoordinatesAction->isChecked()
!= SHOW_POSITION_COORDINATES_DEFAULT)
settings.setValue(SHOW_POSITION_COORDINATES_SETTING,
_showPositionCoordinatesAction->isChecked());
if (_showMotionInfo->isChecked() != SHOW_MOTION_INFO_DEFAULT)
settings.setValue(SHOW_MOTION_INFO_SETTING,
_showMotionInfo->isChecked());
settings.endGroup();
settings.beginGroup(DATA_SETTINGS_GROUP);
if (_showTracksAction->isChecked() != SHOW_TRACKS_DEFAULT)
settings.setValue(SHOW_TRACKS_SETTING, _showTracksAction->isChecked());
@ -2262,6 +2344,12 @@ void GUI::writeSettings()
settings.setValue(MAP_OPACITY_SETTING, _options.mapOpacity);
if (_options.backgroundColor != BACKGROUND_COLOR_DEFAULT)
settings.setValue(BACKGROUND_COLOR_SETTING, _options.backgroundColor);
if (_options.crosshairColor != CROSSHAIR_COLOR_DEFAULT)
settings.setValue(CROSSHAIR_COLOR_SETTING, _options.crosshairColor);
if (_options.infoColor != INFO_COLOR_DEFAULT)
settings.setValue(INFO_COLOR_SETTING, _options.infoColor);
if (_options.infoBackground != INFO_BACKGROUND_DEFAULT)
settings.setValue(INFO_BACKGROUND_SETTING, _options.infoBackground);
if (_options.trackWidth != TRACK_WIDTH_DEFAULT)
settings.setValue(TRACK_WIDTH_SETTING, _options.trackWidth);
if (_options.routeWidth != ROUTE_WIDTH_DEFAULT)
@ -2333,6 +2421,22 @@ void GUI::writeSettings()
settings.setValue(DEM_USERNAME_SETTING, _options.demUsername);
if (_options.demPassword != DEM_PASSWORD_DEFAULT)
settings.setValue(DEM_PASSWORD_SETTING, _options.demPassword);
// the plugins order is random so always store the value
settings.setValue(POSITION_PLUGIN_SETTING, _options.plugin);
index = 0;
for (QMap<QString, QVariantMap>::const_iterator it
= _options.pluginParams.constBegin();
it != _options.pluginParams.constEnd(); ++it) {
if (!it.value().isEmpty()) {
if (index == 0)
settings.beginWriteArray(POSITION_PLUGIN_PARAMS_PREFIX);
settings.setArrayIndex(index++);
settings.setValue(POSITION_PLUGIN_PARAMS_PLUGIN, it.key());
settings.setValue(POSITION_PLUGIN_PARAMS_PARAM, it.value());
}
}
if (index != 0)
settings.endArray();
if (_options.useOpenGL != USE_OPENGL_DEFAULT)
settings.setValue(USE_OPENGL_SETTING, _options.useOpenGL);
if (_options.enableHTTP2 != ENABLE_HTTP2_DEFAULT)
@ -2419,10 +2523,10 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
_showMapAction->setChecked(true);
else
_mapView->showMap(false);
if (settings.value(SHOW_COORDINATES_SETTING, SHOW_COORDINATES_DEFAULT)
if (settings.value(SHOW_CURSOR_COORDINATES_SETTING, SHOW_CURSOR_COORDINATES_DEFAULT)
.toBool()) {
_showCoordinatesAction->setChecked(true);
_mapView->showCoordinates(true);
_mapView->showCursorCoordinates(true);
}
activeMap = settings.value(CURRENT_MAP_SETTING).toString();
settings.endGroup();
@ -2577,6 +2681,12 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
MAP_OPACITY_DEFAULT).toInt();
_options.backgroundColor = settings.value(BACKGROUND_COLOR_SETTING,
BACKGROUND_COLOR_DEFAULT).value<QColor>();
_options.crosshairColor = settings.value(CROSSHAIR_COLOR_SETTING,
CROSSHAIR_COLOR_DEFAULT).value<QColor>();
_options.infoColor = settings.value(INFO_COLOR_SETTING,
INFO_COLOR_DEFAULT).value<QColor>();
_options.infoBackground = settings.value(INFO_BACKGROUND_SETTING,
INFO_BACKGROUND_DEFAULT).toBool();
_options.trackWidth = settings.value(TRACK_WIDTH_SETTING,
TRACK_WIDTH_DEFAULT).toInt();
_options.routeWidth = settings.value(ROUTE_WIDTH_SETTING,
@ -2645,6 +2755,16 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
DEM_USERNAME_DEFAULT).toString();
_options.demPassword = settings.value(DEM_PASSWORD_SETTING,
DEM_PASSWORD_DEFAULT).toString();
_options.plugin = settings.value(POSITION_PLUGIN_SETTING,
POSITION_PLUGIN_DEFAULT).toString();
size = settings.beginReadArray(POSITION_PLUGIN_PARAMS_PREFIX);
for (int i = 0; i < size; i++) {
settings.setArrayIndex(i);
_options.pluginParams.insert(
settings.value(POSITION_PLUGIN_PARAMS_PLUGIN).toString(),
settings.value(POSITION_PLUGIN_PARAMS_PARAM).toMap());
}
settings.endArray();
_options.useOpenGL = settings.value(USE_OPENGL_SETTING, USE_OPENGL_DEFAULT)
.toBool();
_options.enableHTTP2 = settings.value(ENABLE_HTTP2_SETTING,
@ -2683,10 +2803,30 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
.toString();
_options.poiPath = settings.value(POI_PATH_SETTING, POI_PATH_DEFAULT)
.toString();
settings.endGroup();
_positionSource = positionSource(_options);
_showPositionAction->setEnabled(_positionSource != 0);
settings.beginGroup(POSITION_SETTINGS_GROUP);
if (settings.value(SHOW_POSITION_SETTING, SHOW_POSITION_DEFAULT).toBool())
_showPositionAction->trigger();
if (settings.value(FOLLOW_POSITION_SETTING, FOLLOW_POSITION_DEFAULT).toBool())
_followPositionAction->trigger();
if (settings.value(SHOW_POSITION_COORDINATES_SETTING,
SHOW_POSITION_COORDINATES_DEFAULT).toBool())
_showPositionCoordinatesAction->trigger();
if (settings.value(SHOW_MOTION_INFO_SETTING, SHOW_MOTION_INFO_DEFAULT)
.toBool())
_showMotionInfo->trigger();
settings.endGroup();
_mapView->setPalette(_options.palette);
_mapView->setMapOpacity(_options.mapOpacity);
_mapView->setBackgroundColor(_options.backgroundColor);
_mapView->setCrosshairColor(_options.crosshairColor);
_mapView->setInfoColor(_options.infoColor);
_mapView->drawInfoBackground(_options.infoBackground);
_mapView->setTrackWidth(_options.trackWidth);
_mapView->setRouteWidth(_options.routeWidth);
_mapView->setAreaWidth(_options.areaWidth);
@ -2707,6 +2847,7 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
_mapView->setOutputProjection(CRS::projection(_options.outputProjection));
_mapView->setInputProjection(CRS::projection(_options.inputProjection));
_mapView->setTimeZone(_options.timeZone.zone());
_mapView->setPositionSource(_positionSource);
for (int i = 0; i < _tabs.count(); i++) {
_tabs.at(i)->setPalette(_options.palette);
@ -2752,8 +2893,6 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
_dataDir = _options.dataPath;
_mapDir = _options.mapsPath;
_poiDir = _options.poiPath;
settings.endGroup();
}
void GUI::loadInitialMaps(const QString &selected)

View File

@ -24,6 +24,7 @@ class QAction;
class QLabel;
class QSplitter;
class QPrinter;
class QGeoPositionInfoSource;
class FileBrowser;
class GraphTab;
class MapView;
@ -157,6 +158,7 @@ private:
qreal time() const;
qreal movingTime() const;
QAction *mapAction(const QString &name);
QGeoPositionInfoSource *positionSource(const Options &options);
void readSettings(QString &activeMap, QStringList &disabledPOIs);
void writeSettings();
@ -198,6 +200,10 @@ private:
QAction *_showPOILabelsAction;
QAction *_showPOIIconsAction;
QAction *_showMapAction;
QAction *_showPositionAction;
QAction *_followPositionAction;
QAction *_showPositionCoordinatesAction;
QAction *_showMotionInfo;
QAction *_fullscreenAction;
QAction *_loadMapAction;
QAction *_loadMapDirAction;
@ -253,6 +259,7 @@ private:
POI *_poi;
Map *_map;
QGeoPositionInfoSource *_positionSource;
DEMLoader *_dem;
FileBrowser *_browser;

View File

@ -18,6 +18,7 @@
#define LAST_FILE_ICON ":/arrow-right-double.png"
#define FIRST_FILE_ICON ":/arrow-left-double.png"
#define FULLSCREEN_ICON ":/view-fullscreen.png"
#define SHOW_POS_ICON ":/transform-move.png"
// Options dialog icons
#define APPEARANCE_ICON ":/format-stroke-color.png"
@ -27,6 +28,7 @@
#define DATA_ICON ":/view-filter.png"
#define MAPS_ICON ":/applications-internet_32.png"
#define DEM_ICON ":/view-grid.png"
#define POSITION_ICON ":/transform-move_32.png"
#define SHOW_PWD_ICON ":/document-encrypt.png"
#define HIDE_PWD_ICON ":/document-decrypt.png"

View File

@ -5,8 +5,10 @@
#include <QScrollBar>
#include <QClipboard>
#include <QOpenGLWidget>
#include <QGeoPositionInfoSource>
#include "data/poi.h"
#include "data/data.h"
#include "data/dem.h"
#include "map/map.h"
#include "map/pcs.h"
#include "trackitem.h"
@ -20,6 +22,8 @@
#include "graphicsscene.h"
#include "mapaction.h"
#include "markerinfoitem.h"
#include "crosshairitem.h"
#include "motioninfoitem.h"
#include "mapview.h"
@ -44,8 +48,8 @@ static void updateZValues(T &items)
}
MapView::MapView(Map *map, POI *poi, QWidget *parent)
: QGraphicsView(parent)
MapView::MapView(Map *map, POI *poi, QGeoPositionInfoSource *source,
QWidget *parent) : QGraphicsView(parent)
{
Q_ASSERT(map != 0);
Q_ASSERT(poi != 0);
@ -63,10 +67,10 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
_mapScale = new ScaleItem();
_mapScale->setZValue(2.0);
_scene->addItem(_mapScale);
_coordinates = new CoordinatesItem();
_coordinates->setZValue(2.0);
_coordinates->setVisible(false);
_scene->addItem(_coordinates);
_cursorCoordinates = new CoordinatesItem();
_cursorCoordinates->setZValue(2.0);
_cursorCoordinates->setVisible(false);
_scene->addItem(_cursorCoordinates);
_outputProjection = PCS::pcs(3857);
_inputProjection = GCS::gcs(4326);
@ -79,6 +83,25 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
_poi = poi;
connect(_poi, &POI::pointsChanged, this, &MapView::updatePOI);
_positionSource = source;
if (_positionSource)
connect(_positionSource, &QGeoPositionInfoSource::positionUpdated, this,
&MapView::updatePosition);
_crosshair = new CrosshairItem();
_crosshair->setZValue(2.0);
_crosshair->setVisible(false);
_scene->addItem(_crosshair);
_positionCoordinates = new CoordinatesItem();
_positionCoordinates->setZValue(2.0);
_positionCoordinates->setVisible(false);
_scene->addItem(_positionCoordinates);
_motionInfo = new MotionInfoItem();
_motionInfo->setZValue(2.0);
_motionInfo->setVisible(false);
_scene->addItem(_motionInfo);
_mapOpacity = 1.0;
_backgroundColor = Qt::white;
_markerColor = Qt::red;
@ -106,6 +129,10 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
_waypointColor = Qt::black;
_poiSize = 8;
_poiColor = Qt::black;
_followPosition = false;
_showPosition = false;
_showPositionCoordinates = false;
_showMotionInfo = false;
_deviceRatio = 1.0;
_mapRatio = 1.0;
@ -125,7 +152,7 @@ void MapView::centerOn(const QPointF &pos)
QRectF vr(mapToScene(viewport()->rect()).boundingRect());
_res = _map->resolution(vr);
_mapScale->setResolution(_res);
_coordinates->setCoordinates(Coordinates());
_cursorCoordinates->setCoordinates(Coordinates());
}
PathItem *MapView::addTrack(const Track &track)
@ -369,6 +396,8 @@ void MapView::rescale()
it != _pois.constEnd(); it++)
it.value()->setMap(_map);
_crosshair->setMap(_map);
updatePOIVisibility();
}
@ -407,19 +436,21 @@ void MapView::setMap(Map *map)
_scene->setSceneRect(_map->bounds());
for (int i = 0; i < _tracks.size(); i++)
_tracks.at(i)->setMap(map);
_tracks.at(i)->setMap(_map);
for (int i = 0; i < _routes.size(); i++)
_routes.at(i)->setMap(map);
_routes.at(i)->setMap(_map);
for (int i = 0; i < _areas.size(); i++)
_areas.at(i)->setMap(map);
_areas.at(i)->setMap(_map);
for (int i = 0; i < _waypoints.size(); i++)
_waypoints.at(i)->setMap(map);
_waypoints.at(i)->setMap(_map);
for (POIHash::const_iterator it = _pois.constBegin();
it != _pois.constEnd(); it++)
it.value()->setMap(_map);
updatePOIVisibility();
_crosshair->setMap(_map);
QPointF nc = QRectF(_map->ll2xy(cr.topLeft()),
_map->ll2xy(cr.bottomRight())).center();
centerOn(nc);
@ -437,6 +468,20 @@ void MapView::setPOI(POI *poi)
updatePOI();
}
void MapView::setPositionSource(QGeoPositionInfoSource *source)
{
if (_positionSource)
disconnect(_positionSource, &QGeoPositionInfoSource::positionUpdated,
this, &MapView::updatePosition);
if (source)
connect(source, &QGeoPositionInfoSource::positionUpdated, this,
&MapView::updatePosition);
_positionSource = source;
showPosition(_showPosition);
}
void MapView::setGraph(int index)
{
for (int i = 0; i < _tracks.size(); i++)
@ -502,6 +547,8 @@ void MapView::setUnits(Units units)
_routes.at(i)->updateTicks();
_mapScale->setUnits(units);
_cursorCoordinates->setUnits(units);
_positionCoordinates->setUnits(units);
}
void MapView::setCoordinatesFormat(CoordinatesFormat format)
@ -514,7 +561,8 @@ void MapView::setCoordinatesFormat(CoordinatesFormat format)
for (int i = 0; i < _routes.count(); i++)
_routes.at(i)->updateMarkerInfo();
_coordinates->setFormat(format);
_cursorCoordinates->setFormat(format);
_positionCoordinates->setFormat(format);
}
void MapView::setTimeZone(const QTimeZone &zone)
@ -557,7 +605,10 @@ void MapView::digitalZoom(int zoom)
it.value()->setDigitalZoom(_digitalZoom);
_mapScale->setDigitalZoom(_digitalZoom);
_coordinates->setDigitalZoom(_digitalZoom);
_cursorCoordinates->setDigitalZoom(_digitalZoom);
_positionCoordinates->setDigitalZoom(_digitalZoom);
_motionInfo->setDigitalZoom(_digitalZoom);
_crosshair->setDigitalZoom(_digitalZoom);
}
void MapView::zoom(int zoom, const QPoint &pos, bool shift)
@ -658,7 +709,7 @@ void MapView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && event->modifiers() & MODIFIER)
QApplication::clipboard()->setText(Format::coordinates(
_map->xy2ll(mapToScene(event->pos())), _coordinates->format()));
_map->xy2ll(mapToScene(event->pos())), _cursorCoordinates->format()));
else
QGraphicsView::mousePressEvent(event);
}
@ -756,10 +807,16 @@ void MapView::clear()
_waypoints.clear();
_scene->removeItem(_mapScale);
_scene->removeItem(_coordinates);
_scene->removeItem(_cursorCoordinates);
_scene->removeItem(_positionCoordinates);
_scene->removeItem(_crosshair);
_scene->removeItem(_motionInfo);
_scene->clear();
_scene->addItem(_mapScale);
_scene->addItem(_coordinates);
_scene->addItem(_cursorCoordinates);
_scene->addItem(_positionCoordinates);
_scene->addItem(_crosshair);
_scene->addItem(_motionInfo);
_palette.reset();
@ -910,10 +967,31 @@ void MapView::showPOIIcons(bool show)
updatePOIVisibility();
}
void MapView::showCoordinates(bool show)
void MapView::showCursorCoordinates(bool show)
{
_coordinates->setVisible(show);
_cursorCoordinates->setVisible(show);
setMouseTracking(show);
_scene->invalidate();
}
void MapView::showPositionCoordinates(bool show)
{
_showPositionCoordinates = show;
if (_crosshair->isVisible())
_positionCoordinates->setVisible(show);
_scene->invalidate();
}
void MapView::showMotionInfo(bool show)
{
_showMotionInfo = show;
if (_crosshair->isVisible())
_motionInfo->setVisible(show);
_scene->invalidate();
}
void MapView::showOverlappedPOIs(bool show)
@ -1022,6 +1100,10 @@ void MapView::setMapOpacity(int opacity)
void MapView::setBackgroundColor(const QColor &color)
{
_backgroundColor = color;
_cursorCoordinates->setBackgroundColor(color);
_positionCoordinates->setBackgroundColor(color);
_motionInfo->setBackgroundColor(color);
reloadMap();
}
@ -1053,11 +1135,27 @@ void MapView::paintEvent(QPaintEvent *event)
if (_mapScale->pos() != scaleScenePos && !_plot)
_mapScale->setPos(scaleScenePos);
if (_coordinates->isVisible()) {
if (_cursorCoordinates->isVisible()) {
QPointF coordinatesScenePos = mapToScene(rect().bottomLeft()
+ QPoint(COORDINATES_OFFSET, -COORDINATES_OFFSET));
if (_coordinates->pos() != coordinatesScenePos && !_plot)
_coordinates->setPos(coordinatesScenePos);
if (_cursorCoordinates->pos() != coordinatesScenePos && !_plot)
_cursorCoordinates->setPos(coordinatesScenePos);
}
if (_positionCoordinates->isVisible()) {
QPointF coordinatesScenePos = mapToScene(rect().topLeft()
+ QPoint(COORDINATES_OFFSET, COORDINATES_OFFSET
+ _positionCoordinates->boundingRect().height()));
if (_positionCoordinates->pos() != coordinatesScenePos)
_positionCoordinates->setPos(coordinatesScenePos);
}
if (_motionInfo->isVisible()) {
QPointF coordinatesScenePos = mapToScene(rect().topRight()
+ QPoint(-COORDINATES_OFFSET - _motionInfo->boundingRect().width(),
COORDINATES_OFFSET + _motionInfo->boundingRect().height()));
if (_motionInfo->pos() != coordinatesScenePos)
_motionInfo->setPos(coordinatesScenePos);
}
QGraphicsView::paintEvent(event);
@ -1078,15 +1176,17 @@ void MapView::scrollContentsBy(int dx, int dy)
void MapView::mouseMoveEvent(QMouseEvent *event)
{
if (_coordinates->isVisible())
_coordinates->setCoordinates(_map->xy2ll(mapToScene(event->pos())));
if (_cursorCoordinates->isVisible()) {
Coordinates c(_map->xy2ll(mapToScene(event->pos())));
_cursorCoordinates->setCoordinates(c, DEM::elevation(c));
}
QGraphicsView::mouseMoveEvent(event);
}
void MapView::leaveEvent(QEvent *event)
{
_coordinates->setCoordinates(Coordinates());
_cursorCoordinates->setCoordinates(Coordinates());
QGraphicsView::leaveEvent(event);
}
@ -1157,6 +1257,8 @@ void MapView::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
it.value()->setMap(_map);
updatePOIVisibility();
_crosshair->setMap(_map);
QPointF nc = QRectF(_map->ll2xy(cr.topLeft()),
_map->ll2xy(cr.bottomRight())).center();
centerOn(nc);
@ -1206,3 +1308,71 @@ RectC MapView::boundingRect() const
return rect;
}
void MapView::showPosition(bool show)
{
_showPosition = show;
if (!_positionSource) {
_crosshair->setVisible(false);
_positionCoordinates->setVisible(false);
_motionInfo->setVisible(false);
} else if (_showPosition) {
_crosshair->setVisible(true);
if (_showPositionCoordinates)
_positionCoordinates->setVisible(true);
if (_showMotionInfo)
_motionInfo->setVisible(true);
_positionSource->startUpdates();
} else {
_positionSource->stopUpdates();
_crosshair->setVisible(false);
_positionCoordinates->setVisible(false);
_motionInfo->setVisible(false);
}
}
void MapView::followPosition(bool follow)
{
_followPosition = follow;
if (follow && _crosshair->isVisible())
centerOn(_map->ll2xy(_crosshair->coordinates()));
}
void MapView::updatePosition(const QGeoPositionInfo &pos)
{
QGeoCoordinate gc(pos.coordinate());
if (!gc.isValid())
return;
Coordinates c(gc.longitude(), gc.latitude());
_crosshair->setCoordinates(c);
_crosshair->setMap(_map);
_positionCoordinates->setCoordinates(c, gc.altitude());
_motionInfo->setInfo(pos.attribute(QGeoPositionInfo::Direction),
pos.attribute(QGeoPositionInfo::GroundSpeed),
pos.attribute(QGeoPositionInfo::VerticalSpeed));
if (_followPosition)
centerOn(_map->ll2xy(c));
}
void MapView::setCrosshairColor(const QColor &color)
{
_crosshair->setColor(color);
}
void MapView::setInfoColor(const QColor &color)
{
_cursorCoordinates->setColor(color);
_positionCoordinates->setColor(color);
_motionInfo->setColor(color);
}
void MapView::drawInfoBackground(bool draw)
{
_cursorCoordinates->drawBackground(draw);
_positionCoordinates->drawBackground(draw);
_motionInfo->drawBackground(draw);
}

View File

@ -17,6 +17,8 @@
#include "palette.h"
class QGeoPositionInfoSource;
class QGeoPositionInfo;
class Data;
class POI;
class Map;
@ -35,6 +37,8 @@ class Area;
class GraphicsScene;
class QTimeZone;
class MapAction;
class CrosshairItem;
class MotionInfoItem;
class MapView : public QGraphicsView
{
@ -48,7 +52,8 @@ public:
};
Q_DECLARE_FLAGS(PlotFlags, Flag)
MapView(Map *map, POI *poi, QWidget *parent = 0);
MapView(Map *map, POI *poi, QGeoPositionInfoSource *source,
QWidget *parent = 0);
QList<PathItem *> loadData(const Data &data);
void loadMaps(const QList<MapAction*> &maps);
@ -57,6 +62,7 @@ public:
void setPalette(const Palette &palette);
void setPOI(POI *poi);
void setMap(Map *map);
void setPositionSource(QGeoPositionInfoSource *source);
void setGraph(int index);
void plot(QPainter *painter, const QRectF &target, qreal scale,
@ -66,6 +72,9 @@ public:
void setUnits(Units units);
void setMarkerColor(const QColor &color);
void setCrosshairColor(const QColor &color);
void setInfoColor(const QColor &color);
void drawInfoBackground(bool draw);
void setTrackWidth(int width);
void setRouteWidth(int width);
void setAreaWidth(int width);
@ -94,9 +103,11 @@ public:
public slots:
void showMap(bool show);
void showPOI(bool show);
void showPosition(bool show);
void showPOILabels(bool show);
void showPOIIcons(bool show);
void showCoordinates(bool show);
void showCursorCoordinates(bool show);
void showPositionCoordinates(bool show);
void showTicks(bool show);
void showMarkers(bool show);
void showMarkerInfo(MarkerInfoItem::Type type);
@ -109,10 +120,13 @@ public slots:
void showWaypoints(bool show);
void showRouteWaypoints(bool show);
void setMarkerPosition(qreal pos);
void followPosition(bool follow);
void showMotionInfo(bool show);
private slots:
void updatePOI();
void reloadMap();
void updatePosition(const QGeoPositionInfo &pos);
private:
typedef QHash<SearchPointer<Waypoint>, WaypointItem*> POIHash;
@ -148,7 +162,9 @@ private:
GraphicsScene *_scene;
ScaleItem *_mapScale;
CoordinatesItem *_coordinates;
CoordinatesItem *_cursorCoordinates, *_positionCoordinates;
CrosshairItem *_crosshair;
MotionInfoItem *_motionInfo;
QList<TrackItem*> _tracks;
QList<RouteItem*> _routes;
QList<WaypointItem*> _waypoints;
@ -160,6 +176,7 @@ private:
Map *_map;
POI *_poi;
QGeoPositionInfoSource *_positionSource;
Palette _palette;
qreal _mapOpacity;
@ -167,9 +184,10 @@ private:
bool _showMap, _showTracks, _showRoutes, _showAreas, _showWaypoints,
_showWaypointLabels, _showPOI, _showPOILabels, _showRouteWaypoints,
_showMarkers, _showPathTicks, _showPOIIcons, _showWaypointIcons;
_showMarkers, _showPathTicks, _showPOIIcons, _showWaypointIcons,
_showPosition, _showPositionCoordinates, _showMotionInfo;
MarkerInfoItem::Type _markerInfoType;
bool _overlapPOIs;
bool _overlapPOIs, _followPosition;
int _trackWidth, _routeWidth, _areaWidth;
Qt::PenStyle _trackStyle, _routeStyle, _areaStyle;
int _waypointSize, _poiSize;

160
src/GUI/motioninfoitem.cpp Normal file
View File

@ -0,0 +1,160 @@
#include <cmath>
#include <QFont>
#include <QPainter>
#include <QLocale>
#include <QApplication>
#include "font.h"
#include "motioninfoitem.h"
#define DEGREE_UNIT QString::fromUtf8("\xC2\xB0")
MotionInfoItem::MotionInfoItem(QGraphicsItem *parent) : QGraphicsItem(parent)
{
_units = Metric;
_bearing = NAN;
_speed = NAN;
_verticalSpeed = NAN;
_color = Qt::black;
_bgColor = Qt::white;
_drawBackground = false;
_font.setPixelSize(FONT_SIZE);
_font.setFamily(FONT_FAMILY);
_digitalZoom = 0;
setAcceptHoverEvents(true);
updateBoundingRect();
}
void MotionInfoItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
if (std::isnan(_bearing) && std::isnan(_speed) && std::isnan(_verticalSpeed))
return;
if (_drawBackground) {
painter->setPen(Qt::NoPen);
QColor bc(_bgColor);
bc.setAlpha(196);
painter->setBrush(QBrush(bc));
painter->drawRect(_boundingRect);
painter->setBrush(Qt::NoBrush);
}
QFontMetrics fm(_font);
painter->setFont(_font);
painter->setPen(QPen(_color));
painter->drawText(0, -fm.descent(), text());
//painter->setPen(Qt::red);
//painter->drawRect(boundingRect());
}
void MotionInfoItem::setInfo(qreal bearing, qreal speed, qreal verticalSpeed)
{
prepareGeometryChange();
_bearing = bearing;
_speed = speed;
_verticalSpeed = verticalSpeed;
updateBoundingRect();
update();
}
void MotionInfoItem::setUnits(Units units)
{
prepareGeometryChange();
_units = units;
updateBoundingRect();
}
void MotionInfoItem::setDigitalZoom(qreal zoom)
{
_digitalZoom = zoom;
setScale(pow(2, -_digitalZoom));
}
QString MotionInfoItem::speed(const QLocale &l) const
{
if (_units == Nautical)
return l.toString(MS2KN * _speed) + UNIT_SPACE
+ qApp->translate("MotionInfoItem", "kn");
else if (_units == Imperial)
return l.toString(MS2MIH * _speed) + UNIT_SPACE
+ qApp->translate("MotionInfoItem", "mi/h");
else
return l.toString(MS2KMH * _speed) + UNIT_SPACE
+ qApp->translate("MotionInfoItem", "km/h");
}
QString MotionInfoItem::verticalSpeed(const QLocale &l) const
{
if (_units == Nautical || _units == Imperial)
return l.toString(MS2FTMIN * _verticalSpeed) + UNIT_SPACE
+ qApp->translate("MotionInfoItem", "ft/min");
else
return l.toString(MS2MMIN * _verticalSpeed) + UNIT_SPACE
+ qApp->translate("MotionInfoItem", "m/min");
}
static QString bearing(qreal val, const QLocale &l)
{
return l.toString(val) + DEGREE_UNIT;
}
QString MotionInfoItem::text() const
{
QLocale l(QLocale::system());
QString str;
if (!std::isnan(_bearing))
str += bearing(_bearing, l);
if (!std::isnan(_speed)) {
if (!str.isEmpty())
str += ", ";
str += speed(l);
} if (!std::isnan(_verticalSpeed)) {
if (!str.isEmpty())
str += ", ";
str += verticalSpeed(l);
}
return str;
}
void MotionInfoItem::updateBoundingRect()
{
QFontMetrics fm(_font);
QRectF br(fm.tightBoundingRect(text()));
QRectF r1(br);
QRectF r2(br);
r1.moveTop(-fm.ascent());
r2.moveBottom(-fm.descent());
_boundingRect = r1 | r2;
}
void MotionInfoItem::setColor(const QColor &color)
{
_color = color;
update();
}
void MotionInfoItem::setBackgroundColor(const QColor &color)
{
_bgColor = color;
update();
}
void MotionInfoItem::drawBackground(bool draw)
{
_drawBackground = draw;
update();
}

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

@ -0,0 +1,38 @@
#ifndef MOTIONINFOITEM_H
#define MOTIONINFOITEM_H
#include <QGraphicsItem>
#include "units.h"
class MotionInfoItem : public QGraphicsItem
{
public:
MotionInfoItem(QGraphicsItem *parent = 0);
QRectF boundingRect() const {return _boundingRect;}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget);
void setInfo(qreal bearing, qreal speed, qreal verticalSpeed);
void setUnits(Units units);
void setDigitalZoom(qreal zoom);
void setColor(const QColor &color);
void setBackgroundColor(const QColor &color);
void drawBackground(bool draw);
private:
void updateBoundingRect();
QString speed(const QLocale &l) const;
QString verticalSpeed(const QLocale &l) const;
QString text() const;
qreal _bearing, _speed, _verticalSpeed;
Units _units;
QRectF _boundingRect;
QFont _font;
qreal _digitalZoom;
QColor _color, _bgColor;
bool _drawBackground;
};
#endif // MOTIONINFOITEM_H

View File

@ -13,6 +13,7 @@
#include <QLabel>
#include <QSysInfo>
#include <QButtonGroup>
#include <QGeoPositionInfoSource>
#include "icons.h"
#include "infolabel.h"
#include "colorbox.h"
@ -22,6 +23,7 @@
#include "projectioncombobox.h"
#include "dirselectwidget.h"
#include "authenticationwidget.h"
#include "pluginparameters.h"
#include "optionsdialog.h"
@ -39,7 +41,6 @@ static QFrame *line()
}
#endif // Q_OS_MAC
void OptionsDialog::automaticPauseDetectionSet(bool set)
{
_pauseInterval->setEnabled(!set);
@ -275,10 +276,20 @@ QWidget *OptionsDialog::createAppearancePage()
_backgroundColor = new ColorBox();
_backgroundColor->setColor(_options.backgroundColor);
_backgroundColor->enableAlphaChannel(false);
_crosshairColor = new ColorBox();
_crosshairColor->setColor(_options.crosshairColor);
_infoColor = new ColorBox();
_infoColor->setColor(_options.infoColor);
_infoBackground = new QCheckBox(tr("Info background"));
_infoBackground->setChecked(_options.infoBackground);
QFormLayout *mapLayout = new QFormLayout();
mapLayout->addRow(tr("Background color:"), _backgroundColor);
mapLayout->addRow(tr("Map opacity:"), _mapOpacity);
mapLayout->addRow(tr("Crosshair color:"), _crosshairColor);
mapLayout->addRow(tr("Info color:"), _infoColor);
mapLayout->addWidget(_infoBackground);
QWidget *mapTab = new QWidget();
QVBoxLayout *mapTabLayout = new QVBoxLayout();
mapTabLayout->addLayout(mapLayout);
@ -593,6 +604,39 @@ QWidget *OptionsDialog::createDEMPage()
return demPage;
}
QWidget *OptionsDialog::createPositionPage()
{
QStringList plugins(QGeoPositionInfoSource::availableSources());
_positionPlugin = new QComboBox();
_positionPlugin->addItems(plugins);
_positionPlugin->setCurrentIndex(_positionPlugin->findText(_options.plugin));
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
_pluginParameters = new PluginParameters(_positionPlugin->currentText(),
_options.pluginParams);
connect(_positionPlugin, &QComboBox::currentTextChanged, _pluginParameters,
&PluginParameters::setPlugin);
#endif // QT 5.14
QFormLayout *pluginLayout = new QFormLayout();
pluginLayout->addRow(tr("Plugin:"), _positionPlugin);
QVBoxLayout *sourceLayout = new QVBoxLayout();
sourceLayout->addLayout(pluginLayout);
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
sourceLayout->addWidget(_pluginParameters);
#endif // QT 5.14
sourceLayout->addStretch();
QWidget *sourceTab = new QWidget();
sourceTab->setLayout(sourceLayout);
QTabWidget *positionPage = new QTabWidget();
positionPage->addTab(sourceTab, tr("Source"));
return positionPage;
}
QWidget *OptionsDialog::createExportPage()
{
_wysiwyg = new QRadioButton(tr("WYSIWYG"));
@ -741,6 +785,7 @@ OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent)
pages->addWidget(createDataPage());
pages->addWidget(createPOIPage());
pages->addWidget(createDEMPage());
pages->addWidget(createPositionPage());
pages->addWidget(createExportPage());
pages->addWidget(createSystemPage());
@ -752,6 +797,7 @@ OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent)
new QListWidgetItem(QIcon(DATA_ICON), tr("Data"), menu);
new QListWidgetItem(QIcon(POI_ICON), tr("POI"), menu);
new QListWidgetItem(QIcon(DEM_ICON), tr("DEM"), menu);
new QListWidgetItem(QIcon(POSITION_ICON), tr("Position"), menu);
new QListWidgetItem(QIcon(PRINT_EXPORT_ICON), tr("Print & Export"),
menu);
new QListWidgetItem(QIcon(SYSTEM_ICON), tr("System"), menu);
@ -796,6 +842,9 @@ void OptionsDialog::accept()
_options.palette.setShift(_colorOffset->value() / 100.0);
_options.mapOpacity = _mapOpacity->value();
_options.backgroundColor = _backgroundColor->color();
_options.crosshairColor = _crosshairColor->color();
_options.infoColor = _infoColor->color();
_options.infoBackground = _infoBackground->isChecked();
_options.trackWidth = _trackWidth->value();
_options.trackStyle = (Qt::PenStyle) _trackStyle->itemData(
_trackStyle->currentIndex()).toInt();
@ -856,6 +905,11 @@ void OptionsDialog::accept()
_options.demUsername = _demAuth->username();
_options.demPassword = _demAuth->password();
_options.plugin = _positionPlugin->currentText();
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
_options.pluginParams = _pluginParameters->parameters();
#endif // QT 5.14
_options.useOpenGL = _useOpenGL->isChecked();
_options.enableHTTP2 = _enableHTTP2->isChecked();
_options.pixmapCache = _pixmapCache->value();

View File

@ -1,6 +1,7 @@
#ifndef OPTIONSDIALOG_H
#define OPTIONSDIALOG_H
#include <QtGlobal>
#include <QDialog>
#include "palette.h"
#include "units.h"
@ -19,6 +20,7 @@ class PercentSlider;
class ProjectionComboBox;
class DirSelectWidget;
class AuthenticationWidget;
class PluginParameters;
struct Options {
// Appearance
@ -40,6 +42,9 @@ struct Options {
bool graphAntiAliasing;
int mapOpacity;
QColor backgroundColor;
QColor crosshairColor;
QColor infoColor;
bool infoBackground;
// Map
int outputProjection;
int inputProjection;
@ -67,6 +72,9 @@ struct Options {
QString demUsername;
QString demPassword;
bool demAuthorization;
// Position
QString plugin;
QMap<QString, QVariantMap> pluginParams;
// System
bool useOpenGL;
bool enableHTTP2;
@ -107,6 +115,7 @@ private:
QWidget *createSystemPage();
QWidget *createExportPage();
QWidget *createDEMPage();
QWidget *createPositionPage();
Options &_options;
@ -116,6 +125,9 @@ private:
PercentSlider *_colorOffset;
PercentSlider *_mapOpacity;
ColorBox *_backgroundColor;
ColorBox *_crosshairColor;
ColorBox *_infoColor;
QCheckBox *_infoBackground;
QSpinBox *_trackWidth;
StyleComboBox *_trackStyle;
QSpinBox *_routeWidth;
@ -163,6 +175,11 @@ private:
// DEM
QLineEdit *_demURL;
AuthenticationWidget *_demAuth;
// Position
QComboBox *_positionPlugin;
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
PluginParameters *_pluginParameters;
#endif // QT 5.14
// System
QSpinBox *_pixmapCache;
QSpinBox *_connectionTimeout;

View File

@ -0,0 +1,76 @@
#include <QFormLayout>
#include <QLineEdit>
#include "pluginparameters.h"
static const QMap<QString, QStringList> pluginParams = {
{"nmea", {"nmea.source"}},
{"serialnmea", {"serialnmea.serial_port"}},
{"geoclue2", {"desktopId"}}
};
static void deleteLayout(QLayout *layout)
{
if (!layout)
return;
while (layout->count() > 0) {
QLayoutItem *child = layout->takeAt(0);
deleteLayout(child->layout());
delete child->widget();
delete child;
}
delete layout;
}
PluginParameters::PluginParameters(const QString &plugin,
const QMap<QString, QVariantMap> &params, QWidget *parent)
: QWidget(parent), _params(params), _plugin(plugin)
{
setPlugin(plugin);
}
void PluginParameters::setPlugin(const QString &plugin)
{
saveParameters();
QStringList params = pluginParams.value(plugin);
QFormLayout *l = new QFormLayout();
for (int i = 0; i < params.size(); i++) {
QLineEdit *le = new QLineEdit();
le->setObjectName(params.at(i));
le->setText(_params[plugin].value(params.at(i)).toString());
l->addRow(params.at(i) + ":", le);
}
deleteLayout(layout());
setLayout(l);
_plugin = plugin;
}
const QMap<QString, QVariantMap> &PluginParameters::parameters()
{
saveParameters();
return _params;
}
void PluginParameters::saveParameters()
{
QVariantMap &map(_params[_plugin]);
QFormLayout *l = qobject_cast<QFormLayout*>(layout());
if (!l)
return;
for (int i = 0; i < l->rowCount(); i++) {
QLayoutItem *li = l->itemAt(i, QFormLayout::FieldRole);
QLineEdit *le = qobject_cast<QLineEdit*>(li->widget());
if (le) {
if (le->text().isEmpty())
map.remove(le->objectName());
else
map.insert(le->objectName(), le->text());
}
}
}

View File

@ -0,0 +1,27 @@
#ifndef PLUGINPARAMETERS_H
#define PLUGINPARAMETERS_H
#include <QWidget>
#include <QVariantMap>
class PluginParameters : public QWidget
{
Q_OBJECT
public:
PluginParameters(const QString &plugin,
const QMap<QString, QVariantMap> &params, QWidget *parent = 0);
const QMap<QString, QVariantMap> &parameters();
public slots:
void setPlugin(const QString &plugin);
private:
void saveParameters();
QMap<QString, QVariantMap> _params;
QString _plugin;
};
#endif // PLUGINPARAMETERS_H

View File

@ -3,6 +3,9 @@
#define IMPERIAL_UNITS() \
(QLocale::system().measurementSystem() == QLocale::ImperialSystem)
#define POSITION_PLUGIN() \
(QGeoPositionInfoSource::availableSources().isEmpty() \
? "" : QGeoPositionInfoSource::availableSources().first())
#define WINDOW_SETTINGS_GROUP "Window"
#define WINDOW_GEOMETRY_SETTING "geometry"
@ -34,13 +37,23 @@
#define CURRENT_MAP_SETTING "map"
#define SHOW_MAP_SETTING "show"
#define SHOW_MAP_DEFAULT true
#define SHOW_COORDINATES_SETTING "coordinates"
#define SHOW_COORDINATES_DEFAULT false
#define SHOW_CURSOR_COORDINATES_SETTING "coordinates"
#define SHOW_CURSOR_COORDINATES_DEFAULT false
#define POI_SETTINGS_GROUP "POI"
#define OVERLAP_POI_SETTING "overlap"
#define OVERLAP_POI_DEFAULT false
#define POSITION_SETTINGS_GROUP "Position"
#define SHOW_POSITION_SETTING "show"
#define SHOW_POSITION_DEFAULT false
#define FOLLOW_POSITION_SETTING "follow"
#define FOLLOW_POSITION_DEFAULT true
#define SHOW_POSITION_COORDINATES_SETTING "coordinates"
#define SHOW_POSITION_COORDINATES_DEFAULT true
#define SHOW_MOTION_INFO_SETTING "motionInfo"
#define SHOW_MOTION_INFO_DEFAULT true
#define SHOW_POI_ICONS_SETTING "icons"
#define SHOW_POI_ICONS_DEFAULT true
#define SHOW_POI_LABELS_SETTING "labels"
@ -119,6 +132,12 @@
#define MAP_OPACITY_DEFAULT 100
#define BACKGROUND_COLOR_SETTING "backgroundColor"
#define BACKGROUND_COLOR_DEFAULT QColor(Qt::white)
#define CROSSHAIR_COLOR_SETTING "crosshairColor"
#define CROSSHAIR_COLOR_DEFAULT QColor(Qt::red)
#define INFO_COLOR_SETTING "infoColor"
#define INFO_COLOR_DEFAULT QColor(Qt::black)
#define INFO_BACKGROUND_SETTING "infoBackground"
#define INFO_BACKGROUND_DEFAULT false
#define TRACK_WIDTH_SETTING "trackWidth"
#define TRACK_WIDTH_DEFAULT 3
#define ROUTE_WIDTH_SETTING "routeWidth"
@ -179,13 +198,18 @@
#define POI_RADIUS_SETTING "poiRadius"
#define POI_RADIUS_DEFAULT (int)(IMPERIAL_UNITS() ? MIINM : KMINM)
#define DEM_URL_SETTING "demURL"
#define DEM_URL_DEFAULT ""
#define DEM_URL_DEFAULT "http://dem.gpxsee.org/$lat/$lat$lon.hgt.zip"
#define DEM_AUTH_SETTING "demAuthentication"
#define DEM_AUTH_DEFAULT false
#define DEM_USERNAME_SETTING "demUsername"
#define DEM_USERNAME_DEFAULT ""
#define DEM_PASSWORD_SETTING "demPassword"
#define DEM_PASSWORD_DEFAULT ""
#define POSITION_PLUGIN_SETTING "positionPlugin"
#define POSITION_PLUGIN_DEFAULT POSITION_PLUGIN()
#define POSITION_PLUGIN_PARAMS_PREFIX "pluginParameters"
#define POSITION_PLUGIN_PARAMS_PLUGIN "plugin"
#define POSITION_PLUGIN_PARAMS_PARAM "parameters"
#define USE_OPENGL_SETTING "useOpenGL"
#define USE_OPENGL_DEFAULT false
#define ENABLE_HTTP2_SETTING "enableHTTP2"

View File

@ -7,26 +7,28 @@ enum Units {
Nautical
};
#define M2KM 0.001000000000 // m -> km
#define M2MI 0.000621371192 // m -> mi
#define M2NMI 0.000539956803 // m -> nmi
#define M2FT 3.280839900000 // m -> ft
#define MS2KMH 3.600000000000 // m/s -> km/h
#define MS2MIH 2.236936290000 // m/s -> mi/h
#define MS2KN 1.943844490000 // m/s -> kn
#define FT2MI 0.000189393939 // ft -> mi
#define MM2IN 0.039370100000 // mm -> in
#define MM2CM 0.100000000000 // mm -> cm
#define H2S 0.000277777778 // h -> s
#define MIN2S 0.016666666667 // min -> s
#define M2KM 0.001000000000 // m -> km
#define M2MI 0.000621371192 // m -> mi
#define M2NMI 0.000539956803 // m -> nmi
#define M2FT 3.280839900000 // m -> ft
#define MS2KMH 3.600000000000 // m/s -> km/h
#define MS2MIH 2.236936290000 // m/s -> mi/h
#define MS2KN 1.943844490000 // m/s -> kn
#define MS2FTMIN 196.8503937008 // m/s -> ft/min
#define MS2MMIN 60.00000000000 // m/s -> m/min
#define FT2MI 0.000189393939 // ft -> mi
#define MM2IN 0.039370100000 // mm -> in
#define MM2CM 0.100000000000 // mm -> cm
#define H2S 0.000277777778 // h -> s
#define MIN2S 0.016666666667 // min -> s
#define KMINM 1000.0 // 1 km in m
#define MIINFT 5280.0 // 1 mi in ft
#define NMIINFT 6076.11549 // 1 nm in ft
#define MIINM 1609.344 // 1 mi in m
#define NMIINM 1852.0 // 1 nmi in m
#define MININS 60.0 // 1 min in s
#define HINS 3600.0 // 1 hins
#define KMINM 1000.0 // 1 km in m
#define MIINFT 5280.0 // 1 mi in ft
#define NMIINFT 6076.11549 // 1 nm in ft
#define MIINM 1609.344 // 1 mi in m
#define NMIINM 1852.0 // 1 nmi in m
#define MININS 60.0 // 1 min in s
#define HINS 3600.0 // 1 hins
#define C2FS 1.8 // Celsius to Farenheit - scale
#define C2FO 32.0 // Celsius to Farenheit - offset

View File

@ -1,7 +1,6 @@
#include <QApplication>
#include <QFile>
#include <QFileInfo>
#include <QLineF>
#include "gpxparser.h"
#include "tcxparser.h"
#include "csvparser.h"
@ -20,6 +19,7 @@
#include "ov2parser.h"
#include "itnparser.h"
#include "onmoveparsers.h"
#include "twonavparser.h"
#include "data.h"
@ -44,10 +44,11 @@ static OV2Parser ov2;
static ITNParser itn;
static OMDParser omd;
static GHPParser ghp;
static TwoNavParser twonav;
static QMap<QString, Parser*> parsers()
static QMultiMap<QString, Parser*> parsers()
{
QMap<QString, Parser*> map;
QMultiMap<QString, Parser*> map;
map.insert("gpx", &gpx);
map.insert("tcx", &tcx);
@ -72,11 +73,14 @@ static QMap<QString, Parser*> parsers()
map.insert("itn", &itn);
map.insert("omd", &omd);
map.insert("ghp", &ghp);
map.insert("trk", &twonav);
map.insert("rte", &twonav);
map.insert("wpt", &twonav);
return map;
}
QMap<QString, Parser*> Data::_parsers = parsers();
QMultiMap<QString, Parser*> Data::_parsers = parsers();
void Data::processData(QList<TrackData> &trackData, QList<RouteData> &routeData)
{
@ -101,16 +105,21 @@ Data::Data(const QString &fileName, bool tryUnknown)
return;
}
QMap<QString, Parser*>::iterator it;
if ((it = _parsers.find(fi.suffix().toLower())) != _parsers.end()) {
if (it.value()->parse(&file, trackData, routeData, _polygons,
_waypoints)) {
processData(trackData, routeData);
_valid = true;
return;
} else {
_errorLine = it.value()->errorLine();
_errorString = it.value()->errorString();
QMultiMap<QString, Parser*>::iterator it;
QString suffix(fi.suffix().toLower());
if ((it = _parsers.find(suffix)) != _parsers.end()) {
while (it != _parsers.end() && it.key() == suffix) {
if (it.value()->parse(&file, trackData, routeData, _polygons,
_waypoints)) {
processData(trackData, routeData);
_valid = true;
return;
} else {
_errorLine = it.value()->errorLine();
_errorString = it.value()->errorString();
}
file.reset();
++it;
}
} else if (tryUnknown) {
for (it = _parsers.begin(); it != _parsers.end(); it++) {
@ -155,16 +164,21 @@ QString Data::formats()
+ qApp->translate("Data", "SLF files") + " (*.slf);;"
+ qApp->translate("Data", "SML files") + " (*.sml);;"
+ qApp->translate("Data", "TCX files") + " (*.tcx);;"
+ qApp->translate("Data", "TwoNav files") + " (*.rte *.trk *.wpt);;"
+ qApp->translate("Data", "All files") + " (*)";
}
QStringList Data::filter()
{
QStringList filter;
QString last;
for (QMap<QString, Parser*>::iterator it = _parsers.begin();
it != _parsers.end(); it++)
filter << "*." + it.key();
for (QMultiMap<QString, Parser*>::iterator it = _parsers.begin();
it != _parsers.end(); it++) {
if (it.key() != last)
filter << "*." + it.key();
last = it.key();
}
return filter;
}

View File

@ -2,7 +2,7 @@
#define DATA_H
#include <QList>
#include <QMap>
#include <QMultiMap>
#include <QString>
#include <QStringList>
#include "waypoint.h"
@ -39,7 +39,7 @@ private:
QList<Area> _polygons;
QVector<Waypoint> _waypoints;
static QMap<QString, Parser*> _parsers;
static QMultiMap<QString, Parser*> _parsers;
};
#endif // DATA_H

View File

@ -223,6 +223,22 @@ bool FITParser::readField(CTX &ctx, Field *field, QVariant &val, bool &valid)
case 0: // enum
VAL(quint8, 0xffU);
break;
case 3:
case 0x83: // sint16
VAL(qint16, 0x7fffU);
break;
case 4:
case 0x84: // uint16
VAL(quint16, 0xffffU);
break;
case 5:
case 0x85: // sint32
VAL(qint32, 0x7fffffffU);
break;
case 6:
case 0x86: // uint32
VAL(quint32, 0xffffffffU);
break;
case 7: // UTF8 nul terminated string
{QByteArray ba(ctx.file->read(field->size));
ctx.len -= field->size;
@ -230,18 +246,6 @@ bool FITParser::readField(CTX &ctx, Field *field, QVariant &val, bool &valid)
val = ret ? ba : QString();
valid = !ba.isEmpty();}
break;
case 0x83: // sint16
VAL(qint16, 0x7fffU);
break;
case 0x84: // uint16
VAL(quint16, 0xffffU);
break;
case 0x85: // sint32
VAL(qint32, 0x7fffffffU);
break;
case 0x86: // uint32
VAL(quint32, 0xffffffffU);
break;
default:
ret = skipValue(ctx, field->size);
valid = false;

223
src/data/twonavparser.cpp Normal file
View File

@ -0,0 +1,223 @@
#include "common/textcodec.h"
#include "map/gcs.h"
#include "twonavparser.h"
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
#define SKIP_EMPTY QString::SkipEmptyParts
#else // Qt 5.14
#define SKIP_EMPTY Qt::SkipEmptyParts
#endif
static double lon(const QString &str)
{
QStringList l(str.split(QChar(0xBA)));
if (l.size() < 2)
return NAN;
bool ok;
double val = l.at(0).toDouble(&ok);
if (!ok)
return NAN;
if (l.at(1) == "W")
return -val;
else if (l.at(1) == "E")
return val;
else
return NAN;
}
static double lat(const QString &str)
{
QStringList l(str.split(QChar(0xBA)));
if (l.size() < 2)
return NAN;
bool ok;
double val = l.at(0).toDouble(&ok);
if (!ok)
return NAN;
if (l.at(1) == "S")
return -val;
else if (l.at(1) == "N")
return val;
else
return NAN;
}
static QDateTime timestamp(const QString &dateStr, const QString &timeStr)
{
QLocale l("C");
QDate date(l.toDate(dateStr, "dd-MMM-yy"));
if (date.isValid())
date = date.addYears(100);
else {
date = l.toDate(dateStr, "dd-MMM-yyyy");
if (!date.isValid())
return QDateTime();
}
QTime time(l.toTime(timeStr, "H:m:s.z"));
if (!time.isValid()) {
time = l.toTime(timeStr, "H:m:s");
if (!time.isValid())
return QDateTime();
}
return QDateTime(date, time);
}
bool TwoNavParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints)
{
Q_UNUSED(polygons);
TextCodec codec;
GCS gcs;
bool ok, route = false, track = false, waypoint = false;
_errorLine = 1;
_errorString.clear();
quint8 bom[3];
if (file->peek((char*)bom, sizeof(bom)) == sizeof(bom)
&& bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF) {
file->seek(3);
codec = TextCodec(65001);
}
while (!file->atEnd()) {
QByteArray line(file->readLine().trimmed());
if (!line.size())
continue;
switch (line.at(0)) {
case 'B':
{line.remove(0, 1);
QByteArray encoding(line.trimmed());
if (encoding == "UTF-8")
codec = TextCodec(65001);
else {
_errorString = "Invalid/unknown encoding";
return false;
}}
break;
case 'G':
{line.remove(0, 1);
QString datum(line.trimmed());
gcs = GCS::gcs(datum);
if (gcs.isNull()) {
_errorString = "Invalid/unknown datum";
return false;
}}
break;
case 'U':
{line.remove(0, 1);
QByteArray cs(line.trimmed());
if (cs != "1") {
_errorString = "Invalid/unknown coordinate system";
return false;
}}
break;
case 'T':
{QStringList list(codec.toString(line).split(' ', SKIP_EMPTY));
if (list.size() < 4) {
_errorString = "Parse error";
return false;
}
Coordinates c(lon(list.at(3)), lat(list.at(2)));
if (!c.isValid()) {
_errorString = "Invalid coordinates";
return false;
}
Trackpoint t(gcs.toWGS84(c));
if (list.size() > 5) {
QDateTime ts(timestamp(list.at(4), list.at(5)));
if (ts.isValid())
t.setTimestamp(ts);
}
if (list.size() > 7) {
qreal elevation = list.at(7).toDouble(&ok);
if (!ok) {
_errorString = "Invalid altitude";
return false;
}
t.setElevation(elevation);
}
if (!track) {
tracks.append(TrackData());
tracks.last().append(SegmentData());
track = true;
}
tracks.last().last().append(t);}
break;
case 'W':
{QStringList list(codec.toString(line).split(' ', SKIP_EMPTY));
if (list.size() < 5) {
_errorString = "Parse error";
return false;
}
Coordinates c(lon(list.at(4)), lat(list.at(3)));
if (!c.isValid()) {
_errorString = "Invalid coordinates";
return false;
}
Waypoint w(gcs.toWGS84(c));
QString name(list.at(1));
w.setName(name.replace('_', ' ').trimmed());
if (list.size() > 6) {
QDateTime ts(timestamp(list.at(5), list.at(6)));
if (ts.isValid())
w.setTimestamp(ts);
}
if (list.size() > 7) {
qreal elevation = list.at(7).toDouble(&ok);
if (!ok) {
_errorString = "Invalid altitude";
return false;
}
w.setElevation(elevation);
}
if (list.size() > 8)
w.setDescription(list.mid(8).join(' '));
if (route)
routes.last().append(w);
else {
waypoints.append(w);
waypoint = true;
}}
break;
case 'w':
{line.remove(0, 1);
QStringList list(codec.toString(line).split(','));
if (list.size() && waypoints.size())
waypoints.last().setSymbol(list.at(0).trimmed());}
break;
case 'R':
{QStringList list(codec.toString(line).split(','));
routes.append(RouteData());
if (list.size() > 1)
routes.last().setName(list.at(1));
route = true;}
break;
}
_errorLine++;
}
if (!(waypoint | route | track)) {
_errorString = "No valid data found";
return false;
} else
return true;
}

21
src/data/twonavparser.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef TWONAVPARSER_H
#define TWONAVPARSER_H
#include "parser.h"
class TwoNavParser : public Parser
{
public:
TwoNavParser() : _errorLine(0) {}
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 _errorLine;}
private:
QString _errorString;
int _errorLine;
};
#endif // TWONAVPARSER_H

View File

@ -27,6 +27,9 @@ QPair<qreal, qreal> Waypoint::elevations() const
void Waypoint::loadSymbolIcons(const QString &dir)
{
if (dir.isEmpty())
return;
QDir d(dir);
QFileInfoList files(d.entryInfoList(QDir::Files | QDir::Readable));

View File

@ -26,7 +26,7 @@ public:
_data.resize(1U<<subFile->blockBits());
_file.setFileName(subFile->fileName());
_file.open(QIODevice::ReadOnly);
_file.open(QIODevice::ReadOnly | QIODevice::Unbuffered);
}
private:

View File

@ -40,7 +40,7 @@ void TextPointItem::setPos(const QPoint &point, bool padding)
QPainterPath shape;
QRect iconRect;
if (_img) {
if (_img && !_img->isNull()) {
QSize s(_img->size() / _img->devicePixelRatioF());
int xOffset = padding ? s.width() : s.width() / 2;
iconRect = QRect(QPoint(point.x() - xOffset, point.y()
@ -57,7 +57,7 @@ void TextPointItem::setPos(const QPoint &point, bool padding)
void TextPointItem::paint(QPainter *painter) const
{
if (_img) {
if (_img && !_img->isNull()) {
QSize s(_img->size() / _img->devicePixelRatioF());
painter->drawImage(QPoint(_rect.left(), _rect.center().y()
- s.height()/2), *_img);