X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/04e54492f9e946e92bb3709bc3b180a3eed038ed..441f28d396448e94154ef19806a8296a39e68448:/src/vikmapslayer.c diff --git a/src/vikmapslayer.c b/src/vikmapslayer.c index fe097e9e..5c4c73fd 100644 --- a/src/vikmapslayer.c +++ b/src/vikmapslayer.c @@ -173,6 +173,9 @@ struct _VikMapsLayer { gdouble xmapzoom, ymapzoom; gboolean autodownload; + VikCoord *last_center; + gdouble last_xmpp; + gdouble last_ympp; gint dl_tool_x, dl_tool_y; @@ -181,7 +184,7 @@ struct _VikMapsLayer { VikViewport *redownload_vvp; }; -enum { REDOWNLOAD_NONE = 0, REDOWNLOAD_BAD, REDOWNLOAD_ALL }; +enum { REDOWNLOAD_NONE = 0, REDOWNLOAD_BAD, REDOWNLOAD_ALL, DOWNLOAD_OR_REFRESH }; /****************************************/ @@ -221,6 +224,16 @@ void maps_layer_register_type ( const char *label, guint id, VikMapsLayer_MapTyp #define MAPS_LAYER_NTH_ID(n) ((guint)g_list_nth_data(params_maptypes_ids, (n))) #define MAPS_LAYER_NTH_TYPE(n) ((VikMapsLayer_MapType*)g_list_nth_data(__map_types, (n))) +gint vik_maps_layer_get_map_type(VikMapsLayer *vml) +{ + return(vml->maptype); +} + +gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml) +{ + return(g_strdup(MAPS_LAYER_NTH_LABEL(vml->maptype))); +} + /****************************************/ /******** CACHE DIR STUFF ***************/ /****************************************/ @@ -401,6 +414,9 @@ static VikMapsLayer *maps_layer_new ( VikViewport *vvp ) vml->dl_tool_x = vml->dl_tool_y = -1; maps_layer_set_cache_dir ( vml, NULL ); vml->autodownload = FALSE; + vml->last_center = NULL; + vml->last_xmpp = 0.0; + vml->last_ympp = 0.0; vml->dl_right_click_menu = NULL; @@ -413,6 +429,8 @@ static void maps_layer_free ( VikMapsLayer *vml ) g_free ( vml->cache_dir ); if ( vml->dl_right_click_menu ) gtk_object_sink ( GTK_OBJECT(vml->dl_right_click_menu) ); + if (vml->last_center) + g_free(vml->last_center); } static VikMapsLayer *maps_layer_copy ( VikMapsLayer *vml, VikViewport *vvp ) @@ -516,6 +534,31 @@ static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, return pixbuf; } +gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp) +{ + const VikCoord *center = vik_viewport_get_center ( vvp ); + + if (vml->last_center == NULL) { + VikCoord *new_center = g_malloc(sizeof(VikCoord)); + *new_center = *center; + vml->last_center = new_center; + vml->last_xmpp = vik_viewport_get_xmpp(vvp); + vml->last_ympp = vik_viewport_get_ympp(vvp); + return TRUE; + } + + /* TODO: perhaps vik_coord_diff() */ + if (vik_coord_equals(vml->last_center, center) + && (vml->last_xmpp == vik_viewport_get_xmpp(vvp)) + && (vml->last_ympp == vik_viewport_get_ympp(vvp))) + return FALSE; + + *(vml->last_center) = *center; + vml->last_xmpp = vik_viewport_get_xmpp(vvp); + vml->last_ympp = vik_viewport_get_ympp(vvp); + return TRUE; +} + static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br ) { MapCoord ulm, brm; @@ -553,8 +596,10 @@ static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCo guint max_path_len = strlen(vml->cache_dir) + 40; gchar *path_buf = g_malloc ( max_path_len * sizeof(char) ); - if ( vml->autodownload ) + if ( vml->autodownload && should_start_autodownload(vml, vvp)) { + fprintf(stderr, "DEBUG: Starting autodownload\n"); start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE ); + } if ( map_type->tilesize_x == 0 ) { for ( x = xmin; x <= xmax; x++ ) { @@ -655,6 +700,7 @@ typedef struct { gint maxlen; gint mapstoget; gint redownload; + gboolean refresh_display; VikMapsLayer *vml; VikViewport *vvp; gboolean map_layer_alive; @@ -669,8 +715,9 @@ static void mdi_free ( MapDownloadInfo *mdi ) g_free ( mdi ); } -static GWeakNotify weak_ref_cb(MapDownloadInfo *mdi, GObject * dead_vml) +static void weak_ref_cb(gpointer ptr, GObject * dead_vml) { + MapDownloadInfo *mdi = ptr; g_mutex_lock(mdi->mutex); mdi->map_layer_alive = FALSE; g_mutex_unlock(mdi->mutex); @@ -684,14 +731,19 @@ static void map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata ) { for ( y = mdi->y0; y <= mdi->yf; y++ ) { + gboolean remove_mem_cache = FALSE; + gboolean need_download = FALSE; g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE, mdi->cache_dir, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id, mdi->mapcoord.scale, mdi->mapcoord.z, x, y ); + donemaps++; + a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */ + if ( mdi->redownload == REDOWNLOAD_ALL) remove ( mdi->filename_buf ); - else if ( mdi->redownload == REDOWNLOAD_BAD && access ( mdi->filename_buf, F_OK ) == 0 ) + else if ( (mdi->redownload == REDOWNLOAD_BAD) && (access ( mdi->filename_buf, F_OK ) == 0) ) { /* see if this one is bad or what */ GError *gx = NULL; @@ -706,31 +758,39 @@ static void map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata ) if ( access ( mdi->filename_buf, F_OK ) != 0 ) { - mdi->mapcoord.x = x; mdi->mapcoord.y = y; - MAPS_LAYER_NTH_TYPE(mdi->maptype)->download ( &(mdi->mapcoord), mdi->filename_buf ); - gdk_threads_enter(); - g_mutex_lock(mdi->mutex); + 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; + + mdi->mapcoord.x = x; mdi->mapcoord.y = y; + + if (need_download) { + if ( MAPS_LAYER_NTH_TYPE(mdi->maptype)->download ( &(mdi->mapcoord), mdi->filename_buf )) + continue; + } - /* remove from memory cache */ - if ( mdi->redownload != REDOWNLOAD_NONE ) + gdk_threads_enter(); + g_mutex_lock(mdi->mutex); + if (remove_mem_cache) a_mapcache_remove_all_shrinkfactors ( x, y, mdi->mapcoord.z, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id, mdi->mapcoord.scale ); - - if (mdi->map_layer_alive) { - /* TODO: check if it's on visible area */ - vik_layer_emit_update ( VIK_LAYER(mdi->vml) ); - } - g_mutex_unlock(mdi->mutex); - gdk_threads_leave(); - mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */ - - donemaps++; - a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */ + if (mdi->refresh_display && mdi->map_layer_alive) { + /* TODO: check if it's on visible area */ + vik_layer_emit_update ( VIK_LAYER(mdi->vml) ); } + g_mutex_unlock(mdi->mutex); + gdk_threads_leave(); + mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */ + } } g_mutex_lock(mdi->mutex); if (mdi->map_layer_alive) - g_object_weak_unref(VIK_LAYER(mdi->vml), weak_ref_cb, mdi); + g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi); g_mutex_unlock(mdi->mutex); } @@ -764,6 +824,7 @@ static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const V mdi->vvp = vvp; mdi->map_layer_alive = TRUE; mdi->mutex = g_mutex_new(); + mdi->refresh_display = TRUE; /* cache_dir and buffer for dest filename */ mdi->cache_dir = g_strdup ( vml->cache_dir ); @@ -805,7 +866,7 @@ static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const V { gchar *tmp = g_strdup_printf ( "%s %s%d %s %s...", redownload ? "Redownloading" : "Downloading", redownload == REDOWNLOAD_BAD ? "up to " : "", mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype), (mdi->mapstoget == 1) ? "map" : "maps" ); - g_object_weak_ref(VIK_LAYER(mdi->vml), weak_ref_cb, mdi); + g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi); /* launch the thread */ a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */ tmp, /* description string */ @@ -821,6 +882,72 @@ static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const V } } +void maps_layer_download_section_without_redraw( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom) +{ + MapCoord ulm, brm; + VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype); + + if (!map_type->coord_to_mapcoord(ul, zoom, zoom, &ulm) + || !map_type->coord_to_mapcoord(br, zoom, zoom, &brm)) { + fprintf(stderr, "%s() coord_to_mapcoord() failed\n", __PRETTY_FUNCTION__); + return; + } + + MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo)); + gint i, j; + + mdi->vml = vml; + mdi->vvp = vvp; + mdi->map_layer_alive = TRUE; + mdi->mutex = g_mutex_new(); + mdi->refresh_display = FALSE; + + mdi->cache_dir = g_strdup ( vml->cache_dir ); + mdi->maxlen = strlen ( vml->cache_dir ) + 40; + mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) ); + mdi->maptype = vml->maptype; + + mdi->mapcoord = ulm; + + mdi->redownload = REDOWNLOAD_NONE; + + mdi->x0 = MIN(ulm.x, brm.x); + mdi->xf = MAX(ulm.x, brm.x); + mdi->y0 = MIN(ulm.y, brm.y); + mdi->yf = MAX(ulm.y, brm.y); + + mdi->mapstoget = 0; + + for (i = mdi->x0; i <= mdi->xf; i++) { + for (j = mdi->y0; j <= mdi->yf; j++) { + g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE, + vml->cache_dir, map_type->uniq_id, ulm.scale, + ulm.z, i, j ); + if ( access ( mdi->filename_buf, F_OK ) != 0) + mdi->mapstoget++; + } + } + + mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */ + + if (mdi->mapstoget) { + gchar *tmp = g_strdup_printf ( "%s %d %s %s...", "Downloading", mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype), (mdi->mapstoget == 1) ? "map" : "maps" ); + + g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi); + /* launch the thread */ + a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */ + tmp, /* description string */ + (vik_thr_func) map_download_thread, /* function to call within thread */ + mdi, /* pass along data */ + (vik_thr_free_func) mdi_free, /* function to free pass along data */ + (vik_thr_free_func) mdi_cancel_cleanup, + mdi->mapstoget ); + g_free ( tmp ); + } + else + mdi_free ( mdi ); +} + static void maps_layer_redownload_bad ( VikMapsLayer *vml ) { start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD ); @@ -841,7 +968,7 @@ static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton VikCoord ul, br; 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 ); 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 ); - start_download_thread ( vml, vvp, &ul, &br, REDOWNLOAD_NONE ); + start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH ); vml->dl_tool_x = vml->dl_tool_y = -1; return TRUE; }