]> git.street.me.uk Git - andy/viking.git/blame - src/vikmapslayer.c
SF#356778: Download Map Tiles using F5
[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#define MAX_SHRINKFACTOR 8.0000001 /* zoom 1 viewing 8-tiles */
30#define MIN_SHRINKFACTOR 0.0312499 /* zoom 32 viewing 1-tiles */
31
732d1e25
EB
32#define REAL_MIN_SHRINKFACTOR 0.0039062499 /* if shrinkfactor is between MAX and REAL_MAX, will only check for existence */
33
50a14534
EB
34#include <gtk/gtk.h>
35#include <gdk-pixbuf/gdk-pixdata.h>
45acf79e
MA
36#include <glib.h>
37#include <glib/gstdio.h>
4c77d5e0
GB
38#include <glib/gi18n.h>
39
8c00358d 40#ifdef HAVE_STRING_H
50a14534 41#include <string.h>
8c00358d
GB
42#endif
43#ifdef HAVE_MATH_H
50a14534 44#include <math.h>
8c00358d
GB
45#endif
46
50a14534 47#include "globals.h"
53ac8302 48#include "util.h"
50a14534
EB
49#include "coords.h"
50#include "vikcoord.h"
51#include "viktreeview.h"
52#include "vikviewport.h"
53#include "viklayer.h"
54#include "vikmapslayer.h"
50a14534 55
45acf79e 56#ifdef HAVE_UNISTD_H
50a14534 57#include <unistd.h>
45acf79e 58#endif
50a14534
EB
59
60#include "mapcache.h"
61/* only for dialog.h -- ugh */
62#include "vikwaypoint.h"
63#include "dialog.h"
55ddef4e 64#include "preferences.h"
50a14534
EB
65
66#include "vikstatus.h"
67#include "background.h"
68
69#include "vikaggregatelayer.h"
70#include "viklayerspanel.h"
71
72#include "mapcoord.h"
73#include "terraserver.h"
50a14534 74
bce3a7b0
EB
75#include "icons/icons.h"
76
50a14534
EB
77/****** MAP TYPES ******/
78
cdcaf41c
QT
79static GList *__map_types = NULL;
80
81#define NUM_MAP_TYPES g_list_length(__map_types)
50a14534 82
cdcaf41c 83/* List of label for each map type */
a8876892 84static gchar **params_maptypes = NULL;
cdcaf41c
QT
85
86/* Corresponding IDS. (Cf. field uniq_id in VikMapsLayer struct) */
a8876892 87static guint *params_maptypes_ids = NULL;
50a14534
EB
88
89/******** MAPZOOMS *********/
90
fcc2786b
SW
91static 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 };
92static 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 };
93static 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 94
d756fb5c 95#define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0]) - 1)
50a14534
EB
96
97/**************************/
98
99
07059501 100static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file);
7924723c 101static const gchar* maps_layer_tooltip ( VikMapsLayer *vml );
911400b5
AF
102static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len );
103static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
158b3642
RN
104static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation );
105static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation );
50a14534
EB
106static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp );
107static VikMapsLayer *maps_layer_new ( VikViewport *vvp );
108static void maps_layer_free ( VikMapsLayer *vml );
109static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
110static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
941aa6e9 111static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp );
50a14534
EB
112static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir );
113static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload );
114static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp );
e2cb421f 115static guint map_uniq_id_to_index ( guint uniq_id );
50a14534
EB
116
117
118static VikLayerParamScale params_scales[] = {
119 /* min, max, step, digits (decimal places) */
120 { 0, 255, 3, 0 }, /* alpha */
121};
122
123VikLayerParam maps_layer_params[] = {
a8876892 124 { "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Map Type:"), VIK_LAYER_WIDGET_COMBOBOX, NULL, NULL },
e6fd9b70 125 { "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Maps Directory:"), VIK_LAYER_WIDGET_FOLDERENTRY },
4c77d5e0
GB
126 { "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales },
127 { "autodownload", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload maps:"), VIK_LAYER_WIDGET_CHECKBUTTON },
a8876892 128 { "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms, NULL },
50a14534
EB
129};
130
131enum { PARAM_MAPTYPE=0, PARAM_CACHE_DIR, PARAM_ALPHA, PARAM_AUTODOWNLOAD, PARAM_MAPZOOM, NUM_PARAMS };
132
133static VikToolInterface maps_tools[] = {
79dce0cb 134 { { "MapsDownload", "vik-icon-Maps Download", N_("_Maps Download"), NULL, N_("Maps Download"), 0 },
6b59f63d
RN
135 (VikToolConstructorFunc) maps_layer_download_create,
136 NULL,
137 NULL,
138 NULL,
139 (VikToolMouseFunc) maps_layer_download_click,
140 NULL,
141 (VikToolMouseFunc) maps_layer_download_release,
142 NULL,
ef5e8132
RN
143 FALSE,
144 GDK_CURSOR_IS_PIXMAP, &cursor_mapdl_pixbuf },
50a14534
EB
145};
146
147VikLayerInterface vik_maps_layer_interface = {
4c77d5e0 148 N_("Map"),
75078768 149 "<control><shift>M",
5bfafde9 150 &vikmapslayer_pixbuf,
50a14534
EB
151
152 maps_tools,
153 sizeof(maps_tools) / sizeof(maps_tools[0]),
154
155 maps_layer_params,
156 NUM_PARAMS,
157 NULL,
158 0,
159
5a4a28bf
QT
160 VIK_MENU_ITEM_ALL,
161
50a14534
EB
162 (VikLayerFuncCreate) maps_layer_new,
163 (VikLayerFuncRealize) NULL,
b112cbf5 164 (VikLayerFuncPostRead) maps_layer_post_read,
50a14534
EB
165 (VikLayerFuncFree) maps_layer_free,
166
167 (VikLayerFuncProperties) NULL,
168 (VikLayerFuncDraw) maps_layer_draw,
169 (VikLayerFuncChangeCoordMode) NULL,
170
20c7a3a0
QT
171 (VikLayerFuncSetMenuItemsSelection) NULL,
172 (VikLayerFuncGetMenuItemsSelection) NULL,
173
50a14534
EB
174 (VikLayerFuncAddMenuItems) maps_layer_add_menu_items,
175 (VikLayerFuncSublayerAddMenuItems) NULL,
176
177 (VikLayerFuncSublayerRenameRequest) NULL,
178 (VikLayerFuncSublayerToggleVisible) NULL,
9da7faf2 179 (VikLayerFuncSublayerTooltip) NULL,
7924723c 180 (VikLayerFuncLayerTooltip) maps_layer_tooltip,
a5dcfdb7 181 (VikLayerFuncLayerSelected) NULL,
50a14534 182
911400b5
AF
183 (VikLayerFuncMarshall) maps_layer_marshall,
184 (VikLayerFuncUnmarshall) maps_layer_unmarshall,
50a14534
EB
185
186 (VikLayerFuncSetParam) maps_layer_set_param,
187 (VikLayerFuncGetParam) maps_layer_get_param,
188
189 (VikLayerFuncReadFileData) NULL,
190 (VikLayerFuncWriteFileData) NULL,
191
33534cd8 192 (VikLayerFuncDeleteItem) NULL,
d5874ef9 193 (VikLayerFuncCutItem) NULL,
50a14534
EB
194 (VikLayerFuncCopyItem) NULL,
195 (VikLayerFuncPasteItem) NULL,
196 (VikLayerFuncFreeCopiedItem) NULL,
70a23263 197 (VikLayerFuncDragDropRequest) NULL,
77ad64fa
RN
198
199 (VikLayerFuncSelectClick) NULL,
08f14055
RN
200 (VikLayerFuncSelectMove) NULL,
201 (VikLayerFuncSelectRelease) NULL,
e46f259a 202 (VikLayerFuncSelectedViewportMenu) NULL,
50a14534
EB
203};
204
205struct _VikMapsLayer {
206 VikLayer vl;
207 guint maptype;
208 gchar *cache_dir;
209 guint8 alpha;
210 guint mapzoom_id;
211 gdouble xmapzoom, ymapzoom;
212
213 gboolean autodownload;
10ca2bfe
QT
214 VikCoord *last_center;
215 gdouble last_xmpp;
216 gdouble last_ympp;
50a14534
EB
217
218 gint dl_tool_x, dl_tool_y;
219
220 GtkMenu *dl_right_click_menu;
221 VikCoord redownload_ul, redownload_br; /* right click menu only */
222 VikViewport *redownload_vvp;
8e507445
RN
223
224 gboolean license_notice_shown; // FALSE for new maps only, otherwise
225 // TRUE for saved maps & other layer changes as we don't need to show it again
50a14534
EB
226};
227
6a4a29aa
JJ
228enum { REDOWNLOAD_NONE = 0, /* download only missing maps */
229 REDOWNLOAD_BAD, /* download missing and bad maps */
230 REDOWNLOAD_NEW, /* download missing maps that are newer on server only */
231 REDOWNLOAD_ALL, /* download all maps */
232 DOWNLOAD_OR_REFRESH }; /* download missing maps and refresh cache */
50a14534 233
55ddef4e
JJ
234static VikLayerParam prefs[] = {
235 { VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Default maplayer directory:"), VIK_LAYER_WIDGET_FOLDERENTRY, NULL, NULL },
236};
237
238void maps_layer_init ()
239{
240 VikLayerParamData tmp;
241 tmp.s = maps_layer_default_dir();
242 a_preferences_register(prefs, tmp, VIKING_PREFERENCES_GROUP_KEY);
243}
50a14534 244
cdcaf41c
QT
245/****************************************/
246/******** MAPS LAYER TYPES **************/
247/****************************************/
248
e2cb421f 249int _get_index_for_id ( guint id )
cdcaf41c 250{
e2cb421f
GB
251 int index = 0 ;
252 while (params_maptypes_ids[index] != 0)
253 {
254 if (params_maptypes_ids[index] == id)
255 return index;
256 index++;
257 }
258 return -1;
259}
cdcaf41c 260
e2cb421f
GB
261void _add_map_source ( guint id, const char *label, VikMapSource *map )
262{
a8876892
GB
263 gsize len = 0;
264 if (params_maptypes)
265 len = g_strv_length (params_maptypes);
cdcaf41c 266 /* Add the label */
a8876892
GB
267 params_maptypes = g_realloc (params_maptypes, (len+2)*sizeof(gchar*));
268 params_maptypes[len] = g_strdup (label);
269 params_maptypes[len+1] = NULL;
cdcaf41c
QT
270
271 /* Add the id */
a8876892
GB
272 params_maptypes_ids = g_realloc (params_maptypes_ids, (len+2)*sizeof(guint));
273 params_maptypes_ids[len] = id;
274 params_maptypes_ids[len+1] = 0;
cdcaf41c
QT
275
276 /* We have to clone */
820c59f4 277 VikMapSource *clone = VIK_MAP_SOURCE(g_object_ref(map));
cdcaf41c
QT
278 /* Register the clone in the list */
279 __map_types = g_list_append(__map_types, clone);
280
281 /* Hack
e2cb421f 282 We have to ensure the mode LayerParam references the up-to-date
cdcaf41c
QT
283 GLists.
284 */
285 /*
286 memcpy(&maps_layer_params[0].widget_data, &params_maptypes, sizeof(gpointer));
287 memcpy(&maps_layer_params[0].extra_widget_data, &params_maptypes_ids, sizeof(gpointer));
288 */
289 maps_layer_params[0].widget_data = params_maptypes;
290 maps_layer_params[0].extra_widget_data = params_maptypes_ids;
291}
292
e2cb421f
GB
293void _update_map_source ( const char *label, VikMapSource *map, int index )
294{
295 GList *item = g_list_nth (__map_types, index);
296 g_object_unref (item->data);
297 item->data = g_object_ref (map);
298 /* Change previous data */
299 g_free (params_maptypes[index]);
300 params_maptypes[index] = g_strdup (label);
301}
302
17281ebd
GB
303/**
304 * maps_layer_register_map_source:
305 * @map: the new VikMapSource
306 *
307 * Register a new VikMapSource.
308 * Override existing one (equality of id).
309 */
e2cb421f
GB
310void maps_layer_register_map_source ( VikMapSource *map )
311{
312 g_assert(map != NULL);
313
314 guint id = vik_map_source_get_uniq_id(map);
315 const char *label = vik_map_source_get_label(map);
316 g_assert(label != NULL);
317
318 int previous = map_uniq_id_to_index (id);
319 if (previous != NUM_MAP_TYPES)
320 {
321 _update_map_source (label, map, previous);
322 }
323 else
324 {
325 _add_map_source (id, label, map);
326 }
327}
328
a8876892
GB
329#define MAPS_LAYER_NTH_LABEL(n) (params_maptypes[n])
330#define MAPS_LAYER_NTH_ID(n) (params_maptypes_ids[n])
820c59f4 331#define MAPS_LAYER_NTH_TYPE(n) (VIK_MAP_SOURCE(g_list_nth_data(__map_types, (n))))
cdcaf41c 332
7114e879
QT
333gint vik_maps_layer_get_map_type(VikMapsLayer *vml)
334{
335 return(vml->maptype);
336}
337
338gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml)
339{
340 return(g_strdup(MAPS_LAYER_NTH_LABEL(vml->maptype)));
341}
342
50a14534
EB
343/****************************************/
344/******** CACHE DIR STUFF ***************/
345/****************************************/
346
2673b29d 347#define DIRECTDIRACCESS "%s%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d%s"
3d9454e6 348#define DIRSTRUCTURE "%st%ds%dz%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d"
6a27c1bc
MA
349#define MAPS_CACHE_DIR maps_layer_default_dir()
350
50a14534 351#ifdef WINDOWS
6a27c1bc
MA
352#include <io.h>
353#define GLOBAL_MAPS_DIR "C:\\VIKING-MAPS\\"
354#define LOCAL_MAPS_DIR "VIKING-MAPS"
42293fc2
RN
355#elif defined __APPLE__
356#include <stdlib.h>
357#define GLOBAL_MAPS_DIR "/Library/cache/Viking/maps/"
358#define LOCAL_MAPS_DIR "/Library/Application Support/Viking/viking-maps"
50a14534 359#else /* POSIX */
50a14534 360#include <stdlib.h>
50a14534 361#define GLOBAL_MAPS_DIR "/var/cache/maps/"
6a27c1bc
MA
362#define LOCAL_MAPS_DIR ".viking-maps"
363#endif
50a14534 364
0c1044e9 365gchar *maps_layer_default_dir ()
50a14534 366{
3d9454e6
GB
367 static gchar *defaultdir = NULL;
368 if ( ! defaultdir )
50a14534
EB
369 {
370 /* Thanks to Mike Davison for the $VIKING_MAPS usage */
3d9454e6
GB
371 const gchar *mapdir = g_getenv("VIKING_MAPS");
372 if ( mapdir ) {
373 defaultdir = g_strdup ( mapdir );
45acf79e 374 } else if ( g_access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) {
3d9454e6 375 defaultdir = g_strdup ( GLOBAL_MAPS_DIR );
50a14534 376 } else {
6a27c1bc 377 const gchar *home = g_get_home_dir();
45acf79e 378 if (!home || g_access(home, W_OK))
3d9454e6
GB
379 home = g_get_home_dir ();
380 if ( home )
6a27c1bc 381 defaultdir = g_build_filename ( home, LOCAL_MAPS_DIR, NULL );
50a14534 382 else
6a27c1bc 383 defaultdir = g_strdup ( LOCAL_MAPS_DIR );
50a14534 384 }
3d9454e6
GB
385 if (defaultdir && (defaultdir[strlen(defaultdir)-1] != G_DIR_SEPARATOR))
386 {
387 /* Add the separator at the end */
388 gchar *tmp = defaultdir;
389 defaultdir = g_strconcat(tmp, G_DIR_SEPARATOR_S, NULL);
390 g_free(tmp);
391 }
392 g_debug("%s: defaultdir=%s", __FUNCTION__, defaultdir);
50a14534
EB
393 }
394 return defaultdir;
395}
396
50a14534
EB
397static void maps_layer_mkdir_if_default_dir ( VikMapsLayer *vml )
398{
45acf79e 399 if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && g_file_test ( vml->cache_dir, G_FILE_TEST_EXISTS ) == FALSE )
50a14534 400 {
f83131b9 401 g_mkdir ( vml->cache_dir, 0777 );
50a14534
EB
402 }
403}
404
405static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir )
406{
407 guint len;
408 g_assert ( vml != NULL);
e65028db
GB
409 g_free ( vml->cache_dir );
410 vml->cache_dir = NULL;
50a14534
EB
411
412 if ( dir == NULL || dir[0] == '\0' )
6926d79a
RN
413 {
414 if ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir") )
415 vml->cache_dir = g_strdup ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir")->s );
416 }
50a14534
EB
417 else
418 {
419 len = strlen(dir);
3d9454e6 420 if ( dir[len-1] != G_DIR_SEPARATOR )
50a14534
EB
421 {
422 vml->cache_dir = g_malloc ( len+2 );
423 strncpy ( vml->cache_dir, dir, len );
3d9454e6 424 vml->cache_dir[len] = G_DIR_SEPARATOR;
50a14534
EB
425 vml->cache_dir[len+1] = '\0';
426 }
427 else
428 vml->cache_dir = g_strdup ( dir );
429 }
430 maps_layer_mkdir_if_default_dir ( vml );
431}
432
433/****************************************/
434/******** GOBJECT STUFF *****************/
435/****************************************/
436
437GType vik_maps_layer_get_type ()
438{
439 static GType vml_type = 0;
440
441 if (!vml_type)
442 {
443 static const GTypeInfo vml_info =
444 {
445 sizeof (VikMapsLayerClass),
446 NULL, /* base_init */
447 NULL, /* base_finalize */
448 NULL, /* class init */
449 NULL, /* class_finalize */
450 NULL, /* class_data */
451 sizeof (VikMapsLayer),
452 0,
453 NULL /* instance init */
454 };
455 vml_type = g_type_register_static ( VIK_LAYER_TYPE, "VikMapsLayer", &vml_info, 0 );
456 }
457
458 return vml_type;
459}
460
461/****************************************/
462/************** PARAMETERS **************/
463/****************************************/
464
465static guint map_index_to_uniq_id (guint8 index)
466{
467 g_assert ( index < NUM_MAP_TYPES );
820c59f4 468 return vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(index));
50a14534
EB
469}
470
471static guint map_uniq_id_to_index ( guint uniq_id )
472{
473 gint i;
474 for ( i = 0; i < NUM_MAP_TYPES; i++ )
820c59f4 475 if ( vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(i)) == uniq_id )
50a14534
EB
476 return i;
477 return NUM_MAP_TYPES; /* no such thing */
478}
479
158b3642 480static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation )
50a14534 481{
8e507445
RN
482 // When loading from a file don't need the license reminder
483 if ( is_file_operation )
484 vml->license_notice_shown = TRUE;
485
50a14534
EB
486 switch ( id )
487 {
488 case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break;
489 case PARAM_MAPTYPE: {
490 gint maptype = map_uniq_id_to_index(data.u);
4c77d5e0 491 if ( maptype == NUM_MAP_TYPES ) g_warning(_("Unknown map type"));
50a14534
EB
492 else vml->maptype = maptype;
493 break;
494 }
495 case PARAM_ALPHA: if ( data.u <= 255 ) vml->alpha = data.u; break;
496 case PARAM_AUTODOWNLOAD: vml->autodownload = data.b; break;
497 case PARAM_MAPZOOM: if ( data.u < NUM_MAPZOOMS ) {
498 vml->mapzoom_id = data.u;
499 vml->xmapzoom = __mapzooms_x [data.u];
500 vml->ymapzoom = __mapzooms_y [data.u];
4c77d5e0 501 }else g_warning (_("Unknown Map Zoom")); break;
50a14534
EB
502 }
503 return TRUE;
504}
505
158b3642 506static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation )
50a14534
EB
507{
508 VikLayerParamData rv;
509 switch ( id )
510 {
b6865130 511 case PARAM_CACHE_DIR: rv.s = vml->cache_dir ? vml->cache_dir : ""; break;
50a14534
EB
512 case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break;
513 case PARAM_ALPHA: rv.u = vml->alpha; break;
514 case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break;
515 case PARAM_MAPZOOM: rv.u = vml->mapzoom_id; break;
516 }
517 return rv;
518}
519
520/****************************************/
521/****** CREATING, COPYING, FREEING ******/
522/****************************************/
523
524static VikMapsLayer *maps_layer_new ( VikViewport *vvp )
525{
36c78d6d 526 int idx;
50a14534
EB
527 VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) );
528 vik_layer_init ( VIK_LAYER(vml), VIK_LAYER_MAPS );
995e9aff 529 idx = map_uniq_id_to_index(19); /* 19 is id for OSM MapQuest maps */
36c78d6d 530 vml->maptype = (idx < NUM_MAP_TYPES) ? idx : 0;
2673b29d 531 vml->maptype = (idx < NUM_MAP_TYPES) ? idx : 0;
50a14534
EB
532 vml->alpha = 255;
533 vml->mapzoom_id = 0;
534 vml->dl_tool_x = vml->dl_tool_y = -1;
535 maps_layer_set_cache_dir ( vml, NULL );
536 vml->autodownload = FALSE;
10ca2bfe
QT
537 vml->last_center = NULL;
538 vml->last_xmpp = 0.0;
539 vml->last_ympp = 0.0;
50a14534
EB
540
541 vml->dl_right_click_menu = NULL;
8e507445 542 vml->license_notice_shown = FALSE;
50a14534
EB
543
544 return vml;
545}
546
547static void maps_layer_free ( VikMapsLayer *vml )
548{
e65028db
GB
549 g_free ( vml->cache_dir );
550 vml->cache_dir = NULL;
50a14534 551 if ( vml->dl_right_click_menu )
4f14a010 552 g_object_ref_sink ( G_OBJECT(vml->dl_right_click_menu) );
e65028db
GB
553 g_free(vml->last_center);
554 vml->last_center = NULL;
50a14534
EB
555}
556
07059501 557static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file)
dc5758d3 558{
07059501
GB
559 if (from_file != TRUE)
560 {
561 /* If this method is not called in file reading context
562 * it is called in GUI context.
563 * So, we can check if we have to inform the user about inconsistency */
564 VikViewportDrawMode vp_drawmode;
565 VikMapsLayer *vml = VIK_MAPS_LAYER(vl);
820c59f4 566 VikMapSource *map = NULL;
dc5758d3 567
405b74ed 568 vp_drawmode = vik_viewport_get_drawmode ( vp );
820c59f4
GB
569 map = MAPS_LAYER_NTH_TYPE(vml->maptype);
570 if (vik_map_source_get_drawmode(map) != vp_drawmode) {
405b74ed 571 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vp, vik_map_source_get_drawmode(map));
4c77d5e0 572 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 573 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp), msg );
07059501
GB
574 g_free(msg);
575 }
53ac8302
GB
576
577 if (vik_map_source_get_license (map) != NULL) {
8e507445
RN
578 if ( ! vml->license_notice_shown ) {
579 a_dialog_license (VIK_GTK_WINDOW_FROM_WIDGET(vp), vik_map_source_get_label (map),
580 vik_map_source_get_license (map), vik_map_source_get_license_url (map) );
581 vml->license_notice_shown = TRUE;
582 }
53ac8302 583 }
dc5758d3
GB
584 }
585}
586
7924723c
RN
587static const gchar* maps_layer_tooltip ( VikMapsLayer *vml )
588{
589 return vik_maps_layer_get_map_label ( vml );
590}
591
911400b5
AF
592static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len )
593{
594 vik_layer_marshall_params ( VIK_LAYER(vml), data, len );
595}
596
597static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
598{
599 VikMapsLayer *rv = maps_layer_new ( vvp );
600 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
601 return rv;
602}
603
50a14534
EB
604/*********************/
605/****** DRAWING ******/
606/*********************/
607
608static GdkPixbuf *pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha )
609{
610 guchar *pixels;
611 gint width, height, iii, jjj;
612
613 if ( ! gdk_pixbuf_get_has_alpha ( pixbuf ) )
614 {
615 GdkPixbuf *tmp = gdk_pixbuf_add_alpha(pixbuf,FALSE,0,0,0);
616 g_object_unref(G_OBJECT(pixbuf));
617 pixbuf = tmp;
618 }
619
620 pixels = gdk_pixbuf_get_pixels(pixbuf);
621 width = gdk_pixbuf_get_width(pixbuf);
622 height = gdk_pixbuf_get_height(pixbuf);
623
624 /* r,g,b,a,r,g,b,a.... */
625 for (iii = 0; iii < width; iii++) for (jjj = 0; jjj < height; jjj++)
626 {
627 pixels += 3;
628 *pixels++ = alpha;
629 }
630 return pixbuf;
631}
632
633static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdouble yshrinkfactor )
634{
635 GdkPixbuf *tmp;
636 guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf);
9fdb940f 637 tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_NEAREST);
50a14534
EB
638 g_object_unref ( G_OBJECT(pixbuf) );
639 return tmp;
640}
641
642static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, gchar *filename_buf, gint buf_len, gdouble xshrinkfactor, gdouble yshrinkfactor )
643{
644 GdkPixbuf *pixbuf;
645
646 /* get the thing */
647 pixbuf = a_mapcache_get ( mapcoord->x, mapcoord->y, mapcoord->z,
648 mode, mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
649
650 if ( ! pixbuf ) {
2673b29d
RN
651 if ( vik_map_source_is_direct_file_access (MAPS_LAYER_NTH_TYPE(vml->maptype)) )
652 g_snprintf ( filename_buf, buf_len, DIRECTDIRACCESS,
653 vml->cache_dir, (17 - mapcoord->scale), mapcoord->x, mapcoord->y, ".png" );
654 else
655 g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE,
656 vml->cache_dir, mode,
657 mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y );
658
01ecda7e 659 if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
50a14534
EB
660 {
661 GError *gx = NULL;
662 pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx );
663
01ecda7e 664 /* free the pixbuf on error */
50a14534
EB
665 if (gx)
666 {
667 if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE )
4c77d5e0 668 g_warning ( _("Couldn't open image file: %s"), gx->message );
50a14534 669
01ecda7e
MR
670 g_error_free ( gx );
671 if ( pixbuf )
672 g_object_unref ( G_OBJECT(pixbuf) );
673 pixbuf = NULL;
674 } else {
50a14534
EB
675 if ( vml->alpha < 255 )
676 pixbuf = pixbuf_set_alpha ( pixbuf, vml->alpha );
677 if ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 )
678 pixbuf = pixbuf_shrink ( pixbuf, xshrinkfactor, yshrinkfactor );
679
680 a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y,
820c59f4 681 mapcoord->z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(vml->maptype)),
50a14534 682 mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
50a14534
EB
683 }
684 }
685 }
686 return pixbuf;
687}
688
10ca2bfe
QT
689gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp)
690{
691 const VikCoord *center = vik_viewport_get_center ( vvp );
692
bbf2149b 693 if (vik_window_get_pan_move (VIK_WINDOW(VIK_GTK_WINDOW_FROM_WIDGET(GTK_WIDGET(vvp)))))
01da6b4d 694 /* D'n'D pan in action: do not download */
1c6a6010
GB
695 return FALSE;
696
10ca2bfe
QT
697 if (vml->last_center == NULL) {
698 VikCoord *new_center = g_malloc(sizeof(VikCoord));
699 *new_center = *center;
700 vml->last_center = new_center;
701 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
702 vml->last_ympp = vik_viewport_get_ympp(vvp);
703 return TRUE;
704 }
705
706 /* TODO: perhaps vik_coord_diff() */
707 if (vik_coord_equals(vml->last_center, center)
708 && (vml->last_xmpp == vik_viewport_get_xmpp(vvp))
709 && (vml->last_ympp == vik_viewport_get_ympp(vvp)))
710 return FALSE;
711
712 *(vml->last_center) = *center;
713 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
714 vml->last_ympp = vik_viewport_get_ympp(vvp);
715 return TRUE;
716}
717
50a14534
EB
718static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br )
719{
720 MapCoord ulm, brm;
721 gdouble xzoom = vik_viewport_get_xmpp ( vvp );
722 gdouble yzoom = vik_viewport_get_ympp ( vvp );
723 gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0;
2673b29d 724 gboolean existence_only = FALSE;
50a14534
EB
725
726 if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) {
727 xshrinkfactor = vml->xmapzoom / xzoom;
728 yshrinkfactor = vml->ymapzoom / yzoom;
732d1e25
EB
729 xzoom = vml->xmapzoom;
730 yzoom = vml->xmapzoom;
731 if ( ! (xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR &&
732 yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) ) {
733 if ( xshrinkfactor > REAL_MIN_SHRINKFACTOR && yshrinkfactor > REAL_MIN_SHRINKFACTOR )
734 existence_only = TRUE;
735 else {
4c77d5e0 736 g_warning ( _("Cowardly refusing to draw tiles or existence of tiles beyond %d zoom out factor"), (int)( 1.0/REAL_MIN_SHRINKFACTOR));
732d1e25
EB
737 return;
738 }
50a14534
EB
739 }
740 }
741
742 /* coord -> ID */
820c59f4
GB
743 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
744 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm ) &&
745 vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) ) {
50a14534
EB
746
747 /* loop & draw */
748 gint x, y;
749 gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x);
750 gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y);
820c59f4 751 gint mode = vik_map_source_get_uniq_id(map);
50a14534
EB
752
753 VikCoord coord;
754 gint xx, yy, width, height;
755 GdkPixbuf *pixbuf;
756
757 guint max_path_len = strlen(vml->cache_dir) + 40;
758 gchar *path_buf = g_malloc ( max_path_len * sizeof(char) );
759
732d1e25 760 if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) {
33be396e 761 g_debug("%s: Starting autodownload", __FUNCTION__);
c81ded98 762 if ( vik_map_source_supports_download_only_new (map) )
245f48f5
GB
763 // Try to download newer tiles
764 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
765 else
766 // Download only missing tiles
767 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
10ca2bfe 768 }
50a14534 769
820c59f4 770 if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) {
50a14534
EB
771 for ( x = xmin; x <= xmax; x++ ) {
772 for ( y = ymin; y <= ymax; y++ ) {
773 ulm.x = x;
774 ulm.y = y;
775 pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
776 if ( pixbuf ) {
777 width = gdk_pixbuf_get_width ( pixbuf );
778 height = gdk_pixbuf_get_height ( pixbuf );
779
820c59f4 780 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
50a14534
EB
781 vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy );
782 xx -= (width/2);
783 yy -= (height/2);
784
785 vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height );
786 }
787 }
788 }
789 } else { /* tilesize is known, don't have to keep converting coords */
820c59f4
GB
790 gdouble tilesize_x = vik_map_source_get_tilesize_x(map) * xshrinkfactor;
791 gdouble tilesize_y = vik_map_source_get_tilesize_y(map) * yshrinkfactor;
50a14534
EB
792 /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
793 gint tilesize_x_ceil = ceil ( tilesize_x );
794 gint tilesize_y_ceil = ceil ( tilesize_y );
795 gint8 xinc = (ulm.x == xmin) ? 1 : -1;
796 gint8 yinc = (ulm.y == ymin) ? 1 : -1;
797 gdouble xx, yy; gint xx_tmp, yy_tmp;
798 gint base_yy, xend, yend;
732d1e25 799
50a14534
EB
800 xend = (xinc == 1) ? (xmax+1) : (xmin-1);
801 yend = (yinc == 1) ? (ymax+1) : (ymin-1);
802
820c59f4 803 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
50a14534
EB
804 vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp );
805 xx = xx_tmp; yy = yy_tmp;
806 /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
807 * eg if tile size 128, shrinkfactor 0.333 */
808 xx -= (tilesize_x/2);
809 base_yy = yy - (tilesize_y/2);
810
811 for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) {
812 yy = base_yy;
813 for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) {
814 ulm.x = x;
815 ulm.y = y;
732d1e25
EB
816
817 if ( existence_only ) {
2673b29d
RN
818 if ( vik_map_source_is_direct_file_access (MAPS_LAYER_NTH_TYPE(vml->maptype)) )
819 g_snprintf ( path_buf, max_path_len, DIRECTDIRACCESS,
820 vml->cache_dir, (17 - ulm.scale), ulm.x, ulm.y, ".png" );
821 else
822 g_snprintf ( path_buf, max_path_len, DIRSTRUCTURE,
823 vml->cache_dir, mode,
824 ulm.scale, ulm.z, ulm.x, ulm.y );
45acf79e 825 if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) {
ba799357 826 GdkGC *black_gc = GTK_WIDGET(vvp)->style->black_gc;
732d1e25
EB
827 vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil );
828 }
829 } else {
6f0d1bea
JJ
830 int scale_inc;
831 for (scale_inc = 0; scale_inc < 4; scale_inc ++) {
832 /* try with correct then smaller zooms */
833 int scale_factor = 1 << scale_inc; /* 2^scale_inc */
834 MapCoord ulm2 = ulm;
835 ulm2.x = ulm.x / scale_factor;
836 ulm2.y = ulm.y / scale_factor;
837 ulm2.scale = ulm.scale + scale_inc;
838 pixbuf = get_pixbuf ( vml, mode, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor );
839 if ( pixbuf ) {
840 gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil;
841 gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil;
40cfc175
JJ
842#ifdef DEBUG
843 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);
844#endif
6f0d1bea
JJ
845 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
846 break;
847 }
848 }
849 if ( !pixbuf ) {
850 /* retry with bigger zooms */
851 int scale_dec;
852 for (scale_dec = 1; scale_dec < 2; scale_dec ++) {
853 int pict_x, pict_y;
854 int scale_factor = 1 << scale_dec; /* 2^scale_dec */
91dc4449 855 MapCoord ulm2 = ulm;
6f0d1bea
JJ
856 ulm2.x = ulm.x * scale_factor;
857 ulm2.y = ulm.y * scale_factor;
858 ulm2.scale = ulm.scale - scale_dec;
859 for (pict_x = 0; pict_x < scale_factor; pict_x ++) {
860 for (pict_y = 0; pict_y < scale_factor; pict_y ++) {
861 MapCoord ulm3 = ulm2;
862 ulm3.x += pict_x;
863 ulm3.y += pict_y;
864 pixbuf = get_pixbuf ( vml, mode, &ulm3, path_buf, max_path_len, xshrinkfactor / scale_factor, yshrinkfactor / scale_factor );
865 if ( pixbuf ) {
866 gint src_x = 0;
867 gint src_y = 0;
868 gint dest_x = xx + pict_x * (tilesize_x_ceil / scale_factor);
869 gint dest_y = yy + pict_y * (tilesize_y_ceil / scale_factor);
870 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, dest_x, dest_y, tilesize_x_ceil / scale_factor, tilesize_y_ceil / scale_factor );
871 }
872 }
91dc4449
JJ
873 }
874 }
875 }
732d1e25 876 }
50a14534
EB
877
878 yy += tilesize_y;
879 }
880 xx += tilesize_x;
881 }
882 }
883
884 g_free ( path_buf );
885 }
886}
887
888static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp )
889{
820c59f4 890 if ( vik_map_source_get_drawmode(MAPS_LAYER_NTH_TYPE(vml->maptype)) == vik_viewport_get_drawmode ( vvp ) )
50a14534
EB
891 {
892 VikCoord ul, br;
893
82aa018d 894 /* Copyright */
68b1d6c0
GB
895 gdouble level = vik_viewport_get_zoom ( vvp );
896 LatLonBBox bbox;
897 vik_viewport_get_min_max_lat_lon ( vvp, &bbox.south, &bbox.north, &bbox.west, &bbox.east );
898 vik_map_source_get_copyright ( MAPS_LAYER_NTH_TYPE(vml->maptype), bbox, level, vik_viewport_add_copyright, vvp );
82aa018d 899
26336cf0
GB
900 /* Logo */
901 const GdkPixbuf *logo = vik_map_source_get_logo ( MAPS_LAYER_NTH_TYPE(vml->maptype) );
902 vik_viewport_add_logo ( vvp, logo );
903
50a14534
EB
904 /* get corner coords */
905 if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) {
906 /* UTM multi-zone stuff by Kit Transue */
907 gchar leftmost_zone, rightmost_zone, i;
908 leftmost_zone = vik_viewport_leftmost_zone( vvp );
909 rightmost_zone = vik_viewport_rightmost_zone( vvp );
910 for ( i = leftmost_zone; i <= rightmost_zone; ++i ) {
911 vik_viewport_corners_for_zonen ( vvp, i, &ul, &br );
912 maps_layer_draw_section ( vml, vvp, &ul, &br );
913 }
914 }
915 else {
916 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
917 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
918
919 maps_layer_draw_section ( vml, vvp, &ul, &br );
920 }
921 }
922}
923
924/*************************/
925/****** DOWNLOADING ******/
926/*************************/
927
928/* pass along data to thread, exists even if layer is deleted. */
929typedef struct {
930 gchar *cache_dir;
931 gchar *filename_buf;
932 gint x0, y0, xf, yf;
933 MapCoord mapcoord;
934 gint maptype;
935 gint maxlen;
936 gint mapstoget;
937 gint redownload;
7114e879 938 gboolean refresh_display;
550fd035
QT
939 VikMapsLayer *vml;
940 VikViewport *vvp;
941 gboolean map_layer_alive;
942 GMutex *mutex;
50a14534
EB
943} MapDownloadInfo;
944
945static void mdi_free ( MapDownloadInfo *mdi )
946{
550fd035 947 g_mutex_free(mdi->mutex);
50a14534 948 g_free ( mdi->cache_dir );
e65028db 949 mdi->cache_dir = NULL;
50a14534 950 g_free ( mdi->filename_buf );
e65028db 951 mdi->filename_buf = NULL;
50a14534
EB
952 g_free ( mdi );
953}
954
7bb60307 955static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
550fd035 956{
7bb60307 957 MapDownloadInfo *mdi = ptr;
550fd035
QT
958 g_mutex_lock(mdi->mutex);
959 mdi->map_layer_alive = FALSE;
960 g_mutex_unlock(mdi->mutex);
961}
962
634eca0a 963static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
50a14534 964{
825413ba 965 void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype));
50a14534
EB
966 guint donemaps = 0;
967 gint x, y;
968 for ( x = mdi->x0; x <= mdi->xf; x++ )
969 {
970 for ( y = mdi->y0; y <= mdi->yf; y++ )
971 {
94493114 972 gboolean remove_mem_cache = FALSE;
84628352 973 gboolean need_download = FALSE;
50a14534 974 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 975 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
50a14534
EB
976 mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
977
84628352 978 donemaps++;
634eca0a 979 int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
825413ba
SW
980 if (res != 0) {
981 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
634eca0a 982 return -1;
825413ba 983 }
84628352 984
a0058e48 985 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
6a4a29aa
JJ
986 need_download = TRUE;
987 remove_mem_cache = TRUE;
a0058e48
JJ
988
989 } else { /* in case map file already exists */
990 switch (mdi->redownload) {
991 case REDOWNLOAD_NONE:
992 continue;
993
994 case REDOWNLOAD_BAD:
995 {
996 /* see if this one is bad or what */
997 GError *gx = NULL;
998 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
999 if (gx || (!pixbuf)) {
1000 g_remove ( mdi->filename_buf );
1001 need_download = TRUE;
1002 remove_mem_cache = TRUE;
1003 g_error_free ( gx );
1004
1005 } else {
1006 g_object_unref ( pixbuf );
1007 }
1008 break;
1009 }
1010
1011 case REDOWNLOAD_NEW:
1012 need_download = TRUE;
1013 remove_mem_cache = TRUE;
1014 break;
1015
1016 case REDOWNLOAD_ALL:
1017 /* FIXME: need a better way than to erase file in case of server/network problem */
1018 g_remove ( mdi->filename_buf );
1019 need_download = TRUE;
1020 remove_mem_cache = TRUE;
1021 break;
1022
1023 case DOWNLOAD_OR_REFRESH:
1024 remove_mem_cache = TRUE;
1025 break;
1026
1027 default:
1028 g_warning ( "redownload state %d unknown\n", mdi->redownload);
1029 }
1030 }
94493114 1031
94493114 1032 mdi->mapcoord.x = x; mdi->mapcoord.y = y;
84628352
QT
1033
1034 if (need_download) {
825413ba 1035 if ( vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle))
94493114 1036 continue;
84628352 1037 }
94493114 1038
94493114
QT
1039 g_mutex_lock(mdi->mutex);
1040 if (remove_mem_cache)
820c59f4 1041 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 1042 if (mdi->refresh_display && mdi->map_layer_alive) {
94493114 1043 /* TODO: check if it's on visible area */
f01eebd4 1044 vik_layer_emit_update ( VIK_LAYER(mdi->vml), TRUE ); // Yes update display from background
a0b59f2f 1045 }
94493114 1046 g_mutex_unlock(mdi->mutex);
94493114
QT
1047 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
1048
50a14534
EB
1049 }
1050 }
825413ba 1051 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
04e54492
QT
1052 g_mutex_lock(mdi->mutex);
1053 if (mdi->map_layer_alive)
7bb60307 1054 g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
04e54492 1055 g_mutex_unlock(mdi->mutex);
634eca0a 1056 return 0;
50a14534
EB
1057}
1058
1059static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
1060{
1061 if ( mdi->mapcoord.x || mdi->mapcoord.y )
1062 {
1063 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 1064 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
50a14534 1065 mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y );
45acf79e 1066 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
50a14534 1067 {
8c060406 1068 g_remove ( mdi->filename_buf );
50a14534
EB
1069 }
1070 }
1071}
1072
1073static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload )
1074{
1075 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1076 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1077 MapCoord ulm, brm;
820c59f4 1078 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
2673b29d
RN
1079
1080 // Don't ever attempt download on direct access
1081 if ( vik_map_source_is_direct_file_access ( map ) )
1082 return;
1083
820c59f4
GB
1084 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm )
1085 && vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) )
50a14534
EB
1086 {
1087 MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
1088 gint a, b;
1089
550fd035
QT
1090 mdi->vml = vml;
1091 mdi->vvp = vvp;
1092 mdi->map_layer_alive = TRUE;
1093 mdi->mutex = g_mutex_new();
7114e879 1094 mdi->refresh_display = TRUE;
550fd035 1095
50a14534
EB
1096 /* cache_dir and buffer for dest filename */
1097 mdi->cache_dir = g_strdup ( vml->cache_dir );
1098 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1099 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1100 mdi->maptype = vml->maptype;
1101
1102 mdi->mapcoord = ulm;
1103
1104 mdi->redownload = redownload;
1105
1106 mdi->x0 = MIN(ulm.x, brm.x);
1107 mdi->xf = MAX(ulm.x, brm.x);
1108 mdi->y0 = MIN(ulm.y, brm.y);
1109 mdi->yf = MAX(ulm.y, brm.y);
1110
1111 mdi->mapstoget = 0;
1112
1113 if ( mdi->redownload ) {
1114 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
1115 } else {
1116 /* calculate how many we need */
1117 for ( a = mdi->x0; a <= mdi->xf; a++ )
1118 {
1119 for ( b = mdi->y0; b <= mdi->yf; b++ )
1120 {
1121 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 1122 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
50a14534 1123 ulm.z, a, b );
45acf79e 1124 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
50a14534
EB
1125 mdi->mapstoget++;
1126 }
1127 }
1128 }
1129
1130 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1131
1132 if ( mdi->mapstoget )
1133 {
97634600
GB
1134 const gchar *tmp_str;
1135 gchar *tmp;
50a14534 1136
97634600
GB
1137 if (redownload)
1138 {
1139 if (redownload == REDOWNLOAD_BAD)
1140 tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget);
1141 else
1142 tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget);
1143 }
1144 else
1145 {
1146 tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget);
1147 }
1148 tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype));
1149
7bb60307 1150 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
50a14534
EB
1151 /* launch the thread */
1152 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1153 tmp, /* description string */
1154 (vik_thr_func) map_download_thread, /* function to call within thread */
1155 mdi, /* pass along data */
1156 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1157 (vik_thr_free_func) mdi_cancel_cleanup,
1158 mdi->mapstoget );
1159 g_free ( tmp );
1160 }
1161 else
1162 mdi_free ( mdi );
1163 }
1164}
1165
7114e879
QT
1166void maps_layer_download_section_without_redraw( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom)
1167{
7114e879 1168 MapCoord ulm, brm;
820c59f4 1169 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
7114e879 1170
2673b29d
RN
1171 // Don't ever attempt download on direct access
1172 if ( vik_map_source_is_direct_file_access ( map ) )
1173 return;
1174
820c59f4
GB
1175 if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm)
1176 || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) {
4258f4e2 1177 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
7114e879
QT
1178 return;
1179 }
1180
1181 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
1182 gint i, j;
1183
1184 mdi->vml = vml;
1185 mdi->vvp = vvp;
1186 mdi->map_layer_alive = TRUE;
1187 mdi->mutex = g_mutex_new();
1188 mdi->refresh_display = FALSE;
1189
1190 mdi->cache_dir = g_strdup ( vml->cache_dir );
1191 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1192 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1193 mdi->maptype = vml->maptype;
1194
1195 mdi->mapcoord = ulm;
1196
1197 mdi->redownload = REDOWNLOAD_NONE;
1198
1199 mdi->x0 = MIN(ulm.x, brm.x);
1200 mdi->xf = MAX(ulm.x, brm.x);
1201 mdi->y0 = MIN(ulm.y, brm.y);
1202 mdi->yf = MAX(ulm.y, brm.y);
1203
1204 mdi->mapstoget = 0;
1205
1206 for (i = mdi->x0; i <= mdi->xf; i++) {
1207 for (j = mdi->y0; j <= mdi->yf; j++) {
1208 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 1209 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
7114e879 1210 ulm.z, i, j );
45acf79e 1211 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
7114e879
QT
1212 mdi->mapstoget++;
1213 }
1214 }
1215
1216 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1217
1218 if (mdi->mapstoget) {
4c77d5e0
GB
1219 gchar *tmp;
1220 const gchar *fmt;
eb6b0125
JJ
1221 fmt = ngettext("Downloading %d %s map...",
1222 "Downloading %d %s maps...",
1223 mdi->mapstoget);
4c77d5e0 1224 tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) );
7114e879
QT
1225
1226 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1227 /* launch the thread */
1228 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1229 tmp, /* description string */
1230 (vik_thr_func) map_download_thread, /* function to call within thread */
1231 mdi, /* pass along data */
1232 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1233 (vik_thr_free_func) mdi_cancel_cleanup,
1234 mdi->mapstoget );
1235 g_free ( tmp );
1236 }
1237 else
1238 mdi_free ( mdi );
1239}
1240
50a14534
EB
1241static void maps_layer_redownload_bad ( VikMapsLayer *vml )
1242{
1243 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
1244}
a7c1acf1 1245
50a14534
EB
1246static void maps_layer_redownload_all ( VikMapsLayer *vml )
1247{
1248 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
1249}
1250
a7c1acf1
GB
1251static void maps_layer_redownload_new ( VikMapsLayer *vml )
1252{
1253 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
1254}
1255
50a14534
EB
1256static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1257{
941aa6e9
AF
1258 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1259 return FALSE;
50a14534
EB
1260 if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 )
1261 {
1262 if ( event->button == 1 )
1263 {
1264 VikCoord ul, br;
1265 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 );
1266 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 1267 start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
50a14534
EB
1268 vml->dl_tool_x = vml->dl_tool_y = -1;
1269 return TRUE;
1270 }
1271 else
1272 {
1273 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) );
1274 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) );
1275
1276 vml->redownload_vvp = vvp;
1277
1278 vml->dl_tool_x = vml->dl_tool_y = -1;
1279
1280 if ( ! vml->dl_right_click_menu ) {
1281 GtkWidget *item;
1282 vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () );
1283
94ee2264 1284 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _Bad Map(s)") );
50a14534
EB
1285 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
1286 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1287
94ee2264 1288 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _New Map(s)") );
a7c1acf1
GB
1289 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
1290 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1291
94ee2264 1292 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _All Map(s)") );
50a14534
EB
1293 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
1294 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1295 }
1296
1297 gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
1298 gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) );
1299 }
1300 }
1301 return FALSE;
1302}
1303
941aa6e9
AF
1304static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1305{
1306 return vvp;
1307}
1308
50a14534
EB
1309static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1310{
1311 MapCoord tmp;
941aa6e9
AF
1312 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1313 return FALSE;
820c59f4
GB
1314 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1315 if ( vik_map_source_get_drawmode(map) == vik_viewport_get_drawmode ( vvp ) &&
1316 vik_map_source_coord_to_mapcoord ( map, vik_viewport_get_center ( vvp ),
50a14534
EB
1317 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1318 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1319 &tmp ) ) {
1320 vml->dl_tool_x = event->x, vml->dl_tool_y = event->y;
1321 return TRUE;
1322 }
1323 return FALSE;
1324
1325
1326#if 0
1327 if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) )
1328 {
1329 VikCoord coord;
1330 MapCoord mapcoord;
1331 vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
1332 if ( __map_types[vml->maptype].coord_to_mapcoord ( &coord,
1333 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1334 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1335 &mapcoord ) ) {
1336 gchar *filename_buf = g_strdup_printf ( DIRSTRUCTURE,
1337 vml->cache_dir, __map_types[vml->maptype].uniq_id,
1338 mapcoord.scale, mapcoord.z, mapcoord.x, mapcoord.y );
1339
1340 __map_types[vml->maptype].download ( &mapcoord, filename_buf );
1341 g_free ( filename_buf );
1342 vik_layer_emit_update ( VIK_LAYER(vml) );
1343 return TRUE;
1344 }
1345 }
1346 return FALSE;
1347#endif
1348}
1349
50817314 1350static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload )
50a14534
EB
1351{
1352 VikMapsLayer *vml = vml_vvp[0];
1353 VikViewport *vvp = vml_vvp[1];
314c1ccc 1354 VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
50a14534
EB
1355
1356 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1357 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1358
1359 VikCoord ul, br;
1360 MapCoord ulm, brm;
1361
1362 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1363 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1364
820c59f4
GB
1365 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1366 if ( vik_map_source_get_drawmode(map) == vp_drawmode &&
1367 vik_map_source_coord_to_mapcoord ( map, &ul, xzoom, yzoom, &ulm ) &&
1368 vik_map_source_coord_to_mapcoord ( map, &br, xzoom, yzoom, &brm ) )
50817314 1369 start_download_thread ( vml, vvp, &ul, &br, redownload );
820c59f4
GB
1370 else if (vik_map_source_get_drawmode(map) != vp_drawmode) {
1371 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, vik_map_source_get_drawmode(map));
4c77d5e0 1372 gchar *err = g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name));
314c1ccc
QT
1373 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1374 g_free(err);
1375 }
50a14534 1376 else
4c77d5e0 1377 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Wrong zoom level for this map.") );
50a14534
EB
1378
1379}
1380
6a4a29aa 1381static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] )
50817314
GB
1382{
1383 download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
1384}
1385
6a4a29aa
JJ
1386static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] )
1387{
1388 download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW);
1389}
1390
50817314
GB
1391static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
1392{
1393 download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
1394}
1395
50a14534
EB
1396static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp )
1397{
1398 static gpointer pass_along[2];
1399 GtkWidget *item;
1400 pass_along[0] = vml;
1401 pass_along[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) );
1402
1403 item = gtk_menu_item_new();
1404 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
1405 gtk_widget_show ( item );
1406
555ec6f6
RN
1407 /* Now with icons */
1408 item = gtk_image_menu_item_new_with_mnemonic ( _("Download _Missing Onscreen Maps") );
1409 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) );
6a4a29aa 1410 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along );
50a14534
EB
1411 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1412 gtk_widget_show ( item );
50817314 1413
c81ded98 1414 if ( vik_map_source_supports_download_only_new (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) {
555ec6f6
RN
1415 item = gtk_image_menu_item_new_with_mnemonic ( _("Download _New Onscreen Maps") );
1416 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REDO, GTK_ICON_SIZE_MENU) );
6a4a29aa
JJ
1417 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along );
1418 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1419 gtk_widget_show ( item );
1420 }
1421
555ec6f6
RN
1422 item = gtk_image_menu_item_new_with_mnemonic ( _("Reload _All Onscreen Maps") );
1423 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) );
50817314
GB
1424 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
1425 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1426 gtk_widget_show ( item );
50a14534 1427}
6b59f63d
RN
1428
1429/**
1430 * Enable downloading maps of the current screen area either 'new' or 'everything'
1431 */
1432void vik_maps_layer_download ( VikMapsLayer *vml, VikViewport *vvp, gboolean only_new )
1433{
1434 if ( !vml ) return;
1435 if ( !vvp ) return;
1436
1437 static gpointer pass_along[2];
1438 pass_along[0] = vml;
1439 pass_along[1] = vvp;
1440
1441 if ( only_new )
1442 // Get only new maps
1443 maps_layer_download_new_onscreen_maps ( pass_along );
1444 else
1445 // Redownload everything
1446 maps_layer_redownload_all_onscreen_maps ( pass_along );
1447}