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)) {
695 g_debug("%s: Starting autodownload", __FUNCTION__);
696 if ( vik_map_source_supports_if_modified_since (map) )
697 // Try to download newer tiles
698 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
700 // Download only missing tiles
701 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
704 if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) {
705 for ( x = xmin; x <= xmax; x++ ) {
706 for ( y = ymin; y <= ymax; y++ ) {
709 pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
711 width = gdk_pixbuf_get_width ( pixbuf );
712 height = gdk_pixbuf_get_height ( pixbuf );
714 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
715 vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy );
719 vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height );
723 } else { /* tilesize is known, don't have to keep converting coords */
724 gdouble tilesize_x = vik_map_source_get_tilesize_x(map) * xshrinkfactor;
725 gdouble tilesize_y = vik_map_source_get_tilesize_y(map) * yshrinkfactor;
726 /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
727 gint tilesize_x_ceil = ceil ( tilesize_x );
728 gint tilesize_y_ceil = ceil ( tilesize_y );
729 gint8 xinc = (ulm.x == xmin) ? 1 : -1;
730 gint8 yinc = (ulm.y == ymin) ? 1 : -1;
731 gdouble xx, yy; gint xx_tmp, yy_tmp;
732 gint base_yy, xend, yend;
734 GdkGC *black_gc = GTK_WIDGET(vvp)->style->black_gc;
736 xend = (xinc == 1) ? (xmax+1) : (xmin-1);
737 yend = (yinc == 1) ? (ymax+1) : (ymin-1);
739 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
740 vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp );
741 xx = xx_tmp; yy = yy_tmp;
742 /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
743 * eg if tile size 128, shrinkfactor 0.333 */
744 xx -= (tilesize_x/2);
745 base_yy = yy - (tilesize_y/2);
747 for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) {
749 for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) {
753 if ( existence_only ) {
754 g_snprintf ( path_buf, max_path_len, DIRSTRUCTURE,
755 vml->cache_dir, mode,
756 ulm.scale, ulm.z, ulm.x, ulm.y );
757 if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) {
758 vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil );
762 for (scale_inc = 0; scale_inc < 4; scale_inc ++) {
763 /* try with correct then smaller zooms */
764 int scale_factor = 1 << scale_inc; /* 2^scale_inc */
766 ulm2.x = ulm.x / scale_factor;
767 ulm2.y = ulm.y / scale_factor;
768 ulm2.scale = ulm.scale + scale_inc;
769 pixbuf = get_pixbuf ( vml, mode, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor );
771 gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil;
772 gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil;
774 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);
776 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
781 /* retry with bigger zooms */
783 for (scale_dec = 1; scale_dec < 2; scale_dec ++) {
785 int scale_factor = 1 << scale_dec; /* 2^scale_dec */
787 ulm2.x = ulm.x * scale_factor;
788 ulm2.y = ulm.y * scale_factor;
789 ulm2.scale = ulm.scale - scale_dec;
790 for (pict_x = 0; pict_x < scale_factor; pict_x ++) {
791 for (pict_y = 0; pict_y < scale_factor; pict_y ++) {
792 MapCoord ulm3 = ulm2;
795 pixbuf = get_pixbuf ( vml, mode, &ulm3, path_buf, max_path_len, xshrinkfactor / scale_factor, yshrinkfactor / scale_factor );
799 gint dest_x = xx + pict_x * (tilesize_x_ceil / scale_factor);
800 gint dest_y = yy + pict_y * (tilesize_y_ceil / scale_factor);
801 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, dest_x, dest_y, tilesize_x_ceil / scale_factor, tilesize_y_ceil / scale_factor );
819 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp )
821 if ( vik_map_source_get_drawmode(MAPS_LAYER_NTH_TYPE(vml->maptype)) == vik_viewport_get_drawmode ( vvp ) )
825 /* get corner coords */
826 if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) {
827 /* UTM multi-zone stuff by Kit Transue */
828 gchar leftmost_zone, rightmost_zone, i;
829 leftmost_zone = vik_viewport_leftmost_zone( vvp );
830 rightmost_zone = vik_viewport_rightmost_zone( vvp );
831 for ( i = leftmost_zone; i <= rightmost_zone; ++i ) {
832 vik_viewport_corners_for_zonen ( vvp, i, &ul, &br );
833 maps_layer_draw_section ( vml, vvp, &ul, &br );
837 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
838 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
840 maps_layer_draw_section ( vml, vvp, &ul, &br );
845 /*************************/
846 /****** DOWNLOADING ******/
847 /*************************/
849 /* pass along data to thread, exists even if layer is deleted. */
859 gboolean refresh_display;
862 gboolean map_layer_alive;
866 static void mdi_free ( MapDownloadInfo *mdi )
868 g_mutex_free(mdi->mutex);
869 g_free ( mdi->cache_dir );
870 mdi->cache_dir = NULL;
871 g_free ( mdi->filename_buf );
872 mdi->filename_buf = NULL;
876 static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
878 MapDownloadInfo *mdi = ptr;
879 g_mutex_lock(mdi->mutex);
880 mdi->map_layer_alive = FALSE;
881 g_mutex_unlock(mdi->mutex);
884 static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
886 void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype));
889 for ( x = mdi->x0; x <= mdi->xf; x++ )
891 for ( y = mdi->y0; y <= mdi->yf; y++ )
893 gboolean remove_mem_cache = FALSE;
894 gboolean need_download = FALSE;
895 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
896 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
897 mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
900 int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
902 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
906 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
907 need_download = TRUE;
908 remove_mem_cache = TRUE;
910 } else { /* in case map file already exists */
911 switch (mdi->redownload) {
912 case REDOWNLOAD_NONE:
917 /* see if this one is bad or what */
919 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
920 if (gx || (!pixbuf)) {
921 g_remove ( mdi->filename_buf );
922 need_download = TRUE;
923 remove_mem_cache = TRUE;
927 g_object_unref ( pixbuf );
933 need_download = TRUE;
934 remove_mem_cache = TRUE;
938 /* FIXME: need a better way than to erase file in case of server/network problem */
939 g_remove ( mdi->filename_buf );
940 need_download = TRUE;
941 remove_mem_cache = TRUE;
944 case DOWNLOAD_OR_REFRESH:
945 remove_mem_cache = TRUE;
949 g_warning ( "redownload state %d unknown\n", mdi->redownload);
953 mdi->mapcoord.x = x; mdi->mapcoord.y = y;
956 if ( vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle))
961 g_mutex_lock(mdi->mutex);
962 if (remove_mem_cache)
963 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 );
964 if (mdi->refresh_display && mdi->map_layer_alive) {
965 /* TODO: check if it's on visible area */
966 vik_layer_emit_update ( VIK_LAYER(mdi->vml) );
968 g_mutex_unlock(mdi->mutex);
970 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
974 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
975 g_mutex_lock(mdi->mutex);
976 if (mdi->map_layer_alive)
977 g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
978 g_mutex_unlock(mdi->mutex);
982 static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
984 if ( mdi->mapcoord.x || mdi->mapcoord.y )
986 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
987 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
988 mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y );
989 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
991 g_remove ( mdi->filename_buf );
996 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload )
998 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
999 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1001 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1002 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm )
1003 && vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) )
1005 MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
1010 mdi->map_layer_alive = TRUE;
1011 mdi->mutex = g_mutex_new();
1012 mdi->refresh_display = TRUE;
1014 /* cache_dir and buffer for dest filename */
1015 mdi->cache_dir = g_strdup ( vml->cache_dir );
1016 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1017 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1018 mdi->maptype = vml->maptype;
1020 mdi->mapcoord = ulm;
1022 mdi->redownload = redownload;
1024 mdi->x0 = MIN(ulm.x, brm.x);
1025 mdi->xf = MAX(ulm.x, brm.x);
1026 mdi->y0 = MIN(ulm.y, brm.y);
1027 mdi->yf = MAX(ulm.y, brm.y);
1031 if ( mdi->redownload ) {
1032 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
1034 /* calculate how many we need */
1035 for ( a = mdi->x0; a <= mdi->xf; a++ )
1037 for ( b = mdi->y0; b <= mdi->yf; b++ )
1039 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
1040 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
1042 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1048 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1050 if ( mdi->mapstoget )
1052 const gchar *tmp_str;
1057 if (redownload == REDOWNLOAD_BAD)
1058 tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget);
1060 tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget);
1064 tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget);
1066 tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype));
1068 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1069 /* launch the thread */
1070 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1071 tmp, /* description string */
1072 (vik_thr_func) map_download_thread, /* function to call within thread */
1073 mdi, /* pass along data */
1074 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1075 (vik_thr_free_func) mdi_cancel_cleanup,
1084 void maps_layer_download_section_without_redraw( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom)
1087 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1089 if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm)
1090 || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) {
1091 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
1095 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
1100 mdi->map_layer_alive = TRUE;
1101 mdi->mutex = g_mutex_new();
1102 mdi->refresh_display = FALSE;
1104 mdi->cache_dir = g_strdup ( vml->cache_dir );
1105 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1106 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1107 mdi->maptype = vml->maptype;
1109 mdi->mapcoord = ulm;
1111 mdi->redownload = REDOWNLOAD_NONE;
1113 mdi->x0 = MIN(ulm.x, brm.x);
1114 mdi->xf = MAX(ulm.x, brm.x);
1115 mdi->y0 = MIN(ulm.y, brm.y);
1116 mdi->yf = MAX(ulm.y, brm.y);
1120 for (i = mdi->x0; i <= mdi->xf; i++) {
1121 for (j = mdi->y0; j <= mdi->yf; j++) {
1122 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
1123 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
1125 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1130 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1132 if (mdi->mapstoget) {
1135 fmt = ngettext("Downloading %d %s map...",
1136 "Downloading %d %s maps...",
1138 tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) );
1140 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1141 /* launch the thread */
1142 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1143 tmp, /* description string */
1144 (vik_thr_func) map_download_thread, /* function to call within thread */
1145 mdi, /* pass along data */
1146 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1147 (vik_thr_free_func) mdi_cancel_cleanup,
1155 static void maps_layer_redownload_bad ( VikMapsLayer *vml )
1157 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
1160 static void maps_layer_redownload_all ( VikMapsLayer *vml )
1162 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
1165 static void maps_layer_redownload_new ( VikMapsLayer *vml )
1167 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
1170 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1172 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1174 if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 )
1176 if ( event->button == 1 )
1179 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 );
1180 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 );
1181 start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
1182 vml->dl_tool_x = vml->dl_tool_y = -1;
1187 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) );
1188 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) );
1190 vml->redownload_vvp = vvp;
1192 vml->dl_tool_x = vml->dl_tool_y = -1;
1194 if ( ! vml->dl_right_click_menu ) {
1196 vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () );
1198 item = gtk_menu_item_new_with_label ( _("Redownload bad map(s)") );
1199 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
1200 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1202 item = gtk_menu_item_new_with_label ( _("Redownload new map(s)") );
1203 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
1204 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1206 item = gtk_menu_item_new_with_label ( _("Redownload all map(s)") );
1207 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
1208 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1211 gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
1212 gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) );
1218 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1223 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1226 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1228 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1229 if ( vik_map_source_get_drawmode(map) == vik_viewport_get_drawmode ( vvp ) &&
1230 vik_map_source_coord_to_mapcoord ( map, vik_viewport_get_center ( vvp ),
1231 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1232 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1234 vml->dl_tool_x = event->x, vml->dl_tool_y = event->y;
1241 if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) )
1245 vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
1246 if ( __map_types[vml->maptype].coord_to_mapcoord ( &coord,
1247 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1248 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1250 gchar *filename_buf = g_strdup_printf ( DIRSTRUCTURE,
1251 vml->cache_dir, __map_types[vml->maptype].uniq_id,
1252 mapcoord.scale, mapcoord.z, mapcoord.x, mapcoord.y );
1254 __map_types[vml->maptype].download ( &mapcoord, filename_buf );
1255 g_free ( filename_buf );
1256 vik_layer_emit_update ( VIK_LAYER(vml) );
1264 static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload )
1266 VikMapsLayer *vml = vml_vvp[0];
1267 VikViewport *vvp = vml_vvp[1];
1268 VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
1270 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1271 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1276 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1277 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1279 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1280 if ( vik_map_source_get_drawmode(map) == vp_drawmode &&
1281 vik_map_source_coord_to_mapcoord ( map, &ul, xzoom, yzoom, &ulm ) &&
1282 vik_map_source_coord_to_mapcoord ( map, &br, xzoom, yzoom, &brm ) )
1283 start_download_thread ( vml, vvp, &ul, &br, redownload );
1284 else if (vik_map_source_get_drawmode(map) != vp_drawmode) {
1285 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, vik_map_source_get_drawmode(map));
1286 gchar *err = g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name));
1287 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1291 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Wrong zoom level for this map.") );
1295 static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] )
1297 download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
1300 static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] )
1302 download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW);
1305 static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
1307 download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
1310 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp )
1312 static gpointer pass_along[2];
1314 pass_along[0] = vml;
1315 pass_along[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) );
1317 item = gtk_menu_item_new();
1318 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
1319 gtk_widget_show ( item );
1321 item = gtk_menu_item_new_with_label ( _("Download missing Onscreen Maps") );
1322 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along );
1323 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1324 gtk_widget_show ( item );
1326 if ( vik_map_source_supports_if_modified_since (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) {
1327 item = gtk_menu_item_new_with_label ( _("Download new Onscreen Maps") );
1328 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along );
1329 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1330 gtk_widget_show ( item );
1333 /* TODO Add GTK_STOCK_REFRESH icon */
1334 item = gtk_menu_item_new_with_label ( _("Reload all Onscreen Maps") );
1335 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
1336 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1337 gtk_widget_show ( item );