]> git.street.me.uk Git - andy/viking.git/blobdiff - src/vikmapslayer.c
ChangeLog entry
[andy/viking.git] / src / vikmapslayer.c
index fe097e9e8641714ce1e957d66249c5d9fcb1332f..5c4c73fd4c8e9bfa829843e1b5c026dc6d0a21c0 100644 (file)
@@ -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;
     }