Compare commits
182 Commits
Author | SHA1 | Date | |
---|---|---|---|
9bd79a4104 | |||
f9abf21e6d | |||
fb4af33d89 | |||
9eb95daf09 | |||
d291e55bdb | |||
b5893cf506 | |||
8507fe3b52 | |||
79edd6e09d | |||
491c6c9a98 | |||
3c36db9f5a | |||
c4a750f5d4 | |||
e4d7f45103 | |||
c85b90d56d | |||
7babf734bf | |||
25ac235414 | |||
630a5cea83 | |||
a0de7f25c3 | |||
7c6174a8ee | |||
0f512d1269 | |||
246b46ffcb | |||
cc4cbcbeda | |||
64e0b492e6 | |||
52a8b1de5b | |||
5045c03953 | |||
515f1aeb27 | |||
dbb82d6f44 | |||
307a03d46c | |||
b7c03b4b9e | |||
2d1e0934ce | |||
0ff66bc897 | |||
3b68f497fe | |||
a04293b411 | |||
5a4de1cef0 | |||
99d3d8fd0a | |||
d579ce3482 | |||
67ce176b74 | |||
1a88527c60 | |||
9d6a2cce45 | |||
7a5f67790e | |||
704c66449f | |||
42e1331678 | |||
ad3b666a19 | |||
3dd253828e | |||
bb5e50b009 | |||
69384ca315 | |||
676c82b7a4 | |||
5a2be6ff07 | |||
454e725587 | |||
b9d9ab85b2 | |||
15a2df12bd | |||
db7a75088a | |||
378da395fb | |||
da7d0fe32d | |||
789f314ae8 | |||
0986864c6c | |||
83ac0b5ed7 | |||
a1be73fbba | |||
7761935c29 | |||
4da0e8a1c7 | |||
066736b3d2 | |||
fdcbc4c6c2 | |||
b894df26d3 | |||
5a5c0ef68a | |||
56b7014eaf | |||
1f52dad1c6 | |||
0f8859dd20 | |||
398eb152f6 | |||
38ab835898 | |||
927740a196 | |||
4d8b7aa8ae | |||
49c94d34b3 | |||
5c2ac54bb4 | |||
003947263f | |||
6a70e5ea00 | |||
e83be4d553 | |||
ce38077281 | |||
e75a2882a5 | |||
8add7b428f | |||
846f864bd4 | |||
8683254155 | |||
ef2ffd9fc4 | |||
a9c86fd580 | |||
fe360a2578 | |||
a09a58eece | |||
abd1817d83 | |||
7c90174751 | |||
b24f27cf79 | |||
98f88db3cf | |||
f2ddfa6fb7 | |||
54ed0ca9f6 | |||
477b32f444 | |||
1fb6aad50f | |||
4fa9aac917 | |||
03db87535a | |||
92145c8445 | |||
5e8479707b | |||
2039105ba5 | |||
2605e1abeb | |||
8fd17badda | |||
7d62ef038c | |||
138e0e9505 | |||
5dffb2714b | |||
5d8330a68a | |||
ff30163175 | |||
743fb20a95 | |||
50f483663c | |||
96997ffa35 | |||
d738ad7b5a | |||
01d69a4f2a | |||
0e026d6a96 | |||
07825e5701 | |||
03e7d092c4 | |||
0b5d01a1f6 | |||
08aa087f61 | |||
6604f85f4a | |||
5343a1a922 | |||
d6e0757364 | |||
51becc4bf1 | |||
29a821f8b2 | |||
14f4dead76 | |||
96bb3bbdbb | |||
22d18b6d4e | |||
c1b79217a9 | |||
e67a14b072 | |||
473d03cf1f | |||
a339706293 | |||
39c414ca73 | |||
c59d60faed | |||
32d3eab10e | |||
e7729e8745 | |||
bf145c9eb5 | |||
de0a6b0397 | |||
8cf89a580f | |||
152e2a8a09 | |||
6b860fe18c | |||
95f138f5f0 | |||
1fc4dbbb73 | |||
0999cdcba2 | |||
cc16c9e79b | |||
1990c85fd7 | |||
58f70fa833 | |||
0f6c50d588 | |||
89dce5152e | |||
8bce6a44ed | |||
59ecd3fdf0 | |||
a10c729e52 | |||
369601f102 | |||
47d0feeb46 | |||
58a0acc718 | |||
c466527625 | |||
9cd00075c7 | |||
6f72d46d6c | |||
54467e6d45 | |||
3d2e33361d | |||
f91df0d026 | |||
9bd004359d | |||
e170f92e79 | |||
0fb5d8dae6 | |||
5ff931bb5e | |||
5bd744a8ed | |||
035883aab2 | |||
571ed087e3 | |||
c461b2e549 | |||
26b5411465 | |||
8965f450ce | |||
a958544667 | |||
ddf865834a | |||
a4abed8f1f | |||
56061c93cb | |||
7385b08262 | |||
9d79bd9a9d | |||
159e5aeae9 | |||
d8beaed876 | |||
c1584f30d2 | |||
efcefe8fec | |||
5322ee96c8 | |||
51d4e04343 | |||
0f96bc602c | |||
cb6a82a10a | |||
ff0711c620 | |||
74775b2c62 | |||
a6fbae38b8 |
@ -1,4 +1,4 @@
|
||||
version: 7.29.{build}
|
||||
version: 7.35.{build}
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
github: tumic0
|
35
gpxsee.pro
@ -3,7 +3,7 @@ unix:!macx {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 7.29
|
||||
VERSION = 7.35
|
||||
|
||||
QT += core \
|
||||
gui \
|
||||
@ -21,6 +21,7 @@ INCLUDEPATH += ./src
|
||||
HEADERS += src/common/config.h \
|
||||
src/GUI/graphicsscene.h \
|
||||
src/GUI/mapaction.h \
|
||||
src/GUI/marginswidget.h \
|
||||
src/GUI/popup.h \
|
||||
src/common/garmin.h \
|
||||
src/common/staticassert.h \
|
||||
@ -53,7 +54,6 @@ HEADERS += src/common/config.h \
|
||||
src/GUI/palette.h \
|
||||
src/GUI/heartrategraph.h \
|
||||
src/GUI/trackinfo.h \
|
||||
src/GUI/exportdialog.h \
|
||||
src/GUI/fileselectwidget.h \
|
||||
src/GUI/margins.h \
|
||||
src/GUI/temperaturegraph.h \
|
||||
@ -95,7 +95,9 @@ HEADERS += src/common/config.h \
|
||||
src/map/IMG/gmap.h \
|
||||
src/map/IMG/huffmanstream.h \
|
||||
src/map/IMG/huffmantable.h \
|
||||
src/map/IMG/nodfile.h \
|
||||
src/map/IMG/mapdata.h \
|
||||
src/map/IMG/rastertile.h \
|
||||
src/map/IMG/textpathitem.h \
|
||||
src/map/IMG/textpointitem.h \
|
||||
src/map/projection.h \
|
||||
@ -196,8 +198,11 @@ HEADERS += src/common/config.h \
|
||||
src/data/cupparser.h \
|
||||
src/data/gpiparser.h \
|
||||
src/data/address.h \
|
||||
src/data/smlparser.h
|
||||
src/data/smlparser.h \
|
||||
src/GUI/pdfexportdialog.h \
|
||||
src/GUI/pngexportdialog.h
|
||||
SOURCES += src/main.cpp \
|
||||
src/GUI/marginswidget.cpp \
|
||||
src/GUI/popup.cpp \
|
||||
src/common/coordinates.cpp \
|
||||
src/common/rectc.cpp \
|
||||
@ -222,7 +227,6 @@ SOURCES += src/main.cpp \
|
||||
src/GUI/palette.cpp \
|
||||
src/GUI/heartrategraph.cpp \
|
||||
src/GUI/trackinfo.cpp \
|
||||
src/GUI/exportdialog.cpp \
|
||||
src/GUI/fileselectwidget.cpp \
|
||||
src/GUI/temperaturegraph.cpp \
|
||||
src/GUI/trackitem.cpp \
|
||||
@ -256,7 +260,9 @@ SOURCES += src/main.cpp \
|
||||
src/map/IMG/gmap.cpp \
|
||||
src/map/IMG/huffmanstream.cpp \
|
||||
src/map/IMG/huffmantable.cpp \
|
||||
src/map/IMG/nodfile.cpp \
|
||||
src/map/IMG/mapdata.cpp \
|
||||
src/map/IMG/rastertile.cpp \
|
||||
src/map/IMG/textpathitem.cpp \
|
||||
src/map/IMG/textpointitem.cpp \
|
||||
src/map/maplist.cpp \
|
||||
@ -340,12 +346,17 @@ SOURCES += src/main.cpp \
|
||||
src/data/cupparser.cpp \
|
||||
src/GUI/graphicsscene.cpp \
|
||||
src/data/gpiparser.cpp \
|
||||
src/data/smlparser.cpp
|
||||
src/data/smlparser.cpp \
|
||||
src/GUI/pdfexportdialog.cpp \
|
||||
src/GUI/pngexportdialog.cpp
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4) {
|
||||
HEADERS += src/data/geojsonparser.h
|
||||
SOURCES += src/data/geojsonparser.cpp
|
||||
}
|
||||
equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 4) {
|
||||
HEADERS += src/GUI/timezoneinfo.h
|
||||
}
|
||||
|
||||
DEFINES += APP_VERSION=\\\"$$VERSION\\\" \
|
||||
QT_NO_DEPRECATED_WARNINGS
|
||||
@ -366,10 +377,11 @@ TRANSLATIONS = lang/gpxsee_en.ts \
|
||||
lang/gpxsee_es.ts \
|
||||
lang/gpxsee_pt_BR.ts \
|
||||
lang/gpxsee_uk.ts \
|
||||
lang/gpxsee_hu.ts
|
||||
lang/gpxsee_hu.ts \
|
||||
lang/gpxsee_it.ts
|
||||
|
||||
macx {
|
||||
ICON = icons/gpxsee.icns
|
||||
ICON = icons/app/gpxsee.icns
|
||||
QMAKE_INFO_PLIST = pkg/Info.plist
|
||||
locale.path = Contents/Resources/translations
|
||||
locale.files = lang/gpxsee_en.qm \
|
||||
@ -386,7 +398,8 @@ macx {
|
||||
lang/gpxsee_es.qm \
|
||||
lang/gpxsee_pt_BR.qm \
|
||||
lang/gpxsee_uk.qm \
|
||||
lang/gpxsee_hu.qm
|
||||
lang/gpxsee_hu.qm \
|
||||
lang/gpxsee_it.qm
|
||||
csv.path = Contents/Resources
|
||||
csv.files = pkg/csv
|
||||
maps.path = Contents/Resources
|
||||
@ -411,7 +424,7 @@ macx {
|
||||
}
|
||||
|
||||
win32 {
|
||||
RC_ICONS = icons/gpxsee.ico \
|
||||
RC_ICONS = icons/app/gpxsee.ico \
|
||||
icons/formats/gpx.ico \
|
||||
icons/formats/tcx.ico \
|
||||
icons/formats/kml.ico \
|
||||
@ -441,8 +454,8 @@ unix:!macx {
|
||||
csv.path = $$PREFIX/share/gpxsee/csv
|
||||
locale.files = lang/*.qm
|
||||
locale.path = $$PREFIX/share/gpxsee/translations
|
||||
icon.files = icons/gpxsee.png
|
||||
icon.path = $$PREFIX/share/pixmaps
|
||||
icon.files = icons/app/hicolor/*
|
||||
icon.path = $$PREFIX/share/icons/hicolor
|
||||
desktop.files = pkg/gpxsee.desktop
|
||||
desktop.path = $$PREFIX/share/applications
|
||||
mime.files = pkg/gpxsee.xml
|
||||
|
@ -1,8 +1,8 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<!-- GUI -->
|
||||
<file alias="gpxsee.png">icons/gpxsee.png</file>
|
||||
<file alias="gpxsee@2x.png">icons/gpxsee@2x.png</file>
|
||||
<file alias="gpxsee.png">icons/app/gpxsee.png</file>
|
||||
<file alias="gpxsee@2x.png">icons/app/gpxsee@2x.png</file>
|
||||
<file alias="dialog-close.png">icons/GUI/dialog-close.png</file>
|
||||
<file alias="dialog-close@2x.png">icons/GUI/dialog-close@2x.png</file>
|
||||
<file alias="document-open.png">icons/GUI/document-open.png</file>
|
||||
@ -67,10 +67,12 @@
|
||||
<file alias="cinema-11.png">icons/POI/cinema-11.png</file>
|
||||
<file alias="clothing-store-11.png">icons/POI/clothing-store-11.png</file>
|
||||
<file alias="communications-tower-11.png">icons/POI/communications-tower-11.png</file>
|
||||
<file alias="convenience-11.png">icons/POI/convenience-11.png</file>
|
||||
<file alias="dam-11.png">icons/POI/dam-11.png</file>
|
||||
<file alias="danger-11.png">icons/POI/danger-11.png</file>
|
||||
<file alias="drinking-water-11.png">icons/POI/drinking-water-11.png</file>
|
||||
<file alias="fast-food-11.png">icons/POI/fast-food-11.png</file>
|
||||
<file alias="entrance-alt1-11.png">icons/POI/entrance-alt1-11.png</file>
|
||||
<file alias="fire-station-11.png">icons/POI/fire-station-11.png</file>
|
||||
<file alias="fitness-centre-11.png">icons/POI/fitness-centre-11.png</file>
|
||||
<file alias="fuel-11.png">icons/POI/fuel-11.png</file>
|
||||
@ -97,7 +99,6 @@
|
||||
<file alias="place-of-worship-11.png">icons/POI/place-of-worship-11.png</file>
|
||||
<file alias="police-11.png">icons/POI/police-11.png</file>
|
||||
<file alias="post-11.png">icons/POI/post-11.png</file>
|
||||
<file alias="prison-11.png">icons/POI/prison-11.png</file>
|
||||
<file alias="religious-christian-11.png">icons/POI/religious-christian-11.png</file>
|
||||
<file alias="religious-jewish-11.png">icons/POI/religious-jewish-11.png</file>
|
||||
<file alias="religious-muslim-11.png">icons/POI/religious-muslim-11.png</file>
|
||||
|
BIN
icons/POI/convenience-11.png
Normal file
After Width: | Height: | Size: 650 B |
BIN
icons/POI/entrance-alt1-11.png
Normal file
After Width: | Height: | Size: 611 B |
Before Width: | Height: | Size: 323 B |
BIN
icons/app/gpxsee.dia
Normal file
Before Width: | Height: | Size: 361 KiB After Width: | Height: | Size: 361 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
BIN
icons/app/hicolor/128x128/apps/gpxsee.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
icons/app/hicolor/16x16/apps/gpxsee.png
Normal file
After Width: | Height: | Size: 571 B |
BIN
icons/app/hicolor/32x32/apps/gpxsee.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
icons/app/hicolor/48x48/apps/gpxsee.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
icons/app/hicolor/64x64/apps/gpxsee.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
33
icons/app/hicolor/scalable/apps/gpxsee.svg
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
|
||||
<svg width="6cm" height="6cm" viewBox="47 79 119 119" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g>
|
||||
<rect style="fill: #ffffff" x="47.729" y="79.875" width="118.071" height="118.071" rx="10" ry="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 2.35099e-37; stroke-linejoin: round; stroke: #ffffff" x="47.729" y="79.875" width="118.071" height="118.071" rx="10" ry="10"/>
|
||||
</g>
|
||||
<g>
|
||||
<ellipse style="fill: #000000" cx="113" cy="90.875" rx="7.021" ry="7.021"/>
|
||||
<ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke-linejoin: round; stroke: #000000" cx="113" cy="90.875" rx="7.021" ry="7.021"/>
|
||||
</g>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 4; stroke: #000000" points="61.5289,182.479 73.5,125.854 96,151.875 113,90.875 136.5,172.375 151.658,157.199 "/>
|
||||
<g>
|
||||
<ellipse style="fill: #000000" cx="73.5" cy="125.854" rx="7.021" ry="7.021"/>
|
||||
<ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="73.5" cy="125.854" rx="7.021" ry="7.021"/>
|
||||
</g>
|
||||
<g>
|
||||
<ellipse style="fill: #000000" cx="136.5" cy="172.375" rx="7.021" ry="7.021"/>
|
||||
<ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="136.5" cy="172.375" rx="7.021" ry="7.021"/>
|
||||
</g>
|
||||
<g>
|
||||
<ellipse style="fill: #000000" cx="60.7" cy="186.4" rx="7.021" ry="7.021"/>
|
||||
<ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="60.7" cy="186.4" rx="7.021" ry="7.021"/>
|
||||
</g>
|
||||
<g>
|
||||
<ellipse style="fill: #000000" cx="154.5" cy="154.354" rx="7.021" ry="7.021"/>
|
||||
<ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="154.5" cy="154.354" rx="7.021" ry="7.021"/>
|
||||
</g>
|
||||
<g>
|
||||
<ellipse style="fill: #000000" cx="96" cy="151.875" rx="7.021" ry="7.021"/>
|
||||
<ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="96" cy="151.875" rx="7.021" ry="7.021"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
icons/gpxsee.dia
@ -1,4 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="en_US">
|
||||
<context>
|
||||
<name>GUI</name>
|
||||
<message numerus="yes">
|
||||
<location filename="../src/GUI/gui.cpp" line="1392"/>
|
||||
<source>%n files</source>
|
||||
<translation>
|
||||
<numerusform>%n file</numerusform>
|
||||
<numerusform>%n files</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
2018
lang/gpxsee_it.ts
Normal file
@ -7,7 +7,7 @@
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "7.29"
|
||||
!define VERSION "7.35"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}.exe"
|
||||
@ -17,6 +17,9 @@ 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"
|
||||
|
||||
@ -177,6 +180,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
|
||||
!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"
|
||||
|
@ -7,7 +7,7 @@
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "7.29"
|
||||
!define VERSION "7.35"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
@ -17,6 +17,9 @@ 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 "$PROGRAMFILES64\GPXSee"
|
||||
|
||||
@ -184,6 +187,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
|
||||
!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"
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.4" type="WMTS">
|
||||
<name>Antarctica</name>
|
||||
<url type="REST">https://gis.ngdc.noaa.gov/arcgis/rest/services/antarctic/antarctic_basemap/MapServer/WMTS/1.0.0/WMTSCapabilities.xml</url>
|
||||
<url type="REST">https://tiles.arcgis.com/tiles/C8EMgrsFcRFL6LrL/arcgis/rest/services/Antarctic_Basemap/MapServer/WMTS/1.0.0/WMTSCapabilities.xml</url>
|
||||
<copyright>NOAA National Centers for Environmental Information (NCEI); International Bathymetric Chart of the Southern Ocean (IBCSO); General Bathymetric Chart of the Oceans (GEBCO); Natural Earth</copyright>
|
||||
<layer>antarctic_antarctic_basemap</layer>
|
||||
<layer>Antarctic_Basemap</layer>
|
||||
<set>default028mm</set>
|
||||
</map>
|
||||
|
@ -12,7 +12,8 @@ FileSelectWidget::FileSelectWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
QFontMetrics fm(QApplication::font());
|
||||
_edit = new QLineEdit();
|
||||
_edit->setMinimumWidth(fm.boundingRect(QDir::homePath()).width());
|
||||
_edit->setMinimumWidth(fm.averageCharWidth() * (QDir::homePath().length()
|
||||
+ 12));
|
||||
#ifdef Q_OS_WIN32
|
||||
_button = new QPushButton("...");
|
||||
_button->setMaximumWidth(_button->sizeHint().width() / 2);
|
||||
@ -41,3 +42,33 @@ void FileSelectWidget::browse()
|
||||
if (!fileName.isEmpty())
|
||||
_edit->setText(fileName);
|
||||
}
|
||||
|
||||
bool FileSelectWidget::checkFile(QString &error) const
|
||||
{
|
||||
if (_edit->text().isEmpty()) {
|
||||
error = tr("No output file selected.");
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile file(_edit->text());
|
||||
QFileInfo fi(file);
|
||||
bool exists = fi.exists();
|
||||
bool opened = false;
|
||||
|
||||
if (exists && fi.isDir()) {
|
||||
error = tr("%1 is a directory.").arg(file.fileName());
|
||||
return false;
|
||||
} else if ((exists && !fi.isWritable())
|
||||
|| !(opened = file.open(QFile::Append))) {
|
||||
error = tr("%1 is not writable.").arg(file.fileName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opened) {
|
||||
file.close();
|
||||
if (!exists)
|
||||
file.remove();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -14,9 +14,10 @@ class FileSelectWidget : public QWidget
|
||||
public:
|
||||
FileSelectWidget(QWidget *parent = 0);
|
||||
|
||||
QString file() {return _edit->text();}
|
||||
QString file() const {return _edit->text();}
|
||||
void setFile(const QString &file) {_edit->setText(file);}
|
||||
void setFilter(const QString &filter) {_filter = filter;}
|
||||
bool checkFile(QString &error) const;
|
||||
|
||||
private slots:
|
||||
void browse();
|
||||
|
326
src/GUI/gui.cpp
@ -230,13 +230,20 @@ void GUI::createActions()
|
||||
_printFileAction->setActionGroup(_fileActionGroup);
|
||||
connect(_printFileAction, SIGNAL(triggered()), this, SLOT(printFile()));
|
||||
addAction(_printFileAction);
|
||||
_exportFileAction = new QAction(QIcon(EXPORT_FILE_ICON),
|
||||
_exportPDFFileAction = new QAction(QIcon(EXPORT_FILE_ICON),
|
||||
tr("Export to PDF..."), this);
|
||||
_exportFileAction->setMenuRole(QAction::NoRole);
|
||||
_exportFileAction->setShortcut(EXPORT_SHORTCUT);
|
||||
_exportFileAction->setActionGroup(_fileActionGroup);
|
||||
connect(_exportFileAction, SIGNAL(triggered()), this, SLOT(exportFile()));
|
||||
addAction(_exportFileAction);
|
||||
_exportPDFFileAction->setMenuRole(QAction::NoRole);
|
||||
_exportPDFFileAction->setShortcut(PDF_EXPORT_SHORTCUT);
|
||||
_exportPDFFileAction->setActionGroup(_fileActionGroup);
|
||||
connect(_exportPDFFileAction, SIGNAL(triggered()), this, SLOT(exportPDFFile()));
|
||||
addAction(_exportPDFFileAction);
|
||||
_exportPNGFileAction = new QAction(QIcon(EXPORT_FILE_ICON),
|
||||
tr("Export to PNG..."), this);
|
||||
_exportPNGFileAction->setMenuRole(QAction::NoRole);
|
||||
_exportPNGFileAction->setShortcut(PNG_EXPORT_SHORTCUT);
|
||||
_exportPNGFileAction->setActionGroup(_fileActionGroup);
|
||||
connect(_exportPNGFileAction, SIGNAL(triggered()), this, SLOT(exportPNGFile()));
|
||||
addAction(_exportPNGFileAction);
|
||||
_closeFileAction = new QAction(QIcon(CLOSE_FILE_ICON), tr("Close"), this);
|
||||
_closeFileAction->setMenuRole(QAction::NoRole);
|
||||
_closeFileAction->setShortcut(CLOSE_SHORTCUT);
|
||||
@ -248,7 +255,7 @@ void GUI::createActions()
|
||||
_reloadFileAction->setMenuRole(QAction::NoRole);
|
||||
_reloadFileAction->setShortcut(RELOAD_SHORTCUT);
|
||||
_reloadFileAction->setActionGroup(_fileActionGroup);
|
||||
connect(_reloadFileAction, SIGNAL(triggered()), this, SLOT(reloadFile()));
|
||||
connect(_reloadFileAction, SIGNAL(triggered()), this, SLOT(reloadFiles()));
|
||||
addAction(_reloadFileAction);
|
||||
_statisticsAction = new QAction(tr("Statistics..."), this);
|
||||
_statisticsAction->setMenuRole(QAction::NoRole);
|
||||
@ -497,7 +504,8 @@ void GUI::createMenus()
|
||||
fileMenu->addAction(_openFileAction);
|
||||
fileMenu->addSeparator();
|
||||
fileMenu->addAction(_printFileAction);
|
||||
fileMenu->addAction(_exportFileAction);
|
||||
fileMenu->addAction(_exportPDFFileAction);
|
||||
fileMenu->addAction(_exportPNGFileAction);
|
||||
fileMenu->addSeparator();
|
||||
fileMenu->addAction(_statisticsAction);
|
||||
fileMenu->addSeparator();
|
||||
@ -791,7 +799,12 @@ bool GUI::loadFile(const QString &fileName)
|
||||
_trackDistance += track.distance();
|
||||
_time += track.time();
|
||||
_movingTime += track.movingTime();
|
||||
const QDate &date = track.date().date();
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
const QDateTime date = track.date().toTimeZone(
|
||||
_options.timeZone.zone());
|
||||
#else // ENABLE_TIMEZONES
|
||||
const QDateTime &date = track.date();
|
||||
#endif // ENABLE_TIMEZONES
|
||||
if (_dateRange.first.isNull() || _dateRange.first > date)
|
||||
_dateRange.first = date;
|
||||
if (_dateRange.second.isNull() || _dateRange.second < date)
|
||||
@ -923,7 +936,7 @@ void GUI::openOptions()
|
||||
Options options(_options);
|
||||
bool reload = false;
|
||||
|
||||
OptionsDialog dialog(&options, this);
|
||||
OptionsDialog dialog(options, _units, this);
|
||||
if (dialog.exec() != QDialog::Accepted)
|
||||
return;
|
||||
|
||||
@ -965,6 +978,7 @@ void GUI::openOptions()
|
||||
SET_TRACK_OPTION(dataUseDEM, useDEM);
|
||||
SET_TRACK_OPTION(showSecondaryElevation, showSecondaryElevation);
|
||||
SET_TRACK_OPTION(showSecondarySpeed, showSecondarySpeed);
|
||||
SET_TRACK_OPTION(useSegments, useSegments);
|
||||
|
||||
SET_ROUTE_OPTION(dataUseDEM, useDEM);
|
||||
SET_ROUTE_OPTION(showSecondaryElevation, showSecondaryElevation);
|
||||
@ -990,9 +1004,16 @@ void GUI::openOptions()
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||
options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||
#endif // ENABLE_HIDPI
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
if (options.timeZone != _options.timeZone) {
|
||||
_mapView->setTimeZone(options.timeZone.zone());
|
||||
_dateRange.first = _dateRange.first.toTimeZone(options.timeZone.zone());
|
||||
_dateRange.second = _dateRange.second.toTimeZone(options.timeZone.zone());
|
||||
}
|
||||
#endif // ENABLE_TIMEZONES
|
||||
|
||||
if (reload)
|
||||
reloadFile();
|
||||
reloadFiles();
|
||||
|
||||
_options = options;
|
||||
}
|
||||
@ -1006,9 +1027,9 @@ void GUI::printFile()
|
||||
plot(&printer);
|
||||
}
|
||||
|
||||
void GUI::exportFile()
|
||||
void GUI::exportPDFFile()
|
||||
{
|
||||
ExportDialog dialog(&_export, this);
|
||||
PDFExportDialog dialog(_pdfExport, _units, this);
|
||||
if (dialog.exec() != QDialog::Accepted)
|
||||
return;
|
||||
|
||||
@ -1016,16 +1037,53 @@ void GUI::exportFile()
|
||||
printer.setOutputFormat(QPrinter::PdfFormat);
|
||||
printer.setCreator(QString(APP_NAME) + QString(" ")
|
||||
+ QString(APP_VERSION));
|
||||
printer.setResolution(_export.resolution);
|
||||
printer.setOrientation(_export.orientation);
|
||||
printer.setOutputFileName(_export.fileName);
|
||||
printer.setPaperSize(_export.paperSize);
|
||||
printer.setPageMargins(_export.margins.left(), _export.margins.top(),
|
||||
_export.margins.right(), _export.margins.bottom(), QPrinter::Millimeter);
|
||||
printer.setResolution(_pdfExport.resolution);
|
||||
printer.setOrientation(_pdfExport.orientation);
|
||||
printer.setOutputFileName(_pdfExport.fileName);
|
||||
printer.setPaperSize(_pdfExport.paperSize);
|
||||
printer.setPageMargins(_pdfExport.margins.left(), _pdfExport.margins.top(),
|
||||
_pdfExport.margins.right(), _pdfExport.margins.bottom(),
|
||||
QPrinter::Millimeter);
|
||||
|
||||
plot(&printer);
|
||||
}
|
||||
|
||||
void GUI::exportPNGFile()
|
||||
{
|
||||
PNGExportDialog dialog(_pngExport, this);
|
||||
if (dialog.exec() != QDialog::Accepted)
|
||||
return;
|
||||
|
||||
QImage img(_pngExport.size, QImage::Format_ARGB32_Premultiplied);
|
||||
QPainter p(&img);
|
||||
QRectF rect(0, 0, img.width(), img.height());
|
||||
QRectF contentRect(rect.adjusted(_pngExport.margins.left(),
|
||||
_pngExport.margins.top(), -_pngExport.margins.right(),
|
||||
-_pngExport.margins.bottom()));
|
||||
|
||||
if (_pngExport.antialiasing)
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.fillRect(rect, Qt::white);
|
||||
plotMainPage(&p, contentRect, 1.0, true);
|
||||
img.save(_pngExport.fileName);
|
||||
|
||||
if (!_tabs.isEmpty() && _options.separateGraphPage) {
|
||||
QImage img2(_pngExport.size.width(), (int)graphPlotHeight(rect, 1)
|
||||
+ _pngExport.margins.bottom(), QImage::Format_ARGB32_Premultiplied);
|
||||
QPainter p2(&img2);
|
||||
QRectF rect2(0, 0, img2.width(), img2.height());
|
||||
|
||||
if (_pngExport.antialiasing)
|
||||
p2.setRenderHint(QPainter::Antialiasing);
|
||||
p2.fillRect(rect2, Qt::white);
|
||||
plotGraphsPage(&p2, contentRect, 1);
|
||||
|
||||
QFileInfo fi(_pngExport.fileName);
|
||||
img2.save(fi.absolutePath() + "/" + fi.baseName() + "-graphs."
|
||||
+ fi.suffix());
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::statistics()
|
||||
{
|
||||
QLocale l(QLocale::system());
|
||||
@ -1097,12 +1155,13 @@ void GUI::statistics()
|
||||
msgBox.exec();
|
||||
}
|
||||
|
||||
void GUI::plot(QPrinter *printer)
|
||||
void GUI::plotMainPage(QPainter *painter, const QRectF &rect, qreal ratio,
|
||||
bool expand)
|
||||
{
|
||||
QLocale l(QLocale::system());
|
||||
QPainter p(printer);
|
||||
TrackInfo info;
|
||||
qreal ih, gh, mh, ratio;
|
||||
qreal ih, gh, mh;
|
||||
int sc;
|
||||
|
||||
|
||||
if (!_pathName.isNull() && _options.printName)
|
||||
@ -1138,54 +1197,92 @@ void GUI::plot(QPrinter *printer)
|
||||
if (movingTime() > 0 && _options.printMovingTime)
|
||||
info.insert(tr("Moving time"), Format::timeSpan(movingTime()));
|
||||
|
||||
qreal fsr = 1085.0 / (qMax(printer->width(), printer->height())
|
||||
/ (qreal)printer->resolution());
|
||||
ratio = p.paintEngine()->paintDevice()->logicalDpiX() / fsr;
|
||||
if (info.isEmpty()) {
|
||||
ih = 0;
|
||||
mh = 0;
|
||||
} else {
|
||||
ih = info.contentSize().height() * ratio;
|
||||
mh = ih / 2;
|
||||
info.plot(&p, QRectF(0, 0, printer->width(), ih), ratio);
|
||||
info.plot(painter, QRectF(rect.x(), rect.y(), rect.width(), ih), ratio);
|
||||
}
|
||||
if (_graphTabWidget->isVisible() && !_options.separateGraphPage) {
|
||||
qreal r = (((qreal)(printer)->width()) / (qreal)(printer->height()));
|
||||
gh = (printer->width() > printer->height())
|
||||
? 0.15 * r * (printer->height() - ih - 2*mh)
|
||||
: 0.15 * (printer->height() - ih - 2*mh);
|
||||
qreal r = rect.width() / rect.height();
|
||||
gh = (rect.width() > rect.height())
|
||||
? 0.15 * r * (rect.height() - ih - 2*mh)
|
||||
: 0.15 * (rect.height() - ih - 2*mh);
|
||||
if (gh < 150)
|
||||
gh = 150;
|
||||
sc = 2;
|
||||
GraphTab *gt = static_cast<GraphTab*>(_graphTabWidget->currentWidget());
|
||||
gt->plot(&p, QRectF(0, printer->height() - gh, printer->width(), gh),
|
||||
ratio);
|
||||
} else
|
||||
gt->plot(painter, QRectF(rect.x(), rect.y() + rect.height() - gh,
|
||||
rect.width(), gh), ratio);
|
||||
} else {
|
||||
gh = 0;
|
||||
_mapView->plot(&p, QRectF(0, ih + mh, printer->width(), printer->height()
|
||||
- (ih + 2*mh + gh)), ratio, _options.hiresPrint);
|
||||
sc = 1;
|
||||
}
|
||||
|
||||
if (_graphTabWidget->isVisible() && _options.separateGraphPage) {
|
||||
printer->newPage();
|
||||
MapView::PlotFlags flags = MapView::NoFlags;
|
||||
if (_options.hiresPrint)
|
||||
flags |= MapView::HiRes;
|
||||
if (expand)
|
||||
flags |= MapView::Expand;
|
||||
|
||||
int cnt = 0;
|
||||
for (int i = 0; i < _tabs.size(); i++)
|
||||
if (!_tabs.at(i)->isEmpty())
|
||||
cnt++;
|
||||
_mapView->plot(painter, QRectF(rect.x(), rect.y() + ih + mh, rect.width(),
|
||||
rect.height() - (ih + sc*mh + gh)), ratio, flags);
|
||||
}
|
||||
|
||||
qreal sp = ratio * 20;
|
||||
gh = qMin((printer->height() - ((cnt - 1) * sp))/(qreal)cnt,
|
||||
0.20 * printer->height());
|
||||
void GUI::plotGraphsPage(QPainter *painter, const QRectF &rect, qreal ratio)
|
||||
{
|
||||
int cnt = 0;
|
||||
for (int i = 0; i < _tabs.size(); i++)
|
||||
if (!_tabs.at(i)->isEmpty())
|
||||
cnt++;
|
||||
|
||||
qreal y = 0;
|
||||
for (int i = 0; i < _tabs.size(); i++) {
|
||||
if (!_tabs.at(i)->isEmpty()) {
|
||||
_tabs.at(i)->plot(&p, QRectF(0, y, printer->width(), gh),
|
||||
ratio);
|
||||
y += gh + sp;
|
||||
}
|
||||
qreal sp = ratio * 20;
|
||||
qreal gh = qMin((rect.height() - ((cnt - 1) * sp))/(qreal)cnt,
|
||||
0.20 * rect.height());
|
||||
|
||||
qreal y = 0;
|
||||
for (int i = 0; i < _tabs.size(); i++) {
|
||||
if (!_tabs.at(i)->isEmpty()) {
|
||||
_tabs.at(i)->plot(painter, QRectF(rect.x(), rect.y() + y,
|
||||
rect.width(), gh), ratio);
|
||||
y += gh + sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::reloadFile()
|
||||
qreal GUI::graphPlotHeight(const QRectF &rect, qreal ratio)
|
||||
{
|
||||
int cnt = 0;
|
||||
for (int i = 0; i < _tabs.size(); i++)
|
||||
if (!_tabs.at(i)->isEmpty())
|
||||
cnt++;
|
||||
|
||||
qreal sp = ratio * 20;
|
||||
qreal gh = qMin((rect.height() - ((cnt - 1) * sp))/(qreal)cnt,
|
||||
0.20 * rect.height());
|
||||
|
||||
return cnt * gh + (cnt - 1) * sp;
|
||||
}
|
||||
|
||||
void GUI::plot(QPrinter *printer)
|
||||
{
|
||||
QPainter p(printer);
|
||||
qreal fsr = 1085.0 / (qMax(printer->width(), printer->height())
|
||||
/ (qreal)printer->resolution());
|
||||
qreal ratio = p.paintEngine()->paintDevice()->logicalDpiX() / fsr;
|
||||
QRectF rect(0, 0, printer->width(), printer->height());
|
||||
|
||||
plotMainPage(&p, rect, ratio);
|
||||
|
||||
if (!_tabs.isEmpty() && _options.separateGraphPage) {
|
||||
printer->newPage();
|
||||
plotGraphsPage(&p, rect, ratio);
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::reloadFiles()
|
||||
{
|
||||
_trackCount = 0;
|
||||
_routeCount = 0;
|
||||
@ -1195,7 +1292,7 @@ void GUI::reloadFile()
|
||||
_routeDistance = 0;
|
||||
_time = 0;
|
||||
_movingTime = 0;
|
||||
_dateRange = DateRange(QDate(), QDate());
|
||||
_dateRange = DateTimeRange(QDateTime(), QDateTime());
|
||||
_pathName = QString();
|
||||
|
||||
for (int i = 0; i < _tabs.count(); i++)
|
||||
@ -1229,7 +1326,7 @@ void GUI::closeFiles()
|
||||
_routeDistance = 0;
|
||||
_time = 0;
|
||||
_movingTime = 0;
|
||||
_dateRange = DateRange(QDate(), QDate());
|
||||
_dateRange = DateTimeRange(QDateTime(), QDateTime());
|
||||
_pathName = QString();
|
||||
|
||||
_sliderPos = 0;
|
||||
@ -1539,8 +1636,7 @@ void GUI::setTimeType(TimeType type)
|
||||
|
||||
void GUI::setUnits(Units units)
|
||||
{
|
||||
_export.units = units;
|
||||
_options.units = units;
|
||||
_units = units;
|
||||
|
||||
_mapView->setUnits(units);
|
||||
for (int i = 0; i <_tabs.count(); i++)
|
||||
@ -1783,23 +1879,42 @@ void GUI::writeSettings()
|
||||
_showTicksAction->isChecked());
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup(EXPORT_SETTINGS_GROUP);
|
||||
if (_export.orientation != PAPER_ORIENTATION_DEFAULT)
|
||||
settings.setValue(PAPER_ORIENTATION_SETTING, _export.orientation);
|
||||
if (_export.resolution != RESOLUTION_DEFAULT)
|
||||
settings.setValue(RESOLUTION_SETTING, _export.resolution);
|
||||
if (_export.paperSize != PAPER_SIZE_DEFAULT)
|
||||
settings.setValue(PAPER_SIZE_SETTING, _export.paperSize);
|
||||
if (_export.margins.left() != MARGIN_LEFT_DEFAULT)
|
||||
settings.setValue(MARGIN_LEFT_SETTING, _export.margins.left());
|
||||
if (_export.margins.top() != MARGIN_TOP_DEFAULT)
|
||||
settings.setValue(MARGIN_TOP_SETTING, _export.margins.top());
|
||||
if (_export.margins.right() != MARGIN_RIGHT_DEFAULT)
|
||||
settings.setValue(MARGIN_RIGHT_SETTING, _export.margins.right());
|
||||
if (_export.margins.bottom() != MARGIN_BOTTOM_DEFAULT)
|
||||
settings.setValue(MARGIN_BOTTOM_SETTING, _export.margins.bottom());
|
||||
if (_export.fileName != EXPORT_FILENAME_DEFAULT)
|
||||
settings.setValue(EXPORT_FILENAME_SETTING, _export.fileName);
|
||||
settings.beginGroup(PDF_EXPORT_SETTINGS_GROUP);
|
||||
if (_pdfExport.orientation != PAPER_ORIENTATION_DEFAULT)
|
||||
settings.setValue(PAPER_ORIENTATION_SETTING, _pdfExport.orientation);
|
||||
if (_pdfExport.resolution != RESOLUTION_DEFAULT)
|
||||
settings.setValue(RESOLUTION_SETTING, _pdfExport.resolution);
|
||||
if (_pdfExport.paperSize != PAPER_SIZE_DEFAULT)
|
||||
settings.setValue(PAPER_SIZE_SETTING, _pdfExport.paperSize);
|
||||
if (_pdfExport.margins.left() != PDF_MARGIN_LEFT_DEFAULT)
|
||||
settings.setValue(PDF_MARGIN_LEFT_SETTING, _pdfExport.margins.left());
|
||||
if (_pdfExport.margins.top() != PDF_MARGIN_TOP_DEFAULT)
|
||||
settings.setValue(PDF_MARGIN_TOP_SETTING, _pdfExport.margins.top());
|
||||
if (_pdfExport.margins.right() != PDF_MARGIN_RIGHT_DEFAULT)
|
||||
settings.setValue(PDF_MARGIN_RIGHT_SETTING, _pdfExport.margins.right());
|
||||
if (_pdfExport.margins.bottom() != PDF_MARGIN_BOTTOM_DEFAULT)
|
||||
settings.setValue(PDF_MARGIN_BOTTOM_SETTING, _pdfExport.margins.bottom());
|
||||
if (_pdfExport.fileName != PDF_FILENAME_DEFAULT)
|
||||
settings.setValue(PDF_FILENAME_SETTING, _pdfExport.fileName);
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup(PNG_EXPORT_SETTINGS_GROUP);
|
||||
if (_pngExport.size.width() != PNG_WIDTH_DEFAULT)
|
||||
settings.setValue(PNG_WIDTH_SETTING, _pngExport.size.width());
|
||||
if (_pngExport.size.height() != PNG_HEIGHT_DEFAULT)
|
||||
settings.setValue(PNG_HEIGHT_SETTING, _pngExport.size.height());
|
||||
if (_pngExport.margins.left() != PNG_MARGIN_LEFT_DEFAULT)
|
||||
settings.setValue(PNG_MARGIN_LEFT_SETTING, _pngExport.margins.left());
|
||||
if (_pngExport.margins.top() != PNG_MARGIN_TOP_DEFAULT)
|
||||
settings.setValue(PNG_MARGIN_TOP_SETTING, _pngExport.margins.top());
|
||||
if (_pngExport.margins.right() != PNG_MARGIN_RIGHT_DEFAULT)
|
||||
settings.setValue(PNG_MARGIN_RIGHT_SETTING, _pngExport.margins.right());
|
||||
if (_pngExport.margins.bottom() != PNG_MARGIN_BOTTOM_DEFAULT)
|
||||
settings.setValue(PNG_MARGIN_BOTTOM_SETTING, _pngExport.margins.bottom());
|
||||
if (_pngExport.antialiasing != PNG_ANTIALIASING_DEFAULT)
|
||||
settings.setValue(PNG_ANTIALIASING_SETTING, _pngExport.antialiasing);
|
||||
if (_pngExport.fileName != PNG_FILENAME_DEFAULT)
|
||||
settings.setValue(PNG_FILENAME_SETTING, _pngExport.fileName);
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup(OPTIONS_SETTINGS_GROUP);
|
||||
@ -1867,6 +1982,13 @@ void GUI::writeSettings()
|
||||
if (_options.showSecondarySpeed != SHOW_SECONDARY_SPEED_DEFAULT)
|
||||
settings.setValue(SHOW_SECONDARY_SPEED_SETTING,
|
||||
_options.showSecondarySpeed);
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
if (_options.timeZone != TimeZoneInfo())
|
||||
settings.setValue(TIME_ZONE_SETTING, QVariant::fromValue(
|
||||
_options.timeZone));
|
||||
#endif // ENABLE_TIMEZONES
|
||||
if (_options.useSegments != USE_SEGMENTS_DEFAULT)
|
||||
settings.setValue(USE_SEGMENTS_SETTING, _options.useSegments);
|
||||
if (_options.poiRadius != POI_RADIUS_DEFAULT)
|
||||
settings.setValue(POI_RADIUS_SETTING, _options.poiRadius);
|
||||
if (_options.useOpenGL != USE_OPENGL_DEFAULT)
|
||||
@ -2058,23 +2180,42 @@ void GUI::readSettings()
|
||||
}
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup(EXPORT_SETTINGS_GROUP);
|
||||
_export.orientation = (QPrinter::Orientation) settings.value(
|
||||
settings.beginGroup(PDF_EXPORT_SETTINGS_GROUP);
|
||||
_pdfExport.orientation = (QPrinter::Orientation) settings.value(
|
||||
PAPER_ORIENTATION_SETTING, PAPER_ORIENTATION_DEFAULT).toInt();
|
||||
_export.resolution = settings.value(RESOLUTION_SETTING, RESOLUTION_DEFAULT)
|
||||
_pdfExport.resolution = settings.value(RESOLUTION_SETTING,
|
||||
RESOLUTION_DEFAULT).toInt();
|
||||
_pdfExport.paperSize = (QPrinter::PaperSize) settings.value(
|
||||
PAPER_SIZE_SETTING, PAPER_SIZE_DEFAULT).toInt();
|
||||
qreal ml = settings.value(PDF_MARGIN_LEFT_SETTING, PDF_MARGIN_LEFT_DEFAULT)
|
||||
.toReal();
|
||||
qreal mt = settings.value(PDF_MARGIN_TOP_SETTING, PDF_MARGIN_TOP_DEFAULT)
|
||||
.toReal();
|
||||
qreal mr = settings.value(PDF_MARGIN_RIGHT_SETTING,
|
||||
PDF_MARGIN_RIGHT_DEFAULT).toReal();
|
||||
qreal mb = settings.value(PDF_MARGIN_BOTTOM_SETTING,
|
||||
PDF_MARGIN_BOTTOM_DEFAULT).toReal();
|
||||
_pdfExport.margins = MarginsF(ml, mt, mr, mb);
|
||||
_pdfExport.fileName = settings.value(PDF_FILENAME_SETTING,
|
||||
PDF_FILENAME_DEFAULT).toString();
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup(PNG_EXPORT_SETTINGS_GROUP);
|
||||
_pngExport.size = QSize(settings.value(PNG_WIDTH_SETTING, PNG_WIDTH_DEFAULT)
|
||||
.toInt(), settings.value(PNG_HEIGHT_SETTING, PNG_HEIGHT_DEFAULT).toInt());
|
||||
int mli = settings.value(PNG_MARGIN_LEFT_SETTING, PNG_MARGIN_LEFT_DEFAULT)
|
||||
.toInt();
|
||||
_export.paperSize = (QPrinter::PaperSize) settings.value(PAPER_SIZE_SETTING,
|
||||
PAPER_SIZE_DEFAULT).toInt();
|
||||
qreal ml = settings.value(MARGIN_LEFT_SETTING, MARGIN_LEFT_DEFAULT)
|
||||
.toReal();
|
||||
qreal mt = settings.value(MARGIN_TOP_SETTING, MARGIN_TOP_DEFAULT).toReal();
|
||||
qreal mr = settings.value(MARGIN_RIGHT_SETTING, MARGIN_RIGHT_DEFAULT)
|
||||
.toReal();
|
||||
qreal mb = settings.value(MARGIN_BOTTOM_SETTING, MARGIN_BOTTOM_DEFAULT)
|
||||
.toReal();
|
||||
_export.margins = MarginsF(ml, mt, mr, mb);
|
||||
_export.fileName = settings.value(EXPORT_FILENAME_SETTING,
|
||||
EXPORT_FILENAME_DEFAULT).toString();
|
||||
int mti = settings.value(PNG_MARGIN_TOP_SETTING, PNG_MARGIN_TOP_DEFAULT)
|
||||
.toInt();
|
||||
int mri = settings.value(PNG_MARGIN_RIGHT_SETTING, PNG_MARGIN_RIGHT_DEFAULT)
|
||||
.toInt();
|
||||
int mbi = settings.value(PNG_MARGIN_BOTTOM_SETTING, PNG_MARGIN_BOTTOM_DEFAULT)
|
||||
.toInt();
|
||||
_pngExport.margins = QMargins(mli, mti, mri, mbi);
|
||||
_pngExport.antialiasing = settings.value(PNG_ANTIALIASING_SETTING,
|
||||
PNG_ANTIALIASING_DEFAULT).toBool();
|
||||
_pngExport.fileName = settings.value(PNG_FILENAME_SETTING,
|
||||
PNG_FILENAME_DEFAULT).toString();
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup(OPTIONS_SETTINGS_GROUP);
|
||||
@ -2139,6 +2280,11 @@ void GUI::readSettings()
|
||||
_options.showSecondarySpeed = settings.value(
|
||||
SHOW_SECONDARY_SPEED_SETTING,
|
||||
SHOW_SECONDARY_SPEED_DEFAULT).toBool();
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
_options.timeZone = settings.value(TIME_ZONE_SETTING).value<TimeZoneInfo>();
|
||||
#endif // ENABLE_TIMEZONES
|
||||
_options.useSegments = settings.value(USE_SEGMENTS_SETTING,
|
||||
USE_SEGMENTS_DEFAULT).toBool();
|
||||
_options.automaticPause = settings.value(AUTOMATIC_PAUSE_SETTING,
|
||||
AUTOMATIC_PAUSE_DEFAULT).toBool();
|
||||
_options.pauseInterval = settings.value(PAUSE_INTERVAL_SETTING,
|
||||
@ -2203,6 +2349,9 @@ void GUI::readSettings()
|
||||
_options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||
#endif // ENABLE_HIDPI
|
||||
_mapView->setProjection(_options.projection);
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
_mapView->setTimeZone(_options.timeZone.zone());
|
||||
#endif // ENABLE_TIMEZONES
|
||||
|
||||
for (int i = 0; i < _tabs.count(); i++) {
|
||||
_tabs.at(i)->setPalette(_options.palette);
|
||||
@ -2227,6 +2376,7 @@ void GUI::readSettings()
|
||||
Track::useDEM(_options.dataUseDEM);
|
||||
Track::showSecondaryElevation(_options.showSecondaryElevation);
|
||||
Track::showSecondarySpeed(_options.showSecondarySpeed);
|
||||
Track::useSegments(_options.useSegments);
|
||||
Route::useDEM(_options.dataUseDEM);
|
||||
Route::showSecondaryElevation(_options.showSecondaryElevation);
|
||||
Waypoint::useDEM(_options.dataUseDEM);
|
||||
|
@ -10,7 +10,8 @@
|
||||
#include "units.h"
|
||||
#include "timetype.h"
|
||||
#include "format.h"
|
||||
#include "exportdialog.h"
|
||||
#include "pdfexportdialog.h"
|
||||
#include "pngexportdialog.h"
|
||||
#include "optionsdialog.h"
|
||||
|
||||
class QMenu;
|
||||
@ -45,10 +46,11 @@ private slots:
|
||||
void keys();
|
||||
void paths();
|
||||
void printFile();
|
||||
void exportFile();
|
||||
void exportPDFFile();
|
||||
void exportPNGFile();
|
||||
void openFile();
|
||||
void closeAll();
|
||||
void reloadFile();
|
||||
void reloadFiles();
|
||||
void statistics();
|
||||
void openPOIFile();
|
||||
void closePOIFiles();
|
||||
@ -92,11 +94,15 @@ private slots:
|
||||
void mapInitialized();
|
||||
|
||||
private:
|
||||
typedef QPair<QDate, QDate> DateRange;
|
||||
typedef QPair<QDateTime, QDateTime> DateTimeRange;
|
||||
|
||||
void loadPOIs();
|
||||
void closeFiles();
|
||||
void plot(QPrinter *printer);
|
||||
void plotMainPage(QPainter *painter, const QRectF &rect, qreal ratio,
|
||||
bool expand = false);
|
||||
void plotGraphsPage(QPainter *painter, const QRectF &rect, qreal ratio);
|
||||
qreal graphPlotHeight(const QRectF &rect, qreal ratio);
|
||||
|
||||
QAction *createPOIFileAction(const QString &fileName);
|
||||
MapAction *createMapAction(Map *map);
|
||||
@ -113,7 +119,6 @@ private:
|
||||
bool openPOIFile(const QString &fileName);
|
||||
bool loadFile(const QString &fileName);
|
||||
bool loadMap(const QString &fileName);
|
||||
void exportFile(const QString &fileName);
|
||||
void updateStatusBarInfo();
|
||||
void updateWindowTitle();
|
||||
void updateNavigationActions();
|
||||
@ -153,7 +158,8 @@ private:
|
||||
QAction *_aboutAction;
|
||||
QAction *_aboutQtAction;
|
||||
QAction *_printFileAction;
|
||||
QAction *_exportFileAction;
|
||||
QAction *_exportPDFFileAction;
|
||||
QAction *_exportPNGFileAction;
|
||||
QAction *_openFileAction;
|
||||
QAction *_closeFileAction;
|
||||
QAction *_reloadFileAction;
|
||||
@ -220,7 +226,7 @@ private:
|
||||
int _trackCount, _routeCount, _areaCount, _waypointCount;
|
||||
qreal _trackDistance, _routeDistance;
|
||||
qreal _time, _movingTime;
|
||||
DateRange _dateRange;
|
||||
DateTimeRange _dateRange;
|
||||
QString _pathName;
|
||||
|
||||
qreal _sliderPos;
|
||||
@ -228,10 +234,13 @@ private:
|
||||
QList<QByteArray> _windowStates;
|
||||
int _frameStyle;
|
||||
|
||||
Export _export;
|
||||
PDFExport _pdfExport;
|
||||
PNGExport _pngExport;
|
||||
Options _options;
|
||||
|
||||
QString _dataDir, _mapDir, _poiDir;
|
||||
|
||||
Units _units;
|
||||
};
|
||||
|
||||
#endif // GUI_H
|
||||
|
@ -18,7 +18,8 @@
|
||||
#define OPEN_SHORTCUT QKeySequence(QKeySequence::Open)
|
||||
#define CLOSE_SHORTCUT QKeySequence(QKeySequence::Close)
|
||||
#define RELOAD_SHORTCUT QKeySequence(QKeySequence::Refresh)
|
||||
#define EXPORT_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_E)
|
||||
#define PDF_EXPORT_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_E)
|
||||
#define PNG_EXPORT_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_X)
|
||||
#define SHOW_POI_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_P)
|
||||
#define SHOW_MAP_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_M)
|
||||
#define NEXT_MAP_SHORTCUT QKeySequence(QKeySequence::Forward)
|
||||
|
@ -59,8 +59,6 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
|
||||
_poi = poi;
|
||||
connect(_poi, SIGNAL(pointsChanged()), this, SLOT(updatePOI()));
|
||||
|
||||
_units = Metric;
|
||||
_coordinatesFormat = DecimalDegrees;
|
||||
_mapOpacity = 1.0;
|
||||
_backgroundColor = Qt::white;
|
||||
_markerColor = Qt::red;
|
||||
@ -122,7 +120,6 @@ PathItem *MapView::addTrack(const Track &track)
|
||||
ti->setColor(_palette.nextColor());
|
||||
ti->setWidth(_trackWidth);
|
||||
ti->setStyle(_trackStyle);
|
||||
ti->setUnits(_units);
|
||||
ti->setVisible(_showTracks);
|
||||
ti->setDigitalZoom(_digitalZoom);
|
||||
ti->setMarkerColor(_markerColor);
|
||||
@ -149,8 +146,6 @@ PathItem *MapView::addRoute(const Route &route)
|
||||
ri->setColor(_palette.nextColor());
|
||||
ri->setWidth(_routeWidth);
|
||||
ri->setStyle(_routeStyle);
|
||||
ri->setUnits(_units);
|
||||
ri->setCoordinatesFormat(_coordinatesFormat);
|
||||
ri->setVisible(_showRoutes);
|
||||
ri->showWaypoints(_showRouteWaypoints);
|
||||
ri->showWaypointLabels(_showWaypointLabels);
|
||||
@ -200,7 +195,6 @@ void MapView::addWaypoints(const QVector<Waypoint> &waypoints)
|
||||
wi->setSize(_waypointSize);
|
||||
wi->setColor(_waypointColor);
|
||||
wi->showLabel(_showWaypointLabels);
|
||||
wi->setToolTipFormat(_units, _coordinatesFormat);
|
||||
wi->setVisible(_showWaypoints);
|
||||
wi->setDigitalZoom(_digitalZoom);
|
||||
_scene->addItem(wi);
|
||||
@ -401,7 +395,6 @@ void MapView::addPOI(const QList<Waypoint> &waypoints)
|
||||
pi->showLabel(_showPOILabels);
|
||||
pi->setVisible(_showPOI);
|
||||
pi->setDigitalZoom(_digitalZoom);
|
||||
pi->setToolTipFormat(_units, _coordinatesFormat);
|
||||
_scene->addItem(pi);
|
||||
|
||||
_pois.insert(SearchPointer<Waypoint>(&(pi->waypoint())), pi);
|
||||
@ -410,42 +403,32 @@ void MapView::addPOI(const QList<Waypoint> &waypoints)
|
||||
|
||||
void MapView::setUnits(Units units)
|
||||
{
|
||||
if (_units == units)
|
||||
return;
|
||||
|
||||
_units = units;
|
||||
|
||||
_mapScale->setUnits(_units);
|
||||
WaypointItem::setUnits(units);
|
||||
PathItem::setUnits(units);
|
||||
|
||||
for (int i = 0; i < _tracks.count(); i++)
|
||||
_tracks[i]->setUnits(_units);
|
||||
_tracks[i]->updateTicks();
|
||||
for (int i = 0; i < _routes.count(); i++)
|
||||
_routes[i]->setUnits(_units);
|
||||
for (int i = 0; i < _waypoints.size(); i++)
|
||||
_waypoints.at(i)->setToolTipFormat(_units, _coordinatesFormat);
|
||||
_routes[i]->updateTicks();
|
||||
|
||||
for (POIHash::const_iterator it = _pois.constBegin();
|
||||
it != _pois.constEnd(); it++)
|
||||
it.value()->setToolTipFormat(_units, _coordinatesFormat);
|
||||
_mapScale->setUnits(units);
|
||||
}
|
||||
|
||||
void MapView::setCoordinatesFormat(CoordinatesFormat format)
|
||||
{
|
||||
if (_coordinatesFormat == format)
|
||||
return;
|
||||
WaypointItem::setCoordinatesFormat(format);
|
||||
|
||||
_coordinatesFormat = format;
|
||||
_coordinates->setFormat(format);
|
||||
}
|
||||
|
||||
_coordinates->setFormat(_coordinatesFormat);
|
||||
|
||||
for (int i = 0; i < _waypoints.count(); i++)
|
||||
_waypoints.at(i)->setToolTipFormat(_units, _coordinatesFormat);
|
||||
for (int i = 0; i < _routes.count(); i++)
|
||||
_routes[i]->setCoordinatesFormat(_coordinatesFormat);
|
||||
|
||||
for (POIHash::const_iterator it = _pois.constBegin();
|
||||
it != _pois.constEnd(); it++)
|
||||
it.value()->setToolTipFormat(_units, _coordinatesFormat);
|
||||
void MapView::setTimeZone(const QTimeZone &zone)
|
||||
{
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
WaypointItem::setTimeZone(zone);
|
||||
PathItem::setTimeZone(zone);
|
||||
#else // ENABLE_TIMEZONES
|
||||
Q_UNUSED(zone);
|
||||
#endif // ENABLE_TIMEZONES
|
||||
}
|
||||
|
||||
void MapView::clearMapCache()
|
||||
@ -548,7 +531,7 @@ void MapView::keyPressEvent(QKeyEvent *event)
|
||||
}
|
||||
|
||||
void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||
bool hires)
|
||||
PlotFlags flags)
|
||||
{
|
||||
QRect orig, adj;
|
||||
qreal ratio, diff, q;
|
||||
@ -576,10 +559,18 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||
diff = (orig.height() * ratio) - orig.width();
|
||||
adj = orig.adjusted(-diff/2, 0, diff/2, 0);
|
||||
}
|
||||
q = (target.width() / scale) / adj.width();
|
||||
|
||||
// Expand the view if plotting into a bitmap
|
||||
if (flags & Expand) {
|
||||
qreal xdiff = (target.width() - adj.width()) / 2.0;
|
||||
qreal ydiff = (target.height() - adj.height()) / 2.0;
|
||||
adj.adjust(-xdiff, -ydiff, xdiff, ydiff);
|
||||
q = 1.0;
|
||||
} else
|
||||
q = (target.width() / scale) / adj.width();
|
||||
|
||||
// Adjust the view for printing
|
||||
if (hires) {
|
||||
if (flags & HiRes) {
|
||||
zoom = _map->zoom();
|
||||
QRectF vr(mapToScene(orig).boundingRect());
|
||||
origScene = vr.center();
|
||||
@ -611,7 +602,7 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||
render(painter, target, adj);
|
||||
|
||||
// Revert view changes to display mode
|
||||
if (hires) {
|
||||
if (flags & HiRes) {
|
||||
_map->setZoom(zoom);
|
||||
rescale();
|
||||
centerOn(origScene);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <QVector>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QFlags>
|
||||
#include "common/rectc.h"
|
||||
#include "common/config.h"
|
||||
#include "data/waypoint.h"
|
||||
@ -31,12 +32,20 @@ class GraphItem;
|
||||
class AreaItem;
|
||||
class Area;
|
||||
class GraphicsScene;
|
||||
class QTimeZone;
|
||||
|
||||
class MapView : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Flag {
|
||||
NoFlags = 0,
|
||||
HiRes = 1,
|
||||
Expand = 2
|
||||
};
|
||||
Q_DECLARE_FLAGS(PlotFlags, Flag)
|
||||
|
||||
MapView(Map *map, POI *poi, QWidget *parent = 0);
|
||||
|
||||
QList<PathItem *> loadData(const Data &data);
|
||||
@ -45,7 +54,8 @@ public:
|
||||
void setPOI(POI *poi);
|
||||
void setMap(Map *map);
|
||||
|
||||
void plot(QPainter *painter, const QRectF &target, qreal scale, bool hires);
|
||||
void plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||
PlotFlags flags);
|
||||
|
||||
void clear();
|
||||
|
||||
@ -83,6 +93,7 @@ public slots:
|
||||
void showTicks(bool show);
|
||||
void clearMapCache();
|
||||
void setCoordinatesFormat(CoordinatesFormat format);
|
||||
void setTimeZone(const QTimeZone &zone);
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
void setProjection(int id);
|
||||
|
||||
@ -137,8 +148,6 @@ private:
|
||||
POI *_poi;
|
||||
|
||||
Palette _palette;
|
||||
Units _units;
|
||||
CoordinatesFormat _coordinatesFormat;
|
||||
qreal _mapOpacity;
|
||||
Projection _projection;
|
||||
|
||||
|
@ -16,15 +16,22 @@ public:
|
||||
qreal right() const {return _right;}
|
||||
qreal bottom() const {return _bottom;}
|
||||
|
||||
qreal &rleft() {return _left;}
|
||||
qreal &rtop() {return _top;}
|
||||
qreal &rright() {return _right;}
|
||||
qreal &rbottom() {return _bottom;}
|
||||
|
||||
private:
|
||||
qreal _left, _top, _right, _bottom;
|
||||
};
|
||||
|
||||
inline MarginsF operator*(const MarginsF &margins, qreal factor)
|
||||
{
|
||||
return MarginsF(margins.left() * factor, margins.top() * factor,
|
||||
margins.right() * factor, margins.bottom() * factor);
|
||||
}
|
||||
|
||||
inline MarginsF operator/(const MarginsF &margins, qreal factor)
|
||||
{
|
||||
return MarginsF(margins.left() / factor, margins.top() / factor,
|
||||
margins.right() / factor, margins.bottom() / factor);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const MarginsF &margins)
|
||||
{
|
||||
|
111
src/GUI/marginswidget.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
#include <QSpinBox>
|
||||
#include <QGridLayout>
|
||||
#include "units.h"
|
||||
#include "marginswidget.h"
|
||||
|
||||
MarginsWidget::MarginsWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
_top = new QSpinBox();
|
||||
_bottom = new QSpinBox();
|
||||
_left = new QSpinBox();
|
||||
_right = new QSpinBox();
|
||||
|
||||
_top->setMaximumWidth(_top->sizeHint().width());
|
||||
_bottom->setMaximumWidth(_bottom->sizeHint().width());
|
||||
_left->setMaximumWidth(_left->sizeHint().width());
|
||||
_right->setMaximumWidth(_right->sizeHint().width());
|
||||
|
||||
QGridLayout *layout = new QGridLayout();
|
||||
layout->addWidget(_top, 0, 0, 1, 2, Qt::AlignCenter);
|
||||
layout->addWidget(_left, 1, 0, 1, 1, Qt::AlignRight);
|
||||
layout->addWidget(_right, 1, 1, 1, 1, Qt::AlignLeft);
|
||||
layout->addWidget(_bottom, 2, 0, 1, 2, Qt::AlignCenter);
|
||||
|
||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void MarginsWidget::setValue(const QMargins &value)
|
||||
{
|
||||
_top->setValue(value.top());
|
||||
_bottom->setValue(value.bottom());
|
||||
_left->setValue(value.left());
|
||||
_right->setValue(value.right());
|
||||
}
|
||||
|
||||
void MarginsWidget::setUnits(const QString &units)
|
||||
{
|
||||
_top->setSuffix(UNIT_SPACE + units);
|
||||
_bottom->setSuffix(UNIT_SPACE + units);
|
||||
_left->setSuffix(UNIT_SPACE + units);
|
||||
_right->setSuffix(UNIT_SPACE + units);
|
||||
|
||||
_top->setMaximumWidth(_top->sizeHint().width());
|
||||
_bottom->setMaximumWidth(_bottom->sizeHint().width());
|
||||
_left->setMaximumWidth(_left->sizeHint().width());
|
||||
_right->setMaximumWidth(_right->sizeHint().width());
|
||||
}
|
||||
|
||||
QMargins MarginsWidget::value() const
|
||||
{
|
||||
return QMargins(_left->value(), _top->value(), _right->value(),
|
||||
_bottom->value());
|
||||
}
|
||||
|
||||
|
||||
MarginsFWidget::MarginsFWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
_top = new QDoubleSpinBox();
|
||||
_bottom = new QDoubleSpinBox();
|
||||
_left = new QDoubleSpinBox();
|
||||
_right = new QDoubleSpinBox();
|
||||
|
||||
_top->setMaximumWidth(_top->sizeHint().width());
|
||||
_bottom->setMaximumWidth(_bottom->sizeHint().width());
|
||||
_left->setMaximumWidth(_left->sizeHint().width());
|
||||
_right->setMaximumWidth(_right->sizeHint().width());
|
||||
|
||||
QGridLayout *layout = new QGridLayout();
|
||||
layout->addWidget(_top, 0, 0, 1, 2, Qt::AlignCenter);
|
||||
layout->addWidget(_left, 1, 0, 1, 1, Qt::AlignRight);
|
||||
layout->addWidget(_right, 1, 1, 1, 1, Qt::AlignLeft);
|
||||
layout->addWidget(_bottom, 2, 0, 1, 2, Qt::AlignCenter);
|
||||
|
||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void MarginsFWidget::setValue(const MarginsF &value)
|
||||
{
|
||||
_top->setValue(value.top());
|
||||
_bottom->setValue(value.bottom());
|
||||
_left->setValue(value.left());
|
||||
_right->setValue(value.right());
|
||||
}
|
||||
|
||||
void MarginsFWidget::setUnits(const QString &units)
|
||||
{
|
||||
_top->setSuffix(UNIT_SPACE + units);
|
||||
_bottom->setSuffix(UNIT_SPACE + units);
|
||||
_left->setSuffix(UNIT_SPACE + units);
|
||||
_right->setSuffix(UNIT_SPACE + units);
|
||||
|
||||
_top->setMaximumWidth(_top->sizeHint().width());
|
||||
_bottom->setMaximumWidth(_bottom->sizeHint().width());
|
||||
_left->setMaximumWidth(_left->sizeHint().width());
|
||||
_right->setMaximumWidth(_right->sizeHint().width());
|
||||
}
|
||||
|
||||
void MarginsFWidget::setSingleStep(qreal step)
|
||||
{
|
||||
_top->setSingleStep(step);
|
||||
_bottom->setSingleStep(step);
|
||||
_left->setSingleStep(step);
|
||||
_right->setSingleStep(step);
|
||||
}
|
||||
|
||||
MarginsF MarginsFWidget::value() const
|
||||
{
|
||||
return MarginsF(_left->value(), _top->value(), _right->value(),
|
||||
_bottom->value());
|
||||
}
|
48
src/GUI/marginswidget.h
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef MARGINSWIDGET_H
|
||||
#define MARGINSWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMargins>
|
||||
#include "margins.h"
|
||||
|
||||
class QSpinBox;
|
||||
class QDoubleSpinBox;
|
||||
|
||||
class MarginsWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MarginsWidget(QWidget *parent = 0);
|
||||
|
||||
QMargins value() const;
|
||||
void setValue(const QMargins &value);
|
||||
void setUnits(const QString &units);
|
||||
|
||||
private:
|
||||
QSpinBox *_top;
|
||||
QSpinBox *_bottom;
|
||||
QSpinBox *_left;
|
||||
QSpinBox *_right;
|
||||
};
|
||||
|
||||
class MarginsFWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MarginsFWidget(QWidget *parent = 0);
|
||||
|
||||
MarginsF value() const;
|
||||
void setValue(const MarginsF &value);
|
||||
void setUnits(const QString &units);
|
||||
void setSingleStep(qreal step);
|
||||
|
||||
private:
|
||||
QDoubleSpinBox *_top;
|
||||
QDoubleSpinBox *_bottom;
|
||||
QDoubleSpinBox *_left;
|
||||
QDoubleSpinBox *_right;
|
||||
};
|
||||
|
||||
#endif // MARGINSWIDGET_H
|
@ -56,12 +56,12 @@ QWidget *OptionsDialog::createMapPage()
|
||||
+ projections.at(i).value();
|
||||
_projection->addItem(text, QVariant(projections.at(i).key()));
|
||||
}
|
||||
_projection->setCurrentIndex(_projection->findData(_options->projection));
|
||||
_projection->setCurrentIndex(_projection->findData(_options.projection));
|
||||
|
||||
#ifdef ENABLE_HIDPI
|
||||
_hidpi = new QRadioButton(tr("High-resolution"));
|
||||
_lodpi = new QRadioButton(tr("Standard"));
|
||||
if (_options->hidpiMap)
|
||||
if (_options.hidpiMap)
|
||||
_hidpi->setChecked(true);
|
||||
else
|
||||
_lodpi->setChecked(true);
|
||||
@ -112,10 +112,10 @@ QWidget *OptionsDialog::createAppearancePage()
|
||||
{
|
||||
// Tracks
|
||||
_trackWidth = new QSpinBox();
|
||||
_trackWidth->setValue(_options->trackWidth);
|
||||
_trackWidth->setValue(_options.trackWidth);
|
||||
_trackWidth->setMinimum(1);
|
||||
_trackStyle = new StyleComboBox();
|
||||
_trackStyle->setValue(_options->trackStyle);
|
||||
_trackStyle->setValue(_options.trackStyle);
|
||||
QFormLayout *trackLayout = new QFormLayout();
|
||||
#ifdef Q_OS_MAC
|
||||
trackLayout->addRow(tr("Track width:"), _trackWidth);
|
||||
@ -129,10 +129,10 @@ QWidget *OptionsDialog::createAppearancePage()
|
||||
|
||||
// Routes
|
||||
_routeWidth = new QSpinBox();
|
||||
_routeWidth->setValue(_options->routeWidth);
|
||||
_routeWidth->setValue(_options.routeWidth);
|
||||
_routeWidth->setMinimum(1);
|
||||
_routeStyle = new StyleComboBox();
|
||||
_routeStyle->setValue(_options->routeStyle);
|
||||
_routeStyle->setValue(_options.routeStyle);
|
||||
QFormLayout *routeLayout = new QFormLayout();
|
||||
#ifdef Q_OS_MAC
|
||||
routeLayout->addRow(tr("Route width:"), _routeWidth);
|
||||
@ -146,11 +146,11 @@ QWidget *OptionsDialog::createAppearancePage()
|
||||
|
||||
// Areas
|
||||
_areaWidth = new QSpinBox();
|
||||
_areaWidth->setValue(_options->areaWidth);
|
||||
_areaWidth->setValue(_options.areaWidth);
|
||||
_areaStyle = new StyleComboBox();
|
||||
_areaStyle->setValue(_options->areaStyle);
|
||||
_areaStyle->setValue(_options.areaStyle);
|
||||
_areaOpacity = new PercentSlider();
|
||||
_areaOpacity->setValue(_options->areaOpacity);
|
||||
_areaOpacity->setValue(_options.areaOpacity);
|
||||
QFormLayout *areaLayout = new QFormLayout();
|
||||
#ifdef Q_OS_MAC
|
||||
areaLayout->addRow(tr("Area border width:"), _areaWidth);
|
||||
@ -166,18 +166,15 @@ QWidget *OptionsDialog::createAppearancePage()
|
||||
|
||||
// Palette & antialiasing
|
||||
_baseColor = new ColorBox();
|
||||
_baseColor->setColor(_options->palette.color());
|
||||
_colorOffset = new QDoubleSpinBox();
|
||||
_colorOffset->setMinimum(0);
|
||||
_colorOffset->setMaximum(1.0);
|
||||
_colorOffset->setSingleStep(0.01);
|
||||
_colorOffset->setValue(_options->palette.shift());
|
||||
_baseColor->setColor(_options.palette.color());
|
||||
_colorOffset = new PercentSlider();
|
||||
_colorOffset->setValue(_options.palette.shift() * 100);
|
||||
QFormLayout *paletteLayout = new QFormLayout();
|
||||
paletteLayout->addRow(tr("Base color:"), _baseColor);
|
||||
paletteLayout->addRow(tr("Palette shift:"), _colorOffset);
|
||||
|
||||
_pathAA = new QCheckBox(tr("Use anti-aliasing"));
|
||||
_pathAA->setChecked(_options->pathAntiAliasing);
|
||||
_pathAA->setChecked(_options.pathAntiAliasing);
|
||||
QFormLayout *pathAALayout = new QFormLayout();
|
||||
pathAALayout->addWidget(_pathAA);
|
||||
|
||||
@ -204,9 +201,9 @@ QWidget *OptionsDialog::createAppearancePage()
|
||||
// Waypoints
|
||||
_waypointSize = new QSpinBox();
|
||||
_waypointSize->setMinimum(1);
|
||||
_waypointSize->setValue(_options->waypointSize);
|
||||
_waypointSize->setValue(_options.waypointSize);
|
||||
_waypointColor = new ColorBox();
|
||||
_waypointColor->setColor(_options->waypointColor);
|
||||
_waypointColor->setColor(_options.waypointColor);
|
||||
QFormLayout *waypointLayout = new QFormLayout();
|
||||
#ifdef Q_OS_MAC
|
||||
waypointLayout->addRow(tr("Waypoint color:"), _waypointColor);
|
||||
@ -220,9 +217,9 @@ QWidget *OptionsDialog::createAppearancePage()
|
||||
|
||||
_poiSize = new QSpinBox();
|
||||
_poiSize->setMinimum(1);
|
||||
_poiSize->setValue(_options->poiSize);
|
||||
_poiSize->setValue(_options.poiSize);
|
||||
_poiColor = new ColorBox();
|
||||
_poiColor->setColor(_options->poiColor);
|
||||
_poiColor->setColor(_options.poiColor);
|
||||
QFormLayout *poiLayout = new QFormLayout();
|
||||
#ifdef Q_OS_MAC
|
||||
poiLayout->addRow(tr("POI color:"), _poiColor);
|
||||
@ -250,9 +247,9 @@ QWidget *OptionsDialog::createAppearancePage()
|
||||
|
||||
// Graphs
|
||||
_sliderColor = new ColorBox();
|
||||
_sliderColor->setColor(_options->sliderColor);
|
||||
_sliderColor->setColor(_options.sliderColor);
|
||||
_graphWidth = new QSpinBox();
|
||||
_graphWidth->setValue(_options->graphWidth);
|
||||
_graphWidth->setValue(_options.graphWidth);
|
||||
_graphWidth->setMinimum(1);
|
||||
|
||||
QFormLayout *graphLayout = new QFormLayout();
|
||||
@ -260,7 +257,7 @@ QWidget *OptionsDialog::createAppearancePage()
|
||||
graphLayout->addRow(tr("Slider color:"), _sliderColor);
|
||||
|
||||
_graphAA = new QCheckBox(tr("Use anti-aliasing"));
|
||||
_graphAA->setChecked(_options->graphAntiAliasing);
|
||||
_graphAA->setChecked(_options.graphAntiAliasing);
|
||||
QFormLayout *graphAALayout = new QFormLayout();
|
||||
graphAALayout->addWidget(_graphAA);
|
||||
|
||||
@ -274,9 +271,9 @@ QWidget *OptionsDialog::createAppearancePage()
|
||||
|
||||
// Map
|
||||
_mapOpacity = new PercentSlider();
|
||||
_mapOpacity->setValue(_options->mapOpacity);
|
||||
_mapOpacity->setValue(_options.mapOpacity);
|
||||
_backgroundColor = new ColorBox();
|
||||
_backgroundColor->setColor(_options->backgroundColor);
|
||||
_backgroundColor->setColor(_options.backgroundColor);
|
||||
_backgroundColor->enableAlphaChannel(false);
|
||||
|
||||
QFormLayout *mapLayout = new QFormLayout();
|
||||
@ -304,19 +301,19 @@ QWidget *OptionsDialog::createDataPage()
|
||||
QString filterToolTip = tr("Moving average window size");
|
||||
|
||||
_elevationFilter = new OddSpinBox();
|
||||
_elevationFilter->setValue(_options->elevationFilter);
|
||||
_elevationFilter->setValue(_options.elevationFilter);
|
||||
_elevationFilter->setToolTip(filterToolTip);
|
||||
_speedFilter = new OddSpinBox();
|
||||
_speedFilter->setValue(_options->speedFilter);
|
||||
_speedFilter->setValue(_options.speedFilter);
|
||||
_speedFilter->setToolTip(filterToolTip);
|
||||
_heartRateFilter = new OddSpinBox();
|
||||
_heartRateFilter->setValue(_options->heartRateFilter);
|
||||
_heartRateFilter->setValue(_options.heartRateFilter);
|
||||
_heartRateFilter->setToolTip(filterToolTip);
|
||||
_cadenceFilter = new OddSpinBox();
|
||||
_cadenceFilter->setValue(_options->cadenceFilter);
|
||||
_cadenceFilter->setValue(_options.cadenceFilter);
|
||||
_cadenceFilter->setToolTip(filterToolTip);
|
||||
_powerFilter = new OddSpinBox();
|
||||
_powerFilter->setValue(_options->powerFilter);
|
||||
_powerFilter->setValue(_options.powerFilter);
|
||||
_powerFilter->setToolTip(filterToolTip);
|
||||
|
||||
QFormLayout *smoothLayout = new QFormLayout();
|
||||
@ -331,7 +328,7 @@ QWidget *OptionsDialog::createDataPage()
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
_outlierEliminate = new QCheckBox(tr("Eliminate GPS outliers"));
|
||||
_outlierEliminate->setChecked(_options->outlierEliminate);
|
||||
_outlierEliminate->setChecked(_options.outlierEliminate);
|
||||
|
||||
QFormLayout *outlierLayout = new QFormLayout();
|
||||
outlierLayout->addWidget(_outlierEliminate);
|
||||
@ -352,7 +349,7 @@ QWidget *OptionsDialog::createDataPage()
|
||||
|
||||
_automaticPause = new QRadioButton(tr("Automatic"));
|
||||
_manualPause = new QRadioButton(tr("Custom"));
|
||||
if (_options->automaticPause)
|
||||
if (_options.automaticPause)
|
||||
_automaticPause->setChecked(true);
|
||||
else
|
||||
_manualPause->setChecked(true);
|
||||
@ -362,20 +359,20 @@ QWidget *OptionsDialog::createDataPage()
|
||||
_pauseSpeed->setSingleStep(0.1);
|
||||
_pauseSpeed->setMinimum(0.1);
|
||||
_pauseSpeed->setEnabled(_manualPause->isChecked());
|
||||
if (_options->units == Imperial) {
|
||||
_pauseSpeed->setValue(_options->pauseSpeed * MS2MIH);
|
||||
if (_units == Imperial) {
|
||||
_pauseSpeed->setValue(_options.pauseSpeed * MS2MIH);
|
||||
_pauseSpeed->setSuffix(UNIT_SPACE + tr("mi/h"));
|
||||
} else if (_options->units == Nautical) {
|
||||
_pauseSpeed->setValue(_options->pauseSpeed * MS2KN);
|
||||
} else if (_units == Nautical) {
|
||||
_pauseSpeed->setValue(_options.pauseSpeed * MS2KN);
|
||||
_pauseSpeed->setSuffix(UNIT_SPACE + tr("kn"));
|
||||
} else {
|
||||
_pauseSpeed->setValue(_options->pauseSpeed * MS2KMH);
|
||||
_pauseSpeed->setValue(_options.pauseSpeed * MS2KMH);
|
||||
_pauseSpeed->setSuffix(UNIT_SPACE + tr("km/h"));
|
||||
}
|
||||
_pauseInterval = new QSpinBox();
|
||||
_pauseInterval->setMinimum(1);
|
||||
_pauseInterval->setSuffix(UNIT_SPACE + tr("s"));
|
||||
_pauseInterval->setValue(_options->pauseInterval);
|
||||
_pauseInterval->setValue(_options.pauseInterval);
|
||||
_pauseInterval->setEnabled(_manualPause->isChecked());
|
||||
|
||||
connect(_automaticPause, SIGNAL(toggled(bool)), this,
|
||||
@ -403,21 +400,47 @@ QWidget *OptionsDialog::createDataPage()
|
||||
|
||||
_computedSpeed = new QRadioButton(tr("Computed from distance/time"));
|
||||
_reportedSpeed = new QRadioButton(tr("Recorded by device"));
|
||||
if (_options->useReportedSpeed)
|
||||
if (_options.useReportedSpeed)
|
||||
_reportedSpeed->setChecked(true);
|
||||
else
|
||||
_computedSpeed->setChecked(true);
|
||||
_showSecondarySpeed = new QCheckBox(tr("Show secondary speed"));
|
||||
_showSecondarySpeed->setChecked(_options->showSecondarySpeed);
|
||||
_showSecondarySpeed->setChecked(_options.showSecondarySpeed);
|
||||
|
||||
_dataGPSElevation = new QRadioButton(tr("GPS data"));
|
||||
_dataDEMElevation = new QRadioButton(tr("DEM data"));
|
||||
if (_options->dataUseDEM)
|
||||
if (_options.dataUseDEM)
|
||||
_dataDEMElevation->setChecked(true);
|
||||
else
|
||||
_dataGPSElevation->setChecked(true);
|
||||
_showSecondaryElevation = new QCheckBox(tr("Show secondary elevation"));
|
||||
_showSecondaryElevation->setChecked(_options->showSecondaryElevation);
|
||||
_showSecondaryElevation->setChecked(_options.showSecondaryElevation);
|
||||
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
_utcZone = new QRadioButton(tr("UTC"));
|
||||
_systemZone = new QRadioButton(tr("System"));
|
||||
_customZone = new QRadioButton(tr("Custom"));
|
||||
if (_options.timeZone.type() == TimeZoneInfo::UTC)
|
||||
_utcZone->setChecked(true);
|
||||
else if (_options.timeZone.type() == TimeZoneInfo::System)
|
||||
_systemZone->setChecked(true);
|
||||
else
|
||||
_customZone->setChecked(true);
|
||||
_timeZone = new QComboBox();
|
||||
_timeZone->setEnabled(_customZone->isChecked());
|
||||
QList<QByteArray> zones = QTimeZone::availableTimeZoneIds();
|
||||
for (int i = 0; i < zones.size(); i++)
|
||||
_timeZone->addItem(zones.at(i));
|
||||
_timeZone->setCurrentText(_options.timeZone.customZone().id());
|
||||
connect(_customZone, SIGNAL(toggled(bool)), _timeZone,
|
||||
SLOT(setEnabled(bool)));
|
||||
QHBoxLayout *customZoneLayout = new QHBoxLayout();
|
||||
customZoneLayout->addSpacing(20);
|
||||
customZoneLayout->addWidget(_timeZone);
|
||||
#endif // ENABLE_TIMEZONES
|
||||
|
||||
_useSegments = new QCheckBox(tr("Use segments"));
|
||||
_useSegments->setChecked(_options.useSegments);
|
||||
|
||||
QWidget *sourceTab = new QWidget();
|
||||
QVBoxLayout *sourceTabLayout = new QVBoxLayout();
|
||||
@ -439,14 +462,34 @@ QWidget *OptionsDialog::createDataPage()
|
||||
elevationOptions->addWidget(_dataDEMElevation);
|
||||
elevationOptions->addWidget(_showSecondaryElevation);
|
||||
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
QButtonGroup *timeZoneGroup = new QButtonGroup(this);
|
||||
timeZoneGroup->addButton(_utcZone);
|
||||
timeZoneGroup->addButton(_systemZone);
|
||||
timeZoneGroup->addButton(_customZone);
|
||||
QVBoxLayout *zoneOptions = new QVBoxLayout();
|
||||
zoneOptions->addWidget(_utcZone);
|
||||
zoneOptions->addWidget(_systemZone);
|
||||
zoneOptions->addWidget(_customZone);
|
||||
zoneOptions->addItem(customZoneLayout);
|
||||
#endif // ENABLE_TIMEZONES
|
||||
|
||||
QFormLayout *formLayout = new QFormLayout();
|
||||
formLayout->addRow(tr("Speed:"), speedOptions);
|
||||
formLayout->addRow(tr("Elevation:"), elevationOptions);
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
formLayout->addRow(tr("Time zone:"), zoneOptions);
|
||||
#endif // ENABLE_TIMEZONES
|
||||
formLayout->addRow(_useSegments);
|
||||
|
||||
sourceTabLayout->addLayout(formLayout);
|
||||
#else // Q_OS_MAC
|
||||
QFormLayout *speedLayout = new QFormLayout();
|
||||
QFormLayout *elevationLayout = new QFormLayout();
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
QFormLayout *timeZoneLayout = new QFormLayout();
|
||||
#endif // ENABLE_TIMEZONES
|
||||
QFormLayout *segmentsLayout = new QFormLayout();
|
||||
|
||||
speedLayout->addWidget(_computedSpeed);
|
||||
speedLayout->addWidget(_reportedSpeed);
|
||||
@ -462,8 +505,24 @@ QWidget *OptionsDialog::createDataPage()
|
||||
QGroupBox *elevationBox = new QGroupBox(tr("Elevation"));
|
||||
elevationBox->setLayout(elevationLayout);
|
||||
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
timeZoneLayout->addWidget(_utcZone);
|
||||
timeZoneLayout->addWidget(_systemZone);
|
||||
timeZoneLayout->addWidget(_customZone);
|
||||
timeZoneLayout->addItem(customZoneLayout);
|
||||
|
||||
QGroupBox *timeZoneBox = new QGroupBox(tr("Time zone"));
|
||||
timeZoneBox->setLayout(timeZoneLayout);
|
||||
#endif // ENABLE_TIMEZONES
|
||||
|
||||
segmentsLayout->addWidget(_useSegments);
|
||||
|
||||
sourceTabLayout->addWidget(speedBox);
|
||||
sourceTabLayout->addWidget(elevationBox);
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
sourceTabLayout->addWidget(timeZoneBox);
|
||||
#endif // ENABLE_TIMEZONES
|
||||
sourceTabLayout->addLayout(segmentsLayout);
|
||||
#endif // Q_OS_MAC
|
||||
sourceTabLayout->addStretch();
|
||||
sourceTab->setLayout(sourceTabLayout);
|
||||
@ -482,14 +541,14 @@ QWidget *OptionsDialog::createPOIPage()
|
||||
_poiRadius = new QDoubleSpinBox();
|
||||
_poiRadius->setSingleStep(1);
|
||||
_poiRadius->setDecimals(1);
|
||||
if (_options->units == Imperial) {
|
||||
_poiRadius->setValue(_options->poiRadius / MIINM);
|
||||
if (_units == Imperial) {
|
||||
_poiRadius->setValue(_options.poiRadius / MIINM);
|
||||
_poiRadius->setSuffix(UNIT_SPACE + tr("mi"));
|
||||
} else if (_options->units == Nautical) {
|
||||
_poiRadius->setValue(_options->poiRadius / NMIINM);
|
||||
} else if (_units == Nautical) {
|
||||
_poiRadius->setValue(_options.poiRadius / NMIINM);
|
||||
_poiRadius->setSuffix(UNIT_SPACE + tr("nmi"));
|
||||
} else {
|
||||
_poiRadius->setValue(_options->poiRadius / KMINM);
|
||||
_poiRadius->setValue(_options.poiRadius / KMINM);
|
||||
_poiRadius->setSuffix(UNIT_SPACE + tr("km"));
|
||||
}
|
||||
|
||||
@ -509,7 +568,7 @@ QWidget *OptionsDialog::createExportPage()
|
||||
{
|
||||
_wysiwyg = new QRadioButton(tr("WYSIWYG"));
|
||||
_hires = new QRadioButton(tr("High-Resolution"));
|
||||
if (_options->hiresPrint)
|
||||
if (_options.hiresPrint)
|
||||
_hires->setChecked(true);
|
||||
else
|
||||
_wysiwyg->setChecked(true);
|
||||
@ -538,17 +597,17 @@ QWidget *OptionsDialog::createExportPage()
|
||||
|
||||
|
||||
_name = new QCheckBox(tr("Name"));
|
||||
_name->setChecked(_options->printName);
|
||||
_name->setChecked(_options.printName);
|
||||
_date = new QCheckBox(tr("Date"));
|
||||
_date->setChecked(_options->printDate);
|
||||
_date->setChecked(_options.printDate);
|
||||
_distance = new QCheckBox(tr("Distance"));
|
||||
_distance->setChecked(_options->printDistance);
|
||||
_distance->setChecked(_options.printDistance);
|
||||
_time = new QCheckBox(tr("Time"));
|
||||
_time->setChecked(_options->printTime);
|
||||
_time->setChecked(_options.printTime);
|
||||
_movingTime = new QCheckBox(tr("Moving time"));
|
||||
_movingTime->setChecked(_options->printMovingTime);
|
||||
_movingTime->setChecked(_options.printMovingTime);
|
||||
_itemCount = new QCheckBox(tr("Item count (>1)"));
|
||||
_itemCount->setChecked(_options->printItemCount);
|
||||
_itemCount->setChecked(_options.printItemCount);
|
||||
|
||||
QFormLayout *headerTabLayout = new QFormLayout();
|
||||
headerTabLayout->addWidget(_name);
|
||||
@ -563,7 +622,7 @@ QWidget *OptionsDialog::createExportPage()
|
||||
|
||||
|
||||
_separateGraphPage = new QCheckBox(tr("Separate graph page"));
|
||||
_separateGraphPage->setChecked(_options->separateGraphPage);
|
||||
_separateGraphPage->setChecked(_options.separateGraphPage);
|
||||
|
||||
QFormLayout *graphTabLayout = new QFormLayout();
|
||||
graphTabLayout->addWidget(_separateGraphPage);
|
||||
@ -582,23 +641,23 @@ QWidget *OptionsDialog::createExportPage()
|
||||
QWidget *OptionsDialog::createSystemPage()
|
||||
{
|
||||
_useOpenGL = new QCheckBox(tr("Use OpenGL"));
|
||||
_useOpenGL->setChecked(_options->useOpenGL);
|
||||
_useOpenGL->setChecked(_options.useOpenGL);
|
||||
#ifdef ENABLE_HTTP2
|
||||
_enableHTTP2 = new QCheckBox(tr("Enable HTTP/2"));
|
||||
_enableHTTP2->setChecked(_options->enableHTTP2);
|
||||
_enableHTTP2->setChecked(_options.enableHTTP2);
|
||||
#endif // ENABLE_HTTP2
|
||||
|
||||
_pixmapCache = new QSpinBox();
|
||||
_pixmapCache->setMinimum(16);
|
||||
_pixmapCache->setMaximum(1024);
|
||||
_pixmapCache->setSuffix(UNIT_SPACE + tr("MB"));
|
||||
_pixmapCache->setValue(_options->pixmapCache);
|
||||
_pixmapCache->setValue(_options.pixmapCache);
|
||||
|
||||
_connectionTimeout = new QSpinBox();
|
||||
_connectionTimeout->setMinimum(30);
|
||||
_connectionTimeout->setMaximum(120);
|
||||
_connectionTimeout->setSuffix(UNIT_SPACE + tr("s"));
|
||||
_connectionTimeout->setValue(_options->connectionTimeout);
|
||||
_connectionTimeout->setValue(_options.connectionTimeout);
|
||||
|
||||
QFormLayout *formLayout = new QFormLayout();
|
||||
formLayout->addRow(tr("Image cache size:"), _pixmapCache);
|
||||
@ -623,8 +682,8 @@ QWidget *OptionsDialog::createSystemPage()
|
||||
return systemPage;
|
||||
}
|
||||
|
||||
OptionsDialog::OptionsDialog(Options *options, QWidget *parent)
|
||||
: QDialog(parent), _options(options)
|
||||
OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent)
|
||||
: QDialog(parent), _options(options), _units(units)
|
||||
{
|
||||
QStackedWidget *pages = new QStackedWidget();
|
||||
pages->addWidget(createAppearancePage());
|
||||
@ -676,74 +735,82 @@ OptionsDialog::OptionsDialog(Options *options, QWidget *parent)
|
||||
|
||||
void OptionsDialog::accept()
|
||||
{
|
||||
_options->palette.setColor(_baseColor->color());
|
||||
_options->palette.setShift(_colorOffset->value());
|
||||
_options->mapOpacity = _mapOpacity->value();
|
||||
_options->backgroundColor = _backgroundColor->color();
|
||||
_options->trackWidth = _trackWidth->value();
|
||||
_options->trackStyle = (Qt::PenStyle) _trackStyle->itemData(
|
||||
_options.palette.setColor(_baseColor->color());
|
||||
_options.palette.setShift(_colorOffset->value() / 100.0);
|
||||
_options.mapOpacity = _mapOpacity->value();
|
||||
_options.backgroundColor = _backgroundColor->color();
|
||||
_options.trackWidth = _trackWidth->value();
|
||||
_options.trackStyle = (Qt::PenStyle) _trackStyle->itemData(
|
||||
_trackStyle->currentIndex()).toInt();
|
||||
_options->routeWidth = _routeWidth->value();
|
||||
_options->routeStyle = (Qt::PenStyle) _routeStyle->itemData(
|
||||
_options.routeWidth = _routeWidth->value();
|
||||
_options.routeStyle = (Qt::PenStyle) _routeStyle->itemData(
|
||||
_routeStyle->currentIndex()).toInt();
|
||||
_options->pathAntiAliasing = _pathAA->isChecked();
|
||||
_options->areaWidth = _areaWidth->value();
|
||||
_options->areaStyle = (Qt::PenStyle) _areaStyle->itemData(
|
||||
_options.pathAntiAliasing = _pathAA->isChecked();
|
||||
_options.areaWidth = _areaWidth->value();
|
||||
_options.areaStyle = (Qt::PenStyle) _areaStyle->itemData(
|
||||
_areaStyle->currentIndex()).toInt();
|
||||
_options->areaOpacity = _areaOpacity->value();
|
||||
_options->waypointSize = _waypointSize->value();
|
||||
_options->waypointColor = _waypointColor->color();
|
||||
_options->poiSize = _poiSize->value();
|
||||
_options->poiColor = _poiColor->color();
|
||||
_options->graphWidth = _graphWidth->value();
|
||||
_options->sliderColor = _sliderColor->color();
|
||||
_options->graphAntiAliasing = _graphAA->isChecked();
|
||||
_options.areaOpacity = _areaOpacity->value();
|
||||
_options.waypointSize = _waypointSize->value();
|
||||
_options.waypointColor = _waypointColor->color();
|
||||
_options.poiSize = _poiSize->value();
|
||||
_options.poiColor = _poiColor->color();
|
||||
_options.graphWidth = _graphWidth->value();
|
||||
_options.sliderColor = _sliderColor->color();
|
||||
_options.graphAntiAliasing = _graphAA->isChecked();
|
||||
|
||||
_options->projection = _projection->itemData(_projection->currentIndex())
|
||||
_options.projection = _projection->itemData(_projection->currentIndex())
|
||||
.toInt();
|
||||
#ifdef ENABLE_HIDPI
|
||||
_options->hidpiMap = _hidpi->isChecked();
|
||||
_options.hidpiMap = _hidpi->isChecked();
|
||||
#endif // ENABLE_HIDPI
|
||||
|
||||
_options->elevationFilter = _elevationFilter->value();
|
||||
_options->speedFilter = _speedFilter->value();
|
||||
_options->heartRateFilter = _heartRateFilter->value();
|
||||
_options->cadenceFilter = _cadenceFilter->value();
|
||||
_options->powerFilter = _powerFilter->value();
|
||||
_options->outlierEliminate = _outlierEliminate->isChecked();
|
||||
_options->automaticPause = _automaticPause->isChecked();
|
||||
qreal pauseSpeed = (_options->units == Imperial)
|
||||
? _pauseSpeed->value() / MS2MIH : (_options->units == Nautical)
|
||||
_options.elevationFilter = _elevationFilter->value();
|
||||
_options.speedFilter = _speedFilter->value();
|
||||
_options.heartRateFilter = _heartRateFilter->value();
|
||||
_options.cadenceFilter = _cadenceFilter->value();
|
||||
_options.powerFilter = _powerFilter->value();
|
||||
_options.outlierEliminate = _outlierEliminate->isChecked();
|
||||
_options.automaticPause = _automaticPause->isChecked();
|
||||
qreal pauseSpeed = (_units == Imperial)
|
||||
? _pauseSpeed->value() / MS2MIH : (_units == Nautical)
|
||||
? _pauseSpeed->value() / MS2KN : _pauseSpeed->value() / MS2KMH;
|
||||
if (qAbs(pauseSpeed - _options->pauseSpeed) > 0.01)
|
||||
_options->pauseSpeed = pauseSpeed;
|
||||
_options->pauseInterval = _pauseInterval->value();
|
||||
_options->useReportedSpeed = _reportedSpeed->isChecked();
|
||||
_options->dataUseDEM = _dataDEMElevation->isChecked();
|
||||
_options->showSecondaryElevation = _showSecondaryElevation->isChecked();
|
||||
_options->showSecondarySpeed = _showSecondarySpeed->isChecked();
|
||||
if (qAbs(pauseSpeed - _options.pauseSpeed) > 0.01)
|
||||
_options.pauseSpeed = pauseSpeed;
|
||||
_options.pauseInterval = _pauseInterval->value();
|
||||
_options.useReportedSpeed = _reportedSpeed->isChecked();
|
||||
_options.dataUseDEM = _dataDEMElevation->isChecked();
|
||||
_options.showSecondaryElevation = _showSecondaryElevation->isChecked();
|
||||
_options.showSecondarySpeed = _showSecondarySpeed->isChecked();
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
_options.timeZone.setType(_utcZone->isChecked()
|
||||
? TimeZoneInfo::UTC : _systemZone->isChecked()
|
||||
? TimeZoneInfo::System : TimeZoneInfo::Custom);
|
||||
_options.timeZone.setCustomZone(QTimeZone(_timeZone->currentText()
|
||||
.toLatin1()));
|
||||
#endif // ENABLE_TIMEZONES
|
||||
_options.useSegments = _useSegments->isChecked();
|
||||
|
||||
qreal poiRadius = (_options->units == Imperial)
|
||||
? _poiRadius->value() * MIINM : (_options->units == Nautical)
|
||||
qreal poiRadius = (_units == Imperial)
|
||||
? _poiRadius->value() * MIINM : (_units == Nautical)
|
||||
? _poiRadius->value() * NMIINM : _poiRadius->value() * KMINM;
|
||||
if (qAbs(poiRadius - _options->poiRadius) > 0.01)
|
||||
_options->poiRadius = poiRadius;
|
||||
if (qAbs(poiRadius - _options.poiRadius) > 0.01)
|
||||
_options.poiRadius = poiRadius;
|
||||
|
||||
_options->useOpenGL = _useOpenGL->isChecked();
|
||||
_options.useOpenGL = _useOpenGL->isChecked();
|
||||
#ifdef ENABLE_HTTP2
|
||||
_options->enableHTTP2 = _enableHTTP2->isChecked();
|
||||
_options.enableHTTP2 = _enableHTTP2->isChecked();
|
||||
#endif // ENABLE_HTTP2
|
||||
_options->pixmapCache = _pixmapCache->value();
|
||||
_options->connectionTimeout = _connectionTimeout->value();
|
||||
_options.pixmapCache = _pixmapCache->value();
|
||||
_options.connectionTimeout = _connectionTimeout->value();
|
||||
|
||||
_options->hiresPrint = _hires->isChecked();
|
||||
_options->printName = _name->isChecked();
|
||||
_options->printDate = _date->isChecked();
|
||||
_options->printDistance = _distance->isChecked();
|
||||
_options->printTime = _time->isChecked();
|
||||
_options->printMovingTime = _movingTime->isChecked();
|
||||
_options->printItemCount = _itemCount->isChecked();
|
||||
_options->separateGraphPage = _separateGraphPage->isChecked();
|
||||
_options.hiresPrint = _hires->isChecked();
|
||||
_options.printName = _name->isChecked();
|
||||
_options.printDate = _date->isChecked();
|
||||
_options.printDistance = _distance->isChecked();
|
||||
_options.printTime = _time->isChecked();
|
||||
_options.printMovingTime = _movingTime->isChecked();
|
||||
_options.printItemCount = _itemCount->isChecked();
|
||||
_options.separateGraphPage = _separateGraphPage->isChecked();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
@ -5,6 +5,9 @@
|
||||
#include "common/config.h"
|
||||
#include "palette.h"
|
||||
#include "units.h"
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
#include "timezoneinfo.h"
|
||||
#endif // ENABLE_TIMEZONES
|
||||
|
||||
class ColorBox;
|
||||
class StyleComboBox;
|
||||
@ -17,6 +20,7 @@ class QRadioButton;
|
||||
class PercentSlider;
|
||||
class LimitedComboBox;
|
||||
|
||||
|
||||
struct Options {
|
||||
// Appearance
|
||||
Palette palette;
|
||||
@ -56,6 +60,10 @@ struct Options {
|
||||
bool dataUseDEM;
|
||||
bool showSecondaryElevation;
|
||||
bool showSecondarySpeed;
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
TimeZoneInfo timeZone;
|
||||
#endif // ENABLE_TIMEZONES
|
||||
bool useSegments;
|
||||
// POI
|
||||
int poiRadius;
|
||||
// System
|
||||
@ -74,8 +82,6 @@ struct Options {
|
||||
bool printMovingTime;
|
||||
bool printItemCount;
|
||||
bool separateGraphPage;
|
||||
|
||||
Units units;
|
||||
};
|
||||
|
||||
class OptionsDialog : public QDialog
|
||||
@ -86,7 +92,7 @@ public slots:
|
||||
void accept();
|
||||
|
||||
public:
|
||||
OptionsDialog(Options *options, QWidget *parent = 0);
|
||||
OptionsDialog(Options &options, Units units, QWidget *parent = 0);
|
||||
|
||||
private slots:
|
||||
void automaticPauseDetectionSet(bool set);
|
||||
@ -99,11 +105,12 @@ private:
|
||||
QWidget *createSystemPage();
|
||||
QWidget *createExportPage();
|
||||
|
||||
Options *_options;
|
||||
Options &_options;
|
||||
|
||||
Units _units;
|
||||
// Appearance
|
||||
ColorBox *_baseColor;
|
||||
QDoubleSpinBox *_colorOffset;
|
||||
PercentSlider *_colorOffset;
|
||||
PercentSlider *_mapOpacity;
|
||||
ColorBox *_backgroundColor;
|
||||
QSpinBox *_trackWidth;
|
||||
@ -134,7 +141,6 @@ private:
|
||||
OddSpinBox *_cadenceFilter;
|
||||
OddSpinBox *_powerFilter;
|
||||
QCheckBox *_outlierEliminate;
|
||||
|
||||
QRadioButton *_automaticPause;
|
||||
QRadioButton *_manualPause;
|
||||
QDoubleSpinBox *_pauseSpeed;
|
||||
@ -145,6 +151,13 @@ private:
|
||||
QRadioButton *_dataDEMElevation;
|
||||
QCheckBox *_showSecondaryElevation;
|
||||
QCheckBox *_showSecondarySpeed;
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
QRadioButton *_utcZone;
|
||||
QRadioButton *_systemZone;
|
||||
QRadioButton *_customZone;
|
||||
QComboBox *_timeZone;
|
||||
#endif // ENABLE_TIMEZONES
|
||||
QCheckBox *_useSegments;
|
||||
// POI
|
||||
QDoubleSpinBox *_poiRadius;
|
||||
// System
|
||||
|
@ -21,12 +21,16 @@ static inline unsigned segments(qreal distance)
|
||||
return ceil(distance / GEOGRAPHICAL_MILE);
|
||||
}
|
||||
|
||||
Units PathItem::_units = Metric;
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
QTimeZone PathItem::_timeZone = QTimeZone::utc();
|
||||
#endif // ENABLE_TIMEZONES
|
||||
|
||||
PathItem::PathItem(const Path &path, Map *map, QGraphicsItem *parent)
|
||||
: GraphicsItem(parent), _path(path), _map(map)
|
||||
{
|
||||
Q_ASSERT(_path.isValid());
|
||||
|
||||
_units = Metric;
|
||||
_digitalZoom = 0;
|
||||
_width = 3;
|
||||
QBrush brush(Qt::SolidPattern);
|
||||
@ -352,16 +356,6 @@ void PathItem::showTicks(bool show)
|
||||
updateTicks();
|
||||
}
|
||||
|
||||
void PathItem::setUnits(Units units)
|
||||
{
|
||||
if (_units == units)
|
||||
return;
|
||||
|
||||
prepareGeometryChange();
|
||||
_units = units;
|
||||
updateTicks();
|
||||
}
|
||||
|
||||
void PathItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
@ -1,8 +1,12 @@
|
||||
#ifndef PATHITEM_H
|
||||
#define PATHITEM_H
|
||||
|
||||
#include "common/config.h"
|
||||
#include <QGraphicsObject>
|
||||
#include <QPen>
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
#include <QTimeZone>
|
||||
#endif // ENABLE_TIMEZONES
|
||||
#include "data/path.h"
|
||||
#include "markeritem.h"
|
||||
#include "units.h"
|
||||
@ -28,7 +32,6 @@ public:
|
||||
|
||||
void setMap(Map *map);
|
||||
|
||||
void setUnits(Units units);
|
||||
void setColor(const QColor &color);
|
||||
void setWidth(qreal width);
|
||||
void setStyle(Qt::PenStyle style);
|
||||
@ -37,6 +40,13 @@ public:
|
||||
void showMarker(bool show);
|
||||
void showTicks(bool show);
|
||||
|
||||
void updateTicks();
|
||||
|
||||
static void setUnits(Units units) {_units = units;}
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
static void setTimeZone(const QTimeZone &zone) {_timeZone = zone;}
|
||||
#endif // ENABLE_TIMEZONES
|
||||
|
||||
public slots:
|
||||
void moveMarker(qreal distance);
|
||||
void hover(bool hover);
|
||||
@ -49,7 +59,10 @@ protected:
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||
|
||||
Units _units;
|
||||
static Units _units;
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
static QTimeZone _timeZone;
|
||||
#endif // ENABLE_TIMEZONES
|
||||
|
||||
private:
|
||||
const PathSegment *segment(qreal x) const;
|
||||
@ -60,7 +73,6 @@ private:
|
||||
|
||||
qreal xInM() const;
|
||||
unsigned tickSize() const;
|
||||
void updateTicks();
|
||||
|
||||
Path _path;
|
||||
Map *_map;
|
||||
|
@ -1,30 +1,27 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QFormLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGroupBox>
|
||||
#include <QComboBox>
|
||||
#include <QRadioButton>
|
||||
#include <QPushButton>
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
#include <QTabWidget>
|
||||
#include <QDoubleSpinBox>
|
||||
#include "marginswidget.h"
|
||||
#include "fileselectwidget.h"
|
||||
#include "units.h"
|
||||
#include "exportdialog.h"
|
||||
#include "pdfexportdialog.h"
|
||||
|
||||
|
||||
ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
||||
: QDialog(parent), _export(exp)
|
||||
PDFExportDialog::PDFExportDialog(PDFExport &exp, Units units, QWidget *parent)
|
||||
: QDialog(parent), _export(exp), _units(units)
|
||||
{
|
||||
int index;
|
||||
|
||||
_fileSelect = new FileSelectWidget();
|
||||
_fileSelect->setFilter(tr("PDF files") + " (*.pdf);;" + tr("All files")
|
||||
+ " (*)");
|
||||
_fileSelect->setFile(_export->fileName);
|
||||
_fileSelect->setFile(_export.fileName);
|
||||
|
||||
_paperSize = new QComboBox();
|
||||
_paperSize->addItem("A2", QPrinter::A2);
|
||||
@ -39,14 +36,14 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
||||
_paperSize->addItem("Tabloid", QPrinter::Tabloid);
|
||||
_paperSize->addItem("Legal", QPrinter::Legal);
|
||||
_paperSize->addItem("Letter", QPrinter::Letter);
|
||||
if ((index = _paperSize->findData(_export->paperSize)) >= 0)
|
||||
if ((index = _paperSize->findData(_export.paperSize)) >= 0)
|
||||
_paperSize->setCurrentIndex(index);
|
||||
|
||||
_resolution = new QComboBox();
|
||||
_resolution->addItem("150 DPI", 150);
|
||||
_resolution->addItem("300 DPI", 300);
|
||||
_resolution->addItem("600 DPI", 600);
|
||||
if ((index = _resolution->findData(_export->resolution)) >= 0)
|
||||
if ((index = _resolution->findData(_export.resolution)) >= 0)
|
||||
_resolution->setCurrentIndex(index);
|
||||
|
||||
_portrait = new QRadioButton(tr("Portrait"));
|
||||
@ -54,41 +51,16 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
||||
QHBoxLayout *orientationLayout = new QHBoxLayout();
|
||||
orientationLayout->addWidget(_portrait);
|
||||
orientationLayout->addWidget(_landscape);
|
||||
if (_export->orientation == QPrinter::Portrait)
|
||||
if (_export.orientation == QPrinter::Portrait)
|
||||
_portrait->setChecked(true);
|
||||
else
|
||||
_landscape->setChecked(true);
|
||||
|
||||
_topMargin = new QDoubleSpinBox();
|
||||
_bottomMargin = new QDoubleSpinBox();
|
||||
_leftMargin = new QDoubleSpinBox();
|
||||
_rightMargin = new QDoubleSpinBox();
|
||||
QString us = (_export->units == Metric) ? tr("mm") : tr("in");
|
||||
_topMargin->setSuffix(UNIT_SPACE + us);
|
||||
_bottomMargin->setSuffix(UNIT_SPACE + us);
|
||||
_leftMargin->setSuffix(UNIT_SPACE + us);
|
||||
_rightMargin->setSuffix(UNIT_SPACE + us);
|
||||
if (_export->units == Metric) {
|
||||
_topMargin->setValue(_export->margins.top());
|
||||
_bottomMargin->setValue(_export->margins.bottom());
|
||||
_leftMargin->setValue(_export->margins.left());
|
||||
_rightMargin->setValue(_export->margins.right());
|
||||
} else {
|
||||
_topMargin->setValue(_export->margins.top() * MM2IN);
|
||||
_bottomMargin->setValue(_export->margins.bottom() * MM2IN);
|
||||
_leftMargin->setValue(_export->margins.left() * MM2IN);
|
||||
_rightMargin->setValue(_export->margins.right() * MM2IN);
|
||||
_topMargin->setSingleStep(0.1);
|
||||
_bottomMargin->setSingleStep(0.1);
|
||||
_leftMargin->setSingleStep(0.1);
|
||||
_rightMargin->setSingleStep(0.1);
|
||||
}
|
||||
|
||||
QGridLayout *marginsLayout = new QGridLayout();
|
||||
marginsLayout->addWidget(_topMargin, 0, 0, 1, 2, Qt::AlignCenter);
|
||||
marginsLayout->addWidget(_leftMargin, 1, 0, 1, 1, Qt::AlignRight);
|
||||
marginsLayout->addWidget(_rightMargin, 1, 1, 1, 1, Qt::AlignLeft);
|
||||
marginsLayout->addWidget(_bottomMargin, 2, 0, 1, 2, Qt::AlignCenter);
|
||||
_margins = new MarginsFWidget();
|
||||
_margins->setUnits((units == Metric) ? tr("cm") : tr("in"));
|
||||
_margins->setSingleStep(0.1);
|
||||
_margins->setValue((units == Metric)
|
||||
? _export.margins * MM2CM : _export.margins * MM2IN);
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
QGroupBox *pageSetupBox = new QGroupBox(tr("Page Setup"));
|
||||
@ -97,7 +69,7 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
||||
pageSetupLayout->addRow(tr("Page size:"), _paperSize);
|
||||
pageSetupLayout->addRow(tr("Resolution:"), _resolution);
|
||||
pageSetupLayout->addRow(tr("Orientation:"), orientationLayout);
|
||||
pageSetupLayout->addRow(tr("Margins:"), marginsLayout);
|
||||
pageSetupLayout->addRow(tr("Margins:"), _margins);
|
||||
#ifdef Q_OS_MAC
|
||||
QFrame *line = new QFrame();
|
||||
line->setFrameShape(QFrame::HLine);
|
||||
@ -111,7 +83,7 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
QGroupBox *outputFileBox = new QGroupBox(tr("Output file"));
|
||||
QHBoxLayout *outputFileLayout = new QHBoxLayout();
|
||||
QVBoxLayout *outputFileLayout = new QVBoxLayout();
|
||||
outputFileLayout->addWidget(_fileSelect);
|
||||
outputFileBox->setLayout(outputFileLayout);
|
||||
#endif // Q_OS_MAC
|
||||
@ -136,41 +108,13 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
}
|
||||
|
||||
bool ExportDialog::checkFile()
|
||||
void PDFExportDialog::accept()
|
||||
{
|
||||
if (_fileSelect->file().isEmpty()) {
|
||||
QMessageBox::warning(this, tr("Error"), tr("No output file selected."));
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile file(_fileSelect->file());
|
||||
QFileInfo fi(file);
|
||||
bool exists = fi.exists();
|
||||
bool opened = false;
|
||||
|
||||
if (exists && fi.isDir()) {
|
||||
QMessageBox::warning(this, tr("Error"), tr("%1 is a directory.")
|
||||
.arg(file.fileName()));
|
||||
return false;
|
||||
} else if ((exists && !fi.isWritable())
|
||||
|| !(opened = file.open(QFile::Append))) {
|
||||
QMessageBox::warning(this, tr("Error"), tr("%1 is not writable.")
|
||||
.arg(file.fileName()));
|
||||
return false;
|
||||
}
|
||||
if (opened) {
|
||||
file.close();
|
||||
if (!exists)
|
||||
file.remove();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExportDialog::accept()
|
||||
{
|
||||
if (!checkFile())
|
||||
QString error;
|
||||
if (!_fileSelect->checkFile(error)) {
|
||||
QMessageBox::warning(this, tr("Error"), error);
|
||||
return;
|
||||
}
|
||||
|
||||
QPrinter::Orientation orientation = _portrait->isChecked()
|
||||
? QPrinter::Portrait : QPrinter::Landscape;
|
||||
@ -178,17 +122,12 @@ void ExportDialog::accept()
|
||||
(_paperSize->itemData(_paperSize->currentIndex()).toInt());
|
||||
int resolution = _resolution->itemData(_resolution->currentIndex()).toInt();
|
||||
|
||||
_export->fileName = _fileSelect->file();
|
||||
_export->paperSize = paperSize;
|
||||
_export->resolution = resolution;
|
||||
_export->orientation = orientation;
|
||||
if (_export->units == Imperial)
|
||||
_export->margins = MarginsF(_leftMargin->value() / MM2IN,
|
||||
_topMargin->value() / MM2IN, _rightMargin->value() / MM2IN,
|
||||
_bottomMargin->value() / MM2IN);
|
||||
else
|
||||
_export->margins = MarginsF(_leftMargin->value(), _topMargin->value(),
|
||||
_rightMargin->value(), _bottomMargin->value());
|
||||
_export.fileName = _fileSelect->file();
|
||||
_export.paperSize = paperSize;
|
||||
_export.resolution = resolution;
|
||||
_export.orientation = orientation;
|
||||
_export.margins = (_units == Imperial)
|
||||
? _margins->value() / MM2IN : _margins->value() / MM2CM;
|
||||
|
||||
QDialog::accept();
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#ifndef EXPORTDIALOG_H
|
||||
#define EXPORTDIALOG_H
|
||||
#ifndef PDFEXPORTDIALOG_H
|
||||
#define PDFEXPORTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QPrinter>
|
||||
@ -9,42 +9,37 @@
|
||||
class QComboBox;
|
||||
class QRadioButton;
|
||||
class FileSelectWidget;
|
||||
class QDoubleSpinBox;
|
||||
class MarginsFWidget;
|
||||
|
||||
struct Export {
|
||||
struct PDFExport
|
||||
{
|
||||
QString fileName;
|
||||
QPrinter::PaperSize paperSize;
|
||||
QPrinter::Orientation orientation;
|
||||
MarginsF margins;
|
||||
int resolution;
|
||||
|
||||
Units units;
|
||||
};
|
||||
|
||||
class ExportDialog : public QDialog
|
||||
class PDFExportDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ExportDialog(Export *exp, QWidget *parent = 0);
|
||||
PDFExportDialog(PDFExport &exp, Units units, QWidget *parent = 0);
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
|
||||
private:
|
||||
bool checkFile();
|
||||
|
||||
Export *_export;
|
||||
PDFExport &_export;
|
||||
|
||||
Units _units;
|
||||
FileSelectWidget *_fileSelect;
|
||||
QComboBox *_paperSize;
|
||||
QComboBox *_resolution;
|
||||
QRadioButton *_portrait;
|
||||
QRadioButton *_landscape;
|
||||
QDoubleSpinBox *_topMargin;
|
||||
QDoubleSpinBox *_bottomMargin;
|
||||
QDoubleSpinBox *_leftMargin;
|
||||
QDoubleSpinBox *_rightMargin;
|
||||
MarginsFWidget *_margins;
|
||||
};
|
||||
|
||||
#endif // EXPORTDIALOG_H
|
||||
#endif // PDFEXPORTDIALOG_H
|
101
src/GUI/pngexportdialog.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QFormLayout>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGroupBox>
|
||||
#include <QSpinBox>
|
||||
#include <QMessageBox>
|
||||
#include <QTabWidget>
|
||||
#include <QCheckBox>
|
||||
#include "units.h"
|
||||
#include "fileselectwidget.h"
|
||||
#include "marginswidget.h"
|
||||
#include "pngexportdialog.h"
|
||||
|
||||
|
||||
PNGExportDialog::PNGExportDialog(PNGExport &exp, QWidget *parent)
|
||||
: QDialog(parent), _export(exp)
|
||||
{
|
||||
_fileSelect = new FileSelectWidget();
|
||||
_fileSelect->setFilter(tr("PNG files") + " (*.png);;" + tr("All files")
|
||||
+ " (*)");
|
||||
_fileSelect->setFile(_export.fileName);
|
||||
|
||||
_width = new QSpinBox();
|
||||
_width->setMinimum(256);
|
||||
_width->setMaximum(4096);
|
||||
_width->setValue(_export.size.width());
|
||||
_width->setSuffix(UNIT_SPACE + tr("px"));
|
||||
_height = new QSpinBox();
|
||||
_height->setMinimum(256);
|
||||
_height->setMaximum(4096);
|
||||
_height->setValue(_export.size.height());
|
||||
_height->setSuffix(UNIT_SPACE + tr("px"));
|
||||
|
||||
_margins = new MarginsWidget();
|
||||
_margins->setValue(_export.margins);
|
||||
_margins->setUnits(tr("px"));
|
||||
|
||||
_antialiasing = new QCheckBox(tr("Use anti-aliasing"));
|
||||
_antialiasing->setChecked(_export.antialiasing);
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
QGroupBox *pageSetupBox = new QGroupBox(tr("Image Setup"));
|
||||
#endif // Q_OS_MAC
|
||||
QFormLayout *pageSetupLayout = new QFormLayout;
|
||||
pageSetupLayout->addRow(tr("Image width:"), _width);
|
||||
pageSetupLayout->addRow(tr("Image height:"), _height);
|
||||
pageSetupLayout->addRow(tr("Margins:"), _margins);
|
||||
pageSetupLayout->addWidget(_antialiasing);
|
||||
#ifdef Q_OS_MAC
|
||||
QFrame *line = new QFrame();
|
||||
line->setFrameShape(QFrame::HLine);
|
||||
line->setFrameShadow(QFrame::Sunken);
|
||||
pageSetupLayout->addRow(line);
|
||||
pageSetupLayout->addRow(tr("File:"), _fileSelect);
|
||||
pageSetupLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
||||
#else // Q_OS_MAC
|
||||
pageSetupBox->setLayout(pageSetupLayout);
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
QGroupBox *outputFileBox = new QGroupBox(tr("Output file"));
|
||||
QVBoxLayout *outputFileLayout = new QVBoxLayout();
|
||||
outputFileLayout->addWidget(_fileSelect);
|
||||
outputFileBox->setLayout(outputFileLayout);
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
QDialogButtonBox *buttonBox = new QDialogButtonBox();
|
||||
buttonBox->addButton(tr("Export"), QDialogButtonBox::AcceptRole);
|
||||
buttonBox->addButton(QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
#ifdef Q_OS_MAC
|
||||
layout->addLayout(pageSetupLayout);
|
||||
#else // Q_OS_MAC
|
||||
layout->addWidget(pageSetupBox);
|
||||
layout->addWidget(outputFileBox);
|
||||
#endif // Q_OS_MAC
|
||||
layout->addWidget(buttonBox);
|
||||
setLayout(layout);
|
||||
|
||||
setWindowTitle(tr("Export to PNG"));
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
}
|
||||
|
||||
void PNGExportDialog::accept()
|
||||
{
|
||||
QString error;
|
||||
if (!_fileSelect->checkFile(error)) {
|
||||
QMessageBox::warning(this, tr("Error"), error);
|
||||
return;
|
||||
}
|
||||
|
||||
_export.fileName = _fileSelect->file();
|
||||
_export.size = QSize(_width->value(), _height->value());
|
||||
_export.margins = _margins->value();
|
||||
_export.antialiasing = _antialiasing->isChecked();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
41
src/GUI/pngexportdialog.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef PNGEXPORTDIALOG_H
|
||||
#define PNGEXPORTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QMargins>
|
||||
#include "margins.h"
|
||||
|
||||
class FileSelectWidget;
|
||||
class MarginsWidget;
|
||||
class QSpinBox;
|
||||
class QCheckBox;
|
||||
|
||||
struct PNGExport
|
||||
{
|
||||
QString fileName;
|
||||
QSize size;
|
||||
QMargins margins;
|
||||
bool antialiasing;
|
||||
};
|
||||
|
||||
class PNGExportDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PNGExportDialog(PNGExport &exp, QWidget *parent = 0);
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
|
||||
private:
|
||||
PNGExport &_export;
|
||||
|
||||
FileSelectWidget *_fileSelect;
|
||||
QSpinBox *_width;
|
||||
QSpinBox *_height;
|
||||
MarginsWidget *_margins;
|
||||
QCheckBox *_antialiasing;
|
||||
};
|
||||
|
||||
#endif // PNGEXPORTDIALOG_H
|
@ -47,7 +47,6 @@ RouteItem::RouteItem(const Route &route, Map *map, QGraphicsItem *parent)
|
||||
_desc = route.description();
|
||||
_comment = route.comment();
|
||||
_links = route.links();
|
||||
_coordinatesFormat = DecimalDegrees;
|
||||
}
|
||||
|
||||
void RouteItem::setMap(Map *map)
|
||||
@ -58,28 +57,6 @@ void RouteItem::setMap(Map *map)
|
||||
PathItem::setMap(map);
|
||||
}
|
||||
|
||||
void RouteItem::setUnits(Units u)
|
||||
{
|
||||
if (_units == u)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < _waypoints.count(); i++)
|
||||
_waypoints[i]->setToolTipFormat(u, _coordinatesFormat);
|
||||
|
||||
PathItem::setUnits(u);
|
||||
}
|
||||
|
||||
void RouteItem::setCoordinatesFormat(CoordinatesFormat format)
|
||||
{
|
||||
if (_coordinatesFormat == format)
|
||||
return;
|
||||
|
||||
_coordinatesFormat = format;
|
||||
|
||||
for (int i = 0; i < _waypoints.count(); i++)
|
||||
_waypoints[i]->setToolTipFormat(_units, _coordinatesFormat);
|
||||
}
|
||||
|
||||
void RouteItem::showWaypoints(bool show)
|
||||
{
|
||||
for (int i = 0; i < _waypoints.count(); i++)
|
||||
|
@ -19,8 +19,6 @@ public:
|
||||
|
||||
void setMap(Map *map);
|
||||
|
||||
void setUnits(Units u);
|
||||
void setCoordinatesFormat(CoordinatesFormat format);
|
||||
void showWaypoints(bool show);
|
||||
void showWaypointLabels(bool show);
|
||||
|
||||
@ -31,7 +29,6 @@ private:
|
||||
QString _desc;
|
||||
QString _comment;
|
||||
QVector<Link> _links;
|
||||
CoordinatesFormat _coordinatesFormat;
|
||||
|
||||
QVector<WaypointItem*> _waypoints;
|
||||
};
|
||||
|
@ -66,26 +66,45 @@
|
||||
#define SHOW_WAYPOINT_LABELS_SETTING "waypointLabels"
|
||||
#define SHOW_WAYPOINT_LABELS_DEFAULT true
|
||||
|
||||
#define EXPORT_SETTINGS_GROUP "Export"
|
||||
#define PDF_EXPORT_SETTINGS_GROUP "Export"
|
||||
#define PAPER_ORIENTATION_SETTING "orientation"
|
||||
#define PAPER_ORIENTATION_DEFAULT QPrinter::Portrait
|
||||
#define PAPER_SIZE_SETTING "size"
|
||||
#define PAPER_SIZE_DEFAULT (IMPERIAL_UNITS() ? QPrinter::Letter \
|
||||
: QPrinter::A4)
|
||||
#define MARGIN_LEFT_SETTING "marginLeft"
|
||||
#define MARGIN_LEFT_DEFAULT 5 /* mm */
|
||||
#define MARGIN_TOP_SETTING "marginTop"
|
||||
#define MARGIN_TOP_DEFAULT 5 /* mm */
|
||||
#define MARGIN_RIGHT_SETTING "marginRight"
|
||||
#define MARGIN_RIGHT_DEFAULT 5 /* mm */
|
||||
#define MARGIN_BOTTOM_SETTING "marginBottom"
|
||||
#define MARGIN_BOTTOM_DEFAULT 5 /* mm */
|
||||
#define EXPORT_FILENAME_SETTING "fileName"
|
||||
#define EXPORT_FILENAME_DEFAULT QString("%1/export.pdf"). \
|
||||
#define PDF_MARGIN_LEFT_SETTING "marginLeft"
|
||||
#define PDF_MARGIN_LEFT_DEFAULT 5 /* mm */
|
||||
#define PDF_MARGIN_TOP_SETTING "marginTop"
|
||||
#define PDF_MARGIN_TOP_DEFAULT 5 /* mm */
|
||||
#define PDF_MARGIN_RIGHT_SETTING "marginRight"
|
||||
#define PDF_MARGIN_RIGHT_DEFAULT 5 /* mm */
|
||||
#define PDF_MARGIN_BOTTOM_SETTING "marginBottom"
|
||||
#define PDF_MARGIN_BOTTOM_DEFAULT 5 /* mm */
|
||||
#define PDF_FILENAME_SETTING "fileName"
|
||||
#define PDF_FILENAME_DEFAULT QString("%1/export.pdf"). \
|
||||
arg(QDir::currentPath())
|
||||
#define RESOLUTION_SETTING "resolution"
|
||||
#define RESOLUTION_DEFAULT 600
|
||||
|
||||
#define PNG_EXPORT_SETTINGS_GROUP "PNGExport"
|
||||
#define PNG_WIDTH_SETTING "width"
|
||||
#define PNG_WIDTH_DEFAULT 600
|
||||
#define PNG_HEIGHT_SETTING "height"
|
||||
#define PNG_HEIGHT_DEFAULT 800
|
||||
#define PNG_MARGIN_LEFT_SETTING "marginLeft"
|
||||
#define PNG_MARGIN_LEFT_DEFAULT 5 /* px */
|
||||
#define PNG_MARGIN_TOP_SETTING "marginTop"
|
||||
#define PNG_MARGIN_TOP_DEFAULT 5 /* px */
|
||||
#define PNG_MARGIN_RIGHT_SETTING "marginRight"
|
||||
#define PNG_MARGIN_RIGHT_DEFAULT 5 /* px */
|
||||
#define PNG_MARGIN_BOTTOM_SETTING "marginBottom"
|
||||
#define PNG_MARGIN_BOTTOM_DEFAULT 5 /* px */
|
||||
#define PNG_ANTIALIASING_SETTING "antialiasing"
|
||||
#define PNG_ANTIALIASING_DEFAULT true
|
||||
#define PNG_FILENAME_SETTING "fileName"
|
||||
#define PNG_FILENAME_DEFAULT QString("%1/export.png"). \
|
||||
arg(QDir::currentPath())
|
||||
|
||||
#define OPTIONS_SETTINGS_GROUP "Options"
|
||||
#define PALETTE_COLOR_SETTING "paletteColor"
|
||||
#define PALETTE_COLOR_DEFAULT QColor(Qt::blue)
|
||||
@ -122,7 +141,7 @@
|
||||
#define PATH_AA_SETTING "pathAntiAliasing"
|
||||
#define PATH_AA_DEFAULT true
|
||||
#define GRAPH_AA_SETTING "graphAntiAliasing"
|
||||
#define GRAPH_AA_DEFAULT false
|
||||
#define GRAPH_AA_DEFAULT true
|
||||
#define ELEVATION_FILTER_SETTING "elevationFilter"
|
||||
#define ELEVATION_FILTER_DEFAULT 3
|
||||
#define SPEED_FILTER_SETTING "speedFilter"
|
||||
@ -149,6 +168,9 @@
|
||||
#define SHOW_SECONDARY_ELEVATION_DEFAULT false
|
||||
#define SHOW_SECONDARY_SPEED_SETTING "showSecondarySpeed"
|
||||
#define SHOW_SECONDARY_SPEED_DEFAULT false
|
||||
#define TIME_ZONE_SETTING "timeZone"
|
||||
#define USE_SEGMENTS_SETTING "useSegments"
|
||||
#define USE_SEGMENTS_DEFAULT true
|
||||
#define POI_RADIUS_SETTING "poiRadius"
|
||||
#define POI_RADIUS_DEFAULT (int)(IMPERIAL_UNITS() ? MIINM : KMINM)
|
||||
#define USE_OPENGL_SETTING "useOpenGL"
|
||||
|
69
src/GUI/timezoneinfo.h
Normal file
@ -0,0 +1,69 @@
|
||||
#ifndef TIMEZONEINFO_H
|
||||
#define TIMEZONEINFO_H
|
||||
|
||||
#include <QTimeZone>
|
||||
#include <QDataStream>
|
||||
|
||||
class TimeZoneInfo
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
UTC,
|
||||
System,
|
||||
Custom
|
||||
};
|
||||
|
||||
TimeZoneInfo() : _type(UTC), _customZone(QTimeZone::systemTimeZone()) {}
|
||||
|
||||
Type type() const {return _type;}
|
||||
const QTimeZone &customZone() const {return _customZone;}
|
||||
QTimeZone zone() const
|
||||
{
|
||||
if (_type == UTC)
|
||||
return QTimeZone::utc();
|
||||
else if (_type == System)
|
||||
return QTimeZone::systemTimeZone();
|
||||
else
|
||||
return _customZone;
|
||||
}
|
||||
|
||||
void setType(Type type) {_type = type;}
|
||||
void setCustomZone(const QTimeZone &zone) {_customZone = zone;}
|
||||
|
||||
bool operator==(const TimeZoneInfo &other) const
|
||||
{
|
||||
if (_type == UTC || _type == System)
|
||||
return _type == other._type;
|
||||
else
|
||||
return (other._type == Custom && _customZone == other._customZone);
|
||||
}
|
||||
bool operator!=(const TimeZoneInfo &other) {return !(*this == other);}
|
||||
|
||||
private:
|
||||
friend QDataStream& operator<<(QDataStream &out, const TimeZoneInfo &info);
|
||||
friend QDataStream& operator>>(QDataStream &in, TimeZoneInfo &info);
|
||||
|
||||
Type _type;
|
||||
QTimeZone _customZone;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(TimeZoneInfo)
|
||||
|
||||
inline QDataStream &operator<<(QDataStream &out, const TimeZoneInfo &info)
|
||||
{
|
||||
out << static_cast<int>(info._type) << info._customZone;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline QDataStream &operator>>(QDataStream &in, TimeZoneInfo &info)
|
||||
{
|
||||
int t;
|
||||
|
||||
in >> t;
|
||||
info._type = static_cast<TimeZoneInfo::Type>(t);
|
||||
in >> info._customZone;
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
#endif // TIMEZONEINFO_H
|
@ -22,7 +22,13 @@ QString TrackItem::info() const
|
||||
if (_movingTime > 0)
|
||||
tt.insert(tr("Moving time"), Format::timeSpan(_movingTime));
|
||||
if (!_date.isNull())
|
||||
tt.insert(tr("Date"), _date.toString(Qt::SystemLocaleShortDate));
|
||||
tt.insert(tr("Date"),
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
_date.toTimeZone(_timeZone)
|
||||
#else // ENABLE_TIMEZONES
|
||||
_date
|
||||
#endif // ENABLE_TIMEZONES
|
||||
.toString(Qt::SystemLocaleShortDate));
|
||||
if (!_links.isEmpty()) {
|
||||
QString links;
|
||||
for (int i = 0; i < _links.size(); i++) {
|
||||
|
@ -16,6 +16,7 @@ enum Units {
|
||||
#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
|
||||
|
||||
|
@ -13,6 +13,13 @@
|
||||
#define FS(size) \
|
||||
((int)((qreal)size * 1.41))
|
||||
|
||||
|
||||
Units WaypointItem::_units = Metric;
|
||||
CoordinatesFormat WaypointItem::_format = DecimalDegrees;
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
QTimeZone WaypointItem::_timeZone = QTimeZone::utc();
|
||||
#endif // ENABLE_TIMEZONES
|
||||
|
||||
QString WaypointItem::info() const
|
||||
{
|
||||
ToolTip tt;
|
||||
@ -30,7 +37,12 @@ QString WaypointItem::info() const
|
||||
}
|
||||
if (_waypoint.timestamp().isValid())
|
||||
tt.insert(qApp->translate("WaypointItem", "Date"),
|
||||
_waypoint.timestamp().toString(Qt::SystemLocaleShortDate));
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
_waypoint.timestamp().toTimeZone(_timeZone)
|
||||
#else // ENABLE_TIMEZONES
|
||||
_waypoint.timestamp()
|
||||
#endif // ENABLE_TIMEZONES
|
||||
.toString(Qt::SystemLocaleShortDate));
|
||||
if (!_waypoint.description().isEmpty())
|
||||
tt.insert(qApp->translate("WaypointItem", "Description"),
|
||||
_waypoint.description());
|
||||
@ -78,9 +90,6 @@ WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map,
|
||||
_font.setPixelSize(FS(_size));
|
||||
_font.setFamily(FONT_FAMILY);
|
||||
|
||||
_units = Metric;
|
||||
_format = DecimalDegrees;
|
||||
|
||||
updateCache();
|
||||
|
||||
setPos(map->ll2xy(waypoint.coordinates()));
|
||||
@ -151,12 +160,6 @@ void WaypointItem::setColor(const QColor &color)
|
||||
update();
|
||||
}
|
||||
|
||||
void WaypointItem::setToolTipFormat(Units units, CoordinatesFormat format)
|
||||
{
|
||||
_units = units;
|
||||
_format = format;
|
||||
}
|
||||
|
||||
void WaypointItem::showLabel(bool show)
|
||||
{
|
||||
if (_showLabel == show)
|
||||
|
@ -1,9 +1,13 @@
|
||||
#ifndef WAYPOINTITEM_H
|
||||
#define WAYPOINTITEM_H
|
||||
|
||||
#include "common/config.h"
|
||||
#include <cmath>
|
||||
#include <QGraphicsItem>
|
||||
#include <QFont>
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
#include <QTimeZone>
|
||||
#endif // ENABLE_TIMEZONES
|
||||
#include "data/waypoint.h"
|
||||
#include "map/map.h"
|
||||
#include "units.h"
|
||||
@ -23,7 +27,6 @@ public:
|
||||
void setColor(const QColor &color);
|
||||
void showLabel(bool show);
|
||||
void setDigitalZoom(int zoom) {setScale(pow(2, -zoom));}
|
||||
void setToolTipFormat(Units units, CoordinatesFormat format);
|
||||
|
||||
QPainterPath shape() const {return _shape;}
|
||||
QRectF boundingRect() const {return _shape.boundingRect();}
|
||||
@ -32,6 +35,13 @@ public:
|
||||
|
||||
QString info() const;
|
||||
|
||||
static void setUnits(Units units) {_units = units;}
|
||||
static void setCoordinatesFormat(CoordinatesFormat format)
|
||||
{_format = format;}
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
static void setTimeZone(const QTimeZone &zone) {_timeZone = zone;}
|
||||
#endif // ENABLE_TIMEZONES
|
||||
|
||||
protected:
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||
@ -48,8 +58,11 @@ private:
|
||||
QFont _font;
|
||||
QRect _labelBB;
|
||||
|
||||
Units _units;
|
||||
CoordinatesFormat _format;
|
||||
static Units _units;
|
||||
static CoordinatesFormat _format;
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
static QTimeZone _timeZone;
|
||||
#endif // ENABLE_TIMEZONES
|
||||
};
|
||||
|
||||
#endif // WAYPOINTITEM_H
|
||||
|
@ -18,4 +18,8 @@
|
||||
#define ENABLE_GEOJSON
|
||||
#endif // QT >= 5.0
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
|
||||
#define ENABLE_TIMEZONES
|
||||
#endif // QT >= 5.5
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
|
@ -15,7 +15,8 @@ public:
|
||||
bool isNull() const
|
||||
{return _tl.isNull() && _br.isNull();}
|
||||
bool isValid() const
|
||||
{return (_tl.isValid() && _br.isValid() && _tl != _br);}
|
||||
{return (_tl.isValid() && _br.isValid()
|
||||
&& _tl.lat() > _br.lat() && _tl.lon() < _br.lon());}
|
||||
|
||||
Coordinates topLeft() const {return _tl;}
|
||||
Coordinates bottomRight() const {return _br;}
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef RTREE_H
|
||||
#define RTREE_H
|
||||
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <QtGlobal>
|
||||
@ -387,10 +386,10 @@ RTREE_TEMPLATE
|
||||
void RTREE_QUAL::Insert(const ELEMTYPE a_min[NUMDIMS],
|
||||
const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
#ifndef QT_NO_DEBUG
|
||||
for (int index=0; index<NUMDIMS; ++index)
|
||||
Q_ASSERT(a_min[index] <= a_max[index]);
|
||||
#endif //_DEBUG
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
Rect rect;
|
||||
|
||||
@ -407,10 +406,10 @@ RTREE_TEMPLATE
|
||||
void RTREE_QUAL::Remove(const ELEMTYPE a_min[NUMDIMS],
|
||||
const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
#ifndef QT_NO_DEBUG
|
||||
for (int index=0; index<NUMDIMS; ++index)
|
||||
Q_ASSERT(a_min[index] <= a_max[index]);
|
||||
#endif //_DEBUG
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
Rect rect;
|
||||
|
||||
@ -427,10 +426,10 @@ RTREE_TEMPLATE
|
||||
int RTREE_QUAL::Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS],
|
||||
bool a_resultCallback(DATATYPE a_data, void* a_context), void* a_context) const
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
#ifndef QT_NO_DEBUG
|
||||
for (int index=0; index<NUMDIMS; ++index)
|
||||
Q_ASSERT(a_min[index] <= a_max[index]);
|
||||
#endif //_DEBUG
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
Rect rect;
|
||||
|
||||
@ -636,10 +635,10 @@ bool RTREE_QUAL::InsertRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root,
|
||||
{
|
||||
Q_ASSERT(a_rect && a_root);
|
||||
Q_ASSERT(a_level >= 0 && a_level <= (*a_root)->m_level);
|
||||
#ifdef _DEBUG
|
||||
#ifndef QT_NO_DEBUG
|
||||
for (int index=0; index < NUMDIMS; ++index)
|
||||
Q_ASSERT(a_rect->m_min[index] <= a_rect->m_max[index]);
|
||||
#endif //_DEBUG
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
Node* newRoot;
|
||||
Node* newNode;
|
||||
|
@ -33,18 +33,18 @@ public:
|
||||
return false;
|
||||
|
||||
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
||||
if (_be)
|
||||
val = data;
|
||||
else {
|
||||
for (size_t i = 0; i < sizeof(T); i++)
|
||||
*((char *)&val + i) = *((char*)&data + sizeof(T) - 1 - i);
|
||||
}
|
||||
if (_be)
|
||||
val = data;
|
||||
else {
|
||||
for (size_t i = 0; i < sizeof(T); i++)
|
||||
*((char *)&val + i) = *((char*)&data + sizeof(T) - 1 - i);
|
||||
}
|
||||
#else
|
||||
if (_be) {
|
||||
for (size_t i = 0; i < sizeof(T); i++)
|
||||
*((char *)&val + i) = *((char*)&data + sizeof(T) - 1 - i);
|
||||
} else
|
||||
val = data;
|
||||
if (_be) {
|
||||
for (size_t i = 0; i < sizeof(T); i++)
|
||||
*((char *)&val + i) = *((char*)&data + sizeof(T) - 1 - i);
|
||||
} else
|
||||
val = data;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -585,7 +585,9 @@ void KMLParser::document(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints)
|
||||
{
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("Placemark"))
|
||||
if (_reader.name() == QLatin1String("Document"))
|
||||
document(tracks, areas, waypoints);
|
||||
else if (_reader.name() == QLatin1String("Placemark"))
|
||||
placemark(tracks, areas, waypoints);
|
||||
else if (_reader.name() == QLatin1String("Folder"))
|
||||
folder(tracks, areas, waypoints);
|
||||
|
@ -66,13 +66,25 @@ void TCXParser::heartRateBpm(Trackpoint &trackpoint)
|
||||
}
|
||||
}
|
||||
|
||||
void TCXParser::extensions(Trackpoint &trackpoint)
|
||||
void TCXParser::TPX(Trackpoint &trackpoint)
|
||||
{
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("RunCadence"))
|
||||
trackpoint.setCadence(number());
|
||||
else if (_reader.name() == QLatin1String("Watts"))
|
||||
trackpoint.setPower(number());
|
||||
else if (_reader.name() == QLatin1String("Speed"))
|
||||
trackpoint.setSpeed(number());
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void TCXParser::extensions(Trackpoint &trackpoint)
|
||||
{
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("TPX"))
|
||||
TPX(trackpoint);
|
||||
else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ private:
|
||||
void trackpointData(Trackpoint &trackpoint);
|
||||
void waypointData(Waypoint &waypoint);
|
||||
void extensions(Trackpoint &trackpoint);
|
||||
void TPX(Trackpoint &trackpoint);
|
||||
void heartRateBpm(Trackpoint &trackpoint);
|
||||
Coordinates position();
|
||||
qreal number();
|
||||
|
@ -17,7 +17,7 @@ bool Track::_useReportedSpeed = false;
|
||||
bool Track::_useDEM = false;
|
||||
bool Track::_show2ndElevation = false;
|
||||
bool Track::_show2ndSpeed = false;
|
||||
|
||||
bool Track::_useSegments = true;
|
||||
|
||||
static qreal avg(const QVector<qreal> &v)
|
||||
{
|
||||
@ -42,6 +42,12 @@ static qreal MAD(QVector<qreal> &v, qreal m)
|
||||
return median(v);
|
||||
}
|
||||
|
||||
/*
|
||||
Modified Z-score (Iglewicz and Hoaglin)
|
||||
The acceleration data distribution has usualy a (much) higher kurtosis than
|
||||
the normal distribution thus a higher comparsion value than the usual 3.5 is
|
||||
required.
|
||||
*/
|
||||
static QSet<int> eliminate(const QVector<qreal> &v)
|
||||
{
|
||||
QSet<int> rm;
|
||||
@ -51,7 +57,7 @@ static QSet<int> eliminate(const QVector<qreal> &v)
|
||||
qreal M = MAD(w, m);
|
||||
|
||||
for (int i = 0; i < v.size(); i++)
|
||||
if (qAbs((0.6745 * (v.at(i) - m)) / M) > 3.5)
|
||||
if (qAbs((0.6745 * (v.at(i) - m)) / M) > 5.0)
|
||||
rm.insert(i);
|
||||
|
||||
return rm;
|
||||
@ -82,10 +88,20 @@ static GraphSegment filter(const GraphSegment &g, int window)
|
||||
}
|
||||
|
||||
|
||||
Track::Track(const TrackData &data) : _data(data), _pause(0)
|
||||
Track::Track(const TrackData &data) : _pause(0)
|
||||
{
|
||||
qreal ds, dt;
|
||||
|
||||
if (_useSegments)
|
||||
_data = data;
|
||||
else {
|
||||
if (!data.isEmpty()) {
|
||||
_data.append(data.first());
|
||||
for (int i = 1; i < data.size(); i++)
|
||||
_data.first() << data.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _data.size(); i++) {
|
||||
const SegmentData &sd = _data.at(i);
|
||||
_segments.append(Segment());
|
||||
|
@ -49,10 +49,9 @@ public:
|
||||
{_outlierEliminate = eliminate;}
|
||||
static void useReportedSpeed(bool use) {_useReportedSpeed = use;}
|
||||
static void useDEM(bool use) {_useDEM = use;}
|
||||
static void showSecondaryElevation(bool show)
|
||||
{_show2ndElevation = show;}
|
||||
static void showSecondarySpeed(bool show)
|
||||
{_show2ndSpeed = show;}
|
||||
static void showSecondaryElevation(bool show) {_show2ndElevation = show;}
|
||||
static void showSecondarySpeed(bool show) {_show2ndSpeed = show;}
|
||||
static void useSegments(bool use) {_useSegments = use;}
|
||||
|
||||
private:
|
||||
struct Segment {
|
||||
@ -87,6 +86,7 @@ private:
|
||||
static bool _useDEM;
|
||||
static bool _show2ndElevation;
|
||||
static bool _show2ndSpeed;
|
||||
static bool _useSegments;
|
||||
};
|
||||
|
||||
#endif // TRACK_H
|
||||
|
@ -1,4 +1,7 @@
|
||||
#include "common/config.h"
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
#include "GUI/timezoneinfo.h"
|
||||
#endif // ENABLE_TIMEZONES
|
||||
#include "GUI/app.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@ -7,6 +10,9 @@ int main(int argc, char *argv[])
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#endif // ENABLE_HIDPI
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
qRegisterMetaTypeStreamOperators<TimeZoneInfo>("TimeZoneInfo");
|
||||
#endif // ENABLE_TIMEZONES
|
||||
|
||||
App app(argc, argv);
|
||||
return app.run();
|
||||
|
@ -1,38 +1,9 @@
|
||||
#include "bitstream.h"
|
||||
|
||||
|
||||
bool BitStream1::read(int bits, quint32 &val)
|
||||
{
|
||||
val = 0;
|
||||
|
||||
for (int pos = 0; pos < bits; ) {
|
||||
if (!_remaining) {
|
||||
if (!_length || !_file.readUInt8(_hdl, _data))
|
||||
return false;
|
||||
_remaining = 8;
|
||||
_length--;
|
||||
}
|
||||
|
||||
quint32 get = bits - pos;
|
||||
if (get >= _remaining) {
|
||||
val |= _data << pos;
|
||||
pos += _remaining;
|
||||
_remaining = 0;
|
||||
} else {
|
||||
quint32 mask = (1<<get) - 1;
|
||||
val |= (_data & mask)<<pos;
|
||||
_data >>= get;
|
||||
_remaining -= get;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitStream1::flush()
|
||||
{
|
||||
if (_length && !_file.seek(_hdl, _hdl.pos() + _length))
|
||||
if (_length && !_file.seek(_hdl, _file.pos(_hdl) + _length))
|
||||
return false;
|
||||
|
||||
_length = 0;
|
||||
@ -41,8 +12,35 @@ bool BitStream1::flush()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitStream1::readUInt24(quint32 &val)
|
||||
{
|
||||
quint8 b;
|
||||
|
||||
bool BitStream4::read(int bits, quint32 &val)
|
||||
val = 0;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (!read(8, b))
|
||||
return false;
|
||||
val |= (b << (i * 8));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool BitStream4F::flush()
|
||||
{
|
||||
if (_length && !_file.seek(_hdl, _file.pos(_hdl) + _length))
|
||||
return false;
|
||||
|
||||
_length = 0;
|
||||
_used = 32;
|
||||
_unused = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitStream4F::read(int bits, quint32 &val)
|
||||
{
|
||||
if (bits <= 32 - (int)(_used + _unused)) {
|
||||
val = bits ? (_data << _used) >> (32 - bits) : 0;
|
||||
@ -50,6 +48,8 @@ bool BitStream4::read(int bits, quint32 &val)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_unused)
|
||||
return false;
|
||||
quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0;
|
||||
quint32 bytes = qMin(_length, 4U);
|
||||
|
||||
@ -66,14 +66,149 @@ bool BitStream4::read(int bits, quint32 &val)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitStream4::flush()
|
||||
BitStream4R::BitStream4R(const SubFile &file, SubFile::Handle &hdl,
|
||||
quint32 length) : BitStream4(file, hdl, length)
|
||||
{
|
||||
if (_length && !_file.seek(_hdl, _hdl.pos() + _length))
|
||||
return false;
|
||||
_file.seek(_hdl, _file.pos(_hdl) - 4);
|
||||
}
|
||||
|
||||
_length = 0;
|
||||
_used = 32;
|
||||
_unused = 0;
|
||||
bool BitStream4R::readBytes(int bytes, quint32 &val)
|
||||
{
|
||||
quint32 bits = _used % 8;
|
||||
quint32 b;
|
||||
|
||||
if (bits) {
|
||||
if (!read(8 - bits, b))
|
||||
return false;
|
||||
Q_ASSERT(!b);
|
||||
}
|
||||
|
||||
val = 0;
|
||||
for (int i = 0; i < bytes; i++) {
|
||||
if (!read(8, b))
|
||||
return false;
|
||||
val |= (b << (i * 8));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitStream4R::readVUInt32(quint32 &val)
|
||||
{
|
||||
quint32 b;
|
||||
quint8 bytes, shift;
|
||||
|
||||
if (!readBytes(1, b))
|
||||
return false;
|
||||
|
||||
if ((b & 1) == 0) {
|
||||
if ((b & 2) == 0) {
|
||||
bytes = ((b >> 2) & 1) ^ 3;
|
||||
shift = 5;
|
||||
} else {
|
||||
shift = 6;
|
||||
bytes = 1;
|
||||
}
|
||||
} else {
|
||||
shift = 7;
|
||||
bytes = 0;
|
||||
}
|
||||
|
||||
val = b >> (8 - shift);
|
||||
|
||||
if (bytes) {
|
||||
if (!readBytes(bytes, b))
|
||||
return false;
|
||||
val = val | (b << shift);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitStream4R::readVuint32SM(quint32 &val1, quint32 &val2, quint32 &val2Bits)
|
||||
{
|
||||
quint32 b, eb;
|
||||
|
||||
if (!readBytes(1, b))
|
||||
return false;
|
||||
|
||||
if (!(b & 1)) {
|
||||
val1 = b >> 3;
|
||||
val2 = b >> 1 & 3;
|
||||
val2Bits = 2;
|
||||
} else {
|
||||
eb = b & 2;
|
||||
val2 = b >> 2 & 0x3f;
|
||||
val2Bits = eb * 2 + 6;
|
||||
if (!readBytes((eb >> 1 | 2) - 1, b))
|
||||
return false;
|
||||
if (eb) {
|
||||
val2 = val2 | (b & 0xf) << 6;
|
||||
b = b >> 4 & 0xfff;
|
||||
}
|
||||
val1 = b;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitStream4R::skip(quint32 bytes)
|
||||
{
|
||||
if (bytes * 8 > bitsAvailable())
|
||||
return false;
|
||||
|
||||
quint32 ab = (32 - (_used + _unused))/8;
|
||||
if (bytes <= ab)
|
||||
_used += bytes * 8;
|
||||
else {
|
||||
quint32 seek = ((bytes - ab)/4)*4;
|
||||
quint32 read = (bytes - ab)%4;
|
||||
if (seek && !_file.seek(_hdl, _file.pos(_hdl) - seek))
|
||||
return false;
|
||||
_length -= seek;
|
||||
if (read) {
|
||||
quint32 rb = qMin(_length, 4U);
|
||||
if (!_file.readUInt32(_hdl, _data))
|
||||
return false;
|
||||
if (!_file.seek(_hdl, _file.pos(_hdl) - 8))
|
||||
return false;
|
||||
_length -= rb;
|
||||
_unused = (4 - rb) * 8;
|
||||
_used = read * 8;
|
||||
} else
|
||||
_used = 32;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BitStream4R::resize(quint32 bytes)
|
||||
{
|
||||
quint32 ab = (32 - (_used + _unused) + 7)/8;
|
||||
|
||||
if (ab <= bytes)
|
||||
_length = bytes - ab;
|
||||
else {
|
||||
_length = 0;
|
||||
_unused += (ab - bytes) * 8;
|
||||
}
|
||||
}
|
||||
|
||||
void BitStream4R::save(State &state)
|
||||
{
|
||||
state.pos = _file.pos(_hdl);
|
||||
state.length = _length;
|
||||
state.used = _used;
|
||||
state.unused = _unused;
|
||||
state.data = _data;
|
||||
}
|
||||
|
||||
bool BitStream4R::restore(const State &state)
|
||||
{
|
||||
_length = state.length;
|
||||
_used = state.used;
|
||||
_unused = state.unused;
|
||||
_data = state.data;
|
||||
|
||||
return _file.seek(_hdl, state.pos);
|
||||
}
|
||||
|
@ -8,9 +8,11 @@ public:
|
||||
BitStream1(const SubFile &file, SubFile::Handle &hdl, quint32 length)
|
||||
: _file(file), _hdl(hdl), _length(length), _remaining(0) {}
|
||||
|
||||
bool read(int bits, quint32 &val);
|
||||
template<typename T> bool read(int bits, T &val);
|
||||
bool flush();
|
||||
quint32 bitsAvailable() const {return _length * 8 + _remaining;}
|
||||
quint64 bitsAvailable() const {return (quint64)_length * 8 + _remaining;}
|
||||
|
||||
bool readUInt24(quint32 &val);
|
||||
|
||||
private:
|
||||
const SubFile &_file;
|
||||
@ -25,15 +27,105 @@ public:
|
||||
: _file(file), _hdl(hdl), _length(length), _used(32), _unused(0),
|
||||
_data(0) {}
|
||||
|
||||
bool read(int bits, quint32 &val);
|
||||
bool flush();
|
||||
quint32 bitsAvailable() const {return _length * 8 + (32 - _used) - _unused;}
|
||||
quint64 bitsAvailable() const
|
||||
{return (quint64)_length * 8 + (32 - _used) - _unused;}
|
||||
|
||||
private:
|
||||
protected:
|
||||
const SubFile &_file;
|
||||
SubFile::Handle &_hdl;
|
||||
quint32 _length, _used, _unused;
|
||||
quint32 _data;
|
||||
};
|
||||
|
||||
class BitStream4F : public BitStream4 {
|
||||
public:
|
||||
BitStream4F(const SubFile &file, SubFile::Handle &hdl, quint32 length)
|
||||
: BitStream4(file, hdl, length) {}
|
||||
|
||||
bool read(int bits, quint32 &val);
|
||||
bool flush();
|
||||
};
|
||||
|
||||
class BitStream4R : public BitStream4 {
|
||||
public:
|
||||
struct State {
|
||||
quint32 pos;
|
||||
quint32 length;
|
||||
quint32 used;
|
||||
quint32 unused;
|
||||
quint32 data;
|
||||
};
|
||||
|
||||
BitStream4R(const SubFile &file, SubFile::Handle &hdl, quint32 length);
|
||||
|
||||
template<typename T> bool read(int bits, T &val);
|
||||
bool readBytes(int bytes, quint32 &val);
|
||||
bool readVUInt32(quint32 &val);
|
||||
bool readVuint32SM(quint32 &val1, quint32 &val2, quint32 &val2Bits);
|
||||
|
||||
bool skip(quint32 bytes);
|
||||
void resize(quint32 bytes);
|
||||
void save(State &state);
|
||||
bool restore(const State &state);
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool BitStream1::read(int bits, T &val)
|
||||
{
|
||||
val = 0;
|
||||
|
||||
for (int pos = 0; pos < bits; ) {
|
||||
if (!_remaining) {
|
||||
if (!_length || !_file.readUInt8(_hdl, _data))
|
||||
return false;
|
||||
_remaining = 8;
|
||||
_length--;
|
||||
}
|
||||
|
||||
quint32 get = bits - pos;
|
||||
if (get >= _remaining) {
|
||||
val |= _data << pos;
|
||||
pos += _remaining;
|
||||
_remaining = 0;
|
||||
} else {
|
||||
quint32 mask = (1<<get) - 1;
|
||||
val |= (_data & mask)<<pos;
|
||||
_data >>= get;
|
||||
_remaining -= get;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool BitStream4R::read(int bits, T &val)
|
||||
{
|
||||
if (bits <= 32 - (int)(_used + _unused)) {
|
||||
val = bits ? (_data << _used) >> (32 - bits) : 0;
|
||||
_used += bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_unused)
|
||||
return false;
|
||||
quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0;
|
||||
quint32 bytes = qMin(_length, 4U);
|
||||
|
||||
if (!_file.readUInt32(_hdl, _data))
|
||||
return false;
|
||||
if (!_file.seek(_hdl, _file.pos(_hdl) - 8))
|
||||
return false;
|
||||
|
||||
_length -= bytes;
|
||||
_used -= 32 - bits;
|
||||
_unused = (4 - bytes) * 8;
|
||||
|
||||
val = _data >> (32 - _used) | old;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // BITSTREAM_H
|
||||
|
@ -1,74 +1,41 @@
|
||||
#include "huffmanstream.h"
|
||||
|
||||
|
||||
HuffmanStream::HuffmanStream(const SubFile &file, SubFile::Handle &hdl,
|
||||
quint32 length, const HuffmanTable &table, bool line)
|
||||
: BitStream4(file, hdl, length), _table(table), _symbolDataSize(0),
|
||||
_symbolData(0)
|
||||
bool HuffmanStreamF::init(bool line)
|
||||
{
|
||||
if (line) {
|
||||
if (!(sign(_lonSign) && sign(_latSign)))
|
||||
return;
|
||||
return false;
|
||||
} else {
|
||||
_lonSign = 0;
|
||||
_latSign = 0;
|
||||
}
|
||||
|
||||
quint32 eb;
|
||||
if (!read(1, eb))
|
||||
return;
|
||||
if (eb) {
|
||||
qWarning("Extended polygon/lines not supported");
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
bool HuffmanStream::sign(int &val)
|
||||
{
|
||||
quint32 bit;
|
||||
val = 0;
|
||||
|
||||
if (!read(1, bit))
|
||||
if (!_bs.read(1, eb))
|
||||
return false;
|
||||
|
||||
Q_ASSERT(!eb);
|
||||
if (eb)
|
||||
return false;
|
||||
if (bit) {
|
||||
if (!read(1, bit))
|
||||
return false;
|
||||
val = bit ? -1 : 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HuffmanStream::readDelta(int sign, qint32 &symbol)
|
||||
bool HuffmanStreamR::init()
|
||||
{
|
||||
quint8 size;
|
||||
quint32 next;
|
||||
quint8 nextSize = qMin((quint32)(32 - _symbolDataSize), bitsAvailable());
|
||||
|
||||
if (!read(nextSize, next))
|
||||
if (!(sign(_lonSign) && sign(_latSign)))
|
||||
return false;
|
||||
|
||||
_symbolData = (_symbolData << nextSize) | next;
|
||||
_symbolDataSize += nextSize;
|
||||
|
||||
symbol = _table.symbol(_symbolData << (32 - _symbolDataSize), size);
|
||||
|
||||
if (size <= _symbolDataSize)
|
||||
_symbolDataSize -= size;
|
||||
else
|
||||
return false;
|
||||
|
||||
if (symbol && !sign) {
|
||||
if (!_symbolDataSize)
|
||||
return false;
|
||||
else {
|
||||
sign = ((1U << (_symbolDataSize - 1)) & _symbolData) ? -1 : 1;
|
||||
_symbolDataSize--;
|
||||
}
|
||||
}
|
||||
symbol = sign * symbol;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HuffmanStreamR::init(int lonSign, int latSign, quint32 data,
|
||||
quint32 dataSize)
|
||||
{
|
||||
_lonSign = lonSign;
|
||||
_latSign = latSign;
|
||||
_symbolData = data;
|
||||
_symbolDataSize = dataSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -4,11 +4,15 @@
|
||||
#include "bitstream.h"
|
||||
#include "huffmantable.h"
|
||||
|
||||
class HuffmanStream : public BitStream4 {
|
||||
template <class BitStream>
|
||||
class HuffmanStream {
|
||||
public:
|
||||
HuffmanStream(const SubFile &file, SubFile::Handle &hdl, quint32 length,
|
||||
const HuffmanTable &table, bool line);
|
||||
HuffmanStream(BitStream &bitstream, const HuffmanTable &table)
|
||||
: _bs(bitstream), _table(table), _symbolDataSize(0), _symbolData(0),
|
||||
_lonSign(0), _latSign(0) {}
|
||||
|
||||
bool read(int bits, quint32 &val);
|
||||
bool readSymbol(quint32 &symbol);
|
||||
bool readNext(qint32 &lonDelta, qint32 &latDelta)
|
||||
{
|
||||
if (!(readDelta(_lonSign, lonDelta) && readDelta(_latSign, latDelta)))
|
||||
@ -17,19 +21,121 @@ public:
|
||||
return (lonDelta || latDelta);
|
||||
}
|
||||
|
||||
bool readOffset(qint32 &lonDelta, qint32 &latDelta)
|
||||
{return (readDelta(1, lonDelta) && readDelta(1, latDelta));}
|
||||
bool atEnd() const
|
||||
{return _symbolDataSize + bitsAvailable() < _table.maxSymbolSize();}
|
||||
{return _symbolDataSize + _bs.bitsAvailable() < _table.maxSymbolSize();}
|
||||
bool flush() {return _bs.flush();}
|
||||
|
||||
private:
|
||||
protected:
|
||||
bool sign(int &val);
|
||||
bool readDelta(int sign, qint32 &delta);
|
||||
|
||||
BitStream &_bs;
|
||||
const HuffmanTable &_table;
|
||||
quint32 _symbolDataSize;
|
||||
quint32 _symbolData;
|
||||
int _lonSign, _latSign;
|
||||
};
|
||||
|
||||
template <class BitStream>
|
||||
bool HuffmanStream<BitStream>::sign(int &val)
|
||||
{
|
||||
quint32 bit;
|
||||
val = 0;
|
||||
|
||||
if (!_bs.read(1, bit))
|
||||
return false;
|
||||
if (bit) {
|
||||
if (!_bs.read(1, bit))
|
||||
return false;
|
||||
val = bit ? -1 : 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BitStream>
|
||||
bool HuffmanStream<BitStream>::read(int bits, quint32 &val)
|
||||
{
|
||||
if (_symbolDataSize < (quint32)bits) {
|
||||
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 < (quint32)bits)
|
||||
return false;
|
||||
|
||||
val = (_symbolData << (32-_symbolDataSize)) >> (32 - bits);
|
||||
_symbolDataSize -= bits;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
symbol = _table.symbol(_symbolData << (32 - _symbolDataSize), size);
|
||||
if (size > _symbolDataSize)
|
||||
return false;
|
||||
|
||||
_symbolDataSize -= size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class BitStream>
|
||||
bool HuffmanStream<BitStream>::readDelta(int sign, qint32 &delta)
|
||||
{
|
||||
quint32 symbol;
|
||||
if (!readSymbol(symbol))
|
||||
return false;
|
||||
|
||||
if (symbol && !sign) {
|
||||
if (!_symbolDataSize)
|
||||
return false;
|
||||
else {
|
||||
sign = ((1U << (_symbolDataSize - 1)) & _symbolData) ? -1 : 1;
|
||||
_symbolDataSize--;
|
||||
}
|
||||
}
|
||||
delta = sign * symbol;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class HuffmanStreamF : public HuffmanStream<BitStream4F> {
|
||||
public:
|
||||
HuffmanStreamF(BitStream4F &bitstream, const HuffmanTable &table)
|
||||
: HuffmanStream(bitstream, table) {}
|
||||
|
||||
bool init(bool line);
|
||||
bool readOffset(qint32 &lonDelta, qint32 &latDelta)
|
||||
{return (readDelta(1, lonDelta) && readDelta(1, latDelta));}
|
||||
};
|
||||
|
||||
class HuffmanStreamR : public HuffmanStream<BitStream4R> {
|
||||
public:
|
||||
HuffmanStreamR(BitStream4R &bitstream, const HuffmanTable &table)
|
||||
: HuffmanStream(bitstream, table) {}
|
||||
|
||||
bool init();
|
||||
bool init(int lonSign, int latSign, quint32 data, quint32 dataSize);
|
||||
};
|
||||
|
||||
#endif // HUFFMANSTREAM_H
|
||||
|
@ -42,6 +42,8 @@ bool HuffmanTable::load(const SubFile &file, SubFile::Handle &hdl,
|
||||
_s10 = _s14 + _s1c * _s1d;
|
||||
_s18 = _s10 + (_s1 << _s0);
|
||||
|
||||
_id = id;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -55,7 +57,7 @@ bool HuffmanTable::getBuffer(const SubFile &file, SubFile::Handle &hdl,
|
||||
return false;
|
||||
if (!file.readVUInt32(hdl, recordSize))
|
||||
return false;
|
||||
recordOffset = hdl.pos() + recordSize;
|
||||
recordOffset = file.pos(hdl) + recordSize;
|
||||
if (recordOffset > offset + size)
|
||||
return false;
|
||||
};
|
||||
|
@ -13,6 +13,8 @@ public:
|
||||
quint8 maxSymbolSize() const {return _s2;}
|
||||
quint32 symbol(quint32 data, quint8 &size) const;
|
||||
|
||||
quint8 id() const {return _id;}
|
||||
|
||||
private:
|
||||
bool getBuffer(const SubFile &file, SubFile::Handle &hdl, quint32 offset,
|
||||
quint32 size, quint8 id);
|
||||
@ -22,6 +24,8 @@ private:
|
||||
quint8 *_s10, *_s14, *_s18;
|
||||
quint8 _s1c, _s1d, _s1e, _s1f, _s20;
|
||||
quint16 _s22;
|
||||
|
||||
quint8 _id;
|
||||
};
|
||||
|
||||
#endif // HUFFMANTABLE_H
|
||||
|
@ -59,7 +59,7 @@ IMG::IMG(const QString &fileName) : _file(fileName)
|
||||
|
||||
QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2)));
|
||||
_name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed();
|
||||
_blockSize = 1 << (e1 + e2);
|
||||
_blockBits = e1 + e2;
|
||||
|
||||
// Read the FAT table
|
||||
quint8 flag;
|
||||
@ -132,7 +132,6 @@ IMG::IMG(const QString &fileName) : _file(fileName)
|
||||
}
|
||||
|
||||
// Create tile tree
|
||||
|
||||
int minMapZoom = 24;
|
||||
for (TileMap::const_iterator it = tileMap.constBegin();
|
||||
it != tileMap.constEnd(); ++it) {
|
||||
@ -159,14 +158,19 @@ IMG::IMG(const QString &fileName) : _file(fileName)
|
||||
minMapZoom = tile->zooms().min();
|
||||
}
|
||||
|
||||
for (TileMap::const_iterator it = tileMap.constBegin();
|
||||
it != tileMap.constEnd(); ++it) {
|
||||
VectorTile *tile = it.value();
|
||||
// Detect and mark basemap
|
||||
TileTree::Iterator it;
|
||||
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it)) {
|
||||
VectorTile *tile = _tileTree.GetAt(it);
|
||||
if (tile->zooms().min() > minMapZoom)
|
||||
_baseMap = true;
|
||||
if (tile->zooms().min() == minMapZoom)
|
||||
tile->markAsBasemap();
|
||||
}
|
||||
// Allow some extra zoom out on maps without basemaps, but not too much as
|
||||
// this would kill the rendering performance
|
||||
if (!_baseMap)
|
||||
_zooms.setMin(_zooms.min() - 2);
|
||||
|
||||
if (!_tileTree.Count())
|
||||
_errorString = "No usable map tile found";
|
||||
@ -197,9 +201,9 @@ template<class T> bool IMG::readValue(T &val)
|
||||
|
||||
bool IMG::readBlock(int blockNum, char *data)
|
||||
{
|
||||
if (!_file.seek((qint64)blockNum * (qint64)_blockSize))
|
||||
if (!_file.seek((quint64)blockNum << _blockBits))
|
||||
return false;
|
||||
if (read(data, _blockSize) < _blockSize)
|
||||
if (read(data, 1U<<_blockBits) < 1U<<_blockBits)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -14,14 +14,14 @@ public:
|
||||
private:
|
||||
friend class SubFile;
|
||||
|
||||
int blockSize() const {return _blockSize;}
|
||||
unsigned blockBits() const {return _blockBits;}
|
||||
bool readBlock(int blockNum, char *data);
|
||||
qint64 read(char *data, qint64 maxSize);
|
||||
template<class T> bool readValue(T &val);
|
||||
|
||||
QFile _file;
|
||||
quint8 _key;
|
||||
int _blockSize;
|
||||
unsigned _blockBits;
|
||||
};
|
||||
|
||||
#endif // IMG_H
|
||||
|
@ -161,7 +161,7 @@ Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
|
||||
} else if (c <= 0x07) {
|
||||
shieldType = static_cast<Label::Shield::Type>(c);
|
||||
bap = &shieldLabel;
|
||||
} else if (bap == &shieldLabel && QChar(c).isSpace()) {
|
||||
} else if (bap == &shieldLabel && c == 0x20) {
|
||||
bap = &label;
|
||||
} else
|
||||
bap->append(c);
|
||||
|
@ -54,7 +54,7 @@ inline bool pointCb(VectorTile *tile, void *context)
|
||||
}
|
||||
|
||||
|
||||
MapData::MapData() : _typ(0), _style(0), _zooms(15, 28), _baseMap(false),
|
||||
MapData::MapData() : _typ(0), _style(0), _zooms(24, 28), _baseMap(false),
|
||||
_valid(false)
|
||||
{
|
||||
_polyCache.setMaxCost(CACHED_SUBDIVS_COUNT);
|
||||
|
@ -38,7 +38,6 @@ public:
|
||||
Coordinates coordinates;
|
||||
Label label;
|
||||
quint32 type;
|
||||
bool poi;
|
||||
quint64 id;
|
||||
|
||||
bool operator<(const Point &other) const
|
||||
@ -95,8 +94,7 @@ private:
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const MapData::Point &point)
|
||||
{
|
||||
dbg.nospace() << "Point(" << hex << point.type << ", " << point.label
|
||||
<< ", " << point.poi << ")";
|
||||
dbg.nospace() << "Point(" << hex << point.type << ", " << point.label << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
|
@ -1,26 +1,507 @@
|
||||
#include "bitstream.h"
|
||||
#include "huffmanstream.h"
|
||||
#include "subdiv.h"
|
||||
#include "nodfile.h"
|
||||
#include "lblfile.h"
|
||||
#include "netfile.h"
|
||||
|
||||
|
||||
static bool readAdjCounts(BitStream4R &bs, QVector<quint16> &cnts, quint16 &mask)
|
||||
{
|
||||
quint32 val, cnt, bits;
|
||||
if (!bs.read(4, val))
|
||||
return false;
|
||||
|
||||
cnt = ((val >> 2) & 3) + 2;
|
||||
bits = ((val * 2) & 6) + 4;
|
||||
mask = 1<<(3 + ((val * 2) & 6));
|
||||
if (cnt == 5) {
|
||||
if (!bs.read(8, cnt))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cnt < 2)
|
||||
return false;
|
||||
cnts.resize(cnt - 1);
|
||||
for (int i = 0; i < cnts.size(); i++)
|
||||
if (!bs.read(bits, cnts[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool skipShape(BitStream4R &bs)
|
||||
{
|
||||
quint32 v1, v2, v2b;
|
||||
|
||||
if (!bs.readVuint32SM(v1, v2, v2b))
|
||||
return false;
|
||||
|
||||
return bs.skip(v1);
|
||||
}
|
||||
|
||||
static bool skipAdjShapes(BitStream4R &bs, const QVector<quint16> &cnts,
|
||||
quint16 mask, bool firstIsShape)
|
||||
{
|
||||
if (firstIsShape && !skipShape(bs))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < cnts.size(); i++) {
|
||||
if (cnts.at(i) & mask) {
|
||||
if (!skipShape(bs))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool seekToLevel(BitStream4R &bs, quint8 level)
|
||||
{
|
||||
quint32 v1, v2, v2b;
|
||||
|
||||
for (quint8 i = 1; i < level; ) {
|
||||
if (!bs.readVuint32SM(v1, v2, v2b))
|
||||
return false;
|
||||
if (!bs.skip(v1))
|
||||
return false;
|
||||
|
||||
if (v2 & 2)
|
||||
return false;
|
||||
if (v2 & 1)
|
||||
i++;
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool seekToLine(BitStream4R &bs, quint8 line)
|
||||
{
|
||||
quint32 v1, v2, v2b;
|
||||
|
||||
for (quint8 i = 0; i < line; i++) {
|
||||
if (!bs.readVuint32SM(v1, v2, v2b))
|
||||
return false;
|
||||
if (!bs.skip(v1))
|
||||
return false;
|
||||
|
||||
if (v2 & 2)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readLine(BitStream4R &bs, const SubDiv *subdiv,
|
||||
const HuffmanTable &table, IMG::Poly &poly)
|
||||
{
|
||||
quint32 v1, v2, v2b;
|
||||
if (!bs.readVuint32SM(v1, v2, v2b))
|
||||
return false;
|
||||
bs.resize(v1);
|
||||
|
||||
quint32 lon, lat;
|
||||
if (!(bs.read(0x12 - v2b, lon) && bs.read(16, lat)))
|
||||
return false;
|
||||
if (2 < v2b)
|
||||
lon |= (v2 >> 2) << (0x12U - v2b);
|
||||
|
||||
QPoint pos = QPoint(LS(subdiv->lon(), 8) + LS((qint16)lon, 32-subdiv->bits()),
|
||||
LS(subdiv->lat(), 8) + LS((qint16)lat, 32-subdiv->bits()));
|
||||
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
|
||||
|
||||
poly.boundingRect = RectC(c, c);
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
|
||||
HuffmanStreamR stream(bs, table);
|
||||
if (!stream.init())
|
||||
return false;
|
||||
qint32 lonDelta, latDelta;
|
||||
|
||||
while (stream.readNext(lonDelta, latDelta)) {
|
||||
pos.rx() += LS(lonDelta, 32-subdiv->bits());
|
||||
if (pos.rx() < 0 && subdiv->lon() >= 0)
|
||||
pos.rx() = 0x7fffffff;
|
||||
pos.ry() += LS(latDelta, 32-subdiv->bits());
|
||||
|
||||
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
poly.boundingRect = poly.boundingRect.united(c);
|
||||
}
|
||||
|
||||
return stream.atEnd();
|
||||
}
|
||||
|
||||
static bool readNodeGeometry(NODFile *nod, SubFile::Handle &nodHdl,
|
||||
NODFile::AdjacencyInfo &adj, IMG::Poly &poly, quint16 cnt = 0xFFFF)
|
||||
{
|
||||
for (int i = 0; i <= cnt; i++) {
|
||||
int ret = nod->nextNode(nodHdl, adj);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
else if (ret > 0)
|
||||
return (cnt == 0xFFFF);
|
||||
|
||||
Coordinates c(toWGS32(adj.nodeInfo.pos.x()),
|
||||
toWGS32(adj.nodeInfo.pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
poly.boundingRect = poly.boundingRect.united(c);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool skipNodes(NODFile *nod, SubFile::Handle &nodHdl,
|
||||
NODFile::AdjacencyInfo &adj, int cnt)
|
||||
{
|
||||
for (int i = 0; i < cnt; i++)
|
||||
if (nod->nextNode(nodHdl, adj))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readShape(NODFile *nod, SubFile::Handle &nodHdl,
|
||||
NODFile::AdjacencyInfo &adj, BitStream4R &bs, const HuffmanTable &table,
|
||||
const SubDiv *subdiv, quint32 shift, IMG::Poly &poly, quint16 cnt = 0xFFFF,
|
||||
bool check = false)
|
||||
{
|
||||
quint32 v1, v2, v2b;
|
||||
if (!bs.readVuint32SM(v1, v2, v2b))
|
||||
return false;
|
||||
BitStream4R::State state;
|
||||
bs.save(state);
|
||||
bs.resize(v1);
|
||||
|
||||
quint32 flags;
|
||||
if (!bs.read(8, flags))
|
||||
return false;
|
||||
flags |= (v2 << 8);
|
||||
|
||||
bool hasCoordinatesAdjustBit = flags & (1 << (v2b + 7));
|
||||
bool useEosBit = flags & (1 << (v2b + 5));
|
||||
bool startWithStream = flags & (1 << (v2b + 6));
|
||||
|
||||
quint32 extraBits;
|
||||
int lonSign, latSign;
|
||||
|
||||
if ((flags >> (v2b + 4) & 1) == 0) {
|
||||
extraBits = v2b + 4;
|
||||
lonSign = 0;
|
||||
} else {
|
||||
extraBits = v2b + 3;
|
||||
lonSign = 1;
|
||||
if ((flags >> (v2b + 3) & 1) != 0) {
|
||||
lonSign = -1;
|
||||
}
|
||||
}
|
||||
extraBits -= 1;
|
||||
if ((flags >> extraBits & 1) == 0) {
|
||||
latSign = 0;
|
||||
} else {
|
||||
extraBits -= 1;
|
||||
latSign = -1;
|
||||
if ((flags >> extraBits & 1) == 0) {
|
||||
latSign = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (nod->nextNode(nodHdl, adj))
|
||||
return false;
|
||||
QPoint pos(adj.nodeInfo.pos);
|
||||
quint16 nodes = 0;
|
||||
|
||||
if (!startWithStream) {
|
||||
Coordinates c(toWGS32(adj.nodeInfo.pos.x()),
|
||||
toWGS32(adj.nodeInfo.pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
poly.boundingRect = poly.boundingRect.united(c);
|
||||
|
||||
while (!adj.eog) {
|
||||
int ret = nod->nextNode(nodHdl, adj);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
else if (ret > 0)
|
||||
break;
|
||||
nodes++;
|
||||
|
||||
c = Coordinates(toWGS32(adj.nodeInfo.pos.x()),
|
||||
toWGS32(adj.nodeInfo.pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
poly.boundingRect = poly.boundingRect.united(c);
|
||||
pos = adj.nodeInfo.pos;
|
||||
}
|
||||
}
|
||||
|
||||
HuffmanStreamR stream(bs, table);
|
||||
if (!stream.init(lonSign, latSign, flags, extraBits))
|
||||
return false;
|
||||
qint32 lonDelta, latDelta;
|
||||
QVector<QPoint> deltas;
|
||||
|
||||
quint32 adjustBit = 0;
|
||||
quint32 stepsCnt = 0;
|
||||
quint32 steps = 0;
|
||||
quint32 eos = 0;
|
||||
|
||||
while (true) {
|
||||
if ((stepsCnt == steps) && !useEosBit) {
|
||||
if (!stream.readSymbol(steps))
|
||||
break;
|
||||
if (!steps)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!stream.readNext(lonDelta, latDelta))
|
||||
break;
|
||||
|
||||
if (hasCoordinatesAdjustBit && !stream.read(1, adjustBit))
|
||||
return false;
|
||||
|
||||
stepsCnt++;
|
||||
|
||||
if (useEosBit) {
|
||||
if (!stream.read(1, eos))
|
||||
return false;
|
||||
} else {
|
||||
if (steps == stepsCnt)
|
||||
eos = 1;
|
||||
}
|
||||
|
||||
if (!startWithStream) {
|
||||
pos.rx() += LS(lonDelta, 32-subdiv->bits()-shift);
|
||||
pos.ry() += LS(latDelta, 32-subdiv->bits()-shift);
|
||||
|
||||
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
poly.boundingRect = poly.boundingRect.united(c);
|
||||
} else {
|
||||
deltas.append(QPoint(lonDelta, latDelta));
|
||||
poly.points.append(QPointF());
|
||||
}
|
||||
|
||||
if (startWithStream && eos) {
|
||||
for (int i = deltas.size() - 1, j = 0; i >= 0; i--, j++) {
|
||||
pos.rx() -= LS(deltas.at(i).x(), 32-subdiv->bits()-shift);
|
||||
pos.ry() -= LS(deltas.at(i).y(), 32-subdiv->bits()-shift);
|
||||
|
||||
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
|
||||
poly.points[poly.points.size() - 1 - j] = QPointF(c.lon(), c.lat());
|
||||
poly.boundingRect = poly.boundingRect.united(c);
|
||||
}
|
||||
|
||||
pos = adj.nodeInfo.pos;
|
||||
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
poly.boundingRect = poly.boundingRect.united(c);
|
||||
|
||||
stepsCnt = 0;
|
||||
steps = 0;
|
||||
startWithStream = false;
|
||||
|
||||
if (adj.eog)
|
||||
eos = 0;
|
||||
}
|
||||
|
||||
if (eos) {
|
||||
if (nodes >= cnt)
|
||||
break;
|
||||
|
||||
do {
|
||||
int ret = nod->nextNode(nodHdl, adj);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
else if (ret > 0)
|
||||
break;
|
||||
nodes++;
|
||||
|
||||
if (check && nodes == cnt) {
|
||||
if (!(bs.restore(state) && bs.skip(v1)
|
||||
&& bs.readVuint32SM(v1, v2, v2b)))
|
||||
return false;
|
||||
if (5 < v2b)
|
||||
v2 >>= v2b - 2;
|
||||
if (v2 & 1)
|
||||
break;
|
||||
}
|
||||
|
||||
Coordinates c(toWGS32(adj.nodeInfo.pos.x()),
|
||||
toWGS32(adj.nodeInfo.pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
poly.boundingRect = poly.boundingRect.united(c);
|
||||
pos = adj.nodeInfo.pos;
|
||||
} while (!adj.eog && nodes < cnt);
|
||||
|
||||
if (nodes == cnt)
|
||||
break;
|
||||
|
||||
steps = 0;
|
||||
stepsCnt = 0;
|
||||
eos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool NETFile::linkLabel(Handle &hdl, quint32 offset, quint32 size, LBLFile *lbl,
|
||||
Handle &lblHdl, Label &label)
|
||||
{
|
||||
if (!seek(hdl, offset))
|
||||
return false;
|
||||
BitStream1 bs(*this, hdl, size);
|
||||
|
||||
quint32 flags, labelPtr;
|
||||
if (!bs.read(8, flags))
|
||||
return false;
|
||||
if (!(flags & 1))
|
||||
return true;
|
||||
|
||||
if (!bs.readUInt24(labelPtr))
|
||||
return false;
|
||||
if (labelPtr & 0x3FFFFF) {
|
||||
if (labelPtr & 0x400000) {
|
||||
quint32 lblOff;
|
||||
if (lblOffset(hdl, labelPtr & 0x3FFFFF, lblOff) && lblOff)
|
||||
label = lbl->label(lblHdl, lblOff);
|
||||
} else
|
||||
label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NETFile::init(Handle &hdl)
|
||||
{
|
||||
quint8 multiplier;
|
||||
quint16 hdrLen;
|
||||
|
||||
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
|
||||
&& seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
|
||||
&& readUInt32(hdl, _size) && readUInt8(hdl, multiplier)))
|
||||
&& readUInt32(hdl, _size) && readUInt8(hdl, _shift)))
|
||||
return false;
|
||||
|
||||
_multiplier = 1<<multiplier;
|
||||
if (hdrLen >= 0x47) {
|
||||
quint32 info;
|
||||
if (!(seek(hdl, _gmpOffset + 0x37) && readUInt32(hdl, info)))
|
||||
return false;
|
||||
_tableId = ((info >> 2) & 0xF);
|
||||
|
||||
if (!(seek(hdl, _gmpOffset + 0x43) && readUInt32(hdl, _linksOffset)
|
||||
&& readUInt32(hdl, _linksSize) && readUInt8(hdl, _linksShift)))
|
||||
return false;
|
||||
}
|
||||
|
||||
_init = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
|
||||
NODFile *nod, Handle &nodHdl, LBLFile *lbl, Handle &lblHdl,
|
||||
const NODFile::BlockInfo &blockInfo, quint8 linkId, quint8 lineId,
|
||||
const HuffmanTable &table, QList<IMG::Poly> *lines)
|
||||
{
|
||||
if (!_init && !init(hdl))
|
||||
return false;
|
||||
|
||||
Q_ASSERT(_tableId == table.id());
|
||||
if (_tableId != table.id())
|
||||
return false;
|
||||
|
||||
IMG::Poly poly;
|
||||
if (!nod->linkType(nodHdl, blockInfo, linkId, poly.type))
|
||||
return false;
|
||||
|
||||
NODFile::LinkInfo linkInfo;
|
||||
if (!nod->linkInfo(nodHdl, blockInfo, linkId, linkInfo))
|
||||
return false;
|
||||
|
||||
quint32 linkOffset = _linksOffset + (linkInfo.linkOffset << _linksShift);
|
||||
if (linkOffset > _linksOffset + _linksSize)
|
||||
return false;
|
||||
if (!seek(hdl, linkOffset))
|
||||
return false;
|
||||
BitStream4R bs(*this, hdl, linkOffset - _linksOffset);
|
||||
QVector<quint16> ca;
|
||||
quint16 mask = 0;
|
||||
quint32 size;
|
||||
|
||||
quint8 s68 = (linkInfo.flags >> 0x12) & 1;
|
||||
quint8 s69 = (linkInfo.flags >> 0x11) & 1;
|
||||
quint8 s6a = (linkInfo.flags >> 0x13) & 1;
|
||||
|
||||
if (s69 == 0 || s6a == 1) {
|
||||
if (!bs.readVUInt32(size))
|
||||
return false;
|
||||
}
|
||||
if (s69 == 0) {
|
||||
if (!readAdjCounts(bs, ca, mask))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!subdiv->level()) {
|
||||
NODFile::AdjacencyInfo adj(nod, blockInfo, linkId, linkInfo);
|
||||
|
||||
if (s69 == 1) {
|
||||
if (s68 == 1) {
|
||||
if (!readShape(nod, nodHdl, adj, bs, table, subdiv, shift, poly))
|
||||
return false;
|
||||
} else {
|
||||
if (!readNodeGeometry(nod, nodHdl, adj, poly))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
quint16 mask2 = mask + 0xffff;
|
||||
for (int i = 0; i <= ca.size(); i++) {
|
||||
quint16 step = (i < ca.size()) ? ca.at(i) & mask2 : 0xFFFF;
|
||||
bool shape = (i > 0) ? ca.at(i-1) & mask : (s68 == 1);
|
||||
if (i == lineId) {
|
||||
if (shape) {
|
||||
bool check = (i < ca.size()) ? (ca.at(i) & mask) : false;
|
||||
if (!readShape(nod, nodHdl, adj, bs, table, subdiv,
|
||||
shift, poly, step, check))
|
||||
return false;
|
||||
} else {
|
||||
if (!readNodeGeometry(nod, nodHdl, adj, poly, step))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (shape && !skipShape(bs))
|
||||
return false;
|
||||
if (!skipNodes(nod, nodHdl, adj, step))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!skipAdjShapes(bs, ca, mask, s68 == 1))
|
||||
return false;
|
||||
|
||||
if (!seekToLevel(bs, subdiv->level()))
|
||||
return false;
|
||||
if (!seekToLine(bs, lineId))
|
||||
return false;
|
||||
if (!readLine(bs, subdiv, table, poly))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lbl)
|
||||
linkLabel(hdl, linkOffset, _linksSize - (linkOffset - _linksOffset),
|
||||
lbl, lblHdl, poly.label);
|
||||
|
||||
lines->append(poly);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NETFile::lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset)
|
||||
{
|
||||
if (!_multiplier && !init(hdl))
|
||||
if (!_init && !init(hdl))
|
||||
return false;
|
||||
|
||||
if (!(seek(hdl, _offset + netOffset * _multiplier)
|
||||
if (!(seek(hdl, _offset + (netOffset << _shift))
|
||||
&& readUInt24(hdl, lblOffset)))
|
||||
return false;
|
||||
|
||||
|
@ -1,25 +1,42 @@
|
||||
#ifndef NETFILE_H
|
||||
#define NETFILE_H
|
||||
|
||||
#include "img.h"
|
||||
#include "subfile.h"
|
||||
#include "nodfile.h"
|
||||
|
||||
class NODFile;
|
||||
class LBLFile;
|
||||
class SubDiv;
|
||||
class HuffmanTable;
|
||||
|
||||
class NETFile : public SubFile
|
||||
{
|
||||
public:
|
||||
NETFile(IMG *img)
|
||||
: SubFile(img), _offset(0), _size(0), _multiplier(0) {}
|
||||
NETFile(const QString &path)
|
||||
: SubFile(path), _offset(0), _size(0), _multiplier(0) {}
|
||||
NETFile(SubFile *gmp, quint32 offset)
|
||||
: SubFile(gmp, offset), _offset(0), _size(0), _multiplier(0) {}
|
||||
NETFile(IMG *img) : SubFile(img), _offset(0), _size(0), _linksOffset(0),
|
||||
_linksSize(0), _shift(0), _linksShift(0), _init(false) {}
|
||||
NETFile(const QString &path) : SubFile(path), _offset(0), _size(0),
|
||||
_linksOffset(0), _linksSize(0), _shift(0), _linksShift(0),
|
||||
_init(false) {}
|
||||
NETFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
|
||||
_offset(0), _size(0), _linksOffset(0), _linksSize(0), _shift(0),
|
||||
_linksShift(0), _init(false) {}
|
||||
|
||||
bool lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset);
|
||||
bool link(const SubDiv *subdiv, quint32 shift, Handle &hdl, NODFile *nod,
|
||||
Handle &nodHdl, LBLFile *lbl, Handle &lblHdl,
|
||||
const NODFile::BlockInfo &blockInfo, quint8 linkId, quint8 lineId,
|
||||
const HuffmanTable &table, QList<IMG::Poly> *lines);
|
||||
|
||||
private:
|
||||
bool init(Handle &hdl);
|
||||
bool linkLabel(Handle &hdl, quint32 offset, quint32 size, LBLFile *lbl,
|
||||
Handle &lblHdl, Label &label);
|
||||
|
||||
quint32 _offset, _size;
|
||||
quint8 _multiplier;
|
||||
quint32 _offset, _size, _linksOffset, _linksSize;
|
||||
quint8 _shift, _linksShift;
|
||||
quint8 _tableId;
|
||||
bool _init;
|
||||
};
|
||||
|
||||
#endif // NETFILE_H
|
||||
|
553
src/map/IMG/nodfile.cpp
Normal file
@ -0,0 +1,553 @@
|
||||
#include "bitstream.h"
|
||||
#include "nodfile.h"
|
||||
|
||||
|
||||
#define ARRAY_SIZE(array) \
|
||||
(sizeof(array) / sizeof(array[0]))
|
||||
|
||||
static const struct
|
||||
{
|
||||
quint8 lon;
|
||||
quint8 lat;
|
||||
} LLBITS[] = {
|
||||
{0xc, 0xc}, {0x8, 0x10}, {0x10, 0x8}, {0x10, 0x10}, {0xc, 0x14},
|
||||
{0x14, 0xc}, {0x14, 0x14}
|
||||
};
|
||||
|
||||
struct NodeOffset
|
||||
{
|
||||
bool ext;
|
||||
union {
|
||||
qint32 offset;
|
||||
quint8 id;
|
||||
} u;
|
||||
};
|
||||
|
||||
static bool adjDistInfo(BitStream1 &bs, bool extraBit, bool &eog)
|
||||
{
|
||||
quint32 data, cnt;
|
||||
|
||||
if (!bs.read(extraBit | 8, data))
|
||||
return false;
|
||||
|
||||
data <<= !extraBit;
|
||||
eog |= (quint8)data & 1;
|
||||
data >>= 1;
|
||||
|
||||
for (cnt = 0; (data >> cnt) & 1; cnt++) {
|
||||
if (cnt == 4)
|
||||
break;
|
||||
}
|
||||
if (!bs.read(cnt * 4, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool adjNodeInfo(BitStream1 &bs, bool extraBit, NodeOffset &offset)
|
||||
{
|
||||
quint32 data;
|
||||
|
||||
if (!bs.read(9, data))
|
||||
return false;
|
||||
|
||||
data <<= !extraBit;
|
||||
|
||||
if (data & 1) {
|
||||
offset.ext = true;
|
||||
offset.u.id = data >> 1;
|
||||
} else {
|
||||
quint32 bits = (data >> 1) & 7;
|
||||
quint32 data2;
|
||||
|
||||
if (!bs.read(bits + extraBit + 1, data2))
|
||||
return false;
|
||||
|
||||
data = data2 << (6 - extraBit) | data >> 4;
|
||||
bits = 0x19 - bits;
|
||||
offset.ext = false;
|
||||
offset.u.offset = ((qint32)(data << bits) >> bits);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool skipOptAdjData(BitStream1 &bs)
|
||||
{
|
||||
// TODO
|
||||
Q_UNUSED(bs);
|
||||
Q_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool NODFile::init(Handle &hdl)
|
||||
{
|
||||
quint16 hdrLen;
|
||||
|
||||
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)))
|
||||
return false;
|
||||
if (hdrLen < 0x7b)
|
||||
return false;
|
||||
|
||||
if (!(seek(hdl, _gmpOffset + 0x1d) && readUInt32(hdl, _flags)
|
||||
&& readUInt8(hdl, _blockShift) && readUInt8(hdl, _nodeShift)))
|
||||
return false;
|
||||
|
||||
if (!(seek(hdl, _gmpOffset + 0x67) && readUInt32(hdl, _blockOffset)
|
||||
&& readUInt32(hdl, _blockSize) && readUInt16(hdl, _blockRecordSize)
|
||||
&& readUInt32(hdl, _indexOffset) && readUInt32(hdl, _indexSize)
|
||||
&& readUInt16(hdl, _indexRecordSize) && readUInt32(hdl, _indexFlags)))
|
||||
return false;
|
||||
|
||||
if (!_indexRecordSize)
|
||||
return false;
|
||||
quint32 indexCount = _indexSize / _indexRecordSize;
|
||||
if (indexCount <= 0x100)
|
||||
_indexIdSize = 1;
|
||||
else if (indexCount <= 0x1000)
|
||||
_indexIdSize = 2;
|
||||
else if (indexCount <= 0x1000000)
|
||||
_indexIdSize = 3;
|
||||
|
||||
return (_indexIdSize > 0);
|
||||
}
|
||||
|
||||
quint32 NODFile::indexIdSize(Handle &hdl)
|
||||
{
|
||||
if (!_indexIdSize && !init(hdl))
|
||||
return 0;
|
||||
|
||||
return _indexIdSize;
|
||||
}
|
||||
|
||||
bool NODFile::readBlock(Handle &hdl, quint32 blockOffset,
|
||||
BlockInfo &blockInfo) const
|
||||
{
|
||||
blockInfo.offset = blockOffset;
|
||||
|
||||
if (!(seek(hdl, blockInfo.offset + _blockOffset)
|
||||
&& readUInt16(hdl, blockInfo.hdr.s0) && readUInt32(hdl, blockInfo.hdr.s2)
|
||||
&& readUInt32(hdl, blockInfo.hdr.s6) && readUInt32(hdl, blockInfo.hdr.sa)
|
||||
&& readUInt16(hdl, blockInfo.hdr.se) && readUInt8(hdl, blockInfo.hdr.s10)
|
||||
&& readUInt8(hdl, blockInfo.hdr.s11) && readUInt8(hdl, blockInfo.hdr.s12)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NODFile::blockInfo(Handle &hdl, quint32 blockId, BlockInfo &blockInfo) const
|
||||
{
|
||||
quint32 blockOffset;
|
||||
quint32 offset = _indexRecordSize * blockId + _indexOffset;
|
||||
quint32 offsetSize = (_indexFlags & 3) + 1;
|
||||
|
||||
if (offset > _indexOffset + _indexSize)
|
||||
return false;
|
||||
if (!(seek(hdl, offset) && readVUInt32(hdl, offsetSize, blockOffset)))
|
||||
return false;
|
||||
|
||||
return readBlock(hdl, blockOffset << _blockShift, blockInfo);
|
||||
}
|
||||
|
||||
bool NODFile::linkInfo(Handle &hdl, const BlockInfo &blockInfo, quint32 linkId,
|
||||
LinkInfo &linkInfo) const
|
||||
{
|
||||
if (linkId >= blockInfo.hdr.s10)
|
||||
return false;
|
||||
|
||||
quint32 infoOffset = ((blockInfo.hdr.se * linkId) >> 3) + 0x13
|
||||
+ ((blockInfo.hdr.s0 >> 0xb) & 1) + blockInfo.offset + _blockOffset;
|
||||
quint32 s1 = ((blockInfo.hdr.s0 >> 2) & 0x1f) + 8;
|
||||
quint32 s2 = (blockInfo.hdr.s0 >> 7) & 0xf;
|
||||
quint32 skip = (blockInfo.hdr.se * linkId) & 7;
|
||||
|
||||
if (infoOffset > _blockOffset + _blockSize || infoOffset < blockInfo.offset)
|
||||
return false;
|
||||
if (!seek(hdl, infoOffset))
|
||||
return false;
|
||||
|
||||
quint32 unused, flags;
|
||||
BitStream1 bs(*this, hdl, _blockOffset + _blockSize - infoOffset);
|
||||
if (!(bs.read(skip, unused) && bs.read(0xc, flags)))
|
||||
return false;
|
||||
|
||||
linkInfo.flags = ((flags << 8) & 0xf0000) | (flags & 0xff);
|
||||
|
||||
if (!(flags << 8 & 0x10000)) {
|
||||
if (!bs.read(s1, linkInfo.linkOffset))
|
||||
return false;
|
||||
} else {
|
||||
if (!bs.read(s1 - s2, linkInfo.linkOffset))
|
||||
return false;
|
||||
linkInfo.linkOffset += blockInfo.hdr.sa;
|
||||
}
|
||||
|
||||
if (!bs.read(s2, linkInfo.nodeOffset))
|
||||
return false;
|
||||
linkInfo.nodeOffset = (blockInfo.offset - linkInfo.nodeOffset)
|
||||
>> _nodeShift;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NODFile::nodeInfo(Handle &hdl, const BlockInfo &blockInfo,
|
||||
quint32 nodeOffset, NodeInfo &nodeInfo) const
|
||||
{
|
||||
quint32 infoOffset = (nodeOffset << _nodeShift) + _blockOffset;
|
||||
if (infoOffset > _blockOffset + _blockSize || infoOffset < blockInfo.offset)
|
||||
return false;
|
||||
if (!seek(hdl, infoOffset))
|
||||
return false;
|
||||
|
||||
BitStream1 bs(*this, hdl, _blockOffset + _blockSize - infoOffset);
|
||||
|
||||
if (!bs.read(8, nodeInfo.flags))
|
||||
return false;
|
||||
|
||||
if ((nodeInfo.flags & 7) >= ARRAY_SIZE(LLBITS))
|
||||
return false;
|
||||
quint8 lonBits = LLBITS[nodeInfo.flags & 7].lon;
|
||||
quint8 latBits = LLBITS[nodeInfo.flags & 7].lat;
|
||||
quint8 maxBits = ((_flags >> 10) & 7) | 0x18;
|
||||
|
||||
quint32 lon, lat;
|
||||
if (!(bs.read(lonBits, lon) && bs.read(latBits, lat)))
|
||||
return false;
|
||||
|
||||
quint8 lonShift = 0x20 - lonBits;
|
||||
quint8 latShift = 0x20 - latBits;
|
||||
quint8 shift = 0x20 - maxBits;
|
||||
QPoint pos((((int)(lon << lonShift) >> lonShift) << shift)
|
||||
+ blockInfo.hdr.s2, (((int)(lat << latShift) >> latShift) << shift)
|
||||
+ blockInfo.hdr.s6);
|
||||
nodeInfo.bytes = ((lonBits + latBits) >> 3) + 1;
|
||||
|
||||
if ((maxBits < 0x1c) && (nodeInfo.flags & 8)) {
|
||||
quint8 extraBits = 0x1c - maxBits;
|
||||
quint32 extraLon, extraLat;
|
||||
|
||||
if (!(bs.read(extraBits, extraLon) && bs.read(extraBits, extraLat)))
|
||||
return false;
|
||||
pos.setX(pos.x() | extraLon << 4); pos.setY(pos.y() | extraLat << 4);
|
||||
nodeInfo.bytes++;
|
||||
}
|
||||
// TODO?: extra bits
|
||||
|
||||
nodeInfo.pos = pos;
|
||||
nodeInfo.flags &= 0xf8;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NODFile::nodeOffset(Handle &hdl, const BlockInfo &blockInfo,
|
||||
quint8 nodeId, quint32 &nodeOffset) const
|
||||
{
|
||||
if (nodeId >= blockInfo.hdr.s11)
|
||||
return false;
|
||||
|
||||
quint32 offset = ((blockInfo.hdr.s10 * blockInfo.hdr.se + 7) >> 3)
|
||||
+ 0x13 + nodeId * 3 + _blockOffset + blockInfo.offset
|
||||
+ ((blockInfo.hdr.s0 >> 0xb) & 1);
|
||||
|
||||
if (!(seek(hdl, offset) && readUInt24(hdl, nodeOffset)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NODFile::nodeBlock(Handle &hdl, quint32 nodeOffset,
|
||||
BlockInfo &blockInfo) const
|
||||
{
|
||||
int low = 0;
|
||||
int high = _indexSize / _indexRecordSize - 1;
|
||||
quint32 offsetSize = (_indexFlags & 3) + 1;
|
||||
|
||||
while (low <= high) {
|
||||
quint32 m = ((low + high) / 2);
|
||||
quint32 offset = _indexRecordSize * m + _indexOffset;
|
||||
quint32 blockOffset, prevBlockOffset;
|
||||
|
||||
if (m > 0) {
|
||||
if (!(seek(hdl, offset - _indexRecordSize)
|
||||
&& readVUInt32(hdl, offsetSize, prevBlockOffset)
|
||||
&& readVUInt32(hdl, offsetSize, blockOffset)))
|
||||
return false;
|
||||
} else {
|
||||
if (!(seek(hdl, offset)
|
||||
&& readVUInt32(hdl, offsetSize, blockOffset)))
|
||||
return false;
|
||||
prevBlockOffset = 0;
|
||||
}
|
||||
prevBlockOffset <<= _blockShift;
|
||||
blockOffset <<= _blockShift;
|
||||
|
||||
if (blockOffset < nodeOffset)
|
||||
low = m + 1;
|
||||
else {
|
||||
if (prevBlockOffset <= nodeOffset)
|
||||
return readBlock(hdl, blockOffset, blockInfo);
|
||||
else
|
||||
high = m - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NODFile::absAdjInfo(Handle &hdl, AdjacencyInfo &adj) const
|
||||
{
|
||||
quint32 infoOffset = (adj.nodeOffset << _nodeShift) + _blockOffset
|
||||
+ adj.nodeInfo.bytes;
|
||||
if (!seek(hdl, infoOffset))
|
||||
return false;
|
||||
BitStream1 bs(*this, hdl, _blockOffset + _blockSize - infoOffset);
|
||||
|
||||
quint8 linkId = adj.blockInfo.hdr.s10;
|
||||
quint32 m2p = 2;
|
||||
quint32 skip = 8;
|
||||
quint32 flags;
|
||||
quint32 nextOffset = 0xFFFFFFFF;
|
||||
bool extraBit = (adj.nodeInfo.flags >> 6) & 1;
|
||||
bool linkIdValid = true;
|
||||
bool firstLoop = true;
|
||||
NodeOffset offset;
|
||||
|
||||
do {
|
||||
adj.eog = false;
|
||||
|
||||
if (!bs.read(8, flags))
|
||||
return false;
|
||||
|
||||
if (firstLoop) {
|
||||
skip >>= (flags >> 5) & 1;
|
||||
flags |= 0x20;
|
||||
}
|
||||
firstLoop = false;
|
||||
quint32 f4 = flags & 0x10;
|
||||
quint32 f4sn = (f4 >> 4) ^ 1;
|
||||
quint32 m1 = (flags >> 5) & f4sn;
|
||||
quint32 m2 = (f4 >> 3) | (f4sn & (flags >> 6));
|
||||
|
||||
if (m1) {
|
||||
if (!bs.read(8, linkId))
|
||||
return false;
|
||||
linkIdValid = true;
|
||||
}
|
||||
|
||||
if ((m2 != m2p) || (flags & 0x10) || m1) {
|
||||
quint32 data;
|
||||
if (!bs.read(skip, data))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(flags & 0x10)) {
|
||||
if (!adjDistInfo(bs, (m2 == 1 && linkIdValid), adj.eog))
|
||||
return false;
|
||||
|
||||
if (!adjNodeInfo(bs, extraBit, offset))
|
||||
return false;
|
||||
if (!offset.ext)
|
||||
nextOffset = adj.nodeOffset + offset.u.offset;
|
||||
else if (!nodeOffset(adj.extHdl, adj.blockInfo, offset.u.id,
|
||||
nextOffset))
|
||||
return false;
|
||||
|
||||
m2p = m2;
|
||||
}
|
||||
|
||||
if (flags & 0x8) {
|
||||
quint32 data;
|
||||
if (!bs.read(8, data))
|
||||
return false;
|
||||
if (!(data & 0xe0)) {
|
||||
if (!bs.read(8, data))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((_flags & 0x18) && !skipOptAdjData(bs))
|
||||
return false;
|
||||
|
||||
if ((m2 == 1) && linkIdValid) {
|
||||
LinkInfo li;
|
||||
if (adj.linkId == 0xFFFFFFFF) {
|
||||
if (!linkInfo(adj.extHdl, adj.blockInfo, linkId, li))
|
||||
return false;
|
||||
} else
|
||||
li.linkOffset = 0xFFFFFFFF;
|
||||
|
||||
if ((adj.linkOffset == li.linkOffset) || (adj.linkId == linkId)) {
|
||||
adj.nodeOffset = nextOffset;
|
||||
if (offset.ext) {
|
||||
adj.linkId = 0xFFFFFFFF;
|
||||
return nodeBlock(hdl, adj.nodeOffset << _nodeShift,
|
||||
adj.blockInfo);
|
||||
} else {
|
||||
adj.linkId = linkId;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
linkIdValid = false;
|
||||
}
|
||||
} while (!(flags & 0x80));
|
||||
|
||||
adj.nodeOffset = 0xFFFFFFFF;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NODFile::relAdjInfo(Handle &hdl, AdjacencyInfo &adj) const
|
||||
{
|
||||
quint32 infoOffset = (adj.nodeOffset << _nodeShift) + _blockOffset
|
||||
+ adj.nodeInfo.bytes;
|
||||
if (!seek(hdl, infoOffset))
|
||||
return false;
|
||||
|
||||
BitStream1 bs(*this, hdl, _blockOffset + _blockSize - infoOffset);
|
||||
|
||||
quint32 linkId = adj.blockInfo.hdr.s10;
|
||||
quint32 skip = 8;
|
||||
quint32 flagsBits = 8;
|
||||
quint32 flags;
|
||||
quint32 nextOffset = 0xFFFFFFFF;
|
||||
NodeOffset offset;
|
||||
bool extraBit = (adj.nodeInfo.flags >> 6) & 1;
|
||||
bool linkIdValid = true;
|
||||
bool firstLoop = true;
|
||||
|
||||
do {
|
||||
adj.eog = false;
|
||||
|
||||
if (!bs.read(flagsBits, flags))
|
||||
return false;
|
||||
|
||||
flags <<= (8U - flagsBits);
|
||||
if (firstLoop) {
|
||||
skip >>= (flags >> 5) & 1;
|
||||
flags = ((flags >> 1) & 0x20) | (flags & 0xffffffdf);
|
||||
}
|
||||
firstLoop = false;
|
||||
flagsBits >>= (flags >> 3) & 1;
|
||||
quint32 m = (((flags & 0x70) == 0x30) << 1) | ((flags >> 6) & 1);
|
||||
if (!m) {
|
||||
adj.nodeOffset = 0xFFFFFFFF;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((flags & 0x60) == 0x60) {
|
||||
if (!bs.read(8, linkId))
|
||||
return false;
|
||||
linkIdValid = true;
|
||||
}
|
||||
|
||||
if (((flags & 0x70) == 0x70)) {
|
||||
quint32 data;
|
||||
if (!bs.read(skip, data))
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((flags & 0x50) == 0x50) {
|
||||
if (!adjDistInfo(bs, false, adj.eog))
|
||||
return false;
|
||||
adj.eog = true;
|
||||
}
|
||||
if ((flags >> 6) & 1) {
|
||||
if (!adjNodeInfo(bs, extraBit, offset))
|
||||
return false;
|
||||
if (!offset.ext)
|
||||
nextOffset = adj.nodeOffset + offset.u.offset;
|
||||
else if (!nodeOffset(adj.extHdl, adj.blockInfo, offset.u.id,
|
||||
nextOffset))
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((_flags & 0x18) && !skipOptAdjData(bs))
|
||||
return false;
|
||||
|
||||
if (((m == 1) && linkIdValid)) {
|
||||
LinkInfo li;
|
||||
if (adj.linkId == 0xFFFFFFFF) {
|
||||
if (!linkInfo(adj.extHdl, adj.blockInfo, linkId, li))
|
||||
return false;
|
||||
} else
|
||||
li.linkOffset = 0xFFFFFFFF;
|
||||
|
||||
if ((adj.linkOffset == li.linkOffset) || (adj.linkId == linkId)) {
|
||||
adj.nodeOffset = nextOffset;
|
||||
if (offset.ext) {
|
||||
adj.linkId = 0xFFFFFFFF;
|
||||
return nodeBlock(hdl, adj.nodeOffset << _nodeShift,
|
||||
adj.blockInfo);
|
||||
} else {
|
||||
adj.linkId = linkId;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
linkIdValid = false;
|
||||
}
|
||||
} while (!(flags & 0x80));
|
||||
|
||||
adj.nodeOffset = 0xFFFFFFFF;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int NODFile::nextNode(Handle &hdl, AdjacencyInfo &adjInfo)
|
||||
{
|
||||
if (adjInfo.nodeOffset == 0xFFFFFFFF)
|
||||
return 1;
|
||||
|
||||
if (!nodeInfo(hdl, adjInfo.blockInfo, adjInfo.nodeOffset,
|
||||
adjInfo.nodeInfo))
|
||||
return -1;
|
||||
if (!adjacencyInfo(hdl, adjInfo))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NODFile::linkType(Handle &hdl, const BlockInfo &blockInfo, quint8 linkId,
|
||||
quint32 &type) const
|
||||
{
|
||||
quint32 offset = ((blockInfo.hdr.s10 * blockInfo.hdr.se + 7) >> 3) + 0x13
|
||||
+ blockInfo.offset + _blockOffset + ((blockInfo.hdr.s0 >> 0xb) & 1)
|
||||
+ blockInfo.hdr.s11 * 3;
|
||||
quint32 low = 0;
|
||||
quint32 high = blockInfo.hdr.s12 - 1;
|
||||
quint32 pos = blockInfo.hdr.s12;
|
||||
quint16 val;
|
||||
|
||||
if (high > 1) {
|
||||
do {
|
||||
pos = (low + high) / 2;
|
||||
|
||||
if (!(seek(hdl, offset + _blockRecordSize * pos)
|
||||
&& readUInt16(hdl, val)))
|
||||
return false;
|
||||
|
||||
if ((val >> 8) <= linkId)
|
||||
low = pos;
|
||||
else
|
||||
high = pos;
|
||||
} while (low + 1 < high);
|
||||
}
|
||||
|
||||
if (!(seek(hdl, offset + _blockRecordSize * low) && readUInt16(hdl, val)))
|
||||
return false;
|
||||
|
||||
type = val & 0x3f;
|
||||
|
||||
if ((low < high) && (pos != high)) {
|
||||
if (!(seek(hdl, offset + _blockRecordSize * high)
|
||||
&& readUInt16(hdl, val)))
|
||||
return false;
|
||||
if ((val >> 8) <= linkId)
|
||||
type = (val & 0x3f);
|
||||
}
|
||||
|
||||
type <<= 8;
|
||||
|
||||
return true;
|
||||
}
|
98
src/map/IMG/nodfile.h
Normal file
@ -0,0 +1,98 @@
|
||||
#ifndef NODFILE_H
|
||||
#define NODFILE_H
|
||||
|
||||
#include "img.h"
|
||||
#include "subfile.h"
|
||||
|
||||
class NODFile : public SubFile
|
||||
{
|
||||
public:
|
||||
struct BlockInfo
|
||||
{
|
||||
quint32 offset;
|
||||
struct
|
||||
{
|
||||
quint32 s2; // node lon base
|
||||
quint32 s6; // node lat base
|
||||
quint32 sa;
|
||||
quint16 s0; // flags
|
||||
quint16 se; // link info bit size
|
||||
quint8 s10; // links count
|
||||
quint8 s11; // nodes count
|
||||
quint8 s12; // link types count
|
||||
} hdr;
|
||||
};
|
||||
|
||||
struct LinkInfo
|
||||
{
|
||||
quint32 linkOffset;
|
||||
quint32 nodeOffset;
|
||||
quint32 flags;
|
||||
};
|
||||
|
||||
struct NodeInfo
|
||||
{
|
||||
QPoint pos;
|
||||
quint8 flags;
|
||||
quint8 bytes;
|
||||
};
|
||||
|
||||
struct AdjacencyInfo
|
||||
{
|
||||
AdjacencyInfo(const SubFile *file, const BlockInfo &blockInfo,
|
||||
quint32 linkId, const LinkInfo &linkInfo) : extHdl(file),
|
||||
blockInfo(blockInfo), nodeOffset(linkInfo.nodeOffset),
|
||||
linkOffset(linkInfo.linkOffset), linkId(linkId)
|
||||
{}
|
||||
|
||||
Handle extHdl;
|
||||
BlockInfo blockInfo;
|
||||
NodeInfo nodeInfo;
|
||||
quint32 nodeOffset;
|
||||
quint32 linkOffset;
|
||||
quint32 linkId;
|
||||
bool eog;
|
||||
};
|
||||
|
||||
NODFile(IMG *img) : SubFile(img), _indexOffset(0), _indexSize(0),
|
||||
_indexFlags(0), _blockOffset(0), _blockSize(0), _indexRecordSize(0),
|
||||
_blockRecordSize(0), _blockShift(0), _nodeShift(0), _indexIdSize(0) {}
|
||||
NODFile(const QString &path) : SubFile(path), _indexOffset(0), _indexSize(0),
|
||||
_indexFlags(0), _blockOffset(0), _blockSize(0), _indexRecordSize(0),
|
||||
_blockRecordSize(0), _blockShift(0), _nodeShift(0), _indexIdSize(0) {}
|
||||
NODFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
|
||||
_indexOffset(0), _indexSize(0), _indexFlags(0), _blockOffset(0),
|
||||
_blockSize(0), _indexRecordSize(0), _blockRecordSize(0), _blockShift(0),
|
||||
_nodeShift(0), _indexIdSize(0) {}
|
||||
|
||||
quint32 indexIdSize(Handle &hdl);
|
||||
bool blockInfo(Handle &hdl, quint32 blockId, BlockInfo &blockInfo) const;
|
||||
bool linkInfo(Handle &hdl, const BlockInfo &blockInfo, quint32 linkId,
|
||||
LinkInfo &linkInfo) const;
|
||||
bool linkType(Handle &hdl, const BlockInfo &blockInfo, quint8 linkId,
|
||||
quint32 &type) const;
|
||||
int nextNode(Handle &hdl, AdjacencyInfo &adjInfo);
|
||||
|
||||
private:
|
||||
bool init(Handle &hdl);
|
||||
bool nodeInfo(Handle &hdl, const BlockInfo &blockInfo, quint32 nodeOffset,
|
||||
NodeInfo &nodeInfo) const;
|
||||
bool nodeOffset(Handle &hdl, const BlockInfo &blockInfo, quint8 nodeId,
|
||||
quint32 &nodeOffset) const;
|
||||
bool absAdjInfo(Handle &hdl, AdjacencyInfo &adj) const;
|
||||
bool relAdjInfo(Handle &hdl, AdjacencyInfo &adj) const;
|
||||
bool adjacencyInfo(Handle &hdl, AdjacencyInfo &adj) const
|
||||
{
|
||||
return (adj.nodeInfo.flags & 0x20) ? absAdjInfo(hdl, adj)
|
||||
: relAdjInfo(hdl, adj);
|
||||
}
|
||||
bool nodeBlock(Handle &hdl, quint32 nodeOffset, BlockInfo &blockInfo) const;
|
||||
bool readBlock(Handle &hdl, quint32 blockOffset, BlockInfo &blockInfo) const;
|
||||
|
||||
quint32 _flags, _indexOffset, _indexSize, _indexFlags, _blockOffset,
|
||||
_blockSize;
|
||||
quint16 _indexRecordSize, _blockRecordSize;
|
||||
quint8 _blockShift, _nodeShift, _indexIdSize;
|
||||
};
|
||||
|
||||
#endif // NETFILE_H
|
433
src/map/IMG/rastertile.cpp
Normal file
@ -0,0 +1,433 @@
|
||||
#include <QFont>
|
||||
#include <QPainter>
|
||||
#include "textpathitem.h"
|
||||
#include "textpointitem.h"
|
||||
#include "bitmapline.h"
|
||||
#include "style.h"
|
||||
#include "rastertile.h"
|
||||
|
||||
|
||||
#define AREA(rect) \
|
||||
(rect.size().width() * rect.size().height())
|
||||
|
||||
static const QColor shieldColor(Qt::white);
|
||||
static const QColor shieldBgColor1("#dd3e3e");
|
||||
static const QColor shieldBgColor2("#379947");
|
||||
static const QColor shieldBgColor3("#4a7fc1");
|
||||
|
||||
static QString convertUnits(const QString &str)
|
||||
{
|
||||
bool ok;
|
||||
int number = str.toInt(&ok);
|
||||
return ok ? QString::number(qRound(number * 0.3048)) : str;
|
||||
}
|
||||
|
||||
static int minPOIZoom(Style::POIClass cl)
|
||||
{
|
||||
switch (cl) {
|
||||
case Style::Food:
|
||||
case Style::Shopping:
|
||||
case Style::Services:
|
||||
return 26;
|
||||
case Style::Accommodation:
|
||||
case Style::Recreation:
|
||||
return 25;
|
||||
case Style::ManmadePlaces:
|
||||
case Style::NaturePlaces:
|
||||
case Style::Transport:
|
||||
case Style::Community:
|
||||
case Style::Elementary:
|
||||
return 23;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static QFont pixelSizeFont(int pixelSize)
|
||||
{
|
||||
QFont f;
|
||||
f.setPixelSize(pixelSize);
|
||||
return f;
|
||||
}
|
||||
|
||||
static QFont *font(Style::FontSize size, Style::FontSize defaultSize
|
||||
= Style::Normal)
|
||||
{
|
||||
/* The fonts must be initialized on first usage (after the QGuiApplication
|
||||
instance is created) */
|
||||
static QFont large = pixelSizeFont(16);
|
||||
static QFont normal = pixelSizeFont(14);
|
||||
static QFont small = pixelSizeFont(12);
|
||||
static QFont extraSmall = pixelSizeFont(10);
|
||||
|
||||
switch (size) {
|
||||
case Style::None:
|
||||
return 0;
|
||||
case Style::Large:
|
||||
return &large;
|
||||
case Style::Normal:
|
||||
return &normal;
|
||||
case Style::Small:
|
||||
return &small;
|
||||
case Style::ExtraSmall:
|
||||
return &extraSmall;
|
||||
default:
|
||||
return font(defaultSize);
|
||||
}
|
||||
}
|
||||
|
||||
static QFont *poiFont(Style::FontSize size = Style::Normal)
|
||||
{
|
||||
static QFont poi = pixelSizeFont(10);
|
||||
|
||||
switch (size) {
|
||||
case Style::None:
|
||||
return 0;
|
||||
default:
|
||||
return &poi;
|
||||
}
|
||||
}
|
||||
|
||||
static const QColor *shieldBgColor(Label::Shield::Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case Label::Shield::USInterstate:
|
||||
case Label::Shield::Hbox:
|
||||
return &shieldBgColor1;
|
||||
case Label::Shield::USShield:
|
||||
case Label::Shield::Box:
|
||||
return &shieldBgColor2;
|
||||
case Label::Shield::USRound:
|
||||
case Label::Shield::Oval:
|
||||
return &shieldBgColor3;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int minShieldZoom(Label::Shield::Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case Label::Shield::USInterstate:
|
||||
case Label::Shield::Hbox:
|
||||
return 17;
|
||||
case Label::Shield::USShield:
|
||||
case Label::Shield::Box:
|
||||
return 19;
|
||||
case Label::Shield::USRound:
|
||||
case Label::Shield::Oval:
|
||||
return 20;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static qreal area(const QVector<QPointF> &polygon)
|
||||
{
|
||||
qreal area = 0;
|
||||
|
||||
for (int i = 0; i < polygon.size(); i++) {
|
||||
int j = (i + 1) % polygon.size();
|
||||
area += polygon.at(i).x() * polygon.at(j).y();
|
||||
area -= polygon.at(i).y() * polygon.at(j).x();
|
||||
}
|
||||
area /= 2.0;
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
static QPointF centroid(const QVector<QPointF> &polygon)
|
||||
{
|
||||
qreal cx = 0, cy = 0;
|
||||
qreal factor = 1.0 / (6.0 * area(polygon));
|
||||
|
||||
for (int i = 0; i < polygon.size(); i++) {
|
||||
int j = (i + 1) % polygon.size();
|
||||
qreal f = (polygon.at(i).x() * polygon.at(j).y() - polygon.at(j).x()
|
||||
* polygon.at(i).y());
|
||||
cx += (polygon.at(i).x() + polygon.at(j).x()) * f;
|
||||
cy += (polygon.at(i).y() + polygon.at(j).y()) * f;
|
||||
}
|
||||
|
||||
return QPointF(cx * factor, cy * factor);
|
||||
}
|
||||
|
||||
static bool rectNearPolygon(const QPolygonF &polygon, const QRectF &rect)
|
||||
{
|
||||
return (polygon.boundingRect().contains(rect)
|
||||
&& (polygon.containsPoint(rect.topLeft(), Qt::OddEvenFill)
|
||||
|| polygon.containsPoint(rect.topRight(), Qt::OddEvenFill)
|
||||
|| polygon.containsPoint(rect.bottomLeft(), Qt::OddEvenFill)
|
||||
|| polygon.containsPoint(rect.bottomRight(), Qt::OddEvenFill)));
|
||||
}
|
||||
|
||||
|
||||
void RasterTile::render()
|
||||
{
|
||||
QList<TextItem*> textItems;
|
||||
|
||||
processPoints(textItems);
|
||||
processPolygons(textItems);
|
||||
processLines(textItems);
|
||||
|
||||
_img.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&_img);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.translate(-_xy.x(), -_xy.y());
|
||||
|
||||
drawPolygons(&painter);
|
||||
drawLines(&painter);
|
||||
drawTextItems(&painter, textItems);
|
||||
//painter.setPen(Qt::red);
|
||||
//painter.drawRect(QRect(_xy, _img.size()));
|
||||
|
||||
qDeleteAll(textItems);
|
||||
}
|
||||
|
||||
void RasterTile::drawPolygons(QPainter *painter)
|
||||
{
|
||||
for (int n = 0; n < _style->drawOrder().size(); n++) {
|
||||
for (int i = 0; i < _polygons.size(); i++) {
|
||||
const MapData::Poly &poly = _polygons.at(i);
|
||||
if (poly.type != _style->drawOrder().at(n))
|
||||
continue;
|
||||
const Style::Polygon &style = _style->polygon(poly.type);
|
||||
|
||||
painter->setPen(style.pen());
|
||||
painter->setBrush(style.brush());
|
||||
painter->drawPolygon(poly.points);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::drawLines(QPainter *painter)
|
||||
{
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
|
||||
for (int i = 0; i < _lines.size(); i++) {
|
||||
const MapData::Poly &poly = _lines.at(i);
|
||||
const Style::Line &style = _style->line(poly.type);
|
||||
|
||||
if (style.background() == Qt::NoPen)
|
||||
continue;
|
||||
|
||||
painter->setPen(style.background());
|
||||
painter->drawPolyline(poly.points);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _lines.size(); i++) {
|
||||
const MapData::Poly &poly = _lines.at(i);
|
||||
const Style::Line &style = _style->line(poly.type);
|
||||
|
||||
if (!style.img().isNull())
|
||||
BitmapLine::draw(painter, poly.points, style.img());
|
||||
else if (style.foreground() != Qt::NoPen) {
|
||||
painter->setPen(style.foreground());
|
||||
painter->drawPolyline(poly.points);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::drawTextItems(QPainter *painter,
|
||||
const QList<TextItem*> &textItems)
|
||||
{
|
||||
for (int i = 0; i < textItems.size(); i++)
|
||||
textItems.at(i)->paint(painter);
|
||||
}
|
||||
|
||||
static void removeDuplicitLabel(QList<TextItem *> &labels, const QString &text,
|
||||
const QRectF &tileRect)
|
||||
{
|
||||
for (int i = 0; i < labels.size(); i++) {
|
||||
TextItem *item = labels.at(i);
|
||||
if (tileRect.contains(item->boundingRect()) && *(item->text()) == text) {
|
||||
labels.removeAt(i);
|
||||
delete item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processPolygons(QList<TextItem*> &textItems)
|
||||
{
|
||||
QRectF tileRect(_xy, _img.size());
|
||||
QSet<QString> set;
|
||||
QList<TextItem *> labels;
|
||||
|
||||
for (int i = 0; i < _polygons.size(); i++) {
|
||||
MapData::Poly &poly = _polygons[i];
|
||||
bool exists = set.contains(poly.label.text());
|
||||
|
||||
if (poly.label.text().isEmpty())
|
||||
continue;
|
||||
|
||||
if (_zoom <= 23 && (Style::isWaterArea(poly.type)
|
||||
|| Style::isMilitaryArea(poly.type)
|
||||
|| Style::isNatureReserve(poly.type))) {
|
||||
const Style::Polygon &style = _style->polygon(poly.type);
|
||||
TextPointItem *item = new TextPointItem(
|
||||
centroid(poly.points).toPoint(), &poly.label.text(),
|
||||
poiFont(), 0, &style.brush().color());
|
||||
if (item->isValid() && !item->collides(textItems)
|
||||
&& !item->collides(labels)
|
||||
&& !(exists && tileRect.contains(item->boundingRect()))
|
||||
&& rectNearPolygon(poly.points, item->boundingRect())) {
|
||||
if (exists)
|
||||
removeDuplicitLabel(labels, poly.label.text(), tileRect);
|
||||
else
|
||||
set.insert(poly.label.text());
|
||||
labels.append(item);
|
||||
} else
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
textItems.append(labels);
|
||||
}
|
||||
|
||||
void RasterTile::processLines(QList<TextItem*> &textItems)
|
||||
{
|
||||
QRect tileRect(_xy, _img.size());
|
||||
|
||||
qStableSort(_lines);
|
||||
|
||||
if (_zoom >= 22)
|
||||
processStreetNames(tileRect, textItems);
|
||||
processShields(tileRect, textItems);
|
||||
}
|
||||
|
||||
void RasterTile::processStreetNames(const QRect &tileRect,
|
||||
QList<TextItem*> &textItems)
|
||||
{
|
||||
for (int i = 0; i < _lines.size(); i++) {
|
||||
MapData::Poly &poly = _lines[i];
|
||||
const Style::Line &style = _style->line(poly.type);
|
||||
|
||||
if (style.img().isNull() && style.foreground() == Qt::NoPen)
|
||||
continue;
|
||||
if (poly.label.text().isEmpty()
|
||||
|| style.textFontSize() == Style::None)
|
||||
continue;
|
||||
|
||||
if (Style::isContourLine(poly.type))
|
||||
poly.label.setText(convertUnits(poly.label.text()));
|
||||
|
||||
const QFont *fnt = font(style.textFontSize(), Style::Small);
|
||||
const QColor *color = style.textColor().isValid()
|
||||
? &style.textColor() : 0;
|
||||
|
||||
TextPathItem *item = new TextPathItem(poly.points,
|
||||
&poly.label.text(), tileRect, fnt, color);
|
||||
if (item->isValid() && !item->collides(textItems))
|
||||
textItems.append(item);
|
||||
else
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processShields(const QRect &tileRect,
|
||||
QList<TextItem*> &textItems)
|
||||
{
|
||||
for (int type = FIRST_SHIELD; type <= LAST_SHIELD; type++) {
|
||||
if (minShieldZoom(static_cast<Label::Shield::Type>(type)) > _zoom)
|
||||
continue;
|
||||
|
||||
QHash<Label::Shield, QPolygonF> shields;
|
||||
QHash<Label::Shield, const Label::Shield*> sp;
|
||||
|
||||
for (int i = 0; i < _lines.size(); i++) {
|
||||
const MapData::Poly &poly = _lines.at(i);
|
||||
const Label::Shield &shield = poly.label.shield();
|
||||
if (!shield.isValid() || shield.type() != type
|
||||
|| !Style::isMajorRoad(poly.type))
|
||||
continue;
|
||||
|
||||
QPolygonF &p = shields[shield];
|
||||
for (int j = 0; j < poly.points.size(); j++)
|
||||
p.append(poly.points.at(j));
|
||||
|
||||
sp.insert(shield, &shield);
|
||||
}
|
||||
|
||||
for (QHash<Label::Shield, QPolygonF>::const_iterator it
|
||||
= shields.constBegin(); it != shields.constEnd(); ++it) {
|
||||
const QPolygonF &p = it.value();
|
||||
QRectF rect(p.boundingRect() & tileRect);
|
||||
if (AREA(rect) < AREA(QRect(0, 0, _img.width()/4, _img.width()/4)))
|
||||
continue;
|
||||
|
||||
QMap<qreal, int> map;
|
||||
QPointF center = rect.center();
|
||||
for (int j = 0; j < p.size(); j++) {
|
||||
QLineF l(p.at(j), center);
|
||||
map.insert(l.length(), j);
|
||||
}
|
||||
|
||||
QMap<qreal, int>::const_iterator jt = map.constBegin();
|
||||
|
||||
TextPointItem *item = new TextPointItem(
|
||||
p.at(jt.value()).toPoint(), &(sp.value(it.key())->text()),
|
||||
poiFont(), 0, &shieldColor, shieldBgColor(it.key().type()));
|
||||
|
||||
bool valid = false;
|
||||
while (true) {
|
||||
if (!item->collides(textItems)
|
||||
&& tileRect.contains(item->boundingRect().toRect())) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
if (++jt == map.constEnd())
|
||||
break;
|
||||
item->setPos(p.at(jt.value()).toPoint());
|
||||
}
|
||||
|
||||
if (valid)
|
||||
textItems.append(item);
|
||||
else
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processPoints(QList<TextItem*> &textItems)
|
||||
{
|
||||
qSort(_points);
|
||||
|
||||
for (int i = 0; i < _points.size(); i++) {
|
||||
MapData::Point &point = _points[i];
|
||||
const Style::Point &style = _style->point(point.type);
|
||||
bool poi = Style::isPOI(point.type);
|
||||
|
||||
if (poi && _zoom < minPOIZoom(Style::poiClass(point.type)))
|
||||
continue;
|
||||
|
||||
const QString *label = point.label.text().isEmpty()
|
||||
? 0 : &(point.label.text());
|
||||
const QImage *img = style.img().isNull() ? 0 : &style.img();
|
||||
const QFont *fnt = poi
|
||||
? poiFont(style.textFontSize()) : font(style.textFontSize());
|
||||
const QColor *color = style.textColor().isValid()
|
||||
? &style.textColor() : 0;
|
||||
|
||||
if ((!label || !fnt) && !img)
|
||||
continue;
|
||||
|
||||
if (Style::isSpot(point.type))
|
||||
point.label.setText(convertUnits(point.label.text()));
|
||||
if (Style::isSummit(point.type) && !point.label.text().isEmpty()) {
|
||||
QStringList list = point.label.text().split(" ");
|
||||
list.last() = convertUnits(list.last());
|
||||
point.label = list.join(" ");
|
||||
}
|
||||
|
||||
TextPointItem *item = new TextPointItem(QPoint(point.coordinates.lon(),
|
||||
point.coordinates.lat()), label, fnt, img, color);
|
||||
if (item->isValid() && !item->collides(textItems))
|
||||
textItems.append(item);
|
||||
else
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
48
src/map/IMG/rastertile.h
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef RASTERTILE_H
|
||||
#define RASTERTILE_H
|
||||
|
||||
#include <QImage>
|
||||
#include "mapdata.h"
|
||||
|
||||
class QPainter;
|
||||
class TextItem;
|
||||
class Style;
|
||||
|
||||
class RasterTile
|
||||
{
|
||||
public:
|
||||
RasterTile(const Style *style, int zoom, const QRect &rect,
|
||||
const QString &key, const QList<MapData::Poly> &polygons,
|
||||
const QList<MapData::Poly> &lines, QList<MapData::Point> &points)
|
||||
: _style(style), _zoom(zoom), _xy(rect.topLeft()),
|
||||
_key(key), _img(rect.size(), QImage::Format_ARGB32_Premultiplied),
|
||||
_polygons(polygons), _lines(lines), _points(points) {}
|
||||
|
||||
const QString &key() const {return _key;}
|
||||
const QPoint &xy() const {return _xy;}
|
||||
const QImage &img() const {return _img;}
|
||||
|
||||
void render();
|
||||
|
||||
private:
|
||||
void drawPolygons(QPainter *painter);
|
||||
void drawLines(QPainter *painter);
|
||||
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
|
||||
|
||||
void processPolygons(QList<TextItem *> &textItems);
|
||||
void processLines(QList<TextItem*> &textItems);
|
||||
void processPoints(QList<TextItem*> &textItems);
|
||||
void processShields(const QRect &tileRect, QList<TextItem*> &textItems);
|
||||
void processStreetNames(const QRect &tileRect, QList<TextItem*> &textItems);
|
||||
|
||||
const Style *_style;
|
||||
int _zoom;
|
||||
QPoint _xy;
|
||||
QString _key;
|
||||
QImage _img;
|
||||
QList<MapData::Poly> _polygons;
|
||||
QList<MapData::Poly> _lines;
|
||||
QList<MapData::Point> _points;
|
||||
};
|
||||
|
||||
#endif // RASTERTILE_H
|
@ -1,13 +1,15 @@
|
||||
#include <cstring>
|
||||
#include "common/rectc.h"
|
||||
#include "common/garmin.h"
|
||||
#include "deltastream.h"
|
||||
#include "huffmanstream.h"
|
||||
#include "lblfile.h"
|
||||
#include "netfile.h"
|
||||
#include "nodfile.h"
|
||||
#include "rgnfile.h"
|
||||
|
||||
|
||||
#define MASK(bits) ((2U << ((bits) - 1U)) - 1U)
|
||||
|
||||
static quint64 pointId(const QPoint &pos, quint32 type, quint32 labelPtr)
|
||||
{
|
||||
quint64 id;
|
||||
@ -49,11 +51,10 @@ bool RGNFile::skipClassFields(Handle &hdl) const
|
||||
break;
|
||||
}
|
||||
|
||||
return seek(hdl, hdl.pos() + rs);
|
||||
return seek(hdl, pos(hdl) + rs);
|
||||
}
|
||||
|
||||
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3],
|
||||
SegmentType type) const
|
||||
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3]) const
|
||||
{
|
||||
quint32 bitfield = 0xFFFFFFFF;
|
||||
|
||||
@ -61,34 +62,38 @@ bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3],
|
||||
if (!readVBitfield32(hdl, bitfield))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < 29; i++) {
|
||||
for (int i = 0, j = 0; i < 29; i++) {
|
||||
if ((flags[0] >> i) & 1) {
|
||||
if (bitfield & 1) {
|
||||
quint32 m = flags[(i >> 4) + 1] >> ((i * 2) & 0x1e) & 3;
|
||||
switch (i) {
|
||||
case 5:
|
||||
if (m == 1 && type == Point) {
|
||||
quint16 u16;
|
||||
if (!readUInt16(hdl, u16))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
quint32 m = flags[(j >> 4) + 1] >> ((j * 2) & 0x1e) & 3;
|
||||
|
||||
quint32 skip = 0;
|
||||
if (m == 3) {
|
||||
if (!readVUInt32(hdl, skip))
|
||||
return false;
|
||||
} else
|
||||
skip = m + 1;
|
||||
if (!seek(hdl, pos(hdl) + skip))
|
||||
return false;
|
||||
}
|
||||
bitfield >>= 1;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RGNFile::clearFlags()
|
||||
bool RGNFile::skipGblFields(Handle &hdl, quint32 flags) const
|
||||
{
|
||||
memset(_polygonsFlags, 0, sizeof(_polygonsFlags));
|
||||
memset(_linesFlags, 0, sizeof(_linesFlags));
|
||||
memset(_pointsFlags, 0, sizeof(_pointsFlags));
|
||||
int cnt = 0;
|
||||
|
||||
do {
|
||||
cnt = cnt + (flags & 3);
|
||||
flags = flags >> 2;
|
||||
} while (flags != 0);
|
||||
|
||||
return seek(hdl, pos(hdl) + cnt);
|
||||
}
|
||||
|
||||
bool RGNFile::init(Handle &hdl)
|
||||
@ -102,14 +107,20 @@ bool RGNFile::init(Handle &hdl)
|
||||
|
||||
if (hdrLen >= 0x68) {
|
||||
if (!(readUInt32(hdl, _polygonsOffset) && readUInt32(hdl, _polygonsSize)
|
||||
&& seek(hdl, _gmpOffset + 0x2D) && readUInt32(hdl, _polygonsFlags[0])
|
||||
&& readUInt32(hdl, _polygonsFlags[1]) && readUInt32(hdl, _polygonsFlags[2])
|
||||
&& seek(hdl, _gmpOffset + 0x29) && readUInt32(hdl, _polygonsGblFlags)
|
||||
&& readUInt32(hdl, _polygonsLclFlags[0])
|
||||
&& readUInt32(hdl, _polygonsLclFlags[1])
|
||||
&& readUInt32(hdl, _polygonsLclFlags[2])
|
||||
&& readUInt32(hdl, _linesOffset) && readUInt32(hdl, _linesSize)
|
||||
&& seek(hdl, _gmpOffset + 0x49) && readUInt32(hdl, _linesFlags[0])
|
||||
&& readUInt32(hdl, _linesFlags[1]) && readUInt32(hdl, _linesFlags[2])
|
||||
&& seek(hdl, _gmpOffset + 0x45) && readUInt32(hdl, _linesGblFlags)
|
||||
&& readUInt32(hdl, _linesLclFlags[0])
|
||||
&& readUInt32(hdl, _linesLclFlags[1])
|
||||
&& readUInt32(hdl, _linesLclFlags[2])
|
||||
&& readUInt32(hdl, _pointsOffset) && readUInt32(hdl, _pointsSize)
|
||||
&& seek(hdl, _gmpOffset + 0x65) && readUInt32(hdl, _pointsFlags[0])
|
||||
&& readUInt32(hdl, _pointsFlags[1]) && readUInt32(hdl, _pointsFlags[2])))
|
||||
&& seek(hdl, _gmpOffset + 0x61) && readUInt32(hdl, _pointsGblFlags)
|
||||
&& readUInt32(hdl, _pointsLclFlags[0])
|
||||
&& readUInt32(hdl, _pointsLclFlags[1])
|
||||
&& readUInt32(hdl, _pointsLclFlags[2])))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -147,7 +158,7 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
|
||||
qint16 lon, lat;
|
||||
quint16 len;
|
||||
|
||||
while (hdl.pos() < (int)segment.end()) {
|
||||
while (pos(hdl) < segment.end()) {
|
||||
IMG::Poly poly;
|
||||
|
||||
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
|
||||
@ -222,7 +233,7 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||
if (!seek(hdl, segment.offset()))
|
||||
return false;
|
||||
|
||||
while (hdl.pos() < (int)segment.end()) {
|
||||
while (pos(hdl) < segment.end()) {
|
||||
IMG::Poly poly;
|
||||
QPoint pos;
|
||||
|
||||
@ -230,6 +241,7 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)
|
||||
&& readVUInt32(hdl, len)))
|
||||
return false;
|
||||
Q_ASSERT(SubFile::pos(hdl) + len <= segment.end());
|
||||
|
||||
poly.type = 0x10000 | (quint16(type)<<8) | (subtype & 0x1F);
|
||||
labelPtr = 0;
|
||||
@ -239,8 +251,10 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||
LS(subdiv->lat(), 8) + LS(lat, (32-subdiv->bits())));
|
||||
|
||||
qint32 lonDelta, latDelta;
|
||||
HuffmanStream stream(*this, hdl, len, _huffmanTable,
|
||||
segmentType == Line);
|
||||
BitStream4F bs(*this, hdl, len);
|
||||
HuffmanStreamF stream(bs, _huffmanTable);
|
||||
if (!stream.init(segmentType == Line))
|
||||
return false;
|
||||
|
||||
if (shift) {
|
||||
if (!stream.readOffset(lonDelta, latDelta))
|
||||
@ -298,7 +312,11 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||
if (subtype & 0x80 && !skipClassFields(hdl))
|
||||
return false;
|
||||
if (subtype & 0x40 && !skipLclFields(hdl, segmentType == Line
|
||||
? _linesFlags : _polygonsFlags, segmentType))
|
||||
? _linesLclFlags : _polygonsLclFlags))
|
||||
return false;
|
||||
quint32 gblFlags = (segmentType == Line)
|
||||
? _linesGblFlags : _polygonsGblFlags;
|
||||
if (gblFlags && !skipGblFields(hdl, gblFlags))
|
||||
return false;
|
||||
|
||||
if (lbl && (labelPtr & 0x3FFFFF))
|
||||
@ -317,12 +335,13 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
|
||||
const SubDiv::Segment &segment = (segmentType == IndexedPoint)
|
||||
? subdiv->idxPoints() : subdiv->points();
|
||||
|
||||
|
||||
if (!segment.isValid())
|
||||
return true;
|
||||
if (!seek(hdl, segment.offset()))
|
||||
return false;
|
||||
|
||||
while (hdl.pos() < (int)segment.end()) {
|
||||
while (pos(hdl) < segment.end()) {
|
||||
IMG::Point point;
|
||||
quint8 type, subtype;
|
||||
qint16 lon, lat;
|
||||
@ -343,10 +362,9 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
|
||||
point.type = (quint16)type<<8 | subtype;
|
||||
point.coordinates = Coordinates(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
point.id = pointId(pos, point.type, labelPtr & 0x3FFFFF);
|
||||
point.poi = labelPtr & 0x400000;
|
||||
if (lbl && (labelPtr & 0x3FFFFF))
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi,
|
||||
!(point.type == 0x1400 || point.type == 0x1500
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF,
|
||||
labelPtr & 0x400000, !(point.type == 0x1400 || point.type == 0x1500
|
||||
|| point.type == 0x1e00));
|
||||
|
||||
points->append(point);
|
||||
@ -365,7 +383,7 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
||||
if (!seek(hdl, segment.offset()))
|
||||
return false;
|
||||
|
||||
while (hdl.pos() < (int)segment.end()) {
|
||||
while (pos(hdl) < segment.end()) {
|
||||
IMG::Point point;
|
||||
qint16 lon, lat;
|
||||
quint8 type, subtype;
|
||||
@ -379,7 +397,9 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
||||
return false;
|
||||
if (subtype & 0x80 && !skipClassFields(hdl))
|
||||
return false;
|
||||
if (subtype & 0x40 && !skipLclFields(hdl, _pointsFlags, Point))
|
||||
if (subtype & 0x40 && !skipLclFields(hdl, _pointsLclFlags))
|
||||
return false;
|
||||
if (_pointsGblFlags && !skipGblFields(hdl, _pointsGblFlags))
|
||||
return false;
|
||||
|
||||
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
||||
@ -393,9 +413,8 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
||||
|
||||
point.coordinates = Coordinates(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
point.id = pointId(pos, point.type, labelPtr & 0x3FFFFF);
|
||||
point.poi = labelPtr & 0x400000;
|
||||
if (lbl && (labelPtr & 0x3FFFFF))
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, false);
|
||||
|
||||
points->append(point);
|
||||
}
|
||||
@ -403,6 +422,87 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RGNFile::links(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||
NETFile *net, Handle &netHdl, NODFile *nod, Handle &nodHdl, LBLFile *lbl,
|
||||
Handle &lblHdl, QList<IMG::Poly> *lines) const
|
||||
{
|
||||
quint32 size, blockIndexIdSize, blockIndexId;
|
||||
quint8 flags;
|
||||
const SubDiv::Segment &segment = subdiv->roadReferences();
|
||||
|
||||
if (!segment.isValid())
|
||||
return true;
|
||||
if (!seek(hdl, segment.offset()))
|
||||
return false;
|
||||
|
||||
if (!net || !nod)
|
||||
return false;
|
||||
if (!(blockIndexIdSize = nod->indexIdSize(nodHdl)))
|
||||
return false;
|
||||
|
||||
while (pos(hdl) < segment.end()) {
|
||||
if (!readVUInt32(hdl, size))
|
||||
return false;
|
||||
|
||||
quint32 entryStart = pos(hdl);
|
||||
|
||||
if (!(readUInt8(hdl, flags) && readVUInt32(hdl, blockIndexIdSize,
|
||||
blockIndexId)))
|
||||
return false;
|
||||
|
||||
quint8 bits[3];
|
||||
for (int i = 0; i < 3; i++)
|
||||
bits[i] = 0x4000a08 >> (((flags >> (2*i) & 3) << 3) ^ 0x10);
|
||||
quint8 byteSize = ((bits[0] + bits[1] + bits[2]) + 7) >> 3;
|
||||
|
||||
quint32 counts;
|
||||
if (!readVUInt32(hdl, byteSize, counts))
|
||||
return false;
|
||||
|
||||
quint16 b8 = bits[0] ? (MASK(bits[0]) & counts) + 1 : 0;
|
||||
quint16 b10 = bits[1] ? (MASK(bits[1]) & (counts >> bits[0])) + 1 : 0;
|
||||
quint16 b16 = bits[2] ? (MASK(bits[2]) & (counts >> (bits[0] + bits[1])))
|
||||
+ 1 : 0;
|
||||
|
||||
NODFile::BlockInfo blockInfo;
|
||||
if (!nod->blockInfo(nodHdl, blockIndexId, blockInfo))
|
||||
return false;
|
||||
|
||||
quint8 linkId, lineId;
|
||||
for (int i = 0; i < b8 + b10 + b16; i++) {
|
||||
if (!b8 || b8 <= i) {
|
||||
quint16 v16;
|
||||
if (!readUInt16(hdl, v16))
|
||||
return false;
|
||||
|
||||
if (!b16 || b8 + b16 <= i) {
|
||||
int shift = ((i - (b8 + b16)) * 10) % 8;
|
||||
linkId = (quint8)(v16 >> shift);
|
||||
lineId = (((v16 >> shift) >> 8) & 3) + 1;
|
||||
|
||||
if (shift < 6 && i < b8 + b10 + b16 - 1)
|
||||
seek(hdl, pos(hdl) - 1);
|
||||
} else {
|
||||
linkId = (quint8)v16;
|
||||
lineId = v16 >> 8;
|
||||
Q_ASSERT(lineId > 4);
|
||||
}
|
||||
} else {
|
||||
if (!readUInt8(hdl, linkId))
|
||||
return false;
|
||||
lineId = 0;
|
||||
}
|
||||
|
||||
net->link(subdiv, shift, netHdl, nod, nodHdl, lbl, lblHdl,
|
||||
blockInfo, linkId, lineId, _huffmanTable, lines);
|
||||
}
|
||||
|
||||
Q_ASSERT(entryStart + size == pos(hdl));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QMap<RGNFile::SegmentType, SubDiv::Segment> RGNFile::segments(Handle &hdl,
|
||||
SubDiv *subdiv) const
|
||||
{
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
class LBLFile;
|
||||
class NETFile;
|
||||
class NODFile;
|
||||
|
||||
class RGNFile : public SubFile
|
||||
{
|
||||
@ -23,15 +24,14 @@ public:
|
||||
RGNFile(IMG *img)
|
||||
: SubFile(img), _offset(0), _size(0), _polygonsOffset(0),
|
||||
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
|
||||
_pointsSize(0), _init(false) {clearFlags();}
|
||||
_pointsSize(0), _init(false) {}
|
||||
RGNFile(const QString &path)
|
||||
: SubFile(path), _offset(0), _size(0), _polygonsOffset(0),
|
||||
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
|
||||
_pointsSize(0), _init(false) {clearFlags();}
|
||||
_pointsSize(0), _init(false) {}
|
||||
RGNFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), _offset(0),
|
||||
_size(0), _polygonsOffset(0), _polygonsSize(0), _linesOffset(0),
|
||||
_linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false)
|
||||
{clearFlags();}
|
||||
_linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false) {}
|
||||
|
||||
bool initialized() const {return _init;}
|
||||
bool init(Handle &hdl);
|
||||
@ -46,29 +46,35 @@ public:
|
||||
QList<IMG::Poly> *polys) const;
|
||||
bool extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
||||
Handle &lblHdl, QList<IMG::Point> *points) const;
|
||||
bool links(Handle &hdl, const SubDiv *subdiv, quint32 shift, NETFile *net,
|
||||
Handle &netHdl, NODFile *nod, Handle &nodHdl, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Poly> *lines) const;
|
||||
|
||||
bool subdivInit(Handle &hdl, SubDiv *subdiv) const;
|
||||
|
||||
private:
|
||||
QMap<SegmentType, SubDiv::Segment> segments(Handle &hdl, SubDiv *subdiv)
|
||||
const;
|
||||
void clearFlags();
|
||||
bool skipClassFields(Handle &hdl) const;
|
||||
bool skipLclFields(Handle &hdl, const quint32 flags[3], SegmentType type)
|
||||
bool skipLclFields(Handle &hdl, const quint32 flags[3])
|
||||
const;
|
||||
bool skipGblFields(Handle &hdl, quint32 flags) const;
|
||||
|
||||
quint32 _offset;
|
||||
quint32 _size;
|
||||
|
||||
quint32 _polygonsOffset;
|
||||
quint32 _polygonsSize;
|
||||
quint32 _polygonsFlags[3];
|
||||
quint32 _polygonsLclFlags[3];
|
||||
quint32 _polygonsGblFlags;
|
||||
quint32 _linesOffset;
|
||||
quint32 _linesSize;
|
||||
quint32 _linesFlags[3];
|
||||
quint32 _linesLclFlags[3];
|
||||
quint32 _linesGblFlags;
|
||||
quint32 _pointsOffset;
|
||||
quint32 _pointsSize;
|
||||
quint32 _pointsFlags[3];
|
||||
quint32 _pointsLclFlags[3];
|
||||
quint32 _pointsGblFlags;
|
||||
|
||||
HuffmanTable _huffmanTable;
|
||||
|
||||
|
@ -39,9 +39,7 @@ void Style::defaultPolygonStyle()
|
||||
_polygons[TYPE(0x1f)] = Polygon(QBrush(QColor("#9ac269"),
|
||||
Qt::BDiagPattern));
|
||||
_polygons[TYPE(0x28)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x29)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x32)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x3b)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x3c)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x3d)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x3e)] = Polygon(QBrush("#9fc4e1"));
|
||||
@ -51,13 +49,12 @@ void Style::defaultPolygonStyle()
|
||||
_polygons[TYPE(0x42)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x43)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x44)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x45)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x46)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x47)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x48)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x49)] = Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x4b)] = Polygon(QBrush("#f1f0e5"), QPen("#f1f0e5"));
|
||||
_polygons[TYPE(0x4a)] = Polygon(QBrush("#f1f0e5"), QPen("#f1f0e5"));
|
||||
_polygons[TYPE(0x4b)] = Polygon(QBrush("#f1f0e5"), QPen("#f1f0e5"));
|
||||
_polygons[TYPE(0x4c)] = Polygon(QBrush("#9fc4e1", Qt::Dense6Pattern));
|
||||
_polygons[TYPE(0x4d)] = Polygon(QBrush("#ddf1fd"));
|
||||
_polygons[TYPE(0x4e)] = Polygon(QBrush("#f8f8f8"));
|
||||
@ -66,18 +63,73 @@ void Style::defaultPolygonStyle()
|
||||
_polygons[TYPE(0x51)] = Polygon(QBrush("#9fc4e1", Qt::Dense4Pattern));
|
||||
_polygons[TYPE(0x52)] = Polygon(QBrush("#cadfaf"));
|
||||
|
||||
_drawOrder << TYPE(0x4b) << TYPE(0x4a) << TYPE(0x01) << TYPE(0x02)
|
||||
<< TYPE(0x03) << TYPE(0x17) << TYPE(0x18) << TYPE(0x1a) << TYPE(0x28)
|
||||
<< TYPE(0x29) << TYPE(0x32) << TYPE(0x3b) << TYPE(0x3c) << TYPE(0x3d)
|
||||
<< TYPE(0x3e) << TYPE(0x3f) << TYPE(0x40) << TYPE(0x41) << TYPE(0x42)
|
||||
<< TYPE(0x43) << TYPE(0x44) << TYPE(0x45) << TYPE(0x46) << TYPE(0x47)
|
||||
<< TYPE(0x48) << TYPE(0x49) << TYPE(0x4c) << TYPE(0x4d) << TYPE(0x4e)
|
||||
<< TYPE(0x4f) << TYPE(0x50) << TYPE(0x51) << TYPE(0x52) << TYPE(0x14)
|
||||
<< TYPE(0x15) << TYPE(0x16) << TYPE(0x1e) << TYPE(0x1f) << TYPE(0x04)
|
||||
<< TYPE(0x05) << TYPE(0x06) << TYPE(0x07) << TYPE(0x08) << TYPE(0x09)
|
||||
<< TYPE(0x0a) << TYPE(0x0b) << TYPE(0x0c) << TYPE(0x0d) << TYPE(0x0e)
|
||||
<< TYPE(0x0f) << TYPE(0x10) << TYPE(0x11) << TYPE(0x12) << TYPE(0x19)
|
||||
<< TYPE(0x13);
|
||||
// NT types
|
||||
_polygons[0x10800] = _polygons[TYPE(0x01)];
|
||||
_polygons[0x10801] = _polygons[TYPE(0x02)];
|
||||
_polygons[0x10802] = _polygons[TYPE(0x03)];
|
||||
_polygons[0x10901] = _polygons[TYPE(0x04)];
|
||||
_polygons[0x10902] = _polygons[TYPE(0x05)];
|
||||
_polygons[0x10903] = _polygons[TYPE(0x06)];
|
||||
_polygons[0x10904] = _polygons[TYPE(0x07)];
|
||||
_polygons[0x10905] = _polygons[TYPE(0x08)];
|
||||
_polygons[0x10906] = _polygons[TYPE(0x09)];
|
||||
_polygons[0x10907] = _polygons[TYPE(0x0a)];
|
||||
_polygons[0x10908] = _polygons[TYPE(0x0b)];
|
||||
_polygons[0x10909] = _polygons[TYPE(0x0c)];
|
||||
_polygons[0x1090a] = _polygons[TYPE(0x0d)];
|
||||
_polygons[0x1090b] = _polygons[TYPE(0x0e)];
|
||||
_polygons[0x10900] = _polygons[TYPE(0x13)];
|
||||
_polygons[0x10a01] = _polygons[TYPE(0x14)];
|
||||
_polygons[0x10a02] = _polygons[TYPE(0x15)];
|
||||
_polygons[0x10a03] = _polygons[TYPE(0x16)];
|
||||
_polygons[0x10a04] = _polygons[TYPE(0x17)];
|
||||
_polygons[0x1090c] = _polygons[TYPE(0x18)];
|
||||
_polygons[0x1090d] = _polygons[TYPE(0x19)];
|
||||
_polygons[0x1090e] = _polygons[TYPE(0x1a)];
|
||||
_polygons[0x10a05] = _polygons[TYPE(0x1e)];
|
||||
_polygons[0x10a06] = _polygons[TYPE(0x1f)];
|
||||
_polygons[0x10b01] = _polygons[TYPE(0x28)];
|
||||
_polygons[0x10b02] = _polygons[TYPE(0x32)];
|
||||
_polygons[0x10b03] = _polygons[TYPE(0x3c)];
|
||||
_polygons[0x10b04] = _polygons[TYPE(0x3d)];
|
||||
_polygons[0x10b05] = _polygons[TYPE(0x3e)];
|
||||
_polygons[0x10b06] = _polygons[TYPE(0x3f)];
|
||||
_polygons[0x10b07] = _polygons[TYPE(0x40)];
|
||||
_polygons[0x10b08] = _polygons[TYPE(0x41)];
|
||||
_polygons[0x10b09] = _polygons[TYPE(0x42)];
|
||||
_polygons[0x10b0a] = _polygons[TYPE(0x43)];
|
||||
_polygons[0x10b0b] = _polygons[TYPE(0x44)];
|
||||
_polygons[0x10b0c] = _polygons[TYPE(0x46)];
|
||||
_polygons[0x10b0d] = _polygons[TYPE(0x47)];
|
||||
_polygons[0x10b0e] = _polygons[TYPE(0x48)];
|
||||
_polygons[0x10b0f] = _polygons[TYPE(0x49)];
|
||||
_polygons[0x10d01] = _polygons[TYPE(0x4b)];
|
||||
_polygons[0x10b10] = _polygons[TYPE(0x4c)];
|
||||
_polygons[0x10c00] = _polygons[TYPE(0x4d)];
|
||||
_polygons[0x10c01] = _polygons[TYPE(0x4e)];
|
||||
_polygons[0x10c02] = _polygons[TYPE(0x4f)];
|
||||
_polygons[0x10c03] = _polygons[TYPE(0x50)];
|
||||
_polygons[0x10c04] = _polygons[TYPE(0x51)];
|
||||
_polygons[0x10c05] = _polygons[TYPE(0x52)];
|
||||
|
||||
// Draw order
|
||||
_drawOrder << TYPE(0x4b) << 0x10d01 << TYPE(0x4a) << TYPE(0x01) << 0x10800
|
||||
<< TYPE(0x02) << 0x10801 << TYPE(0x03) << 0x10802 << TYPE(0x17) << 0x10a04
|
||||
<< TYPE(0x18) << 0x1090c << TYPE(0x1a) << 0x1090e << TYPE(0x28) << 0x10b01
|
||||
<< TYPE(0x32) << 0x10b02 << TYPE(0x3c) << 0x10b03 << TYPE(0x3d) << 0x10b04
|
||||
<< TYPE(0x3e) << 0x10b05 << TYPE(0x3f) << 0x10b06 << TYPE(0x40) << 0x10b07
|
||||
<< TYPE(0x41) << 0x10b08 << TYPE(0x42) << 0x10b09 << TYPE(0x43) << 0x10b0a
|
||||
<< TYPE(0x44) << 0x10b0b << TYPE(0x46) << 0x10b0c << TYPE(0x47) << 0x10b0d
|
||||
<< TYPE(0x48) << 0x10b0e << TYPE(0x49) << 0x10b0f << TYPE(0x4c) << 0x10b10
|
||||
<< TYPE(0x4d) << 0x10c00 << TYPE(0x4e) << 0x10c01 << TYPE(0x4f) << 0x10c02
|
||||
<< TYPE(0x50) << 0x10c03 << TYPE(0x51) << 0x10c04 << TYPE(0x52) << 0x10c05
|
||||
<< TYPE(0x14) << 0x10a01 << TYPE(0x15) << 0x10a02 << TYPE(0x16) << 0x10a03
|
||||
<< TYPE(0x1e) << 0x10a05 << TYPE(0x1f) << 0x10a06 << TYPE(0x04) << 0x10901
|
||||
<< TYPE(0x05) << 0x10902 << TYPE(0x06) << 0x10903 << TYPE(0x07) << 0x10904
|
||||
<< TYPE(0x08) << 0x10905 << TYPE(0x09) << 0x10906 << TYPE(0x0a) << 0x10907
|
||||
<< TYPE(0x0b) << 0x10908 << TYPE(0x0c) << 0x10909 << TYPE(0x0d) << 0x1090a
|
||||
<< TYPE(0x0e) << 0x1090b << TYPE(0x0f) << TYPE(0x10) << TYPE(0x11)
|
||||
<< TYPE(0x12) << TYPE(0x19) << 0x1090d << TYPE(0x13) << 0x10900;
|
||||
}
|
||||
|
||||
static QImage railroad()
|
||||
@ -148,6 +200,22 @@ void Style::defaultLineStyle()
|
||||
//_lines[TYPE(0x28)] = Line(QPen(QColor("#5a5a5a"), 1, Qt::SolidLine));
|
||||
_lines[TYPE(0x29)] = Line(QPen(QColor("#5a5a5a"), 1, Qt::SolidLine));
|
||||
_lines[TYPE(0x29)].setTextFontSize(None);
|
||||
|
||||
// NT types
|
||||
_lines[0x10c00] = _lines[TYPE(0x14)];
|
||||
_lines[0x10a00] = _lines[TYPE(0x18)];
|
||||
_lines[0x10b04] = _lines[TYPE(0x1e)];
|
||||
_lines[0x10a01] = _lines[TYPE(0x1f)];
|
||||
_lines[0x10900] = _lines[TYPE(0x20)];
|
||||
_lines[0x10901] = _lines[TYPE(0x21)];
|
||||
_lines[0x10902] = _lines[TYPE(0x22)];
|
||||
_lines[0x10903] = _lines[TYPE(0x23)];
|
||||
_lines[0x10904] = _lines[TYPE(0x24)];
|
||||
_lines[0x10905] = _lines[TYPE(0x25)];
|
||||
_lines[0x10a02] = _lines[TYPE(0x26)];
|
||||
_lines[0x10c02] = _lines[TYPE(0x27)];
|
||||
//_lines[0x10c03] = _lines[TYPE(0x28)];
|
||||
_lines[0x10c04] = _lines[TYPE(0x29)];
|
||||
}
|
||||
|
||||
void Style::defaultPointStyle()
|
||||
@ -221,10 +289,13 @@ void Style::defaultPointStyle()
|
||||
_points[0x2d0b] = Point(QImage(":/airfield-11.png"));
|
||||
|
||||
_points[0x2e02] = Point(QImage(":/grocery-11.png"));
|
||||
_points[0x2e03] = Point(QImage(":/shop-11.png"));
|
||||
_points[0x2e05] = Point(QImage(":/pharmacy-11.png"));
|
||||
_points[0x2e06] = Point(QImage(":/convenience-11.png"));
|
||||
_points[0x2e07] = Point(QImage(":/clothing-store-11.png"));
|
||||
_points[0x2e08] = Point(QImage(":/garden-centre-11.png"));
|
||||
_points[0x2e09] = Point(QImage(":/furniture-11.png"));
|
||||
_points[0x2e0a] = Point(QImage(":/shop-11.png"));
|
||||
_points[0x2e0c] = Point(QImage(":/shop-11.png"));
|
||||
|
||||
_points[0x2f01] = Point(QImage(":/fuel-11.png"));
|
||||
@ -248,7 +319,8 @@ void Style::defaultPointStyle()
|
||||
_points[0x3001] = Point(QImage(":/police-11.png"));
|
||||
_points[0x3002] = Point(QImage(":/hospital-11.png"));
|
||||
_points[0x3003] = Point(QImage(":/town-hall-11.png"));
|
||||
_points[0x3007] = Point(QImage(":/prison-11.png"));
|
||||
_points[0x3006] = Point(QImage(":/entrance-alt1-11.png"));
|
||||
_points[0x3007] = Point(QImage(":/town-hall-11.png"));
|
||||
_points[0x3008] = Point(QImage(":/fire-station-11.png"));
|
||||
|
||||
_points[0x4000] = Point(QImage(":/golf-11.png"));
|
||||
@ -296,6 +368,87 @@ void Style::defaultPointStyle()
|
||||
_points[0x6513] = Point(QImage(":/wetland-11.png"));
|
||||
_points[0x6604] = Point(QImage(":/beach-11.png"));
|
||||
_points[0x6616] = Point(QImage(":/mountain-11.png"));
|
||||
|
||||
|
||||
// NT types
|
||||
_points[0x11401] = _points[TYPE(0x01)];
|
||||
_points[0x11402] = _points[TYPE(0x02)];
|
||||
_points[0x11403] = _points[TYPE(0x03)];
|
||||
_points[0x10b00] = _points[0x2a00];
|
||||
_points[0x10b01] = _points[0x2a01];
|
||||
_points[0x10b02] = _points[0x2a02];
|
||||
_points[0x10b03] = _points[0x2a03];
|
||||
_points[0x10b04] = _points[0x2a04];
|
||||
_points[0x10b05] = _points[0x2a05];
|
||||
_points[0x10b06] = _points[0x2a06];
|
||||
_points[0x10b07] = _points[0x2a07];
|
||||
_points[0x10b08] = _points[0x2a08];
|
||||
_points[0x10b09] = _points[0x2a09];
|
||||
_points[0x10b0a] = _points[0x2a0a];
|
||||
_points[0x10b0b] = _points[0x2a0b];
|
||||
_points[0x10b0c] = _points[0x2a0c];
|
||||
_points[0x10b0d] = _points[0x2a0d];
|
||||
_points[0x10b0e] = _points[0x2a0e];
|
||||
_points[0x10b0f] = _points[0x2a0f];
|
||||
_points[0x10b10] = _points[0x2a10];
|
||||
_points[0x10b11] = _points[0x2a11];
|
||||
_points[0x10c01] = _points[0x2b01];
|
||||
_points[0x10c02] = _points[0x2b02];
|
||||
_points[0x10c03] = _points[0x2b03];
|
||||
_points[0x10c04] = _points[0x2b04];
|
||||
_points[0x10d01] = _points[0x2c01];
|
||||
_points[0x10d02] = _points[0x2c02];
|
||||
_points[0x10d03] = _points[0x2c03];
|
||||
_points[0x10d04] = _points[0x2c04];
|
||||
_points[0x10d05] = _points[0x2c05];
|
||||
_points[0x10d06] = _points[0x2c06];
|
||||
_points[0x10d07] = _points[0x2c07];
|
||||
_points[0x10d08] = _points[0x2c08];
|
||||
_points[0x10d0a] = _points[0x2c0a];
|
||||
_points[0x10d0b] = _points[0x2c0b];
|
||||
_points[0x10d0d] = _points[0x2c0d];
|
||||
_points[0x10d0e] = _points[0x2c0e];
|
||||
_points[0x10d10] = _points[0x2c10];
|
||||
_points[0x10e01] = _points[0x2d01];
|
||||
_points[0x10e02] = _points[0x2d02];
|
||||
_points[0x10e03] = _points[0x2d03];
|
||||
_points[0x10e04] = _points[0x2d04];
|
||||
_points[0x10e05] = _points[0x2d05];
|
||||
_points[0x10e06] = _points[0x2d06];
|
||||
_points[0x10e07] = _points[0x2d07];
|
||||
_points[0x10e08] = _points[0x2d08];
|
||||
_points[0x10e09] = _points[0x2d09];
|
||||
_points[0x10e0a] = _points[0x2d0a];
|
||||
_points[0x10e0b] = _points[0x2d0b];
|
||||
_points[0x10f02] = _points[0x2e02];
|
||||
_points[0x10f03] = _points[0x2e03];
|
||||
_points[0x10f05] = _points[0x2e05];
|
||||
_points[0x10f06] = _points[0x2e06];
|
||||
_points[0x10f07] = _points[0x2e07];
|
||||
_points[0x10f08] = _points[0x2e08];
|
||||
_points[0x10f09] = _points[0x2e09];
|
||||
_points[0x10f0a] = _points[0x2e0a];
|
||||
_points[0x11001] = _points[0x2f01];
|
||||
_points[0x11002] = _points[0x2f02];
|
||||
_points[0x11003] = _points[0x2f03];
|
||||
_points[0x11004] = _points[0x2f04];
|
||||
_points[0x11005] = _points[0x2f05];
|
||||
_points[0x11006] = _points[0x2f06];
|
||||
_points[0x11007] = _points[0x2f07];
|
||||
_points[0x11008] = _points[0x2f08];
|
||||
_points[0x11009] = _points[0x2f09];
|
||||
_points[0x1100b] = _points[0x2f0b];
|
||||
_points[0x1100c] = _points[0x2f0c];
|
||||
_points[0x11010] = _points[0x2f10];
|
||||
_points[0x11012] = _points[0x2f12];
|
||||
_points[0x11013] = _points[0x2f13];
|
||||
_points[0x11017] = _points[0x2f17];
|
||||
_points[0x11101] = _points[0x3001];
|
||||
_points[0x11102] = _points[0x3002];
|
||||
_points[0x11103] = _points[0x3003];
|
||||
_points[0x11106] = _points[0x3006];
|
||||
_points[0x11107] = _points[0x3007];
|
||||
_points[0x11108] = _points[0x3008];
|
||||
}
|
||||
|
||||
static bool readBitmap(SubFile *file, SubFile::Handle &hdl, QImage &img,
|
||||
@ -359,7 +512,7 @@ static bool skipLocalization(SubFile *file, SubFile::Handle &hdl)
|
||||
len = len >> 2;
|
||||
}
|
||||
|
||||
if (!file->seek(hdl, hdl.pos() + len))
|
||||
if (!file->seek(hdl, file->pos(hdl) + len))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -985,19 +1138,26 @@ const Style::Point &Style::point(quint32 type) const
|
||||
|
||||
Style::POIClass Style::poiClass(quint32 type)
|
||||
{
|
||||
if ((type >= 0x2a00 && type < 0x2b00) || type == 0x2c0a || type == 0x2d02)
|
||||
if ((type >= 0x2a00 && type < 0x2b00) || type == 0x2c0a || type == 0x2d02
|
||||
|| (type & 0xffff00) == TYPE(0x10b))
|
||||
return Food;
|
||||
else if (type >= 0x2b00 && type < 0x2c00)
|
||||
else if ((type >= 0x2b00 && type < 0x2c00)
|
||||
|| (type & 0xffff00) == TYPE(0x10c))
|
||||
return Accommodation;
|
||||
else if (type >= 0x2c00 && type < 0x2e00)
|
||||
else if ((type >= 0x2c00 && type < 0x2e00)
|
||||
|| (type & 0xffff00) == TYPE(0x10d) || (type & 0xffff00) == TYPE(0x10e))
|
||||
return Recreation;
|
||||
else if (type >= 0x2e00 && type < 0x2f00)
|
||||
else if ((type >= 0x2e00 && type < 0x2f00)
|
||||
|| (type & 0xffff00) == TYPE(0x10f))
|
||||
return Shopping;
|
||||
else if ((type >= 0x2f00 && type < 0x2f0f) || type == 0x2f17)
|
||||
else if ((type >= 0x2f00 && type < 0x2f0f) || type == 0x2f17
|
||||
|| (type >= 0x11001 && type < 0x1100f))
|
||||
return Transport;
|
||||
else if (type >= 0x2f0f && type < 0x3000)
|
||||
else if ((type >= 0x2f0f && type < 0x3000)
|
||||
|| (type >= 0x1100f && type < 0x11100))
|
||||
return Services;
|
||||
else if (type >= 0x3000 && type < 0x3100)
|
||||
else if ((type >= 0x3000 && type < 0x3100)
|
||||
|| (type & 0xffff00) == TYPE(0x111))
|
||||
return Community;
|
||||
else if (type >= 0x4000 && type < 0x6000)
|
||||
return Elementary;
|
||||
|
@ -108,15 +108,19 @@ public:
|
||||
const Point &point(quint32 type) const;
|
||||
const QList<quint32> &drawOrder() const {return _drawOrder;}
|
||||
|
||||
static bool isPOI(quint32 type)
|
||||
{return !((type >= TYPE(0x01) && type <= TYPE(0x1f))
|
||||
|| (type >= 0x11400 && type < 0x11500));}
|
||||
static bool isContourLine(quint32 type)
|
||||
{return ((type >= TYPE(0x20) && type <= TYPE(0x25))
|
||||
|| (type & 0xffff00) == TYPE(0x109));}
|
||||
static bool isWaterArea(quint32 type)
|
||||
{return (type >= TYPE(0x3c) && type <= TYPE(0x44));}
|
||||
{return ((type >= TYPE(0x3c) && type <= TYPE(0x44))
|
||||
|| (type & 0xffff00) == TYPE(0x10b));}
|
||||
static bool isMilitaryArea(quint32 type)
|
||||
{return (type == TYPE(0x04));}
|
||||
{return (type == TYPE(0x04) || type == 0x10901);}
|
||||
static bool isNatureReserve(quint32 type)
|
||||
{return (type == TYPE(0x16));}
|
||||
{return (type == TYPE(0x16) || type == 0x10a03);}
|
||||
static bool isSpot(quint32 type)
|
||||
{return (type == TYPE(0x62) || type == TYPE(0x63));}
|
||||
static bool isSummit(quint32 type)
|
||||
|
@ -21,8 +21,9 @@ public:
|
||||
quint32 _offset, _end;
|
||||
};
|
||||
|
||||
SubDiv(quint32 offset, qint32 lon, qint32 lat, int bits, quint8 objects)
|
||||
: _lon(lon), _lat(lat), _bits(bits), _init(false)
|
||||
SubDiv(quint32 offset, qint32 lon, qint32 lat, quint8 level, quint8 bits,
|
||||
quint8 objects) : _lon(lon), _lat(lat), _level(level), _bits(bits),
|
||||
_init(false)
|
||||
{
|
||||
_tre.objects = objects;
|
||||
_tre.offset = offset;
|
||||
@ -78,6 +79,7 @@ public:
|
||||
qint32 lon() const {return _lon;}
|
||||
qint32 lat() const {return _lat;}
|
||||
quint8 bits() const {return _bits;}
|
||||
quint8 level() const {return _level;}
|
||||
|
||||
// Valid only after initialization
|
||||
Segment points() const
|
||||
@ -94,6 +96,8 @@ public:
|
||||
{return Segment(_rgn.extLinesOffset, _rgn.extLinesEnd);}
|
||||
Segment extPolygons() const
|
||||
{return Segment(_rgn.extPolygonsOffset, _rgn.extPolygonsEnd);}
|
||||
Segment roadReferences() const
|
||||
{return Segment(_rgn.roadReferencesOffset, _rgn.roadReferencesEnd);}
|
||||
|
||||
// Valid only until initialization
|
||||
quint8 objects() const {return _tre.objects;}
|
||||
@ -142,6 +146,7 @@ private:
|
||||
};
|
||||
|
||||
qint32 _lon, _lat;
|
||||
quint8 _level;
|
||||
quint8 _bits;
|
||||
bool _init;
|
||||
union {
|
||||
|