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