2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2005, Evan Battaglia <viking@greentorch.org>
5 * Copyright (C) 2010, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
6 * UTM multi-zone stuff by Kit Transue <notlostyet@didactek.com>
7 * Dynamic map type by Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #define MAX_SHRINKFACTOR 8.0000001 /* zoom 1 viewing 8-tiles */
30 #define MIN_SHRINKFACTOR 0.0312499 /* zoom 32 viewing 1-tiles */
32 #define REAL_MIN_SHRINKFACTOR 0.0039062499 /* if shrinkfactor is between MAX and REAL_MAX, will only check for existence */
35 #include <gdk-pixbuf/gdk-pixdata.h>
37 #include <glib/gstdio.h>
38 #include <glib/gi18n.h>
50 #include "viktreeview.h"
51 #include "vikviewport.h"
53 #include "vikmapslayer.h"
60 /* only for dialog.h -- ugh */
61 #include "vikwaypoint.h"
64 #include "vikstatus.h"
65 #include "background.h"
67 #include "vikaggregatelayer.h"
68 #include "viklayerspanel.h"
71 #include "terraserver.h"
73 #include "icons/icons.h"
75 /****** MAP TYPES ******/
77 static GList
*__map_types
= NULL
;
79 #define NUM_MAP_TYPES g_list_length(__map_types)
81 /* List of label for each map type */
82 static gchar
**params_maptypes
= NULL
;
84 /* Corresponding IDS. (Cf. field uniq_id in VikMapsLayer struct) */
85 static guint
*params_maptypes_ids
= NULL
;
87 /******** MAPZOOMS *********/
89 static 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
};
90 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 };
91 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 };
93 #define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0]) - 1)
95 /**************************/
98 static void maps_layer_post_read (VikLayer
*vl
, VikViewport
*vp
, gboolean from_file
);
99 static void maps_layer_marshall( VikMapsLayer
*vml
, guint8
**data
, gint
*len
);
100 static VikMapsLayer
*maps_layer_unmarshall( guint8
*data
, gint len
, VikViewport
*vvp
);
101 static gboolean
maps_layer_set_param ( VikMapsLayer
*vml
, guint16 id
, VikLayerParamData data
, VikViewport
*vvp
);
102 static VikLayerParamData
maps_layer_get_param ( VikMapsLayer
*vml
, guint16 id
);
103 static void maps_layer_draw ( VikMapsLayer
*vml
, VikViewport
*vvp
);
104 static VikMapsLayer
*maps_layer_new ( VikViewport
*vvp
);
105 static void maps_layer_free ( VikMapsLayer
*vml
);
106 static gboolean
maps_layer_download_release ( VikMapsLayer
*vml
, GdkEventButton
*event
, VikViewport
*vvp
);
107 static gboolean
maps_layer_download_click ( VikMapsLayer
*vml
, GdkEventButton
*event
, VikViewport
*vvp
);
108 static gpointer
maps_layer_download_create ( VikWindow
*vw
, VikViewport
*vvp
);
109 static void maps_layer_set_cache_dir ( VikMapsLayer
*vml
, const gchar
*dir
);
110 static void start_download_thread ( VikMapsLayer
*vml
, VikViewport
*vvp
, const VikCoord
*ul
, const VikCoord
*br
, gint redownload
);
111 static void maps_layer_add_menu_items ( VikMapsLayer
*vml
, GtkMenu
*menu
, VikLayersPanel
*vlp
);
114 static VikLayerParamScale params_scales
[] = {
115 /* min, max, step, digits (decimal places) */
116 { 0, 255, 3, 0 }, /* alpha */
119 VikLayerParam maps_layer_params
[] = {
120 { "mode", VIK_LAYER_PARAM_UINT
, VIK_LAYER_GROUP_NONE
, N_("Map Type:"), VIK_LAYER_WIDGET_COMBOBOX
, NULL
, NULL
},
121 { "directory", VIK_LAYER_PARAM_STRING
, VIK_LAYER_GROUP_NONE
, N_("Maps Directory:"), VIK_LAYER_WIDGET_FOLDERENTRY
},
122 { "alpha", VIK_LAYER_PARAM_UINT
, VIK_LAYER_GROUP_NONE
, N_("Alpha:"), VIK_LAYER_WIDGET_HSCALE
, params_scales
},
123 { "autodownload", VIK_LAYER_PARAM_BOOLEAN
, VIK_LAYER_GROUP_NONE
, N_("Autodownload maps:"), VIK_LAYER_WIDGET_CHECKBUTTON
},
124 { "mapzoom", VIK_LAYER_PARAM_UINT
, VIK_LAYER_GROUP_NONE
, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX
, params_mapzooms
, NULL
},
127 enum { PARAM_MAPTYPE
=0, PARAM_CACHE_DIR
, PARAM_ALPHA
, PARAM_AUTODOWNLOAD
, PARAM_MAPZOOM
, NUM_PARAMS
};
129 static VikToolInterface maps_tools
[] = {
130 { N_("Maps Download"), (VikToolConstructorFunc
) maps_layer_download_create
, NULL
, NULL
, NULL
,
131 (VikToolMouseFunc
) maps_layer_download_click
, NULL
, (VikToolMouseFunc
) maps_layer_download_release
,
132 (VikToolKeyFunc
) NULL
, GDK_CURSOR_IS_PIXMAP
, &cursor_mapdl_pixbuf
},
135 VikLayerInterface vik_maps_layer_interface
= {
137 &vikmapslayer_pixbuf
,
140 sizeof(maps_tools
) / sizeof(maps_tools
[0]),
149 (VikLayerFuncCreate
) maps_layer_new
,
150 (VikLayerFuncRealize
) NULL
,
151 (VikLayerFuncPostRead
) maps_layer_post_read
,
152 (VikLayerFuncFree
) maps_layer_free
,
154 (VikLayerFuncProperties
) NULL
,
155 (VikLayerFuncDraw
) maps_layer_draw
,
156 (VikLayerFuncChangeCoordMode
) NULL
,
158 (VikLayerFuncSetMenuItemsSelection
) NULL
,
159 (VikLayerFuncGetMenuItemsSelection
) NULL
,
161 (VikLayerFuncAddMenuItems
) maps_layer_add_menu_items
,
162 (VikLayerFuncSublayerAddMenuItems
) NULL
,
164 (VikLayerFuncSublayerRenameRequest
) NULL
,
165 (VikLayerFuncSublayerToggleVisible
) NULL
,
167 (VikLayerFuncMarshall
) maps_layer_marshall
,
168 (VikLayerFuncUnmarshall
) maps_layer_unmarshall
,
170 (VikLayerFuncSetParam
) maps_layer_set_param
,
171 (VikLayerFuncGetParam
) maps_layer_get_param
,
173 (VikLayerFuncReadFileData
) NULL
,
174 (VikLayerFuncWriteFileData
) NULL
,
176 (VikLayerFuncDeleteItem
) NULL
,
177 (VikLayerFuncCopyItem
) NULL
,
178 (VikLayerFuncPasteItem
) NULL
,
179 (VikLayerFuncFreeCopiedItem
) NULL
,
180 (VikLayerFuncDragDropRequest
) NULL
,
183 struct _VikMapsLayer
{
189 gdouble xmapzoom
, ymapzoom
;
191 gboolean autodownload
;
192 VikCoord
*last_center
;
196 gint dl_tool_x
, dl_tool_y
;
198 GtkMenu
*dl_right_click_menu
;
199 VikCoord redownload_ul
, redownload_br
; /* right click menu only */
200 VikViewport
*redownload_vvp
;
203 enum { REDOWNLOAD_NONE
= 0, /* download only missing maps */
204 REDOWNLOAD_BAD
, /* download missing and bad maps */
205 REDOWNLOAD_NEW
, /* download missing maps that are newer on server only */
206 REDOWNLOAD_ALL
, /* download all maps */
207 DOWNLOAD_OR_REFRESH
}; /* download missing maps and refresh cache */
210 /****************************************/
211 /******** MAPS LAYER TYPES **************/
212 /****************************************/
214 void maps_layer_register_map_source ( VikMapSource
*map
)
216 g_assert(map
!= NULL
);
218 guint id
= vik_map_source_get_uniq_id(map
);
219 const char *label
= vik_map_source_get_label(map
);
220 g_assert(label
!= NULL
);
224 len
= g_strv_length (params_maptypes
);
226 params_maptypes
= g_realloc (params_maptypes
, (len
+2)*sizeof(gchar
*));
227 params_maptypes
[len
] = g_strdup (label
);
228 params_maptypes
[len
+1] = NULL
;
231 params_maptypes_ids
= g_realloc (params_maptypes_ids
, (len
+2)*sizeof(guint
));
232 params_maptypes_ids
[len
] = id
;
233 params_maptypes_ids
[len
+1] = 0;
235 /* We have to clone */
236 VikMapSource
*clone
= VIK_MAP_SOURCE(g_object_ref(map
));
237 /* Register the clone in the list */
238 __map_types
= g_list_append(__map_types
, clone
);
241 We have to ensure the mode LayerParam reference the up-to-date
245 memcpy(&maps_layer_params[0].widget_data, ¶ms_maptypes, sizeof(gpointer));
246 memcpy(&maps_layer_params[0].extra_widget_data, ¶ms_maptypes_ids, sizeof(gpointer));
248 maps_layer_params
[0].widget_data
= params_maptypes
;
249 maps_layer_params
[0].extra_widget_data
= params_maptypes_ids
;
252 #define MAPS_LAYER_NTH_LABEL(n) (params_maptypes[n])
253 #define MAPS_LAYER_NTH_ID(n) (params_maptypes_ids[n])
254 #define MAPS_LAYER_NTH_TYPE(n) (VIK_MAP_SOURCE(g_list_nth_data(__map_types, (n))))
256 gint
vik_maps_layer_get_map_type(VikMapsLayer
*vml
)
258 return(vml
->maptype
);
261 gchar
*vik_maps_layer_get_map_label(VikMapsLayer
*vml
)
263 return(g_strdup(MAPS_LAYER_NTH_LABEL(vml
->maptype
)));
266 /****************************************/
267 /******** CACHE DIR STUFF ***************/
268 /****************************************/
270 #define DIRSTRUCTURE "%st%ds%dz%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d"
271 #define MAPS_CACHE_DIR maps_layer_default_dir()
275 #define GLOBAL_MAPS_DIR "C:\\VIKING-MAPS\\"
276 #define LOCAL_MAPS_DIR "VIKING-MAPS"
279 #define GLOBAL_MAPS_DIR "/var/cache/maps/"
280 #define LOCAL_MAPS_DIR ".viking-maps"
283 gchar
*maps_layer_default_dir ()
285 static gchar
*defaultdir
= NULL
;
288 /* Thanks to Mike Davison for the $VIKING_MAPS usage */
289 const gchar
*mapdir
= g_getenv("VIKING_MAPS");
291 defaultdir
= g_strdup ( mapdir
);
292 } else if ( g_access ( GLOBAL_MAPS_DIR
, W_OK
) == 0 ) {
293 defaultdir
= g_strdup ( GLOBAL_MAPS_DIR
);
295 const gchar
*home
= g_get_home_dir();
296 if (!home
|| g_access(home
, W_OK
))
297 home
= g_get_home_dir ();
299 defaultdir
= g_build_filename ( home
, LOCAL_MAPS_DIR
, NULL
);
301 defaultdir
= g_strdup ( LOCAL_MAPS_DIR
);
303 if (defaultdir
&& (defaultdir
[strlen(defaultdir
)-1] != G_DIR_SEPARATOR
))
305 /* Add the separator at the end */
306 gchar
*tmp
= defaultdir
;
307 defaultdir
= g_strconcat(tmp
, G_DIR_SEPARATOR_S
, NULL
);
310 g_debug("%s: defaultdir=%s", __FUNCTION__
, defaultdir
);
315 static void maps_layer_mkdir_if_default_dir ( VikMapsLayer
*vml
)
317 if ( vml
->cache_dir
&& strcmp ( vml
->cache_dir
, MAPS_CACHE_DIR
) == 0 && g_file_test ( vml
->cache_dir
, G_FILE_TEST_EXISTS
) == FALSE
)
319 g_mkdir ( vml
->cache_dir
, 0777 );
323 static void maps_layer_set_cache_dir ( VikMapsLayer
*vml
, const gchar
*dir
)
326 g_assert ( vml
!= NULL
);
327 g_free ( vml
->cache_dir
);
328 vml
->cache_dir
= NULL
;
330 if ( dir
== NULL
|| dir
[0] == '\0' )
331 vml
->cache_dir
= g_strdup ( MAPS_CACHE_DIR
);
335 if ( dir
[len
-1] != G_DIR_SEPARATOR
)
337 vml
->cache_dir
= g_malloc ( len
+2 );
338 strncpy ( vml
->cache_dir
, dir
, len
);
339 vml
->cache_dir
[len
] = G_DIR_SEPARATOR
;
340 vml
->cache_dir
[len
+1] = '\0';
343 vml
->cache_dir
= g_strdup ( dir
);
345 maps_layer_mkdir_if_default_dir ( vml
);
348 /****************************************/
349 /******** GOBJECT STUFF *****************/
350 /****************************************/
352 GType
vik_maps_layer_get_type ()
354 static GType vml_type
= 0;
358 static const GTypeInfo vml_info
=
360 sizeof (VikMapsLayerClass
),
361 NULL
, /* base_init */
362 NULL
, /* base_finalize */
363 NULL
, /* class init */
364 NULL
, /* class_finalize */
365 NULL
, /* class_data */
366 sizeof (VikMapsLayer
),
368 NULL
/* instance init */
370 vml_type
= g_type_register_static ( VIK_LAYER_TYPE
, "VikMapsLayer", &vml_info
, 0 );
376 /****************************************/
377 /************** PARAMETERS **************/
378 /****************************************/
380 static guint
map_index_to_uniq_id (guint8 index
)
382 g_assert ( index
< NUM_MAP_TYPES
);
383 return vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(index
));
386 static guint
map_uniq_id_to_index ( guint uniq_id
)
389 for ( i
= 0; i
< NUM_MAP_TYPES
; i
++ )
390 if ( vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(i
)) == uniq_id
)
392 return NUM_MAP_TYPES
; /* no such thing */
395 static gboolean
maps_layer_set_param ( VikMapsLayer
*vml
, guint16 id
, VikLayerParamData data
, VikViewport
*vvp
)
399 case PARAM_CACHE_DIR
: maps_layer_set_cache_dir ( vml
, data
.s
); break;
400 case PARAM_MAPTYPE
: {
401 gint maptype
= map_uniq_id_to_index(data
.u
);
402 if ( maptype
== NUM_MAP_TYPES
) g_warning(_("Unknown map type"));
403 else vml
->maptype
= maptype
;
406 case PARAM_ALPHA
: if ( data
.u
<= 255 ) vml
->alpha
= data
.u
; break;
407 case PARAM_AUTODOWNLOAD
: vml
->autodownload
= data
.b
; break;
408 case PARAM_MAPZOOM
: if ( data
.u
< NUM_MAPZOOMS
) {
409 vml
->mapzoom_id
= data
.u
;
410 vml
->xmapzoom
= __mapzooms_x
[data
.u
];
411 vml
->ymapzoom
= __mapzooms_y
[data
.u
];
412 }else g_warning (_("Unknown Map Zoom")); break;
417 static VikLayerParamData
maps_layer_get_param ( VikMapsLayer
*vml
, guint16 id
)
419 VikLayerParamData rv
;
422 case PARAM_CACHE_DIR
: rv
.s
= vml
->cache_dir
? vml
->cache_dir
: ""; break;
423 case PARAM_MAPTYPE
: rv
.u
= map_index_to_uniq_id ( vml
->maptype
); break;
424 case PARAM_ALPHA
: rv
.u
= vml
->alpha
; break;
425 case PARAM_AUTODOWNLOAD
: rv
.u
= vml
->autodownload
; break;
426 case PARAM_MAPZOOM
: rv
.u
= vml
->mapzoom_id
; break;
431 /****************************************/
432 /****** CREATING, COPYING, FREEING ******/
433 /****************************************/
435 static VikMapsLayer
*maps_layer_new ( VikViewport
*vvp
)
438 VikMapsLayer
*vml
= VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE
, NULL
) );
439 vik_layer_init ( VIK_LAYER(vml
), VIK_LAYER_MAPS
);
440 idx
= map_uniq_id_to_index(13); /* 13 is id for OSM Mapnik maps */
441 vml
->maptype
= (idx
< NUM_MAP_TYPES
) ? idx
: 0;
444 vml
->dl_tool_x
= vml
->dl_tool_y
= -1;
445 maps_layer_set_cache_dir ( vml
, NULL
);
446 vml
->autodownload
= FALSE
;
447 vml
->last_center
= NULL
;
448 vml
->last_xmpp
= 0.0;
449 vml
->last_ympp
= 0.0;
451 vml
->dl_right_click_menu
= NULL
;
456 static void maps_layer_free ( VikMapsLayer
*vml
)
458 g_free ( vml
->cache_dir
);
459 vml
->cache_dir
= NULL
;
460 if ( vml
->dl_right_click_menu
)
461 gtk_object_sink ( GTK_OBJECT(vml
->dl_right_click_menu
) );
462 g_free(vml
->last_center
);
463 vml
->last_center
= NULL
;
466 static void maps_layer_post_read (VikLayer
*vl
, VikViewport
*vp
, gboolean from_file
)
468 if (from_file
!= TRUE
)
470 /* If this method is not called in file reading context
471 * it is called in GUI context.
472 * So, we can check if we have to inform the user about inconsistency */
473 VikViewportDrawMode vp_drawmode
;
474 VikMapsLayer
*vml
= VIK_MAPS_LAYER(vl
);
475 VikMapSource
*map
= NULL
;
477 vp_drawmode
= vik_viewport_get_drawmode ( VIK_VIEWPORT(vp
) );
478 map
= MAPS_LAYER_NTH_TYPE(vml
->maptype
);
479 if (vik_map_source_get_drawmode(map
) != vp_drawmode
) {
480 const gchar
*drawmode_name
= vik_viewport_get_drawmode_name (VIK_VIEWPORT(vp
), vik_map_source_get_drawmode(map
));
481 gchar
*msg
= g_strdup_printf(_("New map cannot be displayed in the current drawmode.\nSelect \"%s\" from View menu to view it."), drawmode_name
);
482 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml
), msg
);
488 static void maps_layer_marshall( VikMapsLayer
*vml
, guint8
**data
, gint
*len
)
490 vik_layer_marshall_params ( VIK_LAYER(vml
), data
, len
);
493 static VikMapsLayer
*maps_layer_unmarshall( guint8
*data
, gint len
, VikViewport
*vvp
)
495 VikMapsLayer
*rv
= maps_layer_new ( vvp
);
496 vik_layer_unmarshall_params ( VIK_LAYER(rv
), data
, len
, vvp
);
500 /*********************/
501 /****** DRAWING ******/
502 /*********************/
504 static GdkPixbuf
*pixbuf_set_alpha ( GdkPixbuf
*pixbuf
, guint8 alpha
)
507 gint width
, height
, iii
, jjj
;
509 if ( ! gdk_pixbuf_get_has_alpha ( pixbuf
) )
511 GdkPixbuf
*tmp
= gdk_pixbuf_add_alpha(pixbuf
,FALSE
,0,0,0);
512 g_object_unref(G_OBJECT(pixbuf
));
516 pixels
= gdk_pixbuf_get_pixels(pixbuf
);
517 width
= gdk_pixbuf_get_width(pixbuf
);
518 height
= gdk_pixbuf_get_height(pixbuf
);
520 /* r,g,b,a,r,g,b,a.... */
521 for (iii
= 0; iii
< width
; iii
++) for (jjj
= 0; jjj
< height
; jjj
++)
529 static GdkPixbuf
*pixbuf_shrink ( GdkPixbuf
*pixbuf
, gdouble xshrinkfactor
, gdouble yshrinkfactor
)
532 guint16 width
= gdk_pixbuf_get_width(pixbuf
), height
= gdk_pixbuf_get_height(pixbuf
);
533 tmp
= gdk_pixbuf_scale_simple(pixbuf
, ceil(width
* xshrinkfactor
), ceil(height
* yshrinkfactor
), GDK_INTERP_NEAREST
);
534 g_object_unref ( G_OBJECT(pixbuf
) );
538 static GdkPixbuf
*get_pixbuf( VikMapsLayer
*vml
, gint mode
, MapCoord
*mapcoord
, gchar
*filename_buf
, gint buf_len
, gdouble xshrinkfactor
, gdouble yshrinkfactor
)
543 pixbuf
= a_mapcache_get ( mapcoord
->x
, mapcoord
->y
, mapcoord
->z
,
544 mode
, mapcoord
->scale
, vml
->alpha
, xshrinkfactor
, yshrinkfactor
);
547 g_snprintf ( filename_buf
, buf_len
, DIRSTRUCTURE
,
548 vml
->cache_dir
, mode
,
549 mapcoord
->scale
, mapcoord
->z
, mapcoord
->x
, mapcoord
->y
);
550 if ( g_file_test ( filename_buf
, G_FILE_TEST_EXISTS
) == TRUE
) {
553 pixbuf
= gdk_pixbuf_new_from_file ( filename_buf
, &gx
);
557 if ( gx
->domain
!= GDK_PIXBUF_ERROR
|| gx
->code
!= GDK_PIXBUF_ERROR_CORRUPT_IMAGE
)
558 g_warning ( _("Couldn't open image file: %s"), gx
->message
);
562 g_object_unref ( G_OBJECT(pixbuf
) );
565 if ( vml
->alpha
< 255 )
566 pixbuf
= pixbuf_set_alpha ( pixbuf
, vml
->alpha
);
567 if ( xshrinkfactor
!= 1.0 || yshrinkfactor
!= 1.0 )
568 pixbuf
= pixbuf_shrink ( pixbuf
, xshrinkfactor
, yshrinkfactor
);
570 a_mapcache_add ( pixbuf
, mapcoord
->x
, mapcoord
->y
,
571 mapcoord
->z
, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(vml
->maptype
)),
572 mapcoord
->scale
, vml
->alpha
, xshrinkfactor
, yshrinkfactor
);
580 gboolean
should_start_autodownload(VikMapsLayer
*vml
, VikViewport
*vvp
)
582 const VikCoord
*center
= vik_viewport_get_center ( vvp
);
584 if (vml
->last_center
== NULL
) {
585 VikCoord
*new_center
= g_malloc(sizeof(VikCoord
));
586 *new_center
= *center
;
587 vml
->last_center
= new_center
;
588 vml
->last_xmpp
= vik_viewport_get_xmpp(vvp
);
589 vml
->last_ympp
= vik_viewport_get_ympp(vvp
);
593 /* TODO: perhaps vik_coord_diff() */
594 if (vik_coord_equals(vml
->last_center
, center
)
595 && (vml
->last_xmpp
== vik_viewport_get_xmpp(vvp
))
596 && (vml
->last_ympp
== vik_viewport_get_ympp(vvp
)))
599 *(vml
->last_center
) = *center
;
600 vml
->last_xmpp
= vik_viewport_get_xmpp(vvp
);
601 vml
->last_ympp
= vik_viewport_get_ympp(vvp
);
605 static void maps_layer_draw_section ( VikMapsLayer
*vml
, VikViewport
*vvp
, VikCoord
*ul
, VikCoord
*br
)
608 gdouble xzoom
= vik_viewport_get_xmpp ( vvp
);
609 gdouble yzoom
= vik_viewport_get_ympp ( vvp
);
610 gdouble xshrinkfactor
= 1.0, yshrinkfactor
= 1.0;
611 gdouble existence_only
= FALSE
;
613 if ( vml
->xmapzoom
&& (vml
->xmapzoom
!= xzoom
|| vml
->ymapzoom
!= yzoom
) ) {
614 xshrinkfactor
= vml
->xmapzoom
/ xzoom
;
615 yshrinkfactor
= vml
->ymapzoom
/ yzoom
;
616 xzoom
= vml
->xmapzoom
;
617 yzoom
= vml
->xmapzoom
;
618 if ( ! (xshrinkfactor
> MIN_SHRINKFACTOR
&& xshrinkfactor
< MAX_SHRINKFACTOR
&&
619 yshrinkfactor
> MIN_SHRINKFACTOR
&& yshrinkfactor
< MAX_SHRINKFACTOR
) ) {
620 if ( xshrinkfactor
> REAL_MIN_SHRINKFACTOR
&& yshrinkfactor
> REAL_MIN_SHRINKFACTOR
)
621 existence_only
= TRUE
;
623 g_warning ( _("Cowardly refusing to draw tiles or existence of tiles beyond %d zoom out factor"), (int)( 1.0/REAL_MIN_SHRINKFACTOR
));
630 VikMapSource
*map
= MAPS_LAYER_NTH_TYPE(vml
->maptype
);
631 if ( vik_map_source_coord_to_mapcoord ( map
, ul
, xzoom
, yzoom
, &ulm
) &&
632 vik_map_source_coord_to_mapcoord ( map
, br
, xzoom
, yzoom
, &brm
) ) {
636 gint xmin
= MIN(ulm
.x
, brm
.x
), xmax
= MAX(ulm
.x
, brm
.x
);
637 gint ymin
= MIN(ulm
.y
, brm
.y
), ymax
= MAX(ulm
.y
, brm
.y
);
638 gint mode
= vik_map_source_get_uniq_id(map
);
641 gint xx
, yy
, width
, height
;
644 guint max_path_len
= strlen(vml
->cache_dir
) + 40;
645 gchar
*path_buf
= g_malloc ( max_path_len
* sizeof(char) );
647 if ( (!existence_only
) && vml
->autodownload
&& should_start_autodownload(vml
, vvp
)) {
649 fputs(stderr
, "DEBUG: Starting autodownload\n");
651 if ( vik_map_source_supports_if_modified_since (map
) )
652 // Try to download newer tiles
653 start_download_thread ( vml
, vvp
, ul
, br
, REDOWNLOAD_NEW
);
655 // Download only missing tiles
656 start_download_thread ( vml
, vvp
, ul
, br
, REDOWNLOAD_NONE
);
659 if ( vik_map_source_get_tilesize_x(map
) == 0 && !existence_only
) {
660 for ( x
= xmin
; x
<= xmax
; x
++ ) {
661 for ( y
= ymin
; y
<= ymax
; y
++ ) {
664 pixbuf
= get_pixbuf ( vml
, mode
, &ulm
, path_buf
, max_path_len
, xshrinkfactor
, yshrinkfactor
);
666 width
= gdk_pixbuf_get_width ( pixbuf
);
667 height
= gdk_pixbuf_get_height ( pixbuf
);
669 vik_map_source_mapcoord_to_center_coord ( map
, &ulm
, &coord
);
670 vik_viewport_coord_to_screen ( vvp
, &coord
, &xx
, &yy
);
674 vik_viewport_draw_pixbuf ( vvp
, pixbuf
, 0, 0, xx
, yy
, width
, height
);
678 } else { /* tilesize is known, don't have to keep converting coords */
679 gdouble tilesize_x
= vik_map_source_get_tilesize_x(map
) * xshrinkfactor
;
680 gdouble tilesize_y
= vik_map_source_get_tilesize_y(map
) * yshrinkfactor
;
681 /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
682 gint tilesize_x_ceil
= ceil ( tilesize_x
);
683 gint tilesize_y_ceil
= ceil ( tilesize_y
);
684 gint8 xinc
= (ulm
.x
== xmin
) ? 1 : -1;
685 gint8 yinc
= (ulm
.y
== ymin
) ? 1 : -1;
686 gdouble xx
, yy
; gint xx_tmp
, yy_tmp
;
687 gint base_yy
, xend
, yend
;
689 GdkGC
*black_gc
= GTK_WIDGET(vvp
)->style
->black_gc
;
691 xend
= (xinc
== 1) ? (xmax
+1) : (xmin
-1);
692 yend
= (yinc
== 1) ? (ymax
+1) : (ymin
-1);
694 vik_map_source_mapcoord_to_center_coord ( map
, &ulm
, &coord
);
695 vik_viewport_coord_to_screen ( vvp
, &coord
, &xx_tmp
, &yy_tmp
);
696 xx
= xx_tmp
; yy
= yy_tmp
;
697 /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
698 * eg if tile size 128, shrinkfactor 0.333 */
699 xx
-= (tilesize_x
/2);
700 base_yy
= yy
- (tilesize_y
/2);
702 for ( x
= ((xinc
== 1) ? xmin
: xmax
); x
!= xend
; x
+=xinc
) {
704 for ( y
= ((yinc
== 1) ? ymin
: ymax
); y
!= yend
; y
+=yinc
) {
708 if ( existence_only
) {
709 g_snprintf ( path_buf
, max_path_len
, DIRSTRUCTURE
,
710 vml
->cache_dir
, mode
,
711 ulm
.scale
, ulm
.z
, ulm
.x
, ulm
.y
);
712 if ( g_file_test ( path_buf
, G_FILE_TEST_EXISTS
) == TRUE
) {
713 vik_viewport_draw_line ( vvp
, black_gc
, xx
+tilesize_x_ceil
, yy
, xx
, yy
+tilesize_y_ceil
);
716 pixbuf
= get_pixbuf ( vml
, mode
, &ulm
, path_buf
, max_path_len
, xshrinkfactor
, yshrinkfactor
);
718 vik_viewport_draw_pixbuf ( vvp
, pixbuf
, 0, 0, xx
, yy
, tilesize_x_ceil
, tilesize_y_ceil
);
720 /* retry with bigger shrinkfactor */
722 for (scale_inc
= 1; scale_inc
< 4; scale_inc
++) {
723 int scale_factor
= 1 << scale_inc
; /* 2^scale_inc */
725 ulm2
.x
= ulm
.x
/ scale_factor
;
726 ulm2
.y
= ulm
.y
/ scale_factor
;
727 ulm2
.scale
= ulm
.scale
+ scale_inc
;
728 pixbuf
= get_pixbuf ( vml
, mode
, &ulm2
, path_buf
, max_path_len
, xshrinkfactor
* scale_factor
, yshrinkfactor
* scale_factor
);
730 gint src_x
= (ulm
.x
% scale_factor
) * tilesize_x_ceil
;
731 gint src_y
= (ulm
.y
% scale_factor
) * tilesize_y_ceil
;
732 vik_viewport_draw_pixbuf ( vvp
, pixbuf
, src_x
, src_y
, xx
, yy
, tilesize_x_ceil
, tilesize_y_ceil
);
749 static void maps_layer_draw ( VikMapsLayer
*vml
, VikViewport
*vvp
)
751 if ( vik_map_source_get_drawmode(MAPS_LAYER_NTH_TYPE(vml
->maptype
)) == vik_viewport_get_drawmode ( vvp
) )
755 /* get corner coords */
756 if ( vik_viewport_get_coord_mode ( vvp
) == VIK_COORD_UTM
&& ! vik_viewport_is_one_zone ( vvp
) ) {
757 /* UTM multi-zone stuff by Kit Transue */
758 gchar leftmost_zone
, rightmost_zone
, i
;
759 leftmost_zone
= vik_viewport_leftmost_zone( vvp
);
760 rightmost_zone
= vik_viewport_rightmost_zone( vvp
);
761 for ( i
= leftmost_zone
; i
<= rightmost_zone
; ++i
) {
762 vik_viewport_corners_for_zonen ( vvp
, i
, &ul
, &br
);
763 maps_layer_draw_section ( vml
, vvp
, &ul
, &br
);
767 vik_viewport_screen_to_coord ( vvp
, 0, 0, &ul
);
768 vik_viewport_screen_to_coord ( vvp
, vik_viewport_get_width(vvp
), vik_viewport_get_height(vvp
), &br
);
770 maps_layer_draw_section ( vml
, vvp
, &ul
, &br
);
775 /*************************/
776 /****** DOWNLOADING ******/
777 /*************************/
779 /* pass along data to thread, exists even if layer is deleted. */
789 gboolean refresh_display
;
792 gboolean map_layer_alive
;
796 static void mdi_free ( MapDownloadInfo
*mdi
)
798 g_mutex_free(mdi
->mutex
);
799 g_free ( mdi
->cache_dir
);
800 mdi
->cache_dir
= NULL
;
801 g_free ( mdi
->filename_buf
);
802 mdi
->filename_buf
= NULL
;
806 static void weak_ref_cb(gpointer ptr
, GObject
* dead_vml
)
808 MapDownloadInfo
*mdi
= ptr
;
809 g_mutex_lock(mdi
->mutex
);
810 mdi
->map_layer_alive
= FALSE
;
811 g_mutex_unlock(mdi
->mutex
);
814 static int map_download_thread ( MapDownloadInfo
*mdi
, gpointer threaddata
)
818 for ( x
= mdi
->x0
; x
<= mdi
->xf
; x
++ )
820 for ( y
= mdi
->y0
; y
<= mdi
->yf
; y
++ )
822 gboolean remove_mem_cache
= FALSE
;
823 gboolean need_download
= FALSE
;
824 g_snprintf ( mdi
->filename_buf
, mdi
->maxlen
, DIRSTRUCTURE
,
825 mdi
->cache_dir
, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi
->maptype
)),
826 mdi
->mapcoord
.scale
, mdi
->mapcoord
.z
, x
, y
);
829 int res
= a_background_thread_progress ( threaddata
, ((gdouble
)donemaps
) / mdi
->mapstoget
); /* this also calls testcancel */
833 if ( mdi
->redownload
== REDOWNLOAD_ALL
)
834 g_remove ( mdi
->filename_buf
);
836 else if ( (mdi
->redownload
== REDOWNLOAD_BAD
) && (g_file_test ( mdi
->filename_buf
, G_FILE_TEST_EXISTS
) == TRUE
) )
838 /* see if this one is bad or what */
840 GdkPixbuf
*pixbuf
= gdk_pixbuf_new_from_file ( mdi
->filename_buf
, &gx
);
842 g_remove ( mdi
->filename_buf
);
844 g_object_unref ( pixbuf
);
849 if ( g_file_test ( mdi
->filename_buf
, G_FILE_TEST_EXISTS
) == FALSE
)
851 need_download
= TRUE
;
852 if (( mdi
->redownload
!= REDOWNLOAD_NONE
) &&
853 ( mdi
->redownload
!= DOWNLOAD_OR_REFRESH
))
854 remove_mem_cache
= TRUE
;
855 } else if ( mdi
->redownload
== DOWNLOAD_OR_REFRESH
) {
856 remove_mem_cache
= TRUE
;
857 } else if ( mdi
->redownload
== REDOWNLOAD_NEW
) {
858 need_download
= TRUE
;
859 remove_mem_cache
= TRUE
;
863 mdi
->mapcoord
.x
= x
; mdi
->mapcoord
.y
= y
;
866 if ( vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi
->maptype
), &(mdi
->mapcoord
), mdi
->filename_buf
))
871 g_mutex_lock(mdi
->mutex
);
872 if (remove_mem_cache
)
873 a_mapcache_remove_all_shrinkfactors ( x
, y
, mdi
->mapcoord
.z
, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi
->maptype
)), mdi
->mapcoord
.scale
);
874 if (mdi
->refresh_display
&& mdi
->map_layer_alive
) {
875 /* TODO: check if it's on visible area */
876 vik_layer_emit_update ( VIK_LAYER(mdi
->vml
) );
878 g_mutex_unlock(mdi
->mutex
);
880 mdi
->mapcoord
.x
= mdi
->mapcoord
.y
= 0; /* we're temporarily between downloads */
884 g_mutex_lock(mdi
->mutex
);
885 if (mdi
->map_layer_alive
)
886 g_object_weak_unref(G_OBJECT(mdi
->vml
), weak_ref_cb
, mdi
);
887 g_mutex_unlock(mdi
->mutex
);
891 static void mdi_cancel_cleanup ( MapDownloadInfo
*mdi
)
893 if ( mdi
->mapcoord
.x
|| mdi
->mapcoord
.y
)
895 g_snprintf ( mdi
->filename_buf
, mdi
->maxlen
, DIRSTRUCTURE
,
896 mdi
->cache_dir
, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi
->maptype
)),
897 mdi
->mapcoord
.scale
, mdi
->mapcoord
.z
, mdi
->mapcoord
.x
, mdi
->mapcoord
.y
);
898 if ( g_file_test ( mdi
->filename_buf
, G_FILE_TEST_EXISTS
) == TRUE
)
900 g_remove ( mdi
->filename_buf
);
905 static void start_download_thread ( VikMapsLayer
*vml
, VikViewport
*vvp
, const VikCoord
*ul
, const VikCoord
*br
, gint redownload
)
907 gdouble xzoom
= vml
->xmapzoom
? vml
->xmapzoom
: vik_viewport_get_xmpp ( vvp
);
908 gdouble yzoom
= vml
->ymapzoom
? vml
->ymapzoom
: vik_viewport_get_ympp ( vvp
);
910 VikMapSource
*map
= MAPS_LAYER_NTH_TYPE(vml
->maptype
);
911 if ( vik_map_source_coord_to_mapcoord ( map
, ul
, xzoom
, yzoom
, &ulm
)
912 && vik_map_source_coord_to_mapcoord ( map
, br
, xzoom
, yzoom
, &brm
) )
914 MapDownloadInfo
*mdi
= g_malloc ( sizeof(MapDownloadInfo
) );
919 mdi
->map_layer_alive
= TRUE
;
920 mdi
->mutex
= g_mutex_new();
921 mdi
->refresh_display
= TRUE
;
923 /* cache_dir and buffer for dest filename */
924 mdi
->cache_dir
= g_strdup ( vml
->cache_dir
);
925 mdi
->maxlen
= strlen ( vml
->cache_dir
) + 40;
926 mdi
->filename_buf
= g_malloc ( mdi
->maxlen
* sizeof(gchar
) );
927 mdi
->maptype
= vml
->maptype
;
931 mdi
->redownload
= redownload
;
933 mdi
->x0
= MIN(ulm
.x
, brm
.x
);
934 mdi
->xf
= MAX(ulm
.x
, brm
.x
);
935 mdi
->y0
= MIN(ulm
.y
, brm
.y
);
936 mdi
->yf
= MAX(ulm
.y
, brm
.y
);
940 if ( mdi
->redownload
) {
941 mdi
->mapstoget
= (mdi
->xf
- mdi
->x0
+ 1) * (mdi
->yf
- mdi
->y0
+ 1);
943 /* calculate how many we need */
944 for ( a
= mdi
->x0
; a
<= mdi
->xf
; a
++ )
946 for ( b
= mdi
->y0
; b
<= mdi
->yf
; b
++ )
948 g_snprintf ( mdi
->filename_buf
, mdi
->maxlen
, DIRSTRUCTURE
,
949 vml
->cache_dir
, vik_map_source_get_uniq_id(map
), ulm
.scale
,
951 if ( g_file_test ( mdi
->filename_buf
, G_FILE_TEST_EXISTS
) == FALSE
)
957 mdi
->mapcoord
.x
= mdi
->mapcoord
.y
= 0; /* for cleanup -- no current map */
959 if ( mdi
->mapstoget
)
961 const gchar
*tmp_str
;
966 if (redownload
== REDOWNLOAD_BAD
)
967 tmp_str
= ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi
->mapstoget
);
969 tmp_str
= ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi
->mapstoget
);
973 tmp_str
= ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi
->mapstoget
);
975 tmp
= g_strdup_printf ( tmp_str
, mdi
->mapstoget
, MAPS_LAYER_NTH_LABEL(vml
->maptype
));
977 g_object_weak_ref(G_OBJECT(mdi
->vml
), weak_ref_cb
, mdi
);
978 /* launch the thread */
979 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml
), /* parent window */
980 tmp
, /* description string */
981 (vik_thr_func
) map_download_thread
, /* function to call within thread */
982 mdi
, /* pass along data */
983 (vik_thr_free_func
) mdi_free
, /* function to free pass along data */
984 (vik_thr_free_func
) mdi_cancel_cleanup
,
993 void maps_layer_download_section_without_redraw( VikMapsLayer
*vml
, VikViewport
*vvp
, VikCoord
*ul
, VikCoord
*br
, gdouble zoom
)
996 VikMapSource
*map
= MAPS_LAYER_NTH_TYPE(vml
->maptype
);
998 if (!vik_map_source_coord_to_mapcoord(map
, ul
, zoom
, zoom
, &ulm
)
999 || !vik_map_source_coord_to_mapcoord(map
, br
, zoom
, zoom
, &brm
)) {
1000 g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__
);
1004 MapDownloadInfo
*mdi
= g_malloc(sizeof(MapDownloadInfo
));
1009 mdi
->map_layer_alive
= TRUE
;
1010 mdi
->mutex
= g_mutex_new();
1011 mdi
->refresh_display
= FALSE
;
1013 mdi
->cache_dir
= g_strdup ( vml
->cache_dir
);
1014 mdi
->maxlen
= strlen ( vml
->cache_dir
) + 40;
1015 mdi
->filename_buf
= g_malloc ( mdi
->maxlen
* sizeof(gchar
) );
1016 mdi
->maptype
= vml
->maptype
;
1018 mdi
->mapcoord
= ulm
;
1020 mdi
->redownload
= REDOWNLOAD_NONE
;
1022 mdi
->x0
= MIN(ulm
.x
, brm
.x
);
1023 mdi
->xf
= MAX(ulm
.x
, brm
.x
);
1024 mdi
->y0
= MIN(ulm
.y
, brm
.y
);
1025 mdi
->yf
= MAX(ulm
.y
, brm
.y
);
1029 for (i
= mdi
->x0
; i
<= mdi
->xf
; i
++) {
1030 for (j
= mdi
->y0
; j
<= mdi
->yf
; j
++) {
1031 g_snprintf ( mdi
->filename_buf
, mdi
->maxlen
, DIRSTRUCTURE
,
1032 vml
->cache_dir
, vik_map_source_get_uniq_id(map
), ulm
.scale
,
1034 if ( g_file_test ( mdi
->filename_buf
, G_FILE_TEST_EXISTS
) == FALSE
)
1039 mdi
->mapcoord
.x
= mdi
->mapcoord
.y
= 0; /* for cleanup -- no current map */
1041 if (mdi
->mapstoget
) {
1044 fmt
= ngettext("Downloading %d %s map...",
1045 "Downloading %d %s maps...",
1047 tmp
= g_strdup_printf ( fmt
, mdi
->mapstoget
, MAPS_LAYER_NTH_LABEL(vml
->maptype
) );
1049 g_object_weak_ref(G_OBJECT(mdi
->vml
), weak_ref_cb
, mdi
);
1050 /* launch the thread */
1051 a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml
), /* parent window */
1052 tmp
, /* description string */
1053 (vik_thr_func
) map_download_thread
, /* function to call within thread */
1054 mdi
, /* pass along data */
1055 (vik_thr_free_func
) mdi_free
, /* function to free pass along data */
1056 (vik_thr_free_func
) mdi_cancel_cleanup
,
1064 static void maps_layer_redownload_bad ( VikMapsLayer
*vml
)
1066 start_download_thread ( vml
, vml
->redownload_vvp
, &(vml
->redownload_ul
), &(vml
->redownload_br
), REDOWNLOAD_BAD
);
1069 static void maps_layer_redownload_all ( VikMapsLayer
*vml
)
1071 start_download_thread ( vml
, vml
->redownload_vvp
, &(vml
->redownload_ul
), &(vml
->redownload_br
), REDOWNLOAD_ALL
);
1074 static void maps_layer_redownload_new ( VikMapsLayer
*vml
)
1076 start_download_thread ( vml
, vml
->redownload_vvp
, &(vml
->redownload_ul
), &(vml
->redownload_br
), REDOWNLOAD_NEW
);
1079 static gboolean
maps_layer_download_release ( VikMapsLayer
*vml
, GdkEventButton
*event
, VikViewport
*vvp
)
1081 if (!vml
|| vml
->vl
.type
!= VIK_LAYER_MAPS
)
1083 if ( vml
->dl_tool_x
!= -1 && vml
->dl_tool_y
!= -1 )
1085 if ( event
->button
== 1 )
1088 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
);
1089 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
);
1090 start_download_thread ( vml
, vvp
, &ul
, &br
, DOWNLOAD_OR_REFRESH
);
1091 vml
->dl_tool_x
= vml
->dl_tool_y
= -1;
1096 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
) );
1097 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
) );
1099 vml
->redownload_vvp
= vvp
;
1101 vml
->dl_tool_x
= vml
->dl_tool_y
= -1;
1103 if ( ! vml
->dl_right_click_menu
) {
1105 vml
->dl_right_click_menu
= GTK_MENU ( gtk_menu_new () );
1107 item
= gtk_menu_item_new_with_label ( _("Redownload bad map(s)") );
1108 g_signal_connect_swapped ( G_OBJECT(item
), "activate", G_CALLBACK(maps_layer_redownload_bad
), vml
);
1109 gtk_menu_shell_append ( GTK_MENU_SHELL(vml
->dl_right_click_menu
), item
);
1111 item
= gtk_menu_item_new_with_label ( _("Redownload new map(s)") );
1112 g_signal_connect_swapped ( G_OBJECT(item
), "activate", G_CALLBACK(maps_layer_redownload_new
), vml
);
1113 gtk_menu_shell_append ( GTK_MENU_SHELL(vml
->dl_right_click_menu
), item
);
1115 item
= gtk_menu_item_new_with_label ( _("Redownload all map(s)") );
1116 g_signal_connect_swapped ( G_OBJECT(item
), "activate", G_CALLBACK(maps_layer_redownload_all
), vml
);
1117 gtk_menu_shell_append ( GTK_MENU_SHELL(vml
->dl_right_click_menu
), item
);
1120 gtk_menu_popup ( vml
->dl_right_click_menu
, NULL
, NULL
, NULL
, NULL
, event
->button
, event
->time
);
1121 gtk_widget_show_all ( GTK_WIDGET(vml
->dl_right_click_menu
) );
1127 static gpointer
maps_layer_download_create ( VikWindow
*vw
, VikViewport
*vvp
)
1132 static gboolean
maps_layer_download_click ( VikMapsLayer
*vml
, GdkEventButton
*event
, VikViewport
*vvp
)
1135 if (!vml
|| vml
->vl
.type
!= VIK_LAYER_MAPS
)
1137 VikMapSource
*map
= MAPS_LAYER_NTH_TYPE(vml
->maptype
);
1138 if ( vik_map_source_get_drawmode(map
) == vik_viewport_get_drawmode ( vvp
) &&
1139 vik_map_source_coord_to_mapcoord ( map
, vik_viewport_get_center ( vvp
),
1140 vml
->xmapzoom
? vml
->xmapzoom
: vik_viewport_get_xmpp ( vvp
),
1141 vml
->ymapzoom
? vml
->ymapzoom
: vik_viewport_get_ympp ( vvp
),
1143 vml
->dl_tool_x
= event
->x
, vml
->dl_tool_y
= event
->y
;
1150 if ( __map_types
[vml
->maptype
].drawmode
== vik_viewport_get_drawmode ( vvp
) )
1154 vik_viewport_screen_to_coord ( vvp
, event
->x
, event
->y
, &coord
);
1155 if ( __map_types
[vml
->maptype
].coord_to_mapcoord ( &coord
,
1156 vml
->xmapzoom
? vml
->xmapzoom
: vik_viewport_get_xmpp ( vvp
),
1157 vml
->ymapzoom
? vml
->ymapzoom
: vik_viewport_get_ympp ( vvp
),
1159 gchar
*filename_buf
= g_strdup_printf ( DIRSTRUCTURE
,
1160 vml
->cache_dir
, __map_types
[vml
->maptype
].uniq_id
,
1161 mapcoord
.scale
, mapcoord
.z
, mapcoord
.x
, mapcoord
.y
);
1163 __map_types
[vml
->maptype
].download ( &mapcoord
, filename_buf
);
1164 g_free ( filename_buf
);
1165 vik_layer_emit_update ( VIK_LAYER(vml
) );
1173 static void download_onscreen_maps ( gpointer vml_vvp
[2], gint redownload
)
1175 VikMapsLayer
*vml
= vml_vvp
[0];
1176 VikViewport
*vvp
= vml_vvp
[1];
1177 VikViewportDrawMode vp_drawmode
= vik_viewport_get_drawmode ( vvp
);
1179 gdouble xzoom
= vml
->xmapzoom
? vml
->xmapzoom
: vik_viewport_get_xmpp ( vvp
);
1180 gdouble yzoom
= vml
->ymapzoom
? vml
->ymapzoom
: vik_viewport_get_ympp ( vvp
);
1185 vik_viewport_screen_to_coord ( vvp
, 0, 0, &ul
);
1186 vik_viewport_screen_to_coord ( vvp
, vik_viewport_get_width(vvp
), vik_viewport_get_height(vvp
), &br
);
1188 VikMapSource
*map
= MAPS_LAYER_NTH_TYPE(vml
->maptype
);
1189 if ( vik_map_source_get_drawmode(map
) == vp_drawmode
&&
1190 vik_map_source_coord_to_mapcoord ( map
, &ul
, xzoom
, yzoom
, &ulm
) &&
1191 vik_map_source_coord_to_mapcoord ( map
, &br
, xzoom
, yzoom
, &brm
) )
1192 start_download_thread ( vml
, vvp
, &ul
, &br
, redownload
);
1193 else if (vik_map_source_get_drawmode(map
) != vp_drawmode
) {
1194 const gchar
*drawmode_name
= vik_viewport_get_drawmode_name (vvp
, vik_map_source_get_drawmode(map
));
1195 gchar
*err
= g_strdup_printf(_("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again."), _(drawmode_name
));
1196 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml
), err
);
1200 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml
), _("Wrong zoom level for this map.") );
1204 static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp
[2] )
1206 download_onscreen_maps( vml_vvp
, REDOWNLOAD_NONE
);
1209 static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp
[2] )
1211 download_onscreen_maps( vml_vvp
, REDOWNLOAD_NEW
);
1214 static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp
[2] )
1216 download_onscreen_maps( vml_vvp
, REDOWNLOAD_ALL
);
1219 static void maps_layer_add_menu_items ( VikMapsLayer
*vml
, GtkMenu
*menu
, VikLayersPanel
*vlp
)
1221 static gpointer pass_along
[2];
1223 pass_along
[0] = vml
;
1224 pass_along
[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp
) );
1226 item
= gtk_menu_item_new();
1227 gtk_menu_shell_append ( GTK_MENU_SHELL(menu
), item
);
1228 gtk_widget_show ( item
);
1230 item
= gtk_menu_item_new_with_label ( _("Download missing Onscreen Maps") );
1231 g_signal_connect_swapped ( G_OBJECT(item
), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps
), pass_along
);
1232 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
1233 gtk_widget_show ( item
);
1235 if ( vik_map_source_supports_if_modified_since (MAPS_LAYER_NTH_TYPE(vml
->maptype
)) ) {
1236 item
= gtk_menu_item_new_with_label ( _("Download new Onscreen Maps from server") );
1237 g_signal_connect_swapped ( G_OBJECT(item
), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps
), pass_along
);
1238 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
1239 gtk_widget_show ( item
);
1242 /* TODO Add GTK_STOCK_REFRESH icon */
1243 item
= gtk_menu_item_new_with_label ( _("Refresh Onscreen Tiles") );
1244 g_signal_connect_swapped ( G_OBJECT(item
), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps
), pass_along
);
1245 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
1246 gtk_widget_show ( item
);