2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2005, Evan Battaglia <viking@greentorch.org>
5 * UTM multi-zone stuff by Kit Transue <notlostyet@didactek.com>
6 * Dynamic map type by Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #define MAX_SHRINKFACTOR 8.0000001 /* zoom 1 viewing 8-tiles */
29 #define MIN_SHRINKFACTOR 0.0312499 /* zoom 32 viewing 1-tiles */
31 #define REAL_MIN_SHRINKFACTOR 0.0039062499 /* if shrinkfactor is between MAX and REAL_MAX, will only check for existence */
34 #include <gdk-pixbuf/gdk-pixdata.h>
36 #include <glib/gstdio.h>
37 #include <glib/gi18n.h>
49 #include "viktreeview.h"
50 #include "vikviewport.h"
52 #include "vikmapslayer.h"
59 /* only for dialog.h -- ugh */
60 #include "vikwaypoint.h"
63 #include "vikstatus.h"
64 #include "background.h"
66 #include "vikaggregatelayer.h"
67 #include "viklayerspanel.h"
70 #include "terraserver.h"
72 #include "icons/icons.h"
74 /****** MAP TYPES ******/
76 static GList *__map_types = NULL;
78 #define NUM_MAP_TYPES g_list_length(__map_types)
80 /* List of label for each map type */
81 static GList *params_maptypes = NULL;
83 /* Corresponding IDS. (Cf. field uniq_id in VikMapsLayer struct) */
84 static GList *params_maptypes_ids = NULL;
86 /******** MAPZOOMS *********/
88 static gchar *params_mapzooms[] = { N_("Use Viking Zoom Level"), "0.25", "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 };
89 static gdouble __mapzooms_x[] = { 0.0, 0.25, 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 };
90 static gdouble __mapzooms_y[] = { 0.0, 0.25, 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 };
92 #define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0]) - 1)
94 /**************************/
97 static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file);
98 static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len );
99 static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
100 static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp );
101 static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id );
102 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp );
103 static VikMapsLayer *maps_layer_new ( VikViewport *vvp );
104 static void maps_layer_free ( VikMapsLayer *vml );
105 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
106 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
107 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp );
108 static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir );
109 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload );
110 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp );
113 static VikLayerParamScale params_scales[] = {
114 /* min, max, step, digits (decimal places) */
115 { 0, 255, 3, 0 }, /* alpha */
118 VikLayerParam maps_layer_params[] = {
119 { "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Map Type:"), VIK_LAYER_WIDGET_RADIOGROUP, NULL, NULL },
120 { "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Maps Directory:"), VIK_LAYER_WIDGET_FOLDERENTRY },
121 { "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales },
122 { "autodownload", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload maps:"), VIK_LAYER_WIDGET_CHECKBUTTON },
123 { "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms },
126 enum { PARAM_MAPTYPE=0, PARAM_CACHE_DIR, PARAM_ALPHA, PARAM_AUTODOWNLOAD, PARAM_MAPZOOM, NUM_PARAMS };
128 static VikToolInterface maps_tools[] = {
129 { N_("Maps Download"), (VikToolConstructorFunc) maps_layer_download_create, NULL, NULL, NULL,
130 (VikToolMouseFunc) maps_layer_download_click, NULL, (VikToolMouseFunc) maps_layer_download_release,
131 (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_mapdl_pixbuf },
134 VikLayerInterface vik_maps_layer_interface = {
136 &vikmapslayer_pixbuf,
139 sizeof(maps_tools) / sizeof(maps_tools[0]),
148 (VikLayerFuncCreate) maps_layer_new,
149 (VikLayerFuncRealize) NULL,
150 (VikLayerFuncPostRead) maps_layer_post_read,
151 (VikLayerFuncFree) maps_layer_free,
153 (VikLayerFuncProperties) NULL,
154 (VikLayerFuncDraw) maps_layer_draw,
155 (VikLayerFuncChangeCoordMode) NULL,
157 (VikLayerFuncSetMenuItemsSelection) NULL,
158 (VikLayerFuncGetMenuItemsSelection) NULL,
160 (VikLayerFuncAddMenuItems) maps_layer_add_menu_items,
161 (VikLayerFuncSublayerAddMenuItems) NULL,
163 (VikLayerFuncSublayerRenameRequest) NULL,
164 (VikLayerFuncSublayerToggleVisible) NULL,
166 (VikLayerFuncMarshall) maps_layer_marshall,
167 (VikLayerFuncUnmarshall) maps_layer_unmarshall,
169 (VikLayerFuncSetParam) maps_layer_set_param,
170 (VikLayerFuncGetParam) maps_layer_get_param,
172 (VikLayerFuncReadFileData) NULL,
173 (VikLayerFuncWriteFileData) NULL,
175 (VikLayerFuncDeleteItem) NULL,
176 (VikLayerFuncCopyItem) NULL,
177 (VikLayerFuncPasteItem) NULL,
178 (VikLayerFuncFreeCopiedItem) NULL,
179 (VikLayerFuncDragDropRequest) NULL,
182 struct _VikMapsLayer {
188 gdouble xmapzoom, ymapzoom;
190 gboolean autodownload;
191 VikCoord *last_center;
195 gint dl_tool_x, dl_tool_y;
197 GtkMenu *dl_right_click_menu;
198 VikCoord redownload_ul, redownload_br; /* right click menu only */
199 VikViewport *redownload_vvp;
202 enum { REDOWNLOAD_NONE = 0, /* download only missing maps */
203 REDOWNLOAD_BAD, /* download missing and bad maps */
204 REDOWNLOAD_NEW, /* download missing maps that are newer on server only */
205 REDOWNLOAD_ALL, /* download all maps */
206 DOWNLOAD_OR_REFRESH }; /* download missing maps and refresh cache */
209 /****************************************/
210 /******** MAPS LAYER TYPES **************/
211 /****************************************/
213 void maps_layer_register_type ( const char *label, guint id, VikMapsLayer_MapType *map_type )
215 g_assert(label != NULL);
216 g_assert(map_type != NULL);
217 g_assert(id == map_type->uniq_id);
220 params_maptypes = g_list_append(params_maptypes, g_strdup(label));
223 params_maptypes_ids = g_list_append(params_maptypes_ids, GUINT_TO_POINTER (id));
225 /* We have to clone */
226 VikMapsLayer_MapType *clone = g_memdup(map_type, sizeof(VikMapsLayer_MapType));
227 /* Register the clone in the list */
228 __map_types = g_list_append(__map_types, clone);
231 We have to ensure the mode LayerParam reference the up-to-date
235 memcpy(&maps_layer_params[0].widget_data, ¶ms_maptypes, sizeof(gpointer));
236 memcpy(&maps_layer_params[0].extra_widget_data, ¶ms_maptypes_ids, sizeof(gpointer));
238 maps_layer_params[0].widget_data = params_maptypes;
239 maps_layer_params[0].extra_widget_data = params_maptypes_ids;
242 #define MAPS_LAYER_NTH_LABEL(n) ((gchar*)g_list_nth_data(params_maptypes, (n)))
243 #define MAPS_LAYER_NTH_ID(n) ((guint)g_list_nth_data(params_maptypes_ids, (n)))
244 #define MAPS_LAYER_NTH_TYPE(n) ((VikMapsLayer_MapType*)g_list_nth_data(__map_types, (n)))
246 gint vik_maps_layer_get_map_type(VikMapsLayer *vml)
248 return(vml->maptype);
251 gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml)
253 return(g_strdup(MAPS_LAYER_NTH_LABEL(vml->maptype)));
256 /****************************************/
257 /******** CACHE DIR STUFF ***************/
258 /****************************************/
260 #define DIRSTRUCTURE "%st%ds%dz%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d"
261 #define MAPS_CACHE_DIR maps_layer_default_dir()
265 #define GLOBAL_MAPS_DIR "C:\\VIKING-MAPS\\"
266 #define LOCAL_MAPS_DIR "VIKING-MAPS"
269 #define GLOBAL_MAPS_DIR "/var/cache/maps/"
270 #define LOCAL_MAPS_DIR ".viking-maps"
273 gchar *maps_layer_default_dir ()
275 static gchar *defaultdir = NULL;
278 /* Thanks to Mike Davison for the $VIKING_MAPS usage */
279 const gchar *mapdir = g_getenv("VIKING_MAPS");
281 defaultdir = g_strdup ( mapdir );
282 } else if ( g_access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) {
283 defaultdir = g_strdup ( GLOBAL_MAPS_DIR );
285 const gchar *home = g_get_home_dir();
286 if (!home || g_access(home, W_OK))
287 home = g_get_home_dir ();
289 defaultdir = g_build_filename ( home, LOCAL_MAPS_DIR, NULL );
291 defaultdir = g_strdup ( LOCAL_MAPS_DIR );
293 if (defaultdir && (defaultdir[strlen(defaultdir)-1] != G_DIR_SEPARATOR))
295 /* Add the separator at the end */
296 gchar *tmp = defaultdir;
297 defaultdir = g_strconcat(tmp, G_DIR_SEPARATOR_S, NULL);
300 g_debug("%s: defaultdir=%s", __FUNCTION__, defaultdir);
305 static void maps_layer_mkdir_if_default_dir ( VikMapsLayer *vml )
307 if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && g_file_test ( vml->cache_dir, G_FILE_TEST_EXISTS ) == FALSE )
309 g_mkdir ( vml->cache_dir, 0777 );
313 static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir )
316 g_assert ( vml != NULL);
317 g_free ( vml->cache_dir );
318 vml->cache_dir = NULL;
320 if ( dir == NULL || dir[0] == '\0' )
321 vml->cache_dir = g_strdup ( MAPS_CACHE_DIR );
325 if ( dir[len-1] != G_DIR_SEPARATOR )
327 vml->cache_dir = g_malloc ( len+2 );
328 strncpy ( vml->cache_dir, dir, len );
329 vml->cache_dir[len] = G_DIR_SEPARATOR;
330 vml->cache_dir[len+1] = '\0';
333 vml->cache_dir = g_strdup ( dir );
335 maps_layer_mkdir_if_default_dir ( vml );
338 /****************************************/
339 /******** GOBJECT STUFF *****************/
340 /****************************************/
342 GType vik_maps_layer_get_type ()
344 static GType vml_type = 0;
348 static const GTypeInfo vml_info =
350 sizeof (VikMapsLayerClass),
351 NULL, /* base_init */
352 NULL, /* base_finalize */
353 NULL, /* class init */
354 NULL, /* class_finalize */
355 NULL, /* class_data */
356 sizeof (VikMapsLayer),
358 NULL /* instance init */
360 vml_type = g_type_register_static ( VIK_LAYER_TYPE, "VikMapsLayer", &vml_info, 0 );
366 /****************************************/
367 /************** PARAMETERS **************/
368 /****************************************/
370 static guint map_index_to_uniq_id (guint8 index)
372 g_assert ( index < NUM_MAP_TYPES );
373 return MAPS_LAYER_NTH_TYPE(index)->uniq_id;
376 static guint map_uniq_id_to_index ( guint uniq_id )
379 for ( i = 0; i < NUM_MAP_TYPES; i++ )
380 if ( MAPS_LAYER_NTH_TYPE(i)->uniq_id == uniq_id )
382 return NUM_MAP_TYPES; /* no such thing */
385 static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp )
389 case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break;
390 case PARAM_MAPTYPE: {
391 gint maptype = map_uniq_id_to_index(data.u);
392 if ( maptype == NUM_MAP_TYPES ) g_warning(_("Unknown map type"));
393 else vml->maptype = maptype;
396 case PARAM_ALPHA: if ( data.u <= 255 ) vml->alpha = data.u; break;
397 case PARAM_AUTODOWNLOAD: vml->autodownload = data.b; break;
398 case PARAM_MAPZOOM: if ( data.u < NUM_MAPZOOMS ) {
399 vml->mapzoom_id = data.u;
400 vml->xmapzoom = __mapzooms_x [data.u];
401 vml->ymapzoom = __mapzooms_y [data.u];
402 }else g_warning (_("Unknown Map Zoom")); break;
407 static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id )
409 VikLayerParamData rv;
412 case PARAM_CACHE_DIR: rv.s = vml->cache_dir ? vml->cache_dir : ""; break;
413 case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break;
414 case PARAM_ALPHA: rv.u = vml->alpha; break;
415 case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break;
416 case PARAM_MAPZOOM: rv.u = vml->mapzoom_id; break;
421 /****************************************/
422 /****** CREATING, COPYING, FREEING ******/
423 /****************************************/
425 static VikMapsLayer *maps_layer_new ( VikViewport *vvp )
428 VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) );
429 vik_layer_init ( VIK_LAYER(vml), VIK_LAYER_MAPS );
430 idx = map_uniq_id_to_index(7); /* 7 is id for google maps */
431 vml->maptype = (idx < NUM_MAP_TYPES) ? idx : 0;
434 vml->dl_tool_x = vml->dl_tool_y = -1;
435 maps_layer_set_cache_dir ( vml, NULL );
436 vml->autodownload = FALSE;
437 vml->last_center = NULL;
438 vml->last_xmpp = 0.0;
439 vml->last_ympp = 0.0;
441 vml->dl_right_click_menu = NULL;
446 static void maps_layer_free ( VikMapsLayer *vml )
448 g_free ( vml->cache_dir );
449 vml->cache_dir = NULL;
450 if ( vml->dl_right_click_menu )
451 gtk_object_sink ( GTK_OBJECT(vml->dl_right_click_menu) );
452 g_free(vml->last_center);
453 vml->last_center = NULL;
456 static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file)
458 if (from_file != TRUE)
460 /* If this method is not called in file reading context
461 * it is called in GUI context.
462 * So, we can check if we have to inform the user about inconsistency */
463 VikViewportDrawMode vp_drawmode;
464 VikMapsLayer *vml = VIK_MAPS_LAYER(vl);
465 VikMapsLayer_MapType *map_type = NULL;
467 vp_drawmode = vik_viewport_get_drawmode ( VIK_VIEWPORT(vp) );
468 map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
469 if (map_type->drawmode != vp_drawmode) {
470 const gchar *drawmode_name = vik_viewport_get_drawmode_name (VIK_VIEWPORT(vp), map_type->drawmode);
471 gchar *msg = g_strdup_printf(_("New map cannot be displayed in the current drawmode.\nSelect \"%s\" from View menu to view it."), drawmode_name);
472 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), msg );
478 static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len )
480 vik_layer_marshall_params ( VIK_LAYER(vml), data, len );
483 static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
485 VikMapsLayer *rv = maps_layer_new ( vvp );
486 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
490 /*********************/
491 /****** DRAWING ******/
492 /*********************/
494 static GdkPixbuf *pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha )
497 gint width, height, iii, jjj;
499 if ( ! gdk_pixbuf_get_has_alpha ( pixbuf ) )
501 GdkPixbuf *tmp = gdk_pixbuf_add_alpha(pixbuf,FALSE,0,0,0);
502 g_object_unref(G_OBJECT(pixbuf));
506 pixels = gdk_pixbuf_get_pixels(pixbuf);
507 width = gdk_pixbuf_get_width(pixbuf);
508 height = gdk_pixbuf_get_height(pixbuf);
510 /* r,g,b,a,r,g,b,a.... */
511 for (iii = 0; iii < width; iii++) for (jjj = 0; jjj < height; jjj++)
519 static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdouble yshrinkfactor )
522 guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf);
523 tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_NEAREST);
524 g_object_unref ( G_OBJECT(pixbuf) );
528 static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, gchar *filename_buf, gint buf_len, gdouble xshrinkfactor, gdouble yshrinkfactor )
533 pixbuf = a_mapcache_get ( mapcoord->x, mapcoord->y, mapcoord->z,
534 mode, mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
537 g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE,
538 vml->cache_dir, mode,
539 mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y );
540 if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE) {
543 pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx );
547 if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE )
548 g_warning ( _("Couldn't open image file: %s"), gx->message );
552 g_object_unref ( G_OBJECT(pixbuf) );
555 if ( vml->alpha < 255 )
556 pixbuf = pixbuf_set_alpha ( pixbuf, vml->alpha );
557 if ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 )
558 pixbuf = pixbuf_shrink ( pixbuf, xshrinkfactor, yshrinkfactor );
560 a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y,
561 mapcoord->z, MAPS_LAYER_NTH_TYPE(vml->maptype)->uniq_id,
562 mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
570 gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp)
572 const VikCoord *center = vik_viewport_get_center ( vvp );
574 if (vml->last_center == NULL) {
575 VikCoord *new_center = g_malloc(sizeof(VikCoord));
576 *new_center = *center;
577 vml->last_center = new_center;
578 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
579 vml->last_ympp = vik_viewport_get_ympp(vvp);
583 /* TODO: perhaps vik_coord_diff() */
584 if (vik_coord_equals(vml->last_center, center)
585 && (vml->last_xmpp == vik_viewport_get_xmpp(vvp))
586 && (vml->last_ympp == vik_viewport_get_ympp(vvp)))
589 *(vml->last_center) = *center;
590 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
591 vml->last_ympp = vik_viewport_get_ympp(vvp);
595 static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br )
598 gdouble xzoom = vik_viewport_get_xmpp ( vvp );
599 gdouble yzoom = vik_viewport_get_ympp ( vvp );
600 gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0;
601 gdouble existence_only = FALSE;
603 if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) {
604 xshrinkfactor = vml->xmapzoom / xzoom;
605 yshrinkfactor = vml->ymapzoom / yzoom;
606 xzoom = vml->xmapzoom;
607 yzoom = vml->xmapzoom;
608 if ( ! (xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR &&
609 yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) ) {
610 if ( xshrinkfactor > REAL_MIN_SHRINKFACTOR && yshrinkfactor > REAL_MIN_SHRINKFACTOR )
611 existence_only = TRUE;
613 g_warning ( _("Cowardly refusing to draw tiles or existence of tiles beyond %d zoom out factor"), (int)( 1.0/REAL_MIN_SHRINKFACTOR));
620 VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
621 if ( map_type->coord_to_mapcoord ( ul, xzoom, yzoom, &ulm ) &&
622 map_type->coord_to_mapcoord ( br, xzoom, yzoom, &brm ) ) {
626 gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x);
627 gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y);
628 gint mode = map_type->uniq_id;
631 gint xx, yy, width, height;
634 guint max_path_len = strlen(vml->cache_dir) + 40;
635 gchar *path_buf = g_malloc ( max_path_len * sizeof(char) );
637 if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) {
639 fputs(stderr, "DEBUG: Starting autodownload\n");
641 if ( map_type->options != NULL && map_type->options->check_file_server_time )
642 // Try to download newer tiles
643 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
645 // Download only missing tiles
646 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
649 if ( map_type->tilesize_x == 0 && !existence_only ) {
650 for ( x = xmin; x <= xmax; x++ ) {
651 for ( y = ymin; y <= ymax; y++ ) {
654 pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
656 width = gdk_pixbuf_get_width ( pixbuf );
657 height = gdk_pixbuf_get_height ( pixbuf );
659 map_type->mapcoord_to_center_coord ( &ulm, &coord );
660 vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy );
664 vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height );
668 } else { /* tilesize is known, don't have to keep converting coords */
669 gdouble tilesize_x = map_type->tilesize_x * xshrinkfactor;
670 gdouble tilesize_y = map_type->tilesize_y * yshrinkfactor;
671 /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
672 gint tilesize_x_ceil = ceil ( tilesize_x );
673 gint tilesize_y_ceil = ceil ( tilesize_y );
674 gint8 xinc = (ulm.x == xmin) ? 1 : -1;
675 gint8 yinc = (ulm.y == ymin) ? 1 : -1;
676 gdouble xx, yy; gint xx_tmp, yy_tmp;
677 gint base_yy, xend, yend;
679 GdkGC *black_gc = GTK_WIDGET(vvp)->style->black_gc;
681 xend = (xinc == 1) ? (xmax+1) : (xmin-1);
682 yend = (yinc == 1) ? (ymax+1) : (ymin-1);
684 map_type->mapcoord_to_center_coord ( &ulm, &coord );
685 vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp );
686 xx = xx_tmp; yy = yy_tmp;
687 /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
688 * eg if tile size 128, shrinkfactor 0.333 */
689 xx -= (tilesize_x/2);
690 base_yy = yy - (tilesize_y/2);
692 for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) {
694 for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) {
698 if ( existence_only ) {
699 g_snprintf ( path_buf, max_path_len, DIRSTRUCTURE,
700 vml->cache_dir, mode,
701 ulm.scale, ulm.z, ulm.x, ulm.y );
702 if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) {
703 vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil );
706 pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
708 vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
710 /* retry with bigger shrinkfactor */
712 for (scale_inc = 1; scale_inc < 4; scale_inc ++) {
713 int scale_factor = 1 << scale_inc; /* 2^scale_inc */
715 ulm2.x = ulm.x / scale_factor;
716 ulm2.y = ulm.y / scale_factor;
717 ulm2.scale = ulm.scale + scale_inc;
718 pixbuf = get_pixbuf ( vml, mode, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor );
720 gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil;
721 gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil;
722 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
739 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp )
741 if ( MAPS_LAYER_NTH_TYPE(vml->maptype)->drawmode == vik_viewport_get_drawmode ( vvp ) )
745 /* get corner coords */
746 if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) {
747 /* UTM multi-zone stuff by Kit Transue */
748 gchar leftmost_zone, rightmost_zone, i;
749 leftmost_zone = vik_viewport_leftmost_zone( vvp );
750 rightmost_zone = vik_viewport_rightmost_zone( vvp );
751 for ( i = leftmost_zone; i <= rightmost_zone; ++i ) {
752 vik_viewport_corners_for_zonen ( vvp, i, &ul, &br );
753 maps_layer_draw_section ( vml, vvp, &ul, &br );
757 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
758 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
760 maps_layer_draw_section ( vml, vvp, &ul, &br );
765 /*************************/
766 /****** DOWNLOADING ******/
767 /*************************/
769 /* pass along data to thread, exists even if layer is deleted. */
779 gboolean refresh_display;
782 gboolean map_layer_alive;
786 static void mdi_free ( MapDownloadInfo *mdi )
788 g_mutex_free(mdi->mutex);
789 g_free ( mdi->cache_dir );
790 mdi->cache_dir = NULL;
791 g_free ( mdi->filename_buf );
792 mdi->filename_buf = NULL;
796 static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
798 MapDownloadInfo *mdi = ptr;
799 g_mutex_lock(mdi->mutex);
800 mdi->map_layer_alive = FALSE;
801 g_mutex_unlock(mdi->mutex);
804 static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
808 for ( x = mdi->x0; x <= mdi->xf; x++ )
810 for ( y = mdi->y0; y <= mdi->yf; y++ )
812 gboolean remove_mem_cache = FALSE;
813 gboolean need_download = FALSE;
814 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
815 mdi->cache_dir, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id,
816 mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
819 int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
823 if ( mdi->redownload == REDOWNLOAD_ALL)
824 g_remove ( mdi->filename_buf );
826 else if ( (mdi->redownload == REDOWNLOAD_BAD) && (g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE) )
828 /* see if this one is bad or what */
830 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
832 g_remove ( mdi->filename_buf );
834 g_object_unref ( pixbuf );
839 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
841 need_download = TRUE;
842 if (( mdi->redownload != REDOWNLOAD_NONE ) &&
843 ( mdi->redownload != DOWNLOAD_OR_REFRESH ))
844 remove_mem_cache = TRUE;
845 } else if ( mdi->redownload == DOWNLOAD_OR_REFRESH ) {
846 remove_mem_cache = TRUE;
847 } else if ( mdi->redownload == REDOWNLOAD_NEW) {
848 need_download = TRUE;
849 remove_mem_cache = TRUE;
853 mdi->mapcoord.x = x; mdi->mapcoord.y = y;
856 if ( MAPS_LAYER_NTH_TYPE(mdi->maptype)->download ( &(mdi->mapcoord), mdi->filename_buf ))
861 g_mutex_lock(mdi->mutex);
862 if (remove_mem_cache)
863 a_mapcache_remove_all_shrinkfactors ( x, y, mdi->mapcoord.z, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id, mdi->mapcoord.scale );
864 if (mdi->refresh_display && mdi->map_layer_alive) {
865 /* TODO: check if it's on visible area */
866 vik_layer_emit_update ( VIK_LAYER(mdi->vml) );
868 g_mutex_unlock(mdi->mutex);
870 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
874 g_mutex_lock(mdi->mutex);
875 if (mdi->map_layer_alive)
876 g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
877 g_mutex_unlock(mdi->mutex);
881 static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
883 if ( mdi->mapcoord.x || mdi->mapcoord.y )
885 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
886 mdi->cache_dir, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id,
887 mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y );
888 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
890 g_remove ( mdi->filename_buf );
895 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload )
897 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
898 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
900 VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
901 if ( map_type->coord_to_mapcoord ( ul, xzoom, yzoom, &ulm )
902 && map_type->coord_to_mapcoord ( br, xzoom, yzoom, &brm ) )
904 MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
909 mdi->map_layer_alive = TRUE;
910 mdi->mutex = g_mutex_new();
911 mdi->refresh_display = TRUE;
913 /* cache_dir and buffer for dest filename */
914 mdi->cache_dir = g_strdup ( vml->cache_dir );
915 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
916 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
917 mdi->maptype = vml->maptype;
921 mdi->redownload = redownload;
923 mdi->x0 = MIN(ulm.x, brm.x);
924 mdi->xf = MAX(ulm.x, brm.x);
925 mdi->y0 = MIN(ulm.y, brm.y);
926 mdi->yf = MAX(ulm.y, brm.y);
930 if ( mdi->redownload ) {
931 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
933 /* calculate how many we need */
934 for ( a = mdi->x0; a <= mdi->xf; a++ )
936 for ( b = mdi->y0; b <= mdi->yf; b++ )
938 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
939 vml->cache_dir, map_type->uniq_id, ulm.scale,
941 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
947 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
949 if ( mdi->mapstoget )
951 const gchar *tmp_str;
956 if (redownload == REDOWNLOAD_BAD)
957 tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget);
959 tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget);
963 tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget);
965 tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype));
967 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
968 /* launch the thread */
969 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
970 tmp, /* description string */
971 (vik_thr_func) map_download_thread, /* function to call within thread */
972 mdi, /* pass along data */
973 (vik_thr_free_func) mdi_free, /* function to free pass along data */
974 (vik_thr_free_func) mdi_cancel_cleanup,
983 void maps_layer_download_section_without_redraw( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom)
986 VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
988 if (!map_type->coord_to_mapcoord(ul, zoom, zoom, &ulm)
989 || !map_type->coord_to_mapcoord(br, zoom, zoom, &brm)) {
990 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
994 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
999 mdi->map_layer_alive = TRUE;
1000 mdi->mutex = g_mutex_new();
1001 mdi->refresh_display = FALSE;
1003 mdi->cache_dir = g_strdup ( vml->cache_dir );
1004 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1005 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1006 mdi->maptype = vml->maptype;
1008 mdi->mapcoord = ulm;
1010 mdi->redownload = REDOWNLOAD_NONE;
1012 mdi->x0 = MIN(ulm.x, brm.x);
1013 mdi->xf = MAX(ulm.x, brm.x);
1014 mdi->y0 = MIN(ulm.y, brm.y);
1015 mdi->yf = MAX(ulm.y, brm.y);
1019 for (i = mdi->x0; i <= mdi->xf; i++) {
1020 for (j = mdi->y0; j <= mdi->yf; j++) {
1021 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
1022 vml->cache_dir, map_type->uniq_id, ulm.scale,
1024 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1029 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1031 if (mdi->mapstoget) {
1034 fmt = ngettext("Downloading %d %s map...",
1035 "Downloading %d %s maps...",
1037 tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) );
1039 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1040 /* launch the thread */
1041 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1042 tmp, /* description string */
1043 (vik_thr_func) map_download_thread, /* function to call within thread */
1044 mdi, /* pass along data */
1045 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1046 (vik_thr_free_func) mdi_cancel_cleanup,
1054 static void maps_layer_redownload_bad ( VikMapsLayer *vml )
1056 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
1059 static void maps_layer_redownload_all ( VikMapsLayer *vml )
1061 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
1064 static void maps_layer_redownload_new ( VikMapsLayer *vml )
1066 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
1069 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1071 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1073 if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 )
1075 if ( event->button == 1 )
1078 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 );
1079 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 );
1080 start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
1081 vml->dl_tool_x = vml->dl_tool_y = -1;
1086 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) );
1087 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) );
1089 vml->redownload_vvp = vvp;
1091 vml->dl_tool_x = vml->dl_tool_y = -1;
1093 if ( ! vml->dl_right_click_menu ) {
1095 vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () );
1097 item = gtk_menu_item_new_with_label ( _("Redownload bad map(s)") );
1098 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
1099 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1101 item = gtk_menu_item_new_with_label ( _("Redownload new map(s)") );
1102 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
1103 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1105 item = gtk_menu_item_new_with_label ( _("Redownload all map(s)") );
1106 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
1107 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1110 gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
1111 gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) );
1117 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1122 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1125 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1127 VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
1128 if ( map_type->drawmode == vik_viewport_get_drawmode ( vvp ) &&
1129 map_type->coord_to_mapcoord ( vik_viewport_get_center ( vvp ),
1130 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1131 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1133 vml->dl_tool_x = event->x, vml->dl_tool_y = event->y;
1140 if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) )
1144 vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
1145 if ( __map_types[vml->maptype].coord_to_mapcoord ( &coord,
1146 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1147 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1149 gchar *filename_buf = g_strdup_printf ( DIRSTRUCTURE,
1150 vml->cache_dir, __map_types[vml->maptype].uniq_id,
1151 mapcoord.scale, mapcoord.z, mapcoord.x, mapcoord.y );
1153 __map_types[vml->maptype].download ( &mapcoord, filename_buf );
1154 g_free ( filename_buf );
1155 vik_layer_emit_update ( VIK_LAYER(vml) );
1163 static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload )
1165 VikMapsLayer *vml = vml_vvp[0];
1166 VikViewport *vvp = vml_vvp[1];
1167 VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
1169 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1170 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1175 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1176 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1178 VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
1179 if ( map_type->drawmode == vp_drawmode &&
1180 map_type->coord_to_mapcoord ( &ul, xzoom, yzoom, &ulm ) &&
1181 map_type->coord_to_mapcoord ( &br, xzoom, yzoom, &brm ) )
1182 start_download_thread ( vml, vvp, &ul, &br, redownload );
1183 else if (map_type->drawmode != vp_drawmode) {
1184 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, map_type->drawmode);
1185 gchar *err = g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name));
1186 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1190 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Wrong zoom level for this map.") );
1194 static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] )
1196 download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
1199 static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] )
1201 download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW);
1204 static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
1206 download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
1209 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp )
1211 static gpointer pass_along[2];
1213 pass_along[0] = vml;
1214 pass_along[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) );
1216 item = gtk_menu_item_new();
1217 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
1218 gtk_widget_show ( item );
1220 item = gtk_menu_item_new_with_label ( _("Download missing Onscreen Maps") );
1221 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along );
1222 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1223 gtk_widget_show ( item );
1225 if ( MAPS_LAYER_NTH_TYPE(vml->maptype)->options != NULL &&
1226 MAPS_LAYER_NTH_TYPE(vml->maptype)->options->check_file_server_time ) {
1227 item = gtk_menu_item_new_with_label ( _("Download new Onscreen Maps from server") );
1228 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along );
1229 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1230 gtk_widget_show ( item );
1233 /* TODO Add GTK_STOCK_REFRESH icon */
1234 item = gtk_menu_item_new_with_label ( _("Refresh Onscreen Tiles") );
1235 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
1236 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1237 gtk_widget_show ( item );