]>
Commit | Line | Data |
---|---|---|
50a14534 EB |
1 | /* |
2 | * viking -- GPS Data and Topo Analyzer, Explorer, and Manager | |
3 | * | |
4 | * Copyright (C) 2005, Evan Battaglia <viking@greentorch.org> | |
a8876892 | 5 | * Copyright (C) 2010, Guilhem Bonnefille <guilhem.bonnefille@gmail.com> |
0fb11294 | 6 | * Copyright (c) 2013, Rob Norris <rw_norris@hotmail.com> |
50a14534 | 7 | * UTM multi-zone stuff by Kit Transue <notlostyet@didactek.com> |
cdcaf41c | 8 | * Dynamic map type by Guilhem Bonnefille <guilhem.bonnefille@gmail.com> |
50a14534 EB |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; either version 2 of the License, or | |
13 | * (at your option) any later version. | |
14 | * | |
15 | * This program is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * GNU General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU General Public License | |
21 | * along with this program; if not, write to the Free Software | |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
23 | * | |
24 | */ | |
25 | ||
4c77d5e0 GB |
26 | #ifdef HAVE_CONFIG_H |
27 | #include "config.h" | |
28 | #endif | |
29 | ||
50a14534 EB |
30 | #include <gtk/gtk.h> |
31 | #include <gdk-pixbuf/gdk-pixdata.h> | |
45acf79e MA |
32 | #include <glib.h> |
33 | #include <glib/gstdio.h> | |
4c77d5e0 GB |
34 | #include <glib/gi18n.h> |
35 | ||
8c00358d | 36 | #ifdef HAVE_STRING_H |
50a14534 | 37 | #include <string.h> |
8c00358d GB |
38 | #endif |
39 | #ifdef HAVE_MATH_H | |
50a14534 | 40 | #include <math.h> |
8c00358d GB |
41 | #endif |
42 | ||
45acf79e | 43 | #ifdef HAVE_UNISTD_H |
50a14534 | 44 | #include <unistd.h> |
45acf79e | 45 | #endif |
50a14534 | 46 | |
a7023a1b | 47 | #include "viking.h" |
450d8665 | 48 | #include "vikmapsourcedefault.h" |
1b14d0d2 | 49 | #include "vikutils.h" |
9979924f | 50 | #include "maputils.h" |
50a14534 | 51 | #include "mapcache.h" |
50a14534 | 52 | #include "background.h" |
a7023a1b RN |
53 | #include "preferences.h" |
54 | #include "vikmapslayer.h" | |
bce3a7b0 | 55 | #include "icons/icons.h" |
99f0d7df | 56 | #include "metatile.h" |
5cca6c53 | 57 | #include "ui_util.h" |
8a5461eb | 58 | #include "map_ids.h" |
bce3a7b0 | 59 | |
0fb11294 RN |
60 | #ifdef HAVE_SQLITE3_H |
61 | #include "sqlite3.h" | |
62 | #include <gio/gio.h> | |
63 | #endif | |
64 | ||
0f7e9133 RN |
65 | #define VIK_SETTINGS_MAP_MAX_TILES "maps_max_tiles" |
66 | static gint MAX_TILES = 1000; | |
67 | ||
68 | #define VIK_SETTINGS_MAP_MIN_SHRINKFACTOR "maps_min_shrinkfactor" | |
69 | #define VIK_SETTINGS_MAP_MAX_SHRINKFACTOR "maps_max_shrinkfactor" | |
70 | static gdouble MAX_SHRINKFACTOR = 8.0000001; /* zoom 1 viewing 8-tiles */ | |
71 | static gdouble MIN_SHRINKFACTOR = 0.0312499; /* zoom 32 viewing 1-tiles */ | |
72 | ||
73 | #define VIK_SETTINGS_MAP_REAL_MIN_SHRINKFACTOR "maps_real_min_shrinkfactor" | |
74 | static gdouble REAL_MIN_SHRINKFACTOR = 0.0039062499; /* if shrinkfactor is between MAX and REAL_MAX, will only check for existence */ | |
75 | ||
d1871cd2 RN |
76 | #define VIK_SETTINGS_MAP_SCALE_INC_UP "maps_scale_inc_up" |
77 | static guint SCALE_INC_UP = 2; | |
78 | #define VIK_SETTINGS_MAP_SCALE_INC_DOWN "maps_scale_inc_down" | |
79 | static guint SCALE_INC_DOWN = 4; | |
80 | #define VIK_SETTINGS_MAP_SCALE_SMALLER_ZOOM_FIRST "maps_scale_smaller_zoom_first" | |
81 | static gboolean SCALE_SMALLER_ZOOM_FIRST = TRUE; | |
82 | ||
50a14534 EB |
83 | /****** MAP TYPES ******/ |
84 | ||
cdcaf41c QT |
85 | static GList *__map_types = NULL; |
86 | ||
87 | #define NUM_MAP_TYPES g_list_length(__map_types) | |
50a14534 | 88 | |
cdcaf41c | 89 | /* List of label for each map type */ |
a8876892 | 90 | static gchar **params_maptypes = NULL; |
cdcaf41c QT |
91 | |
92 | /* Corresponding IDS. (Cf. field uniq_id in VikMapsLayer struct) */ | |
a8876892 | 93 | static guint *params_maptypes_ids = NULL; |
50a14534 EB |
94 | |
95 | /******** MAPZOOMS *********/ | |
96 | ||
fcc2786b SW |
97 | static gchar *params_mapzooms[] = { N_("Use Viking Zoom Level"), "0.25", "0.5", "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "USGS 10k", "USGS 24k", "USGS 25k", "USGS 50k", "USGS 100k", "USGS 200k", "USGS 250k", NULL }; |
98 | static gdouble __mapzooms_x[] = { 0.0, 0.25, 0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 1.016, 2.4384, 2.54, 5.08, 10.16, 20.32, 25.4 }; | |
99 | static gdouble __mapzooms_y[] = { 0.0, 0.25, 0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 1.016, 2.4384, 2.54, 5.08, 10.16, 20.32, 25.4 }; | |
50a14534 | 100 | |
d756fb5c | 101 | #define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0]) - 1) |
50a14534 EB |
102 | |
103 | /**************************/ | |
104 | ||
105 | ||
07059501 | 106 | static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file); |
7924723c | 107 | static const gchar* maps_layer_tooltip ( VikMapsLayer *vml ); |
911400b5 AF |
108 | static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len ); |
109 | static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp ); | |
158b3642 RN |
110 | static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation ); |
111 | static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation ); | |
db43cfa4 | 112 | static void maps_layer_change_param ( GtkWidget *widget, ui_change_values values ); |
50a14534 EB |
113 | static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp ); |
114 | static VikMapsLayer *maps_layer_new ( VikViewport *vvp ); | |
115 | static void maps_layer_free ( VikMapsLayer *vml ); | |
116 | static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp ); | |
117 | static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp ); | |
941aa6e9 | 118 | static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp ); |
50a14534 EB |
119 | static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir ); |
120 | static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload ); | |
121 | static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp ); | |
e2cb421f | 122 | static guint map_uniq_id_to_index ( guint uniq_id ); |
50a14534 EB |
123 | |
124 | ||
125 | static VikLayerParamScale params_scales[] = { | |
126 | /* min, max, step, digits (decimal places) */ | |
127 | { 0, 255, 3, 0 }, /* alpha */ | |
128 | }; | |
129 | ||
8a5461eb | 130 | static VikLayerParamData id_default ( void ) { return VIK_LPD_UINT ( MAP_ID_MAPQUEST_OSM ); } |
a7023a1b RN |
131 | static VikLayerParamData directory_default ( void ) |
132 | { | |
133 | VikLayerParamData data; | |
b781c9db | 134 | VikLayerParamData *pref = a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir"); |
9414408e | 135 | if (pref) data.s = g_strdup ( pref->s ); else data.s = ""; |
a7023a1b RN |
136 | return data; |
137 | } | |
0fb11294 RN |
138 | static VikLayerParamData file_default ( void ) |
139 | { | |
140 | VikLayerParamData data; | |
141 | data.s = ""; | |
142 | return data; | |
143 | } | |
a7023a1b RN |
144 | static VikLayerParamData alpha_default ( void ) { return VIK_LPD_UINT ( 255 ); } |
145 | static VikLayerParamData mapzoom_default ( void ) { return VIK_LPD_UINT ( 0 ); } | |
146 | ||
d281e8b4 RN |
147 | static gchar *cache_types[] = { "Viking", N_("OSM"), NULL }; |
148 | static VikMapsCacheLayout cache_layout_default_value = VIK_MAPS_CACHE_LAYOUT_VIKING; | |
149 | static VikLayerParamData cache_layout_default ( void ) { return VIK_LPD_UINT ( cache_layout_default_value ); } | |
150 | ||
50a14534 | 151 | VikLayerParam maps_layer_params[] = { |
5a1e5516 RN |
152 | // NB mode => id - But can't break file format just to rename something better |
153 | { VIK_LAYER_MAPS, "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Map Type:"), VIK_LAYER_WIDGET_COMBOBOX, NULL, NULL, NULL, id_default, NULL, NULL }, | |
a87f8fa1 | 154 | { VIK_LAYER_MAPS, "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Maps Directory:"), VIK_LAYER_WIDGET_FOLDERENTRY, NULL, NULL, NULL, directory_default, NULL, NULL }, |
d281e8b4 RN |
155 | { VIK_LAYER_MAPS, "cache_type", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Cache Layout:"), VIK_LAYER_WIDGET_COMBOBOX, cache_types, NULL, |
156 | N_("This determines the tile storage layout on disk"), cache_layout_default, NULL, NULL }, | |
857baaa3 | 157 | { VIK_LAYER_MAPS, "mapfile", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Map File:"), VIK_LAYER_WIDGET_FILEENTRY, GINT_TO_POINTER(VF_FILTER_MBTILES), NULL, |
0fb11294 | 158 | N_("An MBTiles file. Only applies when the map type method is 'MBTiles'"), file_default, NULL, NULL }, |
a7023a1b | 159 | { VIK_LAYER_MAPS, "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales, NULL, |
a87f8fa1 RN |
160 | N_("Control the Alpha value for transparency effects"), alpha_default, NULL, NULL }, |
161 | { VIK_LAYER_MAPS, "autodownload", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload maps:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_true_default, NULL, NULL }, | |
56c6d6b2 | 162 | { VIK_LAYER_MAPS, "adlonlymissing", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload Only Gets Missing Maps:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, |
a87f8fa1 | 163 | N_("Using this option avoids attempting to update already acquired tiles. This can be useful if you want to restrict the network usage, without having to resort to manual control. Only applies when 'Autodownload Maps' is on."), vik_lpd_false_default, NULL, NULL }, |
a7023a1b RN |
164 | { VIK_LAYER_MAPS, "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms, NULL, |
165 | N_("Determines the method of displaying map tiles for the current zoom level. 'Viking Zoom Level' uses the best matching level, otherwise setting a fixed value will always use map tiles of the specified value regardless of the actual zoom level."), | |
a87f8fa1 | 166 | mapzoom_default, NULL, NULL }, |
50a14534 EB |
167 | }; |
168 | ||
382566c3 RN |
169 | enum { |
170 | PARAM_MAPTYPE=0, | |
171 | PARAM_CACHE_DIR, | |
d281e8b4 | 172 | PARAM_CACHE_LAYOUT, |
0fb11294 | 173 | PARAM_FILE, |
382566c3 RN |
174 | PARAM_ALPHA, |
175 | PARAM_AUTODOWNLOAD, | |
176 | PARAM_ONLYMISSING, | |
177 | PARAM_MAPZOOM, | |
178 | NUM_PARAMS | |
179 | }; | |
50a14534 | 180 | |
0d66c56c RN |
181 | void maps_layer_set_autodownload_default ( gboolean autodownload ) |
182 | { | |
183 | // Set appropriate function | |
184 | if ( autodownload ) | |
185 | maps_layer_params[PARAM_AUTODOWNLOAD].default_value = vik_lpd_true_default; | |
186 | else | |
187 | maps_layer_params[PARAM_AUTODOWNLOAD].default_value = vik_lpd_false_default; | |
188 | } | |
189 | ||
d281e8b4 RN |
190 | void maps_layer_set_cache_default ( VikMapsCacheLayout layout ) |
191 | { | |
192 | // Override default value returned by the default param function | |
193 | cache_layout_default_value = layout; | |
194 | } | |
195 | ||
50a14534 | 196 | static VikToolInterface maps_tools[] = { |
79dce0cb | 197 | { { "MapsDownload", "vik-icon-Maps Download", N_("_Maps Download"), NULL, N_("Maps Download"), 0 }, |
6b59f63d RN |
198 | (VikToolConstructorFunc) maps_layer_download_create, |
199 | NULL, | |
200 | NULL, | |
201 | NULL, | |
202 | (VikToolMouseFunc) maps_layer_download_click, | |
203 | NULL, | |
204 | (VikToolMouseFunc) maps_layer_download_release, | |
205 | NULL, | |
ef5e8132 | 206 | FALSE, |
63959706 | 207 | GDK_CURSOR_IS_PIXMAP, &cursor_mapdl_pixbuf, NULL }, |
50a14534 EB |
208 | }; |
209 | ||
210 | VikLayerInterface vik_maps_layer_interface = { | |
db386630 | 211 | "Map", |
4c77d5e0 | 212 | N_("Map"), |
75078768 | 213 | "<control><shift>M", |
5bfafde9 | 214 | &vikmapslayer_pixbuf, |
50a14534 EB |
215 | |
216 | maps_tools, | |
217 | sizeof(maps_tools) / sizeof(maps_tools[0]), | |
218 | ||
219 | maps_layer_params, | |
220 | NUM_PARAMS, | |
221 | NULL, | |
222 | 0, | |
223 | ||
5a4a28bf QT |
224 | VIK_MENU_ITEM_ALL, |
225 | ||
50a14534 EB |
226 | (VikLayerFuncCreate) maps_layer_new, |
227 | (VikLayerFuncRealize) NULL, | |
b112cbf5 | 228 | (VikLayerFuncPostRead) maps_layer_post_read, |
50a14534 EB |
229 | (VikLayerFuncFree) maps_layer_free, |
230 | ||
231 | (VikLayerFuncProperties) NULL, | |
232 | (VikLayerFuncDraw) maps_layer_draw, | |
233 | (VikLayerFuncChangeCoordMode) NULL, | |
234 | ||
20c7a3a0 QT |
235 | (VikLayerFuncSetMenuItemsSelection) NULL, |
236 | (VikLayerFuncGetMenuItemsSelection) NULL, | |
237 | ||
50a14534 EB |
238 | (VikLayerFuncAddMenuItems) maps_layer_add_menu_items, |
239 | (VikLayerFuncSublayerAddMenuItems) NULL, | |
240 | ||
241 | (VikLayerFuncSublayerRenameRequest) NULL, | |
242 | (VikLayerFuncSublayerToggleVisible) NULL, | |
9da7faf2 | 243 | (VikLayerFuncSublayerTooltip) NULL, |
7924723c | 244 | (VikLayerFuncLayerTooltip) maps_layer_tooltip, |
a5dcfdb7 | 245 | (VikLayerFuncLayerSelected) NULL, |
50a14534 | 246 | |
911400b5 AF |
247 | (VikLayerFuncMarshall) maps_layer_marshall, |
248 | (VikLayerFuncUnmarshall) maps_layer_unmarshall, | |
50a14534 EB |
249 | |
250 | (VikLayerFuncSetParam) maps_layer_set_param, | |
251 | (VikLayerFuncGetParam) maps_layer_get_param, | |
db43cfa4 | 252 | (VikLayerFuncChangeParam) maps_layer_change_param, |
50a14534 EB |
253 | |
254 | (VikLayerFuncReadFileData) NULL, | |
255 | (VikLayerFuncWriteFileData) NULL, | |
256 | ||
33534cd8 | 257 | (VikLayerFuncDeleteItem) NULL, |
d5874ef9 | 258 | (VikLayerFuncCutItem) NULL, |
50a14534 EB |
259 | (VikLayerFuncCopyItem) NULL, |
260 | (VikLayerFuncPasteItem) NULL, | |
261 | (VikLayerFuncFreeCopiedItem) NULL, | |
70a23263 | 262 | (VikLayerFuncDragDropRequest) NULL, |
77ad64fa RN |
263 | |
264 | (VikLayerFuncSelectClick) NULL, | |
08f14055 RN |
265 | (VikLayerFuncSelectMove) NULL, |
266 | (VikLayerFuncSelectRelease) NULL, | |
e46f259a | 267 | (VikLayerFuncSelectedViewportMenu) NULL, |
50a14534 EB |
268 | }; |
269 | ||
270 | struct _VikMapsLayer { | |
271 | VikLayer vl; | |
272 | guint maptype; | |
273 | gchar *cache_dir; | |
d281e8b4 | 274 | VikMapsCacheLayout cache_layout; |
50a14534 EB |
275 | guint8 alpha; |
276 | guint mapzoom_id; | |
277 | gdouble xmapzoom, ymapzoom; | |
278 | ||
279 | gboolean autodownload; | |
382566c3 | 280 | gboolean adl_only_missing; |
10ca2bfe QT |
281 | VikCoord *last_center; |
282 | gdouble last_xmpp; | |
283 | gdouble last_ympp; | |
50a14534 EB |
284 | |
285 | gint dl_tool_x, dl_tool_y; | |
286 | ||
287 | GtkMenu *dl_right_click_menu; | |
288 | VikCoord redownload_ul, redownload_br; /* right click menu only */ | |
289 | VikViewport *redownload_vvp; | |
0fb11294 RN |
290 | gchar *filename; |
291 | #ifdef HAVE_SQLITE3_H | |
292 | sqlite3 *mbtiles; | |
293 | #endif | |
50a14534 EB |
294 | }; |
295 | ||
6a4a29aa JJ |
296 | enum { REDOWNLOAD_NONE = 0, /* download only missing maps */ |
297 | REDOWNLOAD_BAD, /* download missing and bad maps */ | |
298 | REDOWNLOAD_NEW, /* download missing maps that are newer on server only */ | |
299 | REDOWNLOAD_ALL, /* download all maps */ | |
300 | DOWNLOAD_OR_REFRESH }; /* download missing maps and refresh cache */ | |
50a14534 | 301 | |
55ddef4e | 302 | static VikLayerParam prefs[] = { |
63959706 | 303 | { VIK_LAYER_NUM_TYPES, VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Default map layer directory:"), VIK_LAYER_WIDGET_FOLDERENTRY, NULL, NULL, N_("Choose a directory to store cached Map tiles for this layer"), NULL, NULL, NULL }, |
55ddef4e JJ |
304 | }; |
305 | ||
306 | void maps_layer_init () | |
307 | { | |
308 | VikLayerParamData tmp; | |
309 | tmp.s = maps_layer_default_dir(); | |
310 | a_preferences_register(prefs, tmp, VIKING_PREFERENCES_GROUP_KEY); | |
0f7e9133 RN |
311 | |
312 | gint max_tiles = MAX_TILES; | |
313 | if ( a_settings_get_integer ( VIK_SETTINGS_MAP_MAX_TILES, &max_tiles ) ) | |
314 | MAX_TILES = max_tiles; | |
315 | ||
316 | gdouble gdtmp; | |
317 | if ( a_settings_get_double ( VIK_SETTINGS_MAP_MIN_SHRINKFACTOR, &gdtmp ) ) | |
318 | MIN_SHRINKFACTOR = gdtmp; | |
319 | ||
320 | if ( a_settings_get_double ( VIK_SETTINGS_MAP_MAX_SHRINKFACTOR, &gdtmp ) ) | |
321 | MAX_SHRINKFACTOR = gdtmp; | |
322 | ||
323 | if ( a_settings_get_double ( VIK_SETTINGS_MAP_REAL_MIN_SHRINKFACTOR, &gdtmp ) ) | |
324 | REAL_MIN_SHRINKFACTOR = gdtmp; | |
d1871cd2 RN |
325 | |
326 | gint gitmp = 0; | |
327 | if ( a_settings_get_integer ( VIK_SETTINGS_MAP_SCALE_INC_UP, &gitmp ) ) | |
328 | SCALE_INC_UP = gitmp; | |
329 | ||
330 | if ( a_settings_get_integer ( VIK_SETTINGS_MAP_SCALE_INC_DOWN, &gitmp ) ) | |
331 | SCALE_INC_DOWN = gitmp; | |
332 | ||
333 | gboolean gbtmp = TRUE; | |
334 | if ( a_settings_get_boolean ( VIK_SETTINGS_MAP_SCALE_SMALLER_ZOOM_FIRST, &gbtmp ) ) | |
335 | SCALE_SMALLER_ZOOM_FIRST = gbtmp; | |
336 | ||
55ddef4e | 337 | } |
50a14534 | 338 | |
cdcaf41c QT |
339 | /****************************************/ |
340 | /******** MAPS LAYER TYPES **************/ | |
341 | /****************************************/ | |
342 | ||
5a1e5516 | 343 | void _add_map_source ( guint16 id, const char *label, VikMapSource *map ) |
e2cb421f | 344 | { |
a8876892 GB |
345 | gsize len = 0; |
346 | if (params_maptypes) | |
347 | len = g_strv_length (params_maptypes); | |
cdcaf41c | 348 | /* Add the label */ |
a8876892 GB |
349 | params_maptypes = g_realloc (params_maptypes, (len+2)*sizeof(gchar*)); |
350 | params_maptypes[len] = g_strdup (label); | |
351 | params_maptypes[len+1] = NULL; | |
cdcaf41c QT |
352 | |
353 | /* Add the id */ | |
a8876892 GB |
354 | params_maptypes_ids = g_realloc (params_maptypes_ids, (len+2)*sizeof(guint)); |
355 | params_maptypes_ids[len] = id; | |
356 | params_maptypes_ids[len+1] = 0; | |
cdcaf41c QT |
357 | |
358 | /* We have to clone */ | |
820c59f4 | 359 | VikMapSource *clone = VIK_MAP_SOURCE(g_object_ref(map)); |
cdcaf41c QT |
360 | /* Register the clone in the list */ |
361 | __map_types = g_list_append(__map_types, clone); | |
362 | ||
363 | /* Hack | |
e2cb421f | 364 | We have to ensure the mode LayerParam references the up-to-date |
cdcaf41c QT |
365 | GLists. |
366 | */ | |
367 | /* | |
368 | memcpy(&maps_layer_params[0].widget_data, ¶ms_maptypes, sizeof(gpointer)); | |
369 | memcpy(&maps_layer_params[0].extra_widget_data, ¶ms_maptypes_ids, sizeof(gpointer)); | |
370 | */ | |
371 | maps_layer_params[0].widget_data = params_maptypes; | |
372 | maps_layer_params[0].extra_widget_data = params_maptypes_ids; | |
373 | } | |
374 | ||
e2cb421f GB |
375 | void _update_map_source ( const char *label, VikMapSource *map, int index ) |
376 | { | |
377 | GList *item = g_list_nth (__map_types, index); | |
378 | g_object_unref (item->data); | |
379 | item->data = g_object_ref (map); | |
380 | /* Change previous data */ | |
381 | g_free (params_maptypes[index]); | |
382 | params_maptypes[index] = g_strdup (label); | |
383 | } | |
384 | ||
17281ebd GB |
385 | /** |
386 | * maps_layer_register_map_source: | |
387 | * @map: the new VikMapSource | |
388 | * | |
389 | * Register a new VikMapSource. | |
390 | * Override existing one (equality of id). | |
391 | */ | |
e2cb421f GB |
392 | void maps_layer_register_map_source ( VikMapSource *map ) |
393 | { | |
394 | g_assert(map != NULL); | |
395 | ||
5a1e5516 | 396 | guint16 id = vik_map_source_get_uniq_id(map); |
e2cb421f GB |
397 | const char *label = vik_map_source_get_label(map); |
398 | g_assert(label != NULL); | |
399 | ||
400 | int previous = map_uniq_id_to_index (id); | |
401 | if (previous != NUM_MAP_TYPES) | |
402 | { | |
403 | _update_map_source (label, map, previous); | |
404 | } | |
405 | else | |
406 | { | |
407 | _add_map_source (id, label, map); | |
408 | } | |
409 | } | |
410 | ||
a8876892 GB |
411 | #define MAPS_LAYER_NTH_LABEL(n) (params_maptypes[n]) |
412 | #define MAPS_LAYER_NTH_ID(n) (params_maptypes_ids[n]) | |
820c59f4 | 413 | #define MAPS_LAYER_NTH_TYPE(n) (VIK_MAP_SOURCE(g_list_nth_data(__map_types, (n)))) |
cdcaf41c | 414 | |
c82f9c94 RN |
415 | /** |
416 | * vik_maps_layer_get_map_type: | |
417 | * | |
418 | * Returns the actual map id (rather than the internal type index value) | |
419 | */ | |
420 | guint vik_maps_layer_get_map_type(VikMapsLayer *vml) | |
7114e879 | 421 | { |
c82f9c94 | 422 | return MAPS_LAYER_NTH_ID(vml->maptype); |
7114e879 QT |
423 | } |
424 | ||
114d6588 RN |
425 | /** |
426 | * vik_maps_layer_set_map_type: | |
427 | * | |
428 | */ | |
429 | void vik_maps_layer_set_map_type(VikMapsLayer *vml, guint map_type) | |
430 | { | |
431 | gint maptype = map_uniq_id_to_index(map_type); | |
432 | if ( maptype == NUM_MAP_TYPES ) | |
433 | g_warning(_("Unknown map type")); | |
434 | else | |
435 | vml->maptype = maptype; | |
436 | } | |
437 | ||
438 | /** | |
439 | * vik_maps_layer_get_default_map_type: | |
440 | * | |
441 | */ | |
442 | guint vik_maps_layer_get_default_map_type () | |
443 | { | |
444 | VikLayerInterface *vli = vik_layer_get_interface ( VIK_LAYER_MAPS ); | |
445 | VikLayerParamData vlpd = a_layer_defaults_get ( vli->fixed_layer_name, "mode", VIK_LAYER_PARAM_UINT ); | |
446 | if ( vlpd.u == 0 ) | |
447 | vlpd = id_default(); | |
448 | return vlpd.u; | |
449 | } | |
450 | ||
7114e879 QT |
451 | gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml) |
452 | { | |
453 | return(g_strdup(MAPS_LAYER_NTH_LABEL(vml->maptype))); | |
454 | } | |
455 | ||
50a14534 EB |
456 | /****************************************/ |
457 | /******** CACHE DIR STUFF ***************/ | |
458 | /****************************************/ | |
459 | ||
2673b29d | 460 | #define DIRECTDIRACCESS "%s%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d%s" |
2eb18edc | 461 | #define DIRECTDIRACCESS_WITH_NAME "%s%s" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d%s" |
3d9454e6 | 462 | #define DIRSTRUCTURE "%st%ds%dz%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d" |
6a27c1bc MA |
463 | #define MAPS_CACHE_DIR maps_layer_default_dir() |
464 | ||
50a14534 | 465 | #ifdef WINDOWS |
6a27c1bc MA |
466 | #include <io.h> |
467 | #define GLOBAL_MAPS_DIR "C:\\VIKING-MAPS\\" | |
468 | #define LOCAL_MAPS_DIR "VIKING-MAPS" | |
42293fc2 RN |
469 | #elif defined __APPLE__ |
470 | #include <stdlib.h> | |
471 | #define GLOBAL_MAPS_DIR "/Library/cache/Viking/maps/" | |
472 | #define LOCAL_MAPS_DIR "/Library/Application Support/Viking/viking-maps" | |
50a14534 | 473 | #else /* POSIX */ |
50a14534 | 474 | #include <stdlib.h> |
50a14534 | 475 | #define GLOBAL_MAPS_DIR "/var/cache/maps/" |
6a27c1bc MA |
476 | #define LOCAL_MAPS_DIR ".viking-maps" |
477 | #endif | |
50a14534 | 478 | |
0c1044e9 | 479 | gchar *maps_layer_default_dir () |
50a14534 | 480 | { |
3d9454e6 GB |
481 | static gchar *defaultdir = NULL; |
482 | if ( ! defaultdir ) | |
50a14534 EB |
483 | { |
484 | /* Thanks to Mike Davison for the $VIKING_MAPS usage */ | |
3d9454e6 GB |
485 | const gchar *mapdir = g_getenv("VIKING_MAPS"); |
486 | if ( mapdir ) { | |
487 | defaultdir = g_strdup ( mapdir ); | |
45acf79e | 488 | } else if ( g_access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) { |
3d9454e6 | 489 | defaultdir = g_strdup ( GLOBAL_MAPS_DIR ); |
50a14534 | 490 | } else { |
6a27c1bc | 491 | const gchar *home = g_get_home_dir(); |
45acf79e | 492 | if (!home || g_access(home, W_OK)) |
3d9454e6 GB |
493 | home = g_get_home_dir (); |
494 | if ( home ) | |
6a27c1bc | 495 | defaultdir = g_build_filename ( home, LOCAL_MAPS_DIR, NULL ); |
50a14534 | 496 | else |
6a27c1bc | 497 | defaultdir = g_strdup ( LOCAL_MAPS_DIR ); |
50a14534 | 498 | } |
3d9454e6 GB |
499 | if (defaultdir && (defaultdir[strlen(defaultdir)-1] != G_DIR_SEPARATOR)) |
500 | { | |
501 | /* Add the separator at the end */ | |
502 | gchar *tmp = defaultdir; | |
503 | defaultdir = g_strconcat(tmp, G_DIR_SEPARATOR_S, NULL); | |
504 | g_free(tmp); | |
505 | } | |
506 | g_debug("%s: defaultdir=%s", __FUNCTION__, defaultdir); | |
50a14534 EB |
507 | } |
508 | return defaultdir; | |
509 | } | |
510 | ||
50a14534 EB |
511 | static void maps_layer_mkdir_if_default_dir ( VikMapsLayer *vml ) |
512 | { | |
45acf79e | 513 | if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && g_file_test ( vml->cache_dir, G_FILE_TEST_EXISTS ) == FALSE ) |
50a14534 | 514 | { |
f83131b9 | 515 | g_mkdir ( vml->cache_dir, 0777 ); |
50a14534 EB |
516 | } |
517 | } | |
518 | ||
519 | static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir ) | |
520 | { | |
50a14534 | 521 | g_assert ( vml != NULL); |
e65028db GB |
522 | g_free ( vml->cache_dir ); |
523 | vml->cache_dir = NULL; | |
32f1d63a | 524 | const gchar *mydir = dir; |
50a14534 EB |
525 | |
526 | if ( dir == NULL || dir[0] == '\0' ) | |
6926d79a RN |
527 | { |
528 | if ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir") ) | |
32f1d63a | 529 | mydir = a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir")->s; |
6926d79a | 530 | } |
32f1d63a | 531 | |
1b14d0d2 RN |
532 | gchar *canonical_dir = vu_get_canonical_filename ( VIK_LAYER(vml), mydir ); |
533 | ||
32f1d63a | 534 | // Ensure cache_dir always ends with a separator |
1b14d0d2 RN |
535 | guint len = strlen(canonical_dir); |
536 | if ( canonical_dir[len-1] != G_DIR_SEPARATOR ) | |
50a14534 | 537 | { |
1b14d0d2 RN |
538 | vml->cache_dir = g_strconcat ( canonical_dir, G_DIR_SEPARATOR_S, NULL ); |
539 | g_free ( canonical_dir ); | |
540 | } | |
541 | else { | |
542 | vml->cache_dir = canonical_dir; | |
50a14534 | 543 | } |
32f1d63a | 544 | |
50a14534 EB |
545 | maps_layer_mkdir_if_default_dir ( vml ); |
546 | } | |
547 | ||
0fb11294 RN |
548 | static void maps_layer_set_file ( VikMapsLayer *vml, const gchar *name ) |
549 | { | |
550 | if ( vml->filename ) | |
551 | g_free (vml->filename); | |
552 | vml->filename = g_strdup (name); | |
553 | } | |
554 | ||
50a14534 EB |
555 | /****************************************/ |
556 | /******** GOBJECT STUFF *****************/ | |
557 | /****************************************/ | |
558 | ||
559 | GType vik_maps_layer_get_type () | |
560 | { | |
561 | static GType vml_type = 0; | |
562 | ||
563 | if (!vml_type) | |
564 | { | |
565 | static const GTypeInfo vml_info = | |
566 | { | |
567 | sizeof (VikMapsLayerClass), | |
568 | NULL, /* base_init */ | |
569 | NULL, /* base_finalize */ | |
570 | NULL, /* class init */ | |
571 | NULL, /* class_finalize */ | |
572 | NULL, /* class_data */ | |
573 | sizeof (VikMapsLayer), | |
574 | 0, | |
575 | NULL /* instance init */ | |
576 | }; | |
577 | vml_type = g_type_register_static ( VIK_LAYER_TYPE, "VikMapsLayer", &vml_info, 0 ); | |
578 | } | |
579 | ||
580 | return vml_type; | |
581 | } | |
582 | ||
583 | /****************************************/ | |
584 | /************** PARAMETERS **************/ | |
585 | /****************************************/ | |
586 | ||
d7e495b2 | 587 | static guint map_index_to_uniq_id (guint16 index) |
50a14534 EB |
588 | { |
589 | g_assert ( index < NUM_MAP_TYPES ); | |
820c59f4 | 590 | return vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(index)); |
50a14534 EB |
591 | } |
592 | ||
593 | static guint map_uniq_id_to_index ( guint uniq_id ) | |
594 | { | |
595 | gint i; | |
596 | for ( i = 0; i < NUM_MAP_TYPES; i++ ) | |
820c59f4 | 597 | if ( vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(i)) == uniq_id ) |
50a14534 EB |
598 | return i; |
599 | return NUM_MAP_TYPES; /* no such thing */ | |
600 | } | |
601 | ||
b03ae39b RN |
602 | #define VIK_SETTINGS_MAP_LICENSE_SHOWN "map_license_shown" |
603 | ||
604 | /** | |
605 | * Convenience function to display the license | |
606 | */ | |
607 | static void maps_show_license ( GtkWindow *parent, VikMapSource *map ) | |
192e40fc | 608 | { |
b03ae39b RN |
609 | a_dialog_license ( parent, |
610 | vik_map_source_get_label (map), | |
611 | vik_map_source_get_license (map), | |
612 | vik_map_source_get_license_url (map) ); | |
192e40fc RN |
613 | } |
614 | ||
158b3642 | 615 | static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation ) |
50a14534 EB |
616 | { |
617 | switch ( id ) | |
618 | { | |
619 | case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break; | |
d281e8b4 | 620 | case PARAM_CACHE_LAYOUT: if ( data.u < VIK_MAPS_CACHE_LAYOUT_NUM ) vml->cache_layout = data.u; break; |
0fb11294 | 621 | case PARAM_FILE: maps_layer_set_file ( vml, data.s ); break; |
50a14534 EB |
622 | case PARAM_MAPTYPE: { |
623 | gint maptype = map_uniq_id_to_index(data.u); | |
b03ae39b RN |
624 | if ( maptype == NUM_MAP_TYPES ) |
625 | g_warning(_("Unknown map type")); | |
626 | else { | |
627 | vml->maptype = maptype; | |
628 | ||
629 | // When loading from a file don't need the license reminder - ensure it's saved into the 'seen' list | |
630 | if ( is_file_operation ) { | |
fad0a3f9 | 631 | a_settings_set_integer_list_containing ( VIK_SETTINGS_MAP_LICENSE_SHOWN, data.u ); |
b03ae39b RN |
632 | } |
633 | else { | |
634 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); | |
635 | if (vik_map_source_get_license (map) != NULL) { | |
636 | // Check if licence for this map type has been shown before | |
fad0a3f9 | 637 | if ( ! a_settings_get_integer_list_contains ( VIK_SETTINGS_MAP_LICENSE_SHOWN, data.u ) ) { |
b03ae39b RN |
638 | if ( vvp ) |
639 | maps_show_license ( VIK_GTK_WINDOW_FROM_WIDGET(vvp), map ); | |
fad0a3f9 | 640 | a_settings_set_integer_list_containing ( VIK_SETTINGS_MAP_LICENSE_SHOWN, data.u ); |
b03ae39b RN |
641 | } |
642 | } | |
643 | } | |
644 | } | |
50a14534 EB |
645 | break; |
646 | } | |
647 | case PARAM_ALPHA: if ( data.u <= 255 ) vml->alpha = data.u; break; | |
648 | case PARAM_AUTODOWNLOAD: vml->autodownload = data.b; break; | |
382566c3 | 649 | case PARAM_ONLYMISSING: vml->adl_only_missing = data.b; break; |
50a14534 EB |
650 | case PARAM_MAPZOOM: if ( data.u < NUM_MAPZOOMS ) { |
651 | vml->mapzoom_id = data.u; | |
652 | vml->xmapzoom = __mapzooms_x [data.u]; | |
653 | vml->ymapzoom = __mapzooms_y [data.u]; | |
4c77d5e0 | 654 | }else g_warning (_("Unknown Map Zoom")); break; |
9351abc4 | 655 | default: break; |
50a14534 EB |
656 | } |
657 | return TRUE; | |
658 | } | |
659 | ||
158b3642 | 660 | static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation ) |
50a14534 EB |
661 | { |
662 | VikLayerParamData rv; | |
663 | switch ( id ) | |
664 | { | |
cde1e50e | 665 | case PARAM_CACHE_DIR: |
88542aa9 RN |
666 | { |
667 | gboolean set = FALSE; | |
cde1e50e RN |
668 | /* Only save a blank when the map cache location equals the default |
669 | On reading in, when it is blank then the default is reconstructed | |
670 | Since the default changes dependent on the user and OS, it means the resultant file is more portable */ | |
88542aa9 | 671 | if ( is_file_operation && vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 ) { |
cde1e50e | 672 | rv.s = ""; |
88542aa9 RN |
673 | set = TRUE; |
674 | } | |
675 | else if ( is_file_operation ) { | |
676 | if ( a_vik_get_file_ref_format() == VIK_FILE_REF_FORMAT_RELATIVE ) { | |
677 | gchar *cwd = g_get_current_dir(); | |
678 | if ( cwd ) { | |
679 | rv.s = file_GetRelativeFilename ( cwd, vml->cache_dir ); | |
680 | if ( !rv.s ) rv.s = ""; | |
681 | set = TRUE; | |
682 | } | |
683 | } | |
684 | } | |
685 | if ( !set ) | |
686 | rv.s = vml->cache_dir ? vml->cache_dir : ""; | |
cde1e50e | 687 | break; |
88542aa9 | 688 | } |
d281e8b4 | 689 | case PARAM_CACHE_LAYOUT: rv.u = vml->cache_layout; break; |
0fb11294 | 690 | case PARAM_FILE: rv.s = vml->filename; break; |
50a14534 EB |
691 | case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break; |
692 | case PARAM_ALPHA: rv.u = vml->alpha; break; | |
693 | case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break; | |
382566c3 | 694 | case PARAM_ONLYMISSING: rv.u = vml->adl_only_missing; break; |
50a14534 | 695 | case PARAM_MAPZOOM: rv.u = vml->mapzoom_id; break; |
9351abc4 | 696 | default: break; |
50a14534 EB |
697 | } |
698 | return rv; | |
699 | } | |
700 | ||
db43cfa4 RN |
701 | static void maps_layer_change_param ( GtkWidget *widget, ui_change_values values ) |
702 | { | |
703 | switch ( GPOINTER_TO_INT(values[UI_CHG_PARAM_ID]) ) { | |
0fb11294 RN |
704 | // Alter sensitivity of download option widgets according to the maptype setting. |
705 | case PARAM_MAPTYPE: { | |
706 | // Get new value | |
707 | VikLayerParamData vlpd = a_uibuilder_widget_get_value ( widget, values[UI_CHG_PARAM] ); | |
99f0d7df RN |
708 | // Is it *not* the OSM On Disk Tile Layout or the MBTiles type or the OSM Metatiles type |
709 | gboolean sensitive = ( 21 != vlpd.u && 23 != vlpd.u && 24 != vlpd.u ); | |
0fb11294 RN |
710 | GtkWidget **ww1 = values[UI_CHG_WIDGETS]; |
711 | GtkWidget **ww2 = values[UI_CHG_LABELS]; | |
712 | GtkWidget *w1 = ww1[PARAM_ONLYMISSING]; | |
713 | GtkWidget *w2 = ww2[PARAM_ONLYMISSING]; | |
714 | GtkWidget *w3 = ww1[PARAM_AUTODOWNLOAD]; | |
715 | GtkWidget *w4 = ww2[PARAM_AUTODOWNLOAD]; | |
716 | // Depends on autodownload value | |
717 | gboolean missing_sense = sensitive && VIK_MAPS_LAYER(values[UI_CHG_LAYER])->autodownload; | |
718 | if ( w1 ) gtk_widget_set_sensitive ( w1, missing_sense ); | |
719 | if ( w2 ) gtk_widget_set_sensitive ( w2, missing_sense ); | |
720 | if ( w3 ) gtk_widget_set_sensitive ( w3, sensitive ); | |
721 | if ( w4 ) gtk_widget_set_sensitive ( w4, sensitive ); | |
722 | ||
d281e8b4 RN |
723 | // Cache type not applicable either |
724 | GtkWidget *w9 = ww1[PARAM_CACHE_LAYOUT]; | |
725 | GtkWidget *w10 = ww2[PARAM_CACHE_LAYOUT]; | |
726 | if ( w9 ) gtk_widget_set_sensitive ( w9, sensitive ); | |
727 | if ( w10 ) gtk_widget_set_sensitive ( w10, sensitive ); | |
728 | ||
0fb11294 RN |
729 | // File only applicable for MBTiles type |
730 | // Directory for all other types | |
731 | sensitive = ( 23 == vlpd.u); | |
732 | GtkWidget *w5 = ww1[PARAM_FILE]; | |
733 | GtkWidget *w6 = ww2[PARAM_FILE]; | |
734 | GtkWidget *w7 = ww1[PARAM_CACHE_DIR]; | |
735 | GtkWidget *w8 = ww2[PARAM_CACHE_DIR]; | |
736 | if ( w5 ) gtk_widget_set_sensitive ( w5, sensitive ); | |
737 | if ( w6 ) gtk_widget_set_sensitive ( w6, sensitive ); | |
738 | if ( w7 ) gtk_widget_set_sensitive ( w7, !sensitive ); | |
739 | if ( w8 ) gtk_widget_set_sensitive ( w8, !sensitive ); | |
740 | ||
741 | break; | |
742 | } | |
743 | ||
db43cfa4 RN |
744 | // Alter sensitivity of 'download only missing' widgets according to the autodownload setting. |
745 | case PARAM_AUTODOWNLOAD: { | |
746 | // Get new value | |
747 | VikLayerParamData vlpd = a_uibuilder_widget_get_value ( widget, values[UI_CHG_PARAM] ); | |
748 | GtkWidget **ww1 = values[UI_CHG_WIDGETS]; | |
749 | GtkWidget **ww2 = values[UI_CHG_LABELS]; | |
750 | GtkWidget *w1 = ww1[PARAM_ONLYMISSING]; | |
751 | GtkWidget *w2 = ww2[PARAM_ONLYMISSING]; | |
752 | if ( w1 ) gtk_widget_set_sensitive ( w1, vlpd.b ); | |
753 | if ( w2 ) gtk_widget_set_sensitive ( w2, vlpd.b ); | |
754 | break; | |
755 | } | |
756 | default: break; | |
757 | } | |
758 | } | |
759 | ||
50a14534 EB |
760 | /****************************************/ |
761 | /****** CREATING, COPYING, FREEING ******/ | |
762 | /****************************************/ | |
763 | ||
764 | static VikMapsLayer *maps_layer_new ( VikViewport *vvp ) | |
765 | { | |
766 | VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) ); | |
a0c65899 | 767 | vik_layer_set_type ( VIK_LAYER(vml), VIK_LAYER_MAPS ); |
a7023a1b RN |
768 | |
769 | vik_layer_set_defaults ( VIK_LAYER(vml), vvp ); | |
770 | ||
50a14534 | 771 | vml->dl_tool_x = vml->dl_tool_y = -1; |
10ca2bfe QT |
772 | vml->last_center = NULL; |
773 | vml->last_xmpp = 0.0; | |
774 | vml->last_ympp = 0.0; | |
50a14534 EB |
775 | |
776 | vml->dl_right_click_menu = NULL; | |
0fb11294 | 777 | vml->filename = NULL; |
50a14534 EB |
778 | return vml; |
779 | } | |
780 | ||
781 | static void maps_layer_free ( VikMapsLayer *vml ) | |
782 | { | |
e65028db GB |
783 | g_free ( vml->cache_dir ); |
784 | vml->cache_dir = NULL; | |
50a14534 | 785 | if ( vml->dl_right_click_menu ) |
4f14a010 | 786 | g_object_ref_sink ( G_OBJECT(vml->dl_right_click_menu) ); |
e65028db GB |
787 | g_free(vml->last_center); |
788 | vml->last_center = NULL; | |
0fb11294 RN |
789 | g_free ( vml->filename ); |
790 | vml->filename = NULL; | |
791 | ||
792 | #ifdef HAVE_SQLITE3_H | |
793 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); | |
794 | if ( vik_map_source_is_mbtiles ( map ) ) { | |
795 | if ( vml->mbtiles ) { | |
796 | int ans = sqlite3_close ( vml->mbtiles ); | |
797 | if ( ans != SQLITE_OK ) { | |
798 | // Only to console for information purposes only | |
799 | g_warning ( "SQL Close problem: %d", ans ); | |
800 | } | |
801 | } | |
802 | } | |
803 | #endif | |
50a14534 EB |
804 | } |
805 | ||
07059501 | 806 | static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file) |
dc5758d3 | 807 | { |
0fb11294 RN |
808 | VikMapsLayer *vml = VIK_MAPS_LAYER(vl); |
809 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); | |
810 | ||
a8c22c3f | 811 | if (!from_file) |
07059501 GB |
812 | { |
813 | /* If this method is not called in file reading context | |
814 | * it is called in GUI context. | |
815 | * So, we can check if we have to inform the user about inconsistency */ | |
816 | VikViewportDrawMode vp_drawmode; | |
405b74ed | 817 | vp_drawmode = vik_viewport_get_drawmode ( vp ); |
0fb11294 | 818 | |
820c59f4 | 819 | if (vik_map_source_get_drawmode(map) != vp_drawmode) { |
405b74ed | 820 | const gchar *drawmode_name = vik_viewport_get_drawmode_name (vp, vik_map_source_get_drawmode(map)); |
4c77d5e0 | 821 | gchar *msg = g_strdup_printf(_("New map cannot be displayed in the current drawmode.\nSelect \"%s\" from View menu to view it."), drawmode_name); |
eb0fbfa9 | 822 | a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp), msg ); |
07059501 GB |
823 | g_free(msg); |
824 | } | |
dc5758d3 | 825 | } |
0fb11294 RN |
826 | |
827 | // Performed in post read as we now know the map type | |
828 | #ifdef HAVE_SQLITE3_H | |
829 | // Do some SQL stuff | |
830 | if ( vik_map_source_is_mbtiles ( map ) ) { | |
831 | int ans = sqlite3_open_v2 ( vml->filename, | |
832 | &(vml->mbtiles), | |
833 | SQLITE_OPEN_READONLY, | |
834 | NULL ); | |
835 | if ( ans != SQLITE_OK ) { | |
836 | // That didn't work, so here's why: | |
837 | g_warning ( "%s: %s", __FUNCTION__, sqlite3_errmsg ( vml->mbtiles ) ); | |
838 | ||
839 | a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_WIDGET(vp), | |
840 | _("Failed to open MBTiles file: %s"), | |
841 | vml->filename ); | |
842 | vml->mbtiles = NULL; | |
843 | } | |
844 | } | |
845 | #endif | |
df5b2993 RN |
846 | |
847 | // If the on Disk OSM Tile Layout type | |
848 | if ( vml->maptype == 21 ) | |
849 | // Copy the directory into filename | |
850 | // thus the mapcache look up will be unique when using more than one of these map types | |
851 | vml->filename = g_strdup (vml->cache_dir); | |
dc5758d3 GB |
852 | } |
853 | ||
7924723c RN |
854 | static const gchar* maps_layer_tooltip ( VikMapsLayer *vml ) |
855 | { | |
856 | return vik_maps_layer_get_map_label ( vml ); | |
857 | } | |
858 | ||
911400b5 AF |
859 | static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len ) |
860 | { | |
861 | vik_layer_marshall_params ( VIK_LAYER(vml), data, len ); | |
862 | } | |
863 | ||
864 | static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp ) | |
865 | { | |
866 | VikMapsLayer *rv = maps_layer_new ( vvp ); | |
867 | vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp ); | |
d7e776d0 | 868 | maps_layer_post_read ( VIK_LAYER(rv), vvp, FALSE ); |
911400b5 AF |
869 | return rv; |
870 | } | |
871 | ||
50a14534 EB |
872 | /*********************/ |
873 | /****** DRAWING ******/ | |
874 | /*********************/ | |
875 | ||
50a14534 EB |
876 | static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdouble yshrinkfactor ) |
877 | { | |
878 | GdkPixbuf *tmp; | |
879 | guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf); | |
2d5d32c1 | 880 | tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_BILINEAR); |
50a14534 EB |
881 | g_object_unref ( G_OBJECT(pixbuf) ); |
882 | return tmp; | |
883 | } | |
884 | ||
0fb11294 RN |
885 | #ifdef HAVE_SQLITE3_H |
886 | /* | |
887 | static int sql_select_tile_dump_cb (void *data, int cols, char **fields, char **col_names ) | |
888 | { | |
889 | g_warning ( "Found %d columns", cols ); | |
890 | int i; | |
891 | for ( i = 0; i < cols; i++ ) { | |
892 | g_warning ( "SQL processing %s = %s", col_names[i], fields[i] ); | |
893 | } | |
894 | return 0; | |
895 | } | |
896 | */ | |
897 | ||
898 | /** | |
899 | * | |
900 | */ | |
901 | static GdkPixbuf *get_pixbuf_sql_exec ( sqlite3 *sql, gint xx, gint yy, gint zoom ) | |
902 | { | |
903 | GdkPixbuf *pixbuf = NULL; | |
904 | ||
905 | // MBTiles stored internally with the flipping y thingy (i.e. TMS scheme). | |
906 | gint flip_y = (gint) pow(2, zoom)-1 - yy; | |
907 | gchar *statement = g_strdup_printf ( "SELECT tile_data FROM tiles WHERE zoom_level=%d AND tile_column=%d AND tile_row=%d;", zoom, xx, flip_y ); | |
908 | ||
909 | gboolean finished = FALSE; | |
910 | ||
911 | sqlite3_stmt *sql_stmt = NULL; | |
912 | int ans = sqlite3_prepare_v2 ( sql, statement, -1, &sql_stmt, NULL ); | |
913 | if ( ans != SQLITE_OK ) { | |
914 | g_warning ( "%s: %s - %d", __FUNCTION__, "prepare failure", ans ); | |
915 | finished = TRUE; | |
916 | } | |
917 | ||
918 | while ( !finished ) { | |
919 | ans = sqlite3_step ( sql_stmt ); | |
920 | switch (ans) { | |
921 | case SQLITE_ROW: { | |
922 | // Get tile_data blob | |
923 | int count = sqlite3_column_count(sql_stmt); | |
924 | if ( count != 1 ) { | |
925 | g_warning ( "%s: %s - %d", __FUNCTION__, "count not one", count ); | |
926 | finished = TRUE; | |
927 | } | |
928 | else { | |
929 | const void *data = sqlite3_column_blob ( sql_stmt, 0 ); | |
930 | int bytes = sqlite3_column_bytes ( sql_stmt, 0 ); | |
931 | if ( bytes < 1 ) { | |
932 | g_warning ( "%s: %s (%d)", __FUNCTION__, "not enough bytes", bytes ); | |
933 | finished = TRUE; | |
934 | } | |
935 | else { | |
936 | // Convert these blob bytes into a pixbuf via these streaming operations | |
937 | GInputStream *stream = g_memory_input_stream_new_from_data ( data, bytes, NULL ); | |
938 | GError *error = NULL; | |
939 | pixbuf = gdk_pixbuf_new_from_stream ( stream, NULL, &error ); | |
940 | if (error || (!pixbuf)) { | |
941 | g_warning ( "%s: %s", __FUNCTION__, error->message ); | |
942 | g_error_free ( error ); | |
943 | } | |
944 | g_input_stream_close ( stream, NULL, NULL ); | |
945 | } | |
946 | } | |
947 | break; | |
948 | } | |
949 | default: | |
950 | // e.g. SQLITE_DONE | SQLITE_ERROR | SQLITE_MISUSE | etc... | |
951 | // Finished normally | |
952 | // and give up on any errors | |
953 | if ( ans != SQLITE_DONE ) | |
954 | g_warning ( "%s: %s - %d", __FUNCTION__, "step issue", ans ); | |
955 | finished = TRUE; | |
956 | break; | |
957 | } | |
958 | } | |
959 | ans = sqlite3_finalize ( sql_stmt ); | |
960 | ||
961 | g_free ( statement ); | |
962 | ||
963 | return pixbuf; | |
964 | } | |
965 | #endif | |
966 | ||
967 | static GdkPixbuf *get_mbtiles_pixbuf ( VikMapsLayer *vml, gint xx, gint yy, gint zoom ) | |
968 | { | |
969 | GdkPixbuf *pixbuf = NULL; | |
970 | ||
971 | #ifdef HAVE_SQLITE3_H | |
972 | if ( vml->mbtiles ) { | |
973 | /* | |
974 | gchar *statement = g_strdup_printf ( "SELECT name FROM sqlite_master WHERE type='table';" ); | |
975 | char *errMsg = NULL; | |
976 | int ans = sqlite3_exec ( vml->mbtiles, statement, sql_select_tile_dump_cb, pixbuf, &errMsg ); | |
977 | if ( ans != SQLITE_OK ) { | |
978 | // Only to console for information purposes only | |
979 | g_warning ( "SQL problem: %d for %s - error: %s", ans, statement, errMsg ); | |
980 | sqlite3_free( errMsg ); | |
981 | } | |
982 | g_free ( statement ); | |
983 | */ | |
984 | ||
985 | // Reading BLOBS is a bit more involved and so can't use the simpler sqlite3_exec () | |
986 | // Hence this specific function | |
987 | pixbuf = get_pixbuf_sql_exec ( vml->mbtiles, xx, yy, zoom ); | |
988 | } | |
989 | #endif | |
990 | ||
991 | return pixbuf; | |
992 | } | |
993 | ||
99f0d7df RN |
994 | static GdkPixbuf *get_pixbuf_from_metatile ( VikMapsLayer *vml, gint xx, gint yy, gint zz ) |
995 | { | |
996 | const int tile_max = METATILE_MAX_SIZE; | |
997 | char err_msg[PATH_MAX]; | |
998 | char *buf; | |
999 | int len; | |
1000 | int compressed; | |
1001 | ||
1002 | buf = malloc(tile_max); | |
1003 | if (!buf) { | |
1004 | return NULL; | |
1005 | } | |
1006 | ||
1007 | err_msg[0] = 0; | |
1008 | len = metatile_read(vml->cache_dir, xx, yy, zz, buf, tile_max, &compressed, err_msg); | |
1009 | ||
1010 | if (len > 0) { | |
1011 | if (compressed) { | |
1012 | // Not handled yet - I don't think this is used often - so implement later if necessary | |
1013 | g_warning ( "Compressed metatiles not implemented:%s\n", __FUNCTION__); | |
1014 | return NULL; | |
1015 | } | |
1016 | ||
1017 | // Convert these buf bytes into a pixbuf via these streaming operations | |
1018 | GdkPixbuf *pixbuf = NULL; | |
1019 | ||
1020 | GInputStream *stream = g_memory_input_stream_new_from_data ( buf, len, NULL ); | |
1021 | GError *error = NULL; | |
1022 | pixbuf = gdk_pixbuf_new_from_stream ( stream, NULL, &error ); | |
1023 | if (error || (!pixbuf)) { | |
1024 | g_warning ( "%s: %s", __FUNCTION__, error->message ); | |
1025 | g_error_free ( error ); | |
1026 | } | |
1027 | g_input_stream_close ( stream, NULL, NULL ); | |
1028 | ||
1029 | free(buf); | |
1030 | return pixbuf; | |
1031 | } | |
1032 | else { | |
1033 | g_warning ( "FAILED:%s %s", __FUNCTION__, err_msg); | |
1034 | return NULL; | |
1035 | } | |
1036 | } | |
1037 | ||
1038 | ||
0fb11294 RN |
1039 | static GdkPixbuf *pixbuf_apply_settings ( GdkPixbuf *pixbuf, VikMapsLayer *vml, MapCoord *mapcoord, gdouble xshrinkfactor, gdouble yshrinkfactor ) |
1040 | { | |
1041 | // Apply alpha setting | |
1042 | if ( pixbuf && vml->alpha < 255 ) | |
5cca6c53 | 1043 | pixbuf = ui_pixbuf_set_alpha ( pixbuf, vml->alpha ); |
0fb11294 RN |
1044 | |
1045 | if ( pixbuf && ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 ) ) | |
1046 | pixbuf = pixbuf_shrink ( pixbuf, xshrinkfactor, yshrinkfactor ); | |
1047 | ||
1048 | if ( pixbuf ) | |
1049 | a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y, | |
1050 | mapcoord->z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(vml->maptype)), | |
df5b2993 | 1051 | mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor, vml->filename ); |
0fb11294 RN |
1052 | |
1053 | return pixbuf; | |
1054 | } | |
1055 | ||
2eb18edc RN |
1056 | static void get_filename ( const gchar *cache_dir, |
1057 | VikMapsCacheLayout cl, | |
5a1e5516 | 1058 | guint16 id, |
2eb18edc RN |
1059 | const gchar *name, |
1060 | gint scale, | |
1061 | gint z, | |
1062 | gint x, | |
1063 | gint y, | |
1064 | gchar *filename_buf, | |
14b57d17 RN |
1065 | gint buf_len, |
1066 | const gchar* file_extension ) | |
d281e8b4 RN |
1067 | { |
1068 | switch ( cl ) { | |
1069 | case VIK_MAPS_CACHE_LAYOUT_OSM: | |
2eb18edc RN |
1070 | if ( name ) { |
1071 | if ( g_strcmp0 ( cache_dir, MAPS_CACHE_DIR ) ) | |
1072 | // Cache dir not the default - assume it's been directed somewhere specific | |
14b57d17 | 1073 | g_snprintf ( filename_buf, buf_len, DIRECTDIRACCESS, cache_dir, (17 - scale), x, y, file_extension ); |
2eb18edc RN |
1074 | else |
1075 | // Using default cache - so use the map name in the directory path | |
14b57d17 | 1076 | g_snprintf ( filename_buf, buf_len, DIRECTDIRACCESS_WITH_NAME, cache_dir, name, (17 - scale), x, y, file_extension ); |
2eb18edc RN |
1077 | } |
1078 | else | |
14b57d17 | 1079 | g_snprintf ( filename_buf, buf_len, DIRECTDIRACCESS, cache_dir, (17 - scale), x, y, file_extension ); |
d281e8b4 RN |
1080 | break; |
1081 | default: | |
5a1e5516 | 1082 | g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE, cache_dir, id, scale, z, x, y ); |
d281e8b4 RN |
1083 | break; |
1084 | } | |
1085 | } | |
1086 | ||
5a1e5516 | 1087 | static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, guint16 id, const gchar* mapname, MapCoord *mapcoord, gchar *filename_buf, gint buf_len, gdouble xshrinkfactor, gdouble yshrinkfactor ) |
50a14534 EB |
1088 | { |
1089 | GdkPixbuf *pixbuf; | |
1090 | ||
1091 | /* get the thing */ | |
1092 | pixbuf = a_mapcache_get ( mapcoord->x, mapcoord->y, mapcoord->z, | |
5a1e5516 | 1093 | id, mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor, vml->filename ); |
50a14534 EB |
1094 | |
1095 | if ( ! pixbuf ) { | |
14b57d17 RN |
1096 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); |
1097 | if ( vik_map_source_is_direct_file_access(map) ) { | |
0fb11294 | 1098 | // ATM MBTiles must be 'a direct access type' |
14b57d17 | 1099 | if ( vik_map_source_is_mbtiles(map) ) { |
0fb11294 RN |
1100 | pixbuf = get_mbtiles_pixbuf ( vml, mapcoord->x, mapcoord->y, (17 - mapcoord->scale) ); |
1101 | pixbuf = pixbuf_apply_settings ( pixbuf, vml, mapcoord, xshrinkfactor, yshrinkfactor ); | |
1102 | // return now to avoid file tests that aren't appropriate for this map type | |
1103 | return pixbuf; | |
1104 | } | |
99f0d7df RN |
1105 | else if ( vik_map_source_is_osm_meta_tiles(map) ) { |
1106 | pixbuf = get_pixbuf_from_metatile ( vml, mapcoord->x, mapcoord->y, (17 - mapcoord->scale) ); | |
1107 | pixbuf = pixbuf_apply_settings ( pixbuf, vml, mapcoord, xshrinkfactor, yshrinkfactor ); | |
1108 | return pixbuf; | |
1109 | } | |
0fb11294 | 1110 | else |
5a1e5516 | 1111 | get_filename ( vml->cache_dir, VIK_MAPS_CACHE_LAYOUT_OSM, id, NULL, |
14b57d17 RN |
1112 | mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y, filename_buf, buf_len, |
1113 | vik_map_source_get_file_extension(map) ); | |
0fb11294 | 1114 | } |
2673b29d | 1115 | else |
5a1e5516 | 1116 | get_filename ( vml->cache_dir, vml->cache_layout, id, mapname, |
14b57d17 RN |
1117 | mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y, filename_buf, buf_len, |
1118 | vik_map_source_get_file_extension(map) ); | |
2673b29d | 1119 | |
01ecda7e | 1120 | if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE) |
50a14534 EB |
1121 | { |
1122 | GError *gx = NULL; | |
1123 | pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx ); | |
1124 | ||
01ecda7e | 1125 | /* free the pixbuf on error */ |
50a14534 EB |
1126 | if (gx) |
1127 | { | |
d17be106 RN |
1128 | if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE ) { |
1129 | // Report a warning | |
1130 | if ( IS_VIK_WINDOW ((VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(vml)) ) { | |
1131 | gchar* msg = g_strdup_printf ( _("Couldn't open image file: %s"), gx->message ); | |
1132 | vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(vml), msg, VIK_STATUSBAR_INFO ); | |
1133 | g_free (msg); | |
1134 | } | |
1135 | } | |
50a14534 | 1136 | |
01ecda7e MR |
1137 | g_error_free ( gx ); |
1138 | if ( pixbuf ) | |
1139 | g_object_unref ( G_OBJECT(pixbuf) ); | |
1140 | pixbuf = NULL; | |
1141 | } else { | |
0fb11294 | 1142 | pixbuf = pixbuf_apply_settings ( pixbuf, vml, mapcoord, xshrinkfactor, yshrinkfactor ); |
50a14534 EB |
1143 | } |
1144 | } | |
1145 | } | |
1146 | return pixbuf; | |
1147 | } | |
1148 | ||
9979924f | 1149 | static gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp) |
10ca2bfe QT |
1150 | { |
1151 | const VikCoord *center = vik_viewport_get_center ( vvp ); | |
1152 | ||
bbf2149b | 1153 | if (vik_window_get_pan_move (VIK_WINDOW(VIK_GTK_WINDOW_FROM_WIDGET(GTK_WIDGET(vvp))))) |
01da6b4d | 1154 | /* D'n'D pan in action: do not download */ |
1c6a6010 GB |
1155 | return FALSE; |
1156 | ||
e633ddef | 1157 | // Don't attempt to download unsupported zoom levels |
9979924f | 1158 | gdouble xzoom = vik_viewport_get_xmpp ( vvp ); |
e633ddef RN |
1159 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); |
1160 | guint8 zl = map_utils_mpp_to_zoom_level ( xzoom ); | |
1161 | if ( zl < vik_map_source_get_zoom_min(map) || zl > vik_map_source_get_zoom_max(map) ) | |
9979924f RN |
1162 | return FALSE; |
1163 | ||
10ca2bfe QT |
1164 | if (vml->last_center == NULL) { |
1165 | VikCoord *new_center = g_malloc(sizeof(VikCoord)); | |
1166 | *new_center = *center; | |
1167 | vml->last_center = new_center; | |
1168 | vml->last_xmpp = vik_viewport_get_xmpp(vvp); | |
1169 | vml->last_ympp = vik_viewport_get_ympp(vvp); | |
1170 | return TRUE; | |
1171 | } | |
1172 | ||
1173 | /* TODO: perhaps vik_coord_diff() */ | |
1174 | if (vik_coord_equals(vml->last_center, center) | |
1175 | && (vml->last_xmpp == vik_viewport_get_xmpp(vvp)) | |
1176 | && (vml->last_ympp == vik_viewport_get_ympp(vvp))) | |
1177 | return FALSE; | |
1178 | ||
1179 | *(vml->last_center) = *center; | |
1180 | vml->last_xmpp = vik_viewport_get_xmpp(vvp); | |
1181 | vml->last_ympp = vik_viewport_get_ympp(vvp); | |
1182 | return TRUE; | |
1183 | } | |
1184 | ||
d1871cd2 RN |
1185 | /** |
1186 | * | |
1187 | */ | |
1188 | gboolean try_draw_scale_down (VikMapsLayer *vml, VikViewport *vvp, MapCoord ulm, gint xx, gint yy, gint tilesize_x_ceil, gint tilesize_y_ceil, | |
1189 | gdouble xshrinkfactor, gdouble yshrinkfactor, guint id, const gchar *mapname, gchar *path_buf, guint max_path_len) | |
1190 | { | |
1191 | GdkPixbuf *pixbuf; | |
1192 | int scale_inc; | |
1193 | for (scale_inc = 1; scale_inc < SCALE_INC_DOWN; scale_inc ++) { | |
1194 | // Try with smaller zooms | |
1195 | int scale_factor = 1 << scale_inc; /* 2^scale_inc */ | |
1196 | MapCoord ulm2 = ulm; | |
1197 | ulm2.x = ulm.x / scale_factor; | |
1198 | ulm2.y = ulm.y / scale_factor; | |
1199 | ulm2.scale = ulm.scale + scale_inc; | |
1200 | pixbuf = get_pixbuf ( vml, id, mapname, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor ); | |
1201 | if ( pixbuf ) { | |
1202 | gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil; | |
1203 | gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil; | |
1204 | vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil ); | |
1205 | return TRUE; | |
1206 | } | |
1207 | } | |
1208 | return FALSE; | |
1209 | } | |
1210 | ||
1211 | /** | |
1212 | * | |
1213 | */ | |
1214 | gboolean try_draw_scale_up (VikMapsLayer *vml, VikViewport *vvp, MapCoord ulm, gint xx, gint yy, gint tilesize_x_ceil, gint tilesize_y_ceil, | |
1215 | gdouble xshrinkfactor, gdouble yshrinkfactor, guint id, const gchar *mapname, gchar *path_buf, guint max_path_len) | |
1216 | { | |
1217 | GdkPixbuf *pixbuf; | |
1218 | // Try with bigger zooms | |
1219 | int scale_dec; | |
1220 | for (scale_dec = 1; scale_dec < SCALE_INC_UP; scale_dec ++) { | |
1221 | int pict_x, pict_y; | |
1222 | int scale_factor = 1 << scale_dec; /* 2^scale_dec */ | |
1223 | MapCoord ulm2 = ulm; | |
1224 | ulm2.x = ulm.x * scale_factor; | |
1225 | ulm2.y = ulm.y * scale_factor; | |
1226 | ulm2.scale = ulm.scale - scale_dec; | |
1227 | for (pict_x = 0; pict_x < scale_factor; pict_x ++) { | |
1228 | for (pict_y = 0; pict_y < scale_factor; pict_y ++) { | |
1229 | MapCoord ulm3 = ulm2; | |
1230 | ulm3.x += pict_x; | |
1231 | ulm3.y += pict_y; | |
1232 | pixbuf = get_pixbuf ( vml, id, mapname, &ulm3, path_buf, max_path_len, xshrinkfactor / scale_factor, yshrinkfactor / scale_factor ); | |
1233 | if ( pixbuf ) { | |
1234 | gint src_x = 0; | |
1235 | gint src_y = 0; | |
1236 | gint dest_x = xx + pict_x * (tilesize_x_ceil / scale_factor); | |
1237 | gint dest_y = yy + pict_y * (tilesize_y_ceil / scale_factor); | |
1238 | vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, dest_x, dest_y, tilesize_x_ceil / scale_factor, tilesize_y_ceil / scale_factor ); | |
1239 | return TRUE; | |
1240 | } | |
1241 | } | |
1242 | } | |
1243 | } | |
1244 | return FALSE; | |
1245 | } | |
1246 | ||
50a14534 EB |
1247 | static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br ) |
1248 | { | |
1249 | MapCoord ulm, brm; | |
1250 | gdouble xzoom = vik_viewport_get_xmpp ( vvp ); | |
1251 | gdouble yzoom = vik_viewport_get_ympp ( vvp ); | |
1252 | gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0; | |
2673b29d | 1253 | gboolean existence_only = FALSE; |
50a14534 EB |
1254 | |
1255 | if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) { | |
1256 | xshrinkfactor = vml->xmapzoom / xzoom; | |
1257 | yshrinkfactor = vml->ymapzoom / yzoom; | |
732d1e25 EB |
1258 | xzoom = vml->xmapzoom; |
1259 | yzoom = vml->xmapzoom; | |
1260 | if ( ! (xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR && | |
1261 | yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) ) { | |
6de95419 RN |
1262 | if ( xshrinkfactor > REAL_MIN_SHRINKFACTOR && yshrinkfactor > REAL_MIN_SHRINKFACTOR ) { |
1263 | g_debug ( "%s: existence_only due to SHRINKFACTORS", __FUNCTION__ ); | |
732d1e25 | 1264 | existence_only = TRUE; |
6de95419 | 1265 | } |
732d1e25 | 1266 | else { |
d17be106 RN |
1267 | // Report the reason for not drawing |
1268 | if ( IS_VIK_WINDOW ((VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(vml)) ) { | |
1269 | gchar* msg = g_strdup_printf ( _("Cowardly refusing to draw tiles or existence of tiles beyond %d zoom out factor"), (int)( 1.0/REAL_MIN_SHRINKFACTOR)); | |
1270 | vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(vml), msg, VIK_STATUSBAR_INFO ); | |
1271 | g_free (msg); | |
1272 | } | |
732d1e25 EB |
1273 | return; |
1274 | } | |
50a14534 EB |
1275 | } |
1276 | } | |
1277 | ||
1278 | /* coord -> ID */ | |
820c59f4 GB |
1279 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); |
1280 | if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm ) && | |
1281 | vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) ) { | |
50a14534 EB |
1282 | |
1283 | /* loop & draw */ | |
1284 | gint x, y; | |
1285 | gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x); | |
1286 | gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y); | |
5a1e5516 | 1287 | guint16 id = vik_map_source_get_uniq_id(map); |
2eb18edc | 1288 | const gchar *mapname = vik_map_source_get_name(map); |
50a14534 EB |
1289 | |
1290 | VikCoord coord; | |
1291 | gint xx, yy, width, height; | |
1292 | GdkPixbuf *pixbuf; | |
1293 | ||
6de95419 RN |
1294 | // Prevent the program grinding to a halt if trying to deal with thousands of tiles |
1295 | // which can happen when using a small fixed zoom level and viewing large areas. | |
1296 | // Also prevents very large number of tile download requests | |
1297 | gint tiles = (xmax-xmin) * (ymax-ymin); | |
1298 | if ( tiles > MAX_TILES ) { | |
1299 | g_debug ( "%s: existence_only due to wanting too many tiles (%d)", __FUNCTION__, tiles ); | |
1300 | existence_only = TRUE; | |
1301 | } | |
1302 | ||
50a14534 EB |
1303 | guint max_path_len = strlen(vml->cache_dir) + 40; |
1304 | gchar *path_buf = g_malloc ( max_path_len * sizeof(char) ); | |
1305 | ||
732d1e25 | 1306 | if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) { |
33be396e | 1307 | g_debug("%s: Starting autodownload", __FUNCTION__); |
382566c3 | 1308 | if ( !vml->adl_only_missing && vik_map_source_supports_download_only_new (map) ) |
245f48f5 GB |
1309 | // Try to download newer tiles |
1310 | start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW ); | |
1311 | else | |
1312 | // Download only missing tiles | |
1313 | start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE ); | |
10ca2bfe | 1314 | } |
50a14534 | 1315 | |
820c59f4 | 1316 | if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) { |
50a14534 EB |
1317 | for ( x = xmin; x <= xmax; x++ ) { |
1318 | for ( y = ymin; y <= ymax; y++ ) { | |
1319 | ulm.x = x; | |
1320 | ulm.y = y; | |
5a1e5516 | 1321 | pixbuf = get_pixbuf ( vml, id, mapname, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor ); |
50a14534 EB |
1322 | if ( pixbuf ) { |
1323 | width = gdk_pixbuf_get_width ( pixbuf ); | |
1324 | height = gdk_pixbuf_get_height ( pixbuf ); | |
1325 | ||
820c59f4 | 1326 | vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord ); |
50a14534 EB |
1327 | vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy ); |
1328 | xx -= (width/2); | |
1329 | yy -= (height/2); | |
1330 | ||
1331 | vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height ); | |
1332 | } | |
1333 | } | |
1334 | } | |
1335 | } else { /* tilesize is known, don't have to keep converting coords */ | |
820c59f4 GB |
1336 | gdouble tilesize_x = vik_map_source_get_tilesize_x(map) * xshrinkfactor; |
1337 | gdouble tilesize_y = vik_map_source_get_tilesize_y(map) * yshrinkfactor; | |
50a14534 EB |
1338 | /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */ |
1339 | gint tilesize_x_ceil = ceil ( tilesize_x ); | |
1340 | gint tilesize_y_ceil = ceil ( tilesize_y ); | |
1341 | gint8 xinc = (ulm.x == xmin) ? 1 : -1; | |
1342 | gint8 yinc = (ulm.y == ymin) ? 1 : -1; | |
c60f82df | 1343 | gint xx_tmp, yy_tmp; |
50a14534 | 1344 | gint base_yy, xend, yend; |
732d1e25 | 1345 | |
50a14534 EB |
1346 | xend = (xinc == 1) ? (xmax+1) : (xmin-1); |
1347 | yend = (yinc == 1) ? (ymax+1) : (ymin-1); | |
1348 | ||
820c59f4 | 1349 | vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord ); |
50a14534 EB |
1350 | vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp ); |
1351 | xx = xx_tmp; yy = yy_tmp; | |
1352 | /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off | |
1353 | * eg if tile size 128, shrinkfactor 0.333 */ | |
1354 | xx -= (tilesize_x/2); | |
1355 | base_yy = yy - (tilesize_y/2); | |
1356 | ||
1357 | for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) { | |
1358 | yy = base_yy; | |
1359 | for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) { | |
1360 | ulm.x = x; | |
1361 | ulm.y = y; | |
732d1e25 EB |
1362 | |
1363 | if ( existence_only ) { | |
d281e8b4 | 1364 | if ( vik_map_source_is_direct_file_access (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) |
5a1e5516 | 1365 | get_filename ( vml->cache_dir, VIK_MAPS_CACHE_LAYOUT_OSM, id, vik_map_source_get_name(map), |
14b57d17 | 1366 | ulm.scale, ulm.z, ulm.x, ulm.y, path_buf, max_path_len, vik_map_source_get_file_extension(map) ); |
d281e8b4 | 1367 | else |
5a1e5516 | 1368 | get_filename ( vml->cache_dir, vml->cache_layout, id, vik_map_source_get_name(map), |
14b57d17 | 1369 | ulm.scale, ulm.z, ulm.x, ulm.y, path_buf, max_path_len, vik_map_source_get_file_extension(map) ); |
d281e8b4 | 1370 | |
45acf79e | 1371 | if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) { |
ff37db21 | 1372 | GdkGC *black_gc = gtk_widget_get_style(GTK_WIDGET(vvp))->black_gc; |
732d1e25 EB |
1373 | vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil ); |
1374 | } | |
1375 | } else { | |
d1871cd2 RN |
1376 | // Try correct scale first |
1377 | int scale_factor = 1; | |
1378 | pixbuf = get_pixbuf ( vml, id, mapname, &ulm, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor ); | |
1379 | if ( pixbuf ) { | |
1380 | gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil; | |
1381 | gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil; | |
1382 | vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil ); | |
6f0d1bea | 1383 | } |
d1871cd2 RN |
1384 | else { |
1385 | // Otherwise try different scales | |
1386 | if ( SCALE_SMALLER_ZOOM_FIRST ) { | |
1387 | if ( !try_draw_scale_down(vml,vvp,ulm,xx,yy,tilesize_x_ceil,tilesize_y_ceil,xshrinkfactor,yshrinkfactor,id,mapname,path_buf,max_path_len) ) { | |
1388 | try_draw_scale_up(vml,vvp,ulm,xx,yy,tilesize_x_ceil,tilesize_y_ceil,xshrinkfactor,yshrinkfactor,id,mapname,path_buf,max_path_len); | |
1389 | } | |
1390 | } | |
1391 | else { | |
1392 | if ( !try_draw_scale_up(vml,vvp,ulm,xx,yy,tilesize_x_ceil,tilesize_y_ceil,xshrinkfactor,yshrinkfactor,id,mapname,path_buf,max_path_len) ) { | |
1393 | try_draw_scale_down(vml,vvp,ulm,xx,yy,tilesize_x_ceil,tilesize_y_ceil,xshrinkfactor,yshrinkfactor,id,mapname,path_buf,max_path_len); | |
91dc4449 JJ |
1394 | } |
1395 | } | |
1396 | } | |
732d1e25 | 1397 | } |
50a14534 EB |
1398 | |
1399 | yy += tilesize_y; | |
1400 | } | |
1401 | xx += tilesize_x; | |
1402 | } | |
50a14534 | 1403 | |
33f1dade RN |
1404 | // ATM Only show tile grid lines in extreme debug mode |
1405 | if ( vik_debug && vik_verbose ) { | |
1406 | /* Grid drawing here so it gets drawn on top of the map */ | |
1407 | /* Thus loop around x & y again, but this time separately */ | |
1408 | /* Only showing grid for the current scale */ | |
1409 | GdkGC *black_gc = GTK_WIDGET(vvp)->style->black_gc; | |
1410 | /* Draw single grid lines across the whole screen */ | |
1411 | gint width = vik_viewport_get_width(vvp); | |
1412 | gint height = vik_viewport_get_height(vvp); | |
1413 | xx = xx_tmp; yy = yy_tmp; | |
1414 | gint base_xx = xx - (tilesize_x/2); | |
1415 | base_yy = yy - (tilesize_y/2); | |
1416 | ||
1417 | xx = base_xx; | |
1418 | for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) { | |
1419 | vik_viewport_draw_line ( vvp, black_gc, xx, base_yy, xx, height ); | |
1420 | xx += tilesize_x; | |
1421 | } | |
1422 | ||
1423 | yy = base_yy; | |
1424 | for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) { | |
1425 | vik_viewport_draw_line ( vvp, black_gc, base_xx, yy, width, yy ); | |
1426 | yy += tilesize_y; | |
1427 | } | |
1428 | } | |
1429 | ||
1430 | } | |
50a14534 EB |
1431 | g_free ( path_buf ); |
1432 | } | |
1433 | } | |
1434 | ||
1435 | static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp ) | |
1436 | { | |
820c59f4 | 1437 | if ( vik_map_source_get_drawmode(MAPS_LAYER_NTH_TYPE(vml->maptype)) == vik_viewport_get_drawmode ( vvp ) ) |
50a14534 EB |
1438 | { |
1439 | VikCoord ul, br; | |
1440 | ||
82aa018d | 1441 | /* Copyright */ |
68b1d6c0 GB |
1442 | gdouble level = vik_viewport_get_zoom ( vvp ); |
1443 | LatLonBBox bbox; | |
1444 | vik_viewport_get_min_max_lat_lon ( vvp, &bbox.south, &bbox.north, &bbox.west, &bbox.east ); | |
1445 | vik_map_source_get_copyright ( MAPS_LAYER_NTH_TYPE(vml->maptype), bbox, level, vik_viewport_add_copyright, vvp ); | |
82aa018d | 1446 | |
26336cf0 GB |
1447 | /* Logo */ |
1448 | const GdkPixbuf *logo = vik_map_source_get_logo ( MAPS_LAYER_NTH_TYPE(vml->maptype) ); | |
1449 | vik_viewport_add_logo ( vvp, logo ); | |
1450 | ||
50a14534 EB |
1451 | /* get corner coords */ |
1452 | if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) { | |
1453 | /* UTM multi-zone stuff by Kit Transue */ | |
1454 | gchar leftmost_zone, rightmost_zone, i; | |
1455 | leftmost_zone = vik_viewport_leftmost_zone( vvp ); | |
1456 | rightmost_zone = vik_viewport_rightmost_zone( vvp ); | |
1457 | for ( i = leftmost_zone; i <= rightmost_zone; ++i ) { | |
1458 | vik_viewport_corners_for_zonen ( vvp, i, &ul, &br ); | |
1459 | maps_layer_draw_section ( vml, vvp, &ul, &br ); | |
1460 | } | |
1461 | } | |
1462 | else { | |
1463 | vik_viewport_screen_to_coord ( vvp, 0, 0, &ul ); | |
1464 | vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br ); | |
1465 | ||
1466 | maps_layer_draw_section ( vml, vvp, &ul, &br ); | |
1467 | } | |
1468 | } | |
1469 | } | |
1470 | ||
1471 | /*************************/ | |
1472 | /****** DOWNLOADING ******/ | |
1473 | /*************************/ | |
1474 | ||
1475 | /* pass along data to thread, exists even if layer is deleted. */ | |
1476 | typedef struct { | |
1477 | gchar *cache_dir; | |
1478 | gchar *filename_buf; | |
d281e8b4 | 1479 | VikMapsCacheLayout cache_layout; |
50a14534 EB |
1480 | gint x0, y0, xf, yf; |
1481 | MapCoord mapcoord; | |
1482 | gint maptype; | |
1483 | gint maxlen; | |
1484 | gint mapstoget; | |
1485 | gint redownload; | |
7114e879 | 1486 | gboolean refresh_display; |
550fd035 QT |
1487 | VikMapsLayer *vml; |
1488 | VikViewport *vvp; | |
1489 | gboolean map_layer_alive; | |
1490 | GMutex *mutex; | |
50a14534 EB |
1491 | } MapDownloadInfo; |
1492 | ||
1493 | static void mdi_free ( MapDownloadInfo *mdi ) | |
1494 | { | |
fc6640a9 | 1495 | vik_mutex_free(mdi->mutex); |
50a14534 | 1496 | g_free ( mdi->cache_dir ); |
e65028db | 1497 | mdi->cache_dir = NULL; |
50a14534 | 1498 | g_free ( mdi->filename_buf ); |
e65028db | 1499 | mdi->filename_buf = NULL; |
50a14534 EB |
1500 | g_free ( mdi ); |
1501 | } | |
1502 | ||
7bb60307 | 1503 | static void weak_ref_cb(gpointer ptr, GObject * dead_vml) |
550fd035 | 1504 | { |
7bb60307 | 1505 | MapDownloadInfo *mdi = ptr; |
550fd035 QT |
1506 | g_mutex_lock(mdi->mutex); |
1507 | mdi->map_layer_alive = FALSE; | |
1508 | g_mutex_unlock(mdi->mutex); | |
1509 | } | |
1510 | ||
2113a507 RN |
1511 | static gboolean is_in_area (VikMapSource *map, MapCoord mc) |
1512 | { | |
1513 | VikCoord vc; | |
1514 | vik_map_source_mapcoord_to_center_coord ( map, &mc, &vc ); | |
1515 | ||
1516 | struct LatLon tl; | |
1517 | tl.lat = vik_map_source_get_lat_max(map); | |
1518 | tl.lon = vik_map_source_get_lon_min(map); | |
1519 | struct LatLon br; | |
1520 | br.lat = vik_map_source_get_lat_min(map); | |
1521 | br.lon = vik_map_source_get_lon_max(map); | |
1522 | VikCoord vctl; | |
1523 | vik_coord_load_from_latlon (&vctl, VIK_COORD_LATLON, &tl); | |
1524 | VikCoord vcbr; | |
1525 | vik_coord_load_from_latlon (&vcbr, VIK_COORD_LATLON, &br); | |
1526 | ||
1527 | return vik_coord_inside ( &vc, &vctl, &vcbr ); | |
1528 | } | |
1529 | ||
634eca0a | 1530 | static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata ) |
50a14534 | 1531 | { |
825413ba | 1532 | void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype)); |
50a14534 | 1533 | guint donemaps = 0; |
2113a507 | 1534 | MapCoord mcoord = mdi->mapcoord; |
50a14534 EB |
1535 | gint x, y; |
1536 | for ( x = mdi->x0; x <= mdi->xf; x++ ) | |
1537 | { | |
2113a507 | 1538 | mcoord.x = x; |
50a14534 EB |
1539 | for ( y = mdi->y0; y <= mdi->yf; y++ ) |
1540 | { | |
2113a507 RN |
1541 | mcoord.y = y; |
1542 | // Only attempt to download a tile from supported areas | |
1543 | if ( is_in_area ( MAPS_LAYER_NTH_TYPE(mdi->maptype), mcoord ) ) | |
1544 | { | |
1545 | gboolean remove_mem_cache = FALSE; | |
1546 | gboolean need_download = FALSE; | |
84628352 | 1547 | |
2113a507 RN |
1548 | get_filename ( mdi->cache_dir, mdi->cache_layout, |
1549 | vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)), | |
1550 | vik_map_source_get_name(MAPS_LAYER_NTH_TYPE(mdi->maptype)), | |
1551 | mdi->mapcoord.scale, mdi->mapcoord.z, x, y, mdi->filename_buf, mdi->maxlen, | |
1552 | vik_map_source_get_file_extension(MAPS_LAYER_NTH_TYPE(mdi->maptype)) ); | |
1553 | ||
1554 | donemaps++; | |
1555 | int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */ | |
1556 | if (res != 0) { | |
1557 | vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle); | |
1558 | return -1; | |
1559 | } | |
a0058e48 | 1560 | |
2113a507 RN |
1561 | if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) { |
1562 | need_download = TRUE; | |
1563 | remove_mem_cache = TRUE; | |
a0058e48 | 1564 | |
2113a507 RN |
1565 | } else { /* in case map file already exists */ |
1566 | switch (mdi->redownload) { | |
1567 | case REDOWNLOAD_NONE: | |
1568 | continue; | |
1569 | ||
1570 | case REDOWNLOAD_BAD: | |
1571 | { | |
1572 | /* see if this one is bad or what */ | |
1573 | GError *gx = NULL; | |
1574 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx ); | |
1575 | if (gx || (!pixbuf)) { | |
1576 | g_remove ( mdi->filename_buf ); | |
1577 | need_download = TRUE; | |
1578 | remove_mem_cache = TRUE; | |
1579 | g_error_free ( gx ); | |
a0058e48 | 1580 | |
2113a507 RN |
1581 | } else { |
1582 | g_object_unref ( pixbuf ); | |
1583 | } | |
1584 | break; | |
a0058e48 | 1585 | } |
a0058e48 | 1586 | |
2113a507 RN |
1587 | case REDOWNLOAD_NEW: |
1588 | need_download = TRUE; | |
1589 | remove_mem_cache = TRUE; | |
1590 | break; | |
a0058e48 | 1591 | |
2113a507 RN |
1592 | case REDOWNLOAD_ALL: |
1593 | /* FIXME: need a better way than to erase file in case of server/network problem */ | |
1594 | g_remove ( mdi->filename_buf ); | |
1595 | need_download = TRUE; | |
1596 | remove_mem_cache = TRUE; | |
1597 | break; | |
a0058e48 | 1598 | |
2113a507 RN |
1599 | case DOWNLOAD_OR_REFRESH: |
1600 | remove_mem_cache = TRUE; | |
1601 | break; | |
a0058e48 | 1602 | |
2113a507 RN |
1603 | default: |
1604 | g_warning ( "redownload state %d unknown\n", mdi->redownload); | |
1605 | } | |
a0058e48 | 1606 | } |
94493114 | 1607 | |
2113a507 RN |
1608 | mdi->mapcoord.x = x; mdi->mapcoord.y = y; |
1609 | ||
1610 | if (need_download) { | |
1611 | DownloadResult_t dr = vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle); | |
1612 | switch ( dr ) { | |
1613 | case DOWNLOAD_HTTP_ERROR: | |
1614 | case DOWNLOAD_CONTENT_ERROR: { | |
1615 | // TODO: ?? count up the number of download errors somehow... | |
1616 | gchar* msg = g_strdup_printf ( "%s: %s", vik_maps_layer_get_map_label (mdi->vml), _("Failed to download tile") ); | |
1617 | vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(mdi->vml), msg, VIK_STATUSBAR_INFO ); | |
1618 | g_free (msg); | |
1619 | break; | |
1620 | } | |
1621 | case DOWNLOAD_FILE_WRITE_ERROR: { | |
1622 | gchar* msg = g_strdup_printf ( "%s: %s", vik_maps_layer_get_map_label (mdi->vml), _("Unable to save tile") ); | |
1623 | vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(mdi->vml), msg, VIK_STATUSBAR_INFO ); | |
1624 | g_free (msg); | |
1625 | break; | |
1626 | } | |
1627 | case DOWNLOAD_SUCCESS: | |
1628 | case DOWNLOAD_NOT_REQUIRED: | |
1629 | default: | |
1630 | break; | |
4e815e90 | 1631 | } |
4e815e90 | 1632 | } |
94493114 | 1633 | |
2113a507 RN |
1634 | g_mutex_lock(mdi->mutex); |
1635 | if (remove_mem_cache) | |
1636 | a_mapcache_remove_all_shrinkfactors ( x, y, mdi->mapcoord.z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)), mdi->mapcoord.scale ); | |
1637 | if (mdi->refresh_display && mdi->map_layer_alive) { | |
1638 | /* TODO: check if it's on visible area */ | |
1639 | vik_layer_emit_update ( VIK_LAYER(mdi->vml) ); // NB update display from background | |
1640 | } | |
1641 | g_mutex_unlock(mdi->mutex); | |
1642 | mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */ | |
a0b59f2f | 1643 | } |
50a14534 EB |
1644 | } |
1645 | } | |
825413ba | 1646 | vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle); |
04e54492 QT |
1647 | g_mutex_lock(mdi->mutex); |
1648 | if (mdi->map_layer_alive) | |
7bb60307 | 1649 | g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi); |
04e54492 | 1650 | g_mutex_unlock(mdi->mutex); |
634eca0a | 1651 | return 0; |
50a14534 EB |
1652 | } |
1653 | ||
1654 | static void mdi_cancel_cleanup ( MapDownloadInfo *mdi ) | |
1655 | { | |
1656 | if ( mdi->mapcoord.x || mdi->mapcoord.y ) | |
1657 | { | |
2eb18edc RN |
1658 | get_filename ( mdi->cache_dir, mdi->cache_layout, |
1659 | vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)), | |
1660 | vik_map_source_get_name(MAPS_LAYER_NTH_TYPE(mdi->maptype)), | |
14b57d17 RN |
1661 | mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y, mdi->filename_buf, mdi->maxlen, |
1662 | vik_map_source_get_file_extension(MAPS_LAYER_NTH_TYPE(mdi->maptype)) ); | |
45acf79e | 1663 | if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE) |
50a14534 | 1664 | { |
8c060406 | 1665 | g_remove ( mdi->filename_buf ); |
50a14534 EB |
1666 | } |
1667 | } | |
1668 | } | |
1669 | ||
1670 | static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload ) | |
1671 | { | |
1672 | gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ); | |
1673 | gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ); | |
1674 | MapCoord ulm, brm; | |
820c59f4 | 1675 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); |
2673b29d RN |
1676 | |
1677 | // Don't ever attempt download on direct access | |
1678 | if ( vik_map_source_is_direct_file_access ( map ) ) | |
1679 | return; | |
1680 | ||
820c59f4 GB |
1681 | if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm ) |
1682 | && vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) ) | |
50a14534 EB |
1683 | { |
1684 | MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) ); | |
1685 | gint a, b; | |
1686 | ||
550fd035 QT |
1687 | mdi->vml = vml; |
1688 | mdi->vvp = vvp; | |
1689 | mdi->map_layer_alive = TRUE; | |
fc6640a9 | 1690 | mdi->mutex = vik_mutex_new(); |
7114e879 | 1691 | mdi->refresh_display = TRUE; |
550fd035 | 1692 | |
50a14534 EB |
1693 | /* cache_dir and buffer for dest filename */ |
1694 | mdi->cache_dir = g_strdup ( vml->cache_dir ); | |
1695 | mdi->maxlen = strlen ( vml->cache_dir ) + 40; | |
1696 | mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) ); | |
d281e8b4 | 1697 | mdi->cache_layout = vml->cache_layout; |
50a14534 EB |
1698 | mdi->maptype = vml->maptype; |
1699 | ||
1700 | mdi->mapcoord = ulm; | |
50a14534 EB |
1701 | mdi->redownload = redownload; |
1702 | ||
1703 | mdi->x0 = MIN(ulm.x, brm.x); | |
1704 | mdi->xf = MAX(ulm.x, brm.x); | |
1705 | mdi->y0 = MIN(ulm.y, brm.y); | |
1706 | mdi->yf = MAX(ulm.y, brm.y); | |
1707 | ||
1708 | mdi->mapstoget = 0; | |
1709 | ||
2113a507 RN |
1710 | MapCoord mcoord = mdi->mapcoord; |
1711 | ||
50a14534 EB |
1712 | if ( mdi->redownload ) { |
1713 | mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1); | |
1714 | } else { | |
1715 | /* calculate how many we need */ | |
1716 | for ( a = mdi->x0; a <= mdi->xf; a++ ) | |
1717 | { | |
2113a507 | 1718 | mcoord.x = a; |
50a14534 EB |
1719 | for ( b = mdi->y0; b <= mdi->yf; b++ ) |
1720 | { | |
2113a507 RN |
1721 | mcoord.y = b; |
1722 | // Only count tiles from supported areas | |
1723 | if ( is_in_area (map, mcoord) ) | |
1724 | { | |
1725 | get_filename ( mdi->cache_dir, mdi->cache_layout, | |
1726 | vik_map_source_get_uniq_id(map), | |
1727 | vik_map_source_get_name(map), | |
1728 | ulm.scale, ulm.z, a, b, mdi->filename_buf, mdi->maxlen, | |
1729 | vik_map_source_get_file_extension(map) ); | |
1730 | if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) | |
1731 | mdi->mapstoget++; | |
1732 | } | |
50a14534 EB |
1733 | } |
1734 | } | |
1735 | } | |
1736 | ||
1737 | mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */ | |
1738 | ||
1739 | if ( mdi->mapstoget ) | |
1740 | { | |
97634600 GB |
1741 | const gchar *tmp_str; |
1742 | gchar *tmp; | |
50a14534 | 1743 | |
97634600 GB |
1744 | if (redownload) |
1745 | { | |
1746 | if (redownload == REDOWNLOAD_BAD) | |
1747 | tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget); | |
1748 | else | |
1749 | tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget); | |
1750 | } | |
1751 | else | |
1752 | { | |
1753 | tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget); | |
1754 | } | |
1755 | tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype)); | |
1756 | ||
7bb60307 | 1757 | g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi); |
50a14534 EB |
1758 | /* launch the thread */ |
1759 | a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */ | |
1760 | tmp, /* description string */ | |
1761 | (vik_thr_func) map_download_thread, /* function to call within thread */ | |
1762 | mdi, /* pass along data */ | |
1763 | (vik_thr_free_func) mdi_free, /* function to free pass along data */ | |
1764 | (vik_thr_free_func) mdi_cancel_cleanup, | |
1765 | mdi->mapstoget ); | |
1766 | g_free ( tmp ); | |
1767 | } | |
1768 | else | |
1769 | mdi_free ( mdi ); | |
1770 | } | |
1771 | } | |
1772 | ||
3ac548fa | 1773 | static void maps_layer_download_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom, gint download_method ) |
7114e879 | 1774 | { |
7114e879 | 1775 | MapCoord ulm, brm; |
820c59f4 | 1776 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); |
7114e879 | 1777 | |
2673b29d RN |
1778 | // Don't ever attempt download on direct access |
1779 | if ( vik_map_source_is_direct_file_access ( map ) ) | |
1780 | return; | |
1781 | ||
820c59f4 GB |
1782 | if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm) |
1783 | || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) { | |
4258f4e2 | 1784 | g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__); |
7114e879 QT |
1785 | return; |
1786 | } | |
1787 | ||
1788 | MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo)); | |
1789 | gint i, j; | |
1790 | ||
1791 | mdi->vml = vml; | |
1792 | mdi->vvp = vvp; | |
1793 | mdi->map_layer_alive = TRUE; | |
fc6640a9 | 1794 | mdi->mutex = vik_mutex_new(); |
903dc0b4 | 1795 | mdi->refresh_display = TRUE; |
7114e879 QT |
1796 | |
1797 | mdi->cache_dir = g_strdup ( vml->cache_dir ); | |
1798 | mdi->maxlen = strlen ( vml->cache_dir ) + 40; | |
1799 | mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) ); | |
1800 | mdi->maptype = vml->maptype; | |
d281e8b4 | 1801 | mdi->cache_layout = vml->cache_layout; |
7114e879 QT |
1802 | |
1803 | mdi->mapcoord = ulm; | |
3ac548fa | 1804 | mdi->redownload = download_method; |
7114e879 QT |
1805 | |
1806 | mdi->x0 = MIN(ulm.x, brm.x); | |
1807 | mdi->xf = MAX(ulm.x, brm.x); | |
1808 | mdi->y0 = MIN(ulm.y, brm.y); | |
1809 | mdi->yf = MAX(ulm.y, brm.y); | |
1810 | ||
1811 | mdi->mapstoget = 0; | |
1812 | ||
2113a507 RN |
1813 | MapCoord mcoord = mdi->mapcoord; |
1814 | ||
7114e879 | 1815 | for (i = mdi->x0; i <= mdi->xf; i++) { |
2113a507 | 1816 | mcoord.x = i; |
7114e879 | 1817 | for (j = mdi->y0; j <= mdi->yf; j++) { |
2113a507 RN |
1818 | mcoord.y = j; |
1819 | // Only count tiles from supported areas | |
1820 | if ( is_in_area (map, mcoord) ) { | |
1821 | get_filename ( mdi->cache_dir, mdi->cache_layout, | |
1822 | vik_map_source_get_uniq_id(map), | |
1823 | vik_map_source_get_name(map), | |
1824 | ulm.scale, ulm.z, i, j, mdi->filename_buf, mdi->maxlen, | |
1825 | vik_map_source_get_file_extension(map) ); | |
1826 | if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) | |
1827 | mdi->mapstoget++; | |
1828 | } | |
7114e879 QT |
1829 | } |
1830 | } | |
1831 | ||
1832 | mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */ | |
1833 | ||
1834 | if (mdi->mapstoget) { | |
4c77d5e0 GB |
1835 | gchar *tmp; |
1836 | const gchar *fmt; | |
eb6b0125 JJ |
1837 | fmt = ngettext("Downloading %d %s map...", |
1838 | "Downloading %d %s maps...", | |
1839 | mdi->mapstoget); | |
4c77d5e0 | 1840 | tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) ); |
7114e879 QT |
1841 | |
1842 | g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi); | |
1843 | /* launch the thread */ | |
1844 | a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */ | |
1845 | tmp, /* description string */ | |
1846 | (vik_thr_func) map_download_thread, /* function to call within thread */ | |
1847 | mdi, /* pass along data */ | |
1848 | (vik_thr_free_func) mdi_free, /* function to free pass along data */ | |
1849 | (vik_thr_free_func) mdi_cancel_cleanup, | |
1850 | mdi->mapstoget ); | |
1851 | g_free ( tmp ); | |
1852 | } | |
1853 | else | |
1854 | mdi_free ( mdi ); | |
1855 | } | |
1856 | ||
3ac548fa RN |
1857 | /** |
1858 | * vik_maps_layer_download_section: | |
1859 | * @vml: The Map Layer | |
1860 | * @vvp: The Viewport that the map is on | |
1861 | * @ul: Upper left coordinate of the area to be downloaded | |
1862 | * @br: Bottom right coordinate of the area to be downloaded | |
1863 | * @zoom: The zoom level at which the maps are to be download | |
1864 | * | |
1865 | * Download a specified map area at a certain zoom level | |
1866 | */ | |
1867 | void vik_maps_layer_download_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom ) | |
1868 | { | |
1869 | maps_layer_download_section (vml, vvp, ul, br, zoom, REDOWNLOAD_NONE); | |
1870 | } | |
1871 | ||
50a14534 EB |
1872 | static void maps_layer_redownload_bad ( VikMapsLayer *vml ) |
1873 | { | |
1874 | start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD ); | |
1875 | } | |
a7c1acf1 | 1876 | |
50a14534 EB |
1877 | static void maps_layer_redownload_all ( VikMapsLayer *vml ) |
1878 | { | |
1879 | start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL ); | |
1880 | } | |
1881 | ||
a7c1acf1 GB |
1882 | static void maps_layer_redownload_new ( VikMapsLayer *vml ) |
1883 | { | |
1884 | start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW ); | |
1885 | } | |
1886 | ||
450d8665 RN |
1887 | /** |
1888 | * Display a simple dialog with information about this particular map tile | |
1889 | */ | |
1890 | static void maps_layer_tile_info ( VikMapsLayer *vml ) | |
1891 | { | |
1892 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); | |
1893 | ||
1894 | gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vml->redownload_vvp ); | |
1895 | gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vml->redownload_vvp ); | |
1896 | MapCoord ulm; | |
1897 | ||
1898 | if ( !vik_map_source_coord_to_mapcoord ( map, &(vml->redownload_ul), xzoom, yzoom, &ulm ) ) | |
1899 | return; | |
1900 | ||
1901 | gchar *filename = NULL; | |
450d8665 RN |
1902 | gchar *source = NULL; |
1903 | ||
1904 | if ( vik_map_source_is_direct_file_access ( map ) ) { | |
0fb11294 RN |
1905 | if ( vik_map_source_is_mbtiles ( map ) ) { |
1906 | filename = g_strdup ( vml->filename ); | |
1907 | #ifdef HAVE_SQLITE3_H | |
1908 | // And whether to bother going into the SQL to check it's really there or not... | |
1909 | gchar *exists = NULL; | |
8c778528 | 1910 | gint zoom = 17 - ulm.scale; |
0fb11294 | 1911 | if ( vml->mbtiles ) { |
8c778528 | 1912 | GdkPixbuf *pixbuf = get_pixbuf_sql_exec ( vml->mbtiles, ulm.x, ulm.y, zoom ); |
0fb11294 RN |
1913 | if ( pixbuf ) { |
1914 | exists = g_strdup ( _("YES") ); | |
1915 | g_object_unref ( G_OBJECT(pixbuf) ); | |
1916 | } | |
1917 | else { | |
1918 | exists = g_strdup ( _("NO") ); | |
1919 | } | |
1920 | } | |
1921 | else | |
1922 | exists = g_strdup ( _("NO") ); | |
8c778528 | 1923 | gint flip_y = (gint) pow(2, zoom)-1 - ulm.y; |
0fb11294 | 1924 | // NB Also handles .jpg automatically due to pixbuf_new_from () support - although just print png for now. |
7bad314b | 1925 | source = g_strdup_printf ( "Source: %s (%d%s%d%s%d.%s %s)", filename, zoom, G_DIR_SEPARATOR_S, ulm.x, G_DIR_SEPARATOR_S, flip_y, "png", exists ); |
0fb11294 RN |
1926 | g_free ( exists ); |
1927 | #else | |
7bad314b | 1928 | source = g_strdup ( _("Source: Not available") ); |
0fb11294 RN |
1929 | #endif |
1930 | } | |
99f0d7df RN |
1931 | else if ( vik_map_source_is_osm_meta_tiles ( map ) ) { |
1932 | char path[PATH_MAX]; | |
1933 | xyz_to_meta(path, sizeof(path), vml->cache_dir, ulm.x, ulm.y, 17-ulm.scale ); | |
1934 | source = g_strdup ( path ); | |
1935 | filename = g_strdup ( path ); | |
1936 | } | |
0fb11294 | 1937 | else { |
2eb18edc RN |
1938 | guint max_path_len = strlen(vml->cache_dir) + 40; |
1939 | filename = g_malloc ( max_path_len * sizeof(char) ); | |
1940 | get_filename ( vml->cache_dir, VIK_MAPS_CACHE_LAYOUT_OSM, | |
1941 | vik_map_source_get_uniq_id(map), | |
1942 | NULL, | |
14b57d17 RN |
1943 | ulm.scale, ulm.z, ulm.x, ulm.y, filename, max_path_len, |
1944 | vik_map_source_get_file_extension(map) ); | |
7bad314b | 1945 | source = g_strconcat ( "Source: file://", filename, NULL ); |
0fb11294 | 1946 | } |
450d8665 RN |
1947 | } |
1948 | else { | |
d281e8b4 RN |
1949 | guint max_path_len = strlen(vml->cache_dir) + 40; |
1950 | filename = g_malloc ( max_path_len * sizeof(char) ); | |
2eb18edc RN |
1951 | get_filename ( vml->cache_dir, vml->cache_layout, |
1952 | vik_map_source_get_uniq_id(map), | |
1953 | vik_map_source_get_name(map), | |
14b57d17 RN |
1954 | ulm.scale, ulm.z, ulm.x, ulm.y, filename, max_path_len, |
1955 | vik_map_source_get_file_extension(map) ); | |
7bad314b | 1956 | source = g_strdup_printf ( "Source: http://%s%s", |
450d8665 RN |
1957 | vik_map_source_default_get_hostname ( VIK_MAP_SOURCE_DEFAULT(map) ), |
1958 | vik_map_source_default_get_uri ( VIK_MAP_SOURCE_DEFAULT(map), &ulm ) ); | |
1959 | } | |
1960 | ||
7bad314b RN |
1961 | GArray *array = g_array_new (FALSE, TRUE, sizeof(gchar*)); |
1962 | g_array_append_val ( array, source ); | |
1963 | ||
1964 | gchar *filemsg = NULL; | |
1965 | gchar *timemsg = NULL; | |
450d8665 | 1966 | |
7bad314b RN |
1967 | if ( g_file_test ( filename, G_FILE_TEST_EXISTS ) ) { |
1968 | filemsg = g_strconcat ( "Tile File: ", filename, NULL ); | |
450d8665 RN |
1969 | // Get some timestamp information of the tile |
1970 | struct stat stat_buf; | |
1971 | if ( g_stat ( filename, &stat_buf ) == 0 ) { | |
6be843d5 RN |
1972 | gchar time_buf[64]; |
1973 | strftime ( time_buf, sizeof(time_buf), "%c", gmtime((const time_t *)&stat_buf.st_mtime) ); | |
7bad314b | 1974 | timemsg = g_strdup_printf ( _("Tile File Timestamp: %s"), time_buf ); |
450d8665 | 1975 | } |
0d744b77 | 1976 | else { |
7bad314b | 1977 | timemsg = g_strdup ( _("Tile File Timestamp: Not Available") ); |
0d744b77 | 1978 | } |
7bad314b RN |
1979 | g_array_append_val ( array, filemsg ); |
1980 | g_array_append_val ( array, timemsg ); | |
0d744b77 RN |
1981 | } |
1982 | else { | |
7bad314b RN |
1983 | filemsg = g_strdup_printf ( "Tile File: %s [Not Available]", filename ); |
1984 | g_array_append_val ( array, filemsg ); | |
450d8665 | 1985 | } |
450d8665 | 1986 | |
7bad314b RN |
1987 | a_dialog_list ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Tile Information"), array, 5 ); |
1988 | g_array_free ( array, FALSE ); | |
1989 | ||
1990 | g_free ( timemsg ); | |
1991 | g_free ( filemsg ); | |
450d8665 RN |
1992 | g_free ( source ); |
1993 | g_free ( filename ); | |
1994 | } | |
1995 | ||
50a14534 EB |
1996 | static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp ) |
1997 | { | |
941aa6e9 AF |
1998 | if (!vml || vml->vl.type != VIK_LAYER_MAPS) |
1999 | return FALSE; | |
50a14534 EB |
2000 | if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 ) |
2001 | { | |
2002 | if ( event->button == 1 ) | |
2003 | { | |
2004 | VikCoord ul, br; | |
2005 | vik_viewport_screen_to_coord ( vvp, MAX(0, MIN(event->x, vml->dl_tool_x)), MAX(0, MIN(event->y, vml->dl_tool_y)), &ul ); | |
2006 | vik_viewport_screen_to_coord ( vvp, MIN(vik_viewport_get_width(vvp), MAX(event->x, vml->dl_tool_x)), MIN(vik_viewport_get_height(vvp), MAX ( event->y, vml->dl_tool_y ) ), &br ); | |
a0b59f2f | 2007 | start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH ); |
50a14534 EB |
2008 | vml->dl_tool_x = vml->dl_tool_y = -1; |
2009 | return TRUE; | |
2010 | } | |
2011 | else | |
2012 | { | |
2013 | vik_viewport_screen_to_coord ( vvp, MAX(0, MIN(event->x, vml->dl_tool_x)), MAX(0, MIN(event->y, vml->dl_tool_y)), &(vml->redownload_ul) ); | |
2014 | vik_viewport_screen_to_coord ( vvp, MIN(vik_viewport_get_width(vvp), MAX(event->x, vml->dl_tool_x)), MIN(vik_viewport_get_height(vvp), MAX ( event->y, vml->dl_tool_y ) ), &(vml->redownload_br) ); | |
2015 | ||
2016 | vml->redownload_vvp = vvp; | |
2017 | ||
2018 | vml->dl_tool_x = vml->dl_tool_y = -1; | |
2019 | ||
2020 | if ( ! vml->dl_right_click_menu ) { | |
2021 | GtkWidget *item; | |
2022 | vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () ); | |
2023 | ||
94ee2264 | 2024 | item = gtk_menu_item_new_with_mnemonic ( _("Redownload _Bad Map(s)") ); |
50a14534 EB |
2025 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml ); |
2026 | gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item ); | |
2027 | ||
94ee2264 | 2028 | item = gtk_menu_item_new_with_mnemonic ( _("Redownload _New Map(s)") ); |
a7c1acf1 GB |
2029 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml ); |
2030 | gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item ); | |
2031 | ||
94ee2264 | 2032 | item = gtk_menu_item_new_with_mnemonic ( _("Redownload _All Map(s)") ); |
50a14534 EB |
2033 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml ); |
2034 | gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item ); | |
450d8665 RN |
2035 | |
2036 | item = gtk_image_menu_item_new_with_mnemonic ( _("_Show Tile Information") ); | |
2037 | gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_MENU) ); | |
2038 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_tile_info), vml ); | |
2039 | gtk_menu_shell_append (GTK_MENU_SHELL(vml->dl_right_click_menu), item); | |
50a14534 EB |
2040 | } |
2041 | ||
2042 | gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time ); | |
2043 | gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) ); | |
2044 | } | |
2045 | } | |
2046 | return FALSE; | |
2047 | } | |
2048 | ||
941aa6e9 AF |
2049 | static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp) |
2050 | { | |
2051 | return vvp; | |
2052 | } | |
2053 | ||
50a14534 EB |
2054 | static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp ) |
2055 | { | |
2056 | MapCoord tmp; | |
941aa6e9 AF |
2057 | if (!vml || vml->vl.type != VIK_LAYER_MAPS) |
2058 | return FALSE; | |
820c59f4 GB |
2059 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); |
2060 | if ( vik_map_source_get_drawmode(map) == vik_viewport_get_drawmode ( vvp ) && | |
2061 | vik_map_source_coord_to_mapcoord ( map, vik_viewport_get_center ( vvp ), | |
50a14534 EB |
2062 | vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ), |
2063 | vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ), | |
2064 | &tmp ) ) { | |
2065 | vml->dl_tool_x = event->x, vml->dl_tool_y = event->y; | |
2066 | return TRUE; | |
2067 | } | |
2068 | return FALSE; | |
50a14534 EB |
2069 | } |
2070 | ||
7a7ba2f1 RN |
2071 | // A slightly better way of defining the menu callback information |
2072 | // This should be easier to extend/rework compared to previously | |
2073 | typedef enum { | |
2074 | MA_VML = 0, | |
2075 | MA_VVP, | |
2076 | MA_LAST | |
2077 | } menu_array_index; | |
2078 | ||
2079 | typedef gpointer menu_array_values[MA_LAST]; | |
2080 | ||
2081 | static void download_onscreen_maps ( menu_array_values values, gint redownload ) | |
50a14534 | 2082 | { |
7a7ba2f1 RN |
2083 | VikMapsLayer *vml = VIK_MAPS_LAYER(values[MA_VML]); |
2084 | VikViewport *vvp = VIK_VIEWPORT(values[MA_VVP]); | |
314c1ccc | 2085 | VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp ); |
50a14534 EB |
2086 | |
2087 | gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ); | |
2088 | gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ); | |
2089 | ||
2090 | VikCoord ul, br; | |
2091 | MapCoord ulm, brm; | |
2092 | ||
2093 | vik_viewport_screen_to_coord ( vvp, 0, 0, &ul ); | |
2094 | vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br ); | |
2095 | ||
820c59f4 GB |
2096 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); |
2097 | if ( vik_map_source_get_drawmode(map) == vp_drawmode && | |
2098 | vik_map_source_coord_to_mapcoord ( map, &ul, xzoom, yzoom, &ulm ) && | |
2099 | vik_map_source_coord_to_mapcoord ( map, &br, xzoom, yzoom, &brm ) ) | |
50817314 | 2100 | start_download_thread ( vml, vvp, &ul, &br, redownload ); |
820c59f4 GB |
2101 | else if (vik_map_source_get_drawmode(map) != vp_drawmode) { |
2102 | const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, vik_map_source_get_drawmode(map)); | |
4c77d5e0 | 2103 | gchar *err = g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name)); |
314c1ccc QT |
2104 | a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err ); |
2105 | g_free(err); | |
2106 | } | |
50a14534 | 2107 | else |
4c77d5e0 | 2108 | a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Wrong zoom level for this map.") ); |
50a14534 EB |
2109 | |
2110 | } | |
2111 | ||
7a7ba2f1 | 2112 | static void maps_layer_download_missing_onscreen_maps ( menu_array_values values ) |
50817314 | 2113 | { |
7a7ba2f1 | 2114 | download_onscreen_maps( values, REDOWNLOAD_NONE); |
50817314 GB |
2115 | } |
2116 | ||
7a7ba2f1 | 2117 | static void maps_layer_download_new_onscreen_maps ( menu_array_values values ) |
6a4a29aa | 2118 | { |
7a7ba2f1 | 2119 | download_onscreen_maps( values, REDOWNLOAD_NEW); |
6a4a29aa JJ |
2120 | } |
2121 | ||
7a7ba2f1 | 2122 | static void maps_layer_redownload_all_onscreen_maps ( menu_array_values values ) |
50817314 | 2123 | { |
7a7ba2f1 | 2124 | download_onscreen_maps( values, REDOWNLOAD_ALL); |
50817314 GB |
2125 | } |
2126 | ||
859412d0 | 2127 | static void maps_layer_about ( gpointer vml_vvp[2] ) |
b03ae39b RN |
2128 | { |
2129 | VikMapsLayer *vml = vml_vvp[0]; | |
2130 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); | |
2131 | ||
2132 | if ( vik_map_source_get_license (map) ) | |
2133 | maps_show_license ( VIK_GTK_WINDOW_FROM_LAYER(vml), map ); | |
2134 | else | |
2135 | a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), | |
2136 | vik_map_source_get_label (map) ); | |
2137 | } | |
2138 | ||
3ac548fa RN |
2139 | /** |
2140 | * maps_layer_how_many_maps: | |
2141 | * Copied from maps_layer_download_section but without the actual download and this returns a value | |
2142 | */ | |
2143 | static gint maps_layer_how_many_maps ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom, gint redownload ) | |
2144 | { | |
2145 | MapCoord ulm, brm; | |
2146 | VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype); | |
2147 | ||
2148 | if ( vik_map_source_is_direct_file_access ( map ) ) | |
2149 | return 0; | |
2150 | ||
2151 | if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm) | |
2152 | || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) { | |
2153 | g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__); | |
2154 | return 0; | |
2155 | } | |
2156 | ||
2157 | MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo)); | |
2158 | gint i, j; | |
2159 | ||
2160 | mdi->vml = vml; | |
2161 | mdi->vvp = vvp; | |
2162 | mdi->map_layer_alive = TRUE; | |
fc6640a9 | 2163 | mdi->mutex = vik_mutex_new(); |
3ac548fa RN |
2164 | mdi->refresh_display = FALSE; |
2165 | ||
2166 | mdi->cache_dir = g_strdup ( vml->cache_dir ); | |
2167 | mdi->maxlen = strlen ( vml->cache_dir ) + 40; | |
2168 | mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) ); | |
2169 | mdi->maptype = vml->maptype; | |
d281e8b4 | 2170 | mdi->cache_layout = vml->cache_layout; |
3ac548fa RN |
2171 | |
2172 | mdi->mapcoord = ulm; | |
2173 | mdi->redownload = redownload; | |
2174 | ||
2175 | mdi->x0 = MIN(ulm.x, brm.x); | |
2176 | mdi->xf = MAX(ulm.x, brm.x); | |
2177 | mdi->y0 = MIN(ulm.y, brm.y); | |
2178 | mdi->yf = MAX(ulm.y, brm.y); | |
2179 | ||
2180 | mdi->mapstoget = 0; | |
2181 | ||
2182 | if ( mdi->redownload == REDOWNLOAD_ALL ) { | |
2183 | mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1); | |
2184 | } | |
2185 | else { | |
2186 | /* calculate how many we need */ | |
2113a507 | 2187 | MapCoord mcoord = mdi->mapcoord; |
3ac548fa | 2188 | for (i = mdi->x0; i <= mdi->xf; i++) { |
2113a507 | 2189 | mcoord.x = i; |
3ac548fa | 2190 | for (j = mdi->y0; j <= mdi->yf; j++) { |
2113a507 RN |
2191 | mcoord.y = j; |
2192 | // Only count tiles from supported areas | |
2193 | if ( is_in_area ( map, mcoord ) ) { | |
2194 | get_filename ( mdi->cache_dir, mdi->cache_layout, | |
2195 | vik_map_source_get_uniq_id(map), | |
2196 | vik_map_source_get_name(map), | |
2197 | ulm.scale, ulm.z, i, j, mdi->filename_buf, mdi->maxlen, | |
2198 | vik_map_source_get_file_extension(map) ); | |
2199 | if ( mdi->redownload == REDOWNLOAD_NEW ) { | |
2200 | // Assume the worst - always a new file | |
2201 | // Absolute value would require a server lookup - but that is too slow | |
3ac548fa RN |
2202 | mdi->mapstoget++; |
2203 | } | |
2204 | else { | |
2113a507 RN |
2205 | if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) { |
2206 | // Missing | |
2207 | mdi->mapstoget++; | |
2208 | } | |
2209 | else { | |
2210 | if ( mdi->redownload == REDOWNLOAD_BAD ) { | |
2211 | /* see if this one is bad or what */ | |
2212 | GError *gx = NULL; | |
2213 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx ); | |
2214 | if (gx || (!pixbuf)) { | |
2215 | mdi->mapstoget++; | |
2216 | } | |
2217 | break; | |
2218 | // Other download cases already considered or just ignored | |
3ac548fa | 2219 | } |
3ac548fa RN |
2220 | } |
2221 | } | |
2222 | } | |
2223 | } | |
2224 | } | |
2225 | } | |
2226 | ||
2227 | gint rv = mdi->mapstoget; | |
2228 | ||
2229 | mdi_free ( mdi ); | |
2230 | ||
2231 | return rv; | |
2232 | } | |
2233 | ||
2234 | /** | |
2235 | * maps_dialog_zoom_between: | |
2236 | * This dialog is specific to the map layer, so it's here rather than in dialog.c | |
2237 | */ | |
2238 | gboolean maps_dialog_zoom_between ( GtkWindow *parent, | |
2239 | gchar *title, | |
2240 | gchar *zoom_list[], | |
2241 | gint default_zoom1, | |
2242 | gint default_zoom2, | |
2243 | gint *selected_zoom1, | |
2244 | gint *selected_zoom2, | |
2245 | gchar *download_list[], | |
2246 | gint default_download, | |
2247 | gint *selected_download ) | |
2248 | { | |
2249 | GtkWidget *dialog = gtk_dialog_new_with_buttons ( title, | |
2250 | parent, | |
2251 | GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, | |
2252 | GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, | |
2253 | GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, | |
2254 | NULL ); | |
2255 | gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT ); | |
2256 | GtkWidget *response_w = NULL; | |
2257 | #if GTK_CHECK_VERSION (2, 20, 0) | |
2258 | response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT ); | |
2259 | #endif | |
2260 | GtkWidget *zoom_label1 = gtk_label_new ( _("Zoom Start:") ); | |
2261 | GtkWidget *zoom_combo1 = vik_combo_box_text_new(); | |
2262 | gchar **s; | |
2263 | for (s = zoom_list; *s; s++) | |
2264 | vik_combo_box_text_append ( zoom_combo1, *s ); | |
2265 | gtk_combo_box_set_active ( GTK_COMBO_BOX(zoom_combo1), default_zoom1 ); | |
2266 | ||
2267 | GtkWidget *zoom_label2 = gtk_label_new ( _("Zoom End:") ); | |
2268 | GtkWidget *zoom_combo2 = vik_combo_box_text_new(); | |
2269 | for (s = zoom_list; *s; s++) | |
2270 | vik_combo_box_text_append ( zoom_combo2, *s ); | |
2271 | gtk_combo_box_set_active ( GTK_COMBO_BOX(zoom_combo2), default_zoom2 ); | |
2272 | ||
2273 | GtkWidget *download_label = gtk_label_new(_("Download Maps Method:")); | |
2274 | GtkWidget *download_combo = vik_combo_box_text_new(); | |
2275 | for (s = download_list; *s; s++) | |
2276 | vik_combo_box_text_append ( download_combo, *s ); | |
2277 | gtk_combo_box_set_active ( GTK_COMBO_BOX(download_combo), default_download ); | |
2278 | ||
2279 | GtkTable *box = GTK_TABLE(gtk_table_new(3, 2, FALSE)); | |
2280 | gtk_table_attach_defaults (box, GTK_WIDGET(zoom_label1), 0, 1, 0, 1); | |
2281 | gtk_table_attach_defaults (box, GTK_WIDGET(zoom_combo1), 1, 2, 0, 1); | |
2282 | gtk_table_attach_defaults (box, GTK_WIDGET(zoom_label2), 0, 1, 1, 2); | |
2283 | gtk_table_attach_defaults (box, GTK_WIDGET(zoom_combo2), 1, 2, 1, 2); | |
2284 | gtk_table_attach_defaults (box, GTK_WIDGET(download_label), 0, 1, 2, 3); | |
2285 | gtk_table_attach_defaults (box, GTK_WIDGET(download_combo), 1, 2, 2, 3); | |
2286 | ||
2287 | gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), GTK_WIDGET(box), FALSE, FALSE, 5 ); | |
2288 | ||
2289 | if ( response_w ) | |
2290 | gtk_widget_grab_focus ( response_w ); | |
2291 | ||
2292 | gtk_widget_show_all ( dialog ); | |
2293 | if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) != GTK_RESPONSE_ACCEPT ) { | |
2294 | gtk_widget_destroy(dialog); | |
2295 | return FALSE; | |
2296 | } | |
2297 | ||
2298 | // Return selected options | |
2299 | *selected_zoom1 = gtk_combo_box_get_active ( GTK_COMBO_BOX(zoom_combo1) ); | |
2300 | *selected_zoom2 = gtk_combo_box_get_active ( GTK_COMBO_BOX(zoom_combo2) ); | |
2301 | *selected_download = gtk_combo_box_get_active ( GTK_COMBO_BOX(download_combo) ); | |
2302 | ||
2303 | gtk_widget_destroy(dialog); | |
2304 | return TRUE; | |
2305 | } | |
2306 | ||
2307 | // My best guess of sensible limits | |
2308 | #define REALLY_LARGE_AMOUNT_OF_TILES 5000 | |
2309 | #define CONFIRM_LARGE_AMOUNT_OF_TILES 500 | |
2310 | ||
2311 | /** | |
2312 | * Get all maps in the region for zoom levels specified by the user | |
2313 | * Sort of similar to trw_layer_download_map_along_track_cb function | |
2314 | */ | |
7a7ba2f1 | 2315 | static void maps_layer_download_all ( menu_array_values values ) |
3ac548fa | 2316 | { |
7a7ba2f1 RN |
2317 | VikMapsLayer *vml = VIK_MAPS_LAYER(values[MA_VML]); |
2318 | VikViewport *vvp = VIK_VIEWPORT(values[MA_VVP]); | |
3ac548fa RN |
2319 | |
2320 | // I don't think we should allow users to hammer the servers too much... | |
2321 | // Delibrately not allowing lowest zoom levels | |
2322 | // Still can give massive numbers to download | |
2323 | // A screen size of 1600x1200 gives around 300,000 tiles between 1..128 when none exist before !! | |
2324 | gchar *zoom_list[] = {"1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", NULL }; | |
2325 | gdouble zoom_vals[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024}; | |
2326 | ||
2327 | gint selected_zoom1, selected_zoom2, default_zoom, lower_zoom; | |
2328 | gint selected_download_method; | |
2329 | ||
2330 | gdouble cur_zoom = vik_viewport_get_zoom(vvp); | |
2331 | ||
2332 | for (default_zoom = 0; default_zoom < sizeof(zoom_vals)/sizeof(gdouble); default_zoom++) { | |
2333 | if (cur_zoom == zoom_vals[default_zoom]) | |
2334 | break; | |
2335 | } | |
2336 | default_zoom = (default_zoom == sizeof(zoom_vals)/sizeof(gdouble)) ? sizeof(zoom_vals)/sizeof(gdouble) - 1 : default_zoom; | |
2337 | ||
2338 | // Default to only 2 zoom levels below the current one | |
2339 | if (default_zoom > 1 ) | |
2340 | lower_zoom = default_zoom - 2; | |
2341 | else | |
2342 | lower_zoom = default_zoom; | |
2343 | ||
2344 | // redownload method - needs to align with REDOWNLOAD* macro values | |
2345 | gchar *download_list[] = { _("Missing"), _("Bad"), _("New"), _("Reload All"), NULL }; | |
2346 | ||
2347 | gchar *title = g_strdup_printf ( ("%s: %s"), vik_maps_layer_get_map_label (vml), _("Download for Zoom Levels") ); | |
2348 | ||
2349 | if ( ! maps_dialog_zoom_between ( VIK_GTK_WINDOW_FROM_LAYER(vml), | |
2350 | title, | |
2351 | zoom_list, | |
2352 | lower_zoom, | |
2353 | default_zoom, | |
2354 | &selected_zoom1, | |
2355 | &selected_zoom2, | |
2356 | download_list, | |
2357 | REDOWNLOAD_NONE, // AKA Missing | |
2358 | &selected_download_method ) ) { | |
2359 | // Cancelled | |
2360 | g_free ( title ); | |
2361 | return; | |
2362 | } | |
2363 | g_free ( title ); | |
2364 | ||
2365 | // Find out new current positions | |
2366 | gdouble min_lat, max_lat, min_lon, max_lon; | |
2367 | VikCoord vc_ul, vc_br; | |
2368 | vik_viewport_get_min_max_lat_lon ( vvp, &min_lat, &max_lat, &min_lon, &max_lon ); | |
2369 | struct LatLon ll_ul = { max_lat, min_lon }; | |
2370 | struct LatLon ll_br = { min_lat, max_lon }; | |
2371 | vik_coord_load_from_latlon ( &vc_ul, vik_viewport_get_coord_mode (vvp), &ll_ul ); | |
2372 | vik_coord_load_from_latlon ( &vc_br, vik_viewport_get_coord_mode (vvp), &ll_br ); | |
2373 | ||
2374 | // Get Maps Count - call for each zoom level (in reverse) | |
2375 | // With REDOWNLOAD_NEW this is a possible maximum | |
2376 | // With REDOWNLOAD_NONE this only missing ones - however still has a server lookup per tile | |
2377 | gint map_count = 0; | |
2378 | gint zz; | |
2379 | for ( zz = selected_zoom2; zz >= selected_zoom1; zz-- ) { | |
2380 | map_count = map_count + maps_layer_how_many_maps ( vml, vvp, &vc_ul, &vc_br, zoom_vals[zz], selected_download_method ); | |
2381 | } | |
2382 | ||
2383 | g_debug ("vikmapslayer: download request map count %d for method %d", map_count, selected_download_method); | |
2384 | ||
2385 | // Absolute protection of hammering a map server | |
2386 | if ( map_count > REALLY_LARGE_AMOUNT_OF_TILES ) { | |
2387 | gchar *str = g_strdup_printf (_("You are not allowed to download more than %d tiles in one go (requested %d)"), REALLY_LARGE_AMOUNT_OF_TILES, map_count); | |
2388 | a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), str ); | |
2389 | g_free (str); | |
2390 | return; | |
2391 | } | |
2392 | ||
2393 | // Confirm really want to do this | |
2394 | if ( map_count > CONFIRM_LARGE_AMOUNT_OF_TILES ) { | |
2395 | gchar *str = g_strdup_printf (_("Do you really want to download %d tiles?"), map_count); | |
2396 | gboolean ans = a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vml), str, NULL ); | |
2397 | g_free (str); | |
2398 | if ( ! ans ) | |
2399 | return; | |
2400 | } | |
2401 | ||
2402 | // Get Maps - call for each zoom level (in reverse) | |
2403 | for ( zz = selected_zoom2; zz >= selected_zoom1; zz-- ) { | |
2404 | maps_layer_download_section ( vml, vvp, &vc_ul, &vc_br, zoom_vals[zz], selected_download_method ); | |
2405 | } | |
2406 | } | |
2407 | ||
9095ea4c RN |
2408 | /** |
2409 | * | |
2410 | */ | |
2411 | static void maps_layer_flush ( menu_array_values values ) | |
2412 | { | |
2413 | VikMapsLayer *vml = VIK_MAPS_LAYER(values[MA_VML]); | |
2414 | a_mapcache_flush_type ( vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(vml->maptype)) ); | |
2415 | } | |
2416 | ||
50a14534 EB |
2417 | static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp ) |
2418 | { | |
50a14534 | 2419 | GtkWidget *item; |
7a7ba2f1 RN |
2420 | static menu_array_values values; |
2421 | values[MA_VML] = vml; | |
2422 | values[MA_VVP] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) ); | |
50a14534 EB |
2423 | |
2424 | item = gtk_menu_item_new(); | |
2425 | gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); | |
2426 | gtk_widget_show ( item ); | |
2427 | ||
555ec6f6 RN |
2428 | /* Now with icons */ |
2429 | item = gtk_image_menu_item_new_with_mnemonic ( _("Download _Missing Onscreen Maps") ); | |
2430 | gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) ); | |
7a7ba2f1 | 2431 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), values ); |
50a14534 EB |
2432 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); |
2433 | gtk_widget_show ( item ); | |
50817314 | 2434 | |
c81ded98 | 2435 | if ( vik_map_source_supports_download_only_new (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) { |
555ec6f6 RN |
2436 | item = gtk_image_menu_item_new_with_mnemonic ( _("Download _New Onscreen Maps") ); |
2437 | gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REDO, GTK_ICON_SIZE_MENU) ); | |
7a7ba2f1 | 2438 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), values ); |
6a4a29aa JJ |
2439 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); |
2440 | gtk_widget_show ( item ); | |
2441 | } | |
2442 | ||
555ec6f6 RN |
2443 | item = gtk_image_menu_item_new_with_mnemonic ( _("Reload _All Onscreen Maps") ); |
2444 | gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) ); | |
7a7ba2f1 | 2445 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), values ); |
50817314 GB |
2446 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); |
2447 | gtk_widget_show ( item ); | |
3ac548fa RN |
2448 | |
2449 | item = gtk_image_menu_item_new_with_mnemonic ( _("Download Maps in _Zoom Levels...") ); | |
2450 | gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_DND_MULTIPLE, GTK_ICON_SIZE_MENU) ); | |
7a7ba2f1 | 2451 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_all), values ); |
3ac548fa RN |
2452 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); |
2453 | gtk_widget_show ( item ); | |
b03ae39b RN |
2454 | |
2455 | item = gtk_image_menu_item_new_from_stock ( GTK_STOCK_ABOUT, NULL ); | |
859412d0 | 2456 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_about), values ); |
b03ae39b RN |
2457 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); |
2458 | gtk_widget_show ( item ); | |
9095ea4c RN |
2459 | |
2460 | // Typical users shouldn't need to use this functionality - so debug only ATM | |
2461 | if ( vik_debug ) { | |
2462 | item = gtk_image_menu_item_new_with_mnemonic ( _("Flush Map Cache") ); | |
2463 | gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU) ); | |
2464 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_flush), values ); | |
2465 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); | |
2466 | gtk_widget_show ( item ); | |
2467 | } | |
50a14534 | 2468 | } |
6b59f63d RN |
2469 | |
2470 | /** | |
2471 | * Enable downloading maps of the current screen area either 'new' or 'everything' | |
2472 | */ | |
2473 | void vik_maps_layer_download ( VikMapsLayer *vml, VikViewport *vvp, gboolean only_new ) | |
2474 | { | |
2475 | if ( !vml ) return; | |
2476 | if ( !vvp ) return; | |
2477 | ||
7a7ba2f1 RN |
2478 | static menu_array_values values; |
2479 | values[MA_VML] = vml; | |
2480 | values[MA_VVP] = vvp; | |
6b59f63d RN |
2481 | |
2482 | if ( only_new ) | |
2483 | // Get only new maps | |
7a7ba2f1 | 2484 | maps_layer_download_new_onscreen_maps ( values ); |
6b59f63d RN |
2485 | else |
2486 | // Redownload everything | |
7a7ba2f1 | 2487 | maps_layer_redownload_all_onscreen_maps ( values ); |
6b59f63d | 2488 | } |