]> git.street.me.uk Git - andy/viking.git/blame - src/vikmapslayer.c
Remove direct access for '->style' and replace with gtk_widget_get_style()
[andy/viking.git] / src / vikmapslayer.c
CommitLineData
50a14534
EB
1/*
2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3 *
4 * Copyright (C) 2005, Evan Battaglia <viking@greentorch.org>
a8876892 5 * Copyright (C) 2010, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
50a14534 6 * UTM multi-zone stuff by Kit Transue <notlostyet@didactek.com>
cdcaf41c 7 * Dynamic map type by Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
50a14534
EB
8 *
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.
13 *
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.
18 *
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
22 *
23 */
24
4c77d5e0
GB
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
50a14534
EB
29#define MAX_SHRINKFACTOR 8.0000001 /* zoom 1 viewing 8-tiles */
30#define MIN_SHRINKFACTOR 0.0312499 /* zoom 32 viewing 1-tiles */
31
732d1e25
EB
32#define REAL_MIN_SHRINKFACTOR 0.0039062499 /* if shrinkfactor is between MAX and REAL_MAX, will only check for existence */
33
50a14534
EB
34#include <gtk/gtk.h>
35#include <gdk-pixbuf/gdk-pixdata.h>
45acf79e
MA
36#include <glib.h>
37#include <glib/gstdio.h>
4c77d5e0
GB
38#include <glib/gi18n.h>
39
8c00358d 40#ifdef HAVE_STRING_H
50a14534 41#include <string.h>
8c00358d
GB
42#endif
43#ifdef HAVE_MATH_H
50a14534 44#include <math.h>
8c00358d
GB
45#endif
46
50a14534 47#include "globals.h"
53ac8302 48#include "util.h"
50a14534
EB
49#include "coords.h"
50#include "vikcoord.h"
51#include "viktreeview.h"
52#include "vikviewport.h"
53#include "viklayer.h"
54#include "vikmapslayer.h"
50a14534 55
45acf79e 56#ifdef HAVE_UNISTD_H
50a14534 57#include <unistd.h>
45acf79e 58#endif
50a14534 59
450d8665 60#include "vikmapsourcedefault.h"
50a14534
EB
61#include "mapcache.h"
62/* only for dialog.h -- ugh */
63#include "vikwaypoint.h"
64#include "dialog.h"
55ddef4e 65#include "preferences.h"
50a14534
EB
66
67#include "vikstatus.h"
68#include "background.h"
69
70#include "vikaggregatelayer.h"
71#include "viklayerspanel.h"
72
73#include "mapcoord.h"
50a14534 74
bce3a7b0
EB
75#include "icons/icons.h"
76
50a14534
EB
77/****** MAP TYPES ******/
78
cdcaf41c
QT
79static GList *__map_types = NULL;
80
81#define NUM_MAP_TYPES g_list_length(__map_types)
50a14534 82
cdcaf41c 83/* List of label for each map type */
a8876892 84static gchar **params_maptypes = NULL;
cdcaf41c
QT
85
86/* Corresponding IDS. (Cf. field uniq_id in VikMapsLayer struct) */
a8876892 87static guint *params_maptypes_ids = NULL;
50a14534
EB
88
89/******** MAPZOOMS *********/
90
fcc2786b
SW
91static 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 };
92static 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 };
93static 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 };
50a14534 94
d756fb5c 95#define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0]) - 1)
50a14534
EB
96
97/**************************/
98
99
07059501 100static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file);
7924723c 101static const gchar* maps_layer_tooltip ( VikMapsLayer *vml );
911400b5
AF
102static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len );
103static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
158b3642
RN
104static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation );
105static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation );
50a14534
EB
106static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp );
107static VikMapsLayer *maps_layer_new ( VikViewport *vvp );
108static void maps_layer_free ( VikMapsLayer *vml );
109static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
110static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
941aa6e9 111static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp );
50a14534
EB
112static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir );
113static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload );
114static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp );
e2cb421f 115static guint map_uniq_id_to_index ( guint uniq_id );
50a14534
EB
116
117
118static VikLayerParamScale params_scales[] = {
119 /* min, max, step, digits (decimal places) */
120 { 0, 255, 3, 0 }, /* alpha */
121};
122
123VikLayerParam maps_layer_params[] = {
e6994d8d
RN
124 { "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Map Type:"), VIK_LAYER_WIDGET_COMBOBOX, NULL, NULL, NULL },
125 { "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Maps Directory:"), VIK_LAYER_WIDGET_FOLDERENTRY, NULL, NULL, NULL },
126 { "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales, NULL,
127 N_("Control the Alpha value for transparency effects") },
128 { "autodownload", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload maps:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL },
382566c3
RN
129 { "adlonlymissing", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload Only Gets Missing Maps:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL,
130 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.") },
e6994d8d
RN
131 { "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms, NULL,
132 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.") },
50a14534
EB
133};
134
382566c3
RN
135enum {
136 PARAM_MAPTYPE=0,
137 PARAM_CACHE_DIR,
138 PARAM_ALPHA,
139 PARAM_AUTODOWNLOAD,
140 PARAM_ONLYMISSING,
141 PARAM_MAPZOOM,
142 NUM_PARAMS
143};
50a14534
EB
144
145static VikToolInterface maps_tools[] = {
79dce0cb 146 { { "MapsDownload", "vik-icon-Maps Download", N_("_Maps Download"), NULL, N_("Maps Download"), 0 },
6b59f63d
RN
147 (VikToolConstructorFunc) maps_layer_download_create,
148 NULL,
149 NULL,
150 NULL,
151 (VikToolMouseFunc) maps_layer_download_click,
152 NULL,
153 (VikToolMouseFunc) maps_layer_download_release,
154 NULL,
ef5e8132
RN
155 FALSE,
156 GDK_CURSOR_IS_PIXMAP, &cursor_mapdl_pixbuf },
50a14534
EB
157};
158
159VikLayerInterface vik_maps_layer_interface = {
db386630 160 "Map",
4c77d5e0 161 N_("Map"),
75078768 162 "<control><shift>M",
5bfafde9 163 &vikmapslayer_pixbuf,
50a14534
EB
164
165 maps_tools,
166 sizeof(maps_tools) / sizeof(maps_tools[0]),
167
168 maps_layer_params,
169 NUM_PARAMS,
170 NULL,
171 0,
172
5a4a28bf
QT
173 VIK_MENU_ITEM_ALL,
174
50a14534
EB
175 (VikLayerFuncCreate) maps_layer_new,
176 (VikLayerFuncRealize) NULL,
b112cbf5 177 (VikLayerFuncPostRead) maps_layer_post_read,
50a14534
EB
178 (VikLayerFuncFree) maps_layer_free,
179
180 (VikLayerFuncProperties) NULL,
181 (VikLayerFuncDraw) maps_layer_draw,
182 (VikLayerFuncChangeCoordMode) NULL,
183
20c7a3a0
QT
184 (VikLayerFuncSetMenuItemsSelection) NULL,
185 (VikLayerFuncGetMenuItemsSelection) NULL,
186
50a14534
EB
187 (VikLayerFuncAddMenuItems) maps_layer_add_menu_items,
188 (VikLayerFuncSublayerAddMenuItems) NULL,
189
190 (VikLayerFuncSublayerRenameRequest) NULL,
191 (VikLayerFuncSublayerToggleVisible) NULL,
9da7faf2 192 (VikLayerFuncSublayerTooltip) NULL,
7924723c 193 (VikLayerFuncLayerTooltip) maps_layer_tooltip,
a5dcfdb7 194 (VikLayerFuncLayerSelected) NULL,
50a14534 195
911400b5
AF
196 (VikLayerFuncMarshall) maps_layer_marshall,
197 (VikLayerFuncUnmarshall) maps_layer_unmarshall,
50a14534
EB
198
199 (VikLayerFuncSetParam) maps_layer_set_param,
200 (VikLayerFuncGetParam) maps_layer_get_param,
201
202 (VikLayerFuncReadFileData) NULL,
203 (VikLayerFuncWriteFileData) NULL,
204
33534cd8 205 (VikLayerFuncDeleteItem) NULL,
d5874ef9 206 (VikLayerFuncCutItem) NULL,
50a14534
EB
207 (VikLayerFuncCopyItem) NULL,
208 (VikLayerFuncPasteItem) NULL,
209 (VikLayerFuncFreeCopiedItem) NULL,
70a23263 210 (VikLayerFuncDragDropRequest) NULL,
77ad64fa
RN
211
212 (VikLayerFuncSelectClick) NULL,
08f14055
RN
213 (VikLayerFuncSelectMove) NULL,
214 (VikLayerFuncSelectRelease) NULL,
e46f259a 215 (VikLayerFuncSelectedViewportMenu) NULL,
50a14534
EB
216};
217
218struct _VikMapsLayer {
219 VikLayer vl;
220 guint maptype;
221 gchar *cache_dir;
222 guint8 alpha;
223 guint mapzoom_id;
224 gdouble xmapzoom, ymapzoom;
225
226 gboolean autodownload;
382566c3 227 gboolean adl_only_missing;
10ca2bfe
QT
228 VikCoord *last_center;
229 gdouble last_xmpp;
230 gdouble last_ympp;
50a14534
EB
231
232 gint dl_tool_x, dl_tool_y;
233
234 GtkMenu *dl_right_click_menu;
235 VikCoord redownload_ul, redownload_br; /* right click menu only */
236 VikViewport *redownload_vvp;
8e507445
RN
237
238 gboolean license_notice_shown; // FALSE for new maps only, otherwise
239 // TRUE for saved maps & other layer changes as we don't need to show it again
50a14534
EB
240};
241
6a4a29aa
JJ
242enum { REDOWNLOAD_NONE = 0, /* download only missing maps */
243 REDOWNLOAD_BAD, /* download missing and bad maps */
244 REDOWNLOAD_NEW, /* download missing maps that are newer on server only */
245 REDOWNLOAD_ALL, /* download all maps */
246 DOWNLOAD_OR_REFRESH }; /* download missing maps and refresh cache */
50a14534 247
55ddef4e 248static VikLayerParam prefs[] = {
e6994d8d 249 { VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Default maplayer directory:"), VIK_LAYER_WIDGET_FOLDERENTRY, NULL, NULL, N_("Choose a directory to store cached Map tiles for this layer") },
55ddef4e
JJ
250};
251
252void maps_layer_init ()
253{
254 VikLayerParamData tmp;
255 tmp.s = maps_layer_default_dir();
256 a_preferences_register(prefs, tmp, VIKING_PREFERENCES_GROUP_KEY);
257}
50a14534 258
cdcaf41c
QT
259/****************************************/
260/******** MAPS LAYER TYPES **************/
261/****************************************/
262
e2cb421f 263int _get_index_for_id ( guint id )
cdcaf41c 264{
e2cb421f
GB
265 int index = 0 ;
266 while (params_maptypes_ids[index] != 0)
267 {
268 if (params_maptypes_ids[index] == id)
269 return index;
270 index++;
271 }
272 return -1;
273}
cdcaf41c 274
e2cb421f
GB
275void _add_map_source ( guint id, const char *label, VikMapSource *map )
276{
a8876892
GB
277 gsize len = 0;
278 if (params_maptypes)
279 len = g_strv_length (params_maptypes);
cdcaf41c 280 /* Add the label */
a8876892
GB
281 params_maptypes = g_realloc (params_maptypes, (len+2)*sizeof(gchar*));
282 params_maptypes[len] = g_strdup (label);
283 params_maptypes[len+1] = NULL;
cdcaf41c
QT
284
285 /* Add the id */
a8876892
GB
286 params_maptypes_ids = g_realloc (params_maptypes_ids, (len+2)*sizeof(guint));
287 params_maptypes_ids[len] = id;
288 params_maptypes_ids[len+1] = 0;
cdcaf41c
QT
289
290 /* We have to clone */
820c59f4 291 VikMapSource *clone = VIK_MAP_SOURCE(g_object_ref(map));
cdcaf41c
QT
292 /* Register the clone in the list */
293 __map_types = g_list_append(__map_types, clone);
294
295 /* Hack
e2cb421f 296 We have to ensure the mode LayerParam references the up-to-date
cdcaf41c
QT
297 GLists.
298 */
299 /*
300 memcpy(&maps_layer_params[0].widget_data, &params_maptypes, sizeof(gpointer));
301 memcpy(&maps_layer_params[0].extra_widget_data, &params_maptypes_ids, sizeof(gpointer));
302 */
303 maps_layer_params[0].widget_data = params_maptypes;
304 maps_layer_params[0].extra_widget_data = params_maptypes_ids;
305}
306
e2cb421f
GB
307void _update_map_source ( const char *label, VikMapSource *map, int index )
308{
309 GList *item = g_list_nth (__map_types, index);
310 g_object_unref (item->data);
311 item->data = g_object_ref (map);
312 /* Change previous data */
313 g_free (params_maptypes[index]);
314 params_maptypes[index] = g_strdup (label);
315}
316
17281ebd
GB
317/**
318 * maps_layer_register_map_source:
319 * @map: the new VikMapSource
320 *
321 * Register a new VikMapSource.
322 * Override existing one (equality of id).
323 */
e2cb421f
GB
324void maps_layer_register_map_source ( VikMapSource *map )
325{
326 g_assert(map != NULL);
327
328 guint id = vik_map_source_get_uniq_id(map);
329 const char *label = vik_map_source_get_label(map);
330 g_assert(label != NULL);
331
332 int previous = map_uniq_id_to_index (id);
333 if (previous != NUM_MAP_TYPES)
334 {
335 _update_map_source (label, map, previous);
336 }
337 else
338 {
339 _add_map_source (id, label, map);
340 }
341}
342
a8876892
GB
343#define MAPS_LAYER_NTH_LABEL(n) (params_maptypes[n])
344#define MAPS_LAYER_NTH_ID(n) (params_maptypes_ids[n])
820c59f4 345#define MAPS_LAYER_NTH_TYPE(n) (VIK_MAP_SOURCE(g_list_nth_data(__map_types, (n))))
cdcaf41c 346
7114e879
QT
347gint vik_maps_layer_get_map_type(VikMapsLayer *vml)
348{
349 return(vml->maptype);
350}
351
352gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml)
353{
354 return(g_strdup(MAPS_LAYER_NTH_LABEL(vml->maptype)));
355}
356
50a14534
EB
357/****************************************/
358/******** CACHE DIR STUFF ***************/
359/****************************************/
360
2673b29d 361#define DIRECTDIRACCESS "%s%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d%s"
3d9454e6 362#define DIRSTRUCTURE "%st%ds%dz%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d"
6a27c1bc
MA
363#define MAPS_CACHE_DIR maps_layer_default_dir()
364
50a14534 365#ifdef WINDOWS
6a27c1bc
MA
366#include <io.h>
367#define GLOBAL_MAPS_DIR "C:\\VIKING-MAPS\\"
368#define LOCAL_MAPS_DIR "VIKING-MAPS"
42293fc2
RN
369#elif defined __APPLE__
370#include <stdlib.h>
371#define GLOBAL_MAPS_DIR "/Library/cache/Viking/maps/"
372#define LOCAL_MAPS_DIR "/Library/Application Support/Viking/viking-maps"
50a14534 373#else /* POSIX */
50a14534 374#include <stdlib.h>
50a14534 375#define GLOBAL_MAPS_DIR "/var/cache/maps/"
6a27c1bc
MA
376#define LOCAL_MAPS_DIR ".viking-maps"
377#endif
50a14534 378
0c1044e9 379gchar *maps_layer_default_dir ()
50a14534 380{
3d9454e6
GB
381 static gchar *defaultdir = NULL;
382 if ( ! defaultdir )
50a14534
EB
383 {
384 /* Thanks to Mike Davison for the $VIKING_MAPS usage */
3d9454e6
GB
385 const gchar *mapdir = g_getenv("VIKING_MAPS");
386 if ( mapdir ) {
387 defaultdir = g_strdup ( mapdir );
45acf79e 388 } else if ( g_access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) {
3d9454e6 389 defaultdir = g_strdup ( GLOBAL_MAPS_DIR );
50a14534 390 } else {
6a27c1bc 391 const gchar *home = g_get_home_dir();
45acf79e 392 if (!home || g_access(home, W_OK))
3d9454e6
GB
393 home = g_get_home_dir ();
394 if ( home )
6a27c1bc 395 defaultdir = g_build_filename ( home, LOCAL_MAPS_DIR, NULL );
50a14534 396 else
6a27c1bc 397 defaultdir = g_strdup ( LOCAL_MAPS_DIR );
50a14534 398 }
3d9454e6
GB
399 if (defaultdir && (defaultdir[strlen(defaultdir)-1] != G_DIR_SEPARATOR))
400 {
401 /* Add the separator at the end */
402 gchar *tmp = defaultdir;
403 defaultdir = g_strconcat(tmp, G_DIR_SEPARATOR_S, NULL);
404 g_free(tmp);
405 }
406 g_debug("%s: defaultdir=%s", __FUNCTION__, defaultdir);
50a14534
EB
407 }
408 return defaultdir;
409}
410
50a14534
EB
411static void maps_layer_mkdir_if_default_dir ( VikMapsLayer *vml )
412{
45acf79e 413 if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && g_file_test ( vml->cache_dir, G_FILE_TEST_EXISTS ) == FALSE )
50a14534 414 {
f83131b9 415 g_mkdir ( vml->cache_dir, 0777 );
50a14534
EB
416 }
417}
418
419static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir )
420{
421 guint len;
422 g_assert ( vml != NULL);
e65028db
GB
423 g_free ( vml->cache_dir );
424 vml->cache_dir = NULL;
50a14534
EB
425
426 if ( dir == NULL || dir[0] == '\0' )
6926d79a
RN
427 {
428 if ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir") )
429 vml->cache_dir = g_strdup ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir")->s );
430 }
50a14534
EB
431 else
432 {
433 len = strlen(dir);
3d9454e6 434 if ( dir[len-1] != G_DIR_SEPARATOR )
50a14534
EB
435 {
436 vml->cache_dir = g_malloc ( len+2 );
437 strncpy ( vml->cache_dir, dir, len );
3d9454e6 438 vml->cache_dir[len] = G_DIR_SEPARATOR;
50a14534
EB
439 vml->cache_dir[len+1] = '\0';
440 }
441 else
442 vml->cache_dir = g_strdup ( dir );
443 }
444 maps_layer_mkdir_if_default_dir ( vml );
445}
446
447/****************************************/
448/******** GOBJECT STUFF *****************/
449/****************************************/
450
451GType vik_maps_layer_get_type ()
452{
453 static GType vml_type = 0;
454
455 if (!vml_type)
456 {
457 static const GTypeInfo vml_info =
458 {
459 sizeof (VikMapsLayerClass),
460 NULL, /* base_init */
461 NULL, /* base_finalize */
462 NULL, /* class init */
463 NULL, /* class_finalize */
464 NULL, /* class_data */
465 sizeof (VikMapsLayer),
466 0,
467 NULL /* instance init */
468 };
469 vml_type = g_type_register_static ( VIK_LAYER_TYPE, "VikMapsLayer", &vml_info, 0 );
470 }
471
472 return vml_type;
473}
474
475/****************************************/
476/************** PARAMETERS **************/
477/****************************************/
478
479static guint map_index_to_uniq_id (guint8 index)
480{
481 g_assert ( index < NUM_MAP_TYPES );
820c59f4 482 return vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(index));
50a14534
EB
483}
484
485static guint map_uniq_id_to_index ( guint uniq_id )
486{
487 gint i;
488 for ( i = 0; i < NUM_MAP_TYPES; i++ )
820c59f4 489 if ( vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(i)) == uniq_id )
50a14534
EB
490 return i;
491 return NUM_MAP_TYPES; /* no such thing */
492}
493
158b3642 494static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation )
50a14534 495{
8e507445
RN
496 // When loading from a file don't need the license reminder
497 if ( is_file_operation )
498 vml->license_notice_shown = TRUE;
499
50a14534
EB
500 switch ( id )
501 {
502 case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break;
503 case PARAM_MAPTYPE: {
504 gint maptype = map_uniq_id_to_index(data.u);
4c77d5e0 505 if ( maptype == NUM_MAP_TYPES ) g_warning(_("Unknown map type"));
50a14534
EB
506 else vml->maptype = maptype;
507 break;
508 }
509 case PARAM_ALPHA: if ( data.u <= 255 ) vml->alpha = data.u; break;
510 case PARAM_AUTODOWNLOAD: vml->autodownload = data.b; break;
382566c3 511 case PARAM_ONLYMISSING: vml->adl_only_missing = data.b; break;
50a14534
EB
512 case PARAM_MAPZOOM: if ( data.u < NUM_MAPZOOMS ) {
513 vml->mapzoom_id = data.u;
514 vml->xmapzoom = __mapzooms_x [data.u];
515 vml->ymapzoom = __mapzooms_y [data.u];
4c77d5e0 516 }else g_warning (_("Unknown Map Zoom")); break;
50a14534
EB
517 }
518 return TRUE;
519}
520
158b3642 521static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation )
50a14534
EB
522{
523 VikLayerParamData rv;
524 switch ( id )
525 {
b6865130 526 case PARAM_CACHE_DIR: rv.s = vml->cache_dir ? vml->cache_dir : ""; break;
50a14534
EB
527 case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break;
528 case PARAM_ALPHA: rv.u = vml->alpha; break;
529 case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break;
382566c3 530 case PARAM_ONLYMISSING: rv.u = vml->adl_only_missing; break;
50a14534
EB
531 case PARAM_MAPZOOM: rv.u = vml->mapzoom_id; break;
532 }
533 return rv;
534}
535
536/****************************************/
537/****** CREATING, COPYING, FREEING ******/
538/****************************************/
539
540static VikMapsLayer *maps_layer_new ( VikViewport *vvp )
541{
36c78d6d 542 int idx;
50a14534 543 VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) );
a0c65899 544 vik_layer_set_type ( VIK_LAYER(vml), VIK_LAYER_MAPS );
995e9aff 545 idx = map_uniq_id_to_index(19); /* 19 is id for OSM MapQuest maps */
36c78d6d 546 vml->maptype = (idx < NUM_MAP_TYPES) ? idx : 0;
2673b29d 547 vml->maptype = (idx < NUM_MAP_TYPES) ? idx : 0;
50a14534
EB
548 vml->alpha = 255;
549 vml->mapzoom_id = 0;
550 vml->dl_tool_x = vml->dl_tool_y = -1;
551 maps_layer_set_cache_dir ( vml, NULL );
552 vml->autodownload = FALSE;
382566c3 553 vml->adl_only_missing = FALSE;
10ca2bfe
QT
554 vml->last_center = NULL;
555 vml->last_xmpp = 0.0;
556 vml->last_ympp = 0.0;
50a14534
EB
557
558 vml->dl_right_click_menu = NULL;
8e507445 559 vml->license_notice_shown = FALSE;
50a14534
EB
560
561 return vml;
562}
563
564static void maps_layer_free ( VikMapsLayer *vml )
565{
e65028db
GB
566 g_free ( vml->cache_dir );
567 vml->cache_dir = NULL;
50a14534 568 if ( vml->dl_right_click_menu )
4f14a010 569 g_object_ref_sink ( G_OBJECT(vml->dl_right_click_menu) );
e65028db
GB
570 g_free(vml->last_center);
571 vml->last_center = NULL;
50a14534
EB
572}
573
07059501 574static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file)
dc5758d3 575{
07059501
GB
576 if (from_file != TRUE)
577 {
578 /* If this method is not called in file reading context
579 * it is called in GUI context.
580 * So, we can check if we have to inform the user about inconsistency */
581 VikViewportDrawMode vp_drawmode;
582 VikMapsLayer *vml = VIK_MAPS_LAYER(vl);
820c59f4 583 VikMapSource *map = NULL;
dc5758d3 584
405b74ed 585 vp_drawmode = vik_viewport_get_drawmode ( vp );
820c59f4
GB
586 map = MAPS_LAYER_NTH_TYPE(vml->maptype);
587 if (vik_map_source_get_drawmode(map) != vp_drawmode) {
405b74ed 588 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vp, vik_map_source_get_drawmode(map));
4c77d5e0 589 gchar *msg = g_strdup_printf(_("New map cannot be displayed in the current drawmode.\nSelect \"%s\" from View menu to view it."), drawmode_name);
eb0fbfa9 590 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp), msg );
07059501
GB
591 g_free(msg);
592 }
53ac8302
GB
593
594 if (vik_map_source_get_license (map) != NULL) {
8e507445
RN
595 if ( ! vml->license_notice_shown ) {
596 a_dialog_license (VIK_GTK_WINDOW_FROM_WIDGET(vp), vik_map_source_get_label (map),
597 vik_map_source_get_license (map), vik_map_source_get_license_url (map) );
598 vml->license_notice_shown = TRUE;
599 }
53ac8302 600 }
dc5758d3
GB
601 }
602}
603
7924723c
RN
604static const gchar* maps_layer_tooltip ( VikMapsLayer *vml )
605{
606 return vik_maps_layer_get_map_label ( vml );
607}
608
911400b5
AF
609static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len )
610{
611 vik_layer_marshall_params ( VIK_LAYER(vml), data, len );
612}
613
614static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
615{
616 VikMapsLayer *rv = maps_layer_new ( vvp );
617 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
618 return rv;
619}
620
50a14534
EB
621/*********************/
622/****** DRAWING ******/
623/*********************/
624
625static GdkPixbuf *pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha )
626{
627 guchar *pixels;
628 gint width, height, iii, jjj;
629
630 if ( ! gdk_pixbuf_get_has_alpha ( pixbuf ) )
631 {
632 GdkPixbuf *tmp = gdk_pixbuf_add_alpha(pixbuf,FALSE,0,0,0);
633 g_object_unref(G_OBJECT(pixbuf));
634 pixbuf = tmp;
635 }
636
637 pixels = gdk_pixbuf_get_pixels(pixbuf);
638 width = gdk_pixbuf_get_width(pixbuf);
639 height = gdk_pixbuf_get_height(pixbuf);
640
641 /* r,g,b,a,r,g,b,a.... */
642 for (iii = 0; iii < width; iii++) for (jjj = 0; jjj < height; jjj++)
643 {
644 pixels += 3;
645 *pixels++ = alpha;
646 }
647 return pixbuf;
648}
649
650static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdouble yshrinkfactor )
651{
652 GdkPixbuf *tmp;
653 guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf);
9fdb940f 654 tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_NEAREST);
50a14534
EB
655 g_object_unref ( G_OBJECT(pixbuf) );
656 return tmp;
657}
658
659static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, gchar *filename_buf, gint buf_len, gdouble xshrinkfactor, gdouble yshrinkfactor )
660{
661 GdkPixbuf *pixbuf;
662
663 /* get the thing */
664 pixbuf = a_mapcache_get ( mapcoord->x, mapcoord->y, mapcoord->z,
665 mode, mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
666
667 if ( ! pixbuf ) {
2673b29d
RN
668 if ( vik_map_source_is_direct_file_access (MAPS_LAYER_NTH_TYPE(vml->maptype)) )
669 g_snprintf ( filename_buf, buf_len, DIRECTDIRACCESS,
670 vml->cache_dir, (17 - mapcoord->scale), mapcoord->x, mapcoord->y, ".png" );
671 else
672 g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE,
673 vml->cache_dir, mode,
674 mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y );
675
01ecda7e 676 if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
50a14534
EB
677 {
678 GError *gx = NULL;
679 pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx );
680
01ecda7e 681 /* free the pixbuf on error */
50a14534
EB
682 if (gx)
683 {
684 if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE )
4c77d5e0 685 g_warning ( _("Couldn't open image file: %s"), gx->message );
50a14534 686
01ecda7e
MR
687 g_error_free ( gx );
688 if ( pixbuf )
689 g_object_unref ( G_OBJECT(pixbuf) );
690 pixbuf = NULL;
691 } else {
50a14534
EB
692 if ( vml->alpha < 255 )
693 pixbuf = pixbuf_set_alpha ( pixbuf, vml->alpha );
694 if ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 )
695 pixbuf = pixbuf_shrink ( pixbuf, xshrinkfactor, yshrinkfactor );
696
697 a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y,
820c59f4 698 mapcoord->z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(vml->maptype)),
50a14534 699 mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
50a14534
EB
700 }
701 }
702 }
703 return pixbuf;
704}
705
10ca2bfe
QT
706gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp)
707{
708 const VikCoord *center = vik_viewport_get_center ( vvp );
709
bbf2149b 710 if (vik_window_get_pan_move (VIK_WINDOW(VIK_GTK_WINDOW_FROM_WIDGET(GTK_WIDGET(vvp)))))
01da6b4d 711 /* D'n'D pan in action: do not download */
1c6a6010
GB
712 return FALSE;
713
10ca2bfe
QT
714 if (vml->last_center == NULL) {
715 VikCoord *new_center = g_malloc(sizeof(VikCoord));
716 *new_center = *center;
717 vml->last_center = new_center;
718 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
719 vml->last_ympp = vik_viewport_get_ympp(vvp);
720 return TRUE;
721 }
722
723 /* TODO: perhaps vik_coord_diff() */
724 if (vik_coord_equals(vml->last_center, center)
725 && (vml->last_xmpp == vik_viewport_get_xmpp(vvp))
726 && (vml->last_ympp == vik_viewport_get_ympp(vvp)))
727 return FALSE;
728
729 *(vml->last_center) = *center;
730 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
731 vml->last_ympp = vik_viewport_get_ympp(vvp);
732 return TRUE;
733}
734
50a14534
EB
735static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br )
736{
737 MapCoord ulm, brm;
738 gdouble xzoom = vik_viewport_get_xmpp ( vvp );
739 gdouble yzoom = vik_viewport_get_ympp ( vvp );
740 gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0;
2673b29d 741 gboolean existence_only = FALSE;
50a14534
EB
742
743 if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) {
744 xshrinkfactor = vml->xmapzoom / xzoom;
745 yshrinkfactor = vml->ymapzoom / yzoom;
732d1e25
EB
746 xzoom = vml->xmapzoom;
747 yzoom = vml->xmapzoom;
748 if ( ! (xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR &&
749 yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) ) {
750 if ( xshrinkfactor > REAL_MIN_SHRINKFACTOR && yshrinkfactor > REAL_MIN_SHRINKFACTOR )
751 existence_only = TRUE;
752 else {
4c77d5e0 753 g_warning ( _("Cowardly refusing to draw tiles or existence of tiles beyond %d zoom out factor"), (int)( 1.0/REAL_MIN_SHRINKFACTOR));
732d1e25
EB
754 return;
755 }
50a14534
EB
756 }
757 }
758
759 /* coord -> ID */
820c59f4
GB
760 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
761 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm ) &&
762 vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) ) {
50a14534
EB
763
764 /* loop & draw */
765 gint x, y;
766 gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x);
767 gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y);
820c59f4 768 gint mode = vik_map_source_get_uniq_id(map);
50a14534
EB
769
770 VikCoord coord;
771 gint xx, yy, width, height;
772 GdkPixbuf *pixbuf;
773
774 guint max_path_len = strlen(vml->cache_dir) + 40;
775 gchar *path_buf = g_malloc ( max_path_len * sizeof(char) );
776
732d1e25 777 if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) {
33be396e 778 g_debug("%s: Starting autodownload", __FUNCTION__);
382566c3 779 if ( !vml->adl_only_missing && vik_map_source_supports_download_only_new (map) )
245f48f5
GB
780 // Try to download newer tiles
781 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
782 else
783 // Download only missing tiles
784 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
10ca2bfe 785 }
50a14534 786
820c59f4 787 if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) {
50a14534
EB
788 for ( x = xmin; x <= xmax; x++ ) {
789 for ( y = ymin; y <= ymax; y++ ) {
790 ulm.x = x;
791 ulm.y = y;
792 pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
793 if ( pixbuf ) {
794 width = gdk_pixbuf_get_width ( pixbuf );
795 height = gdk_pixbuf_get_height ( pixbuf );
796
820c59f4 797 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
50a14534
EB
798 vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy );
799 xx -= (width/2);
800 yy -= (height/2);
801
802 vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height );
803 }
804 }
805 }
806 } else { /* tilesize is known, don't have to keep converting coords */
820c59f4
GB
807 gdouble tilesize_x = vik_map_source_get_tilesize_x(map) * xshrinkfactor;
808 gdouble tilesize_y = vik_map_source_get_tilesize_y(map) * yshrinkfactor;
50a14534
EB
809 /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
810 gint tilesize_x_ceil = ceil ( tilesize_x );
811 gint tilesize_y_ceil = ceil ( tilesize_y );
812 gint8 xinc = (ulm.x == xmin) ? 1 : -1;
813 gint8 yinc = (ulm.y == ymin) ? 1 : -1;
814 gdouble xx, yy; gint xx_tmp, yy_tmp;
815 gint base_yy, xend, yend;
732d1e25 816
50a14534
EB
817 xend = (xinc == 1) ? (xmax+1) : (xmin-1);
818 yend = (yinc == 1) ? (ymax+1) : (ymin-1);
819
820c59f4 820 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
50a14534
EB
821 vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp );
822 xx = xx_tmp; yy = yy_tmp;
823 /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
824 * eg if tile size 128, shrinkfactor 0.333 */
825 xx -= (tilesize_x/2);
826 base_yy = yy - (tilesize_y/2);
827
828 for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) {
829 yy = base_yy;
830 for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) {
831 ulm.x = x;
832 ulm.y = y;
732d1e25
EB
833
834 if ( existence_only ) {
2673b29d
RN
835 if ( vik_map_source_is_direct_file_access (MAPS_LAYER_NTH_TYPE(vml->maptype)) )
836 g_snprintf ( path_buf, max_path_len, DIRECTDIRACCESS,
837 vml->cache_dir, (17 - ulm.scale), ulm.x, ulm.y, ".png" );
838 else
839 g_snprintf ( path_buf, max_path_len, DIRSTRUCTURE,
840 vml->cache_dir, mode,
841 ulm.scale, ulm.z, ulm.x, ulm.y );
45acf79e 842 if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) {
ff37db21 843 GdkGC *black_gc = gtk_widget_get_style(GTK_WIDGET(vvp))->black_gc;
732d1e25
EB
844 vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil );
845 }
846 } else {
6f0d1bea
JJ
847 int scale_inc;
848 for (scale_inc = 0; scale_inc < 4; scale_inc ++) {
849 /* try with correct then smaller zooms */
850 int scale_factor = 1 << scale_inc; /* 2^scale_inc */
851 MapCoord ulm2 = ulm;
852 ulm2.x = ulm.x / scale_factor;
853 ulm2.y = ulm.y / scale_factor;
854 ulm2.scale = ulm.scale + scale_inc;
855 pixbuf = get_pixbuf ( vml, mode, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor );
856 if ( pixbuf ) {
857 gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil;
858 gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil;
40cfc175
JJ
859#ifdef DEBUG
860 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);
861#endif
6f0d1bea
JJ
862 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
863 break;
864 }
865 }
866 if ( !pixbuf ) {
867 /* retry with bigger zooms */
868 int scale_dec;
869 for (scale_dec = 1; scale_dec < 2; scale_dec ++) {
870 int pict_x, pict_y;
871 int scale_factor = 1 << scale_dec; /* 2^scale_dec */
91dc4449 872 MapCoord ulm2 = ulm;
6f0d1bea
JJ
873 ulm2.x = ulm.x * scale_factor;
874 ulm2.y = ulm.y * scale_factor;
875 ulm2.scale = ulm.scale - scale_dec;
876 for (pict_x = 0; pict_x < scale_factor; pict_x ++) {
877 for (pict_y = 0; pict_y < scale_factor; pict_y ++) {
878 MapCoord ulm3 = ulm2;
879 ulm3.x += pict_x;
880 ulm3.y += pict_y;
881 pixbuf = get_pixbuf ( vml, mode, &ulm3, path_buf, max_path_len, xshrinkfactor / scale_factor, yshrinkfactor / scale_factor );
882 if ( pixbuf ) {
883 gint src_x = 0;
884 gint src_y = 0;
885 gint dest_x = xx + pict_x * (tilesize_x_ceil / scale_factor);
886 gint dest_y = yy + pict_y * (tilesize_y_ceil / scale_factor);
887 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, dest_x, dest_y, tilesize_x_ceil / scale_factor, tilesize_y_ceil / scale_factor );
888 }
889 }
91dc4449
JJ
890 }
891 }
892 }
732d1e25 893 }
50a14534
EB
894
895 yy += tilesize_y;
896 }
897 xx += tilesize_x;
898 }
899 }
900
901 g_free ( path_buf );
902 }
903}
904
905static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp )
906{
820c59f4 907 if ( vik_map_source_get_drawmode(MAPS_LAYER_NTH_TYPE(vml->maptype)) == vik_viewport_get_drawmode ( vvp ) )
50a14534
EB
908 {
909 VikCoord ul, br;
910
82aa018d 911 /* Copyright */
68b1d6c0
GB
912 gdouble level = vik_viewport_get_zoom ( vvp );
913 LatLonBBox bbox;
914 vik_viewport_get_min_max_lat_lon ( vvp, &bbox.south, &bbox.north, &bbox.west, &bbox.east );
915 vik_map_source_get_copyright ( MAPS_LAYER_NTH_TYPE(vml->maptype), bbox, level, vik_viewport_add_copyright, vvp );
82aa018d 916
26336cf0
GB
917 /* Logo */
918 const GdkPixbuf *logo = vik_map_source_get_logo ( MAPS_LAYER_NTH_TYPE(vml->maptype) );
919 vik_viewport_add_logo ( vvp, logo );
920
50a14534
EB
921 /* get corner coords */
922 if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) {
923 /* UTM multi-zone stuff by Kit Transue */
924 gchar leftmost_zone, rightmost_zone, i;
925 leftmost_zone = vik_viewport_leftmost_zone( vvp );
926 rightmost_zone = vik_viewport_rightmost_zone( vvp );
927 for ( i = leftmost_zone; i <= rightmost_zone; ++i ) {
928 vik_viewport_corners_for_zonen ( vvp, i, &ul, &br );
929 maps_layer_draw_section ( vml, vvp, &ul, &br );
930 }
931 }
932 else {
933 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
934 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
935
936 maps_layer_draw_section ( vml, vvp, &ul, &br );
937 }
938 }
939}
940
941/*************************/
942/****** DOWNLOADING ******/
943/*************************/
944
945/* pass along data to thread, exists even if layer is deleted. */
946typedef struct {
947 gchar *cache_dir;
948 gchar *filename_buf;
949 gint x0, y0, xf, yf;
950 MapCoord mapcoord;
951 gint maptype;
952 gint maxlen;
953 gint mapstoget;
954 gint redownload;
7114e879 955 gboolean refresh_display;
550fd035
QT
956 VikMapsLayer *vml;
957 VikViewport *vvp;
958 gboolean map_layer_alive;
959 GMutex *mutex;
50a14534
EB
960} MapDownloadInfo;
961
962static void mdi_free ( MapDownloadInfo *mdi )
963{
550fd035 964 g_mutex_free(mdi->mutex);
50a14534 965 g_free ( mdi->cache_dir );
e65028db 966 mdi->cache_dir = NULL;
50a14534 967 g_free ( mdi->filename_buf );
e65028db 968 mdi->filename_buf = NULL;
50a14534
EB
969 g_free ( mdi );
970}
971
7bb60307 972static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
550fd035 973{
7bb60307 974 MapDownloadInfo *mdi = ptr;
550fd035
QT
975 g_mutex_lock(mdi->mutex);
976 mdi->map_layer_alive = FALSE;
977 g_mutex_unlock(mdi->mutex);
978}
979
634eca0a 980static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
50a14534 981{
825413ba 982 void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype));
50a14534
EB
983 guint donemaps = 0;
984 gint x, y;
985 for ( x = mdi->x0; x <= mdi->xf; x++ )
986 {
987 for ( y = mdi->y0; y <= mdi->yf; y++ )
988 {
94493114 989 gboolean remove_mem_cache = FALSE;
84628352 990 gboolean need_download = FALSE;
50a14534 991 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 992 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
50a14534
EB
993 mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
994
84628352 995 donemaps++;
634eca0a 996 int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
825413ba
SW
997 if (res != 0) {
998 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
634eca0a 999 return -1;
825413ba 1000 }
84628352 1001
a0058e48 1002 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
6a4a29aa
JJ
1003 need_download = TRUE;
1004 remove_mem_cache = TRUE;
a0058e48
JJ
1005
1006 } else { /* in case map file already exists */
1007 switch (mdi->redownload) {
1008 case REDOWNLOAD_NONE:
1009 continue;
1010
1011 case REDOWNLOAD_BAD:
1012 {
1013 /* see if this one is bad or what */
1014 GError *gx = NULL;
1015 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
1016 if (gx || (!pixbuf)) {
1017 g_remove ( mdi->filename_buf );
1018 need_download = TRUE;
1019 remove_mem_cache = TRUE;
1020 g_error_free ( gx );
1021
1022 } else {
1023 g_object_unref ( pixbuf );
1024 }
1025 break;
1026 }
1027
1028 case REDOWNLOAD_NEW:
1029 need_download = TRUE;
1030 remove_mem_cache = TRUE;
1031 break;
1032
1033 case REDOWNLOAD_ALL:
1034 /* FIXME: need a better way than to erase file in case of server/network problem */
1035 g_remove ( mdi->filename_buf );
1036 need_download = TRUE;
1037 remove_mem_cache = TRUE;
1038 break;
1039
1040 case DOWNLOAD_OR_REFRESH:
1041 remove_mem_cache = TRUE;
1042 break;
1043
1044 default:
1045 g_warning ( "redownload state %d unknown\n", mdi->redownload);
1046 }
1047 }
94493114 1048
94493114 1049 mdi->mapcoord.x = x; mdi->mapcoord.y = y;
84628352
QT
1050
1051 if (need_download) {
825413ba 1052 if ( vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle))
94493114 1053 continue;
84628352 1054 }
94493114 1055
94493114
QT
1056 g_mutex_lock(mdi->mutex);
1057 if (remove_mem_cache)
820c59f4 1058 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 );
7114e879 1059 if (mdi->refresh_display && mdi->map_layer_alive) {
94493114 1060 /* TODO: check if it's on visible area */
da121f9b 1061 vik_layer_emit_update ( VIK_LAYER(mdi->vml) ); // NB update display from background
a0b59f2f 1062 }
94493114 1063 g_mutex_unlock(mdi->mutex);
94493114
QT
1064 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
1065
50a14534
EB
1066 }
1067 }
825413ba 1068 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
04e54492
QT
1069 g_mutex_lock(mdi->mutex);
1070 if (mdi->map_layer_alive)
7bb60307 1071 g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
04e54492 1072 g_mutex_unlock(mdi->mutex);
634eca0a 1073 return 0;
50a14534
EB
1074}
1075
1076static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
1077{
1078 if ( mdi->mapcoord.x || mdi->mapcoord.y )
1079 {
1080 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 1081 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
50a14534 1082 mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y );
45acf79e 1083 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
50a14534 1084 {
8c060406 1085 g_remove ( mdi->filename_buf );
50a14534
EB
1086 }
1087 }
1088}
1089
1090static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload )
1091{
1092 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1093 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1094 MapCoord ulm, brm;
820c59f4 1095 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
2673b29d
RN
1096
1097 // Don't ever attempt download on direct access
1098 if ( vik_map_source_is_direct_file_access ( map ) )
1099 return;
1100
820c59f4
GB
1101 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm )
1102 && vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) )
50a14534
EB
1103 {
1104 MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
1105 gint a, b;
1106
550fd035
QT
1107 mdi->vml = vml;
1108 mdi->vvp = vvp;
1109 mdi->map_layer_alive = TRUE;
1110 mdi->mutex = g_mutex_new();
7114e879 1111 mdi->refresh_display = TRUE;
550fd035 1112
50a14534
EB
1113 /* cache_dir and buffer for dest filename */
1114 mdi->cache_dir = g_strdup ( vml->cache_dir );
1115 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1116 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1117 mdi->maptype = vml->maptype;
1118
1119 mdi->mapcoord = ulm;
1120
1121 mdi->redownload = redownload;
1122
1123 mdi->x0 = MIN(ulm.x, brm.x);
1124 mdi->xf = MAX(ulm.x, brm.x);
1125 mdi->y0 = MIN(ulm.y, brm.y);
1126 mdi->yf = MAX(ulm.y, brm.y);
1127
1128 mdi->mapstoget = 0;
1129
1130 if ( mdi->redownload ) {
1131 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
1132 } else {
1133 /* calculate how many we need */
1134 for ( a = mdi->x0; a <= mdi->xf; a++ )
1135 {
1136 for ( b = mdi->y0; b <= mdi->yf; b++ )
1137 {
1138 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 1139 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
50a14534 1140 ulm.z, a, b );
45acf79e 1141 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
50a14534
EB
1142 mdi->mapstoget++;
1143 }
1144 }
1145 }
1146
1147 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1148
1149 if ( mdi->mapstoget )
1150 {
97634600
GB
1151 const gchar *tmp_str;
1152 gchar *tmp;
50a14534 1153
97634600
GB
1154 if (redownload)
1155 {
1156 if (redownload == REDOWNLOAD_BAD)
1157 tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget);
1158 else
1159 tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget);
1160 }
1161 else
1162 {
1163 tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget);
1164 }
1165 tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype));
1166
7bb60307 1167 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
50a14534
EB
1168 /* launch the thread */
1169 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1170 tmp, /* description string */
1171 (vik_thr_func) map_download_thread, /* function to call within thread */
1172 mdi, /* pass along data */
1173 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1174 (vik_thr_free_func) mdi_cancel_cleanup,
1175 mdi->mapstoget );
1176 g_free ( tmp );
1177 }
1178 else
1179 mdi_free ( mdi );
1180 }
1181}
1182
903dc0b4 1183void maps_layer_download_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom)
7114e879 1184{
7114e879 1185 MapCoord ulm, brm;
820c59f4 1186 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
7114e879 1187
2673b29d
RN
1188 // Don't ever attempt download on direct access
1189 if ( vik_map_source_is_direct_file_access ( map ) )
1190 return;
1191
820c59f4
GB
1192 if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm)
1193 || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) {
4258f4e2 1194 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
7114e879
QT
1195 return;
1196 }
1197
1198 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
1199 gint i, j;
1200
1201 mdi->vml = vml;
1202 mdi->vvp = vvp;
1203 mdi->map_layer_alive = TRUE;
1204 mdi->mutex = g_mutex_new();
903dc0b4 1205 mdi->refresh_display = TRUE;
7114e879
QT
1206
1207 mdi->cache_dir = g_strdup ( vml->cache_dir );
1208 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1209 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1210 mdi->maptype = vml->maptype;
1211
1212 mdi->mapcoord = ulm;
1213
1214 mdi->redownload = REDOWNLOAD_NONE;
1215
1216 mdi->x0 = MIN(ulm.x, brm.x);
1217 mdi->xf = MAX(ulm.x, brm.x);
1218 mdi->y0 = MIN(ulm.y, brm.y);
1219 mdi->yf = MAX(ulm.y, brm.y);
1220
1221 mdi->mapstoget = 0;
1222
1223 for (i = mdi->x0; i <= mdi->xf; i++) {
1224 for (j = mdi->y0; j <= mdi->yf; j++) {
1225 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 1226 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
7114e879 1227 ulm.z, i, j );
45acf79e 1228 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
7114e879
QT
1229 mdi->mapstoget++;
1230 }
1231 }
1232
1233 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1234
1235 if (mdi->mapstoget) {
4c77d5e0
GB
1236 gchar *tmp;
1237 const gchar *fmt;
eb6b0125
JJ
1238 fmt = ngettext("Downloading %d %s map...",
1239 "Downloading %d %s maps...",
1240 mdi->mapstoget);
4c77d5e0 1241 tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) );
7114e879
QT
1242
1243 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1244 /* launch the thread */
1245 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1246 tmp, /* description string */
1247 (vik_thr_func) map_download_thread, /* function to call within thread */
1248 mdi, /* pass along data */
1249 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1250 (vik_thr_free_func) mdi_cancel_cleanup,
1251 mdi->mapstoget );
1252 g_free ( tmp );
1253 }
1254 else
1255 mdi_free ( mdi );
1256}
1257
50a14534
EB
1258static void maps_layer_redownload_bad ( VikMapsLayer *vml )
1259{
1260 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
1261}
a7c1acf1 1262
50a14534
EB
1263static void maps_layer_redownload_all ( VikMapsLayer *vml )
1264{
1265 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
1266}
1267
a7c1acf1
GB
1268static void maps_layer_redownload_new ( VikMapsLayer *vml )
1269{
1270 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
1271}
1272
450d8665
RN
1273/**
1274 * Display a simple dialog with information about this particular map tile
1275 */
1276static void maps_layer_tile_info ( VikMapsLayer *vml )
1277{
1278 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1279
1280 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vml->redownload_vvp );
1281 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vml->redownload_vvp );
1282 MapCoord ulm;
1283
1284 if ( !vik_map_source_coord_to_mapcoord ( map, &(vml->redownload_ul), xzoom, yzoom, &ulm ) )
1285 return;
1286
1287 gchar *filename = NULL;
1288 gchar *message = NULL;
1289 gchar *source = NULL;
1290
1291 if ( vik_map_source_is_direct_file_access ( map ) ) {
1292 filename = g_strdup_printf ( DIRECTDIRACCESS, vml->cache_dir, ulm.scale, ulm.x, ulm.y, ".png" );
1293 source = g_strconcat ( "file://", filename, NULL );
1294 }
1295 else {
1296 filename = g_strdup_printf ( DIRSTRUCTURE, vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale, ulm.z, ulm.x, ulm.y );
1297 source = g_strdup_printf ( "http://%s%s",
1298 vik_map_source_default_get_hostname ( VIK_MAP_SOURCE_DEFAULT(map) ),
1299 vik_map_source_default_get_uri ( VIK_MAP_SOURCE_DEFAULT(map), &ulm ) );
1300 }
1301
1302 if ( g_file_test ( filename, G_FILE_TEST_EXISTS ) ) {
1303
1304 // Get some timestamp information of the tile
1305 struct stat stat_buf;
1306 if ( g_stat ( filename, &stat_buf ) == 0 ) {
1307 time_t file_time = stat_buf.st_mtime;
445a0ba6 1308#if GLIB_CHECK_VERSION(2,26,0)
450d8665
RN
1309 GDateTime* gdt = g_date_time_new_from_unix_utc ( file_time );
1310 gchar *time = g_date_time_format ( gdt, "%c" );
445a0ba6
RN
1311#else
1312 char time[20];
1313 strftime(time, 20, "%Y-%m-%d %H:%M:%S", localtime(&file_time));
1314#endif
450d8665
RN
1315 message = g_strdup_printf ( _("\nSource: %s\n\nTile File: %s\nTile File Timestamp: %s"), source, filename, time );
1316
445a0ba6 1317#if GLIB_CHECK_VERSION(2,26,0)
450d8665
RN
1318 g_free ( time );
1319 g_date_time_unref ( gdt);
445a0ba6 1320#endif
450d8665
RN
1321 }
1322 }
1323 else
1324 message = g_strdup_printf ( _("Source: %s\n\nNo Tile File!"), source );
1325
1326 // Show the info
1327 a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), message );
1328
1329 g_free ( message );
1330 g_free ( source );
1331 g_free ( filename );
1332}
1333
50a14534
EB
1334static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1335{
941aa6e9
AF
1336 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1337 return FALSE;
50a14534
EB
1338 if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 )
1339 {
1340 if ( event->button == 1 )
1341 {
1342 VikCoord ul, br;
1343 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 );
1344 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 );
a0b59f2f 1345 start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
50a14534
EB
1346 vml->dl_tool_x = vml->dl_tool_y = -1;
1347 return TRUE;
1348 }
1349 else
1350 {
1351 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) );
1352 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) );
1353
1354 vml->redownload_vvp = vvp;
1355
1356 vml->dl_tool_x = vml->dl_tool_y = -1;
1357
1358 if ( ! vml->dl_right_click_menu ) {
1359 GtkWidget *item;
1360 vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () );
1361
94ee2264 1362 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _Bad Map(s)") );
50a14534
EB
1363 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
1364 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1365
94ee2264 1366 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _New Map(s)") );
a7c1acf1
GB
1367 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
1368 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1369
94ee2264 1370 item = gtk_menu_item_new_with_mnemonic ( _("Redownload _All Map(s)") );
50a14534
EB
1371 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
1372 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
450d8665
RN
1373
1374 item = gtk_image_menu_item_new_with_mnemonic ( _("_Show Tile Information") );
1375 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_MENU) );
1376 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_tile_info), vml );
1377 gtk_menu_shell_append (GTK_MENU_SHELL(vml->dl_right_click_menu), item);
50a14534
EB
1378 }
1379
1380 gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
1381 gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) );
1382 }
1383 }
1384 return FALSE;
1385}
1386
941aa6e9
AF
1387static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1388{
1389 return vvp;
1390}
1391
50a14534
EB
1392static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1393{
1394 MapCoord tmp;
941aa6e9
AF
1395 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1396 return FALSE;
820c59f4
GB
1397 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1398 if ( vik_map_source_get_drawmode(map) == vik_viewport_get_drawmode ( vvp ) &&
1399 vik_map_source_coord_to_mapcoord ( map, vik_viewport_get_center ( vvp ),
50a14534
EB
1400 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1401 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1402 &tmp ) ) {
1403 vml->dl_tool_x = event->x, vml->dl_tool_y = event->y;
1404 return TRUE;
1405 }
1406 return FALSE;
1407
1408
1409#if 0
1410 if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) )
1411 {
1412 VikCoord coord;
1413 MapCoord mapcoord;
1414 vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
1415 if ( __map_types[vml->maptype].coord_to_mapcoord ( &coord,
1416 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1417 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1418 &mapcoord ) ) {
1419 gchar *filename_buf = g_strdup_printf ( DIRSTRUCTURE,
1420 vml->cache_dir, __map_types[vml->maptype].uniq_id,
1421 mapcoord.scale, mapcoord.z, mapcoord.x, mapcoord.y );
1422
1423 __map_types[vml->maptype].download ( &mapcoord, filename_buf );
1424 g_free ( filename_buf );
1425 vik_layer_emit_update ( VIK_LAYER(vml) );
1426 return TRUE;
1427 }
1428 }
1429 return FALSE;
1430#endif
1431}
1432
50817314 1433static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload )
50a14534
EB
1434{
1435 VikMapsLayer *vml = vml_vvp[0];
1436 VikViewport *vvp = vml_vvp[1];
314c1ccc 1437 VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
50a14534
EB
1438
1439 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1440 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1441
1442 VikCoord ul, br;
1443 MapCoord ulm, brm;
1444
1445 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1446 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1447
820c59f4
GB
1448 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1449 if ( vik_map_source_get_drawmode(map) == vp_drawmode &&
1450 vik_map_source_coord_to_mapcoord ( map, &ul, xzoom, yzoom, &ulm ) &&
1451 vik_map_source_coord_to_mapcoord ( map, &br, xzoom, yzoom, &brm ) )
50817314 1452 start_download_thread ( vml, vvp, &ul, &br, redownload );
820c59f4
GB
1453 else if (vik_map_source_get_drawmode(map) != vp_drawmode) {
1454 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, vik_map_source_get_drawmode(map));
4c77d5e0 1455 gchar *err = g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name));
314c1ccc
QT
1456 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1457 g_free(err);
1458 }
50a14534 1459 else
4c77d5e0 1460 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Wrong zoom level for this map.") );
50a14534
EB
1461
1462}
1463
6a4a29aa 1464static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] )
50817314
GB
1465{
1466 download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
1467}
1468
6a4a29aa
JJ
1469static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] )
1470{
1471 download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW);
1472}
1473
50817314
GB
1474static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
1475{
1476 download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
1477}
1478
50a14534
EB
1479static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp )
1480{
1481 static gpointer pass_along[2];
1482 GtkWidget *item;
1483 pass_along[0] = vml;
1484 pass_along[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) );
1485
1486 item = gtk_menu_item_new();
1487 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
1488 gtk_widget_show ( item );
1489
555ec6f6
RN
1490 /* Now with icons */
1491 item = gtk_image_menu_item_new_with_mnemonic ( _("Download _Missing Onscreen Maps") );
1492 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) );
6a4a29aa 1493 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along );
50a14534
EB
1494 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1495 gtk_widget_show ( item );
50817314 1496
c81ded98 1497 if ( vik_map_source_supports_download_only_new (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) {
555ec6f6
RN
1498 item = gtk_image_menu_item_new_with_mnemonic ( _("Download _New Onscreen Maps") );
1499 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REDO, GTK_ICON_SIZE_MENU) );
6a4a29aa
JJ
1500 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along );
1501 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1502 gtk_widget_show ( item );
1503 }
1504
555ec6f6
RN
1505 item = gtk_image_menu_item_new_with_mnemonic ( _("Reload _All Onscreen Maps") );
1506 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) );
50817314
GB
1507 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
1508 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1509 gtk_widget_show ( item );
50a14534 1510}
6b59f63d
RN
1511
1512/**
1513 * Enable downloading maps of the current screen area either 'new' or 'everything'
1514 */
1515void vik_maps_layer_download ( VikMapsLayer *vml, VikViewport *vvp, gboolean only_new )
1516{
1517 if ( !vml ) return;
1518 if ( !vvp ) return;
1519
1520 static gpointer pass_along[2];
1521 pass_along[0] = vml;
1522 pass_along[1] = vvp;
1523
1524 if ( only_new )
1525 // Get only new maps
1526 maps_layer_download_new_onscreen_maps ( pass_along );
1527 else
1528 // Redownload everything
1529 maps_layer_redownload_all_onscreen_maps ( pass_along );
1530}