]> git.street.me.uk Git - andy/viking.git/commitdiff
Download maps along a track.
authorQuy Tonthat <qtonthat@gmail.com>
Mon, 18 Jun 2007 14:27:12 +0000 (14:27 +0000)
committerQuy Tonthat <qtonthat@gmail.com>
Mon, 18 Jun 2007 14:27:12 +0000 (14:27 +0000)
Maps along a track can now be downloaded by selecting
"Download maps along track..." on the track's context menu.

Problem to be fixed: some maps are missing between far apart trackpoints.

Signed-off-by: Quy Tonthat <qtonthat@gmail.com>
12 files changed:
src/dialog.c
src/dialog.h
src/vikaggregatelayer.c
src/vikaggregatelayer.h
src/vikcoord.c
src/vikcoord.h
src/viklayerspanel.c
src/viklayerspanel.h
src/vikmapslayer.c
src/vikmapslayer.h
src/viktrack.c
src/viktrwlayer.c

index 360a54110e8bcfff1f230945efa12974d9938b30..95b9f3eac4d516735908611706d524c8274acaec 100644 (file)
@@ -611,3 +611,41 @@ void a_dialog_about ( GtkWindow *parent )
   }
   gtk_widget_destroy ( msgbox );
 }
+
+gboolean a_dialog_map_n_zoom(GtkWindow *parent, gchar *mapnames[], gint default_map, gchar *zoom_list[], gint default_zoom, gint *selected_map, gint *selected_zoom)
+{
+  gchar **s;
+
+  GtkWidget *dialog = gtk_dialog_new_with_buttons ( "Download along track", parent, 0, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL );
+
+  GtkWidget *map_label = gtk_label_new("Map type:");
+  GtkWidget *map_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
+  for (s = mapnames; *s; s++)
+    gtk_combo_box_append_text(map_combo, *s);
+  gtk_combo_box_set_active (map_combo, default_map);
+  GtkWidget *zoom_label = gtk_label_new("Zoom level:");
+  GtkWidget *zoom_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
+  for (s = zoom_list; *s; s++)
+    gtk_combo_box_append_text(zoom_combo, *s);
+  gtk_combo_box_set_active (zoom_combo, default_zoom);
+
+  GtkTable *box = GTK_TABLE(gtk_table_new(2, 2, FALSE));
+  gtk_table_attach_defaults(box, GTK_WIDGET(map_label), 0, 1, 0, 1);
+  gtk_table_attach_defaults(box, GTK_WIDGET(map_combo), 1, 2, 0, 1);
+  gtk_table_attach_defaults(box, GTK_WIDGET(zoom_label), 0, 1, 1, 2);
+  gtk_table_attach_defaults(box, GTK_WIDGET(zoom_combo), 1, 2, 1, 2);
+
+  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
+
+  gtk_widget_show_all ( dialog );
+  if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) != GTK_RESPONSE_ACCEPT ) {
+    gtk_widget_destroy(dialog);
+    return FALSE;
+  }
+
+  *selected_map = gtk_combo_box_get_active(map_combo);
+  *selected_zoom = gtk_combo_box_get_active(zoom_combo);
+
+  gtk_widget_destroy(dialog);
+  return TRUE;
+}
index dafce1697f6a614eeddee1f13075e1ced83d31cb..1abc606a6ec7caf063ee2189ea88b84999cde493 100644 (file)
@@ -59,4 +59,5 @@ gboolean a_dialog_time_threshold ( GtkWindow *parent, gchar *title_text, gchar *
 
 void a_dialog_choose_dir ( GtkWidget *entry );
 
+gboolean a_dialog_map_n_zoom(GtkWindow *parent, gchar *mapnames[], gint default_map, gchar *zoom_list[], gint default_zoom, gint *selected_map, gint *selected_zoom);
 #endif
index 4b954b2773c13a79f1bffd77d5f98add55a9ee34..002b60a146cdbbee4b2c67bdbe279bf0c5dc3056 100644 (file)
@@ -400,6 +400,22 @@ VikLayer *vik_aggregate_layer_get_top_visible_layer_of_type ( VikAggregateLayer
   return NULL;
 }
 
+GList *vik_aggregate_layer_get_all_layers_of_type(VikAggregateLayer *val, GList *layers, gint type)
+{
+  GList *l = layers;
+  GList *children = val->children;
+  if (!children)
+    return layers;
+  while (children) {
+    if (VIK_LAYER(children->data)->type == VIK_LAYER_AGGREGATE)
+      l = vik_aggregate_layer_get_all_layers_of_type(VIK_LAYER(children->data), l, type); 
+    else if (VIK_LAYER(children->data)->type == type)
+      l = g_list_prepend(l, children->data); /* now in top down order */
+    children = children->next;
+  }
+  return l;
+}
+
 void vik_aggregate_layer_realize ( VikAggregateLayer *val, VikTreeview *vt, GtkTreeIter *layer_iter )
 {
   GList *i = val->children;
index d62dca45bf099dc64043c1bbcd204f7ad79023f8..935abf22f400a1c06d66c94388426633cf197273 100644 (file)
@@ -61,6 +61,7 @@ gboolean vik_aggregate_layer_load_layers ( VikAggregateLayer *val, FILE *f, gpoi
 gboolean vik_aggregate_layer_is_empty ( VikAggregateLayer *val );
 
 const GList *vik_aggregate_layer_get_children ( VikAggregateLayer *val );
+GList *vik_aggregate_layer_get_all_layers_of_type(VikAggregateLayer *val, GList *layers, gint type);
 
 
 #endif
index a805e4a7764bc173e41428ff12d3436e428243bf..a4bbeadda3ee7175779398c07572acfae3e7e87b 100644 (file)
@@ -115,3 +115,64 @@ gboolean vik_coord_equals ( const VikCoord *coord1, const VikCoord *coord2 )
   else /* VIK_COORD_UTM */
     return coord1->utm_zone == coord2->utm_zone && coord1->north_south == coord2->north_south && coord1->east_west == coord2->east_west;
 }
+
+static void get_north_west(struct LatLon *center, struct LatLon *dist, struct LatLon *nw) 
+{
+  nw->lat = center->lat + dist->lat;
+  nw->lon = center->lon - dist->lon;
+  if (nw->lon < -180)
+    nw->lon += 360.0;
+  if (nw->lat > 90.0) {  /* over north pole */
+    nw->lat = 180 - nw->lat;
+    nw->lon = nw->lon - 180;
+  }
+}
+
+static void get_south_east(struct LatLon *center, struct LatLon *dist, struct LatLon *se) 
+{
+  se->lat = center->lat - dist->lat;
+  se->lon = center->lon + dist->lon;
+  if (se->lon > 180.0)
+    se->lon -= 360.0;
+  if (se->lat < -90.0) {  /* over south pole */
+    se->lat += 180;
+    se->lon = se->lon - 180;
+  }
+}
+
+void vik_coord_set_area(const VikCoord *coord, const struct LatLon *wh, VikCoord *tl, VikCoord *br)
+{
+  struct LatLon center, nw, se;
+  struct LatLon dist;
+
+  dist.lat = wh->lat/2;
+  dist.lon = wh->lon/2;
+
+  vik_coord_to_latlon(coord, &center);
+  get_north_west(&center, &dist, &nw);
+  get_south_east(&center, &dist, &se);
+
+  tl->mode = br->mode = VIK_COORD_LATLON;
+  *((struct LatLon *)tl) = nw;
+  *((struct LatLon *)br) = se;
+}
+
+gboolean vik_coord_inside(const VikCoord *coord, const VikCoord *tl, const VikCoord *br)
+{
+  struct LatLon ll, tl_ll, br_ll;
+
+  vik_coord_to_latlon(coord, &ll);
+  vik_coord_to_latlon(tl, &tl_ll);
+  vik_coord_to_latlon(br, &br_ll);
+
+#ifdef DEBUG
+  fprintf(stderr, "DEBUG: %s() ll=%f, %f tl=%f, %f br=%f, %f\n",
+      __PRETTY_FUNCTION__, ll.lat, ll.lon, tl_ll.lat, tl_ll.lon, br_ll.lat, br_ll.lon);
+#endif
+
+  if ((ll.lat > tl_ll.lat) || (ll.lon < tl_ll.lon))
+    return FALSE;
+  if ((ll.lat  < br_ll.lat) || (ll.lon > br_ll.lon))
+    return FALSE;
+  return TRUE;
+}
index a3d0cf5fe1083bfb8a84d12559d421906d22a282..305e82ee1dcdd06532b7dee7a4354fb3a16ac4bc 100644 (file)
@@ -57,6 +57,8 @@ void vik_coord_to_utm ( const VikCoord *coord, struct UTM *dest );
 
 gboolean vik_coord_equals ( const VikCoord *coord1, const VikCoord *coord2 );
 
+void vik_coord_set_area(const VikCoord *coord, const struct LatLon *wh, VikCoord *tl, VikCoord *br);
+gboolean vik_coord_inside(const VikCoord *coord, const VikCoord *tl, const VikCoord *br);
 /* all coord operations MUST BE ABSTRACTED!!! */
 
 #endif
index 3ce013c3396c189eb36dba36a263d60fc04b189a..11ba08c64aa3cbf08a2c1883850f8455047efae3 100644 (file)
@@ -578,6 +578,13 @@ VikLayer *vik_layers_panel_get_layer_of_type ( VikLayersPanel *vlp, gint type )
     return rv;
 }
 
+GList *vik_layers_panel_get_all_layers_of_type(VikLayersPanel *vlp, gint type)
+{
+  GList *layers = NULL;
+
+  return (vik_aggregate_layer_get_all_layers_of_type ( vlp->toplayer, layers, type ));
+}
+
 VikAggregateLayer *vik_layers_panel_get_top_layer ( VikLayersPanel *vlp )
 {
   return vlp->toplayer;
index 5259524c0ab8f818b0567d42663a8f90eb07b2a0..66a887cdb2a85e61dc29b9fd26605eafe1855eaa 100644 (file)
@@ -69,6 +69,7 @@ gboolean vik_layers_panel_new_layer ( VikLayersPanel *vlp, gint type );
 void vik_layers_panel_clear ( VikLayersPanel *vlp );
 VikAggregateLayer *vik_layers_panel_get_top_layer ( VikLayersPanel *vlp );
 void vik_layers_panel_change_coord_mode ( VikLayersPanel *vlp, VikCoordMode mode );
+GList *vik_layers_panel_get_all_layers_of_type(VikLayersPanel *vlp, gint type);
 
 G_END_DECLS
 
index 54ebfcab6479faf898769eef3458ab037f0f2ea7..d1beed9a443f03ad673ce1637dbf2c16c8819d11 100644 (file)
@@ -224,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 ***************/
 /****************************************/
@@ -690,6 +700,7 @@ typedef struct {
   gint maxlen;
   gint mapstoget;
   gint redownload;
+  gboolean refresh_display;
   VikMapsLayer *vml;
   VikViewport *vvp;
   gboolean map_layer_alive;
@@ -767,7 +778,7 @@ static void map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
       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) {
+      if (mdi->refresh_display && mdi->map_layer_alive) {
         /* TODO: check if it's on visible area */
         vik_layer_emit_update ( VIK_LAYER(mdi->vml) );
       }
@@ -813,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 );
@@ -870,6 +882,74 @@ 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)
+{
+  fprintf(stderr, "DEBUG: downloading ul= %f , %f br= %f , %f\n",
+      ul->north_south, ul->east_west, br->north_south, br->east_west);
+  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 );
index 298d356593743f017b28a5ad1253da810ce02ef0..77d3eff2de817554e7509437e9c6bdbd0b5e6d7b 100644 (file)
@@ -55,5 +55,8 @@ typedef struct {
 } VikMapsLayer_MapType;
 
 void maps_layer_register_type ( const char *label, guint id, VikMapsLayer_MapType *map_type );
+void maps_layer_download_section_without_redraw ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom);
+gint vik_maps_layer_get_map_type(VikMapsLayer *vml);
+gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml);
 
 #endif
index e57a425291885471cf251cd9e517177b3df76730..452901a0adb0d96bf42fce576e33cb75e2c304a3 100644 (file)
@@ -749,4 +749,3 @@ VikTrack *vik_track_unmarshall (guint8 *data, guint datalen)
   }
   return new_tr;
 }
-
index 9e338ad340a7fc3964d0418734cfe6585d7f4a00..ea8da6706ef2aa570017e4b7f15739783eadd926 100644 (file)
@@ -25,6 +25,7 @@
 /* viktrwlayer.c -- 2200 lines can make a difference in the state of things */
 
 #include "viking.h"
+#include "vikmapslayer.h"
 #include "viktrwlayer_pixmap.h"
 #include "viktrwlayer_tpwin.h"
 #include "viktrwlayer_propwin.h"
@@ -184,6 +185,7 @@ static void trw_layer_goto_track_startpoint ( gpointer pass_along[5] );
 static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] );
 static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] );
 static void trw_layer_split_by_timestamp ( gpointer pass_along[6] );
+static void trw_layer_download_map_along_track_cb(gpointer pass_along[6]);
 static void trw_layer_centerize ( gpointer layer_and_vlp[2] );
 static void trw_layer_export ( gpointer layer_and_vlp[2], guint file_type );
 static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] );
@@ -2430,6 +2432,11 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_by_timestamp), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
+
+    item = gtk_menu_item_new_with_label ( "Download maps along track..." );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_download_map_along_track_cb), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+    gtk_widget_show ( item );
   }
 
   if ( vlp && (subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS || subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) )
@@ -3342,3 +3349,147 @@ static guint16 vik_trw_layer_get_menu_selection(VikTrwLayer *vtl)
   return(vtl->menu_selection);
 }
 
+/* ----------- Downloading maps along tracks --------------- */
+
+static int get_download_area_width(VikViewport *vvp, gdouble zoom_level, struct LatLon *wh)
+{
+  /* TODO: calculating based on current size of viewport */
+  const gdouble w_at_zoom_0_125 = 0.0013;
+  const gdouble h_at_zoom_0_125 = 0.0011;
+  gdouble zoom_factor = zoom_level/0.125;
+
+  wh->lat = h_at_zoom_0_125 * zoom_factor;
+  wh->lon = w_at_zoom_0_125 * zoom_factor;
+
+  return 0;   /* all OK */
+}
+
+void vik_track_download_map(VikTrack *tr, VikMapsLayer *vml, VikViewport *vvp, gdouble zoom_level)
+{
+  typedef struct _Rect {
+    VikCoord tl;
+    VikCoord br;
+  } Rect;
+
+  struct LatLon wh;
+  GList *rect_to_download = NULL;
+  GList *rect_iter;
+
+  if (get_download_area_width(vvp, zoom_level, &wh))
+    return;
+
+  GList *iter = tr->trackpoints;
+
+  gboolean new_map = TRUE;
+  VikCoord *cur_coord, tl, br;
+  Rect *rect;
+  /* TODO: handle cases when trackpoints are far apart */
+  while (iter) {
+    cur_coord = &(VIK_TRACKPOINT(iter->data))->coord;
+    if (new_map) {
+      vik_coord_set_area(cur_coord, &wh, &tl, &br);
+      rect = g_malloc(sizeof(Rect));
+      rect->tl = tl;
+      rect->br = br;
+      rect_to_download = g_list_prepend(rect_to_download, rect);
+      new_map = FALSE;
+      iter = iter->next;
+      continue;
+    }
+    gboolean found = FALSE;
+    for (rect_iter = rect_to_download; rect_iter; rect_iter = rect_iter->next) {
+      if (vik_coord_inside(cur_coord, &(((Rect *)(rect_iter->data))->tl), &(((Rect *)(rect_iter->data))->br))) {
+        found = TRUE;
+        break;
+      }
+    }
+    if (found)
+        iter = iter->next;
+    else
+      new_map = TRUE;
+  }
+  for (rect_iter = rect_to_download; rect_iter; rect_iter = rect_iter->next) {
+    maps_layer_download_section_without_redraw(vml, vvp, &(((Rect *)(rect_iter->data))->tl), &(((Rect *)(rect_iter->data))->br), zoom_level);
+  }
+
+  for (rect_iter = rect_to_download; rect_iter; rect_iter = rect_iter->next)
+    g_free(rect_iter->data);
+  g_list_free(rect_to_download);
+}
+
+
+static void trw_layer_download_map_along_track_cb(gpointer pass_along[6])
+{
+  VikMapsLayer *vml;
+  gint selected_map, default_map;
+  gchar *zoomlist[] = {"0.125", "0.25", "0.5", "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", NULL };
+  gdouble zoom_vals[] = {0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
+  gint selected_zoom, default_zoom;
+  int i,j;
+
+
+  VikTrwLayer *vtl = pass_along[0];
+  VikLayersPanel *vlp = pass_along[1];
+  VikTrack *tr = (VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+  VikViewport *vvp = vik_window_viewport((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)));
+
+  GList *vmls = vik_layers_panel_get_all_layers_of_type(vlp, VIK_LAYER_MAPS);
+  int num_maps = g_list_length(vmls);
+
+  if (!num_maps) {
+    a_dialog_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), GTK_MESSAGE_ERROR,"No map layer in use. Create one first", NULL);
+    return;
+  }
+
+  gchar **map_names = g_malloc(1 + num_maps * sizeof(gpointer));
+  VikMapsLayer **map_layers = g_malloc(1 + num_maps * sizeof(gpointer));
+
+  gchar **np = map_names;
+  VikMapsLayer **lp = map_layers;
+  for (i = 0; i < num_maps; i++) {
+    gboolean dup = FALSE;
+    vml = (VikMapsLayer *)(vmls->data);
+    for (j = 0; j < i; j++) { /* no duplicate allowed */
+      if (vik_maps_layer_get_map_type(vml) == vik_maps_layer_get_map_type(map_layers[j])) {
+        dup = TRUE;
+        break;
+      }
+    }
+    if (!dup) {
+      *lp++ = vml;
+      *np++ = vik_maps_layer_get_map_label(vml);
+    }
+    vmls = vmls->next;
+  }
+  *lp = NULL;
+  *np = NULL;
+  num_maps = lp - map_layers;
+
+  for (default_map = 0; default_map < num_maps; default_map++) {
+    /* TODO: check for parent layer's visibility */
+    if (VIK_LAYER(map_layers[default_map])->visible)
+      break;
+  }
+  default_map = (default_map == num_maps) ? 0 : default_map;
+
+  gdouble cur_zoom = vik_viewport_get_zoom(vvp);
+  for (default_zoom = 0; default_zoom < sizeof(zoom_vals)/sizeof(gdouble); default_zoom++) {
+    if (cur_zoom == zoom_vals[default_zoom])
+      break;
+  }
+  default_zoom = (default_zoom == sizeof(zoom_vals)/sizeof(gdouble)) ? sizeof(zoom_vals)/sizeof(gdouble) - 1 : default_zoom;
+
+  if (!a_dialog_map_n_zoom(VIK_GTK_WINDOW_FROM_LAYER(vtl), map_names, default_map, zoomlist, default_zoom, &selected_map, &selected_zoom))
+    goto done;
+
+  vik_track_download_map(tr, map_layers[selected_map], vvp, zoom_vals[selected_zoom]);
+
+done:
+  for (i = 0; i < num_maps; i++)
+    g_free(map_names[i]);
+  g_free(map_names);
+  g_free(map_layers);
+
+  g_list_free(vmls);
+
+}