mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-07-09 00:34:27 +02:00
Compare commits
140 Commits
Author | SHA1 | Date | |
---|---|---|---|
3721084d21 | |||
6076c9d82e | |||
2ef499001d | |||
e4d8ab1feb | |||
2fc82aceab | |||
475eb6185a | |||
cdf3a48516 | |||
dcc3c0086a | |||
0d6aeecebb | |||
704c68443a | |||
183b02a5e7 | |||
e91815150d | |||
73c33450ee | |||
e06d07c176 | |||
c73f30e21f | |||
bbf2044729 | |||
4a86ab9d1e | |||
16c3fea8a8 | |||
f4ec9b6ac4 | |||
44155f9ef0 | |||
a5e809a0f3 | |||
3e70f9262b | |||
3573a2edbe | |||
82d9623c6d | |||
258a9b0201 | |||
36d84f6c98 | |||
15c79a7a13 | |||
34e0294815 | |||
ad6a04b975 | |||
e0f682fcd8 | |||
a801359eed | |||
bb238f4c7e | |||
c1ebc8e74b | |||
110c8c6bed | |||
e8fffe65bf | |||
1731aa1890 | |||
c389889662 | |||
e38e12f89b | |||
26f71f5d00 | |||
65e04ce08b | |||
d84d8e03e0 | |||
475ad358ae | |||
db7e60bdfb | |||
444791fb4c | |||
be3a882baa | |||
6d6dc9f316 | |||
d86e825c60 | |||
6bb2af3da8 | |||
d195526afb | |||
9ec3956672 | |||
3098d2ab95 | |||
dccf9f7e1a | |||
e55c29c33c | |||
bd5728ffa0 | |||
af525d4e3d | |||
96e0b584a0 | |||
0d6e3bac17 | |||
d292b5f533 | |||
ec2cb21a8a | |||
3632ed8816 | |||
58acea1a2d | |||
9e63e3f47e | |||
7581c8a32a | |||
8715e0e37b | |||
36b9813e1b | |||
1a59e1cb24 | |||
7f7d25a6fa | |||
87755952b6 | |||
3821eb4d84 | |||
15af82ee49 | |||
1f8a66108b | |||
9309dd945b | |||
858741c9a5 | |||
26c922d9a2 | |||
2ba78545ef | |||
d2a47d1a51 | |||
b2ca97b836 | |||
979981ffb8 | |||
9a57ca69a0 | |||
7b9bdf1f08 | |||
034647b461 | |||
f1d8497851 | |||
2f2f155707 | |||
6d87587544 | |||
dad2d79361 | |||
9f2d7eb4bb | |||
b57809b3b3 | |||
6cb6c1b4fd | |||
14a01b7126 | |||
315c095af9 | |||
10d2fe4431 | |||
29147e1b8b | |||
0a1a1ac6be | |||
6c102c6d98 | |||
df89952483 | |||
01d8d917cb | |||
d1522210e5 | |||
d3ac528d57 | |||
82eed4759c | |||
2a94e1ac59 | |||
8feeeaa918 | |||
2946fa799e | |||
41ebe8aec7 | |||
e35a8246f9 | |||
725bb8a381 | |||
fc5eea33cf | |||
a1de3c956c | |||
d2d9b94e78 | |||
e6b205e823 | |||
0b680928fd | |||
c0c01eef8b | |||
7cdee93e9e | |||
33071ac8df | |||
c7ff6f3aa1 | |||
c61d4c8201 | |||
05a871c8a0 | |||
ae9dd309e9 | |||
cea0a51d0e | |||
5dcc63600c | |||
c29ed0a2ca | |||
9905de67bd | |||
25b42fd2f8 | |||
0a6d575b21 | |||
21de5e22e4 | |||
4670630e22 | |||
5f79326601 | |||
0c1a123cd9 | |||
9c96e7124a | |||
694847a424 | |||
e7f5da5af7 | |||
d59a37466b | |||
f2bfd584d0 | |||
a9ce6f54c7 | |||
de9bae9d66 | |||
716662322d | |||
2a893fe4ef | |||
a24d55025f | |||
04ddcecb70 | |||
dc9a600a6e | |||
c365de130b |
@ -1,4 +1,4 @@
|
|||||||
version: 7.14.{build}
|
version: 7.18.{build}
|
||||||
configuration: Release
|
configuration: Release
|
||||||
platform: Any CPU
|
platform: Any CPU
|
||||||
environment:
|
environment:
|
||||||
|
@ -6,6 +6,7 @@ os:
|
|||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update; fi
|
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update; fi
|
||||||
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install qt; fi
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install qt; fi
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common GPS log file formats.
|
GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common GPS log file formats.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
* Opens GPX, TCX, FIT, KML, NMEA, IGC, CUP, SLF, LOC, GeoJSON, OziExplorer (PLT, RTE, WPT), Garmin CSV and geotagged JPEG files.
|
* Opens GPX, TCX, FIT, KML, NMEA, IGC, CUP, SLF, LOC, GeoJSON, OziExplorer (PLT, RTE, WPT), Garmin GPI&CSV and geotagged JPEG files.
|
||||||
* User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS, QuadTiles).
|
* User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS, QuadTiles).
|
||||||
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, Garmin IMG & JNX maps, TwoNav RMaps, GeoTIFF images).
|
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, Garmin IMG & JNX maps, TwoNav RMaps, GeoTIFF images).
|
||||||
* Elevation, speed, heart rate, cadence, power, temperature and gear ratio/shifts graphs.
|
* Elevation, speed, heart rate, cadence, power, temperature and gear ratio/shifts graphs.
|
||||||
|
28
gpxsee.pro
28
gpxsee.pro
@ -3,7 +3,7 @@ unix:!macx {
|
|||||||
} else {
|
} else {
|
||||||
TARGET = GPXSee
|
TARGET = GPXSee
|
||||||
}
|
}
|
||||||
VERSION = 7.14
|
VERSION = 7.18
|
||||||
|
|
||||||
QT += core \
|
QT += core \
|
||||||
gui \
|
gui \
|
||||||
@ -19,6 +19,9 @@ 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/popup.h \
|
||||||
|
src/common/garmin.h \
|
||||||
src/common/staticassert.h \
|
src/common/staticassert.h \
|
||||||
src/common/coordinates.h \
|
src/common/coordinates.h \
|
||||||
src/common/range.h \
|
src/common/range.h \
|
||||||
@ -84,6 +87,7 @@ HEADERS += src/common/config.h \
|
|||||||
src/GUI/mapview.h \
|
src/GUI/mapview.h \
|
||||||
src/GUI/font.h \
|
src/GUI/font.h \
|
||||||
src/GUI/areaitem.h \
|
src/GUI/areaitem.h \
|
||||||
|
src/data/link.h \
|
||||||
src/map/IMG/bitmapline.h \
|
src/map/IMG/bitmapline.h \
|
||||||
src/map/IMG/textpathitem.h \
|
src/map/IMG/textpathitem.h \
|
||||||
src/map/IMG/textpointitem.h \
|
src/map/IMG/textpointitem.h \
|
||||||
@ -175,7 +179,6 @@ HEADERS += src/common/config.h \
|
|||||||
src/map/IMG/lblfile.h \
|
src/map/IMG/lblfile.h \
|
||||||
src/map/IMG/vectortile.h \
|
src/map/IMG/vectortile.h \
|
||||||
src/map/IMG/subdiv.h \
|
src/map/IMG/subdiv.h \
|
||||||
src/map/IMG/units.h \
|
|
||||||
src/map/IMG/style.h \
|
src/map/IMG/style.h \
|
||||||
src/map/IMG/netfile.h \
|
src/map/IMG/netfile.h \
|
||||||
src/GUI/limitedcombobox.h \
|
src/GUI/limitedcombobox.h \
|
||||||
@ -183,8 +186,11 @@ HEADERS += src/common/config.h \
|
|||||||
src/map/IMG/textitem.h \
|
src/map/IMG/textitem.h \
|
||||||
src/map/IMG/label.h \
|
src/map/IMG/label.h \
|
||||||
src/data/csv.h \
|
src/data/csv.h \
|
||||||
src/data/cupparser.h
|
src/data/cupparser.h \
|
||||||
|
src/data/gpiparser.h \
|
||||||
|
src/data/address.h
|
||||||
SOURCES += src/main.cpp \
|
SOURCES += src/main.cpp \
|
||||||
|
src/GUI/popup.cpp \
|
||||||
src/common/coordinates.cpp \
|
src/common/coordinates.cpp \
|
||||||
src/common/rectc.cpp \
|
src/common/rectc.cpp \
|
||||||
src/common/range.cpp \
|
src/common/range.cpp \
|
||||||
@ -316,7 +322,9 @@ SOURCES += src/main.cpp \
|
|||||||
src/GUI/pathtickitem.cpp \
|
src/GUI/pathtickitem.cpp \
|
||||||
src/map/IMG/textitem.cpp \
|
src/map/IMG/textitem.cpp \
|
||||||
src/data/csv.cpp \
|
src/data/csv.cpp \
|
||||||
src/data/cupparser.cpp
|
src/data/cupparser.cpp \
|
||||||
|
src/GUI/graphicsscene.cpp \
|
||||||
|
src/data/gpiparser.cpp
|
||||||
|
|
||||||
greaterThan(QT_MAJOR_VERSION, 4) {
|
greaterThan(QT_MAJOR_VERSION, 4) {
|
||||||
HEADERS += src/data/geojsonparser.h
|
HEADERS += src/data/geojsonparser.h
|
||||||
@ -340,7 +348,8 @@ TRANSLATIONS = lang/gpxsee_en.ts \
|
|||||||
lang/gpxsee_da.ts \
|
lang/gpxsee_da.ts \
|
||||||
lang/gpxsee_tr.ts \
|
lang/gpxsee_tr.ts \
|
||||||
lang/gpxsee_es.ts \
|
lang/gpxsee_es.ts \
|
||||||
lang/gpxsee_pt_BR.ts
|
lang/gpxsee_pt_BR.ts \
|
||||||
|
lang/gpxsee_uk.ts
|
||||||
|
|
||||||
macx {
|
macx {
|
||||||
ICON = icons/gpxsee.icns
|
ICON = icons/gpxsee.icns
|
||||||
@ -358,7 +367,8 @@ macx {
|
|||||||
lang/gpxsee_da.qm \
|
lang/gpxsee_da.qm \
|
||||||
lang/gpxsee_tr.qm \
|
lang/gpxsee_tr.qm \
|
||||||
lang/gpxsee_es.qm \
|
lang/gpxsee_es.qm \
|
||||||
lang/gpxsee_pt_BR.qm
|
lang/gpxsee_pt_BR.qm \
|
||||||
|
lang/gpxsee_uk.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
|
||||||
@ -376,7 +386,8 @@ macx {
|
|||||||
icons/formats/loc.icns \
|
icons/formats/loc.icns \
|
||||||
icons/formats/slf.icns \
|
icons/formats/slf.icns \
|
||||||
icons/formats/json.icns \
|
icons/formats/json.icns \
|
||||||
icons/formats/cup.icns
|
icons/formats/cup.icns \
|
||||||
|
icons/formats/gpi.icns
|
||||||
QMAKE_BUNDLE_DATA += locale maps icons csv
|
QMAKE_BUNDLE_DATA += locale maps icons csv
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +405,8 @@ win32 {
|
|||||||
icons/formats/loc.ico \
|
icons/formats/loc.ico \
|
||||||
icons/formats/slf.ico \
|
icons/formats/slf.ico \
|
||||||
icons/formats/json.ico \
|
icons/formats/json.ico \
|
||||||
icons/formats/cup.ico
|
icons/formats/cup.ico \
|
||||||
|
icons/formats/gpi.ico
|
||||||
DEFINES += _USE_MATH_DEFINES \
|
DEFINES += _USE_MATH_DEFINES \
|
||||||
NOGDI
|
NOGDI
|
||||||
}
|
}
|
||||||
|
BIN
icons/formats/gpi.icns
Normal file
BIN
icons/formats/gpi.icns
Normal file
Binary file not shown.
BIN
icons/formats/gpi.ico
Normal file
BIN
icons/formats/gpi.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 303 KiB |
@ -11,3 +11,4 @@ wpt:#66ff00
|
|||||||
loc:#556677
|
loc:#556677
|
||||||
slf:#881199
|
slf:#881199
|
||||||
cup:#20a810
|
cup:#20a810
|
||||||
|
gpi:#fca314
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1456
lang/gpxsee_en.ts
1456
lang/gpxsee_en.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -227,6 +227,22 @@
|
|||||||
<key>CFBundleTypeRole</key>
|
<key>CFBundleTypeRole</key>
|
||||||
<string>Viewer</string>
|
<string>Viewer</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>gpi</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeMIMETypes</key>
|
||||||
|
<array>
|
||||||
|
<string>application/vnd.garmin.gpi</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>icons/gpi.icns</string>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>Garmin POI File</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
|
|
||||||
<key>UTImportedTypeDeclarations</key>
|
<key>UTImportedTypeDeclarations</key>
|
||||||
@ -504,6 +520,27 @@
|
|||||||
<string>application/vnd.naviter.seeyou.cup</string>
|
<string>application/vnd.naviter.seeyou.cup</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>UTTypeIdentifier</key>
|
||||||
|
<string>com.garmin.gpi</string>
|
||||||
|
<key>UTTypeReferenceURL</key>
|
||||||
|
<string>http://www.garmin.com</string>
|
||||||
|
<key>UTTypeDescription</key>
|
||||||
|
<string>Garmin POI File</string>
|
||||||
|
<key>UTTypeConformsTo</key>
|
||||||
|
<array>
|
||||||
|
<string>public.data</string>
|
||||||
|
</array>
|
||||||
|
<key>UTTypeTagSpecification</key>
|
||||||
|
<dict>
|
||||||
|
<key>public.filename-extension</key>
|
||||||
|
<array>
|
||||||
|
<string>gpi</string>
|
||||||
|
</array>
|
||||||
|
<key>public.mime-type</key>
|
||||||
|
<string>application/vnd.garmin.gpi</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -13,14 +13,14 @@
|
|||||||
<p>Features:</p>
|
<p>Features:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Opens GPX, TCX, FIT, KML, IGC, NMEA, SLF, LOC, OziExplorer (PLT,
|
<li>Opens GPX, TCX, FIT, KML, IGC, NMEA, SLF, LOC, OziExplorer (PLT,
|
||||||
WPT, RTE), GeoJSON, SeeYou CUP, Garmin CSV and geotagged
|
WPT, RTE), GeoJSON, SeeYou CUP, Garmin GPI & CSV and
|
||||||
JPEG files.</li>
|
geotagged JPEG files.</li>
|
||||||
<li>User-definable online maps (OpenStreetMap/Google tiles, WMTS,
|
<li>User-definable online maps (OpenStreetMap/Google tiles, WMTS,
|
||||||
WMS, TMS).</li>
|
WMS, TMS).</li>
|
||||||
<li>Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases,
|
<li>Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases,
|
||||||
TwoNav RMaps, Garmin IMG & JNX, GeoTIFF images).</li>
|
TwoNav RMaps, Garmin IMG & JNX, GeoTIFF images).</li>
|
||||||
<li>Elevation, speed, heart rate, cadence, power and temperature
|
<li>Elevation, speed, heart rate, cadence, power, temperature and
|
||||||
graphs.</li>
|
gear ratio graphs.</li>
|
||||||
<li>Support for multiple tracks in one view.</li>
|
<li>Support for multiple tracks in one view.</li>
|
||||||
<li>Support for POI files.</li>
|
<li>Support for POI files.</li>
|
||||||
<li>Print/export to PDF.</li>
|
<li>Print/export to PDF.</li>
|
||||||
@ -69,5 +69,6 @@
|
|||||||
<mimetype>application/slf+xml</mimetype>
|
<mimetype>application/slf+xml</mimetype>
|
||||||
<mimetype>application/geo+json</mimetype>
|
<mimetype>application/geo+json</mimetype>
|
||||||
<mimetype>application/vnd.naviter.seeyou.cup</mimetype>
|
<mimetype>application/vnd.naviter.seeyou.cup</mimetype>
|
||||||
|
<mimetype>application/vnd.garmin.gpi</mimetype>
|
||||||
</mimetypes>
|
</mimetypes>
|
||||||
</component>
|
</component>
|
||||||
|
@ -11,4 +11,4 @@ Icon=gpxsee
|
|||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
Categories=Graphics;Viewer;Education;Geography;Maps;Sports;Qt;
|
Categories=Graphics;Viewer;Education;Geography;Maps;Sports;Qt;
|
||||||
MimeType=application/gpx+xml;application/tcx+xml;application/vnd.ant.fit;application/vnd.google-earth.kml+xml;application/vnd.fai.igc;application/vnd.nmea.nmea;application/vnd.oziexplorer.plt;application/vnd.oziexplorer.rte;application/vnd.oziexplorer.wpt;application/loc+xml;application/slf+xml;application/geo+json;application/vnd.naviter.seeyou.cup;
|
MimeType=application/gpx+xml;application/tcx+xml;application/vnd.ant.fit;application/vnd.google-earth.kml+xml;application/vnd.fai.igc;application/vnd.nmea.nmea;application/vnd.oziexplorer.plt;application/vnd.oziexplorer.rte;application/vnd.oziexplorer.wpt;application/loc+xml;application/slf+xml;application/geo+json;application/vnd.naviter.seeyou.cup;application/vnd.garmin.gpi;
|
||||||
|
@ -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.14"
|
!define VERSION "7.18"
|
||||||
|
|
||||||
; The file to write
|
; The file to write
|
||||||
OutFile "GPXSee-${VERSION}.exe"
|
OutFile "GPXSee-${VERSION}.exe"
|
||||||
@ -106,19 +106,20 @@ Section "GPXSee" SEC_APP
|
|||||||
|
|
||||||
; Associate file formats
|
; Associate file formats
|
||||||
DetailPrint "Associating file types..."
|
DetailPrint "Associating file types..."
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "gpx" "GPS Exchange Format" 6
|
!insertmacro FILE_ASSOCIATION_ADD "gpx" "GPS Exchange Format" 7
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 7
|
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 8
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 8
|
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 9
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 9
|
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 10
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 10
|
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 11
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 data" 11
|
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 12
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track Point File" 12
|
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track Point File" 13
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 13
|
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 14
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "wpt" "OziExplorer Waypoint File" 1
|
!insertmacro FILE_ASSOCIATION_ADD "wpt" "OziExplorer Waypoint File" 1
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "loc" "Geocaching.com Waypoint File" 2
|
!insertmacro FILE_ASSOCIATION_ADD "loc" "Geocaching.com Waypoint File" 2
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "slf" "Sigma Log File" 3
|
!insertmacro FILE_ASSOCIATION_ADD "slf" "Sigma Log File" 3
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "geojson" "GeoJSON" 4
|
!insertmacro FILE_ASSOCIATION_ADD "geojson" "GeoJSON" 4
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "cup" "SeeYou CUP file" 5
|
!insertmacro FILE_ASSOCIATION_ADD "cup" "SeeYou CUP File" 5
|
||||||
|
!insertmacro FILE_ASSOCIATION_ADD "gpi" "Garmin POI File" 6
|
||||||
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
||||||
|
|
||||||
SectionEnd
|
SectionEnd
|
||||||
@ -194,6 +195,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
|
|||||||
!insertmacro LOCALIZATION "Spanish" "es"
|
!insertmacro LOCALIZATION "Spanish" "es"
|
||||||
!insertmacro LOCALIZATION "Swedish" "sv"
|
!insertmacro LOCALIZATION "Swedish" "sv"
|
||||||
!insertmacro LOCALIZATION "Turkish" "tr"
|
!insertmacro LOCALIZATION "Turkish" "tr"
|
||||||
|
!insertmacro LOCALIZATION "Ukrainian" "uk"
|
||||||
SectionGroupEnd
|
SectionGroupEnd
|
||||||
|
|
||||||
;--------------------------------
|
;--------------------------------
|
||||||
@ -229,6 +231,7 @@ Section "Uninstall"
|
|||||||
!insertmacro FILE_ASSOCIATION_REMOVE "slf"
|
!insertmacro FILE_ASSOCIATION_REMOVE "slf"
|
||||||
!insertmacro FILE_ASSOCIATION_REMOVE "geojson"
|
!insertmacro FILE_ASSOCIATION_REMOVE "geojson"
|
||||||
!insertmacro FILE_ASSOCIATION_REMOVE "cup"
|
!insertmacro FILE_ASSOCIATION_REMOVE "cup"
|
||||||
|
!insertmacro FILE_ASSOCIATION_REMOVE "gpi"
|
||||||
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
||||||
|
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
@ -91,4 +91,11 @@
|
|||||||
<generic-icon name="text-plain"/>
|
<generic-icon name="text-plain"/>
|
||||||
<glob pattern="*.cup"/>
|
<glob pattern="*.cup"/>
|
||||||
</mime-type>
|
</mime-type>
|
||||||
|
|
||||||
|
<mime-type type="application/vnd.garmin.gpi">
|
||||||
|
<comment>Garmin POI File</comment>
|
||||||
|
<sub-class-of type="application/octet-stream"/>
|
||||||
|
<generic-icon name="application/octet-stream"/>
|
||||||
|
<glob pattern="*.gpi"/>
|
||||||
|
</mime-type>
|
||||||
</mime-info>
|
</mime-info>
|
||||||
|
@ -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.14"
|
!define VERSION "7.18"
|
||||||
|
|
||||||
; The file to write
|
; The file to write
|
||||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||||
@ -113,19 +113,20 @@ Section "GPXSee" SEC_APP
|
|||||||
|
|
||||||
; Associate file formats
|
; Associate file formats
|
||||||
DetailPrint "Associating file types..."
|
DetailPrint "Associating file types..."
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "gpx" "GPS Exchange Format" 6
|
!insertmacro FILE_ASSOCIATION_ADD "gpx" "GPS Exchange Format" 7
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 7
|
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 8
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 8
|
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 9
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 9
|
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 10
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 10
|
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 11
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 data" 11
|
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 12
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track Point File" 12
|
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track Point File" 13
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 13
|
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 14
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "wpt" "OziExplorer Waypoint File" 1
|
!insertmacro FILE_ASSOCIATION_ADD "wpt" "OziExplorer Waypoint File" 1
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "loc" "Geocaching.com Waypoint File" 2
|
!insertmacro FILE_ASSOCIATION_ADD "loc" "Geocaching.com Waypoint File" 2
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "slf" "Sigma Log File" 3
|
!insertmacro FILE_ASSOCIATION_ADD "slf" "Sigma Log File" 3
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "geojson" "GeoJSON" 4
|
!insertmacro FILE_ASSOCIATION_ADD "geojson" "GeoJSON" 4
|
||||||
!insertmacro FILE_ASSOCIATION_ADD "cup" "SeeYou CUP file" 5
|
!insertmacro FILE_ASSOCIATION_ADD "cup" "SeeYou CUP File" 5
|
||||||
|
!insertmacro FILE_ASSOCIATION_ADD "gpi" "Garmin POI File" 6
|
||||||
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
||||||
|
|
||||||
SectionEnd
|
SectionEnd
|
||||||
@ -196,6 +197,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
|
|||||||
!insertmacro LOCALIZATION "Spanish" "es"
|
!insertmacro LOCALIZATION "Spanish" "es"
|
||||||
!insertmacro LOCALIZATION "Swedish" "sv"
|
!insertmacro LOCALIZATION "Swedish" "sv"
|
||||||
!insertmacro LOCALIZATION "Turkish" "tr"
|
!insertmacro LOCALIZATION "Turkish" "tr"
|
||||||
|
!insertmacro LOCALIZATION "Ukrainian" "uk"
|
||||||
SectionGroupEnd
|
SectionGroupEnd
|
||||||
|
|
||||||
;--------------------------------
|
;--------------------------------
|
||||||
@ -232,6 +234,7 @@ Section "Uninstall"
|
|||||||
!insertmacro FILE_ASSOCIATION_REMOVE "slf"
|
!insertmacro FILE_ASSOCIATION_REMOVE "slf"
|
||||||
!insertmacro FILE_ASSOCIATION_REMOVE "geojson"
|
!insertmacro FILE_ASSOCIATION_REMOVE "geojson"
|
||||||
!insertmacro FILE_ASSOCIATION_REMOVE "cup"
|
!insertmacro FILE_ASSOCIATION_REMOVE "cup"
|
||||||
|
!insertmacro FILE_ASSOCIATION_REMOVE "gpi"
|
||||||
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
||||||
|
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include "map/map.h"
|
#include "map/map.h"
|
||||||
#include "tooltip.h"
|
#include "popup.h"
|
||||||
#include "areaitem.h"
|
#include "areaitem.h"
|
||||||
|
|
||||||
|
|
||||||
QString AreaItem::toolTip() const
|
QString AreaItem::info() const
|
||||||
{
|
{
|
||||||
ToolTip tt;
|
ToolTip tt;
|
||||||
|
|
||||||
@ -20,8 +21,8 @@ QString AreaItem::toolTip() const
|
|||||||
return tt.toString();
|
return tt.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
AreaItem::AreaItem(const Area &area, Map *map, QGraphicsItem *parent)
|
AreaItem::AreaItem(const Area &area, Map *map, GraphicsItem *parent)
|
||||||
: QGraphicsItem(parent), _area(area)
|
: GraphicsItem(parent), _area(area)
|
||||||
{
|
{
|
||||||
_map = map;
|
_map = map;
|
||||||
_digitalZoom = 0;
|
_digitalZoom = 0;
|
||||||
@ -35,8 +36,6 @@ AreaItem::AreaItem(const Area &area, Map *map, QGraphicsItem *parent)
|
|||||||
|
|
||||||
setCursor(Qt::ArrowCursor);
|
setCursor(Qt::ArrowCursor);
|
||||||
setAcceptHoverEvents(true);
|
setAcceptHoverEvents(true);
|
||||||
|
|
||||||
setToolTip(toolTip());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -171,3 +170,9 @@ void AreaItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
|||||||
setZValue(zValue() - 1.0);
|
setZValue(zValue() - 1.0);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AreaItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
Popup::show(event->screenPos(), info(), event->widget());
|
||||||
|
QGraphicsItem::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
#ifndef AREAITEM_H
|
#ifndef AREAITEM_H
|
||||||
#define AREAITEM_H
|
#define AREAITEM_H
|
||||||
|
|
||||||
#include <QGraphicsItem>
|
|
||||||
#include "data/area.h"
|
#include "data/area.h"
|
||||||
|
#include "graphicsscene.h"
|
||||||
|
#include "tooltip.h"
|
||||||
|
|
||||||
class Map;
|
class Map;
|
||||||
|
|
||||||
class AreaItem : public QGraphicsItem
|
class AreaItem : public GraphicsItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AreaItem(const Area &area, Map *map, QGraphicsItem *parent = 0);
|
AreaItem(const Area &area, Map *map, GraphicsItem *parent = 0);
|
||||||
|
|
||||||
QPainterPath shape() const {return _painterPath;}
|
QPainterPath shape() const {return _painterPath;}
|
||||||
QRectF boundingRect() const {return _painterPath.boundingRect();}
|
QRectF boundingRect() const {return _painterPath.boundingRect();}
|
||||||
@ -26,13 +27,17 @@ public:
|
|||||||
void setStyle(Qt::PenStyle style);
|
void setStyle(Qt::PenStyle style);
|
||||||
void setDigitalZoom(int zoom);
|
void setDigitalZoom(int zoom);
|
||||||
|
|
||||||
private:
|
virtual QString info() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
|
||||||
|
private:
|
||||||
QPainterPath painterPath(const Polygon &polygon);
|
QPainterPath painterPath(const Polygon &polygon);
|
||||||
void updatePainterPath();
|
void updatePainterPath();
|
||||||
QString toolTip() const;
|
ToolTip toolTip() const;
|
||||||
|
|
||||||
Area _area;
|
Area _area;
|
||||||
Map *_map;
|
Map *_map;
|
||||||
|
@ -7,10 +7,9 @@ CadenceGraphItem::CadenceGraphItem(const Graph &graph, GraphType type,
|
|||||||
int width, const QColor &color, QGraphicsItem *parent)
|
int width, const QColor &color, QGraphicsItem *parent)
|
||||||
: GraphItem(graph, type, width, color, parent)
|
: GraphItem(graph, type, width, color, parent)
|
||||||
{
|
{
|
||||||
setToolTip(toolTip());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CadenceGraphItem::toolTip() const
|
QString CadenceGraphItem::info() const
|
||||||
{
|
{
|
||||||
ToolTip tt;
|
ToolTip tt;
|
||||||
QLocale l(QLocale::system());
|
QLocale l(QLocale::system());
|
||||||
|
@ -11,8 +11,7 @@ public:
|
|||||||
CadenceGraphItem(const Graph &graph, GraphType type, int width,
|
CadenceGraphItem(const Graph &graph, GraphType type, int width,
|
||||||
const QColor &color, QGraphicsItem *parent = 0);
|
const QColor &color, QGraphicsItem *parent = 0);
|
||||||
|
|
||||||
private:
|
QString info() const;
|
||||||
QString toolTip() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CADENCEGRAPHITEM_H
|
#endif // CADENCEGRAPHITEM_H
|
||||||
|
@ -24,15 +24,13 @@ ElevationGraphItem::ElevationGraphItem(const Graph &graph, GraphType type,
|
|||||||
_descent += prev - cur;
|
_descent += prev - cur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setToolTip(toolTip(Metric));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ElevationGraphItem::toolTip(Units units) const
|
QString ElevationGraphItem::info() const
|
||||||
{
|
{
|
||||||
ToolTip tt;
|
ToolTip tt;
|
||||||
qreal scale = (units == Metric) ? 1.0 : M2FT;
|
qreal scale = (_units == Metric) ? 1.0 : M2FT;
|
||||||
QString su = (units == Metric) ? tr("m") : tr("ft");
|
QString su = (_units == Metric) ? tr("m") : tr("ft");
|
||||||
QLocale l(QLocale::system());
|
QLocale l(QLocale::system());
|
||||||
|
|
||||||
tt.insert(tr("Ascent"), l.toString(ascent() * scale, 'f', 0)
|
tt.insert(tr("Ascent"), l.toString(ascent() * scale, 'f', 0)
|
||||||
@ -46,8 +44,3 @@ QString ElevationGraphItem::toolTip(Units units) const
|
|||||||
|
|
||||||
return tt.toString();
|
return tt.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElevationGraphItem::setUnits(Units units)
|
|
||||||
{
|
|
||||||
setToolTip(toolTip(units));
|
|
||||||
}
|
|
||||||
|
@ -16,11 +16,9 @@ public:
|
|||||||
qreal max() const {return _max;}
|
qreal max() const {return _max;}
|
||||||
qreal min() const {return _min;}
|
qreal min() const {return _min;}
|
||||||
|
|
||||||
void setUnits(Units units);
|
QString info() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString toolTip(Units units) const;
|
|
||||||
|
|
||||||
qreal _ascent, _descent, _min, _max;
|
qreal _ascent, _descent, _min, _max;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,11 +25,9 @@ GearRatioGraphItem::GearRatioGraphItem(const Graph &graph, GraphType type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_top = key;
|
_top = key;
|
||||||
|
|
||||||
setToolTip(toolTip());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GearRatioGraphItem::toolTip() const
|
QString GearRatioGraphItem::info() const
|
||||||
{
|
{
|
||||||
ToolTip tt;
|
ToolTip tt;
|
||||||
QLocale l(QLocale::system());
|
QLocale l(QLocale::system());
|
||||||
|
@ -13,12 +13,11 @@ public:
|
|||||||
const QColor &color, QGraphicsItem *parent = 0);
|
const QColor &color, QGraphicsItem *parent = 0);
|
||||||
|
|
||||||
qreal top() const {return _top;}
|
qreal top() const {return _top;}
|
||||||
|
|
||||||
const QMap<qreal, qreal> &map() const {return _map;}
|
const QMap<qreal, qreal> &map() const {return _map;}
|
||||||
|
|
||||||
private:
|
QString info() const;
|
||||||
QString toolTip() const;
|
|
||||||
|
|
||||||
|
private:
|
||||||
QMap<qreal, qreal> _map;
|
QMap<qreal, qreal> _map;
|
||||||
qreal _top;
|
qreal _top;
|
||||||
};
|
};
|
||||||
|
48
src/GUI/graphicsscene.cpp
Normal file
48
src/GUI/graphicsscene.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include <QGraphicsSceneHelpEvent>
|
||||||
|
#include <QGraphicsView>
|
||||||
|
#include "popup.h"
|
||||||
|
#include "graphicsscene.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Standard GraphicsScene::items() is not pixel accurate, so we use the
|
||||||
|
following function which has the same logic as used in the original
|
||||||
|
QGraphicsScene::helpEvent() function. */
|
||||||
|
QList<QGraphicsItem *> GraphicsScene::itemsAtPosition(const QPoint &screenPos,
|
||||||
|
const QPointF &scenePos, QWidget *widget) const
|
||||||
|
{
|
||||||
|
QGraphicsView *view = widget
|
||||||
|
? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
|
||||||
|
|
||||||
|
if (!view)
|
||||||
|
return items(scenePos, Qt::IntersectsItemShape, Qt::DescendingOrder,
|
||||||
|
QTransform());
|
||||||
|
|
||||||
|
const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)),
|
||||||
|
QSizeF(1, 1));
|
||||||
|
if (!view->isTransformed())
|
||||||
|
return items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder);
|
||||||
|
|
||||||
|
const QTransform viewTransform = view->viewportTransform();
|
||||||
|
if (viewTransform.type() <= QTransform::TxScale)
|
||||||
|
return items(viewTransform.inverted().mapRect(pointRect),
|
||||||
|
Qt::IntersectsItemShape, Qt::DescendingOrder, viewTransform);
|
||||||
|
|
||||||
|
return items(viewTransform.inverted().map(pointRect),
|
||||||
|
Qt::IntersectsItemShape, Qt::DescendingOrder, viewTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsScene::helpEvent(QGraphicsSceneHelpEvent *event)
|
||||||
|
{
|
||||||
|
QList<QGraphicsItem *> list = itemsAtPosition(event->screenPos(),
|
||||||
|
event->scenePos(), event->widget());
|
||||||
|
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
if (list.at(i)->type() == QGraphicsItem::UserType + 1) {
|
||||||
|
GraphicsItem *mi = static_cast<GraphicsItem*>(list.at(i));
|
||||||
|
Popup::show(event->screenPos(), mi->info(), event->widget());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No need to process QGraphicsScene::helpEvent() */
|
||||||
|
}
|
29
src/GUI/graphicsscene.h
Normal file
29
src/GUI/graphicsscene.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef GRAPHICSSCENE_H
|
||||||
|
#define GRAPHICSSCENE_H
|
||||||
|
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QGraphicsItem>
|
||||||
|
|
||||||
|
class GraphicsItem : public QGraphicsItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GraphicsItem(QGraphicsItem *parent = 0) : QGraphicsItem(parent) {}
|
||||||
|
|
||||||
|
virtual QString info() const = 0;
|
||||||
|
int type() const {return QGraphicsItem::UserType + 1;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GraphicsScene : public QGraphicsScene
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GraphicsScene(QObject *parent = 0) : QGraphicsScene(parent) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void helpEvent(QGraphicsSceneHelpEvent *event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<QGraphicsItem *> itemsAtPosition(const QPoint &screenPos,
|
||||||
|
const QPointF &scenePos, QWidget *widget) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GRAPHICSSCENE_H
|
@ -1,13 +1,16 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QGraphicsSceneMouseEvent>
|
||||||
|
#include "popup.h"
|
||||||
#include "graphitem.h"
|
#include "graphitem.h"
|
||||||
|
|
||||||
|
|
||||||
GraphItem::GraphItem(const Graph &graph, GraphType type, int width,
|
GraphItem::GraphItem(const Graph &graph, GraphType type, int width,
|
||||||
const QColor &color, QGraphicsItem *parent)
|
const QColor &color, QGraphicsItem *parent)
|
||||||
: QGraphicsObject(parent), _graph(graph), _type(type)
|
: GraphicsItem(parent), _graph(graph), _type(type)
|
||||||
{
|
{
|
||||||
Q_ASSERT(_graph.isValid());
|
Q_ASSERT(_graph.isValid());
|
||||||
|
|
||||||
|
_units = Metric;
|
||||||
_pen = QPen(color, width);
|
_pen = QPen(color, width);
|
||||||
_sx = 0; _sy = 0;
|
_sx = 0; _sy = 0;
|
||||||
_time = _graph.hasTime();
|
_time = _graph.hasTime();
|
||||||
@ -231,6 +234,9 @@ void GraphItem::updateBounds()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (left == right)
|
||||||
|
_bounds = QRectF();
|
||||||
|
else
|
||||||
_bounds = QRectF(QPointF(left, top), QPointF(right, bottom));
|
_bounds = QRectF(QPointF(left, top), QPointF(right, bottom));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,3 +309,9 @@ void GraphItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
|||||||
|
|
||||||
emit selected(false);
|
emit selected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
Popup::show(event->screenPos(), info(), event->widget());
|
||||||
|
GraphicsItem::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
@ -5,8 +5,9 @@
|
|||||||
#include <QPen>
|
#include <QPen>
|
||||||
#include "data/graph.h"
|
#include "data/graph.h"
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
|
#include "graphicsscene.h"
|
||||||
|
|
||||||
class GraphItem : public QGraphicsObject
|
class GraphItem : public QObject, public GraphicsItem
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -15,6 +16,8 @@ public:
|
|||||||
QGraphicsItem *parent = 0);
|
QGraphicsItem *parent = 0);
|
||||||
virtual ~GraphItem() {}
|
virtual ~GraphItem() {}
|
||||||
|
|
||||||
|
virtual QString info() const = 0;
|
||||||
|
|
||||||
QPainterPath shape() const {return _shape;}
|
QPainterPath shape() const {return _shape;}
|
||||||
QRectF boundingRect() const {return _shape.boundingRect();}
|
QRectF boundingRect() const {return _shape.boundingRect();}
|
||||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||||
@ -30,7 +33,7 @@ public:
|
|||||||
void setGraphType(GraphType type);
|
void setGraphType(GraphType type);
|
||||||
void setColor(const QColor &color);
|
void setColor(const QColor &color);
|
||||||
void setWidth(int width);
|
void setWidth(int width);
|
||||||
virtual void setUnits(Units units) {Q_UNUSED(units);}
|
void setUnits(Units units) {_units = units;}
|
||||||
|
|
||||||
qreal yAtX(qreal x);
|
qreal yAtX(qreal x);
|
||||||
qreal distanceAtTime(qreal time);
|
qreal distanceAtTime(qreal time);
|
||||||
@ -45,10 +48,14 @@ public slots:
|
|||||||
void emitSliderPositionChanged(qreal);
|
void emitSliderPositionChanged(qreal);
|
||||||
void hover(bool hover);
|
void hover(bool hover);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
|
||||||
|
Units _units;
|
||||||
|
|
||||||
|
private:
|
||||||
const GraphSegment *segment(qreal x, GraphType type) const;
|
const GraphSegment *segment(qreal x, GraphType type) const;
|
||||||
void updatePath();
|
void updatePath();
|
||||||
void updateShape();
|
void updateShape();
|
||||||
@ -61,7 +68,6 @@ private:
|
|||||||
QRectF _bounds;
|
QRectF _bounds;
|
||||||
qreal _sx, _sy;
|
qreal _sx, _sy;
|
||||||
QPen _pen;
|
QPen _pen;
|
||||||
|
|
||||||
bool _time;
|
bool _time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "graphitem.h"
|
#include "graphitem.h"
|
||||||
#include "pathitem.h"
|
#include "pathitem.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
#include "graphicsscene.h"
|
||||||
#include "graphview.h"
|
#include "graphview.h"
|
||||||
|
|
||||||
|
|
||||||
@ -23,7 +24,7 @@
|
|||||||
GraphView::GraphView(QWidget *parent)
|
GraphView::GraphView(QWidget *parent)
|
||||||
: QGraphicsView(parent)
|
: QGraphicsView(parent)
|
||||||
{
|
{
|
||||||
_scene = new QGraphicsScene(this);
|
_scene = new GraphicsScene(this);
|
||||||
setScene(_scene);
|
setScene(_scene);
|
||||||
|
|
||||||
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
||||||
@ -37,9 +38,9 @@ GraphView::GraphView(QWidget *parent)
|
|||||||
_yAxis = new AxisItem(AxisItem::Y);
|
_yAxis = new AxisItem(AxisItem::Y);
|
||||||
_yAxis->setZValue(1.0);
|
_yAxis->setZValue(1.0);
|
||||||
_slider = new SliderItem();
|
_slider = new SliderItem();
|
||||||
_slider->setZValue(3.0);
|
_slider->setZValue(4.0);
|
||||||
_sliderInfo = new SliderInfoItem(_slider);
|
_sliderInfo = new SliderInfoItem(_slider);
|
||||||
_sliderInfo->setZValue(3.0);
|
_sliderInfo->setZValue(4.0);
|
||||||
_info = new InfoItem();
|
_info = new InfoItem();
|
||||||
_grid = new GridItem();
|
_grid = new GridItem();
|
||||||
_message = new QGraphicsSimpleTextItem(tr("Data not available"));
|
_message = new QGraphicsSimpleTextItem(tr("Data not available"));
|
||||||
@ -165,6 +166,10 @@ void GraphView::setGraphType(GraphType type)
|
|||||||
for (int i = 0; i < _graphs.count(); i++) {
|
for (int i = 0; i < _graphs.count(); i++) {
|
||||||
GraphItem *gi = _graphs.at(i);
|
GraphItem *gi = _graphs.at(i);
|
||||||
gi->setGraphType(type);
|
gi->setGraphType(type);
|
||||||
|
if (gi->bounds().isNull())
|
||||||
|
removeItem(gi);
|
||||||
|
else
|
||||||
|
addItem(gi);
|
||||||
_bounds |= gi->bounds();
|
_bounds |= gi->bounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,6 +198,7 @@ void GraphView::addGraph(GraphItem *graph)
|
|||||||
SLOT(emitSliderPositionChanged(qreal)));
|
SLOT(emitSliderPositionChanged(qreal)));
|
||||||
|
|
||||||
_graphs.append(graph);
|
_graphs.append(graph);
|
||||||
|
if (!graph->bounds().isNull())
|
||||||
_scene->addItem(graph);
|
_scene->addItem(graph);
|
||||||
_bounds |= graph->bounds();
|
_bounds |= graph->bounds();
|
||||||
|
|
||||||
@ -357,13 +363,13 @@ void GraphView::wheelEvent(QWheelEvent *e)
|
|||||||
QGraphicsView::wheelEvent(e);
|
QGraphicsView::wheelEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphView::paintEvent(QPaintEvent *event)
|
void GraphView::paintEvent(QPaintEvent *e)
|
||||||
{
|
{
|
||||||
QRectF viewRect(mapToScene(rect()).boundingRect());
|
QRectF viewRect(mapToScene(rect()).boundingRect());
|
||||||
_info->setPos(QPointF(viewRect.left() + (viewRect.width()
|
_info->setPos(QPointF(viewRect.left() + (viewRect.width()
|
||||||
- _info->boundingRect().width())/2.0, _info->pos().y()));
|
- _info->boundingRect().width())/2.0, _info->pos().y()));
|
||||||
|
|
||||||
QGraphicsView::paintEvent(event);
|
QGraphicsView::paintEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphView::plot(QPainter *painter, const QRectF &target, qreal scale)
|
void GraphView::plot(QPainter *painter, const QRectF &target, qreal scale)
|
||||||
|
@ -17,6 +17,7 @@ class GraphItem;
|
|||||||
class PathItem;
|
class PathItem;
|
||||||
class GridItem;
|
class GridItem;
|
||||||
class QGraphicsSimpleTextItem;
|
class QGraphicsSimpleTextItem;
|
||||||
|
class GraphicsScene;
|
||||||
|
|
||||||
class GraphView : public QGraphicsView
|
class GraphView : public QGraphicsView
|
||||||
{
|
{
|
||||||
@ -48,10 +49,15 @@ signals:
|
|||||||
protected:
|
protected:
|
||||||
void addGraph(GraphItem *graph);
|
void addGraph(GraphItem *graph);
|
||||||
void removeGraph(GraphItem *graph);
|
void removeGraph(GraphItem *graph);
|
||||||
|
|
||||||
void setGraphType(GraphType type);
|
void setGraphType(GraphType type);
|
||||||
void setUnits(Units units);
|
void setUnits(Units units);
|
||||||
|
|
||||||
|
void resizeEvent(QResizeEvent *e);
|
||||||
|
void mousePressEvent(QMouseEvent *e);
|
||||||
|
void wheelEvent(QWheelEvent *e);
|
||||||
|
void changeEvent(QEvent *e);
|
||||||
|
void paintEvent(QPaintEvent *e);
|
||||||
|
|
||||||
const QString &yLabel() const {return _yLabel;}
|
const QString &yLabel() const {return _yLabel;}
|
||||||
const QString &yUnits() const {return _yUnits;}
|
const QString &yUnits() const {return _yUnits;}
|
||||||
qreal yScale() const {return _yScale;}
|
qreal yScale() const {return _yScale;}
|
||||||
@ -88,13 +94,7 @@ private:
|
|||||||
void removeItem(QGraphicsItem *item);
|
void removeItem(QGraphicsItem *item);
|
||||||
void addItem(QGraphicsItem *item);
|
void addItem(QGraphicsItem *item);
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent *e);
|
GraphicsScene *_scene;
|
||||||
void mousePressEvent(QMouseEvent *e);
|
|
||||||
void wheelEvent(QWheelEvent *e);
|
|
||||||
void changeEvent(QEvent *e);
|
|
||||||
void paintEvent(QPaintEvent *event);
|
|
||||||
|
|
||||||
QGraphicsScene *_scene;
|
|
||||||
|
|
||||||
AxisItem *_xAxis, *_yAxis;
|
AxisItem *_xAxis, *_yAxis;
|
||||||
SliderItem *_slider;
|
SliderItem *_slider;
|
||||||
|
@ -949,6 +949,7 @@ void GUI::openOptions()
|
|||||||
SET_TRACK_OPTION(cadenceFilter, setCadenceFilter);
|
SET_TRACK_OPTION(cadenceFilter, setCadenceFilter);
|
||||||
SET_TRACK_OPTION(powerFilter, setPowerFilter);
|
SET_TRACK_OPTION(powerFilter, setPowerFilter);
|
||||||
SET_TRACK_OPTION(outlierEliminate, setOutlierElimination);
|
SET_TRACK_OPTION(outlierEliminate, setOutlierElimination);
|
||||||
|
SET_TRACK_OPTION(automaticPause, setAutomaticPause);
|
||||||
SET_TRACK_OPTION(pauseSpeed, setPauseSpeed);
|
SET_TRACK_OPTION(pauseSpeed, setPauseSpeed);
|
||||||
SET_TRACK_OPTION(pauseInterval, setPauseInterval);
|
SET_TRACK_OPTION(pauseInterval, setPauseInterval);
|
||||||
SET_TRACK_OPTION(useReportedSpeed, useReportedSpeed);
|
SET_TRACK_OPTION(useReportedSpeed, useReportedSpeed);
|
||||||
@ -1580,7 +1581,6 @@ void GUI::keyPressEvent(QKeyEvent *event)
|
|||||||
else
|
else
|
||||||
_movingTimeAction->trigger();
|
_movingTimeAction->trigger();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_Escape:
|
case Qt::Key_Escape:
|
||||||
if (_fullscreenAction->isChecked()) {
|
if (_fullscreenAction->isChecked()) {
|
||||||
_fullscreenAction->setChecked(false);
|
_fullscreenAction->setChecked(false);
|
||||||
@ -1799,6 +1799,8 @@ void GUI::writeSettings()
|
|||||||
settings.setValue(POWER_FILTER_SETTING, _options.powerFilter);
|
settings.setValue(POWER_FILTER_SETTING, _options.powerFilter);
|
||||||
if (_options.outlierEliminate != OUTLIER_ELIMINATE_DEFAULT)
|
if (_options.outlierEliminate != OUTLIER_ELIMINATE_DEFAULT)
|
||||||
settings.setValue(OUTLIER_ELIMINATE_SETTING, _options.outlierEliminate);
|
settings.setValue(OUTLIER_ELIMINATE_SETTING, _options.outlierEliminate);
|
||||||
|
if (_options.automaticPause != AUTOMATIC_PAUSE_DEFAULT)
|
||||||
|
settings.setValue(AUTOMATIC_PAUSE_SETTING, _options.automaticPause);
|
||||||
if (_options.pauseSpeed != PAUSE_SPEED_DEFAULT)
|
if (_options.pauseSpeed != PAUSE_SPEED_DEFAULT)
|
||||||
settings.setValue(PAUSE_SPEED_SETTING, _options.pauseSpeed);
|
settings.setValue(PAUSE_SPEED_SETTING, _options.pauseSpeed);
|
||||||
if (_options.pauseInterval != PAUSE_INTERVAL_DEFAULT)
|
if (_options.pauseInterval != PAUSE_INTERVAL_DEFAULT)
|
||||||
@ -2073,6 +2075,8 @@ void GUI::readSettings()
|
|||||||
USE_REPORTED_SPEED_DEFAULT).toBool();
|
USE_REPORTED_SPEED_DEFAULT).toBool();
|
||||||
_options.dataUseDEM = settings.value(DATA_USE_DEM_SETTING,
|
_options.dataUseDEM = settings.value(DATA_USE_DEM_SETTING,
|
||||||
DATA_USE_DEM_DEFAULT).toBool();
|
DATA_USE_DEM_DEFAULT).toBool();
|
||||||
|
_options.automaticPause = settings.value(AUTOMATIC_PAUSE_SETTING,
|
||||||
|
AUTOMATIC_PAUSE_DEFAULT).toBool();
|
||||||
_options.pauseInterval = settings.value(PAUSE_INTERVAL_SETTING,
|
_options.pauseInterval = settings.value(PAUSE_INTERVAL_SETTING,
|
||||||
PAUSE_INTERVAL_DEFAULT).toInt();
|
PAUSE_INTERVAL_DEFAULT).toInt();
|
||||||
_options.poiRadius = settings.value(POI_RADIUS_SETTING, POI_RADIUS_DEFAULT)
|
_options.poiRadius = settings.value(POI_RADIUS_SETTING, POI_RADIUS_DEFAULT)
|
||||||
@ -2154,6 +2158,7 @@ void GUI::readSettings()
|
|||||||
Track::setCadenceFilter(_options.cadenceFilter);
|
Track::setCadenceFilter(_options.cadenceFilter);
|
||||||
Track::setPowerFilter(_options.powerFilter);
|
Track::setPowerFilter(_options.powerFilter);
|
||||||
Track::setOutlierElimination(_options.outlierEliminate);
|
Track::setOutlierElimination(_options.outlierEliminate);
|
||||||
|
Track::setAutomaticPause(_options.automaticPause);
|
||||||
Track::setPauseSpeed(_options.pauseSpeed);
|
Track::setPauseSpeed(_options.pauseSpeed);
|
||||||
Track::setPauseInterval(_options.pauseInterval);
|
Track::setPauseInterval(_options.pauseInterval);
|
||||||
Track::useReportedSpeed(_options.useReportedSpeed);
|
Track::useReportedSpeed(_options.useReportedSpeed);
|
||||||
|
@ -7,10 +7,9 @@ HeartRateGraphItem::HeartRateGraphItem(const Graph &graph, GraphType type,
|
|||||||
int width, const QColor &color, QGraphicsItem *parent)
|
int width, const QColor &color, QGraphicsItem *parent)
|
||||||
: GraphItem(graph, type, width, color, parent)
|
: GraphItem(graph, type, width, color, parent)
|
||||||
{
|
{
|
||||||
setToolTip(toolTip());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString HeartRateGraphItem::toolTip() const
|
QString HeartRateGraphItem::info() const
|
||||||
{
|
{
|
||||||
ToolTip tt;
|
ToolTip tt;
|
||||||
QLocale l(QLocale::system());
|
QLocale l(QLocale::system());
|
||||||
|
@ -11,8 +11,7 @@ public:
|
|||||||
HeartRateGraphItem(const Graph &graph, GraphType type, int width,
|
HeartRateGraphItem(const Graph &graph, GraphType type, int width,
|
||||||
const QColor &color, QGraphicsItem *parent = 0);
|
const QColor &color, QGraphicsItem *parent = 0);
|
||||||
|
|
||||||
private:
|
QString info() const;
|
||||||
QString toolTip() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HEARTRATEGRAPHITEM_H
|
#endif // HEARTRATEGRAPHITEM_H
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "scaleitem.h"
|
#include "scaleitem.h"
|
||||||
#include "coordinatesitem.h"
|
#include "coordinatesitem.h"
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
|
#include "graphicsscene.h"
|
||||||
#include "mapview.h"
|
#include "mapview.h"
|
||||||
|
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
|
|||||||
Q_ASSERT(map != 0);
|
Q_ASSERT(map != 0);
|
||||||
Q_ASSERT(poi != 0);
|
Q_ASSERT(poi != 0);
|
||||||
|
|
||||||
_scene = new QGraphicsScene(this);
|
_scene = new GraphicsScene(this);
|
||||||
setScene(_scene);
|
setScene(_scene);
|
||||||
setDragMode(QGraphicsView::ScrollHandDrag);
|
setDragMode(QGraphicsView::ScrollHandDrag);
|
||||||
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
||||||
@ -215,12 +216,12 @@ QList<PathItem *> MapView::loadData(const Data &data)
|
|||||||
QList<PathItem *> paths;
|
QList<PathItem *> paths;
|
||||||
int zoom = _map->zoom();
|
int zoom = _map->zoom();
|
||||||
|
|
||||||
|
for (int i = 0; i < data.areas().count(); i++)
|
||||||
|
addArea(data.areas().at(i));
|
||||||
for (int i = 0; i < data.tracks().count(); i++)
|
for (int i = 0; i < data.tracks().count(); i++)
|
||||||
paths.append(addTrack(data.tracks().at(i)));
|
paths.append(addTrack(data.tracks().at(i)));
|
||||||
for (int i = 0; i < data.routes().count(); i++)
|
for (int i = 0; i < data.routes().count(); i++)
|
||||||
paths.append(addRoute(data.routes().at(i)));
|
paths.append(addRoute(data.routes().at(i)));
|
||||||
for (int i = 0; i < data.areas().count(); i++)
|
|
||||||
addArea(data.areas().at(i));
|
|
||||||
addWaypoints(data.waypoints());
|
addWaypoints(data.waypoints());
|
||||||
|
|
||||||
if (_tracks.empty() && _routes.empty() && _waypoints.empty()
|
if (_tracks.empty() && _routes.empty() && _waypoints.empty()
|
||||||
|
@ -30,6 +30,7 @@ class PathItem;
|
|||||||
class GraphItem;
|
class GraphItem;
|
||||||
class AreaItem;
|
class AreaItem;
|
||||||
class Area;
|
class Area;
|
||||||
|
class GraphicsScene;
|
||||||
|
|
||||||
class MapView : public QGraphicsView
|
class MapView : public QGraphicsView
|
||||||
{
|
{
|
||||||
@ -120,7 +121,7 @@ private:
|
|||||||
void mouseMoveEvent(QMouseEvent *event);
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
void leaveEvent(QEvent *event);
|
void leaveEvent(QEvent *event);
|
||||||
|
|
||||||
QGraphicsScene *_scene;
|
GraphicsScene *_scene;
|
||||||
ScaleItem *_mapScale;
|
ScaleItem *_mapScale;
|
||||||
CoordinatesItem *_coordinates;
|
CoordinatesItem *_coordinates;
|
||||||
QList<TrackItem*> _tracks;
|
QList<TrackItem*> _tracks;
|
||||||
|
@ -37,6 +37,12 @@ static QFrame *line()
|
|||||||
#endif // Q_OS_MAC
|
#endif // Q_OS_MAC
|
||||||
|
|
||||||
|
|
||||||
|
void OptionsDialog::automaticPauseDetectionSet(bool set)
|
||||||
|
{
|
||||||
|
_pauseInterval->setEnabled(!set);
|
||||||
|
_pauseSpeed->setEnabled(!set);
|
||||||
|
}
|
||||||
|
|
||||||
QWidget *OptionsDialog::createMapPage()
|
QWidget *OptionsDialog::createMapPage()
|
||||||
{
|
{
|
||||||
_projection = new LimitedComboBox(200);
|
_projection = new LimitedComboBox(200);
|
||||||
@ -343,10 +349,18 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
filterTab->setLayout(filterTabLayout);
|
filterTab->setLayout(filterTabLayout);
|
||||||
|
|
||||||
|
|
||||||
|
_automaticPause = new QRadioButton(tr("Automatic"));
|
||||||
|
_manualPause = new QRadioButton(tr("Custom"));
|
||||||
|
if (_options->automaticPause)
|
||||||
|
_automaticPause->setChecked(true);
|
||||||
|
else
|
||||||
|
_manualPause->setChecked(true);
|
||||||
|
|
||||||
_pauseSpeed = new QDoubleSpinBox();
|
_pauseSpeed = new QDoubleSpinBox();
|
||||||
_pauseSpeed->setDecimals(1);
|
_pauseSpeed->setDecimals(1);
|
||||||
_pauseSpeed->setSingleStep(0.1);
|
_pauseSpeed->setSingleStep(0.1);
|
||||||
_pauseSpeed->setMinimum(0.1);
|
_pauseSpeed->setMinimum(0.1);
|
||||||
|
_pauseSpeed->setEnabled(_manualPause->isChecked());
|
||||||
if (_options->units == Imperial) {
|
if (_options->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"));
|
||||||
@ -361,10 +375,26 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
_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());
|
||||||
|
|
||||||
QFormLayout *pauseLayout = new QFormLayout();
|
connect(_automaticPause, SIGNAL(toggled(bool)), this,
|
||||||
pauseLayout->addRow(tr("Minimal speed:"), _pauseSpeed);
|
SLOT(automaticPauseDetectionSet(bool)));
|
||||||
pauseLayout->addRow(tr("Minimal duration:"), _pauseInterval);
|
|
||||||
|
QHBoxLayout *pauseTypeLayout = new QHBoxLayout();
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
pauseTypeLayout->addStretch();
|
||||||
|
#endif
|
||||||
|
pauseTypeLayout->addWidget(_automaticPause);
|
||||||
|
pauseTypeLayout->addWidget(_manualPause);
|
||||||
|
pauseTypeLayout->addStretch();
|
||||||
|
|
||||||
|
QFormLayout *pauseValuesLayout = new QFormLayout();
|
||||||
|
pauseValuesLayout->addRow(tr("Minimal speed:"), _pauseSpeed);
|
||||||
|
pauseValuesLayout->addRow(tr("Minimal duration:"), _pauseInterval);
|
||||||
|
|
||||||
|
QVBoxLayout *pauseLayout = new QVBoxLayout();
|
||||||
|
pauseLayout->addLayout(pauseTypeLayout);
|
||||||
|
pauseLayout->addLayout(pauseValuesLayout);
|
||||||
|
|
||||||
QWidget *pauseTab = new QWidget();
|
QWidget *pauseTab = new QWidget();
|
||||||
pauseTab->setLayout(pauseLayout);
|
pauseTab->setLayout(pauseLayout);
|
||||||
@ -679,6 +709,7 @@ void OptionsDialog::accept()
|
|||||||
_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();
|
||||||
qreal pauseSpeed = (_options->units == Imperial)
|
qreal pauseSpeed = (_options->units == Imperial)
|
||||||
? _pauseSpeed->value() / MS2MIH : (_options->units == Nautical)
|
? _pauseSpeed->value() / MS2MIH : (_options->units == Nautical)
|
||||||
? _pauseSpeed->value() / MS2KN : _pauseSpeed->value() / MS2KMH;
|
? _pauseSpeed->value() / MS2KN : _pauseSpeed->value() / MS2KMH;
|
||||||
|
@ -49,6 +49,7 @@ struct Options {
|
|||||||
int cadenceFilter;
|
int cadenceFilter;
|
||||||
int powerFilter;
|
int powerFilter;
|
||||||
bool outlierEliminate;
|
bool outlierEliminate;
|
||||||
|
bool automaticPause;
|
||||||
qreal pauseSpeed;
|
qreal pauseSpeed;
|
||||||
int pauseInterval;
|
int pauseInterval;
|
||||||
bool useReportedSpeed;
|
bool useReportedSpeed;
|
||||||
@ -86,6 +87,9 @@ public slots:
|
|||||||
public:
|
public:
|
||||||
OptionsDialog(Options *options, QWidget *parent = 0);
|
OptionsDialog(Options *options, QWidget *parent = 0);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void automaticPauseDetectionSet(bool set);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWidget *createMapPage();
|
QWidget *createMapPage();
|
||||||
QWidget *createAppearancePage();
|
QWidget *createAppearancePage();
|
||||||
@ -129,6 +133,9 @@ private:
|
|||||||
OddSpinBox *_cadenceFilter;
|
OddSpinBox *_cadenceFilter;
|
||||||
OddSpinBox *_powerFilter;
|
OddSpinBox *_powerFilter;
|
||||||
QCheckBox *_outlierEliminate;
|
QCheckBox *_outlierEliminate;
|
||||||
|
|
||||||
|
QRadioButton *_automaticPause;
|
||||||
|
QRadioButton *_manualPause;
|
||||||
QDoubleSpinBox *_pauseSpeed;
|
QDoubleSpinBox *_pauseSpeed;
|
||||||
QSpinBox *_pauseInterval;
|
QSpinBox *_pauseInterval;
|
||||||
QRadioButton *_computedSpeed;
|
QRadioButton *_computedSpeed;
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include "common/greatcircle.h"
|
#include "common/greatcircle.h"
|
||||||
#include "map/map.h"
|
#include "map/map.h"
|
||||||
#include "pathtickitem.h"
|
#include "pathtickitem.h"
|
||||||
|
#include "popup.h"
|
||||||
#include "pathitem.h"
|
#include "pathitem.h"
|
||||||
|
|
||||||
|
|
||||||
@ -20,7 +22,7 @@ static inline unsigned segments(qreal distance)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PathItem::PathItem(const Path &path, Map *map, QGraphicsItem *parent)
|
PathItem::PathItem(const Path &path, Map *map, QGraphicsItem *parent)
|
||||||
: QGraphicsObject(parent), _path(path), _map(map)
|
: GraphicsItem(parent), _path(path), _map(map)
|
||||||
{
|
{
|
||||||
Q_ASSERT(_path.isValid());
|
Q_ASSERT(_path.isValid());
|
||||||
|
|
||||||
@ -38,6 +40,7 @@ PathItem::PathItem(const Path &path, Map *map, QGraphicsItem *parent)
|
|||||||
|
|
||||||
_markerDistance = _path.first().first().distance();
|
_markerDistance = _path.first().first().distance();
|
||||||
_marker = new MarkerItem(this);
|
_marker = new MarkerItem(this);
|
||||||
|
_marker->setZValue(1);
|
||||||
_marker->setPos(position(_markerDistance));
|
_marker->setPos(position(_markerDistance));
|
||||||
|
|
||||||
setCursor(Qt::ArrowCursor);
|
setCursor(Qt::ArrowCursor);
|
||||||
@ -336,7 +339,6 @@ void PathItem::updateTicks()
|
|||||||
_ticks[i] = new PathTickItem(tr, (i + 1) * ts, this);
|
_ticks[i] = new PathTickItem(tr, (i + 1) * ts, this);
|
||||||
_ticks[i]->setPos(position((i + 1) * ts * xInM()));
|
_ticks[i]->setPos(position((i + 1) * ts * xInM()));
|
||||||
_ticks[i]->setColor(_pen.color());
|
_ticks[i]->setColor(_pen.color());
|
||||||
_ticks[i]->setToolTip(toolTip());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,3 +383,9 @@ void PathItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
|||||||
|
|
||||||
emit selected(false);
|
emit selected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PathItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
Popup::show(event->screenPos(), info(), event->widget());
|
||||||
|
GraphicsItem::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
@ -6,16 +6,18 @@
|
|||||||
#include "data/path.h"
|
#include "data/path.h"
|
||||||
#include "markeritem.h"
|
#include "markeritem.h"
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
|
#include "graphicsscene.h"
|
||||||
|
|
||||||
class Map;
|
class Map;
|
||||||
class PathTickItem;
|
class PathTickItem;
|
||||||
|
|
||||||
class PathItem : public QGraphicsObject
|
class PathItem : public QObject, public GraphicsItem
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PathItem(const Path &path, Map *map, QGraphicsItem *parent = 0);
|
PathItem(const Path &path, Map *map, QGraphicsItem *parent = 0);
|
||||||
|
virtual ~PathItem() {}
|
||||||
|
|
||||||
QPainterPath shape() const {return _shape;}
|
QPainterPath shape() const {return _shape;}
|
||||||
QRectF boundingRect() const {return _shape.boundingRect();}
|
QRectF boundingRect() const {return _shape.boundingRect();}
|
||||||
@ -35,8 +37,6 @@ public:
|
|||||||
void showMarker(bool show);
|
void showMarker(bool show);
|
||||||
void showTicks(bool show);
|
void showTicks(bool show);
|
||||||
|
|
||||||
Units units() const {return _units;}
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void moveMarker(qreal distance);
|
void moveMarker(qreal distance);
|
||||||
void hover(bool hover);
|
void hover(bool hover);
|
||||||
@ -44,6 +44,13 @@ public slots:
|
|||||||
signals:
|
signals:
|
||||||
void selected(bool);
|
void selected(bool);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||||
|
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
|
||||||
|
Units _units;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const PathSegment *segment(qreal x) const;
|
const PathSegment *segment(qreal x) const;
|
||||||
QPointF position(qreal distance) const;
|
QPointF position(qreal distance) const;
|
||||||
@ -55,15 +62,11 @@ private:
|
|||||||
unsigned tickSize() const;
|
unsigned tickSize() const;
|
||||||
void updateTicks();
|
void updateTicks();
|
||||||
|
|
||||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
|
||||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
|
||||||
|
|
||||||
Path _path;
|
Path _path;
|
||||||
Map *_map;
|
Map *_map;
|
||||||
qreal _markerDistance;
|
qreal _markerDistance;
|
||||||
int _digitalZoom;
|
int _digitalZoom;
|
||||||
|
|
||||||
Units _units;
|
|
||||||
qreal _width;
|
qreal _width;
|
||||||
QPen _pen;
|
QPen _pen;
|
||||||
QPainterPath _shape;
|
QPainterPath _shape;
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
#include "popup.h"
|
||||||
|
#include "pathitem.h"
|
||||||
#include "pathtickitem.h"
|
#include "pathtickitem.h"
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +20,7 @@ static QFont defaultFont()
|
|||||||
QFont PathTickItem::_font = defaultFont();
|
QFont PathTickItem::_font = defaultFont();
|
||||||
|
|
||||||
PathTickItem::PathTickItem(const QRectF &tickRect, int value,
|
PathTickItem::PathTickItem(const QRectF &tickRect, int value,
|
||||||
QGraphicsItem *parent) : QGraphicsItem(parent), _tickRect(tickRect),
|
QGraphicsItem *parent) : GraphicsItem(parent), _tickRect(tickRect),
|
||||||
_text(QString::number(value))
|
_text(QString::number(value))
|
||||||
{
|
{
|
||||||
_tickRect.moveCenter(QPointF(0, -_tickRect.height()/2.0 - 3));
|
_tickRect.moveCenter(QPointF(0, -_tickRect.height()/2.0 - 3));
|
||||||
@ -69,3 +72,10 @@ QRect PathTickItem::tickRect(int value)
|
|||||||
return fm.boundingRect(QRect(), Qt::AlignCenter,
|
return fm.boundingRect(QRect(), Qt::AlignCenter,
|
||||||
QString::number(qMax(value, 10))).adjusted(-2, 0, 2, 0);
|
QString::number(qMax(value, 10))).adjusted(-2, 0, 2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PathTickItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
const PathItem *pi = static_cast<PathItem*>(parentItem());
|
||||||
|
Popup::show(event->screenPos(), pi->info(), event->widget());
|
||||||
|
QGraphicsItem::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
|
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QGraphicsItem>
|
#include <QGraphicsItem>
|
||||||
|
#include "graphicsscene.h"
|
||||||
|
|
||||||
class PathTickItem : public QGraphicsItem
|
class PathTickItem : public GraphicsItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PathTickItem(const QRectF &tickRect, int value, QGraphicsItem *parent = 0);
|
PathTickItem(const QRectF &tickRect, int value, QGraphicsItem *parent = 0);
|
||||||
@ -16,8 +17,14 @@ public:
|
|||||||
void setPos(const QPointF &pos);
|
void setPos(const QPointF &pos);
|
||||||
void setColor(const QColor &color) {_brush = QBrush(color);}
|
void setColor(const QColor &color) {_brush = QBrush(color);}
|
||||||
|
|
||||||
|
int type() const {return parentItem()->type();}
|
||||||
|
QString info() const {return static_cast<GraphicsItem*>(parentItem())->info();}
|
||||||
|
|
||||||
static QRect tickRect(int value);
|
static QRect tickRect(int value);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QRectF _tickRect;
|
QRectF _tickRect;
|
||||||
QString _text;
|
QString _text;
|
||||||
|
165
src/GUI/popup.cpp
Normal file
165
src/GUI/popup.cpp
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
#include <QToolTip>
|
||||||
|
#include <QStyle>
|
||||||
|
#include <QStylePainter>
|
||||||
|
#include <QStyleOptionFrame>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDesktopWidget>
|
||||||
|
#include <QBasicTimer>
|
||||||
|
#include "popup.h"
|
||||||
|
|
||||||
|
|
||||||
|
class PopupLabel : public QLabel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PopupLabel(const QString &text, QWidget *parent = 0);
|
||||||
|
~PopupLabel();
|
||||||
|
|
||||||
|
bool eventFilter(QObject *o, QEvent *ev);
|
||||||
|
void place(const QPoint &pos, QWidget *w);
|
||||||
|
void deleteAfterTimer();
|
||||||
|
void stopTimer() {_timer.stop();}
|
||||||
|
|
||||||
|
static PopupLabel *_instance;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *event);
|
||||||
|
void timerEvent(QTimerEvent *event);
|
||||||
|
void contextMenuEvent(QContextMenuEvent *) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QBasicTimer _timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
PopupLabel *PopupLabel::_instance = 0;
|
||||||
|
|
||||||
|
PopupLabel::PopupLabel(const QString &text, QWidget *parent)
|
||||||
|
: QLabel(text, parent, Qt::ToolTip | Qt::BypassGraphicsProxyWidget
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||||
|
| Qt::WindowDoesNotAcceptFocus
|
||||||
|
#endif // QT5
|
||||||
|
)
|
||||||
|
{
|
||||||
|
delete _instance;
|
||||||
|
_instance = this;
|
||||||
|
|
||||||
|
setForegroundRole(QPalette::ToolTipText);
|
||||||
|
setBackgroundRole(QPalette::ToolTipBase);
|
||||||
|
setPalette(QToolTip::palette());
|
||||||
|
ensurePolished();
|
||||||
|
setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0,
|
||||||
|
this));
|
||||||
|
setFrameStyle(QFrame::NoFrame);
|
||||||
|
setAlignment(Qt::AlignLeft);
|
||||||
|
setIndent(1);
|
||||||
|
setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0,
|
||||||
|
this) / 255.0);
|
||||||
|
|
||||||
|
setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||||
|
setOpenExternalLinks(true);
|
||||||
|
setWordWrap(true);
|
||||||
|
|
||||||
|
setMouseTracking(true);
|
||||||
|
|
||||||
|
qApp->installEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PopupLabel::~PopupLabel()
|
||||||
|
{
|
||||||
|
_instance = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopupLabel::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
QStylePainter p(this);
|
||||||
|
QStyleOptionFrame opt;
|
||||||
|
opt.init(this);
|
||||||
|
p.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
|
||||||
|
p.end();
|
||||||
|
QLabel::paintEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopupLabel::timerEvent(QTimerEvent *event)
|
||||||
|
{
|
||||||
|
if (event->timerId() == _timer.timerId()) {
|
||||||
|
_timer.stop();
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PopupLabel::eventFilter(QObject *o, QEvent *ev)
|
||||||
|
{
|
||||||
|
Q_UNUSED(o);
|
||||||
|
|
||||||
|
switch (ev->type()) {
|
||||||
|
case QEvent::KeyPress:
|
||||||
|
case QEvent::KeyRelease: {
|
||||||
|
const int key = static_cast<QKeyEvent *>(ev)->key();
|
||||||
|
if (key == Qt::Key_Escape) {
|
||||||
|
deleteLater();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QEvent::FocusIn:
|
||||||
|
case QEvent::FocusOut:
|
||||||
|
case QEvent::WindowActivate:
|
||||||
|
case QEvent::WindowDeactivate:
|
||||||
|
case QEvent::Close:
|
||||||
|
deleteLater();
|
||||||
|
break;
|
||||||
|
case QEvent::MouseMove: {
|
||||||
|
QRectF r(geometry().adjusted(-5, -20, 5, 20));
|
||||||
|
QPointF p(static_cast<QMouseEvent*>(ev)->globalPos());
|
||||||
|
if (!r.contains(p))
|
||||||
|
deleteAfterTimer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopupLabel::place(const QPoint &pos, QWidget *w)
|
||||||
|
{
|
||||||
|
QRect screen = QApplication::desktop()->screenGeometry(w);
|
||||||
|
QPoint p(pos.x() + 2, pos.y() + 16);
|
||||||
|
|
||||||
|
if (p.x() + width() > screen.x() + screen.width())
|
||||||
|
p.rx() -= 4 + width();
|
||||||
|
if (p.y() + height() > screen.y() + screen.height())
|
||||||
|
p.ry() -= 24 + height();
|
||||||
|
if (p.y() < screen.y())
|
||||||
|
p.setY(screen.y());
|
||||||
|
if (p.x() + width() > screen.x() + screen.width())
|
||||||
|
p.setX(screen.x() + screen.width() - width());
|
||||||
|
if (p.x() < screen.x())
|
||||||
|
p.setX(screen.x());
|
||||||
|
if (p.y() + height() > screen.y() + screen.height())
|
||||||
|
p.setY(screen.y() + screen.height() - height());
|
||||||
|
|
||||||
|
this->move(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopupLabel::deleteAfterTimer()
|
||||||
|
{
|
||||||
|
if (!_timer.isActive())
|
||||||
|
_timer.start(300, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Popup::show(const QPoint &pos, const QString &text, QWidget *w)
|
||||||
|
{
|
||||||
|
if (PopupLabel::_instance) {
|
||||||
|
PopupLabel::_instance->stopTimer();
|
||||||
|
PopupLabel::_instance->setText(text);
|
||||||
|
} else
|
||||||
|
PopupLabel::_instance = new PopupLabel(text);
|
||||||
|
|
||||||
|
PopupLabel::_instance->resize(PopupLabel::_instance->sizeHint());
|
||||||
|
PopupLabel::_instance->place(pos, w);
|
||||||
|
PopupLabel::_instance->showNormal();
|
||||||
|
}
|
14
src/GUI/popup.h
Normal file
14
src/GUI/popup.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef POPUP_H
|
||||||
|
#define POPUP_H
|
||||||
|
|
||||||
|
class QPoint;
|
||||||
|
class QString;
|
||||||
|
class QWidget;
|
||||||
|
|
||||||
|
class Popup
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void show(const QPoint &pos, const QString &text, QWidget *w);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // POPUP_H
|
@ -7,10 +7,9 @@ PowerGraphItem::PowerGraphItem(const Graph &graph, GraphType type, int width,
|
|||||||
const QColor &color, QGraphicsItem *parent)
|
const QColor &color, QGraphicsItem *parent)
|
||||||
: GraphItem(graph, type, width, color, parent)
|
: GraphItem(graph, type, width, color, parent)
|
||||||
{
|
{
|
||||||
setToolTip(toolTip());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PowerGraphItem::toolTip() const
|
QString PowerGraphItem::info() const
|
||||||
{
|
{
|
||||||
ToolTip tt;
|
ToolTip tt;
|
||||||
QLocale l(QLocale::system());
|
QLocale l(QLocale::system());
|
||||||
|
@ -11,8 +11,7 @@ public:
|
|||||||
PowerGraphItem(const Graph &graph, GraphType type, int width,
|
PowerGraphItem(const Graph &graph, GraphType type, int width,
|
||||||
const QColor &color, QGraphicsItem *parent = 0);
|
const QColor &color, QGraphicsItem *parent = 0);
|
||||||
|
|
||||||
private:
|
QString info() const;
|
||||||
QString toolTip() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // POWERGRAPHITEM_H
|
#endif // POWERGRAPHITEM_H
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "routeitem.h"
|
#include "routeitem.h"
|
||||||
|
|
||||||
|
|
||||||
QString RouteItem::toolTip(Units units) const
|
QString RouteItem::info() const
|
||||||
{
|
{
|
||||||
ToolTip tt;
|
ToolTip tt;
|
||||||
|
|
||||||
@ -16,7 +16,18 @@ QString RouteItem::toolTip(Units units) const
|
|||||||
if (!_desc.isEmpty())
|
if (!_desc.isEmpty())
|
||||||
tt.insert(tr("Description"), _desc);
|
tt.insert(tr("Description"), _desc);
|
||||||
tt.insert(tr("Distance"), Format::distance(path().last().last().distance(),
|
tt.insert(tr("Distance"), Format::distance(path().last().last().distance(),
|
||||||
units));
|
_units));
|
||||||
|
if (!_links.isEmpty()) {
|
||||||
|
QString links;
|
||||||
|
for (int i = 0; i < _links.size(); i++) {
|
||||||
|
const Link &link = _links.at(i);
|
||||||
|
links.append(QString("<a href=\"%0\">%1</a>").arg(link.URL(),
|
||||||
|
link.text().isEmpty() ? link.URL() : link.text()));
|
||||||
|
if (i != _links.size() - 1)
|
||||||
|
links.append("<br/>");
|
||||||
|
}
|
||||||
|
tt.insert(tr("Links"), links);
|
||||||
|
}
|
||||||
|
|
||||||
return tt.toString();
|
return tt.toString();
|
||||||
}
|
}
|
||||||
@ -32,9 +43,8 @@ RouteItem::RouteItem(const Route &route, Map *map, QGraphicsItem *parent)
|
|||||||
|
|
||||||
_name = route.name();
|
_name = route.name();
|
||||||
_desc = route.description();
|
_desc = route.description();
|
||||||
|
_links = route.links();
|
||||||
_coordinatesFormat = DecimalDegrees;
|
_coordinatesFormat = DecimalDegrees;
|
||||||
|
|
||||||
setToolTip(toolTip(Metric));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouteItem::setMap(Map *map)
|
void RouteItem::setMap(Map *map)
|
||||||
@ -47,15 +57,13 @@ void RouteItem::setMap(Map *map)
|
|||||||
|
|
||||||
void RouteItem::setUnits(Units u)
|
void RouteItem::setUnits(Units u)
|
||||||
{
|
{
|
||||||
if (units() == u)
|
if (_units == u)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PathItem::setUnits(u);
|
|
||||||
|
|
||||||
setToolTip(toolTip(units()));
|
|
||||||
|
|
||||||
for (int i = 0; i < _waypoints.count(); i++)
|
for (int i = 0; i < _waypoints.count(); i++)
|
||||||
_waypoints[i]->setToolTipFormat(units(), _coordinatesFormat);
|
_waypoints[i]->setToolTipFormat(u, _coordinatesFormat);
|
||||||
|
|
||||||
|
PathItem::setUnits(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouteItem::setCoordinatesFormat(CoordinatesFormat format)
|
void RouteItem::setCoordinatesFormat(CoordinatesFormat format)
|
||||||
@ -66,7 +74,7 @@ void RouteItem::setCoordinatesFormat(CoordinatesFormat format)
|
|||||||
_coordinatesFormat = format;
|
_coordinatesFormat = format;
|
||||||
|
|
||||||
for (int i = 0; i < _waypoints.count(); i++)
|
for (int i = 0; i < _waypoints.count(); i++)
|
||||||
_waypoints[i]->setToolTipFormat(units(), _coordinatesFormat);
|
_waypoints[i]->setToolTipFormat(_units, _coordinatesFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouteItem::showWaypoints(bool show)
|
void RouteItem::showWaypoints(bool show)
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "pathitem.h"
|
#include "pathitem.h"
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
#include "graphicsscene.h"
|
||||||
|
|
||||||
class Map;
|
class Map;
|
||||||
class WaypointItem;
|
class WaypointItem;
|
||||||
@ -23,11 +24,12 @@ public:
|
|||||||
void showWaypoints(bool show);
|
void showWaypoints(bool show);
|
||||||
void showWaypointLabels(bool show);
|
void showWaypointLabels(bool show);
|
||||||
|
|
||||||
private:
|
QString info() const;
|
||||||
QString toolTip(Units units) const;
|
|
||||||
|
|
||||||
|
private:
|
||||||
QString _name;
|
QString _name;
|
||||||
QString _desc;
|
QString _desc;
|
||||||
|
QVector<Link> _links;
|
||||||
CoordinatesFormat _coordinatesFormat;
|
CoordinatesFormat _coordinatesFormat;
|
||||||
|
|
||||||
QVector<WaypointItem*> _waypoints;
|
QVector<WaypointItem*> _waypoints;
|
||||||
|
@ -135,6 +135,8 @@
|
|||||||
#define POWER_FILTER_DEFAULT 3
|
#define POWER_FILTER_DEFAULT 3
|
||||||
#define OUTLIER_ELIMINATE_SETTING "outlierEliminate"
|
#define OUTLIER_ELIMINATE_SETTING "outlierEliminate"
|
||||||
#define OUTLIER_ELIMINATE_DEFAULT true
|
#define OUTLIER_ELIMINATE_DEFAULT true
|
||||||
|
#define AUTOMATIC_PAUSE_SETTING "automaticPause"
|
||||||
|
#define AUTOMATIC_PAUSE_DEFAULT true
|
||||||
#define PAUSE_SPEED_SETTING "pauseSpeed"
|
#define PAUSE_SPEED_SETTING "pauseSpeed"
|
||||||
#define PAUSE_SPEED_DEFAULT 0.5 /* m/s */
|
#define PAUSE_SPEED_DEFAULT 0.5 /* m/s */
|
||||||
#define PAUSE_INTERVAL_SETTING "pauseInterval"
|
#define PAUSE_INTERVAL_SETTING "pauseInterval"
|
||||||
@ -152,7 +154,7 @@
|
|||||||
#define ENABLE_HTTP2_SETTING "enableHTTP2"
|
#define ENABLE_HTTP2_SETTING "enableHTTP2"
|
||||||
#define ENABLE_HTTP2_DEFAULT true
|
#define ENABLE_HTTP2_DEFAULT true
|
||||||
#define PIXMAP_CACHE_SETTING "pixmapCache"
|
#define PIXMAP_CACHE_SETTING "pixmapCache"
|
||||||
#define PIXMAP_CACHE_DEFAULT 64 /* MB */
|
#define PIXMAP_CACHE_DEFAULT 256 /* MB */
|
||||||
#define CONNECTION_TIMEOUT_SETTING "connectionTimeout"
|
#define CONNECTION_TIMEOUT_SETTING "connectionTimeout"
|
||||||
#define CONNECTION_TIMEOUT_DEFAULT 30 /* s */
|
#define CONNECTION_TIMEOUT_DEFAULT 30 /* s */
|
||||||
#define HIRES_PRINT_SETTING "hiresPrint"
|
#define HIRES_PRINT_SETTING "hiresPrint"
|
||||||
|
@ -8,17 +8,14 @@ SpeedGraphItem::SpeedGraphItem(const Graph &graph, GraphType type, int width,
|
|||||||
const QColor &color, qreal movingTime, QGraphicsItem *parent)
|
const QColor &color, qreal movingTime, QGraphicsItem *parent)
|
||||||
: GraphItem(graph, type, width, color, parent)
|
: GraphItem(graph, type, width, color, parent)
|
||||||
{
|
{
|
||||||
_units = Metric;
|
|
||||||
_timeType = Total;
|
_timeType = Total;
|
||||||
|
|
||||||
_max = GraphItem::max();
|
_max = GraphItem::max();
|
||||||
_avg = graph.last().last().s() / graph.last().last().t();
|
_avg = graph.last().last().s() / graph.last().last().t();
|
||||||
_mavg = graph.last().last().s() / movingTime;
|
_mavg = graph.last().last().s() / movingTime;
|
||||||
|
|
||||||
setToolTip(toolTip());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SpeedGraphItem::toolTip() const
|
QString SpeedGraphItem::info() const
|
||||||
{
|
{
|
||||||
ToolTip tt;
|
ToolTip tt;
|
||||||
qreal scale = (_units == Imperial) ? MS2MIH : (_units == Nautical)
|
qreal scale = (_units == Imperial) ? MS2MIH : (_units == Nautical)
|
||||||
@ -40,14 +37,7 @@ QString SpeedGraphItem::toolTip() const
|
|||||||
return tt.toString();
|
return tt.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpeedGraphItem::setUnits(Units units)
|
|
||||||
{
|
|
||||||
_units = units;
|
|
||||||
setToolTip(toolTip());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpeedGraphItem::setTimeType(TimeType type)
|
void SpeedGraphItem::setTimeType(TimeType type)
|
||||||
{
|
{
|
||||||
_timeType = type;
|
_timeType = type;
|
||||||
setToolTip(toolTip());
|
|
||||||
}
|
}
|
||||||
|
@ -16,15 +16,13 @@ public:
|
|||||||
qreal mavg() const {return _mavg;}
|
qreal mavg() const {return _mavg;}
|
||||||
qreal max() const {return _max;}
|
qreal max() const {return _max;}
|
||||||
|
|
||||||
void setUnits(Units units);
|
QString info() const;
|
||||||
|
|
||||||
void setTimeType(TimeType type);
|
void setTimeType(TimeType type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString toolTip() const;
|
|
||||||
|
|
||||||
qreal _avg, _mavg, _max;
|
qreal _avg, _mavg, _max;
|
||||||
TimeType _timeType;
|
TimeType _timeType;
|
||||||
Units _units;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SPEEDGRAPHITEM_H
|
#endif // SPEEDGRAPHITEM_H
|
||||||
|
@ -10,16 +10,14 @@ TemperatureGraphItem::TemperatureGraphItem(const Graph &graph, GraphType type,
|
|||||||
_min = GraphItem::min();
|
_min = GraphItem::min();
|
||||||
_max = GraphItem::max();
|
_max = GraphItem::max();
|
||||||
_avg = GraphItem::avg();
|
_avg = GraphItem::avg();
|
||||||
|
|
||||||
setToolTip(toolTip(Metric));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TemperatureGraphItem::toolTip(Units units) const
|
QString TemperatureGraphItem::info() const
|
||||||
{
|
{
|
||||||
ToolTip tt;
|
ToolTip tt;
|
||||||
qreal scale = (units == Metric) ? 1.0 : C2FS;
|
qreal scale = (_units == Metric) ? 1.0 : C2FS;
|
||||||
qreal offset = (units == Metric) ? 0 : C2FO;
|
qreal offset = (_units == Metric) ? 0 : C2FO;
|
||||||
QString su = (units == Metric) ?
|
QString su = (_units == Metric) ?
|
||||||
QChar(0x00B0) + tr("C") : QChar(0x00B0) + tr("F");
|
QChar(0x00B0) + tr("C") : QChar(0x00B0) + tr("F");
|
||||||
QLocale l(QLocale::system());
|
QLocale l(QLocale::system());
|
||||||
|
|
||||||
@ -32,8 +30,3 @@ QString TemperatureGraphItem::toolTip(Units units) const
|
|||||||
|
|
||||||
return tt.toString();
|
return tt.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemperatureGraphItem::setUnits(Units units)
|
|
||||||
{
|
|
||||||
setToolTip(toolTip(units));
|
|
||||||
}
|
|
||||||
|
@ -15,11 +15,9 @@ public:
|
|||||||
qreal min() const {return _min;}
|
qreal min() const {return _min;}
|
||||||
qreal avg() const {return _avg;}
|
qreal avg() const {return _avg;}
|
||||||
|
|
||||||
void setUnits(Units units);
|
QString info() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString toolTip(Units units) const;
|
|
||||||
|
|
||||||
qreal _min, _max, _avg;
|
qreal _min, _max, _avg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,21 @@
|
|||||||
#include <QImageReader>
|
#include "popup.h"
|
||||||
#include "tooltip.h"
|
#include "tooltip.h"
|
||||||
|
|
||||||
|
static QSize thumbnailSize(const ImageInfo &img, int limit)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
if (img.size().width() > img.size().height()) {
|
||||||
|
width = qMin(img.size().width(), limit);
|
||||||
|
qreal ratio = img.size().width() / (qreal)img.size().height();
|
||||||
|
height = (int)(width / ratio);
|
||||||
|
} else {
|
||||||
|
height = qMin(img.size().height(), limit);
|
||||||
|
qreal ratio = img.size().height() / (qreal)img.size().width();
|
||||||
|
width = (int)(height / ratio);
|
||||||
|
}
|
||||||
|
|
||||||
#define THUMBNAIL_MAX_SIZE 240
|
return QSize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
void ToolTip::insert(const QString &key, const QString &value)
|
void ToolTip::insert(const QString &key, const QString &value)
|
||||||
{
|
{
|
||||||
@ -13,21 +26,17 @@ QString ToolTip::toString() const
|
|||||||
{
|
{
|
||||||
QString html;
|
QString html;
|
||||||
|
|
||||||
if (_img.isValid()) {
|
if (_images.size()) {
|
||||||
int width, height;
|
html = "<div align=\"center\">";
|
||||||
if (_img.size().width() > _img.size().height()) {
|
for (int i = 0; i < _images.size(); i++) {
|
||||||
width = qMin(_img.size().width(), THUMBNAIL_MAX_SIZE);
|
const ImageInfo &img = _images.at(i);
|
||||||
qreal ratio = _img.size().width() / (qreal)_img.size().height();
|
QSize size(thumbnailSize(img, qMin(960/_images.size(), 240)));
|
||||||
height = (int)(width / ratio);
|
|
||||||
} else {
|
|
||||||
height = qMin(_img.size().height(), THUMBNAIL_MAX_SIZE);
|
|
||||||
qreal ratio = _img.size().height() / (qreal)_img.size().width();
|
|
||||||
width = (int)(height / ratio);
|
|
||||||
}
|
|
||||||
|
|
||||||
html += "<div align=\"center\">";
|
html += QString("<a href=\"file:%0\">"
|
||||||
html += QString("<img src=\"file:%0\" width=\"%1\" height=\"%2\"/>")
|
"<img src=\"%0\" width=\"%1\" height=\"%2\"/></a>")
|
||||||
.arg(_img.path(), QString::number(width), QString::number(height));
|
.arg(img.path(), QString::number(size.width()),
|
||||||
|
QString::number(size.height()));
|
||||||
|
}
|
||||||
html += "</div>";
|
html += "</div>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QVector>
|
||||||
#include "common/kv.h"
|
#include "common/kv.h"
|
||||||
#include "data/imageinfo.h"
|
#include "data/imageinfo.h"
|
||||||
|
|
||||||
@ -10,12 +11,12 @@ class ToolTip
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void insert(const QString &key, const QString &value);
|
void insert(const QString &key, const QString &value);
|
||||||
void setImage(const ImageInfo &image) {_img = image;}
|
void setImages(const QVector<ImageInfo> &images) {_images = images;}
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<KV<QString, QString> > _list;
|
QList<KV<QString, QString> > _list;
|
||||||
ImageInfo _img;
|
QVector<ImageInfo> _images;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TOOLTIP_H
|
#endif // TOOLTIP_H
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "trackitem.h"
|
#include "trackitem.h"
|
||||||
|
|
||||||
|
|
||||||
QString TrackItem::toolTip(Units units) const
|
QString TrackItem::info() const
|
||||||
{
|
{
|
||||||
ToolTip tt;
|
ToolTip tt;
|
||||||
|
|
||||||
@ -14,13 +14,24 @@ QString TrackItem::toolTip(Units units) const
|
|||||||
if (!_desc.isEmpty())
|
if (!_desc.isEmpty())
|
||||||
tt.insert(tr("Description"), _desc);
|
tt.insert(tr("Description"), _desc);
|
||||||
tt.insert(tr("Distance"), Format::distance(path().last().last().distance(),
|
tt.insert(tr("Distance"), Format::distance(path().last().last().distance(),
|
||||||
units));
|
_units));
|
||||||
if (_time > 0)
|
if (_time > 0)
|
||||||
tt.insert(tr("Total time"), Format::timeSpan(_time));
|
tt.insert(tr("Total time"), Format::timeSpan(_time));
|
||||||
if (_movingTime > 0)
|
if (_movingTime > 0)
|
||||||
tt.insert(tr("Moving time"), Format::timeSpan(_movingTime));
|
tt.insert(tr("Moving time"), Format::timeSpan(_movingTime));
|
||||||
if (!_date.isNull())
|
if (!_date.isNull())
|
||||||
tt.insert(tr("Date"), _date.toString(Qt::SystemLocaleShortDate));
|
tt.insert(tr("Date"), _date.toString(Qt::SystemLocaleShortDate));
|
||||||
|
if (!_links.isEmpty()) {
|
||||||
|
QString links;
|
||||||
|
for (int i = 0; i < _links.size(); i++) {
|
||||||
|
const Link &link = _links.at(i);
|
||||||
|
links.append(QString("<a href=\"%0\">%1</a>").arg(link.URL(),
|
||||||
|
link.text().isEmpty() ? link.URL() : link.text()));
|
||||||
|
if (i != _links.size() - 1)
|
||||||
|
links.append("<br/>");
|
||||||
|
}
|
||||||
|
tt.insert(tr("Links"), links);
|
||||||
|
}
|
||||||
|
|
||||||
return tt.toString();
|
return tt.toString();
|
||||||
}
|
}
|
||||||
@ -30,15 +41,8 @@ TrackItem::TrackItem(const Track &track, Map *map, QGraphicsItem *parent)
|
|||||||
{
|
{
|
||||||
_name = track.name();
|
_name = track.name();
|
||||||
_desc = track.description();
|
_desc = track.description();
|
||||||
|
_links = track.links();
|
||||||
_date = track.date();
|
_date = track.date();
|
||||||
_time = track.time();
|
_time = track.time();
|
||||||
_movingTime = track.movingTime();
|
_movingTime = track.movingTime();
|
||||||
|
|
||||||
setToolTip(toolTip(Metric));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TrackItem::setUnits(Units units)
|
|
||||||
{
|
|
||||||
PathItem::setUnits(units);
|
|
||||||
setToolTip(toolTip(units));
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "data/track.h"
|
#include "data/track.h"
|
||||||
#include "pathitem.h"
|
#include "pathitem.h"
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
|
#include "graphicsscene.h"
|
||||||
|
|
||||||
class Map;
|
class Map;
|
||||||
|
|
||||||
@ -16,13 +17,12 @@ class TrackItem : public PathItem
|
|||||||
public:
|
public:
|
||||||
TrackItem(const Track &track, Map *map, QGraphicsItem *parent = 0);
|
TrackItem(const Track &track, Map *map, QGraphicsItem *parent = 0);
|
||||||
|
|
||||||
void setUnits(Units units);
|
QString info() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString toolTip(Units units) const;
|
|
||||||
|
|
||||||
QString _name;
|
QString _name;
|
||||||
QString _desc;
|
QString _desc;
|
||||||
|
QVector<Link> _links;
|
||||||
QDateTime _date;
|
QDateTime _date;
|
||||||
qreal _time;
|
qreal _time;
|
||||||
qreal _movingTime;
|
qreal _movingTime;
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QGraphicsSceneMouseEvent>
|
||||||
|
#include <QLabel>
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "tooltip.h"
|
#include "tooltip.h"
|
||||||
|
#include "popup.h"
|
||||||
#include "waypointitem.h"
|
#include "waypointitem.h"
|
||||||
|
|
||||||
|
|
||||||
@ -10,30 +13,54 @@
|
|||||||
#define FS(size) \
|
#define FS(size) \
|
||||||
((int)((qreal)size * 1.41))
|
((int)((qreal)size * 1.41))
|
||||||
|
|
||||||
QString WaypointItem::toolTip(Units units, CoordinatesFormat format)
|
QString WaypointItem::info() const
|
||||||
{
|
{
|
||||||
ToolTip tt;
|
ToolTip tt;
|
||||||
|
|
||||||
if (!_waypoint.name().isEmpty())
|
if (!_waypoint.name().isEmpty())
|
||||||
tt.insert(qApp->translate("WaypointItem", "Name"), _waypoint.name());
|
tt.insert(qApp->translate("WaypointItem", "Name"), _waypoint.name());
|
||||||
tt.insert(qApp->translate("WaypointItem", "Coordinates"),
|
tt.insert(qApp->translate("WaypointItem", "Coordinates"),
|
||||||
Format::coordinates(_waypoint.coordinates(), format));
|
Format::coordinates(_waypoint.coordinates(), _format));
|
||||||
if (_waypoint.hasElevation())
|
if (_waypoint.hasElevation())
|
||||||
tt.insert(qApp->translate("WaypointItem", "Elevation"),
|
tt.insert(qApp->translate("WaypointItem", "Elevation"),
|
||||||
Format::elevation(_waypoint.elevation(), units));
|
Format::elevation(_waypoint.elevation(), _units));
|
||||||
if (_waypoint.timestamp().isValid())
|
if (_waypoint.timestamp().isValid())
|
||||||
tt.insert(qApp->translate("WaypointItem", "Date"),
|
tt.insert(qApp->translate("WaypointItem", "Date"),
|
||||||
_waypoint.timestamp().toString(Qt::SystemLocaleShortDate));
|
_waypoint.timestamp().toString(Qt::SystemLocaleShortDate));
|
||||||
if (!_waypoint.description().isEmpty())
|
if (!_waypoint.description().isEmpty())
|
||||||
tt.insert(qApp->translate("WaypointItem", "Description"),
|
tt.insert(qApp->translate("WaypointItem", "Description"),
|
||||||
_waypoint.description());
|
_waypoint.description());
|
||||||
tt.setImage(_waypoint.image());
|
if (_waypoint.address().isValid()) {
|
||||||
|
QString addr("<address>");
|
||||||
|
addr += _waypoint.address().street();
|
||||||
|
addr += "<br/>" + _waypoint.address().city();
|
||||||
|
if (!_waypoint.address().postalCode().isEmpty())
|
||||||
|
addr += "<br/>" + _waypoint.address().postalCode();
|
||||||
|
if (!_waypoint.address().state().isEmpty())
|
||||||
|
addr += "<br/>" + _waypoint.address().state();
|
||||||
|
if (!_waypoint.address().country().isEmpty())
|
||||||
|
addr += "<br/>" + _waypoint.address().country();
|
||||||
|
addr += "</address>";
|
||||||
|
tt.insert(qApp->translate("WaypointItem", "Address"), addr);
|
||||||
|
}
|
||||||
|
if (!_waypoint.links().isEmpty()) {
|
||||||
|
QString links;
|
||||||
|
for (int i = 0; i < _waypoint.links().size(); i++) {
|
||||||
|
const Link &link = _waypoint.links().at(i);
|
||||||
|
links.append(QString("<a href=\"%0\">%1</a>").arg(link.URL(),
|
||||||
|
link.text().isEmpty() ? link.URL() : link.text()));
|
||||||
|
if (i != _waypoint.links().size() - 1)
|
||||||
|
links.append("<br/>");
|
||||||
|
}
|
||||||
|
tt.insert(qApp->translate("WaypointItem", "Links"), links);
|
||||||
|
}
|
||||||
|
tt.setImages(_waypoint.images());
|
||||||
|
|
||||||
return tt.toString();
|
return tt.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map,
|
WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map,
|
||||||
QGraphicsItem *parent) : QGraphicsItem(parent)
|
QGraphicsItem *parent) : GraphicsItem(parent)
|
||||||
{
|
{
|
||||||
_waypoint = waypoint;
|
_waypoint = waypoint;
|
||||||
_showLabel = true;
|
_showLabel = true;
|
||||||
@ -43,10 +70,12 @@ WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map,
|
|||||||
_font.setPixelSize(FS(_size));
|
_font.setPixelSize(FS(_size));
|
||||||
_font.setFamily(FONT_FAMILY);
|
_font.setFamily(FONT_FAMILY);
|
||||||
|
|
||||||
|
_units = Metric;
|
||||||
|
_format = DecimalDegrees;
|
||||||
|
|
||||||
updateCache();
|
updateCache();
|
||||||
|
|
||||||
setPos(map->ll2xy(waypoint.coordinates()));
|
setPos(map->ll2xy(waypoint.coordinates()));
|
||||||
setToolTip(toolTip(Metric, DecimalDegrees));
|
|
||||||
setCursor(Qt::ArrowCursor);
|
setCursor(Qt::ArrowCursor);
|
||||||
setAcceptHoverEvents(true);
|
setAcceptHoverEvents(true);
|
||||||
}
|
}
|
||||||
@ -116,7 +145,8 @@ void WaypointItem::setColor(const QColor &color)
|
|||||||
|
|
||||||
void WaypointItem::setToolTipFormat(Units units, CoordinatesFormat format)
|
void WaypointItem::setToolTipFormat(Units units, CoordinatesFormat format)
|
||||||
{
|
{
|
||||||
setToolTip(toolTip(units, format));
|
_units = units;
|
||||||
|
_format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaypointItem::showLabel(bool show)
|
void WaypointItem::showLabel(bool show)
|
||||||
@ -148,3 +178,10 @@ void WaypointItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
|||||||
updateCache();
|
updateCache();
|
||||||
setZValue(zValue() - 1.0);
|
setZValue(zValue() - 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WaypointItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
Popup::show(event->screenPos(), info(), event->widget());
|
||||||
|
/* Do not propagate the event any further as lower stacked items (path
|
||||||
|
items) would replace the popup with their own popup */
|
||||||
|
}
|
||||||
|
@ -3,12 +3,15 @@
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <QGraphicsItem>
|
#include <QGraphicsItem>
|
||||||
|
#include <QFont>
|
||||||
#include "data/waypoint.h"
|
#include "data/waypoint.h"
|
||||||
#include "map/map.h"
|
#include "map/map.h"
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
|
#include "graphicsscene.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
|
||||||
class WaypointItem : public QGraphicsItem
|
|
||||||
|
class WaypointItem : public GraphicsItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WaypointItem(const Waypoint &waypoint, Map *map, QGraphicsItem *parent = 0);
|
WaypointItem(const Waypoint &waypoint, Map *map, QGraphicsItem *parent = 0);
|
||||||
@ -16,23 +19,26 @@ public:
|
|||||||
const Waypoint &waypoint() const {return _waypoint;}
|
const Waypoint &waypoint() const {return _waypoint;}
|
||||||
|
|
||||||
void setMap(Map *map) {setPos(map->ll2xy(_waypoint.coordinates()));}
|
void setMap(Map *map) {setPos(map->ll2xy(_waypoint.coordinates()));}
|
||||||
void setToolTipFormat(Units units, CoordinatesFormat format);
|
|
||||||
void setSize(int size);
|
void setSize(int size);
|
||||||
void setColor(const QColor &color);
|
void setColor(const QColor &color);
|
||||||
void showLabel(bool show);
|
void showLabel(bool show);
|
||||||
void setDigitalZoom(int zoom) {setScale(pow(2, -zoom));}
|
void setDigitalZoom(int zoom) {setScale(pow(2, -zoom));}
|
||||||
|
void setToolTipFormat(Units units, CoordinatesFormat format);
|
||||||
|
|
||||||
QPainterPath shape() const {return _shape;}
|
QPainterPath shape() const {return _shape;}
|
||||||
QRectF boundingRect() const {return _shape.boundingRect();}
|
QRectF boundingRect() const {return _shape.boundingRect();}
|
||||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||||
QWidget *widget);
|
QWidget *widget);
|
||||||
|
|
||||||
private:
|
QString info() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
|
||||||
|
private:
|
||||||
void updateCache();
|
void updateCache();
|
||||||
QString toolTip(Units units, CoordinatesFormat format);
|
|
||||||
|
|
||||||
Waypoint _waypoint;
|
Waypoint _waypoint;
|
||||||
QPainterPath _shape;
|
QPainterPath _shape;
|
||||||
@ -41,6 +47,9 @@ private:
|
|||||||
bool _showLabel;
|
bool _showLabel;
|
||||||
QFont _font;
|
QFont _font;
|
||||||
QRect _labelBB;
|
QRect _labelBB;
|
||||||
|
|
||||||
|
Units _units;
|
||||||
|
CoordinatesFormat _format;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WAYPOINTITEM_H
|
#endif // WAYPOINTITEM_H
|
||||||
|
18
src/common/garmin.h
Normal file
18
src/common/garmin.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef GARMIN_H
|
||||||
|
#define GARMIN_H
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
inline double toWGS32(qint32 v)
|
||||||
|
{
|
||||||
|
return (double)(((double)v / (double)(1U<<31)) * (double)180);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double toWGS24(qint32 v)
|
||||||
|
{
|
||||||
|
return (v < 0x800000)
|
||||||
|
? (double)v * 360.0 / (double)(1U<<24)
|
||||||
|
: (double)(v - 0x1000000) * 360.0 / (double)(1<<24);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GARMIN_H
|
35
src/data/address.h
Normal file
35
src/data/address.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef ADDRESS_H
|
||||||
|
#define ADDRESS_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class Address
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Address() {}
|
||||||
|
Address(const QString &street, const QString &city)
|
||||||
|
: _street(street), _city(city) {}
|
||||||
|
|
||||||
|
const QString &street() const {return _street;}
|
||||||
|
const QString &city() const {return _city;}
|
||||||
|
const QString &state() const {return _state;}
|
||||||
|
const QString &country() const {return _country;}
|
||||||
|
const QString &postalCode() const {return _postalCode;}
|
||||||
|
|
||||||
|
void setStreet(const QString &street) {_street = street;}
|
||||||
|
void setCity(const QString &city) {_city = city;}
|
||||||
|
void setState(const QString &state) {_state = state;}
|
||||||
|
void setCountry(const QString &country) {_country = country;}
|
||||||
|
void setPostalCode(const QString &postalCode) {_postalCode = postalCode;}
|
||||||
|
|
||||||
|
bool isValid() const {return !(_street.isEmpty() || _city.isEmpty());}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString _street;
|
||||||
|
QString _city;
|
||||||
|
QString _state;
|
||||||
|
QString _country;
|
||||||
|
QString _postalCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ADDRESS_H
|
@ -18,6 +18,7 @@
|
|||||||
#endif // ENABLE_GEOJSON
|
#endif // ENABLE_GEOJSON
|
||||||
#include "exifparser.h"
|
#include "exifparser.h"
|
||||||
#include "cupparser.h"
|
#include "cupparser.h"
|
||||||
|
#include "gpiparser.h"
|
||||||
#include "dem.h"
|
#include "dem.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
|
||||||
@ -39,6 +40,7 @@ static GeoJSONParser geojson;
|
|||||||
#endif // ENABLE_GEOJSON
|
#endif // ENABLE_GEOJSON
|
||||||
static EXIFParser exif;
|
static EXIFParser exif;
|
||||||
static CUPParser cup;
|
static CUPParser cup;
|
||||||
|
static GPIParser gpi;
|
||||||
|
|
||||||
static QHash<QString, Parser*> parsers()
|
static QHash<QString, Parser*> parsers()
|
||||||
{
|
{
|
||||||
@ -63,6 +65,7 @@ static QHash<QString, Parser*> parsers()
|
|||||||
hash.insert("jpeg", &exif);
|
hash.insert("jpeg", &exif);
|
||||||
hash.insert("jpg", &exif);
|
hash.insert("jpg", &exif);
|
||||||
hash.insert("cup", &cup);
|
hash.insert("cup", &cup);
|
||||||
|
hash.insert("gpi", &gpi);
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
@ -177,6 +180,7 @@ QString Data::formats()
|
|||||||
#ifdef ENABLE_GEOJSON
|
#ifdef ENABLE_GEOJSON
|
||||||
+ qApp->translate("Data", "GeoJSON files") + " (*.geojson *.json);;"
|
+ qApp->translate("Data", "GeoJSON files") + " (*.geojson *.json);;"
|
||||||
#endif // ENABLE_GEOJSON
|
#endif // ENABLE_GEOJSON
|
||||||
|
+ qApp->translate("Data", "GPI files") + " (*.gpi);;"
|
||||||
+ qApp->translate("Data", "GPX files") + " (*.gpx);;"
|
+ qApp->translate("Data", "GPX files") + " (*.gpx);;"
|
||||||
+ qApp->translate("Data", "IGC files") + " (*.igc);;"
|
+ qApp->translate("Data", "IGC files") + " (*.igc);;"
|
||||||
+ qApp->translate("Data", "JPEG images") + " (*.jpg *.jpeg);;"
|
+ qApp->translate("Data", "JPEG images") + " (*.jpg *.jpeg);;"
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
#include <QtEndian>
|
#include <QtEndian>
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||||
|
#include <QtCore/qmath.h>
|
||||||
|
#else // QT5
|
||||||
|
#include <QtMath>
|
||||||
|
#endif // QT5
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include "common/coordinates.h"
|
#include "common/coordinates.h"
|
||||||
@ -37,10 +42,10 @@ static qreal height(const Coordinates &c, const QByteArray *data)
|
|||||||
else
|
else
|
||||||
return NAN;
|
return NAN;
|
||||||
|
|
||||||
int row = (int)((c.lat() - (int)c.lat()) * (samples - 1));
|
int row = (int)((c.lat() - qFloor(c.lat())) * (samples - 1));
|
||||||
int col = (int)((c.lon() - (int)c.lon()) * (samples - 1));
|
int col = (int)((c.lon() - qFloor(c.lon())) * (samples - 1));
|
||||||
qreal dx = ((c.lon() - (int)c.lon()) * (samples - 1)) - col;
|
qreal dx = ((c.lon() - qFloor(c.lon())) * (samples - 1)) - col;
|
||||||
qreal dy = ((c.lat() - (int)c.lat()) * (samples - 1)) - row;
|
qreal dy = ((c.lat() - qFloor(c.lat())) * (samples - 1)) - row;
|
||||||
|
|
||||||
qreal p0 = value(col, row, samples, data);
|
qreal p0 = value(col, row, samples, data);
|
||||||
qreal p1 = value(col + 1, row, samples, data);
|
qreal p1 = value(col + 1, row, samples, data);
|
||||||
@ -75,7 +80,7 @@ qreal DEM::elevation(const Coordinates &c)
|
|||||||
if (_dir.isEmpty())
|
if (_dir.isEmpty())
|
||||||
return NAN;
|
return NAN;
|
||||||
|
|
||||||
Key k((int)c.lon(), (int)c.lat());
|
Key k(qFloor(c.lon()), qFloor(c.lat()));
|
||||||
|
|
||||||
QByteArray *ba = _data[k];
|
QByteArray *ba = _data[k];
|
||||||
if (!ba) {
|
if (!ba) {
|
||||||
|
@ -209,7 +209,7 @@ bool EXIFParser::parseTIFF(QFile *file, QVector<Waypoint> &waypoints)
|
|||||||
|
|
||||||
Waypoint wp(c);
|
Waypoint wp(c);
|
||||||
wp.setName(QFileInfo(file->fileName()).baseName());
|
wp.setName(QFileInfo(file->fileName()).baseName());
|
||||||
wp.setImage(img);
|
wp.addImage(img);
|
||||||
wp.setElevation(altitude(tiff, GPSIFD.value(GPSAltitude),
|
wp.setElevation(altitude(tiff, GPSIFD.value(GPSAltitude),
|
||||||
GPSIFD.value(GPSAltitudeRef)));
|
GPSIFD.value(GPSAltitudeRef)));
|
||||||
wp.setTimestamp(QDateTime(QDate::fromString(text(tiff,
|
wp.setTimestamp(QDateTime(QDate::fromString(text(tiff,
|
||||||
|
749
src/data/gpiparser.cpp
Normal file
749
src/data/gpiparser.cpp
Normal file
@ -0,0 +1,749 @@
|
|||||||
|
#include <QDataStream>
|
||||||
|
#include <QTextCodec>
|
||||||
|
#include <QtEndian>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QBuffer>
|
||||||
|
#include <QImageReader>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||||
|
#include <QTemporaryDir>
|
||||||
|
#endif // QT_VERSION >= 5
|
||||||
|
#include "common/garmin.h"
|
||||||
|
#include "gpiparser.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct RecordHeader {
|
||||||
|
quint16 type;
|
||||||
|
quint16 flags;
|
||||||
|
quint32 size;
|
||||||
|
quint32 extra;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TranslatedString {
|
||||||
|
public:
|
||||||
|
TranslatedString() {}
|
||||||
|
TranslatedString(const QString &lang, const QString &str)
|
||||||
|
: _lang(lang), _str(str) {}
|
||||||
|
|
||||||
|
const QString &str() const {return _str;}
|
||||||
|
const QString &lang() const {return _lang;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString _lang;
|
||||||
|
QString _str;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CryptDevice : public QIODevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CryptDevice(QIODevice *device, quint32 key, quint32 blockSize,
|
||||||
|
QObject *parent = 0);
|
||||||
|
bool isSequential() const {return true;}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
qint64 readData(char *data, qint64 maxSize);
|
||||||
|
qint64 writeData(const char *, qint64) {return -1;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QIODevice *_device;
|
||||||
|
quint32 _key;
|
||||||
|
QByteArray _block;
|
||||||
|
int _available;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void demangle(quint8 *data, quint32 size, quint32 key)
|
||||||
|
{
|
||||||
|
static const unsigned char shuf[] = {
|
||||||
|
0xb, 0xc, 0xa, 0x0,
|
||||||
|
0x8, 0xf, 0x2, 0x1,
|
||||||
|
0x6, 0x4, 0x9, 0x3,
|
||||||
|
0xd, 0x5, 0x7, 0xe
|
||||||
|
};
|
||||||
|
|
||||||
|
int hiCnt = 0, loCnt;
|
||||||
|
quint8 sum = shuf[((key >> 24) + (key >> 16) + (key >> 8) + key) & 0xf];
|
||||||
|
|
||||||
|
for (quint32 i = 0; i < size; i++) {
|
||||||
|
quint8 hiAdd = shuf[key >> (hiCnt << 2) & 0xf] + sum;
|
||||||
|
loCnt = (hiCnt > 6) ? 0 : hiCnt + 1;
|
||||||
|
quint8 loAdd = shuf[key >> (loCnt << 2) & 0xf] + sum;
|
||||||
|
quint8 hi = data[i] - (hiAdd << 4);
|
||||||
|
quint8 lo = data[i] - loAdd;
|
||||||
|
data[i] = (hi & 0xf0) | (lo & 0x0f);
|
||||||
|
hiCnt = (loCnt > 6) ? 0 : loCnt + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CryptDevice::CryptDevice(QIODevice *device, quint32 key, quint32 blockSize,
|
||||||
|
QObject *parent) : QIODevice(parent), _device(device), _key(key), _available(0)
|
||||||
|
{
|
||||||
|
_block.resize(blockSize);
|
||||||
|
setOpenMode(_device->openMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 CryptDevice::readData(char *data, qint64 maxSize)
|
||||||
|
{
|
||||||
|
qint64 rs, ts = 0;
|
||||||
|
int cs;
|
||||||
|
|
||||||
|
if (_available) {
|
||||||
|
cs = qMin(maxSize, (qint64)_available);
|
||||||
|
memcpy(data, _block.constData() + _block.size() - _available, cs);
|
||||||
|
_available -= cs;
|
||||||
|
maxSize -= cs;
|
||||||
|
ts = cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (maxSize) {
|
||||||
|
if ((rs = _device->read(_block.data(), _block.size())) < 0)
|
||||||
|
return -1;
|
||||||
|
else if (!rs)
|
||||||
|
break;
|
||||||
|
_available = rs;
|
||||||
|
demangle((quint8*)_block.data(), _available, _key);
|
||||||
|
cs = qMin(maxSize, (qint64)_available);
|
||||||
|
memcpy(data + ts, _block.constData(), cs);
|
||||||
|
_available -= cs;
|
||||||
|
maxSize -= cs;
|
||||||
|
ts += cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static qint32 readInt24(QDataStream &stream)
|
||||||
|
{
|
||||||
|
unsigned char data[3];
|
||||||
|
quint32 val;
|
||||||
|
|
||||||
|
stream.readRawData((char*)data, sizeof(data));
|
||||||
|
val = data[0] | ((quint32)data[1]) << 8 | ((quint32)data[2]) << 16;
|
||||||
|
return (val > 0x7FFFFF) ? (val & 0x7FFFFF) - 0x800000 : val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint16 nextHeaderType(QDataStream &stream)
|
||||||
|
{
|
||||||
|
quint16 type = 0;
|
||||||
|
|
||||||
|
if (stream.device()->peek((char*)&type, sizeof(type))
|
||||||
|
< (qint64)sizeof(type)) {
|
||||||
|
stream.setStatus(QDataStream::ReadCorruptData);
|
||||||
|
return 0xFFFF;
|
||||||
|
} else
|
||||||
|
return qFromLittleEndian(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint8 readRecordHeader(QDataStream &stream, RecordHeader &hdr)
|
||||||
|
{
|
||||||
|
stream >> hdr.type >> hdr.flags >> hdr.size;
|
||||||
|
if (hdr.flags & 0xA)
|
||||||
|
stream >> hdr.extra;
|
||||||
|
return (hdr.flags & 0xA) ? 12 : 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint32 skipRecord(QDataStream &stream)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
quint8 rs = readRecordHeader(stream, rh);
|
||||||
|
stream.skipRawData(rh.size);
|
||||||
|
|
||||||
|
return rs + rh.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint16 readString(QDataStream &stream, QTextCodec *codec, QString &str)
|
||||||
|
{
|
||||||
|
quint16 len;
|
||||||
|
stream >> len;
|
||||||
|
QByteArray ba;
|
||||||
|
ba.resize(len);
|
||||||
|
stream.readRawData(ba.data(), len);
|
||||||
|
str = codec ? codec->toUnicode(ba) : QString::fromLatin1(ba);
|
||||||
|
|
||||||
|
return len + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint32 readTranslatedObjects(QDataStream &stream, QTextCodec *codec,
|
||||||
|
QList<TranslatedString> &objects)
|
||||||
|
{
|
||||||
|
qint32 size = 0, ret;
|
||||||
|
char lang[2];
|
||||||
|
|
||||||
|
objects.clear();
|
||||||
|
|
||||||
|
stream >> size;
|
||||||
|
ret = size + 4;
|
||||||
|
while (stream.status() == QDataStream::Ok && size > 0) {
|
||||||
|
QString str;
|
||||||
|
stream.readRawData(lang, sizeof(lang));
|
||||||
|
size -= readString(stream, codec, str) + 2;
|
||||||
|
objects.append(TranslatedString(lang, str));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size < 0)
|
||||||
|
stream.setStatus(QDataStream::ReadCorruptData);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint32 readFprsRecord(QDataStream &stream)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
quint16 s1;
|
||||||
|
quint8 rs, s2, s3, s4;
|
||||||
|
|
||||||
|
rs = readRecordHeader(stream, rh);
|
||||||
|
stream >> s1 >> s2 >> s3 >> s4;
|
||||||
|
|
||||||
|
return rs + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint32 readFileDataRecord(QDataStream &stream, QTextCodec *codec)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
quint32 ds, s1;
|
||||||
|
quint16 s2, s3;
|
||||||
|
quint8 rs;
|
||||||
|
QList<TranslatedString> obj;
|
||||||
|
|
||||||
|
rs = readRecordHeader(stream, rh);
|
||||||
|
stream >> s1 >> s2 >> s3;
|
||||||
|
ds = 8;
|
||||||
|
ds += readTranslatedObjects(stream, codec, obj);
|
||||||
|
ds += readTranslatedObjects(stream, codec, obj);
|
||||||
|
|
||||||
|
if (s1 & 0x10) {
|
||||||
|
quint8 ss1, ss2;
|
||||||
|
quint16 ss3;
|
||||||
|
stream >> ss1 >> ss2 >> ss3;
|
||||||
|
ds += 4;
|
||||||
|
}
|
||||||
|
if (s1 & 0x100) {
|
||||||
|
quint32 ss1;
|
||||||
|
stream >> ss1;
|
||||||
|
if (ss1)
|
||||||
|
stream.skipRawData(ss1);
|
||||||
|
ds += ss1 + 4;
|
||||||
|
}
|
||||||
|
if (s1 & 0x400) {
|
||||||
|
QString str;
|
||||||
|
ds += readString(stream, codec, str);
|
||||||
|
}
|
||||||
|
if (s1 & 0x400000) {
|
||||||
|
quint16 ss1;
|
||||||
|
stream >> ss1;
|
||||||
|
if (ss1)
|
||||||
|
stream.skipRawData(ss1);
|
||||||
|
ds += ss1 + 2;
|
||||||
|
}
|
||||||
|
// structure of higher fields not known
|
||||||
|
|
||||||
|
if (ds > rh.size)
|
||||||
|
stream.setStatus(QDataStream::ReadCorruptData);
|
||||||
|
else if (ds < rh.size)
|
||||||
|
// skip remaining unknown fields
|
||||||
|
stream.skipRawData(rh.size - ds);
|
||||||
|
|
||||||
|
return rs + rh.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint32 readDescription(QDataStream &stream, QTextCodec *codec,
|
||||||
|
Waypoint &waypoint)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
quint8 rs;
|
||||||
|
quint32 ds;
|
||||||
|
QList<TranslatedString> obj;
|
||||||
|
|
||||||
|
rs = readRecordHeader(stream, rh);
|
||||||
|
ds = readTranslatedObjects(stream, codec, obj);
|
||||||
|
if (!obj.isEmpty())
|
||||||
|
waypoint.setDescription(obj.first().str());
|
||||||
|
|
||||||
|
if (ds != rh.size)
|
||||||
|
stream.setStatus(QDataStream::ReadCorruptData);
|
||||||
|
|
||||||
|
return rs + rh.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint32 readNotes(QDataStream &stream, QTextCodec *codec,
|
||||||
|
Waypoint &waypoint)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
quint8 rs, s1;
|
||||||
|
quint32 ds = 1;
|
||||||
|
|
||||||
|
rs = readRecordHeader(stream, rh);
|
||||||
|
stream >> s1;
|
||||||
|
if (s1 & 0x1) {
|
||||||
|
QList<TranslatedString> obj;
|
||||||
|
ds += readTranslatedObjects(stream, codec, obj);
|
||||||
|
if (!obj.isEmpty() && waypoint.description().isNull())
|
||||||
|
waypoint.setDescription(obj.first().str());
|
||||||
|
}
|
||||||
|
if (s1 & 0x2) {
|
||||||
|
QString str;
|
||||||
|
ds += readString(stream, codec, str);
|
||||||
|
if (!str.isEmpty() && waypoint.description().isNull())
|
||||||
|
waypoint.setDescription(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ds != rh.size)
|
||||||
|
stream.setStatus(QDataStream::ReadCorruptData);
|
||||||
|
|
||||||
|
return rs + rh.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint32 readContact(QDataStream &stream, QTextCodec *codec,
|
||||||
|
Waypoint &waypoint)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
quint8 rs;
|
||||||
|
quint16 flags;
|
||||||
|
quint32 ds = 2;
|
||||||
|
QString str;
|
||||||
|
QList<TranslatedString> obj;
|
||||||
|
|
||||||
|
rs = readRecordHeader(stream, rh);
|
||||||
|
stream >> flags;
|
||||||
|
|
||||||
|
if (flags & 0x1) // phone
|
||||||
|
ds += readString(stream, codec, str);
|
||||||
|
if (flags & 0x2) // phone2
|
||||||
|
ds += readString(stream, codec, str);
|
||||||
|
if (flags & 0x4) // fax
|
||||||
|
ds += readString(stream, codec, str);
|
||||||
|
if (flags & 0x8) // mail
|
||||||
|
ds += readString(stream, codec, str);
|
||||||
|
if (flags & 0x10) { // web
|
||||||
|
ds += readString(stream, codec, str);
|
||||||
|
QUrl url(str);
|
||||||
|
waypoint.addLink(Link(url.scheme().isEmpty()
|
||||||
|
? "http://" + str : str, str));
|
||||||
|
}
|
||||||
|
if (flags & 0x20) // unknown
|
||||||
|
ds += readTranslatedObjects(stream, codec, obj);
|
||||||
|
|
||||||
|
if (ds != rh.size)
|
||||||
|
stream.setStatus(QDataStream::ReadCorruptData);
|
||||||
|
|
||||||
|
return rs + rh.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint32 readAddress(QDataStream &stream, QTextCodec *codec,
|
||||||
|
Waypoint &waypoint)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
quint8 rs;
|
||||||
|
quint16 flags;
|
||||||
|
quint32 ds = 2;
|
||||||
|
QList<TranslatedString> obj;
|
||||||
|
QString str;
|
||||||
|
Address addr;
|
||||||
|
|
||||||
|
rs = readRecordHeader(stream, rh);
|
||||||
|
stream >> flags;
|
||||||
|
|
||||||
|
if (flags & 0x1) {
|
||||||
|
ds += readTranslatedObjects(stream, codec, obj);
|
||||||
|
if (!obj.isEmpty())
|
||||||
|
addr.setCity(obj.first().str());
|
||||||
|
}
|
||||||
|
if (flags & 0x2) {
|
||||||
|
ds += readTranslatedObjects(stream, codec, obj);
|
||||||
|
if (!obj.isEmpty())
|
||||||
|
addr.setCountry(obj.first().str());
|
||||||
|
}
|
||||||
|
if (flags & 0x4) {
|
||||||
|
ds += readTranslatedObjects(stream, codec, obj);
|
||||||
|
if (!obj.isEmpty())
|
||||||
|
addr.setState(obj.first().str());
|
||||||
|
}
|
||||||
|
if (flags & 0x8) {
|
||||||
|
ds += readString(stream, codec, str);
|
||||||
|
addr.setPostalCode(str);
|
||||||
|
}
|
||||||
|
if (flags & 0x10) {
|
||||||
|
ds += readTranslatedObjects(stream, codec, obj);
|
||||||
|
if (!obj.isEmpty())
|
||||||
|
addr.setStreet(obj.first().str());
|
||||||
|
}
|
||||||
|
if (flags & 0x20) // unknown
|
||||||
|
ds += readString(stream, codec, str);
|
||||||
|
|
||||||
|
waypoint.setAddress(addr);
|
||||||
|
|
||||||
|
if (ds != rh.size)
|
||||||
|
stream.setStatus(QDataStream::ReadCorruptData);
|
||||||
|
|
||||||
|
return rs + rh.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||||
|
static const QTemporaryDir &tempDir()
|
||||||
|
{
|
||||||
|
static QTemporaryDir dir;
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint32 readImageInfo(QDataStream &stream, Waypoint &waypoint,
|
||||||
|
const QString &fileName, int &imgId)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
quint8 rs, s1;
|
||||||
|
quint32 size;
|
||||||
|
|
||||||
|
rs = readRecordHeader(stream, rh);
|
||||||
|
stream >> s1 >> size;
|
||||||
|
|
||||||
|
QByteArray ba;
|
||||||
|
ba.resize(size);
|
||||||
|
stream.readRawData(ba.data(), ba.size());
|
||||||
|
|
||||||
|
if (tempDir().isValid()) {
|
||||||
|
QBuffer buf(&ba);
|
||||||
|
QImageReader ir(&buf);
|
||||||
|
|
||||||
|
QByteArray id(fileName.toUtf8() + QByteArray::number(imgId++));
|
||||||
|
QFile imgFile(tempDir().path() + "/" + QString("%0.%1").arg(
|
||||||
|
QCryptographicHash::hash(id, QCryptographicHash::Sha1).toHex(),
|
||||||
|
QString(ir.format())));
|
||||||
|
imgFile.open(QIODevice::WriteOnly);
|
||||||
|
imgFile.write(ba);
|
||||||
|
imgFile.close();
|
||||||
|
|
||||||
|
waypoint.addImage(ImageInfo(imgFile.fileName(), ir.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size + 5 != rh.size)
|
||||||
|
stream.setStatus(QDataStream::ReadCorruptData);
|
||||||
|
|
||||||
|
return rs + rh.size;
|
||||||
|
}
|
||||||
|
#endif // QT_VERSION >= 5
|
||||||
|
|
||||||
|
static int speed(quint8 flags)
|
||||||
|
{
|
||||||
|
switch (flags >> 4) {
|
||||||
|
case 0x8:
|
||||||
|
return 40;
|
||||||
|
case 0x9:
|
||||||
|
return 30;
|
||||||
|
case 0xA:
|
||||||
|
return 50;
|
||||||
|
case 0xB:
|
||||||
|
return 70;
|
||||||
|
case 0xC:
|
||||||
|
return 80;
|
||||||
|
case 0xD:
|
||||||
|
return 90;
|
||||||
|
case 0xE:
|
||||||
|
return 100;
|
||||||
|
case 0xF:
|
||||||
|
return 120;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint32 readCamera(QDataStream &stream, QVector<Waypoint> &waypoints,
|
||||||
|
QList<Area> &polygons)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
quint8 flags, type, s7, rs;
|
||||||
|
qint32 top, right, bottom, left, lat, lon;
|
||||||
|
quint32 ds = 15;
|
||||||
|
|
||||||
|
|
||||||
|
rs = readRecordHeader(stream, rh);
|
||||||
|
top = readInt24(stream);
|
||||||
|
right = readInt24(stream);
|
||||||
|
bottom = readInt24(stream);
|
||||||
|
left = readInt24(stream);
|
||||||
|
stream >> flags >> type >> s7;
|
||||||
|
|
||||||
|
if (s7) {
|
||||||
|
quint32 skip = s7 + 2 + s7/4;
|
||||||
|
stream.skipRawData(skip);
|
||||||
|
lat = readInt24(stream);
|
||||||
|
lon = readInt24(stream);
|
||||||
|
ds += skip + 6;
|
||||||
|
} else {
|
||||||
|
quint8 s8;
|
||||||
|
stream.skipRawData(9);
|
||||||
|
stream >> s8;
|
||||||
|
quint32 skip = 3 + s8 + s8/4;
|
||||||
|
stream.skipRawData(skip);
|
||||||
|
lat = readInt24(stream);
|
||||||
|
lon = readInt24(stream);
|
||||||
|
ds += skip + 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
waypoints.append(Coordinates(toWGS24(lon), toWGS24(lat)));
|
||||||
|
|
||||||
|
Area area;
|
||||||
|
Polygon polygon;
|
||||||
|
QVector<Coordinates> v(4);
|
||||||
|
v[0] = Coordinates(toWGS24(left), toWGS24(top));
|
||||||
|
v[1] = Coordinates(toWGS24(right), toWGS24(top));
|
||||||
|
v[2] = Coordinates(toWGS24(right), toWGS24(bottom));
|
||||||
|
v[3] = Coordinates(toWGS24(left), toWGS24(bottom));
|
||||||
|
polygon.append(v);
|
||||||
|
area.append(polygon);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 8:
|
||||||
|
area.setDescription(QString("%1 mi/h")
|
||||||
|
.arg(speed(flags)));
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
area.setDescription(QString("%1 km/h")
|
||||||
|
.arg(speed(flags)));
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
case 11:
|
||||||
|
area.setDescription("Red light camera");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
polygons.append(area);
|
||||||
|
|
||||||
|
if (ds > rh.size)
|
||||||
|
stream.setStatus(QDataStream::ReadCorruptData);
|
||||||
|
else if (ds < rh.size)
|
||||||
|
stream.skipRawData(rh.size - ds);
|
||||||
|
|
||||||
|
return rs + rh.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint32 readPOI(QDataStream &stream, QTextCodec *codec,
|
||||||
|
QVector<Waypoint> &waypoints, const QString &fileName, int &imgId)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
quint8 rs;
|
||||||
|
quint32 ds;
|
||||||
|
qint32 lat, lon;
|
||||||
|
quint16 s3;
|
||||||
|
QList<TranslatedString> obj;
|
||||||
|
|
||||||
|
rs = readRecordHeader(stream, rh);
|
||||||
|
stream >> lat >> lon >> s3;
|
||||||
|
stream.skipRawData(s3);
|
||||||
|
ds = 10 + s3;
|
||||||
|
ds += readTranslatedObjects(stream, codec, obj);
|
||||||
|
|
||||||
|
waypoints.append(Waypoint(Coordinates(toWGS32(lon), toWGS32(lat))));
|
||||||
|
if (!obj.isEmpty())
|
||||||
|
waypoints.last().setName(obj.first().str());
|
||||||
|
|
||||||
|
while (stream.status() == QDataStream::Ok && ds < rh.size) {
|
||||||
|
switch(nextHeaderType(stream)) {
|
||||||
|
case 10:
|
||||||
|
ds += readDescription(stream, codec, waypoints.last());
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
ds += readAddress(stream, codec, waypoints.last());
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
ds += readContact(stream, codec, waypoints.last());
|
||||||
|
break;
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||||
|
case 13:
|
||||||
|
ds += readImageInfo(stream, waypoints.last(), fileName, imgId);
|
||||||
|
break;
|
||||||
|
#endif // QT_VERSION >= 5
|
||||||
|
case 14:
|
||||||
|
ds += readNotes(stream, codec, waypoints.last());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ds += skipRecord(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ds != rh.size)
|
||||||
|
stream.setStatus(QDataStream::ReadCorruptData);
|
||||||
|
|
||||||
|
return rs + rh.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static quint32 readSpatialIndex(QDataStream &stream, QTextCodec *codec,
|
||||||
|
QVector<Waypoint> &waypoints, QList<Area> &polygons, const QString &fileName,
|
||||||
|
int &imgId)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
quint32 ds, s5;
|
||||||
|
qint32 top, right, bottom, left;
|
||||||
|
quint16 s6;
|
||||||
|
quint8 rs;
|
||||||
|
|
||||||
|
rs = readRecordHeader(stream, rh);
|
||||||
|
stream >> top >> right >> bottom >> left >> s5 >> s6;
|
||||||
|
stream.skipRawData(s6);
|
||||||
|
ds = 22 + s6;
|
||||||
|
if (rh.flags & 0x8) {
|
||||||
|
while (stream.status() == QDataStream::Ok && ds < rh.size) {
|
||||||
|
switch(nextHeaderType(stream)) {
|
||||||
|
case 2:
|
||||||
|
ds += readPOI(stream, codec, waypoints, fileName, imgId);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
ds += readSpatialIndex(stream, codec, waypoints, polygons,
|
||||||
|
fileName, imgId);
|
||||||
|
break;
|
||||||
|
case 19:
|
||||||
|
ds += readCamera(stream, waypoints, polygons);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ds += skipRecord(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ds != rh.size)
|
||||||
|
stream.setStatus(QDataStream::ReadCorruptData);
|
||||||
|
|
||||||
|
return rs + rh.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void readPOIDatabase(QDataStream &stream, QTextCodec *codec,
|
||||||
|
QVector<Waypoint> &waypoints, QList<Area> &polygons, const QString &fileName,
|
||||||
|
int &imgId)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
QList<TranslatedString> obj;
|
||||||
|
quint32 ds;
|
||||||
|
|
||||||
|
readRecordHeader(stream, rh);
|
||||||
|
ds = readTranslatedObjects(stream, codec, obj);
|
||||||
|
ds += readSpatialIndex(stream, codec, waypoints, polygons, fileName, imgId);
|
||||||
|
if (rh.flags & 0x8) {
|
||||||
|
while (stream.status() == QDataStream::Ok && ds < rh.size) {
|
||||||
|
switch(nextHeaderType(stream)) {
|
||||||
|
case 5: // symbol
|
||||||
|
case 7: // category
|
||||||
|
default:
|
||||||
|
ds += skipRecord(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ds != rh.size)
|
||||||
|
stream.setStatus(QDataStream::ReadCorruptData);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPIParser::readData(QDataStream &stream, QTextCodec *codec,
|
||||||
|
QVector<Waypoint> &waypoints, QList<Area> &polygons, const QString &fileName,
|
||||||
|
int &imgId)
|
||||||
|
{
|
||||||
|
while (stream.status() == QDataStream::Ok) {
|
||||||
|
switch (nextHeaderType(stream)) {
|
||||||
|
case 0x09: // POI database
|
||||||
|
readPOIDatabase(stream, codec, waypoints, polygons, fileName,
|
||||||
|
imgId);
|
||||||
|
break;
|
||||||
|
case 0xffff: // EOF
|
||||||
|
skipRecord(stream);
|
||||||
|
if (stream.status() == QDataStream::Ok)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case 0x16: // route
|
||||||
|
case 0x15: // info header
|
||||||
|
default:
|
||||||
|
skipRecord(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_errorString = "Invalid/corrupted GPI data";
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPIParser::readGPIHeader(QDataStream &stream, QTextCodec **codec)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
char m1[6], m2[2];
|
||||||
|
quint16 codepage = 0;
|
||||||
|
quint8 s2, s3;
|
||||||
|
quint32 ds;
|
||||||
|
|
||||||
|
readRecordHeader(stream, rh);
|
||||||
|
stream.readRawData(m1, sizeof(m1));
|
||||||
|
stream.readRawData(m2, sizeof(m2));
|
||||||
|
stream >> codepage >> s2 >> s3;
|
||||||
|
ds = sizeof(m1) + sizeof(m2) + 4;
|
||||||
|
|
||||||
|
if (codepage == 65001)
|
||||||
|
*codec = QTextCodec::codecForName("UTF-8");
|
||||||
|
else if (codepage == 0)
|
||||||
|
*codec = 0;
|
||||||
|
else
|
||||||
|
*codec = QTextCodec::codecForName(QString("CP%1").arg(codepage)
|
||||||
|
.toLatin1());
|
||||||
|
|
||||||
|
if (s2 & 0x10)
|
||||||
|
ds += readFileDataRecord(stream, *codec);
|
||||||
|
|
||||||
|
if (stream.status() != QDataStream::Ok || ds != rh.size) {
|
||||||
|
_errorString = "Invalid GPI header";
|
||||||
|
return false;
|
||||||
|
} else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPIParser::readFileHeader(QDataStream &stream, quint32 &ebs)
|
||||||
|
{
|
||||||
|
RecordHeader rh;
|
||||||
|
quint32 ds, s7;
|
||||||
|
quint16 s10;
|
||||||
|
quint8 s5, s6, s8, s9;
|
||||||
|
char magic[6];
|
||||||
|
|
||||||
|
readRecordHeader(stream, rh);
|
||||||
|
stream.readRawData(magic, sizeof(magic));
|
||||||
|
if (memcmp(magic, "GRMREC", sizeof(magic))) {
|
||||||
|
_errorString = "Not a GPI file";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
stream >> s5 >> s6 >> s7 >> s8 >> s9 >> s10;
|
||||||
|
stream.skipRawData(s10);
|
||||||
|
ds = sizeof(magic) + 10 + s10;
|
||||||
|
if (rh.flags & 8)
|
||||||
|
ds += readFprsRecord(stream);
|
||||||
|
|
||||||
|
ebs = (s8 & 0x4) ? s9 * 8 + 8 : 0;
|
||||||
|
|
||||||
|
if (stream.status() != QDataStream::Ok || ds != rh.size) {
|
||||||
|
_errorString = "Invalid file header";
|
||||||
|
return false;
|
||||||
|
} else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPIParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||||
|
QList<RouteData> &routes, QList<Area> &polygons, QVector<Waypoint> &waypoints)
|
||||||
|
{
|
||||||
|
Q_UNUSED(tracks);
|
||||||
|
Q_UNUSED(routes);
|
||||||
|
Q_UNUSED(polygons);
|
||||||
|
QDataStream stream(file);
|
||||||
|
QTextCodec *codec = 0;
|
||||||
|
quint32 ebs;
|
||||||
|
int imgId = 0;
|
||||||
|
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
|
||||||
|
if (!readFileHeader(stream, ebs) || !readGPIHeader(stream, &codec))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ebs) {
|
||||||
|
CryptDevice dev(stream.device(), 0xf870b5, ebs);
|
||||||
|
QDataStream cryptStream(&dev);
|
||||||
|
cryptStream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
return readData(cryptStream, codec, waypoints, polygons, file->fileName(),
|
||||||
|
imgId);
|
||||||
|
} else
|
||||||
|
return readData(stream, codec, waypoints, polygons, file->fileName(),
|
||||||
|
imgId);
|
||||||
|
}
|
27
src/data/gpiparser.h
Normal file
27
src/data/gpiparser.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef GPIPARSER_H
|
||||||
|
#define GPIPARSER_H
|
||||||
|
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
class QDataStream;
|
||||||
|
class QTextCodec;
|
||||||
|
|
||||||
|
class GPIParser : public Parser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
|
||||||
|
QList<Area> &polygons, QVector<Waypoint> &waypoints);
|
||||||
|
QString errorString() const {return _errorString;}
|
||||||
|
int errorLine() const {return 0;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool readFileHeader(QDataStream &stream, quint32 &ebs);
|
||||||
|
bool readGPIHeader(QDataStream &stream, QTextCodec **codec);
|
||||||
|
bool readData(QDataStream &stream, QTextCodec *codec,
|
||||||
|
QVector<Waypoint> &waypoints, QList<Area> &polygons,
|
||||||
|
const QString &fileName, int &imgId);
|
||||||
|
|
||||||
|
QString _errorString;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GPIPARSER_H
|
@ -23,6 +23,21 @@ QDateTime GPXParser::time()
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Link GPXParser::link()
|
||||||
|
{
|
||||||
|
QString URL = _reader.attributes().value("href").toString();
|
||||||
|
QString text;
|
||||||
|
|
||||||
|
while (_reader.readNextStartElement()) {
|
||||||
|
if (_reader.name() == QLatin1String("text"))
|
||||||
|
text = _reader.readElementText();
|
||||||
|
else
|
||||||
|
_reader.skipCurrentElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Link(URL, text);
|
||||||
|
}
|
||||||
|
|
||||||
Coordinates GPXParser::coordinates()
|
Coordinates GPXParser::coordinates()
|
||||||
{
|
{
|
||||||
bool res;
|
bool res;
|
||||||
@ -54,8 +69,10 @@ Coordinates GPXParser::coordinates()
|
|||||||
void GPXParser::rpExtension(SegmentData *autoRoute)
|
void GPXParser::rpExtension(SegmentData *autoRoute)
|
||||||
{
|
{
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == QLatin1String("rpt"))
|
if (_reader.name() == QLatin1String("rpt")) {
|
||||||
|
if (autoRoute)
|
||||||
autoRoute->append(Trackpoint(coordinates()));
|
autoRoute->append(Trackpoint(coordinates()));
|
||||||
|
}
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,11 +93,45 @@ void GPXParser::tpExtension(Trackpoint &trackpoint)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPXParser::rteptExtensions(SegmentData *autoRoute)
|
void GPXParser::address(Waypoint &waypoint)
|
||||||
|
{
|
||||||
|
Address addr;
|
||||||
|
|
||||||
|
while (_reader.readNextStartElement()) {
|
||||||
|
if (_reader.name() == QLatin1String("StreetAddress"))
|
||||||
|
addr.setStreet(_reader.readElementText());
|
||||||
|
else if (_reader.name() == QLatin1String("City"))
|
||||||
|
addr.setCity(_reader.readElementText());
|
||||||
|
else if (_reader.name() == QLatin1String("PostalCode"))
|
||||||
|
addr.setPostalCode(_reader.readElementText());
|
||||||
|
else if (_reader.name() == QLatin1String("State"))
|
||||||
|
addr.setState(_reader.readElementText());
|
||||||
|
else if (_reader.name() == QLatin1String("Country"))
|
||||||
|
addr.setCountry(_reader.readElementText());
|
||||||
|
else
|
||||||
|
_reader.skipCurrentElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
waypoint.setAddress(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPXParser::wpExtension(Waypoint &waypoint)
|
||||||
|
{
|
||||||
|
while (_reader.readNextStartElement()) {
|
||||||
|
if (_reader.name() == QLatin1String("Address"))
|
||||||
|
address(waypoint);
|
||||||
|
else
|
||||||
|
_reader.skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPXParser::waypointExtensions(Waypoint &waypoint, SegmentData *autoRoute)
|
||||||
{
|
{
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == QLatin1String("RoutePointExtension"))
|
if (_reader.name() == QLatin1String("RoutePointExtension"))
|
||||||
rpExtension(autoRoute);
|
rpExtension(autoRoute);
|
||||||
|
else if (_reader.name() == QLatin1String("WaypointExtension"))
|
||||||
|
wpExtension(waypoint);
|
||||||
else
|
else
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
@ -134,6 +185,7 @@ void GPXParser::trackpointData(Trackpoint &trackpoint)
|
|||||||
void GPXParser::waypointData(Waypoint &waypoint, SegmentData *autoRoute)
|
void GPXParser::waypointData(Waypoint &waypoint, SegmentData *autoRoute)
|
||||||
{
|
{
|
||||||
qreal gh = NAN;
|
qreal gh = NAN;
|
||||||
|
Link link10;
|
||||||
|
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == QLatin1String("name"))
|
if (_reader.name() == QLatin1String("name"))
|
||||||
@ -146,12 +198,22 @@ void GPXParser::waypointData(Waypoint &waypoint, SegmentData *autoRoute)
|
|||||||
gh = number();
|
gh = number();
|
||||||
else if (_reader.name() == QLatin1String("time"))
|
else if (_reader.name() == QLatin1String("time"))
|
||||||
waypoint.setTimestamp(time());
|
waypoint.setTimestamp(time());
|
||||||
else if (autoRoute && _reader.name() == QLatin1String("extensions"))
|
else if (_reader.name() == QLatin1String("link")) {
|
||||||
rteptExtensions(autoRoute);
|
Link l(link());
|
||||||
|
if (!l.URL().isEmpty())
|
||||||
|
waypoint.addLink(l);
|
||||||
|
} else if (_reader.name() == QLatin1String("url"))
|
||||||
|
link10.setURL(_reader.readElementText());
|
||||||
|
else if (_reader.name() == QLatin1String("urlname"))
|
||||||
|
link10.setText(_reader.readElementText());
|
||||||
|
else if (_reader.name() == QLatin1String("extensions"))
|
||||||
|
waypointExtensions(waypoint, autoRoute);
|
||||||
else
|
else
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!link10.URL().isEmpty())
|
||||||
|
waypoint.addLink(link10);
|
||||||
if (!std::isnan(gh) && !std::isnan(waypoint.elevation()))
|
if (!std::isnan(gh) && !std::isnan(waypoint.elevation()))
|
||||||
waypoint.setElevation(waypoint.elevation() - gh);
|
waypoint.setElevation(waypoint.elevation() - gh);
|
||||||
}
|
}
|
||||||
@ -172,6 +234,7 @@ void GPXParser::routepoints(RouteData &route, QList<TrackData> &tracks)
|
|||||||
TrackData autoRoute;
|
TrackData autoRoute;
|
||||||
autoRoute.append(SegmentData());
|
autoRoute.append(SegmentData());
|
||||||
SegmentData &autoRouteSegment = autoRoute.last();
|
SegmentData &autoRouteSegment = autoRoute.last();
|
||||||
|
Link link10;
|
||||||
|
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == QLatin1String("rtept")) {
|
if (_reader.name() == QLatin1String("rtept")) {
|
||||||
@ -181,10 +244,21 @@ void GPXParser::routepoints(RouteData &route, QList<TrackData> &tracks)
|
|||||||
route.setName(_reader.readElementText());
|
route.setName(_reader.readElementText());
|
||||||
else if (_reader.name() == QLatin1String("desc"))
|
else if (_reader.name() == QLatin1String("desc"))
|
||||||
route.setDescription(_reader.readElementText());
|
route.setDescription(_reader.readElementText());
|
||||||
|
else if (_reader.name() == QLatin1String("link")) {
|
||||||
|
Link l(link());
|
||||||
|
if (!l.URL().isEmpty())
|
||||||
|
route.addLink(l);
|
||||||
|
} else if (_reader.name() == QLatin1String("url"))
|
||||||
|
link10.setURL(_reader.readElementText());
|
||||||
|
else if (_reader.name() == QLatin1String("urlname"))
|
||||||
|
link10.setText(_reader.readElementText());
|
||||||
else
|
else
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!link10.URL().isEmpty())
|
||||||
|
route.addLink(link10);
|
||||||
|
|
||||||
if (!autoRouteSegment.isEmpty()) {
|
if (!autoRouteSegment.isEmpty()) {
|
||||||
autoRoute.setName(route.name());
|
autoRoute.setName(route.name());
|
||||||
autoRoute.setDescription(route.description());
|
autoRoute.setDescription(route.description());
|
||||||
@ -194,6 +268,8 @@ void GPXParser::routepoints(RouteData &route, QList<TrackData> &tracks)
|
|||||||
|
|
||||||
void GPXParser::track(TrackData &track)
|
void GPXParser::track(TrackData &track)
|
||||||
{
|
{
|
||||||
|
Link link10;
|
||||||
|
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == QLatin1String("trkseg")) {
|
if (_reader.name() == QLatin1String("trkseg")) {
|
||||||
track.append(SegmentData());
|
track.append(SegmentData());
|
||||||
@ -202,9 +278,20 @@ void GPXParser::track(TrackData &track)
|
|||||||
track.setName(_reader.readElementText());
|
track.setName(_reader.readElementText());
|
||||||
else if (_reader.name() == QLatin1String("desc"))
|
else if (_reader.name() == QLatin1String("desc"))
|
||||||
track.setDescription(_reader.readElementText());
|
track.setDescription(_reader.readElementText());
|
||||||
|
else if (_reader.name() == QLatin1String("link")) {
|
||||||
|
Link l(link());
|
||||||
|
if (!l.URL().isEmpty())
|
||||||
|
track.addLink(l);
|
||||||
|
} else if (_reader.name() == QLatin1String("url"))
|
||||||
|
link10.setURL(_reader.readElementText());
|
||||||
|
else if (_reader.name() == QLatin1String("urlname"))
|
||||||
|
link10.setText(_reader.readElementText());
|
||||||
else
|
else
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!link10.URL().isEmpty())
|
||||||
|
track.addLink(link10);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPXParser::area(Area &area)
|
void GPXParser::area(Area &area)
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
|
|
||||||
class GPXParser : public Parser
|
class GPXParser : public Parser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -22,14 +21,17 @@ private:
|
|||||||
void rpExtension(SegmentData *autoRoute);
|
void rpExtension(SegmentData *autoRoute);
|
||||||
void tpExtension(Trackpoint &trackpoint);
|
void tpExtension(Trackpoint &trackpoint);
|
||||||
void trkptExtensions(Trackpoint &trackpoint);
|
void trkptExtensions(Trackpoint &trackpoint);
|
||||||
void rteptExtensions(SegmentData *autoRoute);
|
void wpExtension(Waypoint &waypoint);
|
||||||
|
void waypointExtensions(Waypoint &waypoint, SegmentData *autoRoute);
|
||||||
void area(Area &area);
|
void area(Area &area);
|
||||||
void gpxExtensions(QList<Area> &areas);
|
void gpxExtensions(QList<Area> &areas);
|
||||||
void trackpointData(Trackpoint &trackpoint);
|
void trackpointData(Trackpoint &trackpoint);
|
||||||
void waypointData(Waypoint &waypoint, SegmentData *autoRoute = 0);
|
void waypointData(Waypoint &waypoint, SegmentData *autoRoute = 0);
|
||||||
|
void address(Waypoint &waypoint);
|
||||||
qreal number();
|
qreal number();
|
||||||
QDateTime time();
|
QDateTime time();
|
||||||
Coordinates coordinates();
|
Coordinates coordinates();
|
||||||
|
Link link();
|
||||||
|
|
||||||
QXmlStreamReader _reader;
|
QXmlStreamReader _reader;
|
||||||
};
|
};
|
||||||
|
22
src/data/link.h
Normal file
22
src/data/link.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef LINK_H
|
||||||
|
#define LINK_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class Link {
|
||||||
|
public:
|
||||||
|
Link() {}
|
||||||
|
Link(const QString &URL, const QString &text = QString())
|
||||||
|
: _URL(URL), _text(text) {}
|
||||||
|
|
||||||
|
void setURL(const QString &URL) {_URL = URL;}
|
||||||
|
void setText(const QString &text) {_text = text;}
|
||||||
|
const QString &URL() const {return _URL;}
|
||||||
|
const QString &text() const {return _text;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString _URL;
|
||||||
|
QString _text;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LINK_H
|
@ -38,6 +38,11 @@ void LOCParser::waypoint(Waypoint &waypoint)
|
|||||||
} else if (_reader.name() == QLatin1String("coord")) {
|
} else if (_reader.name() == QLatin1String("coord")) {
|
||||||
waypoint.setCoordinates(coordinates());
|
waypoint.setCoordinates(coordinates());
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
|
} else if (_reader.name() == QLatin1String("link")) {
|
||||||
|
const QXmlStreamAttributes &attr = _reader.attributes();
|
||||||
|
QString URL(_reader.readElementText());
|
||||||
|
if (!URL.isEmpty())
|
||||||
|
waypoint.addLink(Link(URL, attr.value("text").toString()));
|
||||||
} else
|
} else
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ public:
|
|||||||
|
|
||||||
const QString &name() const {return _data.name();}
|
const QString &name() const {return _data.name();}
|
||||||
const QString &description() const {return _data.description();}
|
const QString &description() const {return _data.description();}
|
||||||
|
const QVector<Link> &links() const {return _data.links();}
|
||||||
|
|
||||||
bool isValid() const {return _data.size() >= 2;}
|
bool isValid() const {return _data.size() >= 2;}
|
||||||
|
|
||||||
|
@ -4,18 +4,23 @@
|
|||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include "waypoint.h"
|
#include "waypoint.h"
|
||||||
|
#include "link.h"
|
||||||
|
|
||||||
class RouteData : public QVector<Waypoint>
|
class RouteData : public QVector<Waypoint>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const QString& name() const {return _name;}
|
const QString &name() const {return _name;}
|
||||||
const QString& description() const {return _desc;}
|
const QString &description() const {return _desc;}
|
||||||
|
const QVector<Link> &links() const {return _links;}
|
||||||
|
|
||||||
void setName(const QString &name) {_name = name;}
|
void setName(const QString &name) {_name = name;}
|
||||||
void setDescription(const QString &desc) {_desc = desc;}
|
void setDescription(const QString &desc) {_desc = desc;}
|
||||||
|
void addLink(const Link &link) {_links.append(link);}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString _name;
|
QString _name;
|
||||||
QString _desc;
|
QString _desc;
|
||||||
|
QVector<Link> _links;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ROUTEDATA_H
|
#endif // ROUTEDATA_H
|
||||||
|
@ -7,6 +7,7 @@ int Track::_heartRateWindow = 3;
|
|||||||
int Track::_cadenceWindow = 3;
|
int Track::_cadenceWindow = 3;
|
||||||
int Track::_powerWindow = 3;
|
int Track::_powerWindow = 3;
|
||||||
|
|
||||||
|
bool Track::_automaticPause = true;
|
||||||
qreal Track::_pauseSpeed = 0.5;
|
qreal Track::_pauseSpeed = 0.5;
|
||||||
int Track::_pauseInterval = 10;
|
int Track::_pauseInterval = 10;
|
||||||
|
|
||||||
@ -14,6 +15,16 @@ bool Track::_outlierEliminate = true;
|
|||||||
bool Track::_useReportedSpeed = false;
|
bool Track::_useReportedSpeed = false;
|
||||||
|
|
||||||
|
|
||||||
|
static qreal avg(const QVector<qreal> &v)
|
||||||
|
{
|
||||||
|
qreal sum = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < v.size(); i++)
|
||||||
|
sum += v.at(i);
|
||||||
|
|
||||||
|
return sum/v.size();
|
||||||
|
}
|
||||||
|
|
||||||
static qreal median(QVector<qreal> &v)
|
static qreal median(QVector<qreal> &v)
|
||||||
{
|
{
|
||||||
qSort(v.begin(), v.end());
|
qSort(v.begin(), v.end());
|
||||||
@ -24,8 +35,7 @@ static qreal MAD(QVector<qreal> &v, qreal m)
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < v.size(); i++)
|
for (int i = 0; i < v.size(); i++)
|
||||||
v[i] = qAbs(v.at(i) - m);
|
v[i] = qAbs(v.at(i) - m);
|
||||||
qSort(v.begin(), v.end());
|
return median(v);
|
||||||
return v.at(v.size() / 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static QSet<int> eliminate(const QVector<qreal> &v)
|
static QSet<int> eliminate(const QVector<qreal> &v)
|
||||||
@ -74,34 +84,51 @@ Track::Track(const TrackData &data) : _data(data), _pause(0)
|
|||||||
|
|
||||||
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());
|
||||||
if (sd.isEmpty())
|
if (sd.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// precompute distances, times, speeds and acceleration
|
// precompute distances, times, speeds and acceleration
|
||||||
QVector<qreal> acceleration;
|
QVector<qreal> acceleration;
|
||||||
|
|
||||||
_segments.append(Segment());
|
|
||||||
Segment &seg = _segments.last();
|
Segment &seg = _segments.last();
|
||||||
|
|
||||||
seg.distance.append(i ? _segments.at(i-1).distance.last() : 0);
|
seg.distance.append(i && !_segments.at(i-1).distance.isEmpty()
|
||||||
seg.time.append(i ? _segments.at(i-1).time.last() :
|
? _segments.at(i-1).distance.last() : 0);
|
||||||
|
seg.time.append(i && !_segments.at(i-1).time.isEmpty()
|
||||||
|
? _segments.at(i-1).time.last() :
|
||||||
sd.first().hasTimestamp() ? 0 : NAN);
|
sd.first().hasTimestamp() ? 0 : NAN);
|
||||||
seg.speed.append(sd.first().hasTimestamp() ? 0 : NAN);
|
seg.speed.append(sd.first().hasTimestamp() ? 0 : NAN);
|
||||||
acceleration.append(sd.first().hasTimestamp() ? 0 : NAN);
|
acceleration.append(sd.first().hasTimestamp() ? 0 : NAN);
|
||||||
|
bool hasTime = !std::isnan(seg.time.first());
|
||||||
|
|
||||||
for (int j = 1; j < sd.size(); j++) {
|
for (int j = 1; j < sd.size(); j++) {
|
||||||
ds = sd.at(j).coordinates().distanceTo(
|
ds = sd.at(j).coordinates().distanceTo(
|
||||||
sd.at(j-1).coordinates());
|
sd.at(j-1).coordinates());
|
||||||
seg.distance.append(seg.distance.last() + ds);
|
seg.distance.append(seg.distance.last() + ds);
|
||||||
|
|
||||||
if (sd.at(j).timestamp() >= sd.at(j-1).timestamp())
|
if (hasTime && sd.at(j).timestamp().isValid()) {
|
||||||
|
if (sd.at(j).timestamp() > sd.at(j-1).timestamp())
|
||||||
dt = sd.at(j-1).timestamp().msecsTo(
|
dt = sd.at(j-1).timestamp().msecsTo(
|
||||||
sd.at(j).timestamp()) / 1000.0;
|
sd.at(j).timestamp()) / 1000.0;
|
||||||
else {
|
else {
|
||||||
qWarning("%s: %s: time skew detected", qPrintable(_data.name()),
|
qWarning("%s: %s: time skew detected", qPrintable(
|
||||||
qPrintable(sd.at(j).timestamp().toString(Qt::ISODate)));
|
_data.name()), qPrintable(sd.at(j).timestamp().toString(
|
||||||
|
Qt::ISODate)));
|
||||||
dt = 0;
|
dt = 0;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
dt = NAN;
|
||||||
|
if (hasTime) {
|
||||||
|
qWarning("%s: missing timestamp(s), time graphs disabled",
|
||||||
|
qPrintable(_data.name()));
|
||||||
|
hasTime = false;
|
||||||
|
for (int i = 0; i < seg.time.size(); i++)
|
||||||
|
seg.time[i] = NAN;
|
||||||
|
for (int i = 0; i < seg.speed.size(); i++)
|
||||||
|
seg.speed[i] = NAN;
|
||||||
|
}
|
||||||
|
}
|
||||||
seg.time.append(seg.time.last() + dt);
|
seg.time.append(seg.time.last() + dt);
|
||||||
|
|
||||||
if (dt < 1e-3) {
|
if (dt < 1e-3) {
|
||||||
@ -115,13 +142,35 @@ Track::Track(const TrackData &data) : _data(data), _pause(0)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!hasTime)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
// get stop-points + pause duration
|
// get stop-points + pause duration
|
||||||
|
int pauseInterval;
|
||||||
|
qreal pauseSpeed;
|
||||||
|
|
||||||
|
if (_automaticPause) {
|
||||||
|
pauseSpeed = (avg(seg.speed) > 2.8) ? 0.55 : 0.15;
|
||||||
|
pauseInterval = 10;
|
||||||
|
} else {
|
||||||
|
pauseSpeed = _pauseSpeed;
|
||||||
|
pauseInterval = _pauseInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ss = 0, la = 0;
|
||||||
for (int j = 1; j < seg.time.size(); j++) {
|
for (int j = 1; j < seg.time.size(); j++) {
|
||||||
if (seg.time.at(j) > seg.time.at(j-1) + _pauseInterval
|
if (seg.speed.at(j) > pauseSpeed)
|
||||||
&& seg.speed.at(j) < _pauseSpeed) {
|
ss = -1;
|
||||||
_pause += seg.time.at(j) - seg.time.at(j-1);
|
else if (ss < 0)
|
||||||
seg.stop.insert(j-1);
|
ss = j;
|
||||||
seg.stop.insert(j);
|
|
||||||
|
if (ss >= 0 && seg.time.at(j) > seg.time.at(ss) + pauseInterval) {
|
||||||
|
int l = qMax(ss, la);
|
||||||
|
_pause += seg.time.at(j) - seg.time.at(l);
|
||||||
|
for (int k = l; k <= j; k++)
|
||||||
|
seg.stop.insert(k);
|
||||||
|
la = j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ public:
|
|||||||
|
|
||||||
const QString &name() const {return _data.name();}
|
const QString &name() const {return _data.name();}
|
||||||
const QString &description() const {return _data.description();}
|
const QString &description() const {return _data.description();}
|
||||||
|
const QVector<Link> &links() const {return _data.links();}
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
@ -40,6 +41,7 @@ public:
|
|||||||
static void setHeartRateFilter(int window) {_heartRateWindow = window;}
|
static void setHeartRateFilter(int window) {_heartRateWindow = window;}
|
||||||
static void setCadenceFilter(int window) {_cadenceWindow = window;}
|
static void setCadenceFilter(int window) {_cadenceWindow = window;}
|
||||||
static void setPowerFilter(int window) {_powerWindow = window;}
|
static void setPowerFilter(int window) {_powerWindow = window;}
|
||||||
|
static void setAutomaticPause(bool set) {_automaticPause = set;}
|
||||||
static void setPauseSpeed(qreal speed) {_pauseSpeed = speed;}
|
static void setPauseSpeed(qreal speed) {_pauseSpeed = speed;}
|
||||||
static void setPauseInterval(int interval) {_pauseInterval = interval;}
|
static void setPauseInterval(int interval) {_pauseInterval = interval;}
|
||||||
static void setOutlierElimination(bool eliminate)
|
static void setOutlierElimination(bool eliminate)
|
||||||
@ -67,6 +69,7 @@ private:
|
|||||||
static int _heartRateWindow;
|
static int _heartRateWindow;
|
||||||
static int _cadenceWindow;
|
static int _cadenceWindow;
|
||||||
static int _powerWindow;
|
static int _powerWindow;
|
||||||
|
static bool _automaticPause;
|
||||||
static qreal _pauseSpeed;
|
static qreal _pauseSpeed;
|
||||||
static int _pauseInterval;
|
static int _pauseInterval;
|
||||||
static bool _useReportedSpeed;
|
static bool _useReportedSpeed;
|
||||||
|
@ -5,20 +5,25 @@
|
|||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include "trackpoint.h"
|
#include "trackpoint.h"
|
||||||
|
#include "link.h"
|
||||||
|
|
||||||
typedef QVector<Trackpoint> SegmentData;
|
typedef QVector<Trackpoint> SegmentData;
|
||||||
|
|
||||||
class TrackData : public QList<SegmentData>
|
class TrackData : public QList<SegmentData>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const QString& name() const {return _name;}
|
const QString &name() const {return _name;}
|
||||||
const QString& description() const {return _desc;}
|
const QString &description() const {return _desc;}
|
||||||
|
const QVector<Link> &links() const {return _links;}
|
||||||
|
|
||||||
void setName(const QString &name) {_name = name;}
|
void setName(const QString &name) {_name = name;}
|
||||||
void setDescription(const QString &desc) {_desc = desc;}
|
void setDescription(const QString &desc) {_desc = desc;}
|
||||||
|
void addLink(const Link &link) {_links.append(link);}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString _name;
|
QString _name;
|
||||||
QString _desc;
|
QString _desc;
|
||||||
|
QVector<Link> _links;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TRACKDATA_H
|
#endif // TRACKDATA_H
|
||||||
|
@ -4,9 +4,12 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QVector>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "common/coordinates.h"
|
#include "common/coordinates.h"
|
||||||
#include "imageinfo.h"
|
#include "imageinfo.h"
|
||||||
|
#include "link.h"
|
||||||
|
#include "address.h"
|
||||||
|
|
||||||
class Waypoint
|
class Waypoint
|
||||||
{
|
{
|
||||||
@ -18,7 +21,9 @@ public:
|
|||||||
const Coordinates &coordinates() const {return _coordinates;}
|
const Coordinates &coordinates() const {return _coordinates;}
|
||||||
const QString &name() const {return _name;}
|
const QString &name() const {return _name;}
|
||||||
const QString &description() const {return _description;}
|
const QString &description() const {return _description;}
|
||||||
const ImageInfo &image() const {return _image;}
|
const Address &address() const {return _address;}
|
||||||
|
const QVector<ImageInfo> &images() const {return _images;}
|
||||||
|
const QVector<Link> &links() const {return _links;}
|
||||||
const QDateTime ×tamp() const {return _timestamp;}
|
const QDateTime ×tamp() const {return _timestamp;}
|
||||||
qreal elevation() const {return _elevation;}
|
qreal elevation() const {return _elevation;}
|
||||||
|
|
||||||
@ -27,9 +32,11 @@ public:
|
|||||||
void setName(const QString &name) {_name = name;}
|
void setName(const QString &name) {_name = name;}
|
||||||
void setDescription(const QString &description)
|
void setDescription(const QString &description)
|
||||||
{_description = description;}
|
{_description = description;}
|
||||||
|
void setAddress(const Address &address) {_address = address;}
|
||||||
void setTimestamp(const QDateTime ×tamp) {_timestamp = timestamp;}
|
void setTimestamp(const QDateTime ×tamp) {_timestamp = timestamp;}
|
||||||
void setElevation(qreal elevation) {_elevation = elevation;}
|
void setElevation(qreal elevation) {_elevation = elevation;}
|
||||||
void setImage(const ImageInfo &image) {_image = image;}
|
void addImage(const ImageInfo &image) {_images.append(image);}
|
||||||
|
void addLink(const Link &link) {_links.append(link);}
|
||||||
|
|
||||||
bool hasElevation() const {return !std::isnan(_elevation);}
|
bool hasElevation() const {return !std::isnan(_elevation);}
|
||||||
|
|
||||||
@ -41,7 +48,9 @@ private:
|
|||||||
Coordinates _coordinates;
|
Coordinates _coordinates;
|
||||||
QString _name;
|
QString _name;
|
||||||
QString _description;
|
QString _description;
|
||||||
ImageInfo _image;
|
Address _address;
|
||||||
|
QVector<ImageInfo> _images;
|
||||||
|
QVector<Link> _links;
|
||||||
QDateTime _timestamp;
|
QDateTime _timestamp;
|
||||||
qreal _elevation;
|
qreal _elevation;
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "common/rectc.h"
|
#include "common/rectc.h"
|
||||||
#include "units.h"
|
#include "common/garmin.h"
|
||||||
#include "lblfile.h"
|
#include "lblfile.h"
|
||||||
#include "netfile.h"
|
#include "netfile.h"
|
||||||
#include "rgnfile.h"
|
#include "rgnfile.h"
|
||||||
@ -193,7 +193,7 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
|||||||
|
|
||||||
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||||
Coordinates c(toWGS84(pos.x()), toWGS84(pos.y()));
|
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||||
RectC br(c, c);
|
RectC br(c, c);
|
||||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
|||||||
pos.rx() += lonDelta<<(24-subdiv->bits());
|
pos.rx() += lonDelta<<(24-subdiv->bits());
|
||||||
pos.ry() += latDelta<<(24-subdiv->bits());
|
pos.ry() += latDelta<<(24-subdiv->bits());
|
||||||
|
|
||||||
Coordinates c(toWGS84(pos.x()), toWGS84(pos.y()));
|
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||||
br = br.united(c);
|
br = br.united(c);
|
||||||
}
|
}
|
||||||
@ -259,7 +259,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
|||||||
|
|
||||||
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||||
Coordinates c(toWGS84(pos.x()), toWGS84(pos.y()));
|
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||||
RectC br(c, c);
|
RectC br(c, c);
|
||||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||||
|
|
||||||
@ -269,7 +269,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
|||||||
pos.rx() += lonDelta<<(24-subdiv->bits());
|
pos.rx() += lonDelta<<(24-subdiv->bits());
|
||||||
pos.ry() += latDelta<<(24-subdiv->bits());
|
pos.ry() += latDelta<<(24-subdiv->bits());
|
||||||
|
|
||||||
Coordinates c(toWGS84(pos.x()), toWGS84(pos.y()));
|
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||||
br = br.united(c);
|
br = br.united(c);
|
||||||
}
|
}
|
||||||
@ -321,8 +321,8 @@ bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
|||||||
|
|
||||||
qint16 lonOffset = lon<<(24-subdiv->bits());
|
qint16 lonOffset = lon<<(24-subdiv->bits());
|
||||||
qint16 latOffset = lat<<(24-subdiv->bits());
|
qint16 latOffset = lat<<(24-subdiv->bits());
|
||||||
point.coordinates = Coordinates(toWGS84(subdiv->lon() + lonOffset),
|
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
|
||||||
toWGS84(subdiv->lat() + latOffset));
|
toWGS24(subdiv->lat() + latOffset));
|
||||||
|
|
||||||
if (!rect.contains(point.coordinates))
|
if (!rect.contains(point.coordinates))
|
||||||
continue;
|
continue;
|
||||||
@ -367,8 +367,8 @@ bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
|
|||||||
|
|
||||||
qint16 lonOffset = lon<<(24-subdiv->bits());
|
qint16 lonOffset = lon<<(24-subdiv->bits());
|
||||||
qint16 latOffset = lat<<(24-subdiv->bits());
|
qint16 latOffset = lat<<(24-subdiv->bits());
|
||||||
point.coordinates = Coordinates(toWGS84(subdiv->lon() + lonOffset),
|
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
|
||||||
toWGS84(subdiv->lat() + latOffset));
|
toWGS24(subdiv->lat() + latOffset));
|
||||||
|
|
||||||
if (subtype & 0x20) {
|
if (subtype & 0x20) {
|
||||||
if (!readUInt24(hdl, labelPtr))
|
if (!readUInt24(hdl, labelPtr))
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include "common/coordinates.h"
|
#include "common/coordinates.h"
|
||||||
#include "units.h"
|
#include "common/garmin.h"
|
||||||
|
|
||||||
class SubDiv {
|
class SubDiv {
|
||||||
public:
|
public:
|
||||||
@ -51,7 +51,7 @@ private:
|
|||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
inline QDebug operator<<(QDebug dbg, const SubDiv &subdiv)
|
inline QDebug operator<<(QDebug dbg, const SubDiv &subdiv)
|
||||||
{
|
{
|
||||||
Coordinates c(toWGS84(subdiv.lon()), toWGS84(subdiv.lat()));
|
Coordinates c(toWGS24(subdiv.lon()), toWGS24(subdiv.lat()));
|
||||||
dbg.nospace() << "SubDiv(" << c << ", " << subdiv.offset()
|
dbg.nospace() << "SubDiv(" << c << ", " << subdiv.offset()
|
||||||
<< ", " << subdiv.end() << ", " << subdiv.objects() << ")";
|
<< ", " << subdiv.end() << ", " << subdiv.objects() << ")";
|
||||||
return dbg.space();
|
return dbg.space();
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
#include "common/garmin.h"
|
||||||
#include "subdiv.h"
|
#include "subdiv.h"
|
||||||
#include "units.h"
|
|
||||||
#include "trefile.h"
|
#include "trefile.h"
|
||||||
|
|
||||||
|
|
||||||
static void unlock(quint8 *dst, const quint8 *src, quint32 size, quint32 key)
|
static void demangle(quint8 *data, quint32 size, quint32 key)
|
||||||
{
|
{
|
||||||
static const unsigned char shuf[] = {
|
static const unsigned char shuf[] = {
|
||||||
0xb, 0xc, 0xa, 0x0,
|
0xb, 0xc, 0xa, 0x0,
|
||||||
@ -15,8 +15,8 @@ static void unlock(quint8 *dst, const quint8 *src, quint32 size, quint32 key)
|
|||||||
int sum = shuf[((key >> 24) + (key >> 16) + (key >> 8) + key) & 0xf];
|
int sum = shuf[((key >> 24) + (key >> 16) + (key >> 8) + key) & 0xf];
|
||||||
|
|
||||||
for (quint32 i = 0, ringctr = 16; i < size; i++) {
|
for (quint32 i = 0, ringctr = 16; i < size; i++) {
|
||||||
quint32 upper = src[i] >> 4;
|
quint32 upper = data[i] >> 4;
|
||||||
quint32 lower = src[i];
|
quint32 lower = data[i];
|
||||||
|
|
||||||
upper -= sum;
|
upper -= sum;
|
||||||
upper -= key >> ringctr;
|
upper -= key >> ringctr;
|
||||||
@ -28,7 +28,7 @@ static void unlock(quint8 *dst, const quint8 *src, quint32 size, quint32 key)
|
|||||||
lower -= shuf[(key >> ringctr) & 0xf];
|
lower -= shuf[(key >> ringctr) & 0xf];
|
||||||
ringctr = ringctr ? ringctr - 4 : 16;
|
ringctr = ringctr ? ringctr - 4 : 16;
|
||||||
|
|
||||||
dst[i] = ((upper << 4) & 0xf0) | (lower & 0xf);
|
data[i] = ((upper << 4) & 0xf0) | (lower & 0xf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,8 +52,8 @@ bool TREFile::init()
|
|||||||
if (!(seek(hdl, _gmpOffset + 0x15) && readInt24(hdl, north)
|
if (!(seek(hdl, _gmpOffset + 0x15) && readInt24(hdl, north)
|
||||||
&& readInt24(hdl, east) && readInt24(hdl, south) && readInt24(hdl, west)))
|
&& readInt24(hdl, east) && readInt24(hdl, south) && readInt24(hdl, west)))
|
||||||
return false;
|
return false;
|
||||||
_bounds = RectC(Coordinates(toWGS84(west), toWGS84(north)),
|
_bounds = RectC(Coordinates(toWGS24(west), toWGS24(north)),
|
||||||
Coordinates(toWGS84(east), toWGS84(south)));
|
Coordinates(toWGS24(east), toWGS24(south)));
|
||||||
|
|
||||||
// Levels & subdivs info
|
// Levels & subdivs info
|
||||||
quint32 levelsOffset, levelsSize, subdivSize;
|
quint32 levelsOffset, levelsSize, subdivSize;
|
||||||
@ -79,11 +79,9 @@ bool TREFile::init()
|
|||||||
return false;
|
return false;
|
||||||
if (locked) {
|
if (locked) {
|
||||||
quint32 key;
|
quint32 key;
|
||||||
quint8 unlocked[64];
|
|
||||||
if (!seek(hdl, _gmpOffset + 0xAA) || !readUInt32(hdl, key))
|
if (!seek(hdl, _gmpOffset + 0xAA) || !readUInt32(hdl, key))
|
||||||
return false;
|
return false;
|
||||||
unlock(unlocked, levels, levelsSize, key);
|
demangle(levels, levelsSize, key);
|
||||||
memcpy(levels, unlocked, levelsSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 levelsCount = levelsSize / 4;
|
quint32 levelsCount = levelsSize / 4;
|
||||||
@ -152,9 +150,9 @@ bool TREFile::load(int idx)
|
|||||||
sl.append(s);
|
sl.append(s);
|
||||||
|
|
||||||
double min[2], max[2];
|
double min[2], max[2];
|
||||||
RectC bounds(Coordinates(toWGS84(lon - width),
|
RectC bounds(Coordinates(toWGS24(lon - width),
|
||||||
toWGS84(lat + height + 1)), Coordinates(toWGS84(lon + width + 1),
|
toWGS24(lat + height + 1)), Coordinates(toWGS24(lon + width + 1),
|
||||||
toWGS84(lat - height)));
|
toWGS24(lat - height)));
|
||||||
|
|
||||||
min[0] = bounds.left();
|
min[0] = bounds.left();
|
||||||
min[1] = bounds.bottom();
|
min[1] = bounds.bottom();
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
#ifndef UNITS_H
|
|
||||||
#define UNITS_H
|
|
||||||
|
|
||||||
inline double toWGS84(qint32 coord)
|
|
||||||
{
|
|
||||||
return (coord < 0x800000)
|
|
||||||
? (double)coord * 360.0 / (double)(1<<24)
|
|
||||||
: (double)(coord - 0x1000000) * 360.0 / (double)(1<<24);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // UNITS_H
|
|
@ -16,8 +16,8 @@
|
|||||||
#include "imgmap.h"
|
#include "imgmap.h"
|
||||||
|
|
||||||
|
|
||||||
#define TILE_SIZE 256
|
#define TILE_SIZE 384
|
||||||
#define TEXT_EXTENT 256
|
#define TEXT_EXTENT 160
|
||||||
|
|
||||||
#define AREA(rect) \
|
#define AREA(rect) \
|
||||||
(rect.size().width() * rect.size().height())
|
(rect.size().width() * rect.size().height())
|
||||||
@ -419,7 +419,7 @@ void IMGMap::processShields(QList<IMG::Poly> &lines, const QRect &tileRect,
|
|||||||
= shields.constBegin(); it != shields.constEnd(); ++it) {
|
= shields.constBegin(); it != shields.constEnd(); ++it) {
|
||||||
const QPolygonF &p = it.value();
|
const QPolygonF &p = it.value();
|
||||||
QRectF rect(p.boundingRect() & tileRect);
|
QRectF rect(p.boundingRect() & tileRect);
|
||||||
if (qSqrt(AREA(rect)) < 32)
|
if (qSqrt(AREA(rect)) < TILE_SIZE/8)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QMap<qreal, int> map;
|
QMap<qreal, int> map;
|
||||||
|
@ -32,7 +32,7 @@ Range MapSource::zooms(QXmlStreamReader &reader)
|
|||||||
|
|
||||||
if (attr.hasAttribute("min")) {
|
if (attr.hasAttribute("min")) {
|
||||||
min = attr.value("min").toString().toInt(&res);
|
min = attr.value("min").toString().toInt(&res);
|
||||||
if (!res || !OSM::ZOOMS.contains(min)) {
|
if (!res || min < 0) {
|
||||||
reader.raiseError("Invalid minimal zoom level");
|
reader.raiseError("Invalid minimal zoom level");
|
||||||
return Range();
|
return Range();
|
||||||
}
|
}
|
||||||
@ -41,18 +41,13 @@ Range MapSource::zooms(QXmlStreamReader &reader)
|
|||||||
|
|
||||||
if (attr.hasAttribute("max")) {
|
if (attr.hasAttribute("max")) {
|
||||||
max = attr.value("max").toString().toInt(&res);
|
max = attr.value("max").toString().toInt(&res);
|
||||||
if (!res || !OSM::ZOOMS.contains(max)) {
|
if (!res || max < min) {
|
||||||
reader.raiseError("Invalid maximal zoom level");
|
reader.raiseError("Invalid maximal zoom level");
|
||||||
return Range();
|
return Range();
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
max = OSM::ZOOMS.max();
|
max = OSM::ZOOMS.max();
|
||||||
|
|
||||||
if (min > max) {
|
|
||||||
reader.raiseError("Invalid maximal/minimal zoom level combination");
|
|
||||||
return Range();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Range(min, max);
|
return Range(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,8 @@ void OnlineMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
Tile &t = tiles[i];
|
Tile &t = tiles[i];
|
||||||
QPointF tp = _zoom ? QPointF(tl.x() + (t.xy().x() - tile.x())
|
QPointF tp = _zoom ? QPointF(tl.x() + (t.xy().x() - tile.x())
|
||||||
* tileSize(), tl.y() + ((_invertY ? (1<<_zoom) - t.xy().y() - 1 :
|
* tileSize(), tl.y() + ((_invertY ? (1<<_zoom) - t.xy().y() - 1 :
|
||||||
t.xy().y()) - tile.y()) * tileSize()) : QPointF(-128, -128);
|
t.xy().y()) - tile.y()) * tileSize())
|
||||||
|
: QPointF(-_tileSize/2, -_tileSize/2);
|
||||||
|
|
||||||
if (!t.pixmap().isNull()) {
|
if (!t.pixmap().isNull()) {
|
||||||
#ifdef ENABLE_HIDPI
|
#ifdef ENABLE_HIDPI
|
||||||
|
Reference in New Issue
Block a user