1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-09 16:54:28 +02:00

Compare commits

...

199 Commits
7.29 ... 7.36

Author SHA1 Message Date
fa03ecd419 Use the propper array delete operator 2020-11-11 18:47:34 +01:00
609202fe57 Fixed broken QObject parenting 2020-11-11 18:46:26 +01:00
f55d6d8501 API cleanup 2020-11-10 20:14:59 +01:00
731b309ac9 Remove the special timestamps check from the FIT parser
(Use the common logic in the Track class instead)
2020-11-10 20:07:46 +01:00
f85977d881 Merge branch 'origin/master' into Weblate. 2020-11-10 01:04:34 +01:00
12e395270b Version++ 2020-11-10 01:04:28 +01:00
45b637ba17 Merge branch 'origin/master' into Weblate. 2020-11-10 00:58:58 +01:00
f139d33502 Huffman encoded labels
+ more or less related fixes/refactoring
2020-11-10 00:58:19 +01:00
63e7735abe Translated using Weblate (French)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fr/
2020-11-03 15:20:23 +01:00
27122f94ef Merge branch 'origin/master' into Weblate. 2020-11-02 20:16:38 +01:00
0644bb72a0 Broken subdivs are more common than one would expect... 2020-11-02 20:16:02 +01:00
a4d14511de Merge branch 'origin/master' into Weblate. 2020-11-02 00:19:09 +01:00
1225d350d4 Allow broken subdiv bounds produced by mkgmap 2020-11-02 00:18:27 +01:00
a1d93cc548 Merge branch 'origin/master' into Weblate. 2020-11-01 23:48:14 +01:00
80f5bbfbce Print a warning on invalid subdiv bounds 2020-11-01 23:47:44 +01:00
70c9431ee4 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/uk/
2020-10-28 14:26:59 +01:00
de7664ccc7 Added PNG export info 2020-10-28 12:15:46 +01:00
9bd79a4104 Fixed broken tile bounds 2020-10-27 20:52:29 +01:00
f9abf21e6d Fixed warious bounds wrapping issues 2020-10-27 16:46:09 +01:00
fb4af33d89 Version++ 2020-10-27 11:49:07 +01:00
9eb95daf09 Translated using Weblate (Russian)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2020-10-24 01:05:33 +02:00
d291e55bdb Fixed label pointer parsing 2020-10-22 20:32:12 +02:00
b5893cf506 Fixed label text parsing
(use only space as whitespace separator)
2020-10-22 20:30:11 +02:00
8507fe3b52 Added missing collision detection 2020-10-22 01:16:23 +02:00
79edd6e09d Fixed missing reference 2020-10-21 21:21:35 +02:00
491c6c9a98 Do not let the OS rescale(blur) the windows installer 2020-10-21 21:19:15 +02:00
3c36db9f5a Use antialiased graphs as the default 2020-10-21 21:18:26 +02:00
c4a750f5d4 Merge branch 'origin/master' into Weblate. 2020-10-17 21:00:43 +02:00
e4d7f45103 Remove the right item from the list 2020-10-17 20:59:58 +02:00
c85b90d56d Merge branch 'origin/master' into Weblate. 2020-10-17 14:30:20 +02:00
7babf734bf Fixed memory leak 2020-10-17 14:30:06 +02:00
25ac235414 Merge branch 'origin/master' into Weblate. 2020-10-17 14:27:33 +02:00
630a5cea83 Improved polygon labels layout logic 2020-10-17 14:26:59 +02:00
a0de7f25c3 Merge branch 'origin/master' into Weblate. 2020-10-16 22:46:13 +02:00
7c6174a8ee Some more IMG POI style tweaking 2020-10-16 22:45:51 +02:00
0f512d1269 Merge branch 'origin/master' into Weblate. 2020-10-16 00:04:02 +02:00
246b46ffcb Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.7% (373 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/nb_NO/
2020-10-16 00:04:02 +02:00
cc4cbcbeda Various IMG style enchancements 2020-10-16 00:03:26 +02:00
64e0b492e6 Merge branch 'origin/master' into Weblate. 2020-10-14 22:06:05 +02:00
52a8b1de5b Cosmetics 2020-10-14 22:05:48 +02:00
5045c03953 Merge branch 'origin/master' into Weblate. 2020-10-14 22:04:52 +02:00
515f1aeb27 Use propper structure names 2020-10-14 22:04:32 +02:00
dbb82d6f44 Translated using Weblate (Ukrainian)
Currently translated at 98.6% (369 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/uk/
2020-10-13 03:39:03 +02:00
307a03d46c Translated using Weblate (Finnish)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2020-10-13 03:39:02 +02:00
b7c03b4b9e Merge branch 'origin/master' into Weblate. 2020-10-12 21:18:14 +02:00
2d1e0934ce Silenced clang indentation warning 2020-10-12 21:17:18 +02:00
0ff66bc897 Merge branch 'origin/master' into Weblate. 2020-10-12 20:05:30 +02:00
3b68f497fe Fixed ODR (One Definition Rule) violation 2020-10-12 20:05:17 +02:00
a04293b411 Merge branch 'origin/master' into Weblate. 2020-10-11 21:35:42 +02:00
5a4de1cef0 Accept case insensitive authorities names 2020-10-11 21:33:19 +02:00
99d3d8fd0a Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/pt_BR/
2020-10-10 15:26:41 +02:00
d579ce3482 Translated using Weblate (Russian)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2020-10-09 05:22:55 +02:00
67ce176b74 Version++ 2020-10-09 05:12:19 +02:00
1a88527c60 Fixed icon paths 2020-10-08 23:16:09 +02:00
9d6a2cce45 Merge branch 'origin/master' into Weblate. 2020-10-07 22:57:53 +02:00
7a5f67790e Translated using Weblate (Hungarian)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2020-10-07 22:57:53 +02:00
704c66449f Fixed shorcuts duplicity 2020-10-07 22:57:30 +02:00
42e1331678 Merge branch 'origin/master' into Weblate. 2020-10-07 09:04:54 +02:00
ad3b666a19 Code cleanup 2020-10-07 09:04:40 +02:00
3dd253828e Merge branch 'origin/master' into Weblate. 2020-10-07 08:57:48 +02:00
bb5e50b009 Translated using Weblate (Swedish)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2020-10-07 08:57:48 +02:00
69384ca315 Some more Export dialogs polishing 2020-10-07 08:57:24 +02:00
676c82b7a4 Merge branch 'origin/master' into Weblate. 2020-10-07 00:23:48 +02:00
5a2be6ff07 Translated using Weblate (Turkish)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2020-10-07 00:23:48 +02:00
454e725587 Layout polishing 2020-10-07 00:23:24 +02:00
b9d9ab85b2 Merge branch 'origin/master' into Weblate. 2020-10-06 22:12:52 +02:00
15a2df12bd Localization update 2020-10-06 22:12:35 +02:00
db7a75088a Merge branch 'origin/master' into Weblate. 2020-10-06 22:03:15 +02:00
378da395fb Fixed margins operators + print margins now in cm 2020-10-06 22:02:26 +02:00
da7d0fe32d Merge branch 'origin/master' into Weblate. 2020-10-06 21:42:09 +02:00
789f314ae8 Margins widget refactoring 2020-10-06 21:41:23 +02:00
0986864c6c Translated using Weblate (Russian)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2020-10-06 14:26:41 +02:00
83ac0b5ed7 Translated using Weblate (Finnish)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2020-10-06 14:26:41 +02:00
a1be73fbba Use the propper spin box widget 2020-10-04 22:37:24 +02:00
7761935c29 Translated using Weblate (Hungarian)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2020-10-03 23:41:01 +02:00
4da0e8a1c7 Translated using Weblate (Turkish)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2020-10-03 23:41:01 +02:00
066736b3d2 Translated using Weblate (Swedish)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2020-10-03 23:41:01 +02:00
fdcbc4c6c2 Polished czech translation 2020-10-02 09:36:42 +02:00
b894df26d3 Added missing localization 2020-10-02 09:35:05 +02:00
5a5c0ef68a Localization update 2020-10-02 09:13:49 +02:00
56b7014eaf Unify unsupported data handling 2020-09-29 22:03:26 +02:00
1f52dad1c6 Fixed PNG export layout 2020-09-29 19:49:33 +02:00
0f8859dd20 Code cleanup 2020-09-29 18:53:49 +02:00
398eb152f6 Version++ 2020-09-29 00:04:42 +02:00
38ab835898 Translated using Weblate (Hungarian)
Currently translated at 100.0% (373 of 373 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2020-09-28 20:41:10 +02:00
927740a196 Translated using Weblate (Ukrainian)
Currently translated at 98.9% (369 of 373 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/uk/
2020-09-28 20:41:10 +02:00
4d8b7aa8ae Translated using Weblate (Turkish)
Currently translated at 100.0% (373 of 373 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2020-09-28 20:41:09 +02:00
49c94d34b3 Translated using Weblate (Norwegian Bokmål)
Currently translated at 92.2% (344 of 373 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/nb_NO/
2020-09-28 20:41:09 +02:00
5c2ac54bb4 Translated using Weblate (Russian)
Currently translated at 100.0% (373 of 373 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2020-09-28 20:41:09 +02:00
003947263f Translated using Weblate (Finnish)
Currently translated at 100.0% (373 of 373 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2020-09-28 20:41:08 +02:00
6a70e5ea00 Fixed map plot logic 2020-09-27 22:52:04 +02:00
e83be4d553 Fixed/tweaked export output layout 2020-09-27 22:36:08 +02:00
ce38077281 Translated using Weblate (Russian)
Currently translated at 100.0% (373 of 373 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2020-09-27 20:18:12 +02:00
e75a2882a5 Translated using Weblate (Russian)
Currently translated at 100.0% (373 of 373 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2020-09-27 20:18:12 +02:00
8add7b428f Translated using Weblate (Swedish)
Currently translated at 100.0% (373 of 373 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2020-09-27 06:32:52 +02:00
846f864bd4 Merge branch 'origin/master' into Weblate. 2020-09-27 00:49:06 +02:00
8683254155 Translations update 2020-09-27 00:48:53 +02:00
ef2ffd9fc4 Merge branch 'origin/master' into Weblate. 2020-09-27 00:34:53 +02:00
a9c86fd580 Added PNG export 2020-09-27 00:34:38 +02:00
fe360a2578 Merge branch 'origin/master' into Weblate. 2020-09-26 19:05:50 +02:00
a09a58eece Some more code cleanup 2020-09-26 19:05:35 +02:00
abd1817d83 Merge branch 'origin/master' into Weblate. 2020-09-26 18:56:43 +02:00
7c90174751 Cosmetics 2020-09-26 18:56:26 +02:00
b24f27cf79 Merge branch 'origin/master' into Weblate. 2020-09-26 16:12:41 +02:00
98f88db3cf Properly align the NOD file structure 2020-09-26 16:12:10 +02:00
f2ddfa6fb7 Merge branch 'origin/master' into Weblate. 2020-09-26 16:02:46 +02:00
54ed0ca9f6 Fixed/improved error handling 2020-09-26 16:02:14 +02:00
477b32f444 Merge branch 'origin/master' into Weblate. 2020-09-26 12:24:06 +02:00
1fb6aad50f A better segment copy 2020-09-26 12:23:41 +02:00
4fa9aac917 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (360 of 360 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/uk/
2020-09-24 09:40:58 +02:00
03db87535a Translated using Weblate (Russian)
Currently translated at 100.0% (360 of 360 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2020-09-24 09:40:57 +02:00
92145c8445 Translated using Weblate (Finnish)
Currently translated at 100.0% (360 of 360 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2020-09-24 09:40:57 +02:00
5e8479707b Translated using Weblate (Hungarian)
Currently translated at 100.0% (360 of 360 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2020-09-22 12:39:53 +02:00
2039105ba5 Translated using Weblate (Swedish)
Currently translated at 100.0% (360 of 360 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2020-09-21 06:57:20 +02:00
2605e1abeb Translated using Weblate (Czech)
Currently translated at 100.0% (360 of 360 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/cs/
2020-09-20 23:24:26 +02:00
8fd17badda Merge branch 'origin/master' into Weblate. 2020-09-20 23:05:55 +02:00
7d62ef038c Version++ 2020-09-20 23:05:38 +02:00
138e0e9505 Merge branch 'origin/master' into Weblate. 2020-09-20 22:32:56 +02:00
5dffb2714b Translated using Weblate (Turkish)
Currently translated at 100.0% (360 of 360 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2020-09-20 22:32:55 +02:00
5d8330a68a Use a Qt<5.5 compatible vector append 2020-09-20 22:31:56 +02:00
ff30163175 Merge branch 'origin/master' into Weblate. 2020-09-20 22:19:21 +02:00
743fb20a95 Localization update 2020-09-20 22:19:05 +02:00
50f483663c Added configurable segments usage 2020-09-20 22:18:35 +02:00
96997ffa35 Merge branch 'origin/master' into Weblate. 2020-09-18 20:57:49 +02:00
d738ad7b5a Level 0 2020-09-18 20:56:00 +02:00
01d69a4f2a Merge branch 'origin/master' into Weblate. 2020-09-14 16:34:15 +02:00
0e026d6a96 Properly parse TCX trackpoint extensions 2020-09-14 16:33:44 +02:00
07825e5701 Merge branch 'origin/master' into Weblate. 2020-08-30 20:39:45 +02:00
03e7d092c4 Code cleanup 2020-08-26 18:20:15 +02:00
0b5d01a1f6 A little bit more sane subfile interface 2020-08-26 17:58:21 +02:00
08aa087f61 Translated using Weblate (Polish)
Currently translated at 100.0% (359 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/pl/
2020-07-23 19:41:57 +02:00
6604f85f4a Translated using Weblate (Polish)
Currently translated at 100.0% (359 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/pl/
2020-07-23 19:41:56 +02:00
5343a1a922 "multi-size" app icons on linux
+ icon structure cleanup
2020-07-10 00:57:31 +02:00
d6e0757364 Fixed object interconnection 2020-07-06 23:19:42 +02:00
51becc4bf1 Dummy non-class callback functions are not needed 2020-07-02 23:51:15 +02:00
29a821f8b2 Code cleanup 2020-07-02 00:17:41 +02:00
14f4dead76 Merge branch 'origin/master' into Weblate. 2020-06-29 23:46:00 +02:00
96bb3bbdbb Removed obsolete stuff 2020-06-29 23:46:06 +02:00
22d18b6d4e Merge branch 'origin/master' into Weblate. 2020-06-28 21:02:09 +02:00
c1b79217a9 Update gpxsee_en.ts (#296) 2020-06-28 21:02:05 +02:00
e67a14b072 Merge branch 'origin/master' into Weblate. 2020-06-28 19:52:37 +02:00
473d03cf1f Fixed broken extended objects segment fetching 2020-06-28 19:51:59 +02:00
a339706293 Version++ 2020-06-27 22:51:53 +02:00
39c414ca73 Merge branch 'origin/master' into Weblate. 2020-06-27 22:51:44 +02:00
c59d60faed Merge branch 'origin/master' into Weblate. 2020-06-27 22:50:15 +02:00
32d3eab10e Initial (and partial) IMG links support
+ various IMG fixes (RGN parsing, IMG parsing)
2020-06-27 22:46:26 +02:00
e7729e8745 Added missing Italian localization stuff 2020-06-27 18:05:50 +02:00
bf145c9eb5 Merge branch 'origin/master' into Weblate. 2020-06-27 18:05:48 +02:00
de0a6b0397 Merge branch 'origin/master' into Weblate. 2020-06-27 18:00:07 +02:00
8cf89a580f Removed Arabic translation stub as noone is evidently gona use it despite
the Weblate request...
2020-06-27 17:59:15 +02:00
152e2a8a09 Merge branch 'origin/master' into Weblate. 2020-06-27 17:57:23 +02:00
6b860fe18c added italian translation (#295)
Added italian translation
2020-06-27 17:57:18 +02:00
95f138f5f0 Translated using Weblate (German)
Currently translated at 100.0% (359 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/de/
2020-06-11 13:41:42 +02:00
1fc4dbbb73 Cosmetics 2020-05-30 17:10:13 +02:00
0999cdcba2 Fixed Qt version with time zones support
+ reverted broken Qt version check for opengl
2020-05-30 17:06:06 +02:00
cc16c9e79b Merge branch 'origin/master' into Weblate. 2020-05-30 14:20:58 +02:00
1990c85fd7 Updated Antarctica map URL 2020-05-30 14:20:20 +02:00
58f70fa833 Merge branch 'origin/master' into Weblate. 2020-05-30 14:00:01 +02:00
0f6c50d588 Added missing support for nested KML Documents 2020-05-30 13:59:34 +02:00
89dce5152e Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (359 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/pt_BR/
2020-05-29 01:41:40 +02:00
8bce6a44ed Translated using Weblate (French)
Currently translated at 100.0% (359 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fr/
2020-05-29 01:41:40 +02:00
59ecd3fdf0 Translated using Weblate (Turkish)
Currently translated at 100.0% (359 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2020-05-26 12:41:37 +02:00
a10c729e52 Merge branch 'origin/master' into Weblate. 2020-05-21 20:07:40 +02:00
369601f102 Translated using Weblate (Hungarian)
Currently translated at 100.0% (359 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/hu/
2020-05-21 20:07:39 +02:00
47d0feeb46 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (359 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/uk/
2020-05-21 20:07:39 +02:00
58a0acc718 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.4% (357 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/nb_NO/
2020-05-21 20:07:39 +02:00
c466527625 Translated using Weblate (Russian)
Currently translated at 100.0% (359 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2020-05-21 20:07:38 +02:00
9cd00075c7 Translated using Weblate (Finnish)
Currently translated at 100.0% (359 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2020-05-21 20:07:38 +02:00
6f72d46d6c Merge branch 'master' of github.com:tumic0/GPXSee 2020-05-21 20:07:29 +02:00
54467e6d45 Fixed build with Qt < 5.2 2020-05-21 20:06:49 +02:00
3d2e33361d Merge branch 'origin/master' into Weblate. 2020-05-20 23:56:01 +02:00
f91df0d026 Translated using Weblate (Swedish)
Currently translated at 100.0% (359 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2020-05-20 23:56:01 +02:00
9bd004359d Fixed OS X build 2020-05-20 23:45:06 +02:00
e170f92e79 Translated using Weblate (Czech)
Currently translated at 100.0% (359 of 359 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/cs/
2020-05-20 21:13:48 +02:00
0fb5d8dae6 Czech translation 2020-05-20 21:10:32 +02:00
5ff931bb5e Localization update 2020-05-20 21:02:33 +02:00
5bd744a8ed Added time zone settings 2020-05-20 21:00:36 +02:00
035883aab2 Added github FUNDING.yml file 2020-05-03 11:26:43 +02:00
571ed087e3 Back to the original modified Z-score treshold (5) 2020-05-02 20:44:24 +02:00
c461b2e549 Added support for non-standard 8-parts CRSs 2020-05-02 09:48:30 +02:00
26b5411465 Version++ 2020-04-30 21:48:07 +02:00
8965f450ce 32 layers ought to be enough for anybody 2020-04-30 21:46:41 +02:00
a958544667 Added support for IMG maps overlays 2020-04-26 15:46:42 +02:00
ddf865834a Remove unused consructor 2020-04-26 02:01:25 +02:00
a4abed8f1f Code cleanup 2020-04-26 01:17:54 +02:00
56061c93cb Merge branch 'origin/master' into Weblate. 2020-04-22 22:31:14 +02:00
7385b08262 Added Arabic translations file stub 2020-04-22 22:30:45 +02:00
9d79bd9a9d Merge branch 'origin/master' into Weblate. 2020-04-22 00:47:40 +02:00
159e5aeae9 Fixed error handling 2020-04-22 00:47:12 +02:00
d8beaed876 Merge branch 'origin/master' into Weblate. 2020-04-21 23:28:08 +02:00
c1584f30d2 Limit the map bounds properly based on projection, not a magic height 2020-04-21 23:26:35 +02:00
efcefe8fec Merge branch 'origin/master' into Weblate. 2020-04-19 14:52:45 +02:00
5322ee96c8 Merge branch 'origin/master' into Weblate. 2020-04-19 11:36:41 +02:00
51d4e04343 Merge branch 'origin/master' into Weblate. 2020-04-18 00:01:28 +02:00
0f96bc602c Merge branch 'origin/master' into Weblate. 2020-04-15 22:48:54 +02:00
cb6a82a10a Merge branch 'origin/master' into Weblate. 2020-04-09 10:17:58 +02:00
ff0711c620 Merge branch 'origin/master' into Weblate. 2020-04-08 22:28:54 +02:00
74775b2c62 Merge branch 'origin/master' into Weblate. 2020-04-08 00:55:02 +02:00
a6fbae38b8 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (356 of 356 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/pt_BR/
2020-04-07 15:09:42 +02:00
154 changed files with 12689 additions and 6255 deletions

View File

@ -1,4 +1,4 @@
version: 7.29.{build}
version: 7.36.{build}
configuration:
- Release

1
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1 @@
github: tumic0

View File

@ -9,7 +9,7 @@ GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common G
* Support for DEM files (SRTM HGT).
* Support for multiple tracks in one view.
* Support for POI files.
* Print/export to PDF.
* Print/export to PDF/PNG.
* Full-screen mode.
* HiDPI/Retina displays & maps support.
* Native GUI for Windows, Mac OS X and Linux.

View File

@ -3,7 +3,7 @@ unix:!macx {
} else {
TARGET = GPXSee
}
VERSION = 7.29
VERSION = 7.36
QT += core \
gui \
@ -21,6 +21,7 @@ INCLUDEPATH += ./src
HEADERS += src/common/config.h \
src/GUI/graphicsscene.h \
src/GUI/mapaction.h \
src/GUI/marginswidget.h \
src/GUI/popup.h \
src/common/garmin.h \
src/common/staticassert.h \
@ -53,7 +54,6 @@ HEADERS += src/common/config.h \
src/GUI/palette.h \
src/GUI/heartrategraph.h \
src/GUI/trackinfo.h \
src/GUI/exportdialog.h \
src/GUI/fileselectwidget.h \
src/GUI/margins.h \
src/GUI/temperaturegraph.h \
@ -93,9 +93,13 @@ HEADERS += src/common/config.h \
src/map/IMG/bitstream.h \
src/map/IMG/deltastream.h \
src/map/IMG/gmap.h \
src/map/IMG/huffmanbuffer.h \
src/map/IMG/huffmanstream.h \
src/map/IMG/huffmantable.h \
src/map/IMG/huffmantext.h \
src/map/IMG/nodfile.h \
src/map/IMG/mapdata.h \
src/map/IMG/rastertile.h \
src/map/IMG/textpathitem.h \
src/map/IMG/textpointitem.h \
src/map/projection.h \
@ -196,8 +200,11 @@ HEADERS += src/common/config.h \
src/data/cupparser.h \
src/data/gpiparser.h \
src/data/address.h \
src/data/smlparser.h
src/data/smlparser.h \
src/GUI/pdfexportdialog.h \
src/GUI/pngexportdialog.h
SOURCES += src/main.cpp \
src/GUI/marginswidget.cpp \
src/GUI/popup.cpp \
src/common/coordinates.cpp \
src/common/rectc.cpp \
@ -222,7 +229,6 @@ SOURCES += src/main.cpp \
src/GUI/palette.cpp \
src/GUI/heartrategraph.cpp \
src/GUI/trackinfo.cpp \
src/GUI/exportdialog.cpp \
src/GUI/fileselectwidget.cpp \
src/GUI/temperaturegraph.cpp \
src/GUI/trackitem.cpp \
@ -254,9 +260,13 @@ SOURCES += src/main.cpp \
src/map/IMG/bitstream.cpp \
src/map/IMG/deltastream.cpp \
src/map/IMG/gmap.cpp \
src/map/IMG/huffmanbuffer.cpp \
src/map/IMG/huffmanstream.cpp \
src/map/IMG/huffmantable.cpp \
src/map/IMG/huffmantext.cpp \
src/map/IMG/nodfile.cpp \
src/map/IMG/mapdata.cpp \
src/map/IMG/rastertile.cpp \
src/map/IMG/textpathitem.cpp \
src/map/IMG/textpointitem.cpp \
src/map/maplist.cpp \
@ -340,12 +350,17 @@ SOURCES += src/main.cpp \
src/data/cupparser.cpp \
src/GUI/graphicsscene.cpp \
src/data/gpiparser.cpp \
src/data/smlparser.cpp
src/data/smlparser.cpp \
src/GUI/pdfexportdialog.cpp \
src/GUI/pngexportdialog.cpp
greaterThan(QT_MAJOR_VERSION, 4) {
HEADERS += src/data/geojsonparser.h
SOURCES += src/data/geojsonparser.cpp
}
equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 4) {
HEADERS += src/GUI/timezoneinfo.h
}
DEFINES += APP_VERSION=\\\"$$VERSION\\\" \
QT_NO_DEPRECATED_WARNINGS
@ -366,10 +381,11 @@ TRANSLATIONS = lang/gpxsee_en.ts \
lang/gpxsee_es.ts \
lang/gpxsee_pt_BR.ts \
lang/gpxsee_uk.ts \
lang/gpxsee_hu.ts
lang/gpxsee_hu.ts \
lang/gpxsee_it.ts
macx {
ICON = icons/gpxsee.icns
ICON = icons/app/gpxsee.icns
QMAKE_INFO_PLIST = pkg/Info.plist
locale.path = Contents/Resources/translations
locale.files = lang/gpxsee_en.qm \
@ -386,7 +402,8 @@ macx {
lang/gpxsee_es.qm \
lang/gpxsee_pt_BR.qm \
lang/gpxsee_uk.qm \
lang/gpxsee_hu.qm
lang/gpxsee_hu.qm \
lang/gpxsee_it.qm
csv.path = Contents/Resources
csv.files = pkg/csv
maps.path = Contents/Resources
@ -411,7 +428,7 @@ macx {
}
win32 {
RC_ICONS = icons/gpxsee.ico \
RC_ICONS = icons/app/gpxsee.ico \
icons/formats/gpx.ico \
icons/formats/tcx.ico \
icons/formats/kml.ico \
@ -441,8 +458,8 @@ unix:!macx {
csv.path = $$PREFIX/share/gpxsee/csv
locale.files = lang/*.qm
locale.path = $$PREFIX/share/gpxsee/translations
icon.files = icons/gpxsee.png
icon.path = $$PREFIX/share/pixmaps
icon.files = icons/app/hicolor/*
icon.path = $$PREFIX/share/icons/hicolor
desktop.files = pkg/gpxsee.desktop
desktop.path = $$PREFIX/share/applications
mime.files = pkg/gpxsee.xml

View File

@ -1,8 +1,8 @@
<RCC>
<qresource prefix="/">
<!-- GUI -->
<file alias="gpxsee.png">icons/gpxsee.png</file>
<file alias="gpxsee@2x.png">icons/gpxsee@2x.png</file>
<file alias="gpxsee.png">icons/app/gpxsee.png</file>
<file alias="gpxsee@2x.png">icons/app/gpxsee@2x.png</file>
<file alias="dialog-close.png">icons/GUI/dialog-close.png</file>
<file alias="dialog-close@2x.png">icons/GUI/dialog-close@2x.png</file>
<file alias="document-open.png">icons/GUI/document-open.png</file>
@ -67,10 +67,12 @@
<file alias="cinema-11.png">icons/POI/cinema-11.png</file>
<file alias="clothing-store-11.png">icons/POI/clothing-store-11.png</file>
<file alias="communications-tower-11.png">icons/POI/communications-tower-11.png</file>
<file alias="convenience-11.png">icons/POI/convenience-11.png</file>
<file alias="dam-11.png">icons/POI/dam-11.png</file>
<file alias="danger-11.png">icons/POI/danger-11.png</file>
<file alias="drinking-water-11.png">icons/POI/drinking-water-11.png</file>
<file alias="fast-food-11.png">icons/POI/fast-food-11.png</file>
<file alias="entrance-alt1-11.png">icons/POI/entrance-alt1-11.png</file>
<file alias="fire-station-11.png">icons/POI/fire-station-11.png</file>
<file alias="fitness-centre-11.png">icons/POI/fitness-centre-11.png</file>
<file alias="fuel-11.png">icons/POI/fuel-11.png</file>
@ -97,7 +99,6 @@
<file alias="place-of-worship-11.png">icons/POI/place-of-worship-11.png</file>
<file alias="police-11.png">icons/POI/police-11.png</file>
<file alias="post-11.png">icons/POI/post-11.png</file>
<file alias="prison-11.png">icons/POI/prison-11.png</file>
<file alias="religious-christian-11.png">icons/POI/religious-christian-11.png</file>
<file alias="religious-jewish-11.png">icons/POI/religious-jewish-11.png</file>
<file alias="religious-muslim-11.png">icons/POI/religious-muslim-11.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 B

BIN
icons/app/gpxsee.dia Normal file

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 361 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
<svg width="6cm" height="6cm" viewBox="47 79 119 119" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<rect style="fill: #ffffff" x="47.729" y="79.875" width="118.071" height="118.071" rx="10" ry="10"/>
<rect style="fill: none; fill-opacity:0; stroke-width: 2.35099e-37; stroke-linejoin: round; stroke: #ffffff" x="47.729" y="79.875" width="118.071" height="118.071" rx="10" ry="10"/>
</g>
<g>
<ellipse style="fill: #000000" cx="113" cy="90.875" rx="7.021" ry="7.021"/>
<ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke-linejoin: round; stroke: #000000" cx="113" cy="90.875" rx="7.021" ry="7.021"/>
</g>
<polyline style="fill: none; fill-opacity:0; stroke-width: 4; stroke: #000000" points="61.5289,182.479 73.5,125.854 96,151.875 113,90.875 136.5,172.375 151.658,157.199 "/>
<g>
<ellipse style="fill: #000000" cx="73.5" cy="125.854" rx="7.021" ry="7.021"/>
<ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="73.5" cy="125.854" rx="7.021" ry="7.021"/>
</g>
<g>
<ellipse style="fill: #000000" cx="136.5" cy="172.375" rx="7.021" ry="7.021"/>
<ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="136.5" cy="172.375" rx="7.021" ry="7.021"/>
</g>
<g>
<ellipse style="fill: #000000" cx="60.7" cy="186.4" rx="7.021" ry="7.021"/>
<ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="60.7" cy="186.4" rx="7.021" ry="7.021"/>
</g>
<g>
<ellipse style="fill: #000000" cx="154.5" cy="154.354" rx="7.021" ry="7.021"/>
<ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="154.5" cy="154.354" rx="7.021" ry="7.021"/>
</g>
<g>
<ellipse style="fill: #000000" cx="96" cy="151.875" rx="7.021" ry="7.021"/>
<ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="96" cy="151.875" rx="7.021" ry="7.021"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
<context>
<name>GUI</name>
<message numerus="yes">
<location filename="../src/GUI/gui.cpp" line="1392"/>
<source>%n files</source>
<translation>
<numerusform>%n file</numerusform>
<numerusform>%n files</numerusform>
</translation>
</message>
</context>
</TS>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2018
lang/gpxsee_it.ts Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "7.29"
!define VERSION "7.36"
; The file to write
OutFile "GPXSee-${VERSION}.exe"
@ -17,6 +17,9 @@ SetCompressor /SOLID lzma
; Required execution level
RequestExecutionLevel admin
; Don't let the OS scale(blur) the installer GUI
ManifestDPIAware true
; The default installation directory
InstallDir "$PROGRAMFILES\GPXSee"
@ -177,6 +180,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
!insertmacro LOCALIZATION "French" "fr"
!insertmacro LOCALIZATION "German" "de"
!insertmacro LOCALIZATION "Hungarian" "hu"
!insertmacro LOCALIZATION "Italian" "it"
!insertmacro LOCALIZATION "Norwegian" "nb"
!insertmacro LOCALIZATION "Polish" "pl"
!insertmacro LOCALIZATION "Portuguese (Brazil)" "pt_BR"

View File

@ -7,7 +7,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "7.29"
!define VERSION "7.36"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"
@ -17,6 +17,9 @@ SetCompressor /SOLID lzma
; Required execution level
RequestExecutionLevel admin
; Don't let the OS scale(blur) the installer GUI
ManifestDPIAware true
; The default installation directory
InstallDir "$PROGRAMFILES64\GPXSee"
@ -184,6 +187,7 @@ SectionGroup "Localization" SEC_LOCALIZATION
!insertmacro LOCALIZATION "French" "fr"
!insertmacro LOCALIZATION "German" "de"
!insertmacro LOCALIZATION "Hungarian" "hu"
!insertmacro LOCALIZATION "Italian" "it"
!insertmacro LOCALIZATION "Norwegian" "nb"
!insertmacro LOCALIZATION "Polish" "pl"
!insertmacro LOCALIZATION "Portuguese (Brazil)" "pt_BR"

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.gpxsee.org/map/1.4" type="WMTS">
<name>Antarctica</name>
<url type="REST">https://gis.ngdc.noaa.gov/arcgis/rest/services/antarctic/antarctic_basemap/MapServer/WMTS/1.0.0/WMTSCapabilities.xml</url>
<url type="REST">https://tiles.arcgis.com/tiles/C8EMgrsFcRFL6LrL/arcgis/rest/services/Antarctic_Basemap/MapServer/WMTS/1.0.0/WMTSCapabilities.xml</url>
<copyright>NOAA National Centers for Environmental Information (NCEI); International Bathymetric Chart of the Southern Ocean (IBCSO); General Bathymetric Chart of the Oceans (GEBCO); Natural Earth</copyright>
<layer>antarctic_antarctic_basemap</layer>
<layer>Antarctic_Basemap</layer>
<set>default028mm</set>
</map>

View File

@ -12,7 +12,8 @@ FileSelectWidget::FileSelectWidget(QWidget *parent) : QWidget(parent)
{
QFontMetrics fm(QApplication::font());
_edit = new QLineEdit();
_edit->setMinimumWidth(fm.boundingRect(QDir::homePath()).width());
_edit->setMinimumWidth(fm.averageCharWidth() * (QDir::homePath().length()
+ 12));
#ifdef Q_OS_WIN32
_button = new QPushButton("...");
_button->setMaximumWidth(_button->sizeHint().width() / 2);
@ -41,3 +42,33 @@ void FileSelectWidget::browse()
if (!fileName.isEmpty())
_edit->setText(fileName);
}
bool FileSelectWidget::checkFile(QString &error) const
{
if (_edit->text().isEmpty()) {
error = tr("No output file selected.");
return false;
}
QFile file(_edit->text());
QFileInfo fi(file);
bool exists = fi.exists();
bool opened = false;
if (exists && fi.isDir()) {
error = tr("%1 is a directory.").arg(file.fileName());
return false;
} else if ((exists && !fi.isWritable())
|| !(opened = file.open(QFile::Append))) {
error = tr("%1 is not writable.").arg(file.fileName());
return false;
}
if (opened) {
file.close();
if (!exists)
file.remove();
}
return true;
}

View File

@ -14,9 +14,10 @@ class FileSelectWidget : public QWidget
public:
FileSelectWidget(QWidget *parent = 0);
QString file() {return _edit->text();}
QString file() const {return _edit->text();}
void setFile(const QString &file) {_edit->setText(file);}
void setFilter(const QString &filter) {_filter = filter;}
bool checkFile(QString &error) const;
private slots:
void browse();

View File

@ -140,10 +140,9 @@ void GUI::createMapActions()
MapAction *GUI::createMapAction(Map *map)
{
MapAction *a = new MapAction(map);
MapAction *a = new MapAction(map, _mapsActionGroup);
a->setMenuRole(QAction::NoRole);
a->setCheckable(true);
a->setActionGroup(_mapsActionGroup);
connect(a, SIGNAL(triggered()), this, SLOT(mapChanged()));
return a;
@ -230,13 +229,20 @@ void GUI::createActions()
_printFileAction->setActionGroup(_fileActionGroup);
connect(_printFileAction, SIGNAL(triggered()), this, SLOT(printFile()));
addAction(_printFileAction);
_exportFileAction = new QAction(QIcon(EXPORT_FILE_ICON),
_exportPDFFileAction = new QAction(QIcon(EXPORT_FILE_ICON),
tr("Export to PDF..."), this);
_exportFileAction->setMenuRole(QAction::NoRole);
_exportFileAction->setShortcut(EXPORT_SHORTCUT);
_exportFileAction->setActionGroup(_fileActionGroup);
connect(_exportFileAction, SIGNAL(triggered()), this, SLOT(exportFile()));
addAction(_exportFileAction);
_exportPDFFileAction->setMenuRole(QAction::NoRole);
_exportPDFFileAction->setShortcut(PDF_EXPORT_SHORTCUT);
_exportPDFFileAction->setActionGroup(_fileActionGroup);
connect(_exportPDFFileAction, SIGNAL(triggered()), this, SLOT(exportPDFFile()));
addAction(_exportPDFFileAction);
_exportPNGFileAction = new QAction(QIcon(EXPORT_FILE_ICON),
tr("Export to PNG..."), this);
_exportPNGFileAction->setMenuRole(QAction::NoRole);
_exportPNGFileAction->setShortcut(PNG_EXPORT_SHORTCUT);
_exportPNGFileAction->setActionGroup(_fileActionGroup);
connect(_exportPNGFileAction, SIGNAL(triggered()), this, SLOT(exportPNGFile()));
addAction(_exportPNGFileAction);
_closeFileAction = new QAction(QIcon(CLOSE_FILE_ICON), tr("Close"), this);
_closeFileAction->setMenuRole(QAction::NoRole);
_closeFileAction->setShortcut(CLOSE_SHORTCUT);
@ -248,7 +254,7 @@ void GUI::createActions()
_reloadFileAction->setMenuRole(QAction::NoRole);
_reloadFileAction->setShortcut(RELOAD_SHORTCUT);
_reloadFileAction->setActionGroup(_fileActionGroup);
connect(_reloadFileAction, SIGNAL(triggered()), this, SLOT(reloadFile()));
connect(_reloadFileAction, SIGNAL(triggered()), this, SLOT(reloadFiles()));
addAction(_reloadFileAction);
_statisticsAction = new QAction(tr("Statistics..."), this);
_statisticsAction->setMenuRole(QAction::NoRole);
@ -497,7 +503,8 @@ void GUI::createMenus()
fileMenu->addAction(_openFileAction);
fileMenu->addSeparator();
fileMenu->addAction(_printFileAction);
fileMenu->addAction(_exportFileAction);
fileMenu->addAction(_exportPDFFileAction);
fileMenu->addAction(_exportPNGFileAction);
fileMenu->addSeparator();
fileMenu->addAction(_statisticsAction);
fileMenu->addSeparator();
@ -791,7 +798,12 @@ bool GUI::loadFile(const QString &fileName)
_trackDistance += track.distance();
_time += track.time();
_movingTime += track.movingTime();
const QDate &date = track.date().date();
#ifdef ENABLE_TIMEZONES
const QDateTime date = track.date().toTimeZone(
_options.timeZone.zone());
#else // ENABLE_TIMEZONES
const QDateTime &date = track.date();
#endif // ENABLE_TIMEZONES
if (_dateRange.first.isNull() || _dateRange.first > date)
_dateRange.first = date;
if (_dateRange.second.isNull() || _dateRange.second < date)
@ -923,7 +935,7 @@ void GUI::openOptions()
Options options(_options);
bool reload = false;
OptionsDialog dialog(&options, this);
OptionsDialog dialog(options, _units, this);
if (dialog.exec() != QDialog::Accepted)
return;
@ -965,6 +977,7 @@ void GUI::openOptions()
SET_TRACK_OPTION(dataUseDEM, useDEM);
SET_TRACK_OPTION(showSecondaryElevation, showSecondaryElevation);
SET_TRACK_OPTION(showSecondarySpeed, showSecondarySpeed);
SET_TRACK_OPTION(useSegments, useSegments);
SET_ROUTE_OPTION(dataUseDEM, useDEM);
SET_ROUTE_OPTION(showSecondaryElevation, showSecondaryElevation);
@ -990,9 +1003,16 @@ void GUI::openOptions()
_mapView->setDevicePixelRatio(devicePixelRatioF(),
options.hidpiMap ? devicePixelRatioF() : 1.0);
#endif // ENABLE_HIDPI
#ifdef ENABLE_TIMEZONES
if (options.timeZone != _options.timeZone) {
_mapView->setTimeZone(options.timeZone.zone());
_dateRange.first = _dateRange.first.toTimeZone(options.timeZone.zone());
_dateRange.second = _dateRange.second.toTimeZone(options.timeZone.zone());
}
#endif // ENABLE_TIMEZONES
if (reload)
reloadFile();
reloadFiles();
_options = options;
}
@ -1006,9 +1026,9 @@ void GUI::printFile()
plot(&printer);
}
void GUI::exportFile()
void GUI::exportPDFFile()
{
ExportDialog dialog(&_export, this);
PDFExportDialog dialog(_pdfExport, _units, this);
if (dialog.exec() != QDialog::Accepted)
return;
@ -1016,16 +1036,53 @@ void GUI::exportFile()
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setCreator(QString(APP_NAME) + QString(" ")
+ QString(APP_VERSION));
printer.setResolution(_export.resolution);
printer.setOrientation(_export.orientation);
printer.setOutputFileName(_export.fileName);
printer.setPaperSize(_export.paperSize);
printer.setPageMargins(_export.margins.left(), _export.margins.top(),
_export.margins.right(), _export.margins.bottom(), QPrinter::Millimeter);
printer.setResolution(_pdfExport.resolution);
printer.setOrientation(_pdfExport.orientation);
printer.setOutputFileName(_pdfExport.fileName);
printer.setPaperSize(_pdfExport.paperSize);
printer.setPageMargins(_pdfExport.margins.left(), _pdfExport.margins.top(),
_pdfExport.margins.right(), _pdfExport.margins.bottom(),
QPrinter::Millimeter);
plot(&printer);
}
void GUI::exportPNGFile()
{
PNGExportDialog dialog(_pngExport, this);
if (dialog.exec() != QDialog::Accepted)
return;
QImage img(_pngExport.size, QImage::Format_ARGB32_Premultiplied);
QPainter p(&img);
QRectF rect(0, 0, img.width(), img.height());
QRectF contentRect(rect.adjusted(_pngExport.margins.left(),
_pngExport.margins.top(), -_pngExport.margins.right(),
-_pngExport.margins.bottom()));
if (_pngExport.antialiasing)
p.setRenderHint(QPainter::Antialiasing);
p.fillRect(rect, Qt::white);
plotMainPage(&p, contentRect, 1.0, true);
img.save(_pngExport.fileName);
if (!_tabs.isEmpty() && _options.separateGraphPage) {
QImage img2(_pngExport.size.width(), (int)graphPlotHeight(rect, 1)
+ _pngExport.margins.bottom(), QImage::Format_ARGB32_Premultiplied);
QPainter p2(&img2);
QRectF rect2(0, 0, img2.width(), img2.height());
if (_pngExport.antialiasing)
p2.setRenderHint(QPainter::Antialiasing);
p2.fillRect(rect2, Qt::white);
plotGraphsPage(&p2, contentRect, 1);
QFileInfo fi(_pngExport.fileName);
img2.save(fi.absolutePath() + "/" + fi.baseName() + "-graphs."
+ fi.suffix());
}
}
void GUI::statistics()
{
QLocale l(QLocale::system());
@ -1097,12 +1154,13 @@ void GUI::statistics()
msgBox.exec();
}
void GUI::plot(QPrinter *printer)
void GUI::plotMainPage(QPainter *painter, const QRectF &rect, qreal ratio,
bool expand)
{
QLocale l(QLocale::system());
QPainter p(printer);
TrackInfo info;
qreal ih, gh, mh, ratio;
qreal ih, gh, mh;
int sc;
if (!_pathName.isNull() && _options.printName)
@ -1138,54 +1196,92 @@ void GUI::plot(QPrinter *printer)
if (movingTime() > 0 && _options.printMovingTime)
info.insert(tr("Moving time"), Format::timeSpan(movingTime()));
qreal fsr = 1085.0 / (qMax(printer->width(), printer->height())
/ (qreal)printer->resolution());
ratio = p.paintEngine()->paintDevice()->logicalDpiX() / fsr;
if (info.isEmpty()) {
ih = 0;
mh = 0;
} else {
ih = info.contentSize().height() * ratio;
mh = ih / 2;
info.plot(&p, QRectF(0, 0, printer->width(), ih), ratio);
info.plot(painter, QRectF(rect.x(), rect.y(), rect.width(), ih), ratio);
}
if (_graphTabWidget->isVisible() && !_options.separateGraphPage) {
qreal r = (((qreal)(printer)->width()) / (qreal)(printer->height()));
gh = (printer->width() > printer->height())
? 0.15 * r * (printer->height() - ih - 2*mh)
: 0.15 * (printer->height() - ih - 2*mh);
qreal r = rect.width() / rect.height();
gh = (rect.width() > rect.height())
? 0.15 * r * (rect.height() - ih - 2*mh)
: 0.15 * (rect.height() - ih - 2*mh);
if (gh < 150)
gh = 150;
sc = 2;
GraphTab *gt = static_cast<GraphTab*>(_graphTabWidget->currentWidget());
gt->plot(&p, QRectF(0, printer->height() - gh, printer->width(), gh),
ratio);
} else
gt->plot(painter, QRectF(rect.x(), rect.y() + rect.height() - gh,
rect.width(), gh), ratio);
} else {
gh = 0;
_mapView->plot(&p, QRectF(0, ih + mh, printer->width(), printer->height()
- (ih + 2*mh + gh)), ratio, _options.hiresPrint);
sc = 1;
}
if (_graphTabWidget->isVisible() && _options.separateGraphPage) {
printer->newPage();
MapView::PlotFlags flags = MapView::NoFlags;
if (_options.hiresPrint)
flags |= MapView::HiRes;
if (expand)
flags |= MapView::Expand;
int cnt = 0;
for (int i = 0; i < _tabs.size(); i++)
if (!_tabs.at(i)->isEmpty())
cnt++;
_mapView->plot(painter, QRectF(rect.x(), rect.y() + ih + mh, rect.width(),
rect.height() - (ih + sc*mh + gh)), ratio, flags);
}
qreal sp = ratio * 20;
gh = qMin((printer->height() - ((cnt - 1) * sp))/(qreal)cnt,
0.20 * printer->height());
void GUI::plotGraphsPage(QPainter *painter, const QRectF &rect, qreal ratio)
{
int cnt = 0;
for (int i = 0; i < _tabs.size(); i++)
if (!_tabs.at(i)->isEmpty())
cnt++;
qreal y = 0;
for (int i = 0; i < _tabs.size(); i++) {
if (!_tabs.at(i)->isEmpty()) {
_tabs.at(i)->plot(&p, QRectF(0, y, printer->width(), gh),
ratio);
y += gh + sp;
}
qreal sp = ratio * 20;
qreal gh = qMin((rect.height() - ((cnt - 1) * sp))/(qreal)cnt,
0.20 * rect.height());
qreal y = 0;
for (int i = 0; i < _tabs.size(); i++) {
if (!_tabs.at(i)->isEmpty()) {
_tabs.at(i)->plot(painter, QRectF(rect.x(), rect.y() + y,
rect.width(), gh), ratio);
y += gh + sp;
}
}
}
void GUI::reloadFile()
qreal GUI::graphPlotHeight(const QRectF &rect, qreal ratio)
{
int cnt = 0;
for (int i = 0; i < _tabs.size(); i++)
if (!_tabs.at(i)->isEmpty())
cnt++;
qreal sp = ratio * 20;
qreal gh = qMin((rect.height() - ((cnt - 1) * sp))/(qreal)cnt,
0.20 * rect.height());
return cnt * gh + (cnt - 1) * sp;
}
void GUI::plot(QPrinter *printer)
{
QPainter p(printer);
qreal fsr = 1085.0 / (qMax(printer->width(), printer->height())
/ (qreal)printer->resolution());
qreal ratio = p.paintEngine()->paintDevice()->logicalDpiX() / fsr;
QRectF rect(0, 0, printer->width(), printer->height());
plotMainPage(&p, rect, ratio);
if (!_tabs.isEmpty() && _options.separateGraphPage) {
printer->newPage();
plotGraphsPage(&p, rect, ratio);
}
}
void GUI::reloadFiles()
{
_trackCount = 0;
_routeCount = 0;
@ -1195,7 +1291,7 @@ void GUI::reloadFile()
_routeDistance = 0;
_time = 0;
_movingTime = 0;
_dateRange = DateRange(QDate(), QDate());
_dateRange = DateTimeRange(QDateTime(), QDateTime());
_pathName = QString();
for (int i = 0; i < _tabs.count(); i++)
@ -1229,7 +1325,7 @@ void GUI::closeFiles()
_routeDistance = 0;
_time = 0;
_movingTime = 0;
_dateRange = DateRange(QDate(), QDate());
_dateRange = DateTimeRange(QDateTime(), QDateTime());
_pathName = QString();
_sliderPos = 0;
@ -1539,8 +1635,7 @@ void GUI::setTimeType(TimeType type)
void GUI::setUnits(Units units)
{
_export.units = units;
_options.units = units;
_units = units;
_mapView->setUnits(units);
for (int i = 0; i <_tabs.count(); i++)
@ -1783,23 +1878,42 @@ void GUI::writeSettings()
_showTicksAction->isChecked());
settings.endGroup();
settings.beginGroup(EXPORT_SETTINGS_GROUP);
if (_export.orientation != PAPER_ORIENTATION_DEFAULT)
settings.setValue(PAPER_ORIENTATION_SETTING, _export.orientation);
if (_export.resolution != RESOLUTION_DEFAULT)
settings.setValue(RESOLUTION_SETTING, _export.resolution);
if (_export.paperSize != PAPER_SIZE_DEFAULT)
settings.setValue(PAPER_SIZE_SETTING, _export.paperSize);
if (_export.margins.left() != MARGIN_LEFT_DEFAULT)
settings.setValue(MARGIN_LEFT_SETTING, _export.margins.left());
if (_export.margins.top() != MARGIN_TOP_DEFAULT)
settings.setValue(MARGIN_TOP_SETTING, _export.margins.top());
if (_export.margins.right() != MARGIN_RIGHT_DEFAULT)
settings.setValue(MARGIN_RIGHT_SETTING, _export.margins.right());
if (_export.margins.bottom() != MARGIN_BOTTOM_DEFAULT)
settings.setValue(MARGIN_BOTTOM_SETTING, _export.margins.bottom());
if (_export.fileName != EXPORT_FILENAME_DEFAULT)
settings.setValue(EXPORT_FILENAME_SETTING, _export.fileName);
settings.beginGroup(PDF_EXPORT_SETTINGS_GROUP);
if (_pdfExport.orientation != PAPER_ORIENTATION_DEFAULT)
settings.setValue(PAPER_ORIENTATION_SETTING, _pdfExport.orientation);
if (_pdfExport.resolution != RESOLUTION_DEFAULT)
settings.setValue(RESOLUTION_SETTING, _pdfExport.resolution);
if (_pdfExport.paperSize != PAPER_SIZE_DEFAULT)
settings.setValue(PAPER_SIZE_SETTING, _pdfExport.paperSize);
if (_pdfExport.margins.left() != PDF_MARGIN_LEFT_DEFAULT)
settings.setValue(PDF_MARGIN_LEFT_SETTING, _pdfExport.margins.left());
if (_pdfExport.margins.top() != PDF_MARGIN_TOP_DEFAULT)
settings.setValue(PDF_MARGIN_TOP_SETTING, _pdfExport.margins.top());
if (_pdfExport.margins.right() != PDF_MARGIN_RIGHT_DEFAULT)
settings.setValue(PDF_MARGIN_RIGHT_SETTING, _pdfExport.margins.right());
if (_pdfExport.margins.bottom() != PDF_MARGIN_BOTTOM_DEFAULT)
settings.setValue(PDF_MARGIN_BOTTOM_SETTING, _pdfExport.margins.bottom());
if (_pdfExport.fileName != PDF_FILENAME_DEFAULT)
settings.setValue(PDF_FILENAME_SETTING, _pdfExport.fileName);
settings.endGroup();
settings.beginGroup(PNG_EXPORT_SETTINGS_GROUP);
if (_pngExport.size.width() != PNG_WIDTH_DEFAULT)
settings.setValue(PNG_WIDTH_SETTING, _pngExport.size.width());
if (_pngExport.size.height() != PNG_HEIGHT_DEFAULT)
settings.setValue(PNG_HEIGHT_SETTING, _pngExport.size.height());
if (_pngExport.margins.left() != PNG_MARGIN_LEFT_DEFAULT)
settings.setValue(PNG_MARGIN_LEFT_SETTING, _pngExport.margins.left());
if (_pngExport.margins.top() != PNG_MARGIN_TOP_DEFAULT)
settings.setValue(PNG_MARGIN_TOP_SETTING, _pngExport.margins.top());
if (_pngExport.margins.right() != PNG_MARGIN_RIGHT_DEFAULT)
settings.setValue(PNG_MARGIN_RIGHT_SETTING, _pngExport.margins.right());
if (_pngExport.margins.bottom() != PNG_MARGIN_BOTTOM_DEFAULT)
settings.setValue(PNG_MARGIN_BOTTOM_SETTING, _pngExport.margins.bottom());
if (_pngExport.antialiasing != PNG_ANTIALIASING_DEFAULT)
settings.setValue(PNG_ANTIALIASING_SETTING, _pngExport.antialiasing);
if (_pngExport.fileName != PNG_FILENAME_DEFAULT)
settings.setValue(PNG_FILENAME_SETTING, _pngExport.fileName);
settings.endGroup();
settings.beginGroup(OPTIONS_SETTINGS_GROUP);
@ -1867,6 +1981,13 @@ void GUI::writeSettings()
if (_options.showSecondarySpeed != SHOW_SECONDARY_SPEED_DEFAULT)
settings.setValue(SHOW_SECONDARY_SPEED_SETTING,
_options.showSecondarySpeed);
#ifdef ENABLE_TIMEZONES
if (_options.timeZone != TimeZoneInfo())
settings.setValue(TIME_ZONE_SETTING, QVariant::fromValue(
_options.timeZone));
#endif // ENABLE_TIMEZONES
if (_options.useSegments != USE_SEGMENTS_DEFAULT)
settings.setValue(USE_SEGMENTS_SETTING, _options.useSegments);
if (_options.poiRadius != POI_RADIUS_DEFAULT)
settings.setValue(POI_RADIUS_SETTING, _options.poiRadius);
if (_options.useOpenGL != USE_OPENGL_DEFAULT)
@ -2058,23 +2179,42 @@ void GUI::readSettings()
}
settings.endGroup();
settings.beginGroup(EXPORT_SETTINGS_GROUP);
_export.orientation = (QPrinter::Orientation) settings.value(
settings.beginGroup(PDF_EXPORT_SETTINGS_GROUP);
_pdfExport.orientation = (QPrinter::Orientation) settings.value(
PAPER_ORIENTATION_SETTING, PAPER_ORIENTATION_DEFAULT).toInt();
_export.resolution = settings.value(RESOLUTION_SETTING, RESOLUTION_DEFAULT)
_pdfExport.resolution = settings.value(RESOLUTION_SETTING,
RESOLUTION_DEFAULT).toInt();
_pdfExport.paperSize = (QPrinter::PaperSize) settings.value(
PAPER_SIZE_SETTING, PAPER_SIZE_DEFAULT).toInt();
qreal ml = settings.value(PDF_MARGIN_LEFT_SETTING, PDF_MARGIN_LEFT_DEFAULT)
.toReal();
qreal mt = settings.value(PDF_MARGIN_TOP_SETTING, PDF_MARGIN_TOP_DEFAULT)
.toReal();
qreal mr = settings.value(PDF_MARGIN_RIGHT_SETTING,
PDF_MARGIN_RIGHT_DEFAULT).toReal();
qreal mb = settings.value(PDF_MARGIN_BOTTOM_SETTING,
PDF_MARGIN_BOTTOM_DEFAULT).toReal();
_pdfExport.margins = MarginsF(ml, mt, mr, mb);
_pdfExport.fileName = settings.value(PDF_FILENAME_SETTING,
PDF_FILENAME_DEFAULT).toString();
settings.endGroup();
settings.beginGroup(PNG_EXPORT_SETTINGS_GROUP);
_pngExport.size = QSize(settings.value(PNG_WIDTH_SETTING, PNG_WIDTH_DEFAULT)
.toInt(), settings.value(PNG_HEIGHT_SETTING, PNG_HEIGHT_DEFAULT).toInt());
int mli = settings.value(PNG_MARGIN_LEFT_SETTING, PNG_MARGIN_LEFT_DEFAULT)
.toInt();
_export.paperSize = (QPrinter::PaperSize) settings.value(PAPER_SIZE_SETTING,
PAPER_SIZE_DEFAULT).toInt();
qreal ml = settings.value(MARGIN_LEFT_SETTING, MARGIN_LEFT_DEFAULT)
.toReal();
qreal mt = settings.value(MARGIN_TOP_SETTING, MARGIN_TOP_DEFAULT).toReal();
qreal mr = settings.value(MARGIN_RIGHT_SETTING, MARGIN_RIGHT_DEFAULT)
.toReal();
qreal mb = settings.value(MARGIN_BOTTOM_SETTING, MARGIN_BOTTOM_DEFAULT)
.toReal();
_export.margins = MarginsF(ml, mt, mr, mb);
_export.fileName = settings.value(EXPORT_FILENAME_SETTING,
EXPORT_FILENAME_DEFAULT).toString();
int mti = settings.value(PNG_MARGIN_TOP_SETTING, PNG_MARGIN_TOP_DEFAULT)
.toInt();
int mri = settings.value(PNG_MARGIN_RIGHT_SETTING, PNG_MARGIN_RIGHT_DEFAULT)
.toInt();
int mbi = settings.value(PNG_MARGIN_BOTTOM_SETTING, PNG_MARGIN_BOTTOM_DEFAULT)
.toInt();
_pngExport.margins = QMargins(mli, mti, mri, mbi);
_pngExport.antialiasing = settings.value(PNG_ANTIALIASING_SETTING,
PNG_ANTIALIASING_DEFAULT).toBool();
_pngExport.fileName = settings.value(PNG_FILENAME_SETTING,
PNG_FILENAME_DEFAULT).toString();
settings.endGroup();
settings.beginGroup(OPTIONS_SETTINGS_GROUP);
@ -2139,6 +2279,11 @@ void GUI::readSettings()
_options.showSecondarySpeed = settings.value(
SHOW_SECONDARY_SPEED_SETTING,
SHOW_SECONDARY_SPEED_DEFAULT).toBool();
#ifdef ENABLE_TIMEZONES
_options.timeZone = settings.value(TIME_ZONE_SETTING).value<TimeZoneInfo>();
#endif // ENABLE_TIMEZONES
_options.useSegments = settings.value(USE_SEGMENTS_SETTING,
USE_SEGMENTS_DEFAULT).toBool();
_options.automaticPause = settings.value(AUTOMATIC_PAUSE_SETTING,
AUTOMATIC_PAUSE_DEFAULT).toBool();
_options.pauseInterval = settings.value(PAUSE_INTERVAL_SETTING,
@ -2203,6 +2348,9 @@ void GUI::readSettings()
_options.hidpiMap ? devicePixelRatioF() : 1.0);
#endif // ENABLE_HIDPI
_mapView->setProjection(_options.projection);
#ifdef ENABLE_TIMEZONES
_mapView->setTimeZone(_options.timeZone.zone());
#endif // ENABLE_TIMEZONES
for (int i = 0; i < _tabs.count(); i++) {
_tabs.at(i)->setPalette(_options.palette);
@ -2227,6 +2375,7 @@ void GUI::readSettings()
Track::useDEM(_options.dataUseDEM);
Track::showSecondaryElevation(_options.showSecondaryElevation);
Track::showSecondarySpeed(_options.showSecondarySpeed);
Track::useSegments(_options.useSegments);
Route::useDEM(_options.dataUseDEM);
Route::showSecondaryElevation(_options.showSecondaryElevation);
Waypoint::useDEM(_options.dataUseDEM);

View File

@ -10,7 +10,8 @@
#include "units.h"
#include "timetype.h"
#include "format.h"
#include "exportdialog.h"
#include "pdfexportdialog.h"
#include "pngexportdialog.h"
#include "optionsdialog.h"
class QMenu;
@ -45,10 +46,11 @@ private slots:
void keys();
void paths();
void printFile();
void exportFile();
void exportPDFFile();
void exportPNGFile();
void openFile();
void closeAll();
void reloadFile();
void reloadFiles();
void statistics();
void openPOIFile();
void closePOIFiles();
@ -92,11 +94,15 @@ private slots:
void mapInitialized();
private:
typedef QPair<QDate, QDate> DateRange;
typedef QPair<QDateTime, QDateTime> DateTimeRange;
void loadPOIs();
void closeFiles();
void plot(QPrinter *printer);
void plotMainPage(QPainter *painter, const QRectF &rect, qreal ratio,
bool expand = false);
void plotGraphsPage(QPainter *painter, const QRectF &rect, qreal ratio);
qreal graphPlotHeight(const QRectF &rect, qreal ratio);
QAction *createPOIFileAction(const QString &fileName);
MapAction *createMapAction(Map *map);
@ -113,7 +119,6 @@ private:
bool openPOIFile(const QString &fileName);
bool loadFile(const QString &fileName);
bool loadMap(const QString &fileName);
void exportFile(const QString &fileName);
void updateStatusBarInfo();
void updateWindowTitle();
void updateNavigationActions();
@ -153,7 +158,8 @@ private:
QAction *_aboutAction;
QAction *_aboutQtAction;
QAction *_printFileAction;
QAction *_exportFileAction;
QAction *_exportPDFFileAction;
QAction *_exportPNGFileAction;
QAction *_openFileAction;
QAction *_closeFileAction;
QAction *_reloadFileAction;
@ -220,7 +226,7 @@ private:
int _trackCount, _routeCount, _areaCount, _waypointCount;
qreal _trackDistance, _routeDistance;
qreal _time, _movingTime;
DateRange _dateRange;
DateTimeRange _dateRange;
QString _pathName;
qreal _sliderPos;
@ -228,10 +234,13 @@ private:
QList<QByteArray> _windowStates;
int _frameStyle;
Export _export;
PDFExport _pdfExport;
PNGExport _pngExport;
Options _options;
QString _dataDir, _mapDir, _poiDir;
Units _units;
};
#endif // GUI_H

View File

@ -18,7 +18,8 @@
#define OPEN_SHORTCUT QKeySequence(QKeySequence::Open)
#define CLOSE_SHORTCUT QKeySequence(QKeySequence::Close)
#define RELOAD_SHORTCUT QKeySequence(QKeySequence::Refresh)
#define EXPORT_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_E)
#define PDF_EXPORT_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_E)
#define PNG_EXPORT_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_X)
#define SHOW_POI_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_P)
#define SHOW_MAP_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_M)
#define NEXT_MAP_SHORTCUT QKeySequence(QKeySequence::Forward)

View File

@ -59,8 +59,6 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
_poi = poi;
connect(_poi, SIGNAL(pointsChanged()), this, SLOT(updatePOI()));
_units = Metric;
_coordinatesFormat = DecimalDegrees;
_mapOpacity = 1.0;
_backgroundColor = Qt::white;
_markerColor = Qt::red;
@ -122,7 +120,6 @@ PathItem *MapView::addTrack(const Track &track)
ti->setColor(_palette.nextColor());
ti->setWidth(_trackWidth);
ti->setStyle(_trackStyle);
ti->setUnits(_units);
ti->setVisible(_showTracks);
ti->setDigitalZoom(_digitalZoom);
ti->setMarkerColor(_markerColor);
@ -149,8 +146,6 @@ PathItem *MapView::addRoute(const Route &route)
ri->setColor(_palette.nextColor());
ri->setWidth(_routeWidth);
ri->setStyle(_routeStyle);
ri->setUnits(_units);
ri->setCoordinatesFormat(_coordinatesFormat);
ri->setVisible(_showRoutes);
ri->showWaypoints(_showRouteWaypoints);
ri->showWaypointLabels(_showWaypointLabels);
@ -200,7 +195,6 @@ void MapView::addWaypoints(const QVector<Waypoint> &waypoints)
wi->setSize(_waypointSize);
wi->setColor(_waypointColor);
wi->showLabel(_showWaypointLabels);
wi->setToolTipFormat(_units, _coordinatesFormat);
wi->setVisible(_showWaypoints);
wi->setDigitalZoom(_digitalZoom);
_scene->addItem(wi);
@ -401,7 +395,6 @@ void MapView::addPOI(const QList<Waypoint> &waypoints)
pi->showLabel(_showPOILabels);
pi->setVisible(_showPOI);
pi->setDigitalZoom(_digitalZoom);
pi->setToolTipFormat(_units, _coordinatesFormat);
_scene->addItem(pi);
_pois.insert(SearchPointer<Waypoint>(&(pi->waypoint())), pi);
@ -410,42 +403,32 @@ void MapView::addPOI(const QList<Waypoint> &waypoints)
void MapView::setUnits(Units units)
{
if (_units == units)
return;
_units = units;
_mapScale->setUnits(_units);
WaypointItem::setUnits(units);
PathItem::setUnits(units);
for (int i = 0; i < _tracks.count(); i++)
_tracks[i]->setUnits(_units);
_tracks[i]->updateTicks();
for (int i = 0; i < _routes.count(); i++)
_routes[i]->setUnits(_units);
for (int i = 0; i < _waypoints.size(); i++)
_waypoints.at(i)->setToolTipFormat(_units, _coordinatesFormat);
_routes[i]->updateTicks();
for (POIHash::const_iterator it = _pois.constBegin();
it != _pois.constEnd(); it++)
it.value()->setToolTipFormat(_units, _coordinatesFormat);
_mapScale->setUnits(units);
}
void MapView::setCoordinatesFormat(CoordinatesFormat format)
{
if (_coordinatesFormat == format)
return;
WaypointItem::setCoordinatesFormat(format);
_coordinatesFormat = format;
_coordinates->setFormat(format);
}
_coordinates->setFormat(_coordinatesFormat);
for (int i = 0; i < _waypoints.count(); i++)
_waypoints.at(i)->setToolTipFormat(_units, _coordinatesFormat);
for (int i = 0; i < _routes.count(); i++)
_routes[i]->setCoordinatesFormat(_coordinatesFormat);
for (POIHash::const_iterator it = _pois.constBegin();
it != _pois.constEnd(); it++)
it.value()->setToolTipFormat(_units, _coordinatesFormat);
void MapView::setTimeZone(const QTimeZone &zone)
{
#ifdef ENABLE_TIMEZONES
WaypointItem::setTimeZone(zone);
PathItem::setTimeZone(zone);
#else // ENABLE_TIMEZONES
Q_UNUSED(zone);
#endif // ENABLE_TIMEZONES
}
void MapView::clearMapCache()
@ -548,7 +531,7 @@ void MapView::keyPressEvent(QKeyEvent *event)
}
void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
bool hires)
PlotFlags flags)
{
QRect orig, adj;
qreal ratio, diff, q;
@ -576,10 +559,18 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
diff = (orig.height() * ratio) - orig.width();
adj = orig.adjusted(-diff/2, 0, diff/2, 0);
}
q = (target.width() / scale) / adj.width();
// Expand the view if plotting into a bitmap
if (flags & Expand) {
qreal xdiff = (target.width() - adj.width()) / 2.0;
qreal ydiff = (target.height() - adj.height()) / 2.0;
adj.adjust(-xdiff, -ydiff, xdiff, ydiff);
q = 1.0;
} else
q = (target.width() / scale) / adj.width();
// Adjust the view for printing
if (hires) {
if (flags & HiRes) {
zoom = _map->zoom();
QRectF vr(mapToScene(orig).boundingRect());
origScene = vr.center();
@ -611,7 +602,7 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
render(painter, target, adj);
// Revert view changes to display mode
if (hires) {
if (flags & HiRes) {
_map->setZoom(zoom);
rescale();
centerOn(origScene);

View File

@ -5,6 +5,7 @@
#include <QVector>
#include <QHash>
#include <QList>
#include <QFlags>
#include "common/rectc.h"
#include "common/config.h"
#include "data/waypoint.h"
@ -31,12 +32,20 @@ class GraphItem;
class AreaItem;
class Area;
class GraphicsScene;
class QTimeZone;
class MapView : public QGraphicsView
{
Q_OBJECT
public:
enum Flag {
NoFlags = 0,
HiRes = 1,
Expand = 2
};
Q_DECLARE_FLAGS(PlotFlags, Flag)
MapView(Map *map, POI *poi, QWidget *parent = 0);
QList<PathItem *> loadData(const Data &data);
@ -45,7 +54,8 @@ public:
void setPOI(POI *poi);
void setMap(Map *map);
void plot(QPainter *painter, const QRectF &target, qreal scale, bool hires);
void plot(QPainter *painter, const QRectF &target, qreal scale,
PlotFlags flags);
void clear();
@ -83,6 +93,7 @@ public slots:
void showTicks(bool show);
void clearMapCache();
void setCoordinatesFormat(CoordinatesFormat format);
void setTimeZone(const QTimeZone &zone);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
void setProjection(int id);
@ -137,8 +148,6 @@ private:
POI *_poi;
Palette _palette;
Units _units;
CoordinatesFormat _coordinatesFormat;
qreal _mapOpacity;
Projection _projection;

View File

@ -16,15 +16,22 @@ public:
qreal right() const {return _right;}
qreal bottom() const {return _bottom;}
qreal &rleft() {return _left;}
qreal &rtop() {return _top;}
qreal &rright() {return _right;}
qreal &rbottom() {return _bottom;}
private:
qreal _left, _top, _right, _bottom;
};
inline MarginsF operator*(const MarginsF &margins, qreal factor)
{
return MarginsF(margins.left() * factor, margins.top() * factor,
margins.right() * factor, margins.bottom() * factor);
}
inline MarginsF operator/(const MarginsF &margins, qreal factor)
{
return MarginsF(margins.left() / factor, margins.top() / factor,
margins.right() / factor, margins.bottom() / factor);
}
#ifndef QT_NO_DEBUG
inline QDebug operator<<(QDebug dbg, const MarginsF &margins)
{

111
src/GUI/marginswidget.cpp Normal file
View File

@ -0,0 +1,111 @@
#include <QSpinBox>
#include <QGridLayout>
#include "units.h"
#include "marginswidget.h"
MarginsWidget::MarginsWidget(QWidget *parent) : QWidget(parent)
{
_top = new QSpinBox();
_bottom = new QSpinBox();
_left = new QSpinBox();
_right = new QSpinBox();
_top->setMaximumWidth(_top->sizeHint().width());
_bottom->setMaximumWidth(_bottom->sizeHint().width());
_left->setMaximumWidth(_left->sizeHint().width());
_right->setMaximumWidth(_right->sizeHint().width());
QGridLayout *layout = new QGridLayout();
layout->addWidget(_top, 0, 0, 1, 2, Qt::AlignCenter);
layout->addWidget(_left, 1, 0, 1, 1, Qt::AlignRight);
layout->addWidget(_right, 1, 1, 1, 1, Qt::AlignLeft);
layout->addWidget(_bottom, 2, 0, 1, 2, Qt::AlignCenter);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setLayout(layout);
}
void MarginsWidget::setValue(const QMargins &value)
{
_top->setValue(value.top());
_bottom->setValue(value.bottom());
_left->setValue(value.left());
_right->setValue(value.right());
}
void MarginsWidget::setUnits(const QString &units)
{
_top->setSuffix(UNIT_SPACE + units);
_bottom->setSuffix(UNIT_SPACE + units);
_left->setSuffix(UNIT_SPACE + units);
_right->setSuffix(UNIT_SPACE + units);
_top->setMaximumWidth(_top->sizeHint().width());
_bottom->setMaximumWidth(_bottom->sizeHint().width());
_left->setMaximumWidth(_left->sizeHint().width());
_right->setMaximumWidth(_right->sizeHint().width());
}
QMargins MarginsWidget::value() const
{
return QMargins(_left->value(), _top->value(), _right->value(),
_bottom->value());
}
MarginsFWidget::MarginsFWidget(QWidget *parent) : QWidget(parent)
{
_top = new QDoubleSpinBox();
_bottom = new QDoubleSpinBox();
_left = new QDoubleSpinBox();
_right = new QDoubleSpinBox();
_top->setMaximumWidth(_top->sizeHint().width());
_bottom->setMaximumWidth(_bottom->sizeHint().width());
_left->setMaximumWidth(_left->sizeHint().width());
_right->setMaximumWidth(_right->sizeHint().width());
QGridLayout *layout = new QGridLayout();
layout->addWidget(_top, 0, 0, 1, 2, Qt::AlignCenter);
layout->addWidget(_left, 1, 0, 1, 1, Qt::AlignRight);
layout->addWidget(_right, 1, 1, 1, 1, Qt::AlignLeft);
layout->addWidget(_bottom, 2, 0, 1, 2, Qt::AlignCenter);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setLayout(layout);
}
void MarginsFWidget::setValue(const MarginsF &value)
{
_top->setValue(value.top());
_bottom->setValue(value.bottom());
_left->setValue(value.left());
_right->setValue(value.right());
}
void MarginsFWidget::setUnits(const QString &units)
{
_top->setSuffix(UNIT_SPACE + units);
_bottom->setSuffix(UNIT_SPACE + units);
_left->setSuffix(UNIT_SPACE + units);
_right->setSuffix(UNIT_SPACE + units);
_top->setMaximumWidth(_top->sizeHint().width());
_bottom->setMaximumWidth(_bottom->sizeHint().width());
_left->setMaximumWidth(_left->sizeHint().width());
_right->setMaximumWidth(_right->sizeHint().width());
}
void MarginsFWidget::setSingleStep(qreal step)
{
_top->setSingleStep(step);
_bottom->setSingleStep(step);
_left->setSingleStep(step);
_right->setSingleStep(step);
}
MarginsF MarginsFWidget::value() const
{
return MarginsF(_left->value(), _top->value(), _right->value(),
_bottom->value());
}

48
src/GUI/marginswidget.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef MARGINSWIDGET_H
#define MARGINSWIDGET_H
#include <QWidget>
#include <QMargins>
#include "margins.h"
class QSpinBox;
class QDoubleSpinBox;
class MarginsWidget : public QWidget
{
Q_OBJECT
public:
MarginsWidget(QWidget *parent = 0);
QMargins value() const;
void setValue(const QMargins &value);
void setUnits(const QString &units);
private:
QSpinBox *_top;
QSpinBox *_bottom;
QSpinBox *_left;
QSpinBox *_right;
};
class MarginsFWidget : public QWidget
{
Q_OBJECT
public:
MarginsFWidget(QWidget *parent = 0);
MarginsF value() const;
void setValue(const MarginsF &value);
void setUnits(const QString &units);
void setSingleStep(qreal step);
private:
QDoubleSpinBox *_top;
QDoubleSpinBox *_bottom;
QDoubleSpinBox *_left;
QDoubleSpinBox *_right;
};
#endif // MARGINSWIDGET_H

View File

@ -56,12 +56,12 @@ QWidget *OptionsDialog::createMapPage()
+ projections.at(i).value();
_projection->addItem(text, QVariant(projections.at(i).key()));
}
_projection->setCurrentIndex(_projection->findData(_options->projection));
_projection->setCurrentIndex(_projection->findData(_options.projection));
#ifdef ENABLE_HIDPI
_hidpi = new QRadioButton(tr("High-resolution"));
_lodpi = new QRadioButton(tr("Standard"));
if (_options->hidpiMap)
if (_options.hidpiMap)
_hidpi->setChecked(true);
else
_lodpi->setChecked(true);
@ -112,10 +112,10 @@ QWidget *OptionsDialog::createAppearancePage()
{
// Tracks
_trackWidth = new QSpinBox();
_trackWidth->setValue(_options->trackWidth);
_trackWidth->setValue(_options.trackWidth);
_trackWidth->setMinimum(1);
_trackStyle = new StyleComboBox();
_trackStyle->setValue(_options->trackStyle);
_trackStyle->setValue(_options.trackStyle);
QFormLayout *trackLayout = new QFormLayout();
#ifdef Q_OS_MAC
trackLayout->addRow(tr("Track width:"), _trackWidth);
@ -129,10 +129,10 @@ QWidget *OptionsDialog::createAppearancePage()
// Routes
_routeWidth = new QSpinBox();
_routeWidth->setValue(_options->routeWidth);
_routeWidth->setValue(_options.routeWidth);
_routeWidth->setMinimum(1);
_routeStyle = new StyleComboBox();
_routeStyle->setValue(_options->routeStyle);
_routeStyle->setValue(_options.routeStyle);
QFormLayout *routeLayout = new QFormLayout();
#ifdef Q_OS_MAC
routeLayout->addRow(tr("Route width:"), _routeWidth);
@ -146,11 +146,11 @@ QWidget *OptionsDialog::createAppearancePage()
// Areas
_areaWidth = new QSpinBox();
_areaWidth->setValue(_options->areaWidth);
_areaWidth->setValue(_options.areaWidth);
_areaStyle = new StyleComboBox();
_areaStyle->setValue(_options->areaStyle);
_areaStyle->setValue(_options.areaStyle);
_areaOpacity = new PercentSlider();
_areaOpacity->setValue(_options->areaOpacity);
_areaOpacity->setValue(_options.areaOpacity);
QFormLayout *areaLayout = new QFormLayout();
#ifdef Q_OS_MAC
areaLayout->addRow(tr("Area border width:"), _areaWidth);
@ -166,18 +166,15 @@ QWidget *OptionsDialog::createAppearancePage()
// Palette & antialiasing
_baseColor = new ColorBox();
_baseColor->setColor(_options->palette.color());
_colorOffset = new QDoubleSpinBox();
_colorOffset->setMinimum(0);
_colorOffset->setMaximum(1.0);
_colorOffset->setSingleStep(0.01);
_colorOffset->setValue(_options->palette.shift());
_baseColor->setColor(_options.palette.color());
_colorOffset = new PercentSlider();
_colorOffset->setValue(_options.palette.shift() * 100);
QFormLayout *paletteLayout = new QFormLayout();
paletteLayout->addRow(tr("Base color:"), _baseColor);
paletteLayout->addRow(tr("Palette shift:"), _colorOffset);
_pathAA = new QCheckBox(tr("Use anti-aliasing"));
_pathAA->setChecked(_options->pathAntiAliasing);
_pathAA->setChecked(_options.pathAntiAliasing);
QFormLayout *pathAALayout = new QFormLayout();
pathAALayout->addWidget(_pathAA);
@ -204,9 +201,9 @@ QWidget *OptionsDialog::createAppearancePage()
// Waypoints
_waypointSize = new QSpinBox();
_waypointSize->setMinimum(1);
_waypointSize->setValue(_options->waypointSize);
_waypointSize->setValue(_options.waypointSize);
_waypointColor = new ColorBox();
_waypointColor->setColor(_options->waypointColor);
_waypointColor->setColor(_options.waypointColor);
QFormLayout *waypointLayout = new QFormLayout();
#ifdef Q_OS_MAC
waypointLayout->addRow(tr("Waypoint color:"), _waypointColor);
@ -220,9 +217,9 @@ QWidget *OptionsDialog::createAppearancePage()
_poiSize = new QSpinBox();
_poiSize->setMinimum(1);
_poiSize->setValue(_options->poiSize);
_poiSize->setValue(_options.poiSize);
_poiColor = new ColorBox();
_poiColor->setColor(_options->poiColor);
_poiColor->setColor(_options.poiColor);
QFormLayout *poiLayout = new QFormLayout();
#ifdef Q_OS_MAC
poiLayout->addRow(tr("POI color:"), _poiColor);
@ -250,9 +247,9 @@ QWidget *OptionsDialog::createAppearancePage()
// Graphs
_sliderColor = new ColorBox();
_sliderColor->setColor(_options->sliderColor);
_sliderColor->setColor(_options.sliderColor);
_graphWidth = new QSpinBox();
_graphWidth->setValue(_options->graphWidth);
_graphWidth->setValue(_options.graphWidth);
_graphWidth->setMinimum(1);
QFormLayout *graphLayout = new QFormLayout();
@ -260,7 +257,7 @@ QWidget *OptionsDialog::createAppearancePage()
graphLayout->addRow(tr("Slider color:"), _sliderColor);
_graphAA = new QCheckBox(tr("Use anti-aliasing"));
_graphAA->setChecked(_options->graphAntiAliasing);
_graphAA->setChecked(_options.graphAntiAliasing);
QFormLayout *graphAALayout = new QFormLayout();
graphAALayout->addWidget(_graphAA);
@ -274,9 +271,9 @@ QWidget *OptionsDialog::createAppearancePage()
// Map
_mapOpacity = new PercentSlider();
_mapOpacity->setValue(_options->mapOpacity);
_mapOpacity->setValue(_options.mapOpacity);
_backgroundColor = new ColorBox();
_backgroundColor->setColor(_options->backgroundColor);
_backgroundColor->setColor(_options.backgroundColor);
_backgroundColor->enableAlphaChannel(false);
QFormLayout *mapLayout = new QFormLayout();
@ -304,19 +301,19 @@ QWidget *OptionsDialog::createDataPage()
QString filterToolTip = tr("Moving average window size");
_elevationFilter = new OddSpinBox();
_elevationFilter->setValue(_options->elevationFilter);
_elevationFilter->setValue(_options.elevationFilter);
_elevationFilter->setToolTip(filterToolTip);
_speedFilter = new OddSpinBox();
_speedFilter->setValue(_options->speedFilter);
_speedFilter->setValue(_options.speedFilter);
_speedFilter->setToolTip(filterToolTip);
_heartRateFilter = new OddSpinBox();
_heartRateFilter->setValue(_options->heartRateFilter);
_heartRateFilter->setValue(_options.heartRateFilter);
_heartRateFilter->setToolTip(filterToolTip);
_cadenceFilter = new OddSpinBox();
_cadenceFilter->setValue(_options->cadenceFilter);
_cadenceFilter->setValue(_options.cadenceFilter);
_cadenceFilter->setToolTip(filterToolTip);
_powerFilter = new OddSpinBox();
_powerFilter->setValue(_options->powerFilter);
_powerFilter->setValue(_options.powerFilter);
_powerFilter->setToolTip(filterToolTip);
QFormLayout *smoothLayout = new QFormLayout();
@ -331,7 +328,7 @@ QWidget *OptionsDialog::createDataPage()
#endif // Q_OS_MAC
_outlierEliminate = new QCheckBox(tr("Eliminate GPS outliers"));
_outlierEliminate->setChecked(_options->outlierEliminate);
_outlierEliminate->setChecked(_options.outlierEliminate);
QFormLayout *outlierLayout = new QFormLayout();
outlierLayout->addWidget(_outlierEliminate);
@ -352,7 +349,7 @@ QWidget *OptionsDialog::createDataPage()
_automaticPause = new QRadioButton(tr("Automatic"));
_manualPause = new QRadioButton(tr("Custom"));
if (_options->automaticPause)
if (_options.automaticPause)
_automaticPause->setChecked(true);
else
_manualPause->setChecked(true);
@ -362,20 +359,20 @@ QWidget *OptionsDialog::createDataPage()
_pauseSpeed->setSingleStep(0.1);
_pauseSpeed->setMinimum(0.1);
_pauseSpeed->setEnabled(_manualPause->isChecked());
if (_options->units == Imperial) {
_pauseSpeed->setValue(_options->pauseSpeed * MS2MIH);
if (_units == Imperial) {
_pauseSpeed->setValue(_options.pauseSpeed * MS2MIH);
_pauseSpeed->setSuffix(UNIT_SPACE + tr("mi/h"));
} else if (_options->units == Nautical) {
_pauseSpeed->setValue(_options->pauseSpeed * MS2KN);
} else if (_units == Nautical) {
_pauseSpeed->setValue(_options.pauseSpeed * MS2KN);
_pauseSpeed->setSuffix(UNIT_SPACE + tr("kn"));
} else {
_pauseSpeed->setValue(_options->pauseSpeed * MS2KMH);
_pauseSpeed->setValue(_options.pauseSpeed * MS2KMH);
_pauseSpeed->setSuffix(UNIT_SPACE + tr("km/h"));
}
_pauseInterval = new QSpinBox();
_pauseInterval->setMinimum(1);
_pauseInterval->setSuffix(UNIT_SPACE + tr("s"));
_pauseInterval->setValue(_options->pauseInterval);
_pauseInterval->setValue(_options.pauseInterval);
_pauseInterval->setEnabled(_manualPause->isChecked());
connect(_automaticPause, SIGNAL(toggled(bool)), this,
@ -403,21 +400,47 @@ QWidget *OptionsDialog::createDataPage()
_computedSpeed = new QRadioButton(tr("Computed from distance/time"));
_reportedSpeed = new QRadioButton(tr("Recorded by device"));
if (_options->useReportedSpeed)
if (_options.useReportedSpeed)
_reportedSpeed->setChecked(true);
else
_computedSpeed->setChecked(true);
_showSecondarySpeed = new QCheckBox(tr("Show secondary speed"));
_showSecondarySpeed->setChecked(_options->showSecondarySpeed);
_showSecondarySpeed->setChecked(_options.showSecondarySpeed);
_dataGPSElevation = new QRadioButton(tr("GPS data"));
_dataDEMElevation = new QRadioButton(tr("DEM data"));
if (_options->dataUseDEM)
if (_options.dataUseDEM)
_dataDEMElevation->setChecked(true);
else
_dataGPSElevation->setChecked(true);
_showSecondaryElevation = new QCheckBox(tr("Show secondary elevation"));
_showSecondaryElevation->setChecked(_options->showSecondaryElevation);
_showSecondaryElevation->setChecked(_options.showSecondaryElevation);
#ifdef ENABLE_TIMEZONES
_utcZone = new QRadioButton(tr("UTC"));
_systemZone = new QRadioButton(tr("System"));
_customZone = new QRadioButton(tr("Custom"));
if (_options.timeZone.type() == TimeZoneInfo::UTC)
_utcZone->setChecked(true);
else if (_options.timeZone.type() == TimeZoneInfo::System)
_systemZone->setChecked(true);
else
_customZone->setChecked(true);
_timeZone = new QComboBox();
_timeZone->setEnabled(_customZone->isChecked());
QList<QByteArray> zones = QTimeZone::availableTimeZoneIds();
for (int i = 0; i < zones.size(); i++)
_timeZone->addItem(zones.at(i));
_timeZone->setCurrentText(_options.timeZone.customZone().id());
connect(_customZone, SIGNAL(toggled(bool)), _timeZone,
SLOT(setEnabled(bool)));
QHBoxLayout *customZoneLayout = new QHBoxLayout();
customZoneLayout->addSpacing(20);
customZoneLayout->addWidget(_timeZone);
#endif // ENABLE_TIMEZONES
_useSegments = new QCheckBox(tr("Use segments"));
_useSegments->setChecked(_options.useSegments);
QWidget *sourceTab = new QWidget();
QVBoxLayout *sourceTabLayout = new QVBoxLayout();
@ -439,14 +462,34 @@ QWidget *OptionsDialog::createDataPage()
elevationOptions->addWidget(_dataDEMElevation);
elevationOptions->addWidget(_showSecondaryElevation);
#ifdef ENABLE_TIMEZONES
QButtonGroup *timeZoneGroup = new QButtonGroup(this);
timeZoneGroup->addButton(_utcZone);
timeZoneGroup->addButton(_systemZone);
timeZoneGroup->addButton(_customZone);
QVBoxLayout *zoneOptions = new QVBoxLayout();
zoneOptions->addWidget(_utcZone);
zoneOptions->addWidget(_systemZone);
zoneOptions->addWidget(_customZone);
zoneOptions->addItem(customZoneLayout);
#endif // ENABLE_TIMEZONES
QFormLayout *formLayout = new QFormLayout();
formLayout->addRow(tr("Speed:"), speedOptions);
formLayout->addRow(tr("Elevation:"), elevationOptions);
#ifdef ENABLE_TIMEZONES
formLayout->addRow(tr("Time zone:"), zoneOptions);
#endif // ENABLE_TIMEZONES
formLayout->addRow(_useSegments);
sourceTabLayout->addLayout(formLayout);
#else // Q_OS_MAC
QFormLayout *speedLayout = new QFormLayout();
QFormLayout *elevationLayout = new QFormLayout();
#ifdef ENABLE_TIMEZONES
QFormLayout *timeZoneLayout = new QFormLayout();
#endif // ENABLE_TIMEZONES
QFormLayout *segmentsLayout = new QFormLayout();
speedLayout->addWidget(_computedSpeed);
speedLayout->addWidget(_reportedSpeed);
@ -462,8 +505,24 @@ QWidget *OptionsDialog::createDataPage()
QGroupBox *elevationBox = new QGroupBox(tr("Elevation"));
elevationBox->setLayout(elevationLayout);
#ifdef ENABLE_TIMEZONES
timeZoneLayout->addWidget(_utcZone);
timeZoneLayout->addWidget(_systemZone);
timeZoneLayout->addWidget(_customZone);
timeZoneLayout->addItem(customZoneLayout);
QGroupBox *timeZoneBox = new QGroupBox(tr("Time zone"));
timeZoneBox->setLayout(timeZoneLayout);
#endif // ENABLE_TIMEZONES
segmentsLayout->addWidget(_useSegments);
sourceTabLayout->addWidget(speedBox);
sourceTabLayout->addWidget(elevationBox);
#ifdef ENABLE_TIMEZONES
sourceTabLayout->addWidget(timeZoneBox);
#endif // ENABLE_TIMEZONES
sourceTabLayout->addLayout(segmentsLayout);
#endif // Q_OS_MAC
sourceTabLayout->addStretch();
sourceTab->setLayout(sourceTabLayout);
@ -482,14 +541,14 @@ QWidget *OptionsDialog::createPOIPage()
_poiRadius = new QDoubleSpinBox();
_poiRadius->setSingleStep(1);
_poiRadius->setDecimals(1);
if (_options->units == Imperial) {
_poiRadius->setValue(_options->poiRadius / MIINM);
if (_units == Imperial) {
_poiRadius->setValue(_options.poiRadius / MIINM);
_poiRadius->setSuffix(UNIT_SPACE + tr("mi"));
} else if (_options->units == Nautical) {
_poiRadius->setValue(_options->poiRadius / NMIINM);
} else if (_units == Nautical) {
_poiRadius->setValue(_options.poiRadius / NMIINM);
_poiRadius->setSuffix(UNIT_SPACE + tr("nmi"));
} else {
_poiRadius->setValue(_options->poiRadius / KMINM);
_poiRadius->setValue(_options.poiRadius / KMINM);
_poiRadius->setSuffix(UNIT_SPACE + tr("km"));
}
@ -509,7 +568,7 @@ QWidget *OptionsDialog::createExportPage()
{
_wysiwyg = new QRadioButton(tr("WYSIWYG"));
_hires = new QRadioButton(tr("High-Resolution"));
if (_options->hiresPrint)
if (_options.hiresPrint)
_hires->setChecked(true);
else
_wysiwyg->setChecked(true);
@ -538,17 +597,17 @@ QWidget *OptionsDialog::createExportPage()
_name = new QCheckBox(tr("Name"));
_name->setChecked(_options->printName);
_name->setChecked(_options.printName);
_date = new QCheckBox(tr("Date"));
_date->setChecked(_options->printDate);
_date->setChecked(_options.printDate);
_distance = new QCheckBox(tr("Distance"));
_distance->setChecked(_options->printDistance);
_distance->setChecked(_options.printDistance);
_time = new QCheckBox(tr("Time"));
_time->setChecked(_options->printTime);
_time->setChecked(_options.printTime);
_movingTime = new QCheckBox(tr("Moving time"));
_movingTime->setChecked(_options->printMovingTime);
_movingTime->setChecked(_options.printMovingTime);
_itemCount = new QCheckBox(tr("Item count (>1)"));
_itemCount->setChecked(_options->printItemCount);
_itemCount->setChecked(_options.printItemCount);
QFormLayout *headerTabLayout = new QFormLayout();
headerTabLayout->addWidget(_name);
@ -563,7 +622,7 @@ QWidget *OptionsDialog::createExportPage()
_separateGraphPage = new QCheckBox(tr("Separate graph page"));
_separateGraphPage->setChecked(_options->separateGraphPage);
_separateGraphPage->setChecked(_options.separateGraphPage);
QFormLayout *graphTabLayout = new QFormLayout();
graphTabLayout->addWidget(_separateGraphPage);
@ -582,23 +641,23 @@ QWidget *OptionsDialog::createExportPage()
QWidget *OptionsDialog::createSystemPage()
{
_useOpenGL = new QCheckBox(tr("Use OpenGL"));
_useOpenGL->setChecked(_options->useOpenGL);
_useOpenGL->setChecked(_options.useOpenGL);
#ifdef ENABLE_HTTP2
_enableHTTP2 = new QCheckBox(tr("Enable HTTP/2"));
_enableHTTP2->setChecked(_options->enableHTTP2);
_enableHTTP2->setChecked(_options.enableHTTP2);
#endif // ENABLE_HTTP2
_pixmapCache = new QSpinBox();
_pixmapCache->setMinimum(16);
_pixmapCache->setMaximum(1024);
_pixmapCache->setSuffix(UNIT_SPACE + tr("MB"));
_pixmapCache->setValue(_options->pixmapCache);
_pixmapCache->setValue(_options.pixmapCache);
_connectionTimeout = new QSpinBox();
_connectionTimeout->setMinimum(30);
_connectionTimeout->setMaximum(120);
_connectionTimeout->setSuffix(UNIT_SPACE + tr("s"));
_connectionTimeout->setValue(_options->connectionTimeout);
_connectionTimeout->setValue(_options.connectionTimeout);
QFormLayout *formLayout = new QFormLayout();
formLayout->addRow(tr("Image cache size:"), _pixmapCache);
@ -623,8 +682,8 @@ QWidget *OptionsDialog::createSystemPage()
return systemPage;
}
OptionsDialog::OptionsDialog(Options *options, QWidget *parent)
: QDialog(parent), _options(options)
OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent)
: QDialog(parent), _options(options), _units(units)
{
QStackedWidget *pages = new QStackedWidget();
pages->addWidget(createAppearancePage());
@ -676,74 +735,82 @@ OptionsDialog::OptionsDialog(Options *options, QWidget *parent)
void OptionsDialog::accept()
{
_options->palette.setColor(_baseColor->color());
_options->palette.setShift(_colorOffset->value());
_options->mapOpacity = _mapOpacity->value();
_options->backgroundColor = _backgroundColor->color();
_options->trackWidth = _trackWidth->value();
_options->trackStyle = (Qt::PenStyle) _trackStyle->itemData(
_options.palette.setColor(_baseColor->color());
_options.palette.setShift(_colorOffset->value() / 100.0);
_options.mapOpacity = _mapOpacity->value();
_options.backgroundColor = _backgroundColor->color();
_options.trackWidth = _trackWidth->value();
_options.trackStyle = (Qt::PenStyle) _trackStyle->itemData(
_trackStyle->currentIndex()).toInt();
_options->routeWidth = _routeWidth->value();
_options->routeStyle = (Qt::PenStyle) _routeStyle->itemData(
_options.routeWidth = _routeWidth->value();
_options.routeStyle = (Qt::PenStyle) _routeStyle->itemData(
_routeStyle->currentIndex()).toInt();
_options->pathAntiAliasing = _pathAA->isChecked();
_options->areaWidth = _areaWidth->value();
_options->areaStyle = (Qt::PenStyle) _areaStyle->itemData(
_options.pathAntiAliasing = _pathAA->isChecked();
_options.areaWidth = _areaWidth->value();
_options.areaStyle = (Qt::PenStyle) _areaStyle->itemData(
_areaStyle->currentIndex()).toInt();
_options->areaOpacity = _areaOpacity->value();
_options->waypointSize = _waypointSize->value();
_options->waypointColor = _waypointColor->color();
_options->poiSize = _poiSize->value();
_options->poiColor = _poiColor->color();
_options->graphWidth = _graphWidth->value();
_options->sliderColor = _sliderColor->color();
_options->graphAntiAliasing = _graphAA->isChecked();
_options.areaOpacity = _areaOpacity->value();
_options.waypointSize = _waypointSize->value();
_options.waypointColor = _waypointColor->color();
_options.poiSize = _poiSize->value();
_options.poiColor = _poiColor->color();
_options.graphWidth = _graphWidth->value();
_options.sliderColor = _sliderColor->color();
_options.graphAntiAliasing = _graphAA->isChecked();
_options->projection = _projection->itemData(_projection->currentIndex())
_options.projection = _projection->itemData(_projection->currentIndex())
.toInt();
#ifdef ENABLE_HIDPI
_options->hidpiMap = _hidpi->isChecked();
_options.hidpiMap = _hidpi->isChecked();
#endif // ENABLE_HIDPI
_options->elevationFilter = _elevationFilter->value();
_options->speedFilter = _speedFilter->value();
_options->heartRateFilter = _heartRateFilter->value();
_options->cadenceFilter = _cadenceFilter->value();
_options->powerFilter = _powerFilter->value();
_options->outlierEliminate = _outlierEliminate->isChecked();
_options->automaticPause = _automaticPause->isChecked();
qreal pauseSpeed = (_options->units == Imperial)
? _pauseSpeed->value() / MS2MIH : (_options->units == Nautical)
_options.elevationFilter = _elevationFilter->value();
_options.speedFilter = _speedFilter->value();
_options.heartRateFilter = _heartRateFilter->value();
_options.cadenceFilter = _cadenceFilter->value();
_options.powerFilter = _powerFilter->value();
_options.outlierEliminate = _outlierEliminate->isChecked();
_options.automaticPause = _automaticPause->isChecked();
qreal pauseSpeed = (_units == Imperial)
? _pauseSpeed->value() / MS2MIH : (_units == Nautical)
? _pauseSpeed->value() / MS2KN : _pauseSpeed->value() / MS2KMH;
if (qAbs(pauseSpeed - _options->pauseSpeed) > 0.01)
_options->pauseSpeed = pauseSpeed;
_options->pauseInterval = _pauseInterval->value();
_options->useReportedSpeed = _reportedSpeed->isChecked();
_options->dataUseDEM = _dataDEMElevation->isChecked();
_options->showSecondaryElevation = _showSecondaryElevation->isChecked();
_options->showSecondarySpeed = _showSecondarySpeed->isChecked();
if (qAbs(pauseSpeed - _options.pauseSpeed) > 0.01)
_options.pauseSpeed = pauseSpeed;
_options.pauseInterval = _pauseInterval->value();
_options.useReportedSpeed = _reportedSpeed->isChecked();
_options.dataUseDEM = _dataDEMElevation->isChecked();
_options.showSecondaryElevation = _showSecondaryElevation->isChecked();
_options.showSecondarySpeed = _showSecondarySpeed->isChecked();
#ifdef ENABLE_TIMEZONES
_options.timeZone.setType(_utcZone->isChecked()
? TimeZoneInfo::UTC : _systemZone->isChecked()
? TimeZoneInfo::System : TimeZoneInfo::Custom);
_options.timeZone.setCustomZone(QTimeZone(_timeZone->currentText()
.toLatin1()));
#endif // ENABLE_TIMEZONES
_options.useSegments = _useSegments->isChecked();
qreal poiRadius = (_options->units == Imperial)
? _poiRadius->value() * MIINM : (_options->units == Nautical)
qreal poiRadius = (_units == Imperial)
? _poiRadius->value() * MIINM : (_units == Nautical)
? _poiRadius->value() * NMIINM : _poiRadius->value() * KMINM;
if (qAbs(poiRadius - _options->poiRadius) > 0.01)
_options->poiRadius = poiRadius;
if (qAbs(poiRadius - _options.poiRadius) > 0.01)
_options.poiRadius = poiRadius;
_options->useOpenGL = _useOpenGL->isChecked();
_options.useOpenGL = _useOpenGL->isChecked();
#ifdef ENABLE_HTTP2
_options->enableHTTP2 = _enableHTTP2->isChecked();
_options.enableHTTP2 = _enableHTTP2->isChecked();
#endif // ENABLE_HTTP2
_options->pixmapCache = _pixmapCache->value();
_options->connectionTimeout = _connectionTimeout->value();
_options.pixmapCache = _pixmapCache->value();
_options.connectionTimeout = _connectionTimeout->value();
_options->hiresPrint = _hires->isChecked();
_options->printName = _name->isChecked();
_options->printDate = _date->isChecked();
_options->printDistance = _distance->isChecked();
_options->printTime = _time->isChecked();
_options->printMovingTime = _movingTime->isChecked();
_options->printItemCount = _itemCount->isChecked();
_options->separateGraphPage = _separateGraphPage->isChecked();
_options.hiresPrint = _hires->isChecked();
_options.printName = _name->isChecked();
_options.printDate = _date->isChecked();
_options.printDistance = _distance->isChecked();
_options.printTime = _time->isChecked();
_options.printMovingTime = _movingTime->isChecked();
_options.printItemCount = _itemCount->isChecked();
_options.separateGraphPage = _separateGraphPage->isChecked();
QDialog::accept();
}

View File

@ -5,6 +5,9 @@
#include "common/config.h"
#include "palette.h"
#include "units.h"
#ifdef ENABLE_TIMEZONES
#include "timezoneinfo.h"
#endif // ENABLE_TIMEZONES
class ColorBox;
class StyleComboBox;
@ -17,6 +20,7 @@ class QRadioButton;
class PercentSlider;
class LimitedComboBox;
struct Options {
// Appearance
Palette palette;
@ -56,6 +60,10 @@ struct Options {
bool dataUseDEM;
bool showSecondaryElevation;
bool showSecondarySpeed;
#ifdef ENABLE_TIMEZONES
TimeZoneInfo timeZone;
#endif // ENABLE_TIMEZONES
bool useSegments;
// POI
int poiRadius;
// System
@ -74,8 +82,6 @@ struct Options {
bool printMovingTime;
bool printItemCount;
bool separateGraphPage;
Units units;
};
class OptionsDialog : public QDialog
@ -86,7 +92,7 @@ public slots:
void accept();
public:
OptionsDialog(Options *options, QWidget *parent = 0);
OptionsDialog(Options &options, Units units, QWidget *parent = 0);
private slots:
void automaticPauseDetectionSet(bool set);
@ -99,11 +105,12 @@ private:
QWidget *createSystemPage();
QWidget *createExportPage();
Options *_options;
Options &_options;
Units _units;
// Appearance
ColorBox *_baseColor;
QDoubleSpinBox *_colorOffset;
PercentSlider *_colorOffset;
PercentSlider *_mapOpacity;
ColorBox *_backgroundColor;
QSpinBox *_trackWidth;
@ -134,7 +141,6 @@ private:
OddSpinBox *_cadenceFilter;
OddSpinBox *_powerFilter;
QCheckBox *_outlierEliminate;
QRadioButton *_automaticPause;
QRadioButton *_manualPause;
QDoubleSpinBox *_pauseSpeed;
@ -145,6 +151,13 @@ private:
QRadioButton *_dataDEMElevation;
QCheckBox *_showSecondaryElevation;
QCheckBox *_showSecondarySpeed;
#ifdef ENABLE_TIMEZONES
QRadioButton *_utcZone;
QRadioButton *_systemZone;
QRadioButton *_customZone;
QComboBox *_timeZone;
#endif // ENABLE_TIMEZONES
QCheckBox *_useSegments;
// POI
QDoubleSpinBox *_poiRadius;
// System

View File

@ -21,12 +21,16 @@ static inline unsigned segments(qreal distance)
return ceil(distance / GEOGRAPHICAL_MILE);
}
Units PathItem::_units = Metric;
#ifdef ENABLE_TIMEZONES
QTimeZone PathItem::_timeZone = QTimeZone::utc();
#endif // ENABLE_TIMEZONES
PathItem::PathItem(const Path &path, Map *map, QGraphicsItem *parent)
: GraphicsItem(parent), _path(path), _map(map)
{
Q_ASSERT(_path.isValid());
_units = Metric;
_digitalZoom = 0;
_width = 3;
QBrush brush(Qt::SolidPattern);
@ -352,16 +356,6 @@ void PathItem::showTicks(bool show)
updateTicks();
}
void PathItem::setUnits(Units units)
{
if (_units == units)
return;
prepareGeometryChange();
_units = units;
updateTicks();
}
void PathItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event);

View File

@ -1,8 +1,12 @@
#ifndef PATHITEM_H
#define PATHITEM_H
#include "common/config.h"
#include <QGraphicsObject>
#include <QPen>
#ifdef ENABLE_TIMEZONES
#include <QTimeZone>
#endif // ENABLE_TIMEZONES
#include "data/path.h"
#include "markeritem.h"
#include "units.h"
@ -28,7 +32,6 @@ public:
void setMap(Map *map);
void setUnits(Units units);
void setColor(const QColor &color);
void setWidth(qreal width);
void setStyle(Qt::PenStyle style);
@ -37,6 +40,13 @@ public:
void showMarker(bool show);
void showTicks(bool show);
void updateTicks();
static void setUnits(Units units) {_units = units;}
#ifdef ENABLE_TIMEZONES
static void setTimeZone(const QTimeZone &zone) {_timeZone = zone;}
#endif // ENABLE_TIMEZONES
public slots:
void moveMarker(qreal distance);
void hover(bool hover);
@ -49,7 +59,10 @@ protected:
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
Units _units;
static Units _units;
#ifdef ENABLE_TIMEZONES
static QTimeZone _timeZone;
#endif // ENABLE_TIMEZONES
private:
const PathSegment *segment(qreal x) const;
@ -60,7 +73,6 @@ private:
qreal xInM() const;
unsigned tickSize() const;
void updateTicks();
Path _path;
Map *_map;

View File

@ -1,30 +1,27 @@
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QFormLayout>
#include <QGridLayout>
#include <QDialogButtonBox>
#include <QGroupBox>
#include <QComboBox>
#include <QRadioButton>
#include <QPushButton>
#include <QFileInfo>
#include <QMessageBox>
#include <QTabWidget>
#include <QDoubleSpinBox>
#include "marginswidget.h"
#include "fileselectwidget.h"
#include "units.h"
#include "exportdialog.h"
#include "pdfexportdialog.h"
ExportDialog::ExportDialog(Export *exp, QWidget *parent)
: QDialog(parent), _export(exp)
PDFExportDialog::PDFExportDialog(PDFExport &exp, Units units, QWidget *parent)
: QDialog(parent), _export(exp), _units(units)
{
int index;
_fileSelect = new FileSelectWidget();
_fileSelect->setFilter(tr("PDF files") + " (*.pdf);;" + tr("All files")
+ " (*)");
_fileSelect->setFile(_export->fileName);
_fileSelect->setFile(_export.fileName);
_paperSize = new QComboBox();
_paperSize->addItem("A2", QPrinter::A2);
@ -39,14 +36,14 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
_paperSize->addItem("Tabloid", QPrinter::Tabloid);
_paperSize->addItem("Legal", QPrinter::Legal);
_paperSize->addItem("Letter", QPrinter::Letter);
if ((index = _paperSize->findData(_export->paperSize)) >= 0)
if ((index = _paperSize->findData(_export.paperSize)) >= 0)
_paperSize->setCurrentIndex(index);
_resolution = new QComboBox();
_resolution->addItem("150 DPI", 150);
_resolution->addItem("300 DPI", 300);
_resolution->addItem("600 DPI", 600);
if ((index = _resolution->findData(_export->resolution)) >= 0)
if ((index = _resolution->findData(_export.resolution)) >= 0)
_resolution->setCurrentIndex(index);
_portrait = new QRadioButton(tr("Portrait"));
@ -54,41 +51,16 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
QHBoxLayout *orientationLayout = new QHBoxLayout();
orientationLayout->addWidget(_portrait);
orientationLayout->addWidget(_landscape);
if (_export->orientation == QPrinter::Portrait)
if (_export.orientation == QPrinter::Portrait)
_portrait->setChecked(true);
else
_landscape->setChecked(true);
_topMargin = new QDoubleSpinBox();
_bottomMargin = new QDoubleSpinBox();
_leftMargin = new QDoubleSpinBox();
_rightMargin = new QDoubleSpinBox();
QString us = (_export->units == Metric) ? tr("mm") : tr("in");
_topMargin->setSuffix(UNIT_SPACE + us);
_bottomMargin->setSuffix(UNIT_SPACE + us);
_leftMargin->setSuffix(UNIT_SPACE + us);
_rightMargin->setSuffix(UNIT_SPACE + us);
if (_export->units == Metric) {
_topMargin->setValue(_export->margins.top());
_bottomMargin->setValue(_export->margins.bottom());
_leftMargin->setValue(_export->margins.left());
_rightMargin->setValue(_export->margins.right());
} else {
_topMargin->setValue(_export->margins.top() * MM2IN);
_bottomMargin->setValue(_export->margins.bottom() * MM2IN);
_leftMargin->setValue(_export->margins.left() * MM2IN);
_rightMargin->setValue(_export->margins.right() * MM2IN);
_topMargin->setSingleStep(0.1);
_bottomMargin->setSingleStep(0.1);
_leftMargin->setSingleStep(0.1);
_rightMargin->setSingleStep(0.1);
}
QGridLayout *marginsLayout = new QGridLayout();
marginsLayout->addWidget(_topMargin, 0, 0, 1, 2, Qt::AlignCenter);
marginsLayout->addWidget(_leftMargin, 1, 0, 1, 1, Qt::AlignRight);
marginsLayout->addWidget(_rightMargin, 1, 1, 1, 1, Qt::AlignLeft);
marginsLayout->addWidget(_bottomMargin, 2, 0, 1, 2, Qt::AlignCenter);
_margins = new MarginsFWidget();
_margins->setUnits((units == Metric) ? tr("cm") : tr("in"));
_margins->setSingleStep(0.1);
_margins->setValue((units == Metric)
? _export.margins * MM2CM : _export.margins * MM2IN);
#ifndef Q_OS_MAC
QGroupBox *pageSetupBox = new QGroupBox(tr("Page Setup"));
@ -97,7 +69,7 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
pageSetupLayout->addRow(tr("Page size:"), _paperSize);
pageSetupLayout->addRow(tr("Resolution:"), _resolution);
pageSetupLayout->addRow(tr("Orientation:"), orientationLayout);
pageSetupLayout->addRow(tr("Margins:"), marginsLayout);
pageSetupLayout->addRow(tr("Margins:"), _margins);
#ifdef Q_OS_MAC
QFrame *line = new QFrame();
line->setFrameShape(QFrame::HLine);
@ -111,7 +83,7 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
#ifndef Q_OS_MAC
QGroupBox *outputFileBox = new QGroupBox(tr("Output file"));
QHBoxLayout *outputFileLayout = new QHBoxLayout();
QVBoxLayout *outputFileLayout = new QVBoxLayout();
outputFileLayout->addWidget(_fileSelect);
outputFileBox->setLayout(outputFileLayout);
#endif // Q_OS_MAC
@ -136,41 +108,13 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
}
bool ExportDialog::checkFile()
void PDFExportDialog::accept()
{
if (_fileSelect->file().isEmpty()) {
QMessageBox::warning(this, tr("Error"), tr("No output file selected."));
return false;
}
QFile file(_fileSelect->file());
QFileInfo fi(file);
bool exists = fi.exists();
bool opened = false;
if (exists && fi.isDir()) {
QMessageBox::warning(this, tr("Error"), tr("%1 is a directory.")
.arg(file.fileName()));
return false;
} else if ((exists && !fi.isWritable())
|| !(opened = file.open(QFile::Append))) {
QMessageBox::warning(this, tr("Error"), tr("%1 is not writable.")
.arg(file.fileName()));
return false;
}
if (opened) {
file.close();
if (!exists)
file.remove();
}
return true;
}
void ExportDialog::accept()
{
if (!checkFile())
QString error;
if (!_fileSelect->checkFile(error)) {
QMessageBox::warning(this, tr("Error"), error);
return;
}
QPrinter::Orientation orientation = _portrait->isChecked()
? QPrinter::Portrait : QPrinter::Landscape;
@ -178,17 +122,12 @@ void ExportDialog::accept()
(_paperSize->itemData(_paperSize->currentIndex()).toInt());
int resolution = _resolution->itemData(_resolution->currentIndex()).toInt();
_export->fileName = _fileSelect->file();
_export->paperSize = paperSize;
_export->resolution = resolution;
_export->orientation = orientation;
if (_export->units == Imperial)
_export->margins = MarginsF(_leftMargin->value() / MM2IN,
_topMargin->value() / MM2IN, _rightMargin->value() / MM2IN,
_bottomMargin->value() / MM2IN);
else
_export->margins = MarginsF(_leftMargin->value(), _topMargin->value(),
_rightMargin->value(), _bottomMargin->value());
_export.fileName = _fileSelect->file();
_export.paperSize = paperSize;
_export.resolution = resolution;
_export.orientation = orientation;
_export.margins = (_units == Imperial)
? _margins->value() / MM2IN : _margins->value() / MM2CM;
QDialog::accept();
}

View File

@ -1,5 +1,5 @@
#ifndef EXPORTDIALOG_H
#define EXPORTDIALOG_H
#ifndef PDFEXPORTDIALOG_H
#define PDFEXPORTDIALOG_H
#include <QDialog>
#include <QPrinter>
@ -9,42 +9,37 @@
class QComboBox;
class QRadioButton;
class FileSelectWidget;
class QDoubleSpinBox;
class MarginsFWidget;
struct Export {
struct PDFExport
{
QString fileName;
QPrinter::PaperSize paperSize;
QPrinter::Orientation orientation;
MarginsF margins;
int resolution;
Units units;
};
class ExportDialog : public QDialog
class PDFExportDialog : public QDialog
{
Q_OBJECT
public:
ExportDialog(Export *exp, QWidget *parent = 0);
PDFExportDialog(PDFExport &exp, Units units, QWidget *parent = 0);
public slots:
void accept();
private:
bool checkFile();
Export *_export;
PDFExport &_export;
Units _units;
FileSelectWidget *_fileSelect;
QComboBox *_paperSize;
QComboBox *_resolution;
QRadioButton *_portrait;
QRadioButton *_landscape;
QDoubleSpinBox *_topMargin;
QDoubleSpinBox *_bottomMargin;
QDoubleSpinBox *_leftMargin;
QDoubleSpinBox *_rightMargin;
MarginsFWidget *_margins;
};
#endif // EXPORTDIALOG_H
#endif // PDFEXPORTDIALOG_H

101
src/GUI/pngexportdialog.cpp Normal file
View File

@ -0,0 +1,101 @@
#include <QVBoxLayout>
#include <QFormLayout>
#include <QDialogButtonBox>
#include <QGroupBox>
#include <QSpinBox>
#include <QMessageBox>
#include <QTabWidget>
#include <QCheckBox>
#include "units.h"
#include "fileselectwidget.h"
#include "marginswidget.h"
#include "pngexportdialog.h"
PNGExportDialog::PNGExportDialog(PNGExport &exp, QWidget *parent)
: QDialog(parent), _export(exp)
{
_fileSelect = new FileSelectWidget();
_fileSelect->setFilter(tr("PNG files") + " (*.png);;" + tr("All files")
+ " (*)");
_fileSelect->setFile(_export.fileName);
_width = new QSpinBox();
_width->setMinimum(256);
_width->setMaximum(4096);
_width->setValue(_export.size.width());
_width->setSuffix(UNIT_SPACE + tr("px"));
_height = new QSpinBox();
_height->setMinimum(256);
_height->setMaximum(4096);
_height->setValue(_export.size.height());
_height->setSuffix(UNIT_SPACE + tr("px"));
_margins = new MarginsWidget();
_margins->setValue(_export.margins);
_margins->setUnits(tr("px"));
_antialiasing = new QCheckBox(tr("Use anti-aliasing"));
_antialiasing->setChecked(_export.antialiasing);
#ifndef Q_OS_MAC
QGroupBox *pageSetupBox = new QGroupBox(tr("Image Setup"));
#endif // Q_OS_MAC
QFormLayout *pageSetupLayout = new QFormLayout;
pageSetupLayout->addRow(tr("Image width:"), _width);
pageSetupLayout->addRow(tr("Image height:"), _height);
pageSetupLayout->addRow(tr("Margins:"), _margins);
pageSetupLayout->addWidget(_antialiasing);
#ifdef Q_OS_MAC
QFrame *line = new QFrame();
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
pageSetupLayout->addRow(line);
pageSetupLayout->addRow(tr("File:"), _fileSelect);
pageSetupLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
#else // Q_OS_MAC
pageSetupBox->setLayout(pageSetupLayout);
#endif // Q_OS_MAC
#ifndef Q_OS_MAC
QGroupBox *outputFileBox = new QGroupBox(tr("Output file"));
QVBoxLayout *outputFileLayout = new QVBoxLayout();
outputFileLayout->addWidget(_fileSelect);
outputFileBox->setLayout(outputFileLayout);
#endif // Q_OS_MAC
QDialogButtonBox *buttonBox = new QDialogButtonBox();
buttonBox->addButton(tr("Export"), QDialogButtonBox::AcceptRole);
buttonBox->addButton(QDialogButtonBox::Cancel);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QVBoxLayout *layout = new QVBoxLayout;
#ifdef Q_OS_MAC
layout->addLayout(pageSetupLayout);
#else // Q_OS_MAC
layout->addWidget(pageSetupBox);
layout->addWidget(outputFileBox);
#endif // Q_OS_MAC
layout->addWidget(buttonBox);
setLayout(layout);
setWindowTitle(tr("Export to PNG"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
}
void PNGExportDialog::accept()
{
QString error;
if (!_fileSelect->checkFile(error)) {
QMessageBox::warning(this, tr("Error"), error);
return;
}
_export.fileName = _fileSelect->file();
_export.size = QSize(_width->value(), _height->value());
_export.margins = _margins->value();
_export.antialiasing = _antialiasing->isChecked();
QDialog::accept();
}

41
src/GUI/pngexportdialog.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef PNGEXPORTDIALOG_H
#define PNGEXPORTDIALOG_H
#include <QDialog>
#include <QMargins>
#include "margins.h"
class FileSelectWidget;
class MarginsWidget;
class QSpinBox;
class QCheckBox;
struct PNGExport
{
QString fileName;
QSize size;
QMargins margins;
bool antialiasing;
};
class PNGExportDialog : public QDialog
{
Q_OBJECT
public:
PNGExportDialog(PNGExport &exp, QWidget *parent = 0);
public slots:
void accept();
private:
PNGExport &_export;
FileSelectWidget *_fileSelect;
QSpinBox *_width;
QSpinBox *_height;
MarginsWidget *_margins;
QCheckBox *_antialiasing;
};
#endif // PNGEXPORTDIALOG_H

View File

@ -47,7 +47,6 @@ RouteItem::RouteItem(const Route &route, Map *map, QGraphicsItem *parent)
_desc = route.description();
_comment = route.comment();
_links = route.links();
_coordinatesFormat = DecimalDegrees;
}
void RouteItem::setMap(Map *map)
@ -58,28 +57,6 @@ void RouteItem::setMap(Map *map)
PathItem::setMap(map);
}
void RouteItem::setUnits(Units u)
{
if (_units == u)
return;
for (int i = 0; i < _waypoints.count(); i++)
_waypoints[i]->setToolTipFormat(u, _coordinatesFormat);
PathItem::setUnits(u);
}
void RouteItem::setCoordinatesFormat(CoordinatesFormat format)
{
if (_coordinatesFormat == format)
return;
_coordinatesFormat = format;
for (int i = 0; i < _waypoints.count(); i++)
_waypoints[i]->setToolTipFormat(_units, _coordinatesFormat);
}
void RouteItem::showWaypoints(bool show)
{
for (int i = 0; i < _waypoints.count(); i++)

View File

@ -19,8 +19,6 @@ public:
void setMap(Map *map);
void setUnits(Units u);
void setCoordinatesFormat(CoordinatesFormat format);
void showWaypoints(bool show);
void showWaypointLabels(bool show);
@ -31,7 +29,6 @@ private:
QString _desc;
QString _comment;
QVector<Link> _links;
CoordinatesFormat _coordinatesFormat;
QVector<WaypointItem*> _waypoints;
};

View File

@ -66,26 +66,45 @@
#define SHOW_WAYPOINT_LABELS_SETTING "waypointLabels"
#define SHOW_WAYPOINT_LABELS_DEFAULT true
#define EXPORT_SETTINGS_GROUP "Export"
#define PDF_EXPORT_SETTINGS_GROUP "Export"
#define PAPER_ORIENTATION_SETTING "orientation"
#define PAPER_ORIENTATION_DEFAULT QPrinter::Portrait
#define PAPER_SIZE_SETTING "size"
#define PAPER_SIZE_DEFAULT (IMPERIAL_UNITS() ? QPrinter::Letter \
: QPrinter::A4)
#define MARGIN_LEFT_SETTING "marginLeft"
#define MARGIN_LEFT_DEFAULT 5 /* mm */
#define MARGIN_TOP_SETTING "marginTop"
#define MARGIN_TOP_DEFAULT 5 /* mm */
#define MARGIN_RIGHT_SETTING "marginRight"
#define MARGIN_RIGHT_DEFAULT 5 /* mm */
#define MARGIN_BOTTOM_SETTING "marginBottom"
#define MARGIN_BOTTOM_DEFAULT 5 /* mm */
#define EXPORT_FILENAME_SETTING "fileName"
#define EXPORT_FILENAME_DEFAULT QString("%1/export.pdf"). \
#define PDF_MARGIN_LEFT_SETTING "marginLeft"
#define PDF_MARGIN_LEFT_DEFAULT 5 /* mm */
#define PDF_MARGIN_TOP_SETTING "marginTop"
#define PDF_MARGIN_TOP_DEFAULT 5 /* mm */
#define PDF_MARGIN_RIGHT_SETTING "marginRight"
#define PDF_MARGIN_RIGHT_DEFAULT 5 /* mm */
#define PDF_MARGIN_BOTTOM_SETTING "marginBottom"
#define PDF_MARGIN_BOTTOM_DEFAULT 5 /* mm */
#define PDF_FILENAME_SETTING "fileName"
#define PDF_FILENAME_DEFAULT QString("%1/export.pdf"). \
arg(QDir::currentPath())
#define RESOLUTION_SETTING "resolution"
#define RESOLUTION_DEFAULT 600
#define PNG_EXPORT_SETTINGS_GROUP "PNGExport"
#define PNG_WIDTH_SETTING "width"
#define PNG_WIDTH_DEFAULT 600
#define PNG_HEIGHT_SETTING "height"
#define PNG_HEIGHT_DEFAULT 800
#define PNG_MARGIN_LEFT_SETTING "marginLeft"
#define PNG_MARGIN_LEFT_DEFAULT 5 /* px */
#define PNG_MARGIN_TOP_SETTING "marginTop"
#define PNG_MARGIN_TOP_DEFAULT 5 /* px */
#define PNG_MARGIN_RIGHT_SETTING "marginRight"
#define PNG_MARGIN_RIGHT_DEFAULT 5 /* px */
#define PNG_MARGIN_BOTTOM_SETTING "marginBottom"
#define PNG_MARGIN_BOTTOM_DEFAULT 5 /* px */
#define PNG_ANTIALIASING_SETTING "antialiasing"
#define PNG_ANTIALIASING_DEFAULT true
#define PNG_FILENAME_SETTING "fileName"
#define PNG_FILENAME_DEFAULT QString("%1/export.png"). \
arg(QDir::currentPath())
#define OPTIONS_SETTINGS_GROUP "Options"
#define PALETTE_COLOR_SETTING "paletteColor"
#define PALETTE_COLOR_DEFAULT QColor(Qt::blue)
@ -122,7 +141,7 @@
#define PATH_AA_SETTING "pathAntiAliasing"
#define PATH_AA_DEFAULT true
#define GRAPH_AA_SETTING "graphAntiAliasing"
#define GRAPH_AA_DEFAULT false
#define GRAPH_AA_DEFAULT true
#define ELEVATION_FILTER_SETTING "elevationFilter"
#define ELEVATION_FILTER_DEFAULT 3
#define SPEED_FILTER_SETTING "speedFilter"
@ -149,6 +168,9 @@
#define SHOW_SECONDARY_ELEVATION_DEFAULT false
#define SHOW_SECONDARY_SPEED_SETTING "showSecondarySpeed"
#define SHOW_SECONDARY_SPEED_DEFAULT false
#define TIME_ZONE_SETTING "timeZone"
#define USE_SEGMENTS_SETTING "useSegments"
#define USE_SEGMENTS_DEFAULT true
#define POI_RADIUS_SETTING "poiRadius"
#define POI_RADIUS_DEFAULT (int)(IMPERIAL_UNITS() ? MIINM : KMINM)
#define USE_OPENGL_SETTING "useOpenGL"

69
src/GUI/timezoneinfo.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef TIMEZONEINFO_H
#define TIMEZONEINFO_H
#include <QTimeZone>
#include <QDataStream>
class TimeZoneInfo
{
public:
enum Type {
UTC,
System,
Custom
};
TimeZoneInfo() : _type(UTC), _customZone(QTimeZone::systemTimeZone()) {}
Type type() const {return _type;}
const QTimeZone &customZone() const {return _customZone;}
QTimeZone zone() const
{
if (_type == UTC)
return QTimeZone::utc();
else if (_type == System)
return QTimeZone::systemTimeZone();
else
return _customZone;
}
void setType(Type type) {_type = type;}
void setCustomZone(const QTimeZone &zone) {_customZone = zone;}
bool operator==(const TimeZoneInfo &other) const
{
if (_type == UTC || _type == System)
return _type == other._type;
else
return (other._type == Custom && _customZone == other._customZone);
}
bool operator!=(const TimeZoneInfo &other) {return !(*this == other);}
private:
friend QDataStream& operator<<(QDataStream &out, const TimeZoneInfo &info);
friend QDataStream& operator>>(QDataStream &in, TimeZoneInfo &info);
Type _type;
QTimeZone _customZone;
};
Q_DECLARE_METATYPE(TimeZoneInfo)
inline QDataStream &operator<<(QDataStream &out, const TimeZoneInfo &info)
{
out << static_cast<int>(info._type) << info._customZone;
return out;
}
inline QDataStream &operator>>(QDataStream &in, TimeZoneInfo &info)
{
int t;
in >> t;
info._type = static_cast<TimeZoneInfo::Type>(t);
in >> info._customZone;
return in;
}
#endif // TIMEZONEINFO_H

View File

@ -22,7 +22,13 @@ QString TrackItem::info() const
if (_movingTime > 0)
tt.insert(tr("Moving time"), Format::timeSpan(_movingTime));
if (!_date.isNull())
tt.insert(tr("Date"), _date.toString(Qt::SystemLocaleShortDate));
tt.insert(tr("Date"),
#ifdef ENABLE_TIMEZONES
_date.toTimeZone(_timeZone)
#else // ENABLE_TIMEZONES
_date
#endif // ENABLE_TIMEZONES
.toString(Qt::SystemLocaleShortDate));
if (!_links.isEmpty()) {
QString links;
for (int i = 0; i < _links.size(); i++) {

View File

@ -16,6 +16,7 @@ enum Units {
#define MS2KN 1.943844490000 // m/s -> kn
#define FT2MI 0.000189393939 // ft -> mi
#define MM2IN 0.039370100000 // mm -> in
#define MM2CM 0.100000000000 // mm -> cm
#define H2S 0.000277777778 // h -> s
#define MIN2S 0.016666666667 // min -> s

View File

@ -13,6 +13,13 @@
#define FS(size) \
((int)((qreal)size * 1.41))
Units WaypointItem::_units = Metric;
CoordinatesFormat WaypointItem::_format = DecimalDegrees;
#ifdef ENABLE_TIMEZONES
QTimeZone WaypointItem::_timeZone = QTimeZone::utc();
#endif // ENABLE_TIMEZONES
QString WaypointItem::info() const
{
ToolTip tt;
@ -30,7 +37,12 @@ QString WaypointItem::info() const
}
if (_waypoint.timestamp().isValid())
tt.insert(qApp->translate("WaypointItem", "Date"),
_waypoint.timestamp().toString(Qt::SystemLocaleShortDate));
#ifdef ENABLE_TIMEZONES
_waypoint.timestamp().toTimeZone(_timeZone)
#else // ENABLE_TIMEZONES
_waypoint.timestamp()
#endif // ENABLE_TIMEZONES
.toString(Qt::SystemLocaleShortDate));
if (!_waypoint.description().isEmpty())
tt.insert(qApp->translate("WaypointItem", "Description"),
_waypoint.description());
@ -78,9 +90,6 @@ WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map,
_font.setPixelSize(FS(_size));
_font.setFamily(FONT_FAMILY);
_units = Metric;
_format = DecimalDegrees;
updateCache();
setPos(map->ll2xy(waypoint.coordinates()));
@ -151,12 +160,6 @@ void WaypointItem::setColor(const QColor &color)
update();
}
void WaypointItem::setToolTipFormat(Units units, CoordinatesFormat format)
{
_units = units;
_format = format;
}
void WaypointItem::showLabel(bool show)
{
if (_showLabel == show)

View File

@ -1,9 +1,13 @@
#ifndef WAYPOINTITEM_H
#define WAYPOINTITEM_H
#include "common/config.h"
#include <cmath>
#include <QGraphicsItem>
#include <QFont>
#ifdef ENABLE_TIMEZONES
#include <QTimeZone>
#endif // ENABLE_TIMEZONES
#include "data/waypoint.h"
#include "map/map.h"
#include "units.h"
@ -23,7 +27,6 @@ public:
void setColor(const QColor &color);
void showLabel(bool show);
void setDigitalZoom(int zoom) {setScale(pow(2, -zoom));}
void setToolTipFormat(Units units, CoordinatesFormat format);
QPainterPath shape() const {return _shape;}
QRectF boundingRect() const {return _shape.boundingRect();}
@ -32,6 +35,13 @@ public:
QString info() const;
static void setUnits(Units units) {_units = units;}
static void setCoordinatesFormat(CoordinatesFormat format)
{_format = format;}
#ifdef ENABLE_TIMEZONES
static void setTimeZone(const QTimeZone &zone) {_timeZone = zone;}
#endif // ENABLE_TIMEZONES
protected:
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
@ -48,8 +58,11 @@ private:
QFont _font;
QRect _labelBB;
Units _units;
CoordinatesFormat _format;
static Units _units;
static CoordinatesFormat _format;
#ifdef ENABLE_TIMEZONES
static QTimeZone _timeZone;
#endif // ENABLE_TIMEZONES
};
#endif // WAYPOINTITEM_H

View File

@ -18,4 +18,8 @@
#define ENABLE_GEOJSON
#endif // QT >= 5.0
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
#define ENABLE_TIMEZONES
#endif // QT >= 5.5
#endif /* CONFIG_H */

View File

@ -15,4 +15,15 @@ inline double toWGS24(qint32 v)
return toWGS32(LS(v, 8));
}
inline quint8 vs(const quint8 b0)
{
static const quint8 sizes[] = {4, 1, 2, 1, 3, 1, 2, 1};
return sizes[b0 & 0x07];
}
inline quint8 bs(const quint8 val)
{
return (val + 7) >> 3;
}
#endif // GARMIN_H

View File

@ -15,7 +15,8 @@ public:
bool isNull() const
{return _tl.isNull() && _br.isNull();}
bool isValid() const
{return (_tl.isValid() && _br.isValid() && _tl != _br);}
{return (_tl.isValid() && _br.isValid()
&& _tl.lat() > _br.lat() && _tl.lon() < _br.lon());}
Coordinates topLeft() const {return _tl;}
Coordinates bottomRight() const {return _br;}

View File

@ -1,7 +1,6 @@
#ifndef RTREE_H
#define RTREE_H
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <QtGlobal>
@ -387,10 +386,10 @@ RTREE_TEMPLATE
void RTREE_QUAL::Insert(const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId)
{
#ifdef _DEBUG
#ifndef QT_NO_DEBUG
for (int index=0; index<NUMDIMS; ++index)
Q_ASSERT(a_min[index] <= a_max[index]);
#endif //_DEBUG
#endif // QT_NO_DEBUG
Rect rect;
@ -407,10 +406,10 @@ RTREE_TEMPLATE
void RTREE_QUAL::Remove(const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId)
{
#ifdef _DEBUG
#ifndef QT_NO_DEBUG
for (int index=0; index<NUMDIMS; ++index)
Q_ASSERT(a_min[index] <= a_max[index]);
#endif //_DEBUG
#endif // QT_NO_DEBUG
Rect rect;
@ -427,10 +426,10 @@ RTREE_TEMPLATE
int RTREE_QUAL::Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS],
bool a_resultCallback(DATATYPE a_data, void* a_context), void* a_context) const
{
#ifdef _DEBUG
#ifndef QT_NO_DEBUG
for (int index=0; index<NUMDIMS; ++index)
Q_ASSERT(a_min[index] <= a_max[index]);
#endif //_DEBUG
#endif // QT_NO_DEBUG
Rect rect;
@ -636,10 +635,10 @@ bool RTREE_QUAL::InsertRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root,
{
Q_ASSERT(a_rect && a_root);
Q_ASSERT(a_level >= 0 && a_level <= (*a_root)->m_level);
#ifdef _DEBUG
#ifndef QT_NO_DEBUG
for (int index=0; index < NUMDIMS; ++index)
Q_ASSERT(a_rect->m_min[index] <= a_rect->m_max[index]);
#endif //_DEBUG
#endif // QT_NO_DEBUG
Node* newRoot;
Node* newNode;

View File

@ -33,18 +33,18 @@ public:
return false;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
if (_be)
val = data;
else {
for (size_t i = 0; i < sizeof(T); i++)
*((char *)&val + i) = *((char*)&data + sizeof(T) - 1 - i);
}
if (_be)
val = data;
else {
for (size_t i = 0; i < sizeof(T); i++)
*((char *)&val + i) = *((char*)&data + sizeof(T) - 1 - i);
}
#else
if (_be) {
for (size_t i = 0; i < sizeof(T); i++)
*((char *)&val + i) = *((char*)&data + sizeof(T) - 1 - i);
} else
val = data;
if (_be) {
for (size_t i = 0; i < sizeof(T); i++)
*((char *)&val + i) = *((char*)&data + sizeof(T) - 1 - i);
} else
val = data;
#endif
return true;

View File

@ -51,13 +51,13 @@ class FITParser::CTX {
public:
CTX(QFile *file, QVector<Waypoint> &waypoints)
: file(file), waypoints(waypoints), len(0), endian(0), timestamp(0),
lastWrite(0), ratio(NAN) {}
ratio(NAN) {}
QFile *file;
QVector<Waypoint> &waypoints;
quint32 len;
quint8 endian;
quint32 timestamp, lastWrite;
quint32 timestamp;
MessageDefinition defs[16];
qreal ratio;
Trackpoint trackpoint;
@ -361,14 +361,12 @@ bool FITParser::parseData(CTX &ctx, const MessageDefinition *def)
ctx.ratio = ((qreal)front / (qreal)rear);
}
} else if (def->globalId == RECORD_MESSAGE) {
if (ctx.timestamp > ctx.lastWrite
&& ctx.trackpoint.coordinates().isValid()) {
if (ctx.trackpoint.coordinates().isValid()) {
ctx.trackpoint.setTimestamp(QDateTime::fromTime_t(ctx.timestamp
+ 631065600));
ctx.trackpoint.setRatio(ctx.ratio);
ctx.segment.append(ctx.trackpoint);
ctx.trackpoint = Trackpoint();
ctx.lastWrite = ctx.timestamp;
}
} else if (def->globalId == COURSE_POINT)
if (waypoint.coordinates().isValid())

View File

@ -585,7 +585,9 @@ void KMLParser::document(QList<TrackData> &tracks, QList<Area> &areas,
QVector<Waypoint> &waypoints)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("Placemark"))
if (_reader.name() == QLatin1String("Document"))
document(tracks, areas, waypoints);
else if (_reader.name() == QLatin1String("Placemark"))
placemark(tracks, areas, waypoints);
else if (_reader.name() == QLatin1String("Folder"))
folder(tracks, areas, waypoints);

View File

@ -66,13 +66,25 @@ void TCXParser::heartRateBpm(Trackpoint &trackpoint)
}
}
void TCXParser::extensions(Trackpoint &trackpoint)
void TCXParser::TPX(Trackpoint &trackpoint)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("RunCadence"))
trackpoint.setCadence(number());
else if (_reader.name() == QLatin1String("Watts"))
trackpoint.setPower(number());
else if (_reader.name() == QLatin1String("Speed"))
trackpoint.setSpeed(number());
else
_reader.skipCurrentElement();
}
}
void TCXParser::extensions(Trackpoint &trackpoint)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("TPX"))
TPX(trackpoint);
else
_reader.skipCurrentElement();
}

View File

@ -26,6 +26,7 @@ private:
void trackpointData(Trackpoint &trackpoint);
void waypointData(Waypoint &waypoint);
void extensions(Trackpoint &trackpoint);
void TPX(Trackpoint &trackpoint);
void heartRateBpm(Trackpoint &trackpoint);
Coordinates position();
qreal number();

View File

@ -17,7 +17,7 @@ bool Track::_useReportedSpeed = false;
bool Track::_useDEM = false;
bool Track::_show2ndElevation = false;
bool Track::_show2ndSpeed = false;
bool Track::_useSegments = true;
static qreal avg(const QVector<qreal> &v)
{
@ -42,6 +42,12 @@ static qreal MAD(QVector<qreal> &v, qreal m)
return median(v);
}
/*
Modified Z-score (Iglewicz and Hoaglin)
The acceleration data distribution has usualy a (much) higher kurtosis than
the normal distribution thus a higher comparsion value than the usual 3.5 is
required.
*/
static QSet<int> eliminate(const QVector<qreal> &v)
{
QSet<int> rm;
@ -51,7 +57,7 @@ static QSet<int> eliminate(const QVector<qreal> &v)
qreal M = MAD(w, m);
for (int i = 0; i < v.size(); i++)
if (qAbs((0.6745 * (v.at(i) - m)) / M) > 3.5)
if (qAbs((0.6745 * (v.at(i) - m)) / M) > 5.0)
rm.insert(i);
return rm;
@ -82,10 +88,20 @@ static GraphSegment filter(const GraphSegment &g, int window)
}
Track::Track(const TrackData &data) : _data(data), _pause(0)
Track::Track(const TrackData &data) : _pause(0)
{
qreal ds, dt;
if (_useSegments)
_data = data;
else {
if (!data.isEmpty()) {
_data.append(data.first());
for (int i = 1; i < data.size(); i++)
_data.first() << data.at(i);
}
}
for (int i = 0; i < _data.size(); i++) {
const SegmentData &sd = _data.at(i);
_segments.append(Segment());

View File

@ -49,10 +49,9 @@ public:
{_outlierEliminate = eliminate;}
static void useReportedSpeed(bool use) {_useReportedSpeed = use;}
static void useDEM(bool use) {_useDEM = use;}
static void showSecondaryElevation(bool show)
{_show2ndElevation = show;}
static void showSecondarySpeed(bool show)
{_show2ndSpeed = show;}
static void showSecondaryElevation(bool show) {_show2ndElevation = show;}
static void showSecondarySpeed(bool show) {_show2ndSpeed = show;}
static void useSegments(bool use) {_useSegments = use;}
private:
struct Segment {
@ -87,6 +86,7 @@ private:
static bool _useDEM;
static bool _show2ndElevation;
static bool _show2ndSpeed;
static bool _useSegments;
};
#endif // TRACK_H

View File

@ -1,4 +1,7 @@
#include "common/config.h"
#ifdef ENABLE_TIMEZONES
#include "GUI/timezoneinfo.h"
#endif // ENABLE_TIMEZONES
#include "GUI/app.h"
int main(int argc, char *argv[])
@ -7,6 +10,9 @@ int main(int argc, char *argv[])
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif // ENABLE_HIDPI
#ifdef ENABLE_TIMEZONES
qRegisterMetaTypeStreamOperators<TimeZoneInfo>("TimeZoneInfo");
#endif // ENABLE_TIMEZONES
App app(argc, argv);
return app.run();

View File

@ -1,38 +1,9 @@
#include "bitstream.h"
bool BitStream1::read(int bits, quint32 &val)
{
val = 0;
for (int pos = 0; pos < bits; ) {
if (!_remaining) {
if (!_length || !_file.readUInt8(_hdl, _data))
return false;
_remaining = 8;
_length--;
}
quint32 get = bits - pos;
if (get >= _remaining) {
val |= _data << pos;
pos += _remaining;
_remaining = 0;
} else {
quint32 mask = (1<<get) - 1;
val |= (_data & mask)<<pos;
_data >>= get;
_remaining -= get;
break;
}
}
return true;
}
bool BitStream1::flush()
{
if (_length && !_file.seek(_hdl, _hdl.pos() + _length))
if (_length && !_file.seek(_hdl, _file.pos(_hdl) + _length))
return false;
_length = 0;
@ -41,8 +12,35 @@ bool BitStream1::flush()
return true;
}
bool BitStream1::readUInt24(quint32 &val)
{
quint8 b;
bool BitStream4::read(int bits, quint32 &val)
val = 0;
for (int i = 0; i < 3; i++) {
if (!read(8, b))
return false;
val |= (b << (i * 8));
}
return true;
}
bool BitStream4F::flush()
{
if (_length && !_file.seek(_hdl, _file.pos(_hdl) + _length))
return false;
_length = 0;
_used = 32;
_unused = 0;
return true;
}
bool BitStream4F::read(int bits, quint32 &val)
{
if (bits <= 32 - (int)(_used + _unused)) {
val = bits ? (_data << _used) >> (32 - bits) : 0;
@ -50,6 +48,8 @@ bool BitStream4::read(int bits, quint32 &val)
return true;
}
if (_unused)
return false;
quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0;
quint32 bytes = qMin(_length, 4U);
@ -66,14 +66,149 @@ bool BitStream4::read(int bits, quint32 &val)
return true;
}
bool BitStream4::flush()
BitStream4R::BitStream4R(const SubFile &file, SubFile::Handle &hdl,
quint32 length) : BitStream4(file, hdl, length)
{
if (_length && !_file.seek(_hdl, _hdl.pos() + _length))
return false;
_file.seek(_hdl, _file.pos(_hdl) - 4);
}
_length = 0;
_used = 32;
_unused = 0;
bool BitStream4R::readBytes(int bytes, quint32 &val)
{
quint32 bits = _used % 8;
quint32 b;
if (bits) {
if (!read(8 - bits, b))
return false;
Q_ASSERT(!b);
}
val = 0;
for (int i = 0; i < bytes; i++) {
if (!read(8, b))
return false;
val |= (b << (i * 8));
}
return true;
}
bool BitStream4R::readVUInt32(quint32 &val)
{
quint32 b;
quint8 bytes, shift;
if (!readBytes(1, b))
return false;
if ((b & 1) == 0) {
if ((b & 2) == 0) {
bytes = ((b >> 2) & 1) ^ 3;
shift = 5;
} else {
shift = 6;
bytes = 1;
}
} else {
shift = 7;
bytes = 0;
}
val = b >> (8 - shift);
if (bytes) {
if (!readBytes(bytes, b))
return false;
val = val | (b << shift);
}
return true;
}
bool BitStream4R::readVuint32SM(quint32 &val1, quint32 &val2, quint32 &val2Bits)
{
quint32 b, eb;
if (!readBytes(1, b))
return false;
if (!(b & 1)) {
val1 = b >> 3;
val2 = b >> 1 & 3;
val2Bits = 2;
} else {
eb = b & 2;
val2 = b >> 2 & 0x3f;
val2Bits = eb * 2 + 6;
if (!readBytes((eb >> 1 | 2) - 1, b))
return false;
if (eb) {
val2 = val2 | (b & 0xf) << 6;
b = b >> 4 & 0xfff;
}
val1 = b;
}
return true;
}
bool BitStream4R::skip(quint32 bytes)
{
if (bytes * 8 > bitsAvailable())
return false;
quint32 ab = (32 - (_used + _unused))/8;
if (bytes <= ab)
_used += bytes * 8;
else {
quint32 seek = ((bytes - ab)/4)*4;
quint32 read = (bytes - ab)%4;
if (seek && !_file.seek(_hdl, _file.pos(_hdl) - seek))
return false;
_length -= seek;
if (read) {
quint32 rb = qMin(_length, 4U);
if (!_file.readUInt32(_hdl, _data))
return false;
if (!_file.seek(_hdl, _file.pos(_hdl) - 8))
return false;
_length -= rb;
_unused = (4 - rb) * 8;
_used = read * 8;
} else
_used = 32;
}
return true;
}
void BitStream4R::resize(quint32 bytes)
{
quint32 ab = (32 - (_used + _unused) + 7)/8;
if (ab <= bytes)
_length = bytes - ab;
else {
_length = 0;
_unused += (ab - bytes) * 8;
}
}
void BitStream4R::save(State &state)
{
state.pos = _file.pos(_hdl);
state.length = _length;
state.used = _used;
state.unused = _unused;
state.data = _data;
}
bool BitStream4R::restore(const State &state)
{
_length = state.length;
_used = state.used;
_unused = state.unused;
_data = state.data;
return _file.seek(_hdl, state.pos);
}

View File

@ -8,9 +8,11 @@ public:
BitStream1(const SubFile &file, SubFile::Handle &hdl, quint32 length)
: _file(file), _hdl(hdl), _length(length), _remaining(0) {}
bool read(int bits, quint32 &val);
template<typename T> bool read(int bits, T &val);
bool flush();
quint32 bitsAvailable() const {return _length * 8 + _remaining;}
quint64 bitsAvailable() const {return (quint64)_length * 8 + _remaining;}
bool readUInt24(quint32 &val);
private:
const SubFile &_file;
@ -25,15 +27,105 @@ public:
: _file(file), _hdl(hdl), _length(length), _used(32), _unused(0),
_data(0) {}
bool read(int bits, quint32 &val);
bool flush();
quint32 bitsAvailable() const {return _length * 8 + (32 - _used) - _unused;}
quint64 bitsAvailable() const
{return (quint64)_length * 8 + (32 - _used) - _unused;}
private:
protected:
const SubFile &_file;
SubFile::Handle &_hdl;
quint32 _length, _used, _unused;
quint32 _data;
};
class BitStream4F : public BitStream4 {
public:
BitStream4F(const SubFile &file, SubFile::Handle &hdl, quint32 length)
: BitStream4(file, hdl, length) {}
bool read(int bits, quint32 &val);
bool flush();
};
class BitStream4R : public BitStream4 {
public:
struct State {
quint32 pos;
quint32 length;
quint32 used;
quint32 unused;
quint32 data;
};
BitStream4R(const SubFile &file, SubFile::Handle &hdl, quint32 length);
template<typename T> bool read(int bits, T &val);
bool readBytes(int bytes, quint32 &val);
bool readVUInt32(quint32 &val);
bool readVuint32SM(quint32 &val1, quint32 &val2, quint32 &val2Bits);
bool skip(quint32 bytes);
void resize(quint32 bytes);
void save(State &state);
bool restore(const State &state);
};
template<typename T>
bool BitStream1::read(int bits, T &val)
{
val = 0;
for (int pos = 0; pos < bits; ) {
if (!_remaining) {
if (!_length || !_file.readUInt8(_hdl, _data))
return false;
_remaining = 8;
_length--;
}
quint32 get = bits - pos;
if (get >= _remaining) {
val |= _data << pos;
pos += _remaining;
_remaining = 0;
} else {
quint32 mask = (1<<get) - 1;
val |= (_data & mask)<<pos;
_data >>= get;
_remaining -= get;
break;
}
}
return true;
}
template<typename T>
bool BitStream4R::read(int bits, T &val)
{
if (bits <= 32 - (int)(_used + _unused)) {
val = bits ? (_data << _used) >> (32 - bits) : 0;
_used += bits;
return true;
}
if (_unused)
return false;
quint32 old = (_used < 32) ? (_data << _used) >> (32 - bits) : 0;
quint32 bytes = qMin(_length, 4U);
if (!_file.readUInt32(_hdl, _data))
return false;
if (!_file.seek(_hdl, _file.pos(_hdl) - 8))
return false;
_length -= bytes;
_used -= 32 - bits;
_unused = (4 - bytes) * 8;
val = _data >> (32 - _used) | old;
return true;
}
#endif // BITSTREAM_H

View File

@ -81,7 +81,11 @@ bool GMAP::loadTile(const QDir &dir, bool baseMap)
QFileInfoList ml = dir.entryInfoList(QDir::Files);
for (int i = 0; i < ml.size(); i++) {
const QFileInfo &fi = ml.at(i);
tile->addFile(fi.absoluteFilePath(), tileType(fi.suffix()));
SubFile::Type tt = tileType(fi.suffix());
if (VectorTile::isTileFile(tt)) {
_files.append(new QString(fi.absoluteFilePath()));
tile->addFile(_files.last(), tt);
}
}
if (!tile->init()) {
@ -131,8 +135,10 @@ GMAP::GMAP(const QString &fileName) : _fileName(fileName)
fi.absoluteFilePath() == baseMap.absoluteFilePath());
}
if (baseDir.exists(typFilePath))
_typ = new SubFile(baseDir.filePath(typFilePath));
if (baseDir.exists(typFilePath)) {
_files.append(new QString(baseDir.filePath(typFilePath)));
_typ = new SubFile(_files.last());
}
if (!_tileTree.Count())
_errorString = "No usable map tile found";
@ -140,6 +146,11 @@ GMAP::GMAP(const QString &fileName) : _fileName(fileName)
_valid = true;
}
GMAP::~GMAP()
{
qDeleteAll(_files);
}
bool GMAP::isGMAP(const QString &path)
{
QFile file(path);

View File

@ -10,6 +10,7 @@ class GMAP : public MapData
{
public:
GMAP(const QString &fileName);
~GMAP();
QString fileName() const {return _fileName;}
@ -25,6 +26,7 @@ private:
bool loadTile(const QDir &dir, bool baseMap);
QString _fileName;
QList<const QString*> _files;
};
#endif // GMAP_H

View File

@ -0,0 +1,24 @@
#include "rgnfile.h"
#include "huffmanbuffer.h"
bool HuffmanBuffer::load(const RGNFile *rgn, SubFile::Handle &rgnHdl)
{
quint32 recordSize, recordOffset = rgn->dictOffset();
for (int i = 0; i <= _id; i++) {
if (!rgn->seek(rgnHdl, recordOffset))
return false;
if (!rgn->readVUInt32(rgnHdl, recordSize))
return false;
recordOffset = rgn->pos(rgnHdl) + recordSize;
if (recordOffset > rgn->dictOffset() + rgn->dictSize())
return false;
};
resize(recordSize);
for (int i = 0; i < QByteArray::size(); i++)
if (!rgn->readUInt8(rgnHdl, *((quint8*)(data() + i))))
return false;
return true;
}

View File

@ -0,0 +1,21 @@
#ifndef HUFFMANBUFFER_H
#define HUFFMANBUFFER_H
#include <QByteArray>
#include "subfile.h"
class RGNFile;
class HuffmanBuffer : public QByteArray
{
public:
HuffmanBuffer(quint8 id) : _id(id) {}
quint8 id() const {return _id;}
bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl);
private:
quint8 _id;
};
#endif // HUFFMANBUFFER_H

View File

@ -1,74 +1,41 @@
#include "huffmanstream.h"
HuffmanStream::HuffmanStream(const SubFile &file, SubFile::Handle &hdl,
quint32 length, const HuffmanTable &table, bool line)
: BitStream4(file, hdl, length), _table(table), _symbolDataSize(0),
_symbolData(0)
bool HuffmanStreamF::init(bool line)
{
if (line) {
if (!(sign(_lonSign) && sign(_latSign)))
return;
return false;
} else {
_lonSign = 0;
_latSign = 0;
}
quint32 eb;
if (!read(1, eb))
return;
if (eb) {
qWarning("Extended polygon/lines not supported");
flush();
}
}
bool HuffmanStream::sign(int &val)
{
quint32 bit;
val = 0;
if (!read(1, bit))
if (!_bs.read(1, eb))
return false;
Q_ASSERT(!eb);
if (eb)
return false;
if (bit) {
if (!read(1, bit))
return false;
val = bit ? -1 : 1;
}
return true;
}
bool HuffmanStream::readDelta(int sign, qint32 &symbol)
bool HuffmanStreamR::init()
{
quint8 size;
quint32 next;
quint8 nextSize = qMin((quint32)(32 - _symbolDataSize), bitsAvailable());
if (!read(nextSize, next))
if (!(sign(_lonSign) && sign(_latSign)))
return false;
_symbolData = (_symbolData << nextSize) | next;
_symbolDataSize += nextSize;
symbol = _table.symbol(_symbolData << (32 - _symbolDataSize), size);
if (size <= _symbolDataSize)
_symbolDataSize -= size;
else
return false;
if (symbol && !sign) {
if (!_symbolDataSize)
return false;
else {
sign = ((1U << (_symbolDataSize - 1)) & _symbolData) ? -1 : 1;
_symbolDataSize--;
}
}
symbol = sign * symbol;
return true;
}
bool HuffmanStreamR::init(int lonSign, int latSign, quint32 data,
quint32 dataSize)
{
_lonSign = lonSign;
_latSign = latSign;
_symbolData = data;
_symbolDataSize = dataSize;
return true;
}

View File

@ -4,11 +4,15 @@
#include "bitstream.h"
#include "huffmantable.h"
class HuffmanStream : public BitStream4 {
template <class BitStream>
class HuffmanStream {
public:
HuffmanStream(const SubFile &file, SubFile::Handle &hdl, quint32 length,
const HuffmanTable &table, bool line);
HuffmanStream(BitStream &bitstream, const HuffmanTable &table)
: _bs(bitstream), _table(table), _symbolDataSize(0), _symbolData(0),
_lonSign(0), _latSign(0) {}
bool read(int bits, quint32 &val);
bool readSymbol(quint32 &symbol);
bool readNext(qint32 &lonDelta, qint32 &latDelta)
{
if (!(readDelta(_lonSign, lonDelta) && readDelta(_latSign, latDelta)))
@ -17,19 +21,121 @@ public:
return (lonDelta || latDelta);
}
bool readOffset(qint32 &lonDelta, qint32 &latDelta)
{return (readDelta(1, lonDelta) && readDelta(1, latDelta));}
bool atEnd() const
{return _symbolDataSize + bitsAvailable() < _table.maxSymbolSize();}
{return _symbolDataSize + _bs.bitsAvailable() < _table.maxSymbolSize();}
bool flush() {return _bs.flush();}
private:
protected:
bool sign(int &val);
bool readDelta(int sign, qint32 &delta);
BitStream &_bs;
const HuffmanTable &_table;
quint32 _symbolDataSize;
quint32 _symbolData;
int _lonSign, _latSign;
};
template <class BitStream>
bool HuffmanStream<BitStream>::sign(int &val)
{
quint32 bit;
val = 0;
if (!_bs.read(1, bit))
return false;
if (bit) {
if (!_bs.read(1, bit))
return false;
val = bit ? -1 : 1;
}
return true;
}
template <class BitStream>
bool HuffmanStream<BitStream>::read(int bits, quint32 &val)
{
if (_symbolDataSize < (quint32)bits) {
quint32 next;
quint8 nextSize = qMin((quint64)(32 - _symbolDataSize),
_bs.bitsAvailable());
if (!_bs.read(nextSize, next))
return false;
_symbolData = (_symbolData << nextSize) | next;
_symbolDataSize += nextSize;
}
if (_symbolDataSize < (quint32)bits)
return false;
val = (_symbolData << (32-_symbolDataSize)) >> (32 - bits);
_symbolDataSize -= bits;
return true;
}
template <class BitStream>
bool HuffmanStream<BitStream>::readSymbol(quint32 &symbol)
{
quint8 size;
quint32 next;
quint8 nextSize = qMin((quint64)(32 - _symbolDataSize), _bs.bitsAvailable());
if (!_bs.read(nextSize, next))
return false;
_symbolData = (_symbolData << nextSize) | next;
_symbolDataSize += nextSize;
symbol = _table.symbol(_symbolData << (32 - _symbolDataSize), size);
if (size > _symbolDataSize)
return false;
_symbolDataSize -= size;
return true;
}
template <class BitStream>
bool HuffmanStream<BitStream>::readDelta(int sign, qint32 &delta)
{
quint32 symbol;
if (!readSymbol(symbol))
return false;
if (symbol && !sign) {
if (!_symbolDataSize)
return false;
else {
sign = ((1U << (_symbolDataSize - 1)) & _symbolData) ? -1 : 1;
_symbolDataSize--;
}
}
delta = sign * symbol;
return true;
}
class HuffmanStreamF : public HuffmanStream<BitStream4F> {
public:
HuffmanStreamF(BitStream4F &bitstream, const HuffmanTable &table)
: HuffmanStream(bitstream, table) {}
bool init(bool line);
bool readOffset(qint32 &lonDelta, qint32 &latDelta)
{return (readDelta(1, lonDelta) && readDelta(1, latDelta));}
};
class HuffmanStreamR : public HuffmanStream<BitStream4R> {
public:
HuffmanStreamR(BitStream4R &bitstream, const HuffmanTable &table)
: HuffmanStream(bitstream, table) {}
bool init();
bool init(int lonSign, int latSign, quint32 data, quint32 dataSize);
};
#endif // HUFFMANSTREAM_H

View File

@ -1,17 +1,7 @@
#include "common/garmin.h"
#include "huffmantable.h"
static quint8 vs(const quint8 b0)
{
static const quint8 sizes[] = {4, 1, 2, 1, 3, 1, 2, 1};
return sizes[b0 & 0x07];
}
static inline quint8 bs(const quint8 val)
{
return (val + 7) >> 3;
}
static inline quint32 readVUint32(const quint8 *buffer, quint32 bytes)
{
quint32 val = 0;
@ -22,10 +12,9 @@ static inline quint32 readVUint32(const quint8 *buffer, quint32 bytes)
return val;
}
bool HuffmanTable::load(const SubFile &file, SubFile::Handle &hdl,
quint32 offset, quint32 size, quint32 id)
bool HuffmanTable::load(const RGNFile *rgn, SubFile::Handle &rgnHdl)
{
if (!getBuffer(file, hdl, offset, size, id))
if (!_buffer.load(rgn, rgnHdl))
return false;
_s0 = (quint8)_buffer.at(0) & 0x0F;
@ -45,29 +34,6 @@ bool HuffmanTable::load(const SubFile &file, SubFile::Handle &hdl,
return true;
}
bool HuffmanTable::getBuffer(const SubFile &file, SubFile::Handle &hdl,
quint32 offset, quint32 size, quint8 id)
{
quint32 recordSize, recordOffset = offset;
for (int i = 0; i <= id; i++) {
if (!file.seek(hdl, recordOffset))
return false;
if (!file.readVUInt32(hdl, recordSize))
return false;
recordOffset = hdl.pos() + recordSize;
if (recordOffset > offset + size)
return false;
};
_buffer.resize(recordSize);
for (int i = 0; i < _buffer.size(); i++)
if (!file.readUInt8(hdl, *((quint8*)(_buffer.data() + i))))
return false;
return true;
}
quint32 HuffmanTable::symbol(quint32 data, quint8 &size) const
{
quint32 ss, sym;

View File

@ -1,23 +1,22 @@
#ifndef HUFFMANTABLE_H
#define HUFFMANTABLE_H
#include "subfile.h"
#include "huffmanbuffer.h"
class RGNFile;
class HuffmanTable {
public:
HuffmanTable() : _s2(0) {}
HuffmanTable(quint8 id) : _buffer(id) {}
bool load(const SubFile &file, SubFile::Handle &hdl, quint32 offset,
quint32 size, quint32 id);
bool isNull() const {return _s2 == 0;}
bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl);
quint8 maxSymbolSize() const {return _s2;}
quint32 symbol(quint32 data, quint8 &size) const;
private:
bool getBuffer(const SubFile &file, SubFile::Handle &hdl, quint32 offset,
quint32 size, quint8 id);
quint8 id() const {return _buffer.id();}
QByteArray _buffer;
private:
HuffmanBuffer _buffer;
quint8 _s0, _s1, _s2, _s3;
quint8 *_s10, *_s14, *_s18;
quint8 _s1c, _s1d, _s1e, _s1f, _s20;

169
src/map/IMG/huffmantext.cpp Normal file
View File

@ -0,0 +1,169 @@
#include "common/garmin.h"
#include "subfile.h"
#include "huffmantext.h"
static inline quint32 readVUint32(const quint8 *buffer, quint32 bytes)
{
quint32 val = 0;
for (quint32 i = 0; i < bytes; i++)
val = val | (quint32)*(buffer - i) << ((bytes - i - 1) << 3);
return val;
}
bool HuffmanText::load(const RGNFile *rgn, SubFile::Handle &rgnHdl)
{
if (!_buffer.load(rgn, rgnHdl))
return false;
quint8 *buffer = (quint8 *)_buffer.constData();
_b0 = buffer[0];
_b1 = buffer[1];
_b2 = buffer[2];
_b3 = buffer[3];
_vs = vs(buffer[4]);
_bs3 = bs(_b3);
_bs1 = bs(_b1);
_mul = _bs1 + 1 + _vs;
_bp1 = buffer + _vs + 4;
_bp2 = _bp1 + _mul * _b2;
_bp3 = _bp2 + ((_bs3 + 1) << (_b0 & 0xf));
_bp4 = _bp3 - 1;
return true;
}
bool HuffmanText::fetch(const SubFile *file, SubFile::Handle &hdl,
quint32 &data, quint32 &bits, quint32 &usedBits, quint32 &usedData) const
{
quint32 rs, ls, old;
bits = _b1 - bits;
if (usedBits < bits) {
old = usedBits ? usedData >> (0x20 - usedBits) : 0;
if (!file->readVUInt32SW(hdl, 4, usedData))
return false;
ls = bits - usedBits;
rs = 0x20 - (bits - usedBits);
old = usedData >> rs | old << ls;
} else {
ls = bits;
rs = usedBits - bits;
old = usedData >> (0x20 - bits);
}
usedData = usedData << ls;
data = data | old << (0x20 - _b1);
usedBits = rs;
return true;
}
bool HuffmanText::decode(const SubFile *file, SubFile::Handle &hdl,
QVector<quint8> &str) const
{
quint32 bits = 0;
quint32 data = 0;
quint32 usedBits = 0;
quint32 usedData = 0;
quint32 ls = 8;
quint32 lo = _vs * 8 - 8;
while (true) {
if (!fetch(file, hdl, data, bits, usedBits, usedData))
return false;
quint32 off = (data >> (0x20 - (_b0 & 0xf))) * (_bs3 + 1);
quint32 sb = _bp2[off];
quint32 ss = 0;
quint32 sym = _b2 - 1;
quint32 size;
if ((_b0 & 0xf) == 0 || (sb & 1) == 0) {
if ((_b0 & 0xf) != 0) {
ss = sb >> 1;
sym = _bp2[off + 1];
}
quint8 *tp = _bp1 + ss * _mul;
quint32 sd = data >> (0x20 - _b1);
while (ss < sym) {
quint32 cnt = (sym + 1 + ss) >> 1;
quint8 *prev = _bp1 + cnt * _mul;
quint32 nd = readVUint32(prev + _bs1 - 1, _bs1);
if (sd <= nd) {
sym = cnt - (sd < nd);
if (sd < nd) {
prev = tp;
cnt = ss;
}
}
tp = prev;
ss = cnt;
}
quint32 o1 = readVUint32(tp + _bs1 - 1, _bs1);
tp = tp + _bs1;
quint32 o2 = readVUint32(tp + _vs, _vs);
size = tp[0];
quint32 os = (sd - o1) >> (_b1 - size);
if ((_b0 & 0x10) == 0) {
sym = readVUint32(_bp4 + (o2 + 1 + os) * _bs3, _bs3);
} else {
quint32 v = (os + o2) * _b3;
quint32 idx = v >> 3;
quint32 r = v & 7;
quint32 shift = 8 - r;
sym = _bp3[idx] >> r;
if (shift < _b3) {
quint32 sz = bs(_b3 - shift);
quint32 val = readVUint32(_bp3 + idx + sz, sz);
sym = sym | val << shift;
}
}
} else {
sym = readVUint32(_bp2 + off + _bs3, _bs3);
size = (sb >> 1);
}
if (_b1 < size)
return false;
data = data << size;
bits = _b1 - size;
if ((_b3 & 7) == 0) {
for (quint32 i = 0; i < (_b3 >> 3); i++) {
str.append((quint8)sym);
if (((quint8)sym == '\0'))
return true;
sym = sym >> 8;
}
} else {
quint32 cnt = _b3;
if (ls <= _b3) {
do {
quint32 shift = ls;
lo = sym << (8 - shift) | (quint32)((quint8)lo >> shift);
sym = sym >> shift;
str.append((uchar)lo);
if (((uchar)lo == '\0'))
return true;
cnt = cnt - ls;
ls = 8;
} while (7 < cnt);
ls = 8;
}
if (cnt != 0) {
lo = sym << (8 - cnt) | (quint32)((quint8)lo >> cnt);
ls = ls - cnt;
}
}
}
}

35
src/map/IMG/huffmantext.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef HUFFMANTEXT_H
#define HUFFMANTEXT_H
#include "huffmanbuffer.h"
class HuffmanText
{
public:
HuffmanText() : _buffer(0) {}
bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl);
bool decode(const SubFile *file, SubFile::Handle &hdl,
QVector<quint8> &str) const;
private:
bool fetch(const SubFile *file, SubFile::Handle &hdl, quint32 &data,
quint32 &bits, quint32 &usedBits, quint32 &usedData) const;
HuffmanBuffer _buffer;
quint32 _b0;
quint32 _b1;
quint32 _b2;
quint32 _b3;
quint32 _vs;
quint32 _bs3;
quint32 _bs1;
quint32 _mul;
quint8 *_bp1;
quint8 *_bp2;
quint8 *_bp3;
quint8 *_bp4;
};
#endif // HUFFMANTEXT_H

View File

@ -59,7 +59,7 @@ IMG::IMG(const QString &fileName) : _file(fileName)
QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2)));
_name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed();
_blockSize = 1 << (e1 + e2);
_blockBits = e1 + e2;
// Read the FAT table
quint8 flag;
@ -132,7 +132,6 @@ IMG::IMG(const QString &fileName) : _file(fileName)
}
// Create tile tree
int minMapZoom = 24;
for (TileMap::const_iterator it = tileMap.constBegin();
it != tileMap.constEnd(); ++it) {
@ -159,14 +158,19 @@ IMG::IMG(const QString &fileName) : _file(fileName)
minMapZoom = tile->zooms().min();
}
for (TileMap::const_iterator it = tileMap.constBegin();
it != tileMap.constEnd(); ++it) {
VectorTile *tile = it.value();
// Detect and mark basemap
TileTree::Iterator it;
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it)) {
VectorTile *tile = _tileTree.GetAt(it);
if (tile->zooms().min() > minMapZoom)
_baseMap = true;
if (tile->zooms().min() == minMapZoom)
tile->markAsBasemap();
}
// Allow some extra zoom out on maps without basemaps, but not too much as
// this would kill the rendering performance
if (!_baseMap)
_zooms.setMin(_zooms.min() - 2);
if (!_tileTree.Count())
_errorString = "No usable map tile found";
@ -197,9 +201,9 @@ template<class T> bool IMG::readValue(T &val)
bool IMG::readBlock(int blockNum, char *data)
{
if (!_file.seek((qint64)blockNum * (qint64)_blockSize))
if (!_file.seek((quint64)blockNum << _blockBits))
return false;
if (read(data, _blockSize) < _blockSize)
if (read(data, 1U<<_blockBits) < 1U<<_blockBits)
return false;
return true;

View File

@ -14,14 +14,14 @@ public:
private:
friend class SubFile;
int blockSize() const {return _blockSize;}
unsigned blockBits() const {return _blockBits;}
bool readBlock(int blockNum, char *data);
qint64 read(char *data, qint64 maxSize);
template<class T> bool readValue(T &val);
QFile _file;
quint8 _key;
int _blockSize;
unsigned _blockBits;
};
#endif // IMG_H

View File

@ -1,4 +1,6 @@
#include <QTextCodec>
#include "huffmantext.h"
#include "rgnfile.h"
#include "lblfile.h"
enum Charset {Normal, Symbol, Special};
@ -55,21 +57,48 @@ static QString capitalized(const QString &str)
}
bool LBLFile::init(Handle &hdl)
LBLFile::~LBLFile()
{
quint16 codepage;
quint8 multiplier, poiMultiplier;
delete _huffmanText;
delete[] _table;
}
if (!(seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
&& readUInt32(hdl, _size) && readUInt8(hdl, multiplier)
bool LBLFile::load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl)
{
quint16 hdrLen, codepage;
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
&& seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
&& readUInt32(hdl, _size) && readUInt8(hdl, _multiplier)
&& readUInt8(hdl, _encoding) && seek(hdl, _gmpOffset + 0x57)
&& readUInt32(hdl, _poiOffset) && readUInt32(hdl, _poiSize)
&& readUInt8(hdl, poiMultiplier) && seek(hdl, _gmpOffset + 0xAA)
&& readUInt8(hdl, _poiMultiplier) && seek(hdl, _gmpOffset + 0xAA)
&& readUInt16(hdl, codepage)))
return false;
_multiplier = 1<<multiplier;
_poiMultiplier = 1<<poiMultiplier;
if (hdrLen >= 0x132) {
quint32 offset, size;
quint16 recordSize;
if (!(seek(hdl, _gmpOffset + 0x124) && readUInt32(hdl, offset)
&& readUInt32(hdl, size) && readUInt16(hdl, recordSize)))
return false;
if (size && recordSize) {
_table = new quint32[size / recordSize];
if (!seek(hdl, offset))
return false;
for (quint32 i = 0; i < size / recordSize; i++) {
if (!readVUInt32(hdl, recordSize, _table[i]))
return false;
}
}
}
if (_encoding == 11) {
_huffmanText = new HuffmanText();
if (!_huffmanText->load(rgn, rgnHdl))
return false;
}
if (codepage == 65001)
_codec = QTextCodec::codecForName("UTF-8");
@ -82,6 +111,14 @@ bool LBLFile::init(Handle &hdl)
return true;
}
void LBLFile::clear()
{
delete _huffmanText;
delete[] _table;
_huffmanText = 0;
_table = 0;
}
Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize) const
{
Label::Shield::Type shieldType = Label::Shield::None;
@ -135,20 +172,16 @@ Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize) const
}
}
Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
Label LBLFile::str2label(const QVector<quint8> &str, bool capitalize) const
{
Label::Shield::Type shieldType = Label::Shield::None;
QByteArray label, shieldLabel;
QByteArray *bap = &label;
quint8 c;
if (!seek(hdl, offset))
return Label();
for (int i = 0; i < str.size(); i++) {
const quint8 &c = str.at(i);
while (true) {
if (!readUInt8(hdl, c))
return Label();
if (!c || c == 0x1d)
if (c == 0 || c == 0x1d)
break;
if (c == 0x1c)
@ -158,10 +191,10 @@ Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
bap = &label;
else
bap->append(' ');
} else if (c <= 0x07) {
} else if (c < 0x07) {
shieldType = static_cast<Label::Shield::Type>(c);
bap = &shieldLabel;
} else if (bap == &shieldLabel && QChar(c).isSpace()) {
} else if (bap == &shieldLabel && c == 0x20) {
bap = &label;
} else
bap->append(c);
@ -175,21 +208,74 @@ Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
Label::Shield(shieldType, shieldText));
}
Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize)
Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
{
if (!_multiplier && !init(hdl))
return QString();
QVector<quint8> str;
quint8 c;
if (!seek(hdl, offset))
return Label();
do {
if (!readUInt8(hdl, c))
return Label();
str.append(c);
} while (c);
return str2label(str, capitalize);
}
Label LBLFile::labelHuffman(Handle &hdl, quint32 offset, bool capitalize) const
{
QVector<quint8> str;
if (!seek(hdl, offset))
return Label();
if (!_huffmanText->decode(this, hdl, str))
return Label();
if (!_table)
return str2label(str, capitalize);
QVector<quint8> str2;
for (int i = 0; i < str.size(); i++) {
quint32 val = _table[str.at(i)];
if (val) {
if (!seek(hdl, _offset + ((val & 0x7fffff) << _multiplier)))
return Label();
if (str2.size() && str2.back() == '\0')
str2[str2.size() - 1] = ' ';
else if (str2.size())
str2.append(' ');
if (!_huffmanText->decode(this, hdl, str2))
return Label();
} else {
if (str.at(i) == 7) {
str2.append(0);
break;
}
if (str2.size() && str2.back() == '\0')
str2[str2.size() - 1] = ' ';
str2.append(str.at(i));
}
}
return str2label(str2, capitalize);
}
Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize) const
{
quint32 labelOffset;
if (poi) {
quint32 poiOffset;
if (!(_poiSize >= offset * _poiMultiplier
&& seek(hdl, _poiOffset + offset * _poiMultiplier)
if (!(_poiSize >= (offset << _poiMultiplier)
&& seek(hdl, _poiOffset + (offset << _poiMultiplier))
&& readUInt24(hdl, poiOffset) && (poiOffset & 0x3FFFFF)))
return QString();
labelOffset = _offset + (poiOffset & 0x3FFFFF) * _multiplier;
labelOffset = _offset + ((poiOffset & 0x3FFFFF) << _multiplier);
} else
labelOffset = _offset + offset * _multiplier;
labelOffset = _offset + (offset << _multiplier);
if (labelOffset > _offset + _size)
return QString();
@ -200,6 +286,8 @@ Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize)
case 9:
case 10:
return label8b(hdl, labelOffset, capitalize);
case 11:
return labelHuffman(hdl, labelOffset, capitalize);
default:
return Label();
}

View File

@ -5,28 +5,40 @@
#include "label.h"
class QTextCodec;
class HuffmanText;
class RGNFile;
class LBLFile : public SubFile
{
public:
LBLFile(IMG *img)
: SubFile(img), _codec(0), _offset(0), _size(0), _poiOffset(0),
_poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {}
LBLFile(const QString &path)
: SubFile(path), _codec(0), _offset(0), _size(0), _poiOffset(0),
_poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {}
: SubFile(img), _huffmanText(0), _table(0), _codec(0), _offset(0),
_size(0), _poiOffset(0), _poiSize(0), _poiMultiplier(0), _multiplier(0),
_encoding(0) {}
LBLFile(const QString *path)
: SubFile(path), _huffmanText(0), _table(0), _codec(0), _offset(0),
_size(0), _poiOffset(0), _poiSize(0), _poiMultiplier(0), _multiplier(0),
_encoding(0) {}
LBLFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
_codec(0), _offset(0), _size(0), _poiOffset(0), _poiSize(0),
_poiMultiplier(0), _multiplier(0), _encoding(0) {}
_huffmanText(0), _table(0), _codec(0), _offset(0), _size(0),
_poiOffset(0), _poiSize(0), _poiMultiplier(0), _multiplier(0),
_encoding(0) {}
~LBLFile();
bool load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl);
void clear();
Label label(Handle &hdl, quint32 offset, bool poi = false,
bool capitalize = true);
bool capitalize = true) const;
private:
bool init(Handle &hdl);
Label str2label(const QVector<quint8> &str, bool capitalize) const;
Label label6b(Handle &hdl, quint32 offset, bool capitalize) const;
Label label8b(Handle &hdl, quint32 offset, bool capitalize) const;
Label labelHuffman(Handle &hdl, quint32 offset, bool capitalize) const;
HuffmanText *_huffmanText;
quint32 *_table;
QTextCodec *_codec;
quint32 _offset;

View File

@ -54,7 +54,7 @@ inline bool pointCb(VectorTile *tile, void *context)
}
MapData::MapData() : _typ(0), _style(0), _zooms(15, 28), _baseMap(false),
MapData::MapData() : _typ(0), _style(0), _zooms(24, 28), _baseMap(false),
_valid(false)
{
_polyCache.setMaxCost(CACHED_SUBDIVS_COUNT);
@ -107,7 +107,7 @@ void MapData::load()
else {
QString typFile(ProgramPaths::typFile());
if (!typFile.isEmpty()) {
SubFile typ(typFile);
SubFile typ(&typFile);
_style = new Style(&typ);
} else
_style = new Style();

View File

@ -21,7 +21,7 @@ public:
struct Poly {
/* QPointF insted of Coordinates for performance reasons (no need to
duplicate all the vectors for drawing). Note, that we do not want to
ll2xy() the points in the IMG class as this can not be done in
ll2xy() the points in the MapData class as this can not be done in
parallel. */
QVector<QPointF> points;
Label label;
@ -38,22 +38,12 @@ public:
Coordinates coordinates;
Label label;
quint32 type;
bool poi;
quint64 id;
bool operator<(const Point &other) const
{return id < other.id;}
};
struct Polys {
Polys() {}
Polys(const QList<Poly> &polygons, const QList<Poly> &lines)
: polygons(polygons), lines(lines) {}
QList<Poly> polygons;
QList<Poly> lines;
};
MapData();
virtual ~MapData();
@ -88,15 +78,26 @@ protected:
QString _errorString;
private:
struct Polys {
Polys() {}
Polys(const QList<Poly> &polygons, const QList<Poly> &lines)
: polygons(polygons), lines(lines) {}
QList<Poly> polygons;
QList<Poly> lines;
};
QCache<const SubDiv*, Polys> _polyCache;
QCache<const SubDiv*, QList<Point> > _pointCache;
friend class VectorTile;
friend class PolyCTX;
};
#ifndef QT_NO_DEBUG
inline QDebug operator<<(QDebug dbg, const MapData::Point &point)
{
dbg.nospace() << "Point(" << hex << point.type << ", " << point.label
<< ", " << point.poi << ")";
dbg.nospace() << "Point(" << hex << point.type << ", " << point.label << ")";
return dbg.space();
}

View File

@ -1,26 +1,509 @@
#include "bitstream.h"
#include "huffmanstream.h"
#include "subdiv.h"
#include "nodfile.h"
#include "lblfile.h"
#include "rgnfile.h"
#include "netfile.h"
bool NETFile::init(Handle &hdl)
{
quint8 multiplier;
quint16 hdrLen;
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
&& seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
&& readUInt32(hdl, _size) && readUInt8(hdl, multiplier)))
static bool readAdjCounts(BitStream4R &bs, QVector<quint16> &cnts, quint16 &mask)
{
quint32 val, cnt, bits;
if (!bs.read(4, val))
return false;
_multiplier = 1<<multiplier;
cnt = ((val >> 2) & 3) + 2;
bits = ((val * 2) & 6) + 4;
mask = 1<<(3 + ((val * 2) & 6));
if (cnt == 5) {
if (!bs.read(8, cnt))
return false;
}
if (cnt < 2)
return false;
cnts.resize(cnt - 1);
for (int i = 0; i < cnts.size(); i++)
if (!bs.read(bits, cnts[i]))
return false;
return true;
}
bool NETFile::lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset)
static bool skipShape(BitStream4R &bs)
{
if (!_multiplier && !init(hdl))
quint32 v1, v2, v2b;
if (!bs.readVuint32SM(v1, v2, v2b))
return false;
if (!(seek(hdl, _offset + netOffset * _multiplier)
return bs.skip(v1);
}
static bool skipAdjShapes(BitStream4R &bs, const QVector<quint16> &cnts,
quint16 mask, bool firstIsShape)
{
if (firstIsShape && !skipShape(bs))
return false;
for (int i = 0; i < cnts.size(); i++) {
if (cnts.at(i) & mask) {
if (!skipShape(bs))
return false;
}
}
return true;
}
static bool seekToLevel(BitStream4R &bs, quint8 level)
{
quint32 v1, v2, v2b;
for (quint8 i = 1; i < level; ) {
if (!bs.readVuint32SM(v1, v2, v2b))
return false;
if (!bs.skip(v1))
return false;
if (v2 & 2)
return false;
if (v2 & 1)
i++;
};
return true;
}
static bool seekToLine(BitStream4R &bs, quint8 line)
{
quint32 v1, v2, v2b;
for (quint8 i = 0; i < line; i++) {
if (!bs.readVuint32SM(v1, v2, v2b))
return false;
if (!bs.skip(v1))
return false;
if (v2 & 2)
return false;
}
return true;
}
static bool readLine(BitStream4R &bs, const SubDiv *subdiv,
const HuffmanTable *table, MapData::Poly &poly)
{
quint32 v1, v2, v2b;
if (!bs.readVuint32SM(v1, v2, v2b))
return false;
bs.resize(v1);
quint32 lon, lat;
if (!(bs.read(0x12 - v2b, lon) && bs.read(16, lat)))
return false;
if (2 < v2b)
lon |= (v2 >> 2) << (0x12U - v2b);
QPoint pos = QPoint(LS(subdiv->lon(), 8) + LS((qint16)lon, 32-subdiv->bits()),
LS(subdiv->lat(), 8) + LS((qint16)lat, 32-subdiv->bits()));
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
poly.boundingRect = RectC(c, c);
poly.points.append(QPointF(c.lon(), c.lat()));
HuffmanStreamR stream(bs, *table);
if (!stream.init())
return false;
qint32 lonDelta, latDelta;
while (stream.readNext(lonDelta, latDelta)) {
pos.rx() += LS(lonDelta, 32-subdiv->bits());
if (pos.rx() < 0 && subdiv->lon() >= 0)
pos.rx() = 0x7fffffff;
pos.ry() += LS(latDelta, 32-subdiv->bits());
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
poly.points.append(QPointF(c.lon(), c.lat()));
poly.boundingRect = poly.boundingRect.united(c);
}
return stream.atEnd();
}
static bool readNodeGeometry(const NODFile *nod, SubFile::Handle &nodHdl,
NODFile::AdjacencyInfo &adj, MapData::Poly &poly, quint16 cnt = 0xFFFF)
{
for (int i = 0; i <= cnt; i++) {
int ret = nod->nextNode(nodHdl, adj);
if (ret < 0)
return false;
else if (ret > 0)
return (cnt == 0xFFFF);
Coordinates c(toWGS32(adj.nodeInfo.pos.x()),
toWGS32(adj.nodeInfo.pos.y()));
poly.points.append(QPointF(c.lon(), c.lat()));
poly.boundingRect = poly.boundingRect.united(c);
}
return true;
}
static bool skipNodes(const NODFile *nod, SubFile::Handle &nodHdl,
NODFile::AdjacencyInfo &adj, int cnt)
{
for (int i = 0; i < cnt; i++)
if (nod->nextNode(nodHdl, adj))
return false;
return true;
}
static bool readShape(const NODFile *nod, SubFile::Handle &nodHdl,
NODFile::AdjacencyInfo &adj, BitStream4R &bs, const HuffmanTable *table,
const SubDiv *subdiv, quint32 shift, MapData::Poly &poly,
quint16 cnt = 0xFFFF, bool check = false)
{
quint32 v1, v2, v2b;
if (!bs.readVuint32SM(v1, v2, v2b))
return false;
BitStream4R::State state;
bs.save(state);
bs.resize(v1);
quint32 flags;
if (!bs.read(8, flags))
return false;
flags |= (v2 << 8);
bool hasCoordinatesAdjustBit = flags & (1 << (v2b + 7));
bool useEosBit = flags & (1 << (v2b + 5));
bool startWithStream = flags & (1 << (v2b + 6));
quint32 extraBits;
int lonSign, latSign;
if ((flags >> (v2b + 4) & 1) == 0) {
extraBits = v2b + 4;
lonSign = 0;
} else {
extraBits = v2b + 3;
lonSign = 1;
if ((flags >> (v2b + 3) & 1) != 0) {
lonSign = -1;
}
}
extraBits -= 1;
if ((flags >> extraBits & 1) == 0) {
latSign = 0;
} else {
extraBits -= 1;
latSign = -1;
if ((flags >> extraBits & 1) == 0) {
latSign = 1;
}
}
if (nod->nextNode(nodHdl, adj))
return false;
QPoint pos(adj.nodeInfo.pos);
quint16 nodes = 0;
if (!startWithStream) {
Coordinates c(toWGS32(adj.nodeInfo.pos.x()),
toWGS32(adj.nodeInfo.pos.y()));
poly.points.append(QPointF(c.lon(), c.lat()));
poly.boundingRect = poly.boundingRect.united(c);
while (!adj.eog) {
int ret = nod->nextNode(nodHdl, adj);
if (ret < 0)
return false;
else if (ret > 0)
break;
nodes++;
c = Coordinates(toWGS32(adj.nodeInfo.pos.x()),
toWGS32(adj.nodeInfo.pos.y()));
poly.points.append(QPointF(c.lon(), c.lat()));
poly.boundingRect = poly.boundingRect.united(c);
pos = adj.nodeInfo.pos;
}
}
HuffmanStreamR stream(bs, *table);
if (!stream.init(lonSign, latSign, flags, extraBits))
return false;
qint32 lonDelta, latDelta;
QVector<QPoint> deltas;
quint32 adjustBit = 0;
quint32 stepsCnt = 0;
quint32 steps = 0;
quint32 eos = 0;
while (true) {
if ((stepsCnt == steps) && !useEosBit) {
if (!stream.readSymbol(steps))
break;
if (!steps)
break;
}
if (!stream.readNext(lonDelta, latDelta))
break;
if (hasCoordinatesAdjustBit && !stream.read(1, adjustBit))
return false;
stepsCnt++;
if (useEosBit) {
if (!stream.read(1, eos))
return false;
} else {
if (steps == stepsCnt)
eos = 1;
}
if (!startWithStream) {
pos.rx() += LS(lonDelta, 32-subdiv->bits()-shift);
pos.ry() += LS(latDelta, 32-subdiv->bits()-shift);
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
poly.points.append(QPointF(c.lon(), c.lat()));
poly.boundingRect = poly.boundingRect.united(c);
} else {
deltas.append(QPoint(lonDelta, latDelta));
poly.points.append(QPointF());
}
if (startWithStream && eos) {
for (int i = deltas.size() - 1, j = 0; i >= 0; i--, j++) {
pos.rx() -= LS(deltas.at(i).x(), 32-subdiv->bits()-shift);
pos.ry() -= LS(deltas.at(i).y(), 32-subdiv->bits()-shift);
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
poly.points[poly.points.size() - 1 - j] = QPointF(c.lon(), c.lat());
poly.boundingRect = poly.boundingRect.united(c);
}
pos = adj.nodeInfo.pos;
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
poly.points.append(QPointF(c.lon(), c.lat()));
poly.boundingRect = poly.boundingRect.united(c);
stepsCnt = 0;
steps = 0;
startWithStream = false;
if (adj.eog)
eos = 0;
}
if (eos) {
if (nodes >= cnt)
break;
do {
int ret = nod->nextNode(nodHdl, adj);
if (ret < 0)
return false;
else if (ret > 0)
break;
nodes++;
if (check && nodes == cnt) {
if (!(bs.restore(state) && bs.skip(v1)
&& bs.readVuint32SM(v1, v2, v2b)))
return false;
if (5 < v2b)
v2 >>= v2b - 2;
if (v2 & 1)
break;
}
Coordinates c(toWGS32(adj.nodeInfo.pos.x()),
toWGS32(adj.nodeInfo.pos.y()));
poly.points.append(QPointF(c.lon(), c.lat()));
poly.boundingRect = poly.boundingRect.united(c);
pos = adj.nodeInfo.pos;
} while (!adj.eog && nodes < cnt);
if (nodes == cnt)
break;
steps = 0;
stepsCnt = 0;
eos = 0;
}
}
return true;
}
NETFile::~NETFile()
{
delete _huffmanTable;
}
bool NETFile::linkLabel(Handle &hdl, quint32 offset, quint32 size,
const LBLFile *lbl, Handle &lblHdl, Label &label) const
{
if (!seek(hdl, offset))
return false;
BitStream1 bs(*this, hdl, size);
quint32 flags, labelPtr;
if (!bs.read(8, flags))
return false;
if (!(flags & 1))
return true;
if (!bs.readUInt24(labelPtr))
return false;
if (labelPtr & 0x3FFFFF)
label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
return true;
}
bool NETFile::load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl)
{
quint16 hdrLen;
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
&& seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
&& readUInt32(hdl, _size) && readUInt8(hdl, _shift)))
return false;
if (hdrLen >= 0x47) {
quint32 info;
if (!(seek(hdl, _gmpOffset + 0x37) && readUInt32(hdl, info)))
return false;
if (!(seek(hdl, _gmpOffset + 0x43) && readUInt32(hdl, _linksOffset)
&& readUInt32(hdl, _linksSize) && readUInt8(hdl, _linksShift)))
return false;
quint8 tableId = ((info >> 2) & 0xF);
if (_linksSize && (!rgn->huffmanTable() || rgn->huffmanTable()->id()
!= tableId)) {
_huffmanTable = new HuffmanTable(tableId);
if (!_huffmanTable->load(rgn, rgnHdl))
return false;
}
_tp = _huffmanTable ? _huffmanTable : rgn->huffmanTable();
}
return true;
}
void NETFile::clear()
{
delete _huffmanTable;
_huffmanTable = 0;
}
bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
const NODFile *nod, Handle &nodHdl, const LBLFile *lbl, Handle &lblHdl,
const NODFile::BlockInfo &blockInfo, quint8 linkId, quint8 lineId,
QList<MapData::Poly> *lines) const
{
MapData::Poly poly;
if (!nod->linkType(nodHdl, blockInfo, linkId, poly.type))
return false;
NODFile::LinkInfo linkInfo;
if (!nod->linkInfo(nodHdl, blockInfo, linkId, linkInfo))
return false;
quint32 linkOffset = _linksOffset + (linkInfo.linkOffset << _linksShift);
if (linkOffset > _linksOffset + _linksSize)
return false;
if (!seek(hdl, linkOffset))
return false;
BitStream4R bs(*this, hdl, linkOffset - _linksOffset);
QVector<quint16> ca;
quint16 mask = 0;
quint32 size;
quint8 s68 = (linkInfo.flags >> 0x12) & 1;
quint8 s69 = (linkInfo.flags >> 0x11) & 1;
quint8 s6a = (linkInfo.flags >> 0x13) & 1;
if (s69 == 0 || s6a == 1) {
if (!bs.readVUInt32(size))
return false;
}
if (s69 == 0) {
if (!readAdjCounts(bs, ca, mask))
return false;
}
if (!subdiv->level()) {
NODFile::AdjacencyInfo adj(nod, blockInfo, linkId, linkInfo);
if (s69 == 1) {
if (s68 == 1) {
if (!readShape(nod, nodHdl, adj, bs, _tp, subdiv, shift, poly))
return false;
} else {
if (!readNodeGeometry(nod, nodHdl, adj, poly))
return false;
}
} else {
quint16 mask2 = mask + 0xffff;
for (int i = 0; i <= ca.size(); i++) {
quint16 step = (i < ca.size()) ? ca.at(i) & mask2 : 0xFFFF;
bool shape = (i > 0) ? ca.at(i-1) & mask : (s68 == 1);
if (i == lineId) {
if (shape) {
bool check = (i < ca.size()) ? (ca.at(i) & mask) : false;
if (!readShape(nod, nodHdl, adj, bs, _tp, subdiv,
shift, poly, step, check))
return false;
} else {
if (!readNodeGeometry(nod, nodHdl, adj, poly, step))
return false;
}
break;
}
if (shape && !skipShape(bs))
return false;
if (!skipNodes(nod, nodHdl, adj, step))
return false;
}
}
} else {
if (!skipAdjShapes(bs, ca, mask, s68 == 1))
return false;
if (!seekToLevel(bs, subdiv->level()))
return false;
if (!seekToLine(bs, lineId))
return false;
if (!readLine(bs, subdiv, _tp, poly))
return false;
}
if (lbl)
linkLabel(hdl, linkOffset, _linksSize - (linkOffset - _linksOffset),
lbl, lblHdl, poly.label);
lines->append(poly);
return true;
}
bool NETFile::lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset) const
{
if (!(seek(hdl, _offset + (netOffset << _shift))
&& readUInt24(hdl, lblOffset)))
return false;

Some files were not shown because too many files have changed in this diff Show More