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 * Copyright (c) 2013, Rob Norris <rw_norris@hotmail.com>
7 * UTM multi-zone stuff by Kit Transue <notlostyet@didactek.com>
8 * Dynamic map type by Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include <gdk-pixbuf/gdk-pixdata.h>
33 #include <glib/gstdio.h>
34 #include <glib/gi18n.h>
48 #include "vikmapsourcedefault.h"
52 #include "background.h"
53 #include "preferences.h"
54 #include "vikmapslayer.h"
55 #include "icons/icons.h"
62 #define VIK_SETTINGS_MAP_MAX_TILES "maps_max_tiles"
63 static gint MAX_TILES = 1000;
65 #define VIK_SETTINGS_MAP_MIN_SHRINKFACTOR "maps_min_shrinkfactor"
66 #define VIK_SETTINGS_MAP_MAX_SHRINKFACTOR "maps_max_shrinkfactor"
67 static gdouble MAX_SHRINKFACTOR = 8.0000001; /* zoom 1 viewing 8-tiles */
68 static gdouble MIN_SHRINKFACTOR = 0.0312499; /* zoom 32 viewing 1-tiles */
70 #define VIK_SETTINGS_MAP_REAL_MIN_SHRINKFACTOR "maps_real_min_shrinkfactor"
71 static gdouble REAL_MIN_SHRINKFACTOR = 0.0039062499; /* if shrinkfactor is between MAX and REAL_MAX, will only check for existence */
73 /****** MAP TYPES ******/
75 static GList *__map_types = NULL;
77 #define NUM_MAP_TYPES g_list_length(__map_types)
79 /* List of label for each map type */
80 static gchar **params_maptypes = NULL;
82 /* Corresponding IDS. (Cf. field uniq_id in VikMapsLayer struct) */
83 static guint *params_maptypes_ids = NULL;
85 /******** MAPZOOMS *********/
87 static gchar *params_mapzooms[] = { N_("Use Viking Zoom Level"), "0.25", "0.5", "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 };
88 static gdouble __mapzooms_x[] = { 0.0, 0.25, 0.5, 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 };
89 static gdouble __mapzooms_y[] = { 0.0, 0.25, 0.5, 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 };
91 #define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0]) - 1)
93 /**************************/
96 static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file);
97 static const gchar* maps_layer_tooltip ( VikMapsLayer *vml );
98 static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len );
99 static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
100 static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation );
101 static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation );
102 static void maps_layer_change_param ( GtkWidget *widget, ui_change_values values );
103 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp );
104 static VikMapsLayer *maps_layer_new ( VikViewport *vvp );
105 static void maps_layer_free ( VikMapsLayer *vml );
106 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
107 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
108 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp );
109 static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir );
110 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload );
111 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp );
112 static guint map_uniq_id_to_index ( guint uniq_id );
115 static VikLayerParamScale params_scales[] = {
116 /* min, max, step, digits (decimal places) */
117 { 0, 255, 3, 0 }, /* alpha */
120 static VikLayerParamData id_default ( void ) { return VIK_LPD_UINT ( 19 ); } // OSM MapQuest maps
121 static VikLayerParamData directory_default ( void )
123 VikLayerParamData data;
124 VikLayerParamData *pref = a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir");
125 if (pref) data.s = g_strdup ( pref->s ); else data.s = "";
128 static VikLayerParamData file_default ( void )
130 VikLayerParamData data;
134 static VikLayerParamData alpha_default ( void ) { return VIK_LPD_UINT ( 255 ); }
135 static VikLayerParamData mapzoom_default ( void ) { return VIK_LPD_UINT ( 0 ); }
137 static gchar *cache_types[] = { "Viking", N_("OSM"), NULL };
138 static VikMapsCacheLayout cache_layout_default_value = VIK_MAPS_CACHE_LAYOUT_VIKING;
139 static VikLayerParamData cache_layout_default ( void ) { return VIK_LPD_UINT ( cache_layout_default_value ); }
141 VikLayerParam maps_layer_params[] = {
142 // NB mode => id - But can't break file format just to rename something better
143 { VIK_LAYER_MAPS, "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Map Type:"), VIK_LAYER_WIDGET_COMBOBOX, NULL, NULL, NULL, id_default, NULL, NULL },
144 { VIK_LAYER_MAPS, "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Maps Directory:"), VIK_LAYER_WIDGET_FOLDERENTRY, NULL, NULL, NULL, directory_default, NULL, NULL },
145 { VIK_LAYER_MAPS, "cache_type", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Cache Layout:"), VIK_LAYER_WIDGET_COMBOBOX, cache_types, NULL,
146 N_("This determines the tile storage layout on disk"), cache_layout_default, NULL, NULL },
147 { VIK_LAYER_MAPS, "mapfile", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Map File:"), VIK_LAYER_WIDGET_FILEENTRY, GINT_TO_POINTER(VF_FILTER_MBTILES), NULL,
148 N_("An MBTiles file. Only applies when the map type method is 'MBTiles'"), file_default, NULL, NULL },
149 { VIK_LAYER_MAPS, "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales, NULL,
150 N_("Control the Alpha value for transparency effects"), alpha_default, NULL, NULL },
151 { VIK_LAYER_MAPS, "autodownload", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload maps:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_true_default, NULL, NULL },
152 { VIK_LAYER_MAPS, "adlonlymissing", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload Only Gets Missing Maps:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL,
153 N_("Using this option avoids attempting to update already acquired tiles. This can be useful if you want to restrict the network usage, without having to resort to manual control. Only applies when 'Autodownload Maps' is on."), vik_lpd_false_default, NULL, NULL },
154 { VIK_LAYER_MAPS, "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms, NULL,
155 N_("Determines the method of displaying map tiles for the current zoom level. 'Viking Zoom Level' uses the best matching level, otherwise setting a fixed value will always use map tiles of the specified value regardless of the actual zoom level."),
156 mapzoom_default, NULL, NULL },
171 void maps_layer_set_autodownload_default ( gboolean autodownload )
173 // Set appropriate function
175 maps_layer_params[PARAM_AUTODOWNLOAD].default_value = vik_lpd_true_default;
177 maps_layer_params[PARAM_AUTODOWNLOAD].default_value = vik_lpd_false_default;
180 void maps_layer_set_cache_default ( VikMapsCacheLayout layout )
182 // Override default value returned by the default param function
183 cache_layout_default_value = layout;
186 static VikToolInterface maps_tools[] = {
187 { { "MapsDownload", "vik-icon-Maps Download", N_("_Maps Download"), NULL, N_("Maps Download"), 0 },
188 (VikToolConstructorFunc) maps_layer_download_create,
192 (VikToolMouseFunc) maps_layer_download_click,
194 (VikToolMouseFunc) maps_layer_download_release,
197 GDK_CURSOR_IS_PIXMAP, &cursor_mapdl_pixbuf, NULL },
200 VikLayerInterface vik_maps_layer_interface = {
204 &vikmapslayer_pixbuf,
207 sizeof(maps_tools) / sizeof(maps_tools[0]),
216 (VikLayerFuncCreate) maps_layer_new,
217 (VikLayerFuncRealize) NULL,
218 (VikLayerFuncPostRead) maps_layer_post_read,
219 (VikLayerFuncFree) maps_layer_free,
221 (VikLayerFuncProperties) NULL,
222 (VikLayerFuncDraw) maps_layer_draw,
223 (VikLayerFuncChangeCoordMode) NULL,
225 (VikLayerFuncSetMenuItemsSelection) NULL,
226 (VikLayerFuncGetMenuItemsSelection) NULL,
228 (VikLayerFuncAddMenuItems) maps_layer_add_menu_items,
229 (VikLayerFuncSublayerAddMenuItems) NULL,
231 (VikLayerFuncSublayerRenameRequest) NULL,
232 (VikLayerFuncSublayerToggleVisible) NULL,
233 (VikLayerFuncSublayerTooltip) NULL,
234 (VikLayerFuncLayerTooltip) maps_layer_tooltip,
235 (VikLayerFuncLayerSelected) NULL,
237 (VikLayerFuncMarshall) maps_layer_marshall,
238 (VikLayerFuncUnmarshall) maps_layer_unmarshall,
240 (VikLayerFuncSetParam) maps_layer_set_param,
241 (VikLayerFuncGetParam) maps_layer_get_param,
242 (VikLayerFuncChangeParam) maps_layer_change_param,
244 (VikLayerFuncReadFileData) NULL,
245 (VikLayerFuncWriteFileData) NULL,
247 (VikLayerFuncDeleteItem) NULL,
248 (VikLayerFuncCutItem) NULL,
249 (VikLayerFuncCopyItem) NULL,
250 (VikLayerFuncPasteItem) NULL,
251 (VikLayerFuncFreeCopiedItem) NULL,
252 (VikLayerFuncDragDropRequest) NULL,
254 (VikLayerFuncSelectClick) NULL,
255 (VikLayerFuncSelectMove) NULL,
256 (VikLayerFuncSelectRelease) NULL,
257 (VikLayerFuncSelectedViewportMenu) NULL,
260 struct _VikMapsLayer {
264 VikMapsCacheLayout cache_layout;
267 gdouble xmapzoom, ymapzoom;
269 gboolean autodownload;
270 gboolean adl_only_missing;
271 VikCoord *last_center;
275 gint dl_tool_x, dl_tool_y;
277 GtkMenu *dl_right_click_menu;
278 VikCoord redownload_ul, redownload_br; /* right click menu only */
279 VikViewport *redownload_vvp;
281 #ifdef HAVE_SQLITE3_H
286 enum { REDOWNLOAD_NONE = 0, /* download only missing maps */
287 REDOWNLOAD_BAD, /* download missing and bad maps */
288 REDOWNLOAD_NEW, /* download missing maps that are newer on server only */
289 REDOWNLOAD_ALL, /* download all maps */
290 DOWNLOAD_OR_REFRESH }; /* download missing maps and refresh cache */
292 static VikLayerParam prefs[] = {
293 { VIK_LAYER_NUM_TYPES, VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Default map layer directory:"), VIK_LAYER_WIDGET_FOLDERENTRY, NULL, NULL, N_("Choose a directory to store cached Map tiles for this layer"), NULL, NULL, NULL },
296 void maps_layer_init ()
298 VikLayerParamData tmp;
299 tmp.s = maps_layer_default_dir();
300 a_preferences_register(prefs, tmp, VIKING_PREFERENCES_GROUP_KEY);
302 gint max_tiles = MAX_TILES;
303 if ( a_settings_get_integer ( VIK_SETTINGS_MAP_MAX_TILES, &max_tiles ) )
304 MAX_TILES = max_tiles;
307 if ( a_settings_get_double ( VIK_SETTINGS_MAP_MIN_SHRINKFACTOR, &gdtmp ) )
308 MIN_SHRINKFACTOR = gdtmp;
310 if ( a_settings_get_double ( VIK_SETTINGS_MAP_MAX_SHRINKFACTOR, &gdtmp ) )
311 MAX_SHRINKFACTOR = gdtmp;
313 if ( a_settings_get_double ( VIK_SETTINGS_MAP_REAL_MIN_SHRINKFACTOR, &gdtmp ) )
314 REAL_MIN_SHRINKFACTOR = gdtmp;
317 /****************************************/
318 /******** MAPS LAYER TYPES **************/
319 /****************************************/
321 void _add_map_source ( guint16 id, const char *label, VikMapSource *map )
325 len = g_strv_length (params_maptypes);
327 params_maptypes = g_realloc (params_maptypes, (len+2)*sizeof(gchar*));
328 params_maptypes[len] = g_strdup (label);
329 params_maptypes[len+1] = NULL;
332 params_maptypes_ids = g_realloc (params_maptypes_ids, (len+2)*sizeof(guint));
333 params_maptypes_ids[len] = id;
334 params_maptypes_ids[len+1] = 0;
336 /* We have to clone */
337 VikMapSource *clone = VIK_MAP_SOURCE(g_object_ref(map));
338 /* Register the clone in the list */
339 __map_types = g_list_append(__map_types, clone);
342 We have to ensure the mode LayerParam references the up-to-date
346 memcpy(&maps_layer_params[0].widget_data, ¶ms_maptypes, sizeof(gpointer));
347 memcpy(&maps_layer_params[0].extra_widget_data, ¶ms_maptypes_ids, sizeof(gpointer));
349 maps_layer_params[0].widget_data = params_maptypes;
350 maps_layer_params[0].extra_widget_data = params_maptypes_ids;
353 void _update_map_source ( const char *label, VikMapSource *map, int index )
355 GList *item = g_list_nth (__map_types, index);
356 g_object_unref (item->data);
357 item->data = g_object_ref (map);
358 /* Change previous data */
359 g_free (params_maptypes[index]);
360 params_maptypes[index] = g_strdup (label);
364 * maps_layer_register_map_source:
365 * @map: the new VikMapSource
367 * Register a new VikMapSource.
368 * Override existing one (equality of id).
370 void maps_layer_register_map_source ( VikMapSource *map )
372 g_assert(map != NULL);
374 guint16 id = vik_map_source_get_uniq_id(map);
375 const char *label = vik_map_source_get_label(map);
376 g_assert(label != NULL);
378 int previous = map_uniq_id_to_index (id);
379 if (previous != NUM_MAP_TYPES)
381 _update_map_source (label, map, previous);
385 _add_map_source (id, label, map);
389 #define MAPS_LAYER_NTH_LABEL(n) (params_maptypes[n])
390 #define MAPS_LAYER_NTH_ID(n) (params_maptypes_ids[n])
391 #define MAPS_LAYER_NTH_TYPE(n) (VIK_MAP_SOURCE(g_list_nth_data(__map_types, (n))))
393 gint vik_maps_layer_get_map_type(VikMapsLayer *vml)
395 return(vml->maptype);
398 gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml)
400 return(g_strdup(MAPS_LAYER_NTH_LABEL(vml->maptype)));
403 /****************************************/
404 /******** CACHE DIR STUFF ***************/
405 /****************************************/
407 #define DIRECTDIRACCESS "%s%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d%s"
408 #define DIRECTDIRACCESS_WITH_NAME "%s%s" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d%s"
409 #define DIRSTRUCTURE "%st%ds%dz%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d"
410 #define MAPS_CACHE_DIR maps_layer_default_dir()
414 #define GLOBAL_MAPS_DIR "C:\\VIKING-MAPS\\"
415 #define LOCAL_MAPS_DIR "VIKING-MAPS"
416 #elif defined __APPLE__
418 #define GLOBAL_MAPS_DIR "/Library/cache/Viking/maps/"
419 #define LOCAL_MAPS_DIR "/Library/Application Support/Viking/viking-maps"
422 #define GLOBAL_MAPS_DIR "/var/cache/maps/"
423 #define LOCAL_MAPS_DIR ".viking-maps"
426 gchar *maps_layer_default_dir ()
428 static gchar *defaultdir = NULL;
431 /* Thanks to Mike Davison for the $VIKING_MAPS usage */
432 const gchar *mapdir = g_getenv("VIKING_MAPS");
434 defaultdir = g_strdup ( mapdir );
435 } else if ( g_access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) {
436 defaultdir = g_strdup ( GLOBAL_MAPS_DIR );
438 const gchar *home = g_get_home_dir();
439 if (!home || g_access(home, W_OK))
440 home = g_get_home_dir ();
442 defaultdir = g_build_filename ( home, LOCAL_MAPS_DIR, NULL );
444 defaultdir = g_strdup ( LOCAL_MAPS_DIR );
446 if (defaultdir && (defaultdir[strlen(defaultdir)-1] != G_DIR_SEPARATOR))
448 /* Add the separator at the end */
449 gchar *tmp = defaultdir;
450 defaultdir = g_strconcat(tmp, G_DIR_SEPARATOR_S, NULL);
453 g_debug("%s: defaultdir=%s", __FUNCTION__, defaultdir);
458 static void maps_layer_mkdir_if_default_dir ( VikMapsLayer *vml )
460 if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && g_file_test ( vml->cache_dir, G_FILE_TEST_EXISTS ) == FALSE )
462 g_mkdir ( vml->cache_dir, 0777 );
466 static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir )
468 g_assert ( vml != NULL);
469 g_free ( vml->cache_dir );
470 vml->cache_dir = NULL;
471 const gchar *mydir = dir;
473 if ( dir == NULL || dir[0] == '\0' )
475 if ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir") )
476 mydir = a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir")->s;
479 gchar *canonical_dir = vu_get_canonical_filename ( VIK_LAYER(vml), mydir );
481 // Ensure cache_dir always ends with a separator
482 guint len = strlen(canonical_dir);
483 if ( canonical_dir[len-1] != G_DIR_SEPARATOR )
485 vml->cache_dir = g_strconcat ( canonical_dir, G_DIR_SEPARATOR_S, NULL );
486 g_free ( canonical_dir );
489 vml->cache_dir = canonical_dir;
492 maps_layer_mkdir_if_default_dir ( vml );
495 static void maps_layer_set_file ( VikMapsLayer *vml, const gchar *name )
498 g_free (vml->filename);
499 vml->filename = g_strdup (name);
502 /****************************************/
503 /******** GOBJECT STUFF *****************/
504 /****************************************/
506 GType vik_maps_layer_get_type ()
508 static GType vml_type = 0;
512 static const GTypeInfo vml_info =
514 sizeof (VikMapsLayerClass),
515 NULL, /* base_init */
516 NULL, /* base_finalize */
517 NULL, /* class init */
518 NULL, /* class_finalize */
519 NULL, /* class_data */
520 sizeof (VikMapsLayer),
522 NULL /* instance init */
524 vml_type = g_type_register_static ( VIK_LAYER_TYPE, "VikMapsLayer", &vml_info, 0 );
530 /****************************************/
531 /************** PARAMETERS **************/
532 /****************************************/
534 static guint map_index_to_uniq_id (guint16 index)
536 g_assert ( index < NUM_MAP_TYPES );
537 return vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(index));
540 static guint map_uniq_id_to_index ( guint uniq_id )
543 for ( i = 0; i < NUM_MAP_TYPES; i++ )
544 if ( vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(i)) == uniq_id )
546 return NUM_MAP_TYPES; /* no such thing */
549 #define VIK_SETTINGS_MAP_LICENSE_SHOWN "map_license_shown"
552 * Convenience function to display the license
554 static void maps_show_license ( GtkWindow *parent, VikMapSource *map )
556 a_dialog_license ( parent,
557 vik_map_source_get_label (map),
558 vik_map_source_get_license (map),
559 vik_map_source_get_license_url (map) );
562 static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation )
566 case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break;
567 case PARAM_CACHE_LAYOUT: if ( data.u < VIK_MAPS_CACHE_LAYOUT_NUM ) vml->cache_layout = data.u; break;
568 case PARAM_FILE: maps_layer_set_file ( vml, data.s ); break;
569 case PARAM_MAPTYPE: {
570 gint maptype = map_uniq_id_to_index(data.u);
571 if ( maptype == NUM_MAP_TYPES )
572 g_warning(_("Unknown map type"));
574 vml->maptype = maptype;
576 // When loading from a file don't need the license reminder - ensure it's saved into the 'seen' list
577 if ( is_file_operation ) {
578 a_settings_set_integer_list_containing ( VIK_SETTINGS_MAP_LICENSE_SHOWN, data.u );
581 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
582 if (vik_map_source_get_license (map) != NULL) {
583 // Check if licence for this map type has been shown before
584 if ( ! a_settings_get_integer_list_contains ( VIK_SETTINGS_MAP_LICENSE_SHOWN, data.u ) ) {
586 maps_show_license ( VIK_GTK_WINDOW_FROM_WIDGET(vvp), map );
587 a_settings_set_integer_list_containing ( VIK_SETTINGS_MAP_LICENSE_SHOWN, data.u );
594 case PARAM_ALPHA: if ( data.u <= 255 ) vml->alpha = data.u; break;
595 case PARAM_AUTODOWNLOAD: vml->autodownload = data.b; break;
596 case PARAM_ONLYMISSING: vml->adl_only_missing = data.b; break;
597 case PARAM_MAPZOOM: if ( data.u < NUM_MAPZOOMS ) {
598 vml->mapzoom_id = data.u;
599 vml->xmapzoom = __mapzooms_x [data.u];
600 vml->ymapzoom = __mapzooms_y [data.u];
601 }else g_warning (_("Unknown Map Zoom")); break;
607 static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation )
609 VikLayerParamData rv;
612 case PARAM_CACHE_DIR:
614 gboolean set = FALSE;
615 /* Only save a blank when the map cache location equals the default
616 On reading in, when it is blank then the default is reconstructed
617 Since the default changes dependent on the user and OS, it means the resultant file is more portable */
618 if ( is_file_operation && vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 ) {
622 else if ( is_file_operation ) {
623 if ( a_vik_get_file_ref_format() == VIK_FILE_REF_FORMAT_RELATIVE ) {
624 gchar *cwd = g_get_current_dir();
626 rv.s = file_GetRelativeFilename ( cwd, vml->cache_dir );
627 if ( !rv.s ) rv.s = "";
633 rv.s = vml->cache_dir ? vml->cache_dir : "";
636 case PARAM_CACHE_LAYOUT: rv.u = vml->cache_layout; break;
637 case PARAM_FILE: rv.s = vml->filename; break;
638 case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break;
639 case PARAM_ALPHA: rv.u = vml->alpha; break;
640 case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break;
641 case PARAM_ONLYMISSING: rv.u = vml->adl_only_missing; break;
642 case PARAM_MAPZOOM: rv.u = vml->mapzoom_id; break;
648 static void maps_layer_change_param ( GtkWidget *widget, ui_change_values values )
650 switch ( GPOINTER_TO_INT(values[UI_CHG_PARAM_ID]) ) {
651 // Alter sensitivity of download option widgets according to the maptype setting.
652 case PARAM_MAPTYPE: {
654 VikLayerParamData vlpd = a_uibuilder_widget_get_value ( widget, values[UI_CHG_PARAM] );
655 // Is it *not* the OSM On Disk Tile Layout or the MBTiles type
656 gboolean sensitive = ( 21 != vlpd.u && 23 != vlpd.u);
657 GtkWidget **ww1 = values[UI_CHG_WIDGETS];
658 GtkWidget **ww2 = values[UI_CHG_LABELS];
659 GtkWidget *w1 = ww1[PARAM_ONLYMISSING];
660 GtkWidget *w2 = ww2[PARAM_ONLYMISSING];
661 GtkWidget *w3 = ww1[PARAM_AUTODOWNLOAD];
662 GtkWidget *w4 = ww2[PARAM_AUTODOWNLOAD];
663 // Depends on autodownload value
664 gboolean missing_sense = sensitive && VIK_MAPS_LAYER(values[UI_CHG_LAYER])->autodownload;
665 if ( w1 ) gtk_widget_set_sensitive ( w1, missing_sense );
666 if ( w2 ) gtk_widget_set_sensitive ( w2, missing_sense );
667 if ( w3 ) gtk_widget_set_sensitive ( w3, sensitive );
668 if ( w4 ) gtk_widget_set_sensitive ( w4, sensitive );
670 // Cache type not applicable either
671 GtkWidget *w9 = ww1[PARAM_CACHE_LAYOUT];
672 GtkWidget *w10 = ww2[PARAM_CACHE_LAYOUT];
673 if ( w9 ) gtk_widget_set_sensitive ( w9, sensitive );
674 if ( w10 ) gtk_widget_set_sensitive ( w10, sensitive );
676 // File only applicable for MBTiles type
677 // Directory for all other types
678 sensitive = ( 23 == vlpd.u);
679 GtkWidget *w5 = ww1[PARAM_FILE];
680 GtkWidget *w6 = ww2[PARAM_FILE];
681 GtkWidget *w7 = ww1[PARAM_CACHE_DIR];
682 GtkWidget *w8 = ww2[PARAM_CACHE_DIR];
683 if ( w5 ) gtk_widget_set_sensitive ( w5, sensitive );
684 if ( w6 ) gtk_widget_set_sensitive ( w6, sensitive );
685 if ( w7 ) gtk_widget_set_sensitive ( w7, !sensitive );
686 if ( w8 ) gtk_widget_set_sensitive ( w8, !sensitive );
691 // Alter sensitivity of 'download only missing' widgets according to the autodownload setting.
692 case PARAM_AUTODOWNLOAD: {
694 VikLayerParamData vlpd = a_uibuilder_widget_get_value ( widget, values[UI_CHG_PARAM] );
695 GtkWidget **ww1 = values[UI_CHG_WIDGETS];
696 GtkWidget **ww2 = values[UI_CHG_LABELS];
697 GtkWidget *w1 = ww1[PARAM_ONLYMISSING];
698 GtkWidget *w2 = ww2[PARAM_ONLYMISSING];
699 if ( w1 ) gtk_widget_set_sensitive ( w1, vlpd.b );
700 if ( w2 ) gtk_widget_set_sensitive ( w2, vlpd.b );
707 /****************************************/
708 /****** CREATING, COPYING, FREEING ******/
709 /****************************************/
711 static VikMapsLayer *maps_layer_new ( VikViewport *vvp )
713 VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) );
714 vik_layer_set_type ( VIK_LAYER(vml), VIK_LAYER_MAPS );
716 vik_layer_set_defaults ( VIK_LAYER(vml), vvp );
718 vml->dl_tool_x = vml->dl_tool_y = -1;
719 vml->last_center = NULL;
720 vml->last_xmpp = 0.0;
721 vml->last_ympp = 0.0;
723 vml->dl_right_click_menu = NULL;
724 vml->filename = NULL;
728 static void maps_layer_free ( VikMapsLayer *vml )
730 g_free ( vml->cache_dir );
731 vml->cache_dir = NULL;
732 if ( vml->dl_right_click_menu )
733 g_object_ref_sink ( G_OBJECT(vml->dl_right_click_menu) );
734 g_free(vml->last_center);
735 vml->last_center = NULL;
736 g_free ( vml->filename );
737 vml->filename = NULL;
739 #ifdef HAVE_SQLITE3_H
740 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
741 if ( vik_map_source_is_mbtiles ( map ) ) {
742 if ( vml->mbtiles ) {
743 int ans = sqlite3_close ( vml->mbtiles );
744 if ( ans != SQLITE_OK ) {
745 // Only to console for information purposes only
746 g_warning ( "SQL Close problem: %d", ans );
753 static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file)
755 VikMapsLayer *vml = VIK_MAPS_LAYER(vl);
756 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
758 if (from_file != TRUE)
760 /* If this method is not called in file reading context
761 * it is called in GUI context.
762 * So, we can check if we have to inform the user about inconsistency */
763 VikViewportDrawMode vp_drawmode;
764 vp_drawmode = vik_viewport_get_drawmode ( vp );
766 if (vik_map_source_get_drawmode(map) != vp_drawmode) {
767 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vp, vik_map_source_get_drawmode(map));
768 gchar *msg = g_strdup_printf(_("New map cannot be displayed in the current drawmode.\nSelect \"%s\" from View menu to view it."), drawmode_name);
769 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp), msg );
774 // Performed in post read as we now know the map type
775 #ifdef HAVE_SQLITE3_H
777 if ( vik_map_source_is_mbtiles ( map ) ) {
778 int ans = sqlite3_open_v2 ( vml->filename,
780 SQLITE_OPEN_READONLY,
782 if ( ans != SQLITE_OK ) {
783 // That didn't work, so here's why:
784 g_warning ( "%s: %s", __FUNCTION__, sqlite3_errmsg ( vml->mbtiles ) );
786 a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_WIDGET(vp),
787 _("Failed to open MBTiles file: %s"),
794 // If the on Disk OSM Tile Layout type
795 if ( vml->maptype == 21 )
796 // Copy the directory into filename
797 // thus the mapcache look up will be unique when using more than one of these map types
798 vml->filename = g_strdup (vml->cache_dir);
801 static const gchar* maps_layer_tooltip ( VikMapsLayer *vml )
803 return vik_maps_layer_get_map_label ( vml );
806 static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len )
808 vik_layer_marshall_params ( VIK_LAYER(vml), data, len );
811 static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
813 VikMapsLayer *rv = maps_layer_new ( vvp );
814 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
818 /*********************/
819 /****** DRAWING ******/
820 /*********************/
822 static GdkPixbuf *pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha )
825 gint width, height, iii, jjj;
827 if ( ! gdk_pixbuf_get_has_alpha ( pixbuf ) )
829 GdkPixbuf *tmp = gdk_pixbuf_add_alpha(pixbuf,FALSE,0,0,0);
830 g_object_unref(G_OBJECT(pixbuf));
836 pixels = gdk_pixbuf_get_pixels(pixbuf);
837 width = gdk_pixbuf_get_width(pixbuf);
838 height = gdk_pixbuf_get_height(pixbuf);
840 /* r,g,b,a,r,g,b,a.... */
841 for (iii = 0; iii < width; iii++) for (jjj = 0; jjj < height; jjj++)
849 static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdouble yshrinkfactor )
852 guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf);
853 tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_BILINEAR);
854 g_object_unref ( G_OBJECT(pixbuf) );
858 #ifdef HAVE_SQLITE3_H
860 static int sql_select_tile_dump_cb (void *data, int cols, char **fields, char **col_names )
862 g_warning ( "Found %d columns", cols );
864 for ( i = 0; i < cols; i++ ) {
865 g_warning ( "SQL processing %s = %s", col_names[i], fields[i] );
874 static GdkPixbuf *get_pixbuf_sql_exec ( sqlite3 *sql, gint xx, gint yy, gint zoom )
876 GdkPixbuf *pixbuf = NULL;
878 // MBTiles stored internally with the flipping y thingy (i.e. TMS scheme).
879 gint flip_y = (gint) pow(2, zoom)-1 - yy;
880 gchar *statement = g_strdup_printf ( "SELECT tile_data FROM tiles WHERE zoom_level=%d AND tile_column=%d AND tile_row=%d;", zoom, xx, flip_y );
882 gboolean finished = FALSE;
884 sqlite3_stmt *sql_stmt = NULL;
885 int ans = sqlite3_prepare_v2 ( sql, statement, -1, &sql_stmt, NULL );
886 if ( ans != SQLITE_OK ) {
887 g_warning ( "%s: %s - %d", __FUNCTION__, "prepare failure", ans );
891 while ( !finished ) {
892 ans = sqlite3_step ( sql_stmt );
895 // Get tile_data blob
896 int count = sqlite3_column_count(sql_stmt);
898 g_warning ( "%s: %s - %d", __FUNCTION__, "count not one", count );
902 const void *data = sqlite3_column_blob ( sql_stmt, 0 );
903 int bytes = sqlite3_column_bytes ( sql_stmt, 0 );
905 g_warning ( "%s: %s (%d)", __FUNCTION__, "not enough bytes", bytes );
909 // Convert these blob bytes into a pixbuf via these streaming operations
910 GInputStream *stream = g_memory_input_stream_new_from_data ( data, bytes, NULL );
911 GError *error = NULL;
912 pixbuf = gdk_pixbuf_new_from_stream ( stream, NULL, &error );
913 if (error || (!pixbuf)) {
914 g_warning ( "%s: %s", __FUNCTION__, error->message );
915 g_error_free ( error );
917 g_input_stream_close ( stream, NULL, NULL );
923 // e.g. SQLITE_DONE | SQLITE_ERROR | SQLITE_MISUSE | etc...
925 // and give up on any errors
926 if ( ans != SQLITE_DONE )
927 g_warning ( "%s: %s - %d", __FUNCTION__, "step issue", ans );
932 ans = sqlite3_finalize ( sql_stmt );
934 g_free ( statement );
940 static GdkPixbuf *get_mbtiles_pixbuf ( VikMapsLayer *vml, gint xx, gint yy, gint zoom )
942 GdkPixbuf *pixbuf = NULL;
944 #ifdef HAVE_SQLITE3_H
945 if ( vml->mbtiles ) {
947 gchar *statement = g_strdup_printf ( "SELECT name FROM sqlite_master WHERE type='table';" );
949 int ans = sqlite3_exec ( vml->mbtiles, statement, sql_select_tile_dump_cb, pixbuf, &errMsg );
950 if ( ans != SQLITE_OK ) {
951 // Only to console for information purposes only
952 g_warning ( "SQL problem: %d for %s - error: %s", ans, statement, errMsg );
953 sqlite3_free( errMsg );
955 g_free ( statement );
958 // Reading BLOBS is a bit more involved and so can't use the simpler sqlite3_exec ()
959 // Hence this specific function
960 pixbuf = get_pixbuf_sql_exec ( vml->mbtiles, xx, yy, zoom );
967 static GdkPixbuf *pixbuf_apply_settings ( GdkPixbuf *pixbuf, VikMapsLayer *vml, MapCoord *mapcoord, gdouble xshrinkfactor, gdouble yshrinkfactor )
969 // Apply alpha setting
970 if ( pixbuf && vml->alpha < 255 )
971 pixbuf = pixbuf_set_alpha ( pixbuf, vml->alpha );
973 if ( pixbuf && ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 ) )
974 pixbuf = pixbuf_shrink ( pixbuf, xshrinkfactor, yshrinkfactor );
977 a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y,
978 mapcoord->z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(vml->maptype)),
979 mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor, vml->filename );
984 static void get_filename ( const gchar *cache_dir,
985 VikMapsCacheLayout cl,
994 const gchar* file_extension )
997 case VIK_MAPS_CACHE_LAYOUT_OSM:
999 if ( g_strcmp0 ( cache_dir, MAPS_CACHE_DIR ) )
1000 // Cache dir not the default - assume it's been directed somewhere specific
1001 g_snprintf ( filename_buf, buf_len, DIRECTDIRACCESS, cache_dir, (17 - scale), x, y, file_extension );
1003 // Using default cache - so use the map name in the directory path
1004 g_snprintf ( filename_buf, buf_len, DIRECTDIRACCESS_WITH_NAME, cache_dir, name, (17 - scale), x, y, file_extension );
1007 g_snprintf ( filename_buf, buf_len, DIRECTDIRACCESS, cache_dir, (17 - scale), x, y, file_extension );
1010 g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE, cache_dir, id, scale, z, x, y );
1015 static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, guint16 id, const gchar* mapname, MapCoord *mapcoord, gchar *filename_buf, gint buf_len, gdouble xshrinkfactor, gdouble yshrinkfactor )
1020 pixbuf = a_mapcache_get ( mapcoord->x, mapcoord->y, mapcoord->z,
1021 id, mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor, vml->filename );
1024 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1025 if ( vik_map_source_is_direct_file_access(map) ) {
1026 // ATM MBTiles must be 'a direct access type'
1027 if ( vik_map_source_is_mbtiles(map) ) {
1028 pixbuf = get_mbtiles_pixbuf ( vml, mapcoord->x, mapcoord->y, (17 - mapcoord->scale) );
1029 pixbuf = pixbuf_apply_settings ( pixbuf, vml, mapcoord, xshrinkfactor, yshrinkfactor );
1030 // return now to avoid file tests that aren't appropriate for this map type
1034 get_filename ( vml->cache_dir, VIK_MAPS_CACHE_LAYOUT_OSM, id, NULL,
1035 mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y, filename_buf, buf_len,
1036 vik_map_source_get_file_extension(map) );
1039 get_filename ( vml->cache_dir, vml->cache_layout, id, mapname,
1040 mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y, filename_buf, buf_len,
1041 vik_map_source_get_file_extension(map) );
1043 if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
1046 pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx );
1048 /* free the pixbuf on error */
1051 if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE ) {
1053 if ( IS_VIK_WINDOW ((VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(vml)) ) {
1054 gchar* msg = g_strdup_printf ( _("Couldn't open image file: %s"), gx->message );
1055 vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(vml), msg, VIK_STATUSBAR_INFO );
1060 g_error_free ( gx );
1062 g_object_unref ( G_OBJECT(pixbuf) );
1065 pixbuf = pixbuf_apply_settings ( pixbuf, vml, mapcoord, xshrinkfactor, yshrinkfactor );
1072 static gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp)
1074 const VikCoord *center = vik_viewport_get_center ( vvp );
1076 if (vik_window_get_pan_move (VIK_WINDOW(VIK_GTK_WINDOW_FROM_WIDGET(GTK_WIDGET(vvp)))))
1077 /* D'n'D pan in action: do not download */
1080 // Don't attempt to download unsupported zoom levels
1081 gdouble xzoom = vik_viewport_get_xmpp ( vvp );
1082 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1083 guint8 zl = map_utils_mpp_to_zoom_level ( xzoom );
1084 if ( zl < vik_map_source_get_zoom_min(map) || zl > vik_map_source_get_zoom_max(map) )
1087 if (vml->last_center == NULL) {
1088 VikCoord *new_center = g_malloc(sizeof(VikCoord));
1089 *new_center = *center;
1090 vml->last_center = new_center;
1091 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
1092 vml->last_ympp = vik_viewport_get_ympp(vvp);
1096 /* TODO: perhaps vik_coord_diff() */
1097 if (vik_coord_equals(vml->last_center, center)
1098 && (vml->last_xmpp == vik_viewport_get_xmpp(vvp))
1099 && (vml->last_ympp == vik_viewport_get_ympp(vvp)))
1102 *(vml->last_center) = *center;
1103 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
1104 vml->last_ympp = vik_viewport_get_ympp(vvp);
1108 static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br )
1111 gdouble xzoom = vik_viewport_get_xmpp ( vvp );
1112 gdouble yzoom = vik_viewport_get_ympp ( vvp );
1113 gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0;
1114 gboolean existence_only = FALSE;
1116 if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) {
1117 xshrinkfactor = vml->xmapzoom / xzoom;
1118 yshrinkfactor = vml->ymapzoom / yzoom;
1119 xzoom = vml->xmapzoom;
1120 yzoom = vml->xmapzoom;
1121 if ( ! (xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR &&
1122 yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) ) {
1123 if ( xshrinkfactor > REAL_MIN_SHRINKFACTOR && yshrinkfactor > REAL_MIN_SHRINKFACTOR ) {
1124 g_debug ( "%s: existence_only due to SHRINKFACTORS", __FUNCTION__ );
1125 existence_only = TRUE;
1128 // Report the reason for not drawing
1129 if ( IS_VIK_WINDOW ((VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(vml)) ) {
1130 gchar* msg = g_strdup_printf ( _("Cowardly refusing to draw tiles or existence of tiles beyond %d zoom out factor"), (int)( 1.0/REAL_MIN_SHRINKFACTOR));
1131 vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(vml), msg, VIK_STATUSBAR_INFO );
1140 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1141 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm ) &&
1142 vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) ) {
1146 gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x);
1147 gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y);
1148 guint16 id = vik_map_source_get_uniq_id(map);
1149 const gchar *mapname = vik_map_source_get_name(map);
1152 gint xx, yy, width, height;
1155 // Prevent the program grinding to a halt if trying to deal with thousands of tiles
1156 // which can happen when using a small fixed zoom level and viewing large areas.
1157 // Also prevents very large number of tile download requests
1158 gint tiles = (xmax-xmin) * (ymax-ymin);
1159 if ( tiles > MAX_TILES ) {
1160 g_debug ( "%s: existence_only due to wanting too many tiles (%d)", __FUNCTION__, tiles );
1161 existence_only = TRUE;
1164 guint max_path_len = strlen(vml->cache_dir) + 40;
1165 gchar *path_buf = g_malloc ( max_path_len * sizeof(char) );
1167 if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) {
1168 g_debug("%s: Starting autodownload", __FUNCTION__);
1169 if ( !vml->adl_only_missing && vik_map_source_supports_download_only_new (map) )
1170 // Try to download newer tiles
1171 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
1173 // Download only missing tiles
1174 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
1177 if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) {
1178 for ( x = xmin; x <= xmax; x++ ) {
1179 for ( y = ymin; y <= ymax; y++ ) {
1182 pixbuf = get_pixbuf ( vml, id, mapname, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
1184 width = gdk_pixbuf_get_width ( pixbuf );
1185 height = gdk_pixbuf_get_height ( pixbuf );
1187 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
1188 vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy );
1192 vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height );
1196 } else { /* tilesize is known, don't have to keep converting coords */
1197 gdouble tilesize_x = vik_map_source_get_tilesize_x(map) * xshrinkfactor;
1198 gdouble tilesize_y = vik_map_source_get_tilesize_y(map) * yshrinkfactor;
1199 /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
1200 gint tilesize_x_ceil = ceil ( tilesize_x );
1201 gint tilesize_y_ceil = ceil ( tilesize_y );
1202 gint8 xinc = (ulm.x == xmin) ? 1 : -1;
1203 gint8 yinc = (ulm.y == ymin) ? 1 : -1;
1204 gint xx_tmp, yy_tmp;
1205 gint base_yy, xend, yend;
1207 xend = (xinc == 1) ? (xmax+1) : (xmin-1);
1208 yend = (yinc == 1) ? (ymax+1) : (ymin-1);
1210 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
1211 vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp );
1212 xx = xx_tmp; yy = yy_tmp;
1213 /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
1214 * eg if tile size 128, shrinkfactor 0.333 */
1215 xx -= (tilesize_x/2);
1216 base_yy = yy - (tilesize_y/2);
1218 for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) {
1220 for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) {
1224 if ( existence_only ) {
1225 if ( vik_map_source_is_direct_file_access (MAPS_LAYER_NTH_TYPE(vml->maptype)) )
1226 get_filename ( vml->cache_dir, VIK_MAPS_CACHE_LAYOUT_OSM, id, vik_map_source_get_name(map),
1227 ulm.scale, ulm.z, ulm.x, ulm.y, path_buf, max_path_len, vik_map_source_get_file_extension(map) );
1229 get_filename ( vml->cache_dir, vml->cache_layout, id, vik_map_source_get_name(map),
1230 ulm.scale, ulm.z, ulm.x, ulm.y, path_buf, max_path_len, vik_map_source_get_file_extension(map) );
1232 if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) {
1233 GdkGC *black_gc = gtk_widget_get_style(GTK_WIDGET(vvp))->black_gc;
1234 vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil );
1238 for (scale_inc = 0; scale_inc < 4; scale_inc ++) {
1239 /* try with correct then smaller zooms */
1240 int scale_factor = 1 << scale_inc; /* 2^scale_inc */
1241 MapCoord ulm2 = ulm;
1242 ulm2.x = ulm.x / scale_factor;
1243 ulm2.y = ulm.y / scale_factor;
1244 ulm2.scale = ulm.scale + scale_inc;
1245 pixbuf = get_pixbuf ( vml, id, mapname, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor );
1247 gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil;
1248 gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil;
1250 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);
1252 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
1257 /* retry with bigger zooms */
1259 for (scale_dec = 1; scale_dec < 2; scale_dec ++) {
1261 int scale_factor = 1 << scale_dec; /* 2^scale_dec */
1262 MapCoord ulm2 = ulm;
1263 ulm2.x = ulm.x * scale_factor;
1264 ulm2.y = ulm.y * scale_factor;
1265 ulm2.scale = ulm.scale - scale_dec;
1266 for (pict_x = 0; pict_x < scale_factor; pict_x ++) {
1267 for (pict_y = 0; pict_y < scale_factor; pict_y ++) {
1268 MapCoord ulm3 = ulm2;
1271 pixbuf = get_pixbuf ( vml, id, mapname, &ulm3, path_buf, max_path_len, xshrinkfactor / scale_factor, yshrinkfactor / scale_factor );
1275 gint dest_x = xx + pict_x * (tilesize_x_ceil / scale_factor);
1276 gint dest_y = yy + pict_y * (tilesize_y_ceil / scale_factor);
1277 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, dest_x, dest_y, tilesize_x_ceil / scale_factor, tilesize_y_ceil / scale_factor );
1291 g_free ( path_buf );
1295 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp )
1297 if ( vik_map_source_get_drawmode(MAPS_LAYER_NTH_TYPE(vml->maptype)) == vik_viewport_get_drawmode ( vvp ) )
1302 gdouble level = vik_viewport_get_zoom ( vvp );
1304 vik_viewport_get_min_max_lat_lon ( vvp, &bbox.south, &bbox.north, &bbox.west, &bbox.east );
1305 vik_map_source_get_copyright ( MAPS_LAYER_NTH_TYPE(vml->maptype), bbox, level, vik_viewport_add_copyright, vvp );
1308 const GdkPixbuf *logo = vik_map_source_get_logo ( MAPS_LAYER_NTH_TYPE(vml->maptype) );
1309 vik_viewport_add_logo ( vvp, logo );
1311 /* get corner coords */
1312 if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) {
1313 /* UTM multi-zone stuff by Kit Transue */
1314 gchar leftmost_zone, rightmost_zone, i;
1315 leftmost_zone = vik_viewport_leftmost_zone( vvp );
1316 rightmost_zone = vik_viewport_rightmost_zone( vvp );
1317 for ( i = leftmost_zone; i <= rightmost_zone; ++i ) {
1318 vik_viewport_corners_for_zonen ( vvp, i, &ul, &br );
1319 maps_layer_draw_section ( vml, vvp, &ul, &br );
1323 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1324 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1326 maps_layer_draw_section ( vml, vvp, &ul, &br );
1331 /*************************/
1332 /****** DOWNLOADING ******/
1333 /*************************/
1335 /* pass along data to thread, exists even if layer is deleted. */
1338 gchar *filename_buf;
1339 VikMapsCacheLayout cache_layout;
1340 gint x0, y0, xf, yf;
1346 gboolean refresh_display;
1349 gboolean map_layer_alive;
1353 static void mdi_free ( MapDownloadInfo *mdi )
1355 g_mutex_free(mdi->mutex);
1356 g_free ( mdi->cache_dir );
1357 mdi->cache_dir = NULL;
1358 g_free ( mdi->filename_buf );
1359 mdi->filename_buf = NULL;
1363 static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
1365 MapDownloadInfo *mdi = ptr;
1366 g_mutex_lock(mdi->mutex);
1367 mdi->map_layer_alive = FALSE;
1368 g_mutex_unlock(mdi->mutex);
1371 static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
1373 void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype));
1376 for ( x = mdi->x0; x <= mdi->xf; x++ )
1378 for ( y = mdi->y0; y <= mdi->yf; y++ )
1380 gboolean remove_mem_cache = FALSE;
1381 gboolean need_download = FALSE;
1383 get_filename ( mdi->cache_dir, mdi->cache_layout,
1384 vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
1385 vik_map_source_get_name(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
1386 mdi->mapcoord.scale, mdi->mapcoord.z, x, y, mdi->filename_buf, mdi->maxlen,
1387 vik_map_source_get_file_extension(MAPS_LAYER_NTH_TYPE(mdi->maptype)) );
1390 int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
1392 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
1396 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
1397 need_download = TRUE;
1398 remove_mem_cache = TRUE;
1400 } else { /* in case map file already exists */
1401 switch (mdi->redownload) {
1402 case REDOWNLOAD_NONE:
1405 case REDOWNLOAD_BAD:
1407 /* see if this one is bad or what */
1409 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
1410 if (gx || (!pixbuf)) {
1411 g_remove ( mdi->filename_buf );
1412 need_download = TRUE;
1413 remove_mem_cache = TRUE;
1414 g_error_free ( gx );
1417 g_object_unref ( pixbuf );
1422 case REDOWNLOAD_NEW:
1423 need_download = TRUE;
1424 remove_mem_cache = TRUE;
1427 case REDOWNLOAD_ALL:
1428 /* FIXME: need a better way than to erase file in case of server/network problem */
1429 g_remove ( mdi->filename_buf );
1430 need_download = TRUE;
1431 remove_mem_cache = TRUE;
1434 case DOWNLOAD_OR_REFRESH:
1435 remove_mem_cache = TRUE;
1439 g_warning ( "redownload state %d unknown\n", mdi->redownload);
1443 mdi->mapcoord.x = x; mdi->mapcoord.y = y;
1445 if (need_download) {
1446 DownloadResult_t dr = vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle);
1448 case DOWNLOAD_HTTP_ERROR:
1449 case DOWNLOAD_CONTENT_ERROR: {
1450 // TODO: ?? count up the number of download errors somehow...
1451 gchar* msg = g_strdup_printf ( "%s: %s", vik_maps_layer_get_map_label (mdi->vml), _("Failed to download tile") );
1452 vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(mdi->vml), msg, VIK_STATUSBAR_INFO );
1456 case DOWNLOAD_FILE_WRITE_ERROR: {
1457 gchar* msg = g_strdup_printf ( "%s: %s", vik_maps_layer_get_map_label (mdi->vml), _("Unable to save tile") );
1458 vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(mdi->vml), msg, VIK_STATUSBAR_INFO );
1462 case DOWNLOAD_SUCCESS:
1463 case DOWNLOAD_NOT_REQUIRED:
1469 g_mutex_lock(mdi->mutex);
1470 if (remove_mem_cache)
1471 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 );
1472 if (mdi->refresh_display && mdi->map_layer_alive) {
1473 /* TODO: check if it's on visible area */
1474 vik_layer_emit_update ( VIK_LAYER(mdi->vml) ); // NB update display from background
1476 g_mutex_unlock(mdi->mutex);
1477 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
1481 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
1482 g_mutex_lock(mdi->mutex);
1483 if (mdi->map_layer_alive)
1484 g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1485 g_mutex_unlock(mdi->mutex);
1489 static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
1491 if ( mdi->mapcoord.x || mdi->mapcoord.y )
1493 get_filename ( mdi->cache_dir, mdi->cache_layout,
1494 vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
1495 vik_map_source_get_name(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
1496 mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y, mdi->filename_buf, mdi->maxlen,
1497 vik_map_source_get_file_extension(MAPS_LAYER_NTH_TYPE(mdi->maptype)) );
1498 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
1500 g_remove ( mdi->filename_buf );
1505 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload )
1507 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1508 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1510 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1512 // Don't ever attempt download on direct access
1513 if ( vik_map_source_is_direct_file_access ( map ) )
1516 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm )
1517 && vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) )
1519 MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
1524 mdi->map_layer_alive = TRUE;
1525 mdi->mutex = g_mutex_new();
1526 mdi->refresh_display = TRUE;
1528 /* cache_dir and buffer for dest filename */
1529 mdi->cache_dir = g_strdup ( vml->cache_dir );
1530 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1531 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1532 mdi->cache_layout = vml->cache_layout;
1533 mdi->maptype = vml->maptype;
1535 mdi->mapcoord = ulm;
1536 mdi->redownload = redownload;
1538 mdi->x0 = MIN(ulm.x, brm.x);
1539 mdi->xf = MAX(ulm.x, brm.x);
1540 mdi->y0 = MIN(ulm.y, brm.y);
1541 mdi->yf = MAX(ulm.y, brm.y);
1545 if ( mdi->redownload ) {
1546 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
1548 /* calculate how many we need */
1549 for ( a = mdi->x0; a <= mdi->xf; a++ )
1551 for ( b = mdi->y0; b <= mdi->yf; b++ )
1553 get_filename ( mdi->cache_dir, mdi->cache_layout,
1554 vik_map_source_get_uniq_id(map),
1555 vik_map_source_get_name(map),
1556 ulm.scale, ulm.z, a, b, mdi->filename_buf, mdi->maxlen,
1557 vik_map_source_get_file_extension(map) );
1558 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1564 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1566 if ( mdi->mapstoget )
1568 const gchar *tmp_str;
1573 if (redownload == REDOWNLOAD_BAD)
1574 tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget);
1576 tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget);
1580 tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget);
1582 tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype));
1584 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1585 /* launch the thread */
1586 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1587 tmp, /* description string */
1588 (vik_thr_func) map_download_thread, /* function to call within thread */
1589 mdi, /* pass along data */
1590 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1591 (vik_thr_free_func) mdi_cancel_cleanup,
1600 static void maps_layer_download_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom, gint download_method )
1603 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1605 // Don't ever attempt download on direct access
1606 if ( vik_map_source_is_direct_file_access ( map ) )
1609 if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm)
1610 || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) {
1611 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
1615 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
1620 mdi->map_layer_alive = TRUE;
1621 mdi->mutex = g_mutex_new();
1622 mdi->refresh_display = TRUE;
1624 mdi->cache_dir = g_strdup ( vml->cache_dir );
1625 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1626 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1627 mdi->maptype = vml->maptype;
1628 mdi->cache_layout = vml->cache_layout;
1630 mdi->mapcoord = ulm;
1631 mdi->redownload = download_method;
1633 mdi->x0 = MIN(ulm.x, brm.x);
1634 mdi->xf = MAX(ulm.x, brm.x);
1635 mdi->y0 = MIN(ulm.y, brm.y);
1636 mdi->yf = MAX(ulm.y, brm.y);
1640 for (i = mdi->x0; i <= mdi->xf; i++) {
1641 for (j = mdi->y0; j <= mdi->yf; j++) {
1642 get_filename ( mdi->cache_dir, mdi->cache_layout,
1643 vik_map_source_get_uniq_id(map),
1644 vik_map_source_get_name(map),
1645 ulm.scale, ulm.z, i, j, mdi->filename_buf, mdi->maxlen,
1646 vik_map_source_get_file_extension(map) );
1647 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
1652 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1654 if (mdi->mapstoget) {
1657 fmt = ngettext("Downloading %d %s map...",
1658 "Downloading %d %s maps...",
1660 tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) );
1662 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1663 /* launch the thread */
1664 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1665 tmp, /* description string */
1666 (vik_thr_func) map_download_thread, /* function to call within thread */
1667 mdi, /* pass along data */
1668 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1669 (vik_thr_free_func) mdi_cancel_cleanup,
1678 * vik_maps_layer_download_section:
1679 * @vml: The Map Layer
1680 * @vvp: The Viewport that the map is on
1681 * @ul: Upper left coordinate of the area to be downloaded
1682 * @br: Bottom right coordinate of the area to be downloaded
1683 * @zoom: The zoom level at which the maps are to be download
1685 * Download a specified map area at a certain zoom level
1687 void vik_maps_layer_download_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom )
1689 maps_layer_download_section (vml, vvp, ul, br, zoom, REDOWNLOAD_NONE);
1692 static void maps_layer_redownload_bad ( VikMapsLayer *vml )
1694 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
1697 static void maps_layer_redownload_all ( VikMapsLayer *vml )
1699 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
1702 static void maps_layer_redownload_new ( VikMapsLayer *vml )
1704 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
1708 * Display a simple dialog with information about this particular map tile
1710 static void maps_layer_tile_info ( VikMapsLayer *vml )
1712 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1714 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vml->redownload_vvp );
1715 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vml->redownload_vvp );
1718 if ( !vik_map_source_coord_to_mapcoord ( map, &(vml->redownload_ul), xzoom, yzoom, &ulm ) )
1721 gchar *filename = NULL;
1722 gchar *message = NULL;
1723 gchar *source = NULL;
1725 if ( vik_map_source_is_direct_file_access ( map ) ) {
1726 if ( vik_map_source_is_mbtiles ( map ) ) {
1727 filename = g_strdup ( vml->filename );
1728 #ifdef HAVE_SQLITE3_H
1729 // And whether to bother going into the SQL to check it's really there or not...
1730 gchar *exists = NULL;
1731 gint zoom = 17 - ulm.scale;
1732 if ( vml->mbtiles ) {
1733 GdkPixbuf *pixbuf = get_pixbuf_sql_exec ( vml->mbtiles, ulm.x, ulm.y, zoom );
1735 exists = g_strdup ( _("YES") );
1736 g_object_unref ( G_OBJECT(pixbuf) );
1739 exists = g_strdup ( _("NO") );
1743 exists = g_strdup ( _("NO") );
1744 gint flip_y = (gint) pow(2, zoom)-1 - ulm.y;
1745 // NB Also handles .jpg automatically due to pixbuf_new_from () support - although just print png for now.
1746 source = g_strdup_printf ( "%s (%d%s%d%s%d.%s %s)", filename, zoom, G_DIR_SEPARATOR_S, ulm.x, G_DIR_SEPARATOR_S, flip_y, "png", exists );
1749 source = g_strdup ( _("Not available") );
1753 guint max_path_len = strlen(vml->cache_dir) + 40;
1754 filename = g_malloc ( max_path_len * sizeof(char) );
1755 get_filename ( vml->cache_dir, VIK_MAPS_CACHE_LAYOUT_OSM,
1756 vik_map_source_get_uniq_id(map),
1758 ulm.scale, ulm.z, ulm.x, ulm.y, filename, max_path_len,
1759 vik_map_source_get_file_extension(map) );
1760 source = g_strconcat ( "file://", filename, NULL );
1764 guint max_path_len = strlen(vml->cache_dir) + 40;
1765 filename = g_malloc ( max_path_len * sizeof(char) );
1766 get_filename ( vml->cache_dir, vml->cache_layout,
1767 vik_map_source_get_uniq_id(map),
1768 vik_map_source_get_name(map),
1769 ulm.scale, ulm.z, ulm.x, ulm.y, filename, max_path_len,
1770 vik_map_source_get_file_extension(map) );
1771 source = g_strdup_printf ( "http://%s%s",
1772 vik_map_source_default_get_hostname ( VIK_MAP_SOURCE_DEFAULT(map) ),
1773 vik_map_source_default_get_uri ( VIK_MAP_SOURCE_DEFAULT(map), &ulm ) );
1776 if ( g_file_test ( filename, G_FILE_TEST_EXISTS ) ) {
1778 // Get some timestamp information of the tile
1779 struct stat stat_buf;
1780 if ( g_stat ( filename, &stat_buf ) == 0 ) {
1782 strftime ( time_buf, sizeof(time_buf), "%c", gmtime((const time_t *)&stat_buf.st_mtime) );
1783 message = g_strdup_printf ( _("\nSource: %s\n\nTile File: %s\nTile File Timestamp: %s"), source, filename, time_buf );
1786 message = g_strdup_printf ( _("\nSource: %s\n\nTile File: %s\nTile File Timestamp: Not Available"), source, filename );
1789 a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), message );
1792 message = g_strdup_printf ( _("\nSource: %s\n\nTile File: %s [Not Available]"), source, filename );
1793 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), message );
1798 g_free ( filename );
1801 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1803 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1805 if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 )
1807 if ( event->button == 1 )
1810 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 );
1811 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 );
1812 start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
1813 vml->dl_tool_x = vml->dl_tool_y = -1;
1818 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) );
1819 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) );
1821 vml->redownload_vvp = vvp;
1823 vml->dl_tool_x = vml->dl_tool_y = -1;
1825 if ( ! vml->dl_right_click_menu ) {
1827 vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () );
1829 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _Bad Map(s)") );
1830 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
1831 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1833 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _New Map(s)") );
1834 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
1835 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1837 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _All Map(s)") );
1838 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
1839 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1841 item = gtk_image_menu_item_new_with_mnemonic ( _("_Show Tile Information") );
1842 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_MENU) );
1843 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_tile_info), vml );
1844 gtk_menu_shell_append (GTK_MENU_SHELL(vml->dl_right_click_menu), item);
1847 gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
1848 gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) );
1854 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1859 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1862 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1864 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1865 if ( vik_map_source_get_drawmode(map) == vik_viewport_get_drawmode ( vvp ) &&
1866 vik_map_source_coord_to_mapcoord ( map, vik_viewport_get_center ( vvp ),
1867 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1868 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1870 vml->dl_tool_x = event->x, vml->dl_tool_y = event->y;
1876 // A slightly better way of defining the menu callback information
1877 // This should be easier to extend/rework compared to previously
1884 typedef gpointer menu_array_values[MA_LAST];
1886 static void download_onscreen_maps ( menu_array_values values, gint redownload )
1888 VikMapsLayer *vml = VIK_MAPS_LAYER(values[MA_VML]);
1889 VikViewport *vvp = VIK_VIEWPORT(values[MA_VVP]);
1890 VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
1892 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1893 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1898 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1899 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1901 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1902 if ( vik_map_source_get_drawmode(map) == vp_drawmode &&
1903 vik_map_source_coord_to_mapcoord ( map, &ul, xzoom, yzoom, &ulm ) &&
1904 vik_map_source_coord_to_mapcoord ( map, &br, xzoom, yzoom, &brm ) )
1905 start_download_thread ( vml, vvp, &ul, &br, redownload );
1906 else if (vik_map_source_get_drawmode(map) != vp_drawmode) {
1907 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, vik_map_source_get_drawmode(map));
1908 gchar *err = g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name));
1909 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1913 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Wrong zoom level for this map.") );
1917 static void maps_layer_download_missing_onscreen_maps ( menu_array_values values )
1919 download_onscreen_maps( values, REDOWNLOAD_NONE);
1922 static void maps_layer_download_new_onscreen_maps ( menu_array_values values )
1924 download_onscreen_maps( values, REDOWNLOAD_NEW);
1927 static void maps_layer_redownload_all_onscreen_maps ( menu_array_values values )
1929 download_onscreen_maps( values, REDOWNLOAD_ALL);
1932 static void maps_layers_about ( gpointer vml_vvp[2] )
1934 VikMapsLayer *vml = vml_vvp[0];
1935 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1937 if ( vik_map_source_get_license (map) )
1938 maps_show_license ( VIK_GTK_WINDOW_FROM_LAYER(vml), map );
1940 a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml),
1941 vik_map_source_get_label (map) );
1945 * maps_layer_how_many_maps:
1946 * Copied from maps_layer_download_section but without the actual download and this returns a value
1948 static gint maps_layer_how_many_maps ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom, gint redownload )
1951 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1953 if ( vik_map_source_is_direct_file_access ( map ) )
1956 if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm)
1957 || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) {
1958 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
1962 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
1967 mdi->map_layer_alive = TRUE;
1968 mdi->mutex = g_mutex_new();
1969 mdi->refresh_display = FALSE;
1971 mdi->cache_dir = g_strdup ( vml->cache_dir );
1972 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1973 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1974 mdi->maptype = vml->maptype;
1975 mdi->cache_layout = vml->cache_layout;
1977 mdi->mapcoord = ulm;
1978 mdi->redownload = redownload;
1980 mdi->x0 = MIN(ulm.x, brm.x);
1981 mdi->xf = MAX(ulm.x, brm.x);
1982 mdi->y0 = MIN(ulm.y, brm.y);
1983 mdi->yf = MAX(ulm.y, brm.y);
1987 if ( mdi->redownload == REDOWNLOAD_ALL ) {
1988 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
1991 /* calculate how many we need */
1992 for (i = mdi->x0; i <= mdi->xf; i++) {
1993 for (j = mdi->y0; j <= mdi->yf; j++) {
1994 get_filename ( mdi->cache_dir, mdi->cache_layout,
1995 vik_map_source_get_uniq_id(map),
1996 vik_map_source_get_name(map),
1997 ulm.scale, ulm.z, i, j, mdi->filename_buf, mdi->maxlen,
1998 vik_map_source_get_file_extension(map) );
1999 if ( mdi->redownload == REDOWNLOAD_NEW ) {
2000 // Assume the worst - always a new file
2001 // Absolute value would requires server lookup - but that is too slow
2005 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
2010 if ( mdi->redownload == REDOWNLOAD_BAD ) {
2011 /* see if this one is bad or what */
2013 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
2014 if (gx || (!pixbuf)) {
2018 // Other download cases already considered or just ignored
2026 gint rv = mdi->mapstoget;
2034 * maps_dialog_zoom_between:
2035 * This dialog is specific to the map layer, so it's here rather than in dialog.c
2037 gboolean maps_dialog_zoom_between ( GtkWindow *parent,
2042 gint *selected_zoom1,
2043 gint *selected_zoom2,
2044 gchar *download_list[],
2045 gint default_download,
2046 gint *selected_download )
2048 GtkWidget *dialog = gtk_dialog_new_with_buttons ( title,
2050 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
2051 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2052 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
2054 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
2055 GtkWidget *response_w = NULL;
2056 #if GTK_CHECK_VERSION (2, 20, 0)
2057 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
2059 GtkWidget *zoom_label1 = gtk_label_new ( _("Zoom Start:") );
2060 GtkWidget *zoom_combo1 = vik_combo_box_text_new();
2062 for (s = zoom_list; *s; s++)
2063 vik_combo_box_text_append ( zoom_combo1, *s );
2064 gtk_combo_box_set_active ( GTK_COMBO_BOX(zoom_combo1), default_zoom1 );
2066 GtkWidget *zoom_label2 = gtk_label_new ( _("Zoom End:") );
2067 GtkWidget *zoom_combo2 = vik_combo_box_text_new();
2068 for (s = zoom_list; *s; s++)
2069 vik_combo_box_text_append ( zoom_combo2, *s );
2070 gtk_combo_box_set_active ( GTK_COMBO_BOX(zoom_combo2), default_zoom2 );
2072 GtkWidget *download_label = gtk_label_new(_("Download Maps Method:"));
2073 GtkWidget *download_combo = vik_combo_box_text_new();
2074 for (s = download_list; *s; s++)
2075 vik_combo_box_text_append ( download_combo, *s );
2076 gtk_combo_box_set_active ( GTK_COMBO_BOX(download_combo), default_download );
2078 GtkTable *box = GTK_TABLE(gtk_table_new(3, 2, FALSE));
2079 gtk_table_attach_defaults (box, GTK_WIDGET(zoom_label1), 0, 1, 0, 1);
2080 gtk_table_attach_defaults (box, GTK_WIDGET(zoom_combo1), 1, 2, 0, 1);
2081 gtk_table_attach_defaults (box, GTK_WIDGET(zoom_label2), 0, 1, 1, 2);
2082 gtk_table_attach_defaults (box, GTK_WIDGET(zoom_combo2), 1, 2, 1, 2);
2083 gtk_table_attach_defaults (box, GTK_WIDGET(download_label), 0, 1, 2, 3);
2084 gtk_table_attach_defaults (box, GTK_WIDGET(download_combo), 1, 2, 2, 3);
2086 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), GTK_WIDGET(box), FALSE, FALSE, 5 );
2089 gtk_widget_grab_focus ( response_w );
2091 gtk_widget_show_all ( dialog );
2092 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) != GTK_RESPONSE_ACCEPT ) {
2093 gtk_widget_destroy(dialog);
2097 // Return selected options
2098 *selected_zoom1 = gtk_combo_box_get_active ( GTK_COMBO_BOX(zoom_combo1) );
2099 *selected_zoom2 = gtk_combo_box_get_active ( GTK_COMBO_BOX(zoom_combo2) );
2100 *selected_download = gtk_combo_box_get_active ( GTK_COMBO_BOX(download_combo) );
2102 gtk_widget_destroy(dialog);
2106 // My best guess of sensible limits
2107 #define REALLY_LARGE_AMOUNT_OF_TILES 5000
2108 #define CONFIRM_LARGE_AMOUNT_OF_TILES 500
2111 * Get all maps in the region for zoom levels specified by the user
2112 * Sort of similar to trw_layer_download_map_along_track_cb function
2114 static void maps_layer_download_all ( menu_array_values values )
2116 VikMapsLayer *vml = VIK_MAPS_LAYER(values[MA_VML]);
2117 VikViewport *vvp = VIK_VIEWPORT(values[MA_VVP]);
2119 // I don't think we should allow users to hammer the servers too much...
2120 // Delibrately not allowing lowest zoom levels
2121 // Still can give massive numbers to download
2122 // A screen size of 1600x1200 gives around 300,000 tiles between 1..128 when none exist before !!
2123 gchar *zoom_list[] = {"1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", NULL };
2124 gdouble zoom_vals[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
2126 gint selected_zoom1, selected_zoom2, default_zoom, lower_zoom;
2127 gint selected_download_method;
2129 gdouble cur_zoom = vik_viewport_get_zoom(vvp);
2131 for (default_zoom = 0; default_zoom < sizeof(zoom_vals)/sizeof(gdouble); default_zoom++) {
2132 if (cur_zoom == zoom_vals[default_zoom])
2135 default_zoom = (default_zoom == sizeof(zoom_vals)/sizeof(gdouble)) ? sizeof(zoom_vals)/sizeof(gdouble) - 1 : default_zoom;
2137 // Default to only 2 zoom levels below the current one
2138 if (default_zoom > 1 )
2139 lower_zoom = default_zoom - 2;
2141 lower_zoom = default_zoom;
2143 // redownload method - needs to align with REDOWNLOAD* macro values
2144 gchar *download_list[] = { _("Missing"), _("Bad"), _("New"), _("Reload All"), NULL };
2146 gchar *title = g_strdup_printf ( ("%s: %s"), vik_maps_layer_get_map_label (vml), _("Download for Zoom Levels") );
2148 if ( ! maps_dialog_zoom_between ( VIK_GTK_WINDOW_FROM_LAYER(vml),
2156 REDOWNLOAD_NONE, // AKA Missing
2157 &selected_download_method ) ) {
2164 // Find out new current positions
2165 gdouble min_lat, max_lat, min_lon, max_lon;
2166 VikCoord vc_ul, vc_br;
2167 vik_viewport_get_min_max_lat_lon ( vvp, &min_lat, &max_lat, &min_lon, &max_lon );
2168 struct LatLon ll_ul = { max_lat, min_lon };
2169 struct LatLon ll_br = { min_lat, max_lon };
2170 vik_coord_load_from_latlon ( &vc_ul, vik_viewport_get_coord_mode (vvp), &ll_ul );
2171 vik_coord_load_from_latlon ( &vc_br, vik_viewport_get_coord_mode (vvp), &ll_br );
2173 // Get Maps Count - call for each zoom level (in reverse)
2174 // With REDOWNLOAD_NEW this is a possible maximum
2175 // With REDOWNLOAD_NONE this only missing ones - however still has a server lookup per tile
2178 for ( zz = selected_zoom2; zz >= selected_zoom1; zz-- ) {
2179 map_count = map_count + maps_layer_how_many_maps ( vml, vvp, &vc_ul, &vc_br, zoom_vals[zz], selected_download_method );
2182 g_debug ("vikmapslayer: download request map count %d for method %d", map_count, selected_download_method);
2184 // Absolute protection of hammering a map server
2185 if ( map_count > REALLY_LARGE_AMOUNT_OF_TILES ) {
2186 gchar *str = g_strdup_printf (_("You are not allowed to download more than %d tiles in one go (requested %d)"), REALLY_LARGE_AMOUNT_OF_TILES, map_count);
2187 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), str );
2192 // Confirm really want to do this
2193 if ( map_count > CONFIRM_LARGE_AMOUNT_OF_TILES ) {
2194 gchar *str = g_strdup_printf (_("Do you really want to download %d tiles?"), map_count);
2195 gboolean ans = a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vml), str, NULL );
2201 // Get Maps - call for each zoom level (in reverse)
2202 for ( zz = selected_zoom2; zz >= selected_zoom1; zz-- ) {
2203 maps_layer_download_section ( vml, vvp, &vc_ul, &vc_br, zoom_vals[zz], selected_download_method );
2207 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp )
2210 static menu_array_values values;
2211 values[MA_VML] = vml;
2212 values[MA_VVP] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) );
2214 item = gtk_menu_item_new();
2215 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
2216 gtk_widget_show ( item );
2218 /* Now with icons */
2219 item = gtk_image_menu_item_new_with_mnemonic ( _("Download _Missing Onscreen Maps") );
2220 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) );
2221 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), values );
2222 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2223 gtk_widget_show ( item );
2225 if ( vik_map_source_supports_download_only_new (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) {
2226 item = gtk_image_menu_item_new_with_mnemonic ( _("Download _New Onscreen Maps") );
2227 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REDO, GTK_ICON_SIZE_MENU) );
2228 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), values );
2229 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2230 gtk_widget_show ( item );
2233 item = gtk_image_menu_item_new_with_mnemonic ( _("Reload _All Onscreen Maps") );
2234 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) );
2235 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), values );
2236 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2237 gtk_widget_show ( item );
2239 item = gtk_image_menu_item_new_with_mnemonic ( _("Download Maps in _Zoom Levels...") );
2240 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_DND_MULTIPLE, GTK_ICON_SIZE_MENU) );
2241 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_all), values );
2242 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2243 gtk_widget_show ( item );
2245 item = gtk_image_menu_item_new_from_stock ( GTK_STOCK_ABOUT, NULL );
2246 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layers_about), values );
2247 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
2248 gtk_widget_show ( item );
2252 * Enable downloading maps of the current screen area either 'new' or 'everything'
2254 void vik_maps_layer_download ( VikMapsLayer *vml, VikViewport *vvp, gboolean only_new )
2259 static menu_array_values values;
2260 values[MA_VML] = vml;
2261 values[MA_VVP] = vvp;
2264 // Get only new maps
2265 maps_layer_download_new_onscreen_maps ( values );
2267 // Redownload everything
2268 maps_layer_redownload_all_onscreen_maps ( values );