]> git.street.me.uk Git - andy/viking.git/blame - src/vikmapslayer.c
Add a debug printf for map display
[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
EB
47#include "globals.h"
48#include "coords.h"
49#include "vikcoord.h"
50#include "viktreeview.h"
51#include "vikviewport.h"
52#include "viklayer.h"
53#include "vikmapslayer.h"
50a14534 54
45acf79e 55#ifdef HAVE_UNISTD_H
50a14534 56#include <unistd.h>
45acf79e 57#endif
50a14534
EB
58
59#include "mapcache.h"
60/* only for dialog.h -- ugh */
61#include "vikwaypoint.h"
62#include "dialog.h"
55ddef4e 63#include "preferences.h"
50a14534
EB
64
65#include "vikstatus.h"
66#include "background.h"
67
68#include "vikaggregatelayer.h"
69#include "viklayerspanel.h"
70
71#include "mapcoord.h"
72#include "terraserver.h"
50a14534 73
bce3a7b0
EB
74#include "icons/icons.h"
75
50a14534
EB
76/****** MAP TYPES ******/
77
cdcaf41c
QT
78static GList *__map_types = NULL;
79
80#define NUM_MAP_TYPES g_list_length(__map_types)
50a14534 81
cdcaf41c 82/* List of label for each map type */
a8876892 83static gchar **params_maptypes = NULL;
cdcaf41c
QT
84
85/* Corresponding IDS. (Cf. field uniq_id in VikMapsLayer struct) */
a8876892 86static guint *params_maptypes_ids = NULL;
50a14534
EB
87
88/******** MAPZOOMS *********/
89
4c77d5e0 90static gchar *params_mapzooms[] = { N_("Use Viking Zoom Level"), "0.25", "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "USGS 10k", "USGS 24k", "USGS 25k", "USGS 50k", "USGS 100k", "USGS 200k", "USGS 250k", NULL };
50a14534
EB
91static gdouble __mapzooms_x[] = { 0.0, 0.25, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 1.016, 2.4384, 2.54, 5.08, 10.16, 20.32, 25.4 };
92static gdouble __mapzooms_y[] = { 0.0, 0.25, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 1.016, 2.4384, 2.54, 5.08, 10.16, 20.32, 25.4 };
93
d756fb5c 94#define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0]) - 1)
50a14534
EB
95
96/**************************/
97
98
07059501 99static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file);
911400b5
AF
100static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len );
101static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
50a14534
EB
102static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp );
103static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id );
104static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp );
105static VikMapsLayer *maps_layer_new ( VikViewport *vvp );
106static void maps_layer_free ( VikMapsLayer *vml );
107static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
108static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
941aa6e9 109static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp );
50a14534
EB
110static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir );
111static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload );
112static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp );
113
114
115static VikLayerParamScale params_scales[] = {
116 /* min, max, step, digits (decimal places) */
117 { 0, 255, 3, 0 }, /* alpha */
118};
119
120VikLayerParam maps_layer_params[] = {
a8876892 121 { "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Map Type:"), VIK_LAYER_WIDGET_COMBOBOX, NULL, NULL },
e6fd9b70 122 { "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Maps Directory:"), VIK_LAYER_WIDGET_FOLDERENTRY },
4c77d5e0
GB
123 { "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales },
124 { "autodownload", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload maps:"), VIK_LAYER_WIDGET_CHECKBUTTON },
a8876892 125 { "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms, NULL },
50a14534
EB
126};
127
128enum { PARAM_MAPTYPE=0, PARAM_CACHE_DIR, PARAM_ALPHA, PARAM_AUTODOWNLOAD, PARAM_MAPZOOM, NUM_PARAMS };
129
130static VikToolInterface maps_tools[] = {
4c77d5e0 131 { N_("Maps Download"), (VikToolConstructorFunc) maps_layer_download_create, NULL, NULL, NULL,
bce3a7b0 132 (VikToolMouseFunc) maps_layer_download_click, NULL, (VikToolMouseFunc) maps_layer_download_release,
5bfafde9 133 (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_mapdl_pixbuf },
50a14534
EB
134};
135
136VikLayerInterface vik_maps_layer_interface = {
4c77d5e0 137 N_("Map"),
5bfafde9 138 &vikmapslayer_pixbuf,
50a14534
EB
139
140 maps_tools,
141 sizeof(maps_tools) / sizeof(maps_tools[0]),
142
143 maps_layer_params,
144 NUM_PARAMS,
145 NULL,
146 0,
147
5a4a28bf
QT
148 VIK_MENU_ITEM_ALL,
149
50a14534
EB
150 (VikLayerFuncCreate) maps_layer_new,
151 (VikLayerFuncRealize) NULL,
b112cbf5 152 (VikLayerFuncPostRead) maps_layer_post_read,
50a14534
EB
153 (VikLayerFuncFree) maps_layer_free,
154
155 (VikLayerFuncProperties) NULL,
156 (VikLayerFuncDraw) maps_layer_draw,
157 (VikLayerFuncChangeCoordMode) NULL,
158
20c7a3a0
QT
159 (VikLayerFuncSetMenuItemsSelection) NULL,
160 (VikLayerFuncGetMenuItemsSelection) NULL,
161
50a14534
EB
162 (VikLayerFuncAddMenuItems) maps_layer_add_menu_items,
163 (VikLayerFuncSublayerAddMenuItems) NULL,
164
165 (VikLayerFuncSublayerRenameRequest) NULL,
166 (VikLayerFuncSublayerToggleVisible) NULL,
167
911400b5
AF
168 (VikLayerFuncMarshall) maps_layer_marshall,
169 (VikLayerFuncUnmarshall) maps_layer_unmarshall,
50a14534
EB
170
171 (VikLayerFuncSetParam) maps_layer_set_param,
172 (VikLayerFuncGetParam) maps_layer_get_param,
173
174 (VikLayerFuncReadFileData) NULL,
175 (VikLayerFuncWriteFileData) NULL,
176
33534cd8 177 (VikLayerFuncDeleteItem) NULL,
50a14534
EB
178 (VikLayerFuncCopyItem) NULL,
179 (VikLayerFuncPasteItem) NULL,
180 (VikLayerFuncFreeCopiedItem) NULL,
70a23263 181 (VikLayerFuncDragDropRequest) NULL,
50a14534
EB
182};
183
184struct _VikMapsLayer {
185 VikLayer vl;
186 guint maptype;
187 gchar *cache_dir;
188 guint8 alpha;
189 guint mapzoom_id;
190 gdouble xmapzoom, ymapzoom;
191
192 gboolean autodownload;
10ca2bfe
QT
193 VikCoord *last_center;
194 gdouble last_xmpp;
195 gdouble last_ympp;
50a14534
EB
196
197 gint dl_tool_x, dl_tool_y;
198
199 GtkMenu *dl_right_click_menu;
200 VikCoord redownload_ul, redownload_br; /* right click menu only */
201 VikViewport *redownload_vvp;
202};
203
6a4a29aa
JJ
204enum { REDOWNLOAD_NONE = 0, /* download only missing maps */
205 REDOWNLOAD_BAD, /* download missing and bad maps */
206 REDOWNLOAD_NEW, /* download missing maps that are newer on server only */
207 REDOWNLOAD_ALL, /* download all maps */
208 DOWNLOAD_OR_REFRESH }; /* download missing maps and refresh cache */
50a14534 209
55ddef4e
JJ
210static VikLayerParam prefs[] = {
211 { VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Default maplayer directory:"), VIK_LAYER_WIDGET_FOLDERENTRY, NULL, NULL },
212};
213
214void maps_layer_init ()
215{
216 VikLayerParamData tmp;
217 tmp.s = maps_layer_default_dir();
218 a_preferences_register(prefs, tmp, VIKING_PREFERENCES_GROUP_KEY);
219}
50a14534 220
cdcaf41c
QT
221/****************************************/
222/******** MAPS LAYER TYPES **************/
223/****************************************/
224
db03733a 225void maps_layer_register_map_source ( VikMapSource *map )
cdcaf41c 226{
820c59f4 227 g_assert(map != NULL);
6846aafb 228
820c59f4 229 guint id = vik_map_source_get_uniq_id(map);
db03733a 230 const char *label = vik_map_source_get_label(map);
cdcaf41c 231 g_assert(label != NULL);
cdcaf41c 232
a8876892
GB
233 gsize len = 0;
234 if (params_maptypes)
235 len = g_strv_length (params_maptypes);
cdcaf41c 236 /* Add the label */
a8876892
GB
237 params_maptypes = g_realloc (params_maptypes, (len+2)*sizeof(gchar*));
238 params_maptypes[len] = g_strdup (label);
239 params_maptypes[len+1] = NULL;
cdcaf41c
QT
240
241 /* Add the id */
a8876892
GB
242 params_maptypes_ids = g_realloc (params_maptypes_ids, (len+2)*sizeof(guint));
243 params_maptypes_ids[len] = id;
244 params_maptypes_ids[len+1] = 0;
cdcaf41c
QT
245
246 /* We have to clone */
820c59f4 247 VikMapSource *clone = VIK_MAP_SOURCE(g_object_ref(map));
cdcaf41c
QT
248 /* Register the clone in the list */
249 __map_types = g_list_append(__map_types, clone);
250
251 /* Hack
252 We have to ensure the mode LayerParam reference the up-to-date
253 GLists.
254 */
255 /*
256 memcpy(&maps_layer_params[0].widget_data, &params_maptypes, sizeof(gpointer));
257 memcpy(&maps_layer_params[0].extra_widget_data, &params_maptypes_ids, sizeof(gpointer));
258 */
259 maps_layer_params[0].widget_data = params_maptypes;
260 maps_layer_params[0].extra_widget_data = params_maptypes_ids;
261}
262
a8876892
GB
263#define MAPS_LAYER_NTH_LABEL(n) (params_maptypes[n])
264#define MAPS_LAYER_NTH_ID(n) (params_maptypes_ids[n])
820c59f4 265#define MAPS_LAYER_NTH_TYPE(n) (VIK_MAP_SOURCE(g_list_nth_data(__map_types, (n))))
cdcaf41c 266
7114e879
QT
267gint vik_maps_layer_get_map_type(VikMapsLayer *vml)
268{
269 return(vml->maptype);
270}
271
272gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml)
273{
274 return(g_strdup(MAPS_LAYER_NTH_LABEL(vml->maptype)));
275}
276
50a14534
EB
277/****************************************/
278/******** CACHE DIR STUFF ***************/
279/****************************************/
280
3d9454e6 281#define DIRSTRUCTURE "%st%ds%dz%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d"
6a27c1bc
MA
282#define MAPS_CACHE_DIR maps_layer_default_dir()
283
50a14534 284#ifdef WINDOWS
6a27c1bc
MA
285#include <io.h>
286#define GLOBAL_MAPS_DIR "C:\\VIKING-MAPS\\"
287#define LOCAL_MAPS_DIR "VIKING-MAPS"
50a14534 288#else /* POSIX */
50a14534 289#include <stdlib.h>
50a14534 290#define GLOBAL_MAPS_DIR "/var/cache/maps/"
6a27c1bc
MA
291#define LOCAL_MAPS_DIR ".viking-maps"
292#endif
50a14534 293
0c1044e9 294gchar *maps_layer_default_dir ()
50a14534 295{
3d9454e6
GB
296 static gchar *defaultdir = NULL;
297 if ( ! defaultdir )
50a14534
EB
298 {
299 /* Thanks to Mike Davison for the $VIKING_MAPS usage */
3d9454e6
GB
300 const gchar *mapdir = g_getenv("VIKING_MAPS");
301 if ( mapdir ) {
302 defaultdir = g_strdup ( mapdir );
45acf79e 303 } else if ( g_access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) {
3d9454e6 304 defaultdir = g_strdup ( GLOBAL_MAPS_DIR );
50a14534 305 } else {
6a27c1bc 306 const gchar *home = g_get_home_dir();
45acf79e 307 if (!home || g_access(home, W_OK))
3d9454e6
GB
308 home = g_get_home_dir ();
309 if ( home )
6a27c1bc 310 defaultdir = g_build_filename ( home, LOCAL_MAPS_DIR, NULL );
50a14534 311 else
6a27c1bc 312 defaultdir = g_strdup ( LOCAL_MAPS_DIR );
50a14534 313 }
3d9454e6
GB
314 if (defaultdir && (defaultdir[strlen(defaultdir)-1] != G_DIR_SEPARATOR))
315 {
316 /* Add the separator at the end */
317 gchar *tmp = defaultdir;
318 defaultdir = g_strconcat(tmp, G_DIR_SEPARATOR_S, NULL);
319 g_free(tmp);
320 }
321 g_debug("%s: defaultdir=%s", __FUNCTION__, defaultdir);
50a14534
EB
322 }
323 return defaultdir;
324}
325
50a14534
EB
326static void maps_layer_mkdir_if_default_dir ( VikMapsLayer *vml )
327{
45acf79e 328 if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && g_file_test ( vml->cache_dir, G_FILE_TEST_EXISTS ) == FALSE )
50a14534 329 {
f83131b9 330 g_mkdir ( vml->cache_dir, 0777 );
50a14534
EB
331 }
332}
333
334static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir )
335{
336 guint len;
337 g_assert ( vml != NULL);
e65028db
GB
338 g_free ( vml->cache_dir );
339 vml->cache_dir = NULL;
50a14534
EB
340
341 if ( dir == NULL || dir[0] == '\0' )
55ddef4e 342 vml->cache_dir = g_strdup ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir")->s );
50a14534
EB
343 else
344 {
345 len = strlen(dir);
3d9454e6 346 if ( dir[len-1] != G_DIR_SEPARATOR )
50a14534
EB
347 {
348 vml->cache_dir = g_malloc ( len+2 );
349 strncpy ( vml->cache_dir, dir, len );
3d9454e6 350 vml->cache_dir[len] = G_DIR_SEPARATOR;
50a14534
EB
351 vml->cache_dir[len+1] = '\0';
352 }
353 else
354 vml->cache_dir = g_strdup ( dir );
355 }
356 maps_layer_mkdir_if_default_dir ( vml );
357}
358
359/****************************************/
360/******** GOBJECT STUFF *****************/
361/****************************************/
362
363GType vik_maps_layer_get_type ()
364{
365 static GType vml_type = 0;
366
367 if (!vml_type)
368 {
369 static const GTypeInfo vml_info =
370 {
371 sizeof (VikMapsLayerClass),
372 NULL, /* base_init */
373 NULL, /* base_finalize */
374 NULL, /* class init */
375 NULL, /* class_finalize */
376 NULL, /* class_data */
377 sizeof (VikMapsLayer),
378 0,
379 NULL /* instance init */
380 };
381 vml_type = g_type_register_static ( VIK_LAYER_TYPE, "VikMapsLayer", &vml_info, 0 );
382 }
383
384 return vml_type;
385}
386
387/****************************************/
388/************** PARAMETERS **************/
389/****************************************/
390
391static guint map_index_to_uniq_id (guint8 index)
392{
393 g_assert ( index < NUM_MAP_TYPES );
820c59f4 394 return vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(index));
50a14534
EB
395}
396
397static guint map_uniq_id_to_index ( guint uniq_id )
398{
399 gint i;
400 for ( i = 0; i < NUM_MAP_TYPES; i++ )
820c59f4 401 if ( vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(i)) == uniq_id )
50a14534
EB
402 return i;
403 return NUM_MAP_TYPES; /* no such thing */
404}
405
406static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp )
407{
408 switch ( id )
409 {
410 case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break;
411 case PARAM_MAPTYPE: {
412 gint maptype = map_uniq_id_to_index(data.u);
4c77d5e0 413 if ( maptype == NUM_MAP_TYPES ) g_warning(_("Unknown map type"));
50a14534
EB
414 else vml->maptype = maptype;
415 break;
416 }
417 case PARAM_ALPHA: if ( data.u <= 255 ) vml->alpha = data.u; break;
418 case PARAM_AUTODOWNLOAD: vml->autodownload = data.b; break;
419 case PARAM_MAPZOOM: if ( data.u < NUM_MAPZOOMS ) {
420 vml->mapzoom_id = data.u;
421 vml->xmapzoom = __mapzooms_x [data.u];
422 vml->ymapzoom = __mapzooms_y [data.u];
4c77d5e0 423 }else g_warning (_("Unknown Map Zoom")); break;
50a14534
EB
424 }
425 return TRUE;
426}
427
428static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id )
429{
430 VikLayerParamData rv;
431 switch ( id )
432 {
e6fd9b70 433 case PARAM_CACHE_DIR: rv.s = vml->cache_dir ? vml->cache_dir : ""; break;
50a14534
EB
434 case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break;
435 case PARAM_ALPHA: rv.u = vml->alpha; break;
436 case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break;
437 case PARAM_MAPZOOM: rv.u = vml->mapzoom_id; break;
438 }
439 return rv;
440}
441
442/****************************************/
443/****** CREATING, COPYING, FREEING ******/
444/****************************************/
445
446static VikMapsLayer *maps_layer_new ( VikViewport *vvp )
447{
36c78d6d 448 int idx;
50a14534
EB
449 VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) );
450 vik_layer_init ( VIK_LAYER(vml), VIK_LAYER_MAPS );
57789c45 451 idx = map_uniq_id_to_index(13); /* 13 is id for OSM Mapnik maps */
36c78d6d 452 vml->maptype = (idx < NUM_MAP_TYPES) ? idx : 0;
50a14534
EB
453 vml->alpha = 255;
454 vml->mapzoom_id = 0;
455 vml->dl_tool_x = vml->dl_tool_y = -1;
456 maps_layer_set_cache_dir ( vml, NULL );
457 vml->autodownload = FALSE;
10ca2bfe
QT
458 vml->last_center = NULL;
459 vml->last_xmpp = 0.0;
460 vml->last_ympp = 0.0;
50a14534
EB
461
462 vml->dl_right_click_menu = NULL;
463
464 return vml;
465}
466
467static void maps_layer_free ( VikMapsLayer *vml )
468{
e65028db
GB
469 g_free ( vml->cache_dir );
470 vml->cache_dir = NULL;
50a14534
EB
471 if ( vml->dl_right_click_menu )
472 gtk_object_sink ( GTK_OBJECT(vml->dl_right_click_menu) );
e65028db
GB
473 g_free(vml->last_center);
474 vml->last_center = NULL;
50a14534
EB
475}
476
07059501 477static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file)
dc5758d3 478{
07059501
GB
479 if (from_file != TRUE)
480 {
481 /* If this method is not called in file reading context
482 * it is called in GUI context.
483 * So, we can check if we have to inform the user about inconsistency */
484 VikViewportDrawMode vp_drawmode;
485 VikMapsLayer *vml = VIK_MAPS_LAYER(vl);
820c59f4 486 VikMapSource *map = NULL;
dc5758d3 487
07059501 488 vp_drawmode = vik_viewport_get_drawmode ( VIK_VIEWPORT(vp) );
820c59f4
GB
489 map = MAPS_LAYER_NTH_TYPE(vml->maptype);
490 if (vik_map_source_get_drawmode(map) != vp_drawmode) {
491 const gchar *drawmode_name = vik_viewport_get_drawmode_name (VIK_VIEWPORT(vp), vik_map_source_get_drawmode(map));
4c77d5e0 492 gchar *msg = g_strdup_printf(_("New map cannot be displayed in the current drawmode.\nSelect \"%s\" from View menu to view it."), drawmode_name);
07059501
GB
493 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), msg );
494 g_free(msg);
495 }
dc5758d3
GB
496 }
497}
498
911400b5
AF
499static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len )
500{
501 vik_layer_marshall_params ( VIK_LAYER(vml), data, len );
502}
503
504static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
505{
506 VikMapsLayer *rv = maps_layer_new ( vvp );
507 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
508 return rv;
509}
510
50a14534
EB
511/*********************/
512/****** DRAWING ******/
513/*********************/
514
515static GdkPixbuf *pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha )
516{
517 guchar *pixels;
518 gint width, height, iii, jjj;
519
520 if ( ! gdk_pixbuf_get_has_alpha ( pixbuf ) )
521 {
522 GdkPixbuf *tmp = gdk_pixbuf_add_alpha(pixbuf,FALSE,0,0,0);
523 g_object_unref(G_OBJECT(pixbuf));
524 pixbuf = tmp;
525 }
526
527 pixels = gdk_pixbuf_get_pixels(pixbuf);
528 width = gdk_pixbuf_get_width(pixbuf);
529 height = gdk_pixbuf_get_height(pixbuf);
530
531 /* r,g,b,a,r,g,b,a.... */
532 for (iii = 0; iii < width; iii++) for (jjj = 0; jjj < height; jjj++)
533 {
534 pixels += 3;
535 *pixels++ = alpha;
536 }
537 return pixbuf;
538}
539
540static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdouble yshrinkfactor )
541{
542 GdkPixbuf *tmp;
543 guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf);
9fdb940f 544 tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_NEAREST);
50a14534
EB
545 g_object_unref ( G_OBJECT(pixbuf) );
546 return tmp;
547}
548
549static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, gchar *filename_buf, gint buf_len, gdouble xshrinkfactor, gdouble yshrinkfactor )
550{
551 GdkPixbuf *pixbuf;
552
553 /* get the thing */
554 pixbuf = a_mapcache_get ( mapcoord->x, mapcoord->y, mapcoord->z,
555 mode, mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
556
557 if ( ! pixbuf ) {
558 g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE,
559 vml->cache_dir, mode,
560 mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y );
01ecda7e 561 if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
50a14534
EB
562 {
563 GError *gx = NULL;
564 pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx );
565
01ecda7e 566 /* free the pixbuf on error */
50a14534
EB
567 if (gx)
568 {
569 if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE )
4c77d5e0 570 g_warning ( _("Couldn't open image file: %s"), gx->message );
50a14534 571
01ecda7e
MR
572 g_error_free ( gx );
573 if ( pixbuf )
574 g_object_unref ( G_OBJECT(pixbuf) );
575 pixbuf = NULL;
576 } else {
50a14534
EB
577 if ( vml->alpha < 255 )
578 pixbuf = pixbuf_set_alpha ( pixbuf, vml->alpha );
579 if ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 )
580 pixbuf = pixbuf_shrink ( pixbuf, xshrinkfactor, yshrinkfactor );
581
582 a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y,
820c59f4 583 mapcoord->z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(vml->maptype)),
50a14534 584 mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
50a14534
EB
585 }
586 }
587 }
588 return pixbuf;
589}
590
10ca2bfe
QT
591gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp)
592{
593 const VikCoord *center = vik_viewport_get_center ( vvp );
594
595 if (vml->last_center == NULL) {
596 VikCoord *new_center = g_malloc(sizeof(VikCoord));
597 *new_center = *center;
598 vml->last_center = new_center;
599 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
600 vml->last_ympp = vik_viewport_get_ympp(vvp);
601 return TRUE;
602 }
603
604 /* TODO: perhaps vik_coord_diff() */
605 if (vik_coord_equals(vml->last_center, center)
606 && (vml->last_xmpp == vik_viewport_get_xmpp(vvp))
607 && (vml->last_ympp == vik_viewport_get_ympp(vvp)))
608 return FALSE;
609
610 *(vml->last_center) = *center;
611 vml->last_xmpp = vik_viewport_get_xmpp(vvp);
612 vml->last_ympp = vik_viewport_get_ympp(vvp);
613 return TRUE;
614}
615
50a14534
EB
616static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br )
617{
618 MapCoord ulm, brm;
619 gdouble xzoom = vik_viewport_get_xmpp ( vvp );
620 gdouble yzoom = vik_viewport_get_ympp ( vvp );
621 gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0;
732d1e25 622 gdouble existence_only = FALSE;
50a14534
EB
623
624 if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) {
625 xshrinkfactor = vml->xmapzoom / xzoom;
626 yshrinkfactor = vml->ymapzoom / yzoom;
732d1e25
EB
627 xzoom = vml->xmapzoom;
628 yzoom = vml->xmapzoom;
629 if ( ! (xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR &&
630 yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) ) {
631 if ( xshrinkfactor > REAL_MIN_SHRINKFACTOR && yshrinkfactor > REAL_MIN_SHRINKFACTOR )
632 existence_only = TRUE;
633 else {
4c77d5e0 634 g_warning ( _("Cowardly refusing to draw tiles or existence of tiles beyond %d zoom out factor"), (int)( 1.0/REAL_MIN_SHRINKFACTOR));
732d1e25
EB
635 return;
636 }
50a14534
EB
637 }
638 }
639
640 /* coord -> ID */
820c59f4
GB
641 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
642 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm ) &&
643 vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) ) {
50a14534
EB
644
645 /* loop & draw */
646 gint x, y;
647 gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x);
648 gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y);
820c59f4 649 gint mode = vik_map_source_get_uniq_id(map);
50a14534
EB
650
651 VikCoord coord;
652 gint xx, yy, width, height;
653 GdkPixbuf *pixbuf;
654
655 guint max_path_len = strlen(vml->cache_dir) + 40;
656 gchar *path_buf = g_malloc ( max_path_len * sizeof(char) );
657
732d1e25 658 if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) {
214f9ac2
QT
659#ifdef DEBUG
660 fputs(stderr, "DEBUG: Starting autodownload\n");
661#endif
0f08bd0d 662 if ( vik_map_source_supports_if_modified_since (map) )
245f48f5
GB
663 // Try to download newer tiles
664 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
665 else
666 // Download only missing tiles
667 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
10ca2bfe 668 }
50a14534 669
820c59f4 670 if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) {
50a14534
EB
671 for ( x = xmin; x <= xmax; x++ ) {
672 for ( y = ymin; y <= ymax; y++ ) {
673 ulm.x = x;
674 ulm.y = y;
675 pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
676 if ( pixbuf ) {
677 width = gdk_pixbuf_get_width ( pixbuf );
678 height = gdk_pixbuf_get_height ( pixbuf );
679
820c59f4 680 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
50a14534
EB
681 vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy );
682 xx -= (width/2);
683 yy -= (height/2);
684
685 vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height );
686 }
687 }
688 }
689 } else { /* tilesize is known, don't have to keep converting coords */
820c59f4
GB
690 gdouble tilesize_x = vik_map_source_get_tilesize_x(map) * xshrinkfactor;
691 gdouble tilesize_y = vik_map_source_get_tilesize_y(map) * yshrinkfactor;
50a14534
EB
692 /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
693 gint tilesize_x_ceil = ceil ( tilesize_x );
694 gint tilesize_y_ceil = ceil ( tilesize_y );
695 gint8 xinc = (ulm.x == xmin) ? 1 : -1;
696 gint8 yinc = (ulm.y == ymin) ? 1 : -1;
697 gdouble xx, yy; gint xx_tmp, yy_tmp;
698 gint base_yy, xend, yend;
732d1e25
EB
699
700 GdkGC *black_gc = GTK_WIDGET(vvp)->style->black_gc;
701
50a14534
EB
702 xend = (xinc == 1) ? (xmax+1) : (xmin-1);
703 yend = (yinc == 1) ? (ymax+1) : (ymin-1);
704
820c59f4 705 vik_map_source_mapcoord_to_center_coord ( map, &ulm, &coord );
50a14534
EB
706 vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp );
707 xx = xx_tmp; yy = yy_tmp;
708 /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
709 * eg if tile size 128, shrinkfactor 0.333 */
710 xx -= (tilesize_x/2);
711 base_yy = yy - (tilesize_y/2);
712
713 for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) {
714 yy = base_yy;
715 for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) {
716 ulm.x = x;
717 ulm.y = y;
732d1e25
EB
718
719 if ( existence_only ) {
720 g_snprintf ( path_buf, max_path_len, DIRSTRUCTURE,
721 vml->cache_dir, mode,
722 ulm.scale, ulm.z, ulm.x, ulm.y );
45acf79e 723 if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) {
732d1e25
EB
724 vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil );
725 }
726 } else {
6f0d1bea
JJ
727 int scale_inc;
728 for (scale_inc = 0; scale_inc < 4; scale_inc ++) {
729 /* try with correct then smaller zooms */
730 int scale_factor = 1 << scale_inc; /* 2^scale_inc */
731 MapCoord ulm2 = ulm;
732 ulm2.x = ulm.x / scale_factor;
733 ulm2.y = ulm.y / scale_factor;
734 ulm2.scale = ulm.scale + scale_inc;
735 pixbuf = get_pixbuf ( vml, mode, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor );
736 if ( pixbuf ) {
737 gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil;
738 gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil;
40cfc175
JJ
739#ifdef DEBUG
740 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);
741#endif
6f0d1bea
JJ
742 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
743 break;
744 }
745 }
746 if ( !pixbuf ) {
747 /* retry with bigger zooms */
748 int scale_dec;
749 for (scale_dec = 1; scale_dec < 2; scale_dec ++) {
750 int pict_x, pict_y;
751 int scale_factor = 1 << scale_dec; /* 2^scale_dec */
91dc4449 752 MapCoord ulm2 = ulm;
6f0d1bea
JJ
753 ulm2.x = ulm.x * scale_factor;
754 ulm2.y = ulm.y * scale_factor;
755 ulm2.scale = ulm.scale - scale_dec;
756 for (pict_x = 0; pict_x < scale_factor; pict_x ++) {
757 for (pict_y = 0; pict_y < scale_factor; pict_y ++) {
758 MapCoord ulm3 = ulm2;
759 ulm3.x += pict_x;
760 ulm3.y += pict_y;
761 pixbuf = get_pixbuf ( vml, mode, &ulm3, path_buf, max_path_len, xshrinkfactor / scale_factor, yshrinkfactor / scale_factor );
762 if ( pixbuf ) {
763 gint src_x = 0;
764 gint src_y = 0;
765 gint dest_x = xx + pict_x * (tilesize_x_ceil / scale_factor);
766 gint dest_y = yy + pict_y * (tilesize_y_ceil / scale_factor);
767 vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, dest_x, dest_y, tilesize_x_ceil / scale_factor, tilesize_y_ceil / scale_factor );
768 }
769 }
91dc4449
JJ
770 }
771 }
772 }
732d1e25 773 }
50a14534
EB
774
775 yy += tilesize_y;
776 }
777 xx += tilesize_x;
778 }
779 }
780
781 g_free ( path_buf );
782 }
783}
784
785static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp )
786{
820c59f4 787 if ( vik_map_source_get_drawmode(MAPS_LAYER_NTH_TYPE(vml->maptype)) == vik_viewport_get_drawmode ( vvp ) )
50a14534
EB
788 {
789 VikCoord ul, br;
790
791 /* get corner coords */
792 if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) {
793 /* UTM multi-zone stuff by Kit Transue */
794 gchar leftmost_zone, rightmost_zone, i;
795 leftmost_zone = vik_viewport_leftmost_zone( vvp );
796 rightmost_zone = vik_viewport_rightmost_zone( vvp );
797 for ( i = leftmost_zone; i <= rightmost_zone; ++i ) {
798 vik_viewport_corners_for_zonen ( vvp, i, &ul, &br );
799 maps_layer_draw_section ( vml, vvp, &ul, &br );
800 }
801 }
802 else {
803 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
804 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
805
806 maps_layer_draw_section ( vml, vvp, &ul, &br );
807 }
808 }
809}
810
811/*************************/
812/****** DOWNLOADING ******/
813/*************************/
814
815/* pass along data to thread, exists even if layer is deleted. */
816typedef struct {
817 gchar *cache_dir;
818 gchar *filename_buf;
819 gint x0, y0, xf, yf;
820 MapCoord mapcoord;
821 gint maptype;
822 gint maxlen;
823 gint mapstoget;
824 gint redownload;
7114e879 825 gboolean refresh_display;
550fd035
QT
826 VikMapsLayer *vml;
827 VikViewport *vvp;
828 gboolean map_layer_alive;
829 GMutex *mutex;
50a14534
EB
830} MapDownloadInfo;
831
832static void mdi_free ( MapDownloadInfo *mdi )
833{
550fd035 834 g_mutex_free(mdi->mutex);
50a14534 835 g_free ( mdi->cache_dir );
e65028db 836 mdi->cache_dir = NULL;
50a14534 837 g_free ( mdi->filename_buf );
e65028db 838 mdi->filename_buf = NULL;
50a14534
EB
839 g_free ( mdi );
840}
841
7bb60307 842static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
550fd035 843{
7bb60307 844 MapDownloadInfo *mdi = ptr;
550fd035
QT
845 g_mutex_lock(mdi->mutex);
846 mdi->map_layer_alive = FALSE;
847 g_mutex_unlock(mdi->mutex);
848}
849
634eca0a 850static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
50a14534 851{
825413ba 852 void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype));
50a14534
EB
853 guint donemaps = 0;
854 gint x, y;
855 for ( x = mdi->x0; x <= mdi->xf; x++ )
856 {
857 for ( y = mdi->y0; y <= mdi->yf; y++ )
858 {
94493114 859 gboolean remove_mem_cache = FALSE;
84628352 860 gboolean need_download = FALSE;
50a14534 861 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 862 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
50a14534
EB
863 mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
864
84628352 865 donemaps++;
634eca0a 866 int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
825413ba
SW
867 if (res != 0) {
868 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
634eca0a 869 return -1;
825413ba 870 }
84628352 871
50a14534 872 if ( mdi->redownload == REDOWNLOAD_ALL)
8c060406 873 g_remove ( mdi->filename_buf );
093c5c71 874
45acf79e 875 else if ( (mdi->redownload == REDOWNLOAD_BAD) && (g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE) )
50a14534
EB
876 {
877 /* see if this one is bad or what */
878 GError *gx = NULL;
879 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
880 if (gx || (!pixbuf))
8c060406 881 g_remove ( mdi->filename_buf );
50a14534
EB
882 if ( pixbuf )
883 g_object_unref ( pixbuf );
884 if ( gx )
885 g_error_free ( gx );
886 }
887
45acf79e 888 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
50a14534 889 {
84628352
QT
890 need_download = TRUE;
891 if (( mdi->redownload != REDOWNLOAD_NONE ) &&
a0b59f2f 892 ( mdi->redownload != DOWNLOAD_OR_REFRESH ))
94493114
QT
893 remove_mem_cache = TRUE;
894 } else if ( mdi->redownload == DOWNLOAD_OR_REFRESH ) {
895 remove_mem_cache = TRUE;
6a4a29aa
JJ
896 } else if ( mdi->redownload == REDOWNLOAD_NEW) {
897 need_download = TRUE;
898 remove_mem_cache = TRUE;
94493114
QT
899 } else
900 continue;
901
94493114 902 mdi->mapcoord.x = x; mdi->mapcoord.y = y;
84628352
QT
903
904 if (need_download) {
825413ba 905 if ( vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle))
94493114 906 continue;
84628352 907 }
94493114
QT
908
909 gdk_threads_enter();
910 g_mutex_lock(mdi->mutex);
911 if (remove_mem_cache)
820c59f4 912 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 913 if (mdi->refresh_display && mdi->map_layer_alive) {
94493114
QT
914 /* TODO: check if it's on visible area */
915 vik_layer_emit_update ( VIK_LAYER(mdi->vml) );
a0b59f2f 916 }
94493114
QT
917 g_mutex_unlock(mdi->mutex);
918 gdk_threads_leave();
919 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
920
50a14534
EB
921 }
922 }
825413ba 923 vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
04e54492
QT
924 g_mutex_lock(mdi->mutex);
925 if (mdi->map_layer_alive)
7bb60307 926 g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
04e54492 927 g_mutex_unlock(mdi->mutex);
634eca0a 928 return 0;
50a14534
EB
929}
930
931static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
932{
933 if ( mdi->mapcoord.x || mdi->mapcoord.y )
934 {
935 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 936 mdi->cache_dir, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
50a14534 937 mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y );
45acf79e 938 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
50a14534 939 {
8c060406 940 g_remove ( mdi->filename_buf );
50a14534
EB
941 }
942 }
943}
944
945static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload )
946{
947 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
948 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
949 MapCoord ulm, brm;
820c59f4
GB
950 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
951 if ( vik_map_source_coord_to_mapcoord ( map, ul, xzoom, yzoom, &ulm )
952 && vik_map_source_coord_to_mapcoord ( map, br, xzoom, yzoom, &brm ) )
50a14534
EB
953 {
954 MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
955 gint a, b;
956
550fd035
QT
957 mdi->vml = vml;
958 mdi->vvp = vvp;
959 mdi->map_layer_alive = TRUE;
960 mdi->mutex = g_mutex_new();
7114e879 961 mdi->refresh_display = TRUE;
550fd035 962
50a14534
EB
963 /* cache_dir and buffer for dest filename */
964 mdi->cache_dir = g_strdup ( vml->cache_dir );
965 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
966 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
967 mdi->maptype = vml->maptype;
968
969 mdi->mapcoord = ulm;
970
971 mdi->redownload = redownload;
972
973 mdi->x0 = MIN(ulm.x, brm.x);
974 mdi->xf = MAX(ulm.x, brm.x);
975 mdi->y0 = MIN(ulm.y, brm.y);
976 mdi->yf = MAX(ulm.y, brm.y);
977
978 mdi->mapstoget = 0;
979
980 if ( mdi->redownload ) {
981 mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
982 } else {
983 /* calculate how many we need */
984 for ( a = mdi->x0; a <= mdi->xf; a++ )
985 {
986 for ( b = mdi->y0; b <= mdi->yf; b++ )
987 {
988 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 989 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
50a14534 990 ulm.z, a, b );
45acf79e 991 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
50a14534
EB
992 mdi->mapstoget++;
993 }
994 }
995 }
996
997 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
998
999 if ( mdi->mapstoget )
1000 {
97634600
GB
1001 const gchar *tmp_str;
1002 gchar *tmp;
50a14534 1003
97634600
GB
1004 if (redownload)
1005 {
1006 if (redownload == REDOWNLOAD_BAD)
1007 tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget);
1008 else
1009 tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget);
1010 }
1011 else
1012 {
1013 tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget);
1014 }
1015 tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype));
1016
7bb60307 1017 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
50a14534
EB
1018 /* launch the thread */
1019 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1020 tmp, /* description string */
1021 (vik_thr_func) map_download_thread, /* function to call within thread */
1022 mdi, /* pass along data */
1023 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1024 (vik_thr_free_func) mdi_cancel_cleanup,
1025 mdi->mapstoget );
1026 g_free ( tmp );
1027 }
1028 else
1029 mdi_free ( mdi );
1030 }
1031}
1032
7114e879
QT
1033void maps_layer_download_section_without_redraw( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom)
1034{
7114e879 1035 MapCoord ulm, brm;
820c59f4 1036 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
7114e879 1037
820c59f4
GB
1038 if (!vik_map_source_coord_to_mapcoord(map, ul, zoom, zoom, &ulm)
1039 || !vik_map_source_coord_to_mapcoord(map, br, zoom, zoom, &brm)) {
4258f4e2 1040 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
7114e879
QT
1041 return;
1042 }
1043
1044 MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
1045 gint i, j;
1046
1047 mdi->vml = vml;
1048 mdi->vvp = vvp;
1049 mdi->map_layer_alive = TRUE;
1050 mdi->mutex = g_mutex_new();
1051 mdi->refresh_display = FALSE;
1052
1053 mdi->cache_dir = g_strdup ( vml->cache_dir );
1054 mdi->maxlen = strlen ( vml->cache_dir ) + 40;
1055 mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
1056 mdi->maptype = vml->maptype;
1057
1058 mdi->mapcoord = ulm;
1059
1060 mdi->redownload = REDOWNLOAD_NONE;
1061
1062 mdi->x0 = MIN(ulm.x, brm.x);
1063 mdi->xf = MAX(ulm.x, brm.x);
1064 mdi->y0 = MIN(ulm.y, brm.y);
1065 mdi->yf = MAX(ulm.y, brm.y);
1066
1067 mdi->mapstoget = 0;
1068
1069 for (i = mdi->x0; i <= mdi->xf; i++) {
1070 for (j = mdi->y0; j <= mdi->yf; j++) {
1071 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
820c59f4 1072 vml->cache_dir, vik_map_source_get_uniq_id(map), ulm.scale,
7114e879 1073 ulm.z, i, j );
45acf79e 1074 if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
7114e879
QT
1075 mdi->mapstoget++;
1076 }
1077 }
1078
1079 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
1080
1081 if (mdi->mapstoget) {
4c77d5e0
GB
1082 gchar *tmp;
1083 const gchar *fmt;
eb6b0125
JJ
1084 fmt = ngettext("Downloading %d %s map...",
1085 "Downloading %d %s maps...",
1086 mdi->mapstoget);
4c77d5e0 1087 tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) );
7114e879
QT
1088
1089 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
1090 /* launch the thread */
1091 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
1092 tmp, /* description string */
1093 (vik_thr_func) map_download_thread, /* function to call within thread */
1094 mdi, /* pass along data */
1095 (vik_thr_free_func) mdi_free, /* function to free pass along data */
1096 (vik_thr_free_func) mdi_cancel_cleanup,
1097 mdi->mapstoget );
1098 g_free ( tmp );
1099 }
1100 else
1101 mdi_free ( mdi );
1102}
1103
50a14534
EB
1104static void maps_layer_redownload_bad ( VikMapsLayer *vml )
1105{
1106 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
1107}
a7c1acf1 1108
50a14534
EB
1109static void maps_layer_redownload_all ( VikMapsLayer *vml )
1110{
1111 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
1112}
1113
a7c1acf1
GB
1114static void maps_layer_redownload_new ( VikMapsLayer *vml )
1115{
1116 start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
1117}
1118
50a14534
EB
1119static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1120{
941aa6e9
AF
1121 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1122 return FALSE;
50a14534
EB
1123 if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 )
1124 {
1125 if ( event->button == 1 )
1126 {
1127 VikCoord ul, br;
1128 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 );
1129 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 1130 start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
50a14534
EB
1131 vml->dl_tool_x = vml->dl_tool_y = -1;
1132 return TRUE;
1133 }
1134 else
1135 {
1136 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) );
1137 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) );
1138
1139 vml->redownload_vvp = vvp;
1140
1141 vml->dl_tool_x = vml->dl_tool_y = -1;
1142
1143 if ( ! vml->dl_right_click_menu ) {
1144 GtkWidget *item;
1145 vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () );
1146
4c77d5e0 1147 item = gtk_menu_item_new_with_label ( _("Redownload bad map(s)") );
50a14534
EB
1148 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
1149 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1150
a7c1acf1
GB
1151 item = gtk_menu_item_new_with_label ( _("Redownload new map(s)") );
1152 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
1153 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1154
4c77d5e0 1155 item = gtk_menu_item_new_with_label ( _("Redownload all map(s)") );
50a14534
EB
1156 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
1157 gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1158 }
1159
1160 gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
1161 gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) );
1162 }
1163 }
1164 return FALSE;
1165}
1166
941aa6e9
AF
1167static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1168{
1169 return vvp;
1170}
1171
50a14534
EB
1172static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1173{
1174 MapCoord tmp;
941aa6e9
AF
1175 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1176 return FALSE;
820c59f4
GB
1177 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1178 if ( vik_map_source_get_drawmode(map) == vik_viewport_get_drawmode ( vvp ) &&
1179 vik_map_source_coord_to_mapcoord ( map, vik_viewport_get_center ( vvp ),
50a14534
EB
1180 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1181 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1182 &tmp ) ) {
1183 vml->dl_tool_x = event->x, vml->dl_tool_y = event->y;
1184 return TRUE;
1185 }
1186 return FALSE;
1187
1188
1189#if 0
1190 if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) )
1191 {
1192 VikCoord coord;
1193 MapCoord mapcoord;
1194 vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
1195 if ( __map_types[vml->maptype].coord_to_mapcoord ( &coord,
1196 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1197 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1198 &mapcoord ) ) {
1199 gchar *filename_buf = g_strdup_printf ( DIRSTRUCTURE,
1200 vml->cache_dir, __map_types[vml->maptype].uniq_id,
1201 mapcoord.scale, mapcoord.z, mapcoord.x, mapcoord.y );
1202
1203 __map_types[vml->maptype].download ( &mapcoord, filename_buf );
1204 g_free ( filename_buf );
1205 vik_layer_emit_update ( VIK_LAYER(vml) );
1206 return TRUE;
1207 }
1208 }
1209 return FALSE;
1210#endif
1211}
1212
50817314 1213static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload )
50a14534
EB
1214{
1215 VikMapsLayer *vml = vml_vvp[0];
1216 VikViewport *vvp = vml_vvp[1];
314c1ccc 1217 VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
50a14534
EB
1218
1219 gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1220 gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1221
1222 VikCoord ul, br;
1223 MapCoord ulm, brm;
1224
1225 vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1226 vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1227
820c59f4
GB
1228 VikMapSource *map = MAPS_LAYER_NTH_TYPE(vml->maptype);
1229 if ( vik_map_source_get_drawmode(map) == vp_drawmode &&
1230 vik_map_source_coord_to_mapcoord ( map, &ul, xzoom, yzoom, &ulm ) &&
1231 vik_map_source_coord_to_mapcoord ( map, &br, xzoom, yzoom, &brm ) )
50817314 1232 start_download_thread ( vml, vvp, &ul, &br, redownload );
820c59f4
GB
1233 else if (vik_map_source_get_drawmode(map) != vp_drawmode) {
1234 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, vik_map_source_get_drawmode(map));
4c77d5e0 1235 gchar *err = g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name));
314c1ccc
QT
1236 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1237 g_free(err);
1238 }
50a14534 1239 else
4c77d5e0 1240 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), _("Wrong zoom level for this map.") );
50a14534
EB
1241
1242}
1243
6a4a29aa 1244static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] )
50817314
GB
1245{
1246 download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
1247}
1248
6a4a29aa
JJ
1249static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] )
1250{
1251 download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW);
1252}
1253
50817314
GB
1254static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
1255{
1256 download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
1257}
1258
50a14534
EB
1259static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp )
1260{
1261 static gpointer pass_along[2];
1262 GtkWidget *item;
1263 pass_along[0] = vml;
1264 pass_along[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) );
1265
1266 item = gtk_menu_item_new();
1267 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
1268 gtk_widget_show ( item );
1269
6a4a29aa
JJ
1270 item = gtk_menu_item_new_with_label ( _("Download missing Onscreen Maps") );
1271 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along );
50a14534
EB
1272 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1273 gtk_widget_show ( item );
50817314 1274
0f08bd0d 1275 if ( vik_map_source_supports_if_modified_since (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) {
6a4a29aa
JJ
1276 item = gtk_menu_item_new_with_label ( _("Download new Onscreen Maps from server") );
1277 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along );
1278 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1279 gtk_widget_show ( item );
1280 }
1281
1b86e056 1282 /* TODO Add GTK_STOCK_REFRESH icon */
4c77d5e0 1283 item = gtk_menu_item_new_with_label ( _("Refresh Onscreen Tiles") );
50817314
GB
1284 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
1285 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1286 gtk_widget_show ( item );
50a14534 1287}