]> git.street.me.uk Git - andy/viking.git/blame - src/vikmapslayer.c
Only allow JPGs in the file selector for Geotagging.
[andy/viking.git] / src / vikmapslayer.c
CommitLineData
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>
50a14534 6 * UTM multi-zone stuff by Kit Transue <notlostyet@didactek.com>
cdcaf41c 7 * Dynamic map type by Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
50a14534
EB
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
4c77d5e0
GB
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
50a14534
EB
29#include <gtk/gtk.h>
30#include <gdk-pixbuf/gdk-pixdata.h>
45acf79e
MA
31#include <glib.h>
32#include <glib/gstdio.h>
4c77d5e0
GB
33#include <glib/gi18n.h>
34
8c00358d 35#ifdef HAVE_STRING_H
50a14534 36#include <string.h>
8c00358d
GB
37#endif
38#ifdef HAVE_MATH_H
50a14534 39#include <math.h>
8c00358d
GB
40#endif
41
45acf79e 42#ifdef HAVE_UNISTD_H
50a14534 43#include <unistd.h>
45acf79e 44#endif
50a14534 45
a7023a1b 46#include "viking.h"
450d8665 47#include "vikmapsourcedefault.h"
9979924f 48#include "maputils.h"
50a14534 49#include "mapcache.h"
50a14534 50#include "background.h"
a7023a1b
RN
51#include "preferences.h"
52#include "vikmapslayer.h"
bce3a7b0
EB
53#include "icons/icons.h"
54
0f7e9133
RN
55#define VIK_SETTINGS_MAP_MAX_TILES "maps_max_tiles"
56static gint MAX_TILES = 1000;
57
58#define VIK_SETTINGS_MAP_MIN_SHRINKFACTOR "maps_min_shrinkfactor"
59#define VIK_SETTINGS_MAP_MAX_SHRINKFACTOR "maps_max_shrinkfactor"
60static gdouble MAX_SHRINKFACTOR = 8.0000001; /* zoom 1 viewing 8-tiles */
61static gdouble MIN_SHRINKFACTOR = 0.0312499; /* zoom 32 viewing 1-tiles */
62
63#define VIK_SETTINGS_MAP_REAL_MIN_SHRINKFACTOR "maps_real_min_shrinkfactor"
64static gdouble REAL_MIN_SHRINKFACTOR = 0.0039062499; /* if shrinkfactor is between MAX and REAL_MAX, will only check for existence */
65
50a14534
EB
66/****** MAP TYPES ******/
67
cdcaf41c
QT
68static GList *__map_types = NULL;
69
70#define NUM_MAP_TYPES g_list_length(__map_types)
50a14534 71
cdcaf41c 72/* List of label for each map type */
a8876892 73static gchar **params_maptypes = NULL;
cdcaf41c
QT
74
75/* Corresponding IDS. (Cf. field uniq_id in VikMapsLayer struct) */
a8876892 76static guint *params_maptypes_ids = NULL;
50a14534
EB
77
78/******** MAPZOOMS *********/
79
fcc2786b
SW
80static 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 };
81static 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 };
82static 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 83
d756fb5c 84#define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0]) - 1)
50a14534
EB
85
86/**************************/
87
88
07059501 89static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file);
7924723c 90static const gchar* maps_layer_tooltip ( VikMapsLayer *vml );
911400b5
AF
91static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len );
92static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
158b3642
RN
93static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation );
94static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation );
50a14534
EB
95static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp );
96static VikMapsLayer *maps_layer_new ( VikViewport *vvp );
97static void maps_layer_free ( VikMapsLayer *vml );
98static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
99static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
941aa6e9 100static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp );
50a14534
EB
101static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir );
102static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload );
103static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp );
e2cb421f 104static guint map_uniq_id_to_index ( guint uniq_id );
50a14534
EB
105
106
107static VikLayerParamScale params_scales[] = {
108 /* min, max, step, digits (decimal places) */
109 { 0, 255, 3, 0 }, /* alpha */
110};
111
a7023a1b
RN
112static VikLayerParamData mode_default ( void ) { return VIK_LPD_UINT ( 19 ); } // OSM MapQuest maps
113static VikLayerParamData directory_default ( void )
114{
115 VikLayerParamData data;
b781c9db 116 VikLayerParamData *pref = a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir");
9414408e 117 if (pref) data.s = g_strdup ( pref->s ); else data.s = "";
a7023a1b
RN
118 return data;
119}
120static VikLayerParamData alpha_default ( void ) { return VIK_LPD_UINT ( 255 ); }
121static VikLayerParamData mapzoom_default ( void ) { return VIK_LPD_UINT ( 0 ); }
122
50a14534 123VikLayerParam maps_layer_params[] = {
a87f8fa1
RN
124 { VIK_LAYER_MAPS, "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Map Type:"), VIK_LAYER_WIDGET_COMBOBOX, NULL, NULL, NULL, mode_default, NULL, NULL },
125 { 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 },
a7023a1b 126 { VIK_LAYER_MAPS, "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales, NULL,
a87f8fa1
RN
127 N_("Control the Alpha value for transparency effects"), alpha_default, NULL, NULL },
128 { 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 129 { 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 130 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
131 { VIK_LAYER_MAPS, "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms, NULL,
132 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 133 mapzoom_default, NULL, NULL },
50a14534
EB
134};
135
382566c3
RN
136enum {
137 PARAM_MAPTYPE=0,
138 PARAM_CACHE_DIR,
139 PARAM_ALPHA,
140 PARAM_AUTODOWNLOAD,
141 PARAM_ONLYMISSING,
142 PARAM_MAPZOOM,
143 NUM_PARAMS
144};
50a14534 145
0d66c56c
RN
146void maps_layer_set_autodownload_default ( gboolean autodownload )
147{
148 // Set appropriate function
149 if ( autodownload )
150 maps_layer_params[PARAM_AUTODOWNLOAD].default_value = vik_lpd_true_default;
151 else
152 maps_layer_params[PARAM_AUTODOWNLOAD].default_value = vik_lpd_false_default;
153}
154
50a14534 155static VikToolInterface maps_tools[] = {
79dce0cb 156 { { "MapsDownload", "vik-icon-Maps Download", N_("_Maps Download"), NULL, N_("Maps Download"), 0 },
6b59f63d
RN
157 (VikToolConstructorFunc) maps_layer_download_create,
158 NULL,
159 NULL,
160 NULL,
161 (VikToolMouseFunc) maps_layer_download_click,
162 NULL,
163 (VikToolMouseFunc) maps_layer_download_release,
164 NULL,
ef5e8132
RN
165 FALSE,
166 GDK_CURSOR_IS_PIXMAP, &cursor_mapdl_pixbuf },
50a14534
EB
167};
168
169VikLayerInterface vik_maps_layer_interface = {
db386630 170 "Map",
4c77d5e0 171 N_("Map"),
75078768 172 "<control><shift>M",
5bfafde9 173 &vikmapslayer_pixbuf,
50a14534
EB
174
175 maps_tools,
176 sizeof(maps_tools) / sizeof(maps_tools[0]),
177
178 maps_layer_params,
179 NUM_PARAMS,
180 NULL,
181 0,
182
5a4a28bf
QT
183 VIK_MENU_ITEM_ALL,
184
50a14534
EB
185 (VikLayerFuncCreate) maps_layer_new,
186 (VikLayerFuncRealize) NULL,
b112cbf5 187 (VikLayerFuncPostRead) maps_layer_post_read,
50a14534
EB
188 (VikLayerFuncFree) maps_layer_free,
189
190 (VikLayerFuncProperties) NULL,
191 (VikLayerFuncDraw) maps_layer_draw,
192 (VikLayerFuncChangeCoordMode) NULL,
193
20c7a3a0
QT
194 (VikLayerFuncSetMenuItemsSelection) NULL,
195 (VikLayerFuncGetMenuItemsSelection) NULL,
196
50a14534
EB
197 (VikLayerFuncAddMenuItems) maps_layer_add_menu_items,
198 (VikLayerFuncSublayerAddMenuItems) NULL,
199
200 (VikLayerFuncSublayerRenameRequest) NULL,
201 (VikLayerFuncSublayerToggleVisible) NULL,
9da7faf2 202 (VikLayerFuncSublayerTooltip) NULL,
7924723c 203 (VikLayerFuncLayerTooltip) maps_layer_tooltip,
a5dcfdb7 204 (VikLayerFuncLayerSelected) NULL,
50a14534 205
911400b5
AF
206 (VikLayerFuncMarshall) maps_layer_marshall,
207 (VikLayerFuncUnmarshall) maps_layer_unmarshall,
50a14534
EB
208
209 (VikLayerFuncSetParam) maps_layer_set_param,
210 (VikLayerFuncGetParam) maps_layer_get_param,
211
212 (VikLayerFuncReadFileData) NULL,
213 (VikLayerFuncWriteFileData) NULL,
214
33534cd8 215 (VikLayerFuncDeleteItem) NULL,
d5874ef9 216 (VikLayerFuncCutItem) NULL,
50a14534
EB
217 (VikLayerFuncCopyItem) NULL,
218 (VikLayerFuncPasteItem) NULL,
219 (VikLayerFuncFreeCopiedItem) NULL,
70a23263 220 (VikLayerFuncDragDropRequest) NULL,
77ad64fa
RN
221
222 (VikLayerFuncSelectClick) NULL,
08f14055
RN
223 (VikLayerFuncSelectMove) NULL,
224 (VikLayerFuncSelectRelease) NULL,
e46f259a 225 (VikLayerFuncSelectedViewportMenu) NULL,
50a14534
EB
226};
227
228struct _VikMapsLayer {
229 VikLayer vl;
230 guint maptype;
231 gchar *cache_dir;
232 guint8 alpha;
233 guint mapzoom_id;
234 gdouble xmapzoom, ymapzoom;
235
236 gboolean autodownload;
382566c3 237 gboolean adl_only_missing;
10ca2bfe
QT
238 VikCoord *last_center;
239 gdouble last_xmpp;
240 gdouble last_ympp;
50a14534
EB
241
242 gint dl_tool_x, dl_tool_y;
243
244 GtkMenu *dl_right_click_menu;
245 VikCoord redownload_ul, redownload_br; /* right click menu only */
246 VikViewport *redownload_vvp;
247};
248
6a4a29aa
JJ
249enum { REDOWNLOAD_NONE = 0, /* download only missing maps */
250 REDOWNLOAD_BAD, /* download missing and bad maps */
251 REDOWNLOAD_NEW, /* download missing maps that are newer on server only */
252 REDOWNLOAD_ALL, /* download all maps */
253 DOWNLOAD_OR_REFRESH }; /* download missing maps and refresh cache */
50a14534 254
55ddef4e 255static VikLayerParam prefs[] = {
bbd41664 256 { 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") },
55ddef4e
JJ
257};
258
259void maps_layer_init ()
260{
261 VikLayerParamData tmp;
262 tmp.s = maps_layer_default_dir();
263 a_preferences_register(prefs, tmp, VIKING_PREFERENCES_GROUP_KEY);
0f7e9133
RN
264
265 gint max_tiles = MAX_TILES;
266 if ( a_settings_get_integer ( VIK_SETTINGS_MAP_MAX_TILES, &max_tiles ) )
267 MAX_TILES = max_tiles;
268
269 gdouble gdtmp;
270 if ( a_settings_get_double ( VIK_SETTINGS_MAP_MIN_SHRINKFACTOR, &gdtmp ) )
271 MIN_SHRINKFACTOR = gdtmp;
272
273 if ( a_settings_get_double ( VIK_SETTINGS_MAP_MAX_SHRINKFACTOR, &gdtmp ) )
274 MAX_SHRINKFACTOR = gdtmp;
275
276 if ( a_settings_get_double ( VIK_SETTINGS_MAP_REAL_MIN_SHRINKFACTOR, &gdtmp ) )
277 REAL_MIN_SHRINKFACTOR = gdtmp;
55ddef4e 278}
50a14534 279
cdcaf41c
QT
280/****************************************/
281/******** MAPS LAYER TYPES **************/
282/****************************************/
283
e2cb421f
GB
284void _add_map_source ( guint id, const char *label, VikMapSource *map )
285{
a8876892
GB
286 gsize len = 0;
287 if (params_maptypes)
288 len = g_strv_length (params_maptypes);
cdcaf41c 289 /* Add the label */
a8876892
GB
290 params_maptypes = g_realloc (params_maptypes, (len+2)*sizeof(gchar*));
291 params_maptypes[len] = g_strdup (label);
292 params_maptypes[len+1] = NULL;
cdcaf41c
QT
293
294 /* Add the id */
a8876892
GB
295 params_maptypes_ids = g_realloc (params_maptypes_ids, (len+2)*sizeof(guint));
296 params_maptypes_ids[len] = id;
297 params_maptypes_ids[len+1] = 0;
cdcaf41c
QT
298
299 /* We have to clone */
820c59f4 300 VikMapSource *clone = VIK_MAP_SOURCE(g_object_ref(map));
cdcaf41c
QT
301 /* Register the clone in the list */
302 __map_types = g_list_append(__map_types, clone);
303
304 /* Hack
e2cb421f 305 We have to ensure the mode LayerParam references the up-to-date
cdcaf41c
QT
306 GLists.
307 */
308 /*
309 memcpy(&maps_layer_params[0].widget_data, &params_maptypes, sizeof(gpointer));
310 memcpy(&maps_layer_params[0].extra_widget_data, &params_maptypes_ids, sizeof(gpointer));
311 */
312 maps_layer_params[0].widget_data = params_maptypes;
313 maps_layer_params[0].extra_widget_data = params_maptypes_ids;
314}
315
e2cb421f
GB
316void _update_map_source ( const char *label, VikMapSource *map, int index )
317{
318 GList *item = g_list_nth (__map_types, index);
319 g_object_unref (item->data);
320 item->data = g_object_ref (map);
321 /* Change previous data */
322 g_free (params_maptypes[index]);
323 params_maptypes[index] = g_strdup (label);
324}
325
17281ebd
GB
326/**
327 * maps_layer_register_map_source:
328 * @map: the new VikMapSource
329 *
330 * Register a new VikMapSource.
331 * Override existing one (equality of id).
332 */
e2cb421f
GB
333void maps_layer_register_map_source ( VikMapSource *map )
334{
335 g_assert(map != NULL);
336
337 guint id = vik_map_source_get_uniq_id(map);
338 const char *label = vik_map_source_get_label(map);
339 g_assert(label != NULL);
340
341 int previous = map_uniq_id_to_index (id);
342 if (previous != NUM_MAP_TYPES)
343 {
344 _update_map_source (label, map, previous);
345 }
346 else
347 {
348 _add_map_source (id, label, map);
349 }
350}
351
a8876892
GB
352#define MAPS_LAYER_NTH_LABEL(n) (params_maptypes[n])
353#define MAPS_LAYER_NTH_ID(n) (params_maptypes_ids[n])
820c59f4 354#define MAPS_LAYER_NTH_TYPE(n) (VIK_MAP_SOURCE(g_list_nth_data(__map_types, (n))))
cdcaf41c 355
7114e879
QT
356gint vik_maps_layer_get_map_type(VikMapsLayer *vml)
357{
358 return(vml->maptype);
359}
360
361gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml)
362{
363 return(g_strdup(MAPS_LAYER_NTH_LABEL(vml->maptype)));
364}
365
50a14534
EB
366/****************************************/
367/******** CACHE DIR STUFF ***************/
368/****************************************/
369
2673b29d 370#define DIRECTDIRACCESS "%s%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d%s"
3d9454e6 371#define DIRSTRUCTURE "%st%ds%dz%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d"
6a27c1bc
MA
372#define MAPS_CACHE_DIR maps_layer_default_dir()
373
50a14534 374#ifdef WINDOWS
6a27c1bc
MA
375#include <io.h>
376#define GLOBAL_MAPS_DIR "C:\\VIKING-MAPS\\"
377#define LOCAL_MAPS_DIR "VIKING-MAPS"
42293fc2
RN
378#elif defined __APPLE__
379#include <stdlib.h>
380#define GLOBAL_MAPS_DIR "/Library/cache/Viking/maps/"
381#define LOCAL_MAPS_DIR "/Library/Application Support/Viking/viking-maps"
50a14534 382#else /* POSIX */
50a14534 383#include <stdlib.h>
50a14534 384#define GLOBAL_MAPS_DIR "/var/cache/maps/"
6a27c1bc
MA
385#define LOCAL_MAPS_DIR ".viking-maps"
386#endif
50a14534 387
0c1044e9 388gchar *maps_layer_default_dir ()
50a14534 389{
3d9454e6
GB
390 static gchar *defaultdir = NULL;
391 if ( ! defaultdir )
50a14534
EB
392 {
393 /* Thanks to Mike Davison for the $VIKING_MAPS usage */
3d9454e6
GB
394 const gchar *mapdir = g_getenv("VIKING_MAPS");
395 if ( mapdir ) {
396 defaultdir = g_strdup ( mapdir );
45acf79e 397 } else if ( g_access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) {
3d9454e6 398 defaultdir = g_strdup ( GLOBAL_MAPS_DIR );
50a14534 399 } else {
6a27c1bc 400 const gchar *home = g_get_home_dir();
45acf79e 401 if (!home || g_access(home, W_OK))
3d9454e6
GB
402 home = g_get_home_dir ();
403 if ( home )
6a27c1bc 404 defaultdir = g_build_filename ( home, LOCAL_MAPS_DIR, NULL );
50a14534 405 else
6a27c1bc 406 defaultdir = g_strdup ( LOCAL_MAPS_DIR );
50a14534 407 }
3d9454e6
GB
408 if (defaultdir && (defaultdir[strlen(defaultdir)-1] != G_DIR_SEPARATOR))
409 {
410 /* Add the separator at the end */
411 gchar *tmp = defaultdir;
412 defaultdir = g_strconcat(tmp, G_DIR_SEPARATOR_S, NULL);
413 g_free(tmp);
414 }
415 g_debug("%s: defaultdir=%s", __FUNCTION__, defaultdir);
50a14534
EB
416 }
417 return defaultdir;
418}
419
50a14534
EB
420static void maps_layer_mkdir_if_default_dir ( VikMapsLayer *vml )
421{
45acf79e 422 if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && g_file_test ( vml->cache_dir, G_FILE_TEST_EXISTS ) == FALSE )
50a14534 423 {
f83131b9 424 g_mkdir ( vml->cache_dir, 0777 );
50a14534
EB
425 }
426}
427
428static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir )
429{
430 guint len;
431 g_assert ( vml != NULL);
e65028db
GB
432 g_free ( vml->cache_dir );
433 vml->cache_dir = NULL;
32f1d63a 434 const gchar *mydir = dir;
50a14534
EB
435
436 if ( dir == NULL || dir[0] == '\0' )
6926d79a
RN
437 {
438 if ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir") )
32f1d63a 439 mydir = a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir")->s;
6926d79a 440 }
32f1d63a
RN
441
442 // Ensure cache_dir always ends with a separator
443 len = strlen(mydir);
444 if ( mydir[len-1] != G_DIR_SEPARATOR )
50a14534 445 {
32f1d63a
RN
446 vml->cache_dir = g_malloc ( len+2 );
447 strncpy ( vml->cache_dir, mydir, len );
448 vml->cache_dir[len] = G_DIR_SEPARATOR;
449 vml->cache_dir[len+1] = '\0';
50a14534 450 }
32f1d63a
RN
451 else
452 vml->cache_dir = g_strdup ( mydir );
453
50a14534
EB
454 maps_layer_mkdir_if_default_dir ( vml );
455}
456
457/****************************************/
458/******** GOBJECT STUFF *****************/
459/****************************************/
460
461GType vik_maps_layer_get_type ()
462{
463 static GType vml_type = 0;
464
465 if (!vml_type)
466 {
467 static const GTypeInfo vml_info =
468 {
469 sizeof (VikMapsLayerClass),
470 NULL, /* base_init */
471 NULL, /* base_finalize */
472 NULL, /* class init */
473 NULL, /* class_finalize */
474 NULL, /* class_data */
475 sizeof (VikMapsLayer),
476 0,
477 NULL /* instance init */
478 };
479 vml_type = g_type_register_static ( VIK_LAYER_TYPE, "VikMapsLayer", &vml_info, 0 );
480 }
481
482 return vml_type;
483}
484
485/****************************************/
486/************** PARAMETERS **************/
487/****************************************/
488
d7e495b2 489static guint map_index_to_uniq_id (guint16 index)
50a14534
EB
490{
491 g_assert ( index < NUM_MAP_TYPES );
820c59f4 492 return vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(index));
50a14534
EB
493}
494
495static guint map_uniq_id_to_index ( guint uniq_id )
496{
497 gint i;
498 for ( i = 0; i < NUM_MAP_TYPES; i++ )
820c59f4 499 if ( vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(i)) == uniq_id )
50a14534
EB
500 return i;
501 return NUM_MAP_TYPES; /* no such thing */
502}
503
b03ae39b
RN
504#define VIK_SETTINGS_MAP_LICENSE_SHOWN "map_license_shown"
505
506/**
507 * Convenience function to display the license
508 */
509static void maps_show_license ( GtkWindow *parent, VikMapSource *map )
192e40fc 510{
b03ae39b
RN
511 a_dialog_license ( parent,
512 vik_map_source_get_label (map),
513 vik_map_source_get_license (map),
514 vik_map_source_get_license_url (map) );
192e40fc
RN
515}
516
158b3642 517static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation )
50a14534
EB
518{
519 switch ( id )
520 {
521 case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break;
522 case PARAM_MAPTYPE: {
523 gint maptype = map_uniq_id_to_index(data.u);
b03ae39b
RN
524 if ( maptype == NUM_MAP_TYPES )
525 g_warning(_("Unknown map type"));
526 else {
527 vml->maptype = maptype;
528
529 // When loading from a file don't need the license reminder - ensure it's saved into the 'seen' list
530 if ( is_file_operation ) {
531 a_settings_set_integer_list_containing ( VIK_SETTINGS_MAP_LICENSE_SHOWN, maptype );
532 }
533 else {
534 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
535 if (vik_map_source_get_license (map) != NULL) {
536 // Check if licence for this map type has been shown before
537 if ( ! a_settings_get_integer_list_contains ( VIK_SETTINGS_MAP_LICENSE_SHOWN, maptype ) ) {
538 if ( vvp )
539 maps_show_license ( VIK_GTK_WINDOW_FROM_WIDGET(vvp), map );
540 a_settings_set_integer_list_containing ( VIK_SETTINGS_MAP_LICENSE_SHOWN, maptype );
541 }
542 }
543 }
544 }
50a14534
EB
545 break;
546 }
547 case PARAM_ALPHA: if ( data.u <= 255 ) vml->alpha = data.u; break;
548 case PARAM_AUTODOWNLOAD: vml->autodownload = data.b; break;
382566c3 549 case PARAM_ONLYMISSING: vml->adl_only_missing = data.b; break;
50a14534
EB
550 case PARAM_MAPZOOM: if ( data.u < NUM_MAPZOOMS ) {
551 vml->mapzoom_id = data.u;
552 vml->xmapzoom = __mapzooms_x [data.u];
553 vml->ymapzoom = __mapzooms_y [data.u];
4c77d5e0 554 }else g_warning (_("Unknown Map Zoom")); break;
50a14534
EB
555 }
556 return TRUE;
557}
558
158b3642 559static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation )
50a14534
EB
560{
561 VikLayerParamData rv;
562 switch ( id )
563 {
cde1e50e 564 case PARAM_CACHE_DIR:
88542aa9
RN
565 {
566 gboolean set = FALSE;
cde1e50e
RN
567 /* Only save a blank when the map cache location equals the default
568 On reading in, when it is blank then the default is reconstructed
569 Since the default changes dependent on the user and OS, it means the resultant file is more portable */
88542aa9 570 if ( is_file_operation && vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 ) {
cde1e50e 571 rv.s = "";
88542aa9
RN
572 set = TRUE;
573 }
574 else if ( is_file_operation ) {
575 if ( a_vik_get_file_ref_format() == VIK_FILE_REF_FORMAT_RELATIVE ) {
576 gchar *cwd = g_get_current_dir();
577 if ( cwd ) {
578 rv.s = file_GetRelativeFilename ( cwd, vml->cache_dir );
579 if ( !rv.s ) rv.s = "";
580 set = TRUE;
581 }
582 }
583 }
584 if ( !set )
585 rv.s = vml->cache_dir ? vml->cache_dir : "";
cde1e50e 586 break;
88542aa9 587 }
50a14534
EB
588 case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break;
589 case PARAM_ALPHA: rv.u = vml->alpha; break;
590 case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break;
382566c3 591 case PARAM_ONLYMISSING: rv.u = vml->adl_only_missing; break;
50a14534
EB
592 case PARAM_MAPZOOM: rv.u = vml->mapzoom_id; break;
593 }
594 return rv;
595}
596
597/****************************************/
598/****** CREATING, COPYING, FREEING ******/
599/****************************************/
600
601static VikMapsLayer *maps_layer_new ( VikViewport *vvp )
602{
603 VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) );
a0c65899 604 vik_layer_set_type ( VIK_LAYER(vml), VIK_LAYER_MAPS );
a7023a1b
RN
605
606 vik_layer_set_defaults ( VIK_LAYER(vml), vvp );
607
50a14534 608 vml->dl_tool_x = vml->dl_tool_y = -1;
10ca2bfe
QT
609 vml->last_center = NULL;
610 vml->last_xmpp = 0.0;
611 vml->last_ympp = 0.0;
50a14534
EB
612
613 vml->dl_right_click_menu = NULL;
b03ae39b 614 //vml->license_notice_shown = FALSE;
50a14534
EB
615
616 return vml;
617}
618
619static void maps_layer_free ( VikMapsLayer *vml )
620{
e65028db
GB
621 g_free ( vml->cache_dir );
622 vml->cache_dir = NULL;
50a14534 623 if ( vml->dl_right_click_menu )
4f14a010 624 g_object_ref_sink ( G_OBJECT(vml->dl_right_click_menu) );
e65028db
GB
625 g_free(vml->last_center);
626 vml->last_center = NULL;
50a14534
EB
627}
628
07059501 629static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file)
dc5758d3 630{
07059501
GB
631 if (from_file != TRUE)
632 {
633 /* If this method is not called in file reading context
634 * it is called in GUI context.
635 * So, we can check if we have to inform the user about inconsistency */
636 VikViewportDrawMode vp_drawmode;
637 VikMapsLayer *vml = VIK_MAPS_LAYER(vl);
820c59f4 638 VikMapSource *map = NULL;
dc5758d3 639
405b74ed 640 vp_drawmode = vik_viewport_get_drawmode ( vp );
820c59f4
GB
641 map = MAPS_LAYER_NTH_TYPE(vml->maptype);
642 if (vik_map_source_get_drawmode(map) != vp_drawmode) {
405b74ed 643 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vp, vik_map_source_get_drawmode(map));
4c77d5e0 644 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 645 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp), msg );
07059501
GB
646 g_free(msg);
647 }
dc5758d3
GB
648 }
649}
650
7924723c
RN
651static const gchar* maps_layer_tooltip ( VikMapsLayer *vml )
652{
653 return vik_maps_layer_get_map_label ( vml );
654}
655
911400b5
AF
656static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len )
657{
658 vik_layer_marshall_params ( VIK_LAYER(vml), data, len );
659}
660
661static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
662{
663 VikMapsLayer *rv = maps_layer_new ( vvp );
664 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
665 return rv;
666}
667
50a14534
EB
668/*********************/
669/****** DRAWING ******/
670/*********************/
671
672static GdkPixbuf *pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha )
673{
674 guchar *pixels;
675 gint width, height, iii, jjj;
676
677 if ( ! gdk_pixbuf_get_has_alpha ( pixbuf ) )
678 {
679 GdkPixbuf *tmp = gdk_pixbuf_add_alpha(pixbuf,FALSE,0,0,0);
680 g_object_unref(G_OBJECT(pixbuf));
681 pixbuf = tmp;
45b0031e
RN
682 if ( !pixbuf )
683 return NULL;
50a14534
EB
684 }
685
686 pixels = gdk_pixbuf_get_pixels(pixbuf);
687 width = gdk_pixbuf_get_width(pixbuf);
688 height = gdk_pixbuf_get_height(pixbuf);
689
690 /* r,g,b,a,r,g,b,a.... */
691 for (iii = 0; iii < width; iii++) for (jjj = 0; jjj < height; jjj++)
692 {
693 pixels += 3;
694 *pixels++ = alpha;
695 }
696 return pixbuf;
697}
698
699static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdouble yshrinkfactor )
700{
701 GdkPixbuf *tmp;
702 guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf);
2d5d32c1 703 tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_BILINEAR);
50a14534
EB
704 g_object_unref ( G_OBJECT(pixbuf) );
705 return tmp;
706}
707
708static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, gchar *filename_buf, gint buf_len, gdouble xshrinkfactor, gdouble yshrinkfactor )
709{
710 GdkPixbuf *pixbuf;
711
712 /* get the thing */
713 pixbuf = a_mapcache_get ( mapcoord->x, mapcoord->y, mapcoord->z,
714 mode, mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
715
716 if ( ! pixbuf ) {
2673b29d
RN
717 if ( vik_map_source_is_direct_file_access (MAPS_LAYER_NTH_TYPE(vml->maptype)) )
718 g_snprintf ( filename_buf, buf_len, DIRECTDIRACCESS,
719 vml->cache_dir, (17 - mapcoord->scale), mapcoord->x, mapcoord->y, ".png" );
720 else
721 g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE,
722 vml->cache_dir, mode,
723 mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y );
724
01ecda7e 725 if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
50a14534
EB
726 {
727 GError *gx = NULL;
728 pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx );
729
01ecda7e 730 /* free the pixbuf on error */
50a14534
EB
731 if (gx)
732 {
733 if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE )
4c77d5e0 734 g_warning ( _("Couldn't open image file: %s"), gx->message );
50a14534 735
01ecda7e
MR
736 g_error_free ( gx );
737 if ( pixbuf )
738 g_object_unref ( G_OBJECT(pixbuf) );
739 pixbuf = NULL;
740 } else {
50a14534
EB
741 if ( vml->alpha < 255 )
742 pixbuf = pixbuf_set_alpha ( pixbuf, vml->alpha );
743 if ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 )
744 pixbuf = pixbuf_shrink ( pixbuf, xshrinkfactor, yshrinkfactor );
745
45b0031e
RN
746 if ( pixbuf )
747 a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y,
748 mapcoord->z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(vml->maptype)),
749 mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
50a14534
EB
750 }
751 }
752 }
753 return pixbuf;
754}
755
9979924f 756static gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp)
10ca2bfe
QT
757{
758 const VikCoord *center = vik_viewport_get_center ( vvp );
759
bbf2149b 760 if (vik_window_get_pan_move (VIK_WINDOW(VIK_GTK_WINDOW_FROM_WIDGET(GTK_WIDGET(vvp)))))
01da6b4d 761 /* D'n'D pan in action: do not download */
1c6a6010
GB
762 return FALSE;
763
9979924f
RN
764 // TEMPORARY HACK
765 // Prevent requests for downloading tiles at Zoom Level 19 and above for most map types
766 // Allow MapQuest Zoom Level up to 19
767 // TODO: This should be made a property of the map source and then use that value
768 gdouble xzoom = vik_viewport_get_xmpp ( vvp );
769 if ( (vml->maptype != 19 && map_utils_mpp_to_scale (xzoom) < -1) || (vml->maptype == 19 && map_utils_mpp_to_scale (xzoom) < -2) )
770 return FALSE;
771
10ca2bfe
QT
772 if (vml->last_center == NULL) {
773 VikCoord *new_center = g_malloc(sizeof(VikCoord));
774 *new_center = *center;
775 vml->last_center = new_center;
776 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
777 vml->last_ympp = vik_viewport_get_ympp(vvp);
778 return TRUE;
779 }
780
781 /* TODO: perhaps vik_coord_diff() */
782 if (vik_coord_equals(vml->last_center, center)
783 && (vml->last_xmpp == vik_viewport_get_xmpp(vvp))
784 && (vml->last_ympp == vik_viewport_get_ympp(vvp)))
785 return FALSE;
786
787 *(vml->last_center) = *center;
788 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
789 vml->last_ympp = vik_viewport_get_ympp(vvp);
790 return TRUE;
791}
792
50a14534
EB
793static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br )
794{
795 MapCoord ulm, brm;
796 gdouble xzoom = vik_viewport_get_xmpp ( vvp );
797 gdouble yzoom = vik_viewport_get_ympp ( vvp );
798 gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0;
2673b29d 799 gboolean existence_only = FALSE;
50a14534
EB
800
801 if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) {
802 xshrinkfactor = vml->xmapzoom / xzoom;
803 yshrinkfactor = vml->ymapzoom / yzoom;
732d1e25
EB
804 xzoom = vml->xmapzoom;
805 yzoom = vml->xmapzoom;
806 if ( ! (xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR &&
807 yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) ) {
6de95419
RN
808 if ( xshrinkfactor > REAL_MIN_SHRINKFACTOR && yshrinkfactor > REAL_MIN_SHRINKFACTOR ) {
809 g_debug ( "%s: existence_only due to SHRINKFACTORS", __FUNCTION__ );
732d1e25 810 existence_only = TRUE;
6de95419 811 }
732d1e25 812 else {
4c77d5e0 813 g_warning ( _("Cowardly refusing to draw tiles or existence of tiles beyond %d zoom out factor"), (int)( 1.0/REAL_MIN_SHRINKFACTOR));
732d1e25
EB
814 return;
815 }
50a14534
EB
816 }
817 }
818
819 /* coord -> ID */
820c59f4
GB
820 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
821 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm ) &&
822 vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) ) {
50a14534
EB
823
824 /* loop & draw */
825 gint x, y;
826 gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x);
827 gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y);
820c59f4 828 gint mode = vik_map_source_get_uniq_id(map);
50a14534
EB
829
830 VikCoord coord;
831 gint xx, yy, width, height;
832 GdkPixbuf *pixbuf;
833
6de95419
RN
834 // Prevent the program grinding to a halt if trying to deal with thousands of tiles
835 // which can happen when using a small fixed zoom level and viewing large areas.
836 // Also prevents very large number of tile download requests
837 gint tiles = (xmax-xmin) * (ymax-ymin);
838 if ( tiles > MAX_TILES ) {
839 g_debug ( "%s: existence_only due to wanting too many tiles (%d)", __FUNCTION__, tiles );
840 existence_only = TRUE;
841 }
842
50a14534
EB
843 guint max_path_len = strlen(vml->cache_dir) + 40;
844 gchar *path_buf = g_malloc ( max_path_len * sizeof(char) );
845
732d1e25 846 if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) {
33be396e 847 g_debug("%s: Starting autodownload", __FUNCTION__);
382566c3 848 if ( !vml->adl_only_missing && vik_map_source_supports_download_only_new (map) )
245f48f5
GB
849 // Try to download newer tiles
850 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
851 else
852 // Download only missing tiles
853 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
10ca2bfe 854 }
50a14534 855
820c59f4 856 if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) {
50a14534
EB
857 for ( x = xmin; x <= xmax; x++ ) {
858 for ( y = ymin; y <= ymax; y++ ) {
859 ulm.x = x;
860 ulm.y = y;
861 pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
862 if ( pixbuf ) {
863 width = gdk_pixbuf_get_width ( pixbuf );
864 height = gdk_pixbuf_get_height ( pixbuf );
865
820c59f4 866 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
50a14534
EB
867 vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy );
868 xx -= (width/2);
869 yy -= (height/2);
870
871 vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height );
872 }
873 }
874 }
875 } else { /* tilesize is known, don't have to keep converting coords */
820c59f4
GB
876 gdouble tilesize_x = vik_map_source_get_tilesize_x(map) * xshrinkfactor;
877 gdouble tilesize_y = vik_map_source_get_tilesize_y(map) * yshrinkfactor;
50a14534
EB
878 /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
879 gint tilesize_x_ceil = ceil ( tilesize_x );
880 gint tilesize_y_ceil = ceil ( tilesize_y );
881 gint8 xinc = (ulm.x == xmin) ? 1 : -1;
882 gint8 yinc = (ulm.y == ymin) ? 1 : -1;
883 gdouble xx, yy; gint xx_tmp, yy_tmp;
884 gint base_yy, xend, yend;
732d1e25 885
50a14534
EB
886 xend = (xinc == 1) ? (xmax+1) : (xmin-1);
887 yend = (yinc == 1) ? (ymax+1) : (ymin-1);
888
820c59f4 889 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
50a14534
EB
890 vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp );
891 xx = xx_tmp; yy = yy_tmp;
892 /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
893 * eg if tile size 128, shrinkfactor 0.333 */
894 xx -= (tilesize_x/2);
895 base_yy = yy - (tilesize_y/2);
896
897 for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) {
898 yy = base_yy;
899 for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) {
900 ulm.x = x;
901 ulm.y = y;
732d1e25
EB
902
903 if ( existence_only ) {
2673b29d
RN
904 if ( vik_map_source_is_direct_file_access (MAPS_LAYER_NTH_TYPE(vml->maptype)) )
905 g_snprintf ( path_buf, max_path_len, DIRECTDIRACCESS,
906 vml->cache_dir, (17 - ulm.scale), ulm.x, ulm.y, ".png" );
907 else
908 g_snprintf ( path_buf, max_path_len, DIRSTRUCTURE,
909 vml->cache_dir, mode,
910 ulm.scale, ulm.z, ulm.x, ulm.y );
45acf79e 911 if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) {
ff37db21 912 GdkGC *black_gc = gtk_widget_get_style(GTK_WIDGET(vvp))->black_gc;
732d1e25
EB
913 vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil );
914 }
915 } else {
6f0d1bea
JJ
916 int scale_inc;
917 for (scale_inc = 0; scale_inc < 4; scale_inc ++) {
918 /* try with correct then smaller zooms */
919 int scale_factor = 1 << scale_inc; /* 2^scale_inc */
920 MapCoord ulm2 = ulm;
921 ulm2.x = ulm.x / scale_factor;
922 ulm2.y = ulm.y / scale_factor;
923 ulm2.scale = ulm.scale + scale_inc;
924 pixbuf = get_pixbuf ( vml, mode, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor );
925 if ( pixbuf ) {
926 gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil;
927 gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil;
40cfc175
JJ
928#ifdef DEBUG
929 printf("maps_layer_draw_section - x=%d, y=%d, z=%d, src_x=%d, src_y=%d, xx=%d, yy=%d - %x\n", ulm.x, ulm.y, ulm.scale, src_x, src_y, (int)xx, (int)yy, vvp);
930#endif
6f0d1bea
JJ
931 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
932 break;
933 }
934 }
935 if ( !pixbuf ) {
936 /* retry with bigger zooms */
937 int scale_dec;
938 for (scale_dec = 1; scale_dec < 2; scale_dec ++) {
939 int pict_x, pict_y;
940 int scale_factor = 1 << scale_dec; /* 2^scale_dec */
91dc4449 941 MapCoord ulm2 = ulm;
6f0d1bea
JJ
942 ulm2.x = ulm.x * scale_factor;
943 ulm2.y = ulm.y * scale_factor;
944 ulm2.scale = ulm.scale - scale_dec;
945 for (pict_x = 0; pict_x < scale_factor; pict_x ++) {
946 for (pict_y = 0; pict_y < scale_factor; pict_y ++) {
947 MapCoord ulm3 = ulm2;
948 ulm3.x += pict_x;
949 ulm3.y += pict_y;
950 pixbuf = get_pixbuf ( vml, mode, &ulm3, path_buf, max_path_len, xshrinkfactor / scale_factor, yshrinkfactor / scale_factor );
951 if ( pixbuf ) {
952 gint src_x = 0;
953 gint src_y = 0;
954 gint dest_x = xx + pict_x * (tilesize_x_ceil / scale_factor);
955 gint dest_y = yy + pict_y * (tilesize_y_ceil / scale_factor);
956 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, dest_x, dest_y, tilesize_x_ceil / scale_factor, tilesize_y_ceil / scale_factor );
957 }
958 }
91dc4449
JJ
959 }
960 }
961 }
732d1e25 962 }
50a14534
EB
963
964 yy += tilesize_y;
965 }
966 xx += tilesize_x;
967 }
968 }
969
970 g_free ( path_buf );
971 }
972}
973
974static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp )
975{
820c59f4 976 if ( vik_map_source_get_drawmode(MAPS_LAYER_NTH_TYPE(vml->maptype)) == vik_viewport_get_drawmode ( vvp ) )
50a14534
EB
977 {
978 VikCoord ul, br;
979
82aa018d 980 /* Copyright */
68b1d6c0
GB
981 gdouble level = vik_viewport_get_zoom ( vvp );
982 LatLonBBox bbox;
983 vik_viewport_get_min_max_lat_lon ( vvp, &bbox.south, &bbox.north, &bbox.west, &bbox.east );
984 vik_map_source_get_copyright ( MAPS_LAYER_NTH_TYPE(vml->maptype), bbox, level, vik_viewport_add_copyright, vvp );
82aa018d 985
26336cf0
GB
986 /* Logo */
987 const GdkPixbuf *logo = vik_map_source_get_logo ( MAPS_LAYER_NTH_TYPE(vml->maptype) );
988 vik_viewport_add_logo ( vvp, logo );
989
50a14534
EB
990 /* get corner coords */
991 if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) {
992 /* UTM multi-zone stuff by Kit Transue */
993 gchar leftmost_zone, rightmost_zone, i;
994 leftmost_zone = vik_viewport_leftmost_zone( vvp );
995 rightmost_zone = vik_viewport_rightmost_zone( vvp );
996 for ( i = leftmost_zone; i <= rightmost_zone; ++i ) {
997 vik_viewport_corners_for_zonen ( vvp, i, &ul, &br );
998 maps_layer_draw_section ( vml, vvp, &ul, &br );
999 }
1000 }
1001 else {
1002 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1003 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1004
1005 maps_layer_draw_section ( vml, vvp, &ul, &br );
1006 }
1007 }
1008}
1009
1010/*************************/
1011/****** DOWNLOADING ******/
1012/*************************/
1013
1014/* pass along data to thread, exists even if layer is deleted. */
1015typedef struct {
1016 gchar *cache_dir;
1017 gchar *filename_buf;
1018 gint x0, y0, xf, yf;
1019 MapCoord mapcoord;
1020 gint maptype;
1021 gint maxlen;
1022 gint mapstoget;
1023 gint redownload;
7114e879 1024 gboolean refresh_display;
550fd035
QT
1025 VikMapsLayer *vml;
1026 VikViewport *vvp;
1027 gboolean map_layer_alive;
1028 GMutex *mutex;
50a14534
EB
1029} MapDownloadInfo;
1030
1031static void mdi_free ( MapDownloadInfo *mdi )
1032{
550fd035 1033 g_mutex_free(mdi->mutex);
50a14534 1034 g_free ( mdi->cache_dir );
e65028db 1035 mdi->cache_dir = NULL;
50a14534 1036 g_free ( mdi->filename_buf );
e65028db 1037 mdi->filename_buf = NULL;
50a14534
EB
1038 g_free ( mdi );
1039}
1040
7bb60307 1041static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
550fd035 1042{
7bb60307 1043 MapDownloadInfo *mdi = ptr;
550fd035
QT
1044 g_mutex_lock(mdi->mutex);
1045 mdi->map_layer_alive = FALSE;
1046 g_mutex_unlock(mdi->mutex);
1047}
1048
634eca0a 1049static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
50a14534 1050{
825413ba 1051 void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype));
50a14534
EB
1052 guint donemaps = 0;
1053 gint x, y;
1054 for ( x = mdi->x0; x <= mdi->xf; x++ )
1055 {
1056 for ( y = mdi->y0; y <= mdi->yf; y++ )
1057 {
94493114 1058 gboolean remove_mem_cache = FALSE;
84628352 1059 gboolean need_download = FALSE;
50a14534 1060 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 1061 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
50a14534
EB
1062 mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
1063
84628352 1064 donemaps++;
634eca0a 1065 int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
825413ba
SW
1066 if (res != 0) {
1067 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
634eca0a 1068 return -1;
825413ba 1069 }
84628352 1070
a0058e48 1071 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
6a4a29aa
JJ
1072 need_download = TRUE;
1073 remove_mem_cache = TRUE;
a0058e48
JJ
1074
1075 } else { /* in case map file already exists */
1076 switch (mdi->redownload) {
1077 case REDOWNLOAD_NONE:
1078 continue;
1079
1080 case REDOWNLOAD_BAD:
1081 {
1082 /* see if this one is bad or what */
1083 GError *gx = NULL;
1084 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
1085 if (gx || (!pixbuf)) {
1086 g_remove ( mdi->filename_buf );
1087 need_download = TRUE;
1088 remove_mem_cache = TRUE;
1089 g_error_free ( gx );
1090
1091 } else {
1092 g_object_unref ( pixbuf );
1093 }
1094 break;
1095 }
1096
1097 case REDOWNLOAD_NEW:
1098 need_download = TRUE;
1099 remove_mem_cache = TRUE;
1100 break;
1101
1102 case REDOWNLOAD_ALL:
1103 /* FIXME: need a better way than to erase file in case of server/network problem */
1104 g_remove ( mdi->filename_buf );
1105 need_download = TRUE;
1106 remove_mem_cache = TRUE;
1107 break;
1108
1109 case DOWNLOAD_OR_REFRESH:
1110 remove_mem_cache = TRUE;
1111 break;
1112
1113 default:
1114 g_warning ( "redownload state %d unknown\n", mdi->redownload);
1115 }
1116 }
94493114 1117
94493114 1118 mdi->mapcoord.x = x; mdi->mapcoord.y = y;
84628352
QT
1119
1120 if (need_download) {
825413ba 1121 if ( vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle))
94493114 1122 continue;
84628352 1123 }
94493114 1124
94493114
QT
1125 g_mutex_lock(mdi->mutex);
1126 if (remove_mem_cache)
820c59f4 1127 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 );
7114e879 1128 if (mdi->refresh_display && mdi->map_layer_alive) {
94493114 1129 /* TODO: check if it's on visible area */
da121f9b 1130 vik_layer_emit_update ( VIK_LAYER(mdi->vml) ); // NB update display from background
a0b59f2f 1131 }
94493114 1132 g_mutex_unlock(mdi->mutex);
94493114
QT
1133 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
1134
50a14534
EB
1135 }
1136 }
825413ba 1137 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
04e54492
QT
1138 g_mutex_lock(mdi->mutex);
1139 if (mdi->map_layer_alive)
7bb60307 1140 g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
04e54492 1141 g_mutex_unlock(mdi->mutex);
634eca0a 1142 return 0;
50a14534
EB
1143}
1144
1145static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
1146{
1147 if ( mdi->mapcoord.x || mdi->mapcoord.y )
1148 {
1149 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 1150 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
50a14534 1151 mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y );
45acf79e 1152 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
50a14534 1153 {
8c060406 1154 g_remove ( mdi->filename_buf );
50a14534
EB
1155 }
1156 }
1157}
1158
1159static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload )
1160{
1161 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1162 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1163 MapCoord ulm, brm;
820c59f4 1164 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
2673b29d
RN
1165
1166 // Don't ever attempt download on direct access
1167 if ( vik_map_source_is_direct_file_access ( map ) )
1168 return;
1169
820c59f4
GB
1170 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm )
1171 && vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) )
50a14534
EB
1172 {
1173 MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
1174 gint a, b;
1175
550fd035
QT
1176 mdi->vml = vml;
1177 mdi->vvp = vvp;
1178 mdi->map_layer_alive = TRUE;
1179 mdi->mutex = g_mutex_new();
7114e879 1180 mdi->refresh_display = TRUE;
550fd035 1181
50a14534
EB
1182 /* cache_dir and buffer for dest filename */
1183 mdi->cache_dir = g_strdup ( vml->cache_dir );
1184 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1185 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1186 mdi->maptype = vml->maptype;
1187
1188 mdi->mapcoord = ulm;
50a14534
EB
1189 mdi->redownload = redownload;
1190
1191 mdi->x0 = MIN(ulm.x, brm.x);
1192 mdi->xf = MAX(ulm.x, brm.x);
1193 mdi->y0 = MIN(ulm.y, brm.y);
1194 mdi->yf = MAX(ulm.y, brm.y);
1195
1196 mdi->mapstoget = 0;
1197
1198 if ( mdi->redownload ) {
1199 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
1200 } else {
1201 /* calculate how many we need */
1202 for ( a = mdi->x0; a <= mdi->xf; a++ )
1203 {
1204 for ( b = mdi->y0; b <= mdi->yf; b++ )
1205 {
1206 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 1207 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
50a14534 1208 ulm.z, a, b );
45acf79e 1209 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
50a14534
EB
1210 mdi->mapstoget++;
1211 }
1212 }
1213 }
1214
1215 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1216
1217 if ( mdi->mapstoget )
1218 {
97634600
GB
1219 const gchar *tmp_str;
1220 gchar *tmp;
50a14534 1221
97634600
GB
1222 if (redownload)
1223 {
1224 if (redownload == REDOWNLOAD_BAD)
1225 tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget);
1226 else
1227 tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget);
1228 }
1229 else
1230 {
1231 tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget);
1232 }
1233 tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype));
1234
7bb60307 1235 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
50a14534
EB
1236 /* launch the thread */
1237 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1238 tmp, /* description string */
1239 (vik_thr_func) map_download_thread, /* function to call within thread */
1240 mdi, /* pass along data */
1241 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1242 (vik_thr_free_func) mdi_cancel_cleanup,
1243 mdi->mapstoget );
1244 g_free ( tmp );
1245 }
1246 else
1247 mdi_free ( mdi );
1248 }
1249}
1250
3ac548fa 1251static void maps_layer_download_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom, gint download_method )
7114e879 1252{
7114e879 1253 MapCoord ulm, brm;
820c59f4 1254 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
7114e879 1255
2673b29d
RN
1256 // Don't ever attempt download on direct access
1257 if ( vik_map_source_is_direct_file_access ( map ) )
1258 return;
1259
820c59f4
GB
1260 if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm)
1261 || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) {
4258f4e2 1262 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
7114e879
QT
1263 return;
1264 }
1265
1266 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
1267 gint i, j;
1268
1269 mdi->vml = vml;
1270 mdi->vvp = vvp;
1271 mdi->map_layer_alive = TRUE;
1272 mdi->mutex = g_mutex_new();
903dc0b4 1273 mdi->refresh_display = TRUE;
7114e879
QT
1274
1275 mdi->cache_dir = g_strdup ( vml->cache_dir );
1276 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1277 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1278 mdi->maptype = vml->maptype;
1279
1280 mdi->mapcoord = ulm;
3ac548fa 1281 mdi->redownload = download_method;
7114e879
QT
1282
1283 mdi->x0 = MIN(ulm.x, brm.x);
1284 mdi->xf = MAX(ulm.x, brm.x);
1285 mdi->y0 = MIN(ulm.y, brm.y);
1286 mdi->yf = MAX(ulm.y, brm.y);
1287
1288 mdi->mapstoget = 0;
1289
1290 for (i = mdi->x0; i <= mdi->xf; i++) {
1291 for (j = mdi->y0; j <= mdi->yf; j++) {
1292 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 1293 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
7114e879 1294 ulm.z, i, j );
45acf79e 1295 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
7114e879
QT
1296 mdi->mapstoget++;
1297 }
1298 }
1299
1300 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1301
1302 if (mdi->mapstoget) {
4c77d5e0
GB
1303 gchar *tmp;
1304 const gchar *fmt;
eb6b0125
JJ
1305 fmt = ngettext("Downloading %d %s map...",
1306 "Downloading %d %s maps...",
1307 mdi->mapstoget);
4c77d5e0 1308 tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) );
7114e879
QT
1309
1310 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1311 /* launch the thread */
1312 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1313 tmp, /* description string */
1314 (vik_thr_func) map_download_thread, /* function to call within thread */
1315 mdi, /* pass along data */
1316 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1317 (vik_thr_free_func) mdi_cancel_cleanup,
1318 mdi->mapstoget );
1319 g_free ( tmp );
1320 }
1321 else
1322 mdi_free ( mdi );
1323}
1324
3ac548fa
RN
1325/**
1326 * vik_maps_layer_download_section:
1327 * @vml: The Map Layer
1328 * @vvp: The Viewport that the map is on
1329 * @ul: Upper left coordinate of the area to be downloaded
1330 * @br: Bottom right coordinate of the area to be downloaded
1331 * @zoom: The zoom level at which the maps are to be download
1332 *
1333 * Download a specified map area at a certain zoom level
1334 */
1335void vik_maps_layer_download_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom )
1336{
1337 maps_layer_download_section (vml, vvp, ul, br, zoom, REDOWNLOAD_NONE);
1338}
1339
50a14534
EB
1340static void maps_layer_redownload_bad ( VikMapsLayer *vml )
1341{
1342 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
1343}
a7c1acf1 1344
50a14534
EB
1345static void maps_layer_redownload_all ( VikMapsLayer *vml )
1346{
1347 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
1348}
1349
a7c1acf1
GB
1350static void maps_layer_redownload_new ( VikMapsLayer *vml )
1351{
1352 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
1353}
1354
450d8665
RN
1355/**
1356 * Display a simple dialog with information about this particular map tile
1357 */
1358static void maps_layer_tile_info ( VikMapsLayer *vml )
1359{
1360 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1361
1362 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vml->redownload_vvp );
1363 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vml->redownload_vvp );
1364 MapCoord ulm;
1365
1366 if ( !vik_map_source_coord_to_mapcoord ( map, &(vml->redownload_ul), xzoom, yzoom, &ulm ) )
1367 return;
1368
1369 gchar *filename = NULL;
1370 gchar *message = NULL;
1371 gchar *source = NULL;
1372
1373 if ( vik_map_source_is_direct_file_access ( map ) ) {
1374 filename = g_strdup_printf ( DIRECTDIRACCESS, vml->cache_dir, ulm.scale, ulm.x, ulm.y, ".png" );
1375 source = g_strconcat ( "file://", filename, NULL );
1376 }
1377 else {
1378 filename = g_strdup_printf ( DIRSTRUCTURE, vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale, ulm.z, ulm.x, ulm.y );
1379 source = g_strdup_printf ( "http://%s%s",
1380 vik_map_source_default_get_hostname ( VIK_MAP_SOURCE_DEFAULT(map) ),
1381 vik_map_source_default_get_uri ( VIK_MAP_SOURCE_DEFAULT(map), &ulm ) );
1382 }
1383
1384 if ( g_file_test ( filename, G_FILE_TEST_EXISTS ) ) {
1385
1386 // Get some timestamp information of the tile
1387 struct stat stat_buf;
1388 if ( g_stat ( filename, &stat_buf ) == 0 ) {
6be843d5
RN
1389 gchar time_buf[64];
1390 strftime ( time_buf, sizeof(time_buf), "%c", gmtime((const time_t *)&stat_buf.st_mtime) );
1391 message = g_strdup_printf ( _("\nSource: %s\n\nTile File: %s\nTile File Timestamp: %s"), source, filename, time_buf );
450d8665
RN
1392 }
1393 }
1394 else
1395 message = g_strdup_printf ( _("Source: %s\n\nNo Tile File!"), source );
1396
1397 // Show the info
1398 a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), message );
1399
1400 g_free ( message );
1401 g_free ( source );
1402 g_free ( filename );
1403}
1404
50a14534
EB
1405static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1406{
941aa6e9
AF
1407 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1408 return FALSE;
50a14534
EB
1409 if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 )
1410 {
1411 if ( event->button == 1 )
1412 {
1413 VikCoord ul, br;
1414 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 );
1415 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 1416 start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
50a14534
EB
1417 vml->dl_tool_x = vml->dl_tool_y = -1;
1418 return TRUE;
1419 }
1420 else
1421 {
1422 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) );
1423 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) );
1424
1425 vml->redownload_vvp = vvp;
1426
1427 vml->dl_tool_x = vml->dl_tool_y = -1;
1428
1429 if ( ! vml->dl_right_click_menu ) {
1430 GtkWidget *item;
1431 vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () );
1432
94ee2264 1433 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _Bad Map(s)") );
50a14534
EB
1434 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
1435 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1436
94ee2264 1437 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _New Map(s)") );
a7c1acf1
GB
1438 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
1439 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1440
94ee2264 1441 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _All Map(s)") );
50a14534
EB
1442 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
1443 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
450d8665
RN
1444
1445 item = gtk_image_menu_item_new_with_mnemonic ( _("_Show Tile Information") );
1446 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_MENU) );
1447 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_tile_info), vml );
1448 gtk_menu_shell_append (GTK_MENU_SHELL(vml->dl_right_click_menu), item);
50a14534
EB
1449 }
1450
1451 gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
1452 gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) );
1453 }
1454 }
1455 return FALSE;
1456}
1457
941aa6e9
AF
1458static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1459{
1460 return vvp;
1461}
1462
50a14534
EB
1463static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1464{
1465 MapCoord tmp;
941aa6e9
AF
1466 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1467 return FALSE;
820c59f4
GB
1468 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1469 if ( vik_map_source_get_drawmode(map) == vik_viewport_get_drawmode ( vvp ) &&
1470 vik_map_source_coord_to_mapcoord ( map, vik_viewport_get_center ( vvp ),
50a14534
EB
1471 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1472 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1473 &tmp ) ) {
1474 vml->dl_tool_x = event->x, vml->dl_tool_y = event->y;
1475 return TRUE;
1476 }
1477 return FALSE;
1478
1479
1480#if 0
1481 if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) )
1482 {
1483 VikCoord coord;
1484 MapCoord mapcoord;
1485 vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
1486 if ( __map_types[vml->maptype].coord_to_mapcoord ( &coord,
1487 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1488 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1489 &mapcoord ) ) {
1490 gchar *filename_buf = g_strdup_printf ( DIRSTRUCTURE,
1491 vml->cache_dir, __map_types[vml->maptype].uniq_id,
1492 mapcoord.scale, mapcoord.z, mapcoord.x, mapcoord.y );
1493
1494 __map_types[vml->maptype].download ( &mapcoord, filename_buf );
1495 g_free ( filename_buf );
1496 vik_layer_emit_update ( VIK_LAYER(vml) );
1497 return TRUE;
1498 }
1499 }
1500 return FALSE;
1501#endif
1502}
1503
50817314 1504static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload )
50a14534
EB
1505{
1506 VikMapsLayer *vml = vml_vvp[0];
1507 VikViewport *vvp = vml_vvp[1];
314c1ccc 1508 VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
50a14534
EB
1509
1510 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1511 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1512
1513 VikCoord ul, br;
1514 MapCoord ulm, brm;
1515
1516 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1517 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1518
820c59f4
GB
1519 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1520 if ( vik_map_source_get_drawmode(map) == vp_drawmode &&
1521 vik_map_source_coord_to_mapcoord ( map, &ul, xzoom, yzoom, &ulm ) &&
1522 vik_map_source_coord_to_mapcoord ( map, &br, xzoom, yzoom, &brm ) )
50817314 1523 start_download_thread ( vml, vvp, &ul, &br, redownload );
820c59f4
GB
1524 else if (vik_map_source_get_drawmode(map) != vp_drawmode) {
1525 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, vik_map_source_get_drawmode(map));
4c77d5e0 1526 gchar *err = g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name));
314c1ccc
QT
1527 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1528 g_free(err);
1529 }
50a14534 1530 else
4c77d5e0 1531 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Wrong zoom level for this map.") );
50a14534
EB
1532
1533}
1534
6a4a29aa 1535static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] )
50817314
GB
1536{
1537 download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
1538}
1539
6a4a29aa
JJ
1540static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] )
1541{
1542 download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW);
1543}
1544
50817314
GB
1545static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
1546{
1547 download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
1548}
1549
b03ae39b
RN
1550static void maps_layers_about ( gpointer vml_vvp[2] )
1551{
1552 VikMapsLayer *vml = vml_vvp[0];
1553 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1554
1555 if ( vik_map_source_get_license (map) )
1556 maps_show_license ( VIK_GTK_WINDOW_FROM_LAYER(vml), map );
1557 else
1558 a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml),
1559 vik_map_source_get_label (map) );
1560}
1561
3ac548fa
RN
1562/**
1563 * maps_layer_how_many_maps:
1564 * Copied from maps_layer_download_section but without the actual download and this returns a value
1565 */
1566static gint maps_layer_how_many_maps ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom, gint redownload )
1567{
1568 MapCoord ulm, brm;
1569 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1570
1571 if ( vik_map_source_is_direct_file_access ( map ) )
1572 return 0;
1573
1574 if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm)
1575 || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) {
1576 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
1577 return 0;
1578 }
1579
1580 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
1581 gint i, j;
1582
1583 mdi->vml = vml;
1584 mdi->vvp = vvp;
1585 mdi->map_layer_alive = TRUE;
1586 mdi->mutex = g_mutex_new();
1587 mdi->refresh_display = FALSE;
1588
1589 mdi->cache_dir = g_strdup ( vml->cache_dir );
1590 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1591 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1592 mdi->maptype = vml->maptype;
1593
1594 mdi->mapcoord = ulm;
1595 mdi->redownload = redownload;
1596
1597 mdi->x0 = MIN(ulm.x, brm.x);
1598 mdi->xf = MAX(ulm.x, brm.x);
1599 mdi->y0 = MIN(ulm.y, brm.y);
1600 mdi->yf = MAX(ulm.y, brm.y);
1601
1602 mdi->mapstoget = 0;
1603
1604 if ( mdi->redownload == REDOWNLOAD_ALL ) {
1605 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
1606 }
1607 else {
1608 /* calculate how many we need */
1609 for (i = mdi->x0; i <= mdi->xf; i++) {
1610 for (j = mdi->y0; j <= mdi->yf; j++) {
1611 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
1612 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
1613 ulm.z, i, j );
1614 if ( mdi->redownload == REDOWNLOAD_NEW ) {
1615 // Assume the worst - always a new file
1616 // Absolute value would requires server lookup - but that is too slow
1617 mdi->mapstoget++;
1618 }
1619 else {
1620 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
1621 // Missing
1622 mdi->mapstoget++;
1623 }
1624 else {
1625 if ( mdi->redownload == REDOWNLOAD_BAD ) {
1626 /* see if this one is bad or what */
1627 GError *gx = NULL;
1628 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
1629 if (gx || (!pixbuf)) {
1630 mdi->mapstoget++;
1631 }
1632 break;
1633 // Other download cases already considered or just ignored
1634 }
1635 }
1636 }
1637 }
1638 }
1639 }
1640
1641 gint rv = mdi->mapstoget;
1642
1643 mdi_free ( mdi );
1644
1645 return rv;
1646}
1647
1648/**
1649 * maps_dialog_zoom_between:
1650 * This dialog is specific to the map layer, so it's here rather than in dialog.c
1651 */
1652gboolean maps_dialog_zoom_between ( GtkWindow *parent,
1653 gchar *title,
1654 gchar *zoom_list[],
1655 gint default_zoom1,
1656 gint default_zoom2,
1657 gint *selected_zoom1,
1658 gint *selected_zoom2,
1659 gchar *download_list[],
1660 gint default_download,
1661 gint *selected_download )
1662{
1663 GtkWidget *dialog = gtk_dialog_new_with_buttons ( title,
1664 parent,
1665 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1666 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1667 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1668 NULL );
1669 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
1670 GtkWidget *response_w = NULL;
1671#if GTK_CHECK_VERSION (2, 20, 0)
1672 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
1673#endif
1674 GtkWidget *zoom_label1 = gtk_label_new ( _("Zoom Start:") );
1675 GtkWidget *zoom_combo1 = vik_combo_box_text_new();
1676 gchar **s;
1677 for (s = zoom_list; *s; s++)
1678 vik_combo_box_text_append ( zoom_combo1, *s );
1679 gtk_combo_box_set_active ( GTK_COMBO_BOX(zoom_combo1), default_zoom1 );
1680
1681 GtkWidget *zoom_label2 = gtk_label_new ( _("Zoom End:") );
1682 GtkWidget *zoom_combo2 = vik_combo_box_text_new();
1683 for (s = zoom_list; *s; s++)
1684 vik_combo_box_text_append ( zoom_combo2, *s );
1685 gtk_combo_box_set_active ( GTK_COMBO_BOX(zoom_combo2), default_zoom2 );
1686
1687 GtkWidget *download_label = gtk_label_new(_("Download Maps Method:"));
1688 GtkWidget *download_combo = vik_combo_box_text_new();
1689 for (s = download_list; *s; s++)
1690 vik_combo_box_text_append ( download_combo, *s );
1691 gtk_combo_box_set_active ( GTK_COMBO_BOX(download_combo), default_download );
1692
1693 GtkTable *box = GTK_TABLE(gtk_table_new(3, 2, FALSE));
1694 gtk_table_attach_defaults (box, GTK_WIDGET(zoom_label1), 0, 1, 0, 1);
1695 gtk_table_attach_defaults (box, GTK_WIDGET(zoom_combo1), 1, 2, 0, 1);
1696 gtk_table_attach_defaults (box, GTK_WIDGET(zoom_label2), 0, 1, 1, 2);
1697 gtk_table_attach_defaults (box, GTK_WIDGET(zoom_combo2), 1, 2, 1, 2);
1698 gtk_table_attach_defaults (box, GTK_WIDGET(download_label), 0, 1, 2, 3);
1699 gtk_table_attach_defaults (box, GTK_WIDGET(download_combo), 1, 2, 2, 3);
1700
1701 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), GTK_WIDGET(box), FALSE, FALSE, 5 );
1702
1703 if ( response_w )
1704 gtk_widget_grab_focus ( response_w );
1705
1706 gtk_widget_show_all ( dialog );
1707 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) != GTK_RESPONSE_ACCEPT ) {
1708 gtk_widget_destroy(dialog);
1709 return FALSE;
1710 }
1711
1712 // Return selected options
1713 *selected_zoom1 = gtk_combo_box_get_active ( GTK_COMBO_BOX(zoom_combo1) );
1714 *selected_zoom2 = gtk_combo_box_get_active ( GTK_COMBO_BOX(zoom_combo2) );
1715 *selected_download = gtk_combo_box_get_active ( GTK_COMBO_BOX(download_combo) );
1716
1717 gtk_widget_destroy(dialog);
1718 return TRUE;
1719}
1720
1721// My best guess of sensible limits
1722#define REALLY_LARGE_AMOUNT_OF_TILES 5000
1723#define CONFIRM_LARGE_AMOUNT_OF_TILES 500
1724
1725/**
1726 * Get all maps in the region for zoom levels specified by the user
1727 * Sort of similar to trw_layer_download_map_along_track_cb function
1728 */
1729static void maps_layer_download_all ( gpointer vml_vvp[2] )
1730{
1731 VikMapsLayer *vml = vml_vvp[0];
1732 VikViewport *vvp = vml_vvp[1];
1733
1734 // I don't think we should allow users to hammer the servers too much...
1735 // Delibrately not allowing lowest zoom levels
1736 // Still can give massive numbers to download
1737 // A screen size of 1600x1200 gives around 300,000 tiles between 1..128 when none exist before !!
1738 gchar *zoom_list[] = {"1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", NULL };
1739 gdouble zoom_vals[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
1740
1741 gint selected_zoom1, selected_zoom2, default_zoom, lower_zoom;
1742 gint selected_download_method;
1743
1744 gdouble cur_zoom = vik_viewport_get_zoom(vvp);
1745
1746 for (default_zoom = 0; default_zoom < sizeof(zoom_vals)/sizeof(gdouble); default_zoom++) {
1747 if (cur_zoom == zoom_vals[default_zoom])
1748 break;
1749 }
1750 default_zoom = (default_zoom == sizeof(zoom_vals)/sizeof(gdouble)) ? sizeof(zoom_vals)/sizeof(gdouble) - 1 : default_zoom;
1751
1752 // Default to only 2 zoom levels below the current one
1753 if (default_zoom > 1 )
1754 lower_zoom = default_zoom - 2;
1755 else
1756 lower_zoom = default_zoom;
1757
1758 // redownload method - needs to align with REDOWNLOAD* macro values
1759 gchar *download_list[] = { _("Missing"), _("Bad"), _("New"), _("Reload All"), NULL };
1760
1761 gchar *title = g_strdup_printf ( ("%s: %s"), vik_maps_layer_get_map_label (vml), _("Download for Zoom Levels") );
1762
1763 if ( ! maps_dialog_zoom_between ( VIK_GTK_WINDOW_FROM_LAYER(vml),
1764 title,
1765 zoom_list,
1766 lower_zoom,
1767 default_zoom,
1768 &selected_zoom1,
1769 &selected_zoom2,
1770 download_list,
1771 REDOWNLOAD_NONE, // AKA Missing
1772 &selected_download_method ) ) {
1773 // Cancelled
1774 g_free ( title );
1775 return;
1776 }
1777 g_free ( title );
1778
1779 // Find out new current positions
1780 gdouble min_lat, max_lat, min_lon, max_lon;
1781 VikCoord vc_ul, vc_br;
1782 vik_viewport_get_min_max_lat_lon ( vvp, &min_lat, &max_lat, &min_lon, &max_lon );
1783 struct LatLon ll_ul = { max_lat, min_lon };
1784 struct LatLon ll_br = { min_lat, max_lon };
1785 vik_coord_load_from_latlon ( &vc_ul, vik_viewport_get_coord_mode (vvp), &ll_ul );
1786 vik_coord_load_from_latlon ( &vc_br, vik_viewport_get_coord_mode (vvp), &ll_br );
1787
1788 // Get Maps Count - call for each zoom level (in reverse)
1789 // With REDOWNLOAD_NEW this is a possible maximum
1790 // With REDOWNLOAD_NONE this only missing ones - however still has a server lookup per tile
1791 gint map_count = 0;
1792 gint zz;
1793 for ( zz = selected_zoom2; zz >= selected_zoom1; zz-- ) {
1794 map_count = map_count + maps_layer_how_many_maps ( vml, vvp, &vc_ul, &vc_br, zoom_vals[zz], selected_download_method );
1795 }
1796
1797 g_debug ("vikmapslayer: download request map count %d for method %d", map_count, selected_download_method);
1798
1799 // Absolute protection of hammering a map server
1800 if ( map_count > REALLY_LARGE_AMOUNT_OF_TILES ) {
1801 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);
1802 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), str );
1803 g_free (str);
1804 return;
1805 }
1806
1807 // Confirm really want to do this
1808 if ( map_count > CONFIRM_LARGE_AMOUNT_OF_TILES ) {
1809 gchar *str = g_strdup_printf (_("Do you really want to download %d tiles?"), map_count);
1810 gboolean ans = a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vml), str, NULL );
1811 g_free (str);
1812 if ( ! ans )
1813 return;
1814 }
1815
1816 // Get Maps - call for each zoom level (in reverse)
1817 for ( zz = selected_zoom2; zz >= selected_zoom1; zz-- ) {
1818 maps_layer_download_section ( vml, vvp, &vc_ul, &vc_br, zoom_vals[zz], selected_download_method );
1819 }
1820}
1821
50a14534
EB
1822static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp )
1823{
1824 static gpointer pass_along[2];
1825 GtkWidget *item;
1826 pass_along[0] = vml;
1827 pass_along[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) );
1828
1829 item = gtk_menu_item_new();
1830 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
1831 gtk_widget_show ( item );
1832
555ec6f6
RN
1833 /* Now with icons */
1834 item = gtk_image_menu_item_new_with_mnemonic ( _("Download _Missing Onscreen Maps") );
1835 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) );
6a4a29aa 1836 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along );
50a14534
EB
1837 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1838 gtk_widget_show ( item );
50817314 1839
c81ded98 1840 if ( vik_map_source_supports_download_only_new (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) {
555ec6f6
RN
1841 item = gtk_image_menu_item_new_with_mnemonic ( _("Download _New Onscreen Maps") );
1842 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REDO, GTK_ICON_SIZE_MENU) );
6a4a29aa
JJ
1843 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along );
1844 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1845 gtk_widget_show ( item );
1846 }
1847
555ec6f6
RN
1848 item = gtk_image_menu_item_new_with_mnemonic ( _("Reload _All Onscreen Maps") );
1849 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) );
50817314
GB
1850 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
1851 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1852 gtk_widget_show ( item );
3ac548fa
RN
1853
1854 item = gtk_image_menu_item_new_with_mnemonic ( _("Download Maps in _Zoom Levels...") );
1855 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_DND_MULTIPLE, GTK_ICON_SIZE_MENU) );
1856 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_all), pass_along );
1857 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1858 gtk_widget_show ( item );
b03ae39b
RN
1859
1860 item = gtk_image_menu_item_new_from_stock ( GTK_STOCK_ABOUT, NULL );
1861 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layers_about), pass_along );
1862 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1863 gtk_widget_show ( item );
50a14534 1864}
6b59f63d
RN
1865
1866/**
1867 * Enable downloading maps of the current screen area either 'new' or 'everything'
1868 */
1869void vik_maps_layer_download ( VikMapsLayer *vml, VikViewport *vvp, gboolean only_new )
1870{
1871 if ( !vml ) return;
1872 if ( !vvp ) return;
1873
1874 static gpointer pass_along[2];
1875 pass_along[0] = vml;
1876 pass_along[1] = vvp;
1877
1878 if ( only_new )
1879 // Get only new maps
1880 maps_layer_download_new_onscreen_maps ( pass_along );
1881 else
1882 // Redownload everything
1883 maps_layer_redownload_all_onscreen_maps ( pass_along );
1884}