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