2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2005, Evan Battaglia <viking@greentorch.org>
5 * Copyright (C) 2010, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
6 * UTM multi-zone stuff by Kit Transue <notlostyet@didactek.com>
7 * Dynamic map type by Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #define MAX_SHRINKFACTOR 8.0000001 /* zoom 1 viewing 8-tiles */
30 #define MIN_SHRINKFACTOR 0.0312499 /* zoom 32 viewing 1-tiles */
32 #define REAL_MIN_SHRINKFACTOR 0.0039062499 /* if shrinkfactor is between MAX and REAL_MAX, will only check for existence */
35 #include <gdk-pixbuf/gdk-pixdata.h>
37 #include <glib/gstdio.h>
38 #include <glib/gi18n.h>
50 #include "viktreeview.h"
51 #include "vikviewport.h"
53 #include "vikmapslayer.h"
60 /* only for dialog.h -- ugh */
61 #include "vikwaypoint.h"
63 #include "preferences.h"
65 #include "vikstatus.h"
66 #include "background.h"
68 #include "vikaggregatelayer.h"
69 #include "viklayerspanel.h"
72 #include "terraserver.h"
74 #include "icons/icons.h"
76 /****** MAP TYPES ******/
78 static GList *__map_types = NULL;
80 #define NUM_MAP_TYPES g_list_length(__map_types)
82 /* List of label for each map type */
83 static gchar **params_maptypes = NULL;
85 /* Corresponding IDS. (Cf. field uniq_id in VikMapsLayer struct) */
86 static guint *params_maptypes_ids = NULL;
88 /******** MAPZOOMS *********/
90 static gchar *params_mapzooms[] = { N_("Use Viking Zoom Level"), "0.25", "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "USGS 10k", "USGS 24k", "USGS 25k", "USGS 50k", "USGS 100k", "USGS 200k", "USGS 250k", NULL };
91 static gdouble __mapzooms_x[] = { 0.0, 0.25, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 1.016, 2.4384, 2.54, 5.08, 10.16, 20.32, 25.4 };
92 static gdouble __mapzooms_y[] = { 0.0, 0.25, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 1.016, 2.4384, 2.54, 5.08, 10.16, 20.32, 25.4 };
94 #define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0]) - 1)
96 /**************************/
99 static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file);
100 static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len );
101 static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
102 static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation );
103 static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation );
104 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp );
105 static VikMapsLayer *maps_layer_new ( VikViewport *vvp );
106 static void maps_layer_free ( VikMapsLayer *vml );
107 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
108 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
109 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp );
110 static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir );
111 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload );
112 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp );
113 static guint map_uniq_id_to_index ( guint uniq_id );
116 static VikLayerParamScale params_scales[] = {
117 /* min, max, step, digits (decimal places) */
118 { 0, 255, 3, 0 }, /* alpha */
121 VikLayerParam maps_layer_params[] = {
122 { "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Map Type:"), VIK_LAYER_WIDGET_COMBOBOX, NULL, NULL },
123 { "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Maps Directory:"), VIK_LAYER_WIDGET_FOLDERENTRY },
124 { "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales },
125 { "autodownload", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload maps:"), VIK_LAYER_WIDGET_CHECKBUTTON },
126 { "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms, NULL },
129 enum { PARAM_MAPTYPE=0, PARAM_CACHE_DIR, PARAM_ALPHA, PARAM_AUTODOWNLOAD, PARAM_MAPZOOM, NUM_PARAMS };
131 static VikToolInterface maps_tools[] = {
132 { N_("Maps Download"), (VikToolConstructorFunc) maps_layer_download_create, NULL, NULL, NULL,
133 (VikToolMouseFunc) maps_layer_download_click, NULL, (VikToolMouseFunc) maps_layer_download_release,
134 (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_mapdl_pixbuf },
137 VikLayerInterface vik_maps_layer_interface = {
139 &vikmapslayer_pixbuf,
142 sizeof(maps_tools) / sizeof(maps_tools[0]),
151 (VikLayerFuncCreate) maps_layer_new,
152 (VikLayerFuncRealize) NULL,
153 (VikLayerFuncPostRead) maps_layer_post_read,
154 (VikLayerFuncFree) maps_layer_free,
156 (VikLayerFuncProperties) NULL,
157 (VikLayerFuncDraw) maps_layer_draw,
158 (VikLayerFuncChangeCoordMode) NULL,
160 (VikLayerFuncSetMenuItemsSelection) NULL,
161 (VikLayerFuncGetMenuItemsSelection) NULL,
163 (VikLayerFuncAddMenuItems) maps_layer_add_menu_items,
164 (VikLayerFuncSublayerAddMenuItems) NULL,
166 (VikLayerFuncSublayerRenameRequest) NULL,
167 (VikLayerFuncSublayerToggleVisible) NULL,
169 (VikLayerFuncMarshall) maps_layer_marshall,
170 (VikLayerFuncUnmarshall) maps_layer_unmarshall,
172 (VikLayerFuncSetParam) maps_layer_set_param,
173 (VikLayerFuncGetParam) maps_layer_get_param,
175 (VikLayerFuncReadFileData) NULL,
176 (VikLayerFuncWriteFileData) NULL,
178 (VikLayerFuncDeleteItem) NULL,
179 (VikLayerFuncCopyItem) NULL,
180 (VikLayerFuncPasteItem) NULL,
181 (VikLayerFuncFreeCopiedItem) NULL,
182 (VikLayerFuncDragDropRequest) NULL,
185 struct _VikMapsLayer {
191 gdouble xmapzoom, ymapzoom;
193 gboolean autodownload;
194 VikCoord *last_center;
198 gint dl_tool_x, dl_tool_y;
200 GtkMenu *dl_right_click_menu;
201 VikCoord redownload_ul, redownload_br; /* right click menu only */
202 VikViewport *redownload_vvp;
205 enum { REDOWNLOAD_NONE = 0, /* download only missing maps */
206 REDOWNLOAD_BAD, /* download missing and bad maps */
207 REDOWNLOAD_NEW, /* download missing maps that are newer on server only */
208 REDOWNLOAD_ALL, /* download all maps */
209 DOWNLOAD_OR_REFRESH }; /* download missing maps and refresh cache */
211 static VikLayerParam prefs[] = {
212 { VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Default maplayer directory:"), VIK_LAYER_WIDGET_FOLDERENTRY, NULL, NULL },
215 void maps_layer_init ()
217 VikLayerParamData tmp;
218 tmp.s = maps_layer_default_dir();
219 a_preferences_register(prefs, tmp, VIKING_PREFERENCES_GROUP_KEY);
222 /****************************************/
223 /******** MAPS LAYER TYPES **************/
224 /****************************************/
226 int _get_index_for_id ( guint id )
229 while (params_maptypes_ids[index] != 0)
231 if (params_maptypes_ids[index] == id)
238 void _add_map_source ( guint id, const char *label, VikMapSource *map )
242 len = g_strv_length (params_maptypes);
244 params_maptypes = g_realloc (params_maptypes, (len+2)*sizeof(gchar*));
245 params_maptypes[len] = g_strdup (label);
246 params_maptypes[len+1] = NULL;
249 params_maptypes_ids = g_realloc (params_maptypes_ids, (len+2)*sizeof(guint));
250 params_maptypes_ids[len] = id;
251 params_maptypes_ids[len+1] = 0;
253 /* We have to clone */
254 VikMapSource *clone = VIK_MAP_SOURCE(g_object_ref(map));
255 /* Register the clone in the list */
256 __map_types = g_list_append(__map_types, clone);
259 We have to ensure the mode LayerParam references the up-to-date
263 memcpy(&maps_layer_params[0].widget_data, ¶ms_maptypes, sizeof(gpointer));
264 memcpy(&maps_layer_params[0].extra_widget_data, ¶ms_maptypes_ids, sizeof(gpointer));
266 maps_layer_params[0].widget_data = params_maptypes;
267 maps_layer_params[0].extra_widget_data = params_maptypes_ids;
270 void _update_map_source ( const char *label, VikMapSource *map, int index )
272 GList *item = g_list_nth (__map_types, index);
273 g_object_unref (item->data);
274 item->data = g_object_ref (map);
275 /* Change previous data */
276 g_free (params_maptypes[index]);
277 params_maptypes[index] = g_strdup (label);
280 void maps_layer_register_map_source ( VikMapSource *map )
282 g_assert(map != NULL);
284 guint id = vik_map_source_get_uniq_id(map);
285 const char *label = vik_map_source_get_label(map);
286 g_assert(label != NULL);
288 int previous = map_uniq_id_to_index (id);
289 if (previous != NUM_MAP_TYPES)
291 _update_map_source (label, map, previous);
295 _add_map_source (id, label, map);
299 #define MAPS_LAYER_NTH_LABEL(n) (params_maptypes[n])
300 #define MAPS_LAYER_NTH_ID(n) (params_maptypes_ids[n])
301 #define MAPS_LAYER_NTH_TYPE(n) (VIK_MAP_SOURCE(g_list_nth_data(__map_types, (n))))
303 gint vik_maps_layer_get_map_type(VikMapsLayer *vml)
305 return(vml->maptype);
308 gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml)
310 return(g_strdup(MAPS_LAYER_NTH_LABEL(vml->maptype)));
313 /****************************************/
314 /******** CACHE DIR STUFF ***************/
315 /****************************************/
317 #define DIRSTRUCTURE "%st%ds%dz%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d"
318 #define MAPS_CACHE_DIR maps_layer_default_dir()
322 #define GLOBAL_MAPS_DIR "C:\\VIKING-MAPS\\"
323 #define LOCAL_MAPS_DIR "VIKING-MAPS"
326 #define GLOBAL_MAPS_DIR "/var/cache/maps/"
327 #define LOCAL_MAPS_DIR ".viking-maps"
330 gchar *maps_layer_default_dir ()
332 static gchar *defaultdir = NULL;
335 /* Thanks to Mike Davison for the $VIKING_MAPS usage */
336 const gchar *mapdir = g_getenv("VIKING_MAPS");
338 defaultdir = g_strdup ( mapdir );
339 } else if ( g_access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) {
340 defaultdir = g_strdup ( GLOBAL_MAPS_DIR );
342 const gchar *home = g_get_home_dir();
343 if (!home || g_access(home, W_OK))
344 home = g_get_home_dir ();
346 defaultdir = g_build_filename ( home, LOCAL_MAPS_DIR, NULL );
348 defaultdir = g_strdup ( LOCAL_MAPS_DIR );
350 if (defaultdir && (defaultdir[strlen(defaultdir)-1] != G_DIR_SEPARATOR))
352 /* Add the separator at the end */
353 gchar *tmp = defaultdir;
354 defaultdir = g_strconcat(tmp, G_DIR_SEPARATOR_S, NULL);
357 g_debug("%s: defaultdir=%s", __FUNCTION__, defaultdir);
362 static void maps_layer_mkdir_if_default_dir ( VikMapsLayer *vml )
364 if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && g_file_test ( vml->cache_dir, G_FILE_TEST_EXISTS ) == FALSE )
366 g_mkdir ( vml->cache_dir, 0777 );
370 static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir )
373 g_assert ( vml != NULL);
374 g_free ( vml->cache_dir );
375 vml->cache_dir = NULL;
377 if ( dir == NULL || dir[0] == '\0' )
379 if ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir") )
380 vml->cache_dir = g_strdup ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir")->s );
385 if ( dir[len-1] != G_DIR_SEPARATOR )
387 vml->cache_dir = g_malloc ( len+2 );
388 strncpy ( vml->cache_dir, dir, len );
389 vml->cache_dir[len] = G_DIR_SEPARATOR;
390 vml->cache_dir[len+1] = '\0';
393 vml->cache_dir = g_strdup ( dir );
395 maps_layer_mkdir_if_default_dir ( vml );
398 /****************************************/
399 /******** GOBJECT STUFF *****************/
400 /****************************************/
402 GType vik_maps_layer_get_type ()
404 static GType vml_type = 0;
408 static const GTypeInfo vml_info =
410 sizeof (VikMapsLayerClass),
411 NULL, /* base_init */
412 NULL, /* base_finalize */
413 NULL, /* class init */
414 NULL, /* class_finalize */
415 NULL, /* class_data */
416 sizeof (VikMapsLayer),
418 NULL /* instance init */
420 vml_type = g_type_register_static ( VIK_LAYER_TYPE, "VikMapsLayer", &vml_info, 0 );
426 /****************************************/
427 /************** PARAMETERS **************/
428 /****************************************/
430 static guint map_index_to_uniq_id (guint8 index)
432 g_assert ( index < NUM_MAP_TYPES );
433 return vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(index));
436 static guint map_uniq_id_to_index ( guint uniq_id )
439 for ( i = 0; i < NUM_MAP_TYPES; i++ )
440 if ( vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(i)) == uniq_id )
442 return NUM_MAP_TYPES; /* no such thing */
445 static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation )
449 case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break;
450 case PARAM_MAPTYPE: {
451 gint maptype = map_uniq_id_to_index(data.u);
452 if ( maptype == NUM_MAP_TYPES ) g_warning(_("Unknown map type"));
453 else vml->maptype = maptype;
456 case PARAM_ALPHA: if ( data.u <= 255 ) vml->alpha = data.u; break;
457 case PARAM_AUTODOWNLOAD: vml->autodownload = data.b; break;
458 case PARAM_MAPZOOM: if ( data.u < NUM_MAPZOOMS ) {
459 vml->mapzoom_id = data.u;
460 vml->xmapzoom = __mapzooms_x [data.u];
461 vml->ymapzoom = __mapzooms_y [data.u];
462 }else g_warning (_("Unknown Map Zoom")); break;
467 static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation )
469 VikLayerParamData rv;
472 case PARAM_CACHE_DIR: rv.s = vml->cache_dir ? vml->cache_dir : ""; break;
473 case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break;
474 case PARAM_ALPHA: rv.u = vml->alpha; break;
475 case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break;
476 case PARAM_MAPZOOM: rv.u = vml->mapzoom_id; break;
481 /****************************************/
482 /****** CREATING, COPYING, FREEING ******/
483 /****************************************/
485 static VikMapsLayer *maps_layer_new ( VikViewport *vvp )
488 VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) );
489 vik_layer_init ( VIK_LAYER(vml), VIK_LAYER_MAPS );
490 idx = map_uniq_id_to_index(13); /* 13 is id for OSM Mapnik maps */
491 vml->maptype = (idx < NUM_MAP_TYPES) ? idx : 0;
494 vml->dl_tool_x = vml->dl_tool_y = -1;
495 maps_layer_set_cache_dir ( vml, NULL );
496 vml->autodownload = FALSE;
497 vml->last_center = NULL;
498 vml->last_xmpp = 0.0;
499 vml->last_ympp = 0.0;
501 vml->dl_right_click_menu = NULL;
506 static void maps_layer_free ( VikMapsLayer *vml )
508 g_free ( vml->cache_dir );
509 vml->cache_dir = NULL;
510 if ( vml->dl_right_click_menu )
511 gtk_object_sink ( GTK_OBJECT(vml->dl_right_click_menu) );
512 g_free(vml->last_center);
513 vml->last_center = NULL;
516 static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file)
518 if (from_file != TRUE)
520 /* If this method is not called in file reading context
521 * it is called in GUI context.
522 * So, we can check if we have to inform the user about inconsistency */
523 VikViewportDrawMode vp_drawmode;
524 VikMapsLayer *vml = VIK_MAPS_LAYER(vl);
525 VikMapSource *map = NULL;
527 vp_drawmode = vik_viewport_get_drawmode ( VIK_VIEWPORT(vp) );
528 map = MAPS_LAYER_NTH_TYPE(vml->maptype);
529 if (vik_map_source_get_drawmode(map) != vp_drawmode) {
530 const gchar *drawmode_name = vik_viewport_get_drawmode_name (VIK_VIEWPORT(vp), vik_map_source_get_drawmode(map));
531 gchar *msg = g_strdup_printf(_("New map cannot be displayed in the current drawmode.\nSelect \"%s\" from View menu to view it."), drawmode_name);
532 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp), msg );
538 static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len )
540 vik_layer_marshall_params ( VIK_LAYER(vml), data, len );
543 static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
545 VikMapsLayer *rv = maps_layer_new ( vvp );
546 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
550 /*********************/
551 /****** DRAWING ******/
552 /*********************/
554 static GdkPixbuf *pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha )
557 gint width, height, iii, jjj;
559 if ( ! gdk_pixbuf_get_has_alpha ( pixbuf ) )
561 GdkPixbuf *tmp = gdk_pixbuf_add_alpha(pixbuf,FALSE,0,0,0);
562 g_object_unref(G_OBJECT(pixbuf));
566 pixels = gdk_pixbuf_get_pixels(pixbuf);
567 width = gdk_pixbuf_get_width(pixbuf);
568 height = gdk_pixbuf_get_height(pixbuf);
570 /* r,g,b,a,r,g,b,a.... */
571 for (iii = 0; iii < width; iii++) for (jjj = 0; jjj < height; jjj++)
579 static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdouble yshrinkfactor )
582 guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf);
583 tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_NEAREST);
584 g_object_unref ( G_OBJECT(pixbuf) );
588 static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, gchar *filename_buf, gint buf_len, gdouble xshrinkfactor, gdouble yshrinkfactor )
593 pixbuf = a_mapcache_get ( mapcoord->x, mapcoord->y, mapcoord->z,
594 mode, mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
597 g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE,
598 vml->cache_dir, mode,
599 mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y );
600 if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
603 pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx );
605 /* free the pixbuf on error */
608 if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE )
609 g_warning ( _("Couldn't open image file: %s"), gx->message );
613 g_object_unref ( G_OBJECT(pixbuf) );
616 if ( vml->alpha < 255 )
617 pixbuf = pixbuf_set_alpha ( pixbuf, vml->alpha );
618 if ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 )
619 pixbuf = pixbuf_shrink ( pixbuf, xshrinkfactor, yshrinkfactor );
621 a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y,
622 mapcoord->z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(vml->maptype)),
623 mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
630 gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp)
632 const VikCoord *center = vik_viewport_get_center ( vvp );
634 if (vik_window_get_pan_move (VIK_WINDOW(VIK_GTK_WINDOW_FROM_WIDGET(GTK_WIDGET(vvp)))))
635 /* D'n'D pan in action: do not download */
638 if (vml->last_center == NULL) {
639 VikCoord *new_center = g_malloc(sizeof(VikCoord));
640 *new_center = *center;
641 vml->last_center = new_center;
642 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
643 vml->last_ympp = vik_viewport_get_ympp(vvp);
647 /* TODO: perhaps vik_coord_diff() */
648 if (vik_coord_equals(vml->last_center, center)
649 && (vml->last_xmpp == vik_viewport_get_xmpp(vvp))
650 && (vml->last_ympp == vik_viewport_get_ympp(vvp)))
653 *(vml->last_center) = *center;
654 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
655 vml->last_ympp = vik_viewport_get_ympp(vvp);
659 static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br )
662 gdouble xzoom = vik_viewport_get_xmpp ( vvp );
663 gdouble yzoom = vik_viewport_get_ympp ( vvp );
664 gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0;
665 gdouble existence_only = FALSE;
667 if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) {
668 xshrinkfactor = vml->xmapzoom / xzoom;
669 yshrinkfactor = vml->ymapzoom / yzoom;
670 xzoom = vml->xmapzoom;
671 yzoom = vml->xmapzoom;
672 if ( ! (xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR &&
673 yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) ) {
674 if ( xshrinkfactor > REAL_MIN_SHRINKFACTOR && yshrinkfactor > REAL_MIN_SHRINKFACTOR )
675 existence_only = TRUE;
677 g_warning ( _("Cowardly refusing to draw tiles or existence of tiles beyond %d zoom out factor"), (int)( 1.0/REAL_MIN_SHRINKFACTOR));
684 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
685 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm ) &&
686 vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) ) {
690 gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x);
691 gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y);
692 gint mode = vik_map_source_get_uniq_id(map);
695 gint xx, yy, width, height;
698 guint max_path_len = strlen(vml->cache_dir) + 40;
699 gchar *path_buf = g_malloc ( max_path_len * sizeof(char) );
701 if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) {
702 g_debug("%s: Starting autodownload", __FUNCTION__);
703 if ( vik_map_source_supports_download_only_new (map) )
704 // Try to download newer tiles
705 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
707 // Download only missing tiles
708 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
711 if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) {
712 for ( x = xmin; x <= xmax; x++ ) {
713 for ( y = ymin; y <= ymax; y++ ) {
716 pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
718 width = gdk_pixbuf_get_width ( pixbuf );
719 height = gdk_pixbuf_get_height ( pixbuf );
721 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
722 vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy );
726 vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height );
730 } else { /* tilesize is known, don't have to keep converting coords */
731 gdouble tilesize_x = vik_map_source_get_tilesize_x(map) * xshrinkfactor;
732 gdouble tilesize_y = vik_map_source_get_tilesize_y(map) * yshrinkfactor;
733 /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
734 gint tilesize_x_ceil = ceil ( tilesize_x );
735 gint tilesize_y_ceil = ceil ( tilesize_y );
736 gint8 xinc = (ulm.x == xmin) ? 1 : -1;
737 gint8 yinc = (ulm.y == ymin) ? 1 : -1;
738 gdouble xx, yy; gint xx_tmp, yy_tmp;
739 gint base_yy, xend, yend;
741 GdkGC *black_gc = GTK_WIDGET(vvp)->style->black_gc;
743 xend = (xinc == 1) ? (xmax+1) : (xmin-1);
744 yend = (yinc == 1) ? (ymax+1) : (ymin-1);
746 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
747 vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp );
748 xx = xx_tmp; yy = yy_tmp;
749 /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
750 * eg if tile size 128, shrinkfactor 0.333 */
751 xx -= (tilesize_x/2);
752 base_yy = yy - (tilesize_y/2);
754 for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) {
756 for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) {
760 if ( existence_only ) {
761 g_snprintf ( path_buf, max_path_len, DIRSTRUCTURE,
762 vml->cache_dir, mode,
763 ulm.scale, ulm.z, ulm.x, ulm.y );
764 if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) {
765 vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil );
769 for (scale_inc = 0; scale_inc < 4; scale_inc ++) {
770 /* try with correct then smaller zooms */
771 int scale_factor = 1 << scale_inc; /* 2^scale_inc */
773 ulm2.x = ulm.x / scale_factor;
774 ulm2.y = ulm.y / scale_factor;
775 ulm2.scale = ulm.scale + scale_inc;
776 pixbuf = get_pixbuf ( vml, mode, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor );
778 gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil;
779 gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil;
781 printf("maps_layer_draw_section - x=%d, y=%d, z=%d, src_x=%d, src_y=%d, xx=%d, yy=%d - %x\n", ulm.x, ulm.y, ulm.scale, src_x, src_y, (int)xx, (int)yy, vvp);
783 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
788 /* retry with bigger zooms */
790 for (scale_dec = 1; scale_dec < 2; scale_dec ++) {
792 int scale_factor = 1 << scale_dec; /* 2^scale_dec */
794 ulm2.x = ulm.x * scale_factor;
795 ulm2.y = ulm.y * scale_factor;
796 ulm2.scale = ulm.scale - scale_dec;
797 for (pict_x = 0; pict_x < scale_factor; pict_x ++) {
798 for (pict_y = 0; pict_y < scale_factor; pict_y ++) {
799 MapCoord ulm3 = ulm2;
802 pixbuf = get_pixbuf ( vml, mode, &ulm3, path_buf, max_path_len, xshrinkfactor / scale_factor, yshrinkfactor / scale_factor );
806 gint dest_x = xx + pict_x * (tilesize_x_ceil / scale_factor);
807 gint dest_y = yy + pict_y * (tilesize_y_ceil / scale_factor);
808 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, dest_x, dest_y, tilesize_x_ceil / scale_factor, tilesize_y_ceil / scale_factor );
826 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp )
828 if ( vik_map_source_get_drawmode(MAPS_LAYER_NTH_TYPE(vml->maptype)) == vik_viewport_get_drawmode ( vvp ) )
833 gchar *copyright = vik_map_source_get_copyright ( MAPS_LAYER_NTH_TYPE(vml->maptype) );
834 vik_viewport_add_copyright ( vvp, copyright );
836 /* get corner coords */
837 if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) {
838 /* UTM multi-zone stuff by Kit Transue */
839 gchar leftmost_zone, rightmost_zone, i;
840 leftmost_zone = vik_viewport_leftmost_zone( vvp );
841 rightmost_zone = vik_viewport_rightmost_zone( vvp );
842 for ( i = leftmost_zone; i <= rightmost_zone; ++i ) {
843 vik_viewport_corners_for_zonen ( vvp, i, &ul, &br );
844 maps_layer_draw_section ( vml, vvp, &ul, &br );
848 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
849 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
851 maps_layer_draw_section ( vml, vvp, &ul, &br );
856 /*************************/
857 /****** DOWNLOADING ******/
858 /*************************/
860 /* pass along data to thread, exists even if layer is deleted. */
870 gboolean refresh_display;
873 gboolean map_layer_alive;
877 static void mdi_free ( MapDownloadInfo *mdi )
879 g_mutex_free(mdi->mutex);
880 g_free ( mdi->cache_dir );
881 mdi->cache_dir = NULL;
882 g_free ( mdi->filename_buf );
883 mdi->filename_buf = NULL;
887 static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
889 MapDownloadInfo *mdi = ptr;
890 g_mutex_lock(mdi->mutex);
891 mdi->map_layer_alive = FALSE;
892 g_mutex_unlock(mdi->mutex);
895 static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
897 void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype));
900 for ( x = mdi->x0; x <= mdi->xf; x++ )
902 for ( y = mdi->y0; y <= mdi->yf; y++ )
904 gboolean remove_mem_cache = FALSE;
905 gboolean need_download = FALSE;
906 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
907 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
908 mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
911 int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
913 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
917 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
918 need_download = TRUE;
919 remove_mem_cache = TRUE;
921 } else { /* in case map file already exists */
922 switch (mdi->redownload) {
923 case REDOWNLOAD_NONE:
928 /* see if this one is bad or what */
930 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
931 if (gx || (!pixbuf)) {
932 g_remove ( mdi->filename_buf );
933 need_download = TRUE;
934 remove_mem_cache = TRUE;
938 g_object_unref ( pixbuf );
944 need_download = TRUE;
945 remove_mem_cache = TRUE;
949 /* FIXME: need a better way than to erase file in case of server/network problem */
950 g_remove ( mdi->filename_buf );
951 need_download = TRUE;
952 remove_mem_cache = TRUE;
955 case DOWNLOAD_OR_REFRESH:
956 remove_mem_cache = TRUE;
960 g_warning ( "redownload state %d unknown\n", mdi->redownload);
964 mdi->mapcoord.x = x; mdi->mapcoord.y = y;
967 if ( vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle))
972 g_mutex_lock(mdi->mutex);
973 if (remove_mem_cache)
974 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 );
975 if (mdi->refresh_display && mdi->map_layer_alive) {
976 /* TODO: check if it's on visible area */
977 vik_layer_emit_update ( VIK_LAYER(mdi->vml) );
979 g_mutex_unlock(mdi->mutex);
981 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
985 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
986 g_mutex_lock(mdi->mutex);
987 if (mdi->map_layer_alive)
988 g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
989 g_mutex_unlock(mdi->mutex);
993 static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
995 if ( mdi->mapcoord.x || mdi->mapcoord.y )
997 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
998 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
999 mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y );
1000 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
1002 g_remove ( mdi->filename_buf );
1007 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload )
1009 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1010 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1012 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1013 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm )
1014 && vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) )
1016 MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
1021 mdi->map_layer_alive = TRUE;
1022 mdi->mutex = g_mutex_new();
1023 mdi->refresh_display = TRUE;
1025 /* cache_dir and buffer for dest filename */
1026 mdi->cache_dir = g_strdup ( vml->cache_dir );
1027 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1028 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1029 mdi->maptype = vml->maptype;
1031 mdi->mapcoord = ulm;
1033 mdi->redownload = redownload;
1035 mdi->x0 = MIN(ulm.x, brm.x);
1036 mdi->xf = MAX(ulm.x, brm.x);
1037 mdi->y0 = MIN(ulm.y, brm.y);
1038 mdi->yf = MAX(ulm.y, brm.y);
1042 if ( mdi->redownload ) {
1043 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
1045 /* calculate how many we need */
1046 for ( a = mdi->x0; a <= mdi->xf; a++ )
1048 for ( b = mdi->y0; b <= mdi->yf; b++ )
1050 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
1051 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
1053 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1059 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1061 if ( mdi->mapstoget )
1063 const gchar *tmp_str;
1068 if (redownload == REDOWNLOAD_BAD)
1069 tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget);
1071 tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget);
1075 tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget);
1077 tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype));
1079 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1080 /* launch the thread */
1081 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1082 tmp, /* description string */
1083 (vik_thr_func) map_download_thread, /* function to call within thread */
1084 mdi, /* pass along data */
1085 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1086 (vik_thr_free_func) mdi_cancel_cleanup,
1095 void maps_layer_download_section_without_redraw( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom)
1098 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1100 if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm)
1101 || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) {
1102 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
1106 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
1111 mdi->map_layer_alive = TRUE;
1112 mdi->mutex = g_mutex_new();
1113 mdi->refresh_display = FALSE;
1115 mdi->cache_dir = g_strdup ( vml->cache_dir );
1116 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1117 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1118 mdi->maptype = vml->maptype;
1120 mdi->mapcoord = ulm;
1122 mdi->redownload = REDOWNLOAD_NONE;
1124 mdi->x0 = MIN(ulm.x, brm.x);
1125 mdi->xf = MAX(ulm.x, brm.x);
1126 mdi->y0 = MIN(ulm.y, brm.y);
1127 mdi->yf = MAX(ulm.y, brm.y);
1131 for (i = mdi->x0; i <= mdi->xf; i++) {
1132 for (j = mdi->y0; j <= mdi->yf; j++) {
1133 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
1134 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
1136 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1141 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1143 if (mdi->mapstoget) {
1146 fmt = ngettext("Downloading %d %s map...",
1147 "Downloading %d %s maps...",
1149 tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) );
1151 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1152 /* launch the thread */
1153 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1154 tmp, /* description string */
1155 (vik_thr_func) map_download_thread, /* function to call within thread */
1156 mdi, /* pass along data */
1157 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1158 (vik_thr_free_func) mdi_cancel_cleanup,
1166 static void maps_layer_redownload_bad ( VikMapsLayer *vml )
1168 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
1171 static void maps_layer_redownload_all ( VikMapsLayer *vml )
1173 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
1176 static void maps_layer_redownload_new ( VikMapsLayer *vml )
1178 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
1181 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1183 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1185 if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 )
1187 if ( event->button == 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)), &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 ) ), &br );
1192 start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
1193 vml->dl_tool_x = vml->dl_tool_y = -1;
1198 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) );
1199 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) );
1201 vml->redownload_vvp = vvp;
1203 vml->dl_tool_x = vml->dl_tool_y = -1;
1205 if ( ! vml->dl_right_click_menu ) {
1207 vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () );
1209 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _Bad Map(s)") );
1210 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
1211 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1213 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _New Map(s)") );
1214 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
1215 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1217 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _All Map(s)") );
1218 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
1219 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1222 gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
1223 gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) );
1229 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1234 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1237 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1239 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1240 if ( vik_map_source_get_drawmode(map) == vik_viewport_get_drawmode ( vvp ) &&
1241 vik_map_source_coord_to_mapcoord ( map, vik_viewport_get_center ( vvp ),
1242 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1243 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1245 vml->dl_tool_x = event->x, vml->dl_tool_y = event->y;
1252 if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) )
1256 vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
1257 if ( __map_types[vml->maptype].coord_to_mapcoord ( &coord,
1258 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1259 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1261 gchar *filename_buf = g_strdup_printf ( DIRSTRUCTURE,
1262 vml->cache_dir, __map_types[vml->maptype].uniq_id,
1263 mapcoord.scale, mapcoord.z, mapcoord.x, mapcoord.y );
1265 __map_types[vml->maptype].download ( &mapcoord, filename_buf );
1266 g_free ( filename_buf );
1267 vik_layer_emit_update ( VIK_LAYER(vml) );
1275 static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload )
1277 VikMapsLayer *vml = vml_vvp[0];
1278 VikViewport *vvp = vml_vvp[1];
1279 VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
1281 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1282 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1287 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1288 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1290 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1291 if ( vik_map_source_get_drawmode(map) == vp_drawmode &&
1292 vik_map_source_coord_to_mapcoord ( map, &ul, xzoom, yzoom, &ulm ) &&
1293 vik_map_source_coord_to_mapcoord ( map, &br, xzoom, yzoom, &brm ) )
1294 start_download_thread ( vml, vvp, &ul, &br, redownload );
1295 else if (vik_map_source_get_drawmode(map) != vp_drawmode) {
1296 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, vik_map_source_get_drawmode(map));
1297 gchar *err = g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name));
1298 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1302 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Wrong zoom level for this map.") );
1306 static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] )
1308 download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
1311 static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] )
1313 download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW);
1316 static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
1318 download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
1321 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp )
1323 static gpointer pass_along[2];
1325 pass_along[0] = vml;
1326 pass_along[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) );
1328 item = gtk_menu_item_new();
1329 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
1330 gtk_widget_show ( item );
1332 item = gtk_menu_item_new_with_mnemonic ( _("Download _Missing Onscreen Maps") );
1333 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along );
1334 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1335 gtk_widget_show ( item );
1337 if ( vik_map_source_supports_download_only_new (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) {
1338 item = gtk_menu_item_new_with_mnemonic ( _("Download _New Onscreen Maps") );
1339 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along );
1340 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1341 gtk_widget_show ( item );
1344 /* TODO Add GTK_STOCK_REFRESH icon */
1345 item = gtk_menu_item_new_with_mnemonic ( _("Reload _All Onscreen Maps") );
1346 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
1347 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1348 gtk_widget_show ( item );