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