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' )
378 vml->cache_dir = g_strdup ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir")->s );
382 if ( dir[len-1] != G_DIR_SEPARATOR )
384 vml->cache_dir = g_malloc ( len+2 );
385 strncpy ( vml->cache_dir, dir, len );
386 vml->cache_dir[len] = G_DIR_SEPARATOR;
387 vml->cache_dir[len+1] = '\0';
390 vml->cache_dir = g_strdup ( dir );
392 maps_layer_mkdir_if_default_dir ( vml );
395 /****************************************/
396 /******** GOBJECT STUFF *****************/
397 /****************************************/
399 GType vik_maps_layer_get_type ()
401 static GType vml_type = 0;
405 static const GTypeInfo vml_info =
407 sizeof (VikMapsLayerClass),
408 NULL, /* base_init */
409 NULL, /* base_finalize */
410 NULL, /* class init */
411 NULL, /* class_finalize */
412 NULL, /* class_data */
413 sizeof (VikMapsLayer),
415 NULL /* instance init */
417 vml_type = g_type_register_static ( VIK_LAYER_TYPE, "VikMapsLayer", &vml_info, 0 );
423 /****************************************/
424 /************** PARAMETERS **************/
425 /****************************************/
427 static guint map_index_to_uniq_id (guint8 index)
429 g_assert ( index < NUM_MAP_TYPES );
430 return vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(index));
433 static guint map_uniq_id_to_index ( guint uniq_id )
436 for ( i = 0; i < NUM_MAP_TYPES; i++ )
437 if ( vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(i)) == uniq_id )
439 return NUM_MAP_TYPES; /* no such thing */
442 static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation )
446 case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break;
447 case PARAM_MAPTYPE: {
448 gint maptype = map_uniq_id_to_index(data.u);
449 if ( maptype == NUM_MAP_TYPES ) g_warning(_("Unknown map type"));
450 else vml->maptype = maptype;
453 case PARAM_ALPHA: if ( data.u <= 255 ) vml->alpha = data.u; break;
454 case PARAM_AUTODOWNLOAD: vml->autodownload = data.b; break;
455 case PARAM_MAPZOOM: if ( data.u < NUM_MAPZOOMS ) {
456 vml->mapzoom_id = data.u;
457 vml->xmapzoom = __mapzooms_x [data.u];
458 vml->ymapzoom = __mapzooms_y [data.u];
459 }else g_warning (_("Unknown Map Zoom")); break;
464 static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation )
466 VikLayerParamData rv;
469 case PARAM_CACHE_DIR: rv.s = vml->cache_dir ? vml->cache_dir : ""; break;
470 case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break;
471 case PARAM_ALPHA: rv.u = vml->alpha; break;
472 case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break;
473 case PARAM_MAPZOOM: rv.u = vml->mapzoom_id; break;
478 /****************************************/
479 /****** CREATING, COPYING, FREEING ******/
480 /****************************************/
482 static VikMapsLayer *maps_layer_new ( VikViewport *vvp )
485 VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) );
486 vik_layer_init ( VIK_LAYER(vml), VIK_LAYER_MAPS );
487 idx = map_uniq_id_to_index(13); /* 13 is id for OSM Mapnik maps */
488 vml->maptype = (idx < NUM_MAP_TYPES) ? idx : 0;
491 vml->dl_tool_x = vml->dl_tool_y = -1;
492 maps_layer_set_cache_dir ( vml, NULL );
493 vml->autodownload = FALSE;
494 vml->last_center = NULL;
495 vml->last_xmpp = 0.0;
496 vml->last_ympp = 0.0;
498 vml->dl_right_click_menu = NULL;
503 static void maps_layer_free ( VikMapsLayer *vml )
505 g_free ( vml->cache_dir );
506 vml->cache_dir = NULL;
507 if ( vml->dl_right_click_menu )
508 gtk_object_sink ( GTK_OBJECT(vml->dl_right_click_menu) );
509 g_free(vml->last_center);
510 vml->last_center = NULL;
513 static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file)
515 if (from_file != TRUE)
517 /* If this method is not called in file reading context
518 * it is called in GUI context.
519 * So, we can check if we have to inform the user about inconsistency */
520 VikViewportDrawMode vp_drawmode;
521 VikMapsLayer *vml = VIK_MAPS_LAYER(vl);
522 VikMapSource *map = NULL;
524 vp_drawmode = vik_viewport_get_drawmode ( VIK_VIEWPORT(vp) );
525 map = MAPS_LAYER_NTH_TYPE(vml->maptype);
526 if (vik_map_source_get_drawmode(map) != vp_drawmode) {
527 const gchar *drawmode_name = vik_viewport_get_drawmode_name (VIK_VIEWPORT(vp), vik_map_source_get_drawmode(map));
528 gchar *msg = g_strdup_printf(_("New map cannot be displayed in the current drawmode.\nSelect \"%s\" from View menu to view it."), drawmode_name);
529 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp), msg );
535 static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len )
537 vik_layer_marshall_params ( VIK_LAYER(vml), data, len );
540 static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
542 VikMapsLayer *rv = maps_layer_new ( vvp );
543 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
547 /*********************/
548 /****** DRAWING ******/
549 /*********************/
551 static GdkPixbuf *pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha )
554 gint width, height, iii, jjj;
556 if ( ! gdk_pixbuf_get_has_alpha ( pixbuf ) )
558 GdkPixbuf *tmp = gdk_pixbuf_add_alpha(pixbuf,FALSE,0,0,0);
559 g_object_unref(G_OBJECT(pixbuf));
563 pixels = gdk_pixbuf_get_pixels(pixbuf);
564 width = gdk_pixbuf_get_width(pixbuf);
565 height = gdk_pixbuf_get_height(pixbuf);
567 /* r,g,b,a,r,g,b,a.... */
568 for (iii = 0; iii < width; iii++) for (jjj = 0; jjj < height; jjj++)
576 static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdouble yshrinkfactor )
579 guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf);
580 tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_NEAREST);
581 g_object_unref ( G_OBJECT(pixbuf) );
585 static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, gchar *filename_buf, gint buf_len, gdouble xshrinkfactor, gdouble yshrinkfactor )
590 pixbuf = a_mapcache_get ( mapcoord->x, mapcoord->y, mapcoord->z,
591 mode, mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
594 g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE,
595 vml->cache_dir, mode,
596 mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y );
597 if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
600 pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx );
602 /* free the pixbuf on error */
605 if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE )
606 g_warning ( _("Couldn't open image file: %s"), gx->message );
610 g_object_unref ( G_OBJECT(pixbuf) );
613 if ( vml->alpha < 255 )
614 pixbuf = pixbuf_set_alpha ( pixbuf, vml->alpha );
615 if ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 )
616 pixbuf = pixbuf_shrink ( pixbuf, xshrinkfactor, yshrinkfactor );
618 a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y,
619 mapcoord->z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(vml->maptype)),
620 mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
627 gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp)
629 const VikCoord *center = vik_viewport_get_center ( vvp );
631 if (vml->last_center == NULL) {
632 VikCoord *new_center = g_malloc(sizeof(VikCoord));
633 *new_center = *center;
634 vml->last_center = new_center;
635 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
636 vml->last_ympp = vik_viewport_get_ympp(vvp);
640 /* TODO: perhaps vik_coord_diff() */
641 if (vik_coord_equals(vml->last_center, center)
642 && (vml->last_xmpp == vik_viewport_get_xmpp(vvp))
643 && (vml->last_ympp == vik_viewport_get_ympp(vvp)))
646 *(vml->last_center) = *center;
647 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
648 vml->last_ympp = vik_viewport_get_ympp(vvp);
652 static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br )
655 gdouble xzoom = vik_viewport_get_xmpp ( vvp );
656 gdouble yzoom = vik_viewport_get_ympp ( vvp );
657 gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0;
658 gdouble existence_only = FALSE;
660 if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) {
661 xshrinkfactor = vml->xmapzoom / xzoom;
662 yshrinkfactor = vml->ymapzoom / yzoom;
663 xzoom = vml->xmapzoom;
664 yzoom = vml->xmapzoom;
665 if ( ! (xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR &&
666 yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) ) {
667 if ( xshrinkfactor > REAL_MIN_SHRINKFACTOR && yshrinkfactor > REAL_MIN_SHRINKFACTOR )
668 existence_only = TRUE;
670 g_warning ( _("Cowardly refusing to draw tiles or existence of tiles beyond %d zoom out factor"), (int)( 1.0/REAL_MIN_SHRINKFACTOR));
677 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
678 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm ) &&
679 vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) ) {
683 gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x);
684 gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y);
685 gint mode = vik_map_source_get_uniq_id(map);
688 gint xx, yy, width, height;
691 guint max_path_len = strlen(vml->cache_dir) + 40;
692 gchar *path_buf = g_malloc ( max_path_len * sizeof(char) );
694 if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) {
696 fputs(stderr, "DEBUG: Starting autodownload\n");
698 if ( vik_map_source_supports_if_modified_since (map) )
699 // Try to download newer tiles
700 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
702 // Download only missing tiles
703 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
706 if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) {
707 for ( x = xmin; x <= xmax; x++ ) {
708 for ( y = ymin; y <= ymax; y++ ) {
711 pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
713 width = gdk_pixbuf_get_width ( pixbuf );
714 height = gdk_pixbuf_get_height ( pixbuf );
716 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
717 vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy );
721 vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height );
725 } else { /* tilesize is known, don't have to keep converting coords */
726 gdouble tilesize_x = vik_map_source_get_tilesize_x(map) * xshrinkfactor;
727 gdouble tilesize_y = vik_map_source_get_tilesize_y(map) * yshrinkfactor;
728 /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
729 gint tilesize_x_ceil = ceil ( tilesize_x );
730 gint tilesize_y_ceil = ceil ( tilesize_y );
731 gint8 xinc = (ulm.x == xmin) ? 1 : -1;
732 gint8 yinc = (ulm.y == ymin) ? 1 : -1;
733 gdouble xx, yy; gint xx_tmp, yy_tmp;
734 gint base_yy, xend, yend;
736 GdkGC *black_gc = GTK_WIDGET(vvp)->style->black_gc;
738 xend = (xinc == 1) ? (xmax+1) : (xmin-1);
739 yend = (yinc == 1) ? (ymax+1) : (ymin-1);
741 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
742 vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp );
743 xx = xx_tmp; yy = yy_tmp;
744 /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
745 * eg if tile size 128, shrinkfactor 0.333 */
746 xx -= (tilesize_x/2);
747 base_yy = yy - (tilesize_y/2);
749 for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) {
751 for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) {
755 if ( existence_only ) {
756 g_snprintf ( path_buf, max_path_len, DIRSTRUCTURE,
757 vml->cache_dir, mode,
758 ulm.scale, ulm.z, ulm.x, ulm.y );
759 if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) {
760 vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil );
764 for (scale_inc = 0; scale_inc < 4; scale_inc ++) {
765 /* try with correct then smaller zooms */
766 int scale_factor = 1 << scale_inc; /* 2^scale_inc */
768 ulm2.x = ulm.x / scale_factor;
769 ulm2.y = ulm.y / scale_factor;
770 ulm2.scale = ulm.scale + scale_inc;
771 pixbuf = get_pixbuf ( vml, mode, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor );
773 gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil;
774 gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil;
776 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);
778 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
783 /* retry with bigger zooms */
785 for (scale_dec = 1; scale_dec < 2; scale_dec ++) {
787 int scale_factor = 1 << scale_dec; /* 2^scale_dec */
789 ulm2.x = ulm.x * scale_factor;
790 ulm2.y = ulm.y * scale_factor;
791 ulm2.scale = ulm.scale - scale_dec;
792 for (pict_x = 0; pict_x < scale_factor; pict_x ++) {
793 for (pict_y = 0; pict_y < scale_factor; pict_y ++) {
794 MapCoord ulm3 = ulm2;
797 pixbuf = get_pixbuf ( vml, mode, &ulm3, path_buf, max_path_len, xshrinkfactor / scale_factor, yshrinkfactor / scale_factor );
801 gint dest_x = xx + pict_x * (tilesize_x_ceil / scale_factor);
802 gint dest_y = yy + pict_y * (tilesize_y_ceil / scale_factor);
803 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, dest_x, dest_y, tilesize_x_ceil / scale_factor, tilesize_y_ceil / scale_factor );
821 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp )
823 if ( vik_map_source_get_drawmode(MAPS_LAYER_NTH_TYPE(vml->maptype)) == vik_viewport_get_drawmode ( vvp ) )
827 /* get corner coords */
828 if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) {
829 /* UTM multi-zone stuff by Kit Transue */
830 gchar leftmost_zone, rightmost_zone, i;
831 leftmost_zone = vik_viewport_leftmost_zone( vvp );
832 rightmost_zone = vik_viewport_rightmost_zone( vvp );
833 for ( i = leftmost_zone; i <= rightmost_zone; ++i ) {
834 vik_viewport_corners_for_zonen ( vvp, i, &ul, &br );
835 maps_layer_draw_section ( vml, vvp, &ul, &br );
839 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
840 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
842 maps_layer_draw_section ( vml, vvp, &ul, &br );
847 /*************************/
848 /****** DOWNLOADING ******/
849 /*************************/
851 /* pass along data to thread, exists even if layer is deleted. */
861 gboolean refresh_display;
864 gboolean map_layer_alive;
868 static void mdi_free ( MapDownloadInfo *mdi )
870 g_mutex_free(mdi->mutex);
871 g_free ( mdi->cache_dir );
872 mdi->cache_dir = NULL;
873 g_free ( mdi->filename_buf );
874 mdi->filename_buf = NULL;
878 static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
880 MapDownloadInfo *mdi = ptr;
881 g_mutex_lock(mdi->mutex);
882 mdi->map_layer_alive = FALSE;
883 g_mutex_unlock(mdi->mutex);
886 static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
888 void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype));
891 for ( x = mdi->x0; x <= mdi->xf; x++ )
893 for ( y = mdi->y0; y <= mdi->yf; y++ )
895 gboolean remove_mem_cache = FALSE;
896 gboolean need_download = FALSE;
897 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
898 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
899 mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
902 int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
904 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
908 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
909 need_download = TRUE;
910 remove_mem_cache = TRUE;
912 } else { /* in case map file already exists */
913 switch (mdi->redownload) {
914 case REDOWNLOAD_NONE:
919 /* see if this one is bad or what */
921 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
922 if (gx || (!pixbuf)) {
923 g_remove ( mdi->filename_buf );
924 need_download = TRUE;
925 remove_mem_cache = TRUE;
929 g_object_unref ( pixbuf );
935 need_download = TRUE;
936 remove_mem_cache = TRUE;
940 /* FIXME: need a better way than to erase file in case of server/network problem */
941 g_remove ( mdi->filename_buf );
942 need_download = TRUE;
943 remove_mem_cache = TRUE;
946 case DOWNLOAD_OR_REFRESH:
947 remove_mem_cache = TRUE;
951 g_warning ( "redownload state %d unknown\n", mdi->redownload);
955 mdi->mapcoord.x = x; mdi->mapcoord.y = y;
958 if ( vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle))
963 g_mutex_lock(mdi->mutex);
964 if (remove_mem_cache)
965 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 );
966 if (mdi->refresh_display && mdi->map_layer_alive) {
967 /* TODO: check if it's on visible area */
968 vik_layer_emit_update ( VIK_LAYER(mdi->vml) );
970 g_mutex_unlock(mdi->mutex);
972 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
976 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
977 g_mutex_lock(mdi->mutex);
978 if (mdi->map_layer_alive)
979 g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
980 g_mutex_unlock(mdi->mutex);
984 static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
986 if ( mdi->mapcoord.x || mdi->mapcoord.y )
988 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
989 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
990 mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y );
991 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
993 g_remove ( mdi->filename_buf );
998 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload )
1000 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1001 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1003 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1004 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm )
1005 && vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) )
1007 MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
1012 mdi->map_layer_alive = TRUE;
1013 mdi->mutex = g_mutex_new();
1014 mdi->refresh_display = TRUE;
1016 /* cache_dir and buffer for dest filename */
1017 mdi->cache_dir = g_strdup ( vml->cache_dir );
1018 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1019 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1020 mdi->maptype = vml->maptype;
1022 mdi->mapcoord = ulm;
1024 mdi->redownload = redownload;
1026 mdi->x0 = MIN(ulm.x, brm.x);
1027 mdi->xf = MAX(ulm.x, brm.x);
1028 mdi->y0 = MIN(ulm.y, brm.y);
1029 mdi->yf = MAX(ulm.y, brm.y);
1033 if ( mdi->redownload ) {
1034 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
1036 /* calculate how many we need */
1037 for ( a = mdi->x0; a <= mdi->xf; a++ )
1039 for ( b = mdi->y0; b <= mdi->yf; b++ )
1041 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
1042 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
1044 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1050 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1052 if ( mdi->mapstoget )
1054 const gchar *tmp_str;
1059 if (redownload == REDOWNLOAD_BAD)
1060 tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget);
1062 tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget);
1066 tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget);
1068 tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype));
1070 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1071 /* launch the thread */
1072 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1073 tmp, /* description string */
1074 (vik_thr_func) map_download_thread, /* function to call within thread */
1075 mdi, /* pass along data */
1076 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1077 (vik_thr_free_func) mdi_cancel_cleanup,
1086 void maps_layer_download_section_without_redraw( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom)
1089 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1091 if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm)
1092 || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) {
1093 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
1097 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
1102 mdi->map_layer_alive = TRUE;
1103 mdi->mutex = g_mutex_new();
1104 mdi->refresh_display = FALSE;
1106 mdi->cache_dir = g_strdup ( vml->cache_dir );
1107 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1108 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1109 mdi->maptype = vml->maptype;
1111 mdi->mapcoord = ulm;
1113 mdi->redownload = REDOWNLOAD_NONE;
1115 mdi->x0 = MIN(ulm.x, brm.x);
1116 mdi->xf = MAX(ulm.x, brm.x);
1117 mdi->y0 = MIN(ulm.y, brm.y);
1118 mdi->yf = MAX(ulm.y, brm.y);
1122 for (i = mdi->x0; i <= mdi->xf; i++) {
1123 for (j = mdi->y0; j <= mdi->yf; j++) {
1124 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
1125 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
1127 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1132 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1134 if (mdi->mapstoget) {
1137 fmt = ngettext("Downloading %d %s map...",
1138 "Downloading %d %s maps...",
1140 tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) );
1142 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1143 /* launch the thread */
1144 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1145 tmp, /* description string */
1146 (vik_thr_func) map_download_thread, /* function to call within thread */
1147 mdi, /* pass along data */
1148 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1149 (vik_thr_free_func) mdi_cancel_cleanup,
1157 static void maps_layer_redownload_bad ( VikMapsLayer *vml )
1159 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
1162 static void maps_layer_redownload_all ( VikMapsLayer *vml )
1164 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
1167 static void maps_layer_redownload_new ( VikMapsLayer *vml )
1169 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
1172 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1174 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1176 if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 )
1178 if ( event->button == 1 )
1181 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 );
1182 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 );
1183 start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
1184 vml->dl_tool_x = vml->dl_tool_y = -1;
1189 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) );
1190 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) );
1192 vml->redownload_vvp = vvp;
1194 vml->dl_tool_x = vml->dl_tool_y = -1;
1196 if ( ! vml->dl_right_click_menu ) {
1198 vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () );
1200 item = gtk_menu_item_new_with_label ( _("Redownload bad map(s)") );
1201 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
1202 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1204 item = gtk_menu_item_new_with_label ( _("Redownload new map(s)") );
1205 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
1206 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1208 item = gtk_menu_item_new_with_label ( _("Redownload all map(s)") );
1209 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
1210 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1213 gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
1214 gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) );
1220 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1225 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1228 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1230 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1231 if ( vik_map_source_get_drawmode(map) == vik_viewport_get_drawmode ( vvp ) &&
1232 vik_map_source_coord_to_mapcoord ( map, vik_viewport_get_center ( vvp ),
1233 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1234 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1236 vml->dl_tool_x = event->x, vml->dl_tool_y = event->y;
1243 if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) )
1247 vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
1248 if ( __map_types[vml->maptype].coord_to_mapcoord ( &coord,
1249 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1250 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1252 gchar *filename_buf = g_strdup_printf ( DIRSTRUCTURE,
1253 vml->cache_dir, __map_types[vml->maptype].uniq_id,
1254 mapcoord.scale, mapcoord.z, mapcoord.x, mapcoord.y );
1256 __map_types[vml->maptype].download ( &mapcoord, filename_buf );
1257 g_free ( filename_buf );
1258 vik_layer_emit_update ( VIK_LAYER(vml) );
1266 static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload )
1268 VikMapsLayer *vml = vml_vvp[0];
1269 VikViewport *vvp = vml_vvp[1];
1270 VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
1272 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1273 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1278 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1279 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1281 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1282 if ( vik_map_source_get_drawmode(map) == vp_drawmode &&
1283 vik_map_source_coord_to_mapcoord ( map, &ul, xzoom, yzoom, &ulm ) &&
1284 vik_map_source_coord_to_mapcoord ( map, &br, xzoom, yzoom, &brm ) )
1285 start_download_thread ( vml, vvp, &ul, &br, redownload );
1286 else if (vik_map_source_get_drawmode(map) != vp_drawmode) {
1287 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, vik_map_source_get_drawmode(map));
1288 gchar *err = g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name));
1289 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1293 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Wrong zoom level for this map.") );
1297 static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] )
1299 download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
1302 static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] )
1304 download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW);
1307 static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
1309 download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
1312 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp )
1314 static gpointer pass_along[2];
1316 pass_along[0] = vml;
1317 pass_along[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) );
1319 item = gtk_menu_item_new();
1320 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
1321 gtk_widget_show ( item );
1323 item = gtk_menu_item_new_with_label ( _("Download missing Onscreen Maps") );
1324 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along );
1325 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1326 gtk_widget_show ( item );
1328 if ( vik_map_source_supports_if_modified_since (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) {
1329 item = gtk_menu_item_new_with_label ( _("Download new Onscreen Maps") );
1330 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along );
1331 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1332 gtk_widget_show ( item );
1335 /* TODO Add GTK_STOCK_REFRESH icon */
1336 item = gtk_menu_item_new_with_label ( _("Reload all Onscreen Maps") );
1337 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
1338 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1339 gtk_widget_show ( item );