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