]>
Commit | Line | Data |
---|---|---|
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> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 | * | |
21 | */ | |
22 | ||
23 | #define MAX_SHRINKFACTOR 8.0000001 /* zoom 1 viewing 8-tiles */ | |
24 | #define MIN_SHRINKFACTOR 0.0312499 /* zoom 32 viewing 1-tiles */ | |
25 | ||
26 | #include <gtk/gtk.h> | |
27 | #include <gdk-pixbuf/gdk-pixdata.h> | |
28 | #include <stdio.h> | |
29 | #include <string.h> | |
30 | #include <math.h> | |
31 | #include "globals.h" | |
32 | #include "coords.h" | |
33 | #include "vikcoord.h" | |
34 | #include "viktreeview.h" | |
35 | #include "vikviewport.h" | |
36 | #include "viklayer.h" | |
37 | #include "vikmapslayer.h" | |
38 | #include "vikmapslayer_pixmap.h" | |
39 | ||
40 | #include <unistd.h> | |
41 | #include <sys/stat.h> | |
42 | #include <sys/types.h> | |
43 | ||
44 | #include "mapcache.h" | |
45 | /* only for dialog.h -- ugh */ | |
46 | #include "vikwaypoint.h" | |
47 | #include "dialog.h" | |
48 | ||
49 | #include "vikstatus.h" | |
50 | #include "background.h" | |
51 | ||
52 | #include "vikaggregatelayer.h" | |
53 | #include "viklayerspanel.h" | |
54 | ||
55 | #include "mapcoord.h" | |
56 | #include "terraserver.h" | |
57 | #include "googlemaps.h" | |
58 | #include "google.h" | |
59 | #include "khmaps.h" | |
60 | #include "expedia.h" | |
61 | #include "usgs.h" | |
62 | ||
63 | typedef struct { | |
64 | guint8 uniq_id; | |
65 | guint16 tilesize_x; | |
66 | guint16 tilesize_y; | |
67 | guint drawmode; | |
68 | gboolean (*coord_to_mapcoord) ( const VikCoord *src, gdouble xzoom, gdouble yzoom, MapCoord *dest ); | |
69 | void (*mapcoord_to_center_coord) ( MapCoord *src, VikCoord *dest ); | |
70 | void (*download) ( MapCoord *src, const gchar *dest_fn ); | |
71 | /* TODO: constant size (yay!) */ | |
72 | } VikMapsLayer_MapType; | |
73 | ||
74 | ||
75 | /****** MAP TYPES ******/ | |
76 | ||
77 | static const VikMapsLayer_MapType __map_types[] = { | |
78 | ||
79 | { 2, 200, 200, VIK_VIEWPORT_DRAWMODE_UTM, terraserver_topo_coord_to_mapcoord, terraserver_mapcoord_to_center_coord, terraserver_topo_download }, | |
80 | { 1, 200, 200, VIK_VIEWPORT_DRAWMODE_UTM, terraserver_aerial_coord_to_mapcoord, terraserver_mapcoord_to_center_coord, terraserver_aerial_download }, | |
81 | { 4, 200, 200, VIK_VIEWPORT_DRAWMODE_UTM, terraserver_urban_coord_to_mapcoord, terraserver_mapcoord_to_center_coord, terraserver_urban_download }, | |
82 | { 5, 0, 0, VIK_VIEWPORT_DRAWMODE_EXPEDIA, expedia_coord_to_mapcoord, expedia_mapcoord_to_center_coord, expedia_download }, | |
83 | { 9, 128, 128, VIK_VIEWPORT_DRAWMODE_GOOGLE, googlemaps_coord_to_mapcoord, googlemaps_mapcoord_to_center_coord, googlemaps_download }, | |
84 | { 6, 800, 600, VIK_VIEWPORT_DRAWMODE_UTM, usgs_coord_to_mapcoord, usgs_mapcoord_to_center_coord, usgs_download }, | |
85 | { 8, 256, 256, VIK_VIEWPORT_DRAWMODE_KH, khmaps_coord_to_mapcoord, khmaps_mapcoord_to_center_coord, khmaps_download }, | |
86 | { 7, 256, 256, VIK_VIEWPORT_DRAWMODE_MERCATOR, google_coord_to_mapcoord, google_mapcoord_to_center_coord, google_download }, | |
87 | { 10, 256, 256, VIK_VIEWPORT_DRAWMODE_MERCATOR, google_coord_to_mapcoord, google_mapcoord_to_center_coord, google_trans_download }, | |
88 | { 11, 256, 256, VIK_VIEWPORT_DRAWMODE_MERCATOR, google_coord_to_mapcoord, google_mapcoord_to_center_coord, google_kh_download }, | |
89 | }; | |
90 | ||
91 | #define NUM_MAP_TYPES (sizeof(__map_types)/sizeof(__map_types[0])) | |
92 | ||
93 | /******** MAPZOOMS *********/ | |
94 | ||
95 | static 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" }; | |
96 | static 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 }; | |
97 | static 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 }; | |
98 | ||
99 | static gchar *params_maptypes[] = { "Terraserver Topos", "Terraserver Aerials", "Terraserver Urban Areas", "Expedia (Street Maps)", "Google Maps (Street)", "USGS", "KH Maps", "New (Mercator) Google", "Transparent Google", "New (Mercator) KH" }; | |
100 | static guint params_maptypes_ids[] = { 2, 1, 4, 5, 9, 6, 8, 7, 10, 11 }; | |
101 | #define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0])) | |
102 | ||
103 | /**************************/ | |
104 | ||
105 | ||
106 | static VikMapsLayer *maps_layer_copy ( VikMapsLayer *vml, VikViewport *vvp ); | |
107 | static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp ); | |
108 | static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id ); | |
109 | static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp ); | |
110 | static VikMapsLayer *maps_layer_new ( VikViewport *vvp ); | |
111 | static void maps_layer_free ( VikMapsLayer *vml ); | |
112 | static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp ); | |
113 | static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp ); | |
114 | static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir ); | |
115 | static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload ); | |
116 | static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp ); | |
117 | ||
118 | ||
119 | static VikLayerParamScale params_scales[] = { | |
120 | /* min, max, step, digits (decimal places) */ | |
121 | { 0, 255, 3, 0 }, /* alpha */ | |
122 | }; | |
123 | ||
124 | VikLayerParam maps_layer_params[] = { | |
125 | { "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, "Map Type:", VIK_LAYER_WIDGET_RADIOGROUP, params_maptypes, params_maptypes_ids }, | |
126 | { "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, "Maps Directory (Optional):", VIK_LAYER_WIDGET_FILEENTRY }, | |
127 | { "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, "Alpha:", VIK_LAYER_WIDGET_HSCALE, params_scales }, | |
128 | { "autodownload", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, "Autodownload maps:", VIK_LAYER_WIDGET_CHECKBUTTON }, | |
129 | { "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, "Zoom Level:", VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms }, | |
130 | }; | |
131 | ||
132 | enum { PARAM_MAPTYPE=0, PARAM_CACHE_DIR, PARAM_ALPHA, PARAM_AUTODOWNLOAD, PARAM_MAPZOOM, NUM_PARAMS }; | |
133 | ||
134 | static VikToolInterface maps_tools[] = { | |
135 | { "Maps Download", (VikToolInterfaceFunc) maps_layer_download_click, (VikToolInterfaceFunc) maps_layer_download_release }, | |
136 | }; | |
137 | ||
138 | VikLayerInterface vik_maps_layer_interface = { | |
139 | "Map", | |
140 | &mapslayer_pixbuf, | |
141 | ||
142 | maps_tools, | |
143 | sizeof(maps_tools) / sizeof(maps_tools[0]), | |
144 | ||
145 | maps_layer_params, | |
146 | NUM_PARAMS, | |
147 | NULL, | |
148 | 0, | |
149 | ||
150 | (VikLayerFuncCreate) maps_layer_new, | |
151 | (VikLayerFuncRealize) NULL, | |
152 | (VikLayerFuncPostRead) NULL, | |
153 | (VikLayerFuncFree) maps_layer_free, | |
154 | ||
155 | (VikLayerFuncProperties) NULL, | |
156 | (VikLayerFuncDraw) maps_layer_draw, | |
157 | (VikLayerFuncChangeCoordMode) NULL, | |
158 | ||
159 | (VikLayerFuncAddMenuItems) maps_layer_add_menu_items, | |
160 | (VikLayerFuncSublayerAddMenuItems) NULL, | |
161 | ||
162 | (VikLayerFuncSublayerRenameRequest) NULL, | |
163 | (VikLayerFuncSublayerToggleVisible) NULL, | |
164 | ||
165 | (VikLayerFuncCopy) maps_layer_copy, | |
166 | ||
167 | (VikLayerFuncSetParam) maps_layer_set_param, | |
168 | (VikLayerFuncGetParam) maps_layer_get_param, | |
169 | ||
170 | (VikLayerFuncReadFileData) NULL, | |
171 | (VikLayerFuncWriteFileData) NULL, | |
172 | ||
173 | (VikLayerFuncCopyItem) NULL, | |
174 | (VikLayerFuncPasteItem) NULL, | |
175 | (VikLayerFuncFreeCopiedItem) NULL, | |
176 | }; | |
177 | ||
178 | struct _VikMapsLayer { | |
179 | VikLayer vl; | |
180 | guint maptype; | |
181 | gchar *cache_dir; | |
182 | guint8 alpha; | |
183 | guint mapzoom_id; | |
184 | gdouble xmapzoom, ymapzoom; | |
185 | ||
186 | gboolean autodownload; | |
187 | ||
188 | gint dl_tool_x, dl_tool_y; | |
189 | ||
190 | GtkMenu *dl_right_click_menu; | |
191 | VikCoord redownload_ul, redownload_br; /* right click menu only */ | |
192 | VikViewport *redownload_vvp; | |
193 | }; | |
194 | ||
195 | enum { REDOWNLOAD_NONE = 0, REDOWNLOAD_BAD, REDOWNLOAD_ALL }; | |
196 | ||
197 | ||
198 | /****************************************/ | |
199 | /******** CACHE DIR STUFF ***************/ | |
200 | /****************************************/ | |
201 | ||
202 | #ifdef WINDOWS | |
203 | #define MAPS_CACHE_DIR "C:\\VIKING-MAPS\\" | |
204 | #define DIRSTRUCTURE "%st%ds%dz%d\\%d\\%d" | |
205 | #else /* POSIX */ | |
206 | ||
207 | #include <stdlib.h> | |
208 | ||
209 | #define MAPS_CACHE_DIR maps_layer_default_dir() | |
210 | #define GLOBAL_MAPS_DIR "/var/cache/maps/" | |
211 | #define DIRSTRUCTURE "%st%ds%dz%d/%d/%d" | |
212 | ||
213 | static gchar *maps_layer_default_dir () | |
214 | { | |
215 | static gchar defaultdir[512]; | |
216 | static gboolean already_run = 0; | |
217 | if ( ! already_run ) | |
218 | { | |
219 | /* Thanks to Mike Davison for the $VIKING_MAPS usage */ | |
220 | gchar *mapdir = getenv("VIKING_MAPS"); | |
221 | if ( mapdir && strlen(mapdir) < 497 ) { | |
222 | strcpy ( defaultdir, mapdir ); | |
223 | } else if ( access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) { | |
224 | strcpy ( defaultdir, GLOBAL_MAPS_DIR ); | |
225 | } else { | |
226 | gchar *home = getenv("HOME"); | |
227 | if ( home && strlen(home) < 497 ) | |
228 | { | |
229 | strcpy ( defaultdir, home ); | |
230 | strcat ( defaultdir, "/.viking-maps/" ); | |
231 | } | |
232 | else | |
233 | { | |
234 | strcpy ( defaultdir, ".viking-maps/" ); | |
235 | } | |
236 | } | |
237 | already_run = 1; | |
238 | } | |
239 | return defaultdir; | |
240 | } | |
241 | ||
242 | #endif | |
243 | ||
244 | static void maps_layer_mkdir_if_default_dir ( VikMapsLayer *vml ) | |
245 | { | |
246 | if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && access ( vml->cache_dir, F_OK ) != 0 ) | |
247 | { | |
248 | #ifdef WINDOWS | |
249 | mkdir ( vml->cache_dir ); | |
250 | #else | |
251 | mkdir ( vml->cache_dir, 0777 ); | |
252 | #endif | |
253 | } | |
254 | } | |
255 | ||
256 | static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir ) | |
257 | { | |
258 | guint len; | |
259 | g_assert ( vml != NULL); | |
260 | if ( vml->cache_dir ) | |
261 | g_free ( vml->cache_dir ); | |
262 | ||
263 | if ( dir == NULL || dir[0] == '\0' ) | |
264 | vml->cache_dir = g_strdup ( MAPS_CACHE_DIR ); | |
265 | else | |
266 | { | |
267 | len = strlen(dir); | |
268 | if ( dir[len-1] != VIKING_FILE_SEP ) | |
269 | { | |
270 | vml->cache_dir = g_malloc ( len+2 ); | |
271 | strncpy ( vml->cache_dir, dir, len ); | |
272 | vml->cache_dir[len] = VIKING_FILE_SEP; | |
273 | vml->cache_dir[len+1] = '\0'; | |
274 | } | |
275 | else | |
276 | vml->cache_dir = g_strdup ( dir ); | |
277 | } | |
278 | maps_layer_mkdir_if_default_dir ( vml ); | |
279 | } | |
280 | ||
281 | /****************************************/ | |
282 | /******** GOBJECT STUFF *****************/ | |
283 | /****************************************/ | |
284 | ||
285 | GType vik_maps_layer_get_type () | |
286 | { | |
287 | static GType vml_type = 0; | |
288 | ||
289 | if (!vml_type) | |
290 | { | |
291 | static const GTypeInfo vml_info = | |
292 | { | |
293 | sizeof (VikMapsLayerClass), | |
294 | NULL, /* base_init */ | |
295 | NULL, /* base_finalize */ | |
296 | NULL, /* class init */ | |
297 | NULL, /* class_finalize */ | |
298 | NULL, /* class_data */ | |
299 | sizeof (VikMapsLayer), | |
300 | 0, | |
301 | NULL /* instance init */ | |
302 | }; | |
303 | vml_type = g_type_register_static ( VIK_LAYER_TYPE, "VikMapsLayer", &vml_info, 0 ); | |
304 | } | |
305 | ||
306 | return vml_type; | |
307 | } | |
308 | ||
309 | /****************************************/ | |
310 | /************** PARAMETERS **************/ | |
311 | /****************************************/ | |
312 | ||
313 | static guint map_index_to_uniq_id (guint8 index) | |
314 | { | |
315 | g_assert ( index < NUM_MAP_TYPES ); | |
316 | return __map_types[index].uniq_id; | |
317 | } | |
318 | ||
319 | static guint map_uniq_id_to_index ( guint uniq_id ) | |
320 | { | |
321 | gint i; | |
322 | for ( i = 0; i < NUM_MAP_TYPES; i++ ) | |
323 | if ( __map_types[i].uniq_id == uniq_id ) | |
324 | return i; | |
325 | return NUM_MAP_TYPES; /* no such thing */ | |
326 | } | |
327 | ||
328 | static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp ) | |
329 | { | |
330 | switch ( id ) | |
331 | { | |
332 | case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break; | |
333 | case PARAM_MAPTYPE: { | |
334 | gint maptype = map_uniq_id_to_index(data.u); | |
335 | if ( maptype == NUM_MAP_TYPES ) g_warning("Unknown map type"); | |
336 | else vml->maptype = maptype; | |
337 | break; | |
338 | } | |
339 | case PARAM_ALPHA: if ( data.u <= 255 ) vml->alpha = data.u; break; | |
340 | case PARAM_AUTODOWNLOAD: vml->autodownload = data.b; break; | |
341 | case PARAM_MAPZOOM: if ( data.u < NUM_MAPZOOMS ) { | |
342 | vml->mapzoom_id = data.u; | |
343 | vml->xmapzoom = __mapzooms_x [data.u]; | |
344 | vml->ymapzoom = __mapzooms_y [data.u]; | |
345 | }else g_warning ("Unknown Map Zoom"); break; | |
346 | } | |
347 | return TRUE; | |
348 | } | |
349 | ||
350 | static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id ) | |
351 | { | |
352 | VikLayerParamData rv; | |
353 | switch ( id ) | |
354 | { | |
355 | case PARAM_CACHE_DIR: rv.s = (vml->cache_dir && strcmp(vml->cache_dir, MAPS_CACHE_DIR) != 0) ? vml->cache_dir : ""; break; | |
356 | case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break; | |
357 | case PARAM_ALPHA: rv.u = vml->alpha; break; | |
358 | case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break; | |
359 | case PARAM_MAPZOOM: rv.u = vml->mapzoom_id; break; | |
360 | } | |
361 | return rv; | |
362 | } | |
363 | ||
364 | /****************************************/ | |
365 | /****** CREATING, COPYING, FREEING ******/ | |
366 | /****************************************/ | |
367 | ||
368 | static VikMapsLayer *maps_layer_new ( VikViewport *vvp ) | |
369 | { | |
370 | VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) ); | |
371 | vik_layer_init ( VIK_LAYER(vml), VIK_LAYER_MAPS ); | |
372 | vml->maptype = 0; | |
373 | vml->alpha = 255; | |
374 | vml->mapzoom_id = 0; | |
375 | vml->dl_tool_x = vml->dl_tool_y = -1; | |
376 | maps_layer_set_cache_dir ( vml, NULL ); | |
377 | vml->autodownload = FALSE; | |
378 | ||
379 | vml->dl_right_click_menu = NULL; | |
380 | ||
381 | return vml; | |
382 | } | |
383 | ||
384 | static void maps_layer_free ( VikMapsLayer *vml ) | |
385 | { | |
386 | if ( vml->cache_dir ) | |
387 | g_free ( vml->cache_dir ); | |
388 | if ( vml->dl_right_click_menu ) | |
389 | gtk_object_sink ( GTK_OBJECT(vml->dl_right_click_menu) ); | |
390 | } | |
391 | ||
392 | static VikMapsLayer *maps_layer_copy ( VikMapsLayer *vml, VikViewport *vvp ) | |
393 | { | |
394 | VikMapsLayer *rv = maps_layer_new ( vvp ); | |
395 | *rv = *vml; | |
396 | rv->cache_dir = g_strdup(rv->cache_dir); | |
397 | VIK_LAYER(rv)->name = NULL; | |
398 | return rv; | |
399 | } | |
400 | ||
401 | /*********************/ | |
402 | /****** DRAWING ******/ | |
403 | /*********************/ | |
404 | ||
405 | static GdkPixbuf *pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha ) | |
406 | { | |
407 | guchar *pixels; | |
408 | gint width, height, iii, jjj; | |
409 | ||
410 | if ( ! gdk_pixbuf_get_has_alpha ( pixbuf ) ) | |
411 | { | |
412 | GdkPixbuf *tmp = gdk_pixbuf_add_alpha(pixbuf,FALSE,0,0,0); | |
413 | g_object_unref(G_OBJECT(pixbuf)); | |
414 | pixbuf = tmp; | |
415 | } | |
416 | ||
417 | pixels = gdk_pixbuf_get_pixels(pixbuf); | |
418 | width = gdk_pixbuf_get_width(pixbuf); | |
419 | height = gdk_pixbuf_get_height(pixbuf); | |
420 | ||
421 | /* r,g,b,a,r,g,b,a.... */ | |
422 | for (iii = 0; iii < width; iii++) for (jjj = 0; jjj < height; jjj++) | |
423 | { | |
424 | pixels += 3; | |
425 | *pixels++ = alpha; | |
426 | } | |
427 | return pixbuf; | |
428 | } | |
429 | ||
430 | static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdouble yshrinkfactor ) | |
431 | { | |
432 | GdkPixbuf *tmp; | |
433 | guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf); | |
434 | tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_BILINEAR); | |
435 | g_object_unref ( G_OBJECT(pixbuf) ); | |
436 | return tmp; | |
437 | } | |
438 | ||
439 | static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, gchar *filename_buf, gint buf_len, gdouble xshrinkfactor, gdouble yshrinkfactor ) | |
440 | { | |
441 | GdkPixbuf *pixbuf; | |
442 | ||
443 | /* get the thing */ | |
444 | pixbuf = a_mapcache_get ( mapcoord->x, mapcoord->y, mapcoord->z, | |
445 | mode, mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor ); | |
446 | ||
447 | if ( ! pixbuf ) { | |
448 | g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE, | |
449 | vml->cache_dir, mode, | |
450 | mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y ); | |
451 | if ( access ( filename_buf, R_OK ) == 0) { | |
452 | { | |
453 | GError *gx = NULL; | |
454 | pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx ); | |
455 | ||
456 | if (gx) | |
457 | { | |
458 | if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE ) | |
459 | g_warning ( "Couldn't open image file: %s", gx->message ); | |
460 | ||
461 | g_error_free ( gx ); | |
462 | if ( pixbuf ) | |
463 | g_object_unref ( G_OBJECT(pixbuf) ); | |
464 | pixbuf = NULL; | |
465 | } else { | |
466 | if ( vml->alpha < 255 ) | |
467 | pixbuf = pixbuf_set_alpha ( pixbuf, vml->alpha ); | |
468 | if ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 ) | |
469 | pixbuf = pixbuf_shrink ( pixbuf, xshrinkfactor, yshrinkfactor ); | |
470 | ||
471 | a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y, | |
472 | mapcoord->z, __map_types[vml->maptype].uniq_id, | |
473 | mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor ); | |
474 | } | |
475 | } | |
476 | } | |
477 | } | |
478 | return pixbuf; | |
479 | } | |
480 | ||
481 | static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br ) | |
482 | { | |
483 | MapCoord ulm, brm; | |
484 | gdouble xzoom = vik_viewport_get_xmpp ( vvp ); | |
485 | gdouble yzoom = vik_viewport_get_ympp ( vvp ); | |
486 | gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0; | |
487 | ||
488 | if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) { | |
489 | xshrinkfactor = vml->xmapzoom / xzoom; | |
490 | yshrinkfactor = vml->ymapzoom / yzoom; | |
491 | if ( xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR && | |
492 | yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) { | |
493 | xzoom = vml->xmapzoom; | |
494 | yzoom = vml->xmapzoom; | |
495 | } else { | |
496 | 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 ); | |
497 | } | |
498 | } | |
499 | ||
500 | /* coord -> ID */ | |
501 | if ( __map_types[vml->maptype].coord_to_mapcoord ( ul, xzoom, yzoom, &ulm ) && | |
502 | __map_types[vml->maptype].coord_to_mapcoord ( br, xzoom, yzoom, &brm ) ) { | |
503 | ||
504 | /* loop & draw */ | |
505 | gint x, y; | |
506 | gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x); | |
507 | gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y); | |
508 | gint mode = __map_types[vml->maptype].uniq_id; | |
509 | ||
510 | VikCoord coord; | |
511 | gint xx, yy, width, height; | |
512 | GdkPixbuf *pixbuf; | |
513 | ||
514 | guint max_path_len = strlen(vml->cache_dir) + 40; | |
515 | gchar *path_buf = g_malloc ( max_path_len * sizeof(char) ); | |
516 | ||
517 | if ( vml->autodownload ) | |
518 | start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE ); | |
519 | ||
520 | if ( __map_types[vml->maptype].tilesize_x == 0 ) { | |
521 | for ( x = xmin; x <= xmax; x++ ) { | |
522 | for ( y = ymin; y <= ymax; y++ ) { | |
523 | ulm.x = x; | |
524 | ulm.y = y; | |
525 | pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor ); | |
526 | if ( pixbuf ) { | |
527 | width = gdk_pixbuf_get_width ( pixbuf ); | |
528 | height = gdk_pixbuf_get_height ( pixbuf ); | |
529 | ||
530 | __map_types[vml->maptype].mapcoord_to_center_coord ( &ulm, &coord ); | |
531 | vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy ); | |
532 | xx -= (width/2); | |
533 | yy -= (height/2); | |
534 | ||
535 | vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height ); | |
536 | } | |
537 | } | |
538 | } | |
539 | } else { /* tilesize is known, don't have to keep converting coords */ | |
540 | gdouble tilesize_x = __map_types[vml->maptype].tilesize_x * xshrinkfactor; | |
541 | gdouble tilesize_y = __map_types[vml->maptype].tilesize_y * yshrinkfactor; | |
542 | /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */ | |
543 | gint tilesize_x_ceil = ceil ( tilesize_x ); | |
544 | gint tilesize_y_ceil = ceil ( tilesize_y ); | |
545 | gint8 xinc = (ulm.x == xmin) ? 1 : -1; | |
546 | gint8 yinc = (ulm.y == ymin) ? 1 : -1; | |
547 | gdouble xx, yy; gint xx_tmp, yy_tmp; | |
548 | gint base_yy, xend, yend; | |
549 | xend = (xinc == 1) ? (xmax+1) : (xmin-1); | |
550 | yend = (yinc == 1) ? (ymax+1) : (ymin-1); | |
551 | ||
552 | __map_types[vml->maptype].mapcoord_to_center_coord ( &ulm, &coord ); | |
553 | vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp ); | |
554 | xx = xx_tmp; yy = yy_tmp; | |
555 | /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off | |
556 | * eg if tile size 128, shrinkfactor 0.333 */ | |
557 | xx -= (tilesize_x/2); | |
558 | base_yy = yy - (tilesize_y/2); | |
559 | ||
560 | for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) { | |
561 | yy = base_yy; | |
562 | for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) { | |
563 | ulm.x = x; | |
564 | ulm.y = y; | |
565 | pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor ); | |
566 | if ( pixbuf ) | |
567 | vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, tilesize_x_ceil, tilesize_y_ceil ); | |
568 | ||
569 | yy += tilesize_y; | |
570 | } | |
571 | xx += tilesize_x; | |
572 | } | |
573 | } | |
574 | ||
575 | g_free ( path_buf ); | |
576 | } | |
577 | } | |
578 | ||
579 | static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp ) | |
580 | { | |
581 | if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) ) | |
582 | { | |
583 | VikCoord ul, br; | |
584 | ||
585 | /* get corner coords */ | |
586 | if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) { | |
587 | /* UTM multi-zone stuff by Kit Transue */ | |
588 | gchar leftmost_zone, rightmost_zone, i; | |
589 | leftmost_zone = vik_viewport_leftmost_zone( vvp ); | |
590 | rightmost_zone = vik_viewport_rightmost_zone( vvp ); | |
591 | for ( i = leftmost_zone; i <= rightmost_zone; ++i ) { | |
592 | vik_viewport_corners_for_zonen ( vvp, i, &ul, &br ); | |
593 | maps_layer_draw_section ( vml, vvp, &ul, &br ); | |
594 | } | |
595 | } | |
596 | else { | |
597 | vik_viewport_screen_to_coord ( vvp, 0, 0, &ul ); | |
598 | vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br ); | |
599 | ||
600 | maps_layer_draw_section ( vml, vvp, &ul, &br ); | |
601 | } | |
602 | } | |
603 | } | |
604 | ||
605 | /*************************/ | |
606 | /****** DOWNLOADING ******/ | |
607 | /*************************/ | |
608 | ||
609 | /* pass along data to thread, exists even if layer is deleted. */ | |
610 | typedef struct { | |
611 | gchar *cache_dir; | |
612 | gchar *filename_buf; | |
613 | gint x0, y0, xf, yf; | |
614 | MapCoord mapcoord; | |
615 | gint maptype; | |
616 | gint maxlen; | |
617 | gint mapstoget; | |
618 | gint redownload; | |
619 | } MapDownloadInfo; | |
620 | ||
621 | static void mdi_free ( MapDownloadInfo *mdi ) | |
622 | { | |
623 | g_free ( mdi->cache_dir ); | |
624 | g_free ( mdi->filename_buf ); | |
625 | g_free ( mdi ); | |
626 | } | |
627 | ||
628 | static void map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata ) | |
629 | { | |
630 | guint donemaps = 0; | |
631 | gint x, y; | |
632 | for ( x = mdi->x0; x <= mdi->xf; x++ ) | |
633 | { | |
634 | for ( y = mdi->y0; y <= mdi->yf; y++ ) | |
635 | { | |
636 | g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE, | |
637 | mdi->cache_dir, __map_types[mdi->maptype].uniq_id, | |
638 | mdi->mapcoord.scale, mdi->mapcoord.z, x, y ); | |
639 | ||
640 | if ( mdi->redownload == REDOWNLOAD_ALL) | |
641 | remove ( mdi->filename_buf ); | |
642 | else if ( mdi->redownload == REDOWNLOAD_BAD && access ( mdi->filename_buf, F_OK ) == 0 ) | |
643 | { | |
644 | /* see if this one is bad or what */ | |
645 | GError *gx = NULL; | |
646 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx ); | |
647 | if (gx || (!pixbuf)) | |
648 | remove ( mdi->filename_buf ); | |
649 | if ( pixbuf ) | |
650 | g_object_unref ( pixbuf ); | |
651 | if ( gx ) | |
652 | g_error_free ( gx ); | |
653 | } | |
654 | ||
655 | if ( access ( mdi->filename_buf, F_OK ) != 0 ) | |
656 | { | |
657 | mdi->mapcoord.x = x; mdi->mapcoord.y = y; | |
658 | __map_types[mdi->maptype].download ( &(mdi->mapcoord), mdi->filename_buf ); | |
659 | mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */ | |
1fe49af0 EB |
660 | |
661 | if ( mdi->redownload !=- REDOWNLOAD_NONE ) | |
662 | a_mapcache_remove_all_shrinkfactors ( x, y, mdi->mapcoord.z, mdi->maptype, mdi->mapcoord.scale ); | |
663 | ||
664 | ||
50a14534 EB |
665 | donemaps++; |
666 | a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */ | |
667 | } | |
668 | } | |
669 | } | |
670 | } | |
671 | ||
672 | static void mdi_cancel_cleanup ( MapDownloadInfo *mdi ) | |
673 | { | |
674 | if ( mdi->mapcoord.x || mdi->mapcoord.y ) | |
675 | { | |
676 | g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE, | |
677 | mdi->cache_dir, __map_types[mdi->maptype].uniq_id, | |
678 | mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y ); | |
679 | if ( access ( mdi->filename_buf, F_OK ) == 0) | |
680 | { | |
681 | remove ( mdi->filename_buf ); | |
682 | } | |
683 | } | |
684 | } | |
685 | ||
686 | static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload ) | |
687 | { | |
688 | gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ); | |
689 | gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ); | |
690 | MapCoord ulm, brm; | |
691 | if ( __map_types[vml->maptype].coord_to_mapcoord ( ul, xzoom, yzoom, &ulm ) | |
692 | && __map_types[vml->maptype].coord_to_mapcoord ( br, xzoom, yzoom, &brm ) ) | |
693 | { | |
694 | MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) ); | |
695 | gint a, b; | |
696 | ||
697 | /* cache_dir and buffer for dest filename */ | |
698 | mdi->cache_dir = g_strdup ( vml->cache_dir ); | |
699 | mdi->maxlen = strlen ( vml->cache_dir ) + 40; | |
700 | mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) ); | |
701 | mdi->maptype = vml->maptype; | |
702 | ||
703 | mdi->mapcoord = ulm; | |
704 | ||
705 | mdi->redownload = redownload; | |
706 | ||
707 | mdi->x0 = MIN(ulm.x, brm.x); | |
708 | mdi->xf = MAX(ulm.x, brm.x); | |
709 | mdi->y0 = MIN(ulm.y, brm.y); | |
710 | mdi->yf = MAX(ulm.y, brm.y); | |
711 | ||
712 | mdi->mapstoget = 0; | |
713 | ||
714 | if ( mdi->redownload ) { | |
715 | mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1); | |
716 | } else { | |
717 | /* calculate how many we need */ | |
718 | for ( a = mdi->x0; a <= mdi->xf; a++ ) | |
719 | { | |
720 | for ( b = mdi->y0; b <= mdi->yf; b++ ) | |
721 | { | |
722 | g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE, | |
723 | vml->cache_dir, __map_types[vml->maptype].uniq_id, ulm.scale, | |
724 | ulm.z, a, b ); | |
725 | if ( access ( mdi->filename_buf, F_OK ) != 0) | |
726 | mdi->mapstoget++; | |
727 | } | |
728 | } | |
729 | } | |
730 | ||
731 | mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */ | |
732 | ||
733 | if ( mdi->mapstoget ) | |
734 | { | |
735 | gchar *tmp = g_strdup_printf ( "%s %s%d %s %s...", redownload ? "Redownloading" : "Downloading", redownload == REDOWNLOAD_BAD ? "up to " : "", mdi->mapstoget, params_maptypes[vml->maptype], (mdi->mapstoget == 1) ? "map" : "maps" ); | |
736 | ||
737 | /* launch the thread */ | |
738 | a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */ | |
739 | tmp, /* description string */ | |
740 | (vik_thr_func) map_download_thread, /* function to call within thread */ | |
741 | mdi, /* pass along data */ | |
742 | (vik_thr_free_func) mdi_free, /* function to free pass along data */ | |
743 | (vik_thr_free_func) mdi_cancel_cleanup, | |
744 | mdi->mapstoget ); | |
745 | g_free ( tmp ); | |
746 | } | |
747 | else | |
748 | mdi_free ( mdi ); | |
749 | } | |
750 | } | |
751 | ||
752 | static void maps_layer_redownload_bad ( VikMapsLayer *vml ) | |
753 | { | |
754 | start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD ); | |
755 | } | |
756 | static void maps_layer_redownload_all ( VikMapsLayer *vml ) | |
757 | { | |
758 | start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL ); | |
759 | } | |
760 | ||
761 | static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp ) | |
762 | { | |
763 | ||
764 | if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 ) | |
765 | { | |
766 | if ( event->button == 1 ) | |
767 | { | |
768 | VikCoord ul, br; | |
769 | 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 ); | |
770 | 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 ); | |
771 | start_download_thread ( vml, vvp, &ul, &br, REDOWNLOAD_NONE ); | |
772 | vml->dl_tool_x = vml->dl_tool_y = -1; | |
773 | return TRUE; | |
774 | } | |
775 | else | |
776 | { | |
777 | 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) ); | |
778 | 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) ); | |
779 | ||
780 | vml->redownload_vvp = vvp; | |
781 | ||
782 | vml->dl_tool_x = vml->dl_tool_y = -1; | |
783 | ||
784 | if ( ! vml->dl_right_click_menu ) { | |
785 | GtkWidget *item; | |
786 | vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () ); | |
787 | ||
788 | item = gtk_menu_item_new_with_label ( "Redownload bad map(s)" ); | |
789 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml ); | |
790 | gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item ); | |
791 | ||
792 | item = gtk_menu_item_new_with_label ( "Redownload all map(s)" ); | |
793 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml ); | |
794 | gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item ); | |
795 | } | |
796 | ||
797 | gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time ); | |
798 | gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) ); | |
799 | } | |
800 | } | |
801 | return FALSE; | |
802 | } | |
803 | ||
804 | static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp ) | |
805 | { | |
806 | MapCoord tmp; | |
807 | if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) && | |
808 | __map_types[vml->maptype].coord_to_mapcoord ( vik_viewport_get_center ( vvp ), | |
809 | vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ), | |
810 | vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ), | |
811 | &tmp ) ) { | |
812 | vml->dl_tool_x = event->x, vml->dl_tool_y = event->y; | |
813 | return TRUE; | |
814 | } | |
815 | return FALSE; | |
816 | ||
817 | ||
818 | #if 0 | |
819 | if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) ) | |
820 | { | |
821 | VikCoord coord; | |
822 | MapCoord mapcoord; | |
823 | vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord ); | |
824 | if ( __map_types[vml->maptype].coord_to_mapcoord ( &coord, | |
825 | vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ), | |
826 | vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ), | |
827 | &mapcoord ) ) { | |
828 | gchar *filename_buf = g_strdup_printf ( DIRSTRUCTURE, | |
829 | vml->cache_dir, __map_types[vml->maptype].uniq_id, | |
830 | mapcoord.scale, mapcoord.z, mapcoord.x, mapcoord.y ); | |
831 | ||
832 | __map_types[vml->maptype].download ( &mapcoord, filename_buf ); | |
833 | g_free ( filename_buf ); | |
834 | vik_layer_emit_update ( VIK_LAYER(vml) ); | |
835 | return TRUE; | |
836 | } | |
837 | } | |
838 | return FALSE; | |
839 | #endif | |
840 | } | |
841 | ||
842 | static void maps_layer_download_onscreen_maps ( gpointer vml_vvp[2] ) | |
843 | { | |
844 | VikMapsLayer *vml = vml_vvp[0]; | |
845 | VikViewport *vvp = vml_vvp[1]; | |
846 | ||
847 | gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ); | |
848 | gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ); | |
849 | ||
850 | VikCoord ul, br; | |
851 | MapCoord ulm, brm; | |
852 | ||
853 | vik_viewport_screen_to_coord ( vvp, 0, 0, &ul ); | |
854 | vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br ); | |
855 | ||
856 | if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) && | |
857 | __map_types[vml->maptype].coord_to_mapcoord ( &ul, xzoom, yzoom, &ulm ) && | |
858 | __map_types[vml->maptype].coord_to_mapcoord ( &br, xzoom, yzoom, &brm ) ) | |
859 | start_download_thread ( vml, vvp, &ul, &br, REDOWNLOAD_NONE ); | |
860 | else | |
861 | a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), "Wrong drawmode / zoom level for this map." ); | |
862 | ||
863 | } | |
864 | ||
865 | static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp ) | |
866 | { | |
867 | static gpointer pass_along[2]; | |
868 | GtkWidget *item; | |
869 | pass_along[0] = vml; | |
870 | pass_along[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) ); | |
871 | ||
872 | item = gtk_menu_item_new(); | |
873 | gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); | |
874 | gtk_widget_show ( item ); | |
875 | ||
876 | item = gtk_menu_item_new_with_label ( "Download Onscreen Maps" ); | |
877 | g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_onscreen_maps), pass_along ); | |
878 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); | |
879 | gtk_widget_show ( item ); | |
880 | } |