2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2005, Evan Battaglia <viking@greentorch.org>
5 * Copyright (C) 2010, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
6 * UTM multi-zone stuff by Kit Transue <notlostyet@didactek.com>
7 * Dynamic map type by Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
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.
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.
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
29 #define MAX_SHRINKFACTOR 8.0000001 /* zoom 1 viewing 8-tiles */
30 #define MIN_SHRINKFACTOR 0.0312499 /* zoom 32 viewing 1-tiles */
32 #define REAL_MIN_SHRINKFACTOR 0.0039062499 /* if shrinkfactor is between MAX and REAL_MAX, will only check for existence */
35 #include <gdk-pixbuf/gdk-pixdata.h>
37 #include <glib/gstdio.h>
38 #include <glib/gi18n.h>
50 #include "viktreeview.h"
51 #include "vikviewport.h"
53 #include "vikmapslayer.h"
60 /* only for dialog.h -- ugh */
61 #include "vikwaypoint.h"
63 #include "preferences.h"
65 #include "vikstatus.h"
66 #include "background.h"
68 #include "vikaggregatelayer.h"
69 #include "viklayerspanel.h"
72 #include "terraserver.h"
74 #include "icons/icons.h"
76 /****** MAP TYPES ******/
78 static GList *__map_types = NULL;
80 #define NUM_MAP_TYPES g_list_length(__map_types)
82 /* List of label for each map type */
83 static gchar **params_maptypes = NULL;
85 /* Corresponding IDS. (Cf. field uniq_id in VikMapsLayer struct) */
86 static guint *params_maptypes_ids = NULL;
88 /******** MAPZOOMS *********/
90 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 };
91 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 };
92 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 };
94 #define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0]) - 1)
96 /**************************/
99 static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file);
100 static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len );
101 static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
102 static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation );
103 static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation );
104 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp );
105 static VikMapsLayer *maps_layer_new ( VikViewport *vvp );
106 static void maps_layer_free ( VikMapsLayer *vml );
107 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
108 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
109 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp );
110 static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir );
111 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload );
112 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp );
113 static guint map_uniq_id_to_index ( guint uniq_id );
116 static VikLayerParamScale params_scales[] = {
117 /* min, max, step, digits (decimal places) */
118 { 0, 255, 3, 0 }, /* alpha */
121 VikLayerParam maps_layer_params[] = {
122 { "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Map Type:"), VIK_LAYER_WIDGET_COMBOBOX, NULL, NULL },
123 { "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Maps Directory:"), VIK_LAYER_WIDGET_FOLDERENTRY },
124 { "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales },
125 { "autodownload", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload maps:"), VIK_LAYER_WIDGET_CHECKBUTTON },
126 { "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms, NULL },
129 enum { PARAM_MAPTYPE=0, PARAM_CACHE_DIR, PARAM_ALPHA, PARAM_AUTODOWNLOAD, PARAM_MAPZOOM, NUM_PARAMS };
131 static VikToolInterface maps_tools[] = {
132 { N_("Maps Download"), (VikToolConstructorFunc) maps_layer_download_create, NULL, NULL, NULL,
133 (VikToolMouseFunc) maps_layer_download_click, NULL, (VikToolMouseFunc) maps_layer_download_release,
134 (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_mapdl_pixbuf },
137 VikLayerInterface vik_maps_layer_interface = {
139 &vikmapslayer_pixbuf,
142 sizeof(maps_tools) / sizeof(maps_tools[0]),
151 (VikLayerFuncCreate) maps_layer_new,
152 (VikLayerFuncRealize) NULL,
153 (VikLayerFuncPostRead) maps_layer_post_read,
154 (VikLayerFuncFree) maps_layer_free,
156 (VikLayerFuncProperties) NULL,
157 (VikLayerFuncDraw) maps_layer_draw,
158 (VikLayerFuncChangeCoordMode) NULL,
160 (VikLayerFuncSetMenuItemsSelection) NULL,
161 (VikLayerFuncGetMenuItemsSelection) NULL,
163 (VikLayerFuncAddMenuItems) maps_layer_add_menu_items,
164 (VikLayerFuncSublayerAddMenuItems) NULL,
166 (VikLayerFuncSublayerRenameRequest) NULL,
167 (VikLayerFuncSublayerToggleVisible) NULL,
169 (VikLayerFuncMarshall) maps_layer_marshall,
170 (VikLayerFuncUnmarshall) maps_layer_unmarshall,
172 (VikLayerFuncSetParam) maps_layer_set_param,
173 (VikLayerFuncGetParam) maps_layer_get_param,
175 (VikLayerFuncReadFileData) NULL,
176 (VikLayerFuncWriteFileData) NULL,
178 (VikLayerFuncDeleteItem) NULL,
179 (VikLayerFuncCopyItem) NULL,
180 (VikLayerFuncPasteItem) NULL,
181 (VikLayerFuncFreeCopiedItem) NULL,
182 (VikLayerFuncDragDropRequest) NULL,
185 struct _VikMapsLayer {
191 gdouble xmapzoom, ymapzoom;
193 gboolean autodownload;
194 VikCoord *last_center;
198 gint dl_tool_x, dl_tool_y;
200 GtkMenu *dl_right_click_menu;
201 VikCoord redownload_ul, redownload_br; /* right click menu only */
202 VikViewport *redownload_vvp;
205 enum { REDOWNLOAD_NONE = 0, /* download only missing maps */
206 REDOWNLOAD_BAD, /* download missing and bad maps */
207 REDOWNLOAD_NEW, /* download missing maps that are newer on server only */
208 REDOWNLOAD_ALL, /* download all maps */
209 DOWNLOAD_OR_REFRESH }; /* download missing maps and refresh cache */
211 static VikLayerParam prefs[] = {
212 { VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Default maplayer directory:"), VIK_LAYER_WIDGET_FOLDERENTRY, NULL, NULL },
215 void maps_layer_init ()
217 VikLayerParamData tmp;
218 tmp.s = maps_layer_default_dir();
219 a_preferences_register(prefs, tmp, VIKING_PREFERENCES_GROUP_KEY);
222 /****************************************/
223 /******** MAPS LAYER TYPES **************/
224 /****************************************/
226 int _get_index_for_id ( guint id )
229 while (params_maptypes_ids[index] != 0)
231 if (params_maptypes_ids[index] == id)
238 void _add_map_source ( guint id, const char *label, VikMapSource *map )
242 len = g_strv_length (params_maptypes);
244 params_maptypes = g_realloc (params_maptypes, (len+2)*sizeof(gchar*));
245 params_maptypes[len] = g_strdup (label);
246 params_maptypes[len+1] = NULL;
249 params_maptypes_ids = g_realloc (params_maptypes_ids, (len+2)*sizeof(guint));
250 params_maptypes_ids[len] = id;
251 params_maptypes_ids[len+1] = 0;
253 /* We have to clone */
254 VikMapSource *clone = VIK_MAP_SOURCE(g_object_ref(map));
255 /* Register the clone in the list */
256 __map_types = g_list_append(__map_types, clone);
259 We have to ensure the mode LayerParam references the up-to-date
263 memcpy(&maps_layer_params[0].widget_data, ¶ms_maptypes, sizeof(gpointer));
264 memcpy(&maps_layer_params[0].extra_widget_data, ¶ms_maptypes_ids, sizeof(gpointer));
266 maps_layer_params[0].widget_data = params_maptypes;
267 maps_layer_params[0].extra_widget_data = params_maptypes_ids;
270 void _update_map_source ( const char *label, VikMapSource *map, int index )
272 GList *item = g_list_nth (__map_types, index);
273 g_object_unref (item->data);
274 item->data = g_object_ref (map);
275 /* Change previous data */
276 g_free (params_maptypes[index]);
277 params_maptypes[index] = g_strdup (label);
280 void maps_layer_register_map_source ( VikMapSource *map )
282 g_assert(map != NULL);
284 guint id = vik_map_source_get_uniq_id(map);
285 const char *label = vik_map_source_get_label(map);
286 g_assert(label != NULL);
288 int previous = map_uniq_id_to_index (id);
289 if (previous != NUM_MAP_TYPES)
291 _update_map_source (label, map, previous);
295 _add_map_source (id, label, map);
299 #define MAPS_LAYER_NTH_LABEL(n) (params_maptypes[n])
300 #define MAPS_LAYER_NTH_ID(n) (params_maptypes_ids[n])
301 #define MAPS_LAYER_NTH_TYPE(n) (VIK_MAP_SOURCE(g_list_nth_data(__map_types, (n))))
303 gint vik_maps_layer_get_map_type(VikMapsLayer *vml)
305 return(vml->maptype);
308 gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml)
310 return(g_strdup(MAPS_LAYER_NTH_LABEL(vml->maptype)));
313 /****************************************/
314 /******** CACHE DIR STUFF ***************/
315 /****************************************/
317 #define DIRSTRUCTURE "%st%ds%dz%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d"
318 #define MAPS_CACHE_DIR maps_layer_default_dir()
322 #define GLOBAL_MAPS_DIR "C:\\VIKING-MAPS\\"
323 #define LOCAL_MAPS_DIR "VIKING-MAPS"
326 #define GLOBAL_MAPS_DIR "/var/cache/maps/"
327 #define LOCAL_MAPS_DIR ".viking-maps"
330 gchar *maps_layer_default_dir ()
332 static gchar *defaultdir = NULL;
335 /* Thanks to Mike Davison for the $VIKING_MAPS usage */
336 const gchar *mapdir = g_getenv("VIKING_MAPS");
338 defaultdir = g_strdup ( mapdir );
339 } else if ( g_access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) {
340 defaultdir = g_strdup ( GLOBAL_MAPS_DIR );
342 const gchar *home = g_get_home_dir();
343 if (!home || g_access(home, W_OK))
344 home = g_get_home_dir ();
346 defaultdir = g_build_filename ( home, LOCAL_MAPS_DIR, NULL );
348 defaultdir = g_strdup ( LOCAL_MAPS_DIR );
350 if (defaultdir && (defaultdir[strlen(defaultdir)-1] != G_DIR_SEPARATOR))
352 /* Add the separator at the end */
353 gchar *tmp = defaultdir;
354 defaultdir = g_strconcat(tmp, G_DIR_SEPARATOR_S, NULL);
357 g_debug("%s: defaultdir=%s", __FUNCTION__, defaultdir);
362 static void maps_layer_mkdir_if_default_dir ( VikMapsLayer *vml )
364 if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && g_file_test ( vml->cache_dir, G_FILE_TEST_EXISTS ) == FALSE )
366 g_mkdir ( vml->cache_dir, 0777 );
370 static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir )
373 g_assert ( vml != NULL);
374 g_free ( vml->cache_dir );
375 vml->cache_dir = NULL;
377 if ( dir == NULL || dir[0] == '\0' )
379 if ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir") )
380 vml->cache_dir = g_strdup ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir")->s );
385 if ( dir[len-1] != G_DIR_SEPARATOR )
387 vml->cache_dir = g_malloc ( len+2 );
388 strncpy ( vml->cache_dir, dir, len );
389 vml->cache_dir[len] = G_DIR_SEPARATOR;
390 vml->cache_dir[len+1] = '\0';
393 vml->cache_dir = g_strdup ( dir );
395 maps_layer_mkdir_if_default_dir ( vml );
398 /****************************************/
399 /******** GOBJECT STUFF *****************/
400 /****************************************/
402 GType vik_maps_layer_get_type ()
404 static GType vml_type = 0;
408 static const GTypeInfo vml_info =
410 sizeof (VikMapsLayerClass),
411 NULL, /* base_init */
412 NULL, /* base_finalize */
413 NULL, /* class init */
414 NULL, /* class_finalize */
415 NULL, /* class_data */
416 sizeof (VikMapsLayer),
418 NULL /* instance init */
420 vml_type = g_type_register_static ( VIK_LAYER_TYPE, "VikMapsLayer", &vml_info, 0 );
426 /****************************************/
427 /************** PARAMETERS **************/
428 /****************************************/
430 static guint map_index_to_uniq_id (guint8 index)
432 g_assert ( index < NUM_MAP_TYPES );
433 return vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(index));
436 static guint map_uniq_id_to_index ( guint uniq_id )
439 for ( i = 0; i < NUM_MAP_TYPES; i++ )
440 if ( vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(i)) == uniq_id )
442 return NUM_MAP_TYPES; /* no such thing */
445 static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation )
449 case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break;
450 case PARAM_MAPTYPE: {
451 gint maptype = map_uniq_id_to_index(data.u);
452 if ( maptype == NUM_MAP_TYPES ) g_warning(_("Unknown map type"));
453 else vml->maptype = maptype;
456 case PARAM_ALPHA: if ( data.u <= 255 ) vml->alpha = data.u; break;
457 case PARAM_AUTODOWNLOAD: vml->autodownload = data.b; break;
458 case PARAM_MAPZOOM: if ( data.u < NUM_MAPZOOMS ) {
459 vml->mapzoom_id = data.u;
460 vml->xmapzoom = __mapzooms_x [data.u];
461 vml->ymapzoom = __mapzooms_y [data.u];
462 }else g_warning (_("Unknown Map Zoom")); break;
467 static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation )
469 VikLayerParamData rv;
472 case PARAM_CACHE_DIR: rv.s = vml->cache_dir ? vml->cache_dir : ""; break;
473 case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break;
474 case PARAM_ALPHA: rv.u = vml->alpha; break;
475 case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break;
476 case PARAM_MAPZOOM: rv.u = vml->mapzoom_id; break;
481 /****************************************/
482 /****** CREATING, COPYING, FREEING ******/
483 /****************************************/
485 static VikMapsLayer *maps_layer_new ( VikViewport *vvp )
488 VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) );
489 vik_layer_init ( VIK_LAYER(vml), VIK_LAYER_MAPS );
490 idx = map_uniq_id_to_index(13); /* 13 is id for OSM Mapnik maps */
491 vml->maptype = (idx < NUM_MAP_TYPES) ? idx : 0;
494 vml->dl_tool_x = vml->dl_tool_y = -1;
495 maps_layer_set_cache_dir ( vml, NULL );
496 vml->autodownload = FALSE;
497 vml->last_center = NULL;
498 vml->last_xmpp = 0.0;
499 vml->last_ympp = 0.0;
501 vml->dl_right_click_menu = NULL;
506 static void maps_layer_free ( VikMapsLayer *vml )
508 g_free ( vml->cache_dir );
509 vml->cache_dir = NULL;
510 if ( vml->dl_right_click_menu )
511 gtk_object_sink ( GTK_OBJECT(vml->dl_right_click_menu) );
512 g_free(vml->last_center);
513 vml->last_center = NULL;
516 static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file)
518 if (from_file != TRUE)
520 /* If this method is not called in file reading context
521 * it is called in GUI context.
522 * So, we can check if we have to inform the user about inconsistency */
523 VikViewportDrawMode vp_drawmode;
524 VikMapsLayer *vml = VIK_MAPS_LAYER(vl);
525 VikMapSource *map = NULL;
527 vp_drawmode = vik_viewport_get_drawmode ( VIK_VIEWPORT(vp) );
528 map = MAPS_LAYER_NTH_TYPE(vml->maptype);
529 if (vik_map_source_get_drawmode(map) != vp_drawmode) {
530 const gchar *drawmode_name = vik_viewport_get_drawmode_name (VIK_VIEWPORT(vp), vik_map_source_get_drawmode(map));
531 gchar *msg = g_strdup_printf(_("New map cannot be displayed in the current drawmode.\nSelect \"%s\" from View menu to view it."), drawmode_name);
532 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp), msg );
538 static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len )
540 vik_layer_marshall_params ( VIK_LAYER(vml), data, len );
543 static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
545 VikMapsLayer *rv = maps_layer_new ( vvp );
546 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
550 /*********************/
551 /****** DRAWING ******/
552 /*********************/
554 static GdkPixbuf *pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha )
557 gint width, height, iii, jjj;
559 if ( ! gdk_pixbuf_get_has_alpha ( pixbuf ) )
561 GdkPixbuf *tmp = gdk_pixbuf_add_alpha(pixbuf,FALSE,0,0,0);
562 g_object_unref(G_OBJECT(pixbuf));
566 pixels = gdk_pixbuf_get_pixels(pixbuf);
567 width = gdk_pixbuf_get_width(pixbuf);
568 height = gdk_pixbuf_get_height(pixbuf);
570 /* r,g,b,a,r,g,b,a.... */
571 for (iii = 0; iii < width; iii++) for (jjj = 0; jjj < height; jjj++)
579 static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdouble yshrinkfactor )
582 guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf);
583 tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_NEAREST);
584 g_object_unref ( G_OBJECT(pixbuf) );
588 static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, gchar *filename_buf, gint buf_len, gdouble xshrinkfactor, gdouble yshrinkfactor )
593 pixbuf = a_mapcache_get ( mapcoord->x, mapcoord->y, mapcoord->z,
594 mode, mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
597 g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE,
598 vml->cache_dir, mode,
599 mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y );
600 if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
603 pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx );
605 /* free the pixbuf on error */
608 if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE )
609 g_warning ( _("Couldn't open image file: %s"), gx->message );
613 g_object_unref ( G_OBJECT(pixbuf) );
616 if ( vml->alpha < 255 )
617 pixbuf = pixbuf_set_alpha ( pixbuf, vml->alpha );
618 if ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 )
619 pixbuf = pixbuf_shrink ( pixbuf, xshrinkfactor, yshrinkfactor );
621 a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y,
622 mapcoord->z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(vml->maptype)),
623 mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
630 gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp)
632 const VikCoord *center = vik_viewport_get_center ( vvp );
634 if (vik_window_get_pan_move (VIK_GTK_WINDOW_FROM_WIDGET(GTK_WIDGET(vvp))))
635 /* D'n'D pan in action: do not download */
638 if (vml->last_center == NULL) {
639 VikCoord *new_center = g_malloc(sizeof(VikCoord));
640 *new_center = *center;
641 vml->last_center = new_center;
642 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
643 vml->last_ympp = vik_viewport_get_ympp(vvp);
647 /* TODO: perhaps vik_coord_diff() */
648 if (vik_coord_equals(vml->last_center, center)
649 && (vml->last_xmpp == vik_viewport_get_xmpp(vvp))
650 && (vml->last_ympp == vik_viewport_get_ympp(vvp)))
653 *(vml->last_center) = *center;
654 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
655 vml->last_ympp = vik_viewport_get_ympp(vvp);
659 static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br )
662 gdouble xzoom = vik_viewport_get_xmpp ( vvp );
663 gdouble yzoom = vik_viewport_get_ympp ( vvp );
664 gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0;
665 gdouble existence_only = FALSE;
667 if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) {
668 xshrinkfactor = vml->xmapzoom / xzoom;
669 yshrinkfactor = vml->ymapzoom / yzoom;
670 xzoom = vml->xmapzoom;
671 yzoom = vml->xmapzoom;
672 if ( ! (xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR &&
673 yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) ) {
674 if ( xshrinkfactor > REAL_MIN_SHRINKFACTOR && yshrinkfactor > REAL_MIN_SHRINKFACTOR )
675 existence_only = TRUE;
677 g_warning ( _("Cowardly refusing to draw tiles or existence of tiles beyond %d zoom out factor"), (int)( 1.0/REAL_MIN_SHRINKFACTOR));
684 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
685 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm ) &&
686 vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) ) {
690 gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x);
691 gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y);
692 gint mode = vik_map_source_get_uniq_id(map);
695 gint xx, yy, width, height;
698 guint max_path_len = strlen(vml->cache_dir) + 40;
699 gchar *path_buf = g_malloc ( max_path_len * sizeof(char) );
701 if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) {
702 g_debug("%s: Starting autodownload", __FUNCTION__);
703 if ( vik_map_source_supports_download_only_new (map) )
704 // Try to download newer tiles
705 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
707 // Download only missing tiles
708 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
711 if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) {
712 for ( x = xmin; x <= xmax; x++ ) {
713 for ( y = ymin; y <= ymax; y++ ) {
716 pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
718 width = gdk_pixbuf_get_width ( pixbuf );
719 height = gdk_pixbuf_get_height ( pixbuf );
721 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
722 vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy );
726 vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height );
730 } else { /* tilesize is known, don't have to keep converting coords */
731 gdouble tilesize_x = vik_map_source_get_tilesize_x(map) * xshrinkfactor;
732 gdouble tilesize_y = vik_map_source_get_tilesize_y(map) * yshrinkfactor;
733 /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
734 gint tilesize_x_ceil = ceil ( tilesize_x );
735 gint tilesize_y_ceil = ceil ( tilesize_y );
736 gint8 xinc = (ulm.x == xmin) ? 1 : -1;
737 gint8 yinc = (ulm.y == ymin) ? 1 : -1;
738 gdouble xx, yy; gint xx_tmp, yy_tmp;
739 gint base_yy, xend, yend;
741 GdkGC *black_gc = GTK_WIDGET(vvp)->style->black_gc;
743 xend = (xinc == 1) ? (xmax+1) : (xmin-1);
744 yend = (yinc == 1) ? (ymax+1) : (ymin-1);
746 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
747 vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp );
748 xx = xx_tmp; yy = yy_tmp;
749 /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
750 * eg if tile size 128, shrinkfactor 0.333 */
751 xx -= (tilesize_x/2);
752 base_yy = yy - (tilesize_y/2);
754 for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) {
756 for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) {
760 if ( existence_only ) {
761 g_snprintf ( path_buf, max_path_len, DIRSTRUCTURE,
762 vml->cache_dir, mode,
763 ulm.scale, ulm.z, ulm.x, ulm.y );
764 if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) {
765 vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil );
769 for (scale_inc = 0; scale_inc < 4; scale_inc ++) {
770 /* try with correct then smaller zooms */
771 int scale_factor = 1 << scale_inc; /* 2^scale_inc */
773 ulm2.x = ulm.x / scale_factor;
774 ulm2.y = ulm.y / scale_factor;
775 ulm2.scale = ulm.scale + scale_inc;
776 pixbuf = get_pixbuf ( vml, mode, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor );
778 gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil;
779 gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil;
781 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);
783 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
788 /* retry with bigger zooms */
790 for (scale_dec = 1; scale_dec < 2; scale_dec ++) {
792 int scale_factor = 1 << scale_dec; /* 2^scale_dec */
794 ulm2.x = ulm.x * scale_factor;
795 ulm2.y = ulm.y * scale_factor;
796 ulm2.scale = ulm.scale - scale_dec;
797 for (pict_x = 0; pict_x < scale_factor; pict_x ++) {
798 for (pict_y = 0; pict_y < scale_factor; pict_y ++) {
799 MapCoord ulm3 = ulm2;
802 pixbuf = get_pixbuf ( vml, mode, &ulm3, path_buf, max_path_len, xshrinkfactor / scale_factor, yshrinkfactor / scale_factor );
806 gint dest_x = xx + pict_x * (tilesize_x_ceil / scale_factor);
807 gint dest_y = yy + pict_y * (tilesize_y_ceil / scale_factor);
808 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, dest_x, dest_y, tilesize_x_ceil / scale_factor, tilesize_y_ceil / scale_factor );
826 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp )
828 if ( vik_map_source_get_drawmode(MAPS_LAYER_NTH_TYPE(vml->maptype)) == vik_viewport_get_drawmode ( vvp ) )
832 /* get corner coords */
833 if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) {
834 /* UTM multi-zone stuff by Kit Transue */
835 gchar leftmost_zone, rightmost_zone, i;
836 leftmost_zone = vik_viewport_leftmost_zone( vvp );
837 rightmost_zone = vik_viewport_rightmost_zone( vvp );
838 for ( i = leftmost_zone; i <= rightmost_zone; ++i ) {
839 vik_viewport_corners_for_zonen ( vvp, i, &ul, &br );
840 maps_layer_draw_section ( vml, vvp, &ul, &br );
844 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
845 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
847 maps_layer_draw_section ( vml, vvp, &ul, &br );
852 /*************************/
853 /****** DOWNLOADING ******/
854 /*************************/
856 /* pass along data to thread, exists even if layer is deleted. */
866 gboolean refresh_display;
869 gboolean map_layer_alive;
873 static void mdi_free ( MapDownloadInfo *mdi )
875 g_mutex_free(mdi->mutex);
876 g_free ( mdi->cache_dir );
877 mdi->cache_dir = NULL;
878 g_free ( mdi->filename_buf );
879 mdi->filename_buf = NULL;
883 static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
885 MapDownloadInfo *mdi = ptr;
886 g_mutex_lock(mdi->mutex);
887 mdi->map_layer_alive = FALSE;
888 g_mutex_unlock(mdi->mutex);
891 static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
893 void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype));
896 for ( x = mdi->x0; x <= mdi->xf; x++ )
898 for ( y = mdi->y0; y <= mdi->yf; y++ )
900 gboolean remove_mem_cache = FALSE;
901 gboolean need_download = FALSE;
902 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
903 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
904 mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
907 int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
909 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
913 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
914 need_download = TRUE;
915 remove_mem_cache = TRUE;
917 } else { /* in case map file already exists */
918 switch (mdi->redownload) {
919 case REDOWNLOAD_NONE:
924 /* see if this one is bad or what */
926 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
927 if (gx || (!pixbuf)) {
928 g_remove ( mdi->filename_buf );
929 need_download = TRUE;
930 remove_mem_cache = TRUE;
934 g_object_unref ( pixbuf );
940 need_download = TRUE;
941 remove_mem_cache = TRUE;
945 /* FIXME: need a better way than to erase file in case of server/network problem */
946 g_remove ( mdi->filename_buf );
947 need_download = TRUE;
948 remove_mem_cache = TRUE;
951 case DOWNLOAD_OR_REFRESH:
952 remove_mem_cache = TRUE;
956 g_warning ( "redownload state %d unknown\n", mdi->redownload);
960 mdi->mapcoord.x = x; mdi->mapcoord.y = y;
963 if ( vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle))
968 g_mutex_lock(mdi->mutex);
969 if (remove_mem_cache)
970 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 );
971 if (mdi->refresh_display && mdi->map_layer_alive) {
972 /* TODO: check if it's on visible area */
973 vik_layer_emit_update ( VIK_LAYER(mdi->vml) );
975 g_mutex_unlock(mdi->mutex);
977 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
981 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
982 g_mutex_lock(mdi->mutex);
983 if (mdi->map_layer_alive)
984 g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
985 g_mutex_unlock(mdi->mutex);
989 static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
991 if ( mdi->mapcoord.x || mdi->mapcoord.y )
993 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
994 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
995 mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y );
996 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
998 g_remove ( mdi->filename_buf );
1003 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload )
1005 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1006 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1008 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1009 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm )
1010 && vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) )
1012 MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
1017 mdi->map_layer_alive = TRUE;
1018 mdi->mutex = g_mutex_new();
1019 mdi->refresh_display = TRUE;
1021 /* cache_dir and buffer for dest filename */
1022 mdi->cache_dir = g_strdup ( vml->cache_dir );
1023 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1024 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1025 mdi->maptype = vml->maptype;
1027 mdi->mapcoord = ulm;
1029 mdi->redownload = redownload;
1031 mdi->x0 = MIN(ulm.x, brm.x);
1032 mdi->xf = MAX(ulm.x, brm.x);
1033 mdi->y0 = MIN(ulm.y, brm.y);
1034 mdi->yf = MAX(ulm.y, brm.y);
1038 if ( mdi->redownload ) {
1039 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
1041 /* calculate how many we need */
1042 for ( a = mdi->x0; a <= mdi->xf; a++ )
1044 for ( b = mdi->y0; b <= mdi->yf; b++ )
1046 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
1047 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
1049 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1055 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1057 if ( mdi->mapstoget )
1059 const gchar *tmp_str;
1064 if (redownload == REDOWNLOAD_BAD)
1065 tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget);
1067 tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget);
1071 tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget);
1073 tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype));
1075 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1076 /* launch the thread */
1077 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1078 tmp, /* description string */
1079 (vik_thr_func) map_download_thread, /* function to call within thread */
1080 mdi, /* pass along data */
1081 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1082 (vik_thr_free_func) mdi_cancel_cleanup,
1091 void maps_layer_download_section_without_redraw( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom)
1094 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1096 if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm)
1097 || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) {
1098 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
1102 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
1107 mdi->map_layer_alive = TRUE;
1108 mdi->mutex = g_mutex_new();
1109 mdi->refresh_display = FALSE;
1111 mdi->cache_dir = g_strdup ( vml->cache_dir );
1112 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1113 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1114 mdi->maptype = vml->maptype;
1116 mdi->mapcoord = ulm;
1118 mdi->redownload = REDOWNLOAD_NONE;
1120 mdi->x0 = MIN(ulm.x, brm.x);
1121 mdi->xf = MAX(ulm.x, brm.x);
1122 mdi->y0 = MIN(ulm.y, brm.y);
1123 mdi->yf = MAX(ulm.y, brm.y);
1127 for (i = mdi->x0; i <= mdi->xf; i++) {
1128 for (j = mdi->y0; j <= mdi->yf; j++) {
1129 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
1130 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
1132 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1137 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1139 if (mdi->mapstoget) {
1142 fmt = ngettext("Downloading %d %s map...",
1143 "Downloading %d %s maps...",
1145 tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) );
1147 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1148 /* launch the thread */
1149 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1150 tmp, /* description string */
1151 (vik_thr_func) map_download_thread, /* function to call within thread */
1152 mdi, /* pass along data */
1153 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1154 (vik_thr_free_func) mdi_cancel_cleanup,
1162 static void maps_layer_redownload_bad ( VikMapsLayer *vml )
1164 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
1167 static void maps_layer_redownload_all ( VikMapsLayer *vml )
1169 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
1172 static void maps_layer_redownload_new ( VikMapsLayer *vml )
1174 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
1177 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1179 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1181 if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 )
1183 if ( event->button == 1 )
1186 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 );
1187 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 );
1188 start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
1189 vml->dl_tool_x = vml->dl_tool_y = -1;
1194 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) );
1195 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) );
1197 vml->redownload_vvp = vvp;
1199 vml->dl_tool_x = vml->dl_tool_y = -1;
1201 if ( ! vml->dl_right_click_menu ) {
1203 vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () );
1205 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _Bad Map(s)") );
1206 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
1207 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1209 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _New Map(s)") );
1210 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
1211 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1213 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _All Map(s)") );
1214 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
1215 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1218 gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
1219 gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) );
1225 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1230 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1233 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1235 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1236 if ( vik_map_source_get_drawmode(map) == vik_viewport_get_drawmode ( vvp ) &&
1237 vik_map_source_coord_to_mapcoord ( map, vik_viewport_get_center ( vvp ),
1238 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1239 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1241 vml->dl_tool_x = event->x, vml->dl_tool_y = event->y;
1248 if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) )
1252 vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
1253 if ( __map_types[vml->maptype].coord_to_mapcoord ( &coord,
1254 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1255 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1257 gchar *filename_buf = g_strdup_printf ( DIRSTRUCTURE,
1258 vml->cache_dir, __map_types[vml->maptype].uniq_id,
1259 mapcoord.scale, mapcoord.z, mapcoord.x, mapcoord.y );
1261 __map_types[vml->maptype].download ( &mapcoord, filename_buf );
1262 g_free ( filename_buf );
1263 vik_layer_emit_update ( VIK_LAYER(vml) );
1271 static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload )
1273 VikMapsLayer *vml = vml_vvp[0];
1274 VikViewport *vvp = vml_vvp[1];
1275 VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
1277 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1278 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1283 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1284 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1286 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1287 if ( vik_map_source_get_drawmode(map) == vp_drawmode &&
1288 vik_map_source_coord_to_mapcoord ( map, &ul, xzoom, yzoom, &ulm ) &&
1289 vik_map_source_coord_to_mapcoord ( map, &br, xzoom, yzoom, &brm ) )
1290 start_download_thread ( vml, vvp, &ul, &br, redownload );
1291 else if (vik_map_source_get_drawmode(map) != vp_drawmode) {
1292 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, vik_map_source_get_drawmode(map));
1293 gchar *err = g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name));
1294 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1298 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Wrong zoom level for this map.") );
1302 static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] )
1304 download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
1307 static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] )
1309 download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW);
1312 static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
1314 download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
1317 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp )
1319 static gpointer pass_along[2];
1321 pass_along[0] = vml;
1322 pass_along[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) );
1324 item = gtk_menu_item_new();
1325 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
1326 gtk_widget_show ( item );
1328 item = gtk_menu_item_new_with_mnemonic ( _("Download _Missing Onscreen Maps") );
1329 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along );
1330 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1331 gtk_widget_show ( item );
1333 if ( vik_map_source_supports_download_only_new (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) {
1334 item = gtk_menu_item_new_with_mnemonic ( _("Download _New Onscreen Maps") );
1335 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along );
1336 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1337 gtk_widget_show ( item );
1340 /* TODO Add GTK_STOCK_REFRESH icon */
1341 item = gtk_menu_item_new_with_mnemonic ( _("Reload _All Onscreen Maps") );
1342 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
1343 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1344 gtk_widget_show ( item );