mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-07-01 13:29:16 +02:00
Compare commits
133 Commits
Author | SHA1 | Date | |
---|---|---|---|
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.0.{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
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
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
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
|
44
README.md
44
README.md
@ -1,11 +1,19 @@
|
||||
# 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 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.
|
||||
@ -18,8 +26,9 @@ GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common G
|
||||
|
||||
## 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 +37,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 +54,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
|
||||
|
23
gpxsee.pro
23
gpxsee.pro
@ -3,7 +3,7 @@ unix:!macx {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 9.8
|
||||
VERSION = 10.0
|
||||
|
||||
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 \
|
||||
@ -143,6 +150,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 +242,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 \
|
||||
@ -336,6 +347,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 +494,8 @@ 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
|
||||
DEFINES += _USE_MATH_DEFINES \
|
||||
NOGDI
|
||||
}
|
||||
@ -498,7 +511,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
BIN
icons/GUI/transform-move.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/GUI/transform-move@2x.png
Normal file
BIN
icons/GUI/transform-move@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
BIN
icons/GUI/transform-move_32.png
Normal file
BIN
icons/GUI/transform-move_32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
icons/GUI/transform-move_32@2x.png
Normal file
BIN
icons/GUI/transform-move_32@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
BIN
icons/formats/qct.icns
Normal file
BIN
icons/formats/qct.icns
Normal file
Binary file not shown.
BIN
icons/formats/qct.ico
Normal file
BIN
icons/formats/qct.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 306 KiB |
@ -27,3 +27,4 @@ itn:#b8540d
|
||||
wld:#c74c8f
|
||||
omd:#ed09cb
|
||||
ghp:#ed09cb
|
||||
qct:#370642
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -578,6 +578,22 @@
|
||||
<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>
|
||||
</array>
|
||||
|
||||
<key>UTImportedTypeDeclarations</key>
|
||||
@ -1368,6 +1384,29 @@
|
||||
<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>
|
||||
</array>
|
||||
|
||||
<key>UTExportedTypeDeclarations</key>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<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>
|
||||
@ -97,5 +97,6 @@
|
||||
<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>
|
||||
</mimetypes>
|
||||
</component>
|
||||
|
400
pkg/gpxsee.nsi
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
|
@ -285,4 +285,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.0"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
@ -149,13 +177,14 @@ 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 "kml" "Keyhole Markup Language" 25
|
||||
!insertmacro FILE_ASSOCIATION_ADD "kmz" "KML geographic compressed data" 25
|
||||
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 26
|
||||
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 27
|
||||
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 28
|
||||
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track File" 29
|
||||
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 30
|
||||
|
||||
WriteRegStr HKCR "Applications\GPXSee.exe\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
|
||||
WriteRegStr HKCR ".gpx\OpenWithList" "GPXSee.exe" ""
|
||||
@ -201,6 +230,7 @@ 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" ""
|
||||
|
||||
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
||||
|
||||
@ -221,6 +251,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 +263,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 +380,7 @@ Section "Uninstall"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "tfw"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "omd"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "ghp"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "qct"
|
||||
|
||||
DeleteRegValue HKCR ".gpx\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tcx\OpenWithList" "GPXSee.exe"
|
||||
@ -388,6 +425,7 @@ 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"
|
||||
DeleteRegKey HKCR "Applications\GPXSee.exe"
|
||||
|
||||
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
||||
@ -420,4 +458,4 @@ LangString DESC_LOCALIZATION ${LANG_ENGLISH} \
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_MSVC} $(DESC_MSVC)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_APP} $(DESC_APP)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_LOCALIZATION} $(DESC_LOCALIZATION)
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
@ -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
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
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
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
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
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
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
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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
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
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);
|
||||
|
Reference in New Issue
Block a user