Compare commits
101 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 |
@ -1,4 +1,4 @@
|
|||||||
version: 7.30.{build}
|
version: 7.33.{build}
|
||||||
|
|
||||||
configuration:
|
configuration:
|
||||||
- Release
|
- Release
|
||||||
|
35
gpxsee.pro
@ -3,7 +3,7 @@ unix:!macx {
|
|||||||
} else {
|
} else {
|
||||||
TARGET = GPXSee
|
TARGET = GPXSee
|
||||||
}
|
}
|
||||||
VERSION = 7.30
|
VERSION = 7.33
|
||||||
|
|
||||||
QT += core \
|
QT += core \
|
||||||
gui \
|
gui \
|
||||||
@ -14,12 +14,14 @@ greaterThan(QT_MAJOR_VERSION, 4) {
|
|||||||
QT += widgets
|
QT += widgets
|
||||||
QT += printsupport
|
QT += printsupport
|
||||||
}
|
}
|
||||||
lessThan(QT_VERSION, 5.4.0) {QT += opengl}
|
lessThan(QT_MAJOR_VERSION, 5) {QT += opengl}
|
||||||
|
equals(QT_MAJOR_VERSION, 5) : lessThan(QT_MINOR_VERSION, 4) {QT += opengl}
|
||||||
|
|
||||||
INCLUDEPATH += ./src
|
INCLUDEPATH += ./src
|
||||||
HEADERS += src/common/config.h \
|
HEADERS += src/common/config.h \
|
||||||
src/GUI/graphicsscene.h \
|
src/GUI/graphicsscene.h \
|
||||||
src/GUI/mapaction.h \
|
src/GUI/mapaction.h \
|
||||||
|
src/GUI/marginswidget.h \
|
||||||
src/GUI/popup.h \
|
src/GUI/popup.h \
|
||||||
src/common/garmin.h \
|
src/common/garmin.h \
|
||||||
src/common/staticassert.h \
|
src/common/staticassert.h \
|
||||||
@ -52,7 +54,6 @@ HEADERS += src/common/config.h \
|
|||||||
src/GUI/palette.h \
|
src/GUI/palette.h \
|
||||||
src/GUI/heartrategraph.h \
|
src/GUI/heartrategraph.h \
|
||||||
src/GUI/trackinfo.h \
|
src/GUI/trackinfo.h \
|
||||||
src/GUI/exportdialog.h \
|
|
||||||
src/GUI/fileselectwidget.h \
|
src/GUI/fileselectwidget.h \
|
||||||
src/GUI/margins.h \
|
src/GUI/margins.h \
|
||||||
src/GUI/temperaturegraph.h \
|
src/GUI/temperaturegraph.h \
|
||||||
@ -94,6 +95,7 @@ HEADERS += src/common/config.h \
|
|||||||
src/map/IMG/gmap.h \
|
src/map/IMG/gmap.h \
|
||||||
src/map/IMG/huffmanstream.h \
|
src/map/IMG/huffmanstream.h \
|
||||||
src/map/IMG/huffmantable.h \
|
src/map/IMG/huffmantable.h \
|
||||||
|
src/map/IMG/nodfile.h \
|
||||||
src/map/IMG/mapdata.h \
|
src/map/IMG/mapdata.h \
|
||||||
src/map/IMG/rastertile.h \
|
src/map/IMG/rastertile.h \
|
||||||
src/map/IMG/textpathitem.h \
|
src/map/IMG/textpathitem.h \
|
||||||
@ -196,8 +198,11 @@ HEADERS += src/common/config.h \
|
|||||||
src/data/cupparser.h \
|
src/data/cupparser.h \
|
||||||
src/data/gpiparser.h \
|
src/data/gpiparser.h \
|
||||||
src/data/address.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 \
|
SOURCES += src/main.cpp \
|
||||||
|
src/GUI/marginswidget.cpp \
|
||||||
src/GUI/popup.cpp \
|
src/GUI/popup.cpp \
|
||||||
src/common/coordinates.cpp \
|
src/common/coordinates.cpp \
|
||||||
src/common/rectc.cpp \
|
src/common/rectc.cpp \
|
||||||
@ -222,7 +227,6 @@ SOURCES += src/main.cpp \
|
|||||||
src/GUI/palette.cpp \
|
src/GUI/palette.cpp \
|
||||||
src/GUI/heartrategraph.cpp \
|
src/GUI/heartrategraph.cpp \
|
||||||
src/GUI/trackinfo.cpp \
|
src/GUI/trackinfo.cpp \
|
||||||
src/GUI/exportdialog.cpp \
|
|
||||||
src/GUI/fileselectwidget.cpp \
|
src/GUI/fileselectwidget.cpp \
|
||||||
src/GUI/temperaturegraph.cpp \
|
src/GUI/temperaturegraph.cpp \
|
||||||
src/GUI/trackitem.cpp \
|
src/GUI/trackitem.cpp \
|
||||||
@ -256,6 +260,7 @@ SOURCES += src/main.cpp \
|
|||||||
src/map/IMG/gmap.cpp \
|
src/map/IMG/gmap.cpp \
|
||||||
src/map/IMG/huffmanstream.cpp \
|
src/map/IMG/huffmanstream.cpp \
|
||||||
src/map/IMG/huffmantable.cpp \
|
src/map/IMG/huffmantable.cpp \
|
||||||
|
src/map/IMG/nodfile.cpp \
|
||||||
src/map/IMG/mapdata.cpp \
|
src/map/IMG/mapdata.cpp \
|
||||||
src/map/IMG/rastertile.cpp \
|
src/map/IMG/rastertile.cpp \
|
||||||
src/map/IMG/textpathitem.cpp \
|
src/map/IMG/textpathitem.cpp \
|
||||||
@ -341,13 +346,15 @@ SOURCES += src/main.cpp \
|
|||||||
src/data/cupparser.cpp \
|
src/data/cupparser.cpp \
|
||||||
src/GUI/graphicsscene.cpp \
|
src/GUI/graphicsscene.cpp \
|
||||||
src/data/gpiparser.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) {
|
greaterThan(QT_MAJOR_VERSION, 4) {
|
||||||
HEADERS += src/data/geojsonparser.h
|
HEADERS += src/data/geojsonparser.h
|
||||||
SOURCES += src/data/geojsonparser.cpp
|
SOURCES += src/data/geojsonparser.cpp
|
||||||
}
|
}
|
||||||
greaterThan(QT_VERSION, 5.1.0) {
|
equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 4) {
|
||||||
HEADERS += src/GUI/timezoneinfo.h
|
HEADERS += src/GUI/timezoneinfo.h
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,10 +377,11 @@ TRANSLATIONS = lang/gpxsee_en.ts \
|
|||||||
lang/gpxsee_es.ts \
|
lang/gpxsee_es.ts \
|
||||||
lang/gpxsee_pt_BR.ts \
|
lang/gpxsee_pt_BR.ts \
|
||||||
lang/gpxsee_uk.ts \
|
lang/gpxsee_uk.ts \
|
||||||
lang/gpxsee_hu.ts
|
lang/gpxsee_hu.ts \
|
||||||
|
lang/gpxsee_it.ts
|
||||||
|
|
||||||
macx {
|
macx {
|
||||||
ICON = icons/gpxsee.icns
|
ICON = icons/app/gpxsee.icns
|
||||||
QMAKE_INFO_PLIST = pkg/Info.plist
|
QMAKE_INFO_PLIST = pkg/Info.plist
|
||||||
locale.path = Contents/Resources/translations
|
locale.path = Contents/Resources/translations
|
||||||
locale.files = lang/gpxsee_en.qm \
|
locale.files = lang/gpxsee_en.qm \
|
||||||
@ -390,7 +398,8 @@ macx {
|
|||||||
lang/gpxsee_es.qm \
|
lang/gpxsee_es.qm \
|
||||||
lang/gpxsee_pt_BR.qm \
|
lang/gpxsee_pt_BR.qm \
|
||||||
lang/gpxsee_uk.qm \
|
lang/gpxsee_uk.qm \
|
||||||
lang/gpxsee_hu.qm
|
lang/gpxsee_hu.qm \
|
||||||
|
lang/gpxsee_it.qm
|
||||||
csv.path = Contents/Resources
|
csv.path = Contents/Resources
|
||||||
csv.files = pkg/csv
|
csv.files = pkg/csv
|
||||||
maps.path = Contents/Resources
|
maps.path = Contents/Resources
|
||||||
@ -415,7 +424,7 @@ macx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
win32 {
|
win32 {
|
||||||
RC_ICONS = icons/gpxsee.ico \
|
RC_ICONS = icons/app/gpxsee.ico \
|
||||||
icons/formats/gpx.ico \
|
icons/formats/gpx.ico \
|
||||||
icons/formats/tcx.ico \
|
icons/formats/tcx.ico \
|
||||||
icons/formats/kml.ico \
|
icons/formats/kml.ico \
|
||||||
@ -445,8 +454,8 @@ unix:!macx {
|
|||||||
csv.path = $$PREFIX/share/gpxsee/csv
|
csv.path = $$PREFIX/share/gpxsee/csv
|
||||||
locale.files = lang/*.qm
|
locale.files = lang/*.qm
|
||||||
locale.path = $$PREFIX/share/gpxsee/translations
|
locale.path = $$PREFIX/share/gpxsee/translations
|
||||||
icon.files = icons/gpxsee.png
|
icon.files = icons/app/hicolor/*
|
||||||
icon.path = $$PREFIX/share/pixmaps
|
icon.path = $$PREFIX/share/icons/hicolor
|
||||||
desktop.files = pkg/gpxsee.desktop
|
desktop.files = pkg/gpxsee.desktop
|
||||||
desktop.path = $$PREFIX/share/applications
|
desktop.path = $$PREFIX/share/applications
|
||||||
mime.files = pkg/gpxsee.xml
|
mime.files = pkg/gpxsee.xml
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
<!-- GUI -->
|
<!-- GUI -->
|
||||||
<file alias="gpxsee.png">icons/gpxsee.png</file>
|
<file alias="gpxsee.png">icons/app/gpxsee.png</file>
|
||||||
<file alias="gpxsee@2x.png">icons/gpxsee@2x.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.png">icons/GUI/dialog-close.png</file>
|
||||||
<file alias="dialog-close@2x.png">icons/GUI/dialog-close@2x.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>
|
<file alias="document-open.png">icons/GUI/document-open.png</file>
|
||||||
|
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/gpxsee.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
icons/app/hicolor/16x16/gpxsee.png
Normal file
After Width: | Height: | Size: 571 B |
BIN
icons/app/hicolor/32x32/gpxsee.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
icons/app/hicolor/48x48/gpxsee.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
icons/app/hicolor/64x64/gpxsee.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
33
icons/app/hicolor/scalable/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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!DOCTYPE TS>
|
<!DOCTYPE TS>
|
||||||
<TS version="2.1" language="en_US">
|
<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>
|
</TS>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
; The name of the installer
|
; The name of the installer
|
||||||
Name "GPXSee"
|
Name "GPXSee"
|
||||||
; Program version
|
; Program version
|
||||||
!define VERSION "7.30"
|
!define VERSION "7.33"
|
||||||
|
|
||||||
; The file to write
|
; The file to write
|
||||||
OutFile "GPXSee-${VERSION}.exe"
|
OutFile "GPXSee-${VERSION}.exe"
|
||||||
@ -177,6 +177,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
|
|||||||
!insertmacro LOCALIZATION "French" "fr"
|
!insertmacro LOCALIZATION "French" "fr"
|
||||||
!insertmacro LOCALIZATION "German" "de"
|
!insertmacro LOCALIZATION "German" "de"
|
||||||
!insertmacro LOCALIZATION "Hungarian" "hu"
|
!insertmacro LOCALIZATION "Hungarian" "hu"
|
||||||
|
!insertmacro LOCALIZATION "Italian" "it"
|
||||||
!insertmacro LOCALIZATION "Norwegian" "nb"
|
!insertmacro LOCALIZATION "Norwegian" "nb"
|
||||||
!insertmacro LOCALIZATION "Polish" "pl"
|
!insertmacro LOCALIZATION "Polish" "pl"
|
||||||
!insertmacro LOCALIZATION "Portuguese (Brazil)" "pt_BR"
|
!insertmacro LOCALIZATION "Portuguese (Brazil)" "pt_BR"
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
; The name of the installer
|
; The name of the installer
|
||||||
Name "GPXSee"
|
Name "GPXSee"
|
||||||
; Program version
|
; Program version
|
||||||
!define VERSION "7.30"
|
!define VERSION "7.33"
|
||||||
|
|
||||||
; The file to write
|
; The file to write
|
||||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||||
@ -184,6 +184,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
|
|||||||
!insertmacro LOCALIZATION "French" "fr"
|
!insertmacro LOCALIZATION "French" "fr"
|
||||||
!insertmacro LOCALIZATION "German" "de"
|
!insertmacro LOCALIZATION "German" "de"
|
||||||
!insertmacro LOCALIZATION "Hungarian" "hu"
|
!insertmacro LOCALIZATION "Hungarian" "hu"
|
||||||
|
!insertmacro LOCALIZATION "Italian" "it"
|
||||||
!insertmacro LOCALIZATION "Norwegian" "nb"
|
!insertmacro LOCALIZATION "Norwegian" "nb"
|
||||||
!insertmacro LOCALIZATION "Polish" "pl"
|
!insertmacro LOCALIZATION "Polish" "pl"
|
||||||
!insertmacro LOCALIZATION "Portuguese (Brazil)" "pt_BR"
|
!insertmacro LOCALIZATION "Portuguese (Brazil)" "pt_BR"
|
||||||
|
@ -12,7 +12,8 @@ FileSelectWidget::FileSelectWidget(QWidget *parent) : QWidget(parent)
|
|||||||
{
|
{
|
||||||
QFontMetrics fm(QApplication::font());
|
QFontMetrics fm(QApplication::font());
|
||||||
_edit = new QLineEdit();
|
_edit = new QLineEdit();
|
||||||
_edit->setMinimumWidth(fm.boundingRect(QDir::homePath()).width());
|
_edit->setMinimumWidth(fm.averageCharWidth() * (QDir::homePath().length()
|
||||||
|
+ 12));
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
_button = new QPushButton("...");
|
_button = new QPushButton("...");
|
||||||
_button->setMaximumWidth(_button->sizeHint().width() / 2);
|
_button->setMaximumWidth(_button->sizeHint().width() / 2);
|
||||||
@ -41,3 +42,33 @@ void FileSelectWidget::browse()
|
|||||||
if (!fileName.isEmpty())
|
if (!fileName.isEmpty())
|
||||||
_edit->setText(fileName);
|
_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:
|
public:
|
||||||
FileSelectWidget(QWidget *parent = 0);
|
FileSelectWidget(QWidget *parent = 0);
|
||||||
|
|
||||||
QString file() {return _edit->text();}
|
QString file() const {return _edit->text();}
|
||||||
void setFile(const QString &file) {_edit->setText(file);}
|
void setFile(const QString &file) {_edit->setText(file);}
|
||||||
void setFilter(const QString &filter) {_filter = filter;}
|
void setFilter(const QString &filter) {_filter = filter;}
|
||||||
|
bool checkFile(QString &error) const;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void browse();
|
void browse();
|
||||||
|
291
src/GUI/gui.cpp
@ -230,13 +230,20 @@ void GUI::createActions()
|
|||||||
_printFileAction->setActionGroup(_fileActionGroup);
|
_printFileAction->setActionGroup(_fileActionGroup);
|
||||||
connect(_printFileAction, SIGNAL(triggered()), this, SLOT(printFile()));
|
connect(_printFileAction, SIGNAL(triggered()), this, SLOT(printFile()));
|
||||||
addAction(_printFileAction);
|
addAction(_printFileAction);
|
||||||
_exportFileAction = new QAction(QIcon(EXPORT_FILE_ICON),
|
_exportPDFFileAction = new QAction(QIcon(EXPORT_FILE_ICON),
|
||||||
tr("Export to PDF..."), this);
|
tr("Export to PDF..."), this);
|
||||||
_exportFileAction->setMenuRole(QAction::NoRole);
|
_exportPDFFileAction->setMenuRole(QAction::NoRole);
|
||||||
_exportFileAction->setShortcut(EXPORT_SHORTCUT);
|
_exportPDFFileAction->setShortcut(PDF_EXPORT_SHORTCUT);
|
||||||
_exportFileAction->setActionGroup(_fileActionGroup);
|
_exportPDFFileAction->setActionGroup(_fileActionGroup);
|
||||||
connect(_exportFileAction, SIGNAL(triggered()), this, SLOT(exportFile()));
|
connect(_exportPDFFileAction, SIGNAL(triggered()), this, SLOT(exportPDFFile()));
|
||||||
addAction(_exportFileAction);
|
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 = new QAction(QIcon(CLOSE_FILE_ICON), tr("Close"), this);
|
||||||
_closeFileAction->setMenuRole(QAction::NoRole);
|
_closeFileAction->setMenuRole(QAction::NoRole);
|
||||||
_closeFileAction->setShortcut(CLOSE_SHORTCUT);
|
_closeFileAction->setShortcut(CLOSE_SHORTCUT);
|
||||||
@ -497,7 +504,8 @@ void GUI::createMenus()
|
|||||||
fileMenu->addAction(_openFileAction);
|
fileMenu->addAction(_openFileAction);
|
||||||
fileMenu->addSeparator();
|
fileMenu->addSeparator();
|
||||||
fileMenu->addAction(_printFileAction);
|
fileMenu->addAction(_printFileAction);
|
||||||
fileMenu->addAction(_exportFileAction);
|
fileMenu->addAction(_exportPDFFileAction);
|
||||||
|
fileMenu->addAction(_exportPNGFileAction);
|
||||||
fileMenu->addSeparator();
|
fileMenu->addSeparator();
|
||||||
fileMenu->addAction(_statisticsAction);
|
fileMenu->addAction(_statisticsAction);
|
||||||
fileMenu->addSeparator();
|
fileMenu->addSeparator();
|
||||||
@ -928,7 +936,7 @@ void GUI::openOptions()
|
|||||||
Options options(_options);
|
Options options(_options);
|
||||||
bool reload = false;
|
bool reload = false;
|
||||||
|
|
||||||
OptionsDialog dialog(&options, this);
|
OptionsDialog dialog(options, _units, this);
|
||||||
if (dialog.exec() != QDialog::Accepted)
|
if (dialog.exec() != QDialog::Accepted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -970,6 +978,7 @@ void GUI::openOptions()
|
|||||||
SET_TRACK_OPTION(dataUseDEM, useDEM);
|
SET_TRACK_OPTION(dataUseDEM, useDEM);
|
||||||
SET_TRACK_OPTION(showSecondaryElevation, showSecondaryElevation);
|
SET_TRACK_OPTION(showSecondaryElevation, showSecondaryElevation);
|
||||||
SET_TRACK_OPTION(showSecondarySpeed, showSecondarySpeed);
|
SET_TRACK_OPTION(showSecondarySpeed, showSecondarySpeed);
|
||||||
|
SET_TRACK_OPTION(useSegments, useSegments);
|
||||||
|
|
||||||
SET_ROUTE_OPTION(dataUseDEM, useDEM);
|
SET_ROUTE_OPTION(dataUseDEM, useDEM);
|
||||||
SET_ROUTE_OPTION(showSecondaryElevation, showSecondaryElevation);
|
SET_ROUTE_OPTION(showSecondaryElevation, showSecondaryElevation);
|
||||||
@ -1018,9 +1027,9 @@ void GUI::printFile()
|
|||||||
plot(&printer);
|
plot(&printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI::exportFile()
|
void GUI::exportPDFFile()
|
||||||
{
|
{
|
||||||
ExportDialog dialog(&_export, this);
|
PDFExportDialog dialog(_pdfExport, _units, this);
|
||||||
if (dialog.exec() != QDialog::Accepted)
|
if (dialog.exec() != QDialog::Accepted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1028,16 +1037,53 @@ void GUI::exportFile()
|
|||||||
printer.setOutputFormat(QPrinter::PdfFormat);
|
printer.setOutputFormat(QPrinter::PdfFormat);
|
||||||
printer.setCreator(QString(APP_NAME) + QString(" ")
|
printer.setCreator(QString(APP_NAME) + QString(" ")
|
||||||
+ QString(APP_VERSION));
|
+ QString(APP_VERSION));
|
||||||
printer.setResolution(_export.resolution);
|
printer.setResolution(_pdfExport.resolution);
|
||||||
printer.setOrientation(_export.orientation);
|
printer.setOrientation(_pdfExport.orientation);
|
||||||
printer.setOutputFileName(_export.fileName);
|
printer.setOutputFileName(_pdfExport.fileName);
|
||||||
printer.setPaperSize(_export.paperSize);
|
printer.setPaperSize(_pdfExport.paperSize);
|
||||||
printer.setPageMargins(_export.margins.left(), _export.margins.top(),
|
printer.setPageMargins(_pdfExport.margins.left(), _pdfExport.margins.top(),
|
||||||
_export.margins.right(), _export.margins.bottom(), QPrinter::Millimeter);
|
_pdfExport.margins.right(), _pdfExport.margins.bottom(),
|
||||||
|
QPrinter::Millimeter);
|
||||||
|
|
||||||
plot(&printer);
|
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()
|
void GUI::statistics()
|
||||||
{
|
{
|
||||||
QLocale l(QLocale::system());
|
QLocale l(QLocale::system());
|
||||||
@ -1109,12 +1155,13 @@ void GUI::statistics()
|
|||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI::plot(QPrinter *printer)
|
void GUI::plotMainPage(QPainter *painter, const QRectF &rect, qreal ratio,
|
||||||
|
bool expand)
|
||||||
{
|
{
|
||||||
QLocale l(QLocale::system());
|
QLocale l(QLocale::system());
|
||||||
QPainter p(printer);
|
|
||||||
TrackInfo info;
|
TrackInfo info;
|
||||||
qreal ih, gh, mh, ratio;
|
qreal ih, gh, mh;
|
||||||
|
int sc;
|
||||||
|
|
||||||
|
|
||||||
if (!_pathName.isNull() && _options.printName)
|
if (!_pathName.isNull() && _options.printName)
|
||||||
@ -1150,53 +1197,91 @@ void GUI::plot(QPrinter *printer)
|
|||||||
if (movingTime() > 0 && _options.printMovingTime)
|
if (movingTime() > 0 && _options.printMovingTime)
|
||||||
info.insert(tr("Moving time"), Format::timeSpan(movingTime()));
|
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()) {
|
if (info.isEmpty()) {
|
||||||
ih = 0;
|
ih = 0;
|
||||||
mh = 0;
|
mh = 0;
|
||||||
} else {
|
} else {
|
||||||
ih = info.contentSize().height() * ratio;
|
ih = info.contentSize().height() * ratio;
|
||||||
mh = ih / 2;
|
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) {
|
if (_graphTabWidget->isVisible() && !_options.separateGraphPage) {
|
||||||
qreal r = (((qreal)(printer)->width()) / (qreal)(printer->height()));
|
qreal r = rect.width() / rect.height();
|
||||||
gh = (printer->width() > printer->height())
|
gh = (rect.width() > rect.height())
|
||||||
? 0.15 * r * (printer->height() - ih - 2*mh)
|
? 0.15 * r * (rect.height() - ih - 2*mh)
|
||||||
: 0.15 * (printer->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());
|
GraphTab *gt = static_cast<GraphTab*>(_graphTabWidget->currentWidget());
|
||||||
gt->plot(&p, QRectF(0, printer->height() - gh, printer->width(), gh),
|
gt->plot(painter, QRectF(rect.x(), rect.y() + rect.height() - gh,
|
||||||
ratio);
|
rect.width(), gh), ratio);
|
||||||
} else
|
} else {
|
||||||
gh = 0;
|
gh = 0;
|
||||||
_mapView->plot(&p, QRectF(0, ih + mh, printer->width(), printer->height()
|
sc = 1;
|
||||||
- (ih + 2*mh + gh)), ratio, _options.hiresPrint);
|
}
|
||||||
|
|
||||||
if (_graphTabWidget->isVisible() && _options.separateGraphPage) {
|
MapView::PlotFlags flags = MapView::NoFlags;
|
||||||
printer->newPage();
|
if (_options.hiresPrint)
|
||||||
|
flags |= MapView::HiRes;
|
||||||
|
if (expand)
|
||||||
|
flags |= MapView::Expand;
|
||||||
|
|
||||||
int cnt = 0;
|
_mapView->plot(painter, QRectF(rect.x(), rect.y() + ih + mh, rect.width(),
|
||||||
for (int i = 0; i < _tabs.size(); i++)
|
rect.height() - (ih + sc*mh + gh)), ratio, flags);
|
||||||
if (!_tabs.at(i)->isEmpty())
|
}
|
||||||
cnt++;
|
|
||||||
|
|
||||||
qreal sp = ratio * 20;
|
void GUI::plotGraphsPage(QPainter *painter, const QRectF &rect, qreal ratio)
|
||||||
gh = qMin((printer->height() - ((cnt - 1) * sp))/(qreal)cnt,
|
{
|
||||||
0.20 * printer->height());
|
int cnt = 0;
|
||||||
|
for (int i = 0; i < _tabs.size(); i++)
|
||||||
|
if (!_tabs.at(i)->isEmpty())
|
||||||
|
cnt++;
|
||||||
|
|
||||||
qreal y = 0;
|
qreal sp = ratio * 20;
|
||||||
for (int i = 0; i < _tabs.size(); i++) {
|
qreal gh = qMin((rect.height() - ((cnt - 1) * sp))/(qreal)cnt,
|
||||||
if (!_tabs.at(i)->isEmpty()) {
|
0.20 * rect.height());
|
||||||
_tabs.at(i)->plot(&p, QRectF(0, y, printer->width(), gh),
|
|
||||||
ratio);
|
qreal y = 0;
|
||||||
y += gh + sp;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
void GUI::reloadFiles()
|
||||||
{
|
{
|
||||||
_trackCount = 0;
|
_trackCount = 0;
|
||||||
@ -1551,8 +1636,7 @@ void GUI::setTimeType(TimeType type)
|
|||||||
|
|
||||||
void GUI::setUnits(Units units)
|
void GUI::setUnits(Units units)
|
||||||
{
|
{
|
||||||
_export.units = units;
|
_units = units;
|
||||||
_options.units = units;
|
|
||||||
|
|
||||||
_mapView->setUnits(units);
|
_mapView->setUnits(units);
|
||||||
for (int i = 0; i <_tabs.count(); i++)
|
for (int i = 0; i <_tabs.count(); i++)
|
||||||
@ -1795,23 +1879,42 @@ void GUI::writeSettings()
|
|||||||
_showTicksAction->isChecked());
|
_showTicksAction->isChecked());
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
settings.beginGroup(EXPORT_SETTINGS_GROUP);
|
settings.beginGroup(PDF_EXPORT_SETTINGS_GROUP);
|
||||||
if (_export.orientation != PAPER_ORIENTATION_DEFAULT)
|
if (_pdfExport.orientation != PAPER_ORIENTATION_DEFAULT)
|
||||||
settings.setValue(PAPER_ORIENTATION_SETTING, _export.orientation);
|
settings.setValue(PAPER_ORIENTATION_SETTING, _pdfExport.orientation);
|
||||||
if (_export.resolution != RESOLUTION_DEFAULT)
|
if (_pdfExport.resolution != RESOLUTION_DEFAULT)
|
||||||
settings.setValue(RESOLUTION_SETTING, _export.resolution);
|
settings.setValue(RESOLUTION_SETTING, _pdfExport.resolution);
|
||||||
if (_export.paperSize != PAPER_SIZE_DEFAULT)
|
if (_pdfExport.paperSize != PAPER_SIZE_DEFAULT)
|
||||||
settings.setValue(PAPER_SIZE_SETTING, _export.paperSize);
|
settings.setValue(PAPER_SIZE_SETTING, _pdfExport.paperSize);
|
||||||
if (_export.margins.left() != MARGIN_LEFT_DEFAULT)
|
if (_pdfExport.margins.left() != PDF_MARGIN_LEFT_DEFAULT)
|
||||||
settings.setValue(MARGIN_LEFT_SETTING, _export.margins.left());
|
settings.setValue(PDF_MARGIN_LEFT_SETTING, _pdfExport.margins.left());
|
||||||
if (_export.margins.top() != MARGIN_TOP_DEFAULT)
|
if (_pdfExport.margins.top() != PDF_MARGIN_TOP_DEFAULT)
|
||||||
settings.setValue(MARGIN_TOP_SETTING, _export.margins.top());
|
settings.setValue(PDF_MARGIN_TOP_SETTING, _pdfExport.margins.top());
|
||||||
if (_export.margins.right() != MARGIN_RIGHT_DEFAULT)
|
if (_pdfExport.margins.right() != PDF_MARGIN_RIGHT_DEFAULT)
|
||||||
settings.setValue(MARGIN_RIGHT_SETTING, _export.margins.right());
|
settings.setValue(PDF_MARGIN_RIGHT_SETTING, _pdfExport.margins.right());
|
||||||
if (_export.margins.bottom() != MARGIN_BOTTOM_DEFAULT)
|
if (_pdfExport.margins.bottom() != PDF_MARGIN_BOTTOM_DEFAULT)
|
||||||
settings.setValue(MARGIN_BOTTOM_SETTING, _export.margins.bottom());
|
settings.setValue(PDF_MARGIN_BOTTOM_SETTING, _pdfExport.margins.bottom());
|
||||||
if (_export.fileName != EXPORT_FILENAME_DEFAULT)
|
if (_pdfExport.fileName != PDF_FILENAME_DEFAULT)
|
||||||
settings.setValue(EXPORT_FILENAME_SETTING, _export.fileName);
|
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.endGroup();
|
||||||
|
|
||||||
settings.beginGroup(OPTIONS_SETTINGS_GROUP);
|
settings.beginGroup(OPTIONS_SETTINGS_GROUP);
|
||||||
@ -1884,6 +1987,8 @@ void GUI::writeSettings()
|
|||||||
settings.setValue(TIME_ZONE_SETTING, QVariant::fromValue(
|
settings.setValue(TIME_ZONE_SETTING, QVariant::fromValue(
|
||||||
_options.timeZone));
|
_options.timeZone));
|
||||||
#endif // ENABLE_TIMEZONES
|
#endif // ENABLE_TIMEZONES
|
||||||
|
if (_options.useSegments != USE_SEGMENTS_DEFAULT)
|
||||||
|
settings.setValue(USE_SEGMENTS_SETTING, _options.useSegments);
|
||||||
if (_options.poiRadius != POI_RADIUS_DEFAULT)
|
if (_options.poiRadius != POI_RADIUS_DEFAULT)
|
||||||
settings.setValue(POI_RADIUS_SETTING, _options.poiRadius);
|
settings.setValue(POI_RADIUS_SETTING, _options.poiRadius);
|
||||||
if (_options.useOpenGL != USE_OPENGL_DEFAULT)
|
if (_options.useOpenGL != USE_OPENGL_DEFAULT)
|
||||||
@ -2075,23 +2180,42 @@ void GUI::readSettings()
|
|||||||
}
|
}
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
settings.beginGroup(EXPORT_SETTINGS_GROUP);
|
settings.beginGroup(PDF_EXPORT_SETTINGS_GROUP);
|
||||||
_export.orientation = (QPrinter::Orientation) settings.value(
|
_pdfExport.orientation = (QPrinter::Orientation) settings.value(
|
||||||
PAPER_ORIENTATION_SETTING, PAPER_ORIENTATION_DEFAULT).toInt();
|
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();
|
.toInt();
|
||||||
_export.paperSize = (QPrinter::PaperSize) settings.value(PAPER_SIZE_SETTING,
|
int mti = settings.value(PNG_MARGIN_TOP_SETTING, PNG_MARGIN_TOP_DEFAULT)
|
||||||
PAPER_SIZE_DEFAULT).toInt();
|
.toInt();
|
||||||
qreal ml = settings.value(MARGIN_LEFT_SETTING, MARGIN_LEFT_DEFAULT)
|
int mri = settings.value(PNG_MARGIN_RIGHT_SETTING, PNG_MARGIN_RIGHT_DEFAULT)
|
||||||
.toReal();
|
.toInt();
|
||||||
qreal mt = settings.value(MARGIN_TOP_SETTING, MARGIN_TOP_DEFAULT).toReal();
|
int mbi = settings.value(PNG_MARGIN_BOTTOM_SETTING, PNG_MARGIN_BOTTOM_DEFAULT)
|
||||||
qreal mr = settings.value(MARGIN_RIGHT_SETTING, MARGIN_RIGHT_DEFAULT)
|
.toInt();
|
||||||
.toReal();
|
_pngExport.margins = QMargins(mli, mti, mri, mbi);
|
||||||
qreal mb = settings.value(MARGIN_BOTTOM_SETTING, MARGIN_BOTTOM_DEFAULT)
|
_pngExport.antialiasing = settings.value(PNG_ANTIALIASING_SETTING,
|
||||||
.toReal();
|
PNG_ANTIALIASING_DEFAULT).toBool();
|
||||||
_export.margins = MarginsF(ml, mt, mr, mb);
|
_pngExport.fileName = settings.value(PNG_FILENAME_SETTING,
|
||||||
_export.fileName = settings.value(EXPORT_FILENAME_SETTING,
|
PNG_FILENAME_DEFAULT).toString();
|
||||||
EXPORT_FILENAME_DEFAULT).toString();
|
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
settings.beginGroup(OPTIONS_SETTINGS_GROUP);
|
settings.beginGroup(OPTIONS_SETTINGS_GROUP);
|
||||||
@ -2159,6 +2283,8 @@ void GUI::readSettings()
|
|||||||
#ifdef ENABLE_TIMEZONES
|
#ifdef ENABLE_TIMEZONES
|
||||||
_options.timeZone = settings.value(TIME_ZONE_SETTING).value<TimeZoneInfo>();
|
_options.timeZone = settings.value(TIME_ZONE_SETTING).value<TimeZoneInfo>();
|
||||||
#endif // ENABLE_TIMEZONES
|
#endif // ENABLE_TIMEZONES
|
||||||
|
_options.useSegments = settings.value(USE_SEGMENTS_SETTING,
|
||||||
|
USE_SEGMENTS_DEFAULT).toBool();
|
||||||
_options.automaticPause = settings.value(AUTOMATIC_PAUSE_SETTING,
|
_options.automaticPause = settings.value(AUTOMATIC_PAUSE_SETTING,
|
||||||
AUTOMATIC_PAUSE_DEFAULT).toBool();
|
AUTOMATIC_PAUSE_DEFAULT).toBool();
|
||||||
_options.pauseInterval = settings.value(PAUSE_INTERVAL_SETTING,
|
_options.pauseInterval = settings.value(PAUSE_INTERVAL_SETTING,
|
||||||
@ -2250,6 +2376,7 @@ void GUI::readSettings()
|
|||||||
Track::useDEM(_options.dataUseDEM);
|
Track::useDEM(_options.dataUseDEM);
|
||||||
Track::showSecondaryElevation(_options.showSecondaryElevation);
|
Track::showSecondaryElevation(_options.showSecondaryElevation);
|
||||||
Track::showSecondarySpeed(_options.showSecondarySpeed);
|
Track::showSecondarySpeed(_options.showSecondarySpeed);
|
||||||
|
Track::useSegments(_options.useSegments);
|
||||||
Route::useDEM(_options.dataUseDEM);
|
Route::useDEM(_options.dataUseDEM);
|
||||||
Route::showSecondaryElevation(_options.showSecondaryElevation);
|
Route::showSecondaryElevation(_options.showSecondaryElevation);
|
||||||
Waypoint::useDEM(_options.dataUseDEM);
|
Waypoint::useDEM(_options.dataUseDEM);
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
#include "units.h"
|
#include "units.h"
|
||||||
#include "timetype.h"
|
#include "timetype.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
#include "exportdialog.h"
|
#include "pdfexportdialog.h"
|
||||||
|
#include "pngexportdialog.h"
|
||||||
#include "optionsdialog.h"
|
#include "optionsdialog.h"
|
||||||
|
|
||||||
class QMenu;
|
class QMenu;
|
||||||
@ -45,7 +46,8 @@ private slots:
|
|||||||
void keys();
|
void keys();
|
||||||
void paths();
|
void paths();
|
||||||
void printFile();
|
void printFile();
|
||||||
void exportFile();
|
void exportPDFFile();
|
||||||
|
void exportPNGFile();
|
||||||
void openFile();
|
void openFile();
|
||||||
void closeAll();
|
void closeAll();
|
||||||
void reloadFiles();
|
void reloadFiles();
|
||||||
@ -97,6 +99,10 @@ private:
|
|||||||
void loadPOIs();
|
void loadPOIs();
|
||||||
void closeFiles();
|
void closeFiles();
|
||||||
void plot(QPrinter *printer);
|
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);
|
QAction *createPOIFileAction(const QString &fileName);
|
||||||
MapAction *createMapAction(Map *map);
|
MapAction *createMapAction(Map *map);
|
||||||
@ -113,7 +119,6 @@ private:
|
|||||||
bool openPOIFile(const QString &fileName);
|
bool openPOIFile(const QString &fileName);
|
||||||
bool loadFile(const QString &fileName);
|
bool loadFile(const QString &fileName);
|
||||||
bool loadMap(const QString &fileName);
|
bool loadMap(const QString &fileName);
|
||||||
void exportFile(const QString &fileName);
|
|
||||||
void updateStatusBarInfo();
|
void updateStatusBarInfo();
|
||||||
void updateWindowTitle();
|
void updateWindowTitle();
|
||||||
void updateNavigationActions();
|
void updateNavigationActions();
|
||||||
@ -153,7 +158,8 @@ private:
|
|||||||
QAction *_aboutAction;
|
QAction *_aboutAction;
|
||||||
QAction *_aboutQtAction;
|
QAction *_aboutQtAction;
|
||||||
QAction *_printFileAction;
|
QAction *_printFileAction;
|
||||||
QAction *_exportFileAction;
|
QAction *_exportPDFFileAction;
|
||||||
|
QAction *_exportPNGFileAction;
|
||||||
QAction *_openFileAction;
|
QAction *_openFileAction;
|
||||||
QAction *_closeFileAction;
|
QAction *_closeFileAction;
|
||||||
QAction *_reloadFileAction;
|
QAction *_reloadFileAction;
|
||||||
@ -228,10 +234,13 @@ private:
|
|||||||
QList<QByteArray> _windowStates;
|
QList<QByteArray> _windowStates;
|
||||||
int _frameStyle;
|
int _frameStyle;
|
||||||
|
|
||||||
Export _export;
|
PDFExport _pdfExport;
|
||||||
|
PNGExport _pngExport;
|
||||||
Options _options;
|
Options _options;
|
||||||
|
|
||||||
QString _dataDir, _mapDir, _poiDir;
|
QString _dataDir, _mapDir, _poiDir;
|
||||||
|
|
||||||
|
Units _units;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GUI_H
|
#endif // GUI_H
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
#define OPEN_SHORTCUT QKeySequence(QKeySequence::Open)
|
#define OPEN_SHORTCUT QKeySequence(QKeySequence::Open)
|
||||||
#define CLOSE_SHORTCUT QKeySequence(QKeySequence::Close)
|
#define CLOSE_SHORTCUT QKeySequence(QKeySequence::Close)
|
||||||
#define RELOAD_SHORTCUT QKeySequence(QKeySequence::Refresh)
|
#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_POI_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_P)
|
||||||
#define SHOW_MAP_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_M)
|
#define SHOW_MAP_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_M)
|
||||||
#define NEXT_MAP_SHORTCUT QKeySequence(QKeySequence::Forward)
|
#define NEXT_MAP_SHORTCUT QKeySequence(QKeySequence::Forward)
|
||||||
|
@ -531,7 +531,7 @@ void MapView::keyPressEvent(QKeyEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||||
bool hires)
|
PlotFlags flags)
|
||||||
{
|
{
|
||||||
QRect orig, adj;
|
QRect orig, adj;
|
||||||
qreal ratio, diff, q;
|
qreal ratio, diff, q;
|
||||||
@ -559,10 +559,18 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
|||||||
diff = (orig.height() * ratio) - orig.width();
|
diff = (orig.height() * ratio) - orig.width();
|
||||||
adj = orig.adjusted(-diff/2, 0, diff/2, 0);
|
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
|
// Adjust the view for printing
|
||||||
if (hires) {
|
if (flags & HiRes) {
|
||||||
zoom = _map->zoom();
|
zoom = _map->zoom();
|
||||||
QRectF vr(mapToScene(orig).boundingRect());
|
QRectF vr(mapToScene(orig).boundingRect());
|
||||||
origScene = vr.center();
|
origScene = vr.center();
|
||||||
@ -594,7 +602,7 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
|||||||
render(painter, target, adj);
|
render(painter, target, adj);
|
||||||
|
|
||||||
// Revert view changes to display mode
|
// Revert view changes to display mode
|
||||||
if (hires) {
|
if (flags & HiRes) {
|
||||||
_map->setZoom(zoom);
|
_map->setZoom(zoom);
|
||||||
rescale();
|
rescale();
|
||||||
centerOn(origScene);
|
centerOn(origScene);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QFlags>
|
||||||
#include "common/rectc.h"
|
#include "common/rectc.h"
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
#include "data/waypoint.h"
|
#include "data/waypoint.h"
|
||||||
@ -38,6 +39,13 @@ class MapView : public QGraphicsView
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum Flag {
|
||||||
|
NoFlags = 0,
|
||||||
|
HiRes = 1,
|
||||||
|
Expand = 2
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(PlotFlags, Flag)
|
||||||
|
|
||||||
MapView(Map *map, POI *poi, QWidget *parent = 0);
|
MapView(Map *map, POI *poi, QWidget *parent = 0);
|
||||||
|
|
||||||
QList<PathItem *> loadData(const Data &data);
|
QList<PathItem *> loadData(const Data &data);
|
||||||
@ -46,7 +54,8 @@ public:
|
|||||||
void setPOI(POI *poi);
|
void setPOI(POI *poi);
|
||||||
void setMap(Map *map);
|
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();
|
void clear();
|
||||||
|
|
||||||
|
@ -16,15 +16,22 @@ public:
|
|||||||
qreal right() const {return _right;}
|
qreal right() const {return _right;}
|
||||||
qreal bottom() const {return _bottom;}
|
qreal bottom() const {return _bottom;}
|
||||||
|
|
||||||
qreal &rleft() {return _left;}
|
|
||||||
qreal &rtop() {return _top;}
|
|
||||||
qreal &rright() {return _right;}
|
|
||||||
qreal &rbottom() {return _bottom;}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
qreal _left, _top, _right, _bottom;
|
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
|
#ifndef QT_NO_DEBUG
|
||||||
inline QDebug operator<<(QDebug dbg, const MarginsF &margins)
|
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();
|
+ projections.at(i).value();
|
||||||
_projection->addItem(text, QVariant(projections.at(i).key()));
|
_projection->addItem(text, QVariant(projections.at(i).key()));
|
||||||
}
|
}
|
||||||
_projection->setCurrentIndex(_projection->findData(_options->projection));
|
_projection->setCurrentIndex(_projection->findData(_options.projection));
|
||||||
|
|
||||||
#ifdef ENABLE_HIDPI
|
#ifdef ENABLE_HIDPI
|
||||||
_hidpi = new QRadioButton(tr("High-resolution"));
|
_hidpi = new QRadioButton(tr("High-resolution"));
|
||||||
_lodpi = new QRadioButton(tr("Standard"));
|
_lodpi = new QRadioButton(tr("Standard"));
|
||||||
if (_options->hidpiMap)
|
if (_options.hidpiMap)
|
||||||
_hidpi->setChecked(true);
|
_hidpi->setChecked(true);
|
||||||
else
|
else
|
||||||
_lodpi->setChecked(true);
|
_lodpi->setChecked(true);
|
||||||
@ -112,10 +112,10 @@ QWidget *OptionsDialog::createAppearancePage()
|
|||||||
{
|
{
|
||||||
// Tracks
|
// Tracks
|
||||||
_trackWidth = new QSpinBox();
|
_trackWidth = new QSpinBox();
|
||||||
_trackWidth->setValue(_options->trackWidth);
|
_trackWidth->setValue(_options.trackWidth);
|
||||||
_trackWidth->setMinimum(1);
|
_trackWidth->setMinimum(1);
|
||||||
_trackStyle = new StyleComboBox();
|
_trackStyle = new StyleComboBox();
|
||||||
_trackStyle->setValue(_options->trackStyle);
|
_trackStyle->setValue(_options.trackStyle);
|
||||||
QFormLayout *trackLayout = new QFormLayout();
|
QFormLayout *trackLayout = new QFormLayout();
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
trackLayout->addRow(tr("Track width:"), _trackWidth);
|
trackLayout->addRow(tr("Track width:"), _trackWidth);
|
||||||
@ -129,10 +129,10 @@ QWidget *OptionsDialog::createAppearancePage()
|
|||||||
|
|
||||||
// Routes
|
// Routes
|
||||||
_routeWidth = new QSpinBox();
|
_routeWidth = new QSpinBox();
|
||||||
_routeWidth->setValue(_options->routeWidth);
|
_routeWidth->setValue(_options.routeWidth);
|
||||||
_routeWidth->setMinimum(1);
|
_routeWidth->setMinimum(1);
|
||||||
_routeStyle = new StyleComboBox();
|
_routeStyle = new StyleComboBox();
|
||||||
_routeStyle->setValue(_options->routeStyle);
|
_routeStyle->setValue(_options.routeStyle);
|
||||||
QFormLayout *routeLayout = new QFormLayout();
|
QFormLayout *routeLayout = new QFormLayout();
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
routeLayout->addRow(tr("Route width:"), _routeWidth);
|
routeLayout->addRow(tr("Route width:"), _routeWidth);
|
||||||
@ -146,11 +146,11 @@ QWidget *OptionsDialog::createAppearancePage()
|
|||||||
|
|
||||||
// Areas
|
// Areas
|
||||||
_areaWidth = new QSpinBox();
|
_areaWidth = new QSpinBox();
|
||||||
_areaWidth->setValue(_options->areaWidth);
|
_areaWidth->setValue(_options.areaWidth);
|
||||||
_areaStyle = new StyleComboBox();
|
_areaStyle = new StyleComboBox();
|
||||||
_areaStyle->setValue(_options->areaStyle);
|
_areaStyle->setValue(_options.areaStyle);
|
||||||
_areaOpacity = new PercentSlider();
|
_areaOpacity = new PercentSlider();
|
||||||
_areaOpacity->setValue(_options->areaOpacity);
|
_areaOpacity->setValue(_options.areaOpacity);
|
||||||
QFormLayout *areaLayout = new QFormLayout();
|
QFormLayout *areaLayout = new QFormLayout();
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
areaLayout->addRow(tr("Area border width:"), _areaWidth);
|
areaLayout->addRow(tr("Area border width:"), _areaWidth);
|
||||||
@ -166,15 +166,15 @@ QWidget *OptionsDialog::createAppearancePage()
|
|||||||
|
|
||||||
// Palette & antialiasing
|
// Palette & antialiasing
|
||||||
_baseColor = new ColorBox();
|
_baseColor = new ColorBox();
|
||||||
_baseColor->setColor(_options->palette.color());
|
_baseColor->setColor(_options.palette.color());
|
||||||
_colorOffset = new PercentSlider();
|
_colorOffset = new PercentSlider();
|
||||||
_colorOffset->setValue(_options->palette.shift() * 100);
|
_colorOffset->setValue(_options.palette.shift() * 100);
|
||||||
QFormLayout *paletteLayout = new QFormLayout();
|
QFormLayout *paletteLayout = new QFormLayout();
|
||||||
paletteLayout->addRow(tr("Base color:"), _baseColor);
|
paletteLayout->addRow(tr("Base color:"), _baseColor);
|
||||||
paletteLayout->addRow(tr("Palette shift:"), _colorOffset);
|
paletteLayout->addRow(tr("Palette shift:"), _colorOffset);
|
||||||
|
|
||||||
_pathAA = new QCheckBox(tr("Use anti-aliasing"));
|
_pathAA = new QCheckBox(tr("Use anti-aliasing"));
|
||||||
_pathAA->setChecked(_options->pathAntiAliasing);
|
_pathAA->setChecked(_options.pathAntiAliasing);
|
||||||
QFormLayout *pathAALayout = new QFormLayout();
|
QFormLayout *pathAALayout = new QFormLayout();
|
||||||
pathAALayout->addWidget(_pathAA);
|
pathAALayout->addWidget(_pathAA);
|
||||||
|
|
||||||
@ -201,9 +201,9 @@ QWidget *OptionsDialog::createAppearancePage()
|
|||||||
// Waypoints
|
// Waypoints
|
||||||
_waypointSize = new QSpinBox();
|
_waypointSize = new QSpinBox();
|
||||||
_waypointSize->setMinimum(1);
|
_waypointSize->setMinimum(1);
|
||||||
_waypointSize->setValue(_options->waypointSize);
|
_waypointSize->setValue(_options.waypointSize);
|
||||||
_waypointColor = new ColorBox();
|
_waypointColor = new ColorBox();
|
||||||
_waypointColor->setColor(_options->waypointColor);
|
_waypointColor->setColor(_options.waypointColor);
|
||||||
QFormLayout *waypointLayout = new QFormLayout();
|
QFormLayout *waypointLayout = new QFormLayout();
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
waypointLayout->addRow(tr("Waypoint color:"), _waypointColor);
|
waypointLayout->addRow(tr("Waypoint color:"), _waypointColor);
|
||||||
@ -217,9 +217,9 @@ QWidget *OptionsDialog::createAppearancePage()
|
|||||||
|
|
||||||
_poiSize = new QSpinBox();
|
_poiSize = new QSpinBox();
|
||||||
_poiSize->setMinimum(1);
|
_poiSize->setMinimum(1);
|
||||||
_poiSize->setValue(_options->poiSize);
|
_poiSize->setValue(_options.poiSize);
|
||||||
_poiColor = new ColorBox();
|
_poiColor = new ColorBox();
|
||||||
_poiColor->setColor(_options->poiColor);
|
_poiColor->setColor(_options.poiColor);
|
||||||
QFormLayout *poiLayout = new QFormLayout();
|
QFormLayout *poiLayout = new QFormLayout();
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
poiLayout->addRow(tr("POI color:"), _poiColor);
|
poiLayout->addRow(tr("POI color:"), _poiColor);
|
||||||
@ -247,9 +247,9 @@ QWidget *OptionsDialog::createAppearancePage()
|
|||||||
|
|
||||||
// Graphs
|
// Graphs
|
||||||
_sliderColor = new ColorBox();
|
_sliderColor = new ColorBox();
|
||||||
_sliderColor->setColor(_options->sliderColor);
|
_sliderColor->setColor(_options.sliderColor);
|
||||||
_graphWidth = new QSpinBox();
|
_graphWidth = new QSpinBox();
|
||||||
_graphWidth->setValue(_options->graphWidth);
|
_graphWidth->setValue(_options.graphWidth);
|
||||||
_graphWidth->setMinimum(1);
|
_graphWidth->setMinimum(1);
|
||||||
|
|
||||||
QFormLayout *graphLayout = new QFormLayout();
|
QFormLayout *graphLayout = new QFormLayout();
|
||||||
@ -257,7 +257,7 @@ QWidget *OptionsDialog::createAppearancePage()
|
|||||||
graphLayout->addRow(tr("Slider color:"), _sliderColor);
|
graphLayout->addRow(tr("Slider color:"), _sliderColor);
|
||||||
|
|
||||||
_graphAA = new QCheckBox(tr("Use anti-aliasing"));
|
_graphAA = new QCheckBox(tr("Use anti-aliasing"));
|
||||||
_graphAA->setChecked(_options->graphAntiAliasing);
|
_graphAA->setChecked(_options.graphAntiAliasing);
|
||||||
QFormLayout *graphAALayout = new QFormLayout();
|
QFormLayout *graphAALayout = new QFormLayout();
|
||||||
graphAALayout->addWidget(_graphAA);
|
graphAALayout->addWidget(_graphAA);
|
||||||
|
|
||||||
@ -271,9 +271,9 @@ QWidget *OptionsDialog::createAppearancePage()
|
|||||||
|
|
||||||
// Map
|
// Map
|
||||||
_mapOpacity = new PercentSlider();
|
_mapOpacity = new PercentSlider();
|
||||||
_mapOpacity->setValue(_options->mapOpacity);
|
_mapOpacity->setValue(_options.mapOpacity);
|
||||||
_backgroundColor = new ColorBox();
|
_backgroundColor = new ColorBox();
|
||||||
_backgroundColor->setColor(_options->backgroundColor);
|
_backgroundColor->setColor(_options.backgroundColor);
|
||||||
_backgroundColor->enableAlphaChannel(false);
|
_backgroundColor->enableAlphaChannel(false);
|
||||||
|
|
||||||
QFormLayout *mapLayout = new QFormLayout();
|
QFormLayout *mapLayout = new QFormLayout();
|
||||||
@ -301,19 +301,19 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
QString filterToolTip = tr("Moving average window size");
|
QString filterToolTip = tr("Moving average window size");
|
||||||
|
|
||||||
_elevationFilter = new OddSpinBox();
|
_elevationFilter = new OddSpinBox();
|
||||||
_elevationFilter->setValue(_options->elevationFilter);
|
_elevationFilter->setValue(_options.elevationFilter);
|
||||||
_elevationFilter->setToolTip(filterToolTip);
|
_elevationFilter->setToolTip(filterToolTip);
|
||||||
_speedFilter = new OddSpinBox();
|
_speedFilter = new OddSpinBox();
|
||||||
_speedFilter->setValue(_options->speedFilter);
|
_speedFilter->setValue(_options.speedFilter);
|
||||||
_speedFilter->setToolTip(filterToolTip);
|
_speedFilter->setToolTip(filterToolTip);
|
||||||
_heartRateFilter = new OddSpinBox();
|
_heartRateFilter = new OddSpinBox();
|
||||||
_heartRateFilter->setValue(_options->heartRateFilter);
|
_heartRateFilter->setValue(_options.heartRateFilter);
|
||||||
_heartRateFilter->setToolTip(filterToolTip);
|
_heartRateFilter->setToolTip(filterToolTip);
|
||||||
_cadenceFilter = new OddSpinBox();
|
_cadenceFilter = new OddSpinBox();
|
||||||
_cadenceFilter->setValue(_options->cadenceFilter);
|
_cadenceFilter->setValue(_options.cadenceFilter);
|
||||||
_cadenceFilter->setToolTip(filterToolTip);
|
_cadenceFilter->setToolTip(filterToolTip);
|
||||||
_powerFilter = new OddSpinBox();
|
_powerFilter = new OddSpinBox();
|
||||||
_powerFilter->setValue(_options->powerFilter);
|
_powerFilter->setValue(_options.powerFilter);
|
||||||
_powerFilter->setToolTip(filterToolTip);
|
_powerFilter->setToolTip(filterToolTip);
|
||||||
|
|
||||||
QFormLayout *smoothLayout = new QFormLayout();
|
QFormLayout *smoothLayout = new QFormLayout();
|
||||||
@ -328,7 +328,7 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
#endif // Q_OS_MAC
|
#endif // Q_OS_MAC
|
||||||
|
|
||||||
_outlierEliminate = new QCheckBox(tr("Eliminate GPS outliers"));
|
_outlierEliminate = new QCheckBox(tr("Eliminate GPS outliers"));
|
||||||
_outlierEliminate->setChecked(_options->outlierEliminate);
|
_outlierEliminate->setChecked(_options.outlierEliminate);
|
||||||
|
|
||||||
QFormLayout *outlierLayout = new QFormLayout();
|
QFormLayout *outlierLayout = new QFormLayout();
|
||||||
outlierLayout->addWidget(_outlierEliminate);
|
outlierLayout->addWidget(_outlierEliminate);
|
||||||
@ -349,7 +349,7 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
|
|
||||||
_automaticPause = new QRadioButton(tr("Automatic"));
|
_automaticPause = new QRadioButton(tr("Automatic"));
|
||||||
_manualPause = new QRadioButton(tr("Custom"));
|
_manualPause = new QRadioButton(tr("Custom"));
|
||||||
if (_options->automaticPause)
|
if (_options.automaticPause)
|
||||||
_automaticPause->setChecked(true);
|
_automaticPause->setChecked(true);
|
||||||
else
|
else
|
||||||
_manualPause->setChecked(true);
|
_manualPause->setChecked(true);
|
||||||
@ -359,20 +359,20 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
_pauseSpeed->setSingleStep(0.1);
|
_pauseSpeed->setSingleStep(0.1);
|
||||||
_pauseSpeed->setMinimum(0.1);
|
_pauseSpeed->setMinimum(0.1);
|
||||||
_pauseSpeed->setEnabled(_manualPause->isChecked());
|
_pauseSpeed->setEnabled(_manualPause->isChecked());
|
||||||
if (_options->units == Imperial) {
|
if (_units == Imperial) {
|
||||||
_pauseSpeed->setValue(_options->pauseSpeed * MS2MIH);
|
_pauseSpeed->setValue(_options.pauseSpeed * MS2MIH);
|
||||||
_pauseSpeed->setSuffix(UNIT_SPACE + tr("mi/h"));
|
_pauseSpeed->setSuffix(UNIT_SPACE + tr("mi/h"));
|
||||||
} else if (_options->units == Nautical) {
|
} else if (_units == Nautical) {
|
||||||
_pauseSpeed->setValue(_options->pauseSpeed * MS2KN);
|
_pauseSpeed->setValue(_options.pauseSpeed * MS2KN);
|
||||||
_pauseSpeed->setSuffix(UNIT_SPACE + tr("kn"));
|
_pauseSpeed->setSuffix(UNIT_SPACE + tr("kn"));
|
||||||
} else {
|
} else {
|
||||||
_pauseSpeed->setValue(_options->pauseSpeed * MS2KMH);
|
_pauseSpeed->setValue(_options.pauseSpeed * MS2KMH);
|
||||||
_pauseSpeed->setSuffix(UNIT_SPACE + tr("km/h"));
|
_pauseSpeed->setSuffix(UNIT_SPACE + tr("km/h"));
|
||||||
}
|
}
|
||||||
_pauseInterval = new QSpinBox();
|
_pauseInterval = new QSpinBox();
|
||||||
_pauseInterval->setMinimum(1);
|
_pauseInterval->setMinimum(1);
|
||||||
_pauseInterval->setSuffix(UNIT_SPACE + tr("s"));
|
_pauseInterval->setSuffix(UNIT_SPACE + tr("s"));
|
||||||
_pauseInterval->setValue(_options->pauseInterval);
|
_pauseInterval->setValue(_options.pauseInterval);
|
||||||
_pauseInterval->setEnabled(_manualPause->isChecked());
|
_pauseInterval->setEnabled(_manualPause->isChecked());
|
||||||
|
|
||||||
connect(_automaticPause, SIGNAL(toggled(bool)), this,
|
connect(_automaticPause, SIGNAL(toggled(bool)), this,
|
||||||
@ -400,29 +400,29 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
|
|
||||||
_computedSpeed = new QRadioButton(tr("Computed from distance/time"));
|
_computedSpeed = new QRadioButton(tr("Computed from distance/time"));
|
||||||
_reportedSpeed = new QRadioButton(tr("Recorded by device"));
|
_reportedSpeed = new QRadioButton(tr("Recorded by device"));
|
||||||
if (_options->useReportedSpeed)
|
if (_options.useReportedSpeed)
|
||||||
_reportedSpeed->setChecked(true);
|
_reportedSpeed->setChecked(true);
|
||||||
else
|
else
|
||||||
_computedSpeed->setChecked(true);
|
_computedSpeed->setChecked(true);
|
||||||
_showSecondarySpeed = new QCheckBox(tr("Show secondary speed"));
|
_showSecondarySpeed = new QCheckBox(tr("Show secondary speed"));
|
||||||
_showSecondarySpeed->setChecked(_options->showSecondarySpeed);
|
_showSecondarySpeed->setChecked(_options.showSecondarySpeed);
|
||||||
|
|
||||||
_dataGPSElevation = new QRadioButton(tr("GPS data"));
|
_dataGPSElevation = new QRadioButton(tr("GPS data"));
|
||||||
_dataDEMElevation = new QRadioButton(tr("DEM data"));
|
_dataDEMElevation = new QRadioButton(tr("DEM data"));
|
||||||
if (_options->dataUseDEM)
|
if (_options.dataUseDEM)
|
||||||
_dataDEMElevation->setChecked(true);
|
_dataDEMElevation->setChecked(true);
|
||||||
else
|
else
|
||||||
_dataGPSElevation->setChecked(true);
|
_dataGPSElevation->setChecked(true);
|
||||||
_showSecondaryElevation = new QCheckBox(tr("Show secondary elevation"));
|
_showSecondaryElevation = new QCheckBox(tr("Show secondary elevation"));
|
||||||
_showSecondaryElevation->setChecked(_options->showSecondaryElevation);
|
_showSecondaryElevation->setChecked(_options.showSecondaryElevation);
|
||||||
|
|
||||||
#ifdef ENABLE_TIMEZONES
|
#ifdef ENABLE_TIMEZONES
|
||||||
_utcZone = new QRadioButton(tr("UTC"));
|
_utcZone = new QRadioButton(tr("UTC"));
|
||||||
_systemZone = new QRadioButton(tr("System"));
|
_systemZone = new QRadioButton(tr("System"));
|
||||||
_customZone = new QRadioButton(tr("Custom"));
|
_customZone = new QRadioButton(tr("Custom"));
|
||||||
if (_options->timeZone.type() == TimeZoneInfo::UTC)
|
if (_options.timeZone.type() == TimeZoneInfo::UTC)
|
||||||
_utcZone->setChecked(true);
|
_utcZone->setChecked(true);
|
||||||
else if (_options->timeZone.type() == TimeZoneInfo::System)
|
else if (_options.timeZone.type() == TimeZoneInfo::System)
|
||||||
_systemZone->setChecked(true);
|
_systemZone->setChecked(true);
|
||||||
else
|
else
|
||||||
_customZone->setChecked(true);
|
_customZone->setChecked(true);
|
||||||
@ -431,7 +431,7 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
QList<QByteArray> zones = QTimeZone::availableTimeZoneIds();
|
QList<QByteArray> zones = QTimeZone::availableTimeZoneIds();
|
||||||
for (int i = 0; i < zones.size(); i++)
|
for (int i = 0; i < zones.size(); i++)
|
||||||
_timeZone->addItem(zones.at(i));
|
_timeZone->addItem(zones.at(i));
|
||||||
_timeZone->setCurrentText(_options->timeZone.customZone().id());
|
_timeZone->setCurrentText(_options.timeZone.customZone().id());
|
||||||
connect(_customZone, SIGNAL(toggled(bool)), _timeZone,
|
connect(_customZone, SIGNAL(toggled(bool)), _timeZone,
|
||||||
SLOT(setEnabled(bool)));
|
SLOT(setEnabled(bool)));
|
||||||
QHBoxLayout *customZoneLayout = new QHBoxLayout();
|
QHBoxLayout *customZoneLayout = new QHBoxLayout();
|
||||||
@ -439,6 +439,9 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
customZoneLayout->addWidget(_timeZone);
|
customZoneLayout->addWidget(_timeZone);
|
||||||
#endif // ENABLE_TIMEZONES
|
#endif // ENABLE_TIMEZONES
|
||||||
|
|
||||||
|
_useSegments = new QCheckBox(tr("Use segments"));
|
||||||
|
_useSegments->setChecked(_options.useSegments);
|
||||||
|
|
||||||
QWidget *sourceTab = new QWidget();
|
QWidget *sourceTab = new QWidget();
|
||||||
QVBoxLayout *sourceTabLayout = new QVBoxLayout();
|
QVBoxLayout *sourceTabLayout = new QVBoxLayout();
|
||||||
|
|
||||||
@ -477,6 +480,7 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
#ifdef ENABLE_TIMEZONES
|
#ifdef ENABLE_TIMEZONES
|
||||||
formLayout->addRow(tr("Time zone:"), zoneOptions);
|
formLayout->addRow(tr("Time zone:"), zoneOptions);
|
||||||
#endif // ENABLE_TIMEZONES
|
#endif // ENABLE_TIMEZONES
|
||||||
|
formLayout->addRow(_useSegments);
|
||||||
|
|
||||||
sourceTabLayout->addLayout(formLayout);
|
sourceTabLayout->addLayout(formLayout);
|
||||||
#else // Q_OS_MAC
|
#else // Q_OS_MAC
|
||||||
@ -485,6 +489,7 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
#ifdef ENABLE_TIMEZONES
|
#ifdef ENABLE_TIMEZONES
|
||||||
QFormLayout *timeZoneLayout = new QFormLayout();
|
QFormLayout *timeZoneLayout = new QFormLayout();
|
||||||
#endif // ENABLE_TIMEZONES
|
#endif // ENABLE_TIMEZONES
|
||||||
|
QFormLayout *segmentsLayout = new QFormLayout();
|
||||||
|
|
||||||
speedLayout->addWidget(_computedSpeed);
|
speedLayout->addWidget(_computedSpeed);
|
||||||
speedLayout->addWidget(_reportedSpeed);
|
speedLayout->addWidget(_reportedSpeed);
|
||||||
@ -510,11 +515,14 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
timeZoneBox->setLayout(timeZoneLayout);
|
timeZoneBox->setLayout(timeZoneLayout);
|
||||||
#endif // ENABLE_TIMEZONES
|
#endif // ENABLE_TIMEZONES
|
||||||
|
|
||||||
|
segmentsLayout->addWidget(_useSegments);
|
||||||
|
|
||||||
sourceTabLayout->addWidget(speedBox);
|
sourceTabLayout->addWidget(speedBox);
|
||||||
sourceTabLayout->addWidget(elevationBox);
|
sourceTabLayout->addWidget(elevationBox);
|
||||||
#ifdef ENABLE_TIMEZONES
|
#ifdef ENABLE_TIMEZONES
|
||||||
sourceTabLayout->addWidget(timeZoneBox);
|
sourceTabLayout->addWidget(timeZoneBox);
|
||||||
#endif // ENABLE_TIMEZONES
|
#endif // ENABLE_TIMEZONES
|
||||||
|
sourceTabLayout->addLayout(segmentsLayout);
|
||||||
#endif // Q_OS_MAC
|
#endif // Q_OS_MAC
|
||||||
sourceTabLayout->addStretch();
|
sourceTabLayout->addStretch();
|
||||||
sourceTab->setLayout(sourceTabLayout);
|
sourceTab->setLayout(sourceTabLayout);
|
||||||
@ -533,14 +541,14 @@ QWidget *OptionsDialog::createPOIPage()
|
|||||||
_poiRadius = new QDoubleSpinBox();
|
_poiRadius = new QDoubleSpinBox();
|
||||||
_poiRadius->setSingleStep(1);
|
_poiRadius->setSingleStep(1);
|
||||||
_poiRadius->setDecimals(1);
|
_poiRadius->setDecimals(1);
|
||||||
if (_options->units == Imperial) {
|
if (_units == Imperial) {
|
||||||
_poiRadius->setValue(_options->poiRadius / MIINM);
|
_poiRadius->setValue(_options.poiRadius / MIINM);
|
||||||
_poiRadius->setSuffix(UNIT_SPACE + tr("mi"));
|
_poiRadius->setSuffix(UNIT_SPACE + tr("mi"));
|
||||||
} else if (_options->units == Nautical) {
|
} else if (_units == Nautical) {
|
||||||
_poiRadius->setValue(_options->poiRadius / NMIINM);
|
_poiRadius->setValue(_options.poiRadius / NMIINM);
|
||||||
_poiRadius->setSuffix(UNIT_SPACE + tr("nmi"));
|
_poiRadius->setSuffix(UNIT_SPACE + tr("nmi"));
|
||||||
} else {
|
} else {
|
||||||
_poiRadius->setValue(_options->poiRadius / KMINM);
|
_poiRadius->setValue(_options.poiRadius / KMINM);
|
||||||
_poiRadius->setSuffix(UNIT_SPACE + tr("km"));
|
_poiRadius->setSuffix(UNIT_SPACE + tr("km"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,7 +568,7 @@ QWidget *OptionsDialog::createExportPage()
|
|||||||
{
|
{
|
||||||
_wysiwyg = new QRadioButton(tr("WYSIWYG"));
|
_wysiwyg = new QRadioButton(tr("WYSIWYG"));
|
||||||
_hires = new QRadioButton(tr("High-Resolution"));
|
_hires = new QRadioButton(tr("High-Resolution"));
|
||||||
if (_options->hiresPrint)
|
if (_options.hiresPrint)
|
||||||
_hires->setChecked(true);
|
_hires->setChecked(true);
|
||||||
else
|
else
|
||||||
_wysiwyg->setChecked(true);
|
_wysiwyg->setChecked(true);
|
||||||
@ -589,17 +597,17 @@ QWidget *OptionsDialog::createExportPage()
|
|||||||
|
|
||||||
|
|
||||||
_name = new QCheckBox(tr("Name"));
|
_name = new QCheckBox(tr("Name"));
|
||||||
_name->setChecked(_options->printName);
|
_name->setChecked(_options.printName);
|
||||||
_date = new QCheckBox(tr("Date"));
|
_date = new QCheckBox(tr("Date"));
|
||||||
_date->setChecked(_options->printDate);
|
_date->setChecked(_options.printDate);
|
||||||
_distance = new QCheckBox(tr("Distance"));
|
_distance = new QCheckBox(tr("Distance"));
|
||||||
_distance->setChecked(_options->printDistance);
|
_distance->setChecked(_options.printDistance);
|
||||||
_time = new QCheckBox(tr("Time"));
|
_time = new QCheckBox(tr("Time"));
|
||||||
_time->setChecked(_options->printTime);
|
_time->setChecked(_options.printTime);
|
||||||
_movingTime = new QCheckBox(tr("Moving time"));
|
_movingTime = new QCheckBox(tr("Moving time"));
|
||||||
_movingTime->setChecked(_options->printMovingTime);
|
_movingTime->setChecked(_options.printMovingTime);
|
||||||
_itemCount = new QCheckBox(tr("Item count (>1)"));
|
_itemCount = new QCheckBox(tr("Item count (>1)"));
|
||||||
_itemCount->setChecked(_options->printItemCount);
|
_itemCount->setChecked(_options.printItemCount);
|
||||||
|
|
||||||
QFormLayout *headerTabLayout = new QFormLayout();
|
QFormLayout *headerTabLayout = new QFormLayout();
|
||||||
headerTabLayout->addWidget(_name);
|
headerTabLayout->addWidget(_name);
|
||||||
@ -614,7 +622,7 @@ QWidget *OptionsDialog::createExportPage()
|
|||||||
|
|
||||||
|
|
||||||
_separateGraphPage = new QCheckBox(tr("Separate graph page"));
|
_separateGraphPage = new QCheckBox(tr("Separate graph page"));
|
||||||
_separateGraphPage->setChecked(_options->separateGraphPage);
|
_separateGraphPage->setChecked(_options.separateGraphPage);
|
||||||
|
|
||||||
QFormLayout *graphTabLayout = new QFormLayout();
|
QFormLayout *graphTabLayout = new QFormLayout();
|
||||||
graphTabLayout->addWidget(_separateGraphPage);
|
graphTabLayout->addWidget(_separateGraphPage);
|
||||||
@ -633,23 +641,23 @@ QWidget *OptionsDialog::createExportPage()
|
|||||||
QWidget *OptionsDialog::createSystemPage()
|
QWidget *OptionsDialog::createSystemPage()
|
||||||
{
|
{
|
||||||
_useOpenGL = new QCheckBox(tr("Use OpenGL"));
|
_useOpenGL = new QCheckBox(tr("Use OpenGL"));
|
||||||
_useOpenGL->setChecked(_options->useOpenGL);
|
_useOpenGL->setChecked(_options.useOpenGL);
|
||||||
#ifdef ENABLE_HTTP2
|
#ifdef ENABLE_HTTP2
|
||||||
_enableHTTP2 = new QCheckBox(tr("Enable HTTP/2"));
|
_enableHTTP2 = new QCheckBox(tr("Enable HTTP/2"));
|
||||||
_enableHTTP2->setChecked(_options->enableHTTP2);
|
_enableHTTP2->setChecked(_options.enableHTTP2);
|
||||||
#endif // ENABLE_HTTP2
|
#endif // ENABLE_HTTP2
|
||||||
|
|
||||||
_pixmapCache = new QSpinBox();
|
_pixmapCache = new QSpinBox();
|
||||||
_pixmapCache->setMinimum(16);
|
_pixmapCache->setMinimum(16);
|
||||||
_pixmapCache->setMaximum(1024);
|
_pixmapCache->setMaximum(1024);
|
||||||
_pixmapCache->setSuffix(UNIT_SPACE + tr("MB"));
|
_pixmapCache->setSuffix(UNIT_SPACE + tr("MB"));
|
||||||
_pixmapCache->setValue(_options->pixmapCache);
|
_pixmapCache->setValue(_options.pixmapCache);
|
||||||
|
|
||||||
_connectionTimeout = new QSpinBox();
|
_connectionTimeout = new QSpinBox();
|
||||||
_connectionTimeout->setMinimum(30);
|
_connectionTimeout->setMinimum(30);
|
||||||
_connectionTimeout->setMaximum(120);
|
_connectionTimeout->setMaximum(120);
|
||||||
_connectionTimeout->setSuffix(UNIT_SPACE + tr("s"));
|
_connectionTimeout->setSuffix(UNIT_SPACE + tr("s"));
|
||||||
_connectionTimeout->setValue(_options->connectionTimeout);
|
_connectionTimeout->setValue(_options.connectionTimeout);
|
||||||
|
|
||||||
QFormLayout *formLayout = new QFormLayout();
|
QFormLayout *formLayout = new QFormLayout();
|
||||||
formLayout->addRow(tr("Image cache size:"), _pixmapCache);
|
formLayout->addRow(tr("Image cache size:"), _pixmapCache);
|
||||||
@ -674,8 +682,8 @@ QWidget *OptionsDialog::createSystemPage()
|
|||||||
return systemPage;
|
return systemPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionsDialog::OptionsDialog(Options *options, QWidget *parent)
|
OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent)
|
||||||
: QDialog(parent), _options(options)
|
: QDialog(parent), _options(options), _units(units)
|
||||||
{
|
{
|
||||||
QStackedWidget *pages = new QStackedWidget();
|
QStackedWidget *pages = new QStackedWidget();
|
||||||
pages->addWidget(createAppearancePage());
|
pages->addWidget(createAppearancePage());
|
||||||
@ -727,81 +735,82 @@ OptionsDialog::OptionsDialog(Options *options, QWidget *parent)
|
|||||||
|
|
||||||
void OptionsDialog::accept()
|
void OptionsDialog::accept()
|
||||||
{
|
{
|
||||||
_options->palette.setColor(_baseColor->color());
|
_options.palette.setColor(_baseColor->color());
|
||||||
_options->palette.setShift(_colorOffset->value() / 100.0);
|
_options.palette.setShift(_colorOffset->value() / 100.0);
|
||||||
_options->mapOpacity = _mapOpacity->value();
|
_options.mapOpacity = _mapOpacity->value();
|
||||||
_options->backgroundColor = _backgroundColor->color();
|
_options.backgroundColor = _backgroundColor->color();
|
||||||
_options->trackWidth = _trackWidth->value();
|
_options.trackWidth = _trackWidth->value();
|
||||||
_options->trackStyle = (Qt::PenStyle) _trackStyle->itemData(
|
_options.trackStyle = (Qt::PenStyle) _trackStyle->itemData(
|
||||||
_trackStyle->currentIndex()).toInt();
|
_trackStyle->currentIndex()).toInt();
|
||||||
_options->routeWidth = _routeWidth->value();
|
_options.routeWidth = _routeWidth->value();
|
||||||
_options->routeStyle = (Qt::PenStyle) _routeStyle->itemData(
|
_options.routeStyle = (Qt::PenStyle) _routeStyle->itemData(
|
||||||
_routeStyle->currentIndex()).toInt();
|
_routeStyle->currentIndex()).toInt();
|
||||||
_options->pathAntiAliasing = _pathAA->isChecked();
|
_options.pathAntiAliasing = _pathAA->isChecked();
|
||||||
_options->areaWidth = _areaWidth->value();
|
_options.areaWidth = _areaWidth->value();
|
||||||
_options->areaStyle = (Qt::PenStyle) _areaStyle->itemData(
|
_options.areaStyle = (Qt::PenStyle) _areaStyle->itemData(
|
||||||
_areaStyle->currentIndex()).toInt();
|
_areaStyle->currentIndex()).toInt();
|
||||||
_options->areaOpacity = _areaOpacity->value();
|
_options.areaOpacity = _areaOpacity->value();
|
||||||
_options->waypointSize = _waypointSize->value();
|
_options.waypointSize = _waypointSize->value();
|
||||||
_options->waypointColor = _waypointColor->color();
|
_options.waypointColor = _waypointColor->color();
|
||||||
_options->poiSize = _poiSize->value();
|
_options.poiSize = _poiSize->value();
|
||||||
_options->poiColor = _poiColor->color();
|
_options.poiColor = _poiColor->color();
|
||||||
_options->graphWidth = _graphWidth->value();
|
_options.graphWidth = _graphWidth->value();
|
||||||
_options->sliderColor = _sliderColor->color();
|
_options.sliderColor = _sliderColor->color();
|
||||||
_options->graphAntiAliasing = _graphAA->isChecked();
|
_options.graphAntiAliasing = _graphAA->isChecked();
|
||||||
|
|
||||||
_options->projection = _projection->itemData(_projection->currentIndex())
|
_options.projection = _projection->itemData(_projection->currentIndex())
|
||||||
.toInt();
|
.toInt();
|
||||||
#ifdef ENABLE_HIDPI
|
#ifdef ENABLE_HIDPI
|
||||||
_options->hidpiMap = _hidpi->isChecked();
|
_options.hidpiMap = _hidpi->isChecked();
|
||||||
#endif // ENABLE_HIDPI
|
#endif // ENABLE_HIDPI
|
||||||
|
|
||||||
_options->elevationFilter = _elevationFilter->value();
|
_options.elevationFilter = _elevationFilter->value();
|
||||||
_options->speedFilter = _speedFilter->value();
|
_options.speedFilter = _speedFilter->value();
|
||||||
_options->heartRateFilter = _heartRateFilter->value();
|
_options.heartRateFilter = _heartRateFilter->value();
|
||||||
_options->cadenceFilter = _cadenceFilter->value();
|
_options.cadenceFilter = _cadenceFilter->value();
|
||||||
_options->powerFilter = _powerFilter->value();
|
_options.powerFilter = _powerFilter->value();
|
||||||
_options->outlierEliminate = _outlierEliminate->isChecked();
|
_options.outlierEliminate = _outlierEliminate->isChecked();
|
||||||
_options->automaticPause = _automaticPause->isChecked();
|
_options.automaticPause = _automaticPause->isChecked();
|
||||||
qreal pauseSpeed = (_options->units == Imperial)
|
qreal pauseSpeed = (_units == Imperial)
|
||||||
? _pauseSpeed->value() / MS2MIH : (_options->units == Nautical)
|
? _pauseSpeed->value() / MS2MIH : (_units == Nautical)
|
||||||
? _pauseSpeed->value() / MS2KN : _pauseSpeed->value() / MS2KMH;
|
? _pauseSpeed->value() / MS2KN : _pauseSpeed->value() / MS2KMH;
|
||||||
if (qAbs(pauseSpeed - _options->pauseSpeed) > 0.01)
|
if (qAbs(pauseSpeed - _options.pauseSpeed) > 0.01)
|
||||||
_options->pauseSpeed = pauseSpeed;
|
_options.pauseSpeed = pauseSpeed;
|
||||||
_options->pauseInterval = _pauseInterval->value();
|
_options.pauseInterval = _pauseInterval->value();
|
||||||
_options->useReportedSpeed = _reportedSpeed->isChecked();
|
_options.useReportedSpeed = _reportedSpeed->isChecked();
|
||||||
_options->dataUseDEM = _dataDEMElevation->isChecked();
|
_options.dataUseDEM = _dataDEMElevation->isChecked();
|
||||||
_options->showSecondaryElevation = _showSecondaryElevation->isChecked();
|
_options.showSecondaryElevation = _showSecondaryElevation->isChecked();
|
||||||
_options->showSecondarySpeed = _showSecondarySpeed->isChecked();
|
_options.showSecondarySpeed = _showSecondarySpeed->isChecked();
|
||||||
#ifdef ENABLE_TIMEZONES
|
#ifdef ENABLE_TIMEZONES
|
||||||
_options->timeZone.setType(_utcZone->isChecked()
|
_options.timeZone.setType(_utcZone->isChecked()
|
||||||
? TimeZoneInfo::UTC : _systemZone->isChecked()
|
? TimeZoneInfo::UTC : _systemZone->isChecked()
|
||||||
? TimeZoneInfo::System : TimeZoneInfo::Custom);
|
? TimeZoneInfo::System : TimeZoneInfo::Custom);
|
||||||
_options->timeZone.setCustomZone(QTimeZone(_timeZone->currentText()
|
_options.timeZone.setCustomZone(QTimeZone(_timeZone->currentText()
|
||||||
.toLatin1()));
|
.toLatin1()));
|
||||||
#endif // ENABLE_TIMEZONES
|
#endif // ENABLE_TIMEZONES
|
||||||
|
_options.useSegments = _useSegments->isChecked();
|
||||||
|
|
||||||
qreal poiRadius = (_options->units == Imperial)
|
qreal poiRadius = (_units == Imperial)
|
||||||
? _poiRadius->value() * MIINM : (_options->units == Nautical)
|
? _poiRadius->value() * MIINM : (_units == Nautical)
|
||||||
? _poiRadius->value() * NMIINM : _poiRadius->value() * KMINM;
|
? _poiRadius->value() * NMIINM : _poiRadius->value() * KMINM;
|
||||||
if (qAbs(poiRadius - _options->poiRadius) > 0.01)
|
if (qAbs(poiRadius - _options.poiRadius) > 0.01)
|
||||||
_options->poiRadius = poiRadius;
|
_options.poiRadius = poiRadius;
|
||||||
|
|
||||||
_options->useOpenGL = _useOpenGL->isChecked();
|
_options.useOpenGL = _useOpenGL->isChecked();
|
||||||
#ifdef ENABLE_HTTP2
|
#ifdef ENABLE_HTTP2
|
||||||
_options->enableHTTP2 = _enableHTTP2->isChecked();
|
_options.enableHTTP2 = _enableHTTP2->isChecked();
|
||||||
#endif // ENABLE_HTTP2
|
#endif // ENABLE_HTTP2
|
||||||
_options->pixmapCache = _pixmapCache->value();
|
_options.pixmapCache = _pixmapCache->value();
|
||||||
_options->connectionTimeout = _connectionTimeout->value();
|
_options.connectionTimeout = _connectionTimeout->value();
|
||||||
|
|
||||||
_options->hiresPrint = _hires->isChecked();
|
_options.hiresPrint = _hires->isChecked();
|
||||||
_options->printName = _name->isChecked();
|
_options.printName = _name->isChecked();
|
||||||
_options->printDate = _date->isChecked();
|
_options.printDate = _date->isChecked();
|
||||||
_options->printDistance = _distance->isChecked();
|
_options.printDistance = _distance->isChecked();
|
||||||
_options->printTime = _time->isChecked();
|
_options.printTime = _time->isChecked();
|
||||||
_options->printMovingTime = _movingTime->isChecked();
|
_options.printMovingTime = _movingTime->isChecked();
|
||||||
_options->printItemCount = _itemCount->isChecked();
|
_options.printItemCount = _itemCount->isChecked();
|
||||||
_options->separateGraphPage = _separateGraphPage->isChecked();
|
_options.separateGraphPage = _separateGraphPage->isChecked();
|
||||||
|
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ struct Options {
|
|||||||
#ifdef ENABLE_TIMEZONES
|
#ifdef ENABLE_TIMEZONES
|
||||||
TimeZoneInfo timeZone;
|
TimeZoneInfo timeZone;
|
||||||
#endif // ENABLE_TIMEZONES
|
#endif // ENABLE_TIMEZONES
|
||||||
|
bool useSegments;
|
||||||
// POI
|
// POI
|
||||||
int poiRadius;
|
int poiRadius;
|
||||||
// System
|
// System
|
||||||
@ -81,8 +82,6 @@ struct Options {
|
|||||||
bool printMovingTime;
|
bool printMovingTime;
|
||||||
bool printItemCount;
|
bool printItemCount;
|
||||||
bool separateGraphPage;
|
bool separateGraphPage;
|
||||||
|
|
||||||
Units units;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class OptionsDialog : public QDialog
|
class OptionsDialog : public QDialog
|
||||||
@ -93,7 +92,7 @@ public slots:
|
|||||||
void accept();
|
void accept();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OptionsDialog(Options *options, QWidget *parent = 0);
|
OptionsDialog(Options &options, Units units, QWidget *parent = 0);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void automaticPauseDetectionSet(bool set);
|
void automaticPauseDetectionSet(bool set);
|
||||||
@ -106,8 +105,9 @@ private:
|
|||||||
QWidget *createSystemPage();
|
QWidget *createSystemPage();
|
||||||
QWidget *createExportPage();
|
QWidget *createExportPage();
|
||||||
|
|
||||||
Options *_options;
|
Options &_options;
|
||||||
|
|
||||||
|
Units _units;
|
||||||
// Appearance
|
// Appearance
|
||||||
ColorBox *_baseColor;
|
ColorBox *_baseColor;
|
||||||
PercentSlider *_colorOffset;
|
PercentSlider *_colorOffset;
|
||||||
@ -157,6 +157,7 @@ private:
|
|||||||
QRadioButton *_customZone;
|
QRadioButton *_customZone;
|
||||||
QComboBox *_timeZone;
|
QComboBox *_timeZone;
|
||||||
#endif // ENABLE_TIMEZONES
|
#endif // ENABLE_TIMEZONES
|
||||||
|
QCheckBox *_useSegments;
|
||||||
// POI
|
// POI
|
||||||
QDoubleSpinBox *_poiRadius;
|
QDoubleSpinBox *_poiRadius;
|
||||||
// System
|
// System
|
||||||
|
@ -1,30 +1,27 @@
|
|||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QRadioButton>
|
#include <QRadioButton>
|
||||||
#include <QPushButton>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
#include <QDoubleSpinBox>
|
#include "marginswidget.h"
|
||||||
#include "fileselectwidget.h"
|
#include "fileselectwidget.h"
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
#include "exportdialog.h"
|
#include "pdfexportdialog.h"
|
||||||
|
|
||||||
|
|
||||||
ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
PDFExportDialog::PDFExportDialog(PDFExport &exp, Units units, QWidget *parent)
|
||||||
: QDialog(parent), _export(exp)
|
: QDialog(parent), _export(exp), _units(units)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
_fileSelect = new FileSelectWidget();
|
_fileSelect = new FileSelectWidget();
|
||||||
_fileSelect->setFilter(tr("PDF files") + " (*.pdf);;" + tr("All files")
|
_fileSelect->setFilter(tr("PDF files") + " (*.pdf);;" + tr("All files")
|
||||||
+ " (*)");
|
+ " (*)");
|
||||||
_fileSelect->setFile(_export->fileName);
|
_fileSelect->setFile(_export.fileName);
|
||||||
|
|
||||||
_paperSize = new QComboBox();
|
_paperSize = new QComboBox();
|
||||||
_paperSize->addItem("A2", QPrinter::A2);
|
_paperSize->addItem("A2", QPrinter::A2);
|
||||||
@ -39,14 +36,14 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
|||||||
_paperSize->addItem("Tabloid", QPrinter::Tabloid);
|
_paperSize->addItem("Tabloid", QPrinter::Tabloid);
|
||||||
_paperSize->addItem("Legal", QPrinter::Legal);
|
_paperSize->addItem("Legal", QPrinter::Legal);
|
||||||
_paperSize->addItem("Letter", QPrinter::Letter);
|
_paperSize->addItem("Letter", QPrinter::Letter);
|
||||||
if ((index = _paperSize->findData(_export->paperSize)) >= 0)
|
if ((index = _paperSize->findData(_export.paperSize)) >= 0)
|
||||||
_paperSize->setCurrentIndex(index);
|
_paperSize->setCurrentIndex(index);
|
||||||
|
|
||||||
_resolution = new QComboBox();
|
_resolution = new QComboBox();
|
||||||
_resolution->addItem("150 DPI", 150);
|
_resolution->addItem("150 DPI", 150);
|
||||||
_resolution->addItem("300 DPI", 300);
|
_resolution->addItem("300 DPI", 300);
|
||||||
_resolution->addItem("600 DPI", 600);
|
_resolution->addItem("600 DPI", 600);
|
||||||
if ((index = _resolution->findData(_export->resolution)) >= 0)
|
if ((index = _resolution->findData(_export.resolution)) >= 0)
|
||||||
_resolution->setCurrentIndex(index);
|
_resolution->setCurrentIndex(index);
|
||||||
|
|
||||||
_portrait = new QRadioButton(tr("Portrait"));
|
_portrait = new QRadioButton(tr("Portrait"));
|
||||||
@ -54,41 +51,16 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
|||||||
QHBoxLayout *orientationLayout = new QHBoxLayout();
|
QHBoxLayout *orientationLayout = new QHBoxLayout();
|
||||||
orientationLayout->addWidget(_portrait);
|
orientationLayout->addWidget(_portrait);
|
||||||
orientationLayout->addWidget(_landscape);
|
orientationLayout->addWidget(_landscape);
|
||||||
if (_export->orientation == QPrinter::Portrait)
|
if (_export.orientation == QPrinter::Portrait)
|
||||||
_portrait->setChecked(true);
|
_portrait->setChecked(true);
|
||||||
else
|
else
|
||||||
_landscape->setChecked(true);
|
_landscape->setChecked(true);
|
||||||
|
|
||||||
_topMargin = new QDoubleSpinBox();
|
_margins = new MarginsFWidget();
|
||||||
_bottomMargin = new QDoubleSpinBox();
|
_margins->setUnits((units == Metric) ? tr("cm") : tr("in"));
|
||||||
_leftMargin = new QDoubleSpinBox();
|
_margins->setSingleStep(0.1);
|
||||||
_rightMargin = new QDoubleSpinBox();
|
_margins->setValue((units == Metric)
|
||||||
QString us = (_export->units == Metric) ? tr("mm") : tr("in");
|
? _export.margins * MM2CM : _export.margins * MM2IN);
|
||||||
_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);
|
|
||||||
|
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
QGroupBox *pageSetupBox = new QGroupBox(tr("Page Setup"));
|
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("Page size:"), _paperSize);
|
||||||
pageSetupLayout->addRow(tr("Resolution:"), _resolution);
|
pageSetupLayout->addRow(tr("Resolution:"), _resolution);
|
||||||
pageSetupLayout->addRow(tr("Orientation:"), orientationLayout);
|
pageSetupLayout->addRow(tr("Orientation:"), orientationLayout);
|
||||||
pageSetupLayout->addRow(tr("Margins:"), marginsLayout);
|
pageSetupLayout->addRow(tr("Margins:"), _margins);
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
QFrame *line = new QFrame();
|
QFrame *line = new QFrame();
|
||||||
line->setFrameShape(QFrame::HLine);
|
line->setFrameShape(QFrame::HLine);
|
||||||
@ -111,7 +83,7 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
|||||||
|
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
QGroupBox *outputFileBox = new QGroupBox(tr("Output file"));
|
QGroupBox *outputFileBox = new QGroupBox(tr("Output file"));
|
||||||
QHBoxLayout *outputFileLayout = new QHBoxLayout();
|
QVBoxLayout *outputFileLayout = new QVBoxLayout();
|
||||||
outputFileLayout->addWidget(_fileSelect);
|
outputFileLayout->addWidget(_fileSelect);
|
||||||
outputFileBox->setLayout(outputFileLayout);
|
outputFileBox->setLayout(outputFileLayout);
|
||||||
#endif // Q_OS_MAC
|
#endif // Q_OS_MAC
|
||||||
@ -136,41 +108,13 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
|||||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExportDialog::checkFile()
|
void PDFExportDialog::accept()
|
||||||
{
|
{
|
||||||
if (_fileSelect->file().isEmpty()) {
|
QString error;
|
||||||
QMessageBox::warning(this, tr("Error"), tr("No output file selected."));
|
if (!_fileSelect->checkFile(error)) {
|
||||||
return false;
|
QMessageBox::warning(this, tr("Error"), error);
|
||||||
}
|
|
||||||
|
|
||||||
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())
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QPrinter::Orientation orientation = _portrait->isChecked()
|
QPrinter::Orientation orientation = _portrait->isChecked()
|
||||||
? QPrinter::Portrait : QPrinter::Landscape;
|
? QPrinter::Portrait : QPrinter::Landscape;
|
||||||
@ -178,17 +122,12 @@ void ExportDialog::accept()
|
|||||||
(_paperSize->itemData(_paperSize->currentIndex()).toInt());
|
(_paperSize->itemData(_paperSize->currentIndex()).toInt());
|
||||||
int resolution = _resolution->itemData(_resolution->currentIndex()).toInt();
|
int resolution = _resolution->itemData(_resolution->currentIndex()).toInt();
|
||||||
|
|
||||||
_export->fileName = _fileSelect->file();
|
_export.fileName = _fileSelect->file();
|
||||||
_export->paperSize = paperSize;
|
_export.paperSize = paperSize;
|
||||||
_export->resolution = resolution;
|
_export.resolution = resolution;
|
||||||
_export->orientation = orientation;
|
_export.orientation = orientation;
|
||||||
if (_export->units == Imperial)
|
_export.margins = (_units == Imperial)
|
||||||
_export->margins = MarginsF(_leftMargin->value() / MM2IN,
|
? _margins->value() / MM2IN : _margins->value() / MM2CM;
|
||||||
_topMargin->value() / MM2IN, _rightMargin->value() / MM2IN,
|
|
||||||
_bottomMargin->value() / MM2IN);
|
|
||||||
else
|
|
||||||
_export->margins = MarginsF(_leftMargin->value(), _topMargin->value(),
|
|
||||||
_rightMargin->value(), _bottomMargin->value());
|
|
||||||
|
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef EXPORTDIALOG_H
|
#ifndef PDFEXPORTDIALOG_H
|
||||||
#define EXPORTDIALOG_H
|
#define PDFEXPORTDIALOG_H
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QPrinter>
|
#include <QPrinter>
|
||||||
@ -9,42 +9,37 @@
|
|||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QRadioButton;
|
class QRadioButton;
|
||||||
class FileSelectWidget;
|
class FileSelectWidget;
|
||||||
class QDoubleSpinBox;
|
class MarginsFWidget;
|
||||||
|
|
||||||
struct Export {
|
struct PDFExport
|
||||||
|
{
|
||||||
QString fileName;
|
QString fileName;
|
||||||
QPrinter::PaperSize paperSize;
|
QPrinter::PaperSize paperSize;
|
||||||
QPrinter::Orientation orientation;
|
QPrinter::Orientation orientation;
|
||||||
MarginsF margins;
|
MarginsF margins;
|
||||||
int resolution;
|
int resolution;
|
||||||
|
|
||||||
Units units;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExportDialog : public QDialog
|
class PDFExportDialog : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ExportDialog(Export *exp, QWidget *parent = 0);
|
PDFExportDialog(PDFExport &exp, Units units, QWidget *parent = 0);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void accept();
|
void accept();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool checkFile();
|
PDFExport &_export;
|
||||||
|
|
||||||
Export *_export;
|
|
||||||
|
|
||||||
|
Units _units;
|
||||||
FileSelectWidget *_fileSelect;
|
FileSelectWidget *_fileSelect;
|
||||||
QComboBox *_paperSize;
|
QComboBox *_paperSize;
|
||||||
QComboBox *_resolution;
|
QComboBox *_resolution;
|
||||||
QRadioButton *_portrait;
|
QRadioButton *_portrait;
|
||||||
QRadioButton *_landscape;
|
QRadioButton *_landscape;
|
||||||
QDoubleSpinBox *_topMargin;
|
MarginsFWidget *_margins;
|
||||||
QDoubleSpinBox *_bottomMargin;
|
|
||||||
QDoubleSpinBox *_leftMargin;
|
|
||||||
QDoubleSpinBox *_rightMargin;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#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
|
@ -66,26 +66,45 @@
|
|||||||
#define SHOW_WAYPOINT_LABELS_SETTING "waypointLabels"
|
#define SHOW_WAYPOINT_LABELS_SETTING "waypointLabels"
|
||||||
#define SHOW_WAYPOINT_LABELS_DEFAULT true
|
#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_SETTING "orientation"
|
||||||
#define PAPER_ORIENTATION_DEFAULT QPrinter::Portrait
|
#define PAPER_ORIENTATION_DEFAULT QPrinter::Portrait
|
||||||
#define PAPER_SIZE_SETTING "size"
|
#define PAPER_SIZE_SETTING "size"
|
||||||
#define PAPER_SIZE_DEFAULT (IMPERIAL_UNITS() ? QPrinter::Letter \
|
#define PAPER_SIZE_DEFAULT (IMPERIAL_UNITS() ? QPrinter::Letter \
|
||||||
: QPrinter::A4)
|
: QPrinter::A4)
|
||||||
#define MARGIN_LEFT_SETTING "marginLeft"
|
#define PDF_MARGIN_LEFT_SETTING "marginLeft"
|
||||||
#define MARGIN_LEFT_DEFAULT 5 /* mm */
|
#define PDF_MARGIN_LEFT_DEFAULT 5 /* mm */
|
||||||
#define MARGIN_TOP_SETTING "marginTop"
|
#define PDF_MARGIN_TOP_SETTING "marginTop"
|
||||||
#define MARGIN_TOP_DEFAULT 5 /* mm */
|
#define PDF_MARGIN_TOP_DEFAULT 5 /* mm */
|
||||||
#define MARGIN_RIGHT_SETTING "marginRight"
|
#define PDF_MARGIN_RIGHT_SETTING "marginRight"
|
||||||
#define MARGIN_RIGHT_DEFAULT 5 /* mm */
|
#define PDF_MARGIN_RIGHT_DEFAULT 5 /* mm */
|
||||||
#define MARGIN_BOTTOM_SETTING "marginBottom"
|
#define PDF_MARGIN_BOTTOM_SETTING "marginBottom"
|
||||||
#define MARGIN_BOTTOM_DEFAULT 5 /* mm */
|
#define PDF_MARGIN_BOTTOM_DEFAULT 5 /* mm */
|
||||||
#define EXPORT_FILENAME_SETTING "fileName"
|
#define PDF_FILENAME_SETTING "fileName"
|
||||||
#define EXPORT_FILENAME_DEFAULT QString("%1/export.pdf"). \
|
#define PDF_FILENAME_DEFAULT QString("%1/export.pdf"). \
|
||||||
arg(QDir::currentPath())
|
arg(QDir::currentPath())
|
||||||
#define RESOLUTION_SETTING "resolution"
|
#define RESOLUTION_SETTING "resolution"
|
||||||
#define RESOLUTION_DEFAULT 600
|
#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 OPTIONS_SETTINGS_GROUP "Options"
|
||||||
#define PALETTE_COLOR_SETTING "paletteColor"
|
#define PALETTE_COLOR_SETTING "paletteColor"
|
||||||
#define PALETTE_COLOR_DEFAULT QColor(Qt::blue)
|
#define PALETTE_COLOR_DEFAULT QColor(Qt::blue)
|
||||||
@ -150,6 +169,8 @@
|
|||||||
#define SHOW_SECONDARY_SPEED_SETTING "showSecondarySpeed"
|
#define SHOW_SECONDARY_SPEED_SETTING "showSecondarySpeed"
|
||||||
#define SHOW_SECONDARY_SPEED_DEFAULT false
|
#define SHOW_SECONDARY_SPEED_DEFAULT false
|
||||||
#define TIME_ZONE_SETTING "timeZone"
|
#define TIME_ZONE_SETTING "timeZone"
|
||||||
|
#define USE_SEGMENTS_SETTING "useSegments"
|
||||||
|
#define USE_SEGMENTS_DEFAULT true
|
||||||
#define POI_RADIUS_SETTING "poiRadius"
|
#define POI_RADIUS_SETTING "poiRadius"
|
||||||
#define POI_RADIUS_DEFAULT (int)(IMPERIAL_UNITS() ? MIINM : KMINM)
|
#define POI_RADIUS_DEFAULT (int)(IMPERIAL_UNITS() ? MIINM : KMINM)
|
||||||
#define USE_OPENGL_SETTING "useOpenGL"
|
#define USE_OPENGL_SETTING "useOpenGL"
|
||||||
|
@ -16,6 +16,7 @@ enum Units {
|
|||||||
#define MS2KN 1.943844490000 // m/s -> kn
|
#define MS2KN 1.943844490000 // m/s -> kn
|
||||||
#define FT2MI 0.000189393939 // ft -> mi
|
#define FT2MI 0.000189393939 // ft -> mi
|
||||||
#define MM2IN 0.039370100000 // mm -> in
|
#define MM2IN 0.039370100000 // mm -> in
|
||||||
|
#define MM2CM 0.100000000000 // mm -> cm
|
||||||
#define H2S 0.000277777778 // h -> s
|
#define H2S 0.000277777778 // h -> s
|
||||||
#define MIN2S 0.016666666667 // min -> s
|
#define MIN2S 0.016666666667 // min -> s
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
#define ENABLE_GEOJSON
|
#define ENABLE_GEOJSON
|
||||||
#endif // QT >= 5.0
|
#endif // QT >= 5.0
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
|
||||||
#define ENABLE_TIMEZONES
|
#define ENABLE_TIMEZONES
|
||||||
#endif // QT >= 5.2
|
#endif // QT >= 5.5
|
||||||
|
|
||||||
#endif /* CONFIG_H */
|
#endif /* CONFIG_H */
|
||||||
|
@ -66,13 +66,25 @@ void TCXParser::heartRateBpm(Trackpoint &trackpoint)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCXParser::extensions(Trackpoint &trackpoint)
|
void TCXParser::TPX(Trackpoint &trackpoint)
|
||||||
{
|
{
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == QLatin1String("RunCadence"))
|
if (_reader.name() == QLatin1String("RunCadence"))
|
||||||
trackpoint.setCadence(number());
|
trackpoint.setCadence(number());
|
||||||
else if (_reader.name() == QLatin1String("Watts"))
|
else if (_reader.name() == QLatin1String("Watts"))
|
||||||
trackpoint.setPower(number());
|
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
|
else
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ private:
|
|||||||
void trackpointData(Trackpoint &trackpoint);
|
void trackpointData(Trackpoint &trackpoint);
|
||||||
void waypointData(Waypoint &waypoint);
|
void waypointData(Waypoint &waypoint);
|
||||||
void extensions(Trackpoint &trackpoint);
|
void extensions(Trackpoint &trackpoint);
|
||||||
|
void TPX(Trackpoint &trackpoint);
|
||||||
void heartRateBpm(Trackpoint &trackpoint);
|
void heartRateBpm(Trackpoint &trackpoint);
|
||||||
Coordinates position();
|
Coordinates position();
|
||||||
qreal number();
|
qreal number();
|
||||||
|
@ -17,7 +17,7 @@ bool Track::_useReportedSpeed = false;
|
|||||||
bool Track::_useDEM = false;
|
bool Track::_useDEM = false;
|
||||||
bool Track::_show2ndElevation = false;
|
bool Track::_show2ndElevation = false;
|
||||||
bool Track::_show2ndSpeed = false;
|
bool Track::_show2ndSpeed = false;
|
||||||
|
bool Track::_useSegments = true;
|
||||||
|
|
||||||
static qreal avg(const QVector<qreal> &v)
|
static qreal avg(const QVector<qreal> &v)
|
||||||
{
|
{
|
||||||
@ -88,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;
|
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++) {
|
for (int i = 0; i < _data.size(); i++) {
|
||||||
const SegmentData &sd = _data.at(i);
|
const SegmentData &sd = _data.at(i);
|
||||||
_segments.append(Segment());
|
_segments.append(Segment());
|
||||||
|
@ -49,10 +49,9 @@ public:
|
|||||||
{_outlierEliminate = eliminate;}
|
{_outlierEliminate = eliminate;}
|
||||||
static void useReportedSpeed(bool use) {_useReportedSpeed = use;}
|
static void useReportedSpeed(bool use) {_useReportedSpeed = use;}
|
||||||
static void useDEM(bool use) {_useDEM = use;}
|
static void useDEM(bool use) {_useDEM = use;}
|
||||||
static void showSecondaryElevation(bool show)
|
static void showSecondaryElevation(bool show) {_show2ndElevation = show;}
|
||||||
{_show2ndElevation = show;}
|
static void showSecondarySpeed(bool show) {_show2ndSpeed = show;}
|
||||||
static void showSecondarySpeed(bool show)
|
static void useSegments(bool use) {_useSegments = use;}
|
||||||
{_show2ndSpeed = show;}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Segment {
|
struct Segment {
|
||||||
@ -87,6 +86,7 @@ private:
|
|||||||
static bool _useDEM;
|
static bool _useDEM;
|
||||||
static bool _show2ndElevation;
|
static bool _show2ndElevation;
|
||||||
static bool _show2ndSpeed;
|
static bool _show2ndSpeed;
|
||||||
|
static bool _useSegments;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TRACK_H
|
#endif // TRACK_H
|
||||||
|
@ -1,38 +1,9 @@
|
|||||||
#include "bitstream.h"
|
#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()
|
bool BitStream1::flush()
|
||||||
{
|
{
|
||||||
if (_length && !_file.seek(_hdl, _hdl.pos() + _length))
|
if (_length && !_file.seek(_hdl, _file.pos(_hdl) + _length))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_length = 0;
|
_length = 0;
|
||||||
@ -41,8 +12,19 @@ bool BitStream1::flush()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BitStream4F::flush()
|
||||||
|
{
|
||||||
|
if (_length && !_file.seek(_hdl, _file.pos(_hdl) + _length))
|
||||||
|
return false;
|
||||||
|
|
||||||
bool BitStream4::read(int bits, quint32 &val)
|
_length = 0;
|
||||||
|
_used = 32;
|
||||||
|
_unused = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BitStream4F::read(int bits, quint32 &val)
|
||||||
{
|
{
|
||||||
if (bits <= 32 - (int)(_used + _unused)) {
|
if (bits <= 32 - (int)(_used + _unused)) {
|
||||||
val = bits ? (_data << _used) >> (32 - bits) : 0;
|
val = bits ? (_data << _used) >> (32 - bits) : 0;
|
||||||
@ -50,6 +32,8 @@ bool BitStream4::read(int bits, quint32 &val)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_unused)
|
||||||
|
return false;
|
||||||
quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0;
|
quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0;
|
||||||
quint32 bytes = qMin(_length, 4U);
|
quint32 bytes = qMin(_length, 4U);
|
||||||
|
|
||||||
@ -66,14 +50,149 @@ bool BitStream4::read(int bits, quint32 &val)
|
|||||||
return true;
|
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))
|
_file.seek(_hdl, _file.pos(_hdl) - 4);
|
||||||
return false;
|
}
|
||||||
|
|
||||||
_length = 0;
|
bool BitStream4R::readBytes(int bytes, quint32 &val)
|
||||||
_used = 32;
|
{
|
||||||
_unused = 0;
|
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;
|
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,9 @@ public:
|
|||||||
BitStream1(const SubFile &file, SubFile::Handle &hdl, quint32 length)
|
BitStream1(const SubFile &file, SubFile::Handle &hdl, quint32 length)
|
||||||
: _file(file), _hdl(hdl), _length(length), _remaining(0) {}
|
: _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();
|
bool flush();
|
||||||
quint32 bitsAvailable() const {return _length * 8 + _remaining;}
|
quint64 bitsAvailable() const {return (quint64)_length * 8 + _remaining;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const SubFile &_file;
|
const SubFile &_file;
|
||||||
@ -25,15 +25,105 @@ public:
|
|||||||
: _file(file), _hdl(hdl), _length(length), _used(32), _unused(0),
|
: _file(file), _hdl(hdl), _length(length), _used(32), _unused(0),
|
||||||
_data(0) {}
|
_data(0) {}
|
||||||
|
|
||||||
bool read(int bits, quint32 &val);
|
quint64 bitsAvailable() const
|
||||||
bool flush();
|
{return (quint64)_length * 8 + (32 - _used) - _unused;}
|
||||||
quint32 bitsAvailable() const {return _length * 8 + (32 - _used) - _unused;}
|
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
const SubFile &_file;
|
const SubFile &_file;
|
||||||
SubFile::Handle &_hdl;
|
SubFile::Handle &_hdl;
|
||||||
quint32 _length, _used, _unused;
|
quint32 _length, _used, _unused;
|
||||||
quint32 _data;
|
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
|
#endif // BITSTREAM_H
|
||||||
|
@ -1,74 +1,41 @@
|
|||||||
#include "huffmanstream.h"
|
#include "huffmanstream.h"
|
||||||
|
|
||||||
|
bool HuffmanStreamF::init(bool line)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
if (line) {
|
if (line) {
|
||||||
if (!(sign(_lonSign) && sign(_latSign)))
|
if (!(sign(_lonSign) && sign(_latSign)))
|
||||||
return;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
_lonSign = 0;
|
_lonSign = 0;
|
||||||
_latSign = 0;
|
_latSign = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 eb;
|
quint32 eb;
|
||||||
if (!read(1, eb))
|
if (!_bs.read(1, eb))
|
||||||
return;
|
return false;
|
||||||
if (eb) {
|
|
||||||
qWarning("Extended polygon/lines not supported");
|
Q_ASSERT(!eb);
|
||||||
flush();
|
if (eb)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HuffmanStream::sign(int &val)
|
|
||||||
{
|
|
||||||
quint32 bit;
|
|
||||||
val = 0;
|
|
||||||
|
|
||||||
if (!read(1, bit))
|
|
||||||
return false;
|
return false;
|
||||||
if (bit) {
|
|
||||||
if (!read(1, bit))
|
|
||||||
return false;
|
|
||||||
val = bit ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HuffmanStream::readDelta(int sign, qint32 &symbol)
|
bool HuffmanStreamR::init()
|
||||||
{
|
{
|
||||||
quint8 size;
|
if (!(sign(_lonSign) && sign(_latSign)))
|
||||||
quint32 next;
|
|
||||||
quint8 nextSize = qMin((quint32)(32 - _symbolDataSize), bitsAvailable());
|
|
||||||
|
|
||||||
if (!read(nextSize, next))
|
|
||||||
return false;
|
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;
|
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 "bitstream.h"
|
||||||
#include "huffmantable.h"
|
#include "huffmantable.h"
|
||||||
|
|
||||||
class HuffmanStream : public BitStream4 {
|
template <class BitStream>
|
||||||
|
class HuffmanStream {
|
||||||
public:
|
public:
|
||||||
HuffmanStream(const SubFile &file, SubFile::Handle &hdl, quint32 length,
|
HuffmanStream(BitStream &bitstream, const HuffmanTable &table)
|
||||||
const HuffmanTable &table, bool line);
|
: _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)
|
bool readNext(qint32 &lonDelta, qint32 &latDelta)
|
||||||
{
|
{
|
||||||
if (!(readDelta(_lonSign, lonDelta) && readDelta(_latSign, latDelta)))
|
if (!(readDelta(_lonSign, lonDelta) && readDelta(_latSign, latDelta)))
|
||||||
@ -17,19 +21,121 @@ public:
|
|||||||
return (lonDelta || latDelta);
|
return (lonDelta || latDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readOffset(qint32 &lonDelta, qint32 &latDelta)
|
|
||||||
{return (readDelta(1, lonDelta) && readDelta(1, latDelta));}
|
|
||||||
bool atEnd() const
|
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 sign(int &val);
|
||||||
bool readDelta(int sign, qint32 &delta);
|
bool readDelta(int sign, qint32 &delta);
|
||||||
|
|
||||||
|
BitStream &_bs;
|
||||||
const HuffmanTable &_table;
|
const HuffmanTable &_table;
|
||||||
quint32 _symbolDataSize;
|
quint32 _symbolDataSize;
|
||||||
quint32 _symbolData;
|
quint32 _symbolData;
|
||||||
int _lonSign, _latSign;
|
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
|
#endif // HUFFMANSTREAM_H
|
||||||
|
@ -42,6 +42,8 @@ bool HuffmanTable::load(const SubFile &file, SubFile::Handle &hdl,
|
|||||||
_s10 = _s14 + _s1c * _s1d;
|
_s10 = _s14 + _s1c * _s1d;
|
||||||
_s18 = _s10 + (_s1 << _s0);
|
_s18 = _s10 + (_s1 << _s0);
|
||||||
|
|
||||||
|
_id = id;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +57,7 @@ bool HuffmanTable::getBuffer(const SubFile &file, SubFile::Handle &hdl,
|
|||||||
return false;
|
return false;
|
||||||
if (!file.readVUInt32(hdl, recordSize))
|
if (!file.readVUInt32(hdl, recordSize))
|
||||||
return false;
|
return false;
|
||||||
recordOffset = hdl.pos() + recordSize;
|
recordOffset = file.pos(hdl) + recordSize;
|
||||||
if (recordOffset > offset + size)
|
if (recordOffset > offset + size)
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,8 @@ public:
|
|||||||
quint8 maxSymbolSize() const {return _s2;}
|
quint8 maxSymbolSize() const {return _s2;}
|
||||||
quint32 symbol(quint32 data, quint8 &size) const;
|
quint32 symbol(quint32 data, quint8 &size) const;
|
||||||
|
|
||||||
|
quint8 id() const {return _id;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool getBuffer(const SubFile &file, SubFile::Handle &hdl, quint32 offset,
|
bool getBuffer(const SubFile &file, SubFile::Handle &hdl, quint32 offset,
|
||||||
quint32 size, quint8 id);
|
quint32 size, quint8 id);
|
||||||
@ -22,6 +24,8 @@ private:
|
|||||||
quint8 *_s10, *_s14, *_s18;
|
quint8 *_s10, *_s14, *_s18;
|
||||||
quint8 _s1c, _s1d, _s1e, _s1f, _s20;
|
quint8 _s1c, _s1d, _s1e, _s1f, _s20;
|
||||||
quint16 _s22;
|
quint16 _s22;
|
||||||
|
|
||||||
|
quint8 _id;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HUFFMANTABLE_H
|
#endif // HUFFMANTABLE_H
|
||||||
|
@ -59,7 +59,7 @@ IMG::IMG(const QString &fileName) : _file(fileName)
|
|||||||
|
|
||||||
QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2)));
|
QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2)));
|
||||||
_name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed();
|
_name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed();
|
||||||
_blockSize = 1 << (e1 + e2);
|
_blockBits = e1 + e2;
|
||||||
|
|
||||||
// Read the FAT table
|
// Read the FAT table
|
||||||
quint8 flag;
|
quint8 flag;
|
||||||
@ -132,7 +132,6 @@ IMG::IMG(const QString &fileName) : _file(fileName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create tile tree
|
// Create tile tree
|
||||||
|
|
||||||
int minMapZoom = 24;
|
int minMapZoom = 24;
|
||||||
for (TileMap::const_iterator it = tileMap.constBegin();
|
for (TileMap::const_iterator it = tileMap.constBegin();
|
||||||
it != tileMap.constEnd(); ++it) {
|
it != tileMap.constEnd(); ++it) {
|
||||||
@ -159,14 +158,19 @@ IMG::IMG(const QString &fileName) : _file(fileName)
|
|||||||
minMapZoom = tile->zooms().min();
|
minMapZoom = tile->zooms().min();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TileMap::const_iterator it = tileMap.constBegin();
|
// Detect and mark basemap
|
||||||
it != tileMap.constEnd(); ++it) {
|
TileTree::Iterator it;
|
||||||
VectorTile *tile = it.value();
|
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it)) {
|
||||||
|
VectorTile *tile = _tileTree.GetAt(it);
|
||||||
if (tile->zooms().min() > minMapZoom)
|
if (tile->zooms().min() > minMapZoom)
|
||||||
_baseMap = true;
|
_baseMap = true;
|
||||||
if (tile->zooms().min() == minMapZoom)
|
if (tile->zooms().min() == minMapZoom)
|
||||||
tile->markAsBasemap();
|
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())
|
if (!_tileTree.Count())
|
||||||
_errorString = "No usable map tile found";
|
_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)
|
bool IMG::readBlock(int blockNum, char *data)
|
||||||
{
|
{
|
||||||
if (!_file.seek((qint64)blockNum * (qint64)_blockSize))
|
if (!_file.seek((quint64)blockNum << _blockBits))
|
||||||
return false;
|
return false;
|
||||||
if (read(data, _blockSize) < _blockSize)
|
if (read(data, 1U<<_blockBits) < 1U<<_blockBits)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -14,14 +14,14 @@ public:
|
|||||||
private:
|
private:
|
||||||
friend class SubFile;
|
friend class SubFile;
|
||||||
|
|
||||||
int blockSize() const {return _blockSize;}
|
unsigned blockBits() const {return _blockBits;}
|
||||||
bool readBlock(int blockNum, char *data);
|
bool readBlock(int blockNum, char *data);
|
||||||
qint64 read(char *data, qint64 maxSize);
|
qint64 read(char *data, qint64 maxSize);
|
||||||
template<class T> bool readValue(T &val);
|
template<class T> bool readValue(T &val);
|
||||||
|
|
||||||
QFile _file;
|
QFile _file;
|
||||||
quint8 _key;
|
quint8 _key;
|
||||||
int _blockSize;
|
unsigned _blockBits;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IMG_H
|
#endif // IMG_H
|
||||||
|
@ -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)
|
_valid(false)
|
||||||
{
|
{
|
||||||
_polyCache.setMaxCost(CACHED_SUBDIVS_COUNT);
|
_polyCache.setMaxCost(CACHED_SUBDIVS_COUNT);
|
||||||
|
@ -1,26 +1,508 @@
|
|||||||
|
#include "bitstream.h"
|
||||||
|
#include "huffmanstream.h"
|
||||||
|
#include "subdiv.h"
|
||||||
|
#include "nodfile.h"
|
||||||
|
#include "lblfile.h"
|
||||||
#include "netfile.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, b, labelPtr = 0;
|
||||||
|
if (!bs.read(8, flags))
|
||||||
|
return false;
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (!bs.read(8, b))
|
||||||
|
return false;
|
||||||
|
labelPtr |= (b << (i * 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lbl && (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)
|
bool NETFile::init(Handle &hdl)
|
||||||
{
|
{
|
||||||
quint8 multiplier;
|
|
||||||
quint16 hdrLen;
|
quint16 hdrLen;
|
||||||
|
|
||||||
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
|
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
|
||||||
&& seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
|
&& seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
|
||||||
&& readUInt32(hdl, _size) && readUInt8(hdl, multiplier)))
|
&& readUInt32(hdl, _size) && readUInt8(hdl, _shift)))
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
linkLabel(hdl, linkOffset, _linksSize - (linkOffset - _linksOffset), lbl,
|
||||||
|
lblHdl, poly.label);
|
||||||
|
|
||||||
|
lines->append(poly);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NETFile::lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset)
|
bool NETFile::lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset)
|
||||||
{
|
{
|
||||||
if (!_multiplier && !init(hdl))
|
if (!_init && !init(hdl))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!(seek(hdl, _offset + netOffset * _multiplier)
|
if (!(seek(hdl, _offset + (netOffset << _shift))
|
||||||
&& readUInt24(hdl, lblOffset)))
|
&& readUInt24(hdl, lblOffset)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1,25 +1,42 @@
|
|||||||
#ifndef NETFILE_H
|
#ifndef NETFILE_H
|
||||||
#define NETFILE_H
|
#define NETFILE_H
|
||||||
|
|
||||||
|
#include "img.h"
|
||||||
#include "subfile.h"
|
#include "subfile.h"
|
||||||
|
#include "nodfile.h"
|
||||||
|
|
||||||
|
class NODFile;
|
||||||
|
class LBLFile;
|
||||||
|
class SubDiv;
|
||||||
|
class HuffmanTable;
|
||||||
|
|
||||||
class NETFile : public SubFile
|
class NETFile : public SubFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NETFile(IMG *img)
|
NETFile(IMG *img) : SubFile(img), _offset(0), _size(0), _linksOffset(0),
|
||||||
: SubFile(img), _offset(0), _size(0), _multiplier(0) {}
|
_linksSize(0), _shift(0), _linksShift(0), _init(false) {}
|
||||||
NETFile(const QString &path)
|
NETFile(const QString &path) : SubFile(path), _offset(0), _size(0),
|
||||||
: SubFile(path), _offset(0), _size(0), _multiplier(0) {}
|
_linksOffset(0), _linksSize(0), _shift(0), _linksShift(0),
|
||||||
NETFile(SubFile *gmp, quint32 offset)
|
_init(false) {}
|
||||||
: SubFile(gmp, offset), _offset(0), _size(0), _multiplier(0) {}
|
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 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:
|
private:
|
||||||
bool init(Handle &hdl);
|
bool init(Handle &hdl);
|
||||||
|
bool linkLabel(Handle &hdl, quint32 offset, quint32 size, LBLFile *lbl,
|
||||||
|
Handle &lblHdl, Label &label);
|
||||||
|
|
||||||
quint32 _offset, _size;
|
quint32 _offset, _size, _linksOffset, _linksSize;
|
||||||
quint8 _multiplier;
|
quint8 _shift, _linksShift;
|
||||||
|
quint8 _tableId;
|
||||||
|
bool _init;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NETFILE_H
|
#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
|
@ -1,13 +1,15 @@
|
|||||||
#include <cstring>
|
|
||||||
#include "common/rectc.h"
|
#include "common/rectc.h"
|
||||||
#include "common/garmin.h"
|
#include "common/garmin.h"
|
||||||
#include "deltastream.h"
|
#include "deltastream.h"
|
||||||
#include "huffmanstream.h"
|
#include "huffmanstream.h"
|
||||||
#include "lblfile.h"
|
#include "lblfile.h"
|
||||||
#include "netfile.h"
|
#include "netfile.h"
|
||||||
|
#include "nodfile.h"
|
||||||
#include "rgnfile.h"
|
#include "rgnfile.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define MASK(bits) ((2U << ((bits) - 1U)) - 1U)
|
||||||
|
|
||||||
static quint64 pointId(const QPoint &pos, quint32 type, quint32 labelPtr)
|
static quint64 pointId(const QPoint &pos, quint32 type, quint32 labelPtr)
|
||||||
{
|
{
|
||||||
quint64 id;
|
quint64 id;
|
||||||
@ -49,11 +51,10 @@ bool RGNFile::skipClassFields(Handle &hdl) const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return seek(hdl, hdl.pos() + rs);
|
return seek(hdl, pos(hdl) + rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3],
|
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3]) const
|
||||||
SegmentType type) const
|
|
||||||
{
|
{
|
||||||
quint32 bitfield = 0xFFFFFFFF;
|
quint32 bitfield = 0xFFFFFFFF;
|
||||||
|
|
||||||
@ -61,34 +62,38 @@ bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3],
|
|||||||
if (!readVBitfield32(hdl, bitfield))
|
if (!readVBitfield32(hdl, bitfield))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int i = 0; i < 29; i++) {
|
for (int i = 0, j = 0; i < 29; i++) {
|
||||||
if ((flags[0] >> i) & 1) {
|
if ((flags[0] >> i) & 1) {
|
||||||
if (bitfield & 1) {
|
if (bitfield & 1) {
|
||||||
quint32 m = flags[(i >> 4) + 1] >> ((i * 2) & 0x1e) & 3;
|
quint32 m = flags[(j >> 4) + 1] >> ((j * 2) & 0x1e) & 3;
|
||||||
switch (i) {
|
|
||||||
case 5:
|
quint32 skip = 0;
|
||||||
if (m == 1 && type == Point) {
|
if (m == 3) {
|
||||||
quint16 u16;
|
if (!readVUInt32(hdl, skip))
|
||||||
if (!readUInt16(hdl, u16))
|
return false;
|
||||||
return false;
|
} else
|
||||||
}
|
skip = m + 1;
|
||||||
break;
|
if (!seek(hdl, pos(hdl) + skip))
|
||||||
default:
|
return false;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
bitfield >>= 1;
|
bitfield >>= 1;
|
||||||
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RGNFile::clearFlags()
|
bool RGNFile::skipGblFields(Handle &hdl, quint32 flags) const
|
||||||
{
|
{
|
||||||
memset(_polygonsFlags, 0, sizeof(_polygonsFlags));
|
int cnt = 0;
|
||||||
memset(_linesFlags, 0, sizeof(_linesFlags));
|
|
||||||
memset(_pointsFlags, 0, sizeof(_pointsFlags));
|
do {
|
||||||
|
cnt = cnt + (flags & 3);
|
||||||
|
flags = flags >> 2;
|
||||||
|
} while (flags != 0);
|
||||||
|
|
||||||
|
return seek(hdl, pos(hdl) + cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RGNFile::init(Handle &hdl)
|
bool RGNFile::init(Handle &hdl)
|
||||||
@ -102,14 +107,20 @@ bool RGNFile::init(Handle &hdl)
|
|||||||
|
|
||||||
if (hdrLen >= 0x68) {
|
if (hdrLen >= 0x68) {
|
||||||
if (!(readUInt32(hdl, _polygonsOffset) && readUInt32(hdl, _polygonsSize)
|
if (!(readUInt32(hdl, _polygonsOffset) && readUInt32(hdl, _polygonsSize)
|
||||||
&& seek(hdl, _gmpOffset + 0x2D) && readUInt32(hdl, _polygonsFlags[0])
|
&& seek(hdl, _gmpOffset + 0x29) && readUInt32(hdl, _polygonsGblFlags)
|
||||||
&& readUInt32(hdl, _polygonsFlags[1]) && readUInt32(hdl, _polygonsFlags[2])
|
&& readUInt32(hdl, _polygonsLclFlags[0])
|
||||||
|
&& readUInt32(hdl, _polygonsLclFlags[1])
|
||||||
|
&& readUInt32(hdl, _polygonsLclFlags[2])
|
||||||
&& readUInt32(hdl, _linesOffset) && readUInt32(hdl, _linesSize)
|
&& readUInt32(hdl, _linesOffset) && readUInt32(hdl, _linesSize)
|
||||||
&& seek(hdl, _gmpOffset + 0x49) && readUInt32(hdl, _linesFlags[0])
|
&& seek(hdl, _gmpOffset + 0x45) && readUInt32(hdl, _linesGblFlags)
|
||||||
&& readUInt32(hdl, _linesFlags[1]) && readUInt32(hdl, _linesFlags[2])
|
&& readUInt32(hdl, _linesLclFlags[0])
|
||||||
|
&& readUInt32(hdl, _linesLclFlags[1])
|
||||||
|
&& readUInt32(hdl, _linesLclFlags[2])
|
||||||
&& readUInt32(hdl, _pointsOffset) && readUInt32(hdl, _pointsSize)
|
&& readUInt32(hdl, _pointsOffset) && readUInt32(hdl, _pointsSize)
|
||||||
&& seek(hdl, _gmpOffset + 0x65) && readUInt32(hdl, _pointsFlags[0])
|
&& seek(hdl, _gmpOffset + 0x61) && readUInt32(hdl, _pointsGblFlags)
|
||||||
&& readUInt32(hdl, _pointsFlags[1]) && readUInt32(hdl, _pointsFlags[2])))
|
&& readUInt32(hdl, _pointsLclFlags[0])
|
||||||
|
&& readUInt32(hdl, _pointsLclFlags[1])
|
||||||
|
&& readUInt32(hdl, _pointsLclFlags[2])))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +158,7 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
|
|||||||
qint16 lon, lat;
|
qint16 lon, lat;
|
||||||
quint16 len;
|
quint16 len;
|
||||||
|
|
||||||
while (hdl.pos() < (int)segment.end()) {
|
while (pos(hdl) < segment.end()) {
|
||||||
IMG::Poly poly;
|
IMG::Poly poly;
|
||||||
|
|
||||||
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
|
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()))
|
if (!seek(hdl, segment.offset()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (hdl.pos() < (int)segment.end()) {
|
while (pos(hdl) < segment.end()) {
|
||||||
IMG::Poly poly;
|
IMG::Poly poly;
|
||||||
QPoint pos;
|
QPoint pos;
|
||||||
|
|
||||||
@ -230,6 +241,7 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
|||||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)
|
&& readInt16(hdl, lon) && readInt16(hdl, lat)
|
||||||
&& readVUInt32(hdl, len)))
|
&& readVUInt32(hdl, len)))
|
||||||
return false;
|
return false;
|
||||||
|
Q_ASSERT(SubFile::pos(hdl) + len <= segment.end());
|
||||||
|
|
||||||
poly.type = 0x10000 | (quint16(type)<<8) | (subtype & 0x1F);
|
poly.type = 0x10000 | (quint16(type)<<8) | (subtype & 0x1F);
|
||||||
labelPtr = 0;
|
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())));
|
LS(subdiv->lat(), 8) + LS(lat, (32-subdiv->bits())));
|
||||||
|
|
||||||
qint32 lonDelta, latDelta;
|
qint32 lonDelta, latDelta;
|
||||||
HuffmanStream stream(*this, hdl, len, _huffmanTable,
|
BitStream4F bs(*this, hdl, len);
|
||||||
segmentType == Line);
|
HuffmanStreamF stream(bs, _huffmanTable);
|
||||||
|
if (!stream.init(segmentType == Line))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (shift) {
|
if (shift) {
|
||||||
if (!stream.readOffset(lonDelta, latDelta))
|
if (!stream.readOffset(lonDelta, latDelta))
|
||||||
@ -298,7 +312,11 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
|||||||
if (subtype & 0x80 && !skipClassFields(hdl))
|
if (subtype & 0x80 && !skipClassFields(hdl))
|
||||||
return false;
|
return false;
|
||||||
if (subtype & 0x40 && !skipLclFields(hdl, segmentType == Line
|
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;
|
return false;
|
||||||
|
|
||||||
if (lbl && (labelPtr & 0x3FFFFF))
|
if (lbl && (labelPtr & 0x3FFFFF))
|
||||||
@ -317,12 +335,13 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
|
|||||||
const SubDiv::Segment &segment = (segmentType == IndexedPoint)
|
const SubDiv::Segment &segment = (segmentType == IndexedPoint)
|
||||||
? subdiv->idxPoints() : subdiv->points();
|
? subdiv->idxPoints() : subdiv->points();
|
||||||
|
|
||||||
|
|
||||||
if (!segment.isValid())
|
if (!segment.isValid())
|
||||||
return true;
|
return true;
|
||||||
if (!seek(hdl, segment.offset()))
|
if (!seek(hdl, segment.offset()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (hdl.pos() < (int)segment.end()) {
|
while (pos(hdl) < segment.end()) {
|
||||||
IMG::Point point;
|
IMG::Point point;
|
||||||
quint8 type, subtype;
|
quint8 type, subtype;
|
||||||
qint16 lon, lat;
|
qint16 lon, lat;
|
||||||
@ -365,7 +384,7 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
|||||||
if (!seek(hdl, segment.offset()))
|
if (!seek(hdl, segment.offset()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (hdl.pos() < (int)segment.end()) {
|
while (pos(hdl) < segment.end()) {
|
||||||
IMG::Point point;
|
IMG::Point point;
|
||||||
qint16 lon, lat;
|
qint16 lon, lat;
|
||||||
quint8 type, subtype;
|
quint8 type, subtype;
|
||||||
@ -379,7 +398,9 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
|||||||
return false;
|
return false;
|
||||||
if (subtype & 0x80 && !skipClassFields(hdl))
|
if (subtype & 0x80 && !skipClassFields(hdl))
|
||||||
return false;
|
return false;
|
||||||
if (subtype & 0x40 && !skipLclFields(hdl, _pointsFlags, Point))
|
if (subtype & 0x40 && !skipLclFields(hdl, _pointsLclFlags))
|
||||||
|
return false;
|
||||||
|
if (_pointsGblFlags && !skipGblFields(hdl, _pointsGblFlags))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
||||||
@ -403,6 +424,87 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
|||||||
return true;
|
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,
|
QMap<RGNFile::SegmentType, SubDiv::Segment> RGNFile::segments(Handle &hdl,
|
||||||
SubDiv *subdiv) const
|
SubDiv *subdiv) const
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
class LBLFile;
|
class LBLFile;
|
||||||
class NETFile;
|
class NETFile;
|
||||||
|
class NODFile;
|
||||||
|
|
||||||
class RGNFile : public SubFile
|
class RGNFile : public SubFile
|
||||||
{
|
{
|
||||||
@ -23,15 +24,14 @@ public:
|
|||||||
RGNFile(IMG *img)
|
RGNFile(IMG *img)
|
||||||
: SubFile(img), _offset(0), _size(0), _polygonsOffset(0),
|
: SubFile(img), _offset(0), _size(0), _polygonsOffset(0),
|
||||||
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
|
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
|
||||||
_pointsSize(0), _init(false) {clearFlags();}
|
_pointsSize(0), _init(false) {}
|
||||||
RGNFile(const QString &path)
|
RGNFile(const QString &path)
|
||||||
: SubFile(path), _offset(0), _size(0), _polygonsOffset(0),
|
: SubFile(path), _offset(0), _size(0), _polygonsOffset(0),
|
||||||
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(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),
|
RGNFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), _offset(0),
|
||||||
_size(0), _polygonsOffset(0), _polygonsSize(0), _linesOffset(0),
|
_size(0), _polygonsOffset(0), _polygonsSize(0), _linesOffset(0),
|
||||||
_linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false)
|
_linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false) {}
|
||||||
{clearFlags();}
|
|
||||||
|
|
||||||
bool initialized() const {return _init;}
|
bool initialized() const {return _init;}
|
||||||
bool init(Handle &hdl);
|
bool init(Handle &hdl);
|
||||||
@ -46,29 +46,35 @@ public:
|
|||||||
QList<IMG::Poly> *polys) const;
|
QList<IMG::Poly> *polys) const;
|
||||||
bool extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
bool extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
||||||
Handle &lblHdl, QList<IMG::Point> *points) const;
|
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;
|
bool subdivInit(Handle &hdl, SubDiv *subdiv) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMap<SegmentType, SubDiv::Segment> segments(Handle &hdl, SubDiv *subdiv)
|
QMap<SegmentType, SubDiv::Segment> segments(Handle &hdl, SubDiv *subdiv)
|
||||||
const;
|
const;
|
||||||
void clearFlags();
|
|
||||||
bool skipClassFields(Handle &hdl) const;
|
bool skipClassFields(Handle &hdl) const;
|
||||||
bool skipLclFields(Handle &hdl, const quint32 flags[3], SegmentType type)
|
bool skipLclFields(Handle &hdl, const quint32 flags[3])
|
||||||
const;
|
const;
|
||||||
|
bool skipGblFields(Handle &hdl, quint32 flags) const;
|
||||||
|
|
||||||
quint32 _offset;
|
quint32 _offset;
|
||||||
quint32 _size;
|
quint32 _size;
|
||||||
|
|
||||||
quint32 _polygonsOffset;
|
quint32 _polygonsOffset;
|
||||||
quint32 _polygonsSize;
|
quint32 _polygonsSize;
|
||||||
quint32 _polygonsFlags[3];
|
quint32 _polygonsLclFlags[3];
|
||||||
|
quint32 _polygonsGblFlags;
|
||||||
quint32 _linesOffset;
|
quint32 _linesOffset;
|
||||||
quint32 _linesSize;
|
quint32 _linesSize;
|
||||||
quint32 _linesFlags[3];
|
quint32 _linesLclFlags[3];
|
||||||
|
quint32 _linesGblFlags;
|
||||||
quint32 _pointsOffset;
|
quint32 _pointsOffset;
|
||||||
quint32 _pointsSize;
|
quint32 _pointsSize;
|
||||||
quint32 _pointsFlags[3];
|
quint32 _pointsLclFlags[3];
|
||||||
|
quint32 _pointsGblFlags;
|
||||||
|
|
||||||
HuffmanTable _huffmanTable;
|
HuffmanTable _huffmanTable;
|
||||||
|
|
||||||
|
@ -359,7 +359,7 @@ static bool skipLocalization(SubFile *file, SubFile::Handle &hdl)
|
|||||||
len = len >> 2;
|
len = len >> 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file->seek(hdl, hdl.pos() + len))
|
if (!file->seek(hdl, file->pos(hdl) + len))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -21,8 +21,9 @@ public:
|
|||||||
quint32 _offset, _end;
|
quint32 _offset, _end;
|
||||||
};
|
};
|
||||||
|
|
||||||
SubDiv(quint32 offset, qint32 lon, qint32 lat, int bits, quint8 objects)
|
SubDiv(quint32 offset, qint32 lon, qint32 lat, quint8 level, quint8 bits,
|
||||||
: _lon(lon), _lat(lat), _bits(bits), _init(false)
|
quint8 objects) : _lon(lon), _lat(lat), _level(level), _bits(bits),
|
||||||
|
_init(false)
|
||||||
{
|
{
|
||||||
_tre.objects = objects;
|
_tre.objects = objects;
|
||||||
_tre.offset = offset;
|
_tre.offset = offset;
|
||||||
@ -78,6 +79,7 @@ public:
|
|||||||
qint32 lon() const {return _lon;}
|
qint32 lon() const {return _lon;}
|
||||||
qint32 lat() const {return _lat;}
|
qint32 lat() const {return _lat;}
|
||||||
quint8 bits() const {return _bits;}
|
quint8 bits() const {return _bits;}
|
||||||
|
quint8 level() const {return _level;}
|
||||||
|
|
||||||
// Valid only after initialization
|
// Valid only after initialization
|
||||||
Segment points() const
|
Segment points() const
|
||||||
@ -94,6 +96,8 @@ public:
|
|||||||
{return Segment(_rgn.extLinesOffset, _rgn.extLinesEnd);}
|
{return Segment(_rgn.extLinesOffset, _rgn.extLinesEnd);}
|
||||||
Segment extPolygons() const
|
Segment extPolygons() const
|
||||||
{return Segment(_rgn.extPolygonsOffset, _rgn.extPolygonsEnd);}
|
{return Segment(_rgn.extPolygonsOffset, _rgn.extPolygonsEnd);}
|
||||||
|
Segment roadReferences() const
|
||||||
|
{return Segment(_rgn.roadReferencesOffset, _rgn.roadReferencesEnd);}
|
||||||
|
|
||||||
// Valid only until initialization
|
// Valid only until initialization
|
||||||
quint8 objects() const {return _tre.objects;}
|
quint8 objects() const {return _tre.objects;}
|
||||||
@ -142,6 +146,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
qint32 _lon, _lat;
|
qint32 _lon, _lat;
|
||||||
|
quint8 _level;
|
||||||
quint8 _bits;
|
quint8 _bits;
|
||||||
bool _init;
|
bool _init;
|
||||||
union {
|
union {
|
||||||
|
@ -3,26 +3,28 @@
|
|||||||
#include "subfile.h"
|
#include "subfile.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define mod2n(x, m) ((x) & ((m) - 1));
|
||||||
|
|
||||||
bool SubFile::seek(Handle &handle, quint32 pos) const
|
bool SubFile::seek(Handle &handle, quint32 pos) const
|
||||||
{
|
{
|
||||||
if (handle._file) {
|
if (handle._file) {
|
||||||
int blockNum = pos / BLOCK_SIZE;
|
int blockNum = pos >> BLOCK_BITS;
|
||||||
|
|
||||||
if (handle._blockNum != blockNum) {
|
if (handle._blockNum != blockNum) {
|
||||||
if (!handle._file->seek((qint64)blockNum * BLOCK_SIZE))
|
if (!handle._file->seek((quint64)blockNum << BLOCK_BITS))
|
||||||
return false;
|
return false;
|
||||||
if (handle._file->read(handle._data.data(), BLOCK_SIZE) < 0)
|
if (handle._file->read(handle._data.data(), (1<<BLOCK_BITS)) < 0)
|
||||||
return false;
|
return false;
|
||||||
handle._blockNum = blockNum;
|
handle._blockNum = blockNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle._blockPos = pos % BLOCK_SIZE;
|
handle._blockPos = mod2n(pos, 1U<<BLOCK_BITS);
|
||||||
handle._pos = pos;
|
handle._pos = pos;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
quint32 blockSize = _img->blockSize();
|
quint32 blockBits = _img->blockBits();
|
||||||
int blockNum = pos / blockSize;
|
int blockNum = pos >> blockBits;
|
||||||
|
|
||||||
if (handle._blockNum != blockNum) {
|
if (handle._blockNum != blockNum) {
|
||||||
if (blockNum >= _blocks->size())
|
if (blockNum >= _blocks->size())
|
||||||
@ -32,7 +34,7 @@ bool SubFile::seek(Handle &handle, quint32 pos) const
|
|||||||
handle._blockNum = blockNum;
|
handle._blockNum = blockNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle._blockPos = pos % blockSize;
|
handle._blockPos = mod2n(pos, 1U<<blockBits);
|
||||||
handle._pos = pos;
|
handle._pos = pos;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -70,6 +72,22 @@ bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SubFile::readVUInt32(Handle &hdl, quint32 bytes, quint32 &val) const
|
||||||
|
{
|
||||||
|
switch (bytes) {
|
||||||
|
case 1:
|
||||||
|
return readUInt8(hdl, val);
|
||||||
|
case 2:
|
||||||
|
return readUInt16(hdl, val);
|
||||||
|
case 3:
|
||||||
|
return readUInt24(hdl, val);
|
||||||
|
case 4:
|
||||||
|
return readUInt32(hdl, val);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const
|
bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const
|
||||||
{
|
{
|
||||||
quint8 bits;
|
quint8 bits;
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
#include "img.h"
|
#include "img.h"
|
||||||
|
|
||||||
|
|
||||||
#define BLOCK_SIZE 4096
|
#define BLOCK_BITS 12 /* 4096 bytes */
|
||||||
|
|
||||||
class SubFile
|
class SubFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Type {Unknown, TRE, RGN, LBL, NET, TYP, GMP};
|
enum Type {Unknown, TRE, RGN, LBL, NET, NOD, TYP, GMP};
|
||||||
|
|
||||||
class Handle
|
class Handle
|
||||||
{
|
{
|
||||||
@ -22,14 +22,12 @@ public:
|
|||||||
if (subFile && subFile->_path) {
|
if (subFile && subFile->_path) {
|
||||||
_file = new QFile(*(subFile->_path));
|
_file = new QFile(*(subFile->_path));
|
||||||
_file->open(QIODevice::ReadOnly);
|
_file->open(QIODevice::ReadOnly);
|
||||||
_data.resize(BLOCK_SIZE);
|
_data.resize(1U<<BLOCK_BITS);
|
||||||
} else if (subFile)
|
} else if (subFile)
|
||||||
_data.resize(subFile->_img->blockSize());
|
_data.resize(1U<<subFile->_img->blockBits());
|
||||||
}
|
}
|
||||||
~Handle() {delete _file;}
|
~Handle() {delete _file;}
|
||||||
|
|
||||||
int pos() const {return _pos;}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class SubFile;
|
friend class SubFile;
|
||||||
|
|
||||||
@ -57,6 +55,7 @@ public:
|
|||||||
void addBlock(quint16 block) {_blocks->append(block);}
|
void addBlock(quint16 block) {_blocks->append(block);}
|
||||||
|
|
||||||
bool seek(Handle &handle, quint32 pos) const;
|
bool seek(Handle &handle, quint32 pos) const;
|
||||||
|
quint32 pos(Handle &handle) const {return handle._pos;}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool readUInt8(Handle &handle, T &val) const
|
bool readUInt8(Handle &handle, T &val) const
|
||||||
@ -132,6 +131,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool readVUInt32(Handle &hdl, quint32 &val) const;
|
bool readVUInt32(Handle &hdl, quint32 &val) const;
|
||||||
|
bool readVUInt32(Handle &hdl, quint32 bytes, quint32 &val) const;
|
||||||
bool readVBitfield32(Handle &hdl, quint32 &bitfield) const;
|
bool readVBitfield32(Handle &hdl, quint32 &bitfield) const;
|
||||||
|
|
||||||
QString fileName() const {return _path ? *_path : _img->fileName();}
|
QString fileName() const {return _path ? *_path : _img->fileName();}
|
||||||
@ -142,7 +142,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
bool readByte(Handle &handle, quint8 &val) const
|
bool readByte(Handle &handle, quint8 &val) const
|
||||||
{
|
{
|
||||||
int blockSize = _img ? _img->blockSize() : BLOCK_SIZE;
|
int blockSize = _img ? 1U<<_img->blockBits() : 1U<<BLOCK_BITS;
|
||||||
val = handle._data.at(handle._blockPos++);
|
val = handle._data.at(handle._blockPos++);
|
||||||
handle._pos++;
|
handle._pos++;
|
||||||
return (handle._blockPos >= blockSize)
|
return (handle._blockPos >= blockSize)
|
||||||
|
@ -70,14 +70,16 @@ bool TREFile::init()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (hdrLen > 0x9A) {
|
if (hdrLen > 0x9A) {
|
||||||
// TRE7 info
|
// TRE7 info + flags
|
||||||
if (!(seek(hdl, _gmpOffset + 0x7C) && readUInt32(hdl, _extended.offset)
|
if (!(seek(hdl, _gmpOffset + 0x7C) && readUInt32(hdl, _extended.offset)
|
||||||
&& readUInt32(hdl, _extended.size)
|
&& readUInt32(hdl, _extended.size)
|
||||||
&& readUInt16(hdl, _extended.itemSize)))
|
&& readUInt16(hdl, _extended.itemSize) && readUInt32(hdl, _flags)))
|
||||||
return false;
|
|
||||||
// flags
|
|
||||||
if (!(seek(hdl, _gmpOffset + 0x86) && readUInt32(hdl, _flags)))
|
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
_extended.offset = 0;
|
||||||
|
_extended.size = 0;
|
||||||
|
_extended.itemSize = 0;
|
||||||
|
_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tile levels
|
// Tile levels
|
||||||
@ -120,15 +122,43 @@ bool TREFile::init()
|
|||||||
return (_firstLevel >= 0);
|
return (_firstLevel >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TREFile::readExtEntry(Handle &hdl, quint32 &polygons, quint32 &lines,
|
||||||
|
quint32 &points)
|
||||||
|
{
|
||||||
|
int rb = 0;
|
||||||
|
|
||||||
|
if (_flags & 1) {
|
||||||
|
if (!readUInt32(hdl, polygons))
|
||||||
|
return -1;
|
||||||
|
rb += 4;
|
||||||
|
} else
|
||||||
|
polygons = 0;
|
||||||
|
if (_flags & 2) {
|
||||||
|
if (!readUInt32(hdl, lines))
|
||||||
|
return -1;
|
||||||
|
rb += 4;
|
||||||
|
} else
|
||||||
|
lines = 0;
|
||||||
|
if (_flags & 4) {
|
||||||
|
if (!readUInt32(hdl, points))
|
||||||
|
return -1;
|
||||||
|
rb += 4;
|
||||||
|
} else
|
||||||
|
points = 0;
|
||||||
|
|
||||||
|
return rb;
|
||||||
|
}
|
||||||
|
|
||||||
bool TREFile::load(int idx)
|
bool TREFile::load(int idx)
|
||||||
{
|
{
|
||||||
Handle hdl(this);
|
Handle hdl(this);
|
||||||
QList<SubDiv*> sl;
|
QList<SubDiv*> sl;
|
||||||
SubDiv *s = 0;
|
SubDiv *s = 0;
|
||||||
SubDivTree *tree = new SubDivTree();
|
SubDivTree *tree = new SubDivTree();
|
||||||
|
const MapLevel &level = _levels.at(idx);
|
||||||
|
|
||||||
|
|
||||||
_subdivs.insert(_levels.at(idx).bits, tree);
|
_subdivs.insert(level.bits, tree);
|
||||||
|
|
||||||
quint32 skip = 0;
|
quint32 skip = 0;
|
||||||
for (int i = 0; i < idx; i++)
|
for (int i = 0; i < idx; i++)
|
||||||
@ -137,7 +167,7 @@ bool TREFile::load(int idx)
|
|||||||
if (!seek(hdl, _subdivOffset + skip * 16))
|
if (!seek(hdl, _subdivOffset + skip * 16))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int j = 0; j < _levels.at(idx).subdivs; j++) {
|
for (int j = 0; j < level.subdivs; j++) {
|
||||||
quint32 oo;
|
quint32 oo;
|
||||||
qint32 lon, lat, width, height;
|
qint32 lon, lat, width, height;
|
||||||
quint16 nextLevel;
|
quint16 nextLevel;
|
||||||
@ -156,10 +186,10 @@ bool TREFile::load(int idx)
|
|||||||
s->setEnd(offset);
|
s->setEnd(offset);
|
||||||
|
|
||||||
width &= 0x7FFF;
|
width &= 0x7FFF;
|
||||||
width = LS(width, 24 - _levels.at(idx).bits);
|
width = LS(width, 24 - level.bits);
|
||||||
height = LS(height, 24 - _levels.at(idx).bits);
|
height = LS(height, 24 - level.bits);
|
||||||
|
|
||||||
s = new SubDiv(offset, lon, lat, _levels.at(idx).bits, objects);
|
s = new SubDiv(offset, lon, lat, level.level, level.bits, objects);
|
||||||
sl.append(s);
|
sl.append(s);
|
||||||
|
|
||||||
double min[2], max[2];
|
double min[2], max[2];
|
||||||
@ -184,36 +214,31 @@ bool TREFile::load(int idx)
|
|||||||
|
|
||||||
|
|
||||||
// Objects with extended types (TRE7)
|
// Objects with extended types (TRE7)
|
||||||
if (_extended.size && _extended.itemSize >= 12) {
|
if (_extended.size && _extended.itemSize) {
|
||||||
/* Some maps skip entries for the inherited levels, some don't. Our
|
|
||||||
decision is based on the difference between the extended subdivs
|
|
||||||
count and the total subdivs count. */
|
|
||||||
quint32 totalSubdivs = 0;
|
quint32 totalSubdivs = 0;
|
||||||
for (int i = 0; i < _levels.size(); i++)
|
for (int i = 0; i < _levels.size(); i++)
|
||||||
totalSubdivs += _levels.at(i).subdivs;
|
totalSubdivs += _levels.at(i).subdivs;
|
||||||
quint32 extendedSubdivs = _extended.size / _extended.itemSize;
|
quint32 extendedSubdivs = _extended.size / _extended.itemSize;
|
||||||
quint32 diff = totalSubdivs - extendedSubdivs + 1;
|
quint32 diff = totalSubdivs - extendedSubdivs + 1;
|
||||||
|
|
||||||
quint32 polygons, lines, points;
|
|
||||||
if (!seek(hdl, _extended.offset + (skip - diff) * _extended.itemSize))
|
if (!seek(hdl, _extended.offset + (skip - diff) * _extended.itemSize))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
quint32 polygons, lines, points;
|
||||||
|
int rb;
|
||||||
for (int i = 0; i < sl.size(); i++) {
|
for (int i = 0; i < sl.size(); i++) {
|
||||||
if (!(readUInt32(hdl, polygons) && readUInt32(hdl, lines)
|
if ((rb = readExtEntry(hdl, polygons, lines, points)) < 0)
|
||||||
&& readUInt32(hdl, points)))
|
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
sl.at(i)->setExtOffsets(polygons, lines, points);
|
sl.at(i)->setExtOffsets(polygons, lines, points);
|
||||||
if (i)
|
if (i)
|
||||||
sl.at(i-1)->setExtEnds(polygons, lines, points);
|
sl.at(i-1)->setExtEnds(polygons, lines, points);
|
||||||
|
|
||||||
if (!seek(hdl, hdl.pos() + _extended.itemSize - 12))
|
if (!seek(hdl, pos(hdl) + _extended.itemSize - rb))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx != _levels.size() - 1) {
|
if (idx != _levels.size() - 1) {
|
||||||
if (!(readUInt32(hdl, polygons) && readUInt32(hdl, lines)
|
if (readExtEntry(hdl, polygons, lines, points) < 0)
|
||||||
&& readUInt32(hdl, points)))
|
|
||||||
goto error;
|
goto error;
|
||||||
sl.last()->setExtEnds(polygons, lines, points);
|
sl.last()->setExtEnds(polygons, lines, points);
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,8 @@ private:
|
|||||||
|
|
||||||
bool load(int idx);
|
bool load(int idx);
|
||||||
int level(int bits, bool baseMap);
|
int level(int bits, bool baseMap);
|
||||||
bool parsePoly(Handle hdl, quint32 pos, const QMap<int, int> &level2bits,
|
int readExtEntry(Handle &hdl, quint32 &polygons, quint32 &lines,
|
||||||
QMap<quint32, int> &map);
|
quint32 &points);
|
||||||
bool parsePoints(Handle hdl, quint32 pos, const QMap<int, int> &level2bits);
|
|
||||||
|
|
||||||
friend QDebug operator<<(QDebug dbg, const MapLevel &level);
|
friend QDebug operator<<(QDebug dbg, const MapLevel &level);
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ SubFile *VectorTile::file(SubFile::Type type)
|
|||||||
return _lbl;
|
return _lbl;
|
||||||
case SubFile::NET:
|
case SubFile::NET:
|
||||||
return _net;
|
return _net;
|
||||||
|
case SubFile::NOD:
|
||||||
|
return _nod;
|
||||||
case SubFile::GMP:
|
case SubFile::GMP:
|
||||||
return _gmp;
|
return _gmp;
|
||||||
default:
|
default:
|
||||||
@ -51,6 +53,9 @@ SubFile *VectorTile::addFile(IMG *img, SubFile::Type type)
|
|||||||
case SubFile::NET:
|
case SubFile::NET:
|
||||||
_net = new NETFile(img);
|
_net = new NETFile(img);
|
||||||
return _net;
|
return _net;
|
||||||
|
case SubFile::NOD:
|
||||||
|
_nod = new NODFile(img);
|
||||||
|
return _nod;
|
||||||
case SubFile::GMP:
|
case SubFile::GMP:
|
||||||
_gmp = new SubFile(img);
|
_gmp = new SubFile(img);
|
||||||
return _gmp;
|
return _gmp;
|
||||||
@ -74,6 +79,9 @@ SubFile *VectorTile::addFile(const QString &path, SubFile::Type type)
|
|||||||
case SubFile::NET:
|
case SubFile::NET:
|
||||||
_net = new NETFile(path);
|
_net = new NETFile(path);
|
||||||
return _net;
|
return _net;
|
||||||
|
case SubFile::NOD:
|
||||||
|
_nod = new NODFile(path);
|
||||||
|
return _nod;
|
||||||
case SubFile::GMP:
|
case SubFile::GMP:
|
||||||
_gmp = new SubFile(path);
|
_gmp = new SubFile(path);
|
||||||
return _gmp;
|
return _gmp;
|
||||||
@ -96,17 +104,18 @@ bool VectorTile::init()
|
|||||||
bool VectorTile::initGMP()
|
bool VectorTile::initGMP()
|
||||||
{
|
{
|
||||||
SubFile::Handle hdl(_gmp);
|
SubFile::Handle hdl(_gmp);
|
||||||
quint32 tre, rgn, lbl, net;
|
quint32 tre, rgn, lbl, net, nod;
|
||||||
|
|
||||||
if (!(_gmp->seek(hdl, 0x19) && _gmp->readUInt32(hdl, tre)
|
if (!(_gmp->seek(hdl, 0x19) && _gmp->readUInt32(hdl, tre)
|
||||||
&& _gmp->readUInt32(hdl, rgn) && _gmp->readUInt32(hdl, lbl)
|
&& _gmp->readUInt32(hdl, rgn) && _gmp->readUInt32(hdl, lbl)
|
||||||
&& _gmp->readUInt32(hdl, net)))
|
&& _gmp->readUInt32(hdl, net) && _gmp->readUInt32(hdl, nod)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_tre = tre ? new TREFile(_gmp, tre) : 0;
|
_tre = tre ? new TREFile(_gmp, tre) : 0;
|
||||||
_rgn = rgn ? new RGNFile(_gmp, rgn) : 0;
|
_rgn = rgn ? new RGNFile(_gmp, rgn) : 0;
|
||||||
_lbl = lbl ? new LBLFile(_gmp, lbl) : 0;
|
_lbl = lbl ? new LBLFile(_gmp, lbl) : 0;
|
||||||
_net = net ? new NETFile(_gmp, net) : 0;
|
_net = net ? new NETFile(_gmp, net) : 0;
|
||||||
|
_nod = nod ? new NODFile(_gmp, nod) : 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -115,7 +124,7 @@ void VectorTile::polys(const RectC &rect, int bits, bool baseMap,
|
|||||||
QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
||||||
QCache<const SubDiv *, IMG::Polys> *polyCache) const
|
QCache<const SubDiv *, IMG::Polys> *polyCache) const
|
||||||
{
|
{
|
||||||
SubFile::Handle rgnHdl(_rgn), lblHdl(_lbl), netHdl(_net);
|
SubFile::Handle rgnHdl(_rgn), lblHdl(_lbl), netHdl(_net), nodHdl(_nod);
|
||||||
|
|
||||||
if (!_rgn->initialized() && !_rgn->init(rgnHdl))
|
if (!_rgn->initialized() && !_rgn->init(rgnHdl))
|
||||||
return;
|
return;
|
||||||
@ -140,6 +149,8 @@ void VectorTile::polys(const RectC &rect, int bits, bool baseMap,
|
|||||||
lblHdl, &p);
|
lblHdl, &p);
|
||||||
_rgn->extPolyObjects(rgnHdl, subdiv, shift, RGNFile::Line, _lbl,
|
_rgn->extPolyObjects(rgnHdl, subdiv, shift, RGNFile::Line, _lbl,
|
||||||
lblHdl, &l);
|
lblHdl, &l);
|
||||||
|
_rgn->links(rgnHdl, subdiv, shift, _net, netHdl, _nod, nodHdl, _lbl,
|
||||||
|
lblHdl, &l);
|
||||||
|
|
||||||
copyPolys(rect, &p, polygons);
|
copyPolys(rect, &p, polygons);
|
||||||
copyPolys(rect, &l, lines);
|
copyPolys(rect, &l, lines);
|
||||||
|
@ -6,13 +6,15 @@
|
|||||||
#include "rgnfile.h"
|
#include "rgnfile.h"
|
||||||
#include "lblfile.h"
|
#include "lblfile.h"
|
||||||
#include "netfile.h"
|
#include "netfile.h"
|
||||||
|
#include "nodfile.h"
|
||||||
|
|
||||||
class VectorTile {
|
class VectorTile {
|
||||||
public:
|
public:
|
||||||
VectorTile() : _tre(0), _rgn(0), _lbl(0), _net(0), _gmp(0) {}
|
VectorTile() : _tre(0), _rgn(0), _lbl(0), _net(0), _nod(0), _gmp(0) {}
|
||||||
~VectorTile()
|
~VectorTile()
|
||||||
{
|
{
|
||||||
delete _tre; delete _rgn; delete _lbl; delete _net; delete _gmp;
|
delete _tre; delete _rgn; delete _lbl; delete _net; delete _nod;
|
||||||
|
delete _gmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool init();
|
bool init();
|
||||||
@ -37,7 +39,7 @@ public:
|
|||||||
{
|
{
|
||||||
return (type == SubFile::TRE || type == SubFile::LBL
|
return (type == SubFile::TRE || type == SubFile::LBL
|
||||||
|| type == SubFile::RGN || type == SubFile::NET
|
|| type == SubFile::RGN || type == SubFile::NET
|
||||||
|| type == SubFile::GMP);
|
|| type == SubFile::NOD || type == SubFile::GMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -47,6 +49,7 @@ private:
|
|||||||
RGNFile *_rgn;
|
RGNFile *_rgn;
|
||||||
LBLFile *_lbl;
|
LBLFile *_lbl;
|
||||||
NETFile *_net;
|
NETFile *_net;
|
||||||
|
NODFile *_nod;
|
||||||
SubFile *_gmp;
|
SubFile *_gmp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -167,11 +167,6 @@ void IMGMap::ll2xy(QList<MapData::Point> &points)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render(RasterTile &tile)
|
|
||||||
{
|
|
||||||
tile.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||||
{
|
{
|
||||||
Q_UNUSED(flags);
|
Q_UNUSED(flags);
|
||||||
@ -224,7 +219,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QFuture<void> future = QtConcurrent::map(tiles, render);
|
QFuture<void> future = QtConcurrent::map(tiles, &RasterTile::render);
|
||||||
future.waitForFinished();
|
future.waitForFinished();
|
||||||
|
|
||||||
for (int i = 0; i < tiles.size(); i++) {
|
for (int i = 0; i < tiles.size(); i++) {
|
||||||
|
@ -49,11 +49,6 @@ private:
|
|||||||
|
|
||||||
#define META_TYPE(type) static_cast<QMetaType::Type>(type)
|
#define META_TYPE(type) static_cast<QMetaType::Type>(type)
|
||||||
|
|
||||||
static void render(MBTile &tile)
|
|
||||||
{
|
|
||||||
tile.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
static double index2mercator(int index, int zoom)
|
static double index2mercator(int index, int zoom)
|
||||||
{
|
{
|
||||||
return rad2deg(-M_PI + 2 * M_PI * ((double)index / (1<<zoom)));
|
return rad2deg(-M_PI + 2 * M_PI * ((double)index / (1<<zoom)));
|
||||||
@ -314,7 +309,7 @@ void MBTilesMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QFuture<void> future = QtConcurrent::map(tiles, render);
|
QFuture<void> future = QtConcurrent::map(tiles, &MBTile::load);
|
||||||
future.waitForFinished();
|
future.waitForFinished();
|
||||||
|
|
||||||
for (int i = 0; i < tiles.size(); i++) {
|
for (int i = 0; i < tiles.size(); i++) {
|
||||||
|
@ -41,11 +41,6 @@ private:
|
|||||||
QImage _image;
|
QImage _image;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void render(TileImage &ti)
|
|
||||||
{
|
|
||||||
ti.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString quadKey(const QPoint &xy, int zoom)
|
static QString quadKey(const QPoint &xy, int zoom)
|
||||||
{
|
{
|
||||||
QString qk;
|
QString qk;
|
||||||
@ -101,7 +96,7 @@ void TileLoader::loadTilesAsync(QVector<Tile> &list)
|
|||||||
if (!dl.empty())
|
if (!dl.empty())
|
||||||
_downloader->get(dl, _authorization);
|
_downloader->get(dl, _authorization);
|
||||||
|
|
||||||
QFuture<void> future = QtConcurrent::map(imgs, render);
|
QFuture<void> future = QtConcurrent::map(imgs, &TileImage::load);
|
||||||
future.waitForFinished();
|
future.waitForFinished();
|
||||||
|
|
||||||
for (int i = 0; i < imgs.size(); i++) {
|
for (int i = 0; i < imgs.size(); i++) {
|
||||||
@ -153,7 +148,7 @@ void TileLoader::loadTilesSync(QVector<Tile> &list)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QFuture<void> future = QtConcurrent::map(imgs, render);
|
QFuture<void> future = QtConcurrent::map(imgs, &TileImage::load);
|
||||||
future.waitForFinished();
|
future.waitForFinished();
|
||||||
|
|
||||||
for (int i = 0; i < imgs.size(); i++)
|
for (int i = 0; i < imgs.size(); i++)
|
||||||
|