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