Compare commits
172 Commits
Author | SHA1 | Date | |
---|---|---|---|
1000dd3fc1 | |||
50374fc222 | |||
2cc97f8e36 | |||
44aed958a5 | |||
cb2dfd9155 | |||
7d98a797f5 | |||
b17d7eac5f | |||
f24f2abb4d | |||
d9c66c11e0 | |||
1ed2685802 | |||
0483cdb5db | |||
e4c4961e7a | |||
4fbe7f7571 | |||
87c82ec75f | |||
2655091b95 | |||
9b5b422aef | |||
c6e7393df7 | |||
a42280dec3 | |||
4f1c2a7ea3 | |||
93377964d8 | |||
421ab19e7a | |||
01e6053400 | |||
f55e5d639d | |||
306fefe8db | |||
cedaeb1185 | |||
42a39f3eb3 | |||
23400a8c3a | |||
e6fd92266d | |||
321357b74d | |||
897e075505 | |||
932aadee5f | |||
32bf7f0dfa | |||
b539eb8ed8 | |||
741e95cb63 | |||
c161e35379 | |||
d09b937e10 | |||
a1d7689879 | |||
7ff7303eab | |||
5789982024 | |||
0861b0a0b4 | |||
0e735d5726 | |||
308ca9c702 | |||
b1ea38b6ac | |||
428fb934c4 | |||
c4066ef66b | |||
f5523b68a9 | |||
f692e38711 | |||
2d43768f81 | |||
bbfd0d8735 | |||
5dd8dd524a | |||
04c989d3b7 | |||
42f35f95a8 | |||
7861d8f6d8 | |||
9dc9cf9991 | |||
355ddda1e6 | |||
901a44d1e4 | |||
5424b64679 | |||
e4d68de963 | |||
ace03b2003 | |||
97029233e9 | |||
c9a4506cbb | |||
851c64c3ec | |||
7fdc182687 | |||
3e0fb14a75 | |||
ae0604793e | |||
0432665aeb | |||
b7b6a3fe53 | |||
1e3132c9b3 | |||
b4925843c8 | |||
fa55c6d93a | |||
682da37ea6 | |||
a4d91ef17a | |||
7922840b4f | |||
6cf3c9ef96 | |||
9119ebd2cf | |||
9bac76be10 | |||
3bada7f32e | |||
e877e851b1 | |||
811ec2b455 | |||
487919c44b | |||
90170f9e6b | |||
8e1376afde | |||
033e4dcb27 | |||
4a6293dd86 | |||
1589fe27e9 | |||
5f7de6e96c | |||
a2e1937e32 | |||
ae742e8581 | |||
35184abbe7 | |||
9253703a69 | |||
edb3395d95 | |||
39574704b0 | |||
5298110a0e | |||
a1a96e1066 | |||
1c2e1fd5c5 | |||
ae6f91a762 | |||
9a3d81e8de | |||
914b730a21 | |||
94f03670ef | |||
c87fa3741e | |||
40ab7d9086 | |||
c96849da79 | |||
b45860afe9 | |||
9a4b92c35f | |||
f63ee64f90 | |||
caae981c6a | |||
de028cd2d4 | |||
9bfc7e8b89 | |||
ca5b7d72c4 | |||
3deae0c57b | |||
7ddadf9811 | |||
933ecffe93 | |||
0a72c729f8 | |||
a2c88c4fcb | |||
4570ade52c | |||
9eee3b456f | |||
3972bb25e0 | |||
87d534b023 | |||
21cda471cc | |||
bed26ed318 | |||
531edc4862 | |||
f942c9c4bf | |||
e0c807beeb | |||
07ef51164d | |||
7d6f70cfd3 | |||
bb9a43c677 | |||
d2fbe4324b | |||
68ac7f76a8 | |||
dcf98ef025 | |||
3714c7fbd3 | |||
96bf7bd41a | |||
fe3c3dce60 | |||
03bd1fd770 | |||
8d61ed72c6 | |||
ca223e0df3 | |||
b23cc0a4cc | |||
97cd73b000 | |||
310a113e25 | |||
4e79a05379 | |||
f83e320f85 | |||
e7df35d15f | |||
644c854328 | |||
38e1094ad7 | |||
369b12a406 | |||
046c8796fc | |||
fcb3abfc76 | |||
26a001ef0f | |||
0c7508f759 | |||
95e4f34c2a | |||
ad364de7fd | |||
c33ecd38c5 | |||
59070c1412 | |||
da73267627 | |||
09aefd1cc1 | |||
442625232c | |||
6b70f4a958 | |||
f810117cbe | |||
7fe82b12fe | |||
94e2d58805 | |||
8046d06e32 | |||
532bd39bc2 | |||
c487d9c66b | |||
37dddbb18c | |||
37a4f80fbb | |||
a531b7859b | |||
ccfda7ca7f | |||
8e867851e9 | |||
5e36d564aa | |||
db4ed75757 | |||
4eae93e403 | |||
6ffeefe9c9 | |||
4069bfcc6e |
@ -1,4 +1,4 @@
|
||||
version: 9.8.{build}
|
||||
version: 10.1.{build}
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
@ -8,31 +8,16 @@ image:
|
||||
|
||||
environment:
|
||||
NSISDIR: C:\Program Files (x86)\NSIS
|
||||
OPENSSLDIR: C:\OpenSSL-v111-Win64\bin
|
||||
matrix:
|
||||
- QTDIR: C:\Qt\5.15\msvc2019
|
||||
NSI: gpxsee.nsi
|
||||
VCVARS: vcvars32.bat
|
||||
OPENSSLDIR: C:\OpenSSL-v111-Win32\bin
|
||||
LIBCRYPTO: libssl-1_1.dll
|
||||
LIBSSL: libcrypto-1_1.dll
|
||||
- QTDIR: C:\Qt\5.15\msvc2019_64
|
||||
NSI: gpxsee64.nsi
|
||||
VCVARS: vcvars64.bat
|
||||
OPENSSLDIR: C:\OpenSSL-v111-Win64\bin
|
||||
LIBCRYPTO: libssl-1_1-x64.dll
|
||||
LIBSSL: libcrypto-1_1-x64.dll
|
||||
- QTDIR: C:\Qt\6.0\msvc2019_64
|
||||
NSI: gpxsee64.nsi
|
||||
VCVARS: vcvars64.bat
|
||||
OPENSSLDIR: C:\OpenSSL-v111-Win64\bin
|
||||
LIBCRYPTO: libssl-1_1-x64.dll
|
||||
LIBSSL: libcrypto-1_1-x64.dll
|
||||
- QTDIR: C:\Qt\6.2\msvc2019_64
|
||||
NSISDEF: /DQT6
|
||||
|
||||
install:
|
||||
- cmd: |-
|
||||
set PATH=%QTDIR%\bin;%NSISDIR%;%PATH%
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\"%VCVARS%
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat
|
||||
|
||||
build_script:
|
||||
- cmd: |-
|
||||
@ -43,17 +28,16 @@ build_script:
|
||||
md installer
|
||||
copy release\GPXSee.exe installer
|
||||
windeployqt --release installer\GPXSee.exe
|
||||
copy pkg\%NSI% installer
|
||||
copy pkg\macros.nsh installer
|
||||
copy pkg\gpxsee64.nsi installer
|
||||
xcopy pkg\csv installer\csv /i
|
||||
xcopy pkg\maps installer\maps /i
|
||||
xcopy lang\*.qm installer\translations\ /sy
|
||||
xcopy icons\symbols installer\symbols /i
|
||||
copy licence.txt installer
|
||||
copy %OPENSSLDIR%\%LIBCRYPTO% installer
|
||||
copy %OPENSSLDIR%\%LIBSSL% installer
|
||||
copy %OPENSSLDIR%\libcrypto-1_1-x64.dll installer
|
||||
copy %OPENSSLDIR%\libssl-1_1-x64.dll installer
|
||||
|
||||
makensis.exe %NSISDEF% installer\%NSI%
|
||||
makensis.exe %NSISDEF% installer\gpxsee64.nsi
|
||||
|
||||
artifacts:
|
||||
- path: installer\GPXSee-*.exe
|
||||
|
24
.github/workflows/linux.yml
vendored
Normal 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
|
31
.github/workflows/osx.yml
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
name: OS X
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: GPXSee
|
||||
runs-on: macos-10.15
|
||||
steps:
|
||||
- name: Set environment variables
|
||||
run: echo "PATH=/usr/local/opt/qt@5/bin:$PATH" >> $GITHUB_ENV
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Install dependencies
|
||||
run: brew install qt5
|
||||
- name: Create localization
|
||||
run: lrelease gpxsee.pro
|
||||
- name: Configure build
|
||||
run: qmake gpxsee.pro
|
||||
- name: Build project
|
||||
run: make -j3
|
||||
- name: Create DMG
|
||||
run: macdeployqt GPXSee.app -dmg
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: GPXSee.dmg
|
||||
path: GPXSee.dmg
|
32
.travis.yml
@ -1,32 +0,0 @@
|
||||
language: c++
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
dist: focal
|
||||
osx_image: xcode12.5
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/Library/Caches/Homebrew
|
||||
|
||||
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
|
||||
- lrelease gpxsee.pro
|
||||
- qmake gpxsee.pro
|
||||
- make
|
45
README.md
@ -1,25 +1,35 @@
|
||||
# GPXSee
|
||||
GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common GPS log file formats.
|
||||
GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common
|
||||
GPS log file formats.
|
||||
|
||||
## Features
|
||||
* 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, ESRI World-File georeferenced images).
|
||||
* Elevation, speed, heart rate, cadence, power, temperature and gear ratio/shifts graphs.
|
||||
* 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,
|
||||
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,
|
||||
Garmin IMG/GMAP & JNX maps, TwoNav RMaps, GeoTIFF images, BSB charts, KMZ maps,
|
||||
AlpineQuest maps, Locus/OsmAnd/RMaps SQLite maps, Mapsforge vector maps,
|
||||
QCT 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.
|
||||
* Support for POI files.
|
||||
* 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.
|
||||
|
||||

|
||||
|
||||
## Build
|
||||
Build requirements:
|
||||
* Qt5 >= 5.11 or Qt 6.x
|
||||
* C++11 or newer compiler (tested: msvc2017, gcc 7.5.0, clang/Apple LLVM version 10.0.0)
|
||||
* Qt5 >= 5.11 or Qt 6.x*
|
||||
* C++11 or newer compiler (tested: msvc2017, gcc 7.5.0, clang/Apple LLVM version
|
||||
10.0.0)
|
||||
|
||||
Build steps:
|
||||
```shell
|
||||
@ -28,6 +38,9 @@ qmake gpxsee.pro
|
||||
make # nmake on windows
|
||||
```
|
||||
|
||||
_* Qt6 builds do not support other encodings than UTF-X and iso8859-1 in XML
|
||||
files as support for such files was dropped in Qt6._
|
||||
|
||||
## Download
|
||||
* [Windows & OS X builds](http://sourceforge.net/projects/gpxsee)
|
||||
* [Linux packages](http://software.opensuse.org/download.html?project=home%3Atumic%3AGPXSee&package=gpxsee)
|
||||
@ -42,18 +55,22 @@ make # nmake on windows
|
||||
[GPXSee maps repository](https://github.com/tumic0/GPXSee-maps)
|
||||
|
||||
## Translations
|
||||
GPXSee uses [Weblate](https://hosted.weblate.org/projects/gpxsee/translations/) for translations.
|
||||
GPXSee uses [Weblate](https://hosted.weblate.org/projects/gpxsee/translations/)
|
||||
for translations.
|
||||
|
||||
## License
|
||||
GPXSee is licensed under GPL-3.0 (only). However, some 3rd party parts are using different, GPL compatible,
|
||||
licenses:
|
||||
GPXSee is licensed under GPL-3.0 (only). However, some 3rd party parts are using
|
||||
different, GPL compatible, licenses:
|
||||
|
||||
* [Oxygen icons](icons/GUI) - LGPLv3
|
||||
* [Mapbox Maki icons](icons/IMG) - CC0
|
||||
* [Map Icons Collection](icons/symbols) - CC BY SA 3.0
|
||||
* [RTree implementation](src/common/rtree.h) - Public domain
|
||||
* [Albers](src/map/proj/albersequal.cpp), [Geocentric](src/map/geocentric.cpp), [LCC](src/map/proj/lambertconic.cpp),
|
||||
[Mercator](src/map/proj/mercator.cpp), [Polar Stereographic](src/map/proj/polarstereographic.cpp),
|
||||
[Polyconic](src/map/proj/polyconic.cpp) and [Transverse Mercator](src/map/proj/transversemercator.cpp)
|
||||
projections - NIMA Source Code Disclaimer
|
||||
* [Albers](src/map/proj/albersequal.cpp), [Geocentric](src/map/geocentric.cpp),
|
||||
[LCC](src/map/proj/lambertconic.cpp), [Mercator](src/map/proj/mercator.cpp),
|
||||
[Polar Stereographic](src/map/proj/polarstereographic.cpp),
|
||||
[Polyconic](src/map/proj/polyconic.cpp) and
|
||||
[Transverse Mercator](src/map/proj/transversemercator.cpp) projections - NIMA
|
||||
Source Code Disclaimer
|
||||
* [Projection parameters CSV files](pkg/csv) - BSD/EPSG/Public domain
|
||||
* [Mapsforge render theme](data/default.xml) and its [icons](icons/mapsforge) - LGPLv3
|
||||
|
26
gpxsee.pro
@ -3,7 +3,7 @@ unix:!macx {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 9.8
|
||||
VERSION = 10.1
|
||||
|
||||
QT += core \
|
||||
gui \
|
||||
@ -12,12 +12,19 @@ QT += core \
|
||||
sql \
|
||||
concurrent \
|
||||
widgets \
|
||||
printsupport
|
||||
greaterThan(QT_MAJOR_VERSION, 5) {QT += openglwidgets}
|
||||
printsupport \
|
||||
positioning
|
||||
greaterThan(QT_MAJOR_VERSION, 5) {
|
||||
QT += openglwidgets \
|
||||
core5compat
|
||||
}
|
||||
|
||||
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 \
|
||||
@ -105,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 \
|
||||
@ -143,6 +151,7 @@ HEADERS += src/common/config.h \
|
||||
src/map/mapsforge/mapdata.h \
|
||||
src/map/mapsforge/rastertile.h \
|
||||
src/map/mapsforge/subfile.h \
|
||||
src/map/qctmap.h \
|
||||
src/map/textpathitem.h \
|
||||
src/map/textpointitem.h \
|
||||
src/map/prjfile.h \
|
||||
@ -234,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 \
|
||||
@ -301,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 \
|
||||
@ -336,6 +349,7 @@ SOURCES += src/main.cpp \
|
||||
src/map/mapsforge/subfile.cpp \
|
||||
src/map/imgmap.cpp \
|
||||
src/map/prjfile.cpp \
|
||||
src/map/qctmap.cpp \
|
||||
src/map/textpathitem.cpp \
|
||||
src/map/textpointitem.cpp \
|
||||
src/map/bsbmap.cpp \
|
||||
@ -482,7 +496,9 @@ win32 {
|
||||
icons/formats/itn.ico \
|
||||
icons/formats/wld.ico \
|
||||
icons/formats/omd.ico \
|
||||
icons/formats/ghp.ico
|
||||
icons/formats/ghp.ico \
|
||||
icons/formats/qct.ico \
|
||||
icons/formats/trk.ico
|
||||
DEFINES += _USE_MATH_DEFINES \
|
||||
NOGDI
|
||||
}
|
||||
@ -498,7 +514,7 @@ unix:!macx {
|
||||
symbols.path = $$PREFIX/share/gpxsee/symbols
|
||||
locale.files = $$files(lang/*.qm)
|
||||
locale.path = $$PREFIX/share/gpxsee/translations
|
||||
icon.files = $files(icons/app/hicolor/*)
|
||||
icon.files = $$files(icons/app/hicolor/*)
|
||||
icon.path = $$PREFIX/share/icons/hicolor
|
||||
desktop.files = pkg/gpxsee.desktop
|
||||
desktop.path = $$PREFIX/share/applications
|
||||
|
@ -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 -->
|
||||
|
BIN
icons/GUI/transform-move.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/GUI/transform-move@2x.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
icons/GUI/transform-move_32.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
icons/GUI/transform-move_32@2x.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
icons/formats/qct.icns
Normal file
BIN
icons/formats/qct.ico
Normal file
After Width: | Height: | Size: 306 KiB |
@ -27,3 +27,5 @@ itn:#b8540d
|
||||
wld:#c74c8f
|
||||
omd:#ed09cb
|
||||
ghp:#ed09cb
|
||||
qct:#370642
|
||||
trk:#cccccc
|
||||
|
BIN
icons/formats/trk.icns
Normal file
BIN
icons/formats/trk.ico
Normal file
After Width: | Height: | Size: 298 KiB |
BIN
icons/symbols/Flag, Blue.png
Normal file
After Width: | Height: | Size: 747 B |
BIN
icons/symbols/Flag, Green.png
Normal file
After Width: | Height: | Size: 827 B |
BIN
icons/symbols/Flag, Red.png
Normal file
After Width: | Height: | Size: 724 B |
BIN
icons/symbols/Flag.png
Normal file
After Width: | Height: | Size: 724 B |
Before Width: | Height: | Size: 827 B After Width: | Height: | Size: 747 B |
2365
lang/gpxsee_ko.ts
Normal file
@ -578,6 +578,38 @@
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>qct</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/vnd.memory-map.qct</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/qct.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>QuickChart Map File</string>
|
||||
<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>
|
||||
@ -1368,6 +1400,52 @@
|
||||
<string>application/vnd.onmove.ghp</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>com.memory-map.qct</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>https://raw.githubusercontent.com/craigshelley/QuickChart/master/Specification/The%20Quick%20Chart%20File%20Format%20Specification%201.03.pdf</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>QuickChart Map File</string>
|
||||
<key>UTTypeIconFile</key>
|
||||
<string>icons/qct.icns</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>qct</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<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>
|
||||
|
@ -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 & CSV, TomTom OV2 & ITN, ONmove OMD/GHP
|
||||
and geotagged JPEG files.</li>
|
||||
Garmin GPI & CSV, TomTom OV2 & 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,
|
||||
TwoNav RMaps, Garmin IMG & JNX maps, GeoTIFF images,
|
||||
BSB nautical charts, KMZ maps, AlpineQuest maps,
|
||||
Mapsforge maps), ESRI world files.</li>
|
||||
Mapsforge maps, QCT 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>
|
||||
@ -30,6 +30,7 @@
|
||||
<li>Print/export to PDF & PNG.</li>
|
||||
<li>Full-screen mode.</li>
|
||||
<li>HiDPI/Retina displays & maps support.</li>
|
||||
<li>Real-time GPS position.</li>
|
||||
</ul>
|
||||
</description>
|
||||
|
||||
@ -97,5 +98,9 @@
|
||||
<mimetype>application/vnd.esri.wld</mimetype>
|
||||
<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>
|
||||
|
@ -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
|
||||
|
400
pkg/gpxsee.nsi
@ -1,400 +0,0 @@
|
||||
!include "MUI2.nsh"
|
||||
!include "x64.nsh"
|
||||
!include "WinVer.nsh"
|
||||
!include "macros.nsh"
|
||||
|
||||
|
||||
Unicode true
|
||||
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "9.8"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}.exe"
|
||||
; Compression method
|
||||
SetCompressor /SOLID lzma
|
||||
|
||||
; Required execution level
|
||||
RequestExecutionLevel admin
|
||||
|
||||
; Don't let the OS scale(blur) the installer GUI
|
||||
ManifestDPIAware true
|
||||
|
||||
; The default installation directory
|
||||
InstallDir "$PROGRAMFILES\GPXSee"
|
||||
|
||||
; Installer executable info
|
||||
VIProductVersion "${VERSION}.0.0"
|
||||
VIAddVersionKey "ProductVersion" ${VERSION}
|
||||
VIAddVersionKey "FileVersion" "${VERSION}.0.0"
|
||||
VIAddVersionKey "ProductName" "GPXSee"
|
||||
VIAddVersionKey "LegalCopyright" "GPXSee project"
|
||||
VIAddVersionKey "FileDescription" "GPXSee installer"
|
||||
|
||||
; Registry key to check for directory (so if you install again, it will
|
||||
; overwrite the old one automatically)
|
||||
InstallDirRegKey HKLM "Software\GPXSee" "Install_Dir"
|
||||
|
||||
; Registry key for uninstaller
|
||||
!define REGENTRY "Software\Microsoft\Windows\CurrentVersion\Uninstall\GPXSee"
|
||||
|
||||
; Start menu page configuration
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM"
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\GPXSee"
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "GPXSee"
|
||||
|
||||
Var StartMenuFolder
|
||||
|
||||
;--------------------------------
|
||||
|
||||
; Pages
|
||||
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_LICENSE "licence.txt"
|
||||
!insertmacro MUI_PAGE_COMPONENTS
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
|
||||
;--------------------------------
|
||||
|
||||
; Languages
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
|
||||
Function .onInit
|
||||
${IfNot} ${AtLeastWin7}
|
||||
MessageBox MB_OK "GPXSee can only be installed on Windows 7 or later."
|
||||
Abort
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
; The stuff to install
|
||||
Section "GPXSee" SEC_APP
|
||||
|
||||
SectionIn RO
|
||||
|
||||
; Set output path to the installation directory
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
; Put the files there
|
||||
File "gpxsee.exe"
|
||||
File /r "maps"
|
||||
File /r "csv"
|
||||
File /r "symbols"
|
||||
|
||||
; Create the uninstaller
|
||||
WriteUninstaller "$INSTDIR\uninstall.exe"
|
||||
|
||||
; Create start menu entry and add links
|
||||
SetShellVarContext all
|
||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
||||
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\GPXSee.lnk" "$INSTDIR\gpxsee.exe"
|
||||
!insertmacro MUI_STARTMENU_WRITE_END
|
||||
|
||||
; Write the installation path into the registry
|
||||
DetailPrint "Registering application..."
|
||||
WriteRegStr HKLM SOFTWARE\GPXSee "Install_Dir" "$INSTDIR"
|
||||
|
||||
; Write the uninstall keys for Windows
|
||||
WriteRegStr HKLM "${REGENTRY}" "DisplayName" "GPXSee"
|
||||
WriteRegStr HKLM "${REGENTRY}" "Publisher" "Martin Tůma"
|
||||
WriteRegStr HKLM "${REGENTRY}" "DisplayVersion" "${VERSION}"
|
||||
WriteRegStr HKLM "${REGENTRY}" "UninstallString" '"$INSTDIR\uninstall.exe"'
|
||||
WriteRegStr HKLM "${REGENTRY}" "DisplayIcon" '"$INSTDIR\gpxsee.exe"'
|
||||
WriteRegStr HKLM "${REGENTRY}" "InstallLocation" '"$INSTDIR"'
|
||||
WriteRegStr HKLM "${REGENTRY}" "URLInfoAbout" "https://www.gpxsee.org"
|
||||
WriteRegDWORD HKLM "${REGENTRY}" "NoModify" 1
|
||||
WriteRegDWORD HKLM "${REGENTRY}" "NoRepair" 1
|
||||
|
||||
; Associate file formats
|
||||
DetailPrint "Associating file types..."
|
||||
!insertmacro FILE_ASSOCIATION_ADD "wpt" "OziExplorer Waypoint File" 1
|
||||
!insertmacro FILE_ASSOCIATION_ADD "loc" "Geocaching.com Waypoint File" 2
|
||||
!insertmacro FILE_ASSOCIATION_ADD "slf" "Sigma Log File" 3
|
||||
!insertmacro FILE_ASSOCIATION_ADD "geojson" "GeoJSON" 4
|
||||
!insertmacro FILE_ASSOCIATION_ADD "cup" "SeeYou CUP File" 5
|
||||
!insertmacro FILE_ASSOCIATION_ADD "gpi" "Garmin POI File" 6
|
||||
!insertmacro FILE_ASSOCIATION_ADD "sml" "Suunto Markup Language" 7
|
||||
!insertmacro FILE_ASSOCIATION_ADD "img" "Garmin IMG Map" 8
|
||||
!insertmacro FILE_ASSOCIATION_ADD "jnx" "Garmin JNX Map" 9
|
||||
!insertmacro FILE_ASSOCIATION_ADD "kap" "BSB Nautical Chart" 10
|
||||
!insertmacro FILE_ASSOCIATION_ADD "gpx" "GPS Exchange Format" 11
|
||||
!insertmacro FILE_ASSOCIATION_ADD "map" "OziExplorer Map File" 12
|
||||
!insertmacro FILE_ASSOCIATION_ADD "mbtiles" "MBTiles Map File" 13
|
||||
!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 "ov2" "TomTom POI File" 18
|
||||
!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 "tcx" "Training Center XML" 22
|
||||
!insertmacro FILE_ASSOCIATION_ADD "ghp" "ONmove Log File" 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" ""
|
||||
WriteRegStr HKCR ".tcx\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".kml\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".fit\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".igc\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".nmea\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".plt\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".rte\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".wpt\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".loc\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".slf\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".geojson\OpenWithList" "GPXSee.exe" ""
|
||||
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" ""
|
||||
WriteRegStr HKCR ".jpeg\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".img\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".jnx\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".kap\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".map\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".mbtiles\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".rmap\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".rtmap\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tar\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tba\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tif\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tiff\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".xml\OpenWithList" "GPXSee.exe" ""
|
||||
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)'
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "QT framework" SEC_QT
|
||||
|
||||
SectionIn RO
|
||||
|
||||
File "Qt5Core.dll"
|
||||
File "Qt5Gui.dll"
|
||||
File "Qt5Widgets.dll"
|
||||
File "Qt5PrintSupport.dll"
|
||||
File "Qt5Network.dll"
|
||||
File "Qt5Sql.dll"
|
||||
File "Qt5Svg.dll"
|
||||
File "Qt5Concurrent.dll"
|
||||
File /r "platforms"
|
||||
File /r "imageformats"
|
||||
File /r "printsupport"
|
||||
File /r "styles"
|
||||
File /r "sqldrivers"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "MSVC runtime" SEC_MSVC
|
||||
|
||||
SectionIn RO
|
||||
|
||||
SetOutPath $TEMP
|
||||
File "vc_redist.x86.exe"
|
||||
ExecWait '"$TEMP\vc_redist.x86.exe" /install /quiet /norestart'
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "OpenSSL" SEC_OPENSSL
|
||||
|
||||
SectionIn RO
|
||||
|
||||
File "libcrypto-1_1.dll"
|
||||
File "libssl-1_1.dll"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "ANGLE" SEC_ANGLE
|
||||
|
||||
File "libGLESv2.dll"
|
||||
File "libEGL.dll"
|
||||
File "D3DCompiler_47.dll"
|
||||
|
||||
SectionEnd
|
||||
|
||||
SectionGroup "Localization" SEC_LOCALIZATION
|
||||
!insertmacro LOCALIZATION "Chinese (Simplified)" "zh"
|
||||
!insertmacro LOCALIZATION "Czech" "cs"
|
||||
!insertmacro LOCALIZATION "Danish" "da"
|
||||
!insertmacro LOCALIZATION "Esperanto" "eo"
|
||||
!insertmacro LOCALIZATION "Finnish" "fi"
|
||||
!insertmacro LOCALIZATION "French" "fr"
|
||||
!insertmacro LOCALIZATION "German" "de"
|
||||
!insertmacro LOCALIZATION "Hungarian" "hu"
|
||||
!insertmacro LOCALIZATION "Italian" "it"
|
||||
!insertmacro LOCALIZATION "Norwegian" "nb"
|
||||
!insertmacro LOCALIZATION "Polish" "pl"
|
||||
!insertmacro LOCALIZATION "Portuguese (Brazil)" "pt_BR"
|
||||
!insertmacro LOCALIZATION "Russian" "ru"
|
||||
!insertmacro LOCALIZATION "Spanish" "es"
|
||||
!insertmacro LOCALIZATION "Swedish" "sv"
|
||||
!insertmacro LOCALIZATION "Turkish" "tr"
|
||||
!insertmacro LOCALIZATION "Ukrainian" "uk"
|
||||
SectionGroupEnd
|
||||
|
||||
;--------------------------------
|
||||
|
||||
; Uninstaller
|
||||
|
||||
Section "Uninstall"
|
||||
|
||||
; Remove registry keys
|
||||
DeleteRegKey HKLM "${REGENTRY}"
|
||||
DeleteRegKey HKLM SOFTWARE\GPXSee
|
||||
|
||||
; Remove directories used
|
||||
RMDir /r "$INSTDIR"
|
||||
|
||||
; Remove Start menu entries
|
||||
SetShellVarContext all
|
||||
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder
|
||||
Delete "$SMPROGRAMS\$StartMenuFolder\*.*"
|
||||
RMDir "$SMPROGRAMS\$StartMenuFolder"
|
||||
|
||||
; Remove file associations
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "gpx"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "tcx"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "kml"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "fit"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "igc"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "nmea"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "plt"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "rte"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "wpt"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "loc"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "slf"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "geojson"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "cup"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "gpi"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "sml"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "img"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "jnx"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "kap"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "map"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "mbtiles"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "rmap"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "tba"
|
||||
!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"
|
||||
DeleteRegValue HKCR ".kml\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".fit\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".igc\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".nmea\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".plt\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".rte\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".wpt\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".loc\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".slf\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".geojson\OpenWithList" "GPXSee.exe"
|
||||
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"
|
||||
DeleteRegValue HKCR ".jpeg\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".img\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".jnx\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".kap\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".map\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".mbtiles\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".rmap\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".rtmap\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tar\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tba\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tif\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tiff\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".xml\OpenWithList" "GPXSee.exe"
|
||||
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)'
|
||||
|
||||
SectionEnd
|
||||
|
||||
;-------------------------------
|
||||
|
||||
;Descriptions
|
||||
|
||||
;Language strings
|
||||
LangString DESC_QT ${LANG_ENGLISH} \
|
||||
"QT cross-platform application framework."
|
||||
LangString DESC_MSVC ${LANG_ENGLISH} \
|
||||
"Microsoft Visual C++ 2017 runtime. If already installed, will be skipped."
|
||||
LangString DESC_OPENSSL ${LANG_ENGLISH} \
|
||||
"OpenSSL library. Required for HTTPS to work."
|
||||
LangString DESC_ANGLE ${LANG_ENGLISH} \
|
||||
"ANGLE (OpenGL via Direct3D). Enables OpenGL on systems without native OpenGL drivers."
|
||||
LangString DESC_APP ${LANG_ENGLISH} \
|
||||
"GPXSee application"
|
||||
LangString DESC_LOCALIZATION ${LANG_ENGLISH} \
|
||||
"Localization"
|
||||
|
||||
;Assign language strings to sections
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_QT} $(DESC_QT)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_OPENSSL} $(DESC_OPENSSL)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_ANGLE} $(DESC_ANGLE)
|
||||
!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
|
@ -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">
|
||||
@ -285,4 +307,14 @@
|
||||
<glob pattern="*.tfw"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/vnd.memory-map.qct">
|
||||
<comment>QuickChart Map File</comment>
|
||||
<sub-class-of type="application/octet-stream"/>
|
||||
<generic-icon name="application/octet-stream"/>
|
||||
<magic>
|
||||
<match type="little32" offset="0" value="0x1423D5FF"/>
|
||||
</magic>
|
||||
<glob pattern="*.qct"/>
|
||||
</mime-type>
|
||||
|
||||
</mime-info>
|
||||
|
@ -1,15 +1,43 @@
|
||||
!include "MUI2.nsh"
|
||||
!include "x64.nsh"
|
||||
!include "WinVer.nsh"
|
||||
!include "macros.nsh"
|
||||
|
||||
|
||||
; Macros
|
||||
|
||||
; File association
|
||||
!macro FILE_ASSOCIATION_ADD EXT DESC ICON
|
||||
WriteRegStr HKCR ".${EXT}" "" "GPXSee.${EXT}"
|
||||
WriteRegStr HKCR "GPXSee.${EXT}" "" "${DESC}"
|
||||
WriteRegStr HKCR "GPXSee.${EXT}\DefaultIcon" "" "$INSTDIR\GPXSee.exe,${ICON}"
|
||||
WriteRegStr HKCR "GPXSee.${EXT}\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
|
||||
!macroend
|
||||
|
||||
!macro FILE_ASSOCIATION_REMOVE EXT
|
||||
DeleteRegKey HKCR "GPXSee.${EXT}"
|
||||
DeleteRegKey HKCR ".${EXT}"
|
||||
!macroend
|
||||
|
||||
; Translations
|
||||
!macro LOCALIZATION LANG CODE
|
||||
Section "${LANG}"
|
||||
IfFileExists "$INSTDIR\translations" +2 0
|
||||
CreateDirectory "$INSTDIR\translations"
|
||||
File /oname=translations\gpxsee_${CODE}.qm translations\gpxsee_${CODE}.qm
|
||||
!if /FileExists translations\qt_${CODE}.qm
|
||||
File /oname=translations\qt_${CODE}.qm translations\qt_${CODE}.qm
|
||||
!endif
|
||||
SectionEnd
|
||||
!macroend
|
||||
|
||||
;--------------------------------
|
||||
|
||||
Unicode true
|
||||
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "9.8"
|
||||
!define VERSION "10.1"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
@ -149,13 +177,15 @@ Section "GPXSee" SEC_APP
|
||||
!insertmacro FILE_ASSOCIATION_ADD "omd" "ONmove Log File" 21
|
||||
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 22
|
||||
!insertmacro FILE_ASSOCIATION_ADD "ghp" "ONmove Log File" 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
|
||||
!insertmacro FILE_ASSOCIATION_ADD "qct" "QuickChart Map File" 24
|
||||
!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" ""
|
||||
@ -201,6 +231,8 @@ Section "GPXSee" SEC_APP
|
||||
WriteRegStr HKCR ".tfw\OpenWithList" "GPXSee.exe" ""
|
||||
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)'
|
||||
|
||||
@ -221,6 +253,9 @@ Section "QT framework" SEC_QT
|
||||
File "Qt6Sql.dll"
|
||||
File "Qt6Svg.dll"
|
||||
File "Qt6Widgets.dll"
|
||||
File "Qt6Core5Compat.dll"
|
||||
File "Qt6Positioning.dll"
|
||||
File "Qt6SerialPort.dll"
|
||||
!else
|
||||
File "Qt5Core.dll"
|
||||
File "Qt5Gui.dll"
|
||||
@ -230,12 +265,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
|
||||
|
||||
@ -344,6 +382,8 @@ Section "Uninstall"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "tfw"
|
||||
!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"
|
||||
@ -388,6 +428,8 @@ Section "Uninstall"
|
||||
DeleteRegValue HKCR ".tfw\OpenWithList" "GPXSee.exe"
|
||||
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)'
|
||||
|
@ -1,24 +0,0 @@
|
||||
; File association
|
||||
!macro FILE_ASSOCIATION_ADD EXT DESC ICON
|
||||
WriteRegStr HKCR ".${EXT}" "" "GPXSee.${EXT}"
|
||||
WriteRegStr HKCR "GPXSee.${EXT}" "" "${DESC}"
|
||||
WriteRegStr HKCR "GPXSee.${EXT}\DefaultIcon" "" "$INSTDIR\GPXSee.exe,${ICON}"
|
||||
WriteRegStr HKCR "GPXSee.${EXT}\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
|
||||
!macroend
|
||||
|
||||
!macro FILE_ASSOCIATION_REMOVE EXT
|
||||
DeleteRegKey HKCR "GPXSee.${EXT}"
|
||||
DeleteRegKey HKCR ".${EXT}"
|
||||
!macroend
|
||||
|
||||
; Translations
|
||||
!macro LOCALIZATION LANG CODE
|
||||
Section "${LANG}"
|
||||
IfFileExists "$INSTDIR\translations" +2 0
|
||||
CreateDirectory "$INSTDIR\translations"
|
||||
File /oname=translations\gpxsee_${CODE}.qm translations\gpxsee_${CODE}.qm
|
||||
!if /FileExists translations\qt_${CODE}.qm
|
||||
File /oname=translations\qt_${CODE}.qm translations\qt_${CODE}.qm
|
||||
!endif
|
||||
SectionEnd
|
||||
!macroend
|
@ -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();
|
||||
}
|
||||
|
@ -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
@ -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
@ -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
|
@ -36,11 +36,8 @@ void GraphItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
painter->setPen(_pen);
|
||||
painter->drawPath(_path);
|
||||
|
||||
/*
|
||||
QPen p = QPen(QBrush(Qt::red), 0);
|
||||
painter->setPen(p);
|
||||
painter->drawRect(boundingRect());
|
||||
*/
|
||||
//painter->setPen(Qt::red);
|
||||
//painter->drawRect(boundingRect());
|
||||
}
|
||||
|
||||
void GraphItem::setGraphType(GraphType type)
|
||||
@ -78,11 +75,25 @@ void GraphItem::setWidth(int width)
|
||||
|
||||
const GraphSegment *GraphItem::segment(qreal x, GraphType type) const
|
||||
{
|
||||
for (int i = 0; i < _graph.size(); i++)
|
||||
if (x <= _graph.at(i).last().x(type))
|
||||
return &(_graph.at(i));
|
||||
int low = 0;
|
||||
int high = _graph.size() - 1;
|
||||
int mid = 0;
|
||||
|
||||
return 0;
|
||||
while (low <= high) {
|
||||
mid = (high + low) / 2;
|
||||
const GraphPoint &p = _graph.at(mid).last();
|
||||
if (p.x(_type) > x)
|
||||
high = mid - 1;
|
||||
else if (p.x(_type) < x)
|
||||
low = mid + 1;
|
||||
else
|
||||
return &(_graph.at(mid));
|
||||
}
|
||||
|
||||
if (_graph.at(mid).last().x(type) < x)
|
||||
return (mid == _graph.size() - 1) ? 0 : &(_graph.at(mid+1));
|
||||
else
|
||||
return &(_graph.at(mid));
|
||||
}
|
||||
|
||||
qreal GraphItem::yAtX(qreal x) const
|
||||
@ -99,7 +110,7 @@ qreal GraphItem::yAtX(qreal x) const
|
||||
return NAN;
|
||||
|
||||
while (low <= high) {
|
||||
mid = low + ((high - low) / 2);
|
||||
mid = (high + low) / 2;
|
||||
const GraphPoint &p = seg->at(mid);
|
||||
if (p.x(_type) > x)
|
||||
high = mid - 1;
|
||||
@ -137,7 +148,7 @@ qreal GraphItem::distanceAtTime(qreal time) const
|
||||
return NAN;
|
||||
|
||||
while (low <= high) {
|
||||
mid = low + ((high - low) / 2);
|
||||
mid = (high + low) / 2;
|
||||
const GraphPoint &p = seg->at(mid);
|
||||
if (p.t() > time)
|
||||
high = mid - 1;
|
||||
@ -175,7 +186,7 @@ qreal GraphItem::timeAtDistance(qreal distance) const
|
||||
return NAN;
|
||||
|
||||
while (low <= high) {
|
||||
mid = low + ((high - low) / 2);
|
||||
mid = (high + low) / 2;
|
||||
const GraphPoint &p = seg->at(mid);
|
||||
if (p.s() > distance)
|
||||
high = mid - 1;
|
||||
|
@ -350,12 +350,12 @@ void GraphView::mousePressEvent(QMouseEvent *e)
|
||||
|
||||
void GraphView::wheelEvent(QWheelEvent *e)
|
||||
{
|
||||
static int deg = 0;
|
||||
static int deg8 = 0;
|
||||
|
||||
deg += e->angleDelta().y() / 8;
|
||||
if (qAbs(deg) < 15)
|
||||
deg8 += e->angleDelta().y();
|
||||
if (qAbs(deg8) < (15 * 8))
|
||||
return;
|
||||
deg = 0;
|
||||
deg8 = deg8 % (15 * 8);
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||
QPointF pos = mapToScene(e->pos());
|
||||
|
158
src/GUI/gui.cpp
@ -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,25 @@ 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)) {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
QGeoPositionInfoSource *source = QGeoPositionInfoSource::createSource(
|
||||
options.plugin, this);
|
||||
#else // QT 5.14
|
||||
QGeoPositionInfoSource *source = QGeoPositionInfoSource::createSource(
|
||||
options.plugin, options.pluginParams.value(options.plugin), this);
|
||||
#endif // QT 5.14
|
||||
_showPositionAction->setEnabled(source != 0);
|
||||
_mapView->setPositionSource(source);
|
||||
delete _positionSource;
|
||||
_positionSource = source;
|
||||
}
|
||||
|
||||
if (options.hidpiMap != _options.hidpiMap)
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||
@ -2098,6 +2151,8 @@ void GUI::dropEvent(QDropEvent *event)
|
||||
|
||||
void GUI::writeSettings()
|
||||
{
|
||||
int index;
|
||||
|
||||
QSettings settings(qApp->applicationName(), qApp->applicationName());
|
||||
settings.clear();
|
||||
|
||||
@ -2133,8 +2188,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 +2220,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 +2333,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 +2410,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 +2512,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 +2670,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 +2744,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 +2792,36 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs)
|
||||
.toString();
|
||||
_options.poiPath = settings.value(POI_PATH_SETTING, POI_PATH_DEFAULT)
|
||||
.toString();
|
||||
settings.endGroup();
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
_positionSource = QGeoPositionInfoSource::createSource(_options.plugin,
|
||||
this);
|
||||
#else // QT 5.14
|
||||
_positionSource = QGeoPositionInfoSource::createSource(_options.plugin,
|
||||
_options.pluginParams.value(_options.plugin), this);
|
||||
#endif // QT 5.14
|
||||
_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 +2842,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 +2888,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)
|
||||
|
@ -24,6 +24,7 @@ class QAction;
|
||||
class QLabel;
|
||||
class QSplitter;
|
||||
class QPrinter;
|
||||
class QGeoPositionInfoSource;
|
||||
class FileBrowser;
|
||||
class GraphTab;
|
||||
class MapView;
|
||||
@ -198,6 +199,10 @@ private:
|
||||
QAction *_showPOILabelsAction;
|
||||
QAction *_showPOIIconsAction;
|
||||
QAction *_showMapAction;
|
||||
QAction *_showPositionAction;
|
||||
QAction *_followPositionAction;
|
||||
QAction *_showPositionCoordinatesAction;
|
||||
QAction *_showMotionInfo;
|
||||
QAction *_fullscreenAction;
|
||||
QAction *_loadMapAction;
|
||||
QAction *_loadMapDirAction;
|
||||
@ -253,6 +258,7 @@ private:
|
||||
|
||||
POI *_poi;
|
||||
Map *_map;
|
||||
QGeoPositionInfoSource *_positionSource;
|
||||
DEMLoader *_dem;
|
||||
|
||||
FileBrowser *_browser;
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
@ -586,17 +637,17 @@ void MapView::zoom(int zoom, const QPoint &pos, bool shift)
|
||||
|
||||
void MapView::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
static int deg = 0;
|
||||
static int deg8 = 0;
|
||||
bool shift = (event->modifiers() & MODIFIER) ? true : false;
|
||||
// Shift inverts the wheel axis on OS X, so use scrolling in both axes for
|
||||
// the zoom.
|
||||
int delta = event->angleDelta().y()
|
||||
? event->angleDelta().y() : event->angleDelta().x();
|
||||
|
||||
deg += delta / 8;
|
||||
if (qAbs(deg) < 15)
|
||||
deg8 += delta;
|
||||
if (qAbs(deg8) < (15 * 8))
|
||||
return;
|
||||
deg = 0;
|
||||
deg8 = deg8 % (15 * 8);
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||
zoom((delta > 0) ? 1 : -1, event->pos(), 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);
|
||||
}
|
||||
|
@ -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
@ -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
@ -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
|
@ -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();
|
||||
|
@ -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;
|
||||
|
76
src/GUI/pluginparameters.cpp
Normal 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> ¶ms, 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());
|
||||
}
|
||||
}
|
||||
}
|
27
src/GUI/pluginparameters.h
Normal 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> ¶ms, QWidget *parent = 0);
|
||||
|
||||
const QMap<QString, QVariantMap> ¶meters();
|
||||
|
||||
public slots:
|
||||
void setPlugin(const QString &plugin);
|
||||
|
||||
private:
|
||||
void saveParameters();
|
||||
|
||||
QMap<QString, QVariantMap> _params;
|
||||
QString _plugin;
|
||||
};
|
||||
|
||||
#endif // PLUGINPARAMETERS_H
|
@ -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"
|
||||
@ -186,6 +205,11 @@
|
||||
#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"
|
||||
|
@ -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
|
||||
|
@ -104,8 +104,12 @@ void WaypointItem::updateCache()
|
||||
_labelBB = fm.tightBoundingRect(_waypoint.name());
|
||||
|
||||
if (_showIcon && _icon) {
|
||||
p.addRect(-_icon->width()/2.0, -_icon->height(), _icon->width(),
|
||||
_icon->height());
|
||||
if (_font.bold())
|
||||
p.addRect(-_icon->width() * 0.625, -_icon->height() * 1.25,
|
||||
_icon->width() * 1.25, _icon->height() * 1.25);
|
||||
else
|
||||
p.addRect(-_icon->width()/2.0, -_icon->height(), _icon->width(),
|
||||
_icon->height());
|
||||
p.addRect(0, 0, _labelBB.width(), _labelBB.height() + fm.descent());
|
||||
} else {
|
||||
p.addRect(-pointSize/2, -pointSize/2, pointSize, pointSize);
|
||||
@ -113,10 +117,14 @@ void WaypointItem::updateCache()
|
||||
_labelBB.height() + fm.descent());
|
||||
}
|
||||
} else {
|
||||
if (_showIcon && _icon)
|
||||
p.addRect(-_icon->width()/2, -_icon->height(), _icon->width(),
|
||||
_icon->height());
|
||||
else
|
||||
if (_showIcon && _icon) {
|
||||
if (_font.bold())
|
||||
p.addRect(-_icon->width() * 0.625, -_icon->height() * 1.25,
|
||||
_icon->width() * 1.25, _icon->height() * 1.25);
|
||||
else
|
||||
p.addRect(-_icon->width()/2, -_icon->height(), _icon->width(),
|
||||
_icon->height());
|
||||
} else
|
||||
p.addRect(-pointSize/2, -pointSize/2, pointSize, pointSize);
|
||||
}
|
||||
|
||||
@ -143,16 +151,19 @@ void WaypointItem::paint(QPainter *painter,
|
||||
}
|
||||
|
||||
painter->setBrush(QBrush(_color, Qt::SolidPattern));
|
||||
if (_showIcon && _icon)
|
||||
painter->drawPixmap(-_icon->width()/2.0, -_icon->height(), *_icon);
|
||||
else
|
||||
if (_showIcon && _icon) {
|
||||
if (_font.bold())
|
||||
painter->drawPixmap(-_icon->width() * 0.625, -_icon->height() * 1.25,
|
||||
_icon->scaled(_icon->width() * 1.25, _icon->height() * 1.25,
|
||||
Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
else
|
||||
painter->drawPixmap(-_icon->width()/2.0, -_icon->height(), *_icon);
|
||||
} else
|
||||
painter->drawEllipse(-pointSize/2, -pointSize/2, pointSize, pointSize);
|
||||
|
||||
/*
|
||||
painter->setPen(Qt::red);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawPath(_shape);
|
||||
*/
|
||||
//painter->setPen(Qt::red);
|
||||
//painter->setBrush(Qt::NoBrush);
|
||||
//painter->drawPath(_shape);
|
||||
}
|
||||
|
||||
void WaypointItem::setSize(int size)
|
||||
|
@ -1,11 +1,41 @@
|
||||
#include "greatcircle.h"
|
||||
|
||||
#define DELTA 1e-5
|
||||
|
||||
static bool antipodes(const Coordinates &c1, const Coordinates &c2)
|
||||
{
|
||||
return ((qAbs(c1.lat() + c2.lat()) < DELTA)
|
||||
&& (qAbs(180.0 - qAbs(c1.lon() - c2.lon())) < DELTA));
|
||||
}
|
||||
|
||||
GreatCircle::GreatCircle(const Coordinates &c1, const Coordinates &c2)
|
||||
{
|
||||
double lat1 = deg2rad(c1.lat());
|
||||
double lon1 = deg2rad(c1.lon());
|
||||
double lat2 = deg2rad(c2.lat());
|
||||
double lon2 = deg2rad(c2.lon());
|
||||
double lat1, lon1, lat2, lon2;
|
||||
|
||||
if (antipodes(c1, c2)) {
|
||||
/* In case of antipodes (which would lead to garbage output without
|
||||
this hack), move the points DELTA degrees closer to each other in
|
||||
a way that the route never crosses the antimeridian. */
|
||||
if (c1.lon() < c2.lon()) {
|
||||
lon1 = deg2rad(c1.lon() + DELTA);
|
||||
lon2 = deg2rad(c2.lon() - DELTA);
|
||||
} else {
|
||||
lon1 = deg2rad(c1.lon() - DELTA);
|
||||
lon2 = deg2rad(c2.lon() + DELTA);
|
||||
}
|
||||
if (c1.lat() < c2.lat()) {
|
||||
lat1 = deg2rad(c1.lat() + DELTA);
|
||||
lat2 = deg2rad(c2.lat() - DELTA);
|
||||
} else {
|
||||
lat1 = deg2rad(c1.lat() - DELTA);
|
||||
lat2 = deg2rad(c2.lat() + DELTA);
|
||||
}
|
||||
} else {
|
||||
lat1 = deg2rad(c1.lat());
|
||||
lon1 = deg2rad(c1.lon());
|
||||
lat2 = deg2rad(c2.lat());
|
||||
lon2 = deg2rad(c2.lon());
|
||||
}
|
||||
|
||||
double cosLat1 = cos(lat1);
|
||||
double cosLat2 = cos(lat2);
|
||||
|
@ -1,214 +1,59 @@
|
||||
#include <QVector>
|
||||
#include <QTextCodec>
|
||||
#include "textcodec.h"
|
||||
|
||||
static const char32_t cp1250[] = {
|
||||
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A,
|
||||
0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B,
|
||||
0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C,
|
||||
0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
|
||||
0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
|
||||
0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
|
||||
0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
|
||||
0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
|
||||
0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
|
||||
0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
|
||||
0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
|
||||
};
|
||||
|
||||
static const char32_t cp1251[] = {
|
||||
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
|
||||
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x0000, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
|
||||
0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
|
||||
0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
|
||||
0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,
|
||||
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
|
||||
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
|
||||
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
|
||||
0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
|
||||
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
|
||||
0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
|
||||
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
|
||||
0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F
|
||||
};
|
||||
|
||||
static const char32_t cp1252[] = {
|
||||
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178,
|
||||
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
|
||||
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
|
||||
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
|
||||
0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
|
||||
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
|
||||
0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
|
||||
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
|
||||
0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
|
||||
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
|
||||
};
|
||||
|
||||
static const char32_t cp1253[] = {
|
||||
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
|
||||
0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
|
||||
0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
|
||||
0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
|
||||
0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
|
||||
0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
|
||||
0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
|
||||
0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
|
||||
0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000
|
||||
};
|
||||
|
||||
static const char32_t cp1254[] = {
|
||||
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
|
||||
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
|
||||
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
|
||||
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
|
||||
0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
|
||||
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF,
|
||||
0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
|
||||
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
|
||||
0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
|
||||
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF
|
||||
};
|
||||
|
||||
static const char32_t cp1255[] = {
|
||||
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AA, 0x00A5, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
|
||||
0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
|
||||
0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
|
||||
0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3,
|
||||
0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
|
||||
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
|
||||
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
|
||||
0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000
|
||||
};
|
||||
|
||||
static const char32_t cp1256[] = {
|
||||
0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
|
||||
0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA,
|
||||
0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F,
|
||||
0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
|
||||
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
|
||||
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7,
|
||||
0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0641, 0x0642, 0x0643,
|
||||
0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7,
|
||||
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF,
|
||||
0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7,
|
||||
0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2,
|
||||
};
|
||||
|
||||
static const char32_t cp1257[] = {
|
||||
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000,
|
||||
0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7,
|
||||
0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
|
||||
0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
|
||||
0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
|
||||
0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
|
||||
0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
|
||||
0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
|
||||
0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
|
||||
0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
|
||||
0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9,
|
||||
};
|
||||
|
||||
TextCodec::TextCodec() : _table(cp1252)
|
||||
TextCodec::TextCodec()
|
||||
{
|
||||
|
||||
_codec = QTextCodec::codecForName("Windows-1252");
|
||||
}
|
||||
|
||||
TextCodec::TextCodec(int codepage)
|
||||
{
|
||||
switch (codepage) {
|
||||
case 65001:
|
||||
_table = 0;
|
||||
_codec = 0;
|
||||
break;
|
||||
case 932:
|
||||
_codec = QTextCodec::codecForName("Shift-JIS");
|
||||
break;
|
||||
case 936:
|
||||
_codec = QTextCodec::codecForName("GB18030");
|
||||
break;
|
||||
case 949:
|
||||
_codec = QTextCodec::codecForName("EUC-KR");
|
||||
break;
|
||||
case 950:
|
||||
_codec = QTextCodec::codecForName("Big5");
|
||||
break;
|
||||
case 1250:
|
||||
_table = cp1250;
|
||||
_codec = QTextCodec::codecForName("Windows-1250");
|
||||
break;
|
||||
case 1251:
|
||||
_table = cp1251;
|
||||
_codec = QTextCodec::codecForName("Windows-1251");
|
||||
break;
|
||||
case 1253:
|
||||
_table = cp1253;
|
||||
_codec = QTextCodec::codecForName("Windows-1253");
|
||||
break;
|
||||
case 1254:
|
||||
_table = cp1254;
|
||||
_codec = QTextCodec::codecForName("Windows-1254");
|
||||
break;
|
||||
case 1255:
|
||||
_table = cp1255;
|
||||
_codec = QTextCodec::codecForName("Windows-1255");
|
||||
break;
|
||||
case 1256:
|
||||
_table = cp1256;
|
||||
_codec = QTextCodec::codecForName("Windows-1256");
|
||||
break;
|
||||
case 1257:
|
||||
_table = cp1257;
|
||||
_codec = QTextCodec::codecForName("Windows-1257");
|
||||
break;
|
||||
case 1258:
|
||||
_codec = QTextCodec::codecForName("Windows-1258");
|
||||
break;
|
||||
default:
|
||||
_table = cp1252;
|
||||
_codec = QTextCodec::codecForName("Windows-1252");
|
||||
}
|
||||
}
|
||||
|
||||
QString TextCodec::toString(const QByteArray &ba) const
|
||||
{
|
||||
if (_table)
|
||||
return from8bCp(ba);
|
||||
else
|
||||
return QString::fromUtf8(ba);
|
||||
}
|
||||
|
||||
QString TextCodec::from8bCp(const QByteArray &ba) const
|
||||
{
|
||||
QVector<char32_t> ucs4(ba.size());
|
||||
|
||||
for (int i = 0; i < ba.size(); i++) {
|
||||
quint8 c = (quint8)ba.at(i);
|
||||
if (c < 0x80)
|
||||
ucs4[i] = (char32_t)c;
|
||||
else
|
||||
ucs4[i] = _table[c - 0x80];
|
||||
}
|
||||
|
||||
return QString::fromUcs4(ucs4.constData(), ucs4.size());
|
||||
return _codec ? _codec->toUnicode(ba) : QString::fromUtf8(ba);
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
class QTextCodec;
|
||||
|
||||
class TextCodec
|
||||
{
|
||||
public:
|
||||
@ -12,9 +14,7 @@ public:
|
||||
QString toString(const QByteArray &ba) const;
|
||||
|
||||
private:
|
||||
QString from8bCp(const QByteArray &ba) const;
|
||||
|
||||
const char32_t *_table;
|
||||
QTextCodec *_codec;
|
||||
};
|
||||
|
||||
#endif // TEXTCODEC_H
|
||||
|
@ -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,6 +164,7 @@ 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") + " (*)";
|
||||
}
|
||||
|
||||
@ -162,7 +172,7 @@ QStringList Data::filter()
|
||||
{
|
||||
QStringList filter;
|
||||
|
||||
for (QMap<QString, Parser*>::iterator it = _parsers.begin();
|
||||
for (QMultiMap<QString, Parser*>::iterator it = _parsers.begin();
|
||||
it != _parsers.end(); it++)
|
||||
filter << "*." + it.key();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -537,7 +537,7 @@ static quint32 readPOI(DataStream &stream, QVector<Waypoint> &waypoints,
|
||||
quint8 rs;
|
||||
quint32 ds;
|
||||
qint32 lat, lon;
|
||||
quint16 s3, id;
|
||||
quint16 s3, iconId = 0;
|
||||
QList<TranslatedString> obj;
|
||||
|
||||
rs = stream.readRecordHeader(rh);
|
||||
@ -553,8 +553,7 @@ static quint32 readPOI(DataStream &stream, QVector<Waypoint> &waypoints,
|
||||
while (stream.status() == QDataStream::Ok && ds < rh.size) {
|
||||
switch (stream.nextHeaderType()) {
|
||||
case 4:
|
||||
ds += readIconId(stream, id);
|
||||
icons.append(QPair<int, quint16>(waypoints.size() - 1, id));
|
||||
ds += readIconId(stream, iconId);
|
||||
break;
|
||||
case 10:
|
||||
ds += readDescription(stream, waypoints.last());
|
||||
@ -576,6 +575,8 @@ static quint32 readPOI(DataStream &stream, QVector<Waypoint> &waypoints,
|
||||
}
|
||||
}
|
||||
|
||||
icons.append(QPair<int, quint16>(waypoints.size() - 1, iconId));
|
||||
|
||||
if (ds != rh.size)
|
||||
stream.setStatus(QDataStream::ReadCorruptData);
|
||||
|
||||
@ -659,11 +660,16 @@ static quint32 readSymbol(DataStream &stream, QPixmap &pixmap)
|
||||
img.setColorTable(palette);
|
||||
} else
|
||||
img = QImage((uchar*)data.data(), width, height, lineSize,
|
||||
QImage::Format_RGB32);
|
||||
QImage::Format_RGBX8888).rgbSwapped();
|
||||
pixmap = QPixmap::fromImage(img);
|
||||
|
||||
if (ds != rh.size)
|
||||
/* There should be no more data left in the record, but broken GPI files
|
||||
generated by pinns.co.uk tools exist in the wild so we read out
|
||||
the record as a workaround for such files. */
|
||||
if (ds > rh.size)
|
||||
stream.setStatus(QDataStream::ReadCorruptData);
|
||||
else if (ds < rh.size)
|
||||
stream.skipRawData(rh.size - ds);
|
||||
|
||||
return rs + rh.size;
|
||||
}
|
||||
|
229
src/data/twonavparser.cpp
Normal file
@ -0,0 +1,229 @@
|
||||
#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()) {
|
||||
_errorString = "Invalid date/time";
|
||||
return false;
|
||||
}
|
||||
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()) {
|
||||
_errorString = "Invalid date/time";
|
||||
return false;
|
||||
}
|
||||
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
@ -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
|
@ -41,16 +41,15 @@ bool BitStream4F::flush()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitStream4F::read(int bits, quint32 &val)
|
||||
bool BitStream4F::read(quint32 bits, quint32 &val)
|
||||
{
|
||||
if (bits <= 32 - (int)(_used + _unused)) {
|
||||
if (bits <= 32 - (_used + _unused)) {
|
||||
val = bits ? (_data << _used) >> (32 - bits) : 0;
|
||||
_used += bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_unused)
|
||||
return false;
|
||||
Q_ASSERT(_length && !_unused);
|
||||
quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0;
|
||||
quint32 bytes = qMin(_length, 4U);
|
||||
|
||||
@ -73,7 +72,7 @@ BitStream4R::BitStream4R(const SubFile &file, SubFile::Handle &hdl,
|
||||
_file.seek(_hdl, _file.pos(_hdl) - 4);
|
||||
}
|
||||
|
||||
bool BitStream4R::readBytes(int bytes, quint32 &val)
|
||||
bool BitStream4R::readBytes(quint32 bytes, quint32 &val)
|
||||
{
|
||||
quint32 bits = _used % 8;
|
||||
quint32 b;
|
||||
@ -85,7 +84,7 @@ bool BitStream4R::readBytes(int bytes, quint32 &val)
|
||||
}
|
||||
|
||||
val = 0;
|
||||
for (int i = 0; i < bytes; i++) {
|
||||
for (quint32 i = 0; i < bytes; i++) {
|
||||
if (!read(8, b))
|
||||
return false;
|
||||
val |= (b << (i * 8));
|
||||
|
@ -10,7 +10,7 @@ public:
|
||||
BitStream1(const SubFile &file, SubFile::Handle &hdl, quint32 length)
|
||||
: _file(file), _hdl(hdl), _length(length), _remaining(0) {}
|
||||
|
||||
template<typename T> bool read(int bits, T &val);
|
||||
template<typename T> bool read(quint32 bits, T &val);
|
||||
bool flush();
|
||||
quint64 bitsAvailable() const {return (quint64)_length * 8 + _remaining;}
|
||||
|
||||
@ -44,7 +44,7 @@ public:
|
||||
BitStream4F(const SubFile &file, SubFile::Handle &hdl, quint32 length)
|
||||
: BitStream4(file, hdl, length) {}
|
||||
|
||||
bool read(int bits, quint32 &val);
|
||||
bool read(quint32 bits, quint32 &val);
|
||||
bool flush();
|
||||
};
|
||||
|
||||
@ -60,8 +60,8 @@ public:
|
||||
|
||||
BitStream4R(const SubFile &file, SubFile::Handle &hdl, quint32 length);
|
||||
|
||||
template<typename T> bool read(int bits, T &val);
|
||||
bool readBytes(int bytes, quint32 &val);
|
||||
template<typename T> bool read(quint32 bits, T &val);
|
||||
bool readBytes(quint32 bytes, quint32 &val);
|
||||
bool readVUInt32(quint32 &val);
|
||||
bool readVuint32SM(quint32 &val1, quint32 &val2, quint32 &val2Bits);
|
||||
|
||||
@ -73,11 +73,11 @@ public:
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool BitStream1::read(int bits, T &val)
|
||||
bool BitStream1::read(quint32 bits, T &val)
|
||||
{
|
||||
val = 0;
|
||||
|
||||
for (int pos = 0; pos < bits; ) {
|
||||
for (quint32 pos = 0; pos < bits; ) {
|
||||
if (!_remaining) {
|
||||
if (!_length || !_file.readByte(_hdl, &_data))
|
||||
return false;
|
||||
@ -103,16 +103,15 @@ bool BitStream1::read(int bits, T &val)
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool BitStream4R::read(int bits, T &val)
|
||||
bool BitStream4R::read(quint32 bits, T &val)
|
||||
{
|
||||
if (bits <= 32 - (int)(_used + _unused)) {
|
||||
if (bits <= 32 - (_used + _unused)) {
|
||||
val = bits ? (_data << _used) >> (32 - bits) : 0;
|
||||
_used += bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_unused)
|
||||
return false;
|
||||
Q_ASSERT(_length && !_unused);
|
||||
quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0;
|
||||
quint32 bytes = qMin(_length, 4U);
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
using namespace IMG;
|
||||
|
||||
bool HuffmanStreamF::init(bool line)
|
||||
bool HuffmanDeltaStreamF::init(bool line)
|
||||
{
|
||||
if (line) {
|
||||
if (!(sign(_lonSign) && sign(_latSign)))
|
||||
@ -13,7 +13,7 @@ bool HuffmanStreamF::init(bool line)
|
||||
}
|
||||
|
||||
quint32 eb;
|
||||
if (!_bs.read(1, eb))
|
||||
if (!read(1, eb))
|
||||
return false;
|
||||
|
||||
Q_ASSERT(!eb);
|
||||
@ -23,7 +23,7 @@ bool HuffmanStreamF::init(bool line)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HuffmanStreamR::init()
|
||||
bool HuffmanDeltaStreamR::init()
|
||||
{
|
||||
if (!(sign(_lonSign) && sign(_latSign)))
|
||||
return false;
|
||||
@ -31,13 +31,13 @@ bool HuffmanStreamR::init()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HuffmanStreamR::init(int lonSign, int latSign, quint32 data,
|
||||
quint32 dataSize)
|
||||
bool HuffmanDeltaStreamR::init(quint32 data, quint32 dataSize)
|
||||
{
|
||||
_lonSign = lonSign;
|
||||
_latSign = latSign;
|
||||
_symbolData = data;
|
||||
_symbolDataSize = dataSize;
|
||||
|
||||
if (!(sign(_lonSign) && sign(_latSign)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -10,70 +10,48 @@ template <class BitStream>
|
||||
class HuffmanStream {
|
||||
public:
|
||||
HuffmanStream(BitStream &bitstream, const HuffmanTable &table)
|
||||
: _bs(bitstream), _table(table), _symbolDataSize(0), _symbolData(0),
|
||||
_lonSign(0), _latSign(0) {}
|
||||
: _symbolDataSize(0), _symbolData(0), _bs(bitstream), _table(table) {}
|
||||
|
||||
bool read(int bits, quint32 &val);
|
||||
bool read(quint32 bits, quint32 &val);
|
||||
bool readSymbol(quint32 &symbol);
|
||||
bool readNext(qint32 &lonDelta, qint32 &latDelta)
|
||||
{
|
||||
if (!(readDelta(_lonSign, lonDelta) && readDelta(_latSign, latDelta)))
|
||||
return false;
|
||||
|
||||
return (lonDelta || latDelta);
|
||||
}
|
||||
|
||||
bool atEnd() const
|
||||
{return _symbolDataSize + _bs.bitsAvailable() < _table.maxSymbolSize();}
|
||||
bool flush() {return _bs.flush();}
|
||||
{return _symbolDataSize + _bs.bitsAvailable() < _table.symBits();}
|
||||
|
||||
protected:
|
||||
bool sign(int &val);
|
||||
bool readDelta(int sign, qint32 &delta);
|
||||
quint32 _symbolDataSize;
|
||||
quint32 _symbolData;
|
||||
|
||||
private:
|
||||
bool fetchData();
|
||||
|
||||
BitStream &_bs;
|
||||
const HuffmanTable &_table;
|
||||
quint32 _symbolDataSize;
|
||||
quint32 _symbolData;
|
||||
int _lonSign, _latSign;
|
||||
};
|
||||
|
||||
template <class BitStream>
|
||||
bool HuffmanStream<BitStream>::sign(int &val)
|
||||
bool HuffmanStream<BitStream>::fetchData()
|
||||
{
|
||||
quint32 bit;
|
||||
val = 0;
|
||||
quint32 next;
|
||||
quint8 nextSize = qMin((quint64)(32 - _symbolDataSize), _bs.bitsAvailable());
|
||||
|
||||
if (!_bs.read(1, bit))
|
||||
if (!_bs.read(nextSize, next))
|
||||
return false;
|
||||
if (bit) {
|
||||
if (!_bs.read(1, bit))
|
||||
return false;
|
||||
val = bit ? -1 : 1;
|
||||
}
|
||||
|
||||
_symbolData = (nextSize < 32) ? (_symbolData << nextSize) | next : next;
|
||||
_symbolDataSize += nextSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BitStream>
|
||||
bool HuffmanStream<BitStream>::read(int bits, quint32 &val)
|
||||
bool HuffmanStream<BitStream>::read(quint32 bits, quint32 &val)
|
||||
{
|
||||
if (_symbolDataSize < (quint32)bits) {
|
||||
quint32 next;
|
||||
quint8 nextSize = qMin((quint64)(32 - _symbolDataSize),
|
||||
_bs.bitsAvailable());
|
||||
|
||||
if (!_bs.read(nextSize, next))
|
||||
if (_symbolDataSize < bits)
|
||||
if (!fetchData() || _symbolDataSize < bits)
|
||||
return false;
|
||||
|
||||
_symbolData = (_symbolData << nextSize) | next;
|
||||
_symbolDataSize += nextSize;
|
||||
}
|
||||
|
||||
if (_symbolDataSize < (quint32)bits)
|
||||
return false;
|
||||
|
||||
val = (_symbolData << (32-_symbolDataSize)) >> (32 - bits);
|
||||
val = (_symbolData << (32 - _symbolDataSize)) >> (32 - bits);
|
||||
_symbolDataSize -= bits;
|
||||
|
||||
return true;
|
||||
@ -83,14 +61,10 @@ template <class BitStream>
|
||||
bool HuffmanStream<BitStream>::readSymbol(quint32 &symbol)
|
||||
{
|
||||
quint8 size;
|
||||
quint32 next;
|
||||
quint8 nextSize = qMin((quint64)(32 - _symbolDataSize), _bs.bitsAvailable());
|
||||
|
||||
if (!_bs.read(nextSize, next))
|
||||
return false;
|
||||
|
||||
_symbolData = (_symbolData << nextSize) | next;
|
||||
_symbolDataSize += nextSize;
|
||||
if (_symbolDataSize < _table.symBits())
|
||||
if (!fetchData() || !_symbolDataSize)
|
||||
return false;
|
||||
|
||||
symbol = _table.symbol(_symbolData << (32 - _symbolDataSize), size);
|
||||
if (size > _symbolDataSize)
|
||||
@ -102,42 +76,80 @@ bool HuffmanStream<BitStream>::readSymbol(quint32 &symbol)
|
||||
}
|
||||
|
||||
template <class BitStream>
|
||||
bool HuffmanStream<BitStream>::readDelta(int sign, qint32 &delta)
|
||||
class HuffmanDeltaStream : public HuffmanStream<BitStream>
|
||||
{
|
||||
public:
|
||||
HuffmanDeltaStream(BitStream &bitstream, const HuffmanTable &table)
|
||||
: HuffmanStream<BitStream>(bitstream, table), _lonSign(0), _latSign(0) {}
|
||||
|
||||
bool readNext(qint32 &lonDelta, qint32 &latDelta)
|
||||
{
|
||||
if (!(readDelta(_lonSign, lonDelta) && readDelta(_latSign, latDelta)))
|
||||
return false;
|
||||
|
||||
return (lonDelta || latDelta);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool sign(int &val);
|
||||
bool readDelta(int sign, qint32 &delta);
|
||||
|
||||
int _lonSign, _latSign;
|
||||
};
|
||||
|
||||
template <class BitStream>
|
||||
bool HuffmanDeltaStream<BitStream>::sign(int &val)
|
||||
{
|
||||
quint32 bit;
|
||||
val = 0;
|
||||
|
||||
if (!this->read(1, bit))
|
||||
return false;
|
||||
if (bit) {
|
||||
if (!this->read(1, bit))
|
||||
return false;
|
||||
val = bit ? -1 : 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BitStream>
|
||||
bool HuffmanDeltaStream<BitStream>::readDelta(int sign, qint32 &delta)
|
||||
{
|
||||
quint32 symbol;
|
||||
if (!readSymbol(symbol))
|
||||
if (!this->readSymbol(symbol))
|
||||
return false;
|
||||
|
||||
if (symbol && !sign) {
|
||||
if (!_symbolDataSize)
|
||||
quint32 bit;
|
||||
if (!this->read(1, bit))
|
||||
return false;
|
||||
else {
|
||||
sign = ((1U << (_symbolDataSize - 1)) & _symbolData) ? -1 : 1;
|
||||
_symbolDataSize--;
|
||||
}
|
||||
sign = bit ? -1 : 1;
|
||||
}
|
||||
|
||||
delta = sign * symbol;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class HuffmanStreamF : public HuffmanStream<BitStream4F> {
|
||||
class HuffmanDeltaStreamF : public HuffmanDeltaStream<BitStream4F> {
|
||||
public:
|
||||
HuffmanStreamF(BitStream4F &bitstream, const HuffmanTable &table)
|
||||
: HuffmanStream(bitstream, table) {}
|
||||
HuffmanDeltaStreamF(BitStream4F &bitstream, const HuffmanTable &table)
|
||||
: HuffmanDeltaStream(bitstream, table) {}
|
||||
|
||||
bool init(bool line);
|
||||
bool readOffset(qint32 &lonDelta, qint32 &latDelta)
|
||||
{return (readDelta(1, lonDelta) && readDelta(1, latDelta));}
|
||||
};
|
||||
|
||||
class HuffmanStreamR : public HuffmanStream<BitStream4R> {
|
||||
class HuffmanDeltaStreamR : public HuffmanDeltaStream<BitStream4R> {
|
||||
public:
|
||||
HuffmanStreamR(BitStream4R &bitstream, const HuffmanTable &table)
|
||||
: HuffmanStream(bitstream, table) {}
|
||||
HuffmanDeltaStreamR(BitStream4R &bitstream, const HuffmanTable &table)
|
||||
: HuffmanDeltaStream(bitstream, table) {}
|
||||
|
||||
bool init();
|
||||
bool init(int lonSign, int latSign, quint32 data, quint32 dataSize);
|
||||
bool init(quint32 data, quint32 dataSize);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ static inline quint32 readVUint32(const quint8 *buffer, quint32 bytes)
|
||||
{
|
||||
quint32 val = 0;
|
||||
|
||||
for (quint32 i = bytes; i; i--)
|
||||
val |= ((quint32)*(buffer + i)) << ((i-1) * 8);
|
||||
for (quint32 i = 0; i < bytes; i++)
|
||||
val |= ((quint32)*(buffer + i)) << (i * 8);
|
||||
|
||||
return val;
|
||||
}
|
||||
@ -19,89 +19,83 @@ bool HuffmanTable::load(const RGNFile *rgn, SubFile::Handle &rgnHdl)
|
||||
if (!_buffer.load(rgn, rgnHdl))
|
||||
return false;
|
||||
|
||||
_s0 = (quint8)_buffer.at(0) & 0x0F;
|
||||
_s1e = (quint8)_buffer.at(0) & 0x10;
|
||||
_s2 = (quint8)_buffer.at(1);
|
||||
_s3 = bs(_s2);
|
||||
_s1d = (quint8)_buffer.at(2);
|
||||
_s1f = (quint8)_buffer.at(3);
|
||||
_s20 = bs(_s1f);
|
||||
_s1 = _s20 + 1;
|
||||
_s22 = vs(_buffer.at(4));
|
||||
_s1c = _s3 + 1 + _s22;
|
||||
_s14 = (quint8*)(_buffer.data()) + 4 + _s22;
|
||||
_s10 = _s14 + _s1c * _s1d;
|
||||
_s18 = _s10 + (_s1 << _s0);
|
||||
_aclBits = (quint8)_buffer.at(0) & 0x0F;
|
||||
_huffman = (quint8)_buffer.at(0) & 0x10;
|
||||
_symBits = (quint8)_buffer.at(1);
|
||||
_symBytes = bs(_symBits);
|
||||
_bsrchEntries = (quint8)_buffer.at(2);
|
||||
_symbolBits = (quint8)_buffer.at(3);
|
||||
_symbolBytes = bs(_symbolBits);
|
||||
_aclEntryBytes = _symbolBytes + 1;
|
||||
_indexBytes = vs(_buffer.at(4));
|
||||
_bsrchEntryBytes = _symBytes + _indexBytes + 1;
|
||||
_bsrchTable = (const quint8*)(_buffer.constData()) + 4 + _indexBytes;
|
||||
_aclTable = _bsrchTable + _bsrchEntryBytes * _bsrchEntries;
|
||||
_huffmanTable = _aclTable + (_aclEntryBytes << _aclBits);
|
||||
|
||||
return true;
|
||||
return (_symBits <= 32 && _symbolBits <= 32);
|
||||
}
|
||||
|
||||
quint32 HuffmanTable::symbol(quint32 data, quint8 &size) const
|
||||
{
|
||||
quint32 ss, sym;
|
||||
quint8 *tp;
|
||||
quint32 lo, hi;
|
||||
const quint8 *tp;
|
||||
|
||||
|
||||
if (_s0 == 0) {
|
||||
sym = _s1d - 1;
|
||||
ss = 0;
|
||||
if (!_aclBits) {
|
||||
hi = _bsrchEntries - 1;
|
||||
lo = 0;
|
||||
} else {
|
||||
quint32 offset = _s1 * (data >> (0x20U - _s0));
|
||||
tp = _s10 + offset;
|
||||
quint32 offset = _aclEntryBytes * (data >> (32 - _aclBits));
|
||||
tp = _aclTable + offset;
|
||||
|
||||
if ((*tp & 1) != 0) {
|
||||
sym = readVUint32(tp, _s20);
|
||||
if (*tp & 1) {
|
||||
size = *tp >> 1;
|
||||
return sym;
|
||||
return readVUint32(tp + 1, _symbolBytes);;
|
||||
}
|
||||
|
||||
ss = *tp >> 1;
|
||||
sym = tp[1];
|
||||
lo = *tp >> 1;
|
||||
hi = *(tp + 1);
|
||||
}
|
||||
|
||||
tp = ss * _s1c + _s14;
|
||||
data = data >> (0x20U - _s2);
|
||||
tp = _bsrchTable + (lo * _bsrchEntryBytes);
|
||||
data >>= 32 - _symBits;
|
||||
|
||||
quint8 *prev = tp;
|
||||
while (ss < sym) {
|
||||
quint32 cnt = (ss + 1 + sym) >> 1;
|
||||
tp = _s14 + (cnt * _s1c);
|
||||
quint32 nd = readVUint32(tp - 1, _s3);
|
||||
while (lo < hi) {
|
||||
const quint8 *prev = tp;
|
||||
quint32 m = (lo + 1 + hi) >> 1;
|
||||
tp = _bsrchTable + (m * _bsrchEntryBytes);
|
||||
quint32 nd = readVUint32(tp, _symBytes);
|
||||
|
||||
if (data <= nd) {
|
||||
if (data == nd)
|
||||
ss = cnt;
|
||||
else
|
||||
tp = prev;
|
||||
|
||||
sym = cnt - (data < nd);
|
||||
cnt = ss;
|
||||
if (data < nd) {
|
||||
tp = prev;
|
||||
hi = m - 1;
|
||||
} else if (data > nd) {
|
||||
lo = m;
|
||||
} else {
|
||||
lo = m;
|
||||
hi = m;
|
||||
}
|
||||
ss = cnt;
|
||||
prev = tp;
|
||||
}
|
||||
|
||||
sym = readVUint32(tp - 1, _s3);
|
||||
tp = tp + _s3;
|
||||
ss = readVUint32(tp, _s22);
|
||||
quint32 i = readVUint32(tp, _symBytes);
|
||||
tp = tp + _symBytes;
|
||||
size = *tp;
|
||||
sym = (data - sym) >> (_s2 - *tp);
|
||||
|
||||
if (!_s1e)
|
||||
sym = readVUint32(tp, _s20);
|
||||
if (!_huffman)
|
||||
return readVUint32(tp + 1, _symbolBytes);
|
||||
else {
|
||||
sym = (sym + ss) * _s1f;
|
||||
ss = sym >> 3;
|
||||
sym = sym & 7;
|
||||
quint32 shift = 8 - sym;
|
||||
sym = *(_s18 + ss) >> sym;
|
||||
quint32 bi = readVUint32(tp + 1, _indexBytes);
|
||||
quint32 ci = (data - i) >> (_symBits - size);
|
||||
quint32 si = (ci + bi) * _symbolBits;
|
||||
quint32 sbi = si & 7;
|
||||
quint32 shift = 8 - sbi;
|
||||
tp = _huffmanTable + (si >> 3);
|
||||
|
||||
if (shift < _s1f) {
|
||||
tp = _s18 + ss;
|
||||
ss = readVUint32(tp, ((_s1f + 7) - shift) >> 3);
|
||||
sym = (ss << shift) | sym;
|
||||
}
|
||||
if (shift < _symbolBits) {
|
||||
quint32 val = readVUint32(tp + 1, bs(_symbolBits - shift));
|
||||
return (val << shift) | (*tp >> sbi);
|
||||
} else
|
||||
return (*tp >> sbi);
|
||||
}
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
@ -12,18 +12,19 @@ public:
|
||||
HuffmanTable(quint8 id) : _buffer(id) {}
|
||||
|
||||
bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl);
|
||||
quint8 maxSymbolSize() const {return _s2;}
|
||||
quint32 symbol(quint32 data, quint8 &size) const;
|
||||
|
||||
quint32 symbol(quint32 data, quint8 &size) const;
|
||||
quint8 id() const {return _buffer.id();}
|
||||
|
||||
quint8 symBits() const {return _symBits;}
|
||||
quint8 symbolBits() const {return _symbolBits;}
|
||||
|
||||
private:
|
||||
HuffmanBuffer _buffer;
|
||||
quint8 _s0, _s1, _s2, _s3;
|
||||
quint8 *_s10, *_s14, *_s18;
|
||||
quint8 _s1c, _s1d, _s1f, _s20;
|
||||
quint16 _s22;
|
||||
bool _s1e;
|
||||
const quint8 *_aclTable, *_bsrchTable, *_huffmanTable;
|
||||
quint8 _aclBits, _aclEntryBytes, _symBits, _symBytes, _indexBytes,
|
||||
_bsrchEntryBytes, _bsrchEntries, _symbolBits, _symbolBytes;
|
||||
bool _huffman;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,171 +1,33 @@
|
||||
#include "common/garmin.h"
|
||||
#include "subfile.h"
|
||||
#include "huffmanstream.h"
|
||||
#include "huffmantext.h"
|
||||
|
||||
using namespace Garmin;
|
||||
using namespace IMG;
|
||||
|
||||
static inline quint32 readVUint32(const quint8 *buffer, quint32 bytes)
|
||||
{
|
||||
quint32 val = 0;
|
||||
|
||||
for (quint32 i = 0; i < bytes; i++)
|
||||
val = val | (quint32)*(buffer - i) << ((bytes - i - 1) << 3);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
bool HuffmanText::load(const RGNFile *rgn, SubFile::Handle &rgnHdl)
|
||||
{
|
||||
if (!_buffer.load(rgn, rgnHdl))
|
||||
if (!_table.load(rgn, rgnHdl))
|
||||
return false;
|
||||
|
||||
quint8 *buffer = (quint8 *)_buffer.constData();
|
||||
_b0 = buffer[0];
|
||||
_b1 = buffer[1];
|
||||
_b2 = buffer[2];
|
||||
_b3 = buffer[3];
|
||||
_vs = vs(buffer[4]);
|
||||
_bs3 = bs(_b3);
|
||||
_bs1 = bs(_b1);
|
||||
_mul = _bs1 + 1 + _vs;
|
||||
_bp1 = buffer + _vs + 4;
|
||||
_bp2 = _bp1 + _mul * _b2;
|
||||
_bp3 = _bp2 + ((_bs3 + 1) << (_b0 & 0xf));
|
||||
_bp4 = _bp3 - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HuffmanText::fetch(const SubFile *file, SubFile::Handle &hdl,
|
||||
quint32 &data, quint32 &bits, quint32 &usedBits, quint32 &usedData) const
|
||||
{
|
||||
quint32 rs, ls, old;
|
||||
|
||||
bits = _b1 - bits;
|
||||
|
||||
if (usedBits < bits) {
|
||||
old = usedBits ? usedData >> (0x20 - usedBits) : 0;
|
||||
if (!file->readVUInt32SW(hdl, 4, usedData))
|
||||
return false;
|
||||
ls = bits - usedBits;
|
||||
rs = 0x20 - (bits - usedBits);
|
||||
old = usedData >> rs | old << ls;
|
||||
} else {
|
||||
ls = bits;
|
||||
rs = usedBits - bits;
|
||||
old = usedData >> (0x20 - bits);
|
||||
}
|
||||
|
||||
usedData = usedData << ls;
|
||||
data = data | old << (0x20 - _b1);
|
||||
usedBits = rs;
|
||||
|
||||
return true;
|
||||
Q_ASSERT(!(_table.symbolBits() & 7));
|
||||
return !(_table.symbolBits() & 7);
|
||||
}
|
||||
|
||||
bool HuffmanText::decode(const SubFile *file, SubFile::Handle &hdl,
|
||||
QVector<quint8> &str) const
|
||||
quint32 size, QVector<quint8> &str) const
|
||||
{
|
||||
quint32 bits = 0;
|
||||
quint32 data = 0;
|
||||
quint32 usedBits = 0;
|
||||
quint32 usedData = 0;
|
||||
quint32 ls = 8;
|
||||
quint32 lo = _vs * 8 - 8;
|
||||
BitStream4F bs(*file, hdl, size);
|
||||
HuffmanStream<BitStream4F> hs(bs, _table);
|
||||
quint32 sym;
|
||||
|
||||
|
||||
while (true) {
|
||||
if (!fetch(file, hdl, data, bits, usedBits, usedData))
|
||||
return false;
|
||||
|
||||
quint32 off = (data >> (0x20 - (_b0 & 0xf))) * (_bs3 + 1);
|
||||
quint32 sb = _bp2[off];
|
||||
quint32 ss = 0;
|
||||
quint32 sym = _b2 - 1;
|
||||
quint32 size;
|
||||
|
||||
if ((_b0 & 0xf) == 0 || (sb & 1) == 0) {
|
||||
if ((_b0 & 0xf) != 0) {
|
||||
ss = sb >> 1;
|
||||
sym = _bp2[off + 1];
|
||||
}
|
||||
|
||||
quint8 *tp = _bp1 + ss * _mul;
|
||||
quint32 sd = data >> (0x20 - _b1);
|
||||
while (ss < sym) {
|
||||
quint32 cnt = (sym + 1 + ss) >> 1;
|
||||
quint8 *prev = _bp1 + cnt * _mul;
|
||||
quint32 nd = readVUint32(prev + _bs1 - 1, _bs1);
|
||||
|
||||
if (sd <= nd) {
|
||||
sym = cnt - (sd < nd);
|
||||
if (sd < nd) {
|
||||
prev = tp;
|
||||
cnt = ss;
|
||||
}
|
||||
}
|
||||
tp = prev;
|
||||
ss = cnt;
|
||||
}
|
||||
|
||||
quint32 o1 = readVUint32(tp + _bs1 - 1, _bs1);
|
||||
tp = tp + _bs1;
|
||||
quint32 o2 = readVUint32(tp + _vs, _vs);
|
||||
size = tp[0];
|
||||
quint32 os = (sd - o1) >> (_b1 - size);
|
||||
|
||||
if ((_b0 & 0x10) == 0) {
|
||||
sym = readVUint32(_bp4 + (o2 + 1 + os) * _bs3, _bs3);
|
||||
} else {
|
||||
quint32 v = (os + o2) * _b3;
|
||||
quint32 idx = v >> 3;
|
||||
quint32 r = v & 7;
|
||||
quint32 shift = 8 - r;
|
||||
sym = _bp3[idx] >> r;
|
||||
if (shift < _b3) {
|
||||
quint32 sz = bs(_b3 - shift);
|
||||
quint32 val = readVUint32(_bp3 + idx + sz, sz);
|
||||
sym = sym | val << shift;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sym = readVUint32(_bp2 + off + _bs3, _bs3);
|
||||
size = (sb >> 1);
|
||||
}
|
||||
|
||||
if (_b1 < size)
|
||||
return false;
|
||||
data = data << size;
|
||||
bits = _b1 - size;
|
||||
|
||||
if ((_b3 & 7) == 0) {
|
||||
for (quint32 i = 0; i < (_b3 >> 3); i++) {
|
||||
str.append((quint8)sym);
|
||||
if (((quint8)sym == '\0'))
|
||||
return true;
|
||||
sym = sym >> 8;
|
||||
}
|
||||
} else {
|
||||
quint32 cnt = _b3;
|
||||
|
||||
if (ls <= _b3) {
|
||||
do {
|
||||
quint32 shift = ls;
|
||||
lo = sym << (8 - shift) | (quint32)((quint8)lo >> shift);
|
||||
sym = sym >> shift;
|
||||
str.append((uchar)lo);
|
||||
if (((uchar)lo == '\0'))
|
||||
return true;
|
||||
cnt = cnt - ls;
|
||||
ls = 8;
|
||||
} while (7 < cnt);
|
||||
ls = 8;
|
||||
}
|
||||
if (cnt != 0) {
|
||||
lo = sym << (8 - cnt) | (quint32)((quint8)lo >> cnt);
|
||||
ls = ls - cnt;
|
||||
}
|
||||
while (hs.readSymbol(sym)) {
|
||||
for (quint32 i = 0; i < (_table.symbolBits() >> 3); i++) {
|
||||
str.append((quint8)sym);
|
||||
if (((quint8)sym == '\0'))
|
||||
return true;
|
||||
sym = sym >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1,37 +1,21 @@
|
||||
#ifndef IMG_HUFFMANTEXT_H
|
||||
#define IMG_HUFFMANTEXT_H
|
||||
|
||||
#include "huffmanbuffer.h"
|
||||
#include "huffmantable.h"
|
||||
|
||||
namespace IMG {
|
||||
|
||||
class HuffmanText
|
||||
{
|
||||
public:
|
||||
HuffmanText() : _buffer(0) {}
|
||||
HuffmanText() : _table(0) {}
|
||||
|
||||
bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl);
|
||||
bool decode(const SubFile *file, SubFile::Handle &hdl,
|
||||
bool decode(const SubFile *file, SubFile::Handle &hdl, quint32 size,
|
||||
QVector<quint8> &str) const;
|
||||
|
||||
private:
|
||||
bool fetch(const SubFile *file, SubFile::Handle &hdl, quint32 &data,
|
||||
quint32 &bits, quint32 &usedBits, quint32 &usedData) const;
|
||||
|
||||
HuffmanBuffer _buffer;
|
||||
|
||||
quint32 _b0;
|
||||
quint32 _b1;
|
||||
quint32 _b2;
|
||||
quint32 _b3;
|
||||
quint32 _vs;
|
||||
quint32 _bs3;
|
||||
quint32 _bs1;
|
||||
quint32 _mul;
|
||||
quint8 *_bp1;
|
||||
quint8 *_bp2;
|
||||
quint8 *_bp3;
|
||||
quint8 *_bp4;
|
||||
HuffmanTable _table;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ Label LBLFile::str2label(const QVector<quint8> &str, bool capitalize,
|
||||
for (int i = 0; i < str.size(); i++) {
|
||||
const quint8 &c = str.at(i);
|
||||
|
||||
if (c == 0 || c == 0x1d)
|
||||
if (c == 0 || c == 0x1d || c == 0x07)
|
||||
break;
|
||||
|
||||
if (c == 0x1c)
|
||||
@ -268,10 +268,11 @@ Label LBLFile::labelHuffman(Handle &hdl, quint32 offset, bool capitalize,
|
||||
bool convert) const
|
||||
{
|
||||
QVector<quint8> str;
|
||||
quint32 end = _offset + _size;
|
||||
|
||||
if (!seek(hdl, offset))
|
||||
return Label();
|
||||
if (!_huffmanText->decode(this, hdl, str))
|
||||
if (!_huffmanText->decode(this, hdl, end - offset, str))
|
||||
return Label();
|
||||
if (!_table)
|
||||
return str2label(str, capitalize, convert);
|
||||
@ -281,14 +282,16 @@ Label LBLFile::labelHuffman(Handle &hdl, quint32 offset, bool capitalize,
|
||||
for (int i = 0; i < str.size(); i++) {
|
||||
quint32 val = _table[str.at(i)];
|
||||
if (val) {
|
||||
if (!seek(hdl, _offset + ((val & 0x7fffff) << _multiplier)))
|
||||
quint32 off = _offset + ((val & 0x7fffff) << _multiplier);
|
||||
if (!seek(hdl, off))
|
||||
return Label();
|
||||
|
||||
if (str2.size() && str2.back() == '\0')
|
||||
str2[str2.size() - 1] = ' ';
|
||||
else if (str2.size())
|
||||
str2.append(' ');
|
||||
if (!_huffmanText->decode(this, hdl, str2))
|
||||
|
||||
if (!_huffmanText->decode(this, hdl, end - off, str2))
|
||||
return Label();
|
||||
} else {
|
||||
if (str.at(i) == 7) {
|
||||
|
@ -116,7 +116,7 @@ static bool readLine(BitStream4R &bs, const SubDiv *subdiv,
|
||||
poly.boundingRect = RectC(c, c);
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
|
||||
HuffmanStreamR stream(bs, *table);
|
||||
HuffmanDeltaStreamR stream(bs, *table);
|
||||
if (!stream.init())
|
||||
return false;
|
||||
qint32 lonDelta, latDelta;
|
||||
@ -164,18 +164,6 @@ static bool skipNodes(const NODFile *nod, SubFile::Handle &nodHdl,
|
||||
return true;
|
||||
}
|
||||
|
||||
static int sign(quint32 flags, quint32 &bits)
|
||||
{
|
||||
if (!((flags >> bits) & 1)) {
|
||||
bits--;
|
||||
return 0;
|
||||
} else {
|
||||
quint32 sb = bits - 1;
|
||||
bits -= 2;
|
||||
return ((flags >> sb) & 1) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool readShape(const NODFile *nod, SubFile::Handle &nodHdl,
|
||||
NODFile::AdjacencyInfo &adj, BitStream4R &bs, const HuffmanTable *table,
|
||||
const SubDiv *subdiv, quint32 shift, MapData::Poly &poly,
|
||||
@ -197,12 +185,8 @@ static bool readShape(const NODFile *nod, SubFile::Handle &nodHdl,
|
||||
bool startWithStream = flags & (1 << (v2b + 6));
|
||||
bool useEosBit = flags & (1 << (v2b + 5));
|
||||
|
||||
quint32 extraBits = v2b + 4;
|
||||
int lonSign = sign(flags, extraBits);
|
||||
int latSign = sign(flags, extraBits);
|
||||
|
||||
HuffmanStreamR stream(bs, *table);
|
||||
if (!stream.init(lonSign, latSign, flags, extraBits + 1))
|
||||
HuffmanDeltaStreamR stream(bs, *table);
|
||||
if (!stream.init(flags, v2b + 5))
|
||||
return false;
|
||||
|
||||
|
||||
|
@ -162,10 +162,12 @@ void RasterTile::render()
|
||||
drawPolygons(&painter);
|
||||
drawLines(&painter);
|
||||
drawTextItems(&painter, textItems);
|
||||
//painter.setPen(Qt::red);
|
||||
//painter.drawRect(QRect(_xy, _img.size()));
|
||||
|
||||
qDeleteAll(textItems);
|
||||
|
||||
//painter.setPen(Qt::red);
|
||||
//painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
//painter.drawRect(QRect(_xy, _pixmap.size()));
|
||||
}
|
||||
|
||||
void RasterTile::ll2xy(QList<MapData::Poly> &polys)
|
||||
@ -433,7 +435,8 @@ void RasterTile::processPoints(QList<TextItem*> &textItems)
|
||||
? 0 : &(point.label.text());
|
||||
const QImage *img = style.img().isNull() ? 0 : &style.img();
|
||||
const QFont *fnt = poi
|
||||
? poiFont(style.textFontSize()) : font(style.textFontSize());
|
||||
? poiFont(_zoom > 25 ? Style::Normal : style.textFontSize())
|
||||
: font(style.textFontSize());
|
||||
const QColor *color = style.textColor().isValid()
|
||||
? &style.textColor() : &textColor;
|
||||
|
||||
|
@ -287,7 +287,7 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||
|
||||
qint32 lonDelta, latDelta;
|
||||
BitStream4F bs(*this, hdl, len);
|
||||
HuffmanStreamF stream(bs, *_huffmanTable);
|
||||
HuffmanDeltaStreamF stream(bs, *_huffmanTable);
|
||||
if (!stream.init(segmentType == Line))
|
||||
return false;
|
||||
|
||||
@ -312,7 +312,7 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||
poly.boundingRect = poly.boundingRect.united(c);
|
||||
}
|
||||
|
||||
if (!(stream.atEnd() && stream.flush()))
|
||||
if (!(stream.atEnd() && bs.flush()))
|
||||
return false;
|
||||
} else {
|
||||
pos = QPoint(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
||||
@ -581,10 +581,9 @@ bool RGNFile::segments(Handle &hdl, SubDiv *subdiv, SubDiv::Segment seg[5]) cons
|
||||
|
||||
bool RGNFile::subdivInit(Handle &hdl, SubDiv *subdiv) const
|
||||
{
|
||||
SubDiv::Segment seg[5];
|
||||
SubDiv::Segment extPoints, extLines, extPolygons;
|
||||
SubDiv::Segment std[5], extPoints, extLines, extPolygons;
|
||||
|
||||
if (!segments(hdl, subdiv, seg))
|
||||
if (!segments(hdl, subdiv, std))
|
||||
return false;
|
||||
|
||||
if (subdiv->extPointsOffset() != subdiv->extPointsEnd()) {
|
||||
@ -609,8 +608,8 @@ bool RGNFile::subdivInit(Handle &hdl, SubDiv *subdiv) const
|
||||
extLines = SubDiv::Segment(start, end);
|
||||
}
|
||||
|
||||
subdiv->init(seg[Point], seg[IndexedPoint], seg[Line], seg[Polygon],
|
||||
seg[RoadReference], extPoints, extLines, extPolygons);
|
||||
subdiv->init(std[Point], std[IndexedPoint], std[Line], std[Polygon],
|
||||
std[RoadReference], extPoints, extLines, extPolygons);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
#define IMG_SUBDIV_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include "common/coordinates.h"
|
||||
#include "common/garmin.h"
|
||||
|
||||
namespace IMG {
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "sqlitemap.h"
|
||||
#include "mapsforgemap.h"
|
||||
#include "worldfilemap.h"
|
||||
#include "qctmap.h"
|
||||
#include "invalidmap.h"
|
||||
#include "maplist.h"
|
||||
|
||||
@ -66,6 +67,8 @@ Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
|
||||
else if (suffix == "wld" || suffix == "jgw" || suffix == "gfw"
|
||||
|| suffix == "pgw" || suffix == "tfw")
|
||||
map = new WorldFileMap(path, proj);
|
||||
else if (suffix == "qct")
|
||||
map = new QCTMap(path);
|
||||
|
||||
return map ? map : new InvalidMap(path, "Unknown file format");
|
||||
}
|
||||
@ -129,6 +132,7 @@ QString MapList::formats()
|
||||
+ qApp->translate("MapList", "Mapsforge maps") + " (*.map);;"
|
||||
+ qApp->translate("MapList", "OziExplorer maps") + " (*.map);;"
|
||||
+ qApp->translate("MapList", "MBTiles maps") + " (*.mbtiles);;"
|
||||
+ qApp->translate("MapList", "QuickChart maps") + " (*.qct);;"
|
||||
+ qApp->translate("MapList", "TwoNav maps") + " (*.rmap *.rtmap);;"
|
||||
+ qApp->translate("MapList", "Locus/OsmAnd/RMaps SQLite maps")
|
||||
+ " (*.sqlitedb);;"
|
||||
@ -144,7 +148,7 @@ QStringList MapList::filter()
|
||||
QStringList filter;
|
||||
filter << "*.aqm" << "*.gfw" << "*.gmap" << "*.gmapi" << "*.img" << "*.jgw"
|
||||
<< "*.jnx" << "*.kap" << "*.kmz" << "*.map" << "*.mbtiles" << "*.pgw"
|
||||
<< "*.rmap" << "*.rtmap" << "*.sqlitedb" << "*.tar" << "*.tba" << "*.tfw"
|
||||
<< "*.tif" << "*.tiff" << "*.wld" << "*.xml";
|
||||
<< "*.qct" << "*.rmap" << "*.rtmap" << "*.sqlitedb" << "*.tar" << "*.tba"
|
||||
<< "*.tfw" << "*.tif" << "*.tiff" << "*.wld" << "*.xml";
|
||||
return filter;
|
||||
}
|
||||
|
487
src/map/qctmap.cpp
Normal file
@ -0,0 +1,487 @@
|
||||
#include <cstring>
|
||||
#include <QDataStream>
|
||||
#include <QPixmapCache>
|
||||
#include <QPainter>
|
||||
#include "common/util.h"
|
||||
#include "common/color.h"
|
||||
#include "qctmap.h"
|
||||
|
||||
#define TILE_SIZE 64
|
||||
#define TILE_PIXELS (TILE_SIZE * TILE_SIZE)
|
||||
#define MAGIC 0x1423D5FF
|
||||
|
||||
static quint8 bpp(quint8 colours)
|
||||
{
|
||||
if (colours <= 2)
|
||||
return 1;
|
||||
if (colours <= 4)
|
||||
return 2;
|
||||
if (colours <= 8)
|
||||
return 3;
|
||||
if (colours <= 16)
|
||||
return 4;
|
||||
if (colours <= 32)
|
||||
return 5;
|
||||
if (colours <= 64)
|
||||
return 6;
|
||||
if (colours <= 128)
|
||||
return 7;
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
||||
static bool validateTable(const QVector<quint8> &table)
|
||||
{
|
||||
int delta;
|
||||
|
||||
for (int i = 0; i < table.size(); i++) {
|
||||
if (table.at(i) == 128) {
|
||||
if (i + 2 >= table.size())
|
||||
return false;
|
||||
delta = 65537 - (256 * table.at(i+2) + table.at(i+1)) + 2;
|
||||
if (i + delta >= table.size())
|
||||
return false;
|
||||
i += 2;
|
||||
} else if (table.at(i) > 128) {
|
||||
delta = 257 - table.at(i);
|
||||
if (i + delta >= table.size())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool createTable(QDataStream &stream, QVector<quint8> &table)
|
||||
{
|
||||
int idx = 0;
|
||||
int colours = 0;
|
||||
int branches = 0;
|
||||
|
||||
table.reserve(256);
|
||||
|
||||
while (stream.status() == QDataStream::Ok && colours <= branches) {
|
||||
table.resize(table.size() + 1);
|
||||
stream >> table[idx];
|
||||
|
||||
if (table[idx] == 128) {
|
||||
table.resize(table.size() + 2);
|
||||
stream >> table[++idx];
|
||||
stream >> table[++idx];
|
||||
branches++;
|
||||
} else if (table[idx] > 128)
|
||||
branches++;
|
||||
else
|
||||
colours++;
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
return (stream.status() == QDataStream::Ok);
|
||||
}
|
||||
|
||||
static bool huffman(QDataStream &stream, quint8 tileData[TILE_PIXELS])
|
||||
{
|
||||
QVector<quint8> table;
|
||||
if (!createTable(stream, table))
|
||||
return false;
|
||||
|
||||
if (table.size() == 1) {
|
||||
memset(tileData, table[0], TILE_PIXELS);
|
||||
} else {
|
||||
if (!validateTable(table))
|
||||
return false;
|
||||
|
||||
const quint8 *tp = table.constData();
|
||||
int bitsLeft = 8;
|
||||
int bitVal;
|
||||
quint8 val;
|
||||
|
||||
stream >> val;
|
||||
|
||||
for (int pixelnum = 0; pixelnum < TILE_PIXELS; ) {
|
||||
if (*tp < 128) {
|
||||
tileData[pixelnum++] = *tp;
|
||||
tp = table.constData();
|
||||
} else {
|
||||
bitVal = (val & 1);
|
||||
|
||||
val >>= 1;
|
||||
bitsLeft--;
|
||||
if (bitsLeft == 0) {
|
||||
stream >> val;
|
||||
bitsLeft = 8;
|
||||
}
|
||||
|
||||
if (bitVal == 0) {
|
||||
if (*tp == 128)
|
||||
tp += 2;
|
||||
tp++;
|
||||
} else {
|
||||
if (*tp > 128)
|
||||
tp += 257 - (*tp);
|
||||
else if (*tp == 128)
|
||||
tp += 65537 - (256 * tp[2] + tp[1]) + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (stream.status() == QDataStream::Ok);
|
||||
}
|
||||
|
||||
static bool pixelPacking(QDataStream &stream, quint8 tileData[TILE_PIXELS],
|
||||
quint8 colours)
|
||||
{
|
||||
quint8 shift = bpp(colours);
|
||||
quint32 mask = (1 << shift) - 1;
|
||||
int wordSize = 32 / shift;
|
||||
quint8 paletteIndex[256];
|
||||
|
||||
for (quint8 i = 0; i < colours; i++)
|
||||
stream >> paletteIndex[i];
|
||||
|
||||
for (int pixelnum = 0; pixelnum < TILE_PIXELS; ) {
|
||||
quint32 colour, val;
|
||||
stream >> val;
|
||||
|
||||
for (int runs = 0; runs < wordSize; runs++) {
|
||||
colour = val & mask;
|
||||
val = val >> shift;
|
||||
tileData[pixelnum++] = paletteIndex[colour];
|
||||
}
|
||||
}
|
||||
|
||||
return (stream.status() == QDataStream::Ok);
|
||||
}
|
||||
|
||||
static bool rle(QDataStream &stream, quint8 tileData[TILE_PIXELS],
|
||||
quint8 colours)
|
||||
{
|
||||
quint8 bits = bpp(colours);
|
||||
quint8 paletteMask = (1 << bits) - 1;
|
||||
quint8 paletteIndex[256];
|
||||
quint8 val;
|
||||
|
||||
for (quint8 i = 0; i < colours; i++)
|
||||
stream >> paletteIndex[i];
|
||||
|
||||
for (int pixelnum = 0; pixelnum < TILE_PIXELS; ) {
|
||||
stream >> val;
|
||||
|
||||
quint8 colour = val & paletteMask;
|
||||
quint8 runs = val >> bits;
|
||||
|
||||
while (runs-- > 0)
|
||||
tileData[pixelnum++] = paletteIndex[colour];
|
||||
}
|
||||
|
||||
return (stream.status() == QDataStream::Ok);
|
||||
}
|
||||
|
||||
static bool readString(QDataStream &stream, quint32 offset, QString &str)
|
||||
{
|
||||
char c;
|
||||
QByteArray ba;
|
||||
|
||||
if (!stream.device()->seek(offset))
|
||||
return false;
|
||||
|
||||
while (stream.readRawData(&c, 1) == 1) {
|
||||
if (c)
|
||||
ba.append(c);
|
||||
else {
|
||||
str = QString::fromUtf8(ba);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QCTMap::readName(QDataStream &stream)
|
||||
{
|
||||
quint32 title, name;
|
||||
|
||||
stream >> title >> name;
|
||||
if (stream.status() != QDataStream::Ok)
|
||||
return false;
|
||||
|
||||
if (name) {
|
||||
if (!readString(stream, name, _name))
|
||||
return false;
|
||||
} else if (title) {
|
||||
if (!readString(stream, title, _name))
|
||||
return false;
|
||||
} else
|
||||
_name = Util::file2name(path());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QCTMap::readSize(QDataStream &stream)
|
||||
{
|
||||
stream >> _cols >> _rows;
|
||||
return (stream.status() == QDataStream::Ok);
|
||||
}
|
||||
|
||||
bool QCTMap::readDatumShift(QDataStream &stream)
|
||||
{
|
||||
quint32 ext, shift;
|
||||
|
||||
if (!stream.device()->seek(0x54))
|
||||
return false;
|
||||
stream >> ext;
|
||||
if (stream.status() != QDataStream::Ok)
|
||||
return false;
|
||||
if (!ext)
|
||||
return true;
|
||||
if (!stream.device()->seek(ext + 4))
|
||||
return false;
|
||||
stream >> shift;
|
||||
if (stream.status() != QDataStream::Ok)
|
||||
return false;
|
||||
if (!shift)
|
||||
return true;
|
||||
if (!stream.device()->seek(shift))
|
||||
return false;
|
||||
stream >> _shiftN >> _shiftE;
|
||||
|
||||
return (stream.status() == QDataStream::Ok);
|
||||
}
|
||||
|
||||
bool QCTMap::readHeader(QDataStream &stream)
|
||||
{
|
||||
quint32 magic, version;
|
||||
stream >> magic >> version;
|
||||
|
||||
if (stream.status() != QDataStream::Ok || magic != MAGIC) {
|
||||
_errorString = "Not a QCT map";
|
||||
return false;
|
||||
}
|
||||
if (version == 0x20000001) {
|
||||
_errorString = "QC3 files not supported";
|
||||
return false;
|
||||
}
|
||||
if (!readSize(stream)) {
|
||||
_errorString = "Error reading map dimensions";
|
||||
return false;
|
||||
}
|
||||
if (!readName(stream)) {
|
||||
_errorString = "Error reading map name";
|
||||
return false;
|
||||
}
|
||||
if (!readDatumShift(stream)) {
|
||||
_errorString = "Error reading datum shift";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QCTMap::readGeoRef(QDataStream &stream)
|
||||
{
|
||||
if (!stream.device()->seek(0x60))
|
||||
return false;
|
||||
|
||||
stream >> _eas >> _easY >> _easX >> _easYY >> _easXY >> _easXX >> _easYYY
|
||||
>> _easYYX >> _easXXY >> _easXXX >> _nor >> _norY >> _norX >> _norYY
|
||||
>> _norXY >> _norXX >> _norYYY >> _norYYX >> _norXXY >> _norXXX;
|
||||
stream >> _lat >> _latX >> _latY >> _latXX >> _latXY >> _latYY >> _latXXX
|
||||
>> _latXXY >> _latXYY >> _latYYY >> _lon >> _lonX >> _lonY >> _lonXX
|
||||
>> _lonXY >> _lonYY >> _lonXXX >> _lonXXY >> _lonXYY >> _lonYYY;
|
||||
|
||||
return (stream.status() == QDataStream::Ok);
|
||||
}
|
||||
|
||||
bool QCTMap::readPalette(QDataStream &stream)
|
||||
{
|
||||
if (!stream.device()->seek(0x01A0))
|
||||
return false;
|
||||
|
||||
_palette.resize(256);
|
||||
|
||||
quint32 bgr;
|
||||
for (int i = 0; i < _palette.size(); i++) {
|
||||
stream >> bgr;
|
||||
_palette[i] = Color::bgr2rgb(bgr);
|
||||
}
|
||||
|
||||
return (stream.status() == QDataStream::Ok);
|
||||
}
|
||||
|
||||
bool QCTMap::readIndex(QDataStream &stream)
|
||||
{
|
||||
if (!stream.device()->seek(0x45A0))
|
||||
return false;
|
||||
|
||||
_index.resize(_cols * _rows);
|
||||
for (int i = 0; i < _cols * _rows; i++)
|
||||
stream >> _index[i];
|
||||
|
||||
return (stream.status() == QDataStream::Ok);
|
||||
}
|
||||
|
||||
QCTMap::QCTMap(const QString &fileName, QObject *parent)
|
||||
: Map(fileName, parent), _file(fileName), _shiftE(0), _shiftN(0),
|
||||
_mapRatio(1.0), _valid(false)
|
||||
{
|
||||
if (!_file.open(QIODevice::ReadOnly)) {
|
||||
_errorString = fileName + ": " + _file.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
QDataStream stream(&_file);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
if (!readHeader(stream))
|
||||
return;
|
||||
if (!readGeoRef(stream)) {
|
||||
_errorString = "Error reading georeference info";
|
||||
return;
|
||||
}
|
||||
if (!readPalette(stream)) {
|
||||
_errorString = "Error reading colour palette";
|
||||
return;
|
||||
}
|
||||
if (!readIndex(stream)) {
|
||||
_errorString = "Error reading tile index";
|
||||
return;
|
||||
}
|
||||
|
||||
_file.close();
|
||||
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void QCTMap::load()
|
||||
{
|
||||
_file.open(QIODevice::ReadOnly);
|
||||
}
|
||||
|
||||
void QCTMap::unload()
|
||||
{
|
||||
_file.close();
|
||||
}
|
||||
|
||||
QRectF QCTMap::bounds()
|
||||
{
|
||||
return QRectF(QPointF(0, 0), QSizeF(_cols * TILE_SIZE, _rows * TILE_SIZE)
|
||||
/ _mapRatio);
|
||||
}
|
||||
|
||||
QPointF QCTMap::ll2xy(const Coordinates &c)
|
||||
{
|
||||
double lon = c.lon() - _shiftE;
|
||||
double lon2 = lon * lon;
|
||||
double lon3 = lon2 * lon;
|
||||
double lat = c.lat() - _shiftN;
|
||||
double lat2 = lat * lat;
|
||||
double lat3 = lat2 * lat;
|
||||
|
||||
double x = _easXXX*lon3 + _easXX*lon2 + _easX*lon + _easYYY*lat3
|
||||
+ _easYY*lat2 + _easY*lat + _easXXY*lon2*lat
|
||||
+ _easYYX*lat2*lon + _easXY*lon*lat + _eas;
|
||||
double y = _norXXX*lon3 + _norXX*lon2 + _norX*lon + _norYYY*lat3
|
||||
+ _norYY*lat2 + _norY*lat + _norXXY*lon2*lat
|
||||
+ _norYYX*lat2*lon + _norXY*lon*lat + _nor;
|
||||
|
||||
return QPointF(x - _shiftE, y - _shiftN) / _mapRatio;
|
||||
}
|
||||
|
||||
Coordinates QCTMap::xy2ll(const QPointF &p)
|
||||
{
|
||||
qreal x = p.x() * _mapRatio;
|
||||
qreal x2 = x * x;
|
||||
qreal x3 = x2 * x;
|
||||
qreal y = p.y() * _mapRatio;
|
||||
qreal y2 = y * y;
|
||||
qreal y3 = y2 * y;
|
||||
|
||||
double lon = _lon + _lonX*x + _lonY*y + _lonXX*x2
|
||||
+ _lonXY*x*y + _lonYY*y2 + _lonXXX*x3 + _lonXXY*x2*y
|
||||
+ _lonXYY*x*y2 + _lonYYY*y3;
|
||||
double lat = _lat + _latX*x + _latY*y + _latXX*x2
|
||||
+ _latXY*x*y + _latYY*y2 + _latXXX*x3 + _latXXY*x2 * y
|
||||
+ _latXYY*x*y2 + _latYYY*y3;
|
||||
|
||||
return Coordinates(lon + _shiftE, lat + _shiftN);
|
||||
}
|
||||
|
||||
QPixmap QCTMap::tile(int x, int y)
|
||||
{
|
||||
static quint8 rowSeq[] = {
|
||||
0, 32, 16, 48, 8, 40, 24, 56, 4, 36, 20, 52, 12, 44, 28, 60,
|
||||
2, 34, 18, 50, 10, 42, 26, 58, 6, 38, 22, 54, 14, 46, 30, 62,
|
||||
1, 33, 17, 49, 9, 41, 25, 57, 5, 37, 21, 53, 13, 45, 29, 61,
|
||||
3, 35, 19, 51, 11, 43, 27, 59, 7, 39, 23, 55, 15, 47, 31, 63
|
||||
};
|
||||
quint8 tileData[TILE_PIXELS], imgData[TILE_PIXELS];
|
||||
quint8 packing;
|
||||
bool ret;
|
||||
|
||||
|
||||
if (!_file.seek(_index.at(y * _cols + x)))
|
||||
return QPixmap();
|
||||
|
||||
QDataStream stream(&_file);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
stream >> packing;
|
||||
if (stream.status() != QDataStream::Ok)
|
||||
return QPixmap();
|
||||
|
||||
if (packing == 0 || packing == 255)
|
||||
ret = huffman(stream, tileData);
|
||||
else if (packing > 127)
|
||||
ret = pixelPacking(stream, tileData, 256 - packing);
|
||||
else
|
||||
ret = rle(stream, tileData, packing);
|
||||
|
||||
if (!ret)
|
||||
return QPixmap();
|
||||
|
||||
for (int i = 0; i < TILE_SIZE; i++)
|
||||
memcpy(imgData + i * TILE_SIZE, tileData + rowSeq[i] * TILE_SIZE,
|
||||
TILE_SIZE);
|
||||
|
||||
QImage img(imgData, TILE_SIZE, TILE_SIZE, TILE_SIZE,
|
||||
QImage::Format_Indexed8);
|
||||
img.setColorTable(_palette);
|
||||
|
||||
return QPixmap::fromImage(img);
|
||||
}
|
||||
|
||||
void QCTMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
{
|
||||
Q_UNUSED(flags);
|
||||
|
||||
QSizeF ts(TILE_SIZE / _mapRatio, TILE_SIZE / _mapRatio);
|
||||
QPointF tl(floor(rect.left() / ts.width()) * ts.width(),
|
||||
floor(rect.top() / ts.height()) * ts.height());
|
||||
|
||||
QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y());
|
||||
for (int i = 0; i < ceil(s.width() / ts.width()); i++) {
|
||||
for (int j = 0; j < ceil(s.height() / ts.height()); j++) {
|
||||
int x = round(tl.x() * _mapRatio + i * TILE_SIZE) / TILE_SIZE;
|
||||
int y = round(tl.y() * _mapRatio + j * TILE_SIZE) / TILE_SIZE;
|
||||
|
||||
QPixmap pixmap;
|
||||
QString key = path() + "/" + QString::number(x) + "_"
|
||||
+ QString::number(y);
|
||||
if (!QPixmapCache::find(key, &pixmap)) {
|
||||
pixmap = tile(x, y);
|
||||
if (!pixmap.isNull())
|
||||
QPixmapCache::insert(key, pixmap);
|
||||
}
|
||||
|
||||
if (pixmap.isNull())
|
||||
qWarning("%s: error loading tile image", qPrintable(key));
|
||||
else {
|
||||
pixmap.setDevicePixelRatio(_mapRatio);
|
||||
QPointF tp(tl.x() + i * ts.width(), tl.y() + j * ts.height());
|
||||
painter->drawPixmap(tp, pixmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
63
src/map/qctmap.h
Normal file
@ -0,0 +1,63 @@
|
||||
#ifndef QCTMAP_H
|
||||
#define QCTMAP_H
|
||||
|
||||
#include <QFile>
|
||||
#include <QRgb>
|
||||
#include "map.h"
|
||||
|
||||
class QDataStream;
|
||||
|
||||
class QCTMap : public Map
|
||||
{
|
||||
public:
|
||||
QCTMap(const QString &fileName, QObject *parent = 0);
|
||||
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
|
||||
QPointF ll2xy(const Coordinates &c);
|
||||
Coordinates xy2ll(const QPointF &p);
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void load();
|
||||
void unload();
|
||||
|
||||
void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio)
|
||||
{_mapRatio = mapRatio;}
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
private:
|
||||
bool readName(QDataStream &stream);
|
||||
bool readSize(QDataStream &stream);
|
||||
bool readDatumShift(QDataStream &stream);
|
||||
bool readHeader(QDataStream &stream);
|
||||
bool readGeoRef(QDataStream &stream);
|
||||
bool readIndex(QDataStream &stream);
|
||||
bool readPalette(QDataStream &stream);
|
||||
QPixmap tile(int x, int y);
|
||||
|
||||
QFile _file;
|
||||
QString _name;
|
||||
int _rows, _cols;
|
||||
double _lon, _lonX, _lonXX, _lonXXX, _lonY, _lonYY, _lonYYY, _lonXY,
|
||||
_lonXXY, _lonXYY;
|
||||
double _lat, _latX, _latXX, _latXXX, _latY, _latYY, _latYYY, _latXY,
|
||||
_latXXY, _latXYY;
|
||||
double _eas, _easY, _easX, _easYY, _easXY, _easXX, _easYYY, _easYYX,
|
||||
_easXXY, _easXXX;
|
||||
double _nor, _norY, _norX, _norYY, _norXY, _norXX, _norYYY, _norYYX,
|
||||
_norXXY, _norXXX;
|
||||
double _shiftE, _shiftN;
|
||||
QVector<quint32> _index;
|
||||
QVector<QRgb> _palette;
|
||||
|
||||
qreal _mapRatio;
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
};
|
||||
|
||||
#endif // QCTMAP_H
|
@ -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);
|
||||
|