X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/71cea316bc59b175f891ae7eff259742e013563e..26336cf0db5532e80d37c82983338e09d7789d9d:/src/vikmapslayer.c diff --git a/src/vikmapslayer.c b/src/vikmapslayer.c index 597c823c..e43aa6ef 100644 --- a/src/vikmapslayer.c +++ b/src/vikmapslayer.c @@ -2,6 +2,7 @@ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager * * Copyright (C) 2005, Evan Battaglia + * Copyright (C) 2010, Guilhem Bonnefille * UTM multi-zone stuff by Kit Transue * Dynamic map type by Guilhem Bonnefille * @@ -44,6 +45,7 @@ #endif #include "globals.h" +#include "util.h" #include "coords.h" #include "vikcoord.h" #include "viktreeview.h" @@ -59,6 +61,7 @@ /* only for dialog.h -- ugh */ #include "vikwaypoint.h" #include "dialog.h" +#include "preferences.h" #include "vikstatus.h" #include "background.h" @@ -78,10 +81,10 @@ static GList *__map_types = NULL; #define NUM_MAP_TYPES g_list_length(__map_types) /* List of label for each map type */ -static GList *params_maptypes = NULL; +static gchar **params_maptypes = NULL; /* Corresponding IDS. (Cf. field uniq_id in VikMapsLayer struct) */ -static GList *params_maptypes_ids = NULL; +static guint *params_maptypes_ids = NULL; /******** MAPZOOMS *********/ @@ -95,10 +98,11 @@ static gdouble __mapzooms_y[] = { 0.0, 0.25, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64. static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file); +static const gchar* maps_layer_tooltip ( VikMapsLayer *vml ); static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len ); static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp ); -static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp ); -static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id ); +static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation ); +static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation ); static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp ); static VikMapsLayer *maps_layer_new ( VikViewport *vvp ); static void maps_layer_free ( VikMapsLayer *vml ); @@ -108,6 +112,7 @@ static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp ); static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir ); static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload ); static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp ); +static guint map_uniq_id_to_index ( guint uniq_id ); static VikLayerParamScale params_scales[] = { @@ -116,11 +121,11 @@ static VikLayerParamScale params_scales[] = { }; VikLayerParam maps_layer_params[] = { - { "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Map Type:"), VIK_LAYER_WIDGET_RADIOGROUP, NULL, NULL }, + { "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Map Type:"), VIK_LAYER_WIDGET_COMBOBOX, NULL, NULL }, { "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Maps Directory:"), VIK_LAYER_WIDGET_FOLDERENTRY }, { "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales }, { "autodownload", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload maps:"), VIK_LAYER_WIDGET_CHECKBUTTON }, - { "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms }, + { "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms, NULL }, }; enum { PARAM_MAPTYPE=0, PARAM_CACHE_DIR, PARAM_ALPHA, PARAM_AUTODOWNLOAD, PARAM_MAPZOOM, NUM_PARAMS }; @@ -162,6 +167,8 @@ VikLayerInterface vik_maps_layer_interface = { (VikLayerFuncSublayerRenameRequest) NULL, (VikLayerFuncSublayerToggleVisible) NULL, + (VikLayerFuncSublayerTooltip) NULL, + (VikLayerFuncLayerTooltip) maps_layer_tooltip, (VikLayerFuncMarshall) maps_layer_marshall, (VikLayerFuncUnmarshall) maps_layer_unmarshall, @@ -173,6 +180,7 @@ VikLayerInterface vik_maps_layer_interface = { (VikLayerFuncWriteFileData) NULL, (VikLayerFuncDeleteItem) NULL, + (VikLayerFuncCutItem) NULL, (VikLayerFuncCopyItem) NULL, (VikLayerFuncPasteItem) NULL, (VikLayerFuncFreeCopiedItem) NULL, @@ -197,28 +205,58 @@ struct _VikMapsLayer { GtkMenu *dl_right_click_menu; VikCoord redownload_ul, redownload_br; /* right click menu only */ VikViewport *redownload_vvp; + + gboolean license_notice_shown; // FALSE for new maps only, otherwise + // TRUE for saved maps & other layer changes as we don't need to show it again }; -enum { REDOWNLOAD_NONE = 0, REDOWNLOAD_BAD, REDOWNLOAD_ALL, DOWNLOAD_OR_REFRESH }; +enum { REDOWNLOAD_NONE = 0, /* download only missing maps */ + REDOWNLOAD_BAD, /* download missing and bad maps */ + REDOWNLOAD_NEW, /* download missing maps that are newer on server only */ + REDOWNLOAD_ALL, /* download all maps */ + DOWNLOAD_OR_REFRESH }; /* download missing maps and refresh cache */ + +static VikLayerParam prefs[] = { + { VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Default maplayer directory:"), VIK_LAYER_WIDGET_FOLDERENTRY, NULL, NULL }, +}; +void maps_layer_init () +{ + VikLayerParamData tmp; + tmp.s = maps_layer_default_dir(); + a_preferences_register(prefs, tmp, VIKING_PREFERENCES_GROUP_KEY); +} /****************************************/ /******** MAPS LAYER TYPES **************/ /****************************************/ -void maps_layer_register_map_source ( VikMapSource *map ) +int _get_index_for_id ( guint id ) { - g_assert(map != NULL); - - guint id = vik_map_source_get_uniq_id(map); - const char *label = vik_map_source_get_label(map); - g_assert(label != NULL); + int index = 0 ; + while (params_maptypes_ids[index] != 0) + { + if (params_maptypes_ids[index] == id) + return index; + index++; + } + return -1; +} +void _add_map_source ( guint id, const char *label, VikMapSource *map ) +{ + gsize len = 0; + if (params_maptypes) + len = g_strv_length (params_maptypes); /* Add the label */ - params_maptypes = g_list_append(params_maptypes, g_strdup(label)); + params_maptypes = g_realloc (params_maptypes, (len+2)*sizeof(gchar*)); + params_maptypes[len] = g_strdup (label); + params_maptypes[len+1] = NULL; /* Add the id */ - params_maptypes_ids = g_list_append(params_maptypes_ids, GUINT_TO_POINTER (id)); + params_maptypes_ids = g_realloc (params_maptypes_ids, (len+2)*sizeof(guint)); + params_maptypes_ids[len] = id; + params_maptypes_ids[len+1] = 0; /* We have to clone */ VikMapSource *clone = VIK_MAP_SOURCE(g_object_ref(map)); @@ -226,7 +264,7 @@ void maps_layer_register_map_source ( VikMapSource *map ) __map_types = g_list_append(__map_types, clone); /* Hack - We have to ensure the mode LayerParam reference the up-to-date + We have to ensure the mode LayerParam references the up-to-date GLists. */ /* @@ -237,8 +275,37 @@ void maps_layer_register_map_source ( VikMapSource *map ) maps_layer_params[0].extra_widget_data = params_maptypes_ids; } -#define MAPS_LAYER_NTH_LABEL(n) ((gchar*)g_list_nth_data(params_maptypes, (n))) -#define MAPS_LAYER_NTH_ID(n) ((guint)g_list_nth_data(params_maptypes_ids, (n))) +void _update_map_source ( const char *label, VikMapSource *map, int index ) +{ + GList *item = g_list_nth (__map_types, index); + g_object_unref (item->data); + item->data = g_object_ref (map); + /* Change previous data */ + g_free (params_maptypes[index]); + params_maptypes[index] = g_strdup (label); +} + +void maps_layer_register_map_source ( VikMapSource *map ) +{ + g_assert(map != NULL); + + guint id = vik_map_source_get_uniq_id(map); + const char *label = vik_map_source_get_label(map); + g_assert(label != NULL); + + int previous = map_uniq_id_to_index (id); + if (previous != NUM_MAP_TYPES) + { + _update_map_source (label, map, previous); + } + else + { + _add_map_source (id, label, map); + } +} + +#define MAPS_LAYER_NTH_LABEL(n) (params_maptypes[n]) +#define MAPS_LAYER_NTH_ID(n) (params_maptypes_ids[n]) #define MAPS_LAYER_NTH_TYPE(n) (VIK_MAP_SOURCE(g_list_nth_data(__map_types, (n)))) gint vik_maps_layer_get_map_type(VikMapsLayer *vml) @@ -316,7 +383,10 @@ static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir ) vml->cache_dir = NULL; if ( dir == NULL || dir[0] == '\0' ) - vml->cache_dir = g_strdup ( MAPS_CACHE_DIR ); + { + if ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir") ) + vml->cache_dir = g_strdup ( a_preferences_get(VIKING_PREFERENCES_NAMESPACE "maplayer_default_dir")->s ); + } else { len = strlen(dir); @@ -380,8 +450,12 @@ static guint map_uniq_id_to_index ( guint uniq_id ) return NUM_MAP_TYPES; /* no such thing */ } -static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp ) +static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp, gboolean is_file_operation ) { + // When loading from a file don't need the license reminder + if ( is_file_operation ) + vml->license_notice_shown = TRUE; + switch ( id ) { case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break; @@ -402,7 +476,7 @@ static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerPa return TRUE; } -static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id ) +static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id, gboolean is_file_operation ) { VikLayerParamData rv; switch ( id ) @@ -425,7 +499,7 @@ static VikMapsLayer *maps_layer_new ( VikViewport *vvp ) int idx; VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) ); vik_layer_init ( VIK_LAYER(vml), VIK_LAYER_MAPS ); - idx = map_uniq_id_to_index(7); /* 7 is id for google maps */ + idx = map_uniq_id_to_index(13); /* 13 is id for OSM Mapnik maps */ vml->maptype = (idx < NUM_MAP_TYPES) ? idx : 0; vml->alpha = 255; vml->mapzoom_id = 0; @@ -437,6 +511,7 @@ static VikMapsLayer *maps_layer_new ( VikViewport *vvp ) vml->last_ympp = 0.0; vml->dl_right_click_menu = NULL; + vml->license_notice_shown = FALSE; return vml; } @@ -462,17 +537,30 @@ static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_f VikMapsLayer *vml = VIK_MAPS_LAYER(vl); VikMapSource *map = NULL; - vp_drawmode = vik_viewport_get_drawmode ( VIK_VIEWPORT(vp) ); + vp_drawmode = vik_viewport_get_drawmode ( vp ); map = MAPS_LAYER_NTH_TYPE(vml->maptype); if (vik_map_source_get_drawmode(map) != vp_drawmode) { - const gchar *drawmode_name = vik_viewport_get_drawmode_name (VIK_VIEWPORT(vp), vik_map_source_get_drawmode(map)); + const gchar *drawmode_name = vik_viewport_get_drawmode_name (vp, vik_map_source_get_drawmode(map)); gchar *msg = g_strdup_printf(_("New map cannot be displayed in the current drawmode.\nSelect \"%s\" from View menu to view it."), drawmode_name); - a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), msg ); + a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp), msg ); g_free(msg); } + + if (vik_map_source_get_license (map) != NULL) { + if ( ! vml->license_notice_shown ) { + a_dialog_license (VIK_GTK_WINDOW_FROM_WIDGET(vp), vik_map_source_get_label (map), + vik_map_source_get_license (map), vik_map_source_get_license_url (map) ); + vml->license_notice_shown = TRUE; + } + } } } +static const gchar* maps_layer_tooltip ( VikMapsLayer *vml ) +{ + return vik_maps_layer_get_map_label ( vml ); +} + static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len ) { vik_layer_marshall_params ( VIK_LAYER(vml), data, len ); @@ -518,7 +606,7 @@ static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdou { GdkPixbuf *tmp; guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf); - tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_BILINEAR); + tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_NEAREST); g_object_unref ( G_OBJECT(pixbuf) ); return tmp; } @@ -535,21 +623,22 @@ static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE, vml->cache_dir, mode, mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y ); - if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE) { + if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE) { GError *gx = NULL; pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx ); + /* free the pixbuf on error */ if (gx) { if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE ) g_warning ( _("Couldn't open image file: %s"), gx->message ); - g_error_free ( gx ); - if ( pixbuf ) - g_object_unref ( G_OBJECT(pixbuf) ); - pixbuf = NULL; - } else { + g_error_free ( gx ); + if ( pixbuf ) + g_object_unref ( G_OBJECT(pixbuf) ); + pixbuf = NULL; + } else { if ( vml->alpha < 255 ) pixbuf = pixbuf_set_alpha ( pixbuf, vml->alpha ); if ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 ) @@ -558,7 +647,6 @@ static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y, mapcoord->z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(vml->maptype)), mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor ); - } } } } @@ -569,6 +657,10 @@ gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp) { const VikCoord *center = vik_viewport_get_center ( vvp ); + if (vik_window_get_pan_move (VIK_WINDOW(VIK_GTK_WINDOW_FROM_WIDGET(GTK_WIDGET(vvp))))) + /* D'n'D pan in action: do not download */ + return FALSE; + if (vml->last_center == NULL) { VikCoord *new_center = g_malloc(sizeof(VikCoord)); *new_center = *center; @@ -633,10 +725,13 @@ static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCo gchar *path_buf = g_malloc ( max_path_len * sizeof(char) ); if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) { -#ifdef DEBUG - fputs(stderr, "DEBUG: Starting autodownload\n"); -#endif - start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE ); + g_debug("%s: Starting autodownload", __FUNCTION__); + if ( vik_map_source_supports_download_only_new (map) ) + // Try to download newer tiles + start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW ); + else + // Download only missing tiles + start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE ); } if ( vik_map_source_get_tilesize_x(map) == 0 && !existence_only ) { @@ -696,9 +791,52 @@ static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCo vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil ); } } else { - pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor ); - if ( pixbuf ) - vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, tilesize_x_ceil, tilesize_y_ceil ); + int scale_inc; + for (scale_inc = 0; scale_inc < 4; scale_inc ++) { + /* try with correct then smaller zooms */ + int scale_factor = 1 << scale_inc; /* 2^scale_inc */ + MapCoord ulm2 = ulm; + ulm2.x = ulm.x / scale_factor; + ulm2.y = ulm.y / scale_factor; + ulm2.scale = ulm.scale + scale_inc; + pixbuf = get_pixbuf ( vml, mode, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor ); + if ( pixbuf ) { + gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil; + gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil; +#ifdef DEBUG + printf("maps_layer_draw_section - x=%d, y=%d, z=%d, src_x=%d, src_y=%d, xx=%d, yy=%d - %x\n", ulm.x, ulm.y, ulm.scale, src_x, src_y, (int)xx, (int)yy, vvp); +#endif + vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil ); + break; + } + } + if ( !pixbuf ) { + /* retry with bigger zooms */ + int scale_dec; + for (scale_dec = 1; scale_dec < 2; scale_dec ++) { + int pict_x, pict_y; + int scale_factor = 1 << scale_dec; /* 2^scale_dec */ + MapCoord ulm2 = ulm; + ulm2.x = ulm.x * scale_factor; + ulm2.y = ulm.y * scale_factor; + ulm2.scale = ulm.scale - scale_dec; + for (pict_x = 0; pict_x < scale_factor; pict_x ++) { + for (pict_y = 0; pict_y < scale_factor; pict_y ++) { + MapCoord ulm3 = ulm2; + ulm3.x += pict_x; + ulm3.y += pict_y; + pixbuf = get_pixbuf ( vml, mode, &ulm3, path_buf, max_path_len, xshrinkfactor / scale_factor, yshrinkfactor / scale_factor ); + if ( pixbuf ) { + gint src_x = 0; + gint src_y = 0; + gint dest_x = xx + pict_x * (tilesize_x_ceil / scale_factor); + gint dest_y = yy + pict_y * (tilesize_y_ceil / scale_factor); + vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, dest_x, dest_y, tilesize_x_ceil / scale_factor, tilesize_y_ceil / scale_factor ); + } + } + } + } + } } yy += tilesize_y; @@ -717,6 +855,14 @@ static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp ) { VikCoord ul, br; + /* Copyright */ + const gchar *copyright = vik_map_source_get_copyright ( MAPS_LAYER_NTH_TYPE(vml->maptype) ); + vik_viewport_add_copyright ( vvp, copyright ); + + /* Logo */ + const GdkPixbuf *logo = vik_map_source_get_logo ( MAPS_LAYER_NTH_TYPE(vml->maptype) ); + vik_viewport_add_logo ( vvp, logo ); + /* get corner coords */ if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) { /* UTM multi-zone stuff by Kit Transue */ @@ -778,6 +924,7 @@ static void weak_ref_cb(gpointer ptr, GObject * dead_vml) static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata ) { + void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype)); guint donemaps = 0; gint x, y; for ( x = mdi->x0; x <= mdi->xf; x++ ) @@ -792,40 +939,62 @@ static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata ) donemaps++; int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */ - if (res != 0) + if (res != 0) { + vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle); return -1; - - if ( mdi->redownload == REDOWNLOAD_ALL) - g_remove ( mdi->filename_buf ); - - else if ( (mdi->redownload == REDOWNLOAD_BAD) && (g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE) ) - { - /* see if this one is bad or what */ - GError *gx = NULL; - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx ); - if (gx || (!pixbuf)) - g_remove ( mdi->filename_buf ); - if ( pixbuf ) - g_object_unref ( pixbuf ); - if ( gx ) - g_error_free ( gx ); } - if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) - { + if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) { need_download = TRUE; - if (( mdi->redownload != REDOWNLOAD_NONE ) && - ( mdi->redownload != DOWNLOAD_OR_REFRESH )) - remove_mem_cache = TRUE; - } else if ( mdi->redownload == DOWNLOAD_OR_REFRESH ) { remove_mem_cache = TRUE; - } else - continue; + + } else { /* in case map file already exists */ + switch (mdi->redownload) { + case REDOWNLOAD_NONE: + continue; + + case REDOWNLOAD_BAD: + { + /* see if this one is bad or what */ + GError *gx = NULL; + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx ); + if (gx || (!pixbuf)) { + g_remove ( mdi->filename_buf ); + need_download = TRUE; + remove_mem_cache = TRUE; + g_error_free ( gx ); + + } else { + g_object_unref ( pixbuf ); + } + break; + } + + case REDOWNLOAD_NEW: + need_download = TRUE; + remove_mem_cache = TRUE; + break; + + case REDOWNLOAD_ALL: + /* FIXME: need a better way than to erase file in case of server/network problem */ + g_remove ( mdi->filename_buf ); + need_download = TRUE; + remove_mem_cache = TRUE; + break; + + case DOWNLOAD_OR_REFRESH: + remove_mem_cache = TRUE; + break; + + default: + g_warning ( "redownload state %d unknown\n", mdi->redownload); + } + } mdi->mapcoord.x = x; mdi->mapcoord.y = y; if (need_download) { - if ( vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf )) + if ( vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle)) continue; } @@ -843,6 +1012,7 @@ static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata ) } } + vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle); g_mutex_lock(mdi->mutex); if (mdi->map_layer_alive) g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi); @@ -1027,11 +1197,17 @@ static void maps_layer_redownload_bad ( VikMapsLayer *vml ) { start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD ); } + static void maps_layer_redownload_all ( VikMapsLayer *vml ) { start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL ); } +static void maps_layer_redownload_new ( VikMapsLayer *vml ) +{ + start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW ); +} + static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp ) { if (!vml || vml->vl.type != VIK_LAYER_MAPS) @@ -1060,11 +1236,15 @@ static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton GtkWidget *item; vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () ); - item = gtk_menu_item_new_with_label ( _("Redownload bad map(s)") ); + item = gtk_menu_item_new_with_mnemonic ( _("Redownload _Bad Map(s)") ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml ); gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item ); - item = gtk_menu_item_new_with_label ( _("Redownload all map(s)") ); + item = gtk_menu_item_new_with_mnemonic ( _("Redownload _New Map(s)") ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml ); + gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item ); + + item = gtk_menu_item_new_with_mnemonic ( _("Redownload _All Map(s)") ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml ); gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item ); } @@ -1153,11 +1333,16 @@ static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload ) } -static void maps_layer_download_onscreen_maps ( gpointer vml_vvp[2] ) +static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] ) { download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE); } +static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] ) +{ + download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW); +} + static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] ) { download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL); @@ -1174,13 +1359,23 @@ static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLay gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); - item = gtk_menu_item_new_with_label ( _("Download Onscreen Maps") ); - g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_onscreen_maps), pass_along ); + /* Now with icons */ + item = gtk_image_menu_item_new_with_mnemonic ( _("Download _Missing Onscreen Maps") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along ); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show ( item ); - /* TODO Add GTK_STOCK_REFRESH icon */ - item = gtk_menu_item_new_with_label ( _("Refresh Onscreen Tiles") ); + if ( vik_map_source_supports_download_only_new (MAPS_LAYER_NTH_TYPE(vml->maptype)) ) { + item = gtk_image_menu_item_new_with_mnemonic ( _("Download _New Onscreen Maps") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REDO, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along ); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show ( item ); + } + + item = gtk_image_menu_item_new_with_mnemonic ( _("Reload _All Onscreen Maps") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along ); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show ( item );