1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-14 19:04:23 +02:00

Compare commits

...

53 Commits
6.2 ... 7.0

Author SHA1 Message Date
9f0fcdc13e Fixed broken map sources parsing 2018-12-08 02:27:27 +01:00
5b21d550af English translation file shall have plurals only 2018-11-26 23:53:56 +01:00
6f4259298b Localization update 2018-11-26 22:31:27 +01:00
2c1a9f88c4 Enabled Turkish translation 2018-11-22 22:59:31 +01:00
48438f9b4d Translated using Weblate (Turkish)
Currently translated at 100.0% (323 of 323 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2018-11-22 22:41:49 +01:00
9b7651bad4 Translated using Weblate (Turkish)
Currently translated at 56.0% (181 of 323 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2018-11-22 22:41:49 +01:00
b6ef1d36d6 Translated using Weblate (Turkish)
Currently translated at 2.5% (8 of 323 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2018-11-22 22:41:49 +01:00
d3cbdb8b92 Translated using Weblate (Finnish)
Currently translated at 98.7% (320 of 324 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2018-11-22 22:41:49 +01:00
a98e9a9784 Fixed QT4 build 2018-11-17 21:01:08 +01:00
3c6ce2dde2 Propper handling of vector tiles scaling in all map display modes 2018-11-17 10:10:35 +01:00
4c88414677 Scale the tile images in HiDPImode when they are scalable (vector tiles) 2018-11-15 00:38:03 +01:00
ac5476868d Added Turkish translations stub 2018-11-12 20:08:16 +01:00
bf6d7616ba The default constructor is required with some C++ compilers 2018-11-11 18:54:21 +01:00
9842214bb6 Parallelized tile loader 2018-11-10 13:18:54 +01:00
b6e9400392 Code cleanup 2018-11-10 10:44:37 +01:00
c1a217847f QPixmap is not thread safe, do the parallel computations on QImage 2018-11-10 10:40:00 +01:00
409ce889cd Added support for online PBF maps
(https://maps.tilehosting.com)
2018-11-10 00:19:51 +01:00
09242841e3 Fixed Qt 4 cache paths 2018-11-07 23:07:09 +01:00
a299207e5d Use standards compliant paths for the tile chache 2018-11-07 22:53:27 +01:00
efc773d04b Run the parallel computation only for tiles to be (newly) rendered 2018-11-06 01:30:29 +01:00
16c95334a0 Added missing QtConcurrent libs to the installers 2018-11-04 01:14:31 +01:00
49ccb508a0 Fixed broken tiles dir program path 2018-11-04 01:04:47 +01:00
9c6c574443 Added support for vector MBtiles 2018-11-03 00:43:52 +01:00
f762013e1e Changed application data paths to more platform-standard locations 2018-11-02 20:01:19 +01:00
f6b1344ee2 Improved error handling 2018-10-26 18:47:34 +02:00
9f3129f899 Fixed some corner case min/max graph values issue 2018-10-26 09:15:23 +02:00
f05ff372e7 Update gpxsee_fr.ts (#166)
* Update gpxsee_fr.ts

* Update gpxsee_fr.ts

* Update gpxsee_fr.ts

* Update gpxsee_fr.ts

* Update gpxsee_fr.ts
2018-10-20 15:22:10 +02:00
c0adabe3f1 Code cleanup 2018-10-15 01:15:00 +02:00
4a612f12bb Properly handle WMTS TileMatrixLimits and default style 2018-10-15 00:20:20 +02:00
8f4ce8d38c Code cleanup 2018-10-11 18:19:35 +02:00
b73072795a Update PL translation (#165)
Update gpxsee_pl.ts
2018-10-10 23:24:08 +02:00
57d3d9c965 Cosmetics 2018-10-09 22:59:20 +02:00
d97a8c03a7 Danish localization update 2018-10-09 22:48:21 +02:00
58b44d33a7 Fixed broken bounds handling 2018-10-09 22:46:28 +02:00
5c6f405795 appveyor script fix 2018-10-09 01:16:34 +02:00
156467a261 Added missing NSIS include file to appveyor script 2018-10-09 01:04:15 +02:00
f4d5f8d057 NSIS scripts cleanup 2018-10-09 00:46:13 +02:00
b3655f6a1f Squashed commit of the following:
commit f819840aff
Merge: 46bf281 49470f2
Author: Hosted Weblate <hosted@weblate.org>
Date:   Tue Oct 9 00:01:42 2018 +0200

    Merge branch 'origin/master' into Weblate

commit 49470f22b2
Merge: 078b272 ed03e31
Author: Hosted Weblate <hosted@weblate.org>
Date:   Mon Oct 8 23:56:36 2018 +0200

    Merge branch 'origin/master' into Weblate

commit ed03e31949
Merge: ce41409 605b09c
Author: Hosted Weblate <hosted@weblate.org>
Date:   Mon Oct 8 23:53:56 2018 +0200

    Merge branch 'origin/master' into Weblate

commit 605b09c195
Author: Allan Nordhøy <epost@anotheragency.no>
Date:   Mon Oct 8 20:26:04 2018 +0000

    Translated using Weblate (Norwegian Bokmål)

    Currently translated at 92.2% (299 of 324 strings)

    Translation: GPXSee/Translations
    Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/nb/

commit 0898953674
Merge: fd0401a 869fdf5
Author: Hosted Weblate <hosted@weblate.org>
Date:   Mon Oct 8 22:24:40 2018 +0200

    Merge branch 'origin/master' into Weblate

commit 869fdf5982
Merge: 7fe5189 aa32415
Author: Hosted Weblate <hosted@weblate.org>
Date:   Mon Oct 8 22:09:51 2018 +0200

    Merge branch 'origin/master' into Weblate

commit aa32415adb
Author: jan madsen <jsm@janz.dk>
Date:   Mon Oct 8 12:01:51 2018 +0000

    Translated using Weblate (Danish)

    Currently translated at 85.4% (275 of 322 strings)

    Translation: GPXSee/Translations
    Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/da/

commit c1a64d2c0b
Author: jan madsen <jsm@janz.dk>
Date:   Mon Oct 8 10:53:55 2018 +0000

    Translated using Weblate (Danish)

    Currently translated at 34.1% (110 of 322 strings)

    Translation: GPXSee/Translations
    Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/da/

commit 31bbdba548
Author: jan madsen <jsm@janz.dk>
Date:   Mon Oct 8 10:36:54 2018 +0000

    Translated using Weblate (Danish)

    Currently translated at 19.8% (64 of 322 strings)

    Translation: GPXSee/Translations
    Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/da/
2018-10-09 00:18:17 +02:00
f819840aff Merge branch 'origin/master' into Weblate 2018-10-09 00:01:42 +02:00
46bf281644 Enabled Danish localization 2018-10-09 00:01:18 +02:00
49470f22b2 Merge branch 'origin/master' into Weblate 2018-10-08 23:56:36 +02:00
078b272828 Squashed commit of the following:
commit ed03e31949
Merge: ce41409 605b09c
Author: Hosted Weblate <hosted@weblate.org>
Date:   Mon Oct 8 23:53:56 2018 +0200

    Merge branch 'origin/master' into Weblate

commit 605b09c195
Author: Allan Nordhøy <epost@anotheragency.no>
Date:   Mon Oct 8 20:26:04 2018 +0000

    Translated using Weblate (Norwegian Bokmål)

    Currently translated at 92.2% (299 of 324 strings)

    Translation: GPXSee/Translations
    Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/nb/

commit 0898953674
Merge: fd0401a 869fdf5
Author: Hosted Weblate <hosted@weblate.org>
Date:   Mon Oct 8 22:24:40 2018 +0200

    Merge branch 'origin/master' into Weblate

commit 869fdf5982
Merge: 7fe5189 aa32415
Author: Hosted Weblate <hosted@weblate.org>
Date:   Mon Oct 8 22:09:51 2018 +0200

    Merge branch 'origin/master' into Weblate

commit aa32415adb
Author: jan madsen <jsm@janz.dk>
Date:   Mon Oct 8 12:01:51 2018 +0000

    Translated using Weblate (Danish)

    Currently translated at 85.4% (275 of 322 strings)

    Translation: GPXSee/Translations
    Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/da/

commit c1a64d2c0b
Author: jan madsen <jsm@janz.dk>
Date:   Mon Oct 8 10:53:55 2018 +0000

    Translated using Weblate (Danish)

    Currently translated at 34.1% (110 of 322 strings)

    Translation: GPXSee/Translations
    Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/da/

commit 31bbdba548
Author: jan madsen <jsm@janz.dk>
Date:   Mon Oct 8 10:36:54 2018 +0000

    Translated using Weblate (Danish)

    Currently translated at 19.8% (64 of 322 strings)

    Translation: GPXSee/Translations
    Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/da/
2018-10-08 23:56:23 +02:00
ed03e31949 Merge branch 'origin/master' into Weblate 2018-10-08 23:53:56 +02:00
605b09c195 Translated using Weblate (Norwegian Bokmål)
Currently translated at 92.2% (299 of 324 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/nb/
2018-10-08 23:53:55 +02:00
ce41409713 Fixed english translation file (plurals only) 2018-10-08 23:53:24 +02:00
0898953674 Merge branch 'origin/master' into Weblate 2018-10-08 22:24:40 +02:00
fd0401a4a6 Yet another incomplete localization source fix 2018-10-08 22:24:05 +02:00
869fdf5982 Merge branch 'origin/master' into Weblate 2018-10-08 22:09:51 +02:00
7fe518966c Made the "About GPXSee" string better localizable. 2018-10-08 22:08:59 +02:00
e568806366 Never change a winning team! 2018-10-08 22:07:36 +02:00
aa32415adb Translated using Weblate (Danish)
Currently translated at 85.4% (275 of 322 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/da/
2018-10-08 21:29:35 +02:00
c1a64d2c0b Translated using Weblate (Danish)
Currently translated at 34.1% (110 of 322 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/da/
2018-10-08 13:40:14 +02:00
31bbdba548 Translated using Weblate (Danish)
Currently translated at 19.8% (64 of 322 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/da/
2018-10-08 12:53:39 +02:00
86 changed files with 5033 additions and 2948 deletions

View File

@ -1,4 +1,4 @@
version: 6.2.{build}
version: 7.0.{build}
configuration: Release
platform: Any CPU
environment:
@ -34,6 +34,8 @@ build_script:
copy pkg\%NSI% installer
copy pkg\macros.nsh installer
xcopy pkg\csv installer\csv /i
xcopy pkg\maps installer\maps /i

View File

@ -1,10 +1,11 @@
TARGET = GPXSee
VERSION = 6.2
VERSION = 7.0
QT += core \
gui \
network \
sql
sql \
concurrent
greaterThan(QT_MAJOR_VERSION, 4) {
QT += widgets
QT += printsupport
@ -13,15 +14,17 @@ lessThan(QT_MAJOR_VERSION, 5) {QT += opengl}
equals(QT_MAJOR_VERSION, 5) : lessThan(QT_MINOR_VERSION, 4) {QT += opengl}
INCLUDEPATH += ./src
HEADERS += src/config.h \
HEADERS += src/common/config.h \
src/common/staticassert.h \
src/common/coordinates.h \
src/common/range.h \
src/common/rectc.h \
src/common/wgs84.h \
src/common/str2int.h \
src/common/util.h \
src/common/rtree.h \
src/common/kv.h \
src/common/greatcircle.h \
src/common/programpaths.h \
src/GUI/app.h \
src/GUI/icons.h \
src/GUI/gui.h \
@ -71,10 +74,10 @@ HEADERS += src/config.h \
src/GUI/gearratiographitem.h \
src/GUI/oddspinbox.h \
src/GUI/settings.h \
src/GUI/nicenum.h \
src/GUI/cpuarch.h \
src/GUI/searchpointer.h \
src/GUI/mapview.h \
src/GUI/font.h \
src/map/projection.h \
src/map/ellipsoid.h \
src/map/datum.h \
@ -115,6 +118,15 @@ HEADERS += src/config.h \
src/map/crs.h \
src/map/coordinatesystem.h \
src/map/pointd.h \
src/map/rectd.h \
src/map/geocentric.h \
src/map/mercator.h \
src/map/jnxmap.h \
src/map/krovak.h \
src/map/geotiffmap.h \
src/map/image.h \
src/map/mbtilesmap.h \
src/map/osm.h \
src/data/graph.h \
src/data/poi.h \
src/data/waypoint.h \
@ -134,23 +146,15 @@ HEADERS += src/config.h \
src/data/igcparser.h \
src/data/nmeaparser.h \
src/data/oziparsers.h \
src/map/rectd.h \
src/map/geocentric.h \
src/map/mercator.h \
src/map/jnxmap.h \
src/map/krovak.h \
src/data/locparser.h \
src/data/slfparser.h \
src/map/geotiffmap.h \
src/map/image.h \
src/common/greatcircle.h \
src/map/mbtilesmap.h \
src/map/osm.h
src/data/slfparser.h
SOURCES += src/main.cpp \
src/common/coordinates.cpp \
src/common/rectc.cpp \
src/common/range.cpp \
src/common/str2int.cpp \
src/common/util.cpp \
src/common/greatcircle.cpp \
src/common/programpaths.cpp \
src/GUI/app.cpp \
src/GUI/gui.cpp \
src/GUI/axisitem.cpp \
@ -192,7 +196,6 @@ SOURCES += src/main.cpp \
src/GUI/cadencegraphitem.cpp \
src/GUI/powergraphitem.cpp \
src/GUI/gearratiographitem.cpp \
src/GUI/nicenum.cpp \
src/GUI/mapview.cpp \
src/map/maplist.cpp \
src/map/onlinemap.cpp \
@ -229,6 +232,15 @@ SOURCES += src/main.cpp \
src/map/wms.cpp \
src/map/crs.cpp \
src/map/coordinatesystem.cpp \
src/map/geocentric.cpp \
src/map/mercator.cpp \
src/map/jnxmap.cpp \
src/map/krovak.cpp \
src/map/map.cpp \
src/map/geotiffmap.cpp \
src/map/image.cpp \
src/map/mbtilesmap.cpp \
src/map/osm.cpp \
src/data/data.cpp \
src/data/poi.cpp \
src/data/track.cpp \
@ -242,19 +254,8 @@ SOURCES += src/main.cpp \
src/data/igcparser.cpp \
src/data/nmeaparser.cpp \
src/data/oziparsers.cpp \
src/map/geocentric.cpp \
src/map/mercator.cpp \
src/map/jnxmap.cpp \
src/map/krovak.cpp \
src/map/map.cpp \
src/data/locparser.cpp \
src/data/slfparser.cpp \
src/map/geotiffmap.cpp \
src/map/image.cpp \
src/common/greatcircle.cpp \
src/map/mbtilesmap.cpp \
src/map/osm.cpp
src/data/slfparser.cpp
RESOURCES += gpxsee.qrc
TRANSLATIONS = lang/gpxsee_en.ts \
lang/gpxsee_cs.ts \
@ -264,7 +265,9 @@ TRANSLATIONS = lang/gpxsee_en.ts \
lang/gpxsee_fi.ts \
lang/gpxsee_fr.ts \
lang/gpxsee_pl.ts \
lang/gpxsee_nb.ts
lang/gpxsee_nb.ts \
lang/gpxsee_da.ts \
lang/gpxsee_tr.ts
macx {
ICON = icons/gpxsee.icns
@ -278,7 +281,9 @@ macx {
lang/gpxsee_ru.qm \
lang/gpxsee_sv.qm \
lang/gpxsee_pl.qm \
lang/gpxsee_nb.qm
lang/gpxsee_nb.qm \
lang/gpxsee_da.qm \
lang/gpxsee_tr.qm
CSV.path = Contents/Resources
CSV.files = pkg/csv
MAPS.path = Contents/Resources

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

View File

@ -1,14 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
<context>
<name>GUI</name>
<message numerus="yes">
<source>%n files</source>
<translation>
<numerusform>%n file</numerusform>
<numerusform>%n files</numerusform>
</translation>
</message>
</context>
</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

1748
lang/gpxsee_tr.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,36 +1,13 @@
!include "MUI2.nsh"
!include "x64.nsh"
!include "WinVer.nsh"
; Macros
!macro FILE_ASSOCIATION_ADD EXT DESC ICON
WriteRegStr HKCR ".${EXT}" "" "GPXSee.${EXT}"
WriteRegStr HKCR "GPXSee.${EXT}" "" "${DESC}"
WriteRegStr HKCR "GPXSee.${EXT}\DefaultIcon" "" "$INSTDIR\GPXSee.exe,${ICON}"
WriteRegStr HKCR "GPXSee.${EXT}\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
!macroend
!macro FILE_ASSOCIATION_REMOVE EXT
DeleteRegKey HKCR "GPXSee.${EXT}"
DeleteRegKey HKCR ".${EXT}"
!macroend
!macro LOCALIZATION LANG CODE
Section "${LANG}"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_${CODE}.qm translations\gpxsee_${CODE}.qm
!if /FileExists translations\qt_${CODE}.qm
File /oname=translations\qt_${CODE}.qm translations\qt_${CODE}.qm
!endif
SectionEnd
!macroend
!include "macros.nsh"
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "6.2"
!define VERSION "7.0"
; The file to write
OutFile "GPXSee-${VERSION}.exe"
@ -154,6 +131,7 @@ Section "QT framework" SEC_QT
File "Qt5PrintSupport.dll"
File "Qt5Network.dll"
File "Qt5Sql.dll"
File "Qt5Concurrent.dll"
File /r "platforms"
File /r "imageformats"
File /r "printsupport"
@ -203,6 +181,7 @@ SectionEnd
SectionGroup "Localization" SEC_LOCALIZATION
!insertmacro LOCALIZATION "Czech" "cs"
!insertmacro LOCALIZATION "Danish" "da"
!insertmacro LOCALIZATION "Finnish" "fi"
!insertmacro LOCALIZATION "French" "fr"
!insertmacro LOCALIZATION "German" "de"
@ -210,6 +189,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
!insertmacro LOCALIZATION "Polish" "pl"
!insertmacro LOCALIZATION "Russian" "ru"
!insertmacro LOCALIZATION "Swedish" "sv"
!insertmacro LOCALIZATION "Turkish" "tr"
SectionGroupEnd
;--------------------------------

View File

@ -1,36 +1,13 @@
!include "MUI2.nsh"
!include "x64.nsh"
!include "WinVer.nsh"
; Macros
!macro FILE_ASSOCIATION_ADD EXT DESC ICON
WriteRegStr HKCR ".${EXT}" "" "GPXSee.${EXT}"
WriteRegStr HKCR "GPXSee.${EXT}" "" "${DESC}"
WriteRegStr HKCR "GPXSee.${EXT}\DefaultIcon" "" "$INSTDIR\GPXSee.exe,${ICON}"
WriteRegStr HKCR "GPXSee.${EXT}\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
!macroend
!macro FILE_ASSOCIATION_REMOVE EXT
DeleteRegKey HKCR "GPXSee.${EXT}"
DeleteRegKey HKCR ".${EXT}"
!macroend
!macro LOCALIZATION LANG CODE
Section "${LANG}"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_${CODE}.qm translations\gpxsee_${CODE}.qm
!if /FileExists translations\qt_${CODE}.qm
File /oname=translations\qt_${CODE}.qm translations\qt_${CODE}.qm
!endif
SectionEnd
!macroend
!include "macros.nsh"
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "6.2"
!define VERSION "7.0"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"
@ -161,6 +138,7 @@ Section "QT framework" SEC_QT
File "Qt5PrintSupport.dll"
File "Qt5Network.dll"
File "Qt5Sql.dll"
File "Qt5Concurrent.dll"
File /r "platforms"
File /r "imageformats"
File /r "printsupport"
@ -205,6 +183,7 @@ SectionEnd
SectionGroup "Localization" SEC_LOCALIZATION
!insertmacro LOCALIZATION "Czech" "cs"
!insertmacro LOCALIZATION "Danish" "da"
!insertmacro LOCALIZATION "Finnish" "fi"
!insertmacro LOCALIZATION "French" "fr"
!insertmacro LOCALIZATION "German" "de"
@ -212,6 +191,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
!insertmacro LOCALIZATION "Polish" "pl"
!insertmacro LOCALIZATION "Russian" "ru"
!insertmacro LOCALIZATION "Swedish" "sv"
!insertmacro LOCALIZATION "Turkish" "tr"
SectionGroupEnd
;--------------------------------

23
pkg/macros.nsh Normal file
View File

@ -0,0 +1,23 @@
; File association
!macro FILE_ASSOCIATION_ADD EXT DESC ICON
WriteRegStr HKCR ".${EXT}" "" "GPXSee.${EXT}"
WriteRegStr HKCR "GPXSee.${EXT}" "" "${DESC}"
WriteRegStr HKCR "GPXSee.${EXT}\DefaultIcon" "" "$INSTDIR\GPXSee.exe,${ICON}"
WriteRegStr HKCR "GPXSee.${EXT}\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
!macroend
!macro FILE_ASSOCIATION_REMOVE EXT
DeleteRegKey HKCR "GPXSee.${EXT}"
DeleteRegKey HKCR ".${EXT}"
!macroend
; Translations
!macro LOCALIZATION LANG CODE
Section "${LANG}"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_${CODE}.qm translations\gpxsee_${CODE}.qm
!if /FileExists translations\qt_${CODE}.qm
File /oname=translations\qt_${CODE}.qm translations\qt_${CODE}.qm
!endif
SectionEnd
!macroend

View File

@ -6,13 +6,14 @@
#include <QNetworkAccessManager>
#include <QLibraryInfo>
#include <QSettings>
#include "common/programpaths.h"
#include "common/config.h"
#include "map/downloader.h"
#include "map/ellipsoid.h"
#include "map/gcs.h"
#include "map/pcs.h"
#include "opengl.h"
#include "gui.h"
#include "config.h"
#include "settings.h"
#include "app.h"
@ -20,13 +21,21 @@
App::App(int &argc, char **argv) : QApplication(argc, argv),
_argc(argc), _argv(argv)
{
#if defined(Q_OS_WIN32) || defined(Q_OS_MAC)
setApplicationName(APP_NAME);
#else
setApplicationName(QString(APP_NAME).toLower());
#endif
setApplicationVersion(APP_VERSION);
QTranslator *gpxsee = new QTranslator(this);
gpxsee->load(QLocale::system(), "gpxsee", "_", TRANSLATIONS_DIR);
gpxsee->load(QLocale::system(), "gpxsee", "_",
ProgramPaths::translationsDir());
installTranslator(gpxsee);
QTranslator *qt = new QTranslator(this);
#if defined(Q_OS_WIN32) || defined(Q_OS_MAC)
qt->load(QLocale::system(), "qt", "_", TRANSLATIONS_DIR);
qt->load(QLocale::system(), "qt", "_", ProgramPaths::translationsDir());
#else // Q_OS_WIN32 || Q_OS_MAC
qt->load(QLocale::system(), "qt", "_", QLibraryInfo::location(
QLibraryInfo::TranslationsPath));
@ -40,6 +49,11 @@ App::App(int &argc, char **argv) : QApplication(argc, argv),
QNetworkProxyFactory::setUseSystemConfiguration(true);
QSettings settings(APP_NAME, APP_NAME);
settings.beginGroup(OPTIONS_SETTINGS_GROUP);
/* The QNetworkAccessManager must be a child of QApplication, otherwise it
triggers the following warning on exit (and may probably crash):
"QThreadStorage: Thread X exited after QThreadStorage Y destroyed" */
Downloader::setNetworkManager(new QNetworkAccessManager(this));
#ifdef ENABLE_HTTP2
Downloader::enableHTTP2(settings.value(ENABLE_HTTP2_SETTING,
ENABLE_HTTP2_DEFAULT).toBool());
@ -60,14 +74,15 @@ App::~App()
delete _gui;
}
void App::run()
int App::run()
{
_gui->show();
for (int i = 1; i < _argc; i++)
_gui->openFile(QString::fromLocal8Bit(_argv[i]));
QStringList args(arguments());
for (int i = 1; i < args.count(); i++)
_gui->openFile(args.at(i));
exec();
return exec();
}
bool App::event(QEvent *event)
@ -82,41 +97,27 @@ bool App::event(QEvent *event)
void App::loadDatums()
{
QString ef, df;
QString ellipsoidsFile(ProgramPaths::ellipsoidsFile());
QString gcsFile(ProgramPaths::gcsFile());
if (QFile::exists(USER_ELLIPSOID_FILE))
ef = USER_ELLIPSOID_FILE;
else if (QFile::exists(GLOBAL_ELLIPSOID_FILE))
ef = GLOBAL_ELLIPSOID_FILE;
else
if (ellipsoidsFile.isNull())
qWarning("No ellipsoids file found.");
if (gcsFile.isNull())
qWarning("No GCS file found.");
if (QFile::exists(USER_GCS_FILE))
df = USER_GCS_FILE;
else if (QFile::exists(GLOBAL_GCS_FILE))
df = GLOBAL_GCS_FILE;
else
qWarning("No datums file found.");
if (!ef.isNull() && !df.isNull()) {
Ellipsoid::loadList(ef);
GCS::loadList(df);
if (!ellipsoidsFile.isNull() && !gcsFile.isNull()) {
Ellipsoid::loadList(ellipsoidsFile);
GCS::loadList(gcsFile);
} else
qWarning("Maps based on a datum different from WGS84 won't work.");
}
void App::loadPCSs()
{
QString file;
QString pcsFile(ProgramPaths::pcsFile());
if (QFile::exists(USER_PCS_FILE))
file = USER_PCS_FILE;
else if (QFile::exists(GLOBAL_PCS_FILE))
file = GLOBAL_PCS_FILE;
else {
if (pcsFile.isNull())
qWarning("No PCS file found.");
return;
}
PCS::loadList(file);
else
PCS::loadList(pcsFile);
}

View File

@ -12,7 +12,7 @@ class App : QApplication
public:
App(int &argc, char **argv);
~App();
void run();
int run();
protected:
bool event(QEvent *event);

View File

@ -1,7 +1,7 @@
#include <cmath>
#include <QPainter>
#include "config.h"
#include "nicenum.h"
#include "common/util.h"
#include "font.h"
#include "axisitem.h"

View File

@ -7,9 +7,14 @@ CadenceGraphItem::CadenceGraphItem(const Graph &graph, GraphType type,
QGraphicsItem *parent) : GraphItem(graph, type, parent)
{
qreal sum = 0;
_max = graph.first().y();
for (int j = 1; j < graph.size(); j++)
sum += graph.at(j).y() * (graph.at(j).s() - graph.at(j-1).s());
for (int i = 1; i < graph.size(); i++) {
qreal y = graph.at(i).y();
sum += y * (graph.at(i).s() - graph.at(i-1).s());
if (y > _max)
_max = y;
}
_avg = sum/graph.last().s();
setToolTip(toolTip());

View File

@ -11,13 +11,13 @@ public:
CadenceGraphItem(const Graph &graph, GraphType type,
QGraphicsItem *parent = 0);
qreal max() const {return -bounds().top();}
qreal max() const {return _max;}
qreal avg() const {return _avg;}
private:
QString toolTip() const;
qreal _avg;
qreal _avg, _max;
};
#endif // CADENCEGRAPHITEM_H

View File

@ -1,7 +1,6 @@
#include <cmath>
#include <QLocale>
#include "data/data.h"
#include "config.h"
#include "tooltip.h"
#include "elevationgraphitem.h"
#include "elevationgraph.h"

View File

@ -7,6 +7,7 @@ ElevationGraphItem::ElevationGraphItem(const Graph &graph, GraphType type,
QGraphicsItem *parent) : GraphItem(graph, type, parent)
{
_ascent = _descent = 0;
_min = _max = graph.first().y();
for (int j = 1; j < graph.size(); j++) {
qreal cur = graph.at(j).y();
@ -16,6 +17,11 @@ ElevationGraphItem::ElevationGraphItem(const Graph &graph, GraphType type,
_ascent += cur - prev;
if (cur < prev)
_descent += prev - cur;
if (cur < _min)
_min = cur;
if (cur > _max)
_max = cur;
}
setToolTip(toolTip(Metric));

View File

@ -13,15 +13,15 @@ public:
qreal ascent() const {return _ascent;}
qreal descent() const {return _descent;}
qreal min() const {return -bounds().bottom();}
qreal max() const {return -bounds().top();}
qreal min() const {return _min;}
qreal max() const {return _max;}
void setUnits(Units units);
private:
QString toolTip(Units units) const;
qreal _ascent, _descent;
qreal _ascent, _descent, _min, _max;
};
#endif // ELEVATIONGRAPHITEM_H

7
src/GUI/font.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef FONT_H
#define FONT_H
#define FONT_FAMILY "Arial"
#define FONT_SIZE 12 // px
#endif // FONT_H

View File

@ -8,11 +8,18 @@ GearRatioGraphItem::GearRatioGraphItem(const Graph &graph, GraphType type,
QGraphicsItem *parent) : GraphItem(graph, type, parent), _top(NAN)
{
qreal val = NAN;
_min = _max = graph.first().y();
for (int i = 1; i < graph.size(); i++) {
const GraphPoint &p = graph.at(i);
for (int j = 1; j < graph.size(); j++) {
const GraphPoint &p = graph.at(j);
qreal val = _map.value(p.y());
_map.insert(p.y(), val + (p.s() - graph.at(j-1).s()));
_map.insert(p.y(), val + (p.s() - graph.at(i-1).s()));
if (p.y() < _min)
_min = p.y();
if (p.y() > _max)
_max = p.y();
}
for (QMap<qreal, qreal>::const_iterator it = _map.constBegin();

View File

@ -12,8 +12,8 @@ public:
GearRatioGraphItem(const Graph &graph, GraphType type,
QGraphicsItem *parent = 0);
qreal min() const {return -bounds().bottom();}
qreal max() const {return -bounds().top();}
qreal min() const {return _min;}
qreal max() const {return _max;}
qreal top() const {return _top;}
const QMap<qreal, qreal> &map() const {return _map;}
@ -22,7 +22,7 @@ private:
QString toolTip() const;
QMap<qreal, qreal> _map;
qreal _top;
qreal _top, _min, _max;
};
#endif // GEARRATIOGRAPHITEM_H

View File

@ -8,7 +8,6 @@
#include <QLocale>
#include "data/graph.h"
#include "opengl.h"
#include "config.h"
#include "axisitem.h"
#include "slideritem.h"
#include "sliderinfoitem.h"

View File

@ -1,4 +1,4 @@
#include "config.h"
#include "common/config.h"
#include <QApplication>
#include <QSplitter>
#include <QVBoxLayout>
@ -28,6 +28,7 @@
#include <QScreen>
#endif // ENABLE_HIDPI
#include <QStyle>
#include "common/programpaths.h"
#include "data/data.h"
#include "data/poi.h"
#include "map/maplist.h"
@ -108,14 +109,9 @@ GUI::GUI()
void GUI::loadMaps()
{
_ml = new MapList(this);
QString dir;
QString mapDir(ProgramPaths::mapDir());
if (QFile::exists(USER_MAP_DIR))
dir = USER_MAP_DIR;
else if (QFile::exists(GLOBAL_MAP_DIR))
dir = GLOBAL_MAP_DIR;
if (!dir.isNull() && !_ml->loadDir(dir))
if (!mapDir.isNull() && !_ml->loadDir(mapDir))
qWarning("%s", qPrintable(_ml->errorString()));
_map = new EmptyMap(this);
@ -124,14 +120,9 @@ void GUI::loadMaps()
void GUI::loadPOIs()
{
_poi = new POI(this);
QString dir;
QString poiDir(ProgramPaths::poiDir());
if (QFile::exists(USER_POI_DIR))
dir = USER_POI_DIR;
else if (QFile::exists(GLOBAL_POI_DIR))
dir = GLOBAL_POI_DIR;
if (!dir.isNull() && !_poi->loadDir(dir))
if (!poiDir.isNull() && !_poi->loadDir(poiDir))
qWarning("%s", qPrintable(_poi->errorString()));
}
@ -644,14 +635,15 @@ void GUI::about()
QUrl homepage(APP_HOMEPAGE);
msgBox.setWindowTitle(tr("About GPXSee"));
msgBox.setText("<h2>" + QString(APP_NAME) + "</h2><p><p>" + tr("Version ")
+ APP_VERSION + " (" + CPU_ARCH + ", Qt " + QT_VERSION_STR + ")</p>");
msgBox.setText("<h2>" + QString(APP_NAME) + "</h2><p><p>" + tr("Version %1")
.arg(QString(APP_VERSION) + " (" + CPU_ARCH + ", Qt " + QT_VERSION_STR
+ ")") + "</p>");
msgBox.setInformativeText("<table width=\"300\"><tr><td>"
+ tr("GPXSee is distributed under the terms of the GNU General Public "
"License version 3. For more info about GPXSee visit the project "
"homepage at ") + "<a href=\"" + homepage.toString() + "\">"
+ homepage.toString(QUrl::RemoveScheme).mid(2)
+ "</a>.</td></tr></table>");
"homepage at %1.").arg("<a href=\"" + homepage.toString() + "\">"
+ homepage.toString(QUrl::RemoveScheme).mid(2) + "</a>")
+ "</td></tr></table>");
QIcon icon = msgBox.windowIcon();
QSize size = icon.actualSize(QSize(64, 64));
@ -701,19 +693,15 @@ void GUI::paths()
msgBox.setWindowTitle(tr("Paths"));
msgBox.setText("<h3>" + tr("Paths") + "</h3>");
msgBox.setInformativeText(
"<style>td {white-space: pre; padding-right: 1em;}</style><h4>"
+ tr("Global") + "</h4><table><tr><td>" + tr("Map directory:")
+ "</td><td><code>" + QDir::cleanPath(GLOBAL_MAP_DIR)
+ "</code></td></tr><tr><td>" + tr("POI directory:") + "</td><td><code>"
+ QDir::cleanPath(GLOBAL_POI_DIR) + "</code></td></tr><tr><td>"
"<style>td {white-space: pre; padding-right: 1em;}</style><table><tr><td>"
+ tr("Map directory:") + "</td><td><code>"
+ QDir::cleanPath(ProgramPaths::mapDir(true)) + "</code></td></tr><tr><td>"
+ tr("POI directory:") + "</td><td><code>"
+ QDir::cleanPath(ProgramPaths::poiDir(true)) + "</code></td></tr><tr><td>"
+ tr("GCS/PCS directory:") + "</td><td><code>"
+ QDir::cleanPath(GLOBAL_CSV_DIR) + "</code></td></tr></table>"
+ "<h4>" + tr("User-specific") + "</h4><table><tr><td>"
+ tr("Map directory:") + "</td><td><code>" + QDir::cleanPath(USER_MAP_DIR)
+ "</code></td></tr><tr><td>" + tr("POI directory:") + "</td><td><code>"
+ QDir::cleanPath(USER_POI_DIR) + "</code></td></tr><tr><td>"
+ tr("GCS/PCS directory:") + "</td><td><code>"
+ QDir::cleanPath(USER_CSV_DIR) + "</code></td></tr></table>"
+ QDir::cleanPath(ProgramPaths::csvDir(true)) + "</code></td></tr><tr><td>"
+ tr("Tile cache directory:") + "</td><td><code>"
+ QDir::cleanPath(ProgramPaths::tilesDir()) + "</code></td></tr></table>"
);
msgBox.exec();
@ -936,8 +924,8 @@ void GUI::openOptions()
#endif // ENABLE_HTTP2
#ifdef ENABLE_HIDPI
if (options.hidpiMap != _options.hidpiMap)
_mapView->setDevicePixelRatio(options.hidpiMap ? devicePixelRatioF()
: 1.0);
_mapView->setDevicePixelRatio(devicePixelRatioF(),
options.hidpiMap ? devicePixelRatioF() : 1.0);
#endif // ENABLE_HIDPI
if (reload)
@ -1614,7 +1602,7 @@ void GUI::dropEvent(QDropEvent *event)
void GUI::writeSettings()
{
QSettings settings(APP_NAME, APP_NAME);
QSettings settings(qApp->applicationName(), qApp->applicationName());
settings.clear();
settings.beginGroup(WINDOW_SETTINGS_GROUP);
@ -1809,7 +1797,7 @@ void GUI::writeSettings()
void GUI::readSettings()
{
int value;
QSettings settings(APP_NAME, APP_NAME);
QSettings settings(qApp->applicationName(), qApp->applicationName());
settings.beginGroup(WINDOW_SETTINGS_GROUP);
resize(settings.value(WINDOW_SIZE_SETTING, WINDOW_SIZE_DEFAULT).toSize());
@ -2059,7 +2047,8 @@ void GUI::readSettings()
if (_options.useOpenGL)
_mapView->useOpenGL(true);
#ifdef ENABLE_HIDPI
_mapView->setDevicePixelRatio(_options.hidpiMap ? devicePixelRatioF() : 1.0);
_mapView->setDevicePixelRatio(devicePixelRatioF(),
_options.hidpiMap ? devicePixelRatioF() : 1.0);
#endif // ENABLE_HIDPI
for (int i = 0; i < _tabs.count(); i++) {
@ -2142,7 +2131,8 @@ void GUI::show()
void GUI::screenChanged(QScreen *screen)
{
#ifdef ENABLE_HIDPI
_mapView->setDevicePixelRatio(_options.hidpiMap ? devicePixelRatioF() : 1.0);
_mapView->setDevicePixelRatio(devicePixelRatioF(),
_options.hidpiMap ? devicePixelRatioF() : 1.0);
disconnect(SIGNAL(logicalDotsPerInchChanged(qreal)), this,
SLOT(logicalDotsPerInchChanged(qreal)));
@ -2158,6 +2148,7 @@ void GUI::logicalDotsPerInchChanged(qreal dpi)
Q_UNUSED(dpi)
#ifdef ENABLE_HIDPI
_mapView->setDevicePixelRatio(_options.hidpiMap ? devicePixelRatioF() : 1.0);
_mapView->setDevicePixelRatio(devicePixelRatioF(),
_options.hidpiMap ? devicePixelRatioF() : 1.0);
#endif // ENBLE_HIDPI
}

View File

@ -7,9 +7,14 @@ HeartRateGraphItem::HeartRateGraphItem(const Graph &graph, GraphType type,
QGraphicsItem *parent) : GraphItem(graph, type, parent)
{
qreal sum = 0;
_max = graph.first().y();
for (int j = 1; j < graph.size(); j++)
sum += graph.at(j).y() * (graph.at(j).s() - graph.at(j-1).s());
for (int i = 1; i < graph.size(); i++) {
qreal y = graph.at(i).y();
sum += y * (graph.at(i).s() - graph.at(i-1).s());
if (y > _max)
_max = y;
}
_avg = sum/graph.last().s();
setToolTip(toolTip());

View File

@ -11,13 +11,13 @@ public:
HeartRateGraphItem(const Graph &graph, GraphType type,
QGraphicsItem *parent = 0);
qreal max() const {return -bounds().top();}
qreal max() const {return _max;}
qreal avg() const {return _avg;}
private:
QString toolTip() const;
qreal _avg;
qreal _avg, _max;
};
#endif // HEARTRATEGRAPHITEM_H

View File

@ -1,6 +1,6 @@
#include <QFont>
#include <QPainter>
#include "config.h"
#include "font.h"
#include "infoitem.h"
#define PADDING 10

View File

@ -21,6 +21,7 @@
#define MARGIN 10
#define SCALE_OFFSET 7
MapView::MapView(Map *map, POI *poi, QWidget *parent)
: QGraphicsView(parent)
{
@ -72,7 +73,8 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
_poiColor = Qt::black;
#ifdef ENABLE_HIDPI
_ratio = 1.0;
_deviceRatio = 1.0;
_mapRatio = 1.0;
#endif // ENABLE_HIDPI
_opengl = false;
_plot = false;
@ -270,7 +272,7 @@ void MapView::setMap(Map *map)
_map = map;
_map->load();
#ifdef ENABLE_HIDPI
_map->setDevicePixelRatio(_ratio);
_map->setDevicePixelRatio(_deviceRatio, _mapRatio);
#endif // ENABLE_HIDPI
connect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
@ -438,10 +440,10 @@ void MapView::zoom(int zoom, const QPoint &pos)
digitalZoom(zoom);
} else {
Coordinates c = _map->xy2ll(mapToScene(pos));
qreal os = _map->zoom();
qreal ns = (zoom > 0) ? _map->zoomIn() : _map->zoomOut();
int oz = _map->zoom();
int nz = (zoom > 0) ? _map->zoomIn() : _map->zoomOut();
if (ns != os) {
if (nz != oz) {
rescale();
centerOn(_map->ll2xy(c) - (pos - viewport()->rect().center()));
} else {
@ -505,7 +507,7 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
setUpdatesEnabled(false);
_plot = true;
#ifdef ENABLE_HIDPI
_map->setDevicePixelRatio(1.0);
_map->setDevicePixelRatio(_deviceRatio, 1.0);
#endif // ENABLE_HIDPI
// Compute sizes & ratios
@ -566,7 +568,7 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
// Exit plot mode
#ifdef ENABLE_HIDPI
_map->setDevicePixelRatio(_ratio);
_map->setDevicePixelRatio(_deviceRatio, _mapRatio);
#endif // ENABLE_HIDPI
_plot = false;
setUpdatesEnabled(true);
@ -844,19 +846,21 @@ void MapView::reloadMap()
_scene->invalidate();
}
void MapView::setDevicePixelRatio(qreal ratio)
void MapView::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
{
#ifdef ENABLE_HIDPI
if (_ratio == ratio)
if (_deviceRatio == deviceRatio && _mapRatio == mapRatio)
return;
_ratio = ratio;
_deviceRatio = deviceRatio;
_mapRatio = mapRatio;
QPixmapCache::clear();
QRectF vr(mapToScene(viewport()->rect()).boundingRect()
.intersected(_map->bounds()));
RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
_map->setDevicePixelRatio(_ratio);
_map->setDevicePixelRatio(_deviceRatio, _mapRatio);
_scene->setSceneRect(_map->bounds());
for (int i = 0; i < _tracks.size(); i++)
@ -877,6 +881,7 @@ void MapView::setDevicePixelRatio(qreal ratio)
reloadMap();
#else // ENABLE_HIDPI
Q_UNUSED(ratio);
Q_UNUSED(deviceRatio);
Q_UNUSED(mapRatio);
#endif // ENABLE_HIDPI
}

View File

@ -6,12 +6,12 @@
#include <QHash>
#include <QList>
#include "common/rectc.h"
#include "common/config.h"
#include "data/waypoint.h"
#include "searchpointer.h"
#include "units.h"
#include "format.h"
#include "palette.h"
#include "config.h"
class Data;
class POI;
@ -69,7 +69,7 @@ public slots:
void showRouteWaypoints(bool show);
void clearMapCache();
void setCoordinatesFormat(CoordinatesFormat format);
void setDevicePixelRatio(qreal ratio);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
private slots:
void updatePOI();
@ -140,7 +140,8 @@ private:
bool _plot;
#ifdef ENABLE_HIDPI
qreal _ratio;
qreal _deviceRatio;
qreal _mapRatio;
#endif // ENABLE_HIDPI
bool _opengl;
};

View File

@ -1,6 +0,0 @@
#ifndef MISC_H
#define MISC_H
double niceNum(double x, int round);
#endif // MISC_H

View File

@ -2,10 +2,9 @@
#define OPTIONSDIALOG_H
#include <QDialog>
#include "common/config.h"
#include "palette.h"
#include "units.h"
#include "config.h"
class ColorBox;
class StyleComboBox;

View File

@ -1,11 +1,8 @@
#include <cmath>
#include <QApplication>
#include <QCursor>
#include <QPainter>
#include "common/greatcircle.h"
#include "map/map.h"
#include "tooltip.h"
#include "nicenum.h"
#include "pathitem.h"
@ -50,6 +47,7 @@ void PathItem::updateShape()
void PathItem::addSegment(const Coordinates &c1, const Coordinates &c2)
{
if (fabs(c1.lon() - c2.lon()) > 180.0) {
// Split segment on date line crossing
QPointF p;
if (c2.lon() < 0) {

View File

@ -7,9 +7,14 @@ PowerGraphItem::PowerGraphItem(const Graph &graph, GraphType type,
QGraphicsItem *parent) : GraphItem(graph, type, parent)
{
qreal sum = 0;
_max = graph.first().y();
for (int j = 1; j < graph.size(); j++)
sum += graph.at(j).y() * (graph.at(j).s() - graph.at(j-1).s());
for (int i = 1; i < graph.size(); i++) {
qreal y = graph.at(i).y();
sum += y * (graph.at(i).s() - graph.at(i-1).s());
if (y > _max)
_max = y;
}
_avg = sum/graph.last().s();
setToolTip(toolTip());

View File

@ -11,13 +11,13 @@ public:
PowerGraphItem(const Graph &graph, GraphType type,
QGraphicsItem *parent = 0);
qreal max() const {return -bounds().top();}
qreal max() const {return _max;}
qreal avg() const {return _avg;}
private:
QString toolTip() const;
qreal _avg;
qreal _avg, _max;
};
#endif // POWERGRAPHITEM_H

View File

@ -1,7 +1,8 @@
#include <cmath>
#include <QApplication>
#include <QPainter>
#include "config.h"
#include "nicenum.h"
#include "common/util.h"
#include "font.h"
#include "scaleitem.h"

View File

@ -1,5 +1,5 @@
#include <QPainter>
#include "config.h"
#include "font.h"
#include "sliderinfoitem.h"

View File

@ -1,6 +1,5 @@
#include <QLocale>
#include "data/data.h"
#include "config.h"
#include "tooltip.h"
#include "format.h"
#include "speedgraphitem.h"

View File

@ -13,6 +13,13 @@ SpeedGraphItem::SpeedGraphItem(const Graph &graph, GraphType type,
_avg = graph.last().s() / graph.last().t();
_mavg = graph.last().s() / movingTime;
_max = graph.first().y();
for (int i = 1; i < graph.size(); i++) {
qreal y = graph.at(i).y();
if (y > _max)
_max = y;
}
setToolTip(toolTip());
}

View File

@ -12,7 +12,7 @@ public:
SpeedGraphItem(const Graph &graph, GraphType type, qreal movingTime,
QGraphicsItem *parent = 0);
qreal max() const {return -bounds().top();}
qreal max() const {return _max;}
qreal avg() const {return _avg;}
qreal mavg() const {return _mavg;}
@ -22,7 +22,7 @@ public:
private:
QString toolTip() const;
qreal _avg, _mavg;
qreal _avg, _mavg, _max;
Units _units;
TimeType _timeType;

View File

@ -7,9 +7,18 @@ TemperatureGraphItem::TemperatureGraphItem(const Graph &graph, GraphType type,
QGraphicsItem *parent) : GraphItem(graph, type, parent)
{
qreal sum = 0;
_min = _max = graph.first().y();
for (int j = 1; j < graph.size(); j++) {
qreal y = graph.at(j).y();
for (int j = 1; j < graph.size(); j++)
sum += graph.at(j).y() * (graph.at(j).s() - graph.at(j-1).s());
if (y > _max)
_max = y;
if (y < _min)
_min = y;
}
_avg = sum/graph.last().s();
setToolTip(toolTip(Metric));

View File

@ -11,8 +11,8 @@ public:
TemperatureGraphItem(const Graph &graph, GraphType type,
QGraphicsItem *parent = 0);
qreal max() const {return -bounds().top();}
qreal min() const {return -bounds().bottom();}
qreal max() const {return _max;}
qreal min() const {return _min;}
qreal avg() const {return _avg;}
void setUnits(Units units);
@ -20,7 +20,7 @@ public:
private:
QString toolTip(Units units) const;
qreal _avg;
qreal _avg, _min, _max;
};
#endif // TEMPERATUREGRAPHITEM_H

View File

@ -1,6 +1,5 @@
#include <QPaintEngine>
#include <QPaintDevice>
#include "config.h"
#include "infoitem.h"
#include "trackinfo.h"

View File

@ -1,6 +1,6 @@
#include <QApplication>
#include <QPainter>
#include "config.h"
#include "font.h"
#include "tooltip.h"
#include "waypointitem.h"

17
src/common/config.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <QtGlobal>
#define APP_NAME "GPXSee"
#define APP_HOMEPAGE "http://www.gpxsee.org"
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 1)
#define ENABLE_HTTP2
#endif // QT >= 5.10.1
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
#define ENABLE_HIDPI
#endif // QT >= 5.6
#endif /* CONFIG_H */

174
src/common/programpaths.cpp Normal file
View File

@ -0,0 +1,174 @@
#include <QtGlobal>
#include <QDir>
#include "programpaths.h"
#define MAP_DIR "maps"
#define POI_DIR "POI"
#define CSV_DIR "csv"
#define TILES_DIR "tiles"
#define TRANSLATIONS_DIR "translations"
#define ELLIPSOID_FILE "ellipsoids.csv"
#define GCS_FILE "gcs.csv"
#define PCS_FILE "pcs.csv"
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
#include <QApplication>
#if defined(Q_OS_WIN32)
#define USER_DIR QDir::homePath() + QString("/AppData/Roaming/") \
+ qApp->applicationName()
#define GLOBAL_DIR QApplication::applicationDirPath()
#elif defined(Q_OS_MAC)
#define USER_DIR QDir::homePath() \
+ QString("/Library/Application Support/") \
+ qApp->applicationName()
#define GLOBAL_DIR QApplication::applicationDirPath() \
+ QString("/../Resources")
#else
#define USER_DIR QDir::homePath() + QString("/.local/share/") \
+ qApp->applicationName()
#define GLOBAL_DIR QString("/usr/share/") + qApp->applicationName()
#endif
static QString dir(const QString &dirName, bool writable = false)
{
QDir userDir(QDir(USER_DIR).filePath(dirName));
if (writable || userDir.exists())
return userDir.absolutePath();
else {
QDir globalDir(QDir(GLOBAL_DIR).filePath(dirName));
if (globalDir.exists())
return globalDir.absolutePath();
else
return QString();
}
}
static QString file(const QString &path, const QString &fileName)
{
if (path.isNull())
return QString();
QFileInfo fi(QDir(path).filePath(fileName));
return fi.exists() ? fi.absoluteFilePath() : QString();
}
QString ProgramPaths::mapDir(bool writable)
{
return dir(MAP_DIR, writable);
}
QString ProgramPaths::poiDir(bool writable)
{
return dir(POI_DIR, writable);
}
QString ProgramPaths::csvDir(bool writable)
{
return dir(CSV_DIR, writable);
}
QString ProgramPaths::tilesDir()
{
#if defined(Q_OS_WIN32)
return QDir::homePath() + QString("/AppData/Local/")
+ qApp->applicationName() + QString("/cache/") + QString(TILES_DIR);
#elif defined(Q_OS_MAC)
return QDir::homePath() + QString("/Library/Caches/")
+ qApp->applicationName() + QString("/" TILES_DIR);
#else
return QDir::homePath() + QString("/.cache/") + qApp->applicationName()
+ QString("/" TILES_DIR);
#endif
}
QString ProgramPaths::translationsDir()
{
return dir(TRANSLATIONS_DIR);
}
QString ProgramPaths::ellipsoidsFile()
{
return file(dir(CSV_DIR), ELLIPSOID_FILE);
}
QString ProgramPaths::gcsFile()
{
return file(dir(CSV_DIR), GCS_FILE);
}
QString ProgramPaths::pcsFile()
{
return file(dir(CSV_DIR), PCS_FILE);
}
#else // QT_VERSION < 5
#include <QStandardPaths>
QString ProgramPaths::mapDir(bool writable)
{
if (writable)
return QDir(QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation)).filePath(MAP_DIR);
else
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
MAP_DIR, QStandardPaths::LocateDirectory);
}
QString ProgramPaths::poiDir(bool writable)
{
if (writable)
return QDir(QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation)).filePath(POI_DIR);
else
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
POI_DIR, QStandardPaths::LocateDirectory);
}
QString ProgramPaths::csvDir(bool writable)
{
if (writable)
return QDir(QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation)).filePath(CSV_DIR);
else
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
CSV_DIR, QStandardPaths::LocateDirectory);
}
QString ProgramPaths::tilesDir()
{
return QDir(QStandardPaths::writableLocation(
QStandardPaths::CacheLocation)).filePath(TILES_DIR);
}
QString ProgramPaths::translationsDir()
{
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
TRANSLATIONS_DIR, QStandardPaths::LocateDirectory);
}
QString ProgramPaths::ellipsoidsFile()
{
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
CSV_DIR "/" ELLIPSOID_FILE, QStandardPaths::LocateFile);
}
QString ProgramPaths::gcsFile()
{
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
CSV_DIR "/" GCS_FILE, QStandardPaths::LocateFile);
}
QString ProgramPaths::pcsFile()
{
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
CSV_DIR "/" PCS_FILE, QStandardPaths::LocateFile);
}
#endif // QT_VERSION < 5

18
src/common/programpaths.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef PROGRAMPATHS_H
#define PROGRAMPATHS_H
#include <QString>
namespace ProgramPaths
{
QString mapDir(bool writable = false);
QString poiDir(bool writable = false);
QString csvDir(bool writable = false);
QString tilesDir();
QString translationsDir();
QString ellipsoidsFile();
QString gcsFile();
QString pcsFile();
}
#endif // PROGRAMPATHS_H

View File

@ -1,16 +0,0 @@
#include <cctype>
#include "str2int.h"
int str2int(const char *str, int len)
{
int res = 0;
for (const char *sp = str; sp < str + len; sp++) {
if (::isdigit(*sp))
res = res * 10 + *sp - '0';
else
return -1;
}
return res;
}

View File

@ -1,6 +0,0 @@
#ifndef MISC_H
#define MISC_H
int str2int(const char *str, int len);
#endif // MISC_H

View File

@ -1,5 +1,21 @@
#include <cctype>
#include <cmath>
#include "nicenum.h"
#include "util.h"
int str2int(const char *str, int len)
{
int res = 0;
for (const char *sp = str; sp < str + len; sp++) {
if (::isdigit(*sp))
res = res * 10 + *sp - '0';
else
return -1;
}
return res;
}
double niceNum(double x, int round)
{

7
src/common/util.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef UTIL_H
#define UTIL_H
int str2int(const char *str, int len);
double niceNum(double x, int round);
#endif // UTIL_H

View File

@ -1,58 +0,0 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <QtGlobal>
#include <QDir>
#include <QApplication>
#include <QString>
#define APP_NAME "GPXSee"
#define APP_HOMEPAGE "http://www.gpxsee.org"
#define FONT_FAMILY "Arial"
#define FONT_SIZE 12 // px
#define MAP_DIR QString("maps")
#define POI_DIR QString("POI")
#define CSV_DIR QString("csv")
#define ELLIPSOID_FILE QString("ellipsoids.csv")
#define GCS_FILE QString("gcs.csv")
#define PCS_FILE QString("pcs.csv")
#if defined(Q_OS_WIN32)
#define USER_DIR QDir::homePath() + QString("/GPXSee")
#define GLOBAL_DIR QApplication::applicationDirPath()
#elif defined(Q_OS_MAC)
#define USER_DIR QDir::homePath() + QString("/.gpxsee")
#define GLOBAL_DIR QApplication::applicationDirPath() \
+ QString("/../Resources")
#else
#define USER_DIR QDir::homePath() + QString("/.gpxsee")
#define GLOBAL_DIR QString("/usr/share/gpxsee")
#endif
#define USER_CSV_DIR USER_DIR + QString("/") + CSV_DIR
#define USER_ELLIPSOID_FILE USER_CSV_DIR + QString("/") + ELLIPSOID_FILE
#define USER_GCS_FILE USER_CSV_DIR + QString("/") + GCS_FILE
#define USER_PCS_FILE USER_CSV_DIR + QString("/") + PCS_FILE
#define USER_MAP_DIR USER_DIR + QString("/") + MAP_DIR
#define USER_POI_DIR USER_DIR + QString("/") + POI_DIR
#define GLOBAL_CSV_DIR GLOBAL_DIR + QString("/") + CSV_DIR
#define GLOBAL_ELLIPSOID_FILE GLOBAL_CSV_DIR + QString("/") + ELLIPSOID_FILE
#define GLOBAL_GCS_FILE GLOBAL_CSV_DIR + QString("/") + GCS_FILE
#define GLOBAL_PCS_FILE GLOBAL_CSV_DIR + QString("/") + PCS_FILE
#define GLOBAL_MAP_DIR GLOBAL_DIR + QString("/") + MAP_DIR
#define GLOBAL_POI_DIR GLOBAL_DIR + QString("/") + POI_DIR
#define TILES_DIR USER_DIR + QString("/tiles")
#define TRANSLATIONS_DIR GLOBAL_DIR + QString("/translations")
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 1)
#define ENABLE_HTTP2
#endif // QT >= 5.10.1
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
#define ENABLE_HIDPI
#endif // QT >= 5.6
#endif /* CONFIG_H */

View File

@ -1,5 +1,5 @@
#include <cstring>
#include "common/str2int.h"
#include "common/util.h"
#include "igcparser.h"

View File

@ -1,5 +1,5 @@
#include <cstring>
#include "common/str2int.h"
#include "common/util.h"
#include "nmeaparser.h"

View File

@ -1,5 +1,5 @@
#include "common/config.h"
#include "GUI/app.h"
#include "config.h"
int main(int argc, char *argv[])
{
@ -9,7 +9,5 @@ int main(int argc, char *argv[])
#endif // ENABLE_HIDPI
App app(argc, argv);
app.run();
return 0;
return app.run();
}

View File

@ -1,5 +1,5 @@
#include "common/coordinates.h"
#include "common/str2int.h"
#include "common/util.h"
#include "angularunits.h"
static double sDMS2deg(double val)

View File

@ -145,10 +145,10 @@ Atlas::Atlas(const QString &fileName, QObject *parent)
_valid = true;
}
void Atlas::setDevicePixelRatio(qreal ratio)
void Atlas::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
{
for (int i = 0; i < _maps.size(); i++)
_maps[i]->setDevicePixelRatio(ratio);
_maps[i]->setDevicePixelRatio(deviceRatio, mapRatio);
computeBounds();
}
@ -297,9 +297,9 @@ bool Atlas::isAtlas(const QString &path)
{
QFileInfo fi(path);
QString suffix = fi.suffix().toLower();
Tar tar(path);
if (suffix == "tar") {
Tar tar(path);
if (!tar.open())
return false;
QString tbaFileName = fi.completeBaseName() + ".tba";

View File

@ -28,7 +28,7 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal ratio);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
void unload();
bool isValid() const {return _valid;}

View File

@ -2,6 +2,8 @@
#include <QFileInfo>
#include <QNetworkRequest>
#include <QBasicTimer>
#include <QDir>
#include <QTimerEvent>
#include "downloader.h"
@ -79,18 +81,12 @@ private:
int _level;
};
QNetworkAccessManager *Downloader::_manager = 0;
int Downloader::_timeout = 30;
#ifdef ENABLE_HTTP2
bool Downloader::_http2 = true;
#endif // ENABLE_HTTP2
QNetworkAccessManager *Downloader::manager()
{
static QNetworkAccessManager manager;
return &manager;
}
bool Downloader::doDownload(const Download &dl,
const QByteArray &authorization, const Redirect *redirect)
{
@ -123,7 +119,8 @@ bool Downloader::doDownload(const Download &dl,
QVariant(_http2));
#endif // ENABLE_HTTP2
QNetworkReply *reply = manager()->get(request);
Q_ASSERT(_manager);
QNetworkReply *reply = _manager->get(request);
if (reply && reply->isRunning()) {
_currentDownloads.insert(url);
ReplyTimeout::setTimeout(reply, _timeout);
@ -236,7 +233,8 @@ bool Downloader::get(const QList<Download> &list,
#ifdef ENABLE_HTTP2
void Downloader::enableHTTP2(bool enable)
{
Q_ASSERT(_manager);
_http2 = enable;
manager()->clearConnectionCache();
_manager->clearConnectionCache();
}
#endif // ENABLE_HTTP2

View File

@ -7,7 +7,7 @@
#include <QList>
#include <QSet>
#include <QHash>
#include "config.h"
#include "common/config.h"
class Download
@ -46,6 +46,8 @@ public:
= Authorization());
void clearErrors() {_errorDownloads.clear();}
static void setNetworkManager(QNetworkAccessManager *manager)
{_manager = manager;}
static void setTimeout(int timeout) {_timeout = timeout;}
#ifdef ENABLE_HTTP2
static void enableHTTP2(bool enable);
@ -67,11 +69,10 @@ private:
const Redirect *redirect = 0);
bool saveToDisk(const QString &filename, QIODevice *data);
static QNetworkAccessManager *manager();
QSet<QUrl> _currentDownloads;
QHash<QUrl, int> _errorDownloads;
static QNetworkAccessManager *_manager;
static int _timeout;
#ifdef ENABLE_HTTP2
static bool _http2;

View File

@ -1,7 +1,7 @@
#include <QFileInfo>
#include <QPainter>
#include <QImageReader>
#include "config.h"
#include "common/config.h"
#include "geotiff.h"
#include "image.h"
#include "geotiffmap.h"
@ -61,9 +61,11 @@ void GeoTIFFMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
_img->draw(painter, rect, flags);
}
void GeoTIFFMap::setDevicePixelRatio(qreal ratio)
void GeoTIFFMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
{
_ratio = ratio;
Q_UNUSED(deviceRatio);
_ratio = mapRatio;
if (_img)
_img->setDevicePixelRatio(_ratio);
}

View File

@ -25,7 +25,7 @@ public:
void load();
void unload();
void setDevicePixelRatio(qreal ratio);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
bool isValid() const {return _valid;}
QString errorString() const {return _errorString;}

View File

@ -1,6 +1,6 @@
#include <QPainter>
#include <QPixmapCache>
#include "config.h"
#include "common/config.h"
#include "image.h"

View File

@ -2,10 +2,10 @@
#include <QPainter>
#include <QFileInfo>
#include <QPixmapCache>
#include "common/config.h"
#include "rectd.h"
#include "gcs.h"
#include "pcs.h"
#include "config.h"
#include "jnxmap.h"
@ -142,7 +142,7 @@ bool JNXMap::readTiles()
}
JNXMap::JNXMap(const QString &fileName, QObject *parent)
: Map(parent), _file(fileName), _zoom(0), _ratio(1.0), _valid(false)
: Map(parent), _file(fileName), _zoom(0), _mapRatio(1.0), _valid(false)
{
_name = QFileInfo(fileName).fileName();
@ -162,13 +162,13 @@ JNXMap::JNXMap(const QString &fileName, QObject *parent)
QPointF JNXMap::ll2xy(const Coordinates &c)
{
const Zoom &z = _zooms.at(_zoom);
return z.transform.proj2img(_projection.ll2xy(c)) / _ratio;
return z.transform.proj2img(_projection.ll2xy(c)) / _mapRatio;
}
Coordinates JNXMap::xy2ll(const QPointF &p)
{
const Zoom &z = _zooms.at(_zoom);
return _projection.xy2ll(z.transform.img2proj(p * _ratio));
return _projection.xy2ll(z.transform.img2proj(p * _mapRatio));
}
QRectF JNXMap::bounds()
@ -249,8 +249,8 @@ void JNXMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
{
Q_UNUSED(flags);
const RTree<Tile*, qreal, 2> &tree = _zooms.at(_zoom).tree;
Ctx ctx(painter, &_file, _ratio);
QRectF rr(rect.topLeft() * _ratio, rect.size() * _ratio);
Ctx ctx(painter, &_file, _mapRatio);
QRectF rr(rect.topLeft() * _mapRatio, rect.size() * _mapRatio);
qreal min[2], max[2];
min[0] = rr.left();

View File

@ -32,7 +32,8 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal ratio) {_ratio = ratio;}
void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio)
{_mapRatio = mapRatio;}
bool isValid() const {return _valid;}
QString errorString() const {return _errorString;}
@ -63,7 +64,7 @@ private:
int _zoom;
RectC _bounds;
Projection _projection;
qreal _ratio;
qreal _mapRatio;
bool _valid;
QString _errorString;

View File

@ -44,7 +44,7 @@ public:
virtual void clearCache() {}
virtual void load() {}
virtual void unload() {}
virtual void setDevicePixelRatio(qreal) {}
virtual void setDevicePixelRatio(qreal, qreal) {}
virtual bool isValid() const {return true;}
virtual QString errorString() const {return QString();}

View File

@ -1,6 +1,6 @@
#include <QFile>
#include <QXmlStreamReader>
#include "config.h"
#include "common/config.h"
#include "onlinemap.h"
#include "wmtsmap.h"
#include "wmsmap.h"
@ -9,7 +9,8 @@
MapSource::Config::Config() : type(OSM), zooms(OSM::ZOOMS), bounds(OSM::BOUNDS),
format("image/png"), rest(false), tileRatio(1.0) {}
format("image/png"), rest(false), tileRatio(1.0), tileSize(256),
scalable(false) {}
static CoordinateSystem coordinateSystem(QXmlStreamReader &reader)
@ -111,6 +112,43 @@ RectC MapSource::bounds(QXmlStreamReader &reader)
return RectC(Coordinates(left, top), Coordinates(right, bottom));
}
void MapSource::tile(QXmlStreamReader &reader, Config &config)
{
QXmlStreamAttributes attr = reader.attributes();
bool ok;
if (attr.hasAttribute("size")) {
int size = attr.value("size").toString().toInt(&ok);
if (!ok || size < 0) {
reader.raiseError("Invalid tile size");
return;
} else
config.tileSize = size;
}
if (attr.hasAttribute("type")) {
if (attr.value("type") == "raster")
config.scalable = false;
else if (attr.value("type") == "vector")
config.scalable = true;
else {
reader.raiseError("Invalid tile type");
return;
}
}
if (attr.hasAttribute("pixelRatio")) {
#ifdef ENABLE_HIDPI
qreal ratio = attr.value("pixelRatio").toString().toDouble(&ok);
if (!ok || ratio < 0) {
reader.raiseError("Invalid tile pixelRatio");
return;
} else
config.tileRatio = ratio;
#else // ENABLE_HIDPI
reader.raiseError("HiDPI maps not supported");
#endif // ENABLE_HIDPI
}
}
void MapSource::map(QXmlStreamReader &reader, Config &config)
{
const QXmlStreamAttributes &attr = reader.attributes();
@ -168,16 +206,20 @@ void MapSource::map(QXmlStreamReader &reader, Config &config)
attr.value("password").toString());
reader.skipCurrentElement();
} else if (reader.name() == "tilePixelRatio") {
// Legacy tilePixelRatio tag support
#ifdef ENABLE_HIDPI
bool res;
qreal val = reader.readElementText().toDouble(&res);
if (!res)
bool ok;
qreal ratio = reader.readElementText().toDouble(&ok);
if (!ok || ratio <= 0)
reader.raiseError("Invalid tilePixelRatio");
else
config.tileRatio = val;
config.tileRatio = ratio;
#else // ENABLE_HIDPI
reader.raiseError("HiDPI maps not supported");
#endif // ENABLE_HIDPI
} else if (reader.name() == "tile") {
tile(reader, config);
reader.skipCurrentElement();
} else
reader.skipCurrentElement();
}
@ -250,10 +292,12 @@ Map *MapSource::loadMap(const QString &path, QString &errorString)
config.dimensions, config.authorization));
case TMS:
return new OnlineMap(config.name, config.url, config.zooms,
config.bounds, config.tileRatio, config.authorization, true);
config.bounds, config.tileRatio, config.authorization,
config.tileSize, config.scalable, true);
case OSM:
return new OnlineMap(config.name, config.url, config.zooms,
config.bounds, config.tileRatio, config.authorization, false);
config.bounds, config.tileRatio, config.authorization,
config.tileSize, config.scalable, false);
default:
return 0;
}

View File

@ -40,6 +40,8 @@ private:
QList<KV> dimensions;
Authorization authorization;
qreal tileRatio;
int tileSize;
bool scalable;
Config();
};
@ -47,6 +49,7 @@ private:
static RectC bounds(QXmlStreamReader &reader);
static Range zooms(QXmlStreamReader &reader);
static void map(QXmlStreamReader &reader, Config &config);
static void tile(QXmlStreamReader &reader, Config &config);
};
#endif // MAPSOURCE_H

View File

@ -4,22 +4,64 @@
#include <QFileInfo>
#include <QPainter>
#include <QPixmapCache>
#include <QImageReader>
#include <QBuffer>
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
#include <QtCore>
#else // QT_VERSION < 5
#include <QtConcurrent>
#endif // QT_VERSION < 5
#include "common/rectc.h"
#include "common/config.h"
#include "osm.h"
#include "config.h"
#include "mbtilesmap.h"
class MBTile
{
public:
MBTile(int zoom, int scaledSize, const QPoint &xy, const QByteArray &data,
const QString &key) : _zoom(zoom), _scaledSize(scaledSize), _xy(xy),
_data(data), _key(key) {}
const QPoint &xy() const {return _xy;}
const QString &key() const {return _key;}
QPixmap pixmap() const {return QPixmap::fromImage(_image);}
void load() {
QByteArray z(QString::number(_zoom).toLatin1());
QBuffer buffer(&_data);
QImageReader reader(&buffer, z);
if (_scaledSize)
reader.setScaledSize(QSize(_scaledSize, _scaledSize));
reader.read(&_image);
}
private:
int _zoom;
int _scaledSize;
QPoint _xy;
QByteArray _data;
QString _key;
QImage _image;
};
#define META_TYPE(type) static_cast<QMetaType::Type>(type)
static void render(MBTile &tile)
{
tile.load();
}
static double index2mercator(int index, int zoom)
{
return rad2deg(-M_PI + 2 * M_PI * ((double)index / (1<<zoom)));
}
MBTilesMap::MBTilesMap(const QString &fileName, QObject *parent)
: Map(parent), _fileName(fileName), _deviceRatio(1.0), _tileRatio(1.0),
_valid(false)
: Map(parent), _fileName(fileName), _mapRatio(1.0), _tileRatio(1.0),
_scalable(false), _scaledSize(0), _valid(false)
{
_db = QSqlDatabase::addDatabase("QSQLITE", fileName);
_db.setDatabaseName(fileName);
@ -85,12 +127,26 @@ MBTilesMap::MBTilesMap(const QString &fileName, QObject *parent)
QString sql = QString("SELECT tile_data FROM tiles LIMIT 1");
QSqlQuery query(sql, _db);
query.first();
QImage tile = QImage::fromData(query.value(0).toByteArray());
if (tile.isNull() || tile.size().width() != tile.size().height()) {
QByteArray data = query.value(0).toByteArray();
QBuffer buffer(&data);
QImageReader reader(&buffer);
QSize tileSize(reader.size());
if (!tileSize.isValid() || tileSize.width() != tileSize.height()) {
_errorString = "Unsupported/invalid tile images";
return;
}
_tileSize = tile.size().width();
_tileSize = tileSize.width();
}
{
QSqlQuery query("SELECT value FROM metadata WHERE name = 'format'", _db);
if (query.first()) {
if (query.value(0).toString() == "pbf")
_scalable = true;
} else
qWarning("%s: missing map name", qPrintable(_fileName));
}
{
@ -177,14 +233,24 @@ int MBTilesMap::zoomOut()
return _zoom;
}
void MBTilesMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
{
_mapRatio = mapRatio;
if (_scalable) {
_scaledSize = _tileSize * deviceRatio;
_tileRatio = deviceRatio;
}
}
qreal MBTilesMap::coordinatesRatio() const
{
return _deviceRatio > 1.0 ? _deviceRatio / _tileRatio : 1.0;
return _mapRatio > 1.0 ? _mapRatio / _tileRatio : 1.0;
}
qreal MBTilesMap::imageRatio() const
{
return _deviceRatio > 1.0 ? _deviceRatio : _tileRatio;
return _mapRatio > 1.0 ? _mapRatio : _tileRatio;
}
qreal MBTilesMap::tileSize() const
@ -222,27 +288,55 @@ void MBTilesMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
QSizeF s(qMin(rect.right() - tl.x(), b.width()),
qMin(rect.bottom() - tl.y(), b.height()));
for (int i = 0; i < ceil(s.width() / tileSize()); i++) {
for (int j = 0; j < ceil(s.height() / tileSize()); j++) {
int width = ceil(s.width() / tileSize());
int height = ceil(s.height() / tileSize());
QList<MBTile> tiles;
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
QPixmap pm;
QPoint t(tile.x() + i, tile.y() + j);
QString key = _fileName + "-" + QString::number(_zoom) + "_"
+ QString::number(t.x()) + "_" + QString::number(t.y());
if (!QPixmapCache::find(key, &pm))
if (pm.loadFromData(tileData(_zoom, t)))
QPixmapCache::insert(key, pm);
QPointF tp(qMax(tl.x(), b.left()) + (t.x() - tile.x()) * tileSize(),
qMax(tl.y(), b.top()) + (t.y() - tile.y()) * tileSize());
if (!pm.isNull()) {
#ifdef ENABLE_HIDPI
pm.setDevicePixelRatio(imageRatio());
#endif // ENABLE_HIDPI
painter->drawPixmap(tp, pm);
if (QPixmapCache::find(key, pm)) {
QPointF tp(qMax(tl.x(), b.left()) + (t.x() - tile.x())
* tileSize(), qMax(tl.y(), b.top()) + (t.y() - tile.y())
* tileSize());
drawTile(painter, pm, tp);
} else {
tiles.append(MBTile(_zoom, _scaledSize, t, tileData(_zoom, t),
key));
}
}
}
QFuture<void> future = QtConcurrent::map(tiles, render);
future.waitForFinished();
for (int i = 0; i < tiles.size(); i++) {
const MBTile &mt = tiles.at(i);
QPixmap pm(mt.pixmap());
if (pm.isNull())
continue;
QPixmapCache::insert(mt.key(), pm);
QPointF tp(qMax(tl.x(), b.left()) + (mt.xy().x() - tile.x())
* tileSize(), qMax(tl.y(), b.top()) + (mt.xy().y() - tile.y())
* tileSize());
drawTile(painter, pm, tp);
}
}
void MBTilesMap::drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp)
{
#ifdef ENABLE_HIDPI
pixmap.setDevicePixelRatio(imageRatio());
#endif // ENABLE_HIDPI
painter->drawPixmap(tp, pixmap);
}
QPointF MBTilesMap::ll2xy(const Coordinates &c)

View File

@ -29,7 +29,7 @@ public:
void load();
void unload();
void setDevicePixelRatio(qreal ratio) {_deviceRatio = ratio;}
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
bool isValid() const {return _valid;}
QString errorString() const {return _errorString;}
@ -40,6 +40,7 @@ private:
qreal coordinatesRatio() const;
qreal imageRatio() const;
QByteArray tileData(int zoom, const QPoint &tile) const;
void drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp);
QSqlDatabase _db;
@ -48,7 +49,9 @@ private:
Range _zooms;
int _zoom;
int _tileSize;
qreal _deviceRatio, _tileRatio;
qreal _mapRatio, _tileRatio;
bool _scalable;
int _scaledSize;
bool _valid;
QString _errorString;

View File

@ -1,22 +1,23 @@
#include <QtCore>
#include <QPainter>
#include <QDir>
#include "common/rectc.h"
#include "common/programpaths.h"
#include "downloader.h"
#include "osm.h"
#include "config.h"
#include "onlinemap.h"
#define TILE_SIZE 256
OnlineMap::OnlineMap(const QString &name, const QString &url,
const Range &zooms, const RectC &bounds, qreal tileRatio,
const Authorization &authorization, bool invertY, QObject *parent)
const Authorization &authorization, int tileSize, bool scalable, bool invertY,
QObject *parent)
: Map(parent), _name(name), _zooms(zooms), _bounds(bounds),
_zoom(_zooms.max()), _deviceRatio(1.0), _tileRatio(tileRatio),
_invertY(invertY)
_zoom(_zooms.max()), _mapRatio(1.0), _tileRatio(tileRatio),
_tileSize(tileSize), _scalable(scalable), _invertY(invertY), _scaledSize(0)
{
_tileLoader = new TileLoader(TILES_DIR + "/" + _name, this);
_tileLoader = new TileLoader(QDir(ProgramPaths::tilesDir()).filePath(_name),
this);
_tileLoader->setUrl(url);
_tileLoader->setAuthorization(authorization);
connect(_tileLoader, SIGNAL(finished()), this, SIGNAL(loaded()));
@ -45,7 +46,7 @@ int OnlineMap::zoomFit(const QSize &size, const RectC &rect)
QRectF tbr(OSM::ll2m(rect.topLeft()), OSM::ll2m(rect.bottomRight()));
QPointF sc(tbr.width() / size.width(), tbr.height() / size.height());
_zoom = limitZoom(OSM::scale2zoom(qMax(sc.x(), -sc.y())
/ coordinatesRatio(), TILE_SIZE));
/ coordinatesRatio(), _tileSize));
}
return _zoom;
@ -53,7 +54,7 @@ int OnlineMap::zoomFit(const QSize &size, const RectC &rect)
qreal OnlineMap::resolution(const QRectF &rect)
{
return OSM::resolution(rect.center(), _zoom, TILE_SIZE);
return OSM::resolution(rect.center(), _zoom, _tileSize);
}
int OnlineMap::zoomIn()
@ -68,42 +69,50 @@ int OnlineMap::zoomOut()
return _zoom;
}
void OnlineMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
{
_mapRatio = mapRatio;
if (_scalable) {
_scaledSize = _tileSize * deviceRatio;
_tileRatio = deviceRatio;
}
}
qreal OnlineMap::coordinatesRatio() const
{
return _deviceRatio > 1.0 ? _deviceRatio / _tileRatio : 1.0;
return _mapRatio > 1.0 ? _mapRatio / _tileRatio : 1.0;
}
qreal OnlineMap::imageRatio() const
{
return _deviceRatio > 1.0 ? _deviceRatio : _tileRatio;
return _mapRatio > 1.0 ? _mapRatio : _tileRatio;
}
qreal OnlineMap::tileSize() const
{
return (TILE_SIZE / coordinatesRatio());
return (_tileSize / coordinatesRatio());
}
void OnlineMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
{
qreal scale = OSM::zoom2scale(_zoom, TILE_SIZE);
QRectF b(bounds());
qreal scale = OSM::zoom2scale(_zoom, _tileSize);
QPoint tile = OSM::mercator2tile(QPointF(rect.topLeft().x() * scale,
-rect.topLeft().y() * scale) * coordinatesRatio(), _zoom);
QPointF tl(floor(rect.left() / tileSize())
* tileSize(), floor(rect.top() / tileSize()) * tileSize());
QSizeF s(qMin(rect.right() - tl.x(), b.width()),
qMin(rect.bottom() - tl.y(), b.height()));
int width = qCeil(s.width() / tileSize());
int height = qCeil(s.height() / tileSize());
QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y());
int width = _zoom ? qCeil(s.width() / tileSize()) : 1;
int height = _zoom ? qCeil(s.height() / tileSize()) : 1;
QVector<Tile> tiles;
tiles.reserve(width * height);
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++)
tiles.append(Tile(QPoint(tile.x() + i, _invertY ? (1<<_zoom)
- (tile.y() + j) - 1 : tile.y() + j), _zoom));
- (tile.y() + j) - 1 : tile.y() + j), _zoom, _scaledSize));
if (flags & Map::Block)
_tileLoader->loadTilesSync(tiles);
@ -127,14 +136,14 @@ void OnlineMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
QPointF OnlineMap::ll2xy(const Coordinates &c)
{
qreal scale = OSM::zoom2scale(_zoom, TILE_SIZE);
qreal scale = OSM::zoom2scale(_zoom, _tileSize);
QPointF m = OSM::ll2m(c);
return QPointF(m.x() / scale, m.y() / -scale) / coordinatesRatio();
}
Coordinates OnlineMap::xy2ll(const QPointF &p)
{
qreal scale = OSM::zoom2scale(_zoom, TILE_SIZE);
qreal scale = OSM::zoom2scale(_zoom, _tileSize);
return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale)
* coordinatesRatio());
}

View File

@ -13,7 +13,7 @@ class OnlineMap : public Map
public:
OnlineMap(const QString &name, const QString &url, const Range &zooms,
const RectC &bounds, qreal tileRatio, const Authorization &authorization,
bool invertY, QObject *parent = 0);
int tileSize, bool scalable, bool invertY, QObject *parent = 0);
QString name() const {return _name;}
@ -31,7 +31,7 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal ratio) {_deviceRatio = ratio;}
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
void clearCache() {_tileLoader->clearCache();}
private:
@ -45,8 +45,11 @@ private:
Range _zooms;
RectC _bounds;
int _zoom;
qreal _deviceRatio, _tileRatio;
qreal _mapRatio, _tileRatio;
int _tileSize;
bool _scalable;
bool _invertY;
int _scaledSize;
};
#endif // ONLINEMAP_H

View File

@ -7,16 +7,16 @@
#include <QPixmapCache>
#include "common/coordinates.h"
#include "common/rectc.h"
#include "common/config.h"
#include "tar.h"
#include "ozf.h"
#include "image.h"
#include "mapfile.h"
#include "config.h"
#include "ozimap.h"
OziMap::OziMap(const QString &fileName, QObject *parent)
: Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _ratio(1.0), _valid(false)
: Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0), _valid(false)
{
QFileInfo fi(fileName);
QString suffix = fi.suffix().toLower();
@ -78,7 +78,7 @@ OziMap::OziMap(const QString &fileName, QObject *parent)
}
OziMap::OziMap(const QString &fileName, Tar &tar, QObject *parent)
: Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _ratio(1.0), _valid(false)
: Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0), _valid(false)
{
QFileInfo fi(fileName);
QFileInfo map(fi.absolutePath());
@ -217,15 +217,15 @@ void OziMap::unload()
void OziMap::drawTiled(QPainter *painter, const QRectF &rect) const
{
QSizeF ts(_tile.size.width() / _ratio, _tile.size.height() / _ratio);
QSizeF ts(_tile.size.width() / _mapRatio, _tile.size.height() / _mapRatio);
QPointF tl(floor(rect.left() / ts.width()) * ts.width(),
floor(rect.top() / ts.height()) * ts.height());
QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y());
for (int i = 0; i < ceil(s.width() / ts.width()); i++) {
for (int j = 0; j < ceil(s.height() / ts.height()); j++) {
int x = round(tl.x() * _ratio + i * _tile.size.width());
int y = round(tl.y() * _ratio + j * _tile.size.height());
int x = round(tl.x() * _mapRatio + i * _tile.size.width());
int y = round(tl.y() * _mapRatio + j * _tile.size.height());
QString tileName(_tile.path.arg(QString::number(x),
QString::number(y)));
@ -247,7 +247,7 @@ void OziMap::drawTiled(QPainter *painter, const QRectF &rect) const
_tile.path.arg(QString::number(x), QString::number(y))));
else {
#ifdef ENABLE_HIDPI
pixmap.setDevicePixelRatio(_ratio);
pixmap.setDevicePixelRatio(_mapRatio);
#endif // ENABLE_HIDPI
QPointF tp(tl.x() + i * ts.width(), tl.y() + j * ts.height());
painter->drawPixmap(tp, pixmap);
@ -258,16 +258,16 @@ void OziMap::drawTiled(QPainter *painter, const QRectF &rect) const
void OziMap::drawOZF(QPainter *painter, const QRectF &rect) const
{
QSizeF ts(_ozf->tileSize().width() / _ratio, _ozf->tileSize().height()
/ _ratio);
QSizeF ts(_ozf->tileSize().width() / _mapRatio, _ozf->tileSize().height()
/ _mapRatio);
QPointF tl(floor(rect.left() / ts.width()) * ts.width(),
floor(rect.top() / ts.height()) * ts.height());
QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y());
for (int i = 0; i < ceil(s.width() / ts.width()); i++) {
for (int j = 0; j < ceil(s.height() / ts.height()); j++) {
int x = round(tl.x() * _ratio + i * _ozf->tileSize().width());
int y = round(tl.y() * _ratio + j * _ozf->tileSize().height());
int x = round(tl.x() * _mapRatio + i * _ozf->tileSize().width());
int y = round(tl.y() * _mapRatio + j * _ozf->tileSize().height());
QPixmap pixmap;
QString key = _ozf->fileName() + "/" + QString::number(_zoom) + "_"
@ -282,7 +282,7 @@ void OziMap::drawOZF(QPainter *painter, const QRectF &rect) const
qWarning("%s: error loading tile image", qPrintable(key));
else {
#ifdef ENABLE_HIDPI
pixmap.setDevicePixelRatio(_ratio);
pixmap.setDevicePixelRatio(_mapRatio);
#endif // ENABLE_HIDPI
QPointF tp(tl.x() + i * ts.width(), tl.y() + j * ts.height());
painter->drawPixmap(tp, pixmap);
@ -307,23 +307,23 @@ QPointF OziMap::ll2xy(const Coordinates &c)
{
QPointF p(_transform.proj2img(_projection.ll2xy(c)));
return _ozf
? QPointF(p.x() * _scale.x(), p.y() * _scale.y()) / _ratio
: p / _ratio;
? QPointF(p.x() * _scale.x(), p.y() * _scale.y()) / _mapRatio
: p / _mapRatio;
}
Coordinates OziMap::xy2ll(const QPointF &p)
{
return _ozf
? _projection.xy2ll(_transform.img2proj(QPointF(p.x() / _scale.x(),
p.y() / _scale.y()) * _ratio))
: _projection.xy2ll(_transform.img2proj(p * _ratio));
p.y() / _scale.y()) * _mapRatio))
: _projection.xy2ll(_transform.img2proj(p * _mapRatio));
}
QRectF OziMap::bounds()
{
return _ozf
? QRectF(QPointF(0, 0), _ozf->size(_zoom) / _ratio)
: QRectF(QPointF(0, 0), _map.size / _ratio);
? QRectF(QPointF(0, 0), _ozf->size(_zoom) / _mapRatio)
: QRectF(QPointF(0, 0), _map.size / _mapRatio);
}
int OziMap::zoomFit(const QSize &size, const RectC &rect)
@ -371,9 +371,11 @@ void OziMap::rescale(int zoom)
_scale = _ozf->scale(zoom);
}
void OziMap::setDevicePixelRatio(qreal ratio)
void OziMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
{
_ratio = ratio;
Q_UNUSED(deviceRatio);
_mapRatio = mapRatio;
if (_img)
_img->setDevicePixelRatio(_ratio);
_img->setDevicePixelRatio(_mapRatio);
}

View File

@ -33,7 +33,7 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal ratio);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
void load();
void unload();
@ -43,9 +43,9 @@ public:
PointD ll2pp(const Coordinates &c) const
{return _projection.ll2xy(c);}
PointD xy2pp(const QPointF &p) const
{return _transform.img2proj(p * _ratio);}
{return _transform.img2proj(p * _mapRatio);}
QPointF pp2xy(const PointD &p) const
{return _transform.proj2img(p) / _ratio;}
{return _transform.proj2img(p) / _mapRatio;}
private:
struct ImageInfo {
@ -73,7 +73,7 @@ private:
ImageInfo _map, _tile;
int _zoom;
QPointF _scale;
qreal _ratio;
qreal _mapRatio;
bool _valid;
QString _errorString;

View File

@ -11,17 +11,20 @@ class Tile
{
public:
Tile() {}
Tile(const QPoint &xy, const QVariant &zoom, const RectD &bbox = RectD())
{_xy = xy; _zoom = zoom; _bbox = bbox;}
Tile(const QPoint &xy, const QVariant &zoom, int scaledSize = 0,
const RectD &bbox = RectD()) : _xy(xy), _zoom(zoom),
_scaledSize(scaledSize), _bbox(bbox) {}
const QVariant &zoom() const {return _zoom;}
const QPoint &xy() const {return _xy;}
const RectD &bbox() const {return _bbox;}
int scaledSize() const {return _scaledSize;}
QPixmap& pixmap() {return _pixmap;}
private:
QVariant _zoom;
QPoint _xy;
QVariant _zoom;
int _scaledSize;
RectD _bbox;
QPixmap _pixmap;
};

View File

@ -1,17 +1,48 @@
#include <QDir>
#include <QFileInfo>
#include <QEventLoop>
#include <QPixmapCache>
#include <QImageReader>
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
#include <QtCore>
#else // QT_VERSION < 5
#include <QtConcurrent>
#endif // QT_VERSION < 5
#include "tileloader.h"
static bool loadTileFile(Tile &tile, const QString &file)
class TileImage
{
if (!tile.pixmap().load(file)) {
qWarning("%s: error loading tile file", qPrintable(file));
return false;
public:
TileImage() : _tile(0) {}
TileImage(const QString &file, Tile *tile)
: _file(file), _tile(tile) {}
void createPixmap()
{
_tile->pixmap().convertFromImage(_image);
}
void load()
{
QByteArray z(_tile->zoom().toString().toLatin1());
QImageReader reader(_file, z);
if (_tile->scaledSize())
reader.setScaledSize(QSize(_tile->scaledSize(), _tile->scaledSize()));
reader.read(&_image);
}
return true;
const QString &file() const {return _file;}
Tile *tile() {return _tile;}
private:
QString _file;
Tile *_tile;
QImage _image;
};
static void render(TileImage &ti)
{
ti.load();
}
TileLoader::TileLoader(const QString &dir, QObject *parent)
@ -27,18 +58,23 @@ TileLoader::TileLoader(const QString &dir, QObject *parent)
void TileLoader::loadTilesAsync(QVector<Tile> &list)
{
QList<Download> dl;
QList<TileImage> imgs;
for (int i = 0; i < list.size(); i++) {
Tile &t = list[i];
QString file(tileFile(t));
if (QPixmapCache::find(file, t.pixmap()))
continue;
QFileInfo fi(file);
if (fi.exists())
loadTileFile(t, file);
imgs.append(TileImage(file, &t));
else {
QUrl url(tileUrl(t));
if (url.isLocalFile())
loadTileFile(t, url.toLocalFile());
imgs.append(TileImage(url.toLocalFile(), &t));
else
dl.append(Download(url, file));
}
@ -46,45 +82,64 @@ void TileLoader::loadTilesAsync(QVector<Tile> &list)
if (!dl.empty())
_downloader->get(dl, _authorization);
QFuture<void> future = QtConcurrent::map(imgs, render);
future.waitForFinished();
for (int i = 0; i < imgs.size(); i++) {
TileImage &ti = imgs[i];
ti.createPixmap();
QPixmapCache::insert(ti.file(), ti.tile()->pixmap());
}
}
void TileLoader::loadTilesSync(QVector<Tile> &list)
{
QList<Download> dl;
QList<Tile *> tl;
QList<TileImage> imgs;
for (int i = 0; i < list.size(); i++) {
Tile &t = list[i];
QString file(tileFile(t));
if (QPixmapCache::find(file, t.pixmap()))
continue;
QFileInfo fi(file);
if (fi.exists())
loadTileFile(t, file);
imgs.append(TileImage(file, &t));
else {
QUrl url(tileUrl(t));
if (url.isLocalFile())
loadTileFile(t, url.toLocalFile());
else
imgs.append(TileImage(url.toLocalFile(), &t));
else {
dl.append(Download(url, file));
tl.append(&t);
}
}
}
if (dl.empty())
return;
if (!dl.empty()) {
QEventLoop wait;
QObject::connect(_downloader, SIGNAL(finished()), &wait, SLOT(quit()));
if (_downloader->get(dl, _authorization))
wait.exec();
QEventLoop wait;
QObject::connect(_downloader, SIGNAL(finished()), &wait, SLOT(quit()));
if (_downloader->get(dl, _authorization))
wait.exec();
for (int i = 0; i < list.size(); i++) {
Tile &t = list[i];
if (t.pixmap().isNull()) {
QString file = tileFile(t);
for (int i = 0; i < tl.size(); i++) {
Tile *t = tl[i];
QString file = tileFile(*t);
if (QFileInfo(file).exists())
loadTileFile(t, file);
imgs.append(TileImage(file, t));
}
}
QFuture<void> future = QtConcurrent::map(imgs, render);
future.waitForFinished();
for (int i = 0; i < imgs.size(); i++)
imgs[i].createPixmap();
}
void TileLoader::clearCache()

View File

@ -3,7 +3,7 @@
#include <QPainter>
#include "common/wgs84.h"
#include "common/rectc.h"
#include "config.h"
#include "common/programpaths.h"
#include "downloader.h"
#include "tileloader.h"
#include "wmsmap.h"
@ -42,7 +42,7 @@ QString WMSMap::tileUrl(const QString &version) const
QString WMSMap::tilesDir() const
{
return QString(TILES_DIR + "/" + _name);
return QString(QDir(ProgramPaths::tilesDir()).filePath(_name));
}
void WMSMap::computeZooms(const RangeF &scaleDenominator)
@ -104,7 +104,7 @@ bool WMSMap::loadWMS()
WMSMap::WMSMap(const QString &name, const WMS::Setup &setup, QObject *parent)
: Map(parent), _name(name), _setup(setup), _tileLoader(0), _zoom(0),
_ratio(1.0), _valid(false)
_mapRatio(1.0), _valid(false)
{
_tileLoader = new TileLoader(tilesDir(), this);
_tileLoader->setAuthorization(_setup.authorization());
@ -124,8 +124,8 @@ void WMSMap::clearCache()
QRectF WMSMap::bounds()
{
return QRectF(_transform.proj2img(_bbox.topLeft()) / _ratio,
_transform.proj2img(_bbox.bottomRight()) / _ratio);
return QRectF(_transform.proj2img(_bbox.topLeft()) / _mapRatio,
_transform.proj2img(_bbox.bottomRight()) / _mapRatio);
}
int WMSMap::zoomFit(const QSize &size, const RectC &rect)
@ -141,7 +141,7 @@ int WMSMap::zoomFit(const QSize &size, const RectC &rect)
_zoom = 0;
for (int i = 0; i < _zooms.size(); i++) {
if (sd2res(_zooms.at(i)) < resolution / _ratio)
if (sd2res(_zooms.at(i)) < resolution / _mapRatio)
break;
_zoom = i;
}
@ -174,17 +174,17 @@ int WMSMap::zoomOut()
QPointF WMSMap::ll2xy(const Coordinates &c)
{
return _transform.proj2img(_projection.ll2xy(c)) / _ratio;
return _transform.proj2img(_projection.ll2xy(c)) / _mapRatio;
}
Coordinates WMSMap::xy2ll(const QPointF &p)
{
return _projection.xy2ll(_transform.img2proj(p * _ratio));
return _projection.xy2ll(_transform.img2proj(p * _mapRatio));
}
qreal WMSMap::tileSize() const
{
return (TILE_SIZE / _ratio);
return (TILE_SIZE / _mapRatio);
}
void WMSMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
@ -206,7 +206,7 @@ void WMSMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
? RectD(PointD(tbr.y(), tbr.x()), PointD(ttl.y(), ttl.x()))
: RectD(ttl, tbr);
tiles.append(Tile(QPoint(i, j), _zoom, bbox));
tiles.append(Tile(QPoint(i, j), _zoom, 0, bbox));
}
}
@ -220,7 +220,7 @@ void WMSMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
QPointF tp(t.xy().x() * tileSize(), t.xy().y() * tileSize());
if (!t.pixmap().isNull()) {
#ifdef ENABLE_HIDPI
t.pixmap().setDevicePixelRatio(_ratio);
t.pixmap().setDevicePixelRatio(_mapRatio);
#endif // ENABLE_HIDPI
painter->drawPixmap(tp, t.pixmap());
}

View File

@ -31,7 +31,8 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal ratio) {_ratio = ratio;}
void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio)
{_mapRatio = mapRatio;}
void clearCache();
bool isValid() const {return _valid;}
@ -56,7 +57,7 @@ private:
QVector<double> _zooms;
RectD _bbox;
int _zoom;
qreal _ratio;
qreal _mapRatio;
bool _valid;
QString _errorString;

View File

@ -12,6 +12,12 @@
#include "wmts.h"
static void skipParentElement(QXmlStreamReader &reader)
{
while (reader.readNextStartElement())
reader.skipCurrentElement();
}
WMTS::TileMatrix WMTS::tileMatrix(QXmlStreamReader &reader)
{
TileMatrix matrix;
@ -45,24 +51,19 @@ WMTS::TileMatrix WMTS::tileMatrix(QXmlStreamReader &reader)
void WMTS::tileMatrixSet(QXmlStreamReader &reader, CTX &ctx)
{
QString id, crs;
QSet<TileMatrix> matrixes;
while (reader.readNextStartElement()) {
if (reader.name() == "Identifier")
id = reader.readElementText();
else if (reader.name() == "SupportedCRS")
crs = reader.readElementText();
if (reader.name() == "Identifier") {
if (reader.readElementText() != ctx.setup.set()) {
skipParentElement(reader);
return;
}
} else if (reader.name() == "SupportedCRS")
ctx.crs = reader.readElementText();
else if (reader.name() == "TileMatrix")
matrixes.insert(tileMatrix(reader));
ctx.matrixes.insert(tileMatrix(reader));
else
reader.skipCurrentElement();
}
if (id == ctx.setup.set()) {
ctx.crs = crs;
_matrixes = matrixes;
}
}
WMTS::MatrixLimits WMTS::tileMatrixLimits(QXmlStreamReader &reader)
@ -106,22 +107,19 @@ QSet<WMTS::MatrixLimits> WMTS::tileMatrixSetLimits(QXmlStreamReader &reader)
void WMTS::tileMatrixSetLink(QXmlStreamReader &reader, CTX &ctx)
{
QString id;
QSet<MatrixLimits> limits;
while (reader.readNextStartElement()) {
if (reader.name() == "TileMatrixSet")
id = reader.readElementText();
else if (reader.name() == "TileMatrixSetLimits")
limits = tileMatrixSetLimits(reader);
if (reader.name() == "TileMatrixSet") {
if (reader.readElementText() == ctx.setup.set())
ctx.hasSet = true;
else {
skipParentElement(reader);
return;
}
} else if (reader.name() == "TileMatrixSetLimits")
ctx.limits = tileMatrixSetLimits(reader);
else
reader.skipCurrentElement();
}
if (id == ctx.setup.set()) {
ctx.hasSet = true;
_limits = limits;
}
}
RectC WMTS::wgs84BoundingBox(QXmlStreamReader &reader)
@ -158,40 +156,37 @@ QString WMTS::style(QXmlStreamReader &reader)
void WMTS::layer(QXmlStreamReader &reader, CTX &ctx)
{
QString id, tpl;
RectC bounds;
QStringList formats, styles;
while (reader.readNextStartElement()) {
if (reader.name() == "Identifier")
id = reader.readElementText();
else if (reader.name() == "TileMatrixSetLink")
if (reader.name() == "Identifier") {
if (reader.readElementText() == ctx.setup.layer())
ctx.hasLayer = true;
else {
skipParentElement(reader);
return;
}
} else if (reader.name() == "TileMatrixSetLink")
tileMatrixSetLink(reader, ctx);
else if (reader.name() == "WGS84BoundingBox")
bounds = wgs84BoundingBox(reader);
_bounds = wgs84BoundingBox(reader);
else if (reader.name() == "ResourceURL") {
const QXmlStreamAttributes &attr = reader.attributes();
if (attr.value("resourceType") == "tile")
tpl = attr.value("template").toString();
if (attr.value("resourceType") == "tile" && ctx.setup.rest())
_tileUrl = attr.value("template").toString();
reader.skipCurrentElement();
} else if (reader.name() == "Style")
styles.append(style(reader));
else if (reader.name() == "Format")
formats.append(reader.readElementText());
else
} else if (reader.name() == "Style") {
const QXmlStreamAttributes &attr = reader.attributes();
bool isDefault = (attr.value("isDefault") == "true");
QString s = style(reader);
if (isDefault)
ctx.defaultStyle = s;
if (!s.isEmpty() && s == ctx.setup.style())
ctx.hasStyle = true;
} else if (reader.name() == "Format") {
if (reader.readElementText() == ctx.setup.format())
ctx.hasFormat = true;
} else
reader.skipCurrentElement();
}
if (id == ctx.setup.layer()) {
ctx.hasLayer = true;
_bounds = bounds;
if (ctx.setup.rest())
_tileUrl = tpl;
if (styles.contains(ctx.setup.style()) || ctx.setup.style().isEmpty())
ctx.hasStyle = true;
if (formats.contains(ctx.setup.format()))
ctx.hasFormat = true;
}
}
void WMTS::contents(QXmlStreamReader &reader, CTX &ctx)
@ -216,10 +211,24 @@ void WMTS::capabilities(QXmlStreamReader &reader, CTX &ctx)
}
}
bool WMTS::parseCapabilities(const QString &path, const Setup &setup)
void WMTS::createZooms(const CTX &ctx)
{
for (QSet<TileMatrix>::const_iterator mi = ctx.matrixes.constBegin();
mi != ctx.matrixes.constEnd(); ++mi) {
QSet<MatrixLimits>::const_iterator li = ctx.limits.find(
MatrixLimits(mi->id));
if (!ctx.limits.isEmpty() && li == ctx.limits.constEnd())
continue;
_zooms.append(Zoom(mi->id, mi->scaleDenominator, mi->topLeft, mi->tile,
mi->matrix, li == ctx.limits.constEnd() ? QRect() : li->rect));
}
qSort(_zooms);
}
bool WMTS::parseCapabilities(const QString &path, CTX &ctx)
{
QFile file(path);
CTX ctx(setup);
QXmlStreamReader reader;
if (!file.open(QFile::ReadOnly | QFile::Text)) {
@ -244,10 +253,14 @@ bool WMTS::parseCapabilities(const QString &path, const Setup &setup)
_errorString = ctx.setup.layer() + ": layer not provided";
return false;
}
if (!ctx.hasStyle) {
if (!ctx.hasStyle && !ctx.setup.style().isEmpty()) {
_errorString = ctx.setup.style() + ": style not provided";
return false;
}
if (ctx.setup.style().isEmpty() && ctx.defaultStyle.isEmpty()) {
_errorString = "Default style not provided";
return false;
}
if (!ctx.setup.rest() && !ctx.hasFormat) {
_errorString = ctx.setup.format() + ": format not provided";
return false;
@ -265,7 +278,8 @@ bool WMTS::parseCapabilities(const QString &path, const Setup &setup)
_errorString = ctx.crs + ": unknown CRS";
return false;
}
if (_matrixes.isEmpty()) {
createZooms(ctx);
if (_zooms.isEmpty()) {
_errorString = "No usable tile matrix found";
return false;
}
@ -307,10 +321,12 @@ WMTS::WMTS(const QString &file, const WMTS::Setup &setup) : _valid(false)
if (!url.isLocalFile() && !QFileInfo(file).exists())
if (!downloadCapabilities(url.toString(), file, setup.authorization()))
return;
if (!parseCapabilities(url.isLocalFile() ? url.toLocalFile() : file, setup))
CTX ctx(setup);
if (!parseCapabilities(url.isLocalFile() ? url.toLocalFile() : file, ctx))
return;
QString style = setup.style().isEmpty() ? "default" : setup.style();
QString style = setup.style().isEmpty() ? ctx.defaultStyle : setup.style();
if (!setup.rest()) {
_tileUrl = QString("%1%2service=WMTS&Version=1.0.0&request=GetTile"
"&Format=%3&Layer=%4&Style=%5&TileMatrixSet=%6&TileMatrix=$z"
@ -337,26 +353,6 @@ WMTS::WMTS(const QString &file, const WMTS::Setup &setup) : _valid(false)
_valid = true;
}
QList<WMTS::Zoom> WMTS::zooms() const
{
QList<Zoom> zooms;
QSet<TileMatrix>::const_iterator mi;
QSet<MatrixLimits>::const_iterator li;
for (mi = _matrixes.constBegin(); mi != _matrixes.constEnd(); ++mi) {
if ((li = _limits.find(MatrixLimits(mi->id))) == _limits.constEnd())
zooms.append(Zoom(mi->id, mi->scaleDenominator, mi->topLeft,
mi->tile, mi->matrix, QRect()));
else
zooms.append(Zoom(mi->id, mi->scaleDenominator, mi->topLeft,
mi->tile, mi->matrix, li->rect));
}
qSort(zooms);
return zooms;
}
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const WMTS::Setup &setup)
{

View File

@ -80,7 +80,7 @@ public:
WMTS(const QString &path, const Setup &setup);
const RectC &bounds() const {return _bounds;}
QList<Zoom> zooms() const;
const QList<Zoom> &zooms() const {return _zooms;}
const Projection &projection() const {return _projection;}
const QString &tileUrl() const {return _tileUrl;}
@ -117,7 +117,10 @@ private:
struct CTX {
const Setup &setup;
QSet<TileMatrix> matrixes;
QSet<MatrixLimits> limits;
QString crs;
QString defaultStyle;
bool hasLayer;
bool hasStyle;
bool hasFormat;
@ -137,12 +140,12 @@ private:
void layer(QXmlStreamReader &reader, CTX &ctx);
void contents(QXmlStreamReader &reader, CTX &ctx);
void capabilities(QXmlStreamReader &reader, CTX &ctx);
bool parseCapabilities(const QString &path, const Setup &setup);
bool parseCapabilities(const QString &path, CTX &ctx);
bool downloadCapabilities(const QString &url, const QString &file,
const Authorization &authorization);
void createZooms(const CTX &ctx);
QSet<TileMatrix> _matrixes;
QSet<MatrixLimits> _limits;
QList<Zoom> _zooms;
RectC _bounds;
Projection _projection;
QString _tileUrl;

View File

@ -1,8 +1,9 @@
#include <QtCore>
#include <QPainter>
#include <QDir>
#include "common/rectc.h"
#include "common/wgs84.h"
#include "config.h"
#include "common/programpaths.h"
#include "transform.h"
#include "tileloader.h"
#include "wmts.h"
@ -38,7 +39,7 @@ bool WMTSMap::loadWMTS()
WMTSMap::WMTSMap(const QString &name, const WMTS::Setup &setup, qreal tileRatio,
QObject *parent) : Map(parent), _name(name), _setup(setup), _tileLoader(0),
_zoom(0), _deviceRatio(1.0), _tileRatio(tileRatio), _valid(false)
_zoom(0), _mapRatio(1.0), _tileRatio(tileRatio), _valid(false)
{
_tileLoader = new TileLoader(tilesDir(), this);
_tileLoader->setAuthorization(_setup.authorization());
@ -58,7 +59,7 @@ void WMTSMap::clearCache()
QString WMTSMap::tilesDir() const
{
return QString(TILES_DIR + "/" + _name);
return QString(QDir(ProgramPaths::tilesDir()).filePath(_name));
}
double WMTSMap::sd2res(double scaleDenominator) const
@ -150,12 +151,12 @@ int WMTSMap::zoomOut()
qreal WMTSMap::coordinatesRatio() const
{
return _deviceRatio > 1.0 ? _deviceRatio / _tileRatio : 1.0;
return _mapRatio > 1.0 ? _mapRatio / _tileRatio : 1.0;
}
qreal WMTSMap::imageRatio() const
{
return _deviceRatio > 1.0 ? _deviceRatio : _tileRatio;
return _mapRatio > 1.0 ? _mapRatio : _tileRatio;
}
QSizeF WMTSMap::tileSize(const WMTS::Zoom &zoom) const

View File

@ -31,7 +31,8 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal ratio) {_deviceRatio = ratio;}
void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio)
{_mapRatio = mapRatio;}
void clearCache();
bool isValid() const {return _valid;}
@ -55,7 +56,7 @@ private:
Transform _transform;
CoordinateSystem _cs;
int _zoom;
qreal _deviceRatio, _tileRatio;
qreal _mapRatio, _tileRatio;
bool _valid;
QString _errorString;