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 (!vik_window_get_pan_move (VIK_GTK_WINDOW_FROM_WIDGET(GTK_WIDGET(vvp))))
634 if (vml->last_center == NULL) {
635 VikCoord *new_center = g_malloc(sizeof(VikCoord));
636 *new_center = *center;
637 vml->last_center = new_center;
638 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
639 vml->last_ympp = vik_viewport_get_ympp(vvp);
643 /* TODO: perhaps vik_coord_diff() */
644 if (vik_coord_equals(vml->last_center, center)
645 && (vml->last_xmpp == vik_viewport_get_xmpp(vvp))
646 && (vml->last_ympp == vik_viewport_get_ympp(vvp)))
649 *(vml->last_center) = *center;
650 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
651 vml->last_ympp = vik_viewport_get_ympp(vvp);
655 static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br )
658 gdouble xzoom = vik_viewport_get_xmpp ( vvp );
659 gdouble yzoom = vik_viewport_get_ympp ( vvp );
660 gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0;
661 gdouble existence_only = FALSE;
663 if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) {
664 xshrinkfactor = vml->xmapzoom / xzoom;
665 yshrinkfactor = vml->ymapzoom / yzoom;
666 xzoom = vml->xmapzoom;
667 yzoom = vml->xmapzoom;
668 if ( ! (xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR &&
669 yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) ) {
670 if ( xshrinkfactor > REAL_MIN_SHRINKFACTOR && yshrinkfactor > REAL_MIN_SHRINKFACTOR )
671 existence_only = TRUE;
673 g_warning ( _("Cowardly refusing to draw tiles or existence of tiles beyond %d zoom out factor"), (int)( 1.0/REAL_MIN_SHRINKFACTOR));
680 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
681 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm ) &&
682 vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) ) {
686 gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x);
687 gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y);
688 gint mode = vik_map_source_get_uniq_id(map);
691 gint xx, yy, width, height;
694 guint max_path_len = strlen(vml->cache_dir) + 40;
695 gchar *path_buf = g_malloc ( max_path_len * sizeof(char) );
697 if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) {
698 g_debug("%s: Starting autodownload", __FUNCTION__);
699 if ( vik_map_source_supports_download_only_new (map) )
700 // Try to download newer tiles
701 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
703 // Download only missing tiles
704 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
707 if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) {
708 for ( x = xmin; x <= xmax; x++ ) {
709 for ( y = ymin; y <= ymax; y++ ) {
712 pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
714 width = gdk_pixbuf_get_width ( pixbuf );
715 height = gdk_pixbuf_get_height ( pixbuf );
717 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
718 vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy );
722 vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height );
726 } else { /* tilesize is known, don't have to keep converting coords */
727 gdouble tilesize_x = vik_map_source_get_tilesize_x(map) * xshrinkfactor;
728 gdouble tilesize_y = vik_map_source_get_tilesize_y(map) * yshrinkfactor;
729 /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
730 gint tilesize_x_ceil = ceil ( tilesize_x );
731 gint tilesize_y_ceil = ceil ( tilesize_y );
732 gint8 xinc = (ulm.x == xmin) ? 1 : -1;
733 gint8 yinc = (ulm.y == ymin) ? 1 : -1;
734 gdouble xx, yy; gint xx_tmp, yy_tmp;
735 gint base_yy, xend, yend;
737 GdkGC *black_gc = GTK_WIDGET(vvp)->style->black_gc;
739 xend = (xinc == 1) ? (xmax+1) : (xmin-1);
740 yend = (yinc == 1) ? (ymax+1) : (ymin-1);
742 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
743 vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp );
744 xx = xx_tmp; yy = yy_tmp;
745 /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
746 * eg if tile size 128, shrinkfactor 0.333 */
747 xx -= (tilesize_x/2);
748 base_yy = yy - (tilesize_y/2);
750 for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) {
752 for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) {
756 if ( existence_only ) {
757 g_snprintf ( path_buf, max_path_len, DIRSTRUCTURE,
758 vml->cache_dir, mode,
759 ulm.scale, ulm.z, ulm.x, ulm.y );
760 if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) {
761 vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil );
765 for (scale_inc = 0; scale_inc < 4; scale_inc ++) {
766 /* try with correct then smaller zooms */
767 int scale_factor = 1 << scale_inc; /* 2^scale_inc */
769 ulm2.x = ulm.x / scale_factor;
770 ulm2.y = ulm.y / scale_factor;
771 ulm2.scale = ulm.scale + scale_inc;
772 pixbuf = get_pixbuf ( vml, mode, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor );
774 gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil;
775 gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil;
777 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);
779 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
784 /* retry with bigger zooms */
786 for (scale_dec = 1; scale_dec < 2; scale_dec ++) {
788 int scale_factor = 1 << scale_dec; /* 2^scale_dec */
790 ulm2.x = ulm.x * scale_factor;
791 ulm2.y = ulm.y * scale_factor;
792 ulm2.scale = ulm.scale - scale_dec;
793 for (pict_x = 0; pict_x < scale_factor; pict_x ++) {
794 for (pict_y = 0; pict_y < scale_factor; pict_y ++) {
795 MapCoord ulm3 = ulm2;
798 pixbuf = get_pixbuf ( vml, mode, &ulm3, path_buf, max_path_len, xshrinkfactor / scale_factor, yshrinkfactor / scale_factor );
802 gint dest_x = xx + pict_x * (tilesize_x_ceil / scale_factor);
803 gint dest_y = yy + pict_y * (tilesize_y_ceil / scale_factor);
804 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, dest_x, dest_y, tilesize_x_ceil / scale_factor, tilesize_y_ceil / scale_factor );
822 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp )
824 if ( vik_map_source_get_drawmode(MAPS_LAYER_NTH_TYPE(vml->maptype)) == vik_viewport_get_drawmode ( vvp ) )
828 /* get corner coords */
829 if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) {
830 /* UTM multi-zone stuff by Kit Transue */
831 gchar leftmost_zone, rightmost_zone, i;
832 leftmost_zone = vik_viewport_leftmost_zone( vvp );
833 rightmost_zone = vik_viewport_rightmost_zone( vvp );
834 for ( i = leftmost_zone; i <= rightmost_zone; ++i ) {
835 vik_viewport_corners_for_zonen ( vvp, i, &ul, &br );
836 maps_layer_draw_section ( vml, vvp, &ul, &br );
840 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
841 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
843 maps_layer_draw_section ( vml, vvp, &ul, &br );
848 /*************************/
849 /****** DOWNLOADING ******/
850 /*************************/
852 /* pass along data to thread, exists even if layer is deleted. */
862 gboolean refresh_display;
865 gboolean map_layer_alive;
869 static void mdi_free ( MapDownloadInfo *mdi )
871 g_mutex_free(mdi->mutex);
872 g_free ( mdi->cache_dir );
873 mdi->cache_dir = NULL;
874 g_free ( mdi->filename_buf );
875 mdi->filename_buf = NULL;
879 static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
881 MapDownloadInfo *mdi = ptr;
882 g_mutex_lock(mdi->mutex);
883 mdi->map_layer_alive = FALSE;
884 g_mutex_unlock(mdi->mutex);
887 static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
889 void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype));
892 for ( x = mdi->x0; x <= mdi->xf; x++ )
894 for ( y = mdi->y0; y <= mdi->yf; y++ )
896 gboolean remove_mem_cache = FALSE;
897 gboolean need_download = FALSE;
898 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
899 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
900 mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
903 int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
905 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
909 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
910 need_download = TRUE;
911 remove_mem_cache = TRUE;
913 } else { /* in case map file already exists */
914 switch (mdi->redownload) {
915 case REDOWNLOAD_NONE:
920 /* see if this one is bad or what */
922 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
923 if (gx || (!pixbuf)) {
924 g_remove ( mdi->filename_buf );
925 need_download = TRUE;
926 remove_mem_cache = TRUE;
930 g_object_unref ( pixbuf );
936 need_download = TRUE;
937 remove_mem_cache = TRUE;
941 /* FIXME: need a better way than to erase file in case of server/network problem */
942 g_remove ( mdi->filename_buf );
943 need_download = TRUE;
944 remove_mem_cache = TRUE;
947 case DOWNLOAD_OR_REFRESH:
948 remove_mem_cache = TRUE;
952 g_warning ( "redownload state %d unknown\n", mdi->redownload);
956 mdi->mapcoord.x = x; mdi->mapcoord.y = y;
959 if ( vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle))
964 g_mutex_lock(mdi->mutex);
965 if (remove_mem_cache)
966 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 );
967 if (mdi->refresh_display && mdi->map_layer_alive) {
968 /* TODO: check if it's on visible area */
969 vik_layer_emit_update ( VIK_LAYER(mdi->vml) );
971 g_mutex_unlock(mdi->mutex);
973 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
977 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
978 g_mutex_lock(mdi->mutex);
979 if (mdi->map_layer_alive)
980 g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
981 g_mutex_unlock(mdi->mutex);
985 static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
987 if ( mdi->mapcoord.x || mdi->mapcoord.y )
989 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
990 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
991 mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y );
992 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
994 g_remove ( mdi->filename_buf );
999 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload )
1001 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1002 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1004 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1005 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm )
1006 && vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) )
1008 MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
1013 mdi->map_layer_alive = TRUE;
1014 mdi->mutex = g_mutex_new();
1015 mdi->refresh_display = TRUE;
1017 /* cache_dir and buffer for dest filename */
1018 mdi->cache_dir = g_strdup ( vml->cache_dir );
1019 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1020 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1021 mdi->maptype = vml->maptype;
1023 mdi->mapcoord = ulm;
1025 mdi->redownload = redownload;
1027 mdi->x0 = MIN(ulm.x, brm.x);
1028 mdi->xf = MAX(ulm.x, brm.x);
1029 mdi->y0 = MIN(ulm.y, brm.y);
1030 mdi->yf = MAX(ulm.y, brm.y);
1034 if ( mdi->redownload ) {
1035 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
1037 /* calculate how many we need */
1038 for ( a = mdi->x0; a <= mdi->xf; a++ )
1040 for ( b = mdi->y0; b <= mdi->yf; b++ )
1042 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
1043 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
1045 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1051 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1053 if ( mdi->mapstoget )
1055 const gchar *tmp_str;
1060 if (redownload == REDOWNLOAD_BAD)
1061 tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget);
1063 tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget);
1067 tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget);
1069 tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype));
1071 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1072 /* launch the thread */
1073 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1074 tmp, /* description string */
1075 (vik_thr_func) map_download_thread, /* function to call within thread */
1076 mdi, /* pass along data */
1077 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1078 (vik_thr_free_func) mdi_cancel_cleanup,
1087 void maps_layer_download_section_without_redraw( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom)
1090 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1092 if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm)
1093 || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) {
1094 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
1098 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
1103 mdi->map_layer_alive = TRUE;
1104 mdi->mutex = g_mutex_new();
1105 mdi->refresh_display = FALSE;
1107 mdi->cache_dir = g_strdup ( vml->cache_dir );
1108 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1109 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1110 mdi->maptype = vml->maptype;
1112 mdi->mapcoord = ulm;
1114 mdi->redownload = REDOWNLOAD_NONE;
1116 mdi->x0 = MIN(ulm.x, brm.x);
1117 mdi->xf = MAX(ulm.x, brm.x);
1118 mdi->y0 = MIN(ulm.y, brm.y);
1119 mdi->yf = MAX(ulm.y, brm.y);
1123 for (i = mdi->x0; i <= mdi->xf; i++) {
1124 for (j = mdi->y0; j <= mdi->yf; j++) {
1125 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
1126 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
1128 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1133 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1135 if (mdi->mapstoget) {
1138 fmt = ngettext("Downloading %d %s map...",
1139 "Downloading %d %s maps...",
1141 tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) );
1143 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1144 /* launch the thread */
1145 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1146 tmp, /* description string */
1147 (vik_thr_func) map_download_thread, /* function to call within thread */
1148 mdi, /* pass along data */
1149 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1150 (vik_thr_free_func) mdi_cancel_cleanup,
1158 static void maps_layer_redownload_bad ( VikMapsLayer *vml )
1160 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
1163 static void maps_layer_redownload_all ( VikMapsLayer *vml )
1165 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
1168 static void maps_layer_redownload_new ( VikMapsLayer *vml )
1170 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
1173 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1175 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1177 if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 )
1179 if ( event->button == 1 )
1182 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 );
1183 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 );
1184 start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
1185 vml->dl_tool_x = vml->dl_tool_y = -1;
1190 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) );
1191 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) );
1193 vml->redownload_vvp = vvp;
1195 vml->dl_tool_x = vml->dl_tool_y = -1;
1197 if ( ! vml->dl_right_click_menu ) {
1199 vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () );
1201 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _Bad Map(s)") );
1202 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
1203 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1205 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _New Map(s)") );
1206 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
1207 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1209 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _All Map(s)") );
1210 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
1211 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1214 gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
1215 gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) );
1221 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1226 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1229 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1231 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1232 if ( vik_map_source_get_drawmode(map) == vik_viewport_get_drawmode ( vvp ) &&
1233 vik_map_source_coord_to_mapcoord ( map, vik_viewport_get_center ( vvp ),
1234 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1235 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1237 vml->dl_tool_x = event->x, vml->dl_tool_y = event->y;
1244 if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) )
1248 vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
1249 if ( __map_types[vml->maptype].coord_to_mapcoord ( &coord,
1250 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1251 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1253 gchar *filename_buf = g_strdup_printf ( DIRSTRUCTURE,
1254 vml->cache_dir, __map_types[vml->maptype].uniq_id,
1255 mapcoord.scale, mapcoord.z, mapcoord.x, mapcoord.y );
1257 __map_types[vml->maptype].download ( &mapcoord, filename_buf );
1258 g_free ( filename_buf );
1259 vik_layer_emit_update ( VIK_LAYER(vml) );
1267 static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload )
1269 VikMapsLayer *vml = vml_vvp[0];
1270 VikViewport *vvp = vml_vvp[1];
1271 VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
1273 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1274 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1279 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1280 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1282 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1283 if ( vik_map_source_get_drawmode(map) == vp_drawmode &&
1284 vik_map_source_coord_to_mapcoord ( map, &ul, xzoom, yzoom, &ulm ) &&
1285 vik_map_source_coord_to_mapcoord ( map, &br, xzoom, yzoom, &brm ) )
1286 start_download_thread ( vml, vvp, &ul, &br, redownload );
1287 else if (vik_map_source_get_drawmode(map) != vp_drawmode) {
1288 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, vik_map_source_get_drawmode(map));
1289 gchar *err = g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name));
1290 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1294 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Wrong zoom level for this map.") );
1298 static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] )
1300 download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
1303 static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] )
1305 download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW);
1308 static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
1310 download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
1313 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp )
1315 static gpointer pass_along[2];
1317 pass_along[0] = vml;
1318 pass_along[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) );
1320 item = gtk_menu_item_new();
1321 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
1322 gtk_widget_show ( item );
1324 item = gtk_menu_item_new_with_mnemonic ( _("Download _Missing Onscreen Maps") );
1325 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along );
1326 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1327 gtk_widget_show ( item );
1329 if ( vik_map_source_supports_download_only_new (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) {
1330 item = gtk_menu_item_new_with_mnemonic ( _("Download _New Onscreen Maps") );
1331 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along );
1332 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1333 gtk_widget_show ( item );
1336 /* TODO Add GTK_STOCK_REFRESH icon */
1337 item = gtk_menu_item_new_with_mnemonic ( _("Reload _All Onscreen Maps") );
1338 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
1339 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1340 gtk_widget_show ( item );