]> git.street.me.uk Git - andy/viking.git/blobdiff - src/viktrwlayer.c
Using the new icon
[andy/viking.git] / src / viktrwlayer.c
index e9435553432d925820948399a59b7b485959efb3..b3d0e1d0cbc7586b76d15931d1e5114d9acf1c90 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"
 #include "thumbnails.h"
 #include "background.h"
 #include "gpx.h"
+#include "babel.h"
 
 #include <math.h>
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
 
+#define GOOGLE_DIRECTIONS_STRING "(wget -O - \"http://maps.google.com/maps?q=%f,%f to %f,%f&output=js\" 2>/dev/null)"
 #define VIK_TRW_LAYER_TRACK_GC 13
 #define VIK_TRW_LAYER_TRACK_GC_RATES 10
 #define VIK_TRW_LAYER_TRACK_GC_MIN 0
@@ -121,6 +124,10 @@ struct _VikTrwLayer {
   /* track editing tool -- more specifically, moving tps */
   gboolean moving_tp;
 
+  /* magic scissors tool */
+  gboolean magic_scissors_started;
+  VikCoord magic_scissors_coord;
+
   gboolean drawlabels;
   gboolean drawimages;
   guint8 image_alpha;
@@ -135,6 +142,9 @@ struct _VikTrwLayer {
 
   GtkMenu *wp_right_click_menu;
 
+  /* menu */
+  VikStdLayerMenuItem menu_selection;
+
 };
 
 /* A caached waypoint image. */
@@ -154,7 +164,12 @@ struct DrawingParams {
   gdouble ce1, ce2, cn1, cn2;
 };
 
+static void vik_trw_layer_set_menu_selection(VikTrwLayer *vtl, guint16);
+static guint16 vik_trw_layer_get_menu_selection(VikTrwLayer *vtl);
+
 static void trw_layer_delete_item ( gpointer *pass_along );
+static void trw_layer_copy_item_cb( gpointer *pass_along);
+static void trw_layer_cut_item_cb( gpointer *pass_along);
 
 static void trw_layer_find_maxmin_waypoints ( const gchar *name, const VikWaypoint *w, struct LatLon maxmin[2] );
 static void trw_layer_find_maxmin_tracks ( const gchar *name, GList **t, struct LatLon maxmin[2] );    
@@ -171,6 +186,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] );
@@ -219,6 +235,9 @@ static gpointer tool_new_track_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); 
 static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_new_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
+static gpointer tool_magic_scissors_create ( VikWindow *vw, VikViewport *vvp);
+static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
+
 
 static gboolean uppercase_exists_in_hash ( GHashTable *hash, const gchar *str );
 
@@ -254,6 +273,9 @@ static VikToolInterface trw_layer_tools[] = {
 
   { "Show Picture",    (VikToolConstructorFunc) tool_show_picture_create,    NULL, NULL, NULL, 
     (VikToolMouseFunc) tool_show_picture_click,    NULL, NULL },
+
+  { "Magic Scissors",  (VikToolConstructorFunc) tool_magic_scissors_create,  NULL, NULL, NULL,
+    (VikToolMouseFunc) tool_magic_scissors_click, NULL, NULL },
 };
 
 /****** PARAMETERS ******/
@@ -284,7 +306,7 @@ VikLayerParam trw_layer_params[] = {
   { "tracks_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES },
   { "waypoints_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES },
 
-  { "drawmode", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, "Track Drawing Mode:", VIK_LAYER_WIDGET_RADIOGROUP, params_drawmodes },
+  { "drawmode", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, "Track Drawing Mode:", VIK_LAYER_WIDGET_RADIOGROUP, NULL },
   { "drawlines", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, "Draw Track Lines", VIK_LAYER_WIDGET_CHECKBUTTON },
   { "drawpoints", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, "Draw Trackpoints", VIK_LAYER_WIDGET_CHECKBUTTON },
   { "drawelevation", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, "Draw Elevation", VIK_LAYER_WIDGET_CHECKBUTTON },
@@ -304,7 +326,7 @@ VikLayerParam trw_layer_params[] = {
   { "wptextcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, "Waypoint Text:", VIK_LAYER_WIDGET_COLOR, 0 },
   { "wpbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, "Background:", VIK_LAYER_WIDGET_COLOR, 0 },
   { "wpbgand", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, "Fake BG Color Translucency:", VIK_LAYER_WIDGET_CHECKBUTTON, 0 },
-  { "wpsymbol", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, "Waypoint marker:", VIK_LAYER_WIDGET_RADIOGROUP, params_wpsymbols },
+  { "wpsymbol", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, "Waypoint marker:", VIK_LAYER_WIDGET_RADIOGROUP, NULL },
   { "wpsize", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, "Waypoint size:", VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 7 },
   { "wpsyms", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, "Draw Waypoint Symbols:", VIK_LAYER_WIDGET_CHECKBUTTON },
 
@@ -341,6 +363,9 @@ VikLayerInterface vik_trw_layer_interface = {
   (VikLayerFuncDraw)                    vik_trw_layer_draw,
   (VikLayerFuncChangeCoordMode)         trw_layer_change_coord_mode,
 
+  (VikLayerFuncSetMenuItemsSelection)   vik_trw_layer_set_menu_selection,
+  (VikLayerFuncGetMenuItemsSelection)   vik_trw_layer_get_menu_selection,
+
   (VikLayerFuncAddMenuItems)            vik_trw_layer_add_menu_items,
   (VikLayerFuncSublayerAddMenuItems)    vik_trw_layer_sublayer_add_menu_items,
 
@@ -413,12 +438,35 @@ static void trw_layer_del_item ( VikTrwLayer *vtl, gint subtype, gpointer sublay
   trw_layer_delete_item ( pass_along );
 }
 
+static void trw_layer_copy_item_cb( gpointer pass_along[5])
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
+  gint subtype = (gint)pass_along[2];
+  gpointer * sublayer = pass_along[3];
+  guint8 *data = NULL;
+  guint len;
+
+  trw_layer_copy_item( vtl, subtype, sublayer, &data, &len);
+
+  if (data) {
+    a_clipboard_copy( VIK_CLIPBOARD_DATA_SUBLAYER, VIK_LAYER_TRW,
+       subtype, len, data);
+  }
+}
+
+static void trw_layer_cut_item_cb( gpointer pass_along[5])
+{
+  trw_layer_copy_item_cb(pass_along);
+  trw_layer_delete_item(pass_along);
+}
+
 static void trw_layer_copy_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer, guint8 **item, guint *len )
 {
   FlatItem *fi;
   guint8 *id;
   guint il;
 
+  fprintf(stderr, "%s:%s() called\n", __FILE__, __PRETTY_FUNCTION__);
   if (!sublayer) {
     *item = NULL;
     return;
@@ -683,8 +731,22 @@ static VikTrwLayer *trw_layer_copy ( VikTrwLayer *vtl, gpointer vp )
   return rv;
 }
 
+static GList * a_array_to_glist(gpointer data[])
+{
+  GList *gl = NULL;
+  gpointer * p;
+  for (p = data; *p; p++)
+    gl = g_list_prepend(gl, *p);
+  return(g_list_reverse(gl));
+}
+
 VikTrwLayer *vik_trw_layer_new ( gint drawmode )
 {
+  if (trw_layer_params[PARAM_DM].widget_data == NULL)
+    trw_layer_params[PARAM_DM].widget_data = a_array_to_glist(params_drawmodes);
+  if (trw_layer_params[PARAM_WPSYM].widget_data == NULL)
+    trw_layer_params[PARAM_WPSYM].widget_data = a_array_to_glist(params_wpsymbols);
+
   VikTrwLayer *rv = VIK_TRW_LAYER ( g_object_new ( VIK_TRW_LAYER_TYPE, NULL ) );
   vik_layer_init ( VIK_LAYER(rv), VIK_LAYER_TRW );
 
@@ -719,6 +781,9 @@ VikTrwLayer *vik_trw_layer_new ( gint drawmode )
   rv->current_tp_track_name = NULL;
   rv->moving_tp = FALSE;
   rv->moving_wp = FALSE;
+
+  rv->magic_scissors_started = FALSE;
+
   rv->waypoint_rightclick = FALSE;
   rv->last_tpl = NULL;
   rv->last_tp_track_name = NULL;
@@ -1223,6 +1288,8 @@ VikTrwLayer *vik_trw_layer_create ( VikViewport *vp )
 
   rv->coord_mode = vik_viewport_get_coord_mode ( vp );
 
+  rv->menu_selection = vik_layer_get_interface(VIK_LAYER(rv)->type)->menu_items_selection;
+
   return rv;
 }
 
@@ -1760,6 +1827,42 @@ gboolean vik_trw_layer_delete_waypoint ( VikTrwLayer *vtl, const gchar *wp_name
   return was_visible;
 }
 
+static void remove_item_from_treeview(const gchar *name, GtkTreeIter *it, VikTreeview * vt)
+{
+    vik_treeview_item_delete (vt, it );
+}
+
+void vik_trw_layer_delete_all_tracks ( VikTrwLayer *vtl )
+{
+
+  vtl->current_track = NULL;
+  if (vtl->current_tp_track_name)
+    trw_layer_cancel_current_tp(vtl, FALSE);
+  if (vtl->last_tp_track_name)
+    trw_layer_cancel_last_tp ( vtl );
+
+  g_hash_table_foreach(vtl->tracks_iters, (GHFunc) remove_item_from_treeview, VIK_LAYER(vtl)->vt);
+  g_hash_table_remove_all(vtl->tracks_iters);
+  g_hash_table_remove_all(vtl->tracks);
+
+  /* TODO: only update if the layer is visible (ticked) */
+  vik_layer_emit_update ( VIK_LAYER(vtl) );
+}
+
+void vik_trw_layer_delete_all_waypoints ( VikTrwLayer *vtl )
+{
+  vtl->current_wp = NULL;
+  vtl->current_wp_name = NULL;
+  vtl->moving_wp = FALSE;
+
+  g_hash_table_foreach(vtl->waypoints_iters, (GHFunc) remove_item_from_treeview, VIK_LAYER(vtl)->vt);
+  g_hash_table_remove_all(vtl->waypoints_iters);
+  g_hash_table_remove_all(vtl->waypoints);
+
+  /* TODO: only update if the layer is visible (ticked) */
+  vik_layer_emit_update ( VIK_LAYER(vtl) );
+}
+
 static void trw_layer_delete_item ( gpointer pass_along[5] )
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
@@ -2264,6 +2367,16 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
 
+    item = gtk_image_menu_item_new_from_stock ( GTK_STOCK_CUT, NULL );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_cut_item_cb), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+    gtk_widget_show ( item );
+
+    item = gtk_image_menu_item_new_from_stock ( GTK_STOCK_COPY, NULL );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_copy_item_cb), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+    gtk_widget_show ( item );
+
     item = gtk_image_menu_item_new_from_stock ( GTK_STOCK_DELETE, NULL );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_item), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
@@ -2320,6 +2433,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) )
@@ -2674,8 +2792,8 @@ static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *eve
     gint x, y;
     vik_viewport_coord_to_screen ( vvp, &(vtl->current_wp->coord), &x, &y );
 
-    if ( abs(x - event->x) < WAYPOINT_SIZE_APPROX &&
-         abs(y - event->y) < WAYPOINT_SIZE_APPROX )
+    if ( abs(x - event->x) <= WAYPOINT_SIZE_APPROX &&
+         abs(y - event->y) <= WAYPOINT_SIZE_APPROX )
     {
       if ( event->button == 3 )
         vtl->waypoint_rightclick = TRUE; /* remember that we're clicking; other layers will ignore release signal */
@@ -2992,7 +3110,6 @@ static gboolean tool_edit_trackpoint_move ( VikTrwLayer *vtl, GdkEventButton *ev
   if ( t->holding )
   {
     VikCoord new_coord;
-    GdkGC *gc;
     vik_viewport_screen_to_coord ( vvp, event->x, event->y, &new_coord );
 
     /* snap to TP */
@@ -3052,6 +3169,32 @@ static gboolean tool_edit_trackpoint_release ( VikTrwLayer *vtl, GdkEventButton
 }
 
 
+/*** Magic Scissors ***/
+static gpointer tool_magic_scissors_create ( VikWindow *vw, VikViewport *vvp)
+{
+  return vvp;
+}
+
+static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+{
+  VikCoord tmp;
+  vik_viewport_screen_to_coord ( vvp, event->x, event->y, &tmp );
+  if ( vtl->magic_scissors_started ) {
+    struct LatLon start, end;
+    gchar *cmd;
+    vik_coord_to_latlon ( &(vtl->magic_scissors_coord), &start );
+    vik_coord_to_latlon ( &(tmp), &end );
+    cmd = g_strdup_printf(GOOGLE_DIRECTIONS_STRING, start.lat, start.lon, end.lat, end.lon );
+    a_babel_convert_from_shellcommand ( vtl, cmd, "google", NULL, NULL );
+    g_free ( cmd );
+    vik_layer_emit_update ( VIK_LAYER(vtl) );
+  } else {
+    vtl->magic_scissors_coord = tmp;
+  }
+  vtl->magic_scissors_started = !vtl->magic_scissors_started;
+  return TRUE;
+}
+
 /*** Show picture ****/
 
 static gpointer tool_show_picture_create ( VikWindow *vw, VikViewport *vvp)
@@ -3195,3 +3338,236 @@ VikTrack *vik_trw_layer_get_track ( VikTrwLayer *vtl, gchar *name )
 {
   return g_hash_table_lookup ( vtl->tracks, name );
 }
+
+static void vik_trw_layer_set_menu_selection(VikTrwLayer *vtl, guint16 selection)
+{
+  vtl->menu_selection = selection;
+}
+
+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 */
+}
+
+static VikCoord *get_next_coord(VikCoord *from, VikCoord *to, struct LatLon *dist, gdouble gradient)
+{
+  if ((dist->lon >= ABS(to->east_west - from->east_west)) &&
+      (dist->lat >= ABS(to->north_south - from->north_south)))
+    return NULL;
+
+  VikCoord *coord = g_malloc(sizeof(VikCoord));
+  coord->mode = VIK_COORD_LATLON;
+
+  if (ABS(gradient) < 1) {
+    if (from->east_west > to->east_west)
+      coord->east_west = from->east_west - dist->lon;
+    else
+      coord->east_west = from->east_west + dist->lon;
+    coord->north_south = gradient * (coord->east_west - from->east_west) + from->north_south;
+  } else {
+    if (from->north_south > to->north_south)
+      coord->north_south = from->north_south - dist->lat;
+    else
+      coord->north_south = from->north_south + dist->lat;
+    coord->east_west = (1/gradient) * (coord->north_south - from->north_south) + from->north_south;
+  }
+
+  return coord;
+}
+
+static GList *add_fillins(GList *list, VikCoord *from, VikCoord *to, struct LatLon *dist)
+{
+  /* TODO: handle virtical track (to->east_west - from->east_west == 0) */
+  gdouble gradient = (to->north_south - from->north_south)/(to->east_west - from->east_west);
+
+  VikCoord *next = from;
+  while (TRUE) {
+    if ((next = get_next_coord(next, to, dist, gradient)) == NULL)
+        break;
+    list = g_list_prepend(list, next);
+  }
+
+  return list;
+}
+
+void vik_track_download_map(VikTrack *tr, VikMapsLayer *vml, VikViewport *vvp, gdouble zoom_level)
+{
+  typedef struct _Rect {
+    VikCoord tl;
+    VikCoord br;
+    VikCoord center;
+  } Rect;
+#define GLRECT(iter) ((Rect *)((iter)->data))
+
+  struct LatLon wh;
+  GList *rects_to_download = NULL;
+  GList *rect_iter;
+
+  if (get_download_area_width(vvp, zoom_level, &wh))
+    return;
+
+  GList *iter = tr->trackpoints;
+  if (!iter)
+    return;
+
+  gboolean new_map = TRUE;
+  VikCoord *cur_coord, tl, br;
+  Rect *rect;
+  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->center = *cur_coord;
+      rects_to_download = g_list_prepend(rects_to_download, rect);
+      new_map = FALSE;
+      iter = iter->next;
+      continue;
+    }
+    gboolean found = FALSE;
+    for (rect_iter = rects_to_download; rect_iter; rect_iter = rect_iter->next) {
+      if (vik_coord_inside(cur_coord, &GLRECT(rect_iter)->tl, &GLRECT(rect_iter)->br)) {
+        found = TRUE;
+        break;
+      }
+    }
+    if (found)
+        iter = iter->next;
+    else
+      new_map = TRUE;
+  }
+
+  /* fill-ins for far apart points */
+  GList *cur_rect, *next_rect;
+  GList *fillins = NULL;
+  for (cur_rect = rects_to_download;
+      (next_rect = cur_rect->next) != NULL;
+      cur_rect = cur_rect->next) {
+    if ((wh.lon < ABS(GLRECT(cur_rect)->center.east_west - GLRECT(next_rect)->center.east_west)) ||
+        (wh.lat < ABS(GLRECT(cur_rect)->center.north_south - GLRECT(next_rect)->center.north_south))) {
+      fillins = add_fillins(fillins, &GLRECT(cur_rect)->center, &GLRECT(next_rect)->center, &wh);
+    }
+  }
+
+  if (fillins) {
+    GList *iter = fillins;
+    while (iter) {
+      cur_coord = (VikCoord *)(iter->data);
+      vik_coord_set_area(cur_coord, &wh, &tl, &br);
+      rect = g_malloc(sizeof(Rect));
+      rect->tl = tl;
+      rect->br = br;
+      rect->center = *cur_coord;
+      rects_to_download = g_list_prepend(rects_to_download, rect);
+      iter = iter->next;
+    }
+  }
+
+  for (rect_iter = rects_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);
+  }
+
+  if (fillins) {
+    for (iter = fillins; iter; iter = iter->next)
+      g_free(iter->data);
+    g_list_free(fillins);
+  }
+  if (rects_to_download) {
+    for (rect_iter = rects_to_download; rect_iter; rect_iter = rect_iter->next)
+      g_free(rect_iter->data);
+    g_list_free(rects_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);
+
+}