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