1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-03 06:19:15 +02:00

Compare commits

..

97 Commits
5.2 ... 5.6

Author SHA1 Message Date
b4cf614f77 Added missing "other sample dimensions" support for WMS 2018-04-08 19:13:16 +02:00
ca710b6a22 Fixed typo in german ts file
ts files update
2018-04-08 18:50:34 +02:00
c894e75c17 Adjusted stuff to comply with the new map version 1 xsd 2018-04-08 17:48:13 +02:00
259a15332e Fixed QT4 build 2018-04-07 23:04:26 +02:00
c4915891e7 Code cleanup 2018-04-07 18:42:25 +02:00
c5256b25e9 Added missing namespace 2018-04-05 21:13:48 +02:00
81b3a517f8 Use the correct axis order defaults for WMS/WMTS maps 2018-04-05 20:38:23 +02:00
3aa1ab4b4c Set a less restrictive lower bound for WMS scale denominators 2018-04-03 23:14:47 +02:00
d4fb8ed9c9 Fixed error reporting 2018-04-03 23:05:17 +02:00
fb16c3f2db Fixed tile cache reload logic 2018-04-03 22:36:08 +02:00
4096d87a6a Improved default WMS/WMTS style handling 2018-04-03 22:35:13 +02:00
68eac5b8cc Yet another WMS corner case handling fix 2018-04-03 01:14:58 +02:00
88d6904ded Yet another WMS bounding box computation fix 2018-04-03 00:08:01 +02:00
021558b114 Fixed QT4 build 2018-04-02 23:33:10 +02:00
b8815ca9f5 Fixed layer bounding box & scale denominator range joining 2018-04-02 23:27:42 +02:00
e845e216bd Added support for WMS multi-layer maps 2018-04-02 19:59:52 +02:00
60cc869ade The "default" style does not to be set wxplicitly 2018-04-02 18:30:57 +02:00
e3e8fdbacf Fixed WMS 1.1.x support
Added support for HTTP basic authorization
2018-04-01 20:01:25 +02:00
16f2d7ad34 Added support for WMS 1.1.x versions 2018-03-31 11:27:01 +02:00
aecda0e517 Version++ 2018-03-30 10:48:57 +02:00
bf3589812a Initial WMS support (no multi-layer support for now) 2018-03-30 10:25:05 +02:00
8821536419 Fixed most clazy warnings 2018-03-29 00:29:08 +02:00
bda24d9091 Use $HOME as the default open directory (on all platforms) 2018-03-28 02:01:27 +02:00
820e614921 Fixed broken data size copy 2018-03-26 01:02:31 +02:00
35703e3363 Refactoring 2018-03-22 20:00:30 +01:00
a54821863f Includes cleanup 2018-03-21 19:23:17 +01:00
5bc3b2ad05 Merge branch 'master' of https://github.com/tumic0/GPXSee 2018-03-21 19:10:42 +01:00
992fd2c5cd Code cleanup 2018-03-21 19:09:37 +01:00
4b4a1902ef Indent cleanup 2018-03-21 18:52:57 +01:00
7d3bc2112a Update gpxsee.desktop (#85)
Add Swedish translation
2018-03-20 21:29:45 +01:00
4ea2f0752a Do not display negative zeros.
Fixes #86
2018-03-20 21:17:20 +01:00
0bb3b3812c Fixed broken release builds 2018-03-19 22:40:49 +01:00
b23639bef2 Version++ 2018-03-19 20:11:12 +01:00
2d8bf2dbb9 Added missing Swiss grid map file support 2018-03-19 19:56:31 +01:00
29efa84075 Do not depend on the initializing ellipsoid 2018-03-19 19:13:48 +01:00
3d06fe8831 Also clear the error URLs when clearing the tile cache.
Code cleanup.
2018-03-15 18:46:34 +01:00
fe1f6c80b4 Use the correct units for azimuths 2018-03-15 00:27:44 +01:00
35d1e69d7f Merge branch 'master' of https://github.com/tumic0/GPXSee 2018-03-14 07:25:28 +01:00
3043128565 Added finite HTTP response timeout 2018-03-14 07:23:07 +01:00
e56a9e33f3 Added ETRS-TM35FIN (#82) 2018-03-13 09:17:59 +01:00
07aca435d8 Update gpxsee_sv.ts (#81)
Latest strings translated
2018-03-12 20:54:10 +01:00
4e4a3d042a Translations update (#80) 2018-03-12 20:53:15 +01:00
bf5ae22f0d Handle the WGS84 ellipsoid only definitions like the GRS80 ellipsoid only definitions 2018-03-12 20:05:53 +01:00
309fdb675c Removed unused definitions 2018-03-11 20:53:16 +01:00
e0daf367fb Added support for WGS84 GeoTIFF images with the GCS defined using the ellipsoid only 2018-03-11 20:11:42 +01:00
32d8672698 REST variables (dimensions) are apparently case-insensitive 2018-03-11 19:23:40 +01:00
0ef89e200d Translations update 2018-03-11 16:28:30 +01:00
6d6c232dba Version++ 2018-03-11 10:49:02 +01:00
8132ff722d Added support for WMTS dimensions 2018-03-11 10:31:41 +01:00
49792064d7 Fixed error handling 2018-03-11 09:24:04 +01:00
7aef81d823 Added support for EPSG 21781 PCS (Swiss grid)
Fixed swapped LCC1 and LCC2 GeoTIFF coordinate transformation codes
2018-03-11 01:10:24 +01:00
1d3d1aa5b7 Fixed broken zoom rectangle computation 2018-03-10 21:04:14 +01:00
bcd14726f3 Added pace info 2018-03-10 20:25:13 +01:00
fd15799114 Includes cleanup 2018-03-10 09:25:52 +01:00
a8bc2ae4c4 Fixed wrong data type 2018-03-10 08:40:55 +01:00
67aba4703b Some more code cleanup 2018-03-09 23:24:08 +01:00
a64e5e13c3 Remove the 1px offset workaround as it does not work properly anyway... 2018-03-09 21:53:06 +01:00
60fcff7658 Code cleanup 2018-03-09 18:57:23 +01:00
bc881836ac Improved map index caching 2018-03-09 18:56:54 +01:00
de05f5e64b Some more offline map code cleanup 2018-03-08 19:08:39 +01:00
16476dbf74 Offline map code cleanup/refactoring 2018-03-08 02:24:10 +01:00
a21464d98d Added missing virtual destructors 2018-03-08 00:57:09 +01:00
d6746bc444 Code cleanup 2018-03-06 19:28:07 +01:00
e4d8af2040 Update README.md 2018-03-01 20:30:02 +01:00
b40e0d3bbf Fixed accessing of un-initialized variable 2018-03-01 19:06:55 +01:00
9300d671a1 Fixed invalid memory access 2018-03-01 19:06:34 +01:00
b9ed0c3933 Improved scale computation on offline & WMTS maps 2018-02-28 22:19:46 +01:00
46cefada94 Code cleanup 2018-02-27 21:50:29 +01:00
e1e49b32e6 Added some more map definition checking 2018-02-27 01:02:22 +01:00
fa99d01a77 Extended error checking 2018-02-26 22:35:58 +01:00
688e309ef7 Update gpxsee_sv.ts (#79)
Change shortcut letter for "Data"
2018-02-26 19:22:34 +01:00
ae4723acb1 Added GCS 4178 and related PCSs 2018-02-26 19:21:00 +01:00
8c6f70d837 Code cleanup 2018-02-26 19:13:57 +01:00
d1b0e2ef73 Improved error reporting 2018-02-26 19:05:53 +01:00
962310df7d Fixed single point zoom fit on WMTS maps 2018-02-25 19:33:12 +01:00
f8c031e931 Translation update/cleanup 2018-02-25 09:31:19 +01:00
8022a9efbe Update gpxsee_sv.ts (#78) 2018-02-25 09:18:10 +01:00
fbab4b0097 Made the axis order an attribute of the set rather than a separate element 2018-02-25 08:58:40 +01:00
5e5ff6d96f Added support for REST WMTS maps 2018-02-25 02:31:01 +01:00
55e967673c Use image/png as the default image format 2018-02-24 22:31:37 +01:00
757ba6a566 Fixed QT4 build 2018-02-24 16:48:38 +01:00
ee80260e46 Improved capabilities xml parsing
Improved bounds handling
2018-02-24 16:44:30 +01:00
fa3e6d8550 Added error checking 2018-02-24 11:40:54 +01:00
6e95d484cd Added support for OGC:CRS84 CRS to WMTS maps 2018-02-24 11:20:29 +01:00
376587202b Properly handling non-integer tile matrix ids 2018-02-24 10:34:27 +01:00
d11ffc9ea4 Added tile matrix set limits handling
Added axis order setting
2018-02-24 01:59:03 +01:00
bf6ebdc088 Translations update (#77) 2018-02-23 00:13:49 +01:00
619df591e2 Added support for geographic2d "projected" WMTS maps 2018-02-22 21:02:56 +01:00
10aa7d3945 Code cleanup 2018-02-22 18:12:47 +01:00
12319fd8fd Cleanup 2018-02-22 18:07:51 +01:00
ccb7336e3f Added menu accelerator keys 2018-02-22 08:18:10 +01:00
a7fea3878c Version++ 2018-02-22 00:56:49 +01:00
a6cf88aa92 Fixed visual artefacts on transparent tiles 2018-02-22 00:50:45 +01:00
b054cf9046 Using the correct projection for Lambert azimuthal equal area 2018-02-22 00:46:05 +01:00
9c5153f89a Fixed QT4 build 2018-02-21 00:13:11 +01:00
2ebcdeeeff Added ETRS89 data 2018-02-20 23:38:29 +01:00
1bc4833a81 Added initial WMTS support 2018-02-20 23:37:19 +01:00
97 changed files with 6048 additions and 3631 deletions

View File

@ -1,4 +1,4 @@
version: 5.2.{build} version: 5.6.{build}
configuration: Release configuration: Release
platform: Any CPU platform: Any CPU
environment: environment:

View File

@ -3,7 +3,7 @@ GPXSee is a Qt-based GPS log file viewer and analyzer that supports GPX, TCX,
KML, FIT, IGC and NMEA files. KML, FIT, IGC and NMEA files.
## Features ## Features
* User-definable online maps. * User-definable online maps (OSM/Google tiles, WMTS).
* Offline maps (OziExplorer maps, TrekBuddy maps/atlases, GeoTIFF images). * Offline maps (OziExplorer maps, TrekBuddy maps/atlases, GeoTIFF images).
* Elevation, speed, heart rate, cadence, power and temperature graphs. * Elevation, speed, heart rate, cadence, power and temperature graphs.
* Support for multiple tracks in one view. * Support for multiple tracks in one view.

View File

@ -1,5 +1,5 @@
TARGET = GPXSee TARGET = GPXSee
VERSION = 5.2 VERSION = 5.6
QT += core \ QT += core \
gui \ gui \
network network
@ -116,7 +116,14 @@ HEADERS += src/config.h \
src/map/primemeridian.h \ src/map/primemeridian.h \
src/map/linearunits.h \ src/map/linearunits.h \
src/map/ct.h \ src/map/ct.h \
src/map/mapsource.h src/map/mapsource.h \
src/map/tileloader.h \
src/map/wmtsmap.h \
src/map/wmts.h \
src/map/wmsmap.h \
src/map/wms.h \
src/map/crs.h \
src/map/coordinatesystem.h
SOURCES += src/main.cpp \ SOURCES += src/main.cpp \
src/common/coordinates.cpp \ src/common/coordinates.cpp \
src/common/rectc.cpp \ src/common/rectc.cpp \
@ -202,7 +209,14 @@ SOURCES += src/main.cpp \
src/map/angularunits.cpp \ src/map/angularunits.cpp \
src/map/primemeridian.cpp \ src/map/primemeridian.cpp \
src/map/linearunits.cpp \ src/map/linearunits.cpp \
src/map/mapsource.cpp src/map/mapsource.cpp \
src/map/tileloader.cpp \
src/map/wmtsmap.cpp \
src/map/wmts.cpp \
src/map/wmsmap.cpp \
src/map/wms.cpp \
src/map/crs.cpp \
src/map/coordinatesystem.cpp
RESOURCES += gpxsee.qrc RESOURCES += gpxsee.qrc
TRANSLATIONS = lang/gpxsee_cs.ts \ TRANSLATIONS = lang/gpxsee_cs.ts \
lang/gpxsee_sv.ts \ lang/gpxsee_sv.ts \

View File

@ -301,376 +301,380 @@
<context> <context>
<name>GUI</name> <name>GUI</name>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="588"/> <location filename="../src/GUI/gui.cpp" line="592"/>
<source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source> <source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source>
<translation>Program GPXSee je distribuován pod podmínkami licence GNU General Public License verze 3. Pro více informací navštivte stránky programu na adrese </translation> <translation>Program GPXSee je distribuován pod podmínkami licence GNU General Public License verze 3. Pro více informací navštivte stránky programu na adrese </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="662"/> <location filename="../src/GUI/gui.cpp" line="666"/>
<source>Open file</source> <source>Open file</source>
<translation>Otevřít soubor</translation> <translation>Otevřít soubor</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="751"/> <location filename="../src/GUI/gui.cpp" line="757"/>
<source>Open POI file</source> <source>Open POI file</source>
<translation>Otevřít POI soubor</translation> <translation>Otevřít POI soubor</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="195"/> <location filename="../src/GUI/gui.cpp" line="199"/>
<source>Quit</source> <source>Quit</source>
<translation>Ukončit</translation> <translation>Ukončit</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="204"/> <location filename="../src/GUI/gui.cpp" line="208"/>
<location filename="../src/GUI/gui.cpp" line="605"/> <location filename="../src/GUI/gui.cpp" line="609"/>
<location filename="../src/GUI/gui.cpp" line="606"/> <location filename="../src/GUI/gui.cpp" line="610"/>
<source>Keyboard controls</source> <source>Keyboard controls</source>
<translation>Ovládací klávesy</translation> <translation>Ovládací klávesy</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="229"/> <location filename="../src/GUI/gui.cpp" line="233"/>
<source>Close</source> <source>Close</source>
<translation>Zavřít</translation> <translation>Zavřít</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="235"/> <location filename="../src/GUI/gui.cpp" line="239"/>
<source>Reload</source> <source>Reload</source>
<translation>Znovu načíst</translation> <translation>Znovu načíst</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="517"/> <location filename="../src/GUI/gui.cpp" line="521"/>
<source>Show</source> <source>Show</source>
<translation>Zobrazit</translation> <translation>Zobrazit</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="428"/> <location filename="../src/GUI/gui.cpp" line="515"/>
<location filename="../src/GUI/gui.cpp" line="511"/>
<source>File</source> <source>File</source>
<translation>Soubor</translation> <translation>Soubor</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="246"/> <location filename="../src/GUI/gui.cpp" line="250"/>
<source>Close POI files</source> <source>Close POI files</source>
<translation>Zavřit POI soubory</translation> <translation>Zavřit POI soubory</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="248"/> <location filename="../src/GUI/gui.cpp" line="252"/>
<source>Overlap POIs</source> <source>Overlap POIs</source>
<translation>Překrývat POI</translation> <translation>Překrývat POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="252"/> <location filename="../src/GUI/gui.cpp" line="256"/>
<source>Show POI labels</source> <source>Show POI labels</source>
<translation>Zobrazit názvy POI</translation> <translation>Zobrazit názvy POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="257"/> <location filename="../src/GUI/gui.cpp" line="261"/>
<source>Show POIs</source> <source>Show POIs</source>
<translation>Zobrazit POI</translation> <translation>Zobrazit POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="266"/> <location filename="../src/GUI/gui.cpp" line="270"/>
<source>Show map</source> <source>Show map</source>
<translation>Zobrazit mapu</translation> <translation>Zobrazit mapu</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="276"/> <location filename="../src/GUI/gui.cpp" line="280"/>
<source>Clear tile cache</source> <source>Clear tile cache</source>
<translation>Vymazat mezipaměť dlaždic</translation> <translation>Vymazat mezipaměť dlaždic</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="213"/> <location filename="../src/GUI/gui.cpp" line="217"/>
<source>Open...</source> <source>Open...</source>
<translation>Otevřít...</translation> <translation>Otevřít...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="202"/> <location filename="../src/GUI/gui.cpp" line="206"/>
<location filename="../src/GUI/gui.cpp" line="639"/> <location filename="../src/GUI/gui.cpp" line="643"/>
<location filename="../src/GUI/gui.cpp" line="640"/> <location filename="../src/GUI/gui.cpp" line="644"/>
<source>Paths</source> <source>Paths</source>
<translation>Cesty</translation> <translation>Cesty</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="243"/> <location filename="../src/GUI/gui.cpp" line="247"/>
<source>Load POI file...</source> <source>Load POI file...</source>
<translation>Nahrát POI soubor...</translation> <translation>Nahrát POI soubor...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="274"/> <location filename="../src/GUI/gui.cpp" line="278"/>
<source>Load map...</source> <source>Load map...</source>
<translation>Nahrát mapu...</translation> <translation>Nahrát mapu...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="280"/>
<location filename="../src/GUI/gui.cpp" line="284"/> <location filename="../src/GUI/gui.cpp" line="284"/>
<location filename="../src/GUI/gui.cpp" line="622"/> <location filename="../src/GUI/gui.cpp" line="288"/>
<location filename="../src/GUI/gui.cpp" line="626"/>
<source>Next map</source> <source>Next map</source>
<translation>Následující mapa</translation> <translation>Následující mapa</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="294"/> <location filename="../src/GUI/gui.cpp" line="298"/>
<source>Show tracks</source> <source>Show tracks</source>
<translation>Zobrazit cesty</translation> <translation>Zobrazit cesty</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="298"/> <location filename="../src/GUI/gui.cpp" line="302"/>
<source>Show routes</source> <source>Show routes</source>
<translation>Zobrazit trasy</translation> <translation>Zobrazit trasy</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="302"/> <location filename="../src/GUI/gui.cpp" line="306"/>
<source>Show waypoints</source> <source>Show waypoints</source>
<translation>Zobrazit navigační body</translation> <translation>Zobrazit navigační body</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="306"/> <location filename="../src/GUI/gui.cpp" line="310"/>
<source>Waypoint labels</source> <source>Waypoint labels</source>
<translation>Názvy navigačních bodů</translation> <translation>Názvy navigačních bodů</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="317"/> <location filename="../src/GUI/gui.cpp" line="321"/>
<source>Show graphs</source> <source>Show graphs</source>
<translation>Zobrazit grafy</translation> <translation>Zobrazit grafy</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="337"/> <location filename="../src/GUI/gui.cpp" line="341"/>
<source>Show grid</source> <source>Show grid</source>
<translation>Zobrazit mřížku</translation> <translation>Zobrazit mřížku</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="341"/> <location filename="../src/GUI/gui.cpp" line="345"/>
<source>Show slider info</source> <source>Show slider info</source>
<translation>Zobrazit informace o posuvníku</translation> <translation>Zobrazit informace o posuvníku</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="347"/> <location filename="../src/GUI/gui.cpp" line="351"/>
<source>Show toolbars</source> <source>Show toolbars</source>
<translation>Zobrazovat nástrojové lišty</translation> <translation>Zobrazovat nástrojové lišty</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="353"/> <location filename="../src/GUI/gui.cpp" line="357"/>
<source>Total time</source> <source>Total time</source>
<translation>Celkový čas</translation> <translation>Celkový čas</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="358"/> <location filename="../src/GUI/gui.cpp" line="362"/>
<location filename="../src/GUI/gui.cpp" line="926"/> <location filename="../src/GUI/gui.cpp" line="934"/>
<source>Moving time</source> <source>Moving time</source>
<translation>Čistý čas</translation> <translation>Čistý čas</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="365"/> <location filename="../src/GUI/gui.cpp" line="369"/>
<source>Metric</source> <source>Metric</source>
<translation>Metrické</translation> <translation>Metrické</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="370"/> <location filename="../src/GUI/gui.cpp" line="374"/>
<source>Imperial</source> <source>Imperial</source>
<translation>Imperiální</translation> <translation>Imperiální</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="375"/> <location filename="../src/GUI/gui.cpp" line="379"/>
<source>Nautical</source> <source>Nautical</source>
<translation>Námořní</translation> <translation>Námořní</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="382"/> <location filename="../src/GUI/gui.cpp" line="386"/>
<source>Decimal degrees (DD)</source> <source>Decimal degrees (DD)</source>
<translation>Desetinné stupně (DD)</translation> <translation>Desetinné stupně (DD)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="387"/> <location filename="../src/GUI/gui.cpp" line="391"/>
<source>Degrees and decimal minutes (DMM)</source> <source>Degrees and decimal minutes (DMM)</source>
<translation>Stupně a desetinné minuty (DMM)</translation> <translation>Stupně a desetinné minuty (DMM)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="393"/> <location filename="../src/GUI/gui.cpp" line="397"/>
<source>Degrees, minutes, seconds (DMS)</source> <source>Degrees, minutes, seconds (DMS)</source>
<translation>Stupně, minuty, vteřiny (DMS)</translation> <translation>Stupně, minuty, vteřiny (DMS)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="398"/> <location filename="../src/GUI/gui.cpp" line="402"/>
<source>Fullscreen mode</source> <source>Fullscreen mode</source>
<translation>Celoobrazovkový režim</translation> <translation>Celoobrazovkový režim</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="404"/> <location filename="../src/GUI/gui.cpp" line="408"/>
<source>Options...</source> <source>Options...</source>
<translation>Nastavení...</translation> <translation>Nastavení...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="410"/> <location filename="../src/GUI/gui.cpp" line="414"/>
<source>Next</source> <source>Next</source>
<translation>Následující</translation> <translation>Následující</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="413"/> <location filename="../src/GUI/gui.cpp" line="417"/>
<source>Previous</source> <source>Previous</source>
<translation>Předchozí</translation> <translation>Předchozí</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="417"/> <location filename="../src/GUI/gui.cpp" line="421"/>
<source>Last</source> <source>Last</source>
<translation>Poslední</translation> <translation>Poslední</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="420"/> <location filename="../src/GUI/gui.cpp" line="424"/>
<source>First</source> <source>First</source>
<translation>První</translation> <translation>První</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="442"/> <location filename="../src/GUI/gui.cpp" line="464"/>
<source>Map</source>
<translation>Mapa</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="450"/>
<source>Graph</source>
<translation>Graf</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="459"/>
<source>POI</source>
<translation>POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="460"/>
<source>POI files</source> <source>POI files</source>
<translation>POI soubory</translation> <translation>POI soubory</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="471"/> <location filename="../src/GUI/gui.cpp" line="476"/>
<source>Data</source>
<translation>Data</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="472"/>
<source>Display</source> <source>Display</source>
<translation>Zobrazit</translation> <translation>Zobrazit</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="480"/> <location filename="../src/GUI/gui.cpp" line="488"/>
<source>Settings</source>
<translation>Nastavení</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="484"/>
<source>Units</source> <source>Units</source>
<translation>Jednotky</translation> <translation>Jednotky</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="488"/> <location filename="../src/GUI/gui.cpp" line="492"/>
<source>Coordinates format</source> <source>Coordinates format</source>
<translation>Formát souřadnic</translation> <translation>Formát souřadnic</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="498"/> <location filename="../src/GUI/gui.cpp" line="619"/>
<source>Help</source>
<translation>Nápověda</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="615"/>
<source>Append file</source> <source>Append file</source>
<translation>Přidat soubor</translation> <translation>Přidat soubor</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="616"/> <location filename="../src/GUI/gui.cpp" line="620"/>
<source>Next/Previous</source> <source>Next/Previous</source>
<translation>Následující/Předchozí</translation> <translation>Následující/Předchozí</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="618"/> <location filename="../src/GUI/gui.cpp" line="622"/>
<source>Toggle graph type</source> <source>Toggle graph type</source>
<translation>Přepnout typ grafu</translation> <translation>Přepnout typ grafu</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="620"/> <location filename="../src/GUI/gui.cpp" line="624"/>
<source>Toggle time type</source> <source>Toggle time type</source>
<translation>Přepnout typ času</translation> <translation>Přepnout typ času</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="624"/> <location filename="../src/GUI/gui.cpp" line="628"/>
<source>Previous map</source> <source>Previous map</source>
<translation>Předchozí mapa</translation> <translation>Předchozí mapa</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="625"/> <location filename="../src/GUI/gui.cpp" line="629"/>
<source>Zoom in</source> <source>Zoom in</source>
<translation>Přiblížit</translation> <translation>Přiblížit</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="627"/> <location filename="../src/GUI/gui.cpp" line="631"/>
<source>Zoom out</source> <source>Zoom out</source>
<translation>Oddálit</translation> <translation>Oddálit</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="629"/> <location filename="../src/GUI/gui.cpp" line="633"/>
<source>Digital zoom</source> <source>Digital zoom</source>
<translation>Digitální zoom</translation> <translation>Digitální zoom</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="630"/> <location filename="../src/GUI/gui.cpp" line="634"/>
<source>Zoom</source> <source>Zoom</source>
<translation>Zoom</translation> <translation>Zoom</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1127"/> <location filename="../src/GUI/gui.cpp" line="1135"/>
<source>Open map file</source> <source>Open map file</source>
<translation>Otevřít mapový soubor</translation> <translation>Otevřít mapový soubor</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1165"/> <location filename="../src/GUI/gui.cpp" line="1175"/>
<source>No files loaded</source> <source>No files loaded</source>
<translation>Nejsou načteny žádné soubory</translation> <translation>Nejsou načteny žádné soubory</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="912"/> <location filename="../src/GUI/gui.cpp" line="920"/>
<location filename="../src/GUI/gui.cpp" line="915"/> <location filename="../src/GUI/gui.cpp" line="923"/>
<source>Date</source> <source>Date</source>
<translation>Datum</translation> <translation>Datum</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="643"/> <location filename="../src/GUI/gui.cpp" line="432"/>
<source>&amp;File</source>
<translation>&amp;Soubor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="446"/>
<source>&amp;Map</source>
<translation>&amp;Mapa</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="454"/>
<source>&amp;Graph</source>
<translation>&amp;Graf</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="463"/>
<source>&amp;POI</source>
<translation>&amp;POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="475"/>
<source>&amp;Data</source>
<translation>&amp;Data</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="484"/>
<source>&amp;Settings</source>
<translation>&amp;Nastavení</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="502"/>
<source>&amp;Help</source>
<translation>N&amp;ápověda</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="647"/>
<source>Map directory:</source> <source>Map directory:</source>
<translation>Adresář s mapami:</translation> <translation>Adresář s mapami:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="645"/> <location filename="../src/GUI/gui.cpp" line="649"/>
<source>POI directory:</source> <source>POI directory:</source>
<translation>Adresář s POI body:</translation> <translation>Adresář s POI body:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="647"/> <location filename="../src/GUI/gui.cpp" line="651"/>
<source>GCS file:</source> <source>GCS file:</source>
<translation>Soubor s GCS daty:</translation> <translation>Soubor s GCS daty:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="648"/> <location filename="../src/GUI/gui.cpp" line="652"/>
<source>PCS file:</source> <source>PCS file:</source>
<translation>Soubor s PCS daty:</translation> <translation>Soubor s PCS daty:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="650"/> <location filename="../src/GUI/gui.cpp" line="654"/>
<source>Ellipsoids file:</source> <source>Ellipsoids file:</source>
<translation>Soubor s daty elipsoidů:</translation> <translation>Soubor s daty elipsoidů:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="653"/> <location filename="../src/GUI/gui.cpp" line="657"/>
<source>User override directory:</source> <source>User override directory:</source>
<translation>Uživatelský adresář:</translation> <translation>Uživatelský adresář:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="904"/> <location filename="../src/GUI/gui.cpp" line="912"/>
<source>Routes</source> <source>Routes</source>
<translation>Trasy</translation> <translation>Trasy</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1154"/> <location filename="../src/GUI/gui.cpp" line="1164"/>
<source>Error loading map:</source> <source>Error loading map:</source>
<translation>Mapu nelze načíst:</translation> <translation>Mapu nelze načíst:</translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location filename="../src/GUI/gui.cpp" line="1169"/> <location filename="../src/GUI/gui.cpp" line="1179"/>
<source>%n files</source> <source>%n files</source>
<translation> <translation>
<numerusform>%n soubor</numerusform> <numerusform>%n soubor</numerusform>
@ -679,97 +683,97 @@
</translation> </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="609"/> <location filename="../src/GUI/gui.cpp" line="613"/>
<source>Next file</source> <source>Next file</source>
<translation>Následující soubor</translation> <translation>Následující soubor</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="585"/> <location filename="../src/GUI/gui.cpp" line="589"/>
<source>Version </source> <source>Version </source>
<translation>Verze </translation> <translation>Verze </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="218"/> <location filename="../src/GUI/gui.cpp" line="222"/>
<source>Print...</source> <source>Print...</source>
<translation>Tisknout...</translation> <translation>Tisknout...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="223"/> <location filename="../src/GUI/gui.cpp" line="227"/>
<source>Export to PDF...</source> <source>Export to PDF...</source>
<translation>Exportovat do PDF...</translation> <translation>Exportovat do PDF...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="906"/> <location filename="../src/GUI/gui.cpp" line="914"/>
<source>Waypoints</source> <source>Waypoints</source>
<translation>Navigační body</translation> <translation>Navigační body</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="610"/> <location filename="../src/GUI/gui.cpp" line="614"/>
<source>Previous file</source> <source>Previous file</source>
<translation>Předchozí soubor</translation> <translation>Předchozí soubor</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="310"/> <location filename="../src/GUI/gui.cpp" line="314"/>
<source>Route waypoints</source> <source>Route waypoints</source>
<translation>Body tras</translation> <translation>Body tras</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="612"/> <location filename="../src/GUI/gui.cpp" line="616"/>
<source>First file</source> <source>First file</source>
<translation>První soubor</translation> <translation>První soubor</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="614"/> <location filename="../src/GUI/gui.cpp" line="618"/>
<source>Last file</source> <source>Last file</source>
<translation>Poslední soubor</translation> <translation>Poslední soubor</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="740"/> <location filename="../src/GUI/gui.cpp" line="746"/>
<source>Error loading data file:</source> <source>Error loading data file:</source>
<translation>Datový soubor nelze načíst:</translation> <translation>Datový soubor nelze načíst:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="743"/> <location filename="../src/GUI/gui.cpp" line="749"/>
<location filename="../src/GUI/gui.cpp" line="768"/> <location filename="../src/GUI/gui.cpp" line="776"/>
<source>Line: %1</source> <source>Line: %1</source>
<translation>Řádka: %1</translation> <translation>Řádka: %1</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="765"/> <location filename="../src/GUI/gui.cpp" line="773"/>
<source>Error loading POI file:</source> <source>Error loading POI file:</source>
<translation>Soubor POI nelze načíst:</translation> <translation>Soubor POI nelze načíst:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="898"/> <location filename="../src/GUI/gui.cpp" line="906"/>
<source>Name</source> <source>Name</source>
<translation>Název</translation> <translation>Název</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="902"/> <location filename="../src/GUI/gui.cpp" line="910"/>
<source>Tracks</source> <source>Tracks</source>
<translation>Cesty</translation> <translation>Cesty</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="207"/> <location filename="../src/GUI/gui.cpp" line="211"/>
<location filename="../src/GUI/gui.cpp" line="584"/> <location filename="../src/GUI/gui.cpp" line="588"/>
<source>About GPXSee</source> <source>About GPXSee</source>
<translation>O aplikaci GPXSee</translation> <translation>O aplikaci GPXSee</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="522"/> <location filename="../src/GUI/gui.cpp" line="526"/>
<source>Navigation</source> <source>Navigation</source>
<translation>Navigace</translation> <translation>Navigace</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="325"/> <location filename="../src/GUI/gui.cpp" line="329"/>
<location filename="../src/GUI/gui.cpp" line="922"/> <location filename="../src/GUI/gui.cpp" line="930"/>
<source>Distance</source> <source>Distance</source>
<translation>Vzdálenost</translation> <translation>Vzdálenost</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="331"/> <location filename="../src/GUI/gui.cpp" line="335"/>
<location filename="../src/GUI/gui.cpp" line="481"/> <location filename="../src/GUI/gui.cpp" line="485"/>
<location filename="../src/GUI/gui.cpp" line="924"/> <location filename="../src/GUI/gui.cpp" line="932"/>
<source>Time</source> <source>Time</source>
<translation>Čas</translation> <translation>Čas</translation>
</message> </message>
@ -875,27 +879,27 @@
<context> <context>
<name>MapList</name> <name>MapList</name>
<message> <message>
<location filename="../src/map/maplist.cpp" line="131"/> <location filename="../src/map/maplist.cpp" line="130"/>
<source>Supported files</source> <source>Supported files</source>
<translation>Podporované soubory</translation> <translation>Podporované soubory</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="132"/> <location filename="../src/map/maplist.cpp" line="131"/>
<source>OziExplorer maps</source> <source>OziExplorer maps</source>
<translation>OziExplorer mapy</translation> <translation>OziExplorer mapy</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="133"/> <location filename="../src/map/maplist.cpp" line="132"/>
<source>TrekBuddy maps/atlases</source> <source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy mapy/atlasy</translation> <translation>TrekBuddy mapy/atlasy</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="134"/> <location filename="../src/map/maplist.cpp" line="133"/>
<source>GeoTIFF images</source> <source>GeoTIFF images</source>
<translation>GeoTIFF obrázky</translation> <translation>GeoTIFF obrázky</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="135"/> <location filename="../src/map/maplist.cpp" line="134"/>
<source>Online map sources</source> <source>Online map sources</source>
<translation>Online mapové zdroje</translation> <translation>Online mapové zdroje</translation>
</message> </message>
@ -1380,33 +1384,53 @@
<context> <context>
<name>SpeedGraph</name> <name>SpeedGraph</name>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="14"/> <location filename="../src/GUI/speedgraph.cpp" line="16"/>
<location filename="../src/GUI/speedgraph.h" line="14"/> <location filename="../src/GUI/speedgraph.h" line="14"/>
<source>Speed</source> <source>Speed</source>
<translation>Rychlost</translation> <translation>Rychlost</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="89"/> <location filename="../src/GUI/speedgraph.cpp" line="96"/>
<source>km/h</source> <source>km/h</source>
<translation>km/h</translation> <translation>km/h</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="22"/> <location filename="../src/GUI/speedgraph.cpp" line="28"/>
<source>Average</source> <source>Average</source>
<translation>Průměr</translation> <translation>Průměr</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="24"/> <location filename="../src/GUI/speedgraph.cpp" line="25"/>
<source>min/km</source>
<translation>min/km</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="26"/>
<source>min/mi</source>
<translation>min/mi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="26"/>
<source>min/nmi</source>
<translation>min/nmi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="30"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Maximum</translation> <translation>Maximum</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="83"/> <location filename="../src/GUI/speedgraph.cpp" line="32"/>
<source>Pace</source>
<translation>Tempo</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="90"/>
<source>kn</source> <source>kn</source>
<translation>kn</translation> <translation>kn</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="86"/> <location filename="../src/GUI/speedgraph.cpp" line="93"/>
<source>mi/h</source> <source>mi/h</source>
<translation>mi/h</translation> <translation>mi/h</translation>
</message> </message>
@ -1414,30 +1438,50 @@
<context> <context>
<name>SpeedGraphItem</name> <name>SpeedGraphItem</name>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="22"/> <location filename="../src/GUI/speedgraphitem.cpp" line="23"/>
<source>km/h</source> <source>km/h</source>
<translation>km/h</translation> <translation>km/h</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="21"/> <location filename="../src/GUI/speedgraphitem.cpp" line="22"/>
<source>mi/h</source> <source>mi/h</source>
<translation>mi/h</translation> <translation>mi/h</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="22"/> <location filename="../src/GUI/speedgraphitem.cpp" line="23"/>
<source>kn</source> <source>kn</source>
<translation>kn</translation> <translation>kn</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="24"/> <location filename="../src/GUI/speedgraphitem.cpp" line="26"/>
<source>min/km</source>
<translation>min/km</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="27"/>
<source>min/mi</source>
<translation>min/mi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="27"/>
<source>min/nmi</source>
<translation>min/nmi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="29"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Maximum</translation> <translation>Maximum</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="26"/> <location filename="../src/GUI/speedgraphitem.cpp" line="31"/>
<source>Average</source> <source>Average</source>
<translation>Průměr</translation> <translation>Průměr</translation>
</message> </message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="33"/>
<source>Pace</source>
<translation>Tempo</translation>
</message>
</context> </context>
<context> <context>
<name>TemperatureGraph</name> <name>TemperatureGraph</name>

View File

@ -284,7 +284,7 @@
<message> <message>
<location filename="../src/GUI/format.cpp" line="62"/> <location filename="../src/GUI/format.cpp" line="62"/>
<source>nmi</source> <source>nmi</source>
<translation type="unfinished"></translation> <translation>nmi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/format.cpp" line="66"/> <location filename="../src/GUI/format.cpp" line="66"/>
@ -301,365 +301,334 @@
<context> <context>
<name>GUI</name> <name>GUI</name>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="588"/> <location filename="../src/GUI/gui.cpp" line="592"/>
<source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source> <source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source>
<translation>GPXSee wird unter der GNU General Public License version 3 vertrieben. Mehr Informationen zu GPXSee auf der Homepage </translation> <translation>GPXSee wird unter der GNU General Public License version 3 vertrieben. Mehr Informationen zu GPXSee auf der Homepage </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="643"/> <location filename="../src/GUI/gui.cpp" line="647"/>
<source>Map directory:</source> <source>Map directory:</source>
<translation>Kartenverzeichnis:</translation> <translation>Kartenverzeichnis:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="645"/> <location filename="../src/GUI/gui.cpp" line="649"/>
<source>POI directory:</source> <source>POI directory:</source>
<translation>POI-Verzeichnis:</translation> <translation>POI-Verzeichnis:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="647"/> <location filename="../src/GUI/gui.cpp" line="651"/>
<source>GCS file:</source> <source>GCS file:</source>
<translation>GCS-Datei:</translation> <translation>GCS-Datei:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="648"/> <location filename="../src/GUI/gui.cpp" line="652"/>
<source>PCS file:</source> <source>PCS file:</source>
<translation>PCS-Datei:</translation> <translation>PCS-Datei:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="650"/> <location filename="../src/GUI/gui.cpp" line="654"/>
<source>Ellipsoids file:</source> <source>Ellipsoids file:</source>
<translation>Ellipsoidendatei:</translation> <translation>Ellipsoidendatei:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="653"/> <location filename="../src/GUI/gui.cpp" line="657"/>
<source>User override directory:</source> <source>User override directory:</source>
<translation>Benutzerverzeichnis:</translation> <translation>Benutzerverzeichnis:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="662"/> <location filename="../src/GUI/gui.cpp" line="666"/>
<source>Open file</source> <source>Open file</source>
<translation>Datei öffnen</translation> <translation>Datei öffnen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="751"/> <location filename="../src/GUI/gui.cpp" line="757"/>
<source>Open POI file</source> <source>Open POI file</source>
<translation>POI Datei öffnen</translation> <translation>POI Datei öffnen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="195"/> <location filename="../src/GUI/gui.cpp" line="199"/>
<source>Quit</source> <source>Quit</source>
<translation>Beenden</translation> <translation>Beenden</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="204"/> <location filename="../src/GUI/gui.cpp" line="208"/>
<location filename="../src/GUI/gui.cpp" line="605"/> <location filename="../src/GUI/gui.cpp" line="609"/>
<location filename="../src/GUI/gui.cpp" line="606"/> <location filename="../src/GUI/gui.cpp" line="610"/>
<source>Keyboard controls</source> <source>Keyboard controls</source>
<translation>Tastaturkürzel</translation> <translation>Tastaturkürzel</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="229"/> <location filename="../src/GUI/gui.cpp" line="233"/>
<source>Close</source> <source>Close</source>
<translation>Schließen</translation> <translation>Schließen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="235"/> <location filename="../src/GUI/gui.cpp" line="239"/>
<source>Reload</source> <source>Reload</source>
<translation>Neu Laden</translation> <translation>Neu Laden</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="517"/> <location filename="../src/GUI/gui.cpp" line="521"/>
<source>Show</source> <source>Show</source>
<translation>Ansicht</translation> <translation>Ansicht</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="428"/> <location filename="../src/GUI/gui.cpp" line="515"/>
<location filename="../src/GUI/gui.cpp" line="511"/>
<source>File</source> <source>File</source>
<translation>Datei</translation> <translation>Datei</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="246"/> <location filename="../src/GUI/gui.cpp" line="250"/>
<source>Close POI files</source> <source>Close POI files</source>
<translation>POI-Datei schließen</translation> <translation>POI-Datei schließen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="248"/> <location filename="../src/GUI/gui.cpp" line="252"/>
<source>Overlap POIs</source> <source>Overlap POIs</source>
<translation>POI überlappen</translation> <translation>POI überlappen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="252"/> <location filename="../src/GUI/gui.cpp" line="256"/>
<source>Show POI labels</source> <source>Show POI labels</source>
<translation>POI-Labels anzeigen</translation> <translation>POI-Labels anzeigen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="257"/> <location filename="../src/GUI/gui.cpp" line="261"/>
<source>Show POIs</source> <source>Show POIs</source>
<translation>POIs anzeigen</translation> <translation>POIs anzeigen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="266"/> <location filename="../src/GUI/gui.cpp" line="270"/>
<source>Show map</source> <source>Show map</source>
<translation>Karte anzeigen</translation> <translation>Karte anzeigen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="276"/> <location filename="../src/GUI/gui.cpp" line="280"/>
<source>Clear tile cache</source> <source>Clear tile cache</source>
<translation>Tile-Cache bereinigen</translation> <translation>Tile-Cache bereinigen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="213"/> <location filename="../src/GUI/gui.cpp" line="217"/>
<source>Open...</source> <source>Open...</source>
<translation>Öffnen...</translation> <translation>Öffnen...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="202"/> <location filename="../src/GUI/gui.cpp" line="206"/>
<location filename="../src/GUI/gui.cpp" line="639"/> <location filename="../src/GUI/gui.cpp" line="643"/>
<location filename="../src/GUI/gui.cpp" line="640"/> <location filename="../src/GUI/gui.cpp" line="644"/>
<source>Paths</source> <source>Paths</source>
<translation>Pfade</translation> <translation>Pfade</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="243"/> <location filename="../src/GUI/gui.cpp" line="247"/>
<source>Load POI file...</source> <source>Load POI file...</source>
<translation>POI-Datei laden...</translation> <translation>POI-Datei laden...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="274"/> <location filename="../src/GUI/gui.cpp" line="278"/>
<source>Load map...</source> <source>Load map...</source>
<translation>Karte laden...</translation> <translation>Karte laden...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="280"/>
<location filename="../src/GUI/gui.cpp" line="284"/> <location filename="../src/GUI/gui.cpp" line="284"/>
<location filename="../src/GUI/gui.cpp" line="622"/> <location filename="../src/GUI/gui.cpp" line="288"/>
<location filename="../src/GUI/gui.cpp" line="626"/>
<source>Next map</source> <source>Next map</source>
<translation>Nächste Karte</translation> <translation>Nächste Karte</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="294"/> <location filename="../src/GUI/gui.cpp" line="298"/>
<source>Show tracks</source> <source>Show tracks</source>
<translation>Strecken anzeigen</translation> <translation>Strecken anzeigen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="298"/> <location filename="../src/GUI/gui.cpp" line="302"/>
<source>Show routes</source> <source>Show routes</source>
<translation>Routen anzeigen</translation> <translation>Routen anzeigen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="302"/> <location filename="../src/GUI/gui.cpp" line="306"/>
<source>Show waypoints</source> <source>Show waypoints</source>
<translation>Wegpunkte anzeigen</translation> <translation>Wegpunkte anzeigen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="306"/> <location filename="../src/GUI/gui.cpp" line="310"/>
<source>Waypoint labels</source> <source>Waypoint labels</source>
<translation>Wegpunkt Labels</translation> <translation>Wegpunkt Labels</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="317"/> <location filename="../src/GUI/gui.cpp" line="321"/>
<source>Show graphs</source> <source>Show graphs</source>
<translation>Graphen anzeigen</translation> <translation>Graphen anzeigen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="337"/> <location filename="../src/GUI/gui.cpp" line="341"/>
<source>Show grid</source> <source>Show grid</source>
<translation>Gitter anzeigen</translation> <translation>Gitter anzeigen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="341"/> <location filename="../src/GUI/gui.cpp" line="345"/>
<source>Show slider info</source> <source>Show slider info</source>
<translation>Schieberinfo anzeigen</translation> <translation>Schieberinfo anzeigen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="347"/> <location filename="../src/GUI/gui.cpp" line="351"/>
<source>Show toolbars</source> <source>Show toolbars</source>
<translation>Toolbars anzeigen</translation> <translation>Toolbars anzeigen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="353"/> <location filename="../src/GUI/gui.cpp" line="357"/>
<source>Total time</source> <source>Total time</source>
<translation>Gesamtzeit</translation> <translation>Gesamtzeit</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="358"/> <location filename="../src/GUI/gui.cpp" line="362"/>
<location filename="../src/GUI/gui.cpp" line="926"/> <location filename="../src/GUI/gui.cpp" line="934"/>
<source>Moving time</source> <source>Moving time</source>
<translation>Bewegungszeit</translation> <translation>Bewegungszeit</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="365"/> <location filename="../src/GUI/gui.cpp" line="369"/>
<source>Metric</source> <source>Metric</source>
<translation>Metrisch</translation> <translation>Metrisch</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="370"/> <location filename="../src/GUI/gui.cpp" line="374"/>
<source>Imperial</source> <source>Imperial</source>
<translation>Imperial</translation> <translation>Imperial</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="375"/> <location filename="../src/GUI/gui.cpp" line="379"/>
<source>Nautical</source> <source>Nautical</source>
<translation type="unfinished"></translation> <translation>Nautisch</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="382"/> <location filename="../src/GUI/gui.cpp" line="386"/>
<source>Decimal degrees (DD)</source> <source>Decimal degrees (DD)</source>
<translation type="unfinished"></translation> <translation>Dezimalgrad (DD)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="387"/> <location filename="../src/GUI/gui.cpp" line="391"/>
<source>Degrees and decimal minutes (DMM)</source> <source>Degrees and decimal minutes (DMM)</source>
<translation type="unfinished"></translation> <translation>Grad und Dezimalminuten (DMM)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="393"/> <location filename="../src/GUI/gui.cpp" line="397"/>
<source>Degrees, minutes, seconds (DMS)</source> <source>Degrees, minutes, seconds (DMS)</source>
<translation type="unfinished"></translation> <translation>Grad, Minuten, Sekunden (DMS)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="398"/> <location filename="../src/GUI/gui.cpp" line="402"/>
<source>Fullscreen mode</source> <source>Fullscreen mode</source>
<translation>Vollbildmodus</translation> <translation>Vollbildmodus</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="404"/> <location filename="../src/GUI/gui.cpp" line="408"/>
<source>Options...</source> <source>Options...</source>
<translation>Einstellungen...</translation> <translation>Einstellungen...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="410"/> <location filename="../src/GUI/gui.cpp" line="414"/>
<source>Next</source> <source>Next</source>
<translation>Nächste</translation> <translation>Nächste</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="413"/> <location filename="../src/GUI/gui.cpp" line="417"/>
<source>Previous</source> <source>Previous</source>
<translation>Vorherige</translation> <translation>Vorherige</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="417"/> <location filename="../src/GUI/gui.cpp" line="421"/>
<source>Last</source> <source>Last</source>
<translation>Letzte</translation> <translation>Letzte</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="420"/> <location filename="../src/GUI/gui.cpp" line="424"/>
<source>First</source> <source>First</source>
<translation>Erste</translation> <translation>Erste</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="442"/> <location filename="../src/GUI/gui.cpp" line="464"/>
<source>Map</source>
<translation>Karte</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="450"/>
<source>Graph</source>
<translation>Graph</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="459"/>
<source>POI</source>
<translation>POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="460"/>
<source>POI files</source> <source>POI files</source>
<translation>POI-Dateien</translation> <translation>POI-Dateien</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="471"/> <location filename="../src/GUI/gui.cpp" line="476"/>
<source>Data</source>
<translation>Daten</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="472"/>
<source>Display</source> <source>Display</source>
<translation>Anzeige</translation> <translation>Anzeige</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="480"/> <location filename="../src/GUI/gui.cpp" line="488"/>
<source>Settings</source>
<translation>Einstellungen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="484"/>
<source>Units</source> <source>Units</source>
<translation>Einheiten</translation> <translation>Einheiten</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="488"/> <location filename="../src/GUI/gui.cpp" line="492"/>
<source>Coordinates format</source> <source>Coordinates format</source>
<translation type="unfinished"></translation> <translation>Koordinatenformate</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="498"/> <location filename="../src/GUI/gui.cpp" line="619"/>
<source>Help</source>
<translation>Hilfe</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="615"/>
<source>Append file</source> <source>Append file</source>
<translation>An Datei anhängen</translation> <translation>An Datei anhängen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="616"/> <location filename="../src/GUI/gui.cpp" line="620"/>
<source>Next/Previous</source> <source>Next/Previous</source>
<translation>Nächste/Vorherige</translation> <translation>Nächste/Vorherige</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="618"/> <location filename="../src/GUI/gui.cpp" line="622"/>
<source>Toggle graph type</source> <source>Toggle graph type</source>
<translation>Graphtyp umschalten</translation> <translation>Graphtyp umschalten</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="620"/> <location filename="../src/GUI/gui.cpp" line="624"/>
<source>Toggle time type</source> <source>Toggle time type</source>
<translation>Zeittyp umschalten</translation> <translation>Zeittyp umschalten</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="624"/> <location filename="../src/GUI/gui.cpp" line="628"/>
<source>Previous map</source> <source>Previous map</source>
<translation>Vorherige Karte</translation> <translation>Vorherige Karte</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="625"/> <location filename="../src/GUI/gui.cpp" line="629"/>
<source>Zoom in</source> <source>Zoom in</source>
<translation>Hineinzoomen</translation> <translation>Hineinzoomen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="627"/> <location filename="../src/GUI/gui.cpp" line="631"/>
<source>Zoom out</source> <source>Zoom out</source>
<translation>Herauszoomen</translation> <translation>Herauszoomen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="629"/> <location filename="../src/GUI/gui.cpp" line="633"/>
<source>Digital zoom</source> <source>Digital zoom</source>
<translation>Digitaler Zoom</translation> <translation>Digitaler Zoom</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="630"/> <location filename="../src/GUI/gui.cpp" line="634"/>
<source>Zoom</source> <source>Zoom</source>
<translation>Zoom</translation> <translation>Zoom</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1127"/> <location filename="../src/GUI/gui.cpp" line="1135"/>
<source>Open map file</source> <source>Open map file</source>
<translation>Karte Datei öffnen</translation> <translation>Karte Datei öffnen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1154"/> <location filename="../src/GUI/gui.cpp" line="1164"/>
<source>Error loading map:</source> <source>Error loading map:</source>
<translation>Fehler beim Laden der Karte-Datei:</translation> <translation>Fehler beim Laden der Karte-Datei:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1165"/> <location filename="../src/GUI/gui.cpp" line="1175"/>
<source>No files loaded</source> <source>No files loaded</source>
<translation>Keine Dateien geladen</translation> <translation>Keine Dateien geladen</translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location filename="../src/GUI/gui.cpp" line="1169"/> <location filename="../src/GUI/gui.cpp" line="1179"/>
<source>%n files</source> <source>%n files</source>
<translation> <translation>
<numerusform>%n Datei</numerusform> <numerusform>%n Datei</numerusform>
@ -667,108 +636,143 @@
</translation> </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="912"/> <location filename="../src/GUI/gui.cpp" line="920"/>
<location filename="../src/GUI/gui.cpp" line="915"/> <location filename="../src/GUI/gui.cpp" line="923"/>
<source>Date</source> <source>Date</source>
<translation>Datum</translation> <translation>Datum</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="904"/> <location filename="../src/GUI/gui.cpp" line="912"/>
<source>Routes</source> <source>Routes</source>
<translation>Routen</translation> <translation>Routen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="609"/> <location filename="../src/GUI/gui.cpp" line="613"/>
<source>Next file</source> <source>Next file</source>
<translation>Nächste Datei</translation> <translation>Nächste Datei</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="585"/> <location filename="../src/GUI/gui.cpp" line="589"/>
<source>Version </source> <source>Version </source>
<translation>Version </translation> <translation>Version </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="218"/> <location filename="../src/GUI/gui.cpp" line="222"/>
<source>Print...</source> <source>Print...</source>
<translation>Drucken...</translation> <translation>Drucken...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="223"/> <location filename="../src/GUI/gui.cpp" line="227"/>
<source>Export to PDF...</source> <source>Export to PDF...</source>
<translation>Als PDF exportieren...</translation> <translation>Als PDF exportieren...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="906"/> <location filename="../src/GUI/gui.cpp" line="914"/>
<source>Waypoints</source> <source>Waypoints</source>
<translation>Wegpunkte</translation> <translation>Wegpunkte</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="610"/> <location filename="../src/GUI/gui.cpp" line="614"/>
<source>Previous file</source> <source>Previous file</source>
<translation>Vorherige Datei</translation> <translation>Vorherige Datei</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="310"/> <location filename="../src/GUI/gui.cpp" line="314"/>
<source>Route waypoints</source> <source>Route waypoints</source>
<translation>Routen Wegpunkte</translation> <translation>Routen Wegpunkte</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="612"/> <location filename="../src/GUI/gui.cpp" line="432"/>
<source>&amp;File</source>
<translation>&amp;Datei</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="446"/>
<source>&amp;Map</source>
<translation>&amp;Map</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="454"/>
<source>&amp;Graph</source>
<translation>&amp;Graph</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="463"/>
<source>&amp;POI</source>
<translation>&amp;POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="475"/>
<source>&amp;Data</source>
<translation>D&amp;ata</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="484"/>
<source>&amp;Settings</source>
<translation>&amp;Einstellungen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="502"/>
<source>&amp;Help</source>
<translation>&amp;Hilfe</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="616"/>
<source>First file</source> <source>First file</source>
<translation>Erste Datei</translation> <translation>Erste Datei</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="614"/> <location filename="../src/GUI/gui.cpp" line="618"/>
<source>Last file</source> <source>Last file</source>
<translation>Letzte Datei</translation> <translation>Letzte Datei</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="740"/> <location filename="../src/GUI/gui.cpp" line="746"/>
<source>Error loading data file:</source> <source>Error loading data file:</source>
<translation>Fehler beim Laden der Datei:</translation> <translation>Fehler beim Laden der Datei:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="743"/> <location filename="../src/GUI/gui.cpp" line="749"/>
<location filename="../src/GUI/gui.cpp" line="768"/> <location filename="../src/GUI/gui.cpp" line="776"/>
<source>Line: %1</source> <source>Line: %1</source>
<translation>Linie: %1</translation> <translation>Linie: %1</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="765"/> <location filename="../src/GUI/gui.cpp" line="773"/>
<source>Error loading POI file:</source> <source>Error loading POI file:</source>
<translation>Fehler beim Laden der POI-Datei:</translation> <translation>Fehler beim Laden der POI-Datei:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="898"/> <location filename="../src/GUI/gui.cpp" line="906"/>
<source>Name</source> <source>Name</source>
<translation>Name</translation> <translation>Name</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="902"/> <location filename="../src/GUI/gui.cpp" line="910"/>
<source>Tracks</source> <source>Tracks</source>
<translation>Strecken</translation> <translation>Strecken</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="207"/> <location filename="../src/GUI/gui.cpp" line="211"/>
<location filename="../src/GUI/gui.cpp" line="584"/> <location filename="../src/GUI/gui.cpp" line="588"/>
<source>About GPXSee</source> <source>About GPXSee</source>
<translation>Über GPXSee</translation> <translation>Über GPXSee</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="522"/> <location filename="../src/GUI/gui.cpp" line="526"/>
<source>Navigation</source> <source>Navigation</source>
<translation>Navigation</translation> <translation>Navigation</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="325"/> <location filename="../src/GUI/gui.cpp" line="329"/>
<location filename="../src/GUI/gui.cpp" line="922"/> <location filename="../src/GUI/gui.cpp" line="930"/>
<source>Distance</source> <source>Distance</source>
<translation>Distanz</translation> <translation>Distanz</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="331"/> <location filename="../src/GUI/gui.cpp" line="335"/>
<location filename="../src/GUI/gui.cpp" line="481"/> <location filename="../src/GUI/gui.cpp" line="485"/>
<location filename="../src/GUI/gui.cpp" line="924"/> <location filename="../src/GUI/gui.cpp" line="932"/>
<source>Time</source> <source>Time</source>
<translation>Zeit</translation> <translation>Zeit</translation>
</message> </message>
@ -799,7 +803,7 @@
<message> <message>
<location filename="../src/GUI/graphview.cpp" line="120"/> <location filename="../src/GUI/graphview.cpp" line="120"/>
<source>nmi</source> <source>nmi</source>
<translation type="unfinished"></translation> <translation>nmi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/graphview.cpp" line="134"/> <location filename="../src/GUI/graphview.cpp" line="134"/>
@ -874,27 +878,27 @@
<context> <context>
<name>MapList</name> <name>MapList</name>
<message> <message>
<location filename="../src/map/maplist.cpp" line="131"/> <location filename="../src/map/maplist.cpp" line="130"/>
<source>Supported files</source> <source>Supported files</source>
<translation>Unterstütze Dateien</translation> <translation>Unterstütze Dateien</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="132"/> <location filename="../src/map/maplist.cpp" line="131"/>
<source>OziExplorer maps</source> <source>OziExplorer maps</source>
<translation>OziExplorer Karten</translation> <translation>OziExplorer Karten</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="133"/> <location filename="../src/map/maplist.cpp" line="132"/>
<source>TrekBuddy maps/atlases</source> <source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy Karten/Atlanten</translation> <translation>TrekBuddy Karten/Atlanten</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="134"/> <location filename="../src/map/maplist.cpp" line="133"/>
<source>GeoTIFF images</source> <source>GeoTIFF images</source>
<translation>GeoTIFF Bilder</translation> <translation>GeoTIFF Bilder</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="135"/> <location filename="../src/map/maplist.cpp" line="134"/>
<source>Online map sources</source> <source>Online map sources</source>
<translation>Online-Kartenquellen</translation> <translation>Online-Kartenquellen</translation>
</message> </message>
@ -1121,7 +1125,7 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="296"/> <location filename="../src/GUI/optionsdialog.cpp" line="296"/>
<source>kn</source> <source>kn</source>
<translation type="unfinished"></translation> <translation>kn</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="299"/> <location filename="../src/GUI/optionsdialog.cpp" line="299"/>
@ -1161,7 +1165,7 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="331"/> <location filename="../src/GUI/optionsdialog.cpp" line="331"/>
<source>nmi</source> <source>nmi</source>
<translation type="unfinished"></translation> <translation>nmi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="334"/> <location filename="../src/GUI/optionsdialog.cpp" line="334"/>
@ -1363,7 +1367,7 @@
<message> <message>
<location filename="../src/GUI/scaleitem.cpp" line="86"/> <location filename="../src/GUI/scaleitem.cpp" line="86"/>
<source>nmi</source> <source>nmi</source>
<translation type="unfinished"></translation> <translation>nmi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/scaleitem.cpp" line="89"/> <location filename="../src/GUI/scaleitem.cpp" line="89"/>
@ -1379,33 +1383,53 @@
<context> <context>
<name>SpeedGraph</name> <name>SpeedGraph</name>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="14"/> <location filename="../src/GUI/speedgraph.cpp" line="16"/>
<location filename="../src/GUI/speedgraph.h" line="14"/> <location filename="../src/GUI/speedgraph.h" line="14"/>
<source>Speed</source> <source>Speed</source>
<translation>Geschwindigkeit</translation> <translation>Geschwindigkeit</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="89"/> <location filename="../src/GUI/speedgraph.cpp" line="96"/>
<source>km/h</source> <source>km/h</source>
<translation>km/h</translation> <translation>km/h</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="22"/> <location filename="../src/GUI/speedgraph.cpp" line="28"/>
<source>Average</source> <source>Average</source>
<translation>Durchschnitt</translation> <translation>Durchschnitt</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="24"/> <location filename="../src/GUI/speedgraph.cpp" line="25"/>
<source>min/km</source>
<translation>min/km</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="26"/>
<source>min/mi</source>
<translation>min/mi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="26"/>
<source>min/nmi</source>
<translation>min/nmi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="30"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Maximum</translation> <translation>Maximum</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="83"/> <location filename="../src/GUI/speedgraph.cpp" line="32"/>
<source>kn</source> <source>Pace</source>
<translation type="unfinished"></translation> <translation>Tempo</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="86"/> <location filename="../src/GUI/speedgraph.cpp" line="90"/>
<source>kn</source>
<translation>kn</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="93"/>
<source>mi/h</source> <source>mi/h</source>
<translation>mi/h</translation> <translation>mi/h</translation>
</message> </message>
@ -1413,30 +1437,50 @@
<context> <context>
<name>SpeedGraphItem</name> <name>SpeedGraphItem</name>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="22"/> <location filename="../src/GUI/speedgraphitem.cpp" line="23"/>
<source>km/h</source> <source>km/h</source>
<translation>km/h</translation> <translation>km/h</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="21"/> <location filename="../src/GUI/speedgraphitem.cpp" line="22"/>
<source>mi/h</source> <source>mi/h</source>
<translation>mi/h</translation> <translation>mi/h</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="22"/> <location filename="../src/GUI/speedgraphitem.cpp" line="23"/>
<source>kn</source> <source>kn</source>
<translation type="unfinished"></translation> <translation>kn</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="24"/> <location filename="../src/GUI/speedgraphitem.cpp" line="26"/>
<source>min/km</source>
<translation>min/km</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="27"/>
<source>min/mi</source>
<translation>min/mi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="27"/>
<source>min/nmi</source>
<translation>min/nmi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="29"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Maximum</translation> <translation>Maximum</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="26"/> <location filename="../src/GUI/speedgraphitem.cpp" line="31"/>
<source>Average</source> <source>Average</source>
<translation>Durchschnitt</translation> <translation>Durchschnitt</translation>
</message> </message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="33"/>
<source>Pace</source>
<translation>Tempo</translation>
</message>
</context> </context>
<context> <context>
<name>TemperatureGraph</name> <name>TemperatureGraph</name>

View File

@ -301,376 +301,380 @@
<context> <context>
<name>GUI</name> <name>GUI</name>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="588"/> <location filename="../src/GUI/gui.cpp" line="592"/>
<source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source> <source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source>
<translation>GPXSee levitetään GNU yleisen lisenssin version 3 alaisena. Voit katsoa lisätietoja GPXSee:stä projektin kotisivulla </translation> <translation>GPXSee levitetään GNU yleisen lisenssin version 3 alaisena. Voit katsoa lisätietoja GPXSee:stä projektin kotisivulla </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="662"/> <location filename="../src/GUI/gui.cpp" line="666"/>
<source>Open file</source> <source>Open file</source>
<translation>Avaa tiedosto</translation> <translation>Avaa tiedosto</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="751"/> <location filename="../src/GUI/gui.cpp" line="757"/>
<source>Open POI file</source> <source>Open POI file</source>
<translation>Avaa POI-tiedosto</translation> <translation>Avaa POI-tiedosto</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="195"/> <location filename="../src/GUI/gui.cpp" line="199"/>
<source>Quit</source> <source>Quit</source>
<translation>Lopeta</translation> <translation>Lopeta</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="204"/> <location filename="../src/GUI/gui.cpp" line="208"/>
<location filename="../src/GUI/gui.cpp" line="605"/> <location filename="../src/GUI/gui.cpp" line="609"/>
<location filename="../src/GUI/gui.cpp" line="606"/> <location filename="../src/GUI/gui.cpp" line="610"/>
<source>Keyboard controls</source> <source>Keyboard controls</source>
<translation>Näppäimistön säätimet</translation> <translation>Näppäimistön säätimet</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="229"/> <location filename="../src/GUI/gui.cpp" line="233"/>
<source>Close</source> <source>Close</source>
<translation>Sulje</translation> <translation>Sulje</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="235"/> <location filename="../src/GUI/gui.cpp" line="239"/>
<source>Reload</source> <source>Reload</source>
<translation>Lataa uudelleen</translation> <translation>Lataa uudelleen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="517"/> <location filename="../src/GUI/gui.cpp" line="521"/>
<source>Show</source> <source>Show</source>
<translation>Näytä</translation> <translation>Näytä</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="428"/> <location filename="../src/GUI/gui.cpp" line="515"/>
<location filename="../src/GUI/gui.cpp" line="511"/>
<source>File</source> <source>File</source>
<translation>Tiedosto</translation> <translation>Tiedosto</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="246"/> <location filename="../src/GUI/gui.cpp" line="250"/>
<source>Close POI files</source> <source>Close POI files</source>
<translation>Sulje POI-tiedostot</translation> <translation>Sulje POI-tiedostot</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="248"/> <location filename="../src/GUI/gui.cpp" line="252"/>
<source>Overlap POIs</source> <source>Overlap POIs</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="252"/> <location filename="../src/GUI/gui.cpp" line="256"/>
<source>Show POI labels</source> <source>Show POI labels</source>
<translation>Näytä POI:n nimiöt</translation> <translation>Näytä POI:n nimiöt</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="257"/> <location filename="../src/GUI/gui.cpp" line="261"/>
<source>Show POIs</source> <source>Show POIs</source>
<translation>Näytä POI:t</translation> <translation>Näytä POI:t</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="266"/> <location filename="../src/GUI/gui.cpp" line="270"/>
<source>Show map</source> <source>Show map</source>
<translation>Näytä kartta</translation> <translation>Näytä kartta</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="276"/> <location filename="../src/GUI/gui.cpp" line="280"/>
<source>Clear tile cache</source> <source>Clear tile cache</source>
<translation>Tyhjennä välimuisti</translation> <translation>Tyhjennä välimuisti</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="213"/> <location filename="../src/GUI/gui.cpp" line="217"/>
<source>Open...</source> <source>Open...</source>
<translation>Avaa...</translation> <translation>Avaa...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="202"/> <location filename="../src/GUI/gui.cpp" line="206"/>
<location filename="../src/GUI/gui.cpp" line="639"/> <location filename="../src/GUI/gui.cpp" line="643"/>
<location filename="../src/GUI/gui.cpp" line="640"/> <location filename="../src/GUI/gui.cpp" line="644"/>
<source>Paths</source> <source>Paths</source>
<translation>Tiedostopolut</translation> <translation>Tiedostopolut</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="243"/> <location filename="../src/GUI/gui.cpp" line="247"/>
<source>Load POI file...</source> <source>Load POI file...</source>
<translation>Lataa POI-tiedosto...</translation> <translation>Lataa POI-tiedosto...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="274"/> <location filename="../src/GUI/gui.cpp" line="278"/>
<source>Load map...</source> <source>Load map...</source>
<translation>Lataa kartta...</translation> <translation>Lataa kartta...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="280"/>
<location filename="../src/GUI/gui.cpp" line="284"/> <location filename="../src/GUI/gui.cpp" line="284"/>
<location filename="../src/GUI/gui.cpp" line="622"/> <location filename="../src/GUI/gui.cpp" line="288"/>
<location filename="../src/GUI/gui.cpp" line="626"/>
<source>Next map</source> <source>Next map</source>
<translation>Seuraava kartta</translation> <translation>Seuraava kartta</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="294"/> <location filename="../src/GUI/gui.cpp" line="298"/>
<source>Show tracks</source> <source>Show tracks</source>
<translation>Näytä jäljet</translation> <translation>Näytä jäljet</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="298"/> <location filename="../src/GUI/gui.cpp" line="302"/>
<source>Show routes</source> <source>Show routes</source>
<translation>Näytä reitit</translation> <translation>Näytä reitit</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="302"/> <location filename="../src/GUI/gui.cpp" line="306"/>
<source>Show waypoints</source> <source>Show waypoints</source>
<translation>Näytä reittipisteet</translation> <translation>Näytä reittipisteet</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="306"/> <location filename="../src/GUI/gui.cpp" line="310"/>
<source>Waypoint labels</source> <source>Waypoint labels</source>
<translation>Reittipisteen nimiöt</translation> <translation>Reittipisteen nimiöt</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="317"/> <location filename="../src/GUI/gui.cpp" line="321"/>
<source>Show graphs</source> <source>Show graphs</source>
<translation>Näytä kaaviokuvat</translation> <translation>Näytä kaaviokuvat</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="337"/> <location filename="../src/GUI/gui.cpp" line="341"/>
<source>Show grid</source> <source>Show grid</source>
<translation>Näytä ruudukko</translation> <translation>Näytä ruudukko</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="341"/> <location filename="../src/GUI/gui.cpp" line="345"/>
<source>Show slider info</source> <source>Show slider info</source>
<translation>Näytä liukusäätimen arvo</translation> <translation>Näytä liukusäätimen arvo</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="347"/> <location filename="../src/GUI/gui.cpp" line="351"/>
<source>Show toolbars</source> <source>Show toolbars</source>
<translation>Näytä työkalupalkit</translation> <translation>Näytä työkalupalkit</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="353"/> <location filename="../src/GUI/gui.cpp" line="357"/>
<source>Total time</source> <source>Total time</source>
<translation>Kokonaisaika</translation> <translation>Kokonaisaika</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="358"/> <location filename="../src/GUI/gui.cpp" line="362"/>
<location filename="../src/GUI/gui.cpp" line="926"/> <location filename="../src/GUI/gui.cpp" line="934"/>
<source>Moving time</source> <source>Moving time</source>
<translation>Liikkumisaika</translation> <translation>Liikkumisaika</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="365"/> <location filename="../src/GUI/gui.cpp" line="369"/>
<source>Metric</source> <source>Metric</source>
<translation>Metriset</translation> <translation>Metriset</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="370"/> <location filename="../src/GUI/gui.cpp" line="374"/>
<source>Imperial</source> <source>Imperial</source>
<translation>Brittiläiset</translation> <translation>Brittiläiset</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="375"/> <location filename="../src/GUI/gui.cpp" line="379"/>
<source>Nautical</source> <source>Nautical</source>
<translation>Merelliset</translation> <translation>Merelliset</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="382"/> <location filename="../src/GUI/gui.cpp" line="386"/>
<source>Decimal degrees (DD)</source> <source>Decimal degrees (DD)</source>
<translation>Desimaaliasteet (DD)</translation> <translation>Desimaaliasteet (DD)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="387"/> <location filename="../src/GUI/gui.cpp" line="391"/>
<source>Degrees and decimal minutes (DMM)</source> <source>Degrees and decimal minutes (DMM)</source>
<translation>Asteet, desimaaliminuutit (DMM)</translation> <translation>Asteet, desimaaliminuutit (DMM)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="393"/> <location filename="../src/GUI/gui.cpp" line="397"/>
<source>Degrees, minutes, seconds (DMS)</source> <source>Degrees, minutes, seconds (DMS)</source>
<translation>Asteet, minuutit, sekunnit (DMS)</translation> <translation>Asteet, minuutit, sekunnit (DMS)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="398"/> <location filename="../src/GUI/gui.cpp" line="402"/>
<source>Fullscreen mode</source> <source>Fullscreen mode</source>
<translation>Kokoruututila</translation> <translation>Kokoruututila</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="404"/> <location filename="../src/GUI/gui.cpp" line="408"/>
<source>Options...</source> <source>Options...</source>
<translation>Valinnat...</translation> <translation>Valinnat...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="410"/> <location filename="../src/GUI/gui.cpp" line="414"/>
<source>Next</source> <source>Next</source>
<translation>Seuraava</translation> <translation>Seuraava</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="413"/> <location filename="../src/GUI/gui.cpp" line="417"/>
<source>Previous</source> <source>Previous</source>
<translation>Edellinen</translation> <translation>Edellinen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="417"/> <location filename="../src/GUI/gui.cpp" line="421"/>
<source>Last</source> <source>Last</source>
<translation>Viimeinen</translation> <translation>Viimeinen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="420"/> <location filename="../src/GUI/gui.cpp" line="424"/>
<source>First</source> <source>First</source>
<translation>Ensimmäinen</translation> <translation>Ensimmäinen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="442"/> <location filename="../src/GUI/gui.cpp" line="464"/>
<source>Map</source>
<translation>Kartat</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="450"/>
<source>Graph</source>
<translation>Kaaviokuva</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="459"/>
<source>POI</source>
<translation>POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="460"/>
<source>POI files</source> <source>POI files</source>
<translation>POI-tiedostot</translation> <translation>POI-tiedostot</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="471"/> <location filename="../src/GUI/gui.cpp" line="476"/>
<source>Data</source>
<translation>Tiedot</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="472"/>
<source>Display</source> <source>Display</source>
<translation>Näytä</translation> <translation>Näytä</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="480"/> <location filename="../src/GUI/gui.cpp" line="488"/>
<source>Settings</source>
<translation>Asetukset</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="484"/>
<source>Units</source> <source>Units</source>
<translation>Yksiköt</translation> <translation>Yksiköt</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="488"/> <location filename="../src/GUI/gui.cpp" line="492"/>
<source>Coordinates format</source> <source>Coordinates format</source>
<translation>Koordinaattien muoto</translation> <translation>Koordinaattien muoto</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="498"/> <location filename="../src/GUI/gui.cpp" line="619"/>
<source>Help</source>
<translation>Ohje</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="615"/>
<source>Append file</source> <source>Append file</source>
<translation>Lisää tiedosto</translation> <translation>Lisää tiedosto</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="616"/> <location filename="../src/GUI/gui.cpp" line="620"/>
<source>Next/Previous</source> <source>Next/Previous</source>
<translation>Next/Previous</translation> <translation>Next/Previous</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="618"/> <location filename="../src/GUI/gui.cpp" line="622"/>
<source>Toggle graph type</source> <source>Toggle graph type</source>
<translation>Vaihda kaaviokuvan tyyppi</translation> <translation>Vaihda kaaviokuvan tyyppi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="620"/> <location filename="../src/GUI/gui.cpp" line="624"/>
<source>Toggle time type</source> <source>Toggle time type</source>
<translation>Vaihda ajan tyyppi</translation> <translation>Vaihda ajan tyyppi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="624"/> <location filename="../src/GUI/gui.cpp" line="628"/>
<source>Previous map</source> <source>Previous map</source>
<translation>Edellinen kartta</translation> <translation>Edellinen kartta</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="625"/> <location filename="../src/GUI/gui.cpp" line="629"/>
<source>Zoom in</source> <source>Zoom in</source>
<translation>Lähennä</translation> <translation>Lähennä</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="627"/> <location filename="../src/GUI/gui.cpp" line="631"/>
<source>Zoom out</source> <source>Zoom out</source>
<translation>Loitonna</translation> <translation>Loitonna</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="629"/> <location filename="../src/GUI/gui.cpp" line="633"/>
<source>Digital zoom</source> <source>Digital zoom</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="630"/> <location filename="../src/GUI/gui.cpp" line="634"/>
<source>Zoom</source> <source>Zoom</source>
<translation>Zoom</translation> <translation>Zoom</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1127"/> <location filename="../src/GUI/gui.cpp" line="1135"/>
<source>Open map file</source> <source>Open map file</source>
<translation>Avaa karttatiedosto</translation> <translation>Avaa karttatiedosto</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1165"/> <location filename="../src/GUI/gui.cpp" line="1175"/>
<source>No files loaded</source> <source>No files loaded</source>
<translation>Yhtään tiedostoja ei ladattu</translation> <translation>Yhtään tiedostoja ei ladattu</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="912"/> <location filename="../src/GUI/gui.cpp" line="920"/>
<location filename="../src/GUI/gui.cpp" line="915"/> <location filename="../src/GUI/gui.cpp" line="923"/>
<source>Date</source> <source>Date</source>
<translation>Päivämäärä</translation> <translation>Päivämäärä</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="643"/> <location filename="../src/GUI/gui.cpp" line="432"/>
<source>&amp;File</source>
<translation>&amp;Tiedosto</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="446"/>
<source>&amp;Map</source>
<translation>&amp;Kartat</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="454"/>
<source>&amp;Graph</source>
<translation>Kaa&amp;viokuva</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="463"/>
<source>&amp;POI</source>
<translation>&amp;POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="475"/>
<source>&amp;Data</source>
<translation>Tie&amp;dot</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="484"/>
<source>&amp;Settings</source>
<translation>&amp;Asetukset</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="502"/>
<source>&amp;Help</source>
<translation>&amp;Ohje</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="647"/>
<source>Map directory:</source> <source>Map directory:</source>
<translation>Karttojen hakemisto:</translation> <translation>Karttojen hakemisto:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="645"/> <location filename="../src/GUI/gui.cpp" line="649"/>
<source>POI directory:</source> <source>POI directory:</source>
<translation>POI:n hakemisto:</translation> <translation>POI:n hakemisto:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="647"/> <location filename="../src/GUI/gui.cpp" line="651"/>
<source>GCS file:</source> <source>GCS file:</source>
<translation>GCS-tiedosto:</translation> <translation>GCS-tiedosto:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="648"/> <location filename="../src/GUI/gui.cpp" line="652"/>
<source>PCS file:</source> <source>PCS file:</source>
<translation>PCS-tiedosto:</translation> <translation>PCS-tiedosto:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="650"/> <location filename="../src/GUI/gui.cpp" line="654"/>
<source>Ellipsoids file:</source> <source>Ellipsoids file:</source>
<translation>Ellipsoids-tiedosto:</translation> <translation>Ellipsoids-tiedosto:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="653"/> <location filename="../src/GUI/gui.cpp" line="657"/>
<source>User override directory:</source> <source>User override directory:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="904"/> <location filename="../src/GUI/gui.cpp" line="912"/>
<source>Routes</source> <source>Routes</source>
<translation>Reitit</translation> <translation>Reitit</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1154"/> <location filename="../src/GUI/gui.cpp" line="1164"/>
<source>Error loading map:</source> <source>Error loading map:</source>
<translation>Virhe ladattaessa karttaa:</translation> <translation>Virhe ladattaessa karttaa:</translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location filename="../src/GUI/gui.cpp" line="1169"/> <location filename="../src/GUI/gui.cpp" line="1179"/>
<source>%n files</source> <source>%n files</source>
<translation> <translation>
<numerusform>%n tiedosto</numerusform> <numerusform>%n tiedosto</numerusform>
@ -678,97 +682,97 @@
</translation> </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="609"/> <location filename="../src/GUI/gui.cpp" line="613"/>
<source>Next file</source> <source>Next file</source>
<translation>Seuraava tiedosto</translation> <translation>Seuraava tiedosto</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="585"/> <location filename="../src/GUI/gui.cpp" line="589"/>
<source>Version </source> <source>Version </source>
<translation>Versio </translation> <translation>Versio </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="218"/> <location filename="../src/GUI/gui.cpp" line="222"/>
<source>Print...</source> <source>Print...</source>
<translation>Tulosta...</translation> <translation>Tulosta...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="223"/> <location filename="../src/GUI/gui.cpp" line="227"/>
<source>Export to PDF...</source> <source>Export to PDF...</source>
<translation>Vie PDF:ksi...</translation> <translation>Vie PDF:ksi...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="906"/> <location filename="../src/GUI/gui.cpp" line="914"/>
<source>Waypoints</source> <source>Waypoints</source>
<translation>Reittipisteet</translation> <translation>Reittipisteet</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="610"/> <location filename="../src/GUI/gui.cpp" line="614"/>
<source>Previous file</source> <source>Previous file</source>
<translation>Edellinen tiedosto</translation> <translation>Edellinen tiedosto</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="310"/> <location filename="../src/GUI/gui.cpp" line="314"/>
<source>Route waypoints</source> <source>Route waypoints</source>
<translation>Reittipisteet</translation> <translation>Reittipisteet</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="612"/> <location filename="../src/GUI/gui.cpp" line="616"/>
<source>First file</source> <source>First file</source>
<translation>Ensimmäinen tiedosto</translation> <translation>Ensimmäinen tiedosto</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="614"/> <location filename="../src/GUI/gui.cpp" line="618"/>
<source>Last file</source> <source>Last file</source>
<translation>Viimeinen tiedosto</translation> <translation>Viimeinen tiedosto</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="740"/> <location filename="../src/GUI/gui.cpp" line="746"/>
<source>Error loading data file:</source> <source>Error loading data file:</source>
<translation>Virhe ladattaessa datatiedostoa:</translation> <translation>Virhe ladattaessa datatiedostoa:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="743"/> <location filename="../src/GUI/gui.cpp" line="749"/>
<location filename="../src/GUI/gui.cpp" line="768"/> <location filename="../src/GUI/gui.cpp" line="776"/>
<source>Line: %1</source> <source>Line: %1</source>
<translation>Rivi: %1</translation> <translation>Rivi: %1</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="765"/> <location filename="../src/GUI/gui.cpp" line="773"/>
<source>Error loading POI file:</source> <source>Error loading POI file:</source>
<translation>Virhe ladattaessa POI-tiedostoa:</translation> <translation>Virhe ladattaessa POI-tiedostoa:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="898"/> <location filename="../src/GUI/gui.cpp" line="906"/>
<source>Name</source> <source>Name</source>
<translation>Nimi</translation> <translation>Nimi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="902"/> <location filename="../src/GUI/gui.cpp" line="910"/>
<source>Tracks</source> <source>Tracks</source>
<translation>Jäljet</translation> <translation>Jäljet</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="207"/> <location filename="../src/GUI/gui.cpp" line="211"/>
<location filename="../src/GUI/gui.cpp" line="584"/> <location filename="../src/GUI/gui.cpp" line="588"/>
<source>About GPXSee</source> <source>About GPXSee</source>
<translation>Tietoja GPXSee:stä</translation> <translation>Tietoja GPXSee:stä</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="522"/> <location filename="../src/GUI/gui.cpp" line="526"/>
<source>Navigation</source> <source>Navigation</source>
<translation>Navigointi</translation> <translation>Navigointi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="325"/> <location filename="../src/GUI/gui.cpp" line="329"/>
<location filename="../src/GUI/gui.cpp" line="922"/> <location filename="../src/GUI/gui.cpp" line="930"/>
<source>Distance</source> <source>Distance</source>
<translation>Etäisyys</translation> <translation>Etäisyys</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="331"/> <location filename="../src/GUI/gui.cpp" line="335"/>
<location filename="../src/GUI/gui.cpp" line="481"/> <location filename="../src/GUI/gui.cpp" line="485"/>
<location filename="../src/GUI/gui.cpp" line="924"/> <location filename="../src/GUI/gui.cpp" line="932"/>
<source>Time</source> <source>Time</source>
<translation>Aika</translation> <translation>Aika</translation>
</message> </message>
@ -874,27 +878,27 @@
<context> <context>
<name>MapList</name> <name>MapList</name>
<message> <message>
<location filename="../src/map/maplist.cpp" line="131"/> <location filename="../src/map/maplist.cpp" line="130"/>
<source>Supported files</source> <source>Supported files</source>
<translation>Tuetut tiedostot</translation> <translation>Tuetut tiedostot</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="132"/> <location filename="../src/map/maplist.cpp" line="131"/>
<source>OziExplorer maps</source> <source>OziExplorer maps</source>
<translation>OziExplorer -kartat</translation> <translation>OziExplorer -kartat</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="133"/> <location filename="../src/map/maplist.cpp" line="132"/>
<source>TrekBuddy maps/atlases</source> <source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy -kartat/kartastot</translation> <translation>TrekBuddy -kartat/kartastot</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="134"/> <location filename="../src/map/maplist.cpp" line="133"/>
<source>GeoTIFF images</source> <source>GeoTIFF images</source>
<translation>GeoTIFF -kuvat</translation> <translation>GeoTIFF -kuvat</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="135"/> <location filename="../src/map/maplist.cpp" line="134"/>
<source>Online map sources</source> <source>Online map sources</source>
<translation>Online-karttojen lähteet</translation> <translation>Online-karttojen lähteet</translation>
</message> </message>
@ -1379,33 +1383,53 @@
<context> <context>
<name>SpeedGraph</name> <name>SpeedGraph</name>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="14"/> <location filename="../src/GUI/speedgraph.cpp" line="16"/>
<location filename="../src/GUI/speedgraph.h" line="14"/> <location filename="../src/GUI/speedgraph.h" line="14"/>
<source>Speed</source> <source>Speed</source>
<translation>Vauhti</translation> <translation>Vauhti</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="89"/> <location filename="../src/GUI/speedgraph.cpp" line="96"/>
<source>km/h</source> <source>km/h</source>
<translation>km/t</translation> <translation>km/t</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="22"/> <location filename="../src/GUI/speedgraph.cpp" line="28"/>
<source>Average</source> <source>Average</source>
<translation>Keskiarvo</translation> <translation>Keskiarvo</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="24"/> <location filename="../src/GUI/speedgraph.cpp" line="25"/>
<source>min/km</source>
<translation>min/km</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="26"/>
<source>min/mi</source>
<translation>min/mi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="26"/>
<source>min/nmi</source>
<translation>min/mpk</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="30"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Maksimi</translation> <translation>Maksimi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="83"/> <location filename="../src/GUI/speedgraph.cpp" line="32"/>
<source>Pace</source>
<translation>Tahti</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="90"/>
<source>kn</source> <source>kn</source>
<translation>kn</translation> <translation>kn</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="86"/> <location filename="../src/GUI/speedgraph.cpp" line="93"/>
<source>mi/h</source> <source>mi/h</source>
<translation>mph</translation> <translation>mph</translation>
</message> </message>
@ -1413,30 +1437,50 @@
<context> <context>
<name>SpeedGraphItem</name> <name>SpeedGraphItem</name>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="22"/> <location filename="../src/GUI/speedgraphitem.cpp" line="23"/>
<source>km/h</source> <source>km/h</source>
<translation>km/t</translation> <translation>km/t</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="21"/> <location filename="../src/GUI/speedgraphitem.cpp" line="22"/>
<source>mi/h</source> <source>mi/h</source>
<translation>mph</translation> <translation>mph</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="22"/> <location filename="../src/GUI/speedgraphitem.cpp" line="23"/>
<source>kn</source> <source>kn</source>
<translation>kn</translation> <translation>kn</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="24"/> <location filename="../src/GUI/speedgraphitem.cpp" line="26"/>
<source>min/km</source>
<translation>min/km</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="27"/>
<source>min/mi</source>
<translation>min/mi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="27"/>
<source>min/nmi</source>
<translation>min/mpk</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="29"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Maksimi</translation> <translation>Maksimi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="26"/> <location filename="../src/GUI/speedgraphitem.cpp" line="31"/>
<source>Average</source> <source>Average</source>
<translation>Keskiarvo</translation> <translation>Keskiarvo</translation>
</message> </message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="33"/>
<source>Pace</source>
<translation>Tahti</translation>
</message>
</context> </context>
<context> <context>
<name>TemperatureGraph</name> <name>TemperatureGraph</name>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS> <!DOCTYPE TS>
<TS version="2.1" language="de"> <TS version="2.1" language="fr">
<context> <context>
<name>CadenceGraph</name> <name>CadenceGraph</name>
<message> <message>
@ -284,7 +284,7 @@
<message> <message>
<location filename="../src/GUI/format.cpp" line="62"/> <location filename="../src/GUI/format.cpp" line="62"/>
<source>nmi</source> <source>nmi</source>
<translation type="unfinished"></translation> <translation>nmi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/format.cpp" line="66"/> <location filename="../src/GUI/format.cpp" line="66"/>
@ -301,365 +301,334 @@
<context> <context>
<name>GUI</name> <name>GUI</name>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="588"/> <location filename="../src/GUI/gui.cpp" line="592"/>
<source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source> <source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source>
<translation>GPXSee est distribué selon les termes de la licence publique générale GNU (version 3). Pour plus d&apos;information sur GPXSee, visiter le site du projet sur </translation> <translation>GPXSee est distribué selon les termes de la licence publique générale GNU (version 3). Pour plus d&apos;information sur GPXSee, visiter le site du projet sur </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="643"/> <location filename="../src/GUI/gui.cpp" line="647"/>
<source>Map directory:</source> <source>Map directory:</source>
<translation>Dossier des cartes :</translation> <translation>Dossier des cartes :</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="645"/> <location filename="../src/GUI/gui.cpp" line="649"/>
<source>POI directory:</source> <source>POI directory:</source>
<translation>Dossier des POI:</translation> <translation>Dossier des POI:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="647"/> <location filename="../src/GUI/gui.cpp" line="651"/>
<source>GCS file:</source> <source>GCS file:</source>
<translation>Fichier GCS :</translation> <translation>Fichier GCS :</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="648"/> <location filename="../src/GUI/gui.cpp" line="652"/>
<source>PCS file:</source> <source>PCS file:</source>
<translation>Fichier PCS :</translation> <translation>Fichier PCS :</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="650"/> <location filename="../src/GUI/gui.cpp" line="654"/>
<source>Ellipsoids file:</source> <source>Ellipsoids file:</source>
<translation>Fichier des ellipsoïdes :</translation> <translation>Fichier des ellipsoïdes :</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="653"/> <location filename="../src/GUI/gui.cpp" line="657"/>
<source>User override directory:</source> <source>User override directory:</source>
<translation>Dossier de l&apos;utilisateur :</translation> <translation>Dossier de l&apos;utilisateur :</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="662"/> <location filename="../src/GUI/gui.cpp" line="666"/>
<source>Open file</source> <source>Open file</source>
<translation>Ouvrir un fichier</translation> <translation>Ouvrir un fichier</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="751"/> <location filename="../src/GUI/gui.cpp" line="757"/>
<source>Open POI file</source> <source>Open POI file</source>
<translation>Ouvrir un fichier POI</translation> <translation>Ouvrir un fichier POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="195"/> <location filename="../src/GUI/gui.cpp" line="199"/>
<source>Quit</source> <source>Quit</source>
<translation>Quitter</translation> <translation>Quitter</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="204"/> <location filename="../src/GUI/gui.cpp" line="208"/>
<location filename="../src/GUI/gui.cpp" line="605"/> <location filename="../src/GUI/gui.cpp" line="609"/>
<location filename="../src/GUI/gui.cpp" line="606"/> <location filename="../src/GUI/gui.cpp" line="610"/>
<source>Keyboard controls</source> <source>Keyboard controls</source>
<translation>Raccourcis clavier</translation> <translation>Raccourcis clavier</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="229"/> <location filename="../src/GUI/gui.cpp" line="233"/>
<source>Close</source> <source>Close</source>
<translation>Fermer</translation> <translation>Fermer</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="235"/> <location filename="../src/GUI/gui.cpp" line="239"/>
<source>Reload</source> <source>Reload</source>
<translation>Actualiser</translation> <translation>Actualiser</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="517"/> <location filename="../src/GUI/gui.cpp" line="521"/>
<source>Show</source> <source>Show</source>
<translation>Afficher</translation> <translation>Afficher</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="428"/> <location filename="../src/GUI/gui.cpp" line="515"/>
<location filename="../src/GUI/gui.cpp" line="511"/>
<source>File</source> <source>File</source>
<translation>Fichier</translation> <translation>Fichier</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="246"/> <location filename="../src/GUI/gui.cpp" line="250"/>
<source>Close POI files</source> <source>Close POI files</source>
<translation>Fermer les fichiers POI</translation> <translation>Fermer les fichiers POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="248"/> <location filename="../src/GUI/gui.cpp" line="252"/>
<source>Overlap POIs</source> <source>Overlap POIs</source>
<translation>Superposer les POI</translation> <translation>Superposer les POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="252"/> <location filename="../src/GUI/gui.cpp" line="256"/>
<source>Show POI labels</source> <source>Show POI labels</source>
<translation>Afficher les notes des POI</translation> <translation>Afficher les notes des POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="257"/> <location filename="../src/GUI/gui.cpp" line="261"/>
<source>Show POIs</source> <source>Show POIs</source>
<translation>Afficher les POI</translation> <translation>Afficher les POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="266"/> <location filename="../src/GUI/gui.cpp" line="270"/>
<source>Show map</source> <source>Show map</source>
<translation>Afficher la carte</translation> <translation>Afficher la carte</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="276"/> <location filename="../src/GUI/gui.cpp" line="280"/>
<source>Clear tile cache</source> <source>Clear tile cache</source>
<translation>Effacer les tuiles en cache</translation> <translation>Effacer les tuiles en cache</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="213"/> <location filename="../src/GUI/gui.cpp" line="217"/>
<source>Open...</source> <source>Open...</source>
<translation>Ouvrir...</translation> <translation>Ouvrir...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="202"/> <location filename="../src/GUI/gui.cpp" line="206"/>
<location filename="../src/GUI/gui.cpp" line="639"/> <location filename="../src/GUI/gui.cpp" line="643"/>
<location filename="../src/GUI/gui.cpp" line="640"/> <location filename="../src/GUI/gui.cpp" line="644"/>
<source>Paths</source> <source>Paths</source>
<translation>Chemin d&apos;accès</translation> <translation>Chemin d&apos;accès</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="243"/> <location filename="../src/GUI/gui.cpp" line="247"/>
<source>Load POI file...</source> <source>Load POI file...</source>
<translation>Charger un fichier POI...</translation> <translation>Charger un fichier POI...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="274"/> <location filename="../src/GUI/gui.cpp" line="278"/>
<source>Load map...</source> <source>Load map...</source>
<translation>Charger une carte...</translation> <translation>Charger une carte...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="280"/>
<location filename="../src/GUI/gui.cpp" line="284"/> <location filename="../src/GUI/gui.cpp" line="284"/>
<location filename="../src/GUI/gui.cpp" line="622"/> <location filename="../src/GUI/gui.cpp" line="288"/>
<location filename="../src/GUI/gui.cpp" line="626"/>
<source>Next map</source> <source>Next map</source>
<translation>Carte suivante</translation> <translation>Carte suivante</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="294"/> <location filename="../src/GUI/gui.cpp" line="298"/>
<source>Show tracks</source> <source>Show tracks</source>
<translation>Afficher la trace</translation> <translation>Afficher la trace</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="298"/> <location filename="../src/GUI/gui.cpp" line="302"/>
<source>Show routes</source> <source>Show routes</source>
<translation>Afficher la route</translation> <translation>Afficher la route</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="302"/> <location filename="../src/GUI/gui.cpp" line="306"/>
<source>Show waypoints</source> <source>Show waypoints</source>
<translation>Afficher les points de jalonnement</translation> <translation>Afficher les points de jalonnement</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="306"/> <location filename="../src/GUI/gui.cpp" line="310"/>
<source>Waypoint labels</source> <source>Waypoint labels</source>
<translation>Étiquettes des jalons</translation> <translation>Étiquettes des jalons</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="317"/> <location filename="../src/GUI/gui.cpp" line="321"/>
<source>Show graphs</source> <source>Show graphs</source>
<translation>Afficher les graphes</translation> <translation>Afficher les graphes</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="337"/> <location filename="../src/GUI/gui.cpp" line="341"/>
<source>Show grid</source> <source>Show grid</source>
<translation>Afficher la grille</translation> <translation>Afficher la grille</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="341"/> <location filename="../src/GUI/gui.cpp" line="345"/>
<source>Show slider info</source> <source>Show slider info</source>
<translation>Afficher les infos du curseur</translation> <translation>Afficher les infos du curseur</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="347"/> <location filename="../src/GUI/gui.cpp" line="351"/>
<source>Show toolbars</source> <source>Show toolbars</source>
<translation>Afficher la barre d&apos;outils</translation> <translation>Afficher la barre d&apos;outils</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="353"/> <location filename="../src/GUI/gui.cpp" line="357"/>
<source>Total time</source> <source>Total time</source>
<translation>Durée totale</translation> <translation>Durée totale</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="358"/> <location filename="../src/GUI/gui.cpp" line="362"/>
<location filename="../src/GUI/gui.cpp" line="926"/> <location filename="../src/GUI/gui.cpp" line="934"/>
<source>Moving time</source> <source>Moving time</source>
<translation>Durée en déplacement</translation> <translation>Durée en déplacement</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="365"/> <location filename="../src/GUI/gui.cpp" line="369"/>
<source>Metric</source> <source>Metric</source>
<translation>Métrique</translation> <translation>Métrique</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="370"/> <location filename="../src/GUI/gui.cpp" line="374"/>
<source>Imperial</source> <source>Imperial</source>
<translation>Impérial</translation> <translation>Impérial</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="375"/> <location filename="../src/GUI/gui.cpp" line="379"/>
<source>Nautical</source> <source>Nautical</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="382"/> <location filename="../src/GUI/gui.cpp" line="386"/>
<source>Decimal degrees (DD)</source> <source>Decimal degrees (DD)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="387"/> <location filename="../src/GUI/gui.cpp" line="391"/>
<source>Degrees and decimal minutes (DMM)</source> <source>Degrees and decimal minutes (DMM)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="393"/> <location filename="../src/GUI/gui.cpp" line="397"/>
<source>Degrees, minutes, seconds (DMS)</source> <source>Degrees, minutes, seconds (DMS)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="398"/> <location filename="../src/GUI/gui.cpp" line="402"/>
<source>Fullscreen mode</source> <source>Fullscreen mode</source>
<translation>Mode plein écran</translation> <translation>Mode plein écran</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="404"/> <location filename="../src/GUI/gui.cpp" line="408"/>
<source>Options...</source> <source>Options...</source>
<translation>Options...</translation> <translation>Options...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="410"/> <location filename="../src/GUI/gui.cpp" line="414"/>
<source>Next</source> <source>Next</source>
<translation>Suivant</translation> <translation>Suivant</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="413"/> <location filename="../src/GUI/gui.cpp" line="417"/>
<source>Previous</source> <source>Previous</source>
<translation>Précèdant</translation> <translation>Précèdant</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="417"/> <location filename="../src/GUI/gui.cpp" line="421"/>
<source>Last</source> <source>Last</source>
<translation>Dernier</translation> <translation>Dernier</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="420"/> <location filename="../src/GUI/gui.cpp" line="424"/>
<source>First</source> <source>First</source>
<translation>Premier</translation> <translation>Premier</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="442"/> <location filename="../src/GUI/gui.cpp" line="464"/>
<source>Map</source>
<translation>Carte</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="450"/>
<source>Graph</source>
<translation>Graphe</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="459"/>
<source>POI</source>
<translation>POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="460"/>
<source>POI files</source> <source>POI files</source>
<translation>Fichiers POI</translation> <translation>Fichiers POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="471"/> <location filename="../src/GUI/gui.cpp" line="476"/>
<source>Data</source>
<translation>Données</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="472"/>
<source>Display</source> <source>Display</source>
<translation>Affichage</translation> <translation>Affichage</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="480"/> <location filename="../src/GUI/gui.cpp" line="488"/>
<source>Settings</source>
<translation>Paramètres</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="484"/>
<source>Units</source> <source>Units</source>
<translation>Système d&apos;unités</translation> <translation>Système d&apos;unités</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="488"/> <location filename="../src/GUI/gui.cpp" line="492"/>
<source>Coordinates format</source> <source>Coordinates format</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="498"/> <location filename="../src/GUI/gui.cpp" line="619"/>
<source>Help</source>
<translation>Aide</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="615"/>
<source>Append file</source> <source>Append file</source>
<translation>Joindre un fichier</translation> <translation>Joindre un fichier</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="616"/> <location filename="../src/GUI/gui.cpp" line="620"/>
<source>Next/Previous</source> <source>Next/Previous</source>
<translation>Suivant/Précèdant</translation> <translation>Suivant/Précèdant</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="618"/> <location filename="../src/GUI/gui.cpp" line="622"/>
<source>Toggle graph type</source> <source>Toggle graph type</source>
<translation>Controler le type de graphe</translation> <translation>Controler le type de graphe</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="620"/> <location filename="../src/GUI/gui.cpp" line="624"/>
<source>Toggle time type</source> <source>Toggle time type</source>
<translation>Controler le type de durée</translation> <translation>Controler le type de durée</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="624"/> <location filename="../src/GUI/gui.cpp" line="628"/>
<source>Previous map</source> <source>Previous map</source>
<translation>Carte précèdente</translation> <translation>Carte précèdente</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="625"/> <location filename="../src/GUI/gui.cpp" line="629"/>
<source>Zoom in</source> <source>Zoom in</source>
<translation>Zoomer</translation> <translation>Zoomer</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="627"/> <location filename="../src/GUI/gui.cpp" line="631"/>
<source>Zoom out</source> <source>Zoom out</source>
<translation>Dézoomer</translation> <translation>Dézoomer</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="629"/> <location filename="../src/GUI/gui.cpp" line="633"/>
<source>Digital zoom</source> <source>Digital zoom</source>
<translation>Zoom numérique</translation> <translation>Zoom numérique</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="630"/> <location filename="../src/GUI/gui.cpp" line="634"/>
<source>Zoom</source> <source>Zoom</source>
<translation>Zoom</translation> <translation>Zoom</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1127"/> <location filename="../src/GUI/gui.cpp" line="1135"/>
<source>Open map file</source> <source>Open map file</source>
<translation>Ouvrir un fichier de carte</translation> <translation>Ouvrir un fichier de carte</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1154"/> <location filename="../src/GUI/gui.cpp" line="1164"/>
<source>Error loading map:</source> <source>Error loading map:</source>
<translation>Erreur lors du chargement de la carte :</translation> <translation>Erreur lors du chargement de la carte :</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1165"/> <location filename="../src/GUI/gui.cpp" line="1175"/>
<source>No files loaded</source> <source>No files loaded</source>
<translation>Aucun fichier chargé</translation> <translation>Aucun fichier chargé</translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location filename="../src/GUI/gui.cpp" line="1169"/> <location filename="../src/GUI/gui.cpp" line="1179"/>
<source>%n files</source> <source>%n files</source>
<translation> <translation>
<numerusform>%n fichier</numerusform> <numerusform>%n fichier</numerusform>
@ -667,108 +636,143 @@
</translation> </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="912"/> <location filename="../src/GUI/gui.cpp" line="920"/>
<location filename="../src/GUI/gui.cpp" line="915"/> <location filename="../src/GUI/gui.cpp" line="923"/>
<source>Date</source> <source>Date</source>
<translation>Date</translation> <translation>Date</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="904"/> <location filename="../src/GUI/gui.cpp" line="912"/>
<source>Routes</source> <source>Routes</source>
<translation>Routes</translation> <translation>Routes</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="609"/> <location filename="../src/GUI/gui.cpp" line="613"/>
<source>Next file</source> <source>Next file</source>
<translation>Fichier suivant</translation> <translation>Fichier suivant</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="585"/> <location filename="../src/GUI/gui.cpp" line="589"/>
<source>Version </source> <source>Version </source>
<translation>Version </translation> <translation>Version </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="218"/> <location filename="../src/GUI/gui.cpp" line="222"/>
<source>Print...</source> <source>Print...</source>
<translation>Imprimer...</translation> <translation>Imprimer...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="223"/> <location filename="../src/GUI/gui.cpp" line="227"/>
<source>Export to PDF...</source> <source>Export to PDF...</source>
<translation>Exporter au format PDF...</translation> <translation>Exporter au format PDF...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="906"/> <location filename="../src/GUI/gui.cpp" line="914"/>
<source>Waypoints</source> <source>Waypoints</source>
<translation>Points de jalonnement</translation> <translation>Points de jalonnement</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="610"/> <location filename="../src/GUI/gui.cpp" line="614"/>
<source>Previous file</source> <source>Previous file</source>
<translation>Fichier précédent</translation> <translation>Fichier précédent</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="310"/> <location filename="../src/GUI/gui.cpp" line="314"/>
<source>Route waypoints</source> <source>Route waypoints</source>
<translation>Jalons de route</translation> <translation>Jalons de route</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="612"/> <location filename="../src/GUI/gui.cpp" line="432"/>
<source>&amp;File</source>
<translation>&amp;Fichier</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="446"/>
<source>&amp;Map</source>
<translation>&amp;Carte</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="454"/>
<source>&amp;Graph</source>
<translation>&amp;Graphe</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="463"/>
<source>&amp;POI</source>
<translation>&amp;POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="475"/>
<source>&amp;Data</source>
<translation>&amp;Données</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="484"/>
<source>&amp;Settings</source>
<translation>Pa&amp;ramètres</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="502"/>
<source>&amp;Help</source>
<translation>&amp;Aide</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="616"/>
<source>First file</source> <source>First file</source>
<translation>Premier fichier</translation> <translation>Premier fichier</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="614"/> <location filename="../src/GUI/gui.cpp" line="618"/>
<source>Last file</source> <source>Last file</source>
<translation>Dernier fichier</translation> <translation>Dernier fichier</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="740"/> <location filename="../src/GUI/gui.cpp" line="746"/>
<source>Error loading data file:</source> <source>Error loading data file:</source>
<translation>Erreur lors du chargement des données:</translation> <translation>Erreur lors du chargement des données:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="743"/> <location filename="../src/GUI/gui.cpp" line="749"/>
<location filename="../src/GUI/gui.cpp" line="768"/> <location filename="../src/GUI/gui.cpp" line="776"/>
<source>Line: %1</source> <source>Line: %1</source>
<translation>Ligne : %1</translation> <translation>Ligne : %1</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="765"/> <location filename="../src/GUI/gui.cpp" line="773"/>
<source>Error loading POI file:</source> <source>Error loading POI file:</source>
<translation>Erreur lors du chargement du fichier POI :</translation> <translation>Erreur lors du chargement du fichier POI :</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="898"/> <location filename="../src/GUI/gui.cpp" line="906"/>
<source>Name</source> <source>Name</source>
<translation>Nom</translation> <translation>Nom</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="902"/> <location filename="../src/GUI/gui.cpp" line="910"/>
<source>Tracks</source> <source>Tracks</source>
<translation>Traces</translation> <translation>Traces</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="207"/> <location filename="../src/GUI/gui.cpp" line="211"/>
<location filename="../src/GUI/gui.cpp" line="584"/> <location filename="../src/GUI/gui.cpp" line="588"/>
<source>About GPXSee</source> <source>About GPXSee</source>
<translation>À propos de GPXSee</translation> <translation>À propos de GPXSee</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="522"/> <location filename="../src/GUI/gui.cpp" line="526"/>
<source>Navigation</source> <source>Navigation</source>
<translation>Navigation</translation> <translation>Navigation</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="325"/> <location filename="../src/GUI/gui.cpp" line="329"/>
<location filename="../src/GUI/gui.cpp" line="922"/> <location filename="../src/GUI/gui.cpp" line="930"/>
<source>Distance</source> <source>Distance</source>
<translation>Distance</translation> <translation>Distance</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="331"/> <location filename="../src/GUI/gui.cpp" line="335"/>
<location filename="../src/GUI/gui.cpp" line="481"/> <location filename="../src/GUI/gui.cpp" line="485"/>
<location filename="../src/GUI/gui.cpp" line="924"/> <location filename="../src/GUI/gui.cpp" line="932"/>
<source>Time</source> <source>Time</source>
<translation>Temps</translation> <translation>Temps</translation>
</message> </message>
@ -799,7 +803,7 @@
<message> <message>
<location filename="../src/GUI/graphview.cpp" line="120"/> <location filename="../src/GUI/graphview.cpp" line="120"/>
<source>nmi</source> <source>nmi</source>
<translation type="unfinished"></translation> <translation>nmi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/graphview.cpp" line="134"/> <location filename="../src/GUI/graphview.cpp" line="134"/>
@ -874,27 +878,27 @@
<context> <context>
<name>MapList</name> <name>MapList</name>
<message> <message>
<location filename="../src/map/maplist.cpp" line="131"/> <location filename="../src/map/maplist.cpp" line="130"/>
<source>Supported files</source> <source>Supported files</source>
<translation>Formats pris en charge</translation> <translation>Formats pris en charge</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="132"/> <location filename="../src/map/maplist.cpp" line="131"/>
<source>OziExplorer maps</source> <source>OziExplorer maps</source>
<translation>Cartes OziExplorer</translation> <translation>Cartes OziExplorer</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="133"/> <location filename="../src/map/maplist.cpp" line="132"/>
<source>TrekBuddy maps/atlases</source> <source>TrekBuddy maps/atlases</source>
<translation>Cartes ou atlas TrekBuddy</translation> <translation>Cartes ou atlas TrekBuddy</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="134"/> <location filename="../src/map/maplist.cpp" line="133"/>
<source>GeoTIFF images</source> <source>GeoTIFF images</source>
<translation>Images GeoTIFF</translation> <translation>Images GeoTIFF</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="135"/> <location filename="../src/map/maplist.cpp" line="134"/>
<source>Online map sources</source> <source>Online map sources</source>
<translation>Cartes en ligne</translation> <translation>Cartes en ligne</translation>
</message> </message>
@ -1161,7 +1165,7 @@
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="331"/> <location filename="../src/GUI/optionsdialog.cpp" line="331"/>
<source>nmi</source> <source>nmi</source>
<translation type="unfinished"></translation> <translation>nmi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/optionsdialog.cpp" line="334"/> <location filename="../src/GUI/optionsdialog.cpp" line="334"/>
@ -1363,7 +1367,7 @@
<message> <message>
<location filename="../src/GUI/scaleitem.cpp" line="86"/> <location filename="../src/GUI/scaleitem.cpp" line="86"/>
<source>nmi</source> <source>nmi</source>
<translation type="unfinished"></translation> <translation>nmi</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/scaleitem.cpp" line="89"/> <location filename="../src/GUI/scaleitem.cpp" line="89"/>
@ -1379,33 +1383,53 @@
<context> <context>
<name>SpeedGraph</name> <name>SpeedGraph</name>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="14"/> <location filename="../src/GUI/speedgraph.cpp" line="16"/>
<location filename="../src/GUI/speedgraph.h" line="14"/> <location filename="../src/GUI/speedgraph.h" line="14"/>
<source>Speed</source> <source>Speed</source>
<translation>Vitesse</translation> <translation>Vitesse</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="89"/> <location filename="../src/GUI/speedgraph.cpp" line="96"/>
<source>km/h</source> <source>km/h</source>
<translation>km/h</translation> <translation>km/h</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="22"/> <location filename="../src/GUI/speedgraph.cpp" line="28"/>
<source>Average</source> <source>Average</source>
<translation>Moyenne</translation> <translation>Moyenne</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="24"/> <location filename="../src/GUI/speedgraph.cpp" line="25"/>
<source>min/km</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="26"/>
<source>min/mi</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="26"/>
<source>min/nmi</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="30"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Maximum</translation> <translation>Maximum</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="83"/> <location filename="../src/GUI/speedgraph.cpp" line="32"/>
<source>Pace</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="90"/>
<source>kn</source> <source>kn</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="86"/> <location filename="../src/GUI/speedgraph.cpp" line="93"/>
<source>mi/h</source> <source>mi/h</source>
<translation>mi/h</translation> <translation>mi/h</translation>
</message> </message>
@ -1413,30 +1437,50 @@
<context> <context>
<name>SpeedGraphItem</name> <name>SpeedGraphItem</name>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="22"/> <location filename="../src/GUI/speedgraphitem.cpp" line="23"/>
<source>km/h</source> <source>km/h</source>
<translation>km/h</translation> <translation>km/h</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="21"/> <location filename="../src/GUI/speedgraphitem.cpp" line="22"/>
<source>mi/h</source> <source>mi/h</source>
<translation>mi/h</translation> <translation>mi/h</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="22"/> <location filename="../src/GUI/speedgraphitem.cpp" line="23"/>
<source>kn</source> <source>kn</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="24"/> <location filename="../src/GUI/speedgraphitem.cpp" line="26"/>
<source>min/km</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="27"/>
<source>min/mi</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="27"/>
<source>min/nmi</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="29"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Maximum</translation> <translation>Maximum</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="26"/> <location filename="../src/GUI/speedgraphitem.cpp" line="31"/>
<source>Average</source> <source>Average</source>
<translation>Moyenne</translation> <translation>Moyenne</translation>
</message> </message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="33"/>
<source>Pace</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>TemperatureGraph</name> <name>TemperatureGraph</name>

View File

@ -301,376 +301,380 @@
<context> <context>
<name>GUI</name> <name>GUI</name>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="588"/> <location filename="../src/GUI/gui.cpp" line="592"/>
<source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source> <source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source>
<translation>GPXSee распространяется в соответствиями с условиями версии 3 Стандартной Общественной Лицензии GNU. Для получения дополнительной информации о GPXSee посетите страницу проекта </translation> <translation>GPXSee распространяется в соответствиями с условиями версии 3 Стандартной Общественной Лицензии GNU. Для получения дополнительной информации о GPXSee посетите страницу проекта </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="662"/> <location filename="../src/GUI/gui.cpp" line="666"/>
<source>Open file</source> <source>Open file</source>
<translation>Открыть файл</translation> <translation>Открыть файл</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="751"/> <location filename="../src/GUI/gui.cpp" line="757"/>
<source>Open POI file</source> <source>Open POI file</source>
<translation>Открыть файл с точками POI</translation> <translation>Открыть файл с точками POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="195"/> <location filename="../src/GUI/gui.cpp" line="199"/>
<source>Quit</source> <source>Quit</source>
<translation>Выход</translation> <translation>Выход</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="204"/> <location filename="../src/GUI/gui.cpp" line="208"/>
<location filename="../src/GUI/gui.cpp" line="605"/> <location filename="../src/GUI/gui.cpp" line="609"/>
<location filename="../src/GUI/gui.cpp" line="606"/> <location filename="../src/GUI/gui.cpp" line="610"/>
<source>Keyboard controls</source> <source>Keyboard controls</source>
<translation>Управление с помощью клавиатуры</translation> <translation>Управление с помощью клавиатуры</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="229"/> <location filename="../src/GUI/gui.cpp" line="233"/>
<source>Close</source> <source>Close</source>
<translation>Закрыть</translation> <translation>Закрыть</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="235"/> <location filename="../src/GUI/gui.cpp" line="239"/>
<source>Reload</source> <source>Reload</source>
<translation>Обновить</translation> <translation>Обновить</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="517"/> <location filename="../src/GUI/gui.cpp" line="521"/>
<source>Show</source> <source>Show</source>
<translation>Показать</translation> <translation>Показать</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="428"/> <location filename="../src/GUI/gui.cpp" line="515"/>
<location filename="../src/GUI/gui.cpp" line="511"/>
<source>File</source> <source>File</source>
<translation>Файл</translation> <translation>Файл</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="246"/> <location filename="../src/GUI/gui.cpp" line="250"/>
<source>Close POI files</source> <source>Close POI files</source>
<translation>Закрыть файлы с точками POI</translation> <translation>Закрыть файлы с точками POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="248"/> <location filename="../src/GUI/gui.cpp" line="252"/>
<source>Overlap POIs</source> <source>Overlap POIs</source>
<translation>Наложение точек POI</translation> <translation>Наложение точек POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="252"/> <location filename="../src/GUI/gui.cpp" line="256"/>
<source>Show POI labels</source> <source>Show POI labels</source>
<translation>Показать подписи к точкам POI</translation> <translation>Показать подписи к точкам POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="257"/> <location filename="../src/GUI/gui.cpp" line="261"/>
<source>Show POIs</source> <source>Show POIs</source>
<translation>Показать точки POI</translation> <translation>Показать точки POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="266"/> <location filename="../src/GUI/gui.cpp" line="270"/>
<source>Show map</source> <source>Show map</source>
<translation>Показать карту</translation> <translation>Показать карту</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="276"/> <location filename="../src/GUI/gui.cpp" line="280"/>
<source>Clear tile cache</source> <source>Clear tile cache</source>
<translation>Очистить кэш</translation> <translation>Очистить кэш</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="213"/> <location filename="../src/GUI/gui.cpp" line="217"/>
<source>Open...</source> <source>Open...</source>
<translation>Открыть...</translation> <translation>Открыть...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="202"/> <location filename="../src/GUI/gui.cpp" line="206"/>
<location filename="../src/GUI/gui.cpp" line="639"/> <location filename="../src/GUI/gui.cpp" line="643"/>
<location filename="../src/GUI/gui.cpp" line="640"/> <location filename="../src/GUI/gui.cpp" line="644"/>
<source>Paths</source> <source>Paths</source>
<translation>Пути</translation> <translation>Пути</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="243"/> <location filename="../src/GUI/gui.cpp" line="247"/>
<source>Load POI file...</source> <source>Load POI file...</source>
<translation>Загрузить файл с точками POI...</translation> <translation>Загрузить файл с точками POI...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="274"/> <location filename="../src/GUI/gui.cpp" line="278"/>
<source>Load map...</source> <source>Load map...</source>
<translation>Загрузить карту...</translation> <translation>Загрузить карту...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="280"/>
<location filename="../src/GUI/gui.cpp" line="284"/> <location filename="../src/GUI/gui.cpp" line="284"/>
<location filename="../src/GUI/gui.cpp" line="622"/> <location filename="../src/GUI/gui.cpp" line="288"/>
<location filename="../src/GUI/gui.cpp" line="626"/>
<source>Next map</source> <source>Next map</source>
<translation>Следующая карта</translation> <translation>Следующая карта</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="294"/> <location filename="../src/GUI/gui.cpp" line="298"/>
<source>Show tracks</source> <source>Show tracks</source>
<translation>Показать треки</translation> <translation>Показать треки</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="298"/> <location filename="../src/GUI/gui.cpp" line="302"/>
<source>Show routes</source> <source>Show routes</source>
<translation>Показать маршруты</translation> <translation>Показать маршруты</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="302"/> <location filename="../src/GUI/gui.cpp" line="306"/>
<source>Show waypoints</source> <source>Show waypoints</source>
<translation>Показать точки</translation> <translation>Показать точки</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="306"/> <location filename="../src/GUI/gui.cpp" line="310"/>
<source>Waypoint labels</source> <source>Waypoint labels</source>
<translation>Подписи точек</translation> <translation>Подписи точек</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="317"/> <location filename="../src/GUI/gui.cpp" line="321"/>
<source>Show graphs</source> <source>Show graphs</source>
<translation>Показать графики</translation> <translation>Показать графики</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="337"/> <location filename="../src/GUI/gui.cpp" line="341"/>
<source>Show grid</source> <source>Show grid</source>
<translation>Показать сетку</translation> <translation>Показать сетку</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="341"/> <location filename="../src/GUI/gui.cpp" line="345"/>
<source>Show slider info</source> <source>Show slider info</source>
<translation>Показать значение на слайдере</translation> <translation>Показать значение на слайдере</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="347"/> <location filename="../src/GUI/gui.cpp" line="351"/>
<source>Show toolbars</source> <source>Show toolbars</source>
<translation>Показывать панели инструментов</translation> <translation>Показывать панели инструментов</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="353"/> <location filename="../src/GUI/gui.cpp" line="357"/>
<source>Total time</source> <source>Total time</source>
<translation>Общее время</translation> <translation>Общее время</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="358"/> <location filename="../src/GUI/gui.cpp" line="362"/>
<location filename="../src/GUI/gui.cpp" line="926"/> <location filename="../src/GUI/gui.cpp" line="934"/>
<source>Moving time</source> <source>Moving time</source>
<translation>Время движения</translation> <translation>Время движения</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="365"/> <location filename="../src/GUI/gui.cpp" line="369"/>
<source>Metric</source> <source>Metric</source>
<translation>Метрические</translation> <translation>Метрические</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="370"/> <location filename="../src/GUI/gui.cpp" line="374"/>
<source>Imperial</source> <source>Imperial</source>
<translation>Британские</translation> <translation>Британские</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="375"/> <location filename="../src/GUI/gui.cpp" line="379"/>
<source>Nautical</source> <source>Nautical</source>
<translation>Морские</translation> <translation>Морские</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="382"/> <location filename="../src/GUI/gui.cpp" line="386"/>
<source>Decimal degrees (DD)</source> <source>Decimal degrees (DD)</source>
<translation>Десятичные градусы (DD)</translation> <translation>Десятичные градусы (DD)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="387"/> <location filename="../src/GUI/gui.cpp" line="391"/>
<source>Degrees and decimal minutes (DMM)</source> <source>Degrees and decimal minutes (DMM)</source>
<translation>Градусы, десятичные минуты (DMM)</translation> <translation>Градусы, десятичные минуты (DMM)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="393"/> <location filename="../src/GUI/gui.cpp" line="397"/>
<source>Degrees, minutes, seconds (DMS)</source> <source>Degrees, minutes, seconds (DMS)</source>
<translation>Градусы, минуты, секунды (DMS)</translation> <translation>Градусы, минуты, секунды (DMS)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="398"/> <location filename="../src/GUI/gui.cpp" line="402"/>
<source>Fullscreen mode</source> <source>Fullscreen mode</source>
<translation>Полноэкранный режим</translation> <translation>Полноэкранный режим</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="404"/> <location filename="../src/GUI/gui.cpp" line="408"/>
<source>Options...</source> <source>Options...</source>
<translation>Параметры...</translation> <translation>Параметры...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="410"/> <location filename="../src/GUI/gui.cpp" line="414"/>
<source>Next</source> <source>Next</source>
<translation>Следующий</translation> <translation>Следующий</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="413"/> <location filename="../src/GUI/gui.cpp" line="417"/>
<source>Previous</source> <source>Previous</source>
<translation>Предыдущий</translation> <translation>Предыдущий</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="417"/> <location filename="../src/GUI/gui.cpp" line="421"/>
<source>Last</source> <source>Last</source>
<translation>Последний</translation> <translation>Последний</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="420"/> <location filename="../src/GUI/gui.cpp" line="424"/>
<source>First</source> <source>First</source>
<translation>Первый</translation> <translation>Первый</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="442"/> <location filename="../src/GUI/gui.cpp" line="464"/>
<source>Map</source>
<translation>Карты</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="450"/>
<source>Graph</source>
<translation>График</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="459"/>
<source>POI</source>
<translation>Точки POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="460"/>
<source>POI files</source> <source>POI files</source>
<translation>Файлы с точками POI</translation> <translation>Файлы с точками POI</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="471"/> <location filename="../src/GUI/gui.cpp" line="476"/>
<source>Data</source>
<translation>Данные</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="472"/>
<source>Display</source> <source>Display</source>
<translation>Отображать</translation> <translation>Отображать</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="480"/> <location filename="../src/GUI/gui.cpp" line="488"/>
<source>Settings</source>
<translation>Параметры</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="484"/>
<source>Units</source> <source>Units</source>
<translation>Единицы</translation> <translation>Единицы</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="488"/> <location filename="../src/GUI/gui.cpp" line="492"/>
<source>Coordinates format</source> <source>Coordinates format</source>
<translation>Формат координат</translation> <translation>Формат координат</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="498"/> <location filename="../src/GUI/gui.cpp" line="619"/>
<source>Help</source>
<translation>Справка</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="615"/>
<source>Append file</source> <source>Append file</source>
<translation>Добавить файл</translation> <translation>Добавить файл</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="616"/> <location filename="../src/GUI/gui.cpp" line="620"/>
<source>Next/Previous</source> <source>Next/Previous</source>
<translation>Next/Previous</translation> <translation>Next/Previous</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="618"/> <location filename="../src/GUI/gui.cpp" line="622"/>
<source>Toggle graph type</source> <source>Toggle graph type</source>
<translation>Переключить тип графика</translation> <translation>Переключить тип графика</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="620"/> <location filename="../src/GUI/gui.cpp" line="624"/>
<source>Toggle time type</source> <source>Toggle time type</source>
<translation>Переключить тип времени</translation> <translation>Переключить тип времени</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="624"/> <location filename="../src/GUI/gui.cpp" line="628"/>
<source>Previous map</source> <source>Previous map</source>
<translation>Предыдущая карта</translation> <translation>Предыдущая карта</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="625"/> <location filename="../src/GUI/gui.cpp" line="629"/>
<source>Zoom in</source> <source>Zoom in</source>
<translation>Увеличить</translation> <translation>Увеличить</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="627"/> <location filename="../src/GUI/gui.cpp" line="631"/>
<source>Zoom out</source> <source>Zoom out</source>
<translation>Уменьшить</translation> <translation>Уменьшить</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="629"/> <location filename="../src/GUI/gui.cpp" line="633"/>
<source>Digital zoom</source> <source>Digital zoom</source>
<translation>Цифровой зум</translation> <translation>Цифровой зум</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="630"/> <location filename="../src/GUI/gui.cpp" line="634"/>
<source>Zoom</source> <source>Zoom</source>
<translation>Zoom</translation> <translation>Zoom</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1127"/> <location filename="../src/GUI/gui.cpp" line="1135"/>
<source>Open map file</source> <source>Open map file</source>
<translation>Открыть файл карты</translation> <translation>Открыть файл карты</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1165"/> <location filename="../src/GUI/gui.cpp" line="1175"/>
<source>No files loaded</source> <source>No files loaded</source>
<translation>Нет загруженных файлов</translation> <translation>Нет загруженных файлов</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="912"/> <location filename="../src/GUI/gui.cpp" line="920"/>
<location filename="../src/GUI/gui.cpp" line="915"/> <location filename="../src/GUI/gui.cpp" line="923"/>
<source>Date</source> <source>Date</source>
<translation>Дата</translation> <translation>Дата</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="643"/> <location filename="../src/GUI/gui.cpp" line="432"/>
<source>&amp;File</source>
<translation>&amp;Файл</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="446"/>
<source>&amp;Map</source>
<translation>&amp;Карты</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="454"/>
<source>&amp;Graph</source>
<translation>&amp;График</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="463"/>
<source>&amp;POI</source>
<translation>&amp;Точки POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="475"/>
<source>&amp;Data</source>
<translation>&amp;Данные</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="484"/>
<source>&amp;Settings</source>
<translation>&amp;Параметры</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="502"/>
<source>&amp;Help</source>
<translation>&amp;Справка</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="647"/>
<source>Map directory:</source> <source>Map directory:</source>
<translation>Директория с картами:</translation> <translation>Директория с картами:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="645"/> <location filename="../src/GUI/gui.cpp" line="649"/>
<source>POI directory:</source> <source>POI directory:</source>
<translation>Директория с POI:</translation> <translation>Директория с POI:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="647"/> <location filename="../src/GUI/gui.cpp" line="651"/>
<source>GCS file:</source> <source>GCS file:</source>
<translation>GCS файл:</translation> <translation>GCS файл:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="648"/> <location filename="../src/GUI/gui.cpp" line="652"/>
<source>PCS file:</source> <source>PCS file:</source>
<translation>PCS файл:</translation> <translation>PCS файл:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="650"/> <location filename="../src/GUI/gui.cpp" line="654"/>
<source>Ellipsoids file:</source> <source>Ellipsoids file:</source>
<translation>Ellipsoids файл:</translation> <translation>Ellipsoids файл:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="653"/> <location filename="../src/GUI/gui.cpp" line="657"/>
<source>User override directory:</source> <source>User override directory:</source>
<translation>Каталог пользовательских настроек:</translation> <translation>Каталог пользовательских настроек:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="904"/> <location filename="../src/GUI/gui.cpp" line="912"/>
<source>Routes</source> <source>Routes</source>
<translation>Маршруты</translation> <translation>Маршруты</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1154"/> <location filename="../src/GUI/gui.cpp" line="1164"/>
<source>Error loading map:</source> <source>Error loading map:</source>
<translation>Ошибка загрузки карты:</translation> <translation>Ошибка загрузки карты:</translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location filename="../src/GUI/gui.cpp" line="1169"/> <location filename="../src/GUI/gui.cpp" line="1179"/>
<source>%n files</source> <source>%n files</source>
<translation> <translation>
<numerusform>%n файл</numerusform> <numerusform>%n файл</numerusform>
@ -679,97 +683,97 @@
</translation> </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="609"/> <location filename="../src/GUI/gui.cpp" line="613"/>
<source>Next file</source> <source>Next file</source>
<translation>Следующий файл</translation> <translation>Следующий файл</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="585"/> <location filename="../src/GUI/gui.cpp" line="589"/>
<source>Version </source> <source>Version </source>
<translation>Версия </translation> <translation>Версия </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="218"/> <location filename="../src/GUI/gui.cpp" line="222"/>
<source>Print...</source> <source>Print...</source>
<translation>Печать...</translation> <translation>Печать...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="223"/> <location filename="../src/GUI/gui.cpp" line="227"/>
<source>Export to PDF...</source> <source>Export to PDF...</source>
<translation>Экспорт в PDF...</translation> <translation>Экспорт в PDF...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="906"/> <location filename="../src/GUI/gui.cpp" line="914"/>
<source>Waypoints</source> <source>Waypoints</source>
<translation>Точки</translation> <translation>Точки</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="610"/> <location filename="../src/GUI/gui.cpp" line="614"/>
<source>Previous file</source> <source>Previous file</source>
<translation>Предыдущий файл</translation> <translation>Предыдущий файл</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="310"/> <location filename="../src/GUI/gui.cpp" line="314"/>
<source>Route waypoints</source> <source>Route waypoints</source>
<translation>Маршрутные точки</translation> <translation>Маршрутные точки</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="612"/> <location filename="../src/GUI/gui.cpp" line="616"/>
<source>First file</source> <source>First file</source>
<translation>Первый файл</translation> <translation>Первый файл</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="614"/> <location filename="../src/GUI/gui.cpp" line="618"/>
<source>Last file</source> <source>Last file</source>
<translation>Последний файл</translation> <translation>Последний файл</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="740"/> <location filename="../src/GUI/gui.cpp" line="746"/>
<source>Error loading data file:</source> <source>Error loading data file:</source>
<translation>Ошибка загрузки файла данных:</translation> <translation>Ошибка загрузки файла данных:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="743"/> <location filename="../src/GUI/gui.cpp" line="749"/>
<location filename="../src/GUI/gui.cpp" line="768"/> <location filename="../src/GUI/gui.cpp" line="776"/>
<source>Line: %1</source> <source>Line: %1</source>
<translation>Строка: %1</translation> <translation>Строка: %1</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="765"/> <location filename="../src/GUI/gui.cpp" line="773"/>
<source>Error loading POI file:</source> <source>Error loading POI file:</source>
<translation>Ошибка загрузки файла с точками POI:</translation> <translation>Ошибка загрузки файла с точками POI:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="898"/> <location filename="../src/GUI/gui.cpp" line="906"/>
<source>Name</source> <source>Name</source>
<translation>Имя</translation> <translation>Имя</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="902"/> <location filename="../src/GUI/gui.cpp" line="910"/>
<source>Tracks</source> <source>Tracks</source>
<translation>Треки</translation> <translation>Треки</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="207"/> <location filename="../src/GUI/gui.cpp" line="211"/>
<location filename="../src/GUI/gui.cpp" line="584"/> <location filename="../src/GUI/gui.cpp" line="588"/>
<source>About GPXSee</source> <source>About GPXSee</source>
<translation>О GPXSee</translation> <translation>О GPXSee</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="522"/> <location filename="../src/GUI/gui.cpp" line="526"/>
<source>Navigation</source> <source>Navigation</source>
<translation>Навигация</translation> <translation>Навигация</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="325"/> <location filename="../src/GUI/gui.cpp" line="329"/>
<location filename="../src/GUI/gui.cpp" line="922"/> <location filename="../src/GUI/gui.cpp" line="930"/>
<source>Distance</source> <source>Distance</source>
<translation>Расстояние</translation> <translation>Расстояние</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="331"/> <location filename="../src/GUI/gui.cpp" line="335"/>
<location filename="../src/GUI/gui.cpp" line="481"/> <location filename="../src/GUI/gui.cpp" line="485"/>
<location filename="../src/GUI/gui.cpp" line="924"/> <location filename="../src/GUI/gui.cpp" line="932"/>
<source>Time</source> <source>Time</source>
<translation>Время</translation> <translation>Время</translation>
</message> </message>
@ -875,27 +879,27 @@
<context> <context>
<name>MapList</name> <name>MapList</name>
<message> <message>
<location filename="../src/map/maplist.cpp" line="131"/> <location filename="../src/map/maplist.cpp" line="130"/>
<source>Supported files</source> <source>Supported files</source>
<translation>Все поддерживаемые файлы</translation> <translation>Все поддерживаемые файлы</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="132"/> <location filename="../src/map/maplist.cpp" line="131"/>
<source>OziExplorer maps</source> <source>OziExplorer maps</source>
<translation>OziExplorer карты</translation> <translation>OziExplorer карты</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="133"/> <location filename="../src/map/maplist.cpp" line="132"/>
<source>TrekBuddy maps/atlases</source> <source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy карты/атласы</translation> <translation>TrekBuddy карты/атласы</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="134"/> <location filename="../src/map/maplist.cpp" line="133"/>
<source>GeoTIFF images</source> <source>GeoTIFF images</source>
<translation>GeoTIFF изображения</translation> <translation>GeoTIFF изображения</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="135"/> <location filename="../src/map/maplist.cpp" line="134"/>
<source>Online map sources</source> <source>Online map sources</source>
<translation>Источники онлайн карт</translation> <translation>Источники онлайн карт</translation>
</message> </message>
@ -1380,33 +1384,53 @@
<context> <context>
<name>SpeedGraph</name> <name>SpeedGraph</name>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="14"/> <location filename="../src/GUI/speedgraph.cpp" line="16"/>
<location filename="../src/GUI/speedgraph.h" line="14"/> <location filename="../src/GUI/speedgraph.h" line="14"/>
<source>Speed</source> <source>Speed</source>
<translation>Скорость</translation> <translation>Скорость</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="89"/> <location filename="../src/GUI/speedgraph.cpp" line="96"/>
<source>km/h</source> <source>km/h</source>
<translation>км/ч</translation> <translation>км/ч</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="22"/> <location filename="../src/GUI/speedgraph.cpp" line="28"/>
<source>Average</source> <source>Average</source>
<translation>Cреднее</translation> <translation>Cреднее</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="24"/> <location filename="../src/GUI/speedgraph.cpp" line="25"/>
<source>min/km</source>
<translation>мин/км</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="26"/>
<source>min/mi</source>
<translation>мин/мл</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="26"/>
<source>min/nmi</source>
<translation>мин/мор.мл</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="30"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Максимум</translation> <translation>Максимум</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="83"/> <location filename="../src/GUI/speedgraph.cpp" line="32"/>
<source>Pace</source>
<translation>Темп</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="90"/>
<source>kn</source> <source>kn</source>
<translation>уз</translation> <translation>уз</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="86"/> <location filename="../src/GUI/speedgraph.cpp" line="93"/>
<source>mi/h</source> <source>mi/h</source>
<translation>мл/ч</translation> <translation>мл/ч</translation>
</message> </message>
@ -1414,30 +1438,50 @@
<context> <context>
<name>SpeedGraphItem</name> <name>SpeedGraphItem</name>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="22"/> <location filename="../src/GUI/speedgraphitem.cpp" line="23"/>
<source>km/h</source> <source>km/h</source>
<translation>км/ч</translation> <translation>км/ч</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="21"/> <location filename="../src/GUI/speedgraphitem.cpp" line="22"/>
<source>mi/h</source> <source>mi/h</source>
<translation>мл/ч</translation> <translation>мл/ч</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="22"/> <location filename="../src/GUI/speedgraphitem.cpp" line="23"/>
<source>kn</source> <source>kn</source>
<translation>уз</translation> <translation>уз</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="24"/> <location filename="../src/GUI/speedgraphitem.cpp" line="26"/>
<source>min/km</source>
<translation>мин/км</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="27"/>
<source>min/mi</source>
<translation>мин/мл</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="27"/>
<source>min/nmi</source>
<translation>мин/мор.мл</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="29"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Максимум</translation> <translation>Максимум</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="26"/> <location filename="../src/GUI/speedgraphitem.cpp" line="31"/>
<source>Average</source> <source>Average</source>
<translation>Cреднее</translation> <translation>Cреднее</translation>
</message> </message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="33"/>
<source>Pace</source>
<translation>Темп</translation>
</message>
</context> </context>
<context> <context>
<name>TemperatureGraph</name> <name>TemperatureGraph</name>

View File

@ -301,365 +301,334 @@
<context> <context>
<name>GUI</name> <name>GUI</name>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="588"/> <location filename="../src/GUI/gui.cpp" line="592"/>
<source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source> <source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source>
<translation>GPXSee distribueras under vilkoren för GNU General Public License version 3. För mer info om GPXSee, besök hemsidan </translation> <translation>GPXSee distribueras under vilkoren för GNU General Public License version 3. För mer info om GPXSee, besök hemsidan </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="643"/> <location filename="../src/GUI/gui.cpp" line="647"/>
<source>Map directory:</source> <source>Map directory:</source>
<translation>Kartmapp:</translation> <translation>Kartmapp:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="645"/> <location filename="../src/GUI/gui.cpp" line="649"/>
<source>POI directory:</source> <source>POI directory:</source>
<translation>POI-mapp:</translation> <translation>POI-mapp:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="647"/> <location filename="../src/GUI/gui.cpp" line="651"/>
<source>GCS file:</source> <source>GCS file:</source>
<translation>GCS-fil:</translation> <translation>GCS-fil:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="648"/> <location filename="../src/GUI/gui.cpp" line="652"/>
<source>PCS file:</source> <source>PCS file:</source>
<translation>PCS-fil:</translation> <translation>PCS-fil:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="650"/> <location filename="../src/GUI/gui.cpp" line="654"/>
<source>Ellipsoids file:</source> <source>Ellipsoids file:</source>
<translation>Ellipsoids-fil:</translation> <translation>Ellipsoids-fil:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="653"/> <location filename="../src/GUI/gui.cpp" line="657"/>
<source>User override directory:</source> <source>User override directory:</source>
<translation>Användarspecificerad mapp:</translation> <translation>Användarspecificerad mapp:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="662"/> <location filename="../src/GUI/gui.cpp" line="666"/>
<source>Open file</source> <source>Open file</source>
<translation>Öppna fil</translation> <translation>Öppna fil</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="751"/> <location filename="../src/GUI/gui.cpp" line="757"/>
<source>Open POI file</source> <source>Open POI file</source>
<translation>Öppna POI-fil</translation> <translation>Öppna POI-fil</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="195"/> <location filename="../src/GUI/gui.cpp" line="199"/>
<source>Quit</source> <source>Quit</source>
<translation>Avsluta</translation> <translation>Avsluta</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="204"/> <location filename="../src/GUI/gui.cpp" line="208"/>
<location filename="../src/GUI/gui.cpp" line="605"/> <location filename="../src/GUI/gui.cpp" line="609"/>
<location filename="../src/GUI/gui.cpp" line="606"/> <location filename="../src/GUI/gui.cpp" line="610"/>
<source>Keyboard controls</source> <source>Keyboard controls</source>
<translation>Snabbtangenter</translation> <translation>Snabbtangenter</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="229"/> <location filename="../src/GUI/gui.cpp" line="233"/>
<source>Close</source> <source>Close</source>
<translation>Stäng</translation> <translation>Stäng</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="235"/> <location filename="../src/GUI/gui.cpp" line="239"/>
<source>Reload</source> <source>Reload</source>
<translation>Uppdatera</translation> <translation>Uppdatera</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="517"/> <location filename="../src/GUI/gui.cpp" line="521"/>
<source>Show</source> <source>Show</source>
<translation>Visa</translation> <translation>Visa</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="428"/> <location filename="../src/GUI/gui.cpp" line="515"/>
<location filename="../src/GUI/gui.cpp" line="511"/>
<source>File</source> <source>File</source>
<translation>Arkiv</translation> <translation>Arkiv</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="246"/> <location filename="../src/GUI/gui.cpp" line="250"/>
<source>Close POI files</source> <source>Close POI files</source>
<translation>Stäng POI-filer</translation> <translation>Stäng POI-filer</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="248"/> <location filename="../src/GUI/gui.cpp" line="252"/>
<source>Overlap POIs</source> <source>Overlap POIs</source>
<translation>Överlappa POI:er</translation> <translation>Överlappa POI:er</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="252"/> <location filename="../src/GUI/gui.cpp" line="256"/>
<source>Show POI labels</source> <source>Show POI labels</source>
<translation>Visa POI-namn</translation> <translation>Visa POI-namn</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="257"/> <location filename="../src/GUI/gui.cpp" line="261"/>
<source>Show POIs</source> <source>Show POIs</source>
<translation>Visa POI:er</translation> <translation>Visa POI:er</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="266"/> <location filename="../src/GUI/gui.cpp" line="270"/>
<source>Show map</source> <source>Show map</source>
<translation>Visa karta</translation> <translation>Visa karta</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="276"/> <location filename="../src/GUI/gui.cpp" line="280"/>
<source>Clear tile cache</source> <source>Clear tile cache</source>
<translation>Rensa kart-cache</translation> <translation>Rensa kart-cache</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="213"/> <location filename="../src/GUI/gui.cpp" line="217"/>
<source>Open...</source> <source>Open...</source>
<translation>Öppna...</translation> <translation>Öppna...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="202"/> <location filename="../src/GUI/gui.cpp" line="206"/>
<location filename="../src/GUI/gui.cpp" line="639"/> <location filename="../src/GUI/gui.cpp" line="643"/>
<location filename="../src/GUI/gui.cpp" line="640"/> <location filename="../src/GUI/gui.cpp" line="644"/>
<source>Paths</source> <source>Paths</source>
<translation type="unfinished">Sökvägar</translation> <translation>Sökvägar</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="243"/> <location filename="../src/GUI/gui.cpp" line="247"/>
<source>Load POI file...</source> <source>Load POI file...</source>
<translation>Läs in POI-fil...</translation> <translation>Läs in POI-fil...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="274"/> <location filename="../src/GUI/gui.cpp" line="278"/>
<source>Load map...</source> <source>Load map...</source>
<translation>Läs in karta...</translation> <translation>Läs in karta...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="280"/>
<location filename="../src/GUI/gui.cpp" line="284"/> <location filename="../src/GUI/gui.cpp" line="284"/>
<location filename="../src/GUI/gui.cpp" line="622"/> <location filename="../src/GUI/gui.cpp" line="288"/>
<location filename="../src/GUI/gui.cpp" line="626"/>
<source>Next map</source> <source>Next map</source>
<translation>Nästa karta</translation> <translation>Nästa karta</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="294"/> <location filename="../src/GUI/gui.cpp" line="298"/>
<source>Show tracks</source> <source>Show tracks</source>
<translation>Visa spår</translation> <translation>Visa spår</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="298"/> <location filename="../src/GUI/gui.cpp" line="302"/>
<source>Show routes</source> <source>Show routes</source>
<translation>Visa rutter</translation> <translation>Visa rutter</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="302"/> <location filename="../src/GUI/gui.cpp" line="306"/>
<source>Show waypoints</source> <source>Show waypoints</source>
<translation>Visa vägpunkter</translation> <translation>Visa vägpunkter</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="306"/> <location filename="../src/GUI/gui.cpp" line="310"/>
<source>Waypoint labels</source> <source>Waypoint labels</source>
<translation>Vägpunktsnamn</translation> <translation>Vägpunktsnamn</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="317"/> <location filename="../src/GUI/gui.cpp" line="321"/>
<source>Show graphs</source> <source>Show graphs</source>
<translation>Visa diagram</translation> <translation>Visa diagram</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="337"/> <location filename="../src/GUI/gui.cpp" line="341"/>
<source>Show grid</source> <source>Show grid</source>
<translation>Visa stödlinjer</translation> <translation>Visa stödlinjer</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="341"/> <location filename="../src/GUI/gui.cpp" line="345"/>
<source>Show slider info</source> <source>Show slider info</source>
<translation>Visa reglageinfo</translation> <translation>Visa reglageinfo</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="347"/> <location filename="../src/GUI/gui.cpp" line="351"/>
<source>Show toolbars</source> <source>Show toolbars</source>
<translation>Visa verktygsfält</translation> <translation>Visa verktygsfält</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="353"/> <location filename="../src/GUI/gui.cpp" line="357"/>
<source>Total time</source> <source>Total time</source>
<translation>Total tid</translation> <translation>Total tid</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="358"/> <location filename="../src/GUI/gui.cpp" line="362"/>
<location filename="../src/GUI/gui.cpp" line="926"/> <location filename="../src/GUI/gui.cpp" line="934"/>
<source>Moving time</source> <source>Moving time</source>
<translation>Förflyttningstid</translation> <translation>Förflyttningstid</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="365"/> <location filename="../src/GUI/gui.cpp" line="369"/>
<source>Metric</source> <source>Metric</source>
<translation>Meter</translation> <translation>Meter</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="370"/> <location filename="../src/GUI/gui.cpp" line="374"/>
<source>Imperial</source> <source>Imperial</source>
<translation>Imperial</translation> <translation>Imperial</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="375"/> <location filename="../src/GUI/gui.cpp" line="379"/>
<source>Nautical</source> <source>Nautical</source>
<translation>Nautiska</translation> <translation>Nautiska</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="382"/> <location filename="../src/GUI/gui.cpp" line="386"/>
<source>Decimal degrees (DD)</source> <source>Decimal degrees (DD)</source>
<translation>Decimala grader (DD)</translation> <translation>Decimala grader (DD)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="387"/> <location filename="../src/GUI/gui.cpp" line="391"/>
<source>Degrees and decimal minutes (DMM)</source> <source>Degrees and decimal minutes (DMM)</source>
<translation>Grader och decimala minuter (DMM)</translation> <translation>Grader och decimala minuter (DMM)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="393"/> <location filename="../src/GUI/gui.cpp" line="397"/>
<source>Degrees, minutes, seconds (DMS)</source> <source>Degrees, minutes, seconds (DMS)</source>
<translation>Grader, minuter, sekunder (DMS)</translation> <translation>Grader, minuter, sekunder (DMS)</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="398"/> <location filename="../src/GUI/gui.cpp" line="402"/>
<source>Fullscreen mode</source> <source>Fullscreen mode</source>
<translation>Helskärmsläge</translation> <translation>Helskärmsläge</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="404"/> <location filename="../src/GUI/gui.cpp" line="408"/>
<source>Options...</source> <source>Options...</source>
<translation>Alternativ...</translation> <translation>Alternativ...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="410"/> <location filename="../src/GUI/gui.cpp" line="414"/>
<source>Next</source> <source>Next</source>
<translation>Nästa</translation> <translation>Nästa</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="413"/> <location filename="../src/GUI/gui.cpp" line="417"/>
<source>Previous</source> <source>Previous</source>
<translation>Föregående</translation> <translation>Föregående</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="417"/> <location filename="../src/GUI/gui.cpp" line="421"/>
<source>Last</source> <source>Last</source>
<translation>Sista</translation> <translation>Sista</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="420"/> <location filename="../src/GUI/gui.cpp" line="424"/>
<source>First</source> <source>First</source>
<translation>Första</translation> <translation>Första</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="442"/> <location filename="../src/GUI/gui.cpp" line="464"/>
<source>Map</source>
<translation>Karta</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="450"/>
<source>Graph</source>
<translation>Diagram</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="459"/>
<source>POI</source>
<translation>POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="460"/>
<source>POI files</source> <source>POI files</source>
<translation>POI-filer</translation> <translation>POI-filer</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="471"/> <location filename="../src/GUI/gui.cpp" line="476"/>
<source>Data</source>
<translation>Data</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="472"/>
<source>Display</source> <source>Display</source>
<translation>Visa</translation> <translation>Visa</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="480"/> <location filename="../src/GUI/gui.cpp" line="488"/>
<source>Settings</source>
<translation>Inställningar</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="484"/>
<source>Units</source> <source>Units</source>
<translation>Enhet</translation> <translation>Enhet</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="488"/> <location filename="../src/GUI/gui.cpp" line="492"/>
<source>Coordinates format</source> <source>Coordinates format</source>
<translation>Koordinatformat</translation> <translation>Koordinatformat</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="498"/> <location filename="../src/GUI/gui.cpp" line="619"/>
<source>Help</source>
<translation>Hjälp</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="615"/>
<source>Append file</source> <source>Append file</source>
<translation>Lägg till fil</translation> <translation>Lägg till fil</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="616"/> <location filename="../src/GUI/gui.cpp" line="620"/>
<source>Next/Previous</source> <source>Next/Previous</source>
<translation>Nästa/Föregående</translation> <translation>Nästa/Föregående</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="618"/> <location filename="../src/GUI/gui.cpp" line="622"/>
<source>Toggle graph type</source> <source>Toggle graph type</source>
<translation>Växla diagramtyp</translation> <translation>Växla diagramtyp</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="620"/> <location filename="../src/GUI/gui.cpp" line="624"/>
<source>Toggle time type</source> <source>Toggle time type</source>
<translation>Växla tidstyp</translation> <translation>Växla tidstyp</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="624"/> <location filename="../src/GUI/gui.cpp" line="628"/>
<source>Previous map</source> <source>Previous map</source>
<translation>Föregående karta</translation> <translation>Föregående karta</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="625"/> <location filename="../src/GUI/gui.cpp" line="629"/>
<source>Zoom in</source> <source>Zoom in</source>
<translation>Zooma in</translation> <translation>Zooma in</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="627"/> <location filename="../src/GUI/gui.cpp" line="631"/>
<source>Zoom out</source> <source>Zoom out</source>
<translation>Zooma ut</translation> <translation>Zooma ut</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="629"/> <location filename="../src/GUI/gui.cpp" line="633"/>
<source>Digital zoom</source> <source>Digital zoom</source>
<translation>Digital zoom</translation> <translation>Digital zoom</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="630"/> <location filename="../src/GUI/gui.cpp" line="634"/>
<source>Zoom</source> <source>Zoom</source>
<translation>Zoom</translation> <translation>Zoom</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1127"/> <location filename="../src/GUI/gui.cpp" line="1135"/>
<source>Open map file</source> <source>Open map file</source>
<translation>Öppna kartfil</translation> <translation>Öppna kartfil</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1154"/> <location filename="../src/GUI/gui.cpp" line="1164"/>
<source>Error loading map:</source> <source>Error loading map:</source>
<translation>Fel vid inläsning av karta:</translation> <translation>Fel vid inläsning av karta:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="1165"/> <location filename="../src/GUI/gui.cpp" line="1175"/>
<source>No files loaded</source> <source>No files loaded</source>
<translation>Inga filer inlästa</translation> <translation>Inga filer inlästa</translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location filename="../src/GUI/gui.cpp" line="1169"/> <location filename="../src/GUI/gui.cpp" line="1179"/>
<source>%n files</source> <source>%n files</source>
<translation> <translation>
<numerusform>%n filer</numerusform> <numerusform>%n filer</numerusform>
@ -667,108 +636,143 @@
</translation> </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="912"/> <location filename="../src/GUI/gui.cpp" line="920"/>
<location filename="../src/GUI/gui.cpp" line="915"/> <location filename="../src/GUI/gui.cpp" line="923"/>
<source>Date</source> <source>Date</source>
<translation>Datum</translation> <translation>Datum</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="904"/> <location filename="../src/GUI/gui.cpp" line="912"/>
<source>Routes</source> <source>Routes</source>
<translation>Rutter</translation> <translation>Rutter</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="609"/> <location filename="../src/GUI/gui.cpp" line="613"/>
<source>Next file</source> <source>Next file</source>
<translation>Nästa fil</translation> <translation>Nästa fil</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="585"/> <location filename="../src/GUI/gui.cpp" line="589"/>
<source>Version </source> <source>Version </source>
<translation>Version </translation> <translation>Version </translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="218"/> <location filename="../src/GUI/gui.cpp" line="222"/>
<source>Print...</source> <source>Print...</source>
<translation>Skriv ut...</translation> <translation>Skriv ut...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="223"/> <location filename="../src/GUI/gui.cpp" line="227"/>
<source>Export to PDF...</source> <source>Export to PDF...</source>
<translation>Exportera till PDF...</translation> <translation>Exportera till PDF...</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="906"/> <location filename="../src/GUI/gui.cpp" line="914"/>
<source>Waypoints</source> <source>Waypoints</source>
<translation>Vägpunkter</translation> <translation>Vägpunkter</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="610"/> <location filename="../src/GUI/gui.cpp" line="614"/>
<source>Previous file</source> <source>Previous file</source>
<translation>Föregående fil</translation> <translation>Föregående fil</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="310"/> <location filename="../src/GUI/gui.cpp" line="314"/>
<source>Route waypoints</source> <source>Route waypoints</source>
<translation>Ruttvägpunkter</translation> <translation>Ruttvägpunkter</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="612"/> <location filename="../src/GUI/gui.cpp" line="432"/>
<source>&amp;File</source>
<translation>&amp;Arkiv</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="446"/>
<source>&amp;Map</source>
<translation>&amp;Karta</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="454"/>
<source>&amp;Graph</source>
<translation>&amp;Diagram</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="463"/>
<source>&amp;POI</source>
<translation>&amp;POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="475"/>
<source>&amp;Data</source>
<translation>Da&amp;ta</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="484"/>
<source>&amp;Settings</source>
<translation>&amp;Inställningar</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="502"/>
<source>&amp;Help</source>
<translation>&amp;Hjälp</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="616"/>
<source>First file</source> <source>First file</source>
<translation>Första filen</translation> <translation>Första filen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="614"/> <location filename="../src/GUI/gui.cpp" line="618"/>
<source>Last file</source> <source>Last file</source>
<translation>Sista filen</translation> <translation>Sista filen</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="740"/> <location filename="../src/GUI/gui.cpp" line="746"/>
<source>Error loading data file:</source> <source>Error loading data file:</source>
<translation>Fel vid inläsning av datafil:</translation> <translation>Fel vid inläsning av datafil:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="743"/> <location filename="../src/GUI/gui.cpp" line="749"/>
<location filename="../src/GUI/gui.cpp" line="768"/> <location filename="../src/GUI/gui.cpp" line="776"/>
<source>Line: %1</source> <source>Line: %1</source>
<translation>Rad: %1</translation> <translation>Rad: %1</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="765"/> <location filename="../src/GUI/gui.cpp" line="773"/>
<source>Error loading POI file:</source> <source>Error loading POI file:</source>
<translation>Fel vid inläsning av POI-fil:</translation> <translation>Fel vid inläsning av POI-fil:</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="898"/> <location filename="../src/GUI/gui.cpp" line="906"/>
<source>Name</source> <source>Name</source>
<translation>Namn</translation> <translation>Namn</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="902"/> <location filename="../src/GUI/gui.cpp" line="910"/>
<source>Tracks</source> <source>Tracks</source>
<translation>Spår</translation> <translation>Spår</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="207"/> <location filename="../src/GUI/gui.cpp" line="211"/>
<location filename="../src/GUI/gui.cpp" line="584"/> <location filename="../src/GUI/gui.cpp" line="588"/>
<source>About GPXSee</source> <source>About GPXSee</source>
<translation>Om GPXSee</translation> <translation>Om GPXSee</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="522"/> <location filename="../src/GUI/gui.cpp" line="526"/>
<source>Navigation</source> <source>Navigation</source>
<translation>Navigation</translation> <translation>Navigation</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="325"/> <location filename="../src/GUI/gui.cpp" line="329"/>
<location filename="../src/GUI/gui.cpp" line="922"/> <location filename="../src/GUI/gui.cpp" line="930"/>
<source>Distance</source> <source>Distance</source>
<translation>Avstånd</translation> <translation>Avstånd</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/gui.cpp" line="331"/> <location filename="../src/GUI/gui.cpp" line="335"/>
<location filename="../src/GUI/gui.cpp" line="481"/> <location filename="../src/GUI/gui.cpp" line="485"/>
<location filename="../src/GUI/gui.cpp" line="924"/> <location filename="../src/GUI/gui.cpp" line="932"/>
<source>Time</source> <source>Time</source>
<translation>Tid</translation> <translation>Tid</translation>
</message> </message>
@ -874,27 +878,27 @@
<context> <context>
<name>MapList</name> <name>MapList</name>
<message> <message>
<location filename="../src/map/maplist.cpp" line="131"/> <location filename="../src/map/maplist.cpp" line="130"/>
<source>Supported files</source> <source>Supported files</source>
<translation>Filer som stöds</translation> <translation>Filer som stöds</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="132"/> <location filename="../src/map/maplist.cpp" line="131"/>
<source>OziExplorer maps</source> <source>OziExplorer maps</source>
<translation>OziExplorer-kartor</translation> <translation>OziExplorer-kartor</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="133"/> <location filename="../src/map/maplist.cpp" line="132"/>
<source>TrekBuddy maps/atlases</source> <source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy-kartor/-atlaser</translation> <translation>TrekBuddy-kartor/-atlaser</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="134"/> <location filename="../src/map/maplist.cpp" line="133"/>
<source>GeoTIFF images</source> <source>GeoTIFF images</source>
<translation>GeoTIFF-bilder</translation> <translation>GeoTIFF-bilder</translation>
</message> </message>
<message> <message>
<location filename="../src/map/maplist.cpp" line="135"/> <location filename="../src/map/maplist.cpp" line="134"/>
<source>Online map sources</source> <source>Online map sources</source>
<translation>Online-kartkällor</translation> <translation>Online-kartkällor</translation>
</message> </message>
@ -1379,33 +1383,53 @@
<context> <context>
<name>SpeedGraph</name> <name>SpeedGraph</name>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="14"/> <location filename="../src/GUI/speedgraph.cpp" line="16"/>
<location filename="../src/GUI/speedgraph.h" line="14"/> <location filename="../src/GUI/speedgraph.h" line="14"/>
<source>Speed</source> <source>Speed</source>
<translation>Hastighet</translation> <translation>Hastighet</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="89"/> <location filename="../src/GUI/speedgraph.cpp" line="96"/>
<source>km/h</source> <source>km/h</source>
<translation>km/h</translation> <translation>km/h</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="22"/> <location filename="../src/GUI/speedgraph.cpp" line="28"/>
<source>Average</source> <source>Average</source>
<translation>Medel</translation> <translation>Medel</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="24"/> <location filename="../src/GUI/speedgraph.cpp" line="25"/>
<source>min/km</source>
<translation>min/km</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="26"/>
<source>min/mi</source>
<translation>min/mi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="26"/>
<source>min/nmi</source>
<translation>min/nmi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="30"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Max</translation> <translation>Max</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="83"/> <location filename="../src/GUI/speedgraph.cpp" line="32"/>
<source>Pace</source>
<translation>Tempo</translation>
</message>
<message>
<location filename="../src/GUI/speedgraph.cpp" line="90"/>
<source>kn</source> <source>kn</source>
<translation>knop</translation> <translation>knop</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraph.cpp" line="86"/> <location filename="../src/GUI/speedgraph.cpp" line="93"/>
<source>mi/h</source> <source>mi/h</source>
<translation>mi/h</translation> <translation>mi/h</translation>
</message> </message>
@ -1413,30 +1437,50 @@
<context> <context>
<name>SpeedGraphItem</name> <name>SpeedGraphItem</name>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="22"/> <location filename="../src/GUI/speedgraphitem.cpp" line="23"/>
<source>km/h</source> <source>km/h</source>
<translation>km/h</translation> <translation>km/h</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="21"/> <location filename="../src/GUI/speedgraphitem.cpp" line="22"/>
<source>mi/h</source> <source>mi/h</source>
<translation>mi/h</translation> <translation>mi/h</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="22"/> <location filename="../src/GUI/speedgraphitem.cpp" line="23"/>
<source>kn</source> <source>kn</source>
<translation>knop</translation> <translation>knop</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="24"/> <location filename="../src/GUI/speedgraphitem.cpp" line="26"/>
<source>min/km</source>
<translation>min/km</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="27"/>
<source>min/mi</source>
<translation>min/mi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="27"/>
<source>min/nmi</source>
<translation>min/nmi</translation>
</message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="29"/>
<source>Maximum</source> <source>Maximum</source>
<translation>Maximum</translation> <translation>Maximum</translation>
</message> </message>
<message> <message>
<location filename="../src/GUI/speedgraphitem.cpp" line="26"/> <location filename="../src/GUI/speedgraphitem.cpp" line="31"/>
<source>Average</source> <source>Average</source>
<translation>Medel</translation> <translation>Medel</translation>
</message> </message>
<message>
<location filename="../src/GUI/speedgraphitem.cpp" line="33"/>
<source>Pace</source>
<translation>Tempo</translation>
</message>
</context> </context>
<context> <context>
<name>TemperatureGraph</name> <name>TemperatureGraph</name>

View File

@ -21,7 +21,7 @@ Canton Astro 1966,4716,6716,9122,7022,8901,9603,298,-304,-375
Cape,4222,6222,9122,7012,8901,9603,-136,-108,-292 Cape,4222,6222,9122,7012,8901,9603,-136,-108,-292
Cape Canaveral,4717,6717,9122,7008,8901,9603,-2,150,181 Cape Canaveral,4717,6717,9122,7008,8901,9603,-2,150,181
Carthage,4223,6223,9122,7012,8901,9603,-263,6,431 Carthage,4223,6223,9122,7012,8901,9603,-263,6,431
CH-1903,4149,6149,9122,7004,8901,9603,674,15,405 CH-1903,4149,6149,9122,7004,8901,9603,674.374,15.056,405.343
Chatham 1971,4672,6672,9122,7022,8901,9603,175,-38,113 Chatham 1971,4672,6672,9122,7022,8901,9603,175,-38,113
Chua Astro,4224,6224,9122,7022,8901,9603,-134,229,-29 Chua Astro,4224,6224,9122,7022,8901,9603,-134,229,-29
Corrego Alegre,4225,6225,9122,7022,8901,9603,-206,172,-6 Corrego Alegre,4225,6225,9122,7022,8901,9603,-206,172,-6
@ -29,6 +29,7 @@ Djakarta (Batavia),4211,6211,9122,7004,8901,9603,-377,681,-50
DOS 1968,,,9122,7022,8901,9603,230,-199,-752 DOS 1968,,,9122,7022,8901,9603,230,-199,-752
Easter Island 1967,4719,6719,9122,7022,8901,9603,211,147,111 Easter Island 1967,4719,6719,9122,7022,8901,9603,211,147,111
Egypt,4199,6199,9122,7022,8901,9603,-130,-117,-151 Egypt,4199,6199,9122,7022,8901,9603,-130,-117,-151
ETRS 89,4258,6258,9122,7019,8901,9603,0,0,0
European 1950,4230,6230,9122,7022,8901,9603,-87,-98,-121 European 1950,4230,6230,9122,7022,8901,9603,-87,-98,-121
European 1950 (Mean France),,,9122,7022,8901,9603,-87,-96,-120 European 1950 (Mean France),,,9122,7022,8901,9603,-87,-96,-120
European 1950 (Spain and Portugal),,,9122,7022,8901,9603,-84,-107,-120 European 1950 (Spain and Portugal),,,9122,7022,8901,9603,-84,-107,-120
@ -104,6 +105,7 @@ Rijksdriehoeksmeting,4289,6289,9122,7004,8901,9603,593,26,478
Rome 1940,4806,6806,9122,7022,8906,9603,-225,-65,9 Rome 1940,4806,6806,9122,7022,8906,9603,-225,-65,9
RT 90,4124,6124,9122,7004,8901,9603,498,-36,568 RT 90,4124,6124,9122,7004,8901,9603,498,-36,568
S42,4179,6179,9122,7024,8901,9603,28,-121,-77 S42,4179,6179,9122,7024,8901,9603,28,-121,-77
S42 (83),4178,6178,9122,7024,8901,9603,26,-121,-78
Santo (DOS),4730,6730,9122,7022,8901,9603,170,42,84 Santo (DOS),4730,6730,9122,7022,8901,9603,170,42,84
Sao Braz,4184,6184,9122,7022,8901,9603,-203,141,53 Sao Braz,4184,6184,9122,7022,8901,9603,-203,141,53
Sapper Hill 1943,4292,6292,9122,7022,8901,9603,-355,16,74 Sapper Hill 1943,4292,6292,9122,7022,8901,9603,-355,16,74

1 Adindan 4201 6201 9122 7012 8901 9603 -162 -12 206
21 Cape 4222 6222 9122 7012 8901 9603 -136 -108 -292
22 Cape Canaveral 4717 6717 9122 7008 8901 9603 -2 150 181
23 Carthage 4223 6223 9122 7012 8901 9603 -263 6 431
24 CH-1903 4149 6149 9122 7004 8901 9603 674 674.374 15 15.056 405 405.343
25 Chatham 1971 4672 6672 9122 7022 8901 9603 175 -38 113
26 Chua Astro 4224 6224 9122 7022 8901 9603 -134 229 -29
27 Corrego Alegre 4225 6225 9122 7022 8901 9603 -206 172 -6
29 DOS 1968 9122 7022 8901 9603 230 -199 -752
30 Easter Island 1967 4719 6719 9122 7022 8901 9603 211 147 111
31 Egypt 4199 6199 9122 7022 8901 9603 -130 -117 -151
32 ETRS 89 4258 6258 9122 7019 8901 9603 0 0 0
33 European 1950 4230 6230 9122 7022 8901 9603 -87 -98 -121
34 European 1950 (Mean France) 9122 7022 8901 9603 -87 -96 -120
35 European 1950 (Spain and Portugal) 9122 7022 8901 9603 -84 -107 -120
105 Rome 1940 4806 6806 9122 7022 8906 9603 -225 -65 9
106 RT 90 4124 6124 9122 7004 8901 9603 498 -36 568
107 S42 4179 6179 9122 7024 8901 9603 28 -121 -77
108 S42 (83) 4178 6178 9122 7024 8901 9603 26 -121 -78
109 Santo (DOS) 4730 6730 9122 7022 8901 9603 170 42 84
110 Sao Braz 4184 6184 9122 7022 8901 9603 -203 141 53
111 Sapper Hill 1943 4292 6292 9122 7022 8901 9603 -355 16 74

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@ Comment=GPS log file viewer and analyzer
Comment[cz]=Prohlížeč a analyzátor GPS logů Comment[cz]=Prohlížeč a analyzátor GPS logů
Comment[fi]=Ohjelma GPS-lokien katseluun ja analysointiin Comment[fi]=Ohjelma GPS-lokien katseluun ja analysointiin
Comment[ru]=Программа для просмотра и анализа GPS логов Comment[ru]=Программа для просмотра и анализа GPS логов
Comment[sv]=GPS-loggfilsläsare och analysator
Exec=gpxsee %F Exec=gpxsee %F
Icon=gpxsee Icon=gpxsee
Terminal=false Terminal=false

View File

@ -5,7 +5,7 @@
; The name of the installer ; The name of the installer
Name "GPXSee" Name "GPXSee"
; Program version ; Program version
!define VERSION "5.2" !define VERSION "5.6"
; The file to write ; The file to write
OutFile "GPXSee-${VERSION}.exe" OutFile "GPXSee-${VERSION}.exe"

View File

@ -5,7 +5,7 @@
; The name of the installer ; The name of the installer
Name "GPXSee" Name "GPXSee"
; Program version ; Program version
!define VERSION "5.2" !define VERSION "5.6"
; The file to write ; The file to write
OutFile "GPXSee-${VERSION}_x64.exe" OutFile "GPXSee-${VERSION}_x64.exe"

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map> <map xmlns="http://www.gpxsee.org/map/1">
<name>4UMaps</name> <name>4UMaps</name>
<url>http://4umaps.eu/$z/$x/$y.png</url> <url>http://4umaps.eu/$z/$x/$y.png</url>
<copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © 4UMaps.eu</copyright>
<zoom min="2" max="15"/> <zoom min="2" max="15"/>
<bounds bottom="-65"/> <bounds bottom="-65"/>
<copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © 4UMaps.eu</copyright>
</map> </map>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map> <map xmlns="http://www.gpxsee.org/map/1">
<name>Open Street Map</name> <name>Open Street Map</name>
<url>http://tile.openstreetmap.org/$z/$x/$y.png</url> <url>http://tile.openstreetmap.org/$z/$x/$y.png</url>
<copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © OpenStreetMap (CC-BY-SA)</copyright> <copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © OpenStreetMap (CC-BY-SA)</copyright>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map> <map xmlns="http://www.gpxsee.org/map/1">
<name>Open Topo Map</name> <name>Open Topo Map</name>
<url>https://a.tile.opentopomap.org/$z/$x/$y.png</url> <url>https://a.tile.opentopomap.org/$z/$x/$y.png</url>
<zoom max="17"/>
<copyright>Map data: © OpenStreetMap contributors (ODbL), SRTM | Rendering: © OpenTopoMap (CC-BY-SA)</copyright> <copyright>Map data: © OpenStreetMap contributors (ODbL), SRTM | Rendering: © OpenTopoMap (CC-BY-SA)</copyright>
<zoom max="17"/>
</map> </map>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map> <map xmlns="http://www.gpxsee.org/map/1">
<name>USGS Imagery</name> <name>USGS Imagery</name>
<url>https://navigator.er.usgs.gov/tiles/aerial_Imagery.cgi/$z/$x/$y</url> <url>https://navigator.er.usgs.gov/tiles/aerial_Imagery.cgi/$z/$x/$y</url>
<copyright>Map services and data available from U.S. Geological Survey, National Geospatial Program.</copyright>
<zoom min="2" max="15"/> <zoom min="2" max="15"/>
<bounds bottom="0" top="74"/> <bounds bottom="0" top="74"/>
<copyright>Map services and data available from U.S. Geological Survey, National Geospatial Program.</copyright>
</map> </map>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map> <map xmlns="http://www.gpxsee.org/map/1">
<name>USGS Topo</name> <name>USGS Topo</name>
<url>https://navigator.er.usgs.gov/tiles/tcr.cgi/$z/$x/$y.png</url> <url>https://navigator.er.usgs.gov/tiles/tcr.cgi/$z/$x/$y.png</url>
<zoom min="2" max="15"/>
<copyright>Map services and data available from U.S. Geological Survey, National Geospatial Program.</copyright> <copyright>Map services and data available from U.S. Geological Survey, National Geospatial Program.</copyright>
<zoom min="2" max="15"/>
</map> </map>

View File

@ -4,7 +4,9 @@
#include <QFileOpenEvent> #include <QFileOpenEvent>
#include <QNetworkProxyFactory> #include <QNetworkProxyFactory>
#include <QLibraryInfo> #include <QLibraryInfo>
#include "map/onlinemap.h" #include "map/wmts.h"
#include "map/wms.h"
#include "map/tileloader.h"
#include "map/downloader.h" #include "map/downloader.h"
#include "map/ellipsoid.h" #include "map/ellipsoid.h"
#include "map/gcs.h" #include "map/gcs.h"
@ -23,12 +25,12 @@ App::App(int &argc, char **argv) : QApplication(argc, argv),
installTranslator(gpxsee); installTranslator(gpxsee);
QTranslator *qt = new QTranslator(this); QTranslator *qt = new QTranslator(this);
#if defined(Q_OS_WINDOWS) || defined(Q_OS_MAC) #if defined(Q_OS_WIN32) || defined(Q_OS_MAC)
qt->load(QLocale::system(), "qt", "_", TRANSLATIONS_DIR); qt->load(QLocale::system(), "qt", "_", TRANSLATIONS_DIR);
#else // Q_OS_WINDOWS || Q_OS_MAC #else // Q_OS_WIN32 || Q_OS_MAC
qt->load(QLocale::system(), "qt", "_", QLibraryInfo::location( qt->load(QLocale::system(), "qt", "_", QLibraryInfo::location(
QLibraryInfo::TranslationsPath)); QLibraryInfo::TranslationsPath));
#endif // Q_OS_WINDOWS || Q_OS_MAC #endif // Q_OS_WIN32 || Q_OS_MAC
installTranslator(qt); installTranslator(qt);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -36,7 +38,10 @@ App::App(int &argc, char **argv) : QApplication(argc, argv),
#endif // Q_OS_MAC #endif // Q_OS_MAC
QNetworkProxyFactory::setUseSystemConfiguration(true); QNetworkProxyFactory::setUseSystemConfiguration(true);
OnlineMap::setDownloader(new Downloader(this)); Downloader *dl = new Downloader(this);
TileLoader::setDownloader(dl);
WMTS::setDownloader(dl);
WMS::setDownloader(dl);
OPENGL_SET_SAMPLES(4); OPENGL_SET_SAMPLES(4);
loadDatums(); loadDatums();
loadPCSs(); loadPCSs();

View File

@ -73,10 +73,10 @@ QString Format::distance(qreal value, Units units)
QString Format::elevation(qreal value, Units units) QString Format::elevation(qreal value, Units units)
{ {
if (units == Metric) if (units == Metric)
return QString::number(value, 'f', 0) + UNIT_SPACE return QString::number(qRound(value)) + UNIT_SPACE
+ qApp->translate("Format", "m"); + qApp->translate("Format", "m");
else else
return QString::number(value * M2FT, 'f', 0) + UNIT_SPACE return QString::number(qRound(value * M2FT)) + UNIT_SPACE
+ qApp->translate("Format", "ft"); + qApp->translate("Format", "ft");
} }

View File

@ -12,6 +12,7 @@ class GraphItem : public QGraphicsObject
public: public:
GraphItem(const Graph &graph, GraphType type, QGraphicsItem *parent = 0); GraphItem(const Graph &graph, GraphType type, QGraphicsItem *parent = 0);
virtual ~GraphItem() {}
QPainterPath shape() const {return _shape;} QPainterPath shape() const {return _shape;}
QRectF boundingRect() const {return _shape.boundingRect();} QRectF boundingRect() const {return _shape.boundingRect();}

View File

@ -16,6 +16,7 @@ class GraphTab : public GraphView
public: public:
GraphTab(QWidget *parent = 0) : GraphView(parent) GraphTab(QWidget *parent = 0) : GraphView(parent)
{setFrameShape(QFrame::NoFrame);} {setFrameShape(QFrame::NoFrame);}
virtual ~GraphTab() {}
virtual QString label() const = 0; virtual QString label() const = 0;
virtual void loadData(const Data &data, const QList<PathItem *> &paths) = 0; virtual void loadData(const Data &data, const QList<PathItem *> &paths) = 0;

View File

@ -81,12 +81,12 @@ GraphView::~GraphView()
void GraphView::createXLabel() void GraphView::createXLabel()
{ {
_xAxis->setLabel(QString("%1 [%2]").arg(_xLabel).arg(_xUnits)); _xAxis->setLabel(QString("%1 [%2]").arg(_xLabel, _xUnits));
} }
void GraphView::createYLabel() void GraphView::createYLabel()
{ {
_yAxis->setLabel(QString("%1 [%2]").arg(_yLabel).arg(_yUnits)); _yAxis->setLabel(QString("%1 [%2]").arg(_yLabel, _yUnits));
} }
void GraphView::setYLabel(const QString &label) void GraphView::setYLabel(const QString &label)

View File

@ -82,6 +82,10 @@ GUI::GUI()
_sliderPos = 0; _sliderPos = 0;
_dataDir = QDir::homePath();
_mapDir = QDir::homePath();
_poiDir = QDir::homePath();
readSettings(); readSettings();
updateGraphTabs(); updateGraphTabs();
@ -425,7 +429,7 @@ void GUI::createActions()
void GUI::createMenus() void GUI::createMenus()
{ {
QMenu *fileMenu = menuBar()->addMenu(tr("File")); QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(_openFileAction); fileMenu->addAction(_openFileAction);
fileMenu->addSeparator(); fileMenu->addSeparator();
fileMenu->addAction(_printFileAction); fileMenu->addAction(_printFileAction);
@ -439,7 +443,7 @@ void GUI::createMenus()
fileMenu->addAction(_exitAction); fileMenu->addAction(_exitAction);
#endif // Q_OS_MAC #endif // Q_OS_MAC
_mapMenu = menuBar()->addMenu(tr("Map")); _mapMenu = menuBar()->addMenu(tr("&Map"));
_mapMenu->addActions(_mapActions); _mapMenu->addActions(_mapActions);
_mapsEnd = _mapMenu->addSeparator(); _mapsEnd = _mapMenu->addSeparator();
_mapMenu->addAction(_loadMapAction); _mapMenu->addAction(_loadMapAction);
@ -447,7 +451,7 @@ void GUI::createMenus()
_mapMenu->addSeparator(); _mapMenu->addSeparator();
_mapMenu->addAction(_showMapAction); _mapMenu->addAction(_showMapAction);
QMenu *graphMenu = menuBar()->addMenu(tr("Graph")); QMenu *graphMenu = menuBar()->addMenu(tr("&Graph"));
graphMenu->addAction(_distanceGraphAction); graphMenu->addAction(_distanceGraphAction);
graphMenu->addAction(_timeGraphAction); graphMenu->addAction(_timeGraphAction);
graphMenu->addSeparator(); graphMenu->addSeparator();
@ -456,7 +460,7 @@ void GUI::createMenus()
graphMenu->addSeparator(); graphMenu->addSeparator();
graphMenu->addAction(_showGraphsAction); graphMenu->addAction(_showGraphsAction);
QMenu *poiMenu = menuBar()->addMenu(tr("POI")); QMenu *poiMenu = menuBar()->addMenu(tr("&POI"));
_poiFilesMenu = poiMenu->addMenu(tr("POI files")); _poiFilesMenu = poiMenu->addMenu(tr("POI files"));
_poiFilesMenu->addActions(_poiFilesActions); _poiFilesMenu->addActions(_poiFilesActions);
poiMenu->addSeparator(); poiMenu->addSeparator();
@ -468,7 +472,7 @@ void GUI::createMenus()
poiMenu->addSeparator(); poiMenu->addSeparator();
poiMenu->addAction(_showPOIAction); poiMenu->addAction(_showPOIAction);
QMenu *dataMenu = menuBar()->addMenu(tr("Data")); QMenu *dataMenu = menuBar()->addMenu(tr("&Data"));
QMenu *displayMenu = dataMenu->addMenu(tr("Display")); QMenu *displayMenu = dataMenu->addMenu(tr("Display"));
displayMenu->addAction(_showWaypointLabelsAction); displayMenu->addAction(_showWaypointLabelsAction);
displayMenu->addAction(_showRouteWaypointsAction); displayMenu->addAction(_showRouteWaypointsAction);
@ -477,7 +481,7 @@ void GUI::createMenus()
dataMenu->addAction(_showRoutesAction); dataMenu->addAction(_showRoutesAction);
dataMenu->addAction(_showWaypointsAction); dataMenu->addAction(_showWaypointsAction);
QMenu *settingsMenu = menuBar()->addMenu(tr("Settings")); QMenu *settingsMenu = menuBar()->addMenu(tr("&Settings"));
QMenu *timeMenu = settingsMenu->addMenu(tr("Time")); QMenu *timeMenu = settingsMenu->addMenu(tr("Time"));
timeMenu->addAction(_totalTimeAction); timeMenu->addAction(_totalTimeAction);
timeMenu->addAction(_movingTimeAction); timeMenu->addAction(_movingTimeAction);
@ -495,7 +499,7 @@ void GUI::createMenus()
settingsMenu->addSeparator(); settingsMenu->addSeparator();
settingsMenu->addAction(_openOptionsAction); settingsMenu->addAction(_openOptionsAction);
QMenu *helpMenu = menuBar()->addMenu(tr("Help")); QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(_pathsAction); helpMenu->addAction(_pathsAction);
helpMenu->addAction(_keysAction); helpMenu->addAction(_keysAction);
helpMenu->addSeparator(); helpMenu->addSeparator();
@ -660,11 +664,13 @@ void GUI::paths()
void GUI::openFile() void GUI::openFile()
{ {
QStringList files = QFileDialog::getOpenFileNames(this, tr("Open file"), QStringList files = QFileDialog::getOpenFileNames(this, tr("Open file"),
QString(), Data::formats()); _dataDir, Data::formats());
QStringList list = files; QStringList list = files;
for (QStringList::Iterator it = list.begin(); it != list.end(); it++) for (QStringList::Iterator it = list.begin(); it != list.end(); it++)
openFile(*it); openFile(*it);
if (!list.isEmpty())
_dataDir = QFileInfo(list.first()).path();
} }
bool GUI::openFile(const QString &fileName) bool GUI::openFile(const QString &fileName)
@ -749,11 +755,13 @@ bool GUI::loadFile(const QString &fileName)
void GUI::openPOIFile() void GUI::openPOIFile()
{ {
QStringList files = QFileDialog::getOpenFileNames(this, tr("Open POI file"), QStringList files = QFileDialog::getOpenFileNames(this, tr("Open POI file"),
QString(), Data::formats()); _poiDir, Data::formats());
QStringList list = files; QStringList list = files;
for (QStringList::Iterator it = list.begin(); it != list.end(); it++) for (QStringList::Iterator it = list.begin(); it != list.end(); it++)
openPOIFile(*it); openPOIFile(*it);
if (!list.isEmpty())
_poiDir = QFileInfo(list.first()).path();
} }
bool GUI::openPOIFile(const QString &fileName) bool GUI::openPOIFile(const QString &fileName)
@ -1125,11 +1133,13 @@ void GUI::showGraphSliderInfo(bool show)
void GUI::loadMap() void GUI::loadMap()
{ {
QStringList files = QFileDialog::getOpenFileNames(this, tr("Open map file"), QStringList files = QFileDialog::getOpenFileNames(this, tr("Open map file"),
QString(), MapList::formats()); _mapDir, MapList::formats());
QStringList list = files; QStringList list = files;
for (QStringList::Iterator it = list.begin(); it != list.end(); it++) for (QStringList::Iterator it = list.begin(); it != list.end(); it++)
loadMap(*it); loadMap(*it);
if (!list.isEmpty())
_mapDir = QFileInfo(list.first()).path();
} }
bool GUI::loadMap(const QString &fileName) bool GUI::loadMap(const QString &fileName)

View File

@ -224,6 +224,8 @@ private:
Export _export; Export _export;
Options _options; Options _options;
QString _dataDir, _mapDir, _poiDir;
}; };
#endif // GUI_H #endif // GUI_H

View File

@ -23,7 +23,7 @@ void InfoItem::updateBoundingRect()
for (i = _list.constBegin(); i != _list.constEnd(); i++) { for (i = _list.constBegin(); i != _list.constEnd(); i++) {
width += fm.width(i->key + ": "); width += fm.width(i->key + ": ");
width += fm.width(i->value) + ((i == _list.end() - 1) ? 0 : PADDING); width += fm.width(i->value) + ((i == _list.constEnd() - 1) ? 0 : PADDING);
} }
_boundingRect = QRectF(0, 0, width, _list.isEmpty() ? 0 : fm.height()); _boundingRect = QRectF(0, 0, width, _list.isEmpty() ? 0 : fm.height());
@ -49,8 +49,8 @@ void InfoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
painter->drawText(width, fm.height() - fm.descent(), i->key + ": "); painter->drawText(width, fm.height() - fm.descent(), i->key + ": ");
width += fm.width(i->key + ": "); width += fm.width(i->key + ": ");
painter->drawText(width, fm.height() - fm.descent(), i->value); painter->drawText(width, fm.height() - fm.descent(), i->value);
width += fm.width(i->value) + ((i == _list.end() - 1) ? 0 : PADDING); width += fm.width(i->value) + ((i == _list.constEnd() - 1) ? 0 : PADDING);
if (i != _list.end() - 1) { if (i != _list.constEnd() - 1) {
painter->save(); painter->save();
painter->setPen(Qt::gray); painter->setPen(Qt::gray);
painter->drawLine(width - PADDING/2, fm.descent(), painter->drawLine(width - PADDING/2, fm.descent(),

View File

@ -76,6 +76,7 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
_digitalZoom = 0; _digitalZoom = 0;
_map->setBackgroundColor(_backgroundColor); _map->setBackgroundColor(_backgroundColor);
_res = _map->resolution(_map->bounds());
_scene->setSceneRect(_map->bounds()); _scene->setSceneRect(_map->bounds());
centerOn(_scene->sceneRect().center()); centerOn(_scene->sceneRect().center());
@ -84,18 +85,8 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
void MapView::centerOn(const QPointF &pos) void MapView::centerOn(const QPointF &pos)
{ {
QGraphicsView::centerOn(pos); QGraphicsView::centerOn(pos);
QRectF vr(mapToScene(viewport()->rect()).boundingRect());
/* Fix the offset caused by QGraphicsView::centerOn() approximation */ _res = _map->resolution(vr);
QPointF center = mapToScene(viewport()->rect().center());
QPoint offset((int)(pos.x() - center.x()), (int)(pos.y() - center.y()));
if (qAbs(offset.x()) == 1)
horizontalScrollBar()->setValue(horizontalScrollBar()->value()
+ offset.x());
if (qAbs(offset.y()) == 1)
verticalScrollBar()->setValue(verticalScrollBar()->value()
+ offset.y());
_res = _map->resolution(pos);
_mapScale->setResolution(_res); _mapScale->setResolution(_res);
} }
@ -177,7 +168,7 @@ void MapView::addWaypoints(const QList<Waypoint> &waypoints)
QList<PathItem *> MapView::loadData(const Data &data) QList<PathItem *> MapView::loadData(const Data &data)
{ {
QList<PathItem *> paths; QList<PathItem *> paths;
qreal zoom = _map->zoom(); int zoom = _map->zoom();
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))));
@ -188,7 +179,7 @@ QList<PathItem *> MapView::loadData(const Data &data)
if (_tracks.empty() && _routes.empty() && _waypoints.empty()) if (_tracks.empty() && _routes.empty() && _waypoints.empty())
return paths; return paths;
if (mapZoom() != zoom) if (fitMapZoom() != zoom)
rescale(); rescale();
else else
updatePOIVisibility(); updatePOIVisibility();
@ -198,13 +189,13 @@ QList<PathItem *> MapView::loadData(const Data &data)
return paths; return paths;
} }
qreal MapView::mapZoom() const int MapView::fitMapZoom() const
{ {
RectC br = _tr | _rr | _wr; RectC br = _tr | _rr | _wr;
return _map->zoomFit(viewport()->size() - QSize(2*MARGIN, 2*MARGIN), return _map->zoomFit(viewport()->size() - QSize(2*MARGIN, 2*MARGIN),
br.isNull() ? RectC(_map->xy2ll(sceneRect().topLeft()), br.isNull() ? RectC(_map->xy2ll(_map->bounds().topLeft()),
_map->xy2ll(sceneRect().bottomRight())) : br); _map->xy2ll(_map->bounds().bottomRight())) : br);
} }
QPointF MapView::contentCenter() const QPointF MapView::contentCenter() const
@ -267,9 +258,9 @@ void MapView::setPalette(const Palette &palette)
void MapView::setMap(Map *map) void MapView::setMap(Map *map)
{ {
QPointF pos = mapToScene(viewport()->rect().center()); QRectF vr(mapToScene(viewport()->rect()).boundingRect()
Coordinates center = _map->xy2ll(pos); .intersected(_map->bounds()));
qreal resolution = _map->resolution(pos); RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
_map->unload(); _map->unload();
disconnect(_map, SIGNAL(loaded()), this, SLOT(reloadMap())); disconnect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
@ -281,7 +272,7 @@ void MapView::setMap(Map *map)
digitalZoom(0); digitalZoom(0);
_map->zoomFit(resolution, center); _map->zoomFit(viewport()->rect().size(), cr);
_scene->setSceneRect(_map->bounds()); _scene->setSceneRect(_map->bounds());
for (int i = 0; i < _tracks.size(); i++) for (int i = 0; i < _tracks.size(); i++)
@ -296,7 +287,7 @@ void MapView::setMap(Map *map)
it.value()->setMap(_map); it.value()->setMap(_map);
updatePOIVisibility(); updatePOIVisibility();
centerOn(_map->ll2xy(center)); centerOn(_map->ll2xy(cr.center()));
resetCachedContent(); resetCachedContent();
QPixmapCache::clear(); QPixmapCache::clear();
@ -398,7 +389,10 @@ void MapView::setCoordinatesFormat(CoordinatesFormat format)
void MapView::clearMapCache() void MapView::clearMapCache()
{ {
_map->clearCache(); _map->clearCache();
resetCachedContent();
fitMapZoom();
rescale();
centerOn(contentCenter());
} }
void MapView::digitalZoom(int zoom) void MapView::digitalZoom(int zoom)
@ -499,9 +493,9 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
bool hires) bool hires)
{ {
QRect orig, adj; QRect orig, adj;
qreal ratio, diff, origRes, q; qreal ratio, diff, q;
QPointF origScene, origPos; QPointF origScene, origPos;
Coordinates origLL; RectC origC;
// Enter plot mode // Enter plot mode
@ -526,9 +520,9 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
// Adjust the view for printing // Adjust the view for printing
if (hires) { if (hires) {
origScene = mapToScene(orig.center()); QRectF vr(mapToScene(orig).boundingRect());
origLL = _map->xy2ll(origScene); origC = RectC(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
origRes = _map->resolution(origScene); origScene = vr.center();
QPointF s(painter->device()->logicalDpiX() QPointF s(painter->device()->logicalDpiX()
/ (qreal)metric(QPaintDevice::PdmDpiX), / (qreal)metric(QPaintDevice::PdmDpiX),
@ -558,7 +552,7 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
// Revert view changes to display mode // Revert view changes to display mode
if (hires) { if (hires) {
_map->zoomFit(origRes, origLL); _map->zoomFit(orig.size(), origC);
rescale(); rescale();
centerOn(origScene); centerOn(origScene);
} }
@ -761,25 +755,22 @@ void MapView::setBackgroundColor(const QColor &color)
void MapView::drawBackground(QPainter *painter, const QRectF &rect) void MapView::drawBackground(QPainter *painter, const QRectF &rect)
{ {
painter->fillRect(rect, _backgroundColor);
if (_showMap) { if (_showMap) {
QRectF ir = rect.intersected(_map->bounds()); QRectF ir = rect.intersected(_map->bounds());
if (_opacity < 1.0 || ir != rect)
painter->fillRect(rect, _backgroundColor);
if (_opacity < 1.0) if (_opacity < 1.0)
painter->setOpacity(_opacity); painter->setOpacity(_opacity);
_map->draw(painter, ir); _map->draw(painter, ir);
} else }
painter->fillRect(rect, _backgroundColor);
} }
void MapView::resizeEvent(QResizeEvent *event) void MapView::resizeEvent(QResizeEvent *event)
{ {
QGraphicsView::resizeEvent(event); QGraphicsView::resizeEvent(event);
qreal zoom = _map->zoom(); int zoom = _map->zoom();
if (mapZoom() != zoom) if (fitMapZoom() != zoom)
rescale(); rescale();
centerOn(contentCenter()); centerOn(contentCenter());
@ -800,8 +791,8 @@ void MapView::scrollContentsBy(int dx, int dy)
{ {
QGraphicsView::scrollContentsBy(dx, dy); QGraphicsView::scrollContentsBy(dx, dy);
QPointF center = mapToScene(viewport()->rect().center()); QRectF sr(mapToScene(viewport()->rect()).boundingRect());
qreal res = _map->resolution(center); qreal res = _map->resolution(sr);
if (qMax(res, _res) / qMin(res, _res) > 1.1) { if (qMax(res, _res) / qMin(res, _res) > 1.1) {
_mapScale->setResolution(res); _mapScale->setResolution(res);

View File

@ -80,7 +80,7 @@ private:
void loadPOI(); void loadPOI();
void clearPOI(); void clearPOI();
qreal mapZoom() const; int fitMapZoom() const;
QPointF contentCenter() const; QPointF contentCenter() const;
void rescale(); void rescale();
void centerOn(const QPointF &pos); void centerOn(const QPointF &pos);

View File

@ -1,16 +1,18 @@
#include "data/data.h" #include "data/data.h"
#include "config.h" #include "config.h"
#include "tooltip.h" #include "tooltip.h"
#include "format.h"
#include "speedgraphitem.h" #include "speedgraphitem.h"
#include "speedgraph.h" #include "speedgraph.h"
SpeedGraph::SpeedGraph(QWidget *parent) : GraphTab(parent) SpeedGraph::SpeedGraph(QWidget *parent) : GraphTab(parent)
{ {
_units = Metric;
_timeType = Total; _timeType = Total;
_showTracks = true; _showTracks = true;
setYUnits(Metric); setYUnits();
setYLabel(tr("Speed")); setYLabel(tr("Speed"));
setSliderPrecision(1); setSliderPrecision(1);
@ -19,10 +21,15 @@ SpeedGraph::SpeedGraph(QWidget *parent) : GraphTab(parent)
void SpeedGraph::setInfo() void SpeedGraph::setInfo()
{ {
if (_showTracks) { if (_showTracks) {
QString pace = Format::timeSpan((3600.0 / (avg() * yScale())), false);
QString pu = (_units == Metric) ? tr("min/km") : (_units == Imperial) ?
tr("min/mi") : tr("min/nmi");
GraphView::addInfo(tr("Average"), QString::number(avg() * yScale(), 'f', GraphView::addInfo(tr("Average"), QString::number(avg() * yScale(), 'f',
1) + UNIT_SPACE + yUnits()); 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Maximum"), QString::number(max() * yScale(), 'f', GraphView::addInfo(tr("Maximum"), QString::number(max() * yScale(), 'f',
1) + UNIT_SPACE + yUnits()); 1) + UNIT_SPACE + yUnits());
GraphView::addInfo(tr("Pace"), pace + UNIT_SPACE + pu);
} else } else
clearInfo(); clearInfo();
} }
@ -77,12 +84,12 @@ void SpeedGraph::clear()
GraphView::clear(); GraphView::clear();
} }
void SpeedGraph::setYUnits(Units units) void SpeedGraph::setYUnits()
{ {
if (units == Nautical) { if (_units == Nautical) {
GraphView::setYUnits(tr("kn")); GraphView::setYUnits(tr("kn"));
setYScale(MS2KN); setYScale(MS2KN);
} else if (units == Imperial) { } else if (_units == Imperial) {
GraphView::setYUnits(tr("mi/h")); GraphView::setYUnits(tr("mi/h"));
setYScale(MS2MIH); setYScale(MS2MIH);
} else { } else {
@ -93,7 +100,9 @@ void SpeedGraph::setYUnits(Units units)
void SpeedGraph::setUnits(Units units) void SpeedGraph::setUnits(Units units)
{ {
setYUnits(units); _units = units;
setYUnits();
setInfo(); setInfo();
GraphView::setUnits(units); GraphView::setUnits(units);

View File

@ -21,13 +21,14 @@ public:
private: private:
qreal avg() const; qreal avg() const;
qreal max() const {return bounds().bottom();} qreal max() const {return bounds().bottom();}
void setYUnits(Units units); void setYUnits();
void setInfo(); void setInfo();
QList<QPointF> _avg; QList<QPointF> _avg;
QList<QPointF> _mavg; QList<QPointF> _mavg;
enum TimeType _timeType; Units _units;
TimeType _timeType;
bool _showTracks; bool _showTracks;
}; };

View File

@ -1,4 +1,5 @@
#include "tooltip.h" #include "tooltip.h"
#include "format.h"
#include "speedgraphitem.h" #include "speedgraphitem.h"
SpeedGraphItem::SpeedGraphItem(const Graph &graph, GraphType type, SpeedGraphItem::SpeedGraphItem(const Graph &graph, GraphType type,
@ -20,11 +21,16 @@ QString SpeedGraphItem::toolTip() const
? MS2KN : MS2KMH; ? MS2KN : MS2KMH;
QString su = (_units == Imperial) ? tr("mi/h") : (_units == Nautical) QString su = (_units == Imperial) ? tr("mi/h") : (_units == Nautical)
? tr("kn") : tr("km/h"); ? tr("kn") : tr("km/h");
QString pace = Format::timeSpan((3600.0 / ((_timeType == Total)
? avg() * scale : mavg() * scale)), false);
QString pu = (_units == Metric) ? tr("min/km") : (_units == Imperial) ?
tr("min/mi") : tr("min/nmi");
tt.insert(tr("Maximum"), QString::number(max() * scale, 'f', 1) tt.insert(tr("Maximum"), QString::number(max() * scale, 'f', 1)
+ UNIT_SPACE + su); + UNIT_SPACE + su);
tt.insert(tr("Average"), QString::number((_timeType == Total) tt.insert(tr("Average"), QString::number((_timeType == Total)
? avg() * scale : mavg() * scale, 'f', 1) + UNIT_SPACE + su); ? avg() * scale : mavg() * scale, 'f', 1) + UNIT_SPACE + su);
tt.insert(tr("Pace"), pace + UNIT_SPACE + pu);
return tt.toString(); return tt.toString();
} }

View File

@ -15,7 +15,6 @@ class Coordinates
{ {
public: public:
Coordinates() {_lon = NAN; _lat = NAN;} Coordinates() {_lon = NAN; _lat = NAN;}
Coordinates(const Coordinates &c) {_lon = c._lon; _lat = c._lat;}
Coordinates(qreal lon, qreal lat) {_lon = lon; _lat = lat;} Coordinates(qreal lon, qreal lat) {_lon = lon; _lat = lat;}
qreal &rlon() {return _lon;} qreal &rlon() {return _lon;}

View File

@ -8,6 +8,15 @@ void RangeF::resize(qreal size)
_max += adj; _max += adj;
} }
RangeF RangeF::operator&(const RangeF &r) const
{
if (isNull() || r.isNull())
return RangeF();
RangeF tmp(qMax(this->_min, r._min), qMin(this->_max, r._max));
return tmp.isValid() ? tmp : RangeF();
}
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const Range &range) QDebug operator<<(QDebug dbg, const Range &range)
{ {

View File

@ -14,6 +14,11 @@ public:
int max() const {return _max;} int max() const {return _max;}
int size() const {return (_max - _min);} int size() const {return (_max - _min);}
bool isValid() const {return size() >= 0;}
void setMin(int min) {_min = min;}
void setMax(int max) {_max = max;}
private: private:
int _min, _max; int _min, _max;
}; };
@ -24,10 +29,19 @@ public:
RangeF() {_min = 0; _max = 0;} RangeF() {_min = 0; _max = 0;}
RangeF(qreal min, qreal max) {_min = min, _max = max;} RangeF(qreal min, qreal max) {_min = min, _max = max;}
RangeF operator&(const RangeF &r) const;
RangeF &operator&=(const RangeF &r) {*this = *this & r; return *this;}
qreal min() const {return _min;} qreal min() const {return _min;}
qreal max() const {return _max;} qreal max() const {return _max;}
qreal size() const {return (_max - _min);} qreal size() const {return (_max - _min);}
bool isNull() const {return _min == 0 && _max == 0;}
bool isValid() const {return size() >= 0;}
void setMin(qreal min) {_min = min;}
void setMax(qreal max) {_max = max;}
void resize(qreal size); void resize(qreal size);
private: private:

View File

@ -44,6 +44,76 @@ RectC RectC::operator|(const RectC &r) const
return tmp; return tmp;
} }
RectC RectC::operator&(const RectC &r) const
{
if (isNull() || r.isNull())
return RectC();
qreal l1 = _tl.lon();
qreal r1 = _tl.lon();
if (_br.lon() - _tl.lon() < 0)
l1 = _br.lon();
else
r1 = _br.lon();
qreal l2 = r._tl.lon();
qreal r2 = r._tl.lon();
if (r._br.lon() - r._tl.lon() < 0)
l2 = r._br.lon();
else
r2 = r._br.lon();
if (l1 > r2 || l2 > r1)
return RectC();
qreal t1 = _tl.lat();
qreal b1 = _tl.lat();
if (_br.lat() - _tl.lat() < 0)
t1 = _br.lat();
else
b1 = _br.lat();
qreal t2 = r._tl.lat();
qreal b2 = r._tl.lat();
if (r._br.lat() - r._tl.lat() < 0)
t2 = r._br.lat();
else
b2 = r._br.lat();
if (t1 > b2 || t2 > b1)
return RectC();
RectC tmp;
tmp._tl.setLon(qMax(l1, l2));
tmp._br.setLon(qMin(r1, r2));
tmp._tl.setLat(qMax(t1, t2));
tmp._br.setLat(qMin(b1, b2));
return tmp;
}
RectC RectC::normalized() const
{
RectC r;
if (_br.lon() < _tl.lon()) {
r._tl.setLon(_br.lon());
r._br.setLon(_tl.lon());
} else {
r._tl.setLon(_tl.lon());
r._br.setLon(_br.lon());
}
if (_br.lat() < _tl.lat()) {
r._tl.setLat(_br.lat());
r._br.setLat(_tl.lat());
} else {
r._tl.setLat(_tl.lat());
r._br.setLat(_br.lat());
}
return r;
}
void RectC::unite(const Coordinates &c) void RectC::unite(const Coordinates &c)
{ {
if (isNull()) { if (isNull()) {

View File

@ -30,8 +30,11 @@ public:
RectC operator|(const RectC &r) const; RectC operator|(const RectC &r) const;
RectC &operator|=(const RectC &r) {*this = *this | r; return *this;} RectC &operator|=(const RectC &r) {*this = *this | r; return *this;}
RectC operator&(const RectC &r) const;
RectC &operator&=(const RectC &r) {*this = *this & r; return *this;}
void unite(const Coordinates &c); void unite(const Coordinates &c);
RectC normalized() const;
private: private:
Coordinates _tl, _br; Coordinates _tl, _br;

View File

@ -23,13 +23,13 @@ static QHash<QString, Parser*> parsers()
{ {
QHash<QString, Parser*> hash; QHash<QString, Parser*> hash;
hash.insert("gpx", &gpx); hash.insert("gpx", &gpx);
hash.insert("tcx", &tcx); hash.insert("tcx", &tcx);
hash.insert("kml", &kml); hash.insert("kml", &kml);
hash.insert("fit", &fit); hash.insert("fit", &fit);
hash.insert("csv", &csv); hash.insert("csv", &csv);
hash.insert("igc", &igc); hash.insert("igc", &igc);
hash.insert("nmea", &nmea); hash.insert("nmea", &nmea);
return hash; return hash;
} }

View File

@ -41,6 +41,7 @@ Defense.
*/ */
#include "ellipsoid.h"
#include "albersequal.h" #include "albersequal.h"
@ -69,7 +70,6 @@ AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
double sp1, sp2; double sp1, sp2;
_e = ellipsoid;
_latitudeOrigin = deg2rad(latitudeOrigin); _latitudeOrigin = deg2rad(latitudeOrigin);
_longitudeOrigin = deg2rad(longitudeOrigin); _longitudeOrigin = deg2rad(longitudeOrigin);
_falseEasting = falseEasting; _falseEasting = falseEasting;
@ -78,7 +78,9 @@ AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
sp1 = deg2rad(standardParallel1); sp1 = deg2rad(standardParallel1);
sp2 = deg2rad(standardParallel2); sp2 = deg2rad(standardParallel2);
_es2 = 2 * _e->flattening() - _e->flattening() * _e->flattening(); _a2 = ellipsoid->radius() * ellipsoid->radius();
_es2 = 2 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
_es = sqrt(_es2); _es = sqrt(_es2);
_one_minus_es2 = 1 - _es2; _one_minus_es2 = 1 - _es2;
_two_es = 2 * _es; _two_es = 2 * _es;
@ -108,7 +110,7 @@ AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
_n = sin_lat1; _n = sin_lat1;
_C = sqr_m1 + _n * q1; _C = sqr_m1 + _n * q1;
_a_over_n = _e->radius() / _n; _a_over_n = ellipsoid->radius() / _n;
nq0 = _n * q0; nq0 = _n * q0;
_rho0 = (_C < nq0) ? 0 : _a_over_n * sqrt(_C - nq0); _rho0 = (_C < nq0) ? 0 : _a_over_n * sqrt(_C - nq0);
} }
@ -171,7 +173,7 @@ Coordinates AlbersEqual::xy2ll(const QPointF &p) const
if (rho != 0.0) if (rho != 0.0)
theta = atan2(dx, rho0_minus_dy); theta = atan2(dx, rho0_minus_dy);
rho_n = rho * _n; rho_n = rho * _n;
q = (_C - (rho_n * rho_n) / (_e->radius() * _e->radius())) / _n; q = (_C - (rho_n * rho_n) / _a2) / _n;
qc = 1 - ((_one_minus_es2) / (_two_es)) * log((1.0 - _es) / (1.0 + _es)); qc = 1 - ((_one_minus_es2) / (_two_es)) * log((1.0 - _es) / (1.0 + _es));
if (fabs(fabs(qc) - fabs(q)) > 1.0e-6) { if (fabs(fabs(qc) - fabs(q)) > 1.0e-6) {
q_over_2 = q / 2.0; q_over_2 = q / 2.0;

View File

@ -1,9 +1,10 @@
#ifndef ALBERSEQUAL_H #ifndef ALBERSEQUAL_H
#define ALBERSEQUAL_H #define ALBERSEQUAL_H
#include "ellipsoid.h"
#include "ct.h" #include "ct.h"
class Ellipsoid;
class AlbersEqual : public CT class AlbersEqual : public CT
{ {
public: public:
@ -17,13 +18,12 @@ public:
virtual Coordinates xy2ll(const QPointF &p) const; virtual Coordinates xy2ll(const QPointF &p) const;
private: private:
const Ellipsoid *_e;
double _latitudeOrigin; double _latitudeOrigin;
double _longitudeOrigin; double _longitudeOrigin;
double _falseEasting; double _falseEasting;
double _falseNorthing; double _falseNorthing;
double _a2;
double _rho0; double _rho0;
double _C; double _C;
double _n; double _n;

View File

@ -8,7 +8,8 @@ static double sDMS2deg(double val)
const char *decimal; const char *decimal;
QString qstr(QString::number(qAbs(val), 'f', 7)); QString qstr(QString::number(qAbs(val), 'f', 7));
const char *str = qstr.toLatin1().constData(); QByteArray ba = qstr.toLatin1();
const char *str = ba.constData();
decimal = strrchr(str, '.'); decimal = strrchr(str, '.');
int deg = str2int(str, decimal - str); int deg = str2int(str, decimal - str);
int min = str2int(decimal + 1, 2); int min = str2int(decimal + 1, 2);

View File

@ -2,6 +2,7 @@
#include <QtAlgorithms> #include <QtAlgorithms>
#include <QPainter> #include <QPainter>
#include "common/rectc.h" #include "common/rectc.h"
#include "offlinemap.h"
#include "tar.h" #include "tar.h"
#include "atlas.h" #include "atlas.h"
@ -15,8 +16,8 @@ static bool resCmp(const OfflineMap *m1, const OfflineMap *m2)
{ {
qreal r1, r2; qreal r1, r2;
r1 = m1->resolution(m1->bounds().center()); r1 = m1->resolution(m1->bounds());
r2 = m2->resolution(m2->bounds().center()); r2 = m2->resolution(m2->bounds());
return r1 > r2; return r1 > r2;
} }
@ -37,8 +38,8 @@ void Atlas::computeZooms()
_zooms.append(QPair<int, int>(0, _maps.count() - 1)); _zooms.append(QPair<int, int>(0, _maps.count() - 1));
for (int i = 1; i < _maps.count(); i++) { for (int i = 1; i < _maps.count(); i++) {
qreal last = _maps.at(i-1)->resolution(_maps.at(i)->bounds().center()); qreal last = _maps.at(i-1)->resolution(_maps.at(i)->bounds());
qreal cur = _maps.at(i)->resolution(_maps.at(i)->bounds().center()); qreal cur = _maps.at(i)->resolution(_maps.at(i)->bounds());
if (cur < last * ZOOM_THRESHOLD) { if (cur < last * ZOOM_THRESHOLD) {
_zooms.last().second = i-1; _zooms.last().second = i-1;
_zooms.append(QPair<int, int>(i, _maps.count() - 1)); _zooms.append(QPair<int, int>(i, _maps.count() - 1));
@ -78,21 +79,19 @@ void Atlas::computeBounds()
BR(_maps.at(i))), QRectF(offsets.at(i), _maps.at(i)->bounds().size()))); BR(_maps.at(i))), QRectF(offsets.at(i), _maps.at(i)->bounds().size())));
} }
Atlas::Atlas(const QString &fileName, QObject *parent) : Map(parent) Atlas::Atlas(const QString &fileName, QObject *parent)
: Map(parent), _zoom(0), _mapIndex(-1), _valid(false)
{ {
QFileInfo fi(fileName); QFileInfo fi(fileName);
QByteArray ba; QByteArray ba;
QString suffix = fi.suffix().toLower(); QString suffix = fi.suffix().toLower();
Tar tar; Tar tar(fileName);
_valid = false;
_zoom = 0;
_name = fi.dir().dirName(); _name = fi.dir().dirName();
_ci = -1; _cz = -1;
if (suffix == "tar") { if (suffix == "tar") {
if (!tar.load(fileName)) { if (!tar.open()) {
_errorString = "Error reading tar file"; _errorString = "Error reading tar file";
return; return;
} }
@ -112,7 +111,6 @@ Atlas::Atlas(const QString &fileName, QObject *parent) : Map(parent)
return; return;
} }
QDir dir(fi.absolutePath()); QDir dir(fi.absolutePath());
QFileInfoList layers = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); QFileInfoList layers = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
for (int n = 0; n < layers.count(); n++) { for (int n = 0; n < layers.count(); n++) {
@ -149,12 +147,6 @@ Atlas::Atlas(const QString &fileName, QObject *parent) : Map(parent)
_valid = true; _valid = true;
} }
Atlas::~Atlas()
{
for (int i = 0; i < _maps.size(); i++)
delete _maps.at(i);
}
QRectF Atlas::bounds() const QRectF Atlas::bounds() const
{ {
QSizeF s(0, 0); QSizeF s(0, 0);
@ -169,28 +161,24 @@ QRectF Atlas::bounds() const
return QRectF(QPointF(0, 0), s); return QRectF(QPointF(0, 0), s);
} }
qreal Atlas::resolution(const QPointF &p) const qreal Atlas::resolution(const QRectF &rect) const
{ {
int idx = _zooms.at(_zoom).first; int idx = _zooms.at(_zoom).first;
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).second; i++) { for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).second; i++) {
if (_bounds.at(i).second.contains(_maps.at(i)->xy2pp(p))) { if (_bounds.at(i).second.contains(_maps.at(i)->xy2pp(rect.center()))) {
idx = i; idx = i;
break; break;
} }
} }
return _maps.at(idx)->resolution(p); return _maps.at(idx)->resolution(rect);
} }
qreal Atlas::zoom() const int Atlas::zoomFit(const QSize &size, const RectC &br)
{
return _zoom;
}
qreal Atlas::zoomFit(const QSize &size, const RectC &br)
{ {
_zoom = 0; _zoom = 0;
_mapIndex = -1;
if (!br.isValid()) { if (!br.isValid()) {
_zoom = _zooms.size() - 1; _zoom = _zooms.size() - 1;
@ -217,35 +205,19 @@ qreal Atlas::zoomFit(const QSize &size, const RectC &br)
return _zoom; return _zoom;
} }
qreal Atlas::zoomFit(qreal resolution, const Coordinates &c) int Atlas::zoomIn()
{
_zoom = 0;
for (int z = 0; z < _zooms.count(); z++) {
for (int i = _zooms.at(z).first; i <= _zooms.at(z).second; i++) {
if (!_bounds.at(i).first.contains(_maps.at(i)->ll2pp(c)))
continue;
if (_maps.at(i)->resolution(_maps.at(i)->ll2xy(c)) < resolution)
return _zoom;
_zoom = z;
break;
}
}
return _zoom;
}
qreal Atlas::zoomIn()
{ {
_zoom = qMin(_zoom + 1, _zooms.size() - 1); _zoom = qMin(_zoom + 1, _zooms.size() - 1);
_mapIndex = -1;
return _zoom; return _zoom;
} }
qreal Atlas::zoomOut() int Atlas::zoomOut()
{ {
_zoom = qMax(_zoom - 1, 0); _zoom = qMax(_zoom - 1, 0);
_mapIndex = -1;
return _zoom; return _zoom;
} }
@ -253,26 +225,21 @@ QPointF Atlas::ll2xy(const Coordinates &c)
{ {
QPointF pp; QPointF pp;
if (_cz != _zoom) { if (_mapIndex >= 0)
_ci = -1; pp = _maps.at(_mapIndex)->ll2pp(c);
_cz = _zoom; if (_mapIndex < 0 || !_bounds.at(_mapIndex).first.contains(pp)) {
} _mapIndex = _zooms.at(_zoom).first;
if (_ci >= 0)
pp = _maps.at(_ci)->ll2pp(c);
if (_ci < 0 || !_bounds.at(_ci).first.contains(pp)) {
_ci = _zooms.at(_zoom).first;
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).second; i++) { for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).second; i++) {
pp = _maps.at(i)->ll2pp(c); pp = _maps.at(i)->ll2pp(c);
if (_bounds.at(i).first.contains(pp)) { if (_bounds.at(i).first.contains(pp)) {
_ci = i; _mapIndex = i;
break; break;
} }
} }
} }
QPointF p = _maps.at(_ci)->pp2xy(pp); QPointF p = _maps.at(_mapIndex)->pp2xy(pp);
return p + _bounds.at(_ci).second.topLeft(); return p + _bounds.at(_mapIndex).second.topLeft();
} }
Coordinates Atlas::xy2ll(const QPointF &p) Coordinates Atlas::xy2ll(const QPointF &p)
@ -332,10 +299,10 @@ bool Atlas::isAtlas(const QString &path)
{ {
QFileInfo fi(path); QFileInfo fi(path);
QString suffix = fi.suffix().toLower(); QString suffix = fi.suffix().toLower();
Tar tar; Tar tar(path);
if (suffix == "tar") { if (suffix == "tar") {
if (!tar.load(path)) if (!tar.open())
return false; return false;
QString tbaFileName = fi.completeBaseName() + ".tba"; QString tbaFileName = fi.completeBaseName() + ".tba";
return tar.contains(tbaFileName); return tar.contains(tbaFileName);

View File

@ -1,10 +1,9 @@
#ifndef ATLAS_H #ifndef ATLAS_H
#define ATLAS_H #define ATLAS_H
#include <QFileInfoList>
#include "map.h" #include "map.h"
#include "offlinemap.h"
class OfflineMap;
class Atlas : public Map class Atlas : public Map
{ {
@ -12,18 +11,16 @@ class Atlas : public Map
public: public:
Atlas(const QString &fileName, QObject *parent = 0); Atlas(const QString &fileName, QObject *parent = 0);
~Atlas();
const QString &name() const {return _name;} const QString &name() const {return _name;}
QRectF bounds() const; QRectF bounds() const;
qreal resolution(const QPointF &p) const; qreal resolution(const QRectF &rect) const;
qreal zoom() const; int zoom() const {return _zoom;}
qreal zoomFit(const QSize &size, const RectC &br); int zoomFit(const QSize &size, const RectC &br);
qreal zoomFit(qreal resolution, const Coordinates &c); int zoomIn();
qreal zoomIn(); int zoomOut();
qreal zoomOut();
QPointF ll2xy(const Coordinates &c); QPointF ll2xy(const Coordinates &c);
Coordinates xy2ll(const QPointF &p); Coordinates xy2ll(const QPointF &p);
@ -33,7 +30,7 @@ public:
void unload(); void unload();
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static bool isAtlas(const QString &path); static bool isAtlas(const QString &path);
@ -43,15 +40,15 @@ private:
void computeBounds(); void computeBounds();
QString _name; QString _name;
bool _valid;
QString _errorString;
QList<OfflineMap*> _maps; QList<OfflineMap*> _maps;
QVector<QPair<int, int> > _zooms; QVector<QPair<int, int> > _zooms;
QVector<QPair<QRectF, QRectF> > _bounds; QVector<QPair<QRectF, QRectF> > _bounds;
int _zoom; int _zoom;
int _mapIndex;
int _ci, _cz; bool _valid;
QString _errorString;
}; };
#endif // ATLAS_H #endif // ATLAS_H

View File

@ -0,0 +1,56 @@
#include "coordinatesystem.h"
CoordinateSystem::CoordinateSystem(int code)
{
switch (code) {
case 1024:
case 1035:
case 1039:
case 4400:
case 4409:
case 4463:
case 4464:
case 4465:
case 4466:
case 4467:
case 4469:
case 4470:
case 4495:
case 4496:
case 4497:
case 4498:
case 4499:
_axisOrder = XY;
break;
case 4500:
case 4530:
case 4531:
case 4532:
_axisOrder = YX;
break;
default:
_axisOrder = Unknown;
break;
}
}
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const CoordinateSystem &cs)
{
QString ao;
switch (cs.axisOrder()) {
case CoordinateSystem::XY:
ao = "XY";
break;
case CoordinateSystem::YX:
ao = "YX";
break;
default:
ao = "Unknown";
}
dbg.nospace() << "CoordinateSystem(" << ao << ")";
return dbg.space();
}
#endif // QT_NO_DEBUG

View File

@ -0,0 +1,27 @@
#ifndef COORDINATESYSTEM_H
#define COORDINATESYSTEM_H
#include <QDebug>
class CoordinateSystem
{
public:
enum AxisOrder {Unknown, XY, YX};
CoordinateSystem() : _axisOrder(Unknown) {}
CoordinateSystem(AxisOrder axisOrder) : _axisOrder(axisOrder) {}
CoordinateSystem(int code);
bool isValid() const {return (_axisOrder != Unknown);}
AxisOrder axisOrder() const {return _axisOrder;}
private:
AxisOrder _axisOrder;
};
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const CoordinateSystem &cs);
#endif // QT_NO_DEBUG
#endif // COORDINATESYSTEM_H

45
src/map/crs.cpp Normal file
View File

@ -0,0 +1,45 @@
#include <QStringList>
#include "pcs.h"
#include "crs.h"
Projection CRS::projection(const QString &crs)
{
QStringList list(crs.split(':'));
QString authority, code;
bool res;
int epsg;
const PCS *pcs;
const GCS *gcs;
switch (list.size()) {
case 2:
authority = list.at(0);
code = list.at(1);
break;
case 7:
authority = list.at(4);
code = list.at(6);
break;
default:
return Projection();
}
if (authority == "EPSG") {
epsg = code.toInt(&res);
if (!res)
return Projection();
if ((pcs = PCS::pcs(epsg)))
return Projection(pcs);
else if ((gcs = GCS::gcs(epsg)))
return Projection(gcs);
else
return Projection();
} else if (authority == "OGC") {
if (code == "CRS84")
return Projection(GCS::gcs(4326), CoordinateSystem::XY);
else
return Projection();
} else
return Projection();
}

11
src/map/crs.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef CRS_H
#define CRS_H
#include "projection.h"
namespace CRS
{
Projection projection(const QString &crs);
}
#endif // CRS_H

View File

@ -2,6 +2,7 @@
#include <QFileInfo> #include <QFileInfo>
#include <QNetworkRequest> #include <QNetworkRequest>
#include <QNetworkReply> #include <QNetworkReply>
#include <QBasicTimer>
#include "config.h" #include "config.h"
#include "downloader.h" #include "downloader.h"
@ -25,15 +26,68 @@
#define ATTR_LEVEL (QNetworkRequest::Attribute)(QNetworkRequest::User + 2) #define ATTR_LEVEL (QNetworkRequest::Attribute)(QNetworkRequest::User + 2)
#define MAX_REDIRECT_LEVEL 5 #define MAX_REDIRECT_LEVEL 5
#define TIMEOUT 30 /* s */
Authorization::Authorization(const QString &username, const QString &password)
{
QString concatenated = username + ":" + password;
QByteArray data = concatenated.toLocal8Bit().toBase64();
_header = "Basic " + data;
}
class Downloader::ReplyTimeout : public QObject
{
public:
static void setTimeout(QNetworkReply *reply, int timeout)
{
Q_ASSERT(reply);
new ReplyTimeout(reply, timeout);
}
private:
ReplyTimeout(QNetworkReply *reply, int timeout) : QObject(reply)
{
_timer.start(timeout * 1000, this);
}
void timerEvent(QTimerEvent *ev)
{
if (!_timer.isActive() || ev->timerId() != _timer.timerId())
return;
QNetworkReply *reply = static_cast<QNetworkReply*>(parent());
if (reply->isRunning())
reply->close();
_timer.stop();
}
QBasicTimer _timer;
};
class Downloader::Redirect
{
public:
Redirect() : _level(0) {}
Redirect(const QUrl &origin, int level) :
_origin(origin), _level(level) {}
const QUrl &origin() const {return _origin;}
int level() const {return _level;}
private:
QUrl _origin;
int _level;
};
Downloader::Downloader(QObject *parent) : QObject(parent) Downloader::Downloader(QObject *parent) : QObject(parent)
{ {
connect(&_manager, SIGNAL(finished(QNetworkReply*)), connect(&_manager, SIGNAL(finished(QNetworkReply*)),
SLOT(downloadFinished(QNetworkReply*))); SLOT(downloadFinished(QNetworkReply*)));
} }
bool Downloader::doDownload(const Download &dl, const Redirect &redirect) bool Downloader::doDownload(const Download &dl,
const QByteArray &authorization, const Redirect *redirect)
{ {
QUrl url(dl.url()); QUrl url(dl.url());
@ -44,14 +98,20 @@ bool Downloader::doDownload(const Download &dl, const Redirect &redirect)
QNetworkRequest request(url); QNetworkRequest request(url);
request.setAttribute(ATTR_FILE, QVariant(dl.file())); request.setAttribute(ATTR_FILE, QVariant(dl.file()));
if (!redirect.isNull()) { if (redirect) {
request.setAttribute(ATTR_ORIGIN, QVariant(redirect.origin())); request.setAttribute(ATTR_ORIGIN, QVariant(redirect->origin()));
request.setAttribute(ATTR_LEVEL, QVariant(redirect.level())); request.setAttribute(ATTR_LEVEL, QVariant(redirect->level()));
} }
request.setRawHeader("User-Agent", USER_AGENT); request.setRawHeader("User-Agent", USER_AGENT);
QNetworkReply *reply = _manager.get(request); if (!authorization.isNull())
request.setRawHeader("Authorization", authorization);
_currentDownloads.insert(url, reply); QNetworkReply *reply = _manager.get(request);
if (reply) {
_currentDownloads.insert(url);
ReplyTimeout::setTimeout(reply, TIMEOUT);
} else
return false;
return true; return true;
} }
@ -61,7 +121,7 @@ bool Downloader::saveToDisk(const QString &filename, QIODevice *data)
QFile file(filename); QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) { if (!file.open(QIODevice::WriteOnly)) {
qWarning("Error writing map tile: %s: %s\n", qWarning("Error writing file: %s: %s\n",
qPrintable(filename), qPrintable(file.errorString())); qPrintable(filename), qPrintable(file.errorString()));
return false; return false;
} }
@ -80,11 +140,11 @@ void Downloader::downloadFinished(QNetworkReply *reply)
QUrl origin = reply->request().attribute(ATTR_ORIGIN).toUrl(); QUrl origin = reply->request().attribute(ATTR_ORIGIN).toUrl();
if (origin.isEmpty()) { if (origin.isEmpty()) {
_errorDownloads.insert(url); _errorDownloads.insert(url);
qWarning("Error downloading map tile: %s: %s\n", qWarning("Error downloading file: %s: %s\n",
url.toEncoded().constData(), qPrintable(reply->errorString())); url.toEncoded().constData(), qPrintable(reply->errorString()));
} else { } else {
_errorDownloads.insert(origin); _errorDownloads.insert(origin);
qWarning("Error downloading map tile: %s -> %s: %s\n", qWarning("Error downloading file: %s -> %s: %s\n",
origin.toEncoded().constData(), url.toEncoded().constData(), origin.toEncoded().constData(), url.toEncoded().constData(),
qPrintable(reply->errorString())); qPrintable(reply->errorString()));
} }
@ -99,17 +159,18 @@ void Downloader::downloadFinished(QNetworkReply *reply)
if (location == url) { if (location == url) {
_errorDownloads.insert(url); _errorDownloads.insert(url);
qWarning("Error downloading map tile: %s: " qWarning("Error downloading file: %s: "
"redirect loop\n", url.toEncoded().constData()); "redirect loop\n", url.toEncoded().constData());
} else if (level >= MAX_REDIRECT_LEVEL) { } else if (level >= MAX_REDIRECT_LEVEL) {
_errorDownloads.insert(origin); _errorDownloads.insert(origin);
qWarning("Error downloading map tile: %s: " qWarning("Error downloading file: %s: "
"redirect level limit reached\n", "redirect level limit reached\n",
origin.toEncoded().constData()); origin.toEncoded().constData());
} else { } else {
Redirect redirect(origin.isEmpty() ? url : origin, level + 1); Redirect redirect(origin.isEmpty() ? url : origin, level + 1);
Download dl(location, filename); Download dl(location, filename);
doDownload(dl, redirect); doDownload(dl, reply->request().rawHeader("Authorization"),
&redirect);
} }
} else } else
if (!saveToDisk(filename, reply)) if (!saveToDisk(filename, reply))
@ -123,12 +184,13 @@ void Downloader::downloadFinished(QNetworkReply *reply)
emit finished(); emit finished();
} }
bool Downloader::get(const QList<Download> &list) bool Downloader::get(const QList<Download> &list,
const Authorization &authorization)
{ {
bool finishEmitted = false; bool finishEmitted = false;
for (int i = 0; i < list.count(); i++) for (int i = 0; i < list.count(); i++)
finishEmitted |= doDownload(list.at(i)); finishEmitted |= doDownload(list.at(i), authorization.header());
return finishEmitted; return finishEmitted;
} }

View File

@ -1,20 +1,18 @@
#ifndef DOWNLOADER_H #ifndef DOWNLOADER_H
#define DOWNLOADER_H #define DOWNLOADER_H
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QUrl> #include <QUrl>
#include <QList> #include <QList>
#include <QMap>
#include <QSet> #include <QSet>
class QNetworkReply; class QNetworkReply;
class Download class Download
{ {
public: public:
Download(const QUrl &url, const QString &file) Download(const QUrl &url, const QString &file) : _url(url), _file(file) {}
{_url = url; _file = file;}
const QUrl& url() const {return _url;} const QUrl& url() const {return _url;}
const QString& file() const {return _file;} const QString& file() const {return _file;}
@ -23,6 +21,17 @@ private:
QString _file; QString _file;
}; };
class Authorization
{
public:
Authorization() {}
Authorization(const QString &username, const QString &password);
const QByteArray &header() const {return _header;}
private:
QByteArray _header;
};
class Downloader : public QObject class Downloader : public QObject
{ {
@ -31,7 +40,9 @@ class Downloader : public QObject
public: public:
Downloader(QObject *parent = 0); Downloader(QObject *parent = 0);
bool get(const QList<Download> &list); bool get(const QList<Download> &list, const Authorization &authorization
= Authorization());
void clearErrors() {_errorDownloads.clear();}
signals: signals:
void finished(); void finished();
@ -40,28 +51,15 @@ private slots:
void downloadFinished(QNetworkReply *reply); void downloadFinished(QNetworkReply *reply);
private: private:
class Redirect class Redirect;
{ class ReplyTimeout;
public:
Redirect() : _level(0) {}
Redirect(const QUrl &origin, int level) :
_origin(origin), _level(level) {}
const QUrl &origin() const {return _origin;} bool doDownload(const Download &dl, const QByteArray &authorization,
int level() const {return _level;} const Redirect *redirect = 0);
bool isNull() const {return (_level == 0);}
private:
QUrl _origin;
int _level;
};
bool doDownload(const Download &dl, const Redirect &redirect = Redirect());
bool saveToDisk(const QString &filename, QIODevice *data); bool saveToDisk(const QString &filename, QIODevice *data);
QNetworkAccessManager _manager; QNetworkAccessManager _manager;
QMap<QUrl, QNetworkReply *> _currentDownloads; QSet<QUrl> _currentDownloads;
QSet<QUrl> _errorDownloads; QSet<QUrl> _errorDownloads;
}; };

View File

@ -14,9 +14,9 @@ QMap<int, Ellipsoid> Ellipsoid::WGS84()
const Ellipsoid *Ellipsoid::ellipsoid(int id) const Ellipsoid *Ellipsoid::ellipsoid(int id)
{ {
QMap<int, Ellipsoid>::const_iterator it = _ellipsoids.find(id); QMap<int, Ellipsoid>::const_iterator it(_ellipsoids.find(id));
if (it == _ellipsoids.end()) if (it == _ellipsoids.constEnd())
return 0; return 0;
else else
return &(it.value()); return &(it.value());

View File

@ -6,8 +6,9 @@
#include "emptymap.h" #include "emptymap.h"
#define SCALE_MIN 0.5 #define ZOOM_MIN 0
#define SCALE_MAX 1.0E-6 #define ZOOM_MAX 19
#define TILE_SIZE 256
static QPointF ll2m(const Coordinates &c) static QPointF ll2m(const Coordinates &c)
{ {
@ -19,10 +20,30 @@ static Coordinates m2ll(const QPointF &p)
return Coordinates(p.x(), rad2deg(2 * atan(exp(deg2rad(p.y()))) - M_PI/2)); return Coordinates(p.x(), rad2deg(2 * atan(exp(deg2rad(p.y()))) - M_PI/2));
} }
static qreal zoom2scale(int zoom)
{
return (360.0/(qreal)((1<<zoom) * TILE_SIZE));
}
static int scale2zoom(qreal scale)
{
return (int)log2(360.0/(scale * (qreal)TILE_SIZE));
}
static int limitZoom(int zoom)
{
if (zoom < ZOOM_MIN)
return ZOOM_MIN;
if (zoom > ZOOM_MAX)
return ZOOM_MAX;
return zoom;
}
EmptyMap::EmptyMap(QObject *parent) : Map(parent) EmptyMap::EmptyMap(QObject *parent) : Map(parent)
{ {
_scale = SCALE_MAX; _zoom = ZOOM_MAX;
} }
QRectF EmptyMap::bounds() const QRectF EmptyMap::bounds() const
@ -30,49 +51,38 @@ QRectF EmptyMap::bounds() const
return QRectF(ll2xy(Coordinates(-180, 85)), ll2xy(Coordinates(180, -85))); return QRectF(ll2xy(Coordinates(-180, 85)), ll2xy(Coordinates(180, -85)));
} }
qreal EmptyMap::zoomFit(const QSize &size, const RectC &br) int EmptyMap::zoomFit(const QSize &size, const RectC &br)
{ {
if (!br.isValid()) if (!br.isValid())
_scale = SCALE_MAX; _zoom = ZOOM_MAX;
else { else {
QRectF tbr(ll2m(br.topLeft()), ll2m(br.bottomRight())); QRectF tbr(ll2m(br.topLeft()), ll2m(br.bottomRight()));
QPointF sc(tbr.width() / size.width(), tbr.height() / size.height()); QPointF sc(tbr.width() / size.width(), tbr.height() / size.height());
_scale = qMax(sc.x(), sc.y());
_zoom = limitZoom(scale2zoom(qMax(sc.x(), sc.y())));
} }
_scale = qMax(_scale, SCALE_MAX); return _zoom;
_scale = qMin(_scale, SCALE_MIN);
return _scale;
} }
qreal EmptyMap::zoomFit(qreal resolution, const Coordinates &c) qreal EmptyMap::resolution(const QRectF &rect) const
{ {
_scale = (360.0 * resolution) / (WGS84_RADIUS * 2 * M_PI qreal scale = zoom2scale(_zoom);
* cos(deg2rad(c.lat())));
_scale = qMax(_scale, SCALE_MAX); return (WGS84_RADIUS * 2.0 * M_PI * scale / 360.0
_scale = qMin(_scale, SCALE_MIN); * cos(2.0 * atan(exp(deg2rad(-rect.center().y() * scale))) - M_PI/2));
return _scale;
} }
qreal EmptyMap::resolution(const QPointF &p) const int EmptyMap::zoomIn()
{ {
return (WGS84_RADIUS * 2 * M_PI * _scale / 360.0 _zoom = qMin(_zoom + 1, ZOOM_MAX);
* cos(2.0 * atan(exp(deg2rad(-p.y() * _scale))) - M_PI/2)); return _zoom;
} }
qreal EmptyMap::zoomIn() int EmptyMap::zoomOut()
{ {
_scale = qMax(_scale / 2.0, SCALE_MAX); _zoom = qMax(_zoom - 1, ZOOM_MIN);
return _scale; return _zoom;
}
qreal EmptyMap::zoomOut()
{
_scale = qMin(_scale * 2.0, SCALE_MIN);
return _scale;
} }
void EmptyMap::draw(QPainter *painter, const QRectF &rect) void EmptyMap::draw(QPainter *painter, const QRectF &rect)
@ -82,12 +92,13 @@ void EmptyMap::draw(QPainter *painter, const QRectF &rect)
QPointF EmptyMap::ll2xy(const Coordinates &c) const QPointF EmptyMap::ll2xy(const Coordinates &c) const
{ {
qreal scale = zoom2scale(_zoom);
QPointF m = ll2m(c); QPointF m = ll2m(c);
return QPointF(m.x() / _scale, m.y() / -_scale); return QPointF(m.x() / scale, m.y() / -scale);
} }
Coordinates EmptyMap::xy2ll(const QPointF &p) const Coordinates EmptyMap::xy2ll(const QPointF &p) const
{ {
QPointF m(p.x() * _scale, -p.y() * _scale); qreal scale = zoom2scale(_zoom);
return m2ll(QPointF(p.x() * _scale, -p.y() * _scale)); return m2ll(QPointF(p.x() * scale, -p.y() * scale));
} }

View File

@ -1,7 +1,6 @@
#ifndef EMPTYMAP_H #ifndef EMPTYMAP_H
#define EMPTYMAP_H #define EMPTYMAP_H
#include "common/coordinates.h"
#include "map.h" #include "map.h"
class EmptyMap : public Map class EmptyMap : public Map
@ -14,13 +13,12 @@ public:
const QString &name() const {return _name;} const QString &name() const {return _name;}
QRectF bounds() const; QRectF bounds() const;
qreal resolution(const QPointF &p) const; qreal resolution(const QRectF &rect) const;
qreal zoom() const {return _scale;} int zoom() const {return _zoom;}
qreal zoomFit(const QSize &size, const RectC &br); int zoomFit(const QSize &size, const RectC &br);
qreal zoomFit(qreal resolution, const Coordinates &c); int zoomIn();
qreal zoomIn(); int zoomOut();
qreal zoomOut();
QPointF ll2xy(const Coordinates &c) QPointF ll2xy(const Coordinates &c)
{return static_cast<const EmptyMap &>(*this).ll2xy(c);} {return static_cast<const EmptyMap &>(*this).ll2xy(c);}
@ -34,7 +32,7 @@ private:
Coordinates xy2ll(const QPointF &p) const; Coordinates xy2ll(const QPointF &p) const;
QString _name; QString _name;
qreal _scale; int _zoom;
}; };
#endif // EMPTYMAP_H #endif // EMPTYMAP_H

View File

@ -92,62 +92,62 @@ void GCS::loadList(const QString &path)
QByteArray line = file.readLine(); QByteArray line = file.readLine();
QList<QByteArray> list = line.split(','); QList<QByteArray> list = line.split(',');
if (list.size() < 10) { if (list.size() < 10) {
qWarning("%s: %d: Format error", qPrintable(path), ln); qWarning("%s:%d: Format error", qPrintable(path), ln);
continue; continue;
} }
int id = parameter(list[1], &res); int id = parameter(list[1], &res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid GCS code", qPrintable(path), ln); qWarning("%s:%d: Invalid GCS code", qPrintable(path), ln);
continue; continue;
} }
int gd = parameter(list[2], &res); int gd = parameter(list[2], &res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid geodetic datum code", qPrintable(path), qWarning("%s:%d: Invalid geodetic datum code", qPrintable(path),
ln); ln);
continue; continue;
} }
int au = list[3].trimmed().toInt(&res); int au = list[3].trimmed().toInt(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid angular units code", qPrintable(path), qWarning("%s:%d: Invalid angular units code", qPrintable(path),
ln); ln);
continue; continue;
} }
int el = list[4].trimmed().toInt(&res); int el = list[4].trimmed().toInt(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid ellipsoid code", qPrintable(path), ln); qWarning("%s:%d: Invalid ellipsoid code", qPrintable(path), ln);
continue; continue;
} }
int pm = list[5].trimmed().toInt(&res); int pm = list[5].trimmed().toInt(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid prime meridian code", qPrintable(path), qWarning("%s:%d: Invalid prime meridian code", qPrintable(path),
ln); ln);
continue; continue;
} }
int ct = list[6].trimmed().toInt(&res); int ct = list[6].trimmed().toInt(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid coordinates transformation code", qWarning("%s:%d: Invalid coordinates transformation code",
qPrintable(path), ln); qPrintable(path), ln);
continue; continue;
} }
double dx = list[7].trimmed().toDouble(&res); double dx = list[7].trimmed().toDouble(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid dx", qPrintable(path), ln); qWarning("%s:%d: Invalid dx", qPrintable(path), ln);
continue; continue;
} }
double dy = list[8].trimmed().toDouble(&res); double dy = list[8].trimmed().toDouble(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid dy", qPrintable(path), ln); qWarning("%s:%d: Invalid dy", qPrintable(path), ln);
continue; continue;
} }
double dz = list[9].trimmed().toDouble(&res); double dz = list[9].trimmed().toDouble(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid dz", qPrintable(path), ln); qWarning("%s:%d: Invalid dz", qPrintable(path), ln);
continue; continue;
} }
if (!(e = Ellipsoid::ellipsoid(el))) { if (!(e = Ellipsoid::ellipsoid(el))) {
qWarning("%s: %d: Unknown ellipsoid code", qPrintable(path), ln); qWarning("%s:%d: Unknown ellipsoid code", qPrintable(path), ln);
continue; continue;
} }
@ -157,7 +157,7 @@ void GCS::loadList(const QString &path)
datum = Datum(e, dx, dy, dz); datum = Datum(e, dx, dy, dz);
break; break;
default: default:
qWarning("%s: %d: Unknown coordinates transformation method", qWarning("%s:%d: Unknown coordinates transformation method",
qPrintable(path), ln); qPrintable(path), ln);
continue; continue;
} }
@ -166,7 +166,7 @@ void GCS::loadList(const QString &path)
if (gcs.isValid()) if (gcs.isValid())
_gcss.append(Entry(id, gd, list[0].trimmed(), gcs)); _gcss.append(Entry(id, gd, list[0].trimmed(), gcs));
else else
qWarning("%s: %d: Unknown prime meridian/angular units code", qWarning("%s:%d: Unknown prime meridian/angular units code",
qPrintable(path), ln); qPrintable(path), ln);
} }
} }

View File

@ -25,7 +25,6 @@ public:
Coordinates toWGS84(const Coordinates &c) const; Coordinates toWGS84(const Coordinates &c) const;
Coordinates fromWGS84(const Coordinates &c) const; Coordinates fromWGS84(const Coordinates &c) const;
static const GCS *gcs(int id); static const GCS *gcs(int id);
static const GCS *gcs(int geodeticDatum, int primeMeridian, static const GCS *gcs(int geodeticDatum, int primeMeridian,
int angularUnits); int angularUnits);

View File

@ -1,7 +1,7 @@
#include <QFileInfo> #include <QFileInfo>
#include <QtEndian> #include <QtEndian>
#include "pcs.h" #include "pcs.h"
#include "latlon.h" #include "tifffile.h"
#include "geotiff.h" #include "geotiff.h"
@ -9,41 +9,53 @@
#define TIFF_SHORT 3 #define TIFF_SHORT 3
#define TIFF_LONG 4 #define TIFF_LONG 4
#define ModelPixelScaleTag 33550 #define ModelPixelScaleTag 33550
#define ModelTiepointTag 33922 #define ModelTiepointTag 33922
#define ModelTransformationTag 34264 #define ModelTransformationTag 34264
#define GeoKeyDirectoryTag 34735 #define GeoKeyDirectoryTag 34735
#define GeoDoubleParamsTag 34736 #define GeoDoubleParamsTag 34736
#define ImageWidth 256
#define ImageHeight 257
#define GTModelTypeGeoKey 1024 #define GTModelTypeGeoKey 1024
#define GTRasterTypeGeoKey 1025 #define GTRasterTypeGeoKey 1025
#define GeographicTypeGeoKey 2048 #define GeographicTypeGeoKey 2048
#define GeogGeodeticDatumGeoKey 2050 #define GeogGeodeticDatumGeoKey 2050
#define GeogPrimeMeridianGeoKey 2051 #define GeogPrimeMeridianGeoKey 2051
#define GeogAngularUnitsGeoKey 2054 #define GeogAngularUnitsGeoKey 2054
#define ProjectedCSTypeGeoKey 3072 #define GeogEllipsoidGeoKey 2056
#define ProjectionGeoKey 3074 #define GeogAzimuthUnitsGeoKey 2060
#define ProjCoordTransGeoKey 3075 #define ProjectedCSTypeGeoKey 3072
#define ProjLinearUnitsGeoKey 3076 #define ProjectionGeoKey 3074
#define ProjStdParallel1GeoKey 3078 #define ProjCoordTransGeoKey 3075
#define ProjStdParallel2GeoKey 3079 #define ProjLinearUnitsGeoKey 3076
#define ProjNatOriginLongGeoKey 3080 #define ProjStdParallel1GeoKey 3078
#define ProjNatOriginLatGeoKey 3081 #define ProjStdParallel2GeoKey 3079
#define ProjFalseEastingGeoKey 3082 #define ProjNatOriginLongGeoKey 3080
#define ProjFalseNorthingGeoKey 3083 #define ProjNatOriginLatGeoKey 3081
#define ProjScaleAtNatOriginGeoKey 3092 #define ProjFalseEastingGeoKey 3082
#define ProjFalseNorthingGeoKey 3083
#define ProjCenterLongGeoKey 3088
#define ProjCenterLatGeoKey 3089
#define ProjScaleAtNatOriginGeoKey 3092
#define ProjScaleAtCenterGeoKey 3093
#define ProjAzimuthAngleGeoKey 3094
#define ProjRectifiedGridAngleGeoKey 3096
#define ModelTypeProjected 1
#define ModelTypeGeographic 2
#define ModelTypeGeocentric 3
#define CT_TransverseMercator 1
#define CT_ObliqueMercator 3
#define CT_Mercator 7
#define CT_LambertConfConic_2SP 8
#define CT_LambertConfConic_1SP 9
#define CT_LambertAzimEqualArea 10
#define CT_AlbersEqualArea 11
#define ModelTypeProjected 1
#define ModelTypeGeographic 2
#define ModelTypeGeocentric 3
#define IS_SET(map, key) \ #define IS_SET(map, key) \
((map).contains(key) && (map).value(key).SHORT != 32767) ((map).contains(key) && (map).value(key).SHORT != 32767)
#define ARRAY_SIZE(a) \
(sizeof(a) / sizeof(*a))
typedef struct { typedef struct {
quint16 KeyDirectoryVersion; quint16 KeyDirectoryVersion;
@ -219,10 +231,12 @@ bool GeoTIFF::readKeys(TIFFFile &file, Ctx &ctx, QMap<quint16, Value> &kv) const
case GeogGeodeticDatumGeoKey: case GeogGeodeticDatumGeoKey:
case GeogPrimeMeridianGeoKey: case GeogPrimeMeridianGeoKey:
case GeogAngularUnitsGeoKey: case GeogAngularUnitsGeoKey:
case GeogAzimuthUnitsGeoKey:
case ProjectedCSTypeGeoKey: case ProjectedCSTypeGeoKey:
case ProjectionGeoKey: case ProjectionGeoKey:
case ProjCoordTransGeoKey: case ProjCoordTransGeoKey:
case ProjLinearUnitsGeoKey: case ProjLinearUnitsGeoKey:
case GeogEllipsoidGeoKey:
if (entry.TIFFTagLocation != 0 || entry.Count != 1) if (entry.TIFFTagLocation != 0 || entry.Count != 1)
return false; return false;
value.SHORT = entry.ValueOffset; value.SHORT = entry.ValueOffset;
@ -235,6 +249,11 @@ bool GeoTIFF::readKeys(TIFFFile &file, Ctx &ctx, QMap<quint16, Value> &kv) const
case ProjFalseNorthingGeoKey: case ProjFalseNorthingGeoKey:
case ProjStdParallel1GeoKey: case ProjStdParallel1GeoKey:
case ProjStdParallel2GeoKey: case ProjStdParallel2GeoKey:
case ProjCenterLongGeoKey:
case ProjCenterLatGeoKey:
case ProjScaleAtCenterGeoKey:
case ProjAzimuthAngleGeoKey:
case ProjRectifiedGridAngleGeoKey:
if (!readGeoValue(file, ctx.values, entry.ValueOffset, if (!readGeoValue(file, ctx.values, entry.ValueOffset,
value.DOUBLE)) value.DOUBLE))
return false; return false;
@ -272,13 +291,20 @@ const GCS *GeoTIFF::gcs(QMap<quint16, Value> &kv)
if (!(gcs = GCS::gcs(kv.value(GeographicTypeGeoKey).SHORT))) if (!(gcs = GCS::gcs(kv.value(GeographicTypeGeoKey).SHORT)))
_errorString = QString("%1: unknown GCS") _errorString = QString("%1: unknown GCS")
.arg(kv.value(GeographicTypeGeoKey).SHORT); .arg(kv.value(GeographicTypeGeoKey).SHORT);
} else if (IS_SET(kv, GeogGeodeticDatumGeoKey)) { } else if (IS_SET(kv, GeogGeodeticDatumGeoKey)
|| kv.value(GeogEllipsoidGeoKey).SHORT == 7019
|| kv.value(GeogEllipsoidGeoKey).SHORT == 7030) {
int pm = IS_SET(kv, GeogPrimeMeridianGeoKey) int pm = IS_SET(kv, GeogPrimeMeridianGeoKey)
? kv.value(GeogPrimeMeridianGeoKey).SHORT : 8901; ? kv.value(GeogPrimeMeridianGeoKey).SHORT : 8901;
int au = IS_SET(kv, GeogAngularUnitsGeoKey) int au = IS_SET(kv, GeogAngularUnitsGeoKey)
? kv.value(GeogAngularUnitsGeoKey).SHORT : 9102; ? kv.value(GeogAngularUnitsGeoKey).SHORT : 9102;
if (!(gcs = GCS::gcs(kv.value(GeogGeodeticDatumGeoKey).SHORT, pm, au))) // If only the ellipsoid is defined and it is GRS80 or WGS84, handle
// such definition as a WGS84 geodetic datum.
int gd = IS_SET(kv, GeogGeodeticDatumGeoKey)
? kv.value(GeogGeodeticDatumGeoKey).SHORT : 6326;
if (!(gcs = GCS::gcs(gd, pm, au)))
_errorString = QString("%1+%2: unknown geodetic datum + prime" _errorString = QString("%1+%2: unknown geodetic datum + prime"
" meridian combination") " meridian combination")
.arg(kv.value(GeogGeodeticDatumGeoKey).SHORT) .arg(kv.value(GeogGeodeticDatumGeoKey).SHORT)
@ -297,17 +323,19 @@ Projection::Method GeoTIFF::method(QMap<quint16, Value> &kv)
} }
switch (kv.value(ProjCoordTransGeoKey).SHORT) { switch (kv.value(ProjCoordTransGeoKey).SHORT) {
case 1: case CT_TransverseMercator:
return Projection::Method(9807); return Projection::Method(9807);
case 7: case CT_ObliqueMercator:
return Projection::Method(9815);
case CT_Mercator:
return Projection::Method(1024); return Projection::Method(1024);
case 8: case CT_LambertConfConic_2SP:
return Projection::Method(9801);
case 9:
return Projection::Method(9802); return Projection::Method(9802);
case 10: case CT_LambertConfConic_1SP:
return Projection::Method(9801);
case CT_LambertAzimEqualArea:
return Projection::Method(9820); return Projection::Method(9820);
case 11: case CT_AlbersEqualArea:
return Projection::Method(9822); return Projection::Method(9822);
default: default:
_errorString = QString("%1: unknown coordinate transformation method") _errorString = QString("%1: unknown coordinate transformation method")
@ -325,8 +353,7 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
.arg(kv.value(ProjectedCSTypeGeoKey).SHORT); .arg(kv.value(ProjectedCSTypeGeoKey).SHORT);
return false; return false;
} }
_projection = Projection(pcs->gcs(), pcs->method(), pcs->setup(), _projection = Projection(pcs);
pcs->units());
} else if (IS_SET(kv, ProjectionGeoKey)) { } else if (IS_SET(kv, ProjectionGeoKey)) {
const GCS *g = gcs(kv); const GCS *g = gcs(kv);
if (!g) if (!g)
@ -338,9 +365,10 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
.arg(kv.value(ProjectionGeoKey).SHORT); .arg(kv.value(ProjectionGeoKey).SHORT);
return false; return false;
} }
_projection = Projection(pcs->gcs(), pcs->method(), pcs->setup(), _projection = Projection(pcs);
pcs->units());
} else { } else {
double lat0, lon0, scale, fe, fn, sp1, sp2;
const GCS *g = gcs(kv); const GCS *g = gcs(kv);
if (!g) if (!g)
return false; return false;
@ -350,6 +378,8 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
AngularUnits au(IS_SET(kv, GeogAngularUnitsGeoKey) AngularUnits au(IS_SET(kv, GeogAngularUnitsGeoKey)
? kv.value(GeogAngularUnitsGeoKey).SHORT : 9102); ? kv.value(GeogAngularUnitsGeoKey).SHORT : 9102);
AngularUnits zu(IS_SET(kv, GeogAzimuthUnitsGeoKey)
? kv.value(GeogAzimuthUnitsGeoKey).SHORT : 9102);
LinearUnits lu(IS_SET(kv, ProjLinearUnitsGeoKey) LinearUnits lu(IS_SET(kv, ProjLinearUnitsGeoKey)
? kv.value(ProjLinearUnitsGeoKey).SHORT : 9001); ? kv.value(ProjLinearUnitsGeoKey).SHORT : 9001);
if (lu.isNull()) { if (lu.isNull()) {
@ -358,17 +388,48 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
return false; return false;
} }
Projection::Setup setup( if (kv.contains(ProjNatOriginLatGeoKey))
au.toDegrees(kv.value(ProjNatOriginLatGeoKey).DOUBLE), lat0 = au.toDegrees(kv.value(ProjNatOriginLatGeoKey).DOUBLE);
au.toDegrees(kv.value(ProjNatOriginLongGeoKey).DOUBLE), else if (kv.contains(ProjCenterLatGeoKey))
kv.value(ProjScaleAtNatOriginGeoKey).DOUBLE, lat0 = au.toDegrees(kv.value(ProjCenterLatGeoKey).DOUBLE);
lu.toMeters(kv.value(ProjFalseEastingGeoKey).DOUBLE), else
lu.toMeters(kv.value(ProjFalseNorthingGeoKey).DOUBLE), lat0 = NAN;
au.toDegrees(kv.value(ProjStdParallel1GeoKey).DOUBLE), if (kv.contains(ProjNatOriginLongGeoKey))
au.toDegrees(kv.value(ProjStdParallel2GeoKey).DOUBLE) lon0 = au.toDegrees(kv.value(ProjNatOriginLongGeoKey).DOUBLE);
); else if (kv.contains(ProjCenterLongGeoKey))
lon0 = au.toDegrees(kv.value(ProjCenterLongGeoKey).DOUBLE);
else
lon0 = NAN;
if (kv.contains(ProjScaleAtNatOriginGeoKey))
scale = kv.value(ProjScaleAtNatOriginGeoKey).DOUBLE;
else if (kv.contains(ProjScaleAtCenterGeoKey))
scale = kv.value(ProjScaleAtCenterGeoKey).DOUBLE;
else
scale = NAN;
if (kv.contains(ProjStdParallel1GeoKey))
sp1 = au.toDegrees(kv.value(ProjStdParallel1GeoKey).DOUBLE);
else if (kv.contains(ProjAzimuthAngleGeoKey))
sp1 = zu.toDegrees(kv.value(ProjAzimuthAngleGeoKey).DOUBLE);
else
sp1 = NAN;
if (kv.contains(ProjStdParallel2GeoKey))
sp2 = au.toDegrees(kv.value(ProjStdParallel2GeoKey).DOUBLE);
else if (kv.contains(ProjRectifiedGridAngleGeoKey))
sp2 = au.toDegrees(kv.value(ProjRectifiedGridAngleGeoKey).DOUBLE);
else
sp2 = NAN;
if (kv.contains(ProjFalseNorthingGeoKey))
fn = lu.toMeters(kv.value(ProjFalseNorthingGeoKey).DOUBLE);
else
fn = NAN;
if (kv.contains(ProjFalseEastingGeoKey))
fe = lu.toMeters(kv.value(ProjFalseEastingGeoKey).DOUBLE);
else
fe = NAN;
_projection = Projection(g, m, setup, lu); Projection::Setup setup(lat0, lon0, scale, fe, fn, sp1, sp2);
PCS pcs(g, m, setup, lu, CoordinateSystem());
_projection = Projection(&pcs);
} }
return true; return true;
@ -385,7 +446,7 @@ bool GeoTIFF::geographicModel(QMap<quint16, Value> &kv)
return true; return true;
} }
bool GeoTIFF::load(const QString &path) GeoTIFF::GeoTIFF(const QString &path)
{ {
quint32 ifd; quint32 ifd;
QList<ReferencePoint> points; QList<ReferencePoint> points;
@ -399,86 +460,76 @@ bool GeoTIFF::load(const QString &path)
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
_errorString = QString("Error opening TIFF file: %1") _errorString = QString("Error opening TIFF file: %1")
.arg(file.errorString()); .arg(file.errorString());
return false; return;
} }
if (!file.readHeader(ifd)) { if (!file.readHeader(ifd)) {
_errorString = "Invalid TIFF header"; _errorString = "Invalid TIFF header";
return false; return;
} }
while (ifd) { while (ifd) {
if (!readIFD(file, ifd, ctx)) { if (!readIFD(file, ifd, ctx)) {
_errorString = "Invalid IFD"; _errorString = "Invalid IFD";
return false; return;
} }
} }
if (!ctx.keys) { if (!ctx.keys) {
_errorString = "Not a GeoTIFF file"; _errorString = "Not a GeoTIFF file";
return false; return;
} }
if (ctx.scale) { if (ctx.scale) {
if (!readScale(file, ctx.scale, scale)) { if (!readScale(file, ctx.scale, scale)) {
_errorString = "Error reading model pixel scale"; _errorString = "Error reading model pixel scale";
return false; return;
} }
} }
if (ctx.tiepoints) { if (ctx.tiepoints) {
if (!readTiepoints(file, ctx.tiepoints, ctx.tiepointCount, points)) { if (!readTiepoints(file, ctx.tiepoints, ctx.tiepointCount, points)) {
_errorString = "Error reading raster->model tiepoint pairs"; _errorString = "Error reading raster->model tiepoint pairs";
return false; return;
} }
} }
if (!readKeys(file, ctx, kv)) { if (!readKeys(file, ctx, kv)) {
_errorString = "Error reading Geo key/value"; _errorString = "Error reading Geo key/value";
return false; return;
} }
switch (kv.value(GTModelTypeGeoKey).SHORT) { switch (kv.value(GTModelTypeGeoKey).SHORT) {
case ModelTypeProjected: case ModelTypeProjected:
if (!projectedModel(kv)) if (!projectedModel(kv))
return false; return;
break; break;
case ModelTypeGeographic: case ModelTypeGeographic:
if (!geographicModel(kv)) if (!geographicModel(kv))
return false; return;
break; break;
case ModelTypeGeocentric: case ModelTypeGeocentric:
_errorString = "Geocentric models are not supported"; _errorString = "Geocentric models are not supported";
return false; return;
default: default:
_errorString = "Unknown/missing model type"; _errorString = "Unknown/missing model type";
return false; return;
} }
if (ctx.scale && ctx.tiepoints) { if (ctx.scale && ctx.tiepoints)
const ReferencePoint &p = points.first(); _transform = Transform(points.first(), scale);
_transform = QTransform(scale.x(), 0, 0, -scale.y(), p.pp.x() - p.xy.x() else if (ctx.tiepointCount > 1)
/ scale.x(), p.pp.y() + p.xy.x() / scale.y()).inverted(); _transform = Transform(points);
} else if (ctx.tiepointCount > 1) { else if (ctx.matrix) {
Transform t(points);
if (t.isNull()) {
_errorString = t.errorString();
return false;
}
_transform = t.transform();
} else if (ctx.matrix) {
double m[16]; double m[16];
if (!readMatrix(file, ctx.matrix, m)) { if (!readMatrix(file, ctx.matrix, m)) {
_errorString = "Error reading transformation matrix"; _errorString = "Error reading transformation matrix";
return false; return;
} }
if (m[2] != 0.0 || m[6] != 0.0 || m[8] != 0.0 || m[9] != 0.0 _transform = Transform(m);
|| m[10] != 0.0 || m[11] != 0.0) {
_errorString = "Not a baseline transformation matrix";
}
_transform = QTransform(m[0], m[1], m[4], m[5], m[3], m[7]).inverted();
} else { } else {
_errorString = "Incomplete/missing model transformation info"; _errorString = "Incomplete/missing model transformation info";
return false; return;
} }
return true; if (!_transform.isValid())
_errorString = _transform.errorString();
} }

View File

@ -1,23 +1,24 @@
#ifndef GEOTIFF_H #ifndef GEOTIFF_H
#define GEOTIFF_H #define GEOTIFF_H
#include <QTransform>
#include <QFile>
#include <QMap> #include <QMap>
#include "gcs.h" #include <QList>
#include "projection.h"
#include "tifffile.h"
#include "transform.h" #include "transform.h"
#include "linearunits.h" #include "projection.h"
class TIFFFile;
class GCS;
class GeoTIFF class GeoTIFF
{ {
public: public:
bool load(const QString &path); GeoTIFF(const QString &path);
bool isValid() const {return _projection.isValid() && _transform.isValid();}
const QString &errorString() const {return _errorString;} const QString &errorString() const {return _errorString;}
const Projection &projection() const {return _projection;} const Projection &projection() const {return _projection;}
const QTransform &transform() const {return _transform;} const Transform &transform() const {return _transform;}
private: private:
union Value { union Value {
@ -52,7 +53,7 @@ private:
bool geographicModel(QMap<quint16, Value> &kv); bool geographicModel(QMap<quint16, Value> &kv);
bool projectedModel(QMap<quint16, Value> &kv); bool projectedModel(QMap<quint16, Value> &kv);
QTransform _transform; Transform _transform;
Projection _projection; Projection _projection;
QString _errorString; QString _errorString;

View File

@ -1,193 +1,72 @@
/* #include <cmath>
* Based on libgeotrans with the following Source Code Disclaimer: #include "ellipsoid.h"
1. The GEOTRANS source code ("the software") is provided free of charge by
the National Imagery and Mapping Agency (NIMA) of the United States
Department of Defense. Although NIMA makes no copyright claim under Title 17
U.S.C., NIMA claims copyrights in the source code under other legal regimes.
NIMA hereby grants to each user of the software a license to use and
distribute the software, and develop derivative works.
2. Warranty Disclaimer: The software was developed to meet only the internal
requirements of the U.S. National Imagery and Mapping Agency. The software
is provided "as is," and no warranty, express or implied, including but not
limited to the implied warranties of merchantability and fitness for
particular purpose or arising by statute or otherwise in law or from a
course of dealing or usage in trade, is made by NIMA as to the accuracy and
functioning of the software.
3. NIMA and its personnel are not required to provide technical support or
general assistance with respect to the software.
4. Neither NIMA nor its personnel will be liable for any claims, losses, or
damages arising from or connected with the use of the software. The user
agrees to hold harmless the United States National Imagery and Mapping
Agency. The user's sole and exclusive remedy is to stop using the software.
5. NIMA requests that products developed using the software credit the
source of the software with the following statement, "The product was
developed using GEOTRANS, a product of the National Imagery and Mapping
Agency and U.S. Army Engineering Research and Development Center."
6. For any products developed using the software, NIMA requires a disclaimer
that use of the software does not indicate endorsement or approval of the
product by the Secretary of Defense or the National Imagery and Mapping
Agency. Pursuant to the United States Code, 10 U.S.C. Sec. 2797, the name of
the National Imagery and Mapping Agency, the initials "NIMA", the seal of
the National Imagery and Mapping Agency, or any colorable imitation thereof
shall not be used to imply approval, endorsement, or authorization of a
product without prior written permission from United States Secretary of
Defense.
*/
#include "lambertazimuthal.h" #include "lambertazimuthal.h"
#define sin2(x) (sin(x) * sin(x))
#ifndef M_PI_2 #define sqr(x) ((x) * (x))
#define M_PI_2 1.57079632679489661923
#endif // M_PI_2
LambertAzimuthal::LambertAzimuthal(const Ellipsoid *ellipsoid, LambertAzimuthal::LambertAzimuthal(const Ellipsoid *ellipsoid,
double latitudeOrigin, double longitudeOrigin, double falseEasting, double latitudeOrigin, double longitudeOrigin, double falseEasting,
double falseNorthing) double falseNorthing)
{ {
double es2, es4, es6; double lat0 = deg2rad(latitudeOrigin);
es2 = 2 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
es4 = es2 * es2;
es6 = es4 * es2;
_ra = ellipsoid->radius() * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0
* es6 / 3024.0);
_latOrigin = deg2rad(latitudeOrigin);
_sinLatOrigin = sin(_latOrigin);
_cosLatOrigin = cos(_latOrigin);
_absLatOrigin = fabs(_latOrigin);
_lonOrigin = deg2rad(longitudeOrigin);
if (_lonOrigin > M_PI)
_lonOrigin -= 2.0 * M_PI;
_falseNorthing = falseNorthing;
_falseEasting = falseEasting; _falseEasting = falseEasting;
_falseNorthing = falseNorthing;
_lon0 = deg2rad(longitudeOrigin);
_a = ellipsoid->radius();
_es2 = 2.0 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
_es = sqrt(_es2);
double q0 = (1.0 - _es2) * ((sin(lat0) / (1.0 - _es2 * sin2(lat0)))
- ((1.0/(2.0*_es)) * log((1.0 - _es * sin(lat0)) / (1.0 + _es
* sin(lat0)))));
_qP = (1.0 - _es2) * ((1.0 / (1.0 - _es2)) - ((1.0/(2.0*_es))
* log((1.0 - _es) / (1.0 + _es))));
_beta0 = asin(q0 / _qP);
_Rq = _a * sqrt(_qP / 2.0);
_D = _a * (cos(lat0) / sqrt(1.0 - _es2 * sin2(lat0))) / (_Rq * cos(_beta0));
} }
QPointF LambertAzimuthal::ll2xy(const Coordinates &c) const QPointF LambertAzimuthal::ll2xy(const Coordinates &c) const
{ {
double dlam; double lon = deg2rad(c.lon());
double k_prime; double lat = deg2rad(c.lat());
double cd;
double rlat = deg2rad(c.lat());
double slat = sin(rlat);
double clat = cos(rlat);
double cos_c;
double sin_dlam, cos_dlam;
double Ra_kprime;
double Ra_PI_OVER_2_Lat;
QPointF p;
double q = (1.0 - _es2) * ((sin(lat) / (1.0 - _es2 * sin2(lat)))
- ((1.0/(2.0*_es)) * log((1.0 - _es * sin(lat)) / (1.0 + _es
* sin(lat)))));
double beta = asin(q / _qP);
double B = _Rq * sqrt(2.0 / (1.0 + sin(_beta0) * sin(beta) + (cos(_beta0)
* cos(beta) * cos(lon - _lon0))));
dlam = deg2rad(c.lon()) - _lonOrigin; double x = _falseEasting + ((B * _D) * (cos(beta) * sin(lon - _lon0)));
if (dlam > M_PI) double y = _falseNorthing + (B / _D) * ((cos(_beta0) * sin(beta))
dlam -= 2.0 * M_PI; - (sin(_beta0) * cos(beta) * cos(lon - _lon0)));
if (dlam < -M_PI)
dlam += 2.0 * M_PI;
sin_dlam = sin(dlam); return QPointF(x, y);
cos_dlam = cos(dlam);
if (fabs(_absLatOrigin - M_PI_2) < 1.0e-10) {
if (_latOrigin >= 0.0) {
Ra_PI_OVER_2_Lat = _ra * (M_PI_2 - rlat);
p.rx() = Ra_PI_OVER_2_Lat * sin_dlam + _falseEasting;
p.ry() = -1.0 * (Ra_PI_OVER_2_Lat * cos_dlam) + _falseNorthing;
} else {
Ra_PI_OVER_2_Lat = _ra * (M_PI_2 + rlat);
p.rx() = Ra_PI_OVER_2_Lat * sin_dlam + _falseEasting;
p.ry() = Ra_PI_OVER_2_Lat * cos_dlam + _falseNorthing;
}
} else if (_absLatOrigin <= 1.0e-10) {
cos_c = clat * cos_dlam;
if (fabs(fabs(cos_c) - 1.0) < 1.0e-14) {
if (cos_c >= 0.0) {
p.rx() = _falseEasting;
p.ry() = _falseNorthing;
} else
return QPointF(NAN, NAN);
} else {
cd = acos(cos_c);
k_prime = cd / sin(cd);
Ra_kprime = _ra * k_prime;
p.rx() = Ra_kprime * clat * sin_dlam + _falseEasting;
p.ry() = Ra_kprime * slat + _falseNorthing;
}
} else {
cos_c = (_sinLatOrigin * slat) + (_cosLatOrigin * clat * cos_dlam);
if (fabs(fabs(cos_c) - 1.0) < 1.0e-14) {
if (cos_c >= 0.0) {
p.rx() = _falseEasting;
p.ry() = _falseNorthing;
} else
return QPointF(NAN, NAN);
} else {
cd = acos(cos_c);
k_prime = cd / sin(cd);
Ra_kprime = _ra * k_prime;
p.rx() = Ra_kprime * clat * sin_dlam + _falseEasting;
p.ry() = Ra_kprime * (_cosLatOrigin * slat - _sinLatOrigin * clat
* cos_dlam) + _falseNorthing;
}
}
return p;
} }
Coordinates LambertAzimuthal::xy2ll(const QPointF &p) const Coordinates LambertAzimuthal::xy2ll(const QPointF &p) const
{ {
double dx, dy; double es4 = _es2 * _es2;
double rho; double es6 = _es2 * es4;
double cd;
double sin_c, cos_c, dy_sinc;
double lat, lon;
double rho = sqrt(sqr((p.x() - _falseEasting) / _D) + sqr(_D * (p.y()
- _falseNorthing)));
double C = 2.0 * asin(rho / (2.0*_Rq));
double betaS = asin((cos(C) * sin(_beta0)) + ((_D * (p.y() -_falseNorthing)
* sin(C) * cos(_beta0)) / rho));
dy = p.y() - _falseNorthing; double lon = _lon0 + atan((p.x() - _falseEasting) * sin(C) / (_D * rho
dx = p.x() - _falseEasting; * cos(_beta0) * cos(C) - sqr(_D) * (p.y() - _falseNorthing) * sin(_beta0)
rho = sqrt(dx * dx + dy * dy); * sin(C)));
if (fabs(rho) <= 1.0e-10) { double lat = betaS + ((_es2/3.0 + 31.0*es4/180.0 + 517.0*es6/5040.0)
lat = _latOrigin; * sin(2.0*betaS)) + ((23.0*es4/360.0 + 251.0*es6/3780.0) * sin(4.0*betaS))
lon = _lonOrigin; + ((761.0*es6/45360.0)*sin(6.0*betaS));
} else {
cd = rho / _ra;
sin_c = sin(cd);
cos_c = cos(cd);
dy_sinc = dy * sin_c;
lat = asin((cos_c * _sinLatOrigin) + ((dy_sinc * _cosLatOrigin) / rho));
if (fabs(_absLatOrigin - M_PI_2) < 1.0e-10) {
if (_latOrigin >= 0.0)
lon = _lonOrigin + atan2(dx, -dy);
else
lon = _lonOrigin + atan2(dx, dy);
}
else
lon = _lonOrigin + atan2((dx * sin_c), ((rho * _cosLatOrigin
* cos_c) - (dy_sinc * _sinLatOrigin)));
}
if (lat > M_PI_2)
lat = M_PI_2;
else if (lat < -M_PI_2)
lat = -M_PI_2;
if (lon > M_PI)
lon -= 2.0 * M_PI;
if (lon < -M_PI)
lon += 2.0 * M_PI;
if (lon > M_PI)
lon = M_PI;
else if (lon < -M_PI)
lon = -M_PI;
return Coordinates(rad2deg(lon), rad2deg(lat)); return Coordinates(rad2deg(lon), rad2deg(lat));
} }

View File

@ -1,9 +1,10 @@
#ifndef LAMBERTAZIMUTHAL_H #ifndef LAMBERTAZIMUTHAL_H
#define LAMBERTAZIMUTHAL_H #define LAMBERTAZIMUTHAL_H
#include "ellipsoid.h"
#include "ct.h" #include "ct.h"
class Ellipsoid;
class LambertAzimuthal : public CT class LambertAzimuthal : public CT
{ {
public: public:
@ -16,15 +17,10 @@ public:
virtual Coordinates xy2ll(const QPointF &p) const; virtual Coordinates xy2ll(const QPointF &p) const;
private: private:
double _ra; double _lon0;
double _sinLatOrigin;
double _cosLatOrigin;
double _absLatOrigin;
double _latOrigin;
double _lonOrigin;
double _falseNorthing; double _falseNorthing;
double _falseEasting; double _falseEasting;
double _a, _es, _es2, _qP, _beta0, _Rq, _D;
}; };
#endif // LAMBERTAZIMUTHAL_H #endif // LAMBERTAZIMUTHAL_H

View File

@ -42,6 +42,7 @@ Defense.
*/ */
#include <cmath> #include <cmath>
#include "ellipsoid.h"
#include "lambertconic.h" #include "lambertconic.h"
#ifndef M_PI_2 #ifndef M_PI_2

View File

@ -1,9 +1,10 @@
#ifndef LAMBERTCONIC_H #ifndef LAMBERTCONIC_H
#define LAMBERTCONIC_H #define LAMBERTCONIC_H
#include "ellipsoid.h"
#include "ct.h" #include "ct.h"
class Ellipsoid;
class LambertConic1 : public CT class LambertConic1 : public CT
{ {
public: public:

View File

@ -5,9 +5,9 @@
#include <QString> #include <QString>
#include <QRectF> #include <QRectF>
#include <QColor> #include <QColor>
#include "common/coordinates.h"
class QPainter; class QPainter;
class Coordinates;
class RectC; class RectC;
class Map : public QObject class Map : public QObject
@ -15,18 +15,18 @@ class Map : public QObject
Q_OBJECT Q_OBJECT
public: public:
Map(QObject *parent = 0) : QObject(parent) {_backgroundColor = Qt::white;} Map(QObject *parent = 0) : QObject(parent), _backgroundColor(Qt::white) {}
virtual ~Map() {}
virtual const QString &name() const = 0; virtual const QString &name() const = 0;
virtual QRectF bounds() const = 0; virtual QRectF bounds() const = 0;
virtual qreal resolution(const QPointF &p) const = 0; virtual qreal resolution(const QRectF &rect) const = 0;
virtual qreal zoom() const = 0; virtual int zoom() const = 0;
virtual qreal zoomFit(const QSize &size, const RectC &br) = 0; virtual int zoomFit(const QSize &size, const RectC &br) = 0;
virtual qreal zoomFit(qreal resolution, const Coordinates &c) = 0; virtual int zoomIn() = 0;
virtual qreal zoomIn() = 0; virtual int zoomOut() = 0;
virtual qreal zoomOut() = 0;
virtual QPointF ll2xy(const Coordinates &c) = 0; virtual QPointF ll2xy(const Coordinates &c) = 0;
virtual Coordinates xy2ll(const QPointF &p) = 0; virtual Coordinates xy2ll(const QPointF &p) = 0;
@ -40,6 +40,9 @@ public:
void setBackgroundColor(const QColor &color) {_backgroundColor = color;} void setBackgroundColor(const QColor &color) {_backgroundColor = color;}
virtual bool isValid() const {return true;}
virtual QString errorString() const {return QString();}
signals: signals:
void loaded(); void loaded();

View File

@ -1,5 +1,7 @@
#include <QIODevice>
#include "utm.h" #include "utm.h"
#include "gcs.h" #include "gcs.h"
#include "pcs.h"
#include "mapfile.h" #include "mapfile.h"
@ -127,7 +129,7 @@ int MapFile::parse(QIODevice &device, QList<CalibrationPoint> &points,
ln++; ln++;
} }
return (ln == 1) ? 1 : 0; return (ln < 9) ? ln : 0;
} }
bool MapFile::parseMapFile(QIODevice &device, QList<CalibrationPoint> &points, bool MapFile::parseMapFile(QIODevice &device, QList<CalibrationPoint> &points,
@ -162,18 +164,21 @@ const GCS *MapFile::createGCS(const QString &datum)
bool MapFile::createProjection(const GCS *gcs, const QString &name, bool MapFile::createProjection(const GCS *gcs, const QString &name,
const Projection::Setup &setup, QList<CalibrationPoint> &points) const Projection::Setup &setup, QList<CalibrationPoint> &points)
{ {
PCS pcs;
if (name == "Mercator") if (name == "Mercator")
_projection = Projection(gcs, 1024, setup, 9001); pcs = PCS(gcs, 1024, setup, 9001);
else if (name == "Transverse Mercator") else if (name == "Transverse Mercator")
_projection = Projection(gcs, 9807, setup, 9001); pcs = PCS(gcs, 9807, setup, 9001);
else if (name == "Latitude/Longitude") else if (name == "Latitude/Longitude") {
_projection = Projection(gcs); _projection = Projection(gcs);
else if (name == "Lambert Conformal Conic") return true;
_projection = Projection(gcs, 9802, setup, 9001); } else if (name == "Lambert Conformal Conic")
pcs = PCS(gcs, 9802, setup, 9001);
else if (name == "Albers Equal Area") else if (name == "Albers Equal Area")
_projection = Projection(gcs, 9822, setup, 9001); pcs = PCS(gcs, 9822, setup, 9001);
else if (name == "(A)Lambert Azimuthual Equal Area") else if (name == "(A)Lambert Azimuthual Equal Area")
_projection = Projection(gcs, 9820, setup, 9001); pcs = PCS(gcs, 9820, setup, 9001);
else if (name == "(UTM) Universal Transverse Mercator") { else if (name == "(UTM) Universal Transverse Mercator") {
int zone; int zone;
if (points.first().zone) if (points.first().zone)
@ -184,42 +189,47 @@ bool MapFile::createProjection(const GCS *gcs, const QString &name,
_errorString = "Can not determine UTM zone"; _errorString = "Can not determine UTM zone";
return false; return false;
} }
_projection = Projection(gcs, 9807, UTM::setup(zone), 9001); pcs = PCS(gcs, 9807, UTM::setup(zone), 9001);
} else if (name == "(NZTM2) New Zealand TM 2000") } else if (name == "(NZTM2) New Zealand TM 2000")
_projection = Projection(gcs, 9807, Projection::Setup(0, 173.0, 0.9996, pcs = PCS(gcs, 9807, Projection::Setup(0, 173.0, 0.9996, 1600000,
1600000, 10000000, NAN, NAN), 9001); 10000000, NAN, NAN), 9001);
else if (name == "(BNG) British National Grid") else if (name == "(BNG) British National Grid")
_projection = Projection(gcs, 9807, Projection::Setup(49, -2, 0.999601, pcs = PCS(gcs, 9807, Projection::Setup(49, -2, 0.999601, 400000,
400000, -100000, NAN, NAN), 9001); -100000, NAN, NAN), 9001);
else if (name == "(IG) Irish Grid") else if (name == "(IG) Irish Grid")
_projection = Projection(gcs, 9807, Projection::Setup(53.5, -8, pcs = PCS(gcs, 9807, Projection::Setup(53.5, -8, 1.000035, 200000,
1.000035, 200000, 250000, NAN, NAN), 9001); 250000, NAN, NAN), 9001);
else if (name == "(SG) Swedish Grid") else if (name == "(SG) Swedish Grid")
_projection = Projection(gcs, 9807, Projection::Setup(0, 15.808278, 1, pcs = PCS(gcs, 9807, Projection::Setup(0, 15.808278, 1, 1500000, 0, NAN,
1500000, 0, NAN, NAN), 9001); NAN), 9001);
else if (name == "(I) France Zone I") else if (name == "(I) France Zone I")
_projection = Projection(gcs, 9802, Projection::Setup(49.5, 2.337229, pcs = PCS(gcs, 9802, Projection::Setup(49.5, 2.337229, NAN, 600000,
NAN, 600000, 1200000, 48.598523, 50.395912), 9001); 1200000, 48.598523, 50.395912), 9001);
else if (name == "(II) France Zone II") else if (name == "(II) France Zone II")
_projection = Projection(gcs, 9802, Projection::Setup(46.8, 2.337229, pcs = PCS(gcs, 9802, Projection::Setup(46.8, 2.337229, NAN, 600000,
NAN, 600000, 2200000, 45.898919, 47.696014), 9001); 2200000, 45.898919, 47.696014), 9001);
else if (name == "(III) France Zone III") else if (name == "(III) France Zone III")
_projection = Projection(gcs, 9802, Projection::Setup(44.1, 2.337229, pcs = PCS(gcs, 9802, Projection::Setup(44.1, 2.337229, NAN, 600000,
NAN, 600000, 3200000, 43.199291, 44.996094), 9001); 3200000, 43.199291, 44.996094), 9001);
else if (name == "(IV) France Zone IV") else if (name == "(IV) France Zone IV")
_projection = Projection(gcs, 9802, Projection::Setup(42.165, 2.337229, pcs = PCS(gcs, 9802, Projection::Setup(42.165, 2.337229, NAN, 234.358,
NAN, 234.358, 4185861.369, 41.560388, 42.767663), 9001); 4185861.369, 41.560388, 42.767663), 9001);
else if (name == "(VICGRID) Victoria Australia") else if (name == "(VICGRID) Victoria Australia")
_projection = Projection(gcs, 9802, Projection::Setup(-37, 145, NAN, pcs = PCS(gcs, 9802, Projection::Setup(-37, 145, NAN, 2500000, 4500000,
2500000, 4500000, -36, -38), 9001); -36, -38), 9001);
else if (name == "(VG94) VICGRID94 Victoria Australia") else if (name == "(VG94) VICGRID94 Victoria Australia")
_projection = Projection(gcs, 9802, Projection::Setup(-37, 145, NAN, pcs = PCS(gcs, 9802, Projection::Setup(-37, 145, NAN, 2500000, 2500000,
2500000, 2500000, -36, -38), 9001); -36, -38), 9001);
else if (name == "(SUI) Swiss Grid")
pcs = PCS(gcs, 9815, Projection::Setup(46.570866, 7.26225, 1.0, 600000,
200000, 90.0, 90.0), 9001);
else { else {
_errorString = QString("%1: Unknown map projection").arg(name); _errorString = QString("%1: Unknown map projection").arg(name);
return false; return false;
} }
_projection = Projection(&pcs);
return true; return true;
} }
@ -234,18 +244,16 @@ bool MapFile::computeTransformation(QList<CalibrationPoint> &points)
rp.append(points.at(i).rp); rp.append(points.at(i).rp);
} }
Transform t(rp); _transform = Transform(rp);
if (t.isNull()) { if (!_transform.isValid()) {
_errorString = t.errorString(); _errorString = _transform.errorString();
return false; return false;
} }
_transform = t.transform();
return true; return true;
} }
bool MapFile::load(QIODevice &file) MapFile::MapFile(QIODevice &file)
{ {
QList<CalibrationPoint> points; QList<CalibrationPoint> points;
QString ct, datum; QString ct, datum;
@ -253,13 +261,11 @@ bool MapFile::load(QIODevice &file)
const GCS *gcs; const GCS *gcs;
if (!parseMapFile(file, points, ct, setup, datum)) if (!parseMapFile(file, points, ct, setup, datum))
return false; return;
if (!(gcs = createGCS(datum))) if (!(gcs = createGCS(datum)))
return false; return;
if (!createProjection(gcs, ct, setup, points)) if (!createProjection(gcs, ct, setup, points))
return false; return;
if (!computeTransformation(points)) if (!computeTransformation(points))
return false; return;
return true;
} }

View File

@ -1,20 +1,23 @@
#ifndef MAPFILE_H #ifndef MAPFILE_H
#define MAPFILE_H #define MAPFILE_H
#include <QIODevice>
#include <QTransform>
#include "gcs.h"
#include "transform.h" #include "transform.h"
#include "projection.h" #include "projection.h"
class QIODevice;
class GCS;
class MapFile class MapFile
{ {
public: public:
bool load(QIODevice &file); MapFile(QIODevice &file);
bool isValid() const
{return !_image.isNull() && _projection.isValid() && _transform.isValid();}
const QString &errorString() const {return _errorString;} const QString &errorString() const {return _errorString;}
const Projection &projection() const {return _projection;} const Projection &projection() const {return _projection;}
const QTransform &transform() const {return _transform;} const Transform &transform() const {return _transform;}
const QString &name() const {return _name;} const QString &name() const {return _name;}
const QString &image() const {return _image;} const QString &image() const {return _image;}
@ -41,7 +44,7 @@ private:
QSize _size; QSize _size;
Projection _projection; Projection _projection;
QTransform _transform; Transform _transform;
QString _errorString; QString _errorString;
}; };

View File

@ -1,6 +1,5 @@
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
#include "common/range.h"
#include "atlas.h" #include "atlas.h"
#include "offlinemap.h" #include "offlinemap.h"
#include "onlinemap.h" #include "onlinemap.h"
@ -13,7 +12,7 @@ bool MapList::loadSource(const QString &path, bool dir)
MapSource ms; MapSource ms;
Map *map; Map *map;
if (!ms.loadFile(path, &map)) { if (!(map = ms.loadFile(path))) {
if (dir) if (dir)
_errorString += path + ": " + ms.errorString() + "\n"; _errorString += path + ": " + ms.errorString() + "\n";
else else

View File

@ -3,9 +3,8 @@
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include "map.h"
class Tar; class Map;
class MapList : public QObject class MapList : public QObject
{ {

View File

@ -1,9 +1,10 @@
#include <QFile> #include <QFile>
#include <QXmlStreamReader> #include <QXmlStreamReader>
#include "onlinemap.h" #include "onlinemap.h"
#include "wmtsmap.h"
#include "wmsmap.h"
#include "mapsource.h" #include "mapsource.h"
#define ZOOM_MAX 19 #define ZOOM_MAX 19
#define ZOOM_MIN 0 #define ZOOM_MIN 0
#define BOUNDS_LEFT -180 #define BOUNDS_LEFT -180
@ -11,6 +12,23 @@
#define BOUNDS_RIGHT 180 #define BOUNDS_RIGHT 180
#define BOUNDS_BOTTOM -85.0511 #define BOUNDS_BOTTOM -85.0511
MapSource::Config::Config() : type(OSM), zooms(ZOOM_MIN, ZOOM_MAX),
bounds(Coordinates(BOUNDS_LEFT, BOUNDS_TOP), Coordinates(BOUNDS_RIGHT,
BOUNDS_BOTTOM)), format("image/png"), rest(false) {}
static CoordinateSystem coordinateSystem(QXmlStreamReader &reader)
{
QXmlStreamAttributes attr = reader.attributes();
if (attr.value("axis") == "yx")
return CoordinateSystem::YX;
else if (attr.value("axis") == "xy")
return CoordinateSystem::XY;
else
return CoordinateSystem::Unknown;
}
Range MapSource::zooms(QXmlStreamReader &reader) Range MapSource::zooms(QXmlStreamReader &reader)
{ {
const QXmlStreamAttributes &attr = reader.attributes(); const QXmlStreamAttributes &attr = reader.attributes();
@ -18,11 +36,7 @@ Range MapSource::zooms(QXmlStreamReader &reader)
bool res; bool res;
if (attr.hasAttribute("min")) { if (attr.hasAttribute("min")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
min = attr.value("min").toString().toInt(&res); min = attr.value("min").toString().toInt(&res);
#else // QT_VERSION < 5
min = attr.value("min").toInt(&res);
#endif // QT_VERSION < 5
if (!res || (min < ZOOM_MIN || min > ZOOM_MAX)) { if (!res || (min < ZOOM_MIN || min > ZOOM_MAX)) {
reader.raiseError("Invalid minimal zoom level"); reader.raiseError("Invalid minimal zoom level");
return Range(); return Range();
@ -31,11 +45,7 @@ Range MapSource::zooms(QXmlStreamReader &reader)
min = ZOOM_MIN; min = ZOOM_MIN;
if (attr.hasAttribute("max")) { if (attr.hasAttribute("max")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
max = attr.value("max").toString().toInt(&res); max = attr.value("max").toString().toInt(&res);
#else // QT_VERSION < 5
max = attr.value("max").toInt(&res);
#endif // QT_VERSION < 5
if (!res || (max < ZOOM_MIN || max > ZOOM_MAX)) { if (!res || (max < ZOOM_MIN || max > ZOOM_MAX)) {
reader.raiseError("Invalid maximal zoom level"); reader.raiseError("Invalid maximal zoom level");
return Range(); return Range();
@ -43,7 +53,7 @@ Range MapSource::zooms(QXmlStreamReader &reader)
} else } else
max = ZOOM_MAX; max = ZOOM_MAX;
if (min > max || max < min) { if (min > max) {
reader.raiseError("Invalid maximal/minimal zoom level combination"); reader.raiseError("Invalid maximal/minimal zoom level combination");
return Range(); return Range();
} }
@ -58,11 +68,7 @@ RectC MapSource::bounds(QXmlStreamReader &reader)
bool res; bool res;
if (attr.hasAttribute("top")) { if (attr.hasAttribute("top")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
top = attr.value("top").toString().toDouble(&res); top = attr.value("top").toString().toDouble(&res);
#else // QT_VERSION < 5
top = attr.value("top").toDouble(&res);
#endif // QT_VERSION < 5
if (!res || (top < BOUNDS_BOTTOM || top > BOUNDS_TOP)) { if (!res || (top < BOUNDS_BOTTOM || top > BOUNDS_TOP)) {
reader.raiseError("Invalid bounds top value"); reader.raiseError("Invalid bounds top value");
return RectC(); return RectC();
@ -71,11 +77,7 @@ RectC MapSource::bounds(QXmlStreamReader &reader)
top = BOUNDS_TOP; top = BOUNDS_TOP;
if (attr.hasAttribute("bottom")) { if (attr.hasAttribute("bottom")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
bottom = attr.value("bottom").toString().toDouble(&res); bottom = attr.value("bottom").toString().toDouble(&res);
#else // QT_VERSION < 5
bottom = attr.value("bottom").toDouble(&res);
#endif // QT_VERSION < 5
if (!res || (bottom < BOUNDS_BOTTOM || bottom > BOUNDS_TOP)) { if (!res || (bottom < BOUNDS_BOTTOM || bottom > BOUNDS_TOP)) {
reader.raiseError("Invalid bounds bottom value"); reader.raiseError("Invalid bounds bottom value");
return RectC(); return RectC();
@ -84,11 +86,7 @@ RectC MapSource::bounds(QXmlStreamReader &reader)
bottom = BOUNDS_BOTTOM; bottom = BOUNDS_BOTTOM;
if (attr.hasAttribute("left")) { if (attr.hasAttribute("left")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
left = attr.value("left").toString().toDouble(&res); left = attr.value("left").toString().toDouble(&res);
#else // QT_VERSION < 5
left = attr.value("left").toDouble(&res);
#endif // QT_VERSION < 5
if (!res || (left < BOUNDS_LEFT || left > BOUNDS_RIGHT)) { if (!res || (left < BOUNDS_LEFT || left > BOUNDS_RIGHT)) {
reader.raiseError("Invalid bounds left value"); reader.raiseError("Invalid bounds left value");
return RectC(); return RectC();
@ -97,11 +95,7 @@ RectC MapSource::bounds(QXmlStreamReader &reader)
left = BOUNDS_LEFT; left = BOUNDS_LEFT;
if (attr.hasAttribute("right")) { if (attr.hasAttribute("right")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
right = attr.value("right").toString().toDouble(&res); right = attr.value("right").toString().toDouble(&res);
#else // QT_VERSION < 5
right = attr.value("right").toDouble(&res);
#endif // QT_VERSION < 5
if (!res || (right < BOUNDS_LEFT || right > BOUNDS_RIGHT)) { if (!res || (right < BOUNDS_LEFT || right > BOUNDS_RIGHT)) {
reader.raiseError("Invalid bounds right value"); reader.raiseError("Invalid bounds right value");
return RectC(); return RectC();
@ -109,11 +103,11 @@ RectC MapSource::bounds(QXmlStreamReader &reader)
} else } else
right = BOUNDS_RIGHT; right = BOUNDS_RIGHT;
if (bottom > top || top < bottom) { if (bottom >= top) {
reader.raiseError("Invalid bottom/top bounds combination"); reader.raiseError("Invalid bottom/top bounds combination");
return RectC(); return RectC();
} }
if (left > right || right < left) { if (left >= right) {
reader.raiseError("Invalid left/right bounds combination"); reader.raiseError("Invalid left/right bounds combination");
return RectC(); return RectC();
} }
@ -121,52 +115,128 @@ RectC MapSource::bounds(QXmlStreamReader &reader)
return RectC(Coordinates(left, top), Coordinates(right, bottom)); return RectC(Coordinates(left, top), Coordinates(right, bottom));
} }
void MapSource::map(QXmlStreamReader &reader, Map **map) void MapSource::map(QXmlStreamReader &reader, Config &config)
{ {
QString name, url; const QXmlStreamAttributes &attr = reader.attributes();
Range z(ZOOM_MIN, ZOOM_MAX); config.type = (attr.value("type") == "WMTS") ? WMTS
RectC b(Coordinates(BOUNDS_LEFT, BOUNDS_TOP), : (attr.value("type") == "WMS") ? WMS : OSM;
Coordinates(BOUNDS_RIGHT, BOUNDS_BOTTOM));
while (reader.readNextStartElement()) { while (reader.readNextStartElement()) {
if (reader.name() == "name") if (reader.name() == "name")
name = reader.readElementText(); config.name = reader.readElementText();
else if (reader.name() == "url") else if (reader.name() == "url") {
url = reader.readElementText(); config.rest = (reader.attributes().value("type") == "REST")
else if (reader.name() == "zoom") { ? true : false;
z = zooms(reader); config.url = reader.readElementText();
} else if (reader.name() == "zoom") {
config.zooms = zooms(reader);
reader.skipCurrentElement(); reader.skipCurrentElement();
} else if (reader.name() == "bounds") { } else if (reader.name() == "bounds") {
b = bounds(reader); config.bounds = bounds(reader);
reader.skipCurrentElement();
} else if (reader.name() == "format")
config.format = reader.readElementText();
else if (reader.name() == "layer")
config.layer = reader.readElementText();
else if (reader.name() == "style")
config.style = reader.readElementText();
else if (reader.name() == "set") {
config.coordinateSystem = coordinateSystem(reader);
config.set = reader.readElementText();
} else if (reader.name() == "dimension") {
QXmlStreamAttributes attr = reader.attributes();
if (!attr.hasAttribute("id"))
reader.raiseError("Missing dimension id");
else
config.dimensions.append(QPair<QString, QString>(
attr.value("id").toString(), reader.readElementText()));
} else if (reader.name() == "crs") {
config.coordinateSystem = coordinateSystem(reader);
config.crs = reader.readElementText();
} else if (reader.name() == "authorization") {
QXmlStreamAttributes attr = reader.attributes();
config.authorization = Authorization(
attr.value("username").toString(),
attr.value("password").toString());
reader.skipCurrentElement(); reader.skipCurrentElement();
} else } else
reader.skipCurrentElement(); reader.skipCurrentElement();
} }
*map = reader.error() ? 0 : new OnlineMap(name, url, z, b);
} }
bool MapSource::loadFile(const QString &path, Map **map) Map *MapSource::loadFile(const QString &path)
{ {
QFile file(path); QFile file(path);
QXmlStreamReader reader; QXmlStreamReader reader;
Config config;
Map *m;
if (!file.open(QFile::ReadOnly | QFile::Text)) { if (!file.open(QFile::ReadOnly | QFile::Text)) {
_errorString = file.errorString(); _errorString = file.errorString();
return false; return 0;
} }
reader.setDevice(&file); reader.setDevice(&file);
if (reader.readNextStartElement()) { if (reader.readNextStartElement()) {
if (reader.name() == "map") if (reader.name() == "map")
MapSource::map(reader, map); map(reader, config);
else else
reader.raiseError("Not an online map source file"); reader.raiseError("Not an online map source file");
} }
if (reader.error()) {
_errorString = QString("%1: %2").arg(reader.lineNumber())
.arg(reader.errorString());
return 0;
}
_errorString = reader.error() ? QString("%1: %2").arg(reader.lineNumber()) if (config.name.isEmpty()) {
.arg(reader.errorString()) : QString(); _errorString = "Missing name definition";
return 0;
}
if (config.url.isEmpty()) {
_errorString = "Missing URL definition";
return 0;
}
if (config.type == WMTS || config.type == WMS) {
if (config.layer.isEmpty()) {
_errorString = "Missing layer definition";
return 0;
}
if (config.format.isEmpty()) {
_errorString = "Missing format definition";
return 0;
}
}
if (config.type == WMTS) {
if (config.set.isEmpty()) {
_errorString = "Missing set definiton";
return 0;
}
}
if (config.type == WMS) {
if (config.crs.isEmpty()) {
_errorString = "Missing CRS definiton";
return 0;
}
}
return !reader.error(); if (config.type == WMTS)
m = new WMTSMap(config.name, WMTS::Setup(config.url, config.layer,
config.set, config.style, config.format, config.rest,
config.coordinateSystem, config.dimensions, config.authorization));
else if (config.type == WMS)
m = new WMSMap(config.name, WMS::Setup(config.url, config.layer,
config.style, config.format, config.crs, config.coordinateSystem,
config.dimensions, config.authorization));
else
m = new OnlineMap(config.name, config.url, config.zooms, config.bounds);
if (!m->isValid()) {
_errorString = m->errorString();
delete m;
return 0;
}
return m;
} }

View File

@ -4,6 +4,8 @@
#include <QList> #include <QList>
#include "common/range.h" #include "common/range.h"
#include "common/rectc.h" #include "common/rectc.h"
#include "downloader.h"
#include "coordinatesystem.h"
class Map; class Map;
class QXmlStreamReader; class QXmlStreamReader;
@ -11,13 +13,38 @@ class QXmlStreamReader;
class MapSource class MapSource
{ {
public: public:
bool loadFile(const QString &path, Map **map); Map *loadFile(const QString &path);
const QString &errorString() const {return _errorString;} const QString &errorString() const {return _errorString;}
private: private:
enum Type {
OSM,
WMTS,
WMS
};
struct Config {
Type type;
QString name;
QString url;
Range zooms;
RectC bounds;
QString layer;
QString style;
QString set;
QString format;
QString crs;
CoordinateSystem coordinateSystem;
bool rest;
QList<QPair<QString, QString> > dimensions;
Authorization authorization;
Config();
};
RectC bounds(QXmlStreamReader &reader); RectC bounds(QXmlStreamReader &reader);
Range zooms(QXmlStreamReader &reader); Range zooms(QXmlStreamReader &reader);
void map(QXmlStreamReader &reader, Map **map); void map(QXmlStreamReader &reader, Config &config);
QString _errorString; QString _errorString;
}; };

View File

@ -5,7 +5,8 @@
#include <cfloat> #include <cfloat>
#include <QDebug> #include <QDebug>
class Matrix { class Matrix
{
public: public:
Matrix() {_h = 0; _w = 0; _m = 0;} Matrix() {_h = 0; _w = 0; _m = 0;}
Matrix(size_t h, size_t w); Matrix(size_t h, size_t w);

View File

@ -1,4 +1,3 @@
#include <QtGlobal>
#include <QPainter> #include <QPainter>
#include <QFileInfo> #include <QFileInfo>
#include <QMap> #include <QMap>
@ -9,56 +8,49 @@
#include <QPixmapCache> #include <QPixmapCache>
#include "common/coordinates.h" #include "common/coordinates.h"
#include "common/rectc.h" #include "common/rectc.h"
#include "tar.h"
#include "ozf.h"
#include "mapfile.h" #include "mapfile.h"
#include "geotiff.h" #include "geotiff.h"
#include "offlinemap.h" #include "offlinemap.h"
void OfflineMap::computeResolution() bool OfflineMap::setImageInfo(const QString &path)
{ {
Coordinates tl = xy2ll((bounds().topLeft())); QFileInfo ii(_map.path);
Coordinates br = xy2ll(bounds().bottomRight());
qreal ds = tl.distanceTo(br);
qreal ps = QLineF(bounds().topLeft(), bounds().bottomRight()).length();
_resolution = ds/ps;
}
bool OfflineMap::getImageInfo(const QString &path)
{
QFileInfo ii(_imgPath);
if (ii.isRelative()) if (ii.isRelative())
ii.setFile(path + "/" + _imgPath); ii.setFile(path + "/" + _map.path);
if (!ii.exists()) { if (!ii.exists()) {
int last = _imgPath.lastIndexOf('\\'); int last = _map.path.lastIndexOf('\\');
if (last >= 0 && last < _imgPath.length() - 1) { if (last >= 0 && last < _map.path.length() - 1) {
QStringRef fn(&_imgPath, last + 1, _imgPath.length() - last - 1); QStringRef fn(&_map.path, last + 1, _map.path.length() - last - 1);
ii.setFile(path + "/" + fn.toString()); ii.setFile(path + "/" + fn.toString());
} }
} }
if (ii.exists()) if (ii.exists())
_imgPath = ii.absoluteFilePath(); _map.path = ii.absoluteFilePath();
else { else {
_errorString = QString("%1: No such image file").arg(_imgPath); _errorString = QString("%1: No such image file").arg(_map.path);
return false; return false;
} }
if (OZF::isOZF(_imgPath)) { if (OZF::isOZF(_map.path)) {
if (!_ozf.load(_imgPath)) { _ozf = new OZF(_map.path);
if (!_ozf->open()) {
_errorString = QString("%1: Error loading OZF file") _errorString = QString("%1: Error loading OZF file")
.arg(QFileInfo(_imgPath).fileName()); .arg(_ozf->fileName());
return false; return false;
} }
_scale = _ozf->scale(_zoom);
} else { } else {
QImageReader img(_imgPath); QImageReader img(_map.path);
_size = img.size(); _map.size = img.size();
if (!_size.isValid()) { if (!_map.size.isValid()) {
_errorString = QString("%1: Error reading map image") _errorString = QString("%1: Error reading map image")
.arg(QFileInfo(_imgPath).fileName()); .arg(QFileInfo(_map.path).fileName());
return false; return false;
} }
} }
@ -66,27 +58,33 @@ bool OfflineMap::getImageInfo(const QString &path)
return true; return true;
} }
bool OfflineMap::getTileInfo(const QStringList &tiles, const QString &path) bool OfflineMap::setTileInfo(const QStringList &tiles, const QString &path)
{ {
if (!_map.size.isValid()) {
_errorString = "Missing total image size (IWH)";
return false;
}
QRegExp rx("_[0-9]+_[0-9]+\\."); QRegExp rx("_[0-9]+_[0-9]+\\.");
for (int i = 0; i < tiles.size(); i++) { for (int i = 0; i < tiles.size(); i++) {
if (tiles.at(i).contains(rx)) { if (tiles.at(i).contains(rx)) {
_tileName = QString(tiles.at(i)).replace(rx, "_%1_%2."); _tile.path = QString(tiles.at(i)).replace(rx, "_%1_%2.");
if (path.isNull()) { if (_tar) {
QByteArray ba = _tar.file(tiles.at(i)); QByteArray ba = _tar->file(tiles.at(i));
QBuffer buffer(&ba); QBuffer buffer(&ba);
_tileSize = QImageReader(&buffer).size(); _tile.size = QImageReader(&buffer).size();
} else { } else {
_tileName = path + "/" + _tileName; _tile.path = path + "/" + _tile.path;
_tileSize = QImageReader(path + "/" + tiles.at(i)).size(); _tile.size = QImageReader(path + "/" + tiles.at(i)).size();
} }
if (!_tileSize.isValid()) { if (!_tile.size.isValid()) {
_errorString = QString("Error retrieving tile size: " _errorString = QString("Error retrieving tile size: "
"%1: Invalid image").arg(QFileInfo(tiles.at(i)).fileName()); "%1: Invalid image").arg(QFileInfo(tiles.at(i)).fileName());
return false; return false;
} }
_map.path = QString();
return true; return true;
} }
} }
@ -95,72 +93,59 @@ bool OfflineMap::getTileInfo(const QStringList &tiles, const QString &path)
return false; return false;
} }
bool OfflineMap::totalSizeSet()
{
if (!_size.isValid()) {
_errorString = "Missing total image size (IWH)";
return false;
} else
return true;
}
OfflineMap::OfflineMap(const QString &fileName, QObject *parent) OfflineMap::OfflineMap(const QString &fileName, QObject *parent)
: Map(parent) : Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _valid(false)
{ {
QFileInfo fi(fileName); QFileInfo fi(fileName);
QString suffix = fi.suffix().toLower(); QString suffix = fi.suffix().toLower();
_valid = false;
_img = 0;
_resolution = 0.0;
_zoom = 0;
_scale = QPointF(1.0, 1.0);
if (suffix == "tar") { if (suffix == "tar") {
if (!_tar.load(fileName)) { _tar = new Tar(fileName);
if (!_tar->open()) {
_errorString = "Error reading tar file"; _errorString = "Error reading tar file";
return; return;
} }
QString mapFileName = fi.completeBaseName() + ".map"; QString mapFileName = fi.completeBaseName() + ".map";
QByteArray ba = _tar.file(mapFileName); QByteArray ba = _tar->file(mapFileName);
if (ba.isNull()) { if (ba.isNull()) {
_errorString = "Map file not found"; _errorString = "Map file not found";
return; return;
} }
QBuffer mapFile(&ba); QBuffer buffer(&ba);
MapFile mf; MapFile mf(buffer);
if (!mf.load(mapFile)) { if (!mf.isValid()) {
_errorString = mf.errorString(); _errorString = mf.errorString();
return; return;
} else { } else {
_name = mf.name(); _name = mf.name();
_size = mf.size(); _map.size = mf.size();
_imgPath = mf.image(); _map.path = mf.image();
_projection = mf.projection(); _projection = mf.projection();
_transform = mf.transform(); _transform = mf.transform();
} }
} else if (suffix == "map") { } else if (suffix == "map") {
MapFile mf; QFile file(fileName);
QFile mapFile(fileName); MapFile mf(file);
if (!mf.load(mapFile)) { if (!mf.isValid()) {
_errorString = mf.errorString(); _errorString = mf.errorString();
return; return;
} else { } else {
_name = mf.name(); _name = mf.name();
_size = mf.size(); _map.size = mf.size();
_imgPath = mf.image(); _map.path = mf.image();
_projection = mf.projection(); _projection = mf.projection();
_transform = mf.transform(); _transform = mf.transform();
} }
} else if (suffix == "tif" || suffix == "tiff") { } else if (suffix == "tif" || suffix == "tiff") {
GeoTIFF gt; GeoTIFF gt(fileName);
if (!gt.load(fileName)) { if (!gt.isValid()) {
_errorString = gt.errorString(); _errorString = gt.errorString();
return; return;
} else { } else {
_name = fi.fileName(); _name = fi.fileName();
_imgPath = fileName; _map.path = fileName;
_projection = gt.projection(); _projection = gt.projection();
_transform = gt.transform(); _transform = gt.transform();
} }
@ -169,93 +154,78 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent)
return; return;
} }
if (_tar.isOpen()) { if (_tar) {
if (!totalSizeSet()) if (!setTileInfo(_tar->files()))
return; return;
if (!getTileInfo(_tar.files()))
return;
_imgPath = QString();
} else { } else {
QDir set(fi.absolutePath() + "/" + "set"); QDir set(fi.absolutePath() + "/" + "set");
if (set.exists()) { if (set.exists()) {
if (!totalSizeSet()) if (!setTileInfo(set.entryList(), set.absolutePath()))
return; return;
if (!getTileInfo(set.entryList(), set.absolutePath()))
return;
_imgPath = QString();
} else { } else {
if (!getImageInfo(fi.absolutePath())) if (!setImageInfo(fi.absolutePath()))
return; return;
} }
} }
_inverted = _transform.inverted();
computeResolution();
_valid = true; _valid = true;
} }
OfflineMap::OfflineMap(const QString &fileName, Tar &tar, QObject *parent) OfflineMap::OfflineMap(const QString &fileName, Tar &tar, QObject *parent)
: Map(parent) : Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _valid(false)
{ {
QFileInfo fi(fileName); QFileInfo fi(fileName);
MapFile mf;
_valid = false;
_img = 0;
_resolution = 0.0;
_zoom = 0;
_scale = QPointF(1.0, 1.0);
QFileInfo map(fi.absolutePath()); QFileInfo map(fi.absolutePath());
QFileInfo layer(map.absolutePath()); QFileInfo layer(map.absolutePath());
QString mapFile = layer.fileName() + "/" + map.fileName() + "/" QString mapFile = layer.fileName() + "/" + map.fileName() + "/"
+ fi.fileName(); + fi.fileName();
QByteArray ba = tar.file(mapFile); QByteArray ba = tar.file(mapFile);
if (ba.isNull()) { if (ba.isNull()) {
_errorString = "Map file not found"; _errorString = "Map file not found";
return; return;
} }
QBuffer buffer(&ba); QBuffer buffer(&ba);
MapFile mf(buffer);
if (!mf.load(buffer)) { if (!mf.isValid()) {
_errorString = mf.errorString(); _errorString = mf.errorString();
return; return;
} }
_name = mf.name(); _name = mf.name();
_size = mf.size(); _map.size = mf.size();
_projection = mf.projection(); _projection = mf.projection();
_transform = mf.transform(); _transform = mf.transform();
_tar = new Tar(fi.absolutePath() + "/" + fi.completeBaseName() + ".tar");
_inverted = _transform.inverted();
computeResolution();
_tarPath = fi.absolutePath() + "/" + fi.completeBaseName() + ".tar";
_valid = true; _valid = true;
} }
OfflineMap::~OfflineMap() OfflineMap::~OfflineMap()
{ {
delete _img; delete _img;
delete _tar;
delete _ozf;
} }
void OfflineMap::load() void OfflineMap::load()
{ {
if (!_tarPath.isNull() && !_tileSize.isValid()) { if (_tar && !_tar->isOpen()) {
if (!_tar.load(_tarPath)) { if (!_tar->open()) {
qWarning("%s: error loading tar file", qPrintable(_tarPath)); qWarning("%s: error loading tar file",
qPrintable(_tar->fileName()));
return; return;
} }
if (!getTileInfo(_tar.files())) if (!setTileInfo(_tar->files()))
qWarning("%s: %s", qPrintable(_tarPath), qPrintable(_errorString)); qWarning("%s: %s", qPrintable(_tar->fileName()),
qPrintable(_errorString));
return; return;
} }
if (!_img && !_imgPath.isNull() && !_ozf.isOpen()) { if (!_ozf && !_img && _map.isValid()) {
_img = new QImage(_imgPath); _img = new QImage(_map.path);
if (_img->isNull()) if (_img->isNull())
qWarning("%s: error loading map image", qPrintable(_imgPath)); qWarning("%s: error loading map image", qPrintable(_map.path));
} }
} }
@ -265,26 +235,26 @@ void OfflineMap::unload()
_img = 0; _img = 0;
} }
void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect) void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect) const
{ {
QPoint tl = QPoint((int)floor(rect.left() / (qreal)_tileSize.width()) QPoint tl = QPoint((int)floor(rect.left() / (qreal)_tile.size.width())
* _tileSize.width(), (int)floor(rect.top() / _tileSize.height()) * _tile.size.width(), (int)floor(rect.top() / _tile.size.height())
* _tileSize.height()); * _tile.size.height());
QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y()); QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y());
for (int i = 0; i < ceil(s.width() / _tileSize.width()); i++) { for (int i = 0; i < ceil(s.width() / _tile.size.width()); i++) {
for (int j = 0; j < ceil(s.height() / _tileSize.height()); j++) { for (int j = 0; j < ceil(s.height() / _tile.size.height()); j++) {
int x = tl.x() + i * _tileSize.width(); int x = tl.x() + i * _tile.size.width();
int y = tl.y() + j * _tileSize.height(); int y = tl.y() + j * _tile.size.height();
QString tileName(_tileName.arg(QString::number(x), QString tileName(_tile.path.arg(QString::number(x),
QString::number(y))); QString::number(y)));
QPixmap pixmap; QPixmap pixmap;
if (_tar.isOpen()) { if (_tar) {
QString key = _tar.fileName() + "/" + tileName; QString key = _tar->fileName() + "/" + tileName;
if (!QPixmapCache::find(key, &pixmap)) { if (!QPixmapCache::find(key, &pixmap)) {
QByteArray ba = _tar.file(tileName); QByteArray ba = _tar->file(tileName);
pixmap = QPixmap::fromImage(QImage::fromData(ba)); pixmap = QPixmap::fromImage(QImage::fromData(ba));
if (!pixmap.isNull()) if (!pixmap.isNull())
QPixmapCache::insert(key, pixmap); QPixmapCache::insert(key, pixmap);
@ -294,8 +264,8 @@ void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect)
if (pixmap.isNull()) { if (pixmap.isNull()) {
qWarning("%s: error loading tile image", qPrintable( qWarning("%s: error loading tile image", qPrintable(
_tileName.arg(QString::number(x), QString::number(y)))); _tile.path.arg(QString::number(x), QString::number(y))));
painter->fillRect(QRectF(QPoint(x, y), _tileSize), painter->fillRect(QRectF(QPoint(x, y), _tile.size),
_backgroundColor); _backgroundColor);
} else } else
painter->drawPixmap(QPoint(x, y), pixmap); painter->drawPixmap(QPoint(x, y), pixmap);
@ -303,30 +273,30 @@ void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect)
} }
} }
void OfflineMap::drawOZF(QPainter *painter, const QRectF &rect) void OfflineMap::drawOZF(QPainter *painter, const QRectF &rect) const
{ {
QPoint tl = QPoint((int)floor(rect.left() / _ozf.tileSize().width()) QPoint tl = QPoint((int)floor(rect.left() / _ozf->tileSize().width())
* _ozf.tileSize().width(), (int)floor(rect.top() * _ozf->tileSize().width(), (int)floor(rect.top()
/ _ozf.tileSize().height()) * _ozf.tileSize().height()); / _ozf->tileSize().height()) * _ozf->tileSize().height());
QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y()); QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y());
for (int i = 0; i < ceil(s.width() / _ozf.tileSize().width()); i++) { for (int i = 0; i < ceil(s.width() / _ozf->tileSize().width()); i++) {
for (int j = 0; j < ceil(s.height() / _ozf.tileSize().height()); j++) { for (int j = 0; j < ceil(s.height() / _ozf->tileSize().height()); j++) {
int x = tl.x() + i * _ozf.tileSize().width(); int x = tl.x() + i * _ozf->tileSize().width();
int y = tl.y() + j * _ozf.tileSize().height(); int y = tl.y() + j * _ozf->tileSize().height();
QPixmap pixmap; QPixmap pixmap;
QString key = _ozf.fileName() + "/" + QString::number(_zoom) + "_" QString key = _ozf->fileName() + "/" + QString::number(_zoom) + "_"
+ QString::number(x) + "_" + QString::number(y); + QString::number(x) + "_" + QString::number(y);
if (!QPixmapCache::find(key, &pixmap)) { if (!QPixmapCache::find(key, &pixmap)) {
pixmap = _ozf.tile(_zoom, x, y); pixmap = _ozf->tile(_zoom, x, y);
if (!pixmap.isNull()) if (!pixmap.isNull())
QPixmapCache::insert(key, pixmap); QPixmapCache::insert(key, pixmap);
} }
if (pixmap.isNull()) { if (pixmap.isNull()) {
qWarning("%s: error loading tile image", qPrintable(key)); qWarning("%s: error loading tile image", qPrintable(key));
painter->fillRect(QRectF(QPoint(x, y), _ozf.tileSize()), painter->fillRect(QRectF(QPoint(x, y), _ozf->tileSize()),
_backgroundColor); _backgroundColor);
} else } else
painter->drawPixmap(QPoint(x, y), pixmap); painter->drawPixmap(QPoint(x, y), pixmap);
@ -334,7 +304,7 @@ void OfflineMap::drawOZF(QPainter *painter, const QRectF &rect)
} }
} }
void OfflineMap::drawImage(QPainter *painter, const QRectF &rect) void OfflineMap::drawImage(QPainter *painter, const QRectF &rect) const
{ {
QRect r(rect.toRect()); QRect r(rect.toRect());
painter->drawImage(r.left(), r.top(), *_img, r.left(), r.top(), painter->drawImage(r.left(), r.top(), *_img, r.left(), r.top(),
@ -343,9 +313,9 @@ void OfflineMap::drawImage(QPainter *painter, const QRectF &rect)
void OfflineMap::draw(QPainter *painter, const QRectF &rect) void OfflineMap::draw(QPainter *painter, const QRectF &rect)
{ {
if (_ozf.isOpen()) if (_ozf)
drawOZF(painter, rect); drawOZF(painter, rect);
else if (_tileSize.isValid()) else if (_tile.isValid())
drawTiled(painter, rect); drawTiled(painter, rect);
else if (_img && !_img->isNull()) else if (_img && !_img->isNull())
drawImage(painter, rect); drawImage(painter, rect);
@ -353,73 +323,54 @@ void OfflineMap::draw(QPainter *painter, const QRectF &rect)
painter->fillRect(rect, _backgroundColor); painter->fillRect(rect, _backgroundColor);
} }
QPointF OfflineMap::ll2xy(const Coordinates &c) QPointF OfflineMap::ll2xy(const Coordinates &c) const
{ {
if (_ozf.isOpen()) { QPointF p(_transform.proj2img(_projection.ll2xy(c)));
QPointF p(_transform.map(_projection.ll2xy(c))); return _ozf ? QPointF(p.x() * _scale.x(), p.y() * _scale.y()) : p;
return QPointF(p.x() * _scale.x(), p.y() * _scale.y());
} else
return _transform.map(_projection.ll2xy(c));
} }
Coordinates OfflineMap::xy2ll(const QPointF &p) Coordinates OfflineMap::xy2ll(const QPointF &p) const
{ {
if (_ozf.isOpen()) { return _ozf
return _projection.xy2ll(_inverted.map(QPointF(p.x() / _scale.x(), ? _projection.xy2ll(_transform.img2proj(QPointF(p.x() / _scale.x(),
p.y() / _scale.y()))); p.y() / _scale.y())))
} else : _projection.xy2ll(_transform.img2proj(p));
return _projection.xy2ll(_inverted.map(p));
} }
QRectF OfflineMap::bounds() const QRectF OfflineMap::bounds() const
{ {
if (_ozf.isOpen()) return _ozf
return QRectF(QPointF(0, 0), _ozf.size(_zoom)); ? QRectF(QPointF(0, 0), _ozf->size(_zoom))
else : QRectF(QPointF(0, 0), _map.size);
return QRectF(QPointF(0, 0), _size);
} }
qreal OfflineMap::resolution(const QPointF &p) const qreal OfflineMap::resolution(const QRectF &rect) const
{ {
Q_UNUSED(p); Coordinates tl = xy2ll((rect.topLeft()));
Coordinates br = xy2ll(rect.bottomRight());
if (_ozf.isOpen()) qreal ds = tl.distanceTo(br);
return _resolution / ((_scale.x() + _scale.y()) / 2.0); qreal ps = QLineF(rect.topLeft(), rect.bottomRight()).length();
else
return _resolution; return ds/ps;
} }
qreal OfflineMap::zoomFit(const QSize &size, const RectC &br) int OfflineMap::zoomFit(const QSize &size, const RectC &rect)
{ {
if (_ozf.isOpen()) { if (!_ozf)
if (!br.isValid()) return _zoom;
rescale(0);
else {
QRect sbr(QRectF(_transform.map(_projection.ll2xy(br.topLeft())),
_transform.map(_projection.ll2xy(br.bottomRight())))
.toRect().normalized());
for (int i = 0; i < _ozf.zooms(); i++) { if (!rect.isValid())
rescale(i); rescale(0);
if (sbr.size().width() * _scale.x() <= size.width() else {
&& sbr.size().height() * _scale.y() <= size.height()) QPointF tl(_transform.proj2img(_projection.ll2xy(rect.topLeft())));
break; QPointF br(_transform.proj2img(_projection.ll2xy(rect.bottomRight())));
} QRect sbr(QRectF(tl, br).toRect().normalized());
}
}
return _zoom; for (int i = 0; i < _ozf->zooms(); i++) {
}
qreal OfflineMap::zoomFit(qreal resolution, const Coordinates &c)
{
Q_UNUSED(c);
if (_ozf.isOpen()) {
for (int i = 0; i < _ozf.zooms(); i++) {
rescale(i); rescale(i);
qreal sr = _resolution / ((_scale.x() + _scale.y()) / 2.0); if (sbr.size().width() * _scale.x() <= size.width()
if (sr >= resolution) && sbr.size().height() * _scale.y() <= size.height())
break; break;
} }
} }
@ -427,18 +378,18 @@ qreal OfflineMap::zoomFit(qreal resolution, const Coordinates &c)
return _zoom; return _zoom;
} }
qreal OfflineMap::zoomIn() int OfflineMap::zoomIn()
{ {
if (_ozf.isOpen()) if (_ozf)
rescale(qMax(_zoom - 1, 0)); rescale(qMax(_zoom - 1, 0));
return _zoom; return _zoom;
} }
qreal OfflineMap::zoomOut() int OfflineMap::zoomOut()
{ {
if (_ozf.isOpen()) if (_ozf)
rescale(qMin(_zoom + 1, _ozf.zooms() - 1)); rescale(qMin(_zoom + 1, _ozf->zooms() - 1));
return _zoom; return _zoom;
} }
@ -446,7 +397,5 @@ qreal OfflineMap::zoomOut()
void OfflineMap::rescale(int zoom) void OfflineMap::rescale(int zoom)
{ {
_zoom = zoom; _zoom = zoom;
_scale = QPointF( _scale = _ozf->scale(zoom);
(qreal)_ozf.size(_zoom).width() / (qreal)_ozf.size(0).width(),
(qreal)_ozf.size(_zoom).height() / (qreal)_ozf.size(0).height());
} }

View File

@ -1,15 +1,12 @@
#ifndef OFFLINEMAP_H #ifndef OFFLINEMAP_H
#define OFFLINEMAP_H #define OFFLINEMAP_H
#include <QTransform>
#include "projection.h"
#include "transform.h" #include "transform.h"
#include "linearunits.h" #include "projection.h"
#include "map.h" #include "map.h"
#include "tar.h"
#include "ozf.h"
class QIODevice; class Tar;
class OZF;
class QImage; class QImage;
class OfflineMap : public Map class OfflineMap : public Map
@ -24,16 +21,17 @@ public:
const QString &name() const {return _name;} const QString &name() const {return _name;}
QRectF bounds() const; QRectF bounds() const;
qreal resolution(const QPointF &p) const; qreal resolution(const QRectF &rect) const;
qreal zoom() const {return _zoom;} int zoom() const {return _zoom;}
qreal zoomFit(const QSize &size, const RectC &br); int zoomFit(const QSize &size, const RectC &rect);
qreal zoomFit(qreal resolution, const Coordinates &c); int zoomIn();
qreal zoomIn(); int zoomOut();
qreal zoomOut();
QPointF ll2xy(const Coordinates &c); QPointF ll2xy(const Coordinates &c)
Coordinates xy2ll(const QPointF &p); {return static_cast<const OfflineMap &>(*this).ll2xy(c);}
Coordinates xy2ll(const QPointF &p)
{return static_cast<const OfflineMap &>(*this).xy2ll(p);}
void draw(QPainter *painter, const QRectF &rect); void draw(QPainter *painter, const QRectF &rect);
@ -41,43 +39,43 @@ public:
void unload(); void unload();
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;} QString errorString() const {return _errorString;}
QPointF ll2pp(const Coordinates &c) const QPointF ll2pp(const Coordinates &c) const
{return _projection.ll2xy(c);} {return _projection.ll2xy(c);}
QPointF xy2pp(const QPointF &p) const QPointF xy2pp(const QPointF &p) const
{return _inverted.map(p);} {return _transform.img2proj(p);}
QPointF pp2xy(const QPointF &p) const QPointF pp2xy(const QPointF &p) const
{return _transform.map(p);} {return _transform.proj2img(p);}
private: private:
bool getTileInfo(const QStringList &tiles, const QString &path = QString()); struct ImageInfo {
bool getImageInfo(const QString &path); QSize size;
bool totalSizeSet(); QString path;
void drawTiled(QPainter *painter, const QRectF &rect); bool isValid() const {return size.isValid() && !path.isEmpty();}
void drawOZF(QPainter *painter, const QRectF &rect); };
void drawImage(QPainter *painter, const QRectF &rect);
QPointF ll2xy(const Coordinates &c) const;
Coordinates xy2ll(const QPointF &p) const;
bool setTileInfo(const QStringList &tiles, const QString &path = QString());
bool setImageInfo(const QString &path);
void drawTiled(QPainter *painter, const QRectF &rect) const;
void drawOZF(QPainter *painter, const QRectF &rect) const;
void drawImage(QPainter *painter, const QRectF &rect) const;
void computeResolution();
void rescale(int zoom); void rescale(int zoom);
QString _name; QString _name;
Projection _projection; Projection _projection;
QTransform _transform, _inverted; Transform _transform;
OZF _ozf;
Tar _tar;
QString _tarPath;
QImage *_img; QImage *_img;
QString _imgPath; Tar *_tar;
QSize _tileSize; OZF *_ozf;
QString _tileName; ImageInfo _map, _tile;
QSize _size;
int _zoom; int _zoom;
qreal _resolution;
QPointF _scale; QPointF _scale;
bool _valid; bool _valid;

View File

@ -1,5 +1,3 @@
#include <QFileInfo>
#include <QDir>
#include <QPainter> #include <QPainter>
#include "common/coordinates.h" #include "common/coordinates.h"
#include "common/rectc.h" #include "common/rectc.h"
@ -41,45 +39,35 @@ static int scale2zoom(qreal scale)
return (int)log2(360.0/(scale * (qreal)TILE_SIZE)); return (int)log2(360.0/(scale * (qreal)TILE_SIZE));
} }
static bool loadTileFile(Tile &tile, const QString &file)
{
if (!tile.pixmap().load(file)) {
qWarning("%s: error loading tile file\n", qPrintable(file));
return false;
}
return true;
}
Downloader *OnlineMap::downloader;
OnlineMap::OnlineMap(const QString &name, const QString &url, OnlineMap::OnlineMap(const QString &name, const QString &url,
const Range &zooms, const RectC &bounds, QObject *parent) const Range &zooms, const RectC &bounds, QObject *parent) :
: Map(parent), _name(name), _url(url), _zooms(zooms), _bounds(bounds) Map(parent), _name(name), _zooms(zooms), _bounds(bounds),
_block(false), _valid(false)
{ {
_block = false; QString dir(TILES_DIR + "/" + _name);
_zoom = _zooms.max();
QString path = TILES_DIR + QString("/") + name; _zoom = _zooms.max();
if (!QDir().mkpath(path)) _tileLoader = TileLoader(url, dir);
qWarning("Error creating tiles dir: %s\n", qPrintable(path));
if (!QDir().mkpath(dir)) {
_errorString = "Error creating tiles dir";
return;
}
_valid = true;
} }
void OnlineMap::load() void OnlineMap::load()
{ {
connect(downloader, SIGNAL(finished()), this, SLOT(emitLoaded())); connect(TileLoader::downloader(), SIGNAL(finished()), this,
SLOT(emitLoaded()));
} }
void OnlineMap::unload() void OnlineMap::unload()
{ {
disconnect(downloader, SIGNAL(finished()), this, SLOT(emitLoaded())); disconnect(TileLoader::downloader(), SIGNAL(finished()), this,
} SLOT(emitLoaded()));
void OnlineMap::fillTile(Tile &tile)
{
tile.pixmap() = QPixmap(TILE_SIZE, TILE_SIZE);
tile.pixmap().fill(_backgroundColor);
} }
void OnlineMap::emitLoaded() void OnlineMap::emitLoaded()
@ -87,91 +75,6 @@ void OnlineMap::emitLoaded()
emit loaded(); emit loaded();
} }
void OnlineMap::loadTilesAsync(QList<Tile> &list)
{
QList<Download> dl;
for (int i = 0; i < list.size(); i++) {
Tile &t = list[i];
QString file = tileFile(t);
QFileInfo fi(file);
if (!fi.exists()) {
fillTile(t);
dl.append(Download(tileUrl(t), file));
} else
loadTileFile(t, file);
}
if (!dl.empty())
downloader->get(dl);
}
void OnlineMap::loadTilesSync(QList<Tile> &list)
{
QList<Download> dl;
for (int i = 0; i < list.size(); i++) {
Tile &t = list[i];
QString file = tileFile(t);
QFileInfo fi(file);
if (!fi.exists())
dl.append(Download(tileUrl(t), file));
else
loadTileFile(t, file);
}
if (dl.empty())
return;
QEventLoop wait;
connect(downloader, SIGNAL(finished()), &wait, SLOT(quit()));
if (downloader->get(dl))
wait.exec();
for (int i = 0; i < list.size(); i++) {
Tile &t = list[i];
if (t.pixmap().isNull()) {
QString file = tileFile(t);
QFileInfo fi(file);
if (!(fi.exists() && loadTileFile(t, file)))
fillTile(t);
}
}
}
QString OnlineMap::tileUrl(const Tile &tile) const
{
QString url(_url);
url.replace("$z", QString::number(tile.zoom()));
url.replace("$x", QString::number(tile.xy().x()));
url.replace("$y", QString::number(tile.xy().y()));
return url;
}
QString OnlineMap::tileFile(const Tile &tile) const
{
QString file = TILES_DIR + QString("/%1/%2-%3-%4").arg(name())
.arg(tile.zoom()).arg(tile.xy().x()).arg(tile.xy().y());
return file;
}
void OnlineMap::clearCache()
{
QString path = TILES_DIR + QString("/") + name();
QDir dir = QDir(path);
QStringList list = dir.entryList();
for (int i = 0; i < list.count(); i++)
dir.remove(list.at(i));
}
QRectF OnlineMap::bounds() const QRectF OnlineMap::bounds() const
{ {
return QRectF(ll2xy(_bounds.topLeft()), ll2xy(_bounds.bottomRight())); return QRectF(ll2xy(_bounds.topLeft()), ll2xy(_bounds.bottomRight()));
@ -187,7 +90,7 @@ int OnlineMap::limitZoom(int zoom) const
return zoom; return zoom;
} }
qreal OnlineMap::zoomFit(const QSize &size, const RectC &br) int OnlineMap::zoomFit(const QSize &size, const RectC &br)
{ {
if (!br.isValid()) if (!br.isValid())
_zoom = _zooms.max(); _zoom = _zooms.max();
@ -201,29 +104,21 @@ qreal OnlineMap::zoomFit(const QSize &size, const RectC &br)
return _zoom; return _zoom;
} }
qreal OnlineMap::zoomFit(qreal resolution, const Coordinates &c) qreal OnlineMap::resolution(const QRectF &rect) const
{
_zoom = limitZoom((int)log2((WGS84_RADIUS * 2.0 * M_PI
* cos(deg2rad(c.lat()))) / (resolution * TILE_SIZE)));
return _zoom;
}
qreal OnlineMap::resolution(const QPointF &p) const
{ {
qreal scale = zoom2scale(_zoom); qreal scale = zoom2scale(_zoom);
return (WGS84_RADIUS * 2.0 * M_PI * scale / 360.0 return (WGS84_RADIUS * 2.0 * M_PI * scale / 360.0
* cos(2.0 * atan(exp(deg2rad(-p.y() * scale))) - M_PI/2)); * cos(2.0 * atan(exp(deg2rad(-rect.center().y() * scale))) - M_PI/2));
} }
qreal OnlineMap::zoomIn() int OnlineMap::zoomIn()
{ {
_zoom = qMin(_zoom + 1, _zooms.max()); _zoom = qMin(_zoom + 1, _zooms.max());
return _zoom; return _zoom;
} }
qreal OnlineMap::zoomOut() int OnlineMap::zoomOut()
{ {
_zoom = qMax(_zoom - 1, _zooms.min()); _zoom = qMax(_zoom - 1, _zooms.min());
return _zoom; return _zoom;
@ -245,15 +140,19 @@ void OnlineMap::draw(QPainter *painter, const QRectF &rect)
tiles.append(Tile(QPoint(tile.x() + i, tile.y() + j), _zoom)); tiles.append(Tile(QPoint(tile.x() + i, tile.y() + j), _zoom));
if (_block) if (_block)
loadTilesSync(tiles); _tileLoader.loadTilesSync(tiles);
else else
loadTilesAsync(tiles); _tileLoader.loadTilesAsync(tiles);
for (int i = 0; i < tiles.count(); i++) { for (int i = 0; i < tiles.count(); i++) {
Tile &t = tiles[i]; Tile &t = tiles[i];
QPoint tp(tl.x() + (t.xy().x() - tile.x()) * TILE_SIZE, QPoint tp(tl.x() + (t.xy().x() - tile.x()) * TILE_SIZE,
tl.y() + (t.xy().y() - tile.y()) * TILE_SIZE); tl.y() + (t.xy().y() - tile.y()) * TILE_SIZE);
painter->drawPixmap(tp, t.pixmap()); if (t.pixmap().isNull())
painter->fillRect(QRect(tp, QSize(TILE_SIZE, TILE_SIZE)),
_backgroundColor);
else
painter->drawPixmap(tp, t.pixmap());
} }
} }

View File

@ -1,13 +1,10 @@
#ifndef ONLINEMAP_H #ifndef ONLINEMAP_H
#define ONLINEMAP_H #define ONLINEMAP_H
#include "common/coordinates.h"
#include "common/range.h" #include "common/range.h"
#include "common/rectc.h" #include "common/rectc.h"
#include "map.h" #include "map.h"
#include "tile.h" #include "tileloader.h"
class Downloader;
class OnlineMap : public Map class OnlineMap : public Map
{ {
@ -20,13 +17,12 @@ public:
const QString &name() const {return _name;} const QString &name() const {return _name;}
QRectF bounds() const; QRectF bounds() const;
qreal resolution(const QPointF &p) const; qreal resolution(const QRectF &rect) const;
qreal zoom() const {return _zoom;} int zoom() const {return _zoom;}
qreal zoomFit(const QSize &size, const RectC &br); int zoomFit(const QSize &size, const RectC &br);
qreal zoomFit(qreal resolution, const Coordinates &c); int zoomIn();
qreal zoomIn(); int zoomOut();
qreal zoomOut();
QPointF ll2xy(const Coordinates &c) QPointF ll2xy(const Coordinates &c)
{return static_cast<const OnlineMap &>(*this).ll2xy(c);} {return static_cast<const OnlineMap &>(*this).ll2xy(c);}
@ -36,36 +32,31 @@ public:
void draw(QPainter *painter, const QRectF &rect); void draw(QPainter *painter, const QRectF &rect);
void setBlockingMode(bool block) {_block = block;} void setBlockingMode(bool block) {_block = block;}
void clearCache(); void clearCache() {_tileLoader.clearCache();}
static void setDownloader(Downloader *downloader)
{OnlineMap::downloader = downloader;}
void load(); void load();
void unload(); void unload();
bool isValid() const {return _valid;}
QString errorString() const {return _errorString;}
private slots: private slots:
void emitLoaded(); void emitLoaded();
private: private:
QPointF ll2xy(const Coordinates &c) const; QPointF ll2xy(const Coordinates &c) const;
Coordinates xy2ll(const QPointF &p) const; Coordinates xy2ll(const QPointF &p) const;
void fillTile(Tile &tile);
QString tileUrl(const Tile &tile) const;
QString tileFile(const Tile &tile) const;
void loadTilesAsync(QList<Tile> &list);
void loadTilesSync(QList<Tile> &list);
int limitZoom(int zoom) const; int limitZoom(int zoom) const;
TileLoader _tileLoader;
QString _name; QString _name;
QString _url;
Range _zooms; Range _zooms;
RectC _bounds; RectC _bounds;
int _zoom; int _zoom;
bool _block; bool _block;
static Downloader *downloader; bool _valid;
QString _errorString;
}; };
#endif // ONLINEMAP_H #endif // ONLINEMAP_H

View File

@ -185,12 +185,8 @@ bool OZF::readTileTable()
return _zooms.isEmpty() ? false : true; return _zooms.isEmpty() ? false : true;
} }
bool OZF::load(const QString &path) bool OZF::open()
{ {
if (_file.isOpen())
_file.close();
_file.setFileName(path);
if (!_file.open(QIODevice::ReadOnly)) if (!_file.open(QIODevice::ReadOnly))
return false; return false;
@ -227,7 +223,7 @@ QPixmap OZF::tile(int zoom, int x, int y)
quint32 bes = qToBigEndian(tileSize().width() * tileSize().height()); quint32 bes = qToBigEndian(tileSize().width() * tileSize().height());
QByteArray ba; QByteArray ba;
ba.resize(sizeof(bes) + size); ba.resize(sizeof(bes) + size);
*(ba.data()) = bes; memcpy(ba.data(), &bes, sizeof(bes));
if (!read(ba.data() + sizeof(bes), size, 16)) if (!read(ba.data() + sizeof(bes), size, 16))
return QPixmap(); return QPixmap();
@ -250,6 +246,12 @@ QSize OZF::size(int zoom) const
return _zooms.at(zoom).size; return _zooms.at(zoom).size;
} }
QPointF OZF::scale(int zoom) const
{
return QPointF((qreal)size(zoom).width() / (qreal)size(0).width(),
(qreal)size(zoom).height() / (qreal)size(0).height());
}
bool OZF::isOZF(const QString &path) bool OZF::isOZF(const QString &path)
{ {
QFile file(path); QFile file(path);

View File

@ -12,15 +12,17 @@
class OZF class OZF
{ {
public: public:
OZF() : _tileSize(0), _decrypt(false), _key(0) {} OZF(const QString &name) : _tileSize(0), _decrypt(false), _key(0),
_file(name) {}
bool load(const QString &path); bool open();
QString fileName() const {return _file.fileName();} QString fileName() const {return _file.fileName();}
bool isOpen() const {return _file.isOpen();} bool isOpen() const {return _file.isOpen();}
int zooms() const {return _zooms.size();} int zooms() const {return _zooms.size();}
QSize size(int zoom) const; QSize size(int zoom) const;
QPointF scale(int zoom) const;
QSize tileSize() const {return QSize(_tileSize, _tileSize);} QSize tileSize() const {return QSize(_tileSize, _tileSize);}
QPixmap tile(int zoom, int x, int y); QPixmap tile(int zoom, int x, int y);

View File

@ -22,6 +22,7 @@ static bool parameter(int key, double val, int units, Projection::Setup &setup)
{ {
switch (key) { switch (key) {
case 8801: case 8801:
case 8811:
case 8821: case 8821:
{AngularUnits au(units); {AngularUnits au(units);
if (au.isNull()) if (au.isNull())
@ -29,6 +30,7 @@ static bool parameter(int key, double val, int units, Projection::Setup &setup)
setup.setLatitudeOrigin(au.toDegrees(val));} setup.setLatitudeOrigin(au.toDegrees(val));}
return true; return true;
case 8802: case 8802:
case 8812:
case 8822: case 8822:
{AngularUnits au(units); {AngularUnits au(units);
if (au.isNull()) if (au.isNull())
@ -36,9 +38,11 @@ static bool parameter(int key, double val, int units, Projection::Setup &setup)
setup.setLongitudeOrigin(au.toDegrees(val));} setup.setLongitudeOrigin(au.toDegrees(val));}
return true; return true;
case 8805: case 8805:
case 8815:
setup.setScale(val); setup.setScale(val);
return true; return true;
case 8806: case 8806:
case 8816:
case 8826: case 8826:
{LinearUnits lu(units); {LinearUnits lu(units);
if (lu.isNull()) if (lu.isNull())
@ -46,18 +50,21 @@ static bool parameter(int key, double val, int units, Projection::Setup &setup)
setup.setFalseEasting(lu.toMeters(val));} setup.setFalseEasting(lu.toMeters(val));}
return true; return true;
case 8807: case 8807:
case 8817:
case 8827: case 8827:
{LinearUnits lu(units); {LinearUnits lu(units);
if (lu.isNull()) if (lu.isNull())
return false; return false;
setup.setFalseNorthing(lu.toMeters(val));} setup.setFalseNorthing(lu.toMeters(val));}
return true; return true;
case 8813:
case 8823: case 8823:
{AngularUnits au(units); {AngularUnits au(units);
if (au.isNull()) if (au.isNull())
return false; return false;
setup.setStandardParallel1(au.toDegrees(val));} setup.setStandardParallel1(au.toDegrees(val));}
return true; return true;
case 8814:
case 8824: case 8824:
{AngularUnits au(units); {AngularUnits au(units);
if (au.isNull()) if (au.isNull())
@ -74,7 +81,7 @@ static int projectionSetup(const QList<QByteArray> &list,
{ {
bool r1, r2, r3; bool r1, r2, r3;
for (int i = 6; i < 24; i += 3) { for (int i = 7; i < 28; i += 3) {
QString ks = list[i].trimmed(); QString ks = list[i].trimmed();
if (ks.isEmpty()) if (ks.isEmpty())
break; break;
@ -83,10 +90,10 @@ static int projectionSetup(const QList<QByteArray> &list,
double val = list[i+1].trimmed().toDouble(&r2); double val = list[i+1].trimmed().toDouble(&r2);
int un = list[i+2].trimmed().toInt(&r3); int un = list[i+2].trimmed().toInt(&r3);
if (!r1 || !r2 || !r3) if (!r1 || !r2 || !r3)
return (i - 6)/3 + 1; return (i - 7)/3 + 1;
if (!parameter(key, val, un, setup)) if (!parameter(key, val, un, setup))
return (i - 6)/3 + 1; return (i - 7)/3 + 1;
} }
return 0; return 0;
@ -129,49 +136,60 @@ void PCS::loadList(const QString &path)
QByteArray line = file.readLine(); QByteArray line = file.readLine();
QList<QByteArray> list = line.split(','); QList<QByteArray> list = line.split(',');
if (list.size() != 24) { if (list.size() != 28) {
qWarning("%s: %d: Format error", qPrintable(path), ln); qWarning("%s:%d: Format error", qPrintable(path), ln);
continue; continue;
} }
int id = list[1].trimmed().toInt(&res); int id = list[1].trimmed().toInt(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid PCS code", qPrintable(path), ln); qWarning("%s:%d: Invalid PCS code", qPrintable(path), ln);
continue; continue;
} }
int gcsid = list[2].trimmed().toInt(&res); int gcsid = list[2].trimmed().toInt(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid GCS code", qPrintable(path), ln); qWarning("%s:%d: Invalid GCS code", qPrintable(path), ln);
continue; continue;
} }
int proj = list[3].trimmed().toInt(&res); int proj = list[3].trimmed().toInt(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid projection code", qPrintable(path), ln); qWarning("%s:%d: Invalid projection code", qPrintable(path), ln);
continue; continue;
} }
int units = list[4].trimmed().toInt(&res); int units = list[4].trimmed().toInt(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid linear units code", qPrintable(path), ln); qWarning("%s:%d: Invalid linear units code", qPrintable(path), ln);
continue; continue;
} }
int transform = list[5].trimmed().toInt(&res); int transform = list[5].trimmed().toInt(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid coordinate transformation code", qWarning("%s:%d: Invalid coordinate transformation code",
qPrintable(path), ln);
continue;
}
int cs = list[6].trimmed().toInt(&res);
if (!res) {
qWarning("%s:%d: Invalid coordinate system code",
qPrintable(path), ln); qPrintable(path), ln);
continue; continue;
} }
if (LinearUnits(units).isNull()) { if (!LinearUnits(units).isValid()) {
qWarning("%s: %d: Unknown linear units code", qPrintable(path), ln); qWarning("%s:%d: Unknown linear units code", qPrintable(path), ln);
continue; continue;
} }
if (Projection::Method(transform).isNull()) { if (!Projection::Method(transform).isValid()) {
qWarning("%s: %d: Unknown coordinate transformation code", qWarning("%s:%d: Unknown coordinate transformation code",
qPrintable(path), ln); qPrintable(path), ln);
continue; continue;
} }
if (!CoordinateSystem(cs).isValid()) {
qWarning("%s:%d: Unknown coordinate system code", qPrintable(path),
ln);
continue;
}
if (!(gcs = GCS::gcs(gcsid))) { if (!(gcs = GCS::gcs(gcsid))) {
qWarning("%s: %d: Unknown GCS code", qPrintable(path), ln); qWarning("%s:%d: Unknown GCS code", qPrintable(path), ln);
continue; continue;
} }
@ -182,7 +200,7 @@ void PCS::loadList(const QString &path)
continue; continue;
} }
PCS pcs(gcs, transform, setup, units); PCS pcs(gcs, transform, setup, units, cs);
_pcss.append(Entry(id, proj, pcs)); _pcss.append(Entry(id, proj, pcs));
} }
} }

View File

@ -5,6 +5,7 @@
#include <QList> #include <QList>
#include "gcs.h" #include "gcs.h"
#include "linearunits.h" #include "linearunits.h"
#include "coordinatesystem.h"
#include "projection.h" #include "projection.h"
class PCS class PCS
@ -12,18 +13,20 @@ class PCS
public: public:
PCS() : _gcs(0) {} PCS() : _gcs(0) {}
PCS(const GCS *gcs, const Projection::Method &method, PCS(const GCS *gcs, const Projection::Method &method,
const Projection::Setup &setup, const LinearUnits &units) const Projection::Setup &setup, const LinearUnits &units,
: _gcs(gcs), _method(method), _setup(setup), _units(units) {} const CoordinateSystem &cs = CoordinateSystem())
: _gcs(gcs), _method(method), _setup(setup), _units(units), _cs(cs) {}
PCS(const GCS *gcs, int proj); PCS(const GCS *gcs, int proj);
const GCS *gcs() const {return _gcs;} const GCS *gcs() const {return _gcs;}
const Projection::Method &method() const {return _method;} const Projection::Method &method() const {return _method;}
const Projection::Setup &setup() const {return _setup;} const Projection::Setup &setup() const {return _setup;}
const LinearUnits &units() const {return _units;} const LinearUnits &units() const {return _units;}
const CoordinateSystem &coordinateSystem() const {return _cs;}
bool isNull() const bool isNull() const
{return (_gcs->isNull() && _units.isNull() && _method.isNull() {return (_gcs->isNull() && _units.isNull() && _method.isNull()
&& _setup.isNull());} && _setup.isNull());}
bool isValid() const bool isValid() const
{return (_gcs->isValid() && _units.isValid() && _method.isValid());} {return (_gcs->isValid() && _units.isValid() && _method.isValid());}
@ -38,9 +41,9 @@ private:
Projection::Method _method; Projection::Method _method;
Projection::Setup _setup; Projection::Setup _setup;
LinearUnits _units; LinearUnits _units;
CoordinateSystem _cs;
static QList<Entry> _pcss; static QList<Entry> _pcss;
static GCS _nullGCS;
}; };
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG

View File

@ -6,6 +6,7 @@
#include "lambertazimuthal.h" #include "lambertazimuthal.h"
#include "latlon.h" #include "latlon.h"
#include "gcs.h" #include "gcs.h"
#include "pcs.h"
#include "projection.h" #include "projection.h"
@ -16,6 +17,7 @@ Projection::Method::Method(int id)
case 9801: case 9801:
case 9802: case 9802:
case 9807: case 9807:
case 9815:
case 9820: case 9820:
case 9822: case 9822:
case 9841: case 9841:
@ -26,29 +28,31 @@ Projection::Method::Method(int id)
} }
} }
Projection::Projection(const GCS *gcs, const Method &method, const Setup &setup, Projection::Projection(const PCS *pcs) : _gcs(pcs->gcs()), _units(pcs->units()),
const LinearUnits &units) : _gcs(gcs), _units(units) _cs(pcs->coordinateSystem()), _geographic(false)
{ {
const Ellipsoid *ellipsoid = _gcs->datum().ellipsoid(); const Ellipsoid *ellipsoid = _gcs->datum().ellipsoid();
const Projection::Setup &setup = pcs->setup();
switch (method.id()) { switch (pcs->method().id()) {
case 9807:
_ct = new TransverseMercator(ellipsoid, setup.latitudeOrigin(),
setup.longitudeOrigin(), setup.scale(), setup.falseEasting(),
setup.falseNorthing());
break;
case 1024: case 1024:
case 9841: case 9841:
_ct = new Mercator(); _ct = new Mercator();
break; break;
case 9801:
case 9815: // Oblique mercator aproximation using LCC1
_ct = new LambertConic1(ellipsoid, setup.latitudeOrigin(),
setup.longitudeOrigin(), setup.scale(), setup.falseEasting(),
setup.falseNorthing());
break;
case 9802: case 9802:
_ct = new LambertConic2(ellipsoid, setup.standardParallel1(), _ct = new LambertConic2(ellipsoid, setup.standardParallel1(),
setup.standardParallel2(), setup.latitudeOrigin(), setup.standardParallel2(), setup.latitudeOrigin(),
setup.longitudeOrigin(), setup.falseEasting(), setup.longitudeOrigin(), setup.falseEasting(),
setup.falseNorthing()); setup.falseNorthing());
break; break;
case 9801: case 9807:
_ct = new LambertConic1(ellipsoid, setup.latitudeOrigin(), _ct = new TransverseMercator(ellipsoid, setup.latitudeOrigin(),
setup.longitudeOrigin(), setup.scale(), setup.falseEasting(), setup.longitudeOrigin(), setup.scale(), setup.falseEasting(),
setup.falseNorthing()); setup.falseNorthing());
break; break;
@ -68,17 +72,19 @@ Projection::Projection(const GCS *gcs, const Method &method, const Setup &setup,
} }
} }
Projection::Projection(const GCS *gcs) : _gcs(gcs) Projection::Projection(const GCS *gcs, const CoordinateSystem &cs)
: _gcs(gcs), _units(LinearUnits(9001)), _cs(cs), _geographic(true)
{ {
_ct = new LatLon(gcs->angularUnits()); _ct = new LatLon(gcs->angularUnits());
_units = LinearUnits(9001);
} }
Projection::Projection(const Projection &p) Projection::Projection(const Projection &p)
{ {
_gcs = p._gcs; _gcs = p._gcs;
_units = p._units; _units = p._units;
_ct = p._ct->clone(); _ct = p._ct ? p._ct->clone() : 0;
_geographic = p._geographic;
_cs = p._cs;
} }
Projection::~Projection() Projection::~Projection()
@ -90,19 +96,23 @@ Projection &Projection::operator=(const Projection &p)
{ {
_gcs = p._gcs; _gcs = p._gcs;
_units = p._units; _units = p._units;
_ct = p._ct->clone(); _ct = p._ct ? p._ct->clone() : 0;
_geographic = p._geographic;
_cs = p._cs;
return *this; return *this;
} }
QPointF Projection::ll2xy(const Coordinates &c) const QPointF Projection::ll2xy(const Coordinates &c) const
{ {
return _units.fromMeters(_ct->ll2xy(_gcs->fromWGS84(c))); return isValid()
? _units.fromMeters(_ct->ll2xy(_gcs->fromWGS84(c))) : QPointF();
} }
Coordinates Projection::xy2ll(const QPointF &p) const Coordinates Projection::xy2ll(const QPointF &p) const
{ {
return _gcs->toWGS84(_ct->xy2ll(_units.toMeters(p))); return isValid()
? _gcs->toWGS84(_ct->xy2ll(_units.toMeters(p))) : Coordinates();
} }
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG

View File

@ -5,8 +5,10 @@
#include <QDebug> #include <QDebug>
#include "common/coordinates.h" #include "common/coordinates.h"
#include "linearunits.h" #include "linearunits.h"
#include "coordinatesystem.h"
class GCS; class GCS;
class PCS;
class CT; class CT;
class AngularUnits; class AngularUnits;
@ -68,22 +70,31 @@ public:
int _id; int _id;
}; };
Projection() : _gcs(0), _ct(0) {} Projection() : _gcs(0), _ct(0), _geographic(false) {}
Projection(const Projection &p); Projection(const Projection &p);
Projection(const GCS *gcs, const Method &method, const Setup &setup, Projection(const PCS *pcs);
const LinearUnits &units); Projection(const GCS *gcs, const CoordinateSystem &cs
Projection(const GCS *gcs); = CoordinateSystem(CoordinateSystem::YX));
~Projection(); ~Projection();
Projection &operator=(const Projection &p); Projection &operator=(const Projection &p);
bool isNull() const {return (_gcs == 0 && _ct == 0 && _units.isNull());}
bool isValid() const {return !(_gcs == 0 || _ct == 0 || _units.isNull());}
bool isGeographic() const {return _geographic;}
QPointF ll2xy(const Coordinates &c) const; QPointF ll2xy(const Coordinates &c) const;
Coordinates xy2ll(const QPointF &p) const; Coordinates xy2ll(const QPointF &p) const;
const LinearUnits &units() const {return _units;}
const CoordinateSystem &coordinateSystem() const {return _cs;}
private: private:
const GCS * _gcs; const GCS *_gcs;
CT *_ct; const CT *_ct;
LinearUnits _units; LinearUnits _units;
CoordinateSystem _cs;
bool _geographic;
}; };
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG

View File

@ -44,17 +44,12 @@ static quint64 number(const char* data, size_t size, int base = 8)
return val; return val;
} }
bool Tar::load(const QString &path) bool Tar::open()
{ {
if (_file.isOpen())
_file.close();
_index.clear();
_file.setFileName(path);
if (!_file.open(QIODevice::ReadOnly)) if (!_file.open(QIODevice::ReadOnly))
return false; return false;
QFileInfo fi(path); QFileInfo fi(_file.fileName());
QString tmiPath = fi.path() + "/" + fi.completeBaseName() + ".tmi"; QString tmiPath = fi.path() + "/" + fi.completeBaseName() + ".tmi";
if (loadTmi(tmiPath)) if (loadTmi(tmiPath))
@ -121,8 +116,8 @@ QByteArray Tar::file(const QString &name)
struct Header *hdr = (struct Header*)&buffer; struct Header *hdr = (struct Header*)&buffer;
quint64 size; quint64 size;
QMap<QString, quint64>::const_iterator it = _index.find(name); QMap<QString, quint64>::const_iterator it(_index.find(name));
if (it == _index.end()) if (it == _index.constEnd())
return QByteArray(); return QByteArray();
Q_ASSERT(_file.isOpen()); Q_ASSERT(_file.isOpen());

View File

@ -8,7 +8,9 @@
class Tar class Tar
{ {
public: public:
bool load(const QString &path); Tar(const QString &name) : _file(name) {}
bool open();
QStringList files() const {return _index.keys();} QStringList files() const {return _index.keys();}
QByteArray file(const QString &name); QByteArray file(const QString &name);

View File

@ -7,7 +7,7 @@
class TIFFFile : public QFile class TIFFFile : public QFile
{ {
public: public:
TIFFFile() : QFile(), _be(false) {} TIFFFile() : _be(false) {}
TIFFFile(const QString &path) : QFile(path), _be(false) {} TIFFFile(const QString &path) : QFile(path), _be(false) {}
bool readHeader(quint32 &ifd); bool readHeader(quint32 &ifd);
@ -33,8 +33,8 @@ public:
val = data; val = data;
#endif #endif
return true; return true;
} }
private: private:
bool _be; bool _be;

View File

@ -8,23 +8,26 @@
class Tile class Tile
{ {
public: public:
Tile(const QPoint &xy, int zoom) Tile(const QPoint &xy, const QVariant &zoom, const QRectF &bbox = QRectF())
{_xy = xy; _zoom = zoom;} {_xy = xy; _zoom = zoom; _bbox = bbox;}
int zoom() const {return _zoom;} const QVariant &zoom() const {return _zoom;}
const QPoint& xy() const {return _xy;} const QPoint &xy() const {return _xy;}
const QRectF &bbox() const {return _bbox;}
QPixmap& pixmap() {return _pixmap;} QPixmap& pixmap() {return _pixmap;}
private: private:
int _zoom; QVariant _zoom;
QPoint _xy; QPoint _xy;
QRectF _bbox;
QPixmap _pixmap; QPixmap _pixmap;
}; };
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG
inline QDebug operator<<(QDebug dbg, const Tile &tile) inline QDebug operator<<(QDebug dbg, const Tile &tile)
{ {
dbg.nospace() << "Tile(" << tile.zoom() << ", " << tile.xy() << ")"; dbg.nospace() << "Tile(" << tile.zoom() << ", " << tile.xy() << ", "
<< tile.bbox() << ")";
return dbg.space(); return dbg.space();
} }
#endif // QT_NO_DEBUG #endif // QT_NO_DEBUG

110
src/map/tileloader.cpp Normal file
View File

@ -0,0 +1,110 @@
#include <QDir>
#include <QFileInfo>
#include <QEventLoop>
#include "downloader.h"
#include "tileloader.h"
static bool loadTileFile(Tile &tile, const QString &file)
{
if (!tile.pixmap().load(file)) {
qWarning("%s: error loading tile file\n", qPrintable(file));
return false;
}
return true;
}
Downloader *TileLoader::_downloader = 0;
void TileLoader::loadTilesAsync(QList<Tile> &list)
{
QList<Download> dl;
for (int i = 0; i < list.size(); i++) {
Tile &t = list[i];
QString file = tileFile(t);
QFileInfo fi(file);
if (!fi.exists())
dl.append(Download(tileUrl(t), file));
else
loadTileFile(t, file);
}
if (!dl.empty())
_downloader->get(dl, _authorization);
}
void TileLoader::loadTilesSync(QList<Tile> &list)
{
QList<Download> dl;
for (int i = 0; i < list.size(); i++) {
Tile &t = list[i];
QString file = tileFile(t);
QFileInfo fi(file);
if (!fi.exists())
dl.append(Download(tileUrl(t), file));
else
loadTileFile(t, file);
}
if (dl.empty())
return;
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);
if (QFileInfo(file).exists())
loadTileFile(t, file);
}
}
}
void TileLoader::clearCache()
{
QDir dir = QDir(_dir);
QStringList list = dir.entryList();
for (int i = 0; i < list.count(); i++)
dir.remove(list.at(i));
_downloader->clearErrors();
}
QString TileLoader::tileUrl(const Tile &tile) const
{
QString url(_url);
if (!tile.bbox().isNull()) {
QString bbox = QString("%1,%2,%3,%4").arg(
QString::number(tile.bbox().left(), 'f', 6),
QString::number(tile.bbox().bottom(), 'f', 6),
QString::number(tile.bbox().right(), 'f', 6),
QString::number(tile.bbox().top(), 'f', 6));
url.replace("$bbox", bbox);
} else {
url.replace("$z", tile.zoom().toString());
url.replace("$x", QString::number(tile.xy().x()));
url.replace("$y", QString::number(tile.xy().y()));
}
return url;
}
QString TileLoader::tileFile(const Tile &tile) const
{
QString file = _dir + QString("/%1-%2-%3").arg(tile.zoom().toString())
.arg(tile.xy().x()).arg(tile.xy().y());
return file;
}

35
src/map/tileloader.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef TILELOADER_H
#define TILELOADER_H
#include <QString>
#include "tile.h"
#include "downloader.h"
class TileLoader
{
public:
TileLoader() {}
TileLoader(const QString &url, const QString &dir,
const Authorization &authorization = Authorization())
: _url(url), _dir(dir), _authorization(authorization) {}
void loadTilesAsync(QList<Tile> &list);
void loadTilesSync(QList<Tile> &list);
void clearCache();
static Downloader *downloader() {return _downloader;}
static void setDownloader(Downloader *downloader)
{_downloader = downloader;}
private:
QString tileUrl(const Tile &tile) const;
QString tileFile(const Tile &tile) const;
QString _url;
QString _dir;
Authorization _authorization;
static Downloader *_downloader;
};
#endif // TILELOADER_Honlinemap

View File

@ -2,6 +2,9 @@
#include "matrix.h" #include "matrix.h"
#include "transform.h" #include "transform.h"
#define NULL_QTRANSFORM 0,0,0,0,0,0,0,0,0
void Transform::simple(const QList<ReferencePoint> &points) void Transform::simple(const QList<ReferencePoint> &points)
{ {
if (points.at(0).xy.x() == points.at(1).xy.x() if (points.at(0).xy.x() == points.at(1).xy.x()
@ -18,7 +21,8 @@ void Transform::simple(const QList<ReferencePoint> &points)
dX = points.at(1).xy.x() - points.at(1).pp.x() * sX; dX = points.at(1).xy.x() - points.at(1).pp.x() * sX;
dY = points.at(0).xy.y() - points.at(0).pp.y() * sY; dY = points.at(0).xy.y() - points.at(0).pp.y() * sY;
_transform = QTransform(sX, 0, 0, sY, dX, dY); _proj2img = QTransform(sX, 0, 0, sY, dX, dY);
_img2proj = _proj2img.inverted();
} }
void Transform::affine(const QList<ReferencePoint> &points) void Transform::affine(const QList<ReferencePoint> &points)
@ -59,8 +63,15 @@ void Transform::affine(const QList<ReferencePoint> &points)
return; return;
} }
_transform = QTransform(M.m(0,3), M.m(0,4), M.m(1,3), M.m(1,4), M.m(2,3), _proj2img = QTransform(M.m(0,3), M.m(0,4), M.m(1,3), M.m(1,4), M.m(2,3),
M.m(2,4)); M.m(2,4));
_img2proj = _proj2img.inverted();
}
Transform::Transform()
: _proj2img(NULL_QTRANSFORM), _img2proj(NULL_QTRANSFORM)
{
} }
Transform::Transform(const QList<ReferencePoint> &points) Transform::Transform(const QList<ReferencePoint> &points)
@ -73,6 +84,29 @@ Transform::Transform(const QList<ReferencePoint> &points)
affine(points); affine(points);
} }
Transform::Transform(const ReferencePoint &p, const QPointF &scale)
: _proj2img(NULL_QTRANSFORM), _img2proj(NULL_QTRANSFORM)
{
if (scale.x() == 0.0 || scale.y() == 0.0) {
_errorString = "Invalid scale factor";
return;
}
_img2proj = QTransform(scale.x(), 0, 0, -scale.y(), p.pp.x() - p.xy.x()
/ scale.x(), p.pp.y() + p.xy.x() / scale.y());
_proj2img = _img2proj.inverted();
}
Transform::Transform(double m[16])
: _proj2img(NULL_QTRANSFORM), _img2proj(NULL_QTRANSFORM)
{
_img2proj = QTransform(m[0], m[1], m[4], m[5], m[3], m[7]);
if (!_img2proj.isInvertible())
_errorString = "Singular transformation matrix";
else
_proj2img = _img2proj.inverted();
}
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const ReferencePoint &p) QDebug operator<<(QDebug dbg, const ReferencePoint &p)
{ {

View File

@ -3,7 +3,7 @@
#include <QTransform> #include <QTransform>
#include <QList> #include <QList>
#include "common/coordinates.h" #include <QDebug>
struct ReferencePoint { struct ReferencePoint {
QPoint xy; QPoint xy;
@ -13,17 +13,23 @@ struct ReferencePoint {
class Transform class Transform
{ {
public: public:
Transform();
Transform(const QList<ReferencePoint> &points); Transform(const QList<ReferencePoint> &points);
Transform(const ReferencePoint &p, const QPointF &scale);
Transform(double m[16]);
bool isNull() {return _transform.type() == QTransform::TxNone;} QPointF proj2img(const QPointF &p) const {return _proj2img.map(p);}
QPointF img2proj(const QPointF &p) const {return _img2proj.map(p);}
bool isValid() const
{return _proj2img.isInvertible() && _img2proj.isInvertible();}
const QString &errorString() const {return _errorString;} const QString &errorString() const {return _errorString;}
const QTransform &transform() const {return _transform;}
private: private:
void simple(const QList<ReferencePoint> &points); void simple(const QList<ReferencePoint> &points);
void affine(const QList<ReferencePoint> &points); void affine(const QList<ReferencePoint> &points);
QTransform _transform; QTransform _proj2img, _img2proj;
QString _errorString; QString _errorString;
}; };

View File

@ -47,14 +47,14 @@ Defense.
#define SPHSN(lat) \ #define SPHSN(lat) \
((double)(_e->radius() / sqrt(1.e0 - _es * pow(sin(lat), 2)))) ((double)(_a / sqrt(1.e0 - _es * pow(sin(lat), 2))))
#define SPHTMD(lat) \ #define SPHTMD(lat) \
((double)(_ap * lat - _bp * sin(2.e0 * lat) + _cp * sin(4.e0 * lat) \ ((double)(_ap * lat - _bp * sin(2.e0 * lat) + _cp * sin(4.e0 * lat) \
- _dp * sin(6.e0 * lat) + _ep * sin(8.e0 * lat))) - _dp * sin(6.e0 * lat) + _ep * sin(8.e0 * lat)))
#define DENOM(lat) \ #define DENOM(lat) \
((double)(sqrt(1.e0 - _es * pow(sin(lat),2)))) ((double)(sqrt(1.e0 - _es * pow(sin(lat),2))))
#define SPHSR(lat) \ #define SPHSR(lat) \
((double)(_e->radius() * (1.e0 - _es) / pow(DENOM(lat), 3))) ((double)(_a * (1.e0 - _es) / pow(DENOM(lat), 3)))
TransverseMercator::TransverseMercator(const Ellipsoid *ellipsoid, TransverseMercator::TransverseMercator(const Ellipsoid *ellipsoid,
@ -65,31 +65,32 @@ TransverseMercator::TransverseMercator(const Ellipsoid *ellipsoid,
double b; double b;
_e = ellipsoid; _a = ellipsoid->radius();
_longitudeOrigin = deg2rad(longitudeOrigin); _longitudeOrigin = deg2rad(longitudeOrigin);
_latitudeOrigin = deg2rad(latitudeOrigin); _latitudeOrigin = deg2rad(latitudeOrigin);
_scale = scale; _scale = scale;
_falseEasting = falseEasting; _falseEasting = falseEasting;
_falseNorthing = falseNorthing; _falseNorthing = falseNorthing;
_es = 2 * _e->flattening() - _e->flattening() * _e->flattening(); _es = 2 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
_ebs = (1 / (1 - _es)) - 1; _ebs = (1 / (1 - _es)) - 1;
b = _e->radius() * (1 - _e->flattening()); b = _a * (1 - ellipsoid->flattening());
tn = (_e->radius() - b) / (_e->radius() + b); tn = (_a - b) / (_a + b);
tn2 = tn * tn; tn2 = tn * tn;
tn3 = tn2 * tn; tn3 = tn2 * tn;
tn4 = tn3 * tn; tn4 = tn3 * tn;
tn5 = tn4 * tn; tn5 = tn4 * tn;
_ap = _e->radius() * (1.e0 - tn + 5.e0 * (tn2 - tn3) / 4.e0 + 81.e0 _ap = _a * (1.e0 - tn + 5.e0 * (tn2 - tn3) / 4.e0 + 81.e0
* (tn4 - tn5) / 64.e0); * (tn4 - tn5) / 64.e0);
_bp = 3.e0 * _e->radius() * (tn - tn2 + 7.e0 * (tn3 - tn4) / 8.e0 + 55.e0 _bp = 3.e0 * _a * (tn - tn2 + 7.e0 * (tn3 - tn4) / 8.e0 + 55.e0
* tn5 / 64.e0 ) / 2.e0; * tn5 / 64.e0 ) / 2.e0;
_cp = 15.e0 * _e->radius() * (tn2 - tn3 + 3.e0 * (tn4 - tn5 ) / 4.e0) / 16.0; _cp = 15.e0 * _a * (tn2 - tn3 + 3.e0 * (tn4 - tn5 ) / 4.e0) / 16.0;
_dp = 35.e0 * _e->radius() * (tn3 - tn4 + 11.e0 * tn5 / 16.e0) / 48.e0; _dp = 35.e0 * _a * (tn3 - tn4 + 11.e0 * tn5 / 16.e0) / 48.e0;
_ep = 315.e0 * _e->radius() * (tn4 - tn5) / 512.e0; _ep = 315.e0 * _a * (tn4 - tn5) / 512.e0;
} }
QPointF TransverseMercator::ll2xy(const Coordinates &c) const QPointF TransverseMercator::ll2xy(const Coordinates &c) const

View File

@ -2,7 +2,8 @@
#define TRANSVERSEMERCATOR_H #define TRANSVERSEMERCATOR_H
#include "ct.h" #include "ct.h"
#include "ellipsoid.h"
class Ellipsoid;
class TransverseMercator : public CT class TransverseMercator : public CT
{ {
@ -17,12 +18,12 @@ public:
virtual Coordinates xy2ll(const QPointF &p) const; virtual Coordinates xy2ll(const QPointF &p) const;
private: private:
const Ellipsoid *_e;
double _longitudeOrigin; double _longitudeOrigin;
double _latitudeOrigin; double _latitudeOrigin;
double _scale; double _scale;
double _falseEasting; double _falseEasting;
double _falseNorthing; double _falseNorthing;
double _a;
double _es; double _es;
double _ebs; double _ebs;

View File

@ -3,11 +3,10 @@
#include "projection.h" #include "projection.h"
class UTM namespace UTM
{ {
public: int zone(const Coordinates &c);
static int zone(const Coordinates &c); Projection::Setup setup(int zone);
static Projection::Setup setup(int zone); }
};
#endif // UTM_H #endif // UTM_H

288
src/map/wms.cpp Normal file
View File

@ -0,0 +1,288 @@
#include <QFileInfo>
#include <QEventLoop>
#include <QXmlStreamReader>
#include <QStringList>
#include "downloader.h"
#include "crs.h"
#include "wms.h"
Downloader *WMS::_downloader = 0;
WMS::CTX::CTX(const Setup &setup) : setup(setup), formatSupported(false)
{
QStringList ll = setup.layer().split(',');
if (setup.style().isEmpty()) {
for (int i = 0; i < ll.size(); i++)
layers.append(Layer(ll.at(i)));
} else {
QStringList sl = setup.style().split(',');
if (ll.size() != sl.size())
return;
for (int i = 0; i < ll.size(); i++)
layers.append(Layer(ll.at(i), sl.at(i)));
}
}
void WMS::getMap(QXmlStreamReader &reader, CTX &ctx)
{
while (reader.readNextStartElement()) {
if (reader.name() == "Format") {
if (reader.readElementText() == ctx.setup.format())
ctx.formatSupported = true;
} else
reader.skipCurrentElement();
}
}
void WMS::request(QXmlStreamReader &reader, CTX &ctx)
{
while (reader.readNextStartElement()) {
if (reader.name() == "GetMap")
getMap(reader, ctx);
else
reader.skipCurrentElement();
}
}
QString WMS::style(QXmlStreamReader &reader)
{
QString name;
while (reader.readNextStartElement()) {
if (reader.name() == "Name")
name = reader.readElementText();
else
reader.skipCurrentElement();
}
return name;
}
RectC WMS::geographicBoundingBox(QXmlStreamReader &reader)
{
qreal left = NAN, top = NAN, right = NAN, bottom = NAN;
while (reader.readNextStartElement()) {
if (reader.name() == "westBoundLongitude")
left = reader.readElementText().toDouble();
else if (reader.name() == "eastBoundLongitude")
right = reader.readElementText().toDouble();
else if (reader.name() == "northBoundLatitude")
top = reader.readElementText().toDouble();
else if (reader.name() == "southBoundLatitude")
bottom = reader.readElementText().toDouble();
else
reader.skipCurrentElement();
}
return RectC(Coordinates(left, top), Coordinates(right, bottom));
}
void WMS::layer(QXmlStreamReader &reader, CTX &ctx,
const QList<QString> &pCRSs, const QList<QString> &pStyles,
RangeF &pScaleDenominator, RectC &pBoundingBox)
{
QString name;
QList<QString> CRSs(pCRSs);
QList<QString> styles(pStyles);
RangeF scaleDenominator(pScaleDenominator);
RectC boundingBox(pBoundingBox);
int index;
while (reader.readNextStartElement()) {
if (reader.name() == "Name")
name = reader.readElementText();
else if (reader.name() == "CRS" || reader.name() == "SRS")
CRSs.append(reader.readElementText());
else if (reader.name() == "Style")
styles.append(style(reader));
else if (reader.name() == "MinScaleDenominator") {
double sd = reader.readElementText().toDouble();
if (sd > 0)
scaleDenominator.setMin(sd);
} else if (reader.name() == "MaxScaleDenominator") {
double sd = reader.readElementText().toDouble();
if (sd > 0)
scaleDenominator.setMax(sd);
} else if (reader.name() == "LatLonBoundingBox") {
QXmlStreamAttributes attr = reader.attributes();
boundingBox = RectC(Coordinates(
attr.value("minx").toString().toDouble(),
attr.value("maxy").toString().toDouble()),
Coordinates(attr.value("maxx").toString().toDouble(),
attr.value("miny").toString().toDouble()));
reader.skipCurrentElement();
} else if (reader.name() == "EX_GeographicBoundingBox")
boundingBox = geographicBoundingBox(reader);
else if (reader.name() == "Layer")
layer(reader, ctx, CRSs, styles, scaleDenominator, boundingBox);
else
reader.skipCurrentElement();
}
if ((index = ctx.layers.indexOf(name)) >= 0) {
Layer &layer = ctx.layers[index];
layer.scaleDenominator = scaleDenominator;
layer.boundingBox = boundingBox;
layer.isDefined = true;
layer.hasStyle = styles.contains(layer.style) || layer.style.isEmpty();
layer.hasCRS = CRSs.contains(ctx.setup.crs());
}
}
void WMS::capability(QXmlStreamReader &reader, CTX &ctx)
{
QList<QString> CRSs;
QList<QString> styles;
RangeF scaleDenominator(133.295598991, 559082264.0287178);
RectC boundingBox;
while (reader.readNextStartElement()) {
if (reader.name() == "Layer")
layer(reader, ctx, CRSs, styles, scaleDenominator, boundingBox);
else if (reader.name() == "Request")
request(reader, ctx);
else
reader.skipCurrentElement();
}
}
void WMS::capabilities(QXmlStreamReader &reader, CTX &ctx)
{
_version = reader.attributes().value("version").toString();
while (reader.readNextStartElement()) {
if (reader.name() == "Capability")
capability(reader, ctx);
else
reader.skipCurrentElement();
}
}
bool WMS::parseCapabilities(const QString &path, const Setup &setup)
{
QFile file(path);
CTX ctx(setup);
QXmlStreamReader reader;
if (ctx.layers.isEmpty()) {
_errorString = "Invalid layers/styles list definition";
return false;
}
if (!file.open(QFile::ReadOnly | QFile::Text)) {
_errorString = file.errorString();
return false;
}
reader.setDevice(&file);
if (reader.readNextStartElement()) {
if (reader.name() == "WMS_Capabilities"
|| reader.name() == "WMT_MS_Capabilities")
capabilities(reader, ctx);
else
reader.raiseError("Not a WMS Capabilities XML file");
}
if (reader.error()) {
_errorString = QString("%1:%2: %3").arg(path).arg(reader.lineNumber())
.arg(reader.errorString());
return false;
}
if (!ctx.formatSupported) {
_errorString = ctx.setup.format() + ": format not provided";
return false;
}
for (int i = 0; i < ctx.layers.size(); i++) {
const Layer &layer = ctx.layers.at(i);
if (!layer.isDefined) {
_errorString = layer.name + ": layer not provided";
return false;
}
if (!layer.hasStyle) {
_errorString = layer.style + ": style not provided for layer "
+ layer.name;
return false;
}
if (!layer.hasCRS) {
_errorString = ctx.setup.crs() + ": CRS not provided for layer "
+ layer.name;
return false;
}
if (!layer.scaleDenominator.isValid()
|| layer.scaleDenominator.isNull()) {
_errorString = "Invalid scale denominator range for layer "
+ layer.name;
return false;
}
if (!layer.boundingBox.isValid()) {
_errorString = "Invalid/missing bounding box for layer "
+ layer.name;
return false;
}
}
_projection = CRS::projection(ctx.setup.crs());
if (_projection.isNull()) {
_errorString = ctx.setup.crs() + ": unknown CRS";
return false;
}
_boundingBox = ctx.layers.first().boundingBox;
for (int i = 1; i < ctx.layers.size(); i++)
_boundingBox &= ctx.layers.at(i).boundingBox;
if (_boundingBox.isNull()) {
_errorString = "Empty layers bounding box join";
return false;
}
_scaleDenominator = ctx.layers.first().scaleDenominator;
for (int i = 1; i < ctx.layers.size(); i++)
_scaleDenominator &= ctx.layers.at(i).scaleDenominator;
if (_scaleDenominator.isNull()) {
_errorString = "Empty layers scale denominator range join";
return false;
}
return true;
}
bool WMS::getCapabilities(const QString &url, const QString &file,
const Authorization &authorization)
{
QList<Download> dl;
dl.append(Download(url, file));
QEventLoop wait;
QObject::connect(_downloader, SIGNAL(finished()), &wait, SLOT(quit()));
if (_downloader->get(dl, authorization))
wait.exec();
if (QFileInfo(file).exists())
return true;
else {
_errorString = "Error downloading capabilities XML file";
return false;
}
}
WMS::WMS(const QString &file, const WMS::Setup &setup) : _valid(false)
{
QString capaUrl = QString("%1?service=WMS&request=GetCapabilities")
.arg(setup.url());
if (!QFileInfo(file).exists())
if (!getCapabilities(capaUrl, file, setup.authorization()))
return;
if (!parseCapabilities(file, setup))
return;
_valid = true;
}

113
src/map/wms.h Normal file
View File

@ -0,0 +1,113 @@
#ifndef WMS_H
#define WMS_H
#include <QString>
#include <QRectF>
#include "common/range.h"
#include "common/rectc.h"
#include "projection.h"
#include "downloader.h"
#include "coordinatesystem.h"
class QXmlStreamReader;
class WMS
{
public:
class Setup
{
public:
Setup(const QString &url, const QString &layer, const QString &style,
const QString &format, const QString &crs,
const CoordinateSystem &cs,
const QList<QPair<QString, QString> > &dimensions,
const Authorization &authorization = Authorization())
: _url(url), _layer(layer), _style(style), _format(format),
_crs(crs), _cs(cs), _dimensions(dimensions),
_authorization(authorization) {}
const QString &url() const {return _url;}
const Authorization &authorization() const {return _authorization;}
const QString &layer() const {return _layer;}
const QString &style() const {return _style;}
const QString &format() const {return _format;}
const QString &crs() const {return _crs;}
const CoordinateSystem &coordinateSystem() const {return _cs;}
const QList<QPair<QString, QString> > &dimensions() const
{return _dimensions;}
private:
QString _url;
QString _layer;
QString _style;
QString _format;
QString _crs;
CoordinateSystem _cs;
QList<QPair<QString, QString> > _dimensions;
Authorization _authorization;
};
WMS(const QString &path, const Setup &setup);
const Projection &projection() const {return _projection;}
const RangeF &scaleDenominator() const {return _scaleDenominator;}
const RectC &boundingBox() const {return _boundingBox;}
const QString &version() const {return _version;}
bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;}
static void setDownloader(Downloader *downloader)
{_downloader = downloader;}
private:
struct Layer {
QString name;
QString style;
RangeF scaleDenominator;
RectC boundingBox;
bool isDefined;
bool hasStyle;
bool hasCRS;
Layer(const QString &name, const QString &style = QString())
: name(name), style(style), isDefined(false), hasStyle(false),
hasCRS(false) {}
bool operator==(const Layer &other) const
{return this->name == other.name;}
};
struct CTX {
const Setup &setup;
QList<Layer> layers;
bool formatSupported;
CTX(const Setup &setup);
};
RectC geographicBoundingBox(QXmlStreamReader &reader);
QString style(QXmlStreamReader &reader);
void getMap(QXmlStreamReader &reader, CTX &ctx);
void request(QXmlStreamReader &reader, CTX &ctx);
void layer(QXmlStreamReader &reader, CTX &ctx, const QList<QString> &pCRSs,
const QList<QString> &pStyles, RangeF &pScaleDenominator,
RectC &pBoundingBox);
void capability(QXmlStreamReader &reader, CTX &ctx);
void capabilities(QXmlStreamReader &reader, CTX &ctx);
bool parseCapabilities(const QString &path, const Setup &setup);
bool getCapabilities(const QString &url, const QString &file,
const Authorization &authorization);
Projection _projection;
RangeF _scaleDenominator;
RectC _boundingBox;
QString _version;
bool _valid;
QString _errorString;
static Downloader *_downloader;
};
#endif // WMS_H

256
src/map/wmsmap.cpp Normal file
View File

@ -0,0 +1,256 @@
#include <QDir>
#include <QPainter>
#include "common/wgs84.h"
#include "common/rectc.h"
#include "config.h"
#include "downloader.h"
#include "wmsmap.h"
#define CAPABILITIES_FILE "capabilities.xml"
#define TILE_SIZE 256
qreal WMSMap::sd2res(qreal scaleDenominator) const
{
return scaleDenominator * 0.28e-3 * _projection.units().fromMeters(1.0);
}
QString WMSMap::tileUrl(const QString &version) const
{
QString url;
url = QString("%1?version=%2&request=GetMap&bbox=$bbox"
"&width=%3&height=%4&layers=%5&styles=%6&format=%7&transparent=true")
.arg(_setup.url(), version, QString::number(TILE_SIZE),
QString::number(TILE_SIZE), _setup.layer(), _setup.style(),
_setup.format());
if (version >= "1.3.0")
url.append(QString("&CRS=%1").arg(_setup.crs()));
else
url.append(QString("&SRS=%1").arg(_setup.crs()));
for (int i = 0; i < _setup.dimensions().size(); i++) {
const QPair<QString, QString> &dim = _setup.dimensions().at(i);
url.append(QString("&%1=%2").arg(dim.first, dim.second));
}
return url;
}
QString WMSMap::tilesDir() const
{
return QString(TILES_DIR + "/" + _name);
}
void WMSMap::computeZooms(const RangeF &scaleDenominator)
{
_zooms.clear();
if (scaleDenominator.size() > 0) {
qreal ld = log2(scaleDenominator.max()) - log2(scaleDenominator.min());
int cld = ceil(ld);
qreal step = ld / (qreal)cld;
qreal lmax = log2(scaleDenominator.max());
for (int i = 0; i <= cld; i++)
_zooms.append(pow(2.0, lmax - i * step));
} else
_zooms.append(scaleDenominator.min());
}
void WMSMap::updateTransform()
{
qreal scaleDenominator = _zooms.at(_zoom);
ReferencePoint tl, br;
qreal pixelSpan = sd2res(scaleDenominator);
if (_projection.isGeographic())
pixelSpan /= deg2rad(WGS84_RADIUS);
tl.xy = QPoint(0, 0);
tl.pp = _boundingBox.topLeft();
br.xy = QPoint(_boundingBox.width() / pixelSpan, -_boundingBox.height()
/ pixelSpan);
br.pp = _boundingBox.bottomRight();
QList<ReferencePoint> points;
points << tl << br;
_transform = Transform(points);
}
bool WMSMap::loadWMS()
{
QString file = tilesDir() + "/" + CAPABILITIES_FILE;
WMS wms(file, _setup);
if (!wms.isValid()) {
_errorString = wms.errorString();
return false;
}
_projection = wms.projection();
RectC bb = wms.boundingBox().normalized();
_boundingBox = QRectF(_projection.ll2xy(Coordinates(bb.topLeft().lon(),
bb.bottomRight().lat())), _projection.ll2xy(Coordinates(
bb.bottomRight().lon(), bb.topLeft().lat())));
_tileLoader = TileLoader(tileUrl(wms.version()), tilesDir(),
_setup.authorization());
if (wms.version() >= "1.3.0") {
if (_setup.coordinateSystem().axisOrder() == CoordinateSystem::Unknown)
_cs = _projection.coordinateSystem();
else
_cs = _setup.coordinateSystem();
} else
_cs = CoordinateSystem::XY;
computeZooms(wms.scaleDenominator());
updateTransform();
return true;
}
WMSMap::WMSMap(const QString &name, const WMS::Setup &setup, QObject *parent)
: Map(parent), _name(name), _setup(setup), _zoom(0), _block(false),
_valid(false)
{
if (!QDir().mkpath(tilesDir())) {
_errorString = "Error creating tiles dir";
return;
}
_valid = loadWMS();
}
void WMSMap::clearCache()
{
_tileLoader.clearCache();
_zoom = 0;
if (!loadWMS())
qWarning("%s: %s\n", qPrintable(_name), qPrintable(_errorString));
}
void WMSMap::load()
{
connect(TileLoader::downloader(), SIGNAL(finished()), this,
SLOT(emitLoaded()));
}
void WMSMap::unload()
{
disconnect(TileLoader::downloader(), SIGNAL(finished()), this,
SLOT(emitLoaded()));
}
void WMSMap::emitLoaded()
{
emit loaded();
}
QRectF WMSMap::bounds() const
{
qreal pixelSpan = sd2res(_zooms.at(_zoom));
if (_projection.isGeographic())
pixelSpan /= deg2rad(WGS84_RADIUS);
QSizeF size(_boundingBox.width() / pixelSpan, -_boundingBox.height()
/ pixelSpan);
return QRectF(QPointF(0, 0), size);
}
qreal WMSMap::resolution(const QRectF &rect) const
{
Coordinates tl = xy2ll((rect.topLeft()));
Coordinates br = xy2ll(rect.bottomRight());
qreal ds = tl.distanceTo(br);
qreal ps = QLineF(rect.topLeft(), rect.bottomRight()).length();
return ds/ps;
}
int WMSMap::zoomFit(const QSize &size, const RectC &br)
{
if (br.isValid()) {
QRectF tbr(_projection.ll2xy(br.topLeft()),
_projection.ll2xy(br.bottomRight()));
QPointF sc(tbr.width() / size.width(), tbr.height() / size.height());
qreal resolution = qMax(qAbs(sc.x()), qAbs(sc.y()));
if (_projection.isGeographic())
resolution *= deg2rad(WGS84_RADIUS);
_zoom = 0;
for (int i = 0; i < _zooms.size(); i++) {
if (sd2res(_zooms.at(i)) < resolution)
break;
_zoom = i;
}
} else
_zoom = _zooms.size() - 1;
updateTransform();
return _zoom;
}
int WMSMap::zoomIn()
{
_zoom = qMin(_zoom + 1, _zooms.size() - 1);
updateTransform();
return _zoom;
}
int WMSMap::zoomOut()
{
_zoom = qMax(_zoom - 1, 0);
updateTransform();
return _zoom;
}
QPointF WMSMap::ll2xy(const Coordinates &c) const
{
return _transform.proj2img(_projection.ll2xy(c));
}
Coordinates WMSMap::xy2ll(const QPointF &p) const
{
return _projection.xy2ll(_transform.img2proj(p));
}
void WMSMap::draw(QPainter *painter, const QRectF &rect)
{
QPoint tl = QPoint((int)floor(rect.left() / (qreal)TILE_SIZE),
(int)floor(rect.top() / (qreal)TILE_SIZE));
QPoint br = QPoint((int)ceil(rect.right() / (qreal)TILE_SIZE),
(int)ceil(rect.bottom() / (qreal)TILE_SIZE));
QList<Tile> tiles;
for (int i = tl.x(); i < br.x(); i++) {
for (int j = tl.y(); j < br.y(); j++) {
QPointF ttl(_transform.img2proj(QPointF(i * TILE_SIZE,
j * TILE_SIZE)));
QPointF tbr(_transform.img2proj(QPointF(i * TILE_SIZE + TILE_SIZE
- 1, j * TILE_SIZE + TILE_SIZE - 1)));
QRectF bbox = (_cs.axisOrder() == CoordinateSystem::YX)
? QRectF(QPointF(tbr.y(), tbr.x()), QPointF(ttl.y(), ttl.x()))
: QRectF(ttl, tbr);
tiles.append(Tile(QPoint(i, j), _zoom, bbox));
}
}
if (_block)
_tileLoader.loadTilesSync(tiles);
else
_tileLoader.loadTilesAsync(tiles);
for (int i = 0; i < tiles.count(); i++) {
Tile &t = tiles[i];
QPoint tp(t.xy().x() * TILE_SIZE, t.xy().y() * TILE_SIZE);
if (t.pixmap().isNull())
painter->fillRect(QRect(tp, QSize(TILE_SIZE, TILE_SIZE)),
_backgroundColor);
else
painter->drawPixmap(tp, t.pixmap());
}
}

74
src/map/wmsmap.h Normal file
View File

@ -0,0 +1,74 @@
#ifndef WMSMAP_H
#define WMSMAP_H
#include "transform.h"
#include "projection.h"
#include "map.h"
#include "wms.h"
#include "tileloader.h"
class WMSMap : public Map
{
Q_OBJECT
public:
WMSMap(const QString &name, const WMS::Setup &setup, QObject *parent = 0);
const QString &name() const {return _name;}
QRectF bounds() const;
qreal resolution(const QRectF &rect) const;
int zoom() const {return _zoom;}
int zoomFit(const QSize &size, const RectC &br);
int zoomIn();
int zoomOut();
QPointF ll2xy(const Coordinates &c)
{return static_cast<const WMSMap &>(*this).ll2xy(c);}
Coordinates xy2ll(const QPointF &p)
{return static_cast<const WMSMap &>(*this).xy2ll(p);}
void draw(QPainter *painter, const QRectF &rect);
void setBlockingMode(bool block) {_block = block;}
void clearCache();
void load();
void unload();
bool isValid() const {return _valid;}
QString errorString() const {return _errorString;}
private slots:
void emitLoaded();
private:
QString tileUrl(const QString &version) const;
qreal sd2res(qreal scaleDenominator) const;
QString tilesDir() const;
void computeZooms(const RangeF &scaleDenominator);
void updateTransform();
bool loadWMS();
QPointF ll2xy(const Coordinates &c) const;
Coordinates xy2ll(const QPointF &p) const;
QString _name;
WMS::Setup _setup;
TileLoader _tileLoader;
Projection _projection;
Transform _transform;
CoordinateSystem _cs;
QVector<qreal> _zooms;
QRectF _boundingBox;
int _zoom;
bool _block;
bool _valid;
QString _errorString;
};
#endif // WMSMAP_H

376
src/map/wmts.cpp Normal file
View File

@ -0,0 +1,376 @@
#include <QXmlStreamReader>
#include <QFile>
#include <QFileInfo>
#include <QEventLoop>
#include <QTextStream>
#include <QStringList>
#include <QtAlgorithms>
#include <QXmlStreamReader>
#include "downloader.h"
#include "pcs.h"
#include "crs.h"
#include "wmts.h"
Downloader *WMTS::_downloader = 0;
WMTS::TileMatrix WMTS::tileMatrix(QXmlStreamReader &reader)
{
TileMatrix matrix;
while (reader.readNextStartElement()) {
if (reader.name() == "Identifier")
matrix.id = reader.readElementText();
else if (reader.name() == "ScaleDenominator")
matrix.scaleDenominator = reader.readElementText().toDouble();
else if (reader.name() == "TopLeftCorner") {
QString str = reader.readElementText();
QTextStream ts(&str);
ts >> matrix.topLeft.rx() >> matrix.topLeft.ry();
} else if (reader.name() == "TileWidth")
matrix.tile.setWidth(reader.readElementText().toInt());
else if (reader.name() == "TileHeight")
matrix.tile.setHeight(reader.readElementText().toInt());
else if (reader.name() == "MatrixWidth")
matrix.matrix.setWidth(reader.readElementText().toInt());
else if (reader.name() == "MatrixHeight")
matrix.matrix.setHeight(reader.readElementText().toInt());
else
reader.skipCurrentElement();
}
if (!matrix.isValid())
reader.raiseError("Invalid TileMatrix definition");
return matrix;
}
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();
else if (reader.name() == "TileMatrix")
matrixes.insert(tileMatrix(reader));
else
reader.skipCurrentElement();
}
if (id == ctx.setup.set()) {
ctx.crs = crs;
_matrixes = matrixes;
}
}
WMTS::MatrixLimits WMTS::tileMatrixLimits(QXmlStreamReader &reader)
{
MatrixLimits limits;
while (reader.readNextStartElement()) {
if (reader.name() == "TileMatrix")
limits.id = reader.readElementText();
else if (reader.name() == "MinTileRow")
limits.rect.setTop(reader.readElementText().toInt());
else if (reader.name() == "MaxTileRow")
limits.rect.setBottom(reader.readElementText().toInt());
else if (reader.name() == "MinTileCol")
limits.rect.setLeft(reader.readElementText().toInt());
else if (reader.name() == "MaxTileCol")
limits.rect.setRight(reader.readElementText().toInt());
else
reader.skipCurrentElement();
}
if (!limits.isValid())
reader.raiseError("Invalid TileMatrixLimits definition");
return limits;
}
QSet<WMTS::MatrixLimits> WMTS::tileMatrixSetLimits(QXmlStreamReader &reader)
{
QSet<MatrixLimits> limits;
while (reader.readNextStartElement()) {
if (reader.name() == "TileMatrixLimits")
limits.insert(tileMatrixLimits(reader));
else
reader.skipCurrentElement();
}
return limits;
}
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);
else
reader.skipCurrentElement();
}
if (id == ctx.setup.set()) {
ctx.hasSet = true;
_limits = limits;
}
}
RectC WMTS::wgs84BoundingBox(QXmlStreamReader &reader)
{
Coordinates topLeft, bottomRight;
while (reader.readNextStartElement()) {
if (reader.name() == "LowerCorner") {
QString str = reader.readElementText();
QTextStream(&str) >> topLeft.rlon() >> bottomRight.rlat();
} else if (reader.name() == "UpperCorner") {
QString str = reader.readElementText();
QTextStream(&str) >> bottomRight.rlon() >> topLeft.rlat();
} else
reader.skipCurrentElement();
}
return RectC(topLeft, bottomRight);
}
QString WMTS::style(QXmlStreamReader &reader)
{
QString id;
while (reader.readNextStartElement()) {
if (reader.name() == "Identifier")
id = reader.readElementText();
else
reader.skipCurrentElement();
}
return id;
}
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")
tileMatrixSetLink(reader, ctx);
else if (reader.name() == "WGS84BoundingBox")
bounds = wgs84BoundingBox(reader);
else if (reader.name() == "ResourceURL") {
const QXmlStreamAttributes &attr = reader.attributes();
if (attr.value("resourceType") == "tile")
tpl = 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
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)
{
while (reader.readNextStartElement()) {
if (reader.name() == "TileMatrixSet")
tileMatrixSet(reader, ctx);
else if (reader.name() == "Layer")
layer(reader, ctx);
else
reader.skipCurrentElement();
}
}
void WMTS::capabilities(QXmlStreamReader &reader, CTX &ctx)
{
while (reader.readNextStartElement()) {
if (reader.name() == "Contents")
contents(reader, ctx);
else
reader.skipCurrentElement();
}
}
bool WMTS::parseCapabilities(const QString &path, const Setup &setup)
{
QFile file(path);
CTX ctx(setup);
QXmlStreamReader reader;
if (!file.open(QFile::ReadOnly | QFile::Text)) {
_errorString = file.errorString();
return false;
}
reader.setDevice(&file);
if (reader.readNextStartElement()) {
if (reader.name() == "Capabilities")
capabilities(reader, ctx);
else
reader.raiseError("Not a Capabilities XML file");
}
if (reader.error()) {
_errorString = QString("%1:%2: %3").arg(path).arg(reader.lineNumber())
.arg(reader.errorString());
return false;
}
if (!ctx.hasLayer) {
_errorString = ctx.setup.layer() + ": layer not provided";
return false;
}
if (!ctx.hasStyle) {
_errorString = ctx.setup.style() + ": style not provided";
return false;
}
if (!ctx.setup.rest() && !ctx.hasFormat) {
_errorString = ctx.setup.format() + ": format not provided";
return false;
}
if (!ctx.hasSet) {
_errorString = ctx.setup.set() + ": set not provided";
return false;
}
if (ctx.crs.isNull()) {
_errorString = "Missing CRS definition";
return false;
}
_projection = CRS::projection(ctx.crs);
if (_projection.isNull()) {
_errorString = ctx.crs + ": unknown CRS";
return false;
}
if (_matrixes.isEmpty()) {
_errorString = "No usable tile matrix found";
return false;
}
if (ctx.setup.rest() && _tileUrl.isNull()) {
_errorString = "Missing tile URL template";
return false;
}
return true;
}
bool WMTS::getCapabilities(const QString &url, const QString &file,
const Authorization &authorization)
{
QList<Download> dl;
dl.append(Download(url, file));
QEventLoop wait;
QObject::connect(_downloader, SIGNAL(finished()), &wait, SLOT(quit()));
if (_downloader->get(dl, authorization))
wait.exec();
if (QFileInfo(file).exists())
return true;
else {
_errorString = "Error downloading capabilities XML file";
return false;
}
}
WMTS::WMTS(const QString &file, const WMTS::Setup &setup) : _valid(false)
{
QString capaUrl = setup.rest() ? setup.url() :
QString("%1?service=WMTS&Version=1.0.0&request=GetCapabilities")
.arg(setup.url());
if (!QFileInfo(file).exists())
if (!getCapabilities(capaUrl, file, setup.authorization()))
return;
if (!parseCapabilities(file, setup))
return;
QString style = setup.style().isEmpty() ? "default" : setup.style();
if (!setup.rest()) {
_tileUrl = QString("%1?service=WMTS&Version=1.0.0&request=GetTile"
"&Format=%2&Layer=%3&Style=%4&TileMatrixSet=%5&TileMatrix=$z"
"&TileRow=$y&TileCol=$x").arg(setup.url(), setup.format(),
setup.layer(), style, setup.set());
for (int i = 0; i < setup.dimensions().size(); i++) {
const QPair<QString, QString> &dim = setup.dimensions().at(i);
_tileUrl.append(QString("&%1=%2").arg(dim.first, dim.second));
}
} else {
_tileUrl.replace("{Style}", style, Qt::CaseInsensitive);
_tileUrl.replace("{TileMatrixSet}", setup.set(), Qt::CaseInsensitive);
_tileUrl.replace("{TileMatrix}", "$z", Qt::CaseInsensitive);
_tileUrl.replace("{TileRow}", "$y", Qt::CaseInsensitive);
_tileUrl.replace("{TileCol}", "$x", Qt::CaseInsensitive);
for (int i = 0; i < setup.dimensions().size(); i++) {
const QPair<QString, QString> &dim = setup.dimensions().at(i);
_tileUrl.replace(QString("{%1}").arg(dim.first), dim.second,
Qt::CaseInsensitive);
}
}
_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)
{
dbg.nospace() << "Setup(" << setup.url() << ", " << setup.layer() << ", "
<< setup.set() << ", " << setup.style() << ", " << setup.format() << ", "
<< setup.rest() << ")";
return dbg.space();
}
QDebug operator<<(QDebug dbg, const WMTS::Zoom &zoom)
{
dbg.nospace() << "Zoom(" << zoom.id() << ", " << zoom.scaleDenominator()
<< ", " << zoom.topLeft() << ", " << zoom.tile() << ", " << zoom.matrix()
<< ", " << zoom.limits() << ")";
return dbg.space();
}
#endif // QT_NO_DEBUG

178
src/map/wmts.h Normal file
View File

@ -0,0 +1,178 @@
#ifndef WMTS_H
#define WMTS_H
#include <QSize>
#include <QRect>
#include <QSet>
#include <QList>
#include <QHash>
#include "common/rectc.h"
#include "projection.h"
#include "downloader.h"
#include "coordinatesystem.h"
class QXmlStreamReader;
class WMTS
{
public:
class Setup
{
public:
Setup(const QString &url, const QString &layer, const QString &set,
const QString &style, const QString &format, bool rest,
const CoordinateSystem &cs,
const QList<QPair<QString, QString> > &dimensions,
const Authorization &authorization = Authorization())
: _url(url), _layer(layer), _set(set), _style(style),
_format(format), _rest(rest), _cs(cs), _dimensions(dimensions),
_authorization(authorization) {}
const QString &url() const {return _url;}
const Authorization &authorization() const {return _authorization;}
const QString &layer() const {return _layer;}
const QString &set() const {return _set;}
const QString &style() const {return _style;}
const QString &format() const {return _format;}
bool rest() const {return _rest;}
const CoordinateSystem &coordinateSystem() const {return _cs;}
const QList<QPair<QString, QString> > &dimensions() const
{return _dimensions;}
private:
QString _url;
QString _layer;
QString _set;
QString _style;
QString _format;
bool _rest;
CoordinateSystem _cs;
QList<QPair<QString, QString> > _dimensions;
Authorization _authorization;
};
class Zoom
{
public:
Zoom(const QString &id, qreal scaleDenominator, const QPointF &topLeft,
const QSize &tile, const QSize &matrix, const QRect &limits) :
_id(id), _scaleDenominator(scaleDenominator), _topLeft(topLeft),
_tile(tile), _matrix(matrix), _limits(limits) {}
bool operator<(const Zoom &other) const
{return _scaleDenominator > other._scaleDenominator;}
const QString &id() const {return _id;}
qreal scaleDenominator() const {return _scaleDenominator;}
const QPointF &topLeft() const {return _topLeft;}
const QSize &tile() const {return _tile;}
const QSize &matrix() const {return _matrix;}
const QRect &limits() const {return _limits;}
private:
QString _id;
qreal _scaleDenominator;
QPointF _topLeft;
QSize _tile;
QSize _matrix;
QRect _limits;
};
WMTS(const QString &path, const Setup &setup);
const RectC &bounds() const {return _bounds;}
QList<Zoom> zooms() const;
const Projection &projection() const {return _projection;}
const QString &tileUrl() const {return _tileUrl;}
bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;}
static void setDownloader(Downloader *downloader)
{_downloader = downloader;}
private:
struct TileMatrix {
QString id;
qreal scaleDenominator;
QPointF topLeft;
QSize tile;
QSize matrix;
TileMatrix() : scaleDenominator(0) {}
bool operator==(const TileMatrix &other) const
{return this->id == other.id;}
bool isValid() const
{return !id.isEmpty() && scaleDenominator > 0 && tile.isValid()
&& matrix.isValid();}
};
struct MatrixLimits {
QString id;
QRect rect;
MatrixLimits() {}
MatrixLimits(const QString &id) : id(id) {}
bool operator==(const MatrixLimits &other) const
{return this->id == other.id;}
bool isValid() const
{return !id.isEmpty() && rect.isValid();}
};
struct CTX {
const Setup &setup;
QString crs;
bool hasLayer;
bool hasStyle;
bool hasFormat;
bool hasSet;
CTX(const Setup &setup) : setup(setup), hasLayer(false), hasStyle(false),
hasFormat(false), hasSet(false) {}
};
RectC wgs84BoundingBox(QXmlStreamReader &reader);
MatrixLimits tileMatrixLimits(QXmlStreamReader &reader);
TileMatrix tileMatrix(QXmlStreamReader &reader);
QSet<MatrixLimits> tileMatrixSetLimits(QXmlStreamReader &reader);
QString style(QXmlStreamReader &reader);
void tileMatrixSet(QXmlStreamReader &reader, CTX &ctx);
void tileMatrixSetLink(QXmlStreamReader &reader, CTX &ctx);
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 getCapabilities(const QString &url, const QString &file,
const Authorization &authorization);
QSet<TileMatrix> _matrixes;
QSet<MatrixLimits> _limits;
RectC _bounds;
Projection _projection;
QString _tileUrl;
bool _valid;
QString _errorString;
static Downloader *_downloader;
friend uint qHash(const WMTS::TileMatrix &key);
friend uint qHash(const WMTS::MatrixLimits &key);
};
inline uint qHash(const WMTS::TileMatrix &key)
{
return ::qHash(key.id);
}
inline uint qHash(const WMTS::MatrixLimits &key)
{
return ::qHash(key.id);
}
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const WMTS::Setup &setup);
QDebug operator<<(QDebug dbg, const WMTS::Zoom &zoom);
#endif // QT_NO_DEBUG
#endif // WMTS_H

215
src/map/wmtsmap.cpp Normal file
View File

@ -0,0 +1,215 @@
#include <QPainter>
#include "common/rectc.h"
#include "common/wgs84.h"
#include "config.h"
#include "transform.h"
#include "downloader.h"
#include "wmts.h"
#include "wmtsmap.h"
#define CAPABILITIES_FILE "capabilities.xml"
bool WMTSMap::loadWMTS()
{
QString file = tilesDir() + "/" + CAPABILITIES_FILE;
WMTS wmts(file, _setup);
if (!wmts.isValid()) {
_errorString = wmts.errorString();
return false;
}
_bounds = wmts.bounds();
_zooms = wmts.zooms();
_projection = wmts.projection();
_tileLoader = TileLoader(wmts.tileUrl(), tilesDir(),
_setup.authorization());
if (_setup.coordinateSystem().axisOrder() == CoordinateSystem::Unknown)
_cs = _projection.coordinateSystem();
else
_cs = _setup.coordinateSystem();
updateTransform();
return true;
}
WMTSMap::WMTSMap(const QString &name, const WMTS::Setup &setup, QObject *parent)
: Map(parent), _name(name), _setup(setup), _zoom(0), _block(false),
_valid(false)
{
if (!QDir().mkpath(tilesDir())) {
_errorString = "Error creating tiles dir";
return;
}
_valid = loadWMTS();
}
void WMTSMap::clearCache()
{
_tileLoader.clearCache();
_zoom = 0;
if (!loadWMTS())
qWarning("%s: %s\n", qPrintable(_name), qPrintable(_errorString));
}
QString WMTSMap::tilesDir() const
{
return QString(TILES_DIR + "/" + _name);
}
qreal WMTSMap::sd2res(qreal scaleDenominator) const
{
return scaleDenominator * 0.28e-3 * _projection.units().fromMeters(1.0);
}
void WMTSMap::updateTransform()
{
const WMTS::Zoom &z = _zooms.at(_zoom);
ReferencePoint tl, br;
QPointF topLeft = (_cs.axisOrder() == CoordinateSystem::YX)
? QPointF(z.topLeft().y(), z.topLeft().x()) : z.topLeft();
qreal pixelSpan = sd2res(z.scaleDenominator());
if (_projection.isGeographic())
pixelSpan /= deg2rad(WGS84_RADIUS);
QPointF tileSpan(z.tile().width() * pixelSpan, z.tile().height() * pixelSpan);
QPointF bottomRight(topLeft.x() + tileSpan.x() * z.matrix().width(),
topLeft.y() - tileSpan.y() * z.matrix().height());
tl.xy = QPoint(0, 0);
tl.pp = topLeft;
br.xy = QPoint(z.tile().width() * z.matrix().width(),
z.tile().height() * z.matrix().height());
br.pp = bottomRight;
QList<ReferencePoint> points;
points << tl << br;
_transform = Transform(points);
}
void WMTSMap::load()
{
connect(TileLoader::downloader(), SIGNAL(finished()), this,
SLOT(emitLoaded()));
}
void WMTSMap::unload()
{
disconnect(TileLoader::downloader(), SIGNAL(finished()), this,
SLOT(emitLoaded()));
}
void WMTSMap::emitLoaded()
{
emit loaded();
}
QRectF WMTSMap::bounds() const
{
const WMTS::Zoom &z = _zooms.at(_zoom);
QRectF tileBounds, bounds;
tileBounds = (z.limits().isNull()) ?
QRectF(QPointF(0, 0), QSize(z.tile().width() * z.matrix().width(),
z.tile().height() * z.matrix().height()))
: QRectF(QPointF(z.limits().left() * z.tile().width(), z.limits().top()
* z.tile().height()), QSize(z.tile().width() * z.limits().width(),
z.tile().height() * z.limits().height()));
bounds = _bounds.isValid() ? QRectF(ll2xy(_bounds.topLeft()),
ll2xy(_bounds.bottomRight())) : QRectF();
return _bounds.isValid() ? tileBounds.intersected(bounds) : tileBounds;
}
int WMTSMap::zoomFit(const QSize &size, const RectC &br)
{
if (br.isValid()) {
QRectF tbr(_projection.ll2xy(br.topLeft()),
_projection.ll2xy(br.bottomRight()));
QPointF sc(tbr.width() / size.width(), tbr.height() / size.height());
qreal resolution = qMax(qAbs(sc.x()), qAbs(sc.y()));
if (_projection.isGeographic())
resolution *= deg2rad(WGS84_RADIUS);
_zoom = 0;
for (int i = 0; i < _zooms.size(); i++) {
if (sd2res(_zooms.at(i).scaleDenominator()) < resolution)
break;
_zoom = i;
}
} else
_zoom = _zooms.size() - 1;
updateTransform();
return _zoom;
}
qreal WMTSMap::resolution(const QRectF &rect) const
{
Coordinates tl = xy2ll((rect.topLeft()));
Coordinates br = xy2ll(rect.bottomRight());
qreal ds = tl.distanceTo(br);
qreal ps = QLineF(rect.topLeft(), rect.bottomRight()).length();
return ds/ps;
}
int WMTSMap::zoomIn()
{
_zoom = qMin(_zoom + 1, _zooms.size() - 1);
updateTransform();
return _zoom;
}
int WMTSMap::zoomOut()
{
_zoom = qMax(_zoom - 1, 0);
updateTransform();
return _zoom;
}
void WMTSMap::draw(QPainter *painter, const QRectF &rect)
{
const WMTS::Zoom &z = _zooms.at(_zoom);
QPoint tl = QPoint((int)floor(rect.left() / (qreal)z.tile().width()),
(int)floor(rect.top() / (qreal)z.tile().height()));
QPoint br = QPoint((int)ceil(rect.right() / (qreal)z.tile().width()),
(int)ceil(rect.bottom() / (qreal)z.tile().height()));
QList<Tile> tiles;
for (int i = tl.x(); i < br.x(); i++)
for (int j = tl.y(); j < br.y(); j++)
tiles.append(Tile(QPoint(i, j), z.id()));
if (_block)
_tileLoader.loadTilesSync(tiles);
else
_tileLoader.loadTilesAsync(tiles);
for (int i = 0; i < tiles.count(); i++) {
Tile &t = tiles[i];
QPoint tp(t.xy().x() * z.tile().width(), t.xy().y() * z.tile().height());
if (t.pixmap().isNull())
painter->fillRect(QRect(tp, z.tile()), _backgroundColor);
else
painter->drawPixmap(tp, t.pixmap());
}
}
QPointF WMTSMap::ll2xy(const Coordinates &c) const
{
return _transform.proj2img(_projection.ll2xy(c));
}
Coordinates WMTSMap::xy2ll(const QPointF &p) const
{
return _projection.xy2ll(_transform.img2proj(p));
}

71
src/map/wmtsmap.h Normal file
View File

@ -0,0 +1,71 @@
#ifndef WMTSMAP_H
#define WMTSMAP_H
#include "transform.h"
#include "projection.h"
#include "map.h"
#include "wmts.h"
#include "tileloader.h"
class WMTSMap : public Map
{
Q_OBJECT
public:
WMTSMap(const QString &name, const WMTS::Setup &setup, QObject *parent = 0);
const QString &name() const {return _name;}
QRectF bounds() const;
qreal resolution(const QRectF &rect) const;
int zoom() const {return _zoom;}
int zoomFit(const QSize &size, const RectC &br);
int zoomIn();
int zoomOut();
QPointF ll2xy(const Coordinates &c)
{return static_cast<const WMTSMap &>(*this).ll2xy(c);}
Coordinates xy2ll(const QPointF &p)
{return static_cast<const WMTSMap &>(*this).xy2ll(p);}
void draw(QPainter *painter, const QRectF &rect);
void setBlockingMode(bool block) {_block = block;}
void clearCache();
void load();
void unload();
bool isValid() const {return _valid;}
QString errorString() const {return _errorString;}
private slots:
void emitLoaded();
private:
bool loadWMTS();
qreal sd2res(qreal scaleDenominator) const;
QString tilesDir() const;
void updateTransform();
QPointF ll2xy(const Coordinates &c) const;
Coordinates xy2ll(const QPointF &p) const;
QString _name;
WMTS::Setup _setup;
TileLoader _tileLoader;
RectC _bounds;
QList<WMTS::Zoom> _zooms;
Projection _projection;
Transform _transform;
CoordinateSystem _cs;
int _zoom;
bool _block;
bool _valid;
QString _errorString;
};
#endif // WMTSMAP_H