]> git.street.me.uk Git - andy/viking.git/blobdiff - src/vikwindow.c
[DOC] Mention map tilesize configuration.
[andy/viking.git] / src / vikwindow.c
index 4147ce255b6903fb12d6240a8edb94e982ed8787..3ebda9d822d6eae253e884df89f0e453dbb688d7 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
  * Copyright (C) 2005-2006, Alex Foobarian <foobarian@gmail.com>
- * Copyright (C) 2012-2014, Rob Norris <rw_norris@hotmail.com>
+ * Copyright (C) 2012-2015, Rob Norris <rw_norris@hotmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include "vikexttool_datasources.h"
 #include "garminsymbols.h"
 #include "vikmapslayer.h"
+#include "vikrouting.h"
 #include "geonamessearch.h"
-#include "vikutils.h"
 #include "dir.h"
+#include "kmz.h"
 
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
@@ -329,6 +330,7 @@ void vik_window_statusbar_update ( VikWindow *vw, const gchar* message, vik_stat
 static void destroy_window ( GtkWidget *widget,
                              gpointer   data )
 {
+    g_debug ( "%s", __FUNCTION__ );
     if ( ! --window_count ) {
       g_free ( last_folder_files_uri );
       g_free ( last_folder_images_uri );
@@ -350,6 +352,10 @@ VikWindow *vik_window_new_window ()
   {
     VikWindow *vw = window_new ();
 
+    if ( window_count == 0 ) {
+       vik_window_statusbar_update ( vw, _("This is Viking "VIKING_VERSION), VIK_STATUSBAR_INFO );
+    }
+
     g_signal_connect (G_OBJECT (vw), "destroy",
                      G_CALLBACK (destroy_window), NULL);
     g_signal_connect (G_OBJECT (vw), "newwindow",
@@ -462,12 +468,6 @@ void vik_window_new_window_finish ( VikWindow *vw )
   if ( vw->filename )
     return;
 
-  if ( a_vik_get_startup_method ( ) == VIK_STARTUP_METHOD_SPECIFIED_FILE ) {
-    vik_window_open_file ( vw, a_vik_get_startup_file(), TRUE );
-    if ( vw->filename )
-      return;
-  }
-
   // Maybe add a default map layer
   if ( a_vik_get_add_default_map_layer () ) {
     VikMapsLayer *vml = VIK_MAPS_LAYER ( vik_layer_create(VIK_LAYER_MAPS, vw->viking_vvp, FALSE) );
@@ -497,12 +497,14 @@ void vik_window_new_window_finish ( VikWindow *vw )
 
 static void open_window ( VikWindow *vw, GSList *files )
 {
+  if ( !vw  )
+    return;
   gboolean change_fn = (g_slist_length(files) == 1); /* only change fn if one file */
   GSList *cur_file = files;
   while ( cur_file ) {
     // Only open a new window if a viking file
     gchar *file_name = cur_file->data;
-    if (vw != NULL && vw->filename && check_file_magic_vik ( file_name ) ) {
+    if (vw->filename && check_file_magic_vik ( file_name ) ) {
       VikWindow *newvw = vik_window_new_window ();
       if (newvw)
         vik_window_open_file ( newvw, file_name, TRUE );
@@ -1202,11 +1204,9 @@ gboolean draw_buf_done = TRUE;
 static gboolean draw_buf(gpointer data)
 {
   gpointer *pass_along = data;
-  gdk_threads_enter();
   gdk_draw_drawable (pass_along[0], pass_along[1],
                     pass_along[2], 0, 0, 0, 0, -1, -1);
   draw_buf_done = TRUE;
-  gdk_threads_leave();
   return FALSE;
 }
 
@@ -2729,7 +2729,7 @@ static void view_main_menu_cb ( GtkAction *a, VikWindow *vw )
       toggle_main_menu ( vw );
   }
   else
-    toggle_toolbar ( vw );
+    toggle_main_menu ( vw );
 }
 
 /***************************************
@@ -2804,8 +2804,7 @@ static const GdkCursor *toolbox_get_cursor(toolbox_tools_t *vt, const gchar *too
   toolbox_tool_t *t = &vt->tools[tool];
   if (t->ti.cursor == NULL) {
     if (t->ti.cursor_type == GDK_CURSOR_IS_PIXMAP && t->ti.cursor_data != NULL) {
-      GError *cursor_load_err = NULL;
-      GdkPixbuf *cursor_pixbuf = gdk_pixbuf_from_pixdata (t->ti.cursor_data, FALSE, &cursor_load_err);
+      GdkPixbuf *cursor_pixbuf = gdk_pixbuf_from_pixdata (t->ti.cursor_data, FALSE, NULL);
       /* TODO: settable offeset */
       t->ti.cursor = gdk_cursor_new_from_pixbuf ( gdk_display_get_default(), cursor_pixbuf, 3, 3 );
       g_object_unref ( G_OBJECT(cursor_pixbuf) );
@@ -2970,6 +2969,22 @@ gboolean vik_window_get_pan_move ( VikWindow *vw )
   return vw->pan_move;
 }
 
+/**
+ * Remove the potentially auto added map
+ */
+static void remove_default_map_layer ( VikWindow *vw )
+{
+  if ( a_vik_get_add_default_map_layer () ) {
+    VikAggregateLayer *top = vik_layers_panel_get_top_layer(vw->viking_vlp);
+    if ( vik_aggregate_layer_count(top) == 1 ) {
+      VikLayer *vl = vik_aggregate_layer_get_top_visible_layer_of_type (top, VIK_LAYER_MAPS);
+      // Could try to compare name vs _("Default Map") but this might have i8n issues if not translated
+      if ( vl )
+        vik_aggregate_layer_delete_layer ( top, vl );
+    }
+  }
+}
+
 static void on_activate_recent_item (GtkRecentChooser *chooser,
                                      VikWindow *self)
 {
@@ -2989,6 +3004,7 @@ static void on_activate_recent_item (GtkRecentChooser *chooser,
       // NB: GSList & contents are freed by main.open_window
     }
     else {
+      remove_default_map_layer ( self );
       vik_window_open_file ( self, path, TRUE );
       g_free ( path );
     }
@@ -3086,8 +3102,7 @@ void vik_window_open_file ( VikWindow *vw, const gchar *filename, gboolean chang
   vw->filename = g_strdup ( filename );
   gboolean success = FALSE;
   gboolean restore_original_filename = FALSE;
-
-  vw->loaded_type = a_file_load ( vik_layers_panel_get_top_layer(vw->viking_vlp), vw->viking_vvp, filename );
+  vw->loaded_type = a_file_load ( vik_layers_panel_get_top_layer(vw->viking_vlp), vw->viking_vvp, vw->containing_vtl, filename );
   switch ( vw->loaded_type )
   {
     case LOAD_TYPE_READ_FAILURE:
@@ -3261,6 +3276,7 @@ static void load_file ( GtkAction *a, VikWindow *vw )
         if ( newwindow && check_file_magic_vik ( file_name ) ) {
           // Load first of many .vik files in current window
           if ( first_vik_file ) {
+            remove_default_map_layer ( vw );
             vik_window_open_file ( vw, file_name, TRUE );
             first_vik_file = FALSE;
           }
@@ -3488,10 +3504,6 @@ static void export_to_kml ( GtkAction *a, VikWindow *vw )
   export_to_common ( vw, FILE_TYPE_KML, ".kml" );
 }
 
-#if !GLIB_CHECK_VERSION(2,26,0)
-typedef struct stat GStatBuf;
-#endif
-
 static void file_properties_cb ( GtkAction *a, VikWindow *vw )
 {
   gchar *message = NULL;
@@ -3707,7 +3719,7 @@ static void default_location_cb ( GtkAction *a, VikWindow *vw )
     { VIK_LAYER_NUM_TYPES,
       VIKING_PREFERENCES_NAMESPACE "default_latitude",
       VIK_LAYER_PARAM_DOUBLE,
-      VIK_LOCATION_LAT,
+      VIK_LAYER_GROUP_NONE,
       NULL,
       VIK_LAYER_WIDGET_SPINBUTTON,
       NULL,
@@ -3722,7 +3734,7 @@ static void default_location_cb ( GtkAction *a, VikWindow *vw )
     { VIK_LAYER_NUM_TYPES,
       VIKING_PREFERENCES_NAMESPACE "default_longitude",
       VIK_LAYER_PARAM_DOUBLE,
-      VIK_LOCATION_LONG,
+      VIK_LAYER_GROUP_NONE,
       NULL,
       VIK_LAYER_WIDGET_SPINBUTTON,
       NULL,
@@ -3748,11 +3760,20 @@ static void default_location_cb ( GtkAction *a, VikWindow *vw )
   a_preferences_save_to_file();
 }
 
+/**
+ * Delete All
+ */
 static void clear_cb ( GtkAction *a, VikWindow *vw )
 {
-  vik_layers_panel_clear ( vw->viking_vlp );
-  window_set_filename ( vw, NULL );
-  draw_update ( vw );
+  // Do nothing if empty
+  VikAggregateLayer *top = vik_layers_panel_get_top_layer(vw->viking_vlp);
+  if ( ! vik_aggregate_layer_is_empty(top) ) {
+    if ( a_dialog_yes_or_no ( GTK_WINDOW(vw), _("Are you sure you wish to delete all layers?"), NULL ) ) {
+      vik_layers_panel_clear ( vw->viking_vlp );
+      window_set_filename ( vw, NULL );
+      draw_update ( vw );
+    }
+  }
 }
 
 static void window_close ( GtkAction *a, VikWindow *vw )
@@ -3782,7 +3803,7 @@ static void zoom_to_cb ( GtkAction *a, VikWindow *vw )
   }
 }
 
-static void save_image_file ( VikWindow *vw, const gchar *fn, guint w, guint h, gdouble zoom, gboolean save_as_png )
+static void save_image_file ( VikWindow *vw, const gchar *fn, guint w, guint h, gdouble zoom, gboolean save_as_png, gboolean save_kmz )
 {
   /* more efficient way: stuff draws directly to pixbuf (fork viewport) */
   GdkPixbuf *pixbuf_to_save;
@@ -3825,17 +3846,27 @@ static void save_image_file ( VikWindow *vw, const gchar *fn, guint w, guint h,
     goto cleanup;
   }
 
-  gdk_pixbuf_save ( pixbuf_to_save, fn, save_as_png ? "png" : "jpeg", &error, NULL );
-  if (error)
-  {
-    g_warning("Unable to write to file %s: %s", fn, error->message );
-    gtk_message_dialog_set_markup ( GTK_MESSAGE_DIALOG(msgbox), _("Failed to generate image file.") );
-    g_error_free (error);
+  int ans = 0; // Default to success
+
+  if ( save_kmz ) {
+    gdouble north, east, south, west;
+    vik_viewport_get_min_max_lat_lon ( vw->viking_vvp, &south, &north, &west, &east );
+    ans = kmz_save_file ( pixbuf_to_save, fn, north, east, south, west );
   }
   else {
-    // Success
-    gtk_message_dialog_set_markup ( GTK_MESSAGE_DIALOG(msgbox), _("Image file generated.") );
+    gdk_pixbuf_save ( pixbuf_to_save, fn, save_as_png ? "png" : "jpeg", &error, NULL );
+    if (error) {
+      g_warning("Unable to write to file %s: %s", fn, error->message );
+      g_error_free (error);
+      ans = 42;
+    }
   }
+
+  if ( ans == 0 )
+    gtk_message_dialog_set_markup ( GTK_MESSAGE_DIALOG(msgbox), _("Image file generated.") );
+  else
+    gtk_message_dialog_set_markup ( GTK_MESSAGE_DIALOG(msgbox), _("Failed to generate image file.") );
+
   g_object_unref ( G_OBJECT(pixbuf_to_save) );
 
  cleanup:
@@ -3983,13 +4014,19 @@ static void draw_to_image_file_total_area_cb (GtkSpinButton *spinbutton, gpointe
   g_free ( label_text );
 }
 
+typedef enum {
+  VW_GEN_SINGLE_IMAGE,
+  VW_GEN_DIRECTORY_OF_IMAGES,
+  VW_GEN_KMZ_FILE,
+} img_generation_t;
+
 /*
  * Get an allocated filename (or directory as specified)
  */
-static gchar* draw_image_filename ( VikWindow *vw, gboolean one_image_only )
+static gchar* draw_image_filename ( VikWindow *vw, img_generation_t img_gen )
 {
   gchar *fn = NULL;
-  if ( one_image_only )
+  if ( img_gen != VW_GEN_DIRECTORY_OF_IMAGES )
   {
     // Single file
     GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Save Image"),
@@ -4009,21 +4046,31 @@ static gchar* draw_image_filename ( VikWindow *vw, gboolean one_image_only )
     gtk_file_filter_add_pattern ( filter, "*" );
     gtk_file_chooser_add_filter ( chooser, filter );
 
-    filter = gtk_file_filter_new ();
-    gtk_file_filter_set_name ( filter, _("JPG") );
-    gtk_file_filter_add_mime_type ( filter, "image/jpeg");
-    gtk_file_chooser_add_filter ( chooser, filter );
-
-    if ( !vw->draw_image_save_as_png )
+    if ( img_gen == VW_GEN_KMZ_FILE ) {
+      filter = gtk_file_filter_new ();
+      gtk_file_filter_set_name ( filter, _("KMZ") );
+      gtk_file_filter_add_mime_type ( filter, "vnd.google-earth.kmz");
+      gtk_file_filter_add_pattern ( filter, "*.kmz" );
+      gtk_file_chooser_add_filter ( chooser, filter );
       gtk_file_chooser_set_filter ( chooser, filter );
+    }
+    else {
+      filter = gtk_file_filter_new ();
+      gtk_file_filter_set_name ( filter, _("JPG") );
+      gtk_file_filter_add_mime_type ( filter, "image/jpeg");
+      gtk_file_chooser_add_filter ( chooser, filter );
 
-    filter = gtk_file_filter_new ();
-    gtk_file_filter_set_name ( filter, _("PNG") );
-    gtk_file_filter_add_mime_type ( filter, "image/png");
-    gtk_file_chooser_add_filter ( chooser, filter );
+      if ( !vw->draw_image_save_as_png )
+        gtk_file_chooser_set_filter ( chooser, filter );
 
-    if ( vw->draw_image_save_as_png )
-      gtk_file_chooser_set_filter ( chooser, filter );
+      filter = gtk_file_filter_new ();
+      gtk_file_filter_set_name ( filter, _("PNG") );
+      gtk_file_filter_add_mime_type ( filter, "image/png");
+      gtk_file_chooser_add_filter ( chooser, filter );
+
+      if ( vw->draw_image_save_as_png )
+        gtk_file_chooser_set_filter ( chooser, filter );
+    }
 
     gtk_window_set_transient_for ( GTK_WINDOW(dialog), GTK_WINDOW(vw) );
     gtk_window_set_destroy_with_parent ( GTK_WINDOW(dialog), TRUE );
@@ -4064,7 +4111,7 @@ static gchar* draw_image_filename ( VikWindow *vw, gboolean one_image_only )
   return fn;
 }
 
-static void draw_to_image_file ( VikWindow *vw, gboolean one_image_only )
+static void draw_to_image_file ( VikWindow *vw, img_generation_t img_gen )
 {
   /* todo: default for answers inside VikWindow or static (thruout instance) */
   GtkWidget *dialog = gtk_dialog_new_with_buttons ( _("Save to Image File"), GTK_WINDOW(vw),
@@ -4075,13 +4122,12 @@ static void draw_to_image_file ( VikWindow *vw, gboolean one_image_only )
                                                   GTK_RESPONSE_ACCEPT,
                                                   NULL );
   GtkWidget *width_label, *width_spin, *height_label, *height_spin;
-  GtkWidget *png_radio, *jpeg_radio;
   GtkWidget *current_window_button;
   gpointer current_window_pass_along[7];
   GtkWidget *zoom_label, *zoom_combo;
   GtkWidget *total_size_label;
 
-  /* only used if (!one_image_only) */
+  // only used for VW_GEN_DIRECTORY_OF_IMAGES
   GtkWidget *tiles_width_spin = NULL, *tiles_height_spin = NULL;
 
   width_label = gtk_label_new ( _("Width (pixels):") );
@@ -4112,16 +4158,22 @@ static void draw_to_image_file ( VikWindow *vw, gboolean one_image_only )
   current_window_pass_along [1] = width_spin;
   current_window_pass_along [2] = height_spin;
   current_window_pass_along [3] = zoom_combo;
-  current_window_pass_along [4] = NULL; /* used for one_image_only != 1 */
-  current_window_pass_along [5] = NULL;
+  current_window_pass_along [4] = NULL; // Only for directory of tiles: width
+  current_window_pass_along [5] = NULL; // Only for directory of tiles: height
   current_window_pass_along [6] = total_size_label;
   g_signal_connect ( G_OBJECT(current_window_button), "button_press_event", G_CALLBACK(draw_to_image_file_current_window_cb), current_window_pass_along );
 
-  png_radio = gtk_radio_button_new_with_label ( NULL, _("Save as PNG") );
-  jpeg_radio = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON(png_radio), _("Save as JPEG") );
+  GtkWidget *png_radio = gtk_radio_button_new_with_label ( NULL, _("Save as PNG") );
+  GtkWidget *jpeg_radio = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON(png_radio), _("Save as JPEG") );
 
-  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), png_radio, FALSE, FALSE, 0);
-  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), jpeg_radio, FALSE, FALSE, 0);
+  if ( img_gen == VW_GEN_KMZ_FILE ) {
+    // Don't show image type selection if creating a KMZ (always JPG internally)
+    // Start with viewable area by default
+    draw_to_image_file_current_window_cb ( current_window_button, NULL, current_window_pass_along );
+  } else {
+    gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), jpeg_radio, FALSE, FALSE, 0);
+    gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), png_radio, FALSE, FALSE, 0);
+  }
 
   if ( ! vw->draw_image_save_as_png )
     gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(jpeg_radio), TRUE );
@@ -4137,7 +4189,7 @@ static void draw_to_image_file ( VikWindow *vw, gboolean one_image_only )
   gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), zoom_label, FALSE, FALSE, 0);
   gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), zoom_combo, FALSE, FALSE, 0);
 
-  if ( ! one_image_only )
+  if ( img_gen == VW_GEN_DIRECTORY_OF_IMAGES )
   {
     GtkWidget *tiles_width_label, *tiles_height_label;
 
@@ -4170,19 +4222,44 @@ static void draw_to_image_file ( VikWindow *vw, gboolean one_image_only )
   {
     gtk_widget_hide ( GTK_WIDGET(dialog) );
 
-    gchar *fn = draw_image_filename ( vw, one_image_only );
+    gchar *fn = draw_image_filename ( vw, img_gen );
     if ( !fn )
       return;
 
     gint active_z = gtk_combo_box_get_active ( GTK_COMBO_BOX(zoom_combo) );
     gdouble zoom = pow (2, active_z-2 );
 
-    if ( one_image_only )
+    if ( img_gen == VW_GEN_SINGLE_IMAGE )
       save_image_file ( vw, fn, 
                       vw->draw_image_width = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON(width_spin) ),
                       vw->draw_image_height = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON(height_spin) ),
                       zoom,
-                      vw->draw_image_save_as_png = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(png_radio) ) );
+                      vw->draw_image_save_as_png = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(png_radio) ),
+                      FALSE );
+    else if ( img_gen == VW_GEN_KMZ_FILE ) {
+      // Remove some viewport overlays as these aren't useful in KMZ file.
+      gboolean restore_xhair = vik_viewport_get_draw_centermark ( vw->viking_vvp );
+      if ( restore_xhair )
+        vik_viewport_set_draw_centermark ( vw->viking_vvp, FALSE );
+      gboolean restore_scale = vik_viewport_get_draw_scale ( vw->viking_vvp );
+      if ( restore_scale )
+        vik_viewport_set_draw_scale ( vw->viking_vvp, FALSE );
+
+      save_image_file ( vw,
+                        fn,
+                        gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON(width_spin) ),
+                        gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON(height_spin) ),
+                        zoom,
+                        FALSE, // JPG
+                        TRUE );
+
+      if ( restore_xhair )
+        vik_viewport_set_draw_centermark ( vw->viking_vvp, TRUE );
+      if ( restore_scale )
+        vik_viewport_set_draw_scale ( vw->viking_vvp, TRUE );
+      if ( restore_xhair || restore_scale )
+        draw_update ( vw );
+    }
     else {
       // NB is in UTM mode ATM
       save_image_dir ( vw, fn,
@@ -4199,15 +4276,64 @@ static void draw_to_image_file ( VikWindow *vw, gboolean one_image_only )
   gtk_widget_destroy ( GTK_WIDGET(dialog) );
 }
 
+static void draw_to_kmz_file_cb ( GtkAction *a, VikWindow *vw )
+{
+  if ( vik_viewport_get_coord_mode(vw->viking_vvp) == VIK_COORD_UTM ) {
+    a_dialog_error_msg ( GTK_WINDOW(vw), _("This feature is not available in UTM mode") );
+    return;
+  }
+  // NB ATM This only generates a KMZ file with the current viewport image - intended mostly for map images [but will include any lines/icons from track & waypoints that are drawn]
+  // (it does *not* include a full KML dump of every track, waypoint etc...)
+  draw_to_image_file ( vw, VW_GEN_KMZ_FILE );
+}
 
 static void draw_to_image_file_cb ( GtkAction *a, VikWindow *vw )
 {
-  draw_to_image_file ( vw, TRUE );
+  draw_to_image_file ( vw, VW_GEN_SINGLE_IMAGE );
 }
 
 static void draw_to_image_dir_cb ( GtkAction *a, VikWindow *vw )
 {
-  draw_to_image_file ( vw, FALSE );
+  draw_to_image_file ( vw, VW_GEN_DIRECTORY_OF_IMAGES );
+}
+
+/**
+ *
+ */
+static void import_kmz_file_cb ( GtkAction *a, VikWindow *vw )
+{
+  GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Open File"),
+                                                   GTK_WINDOW(vw),
+                                                   GTK_FILE_CHOOSER_ACTION_OPEN,
+                                                   GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                                   GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+                                                   NULL);
+
+  GtkFileFilter *filter;
+  filter = gtk_file_filter_new ();
+  gtk_file_filter_set_name ( filter, _("KMZ") );
+  gtk_file_filter_add_mime_type ( filter, "vnd.google-earth.kmz");
+  gtk_file_filter_add_pattern ( filter, "*.kmz" );
+  gtk_file_chooser_add_filter ( GTK_FILE_CHOOSER(dialog), filter );
+  gtk_file_chooser_set_filter ( GTK_FILE_CHOOSER(dialog), filter );
+
+  filter = gtk_file_filter_new ();
+  gtk_file_filter_set_name( filter, _("All") );
+  gtk_file_filter_add_pattern ( filter, "*" );
+  gtk_file_chooser_add_filter ( GTK_FILE_CHOOSER(dialog), filter );
+  // Default to any file - same as before open filters were added
+  gtk_file_chooser_set_filter ( GTK_FILE_CHOOSER(dialog), filter );
+
+  if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )  {
+    gchar *fn = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(dialog) );
+    // TODO convert ans value into readable explaination of failure...
+    int ans = kmz_open_file ( fn, vw->viking_vvp, vw->viking_vlp );
+    if ( ans )
+      a_dialog_error_msg_extra ( GTK_WINDOW(vw), _("Unable to import %s."), fn );
+
+    draw_update ( vw );
+  }
+  gtk_widget_destroy ( dialog );
 }
 
 static void print_cb ( GtkAction *a, VikWindow *vw )
@@ -4347,8 +4473,6 @@ static GtkActionEntry entries[] = {
   { "Export",    GTK_STOCK_CONVERT,      N_("_Export All"),               NULL,         N_("Export All TrackWaypoint Layers"),              (GCallback)NULL                  },
   { "ExportGPX", NULL,                   N_("_GPX..."),                      NULL,         N_("Export as GPX"),                                (GCallback)export_to_gpx         },
   { "Acquire",   GTK_STOCK_GO_DOWN,      N_("A_cquire"),                  NULL,         NULL,                                               (GCallback)NULL },
-  { "AcquireGPS",   NULL,                N_("From _GPS..."),                     NULL,         N_("Transfer data from a GPS device"),              (GCallback)acquire_from_gps      },
-  { "AcquireGPSBabel",   NULL,                N_("Import File With GPS_Babel..."),               NULL,         N_("Import file via GPSBabel converter"),              (GCallback)acquire_from_file      },
   { "AcquireRouting",   NULL,             N_("_Directions..."),     NULL,         N_("Get driving directions"),           (GCallback)acquire_from_routing   },
 #ifdef VIK_CONFIG_OPENSTREETMAP
   { "AcquireOSM",   NULL,                 N_("_OSM Traces..."),          NULL,         N_("Get traces from OpenStreetMap"),            (GCallback)acquire_from_osm       },
@@ -4367,6 +4491,10 @@ static GtkActionEntry entries[] = {
   { "Save",      GTK_STOCK_SAVE,         N_("_Save"),                         "<control>S", N_("Save the file"),                                (GCallback)save_file             },
   { "SaveAs",    GTK_STOCK_SAVE_AS,      N_("Save _As..."),                      NULL,  N_("Save the file under different name"),           (GCallback)save_file_as          },
   { "FileProperties", NULL,              N_("Properties..."),                    NULL,  N_("File Properties"),                              (GCallback)file_properties_cb },
+#ifdef HAVE_ZIP_H
+  { "ImportKMZ", GTK_STOCK_CONVERT,      N_("Import KMZ _Map File..."),        NULL,  N_("Import a KMZ file"), (GCallback)import_kmz_file_cb },
+  { "GenKMZ",    GTK_STOCK_DND,          N_("Generate _KMZ Map File..."),        NULL,  N_("Generate a KMZ file with an overlay of the current view"), (GCallback)draw_to_kmz_file_cb },
+#endif
   { "GenImg",    GTK_STOCK_FILE,         N_("_Generate Image File..."),          NULL,  N_("Save a snapshot of the workspace into a file"), (GCallback)draw_to_image_file_cb },
   { "GenImgDir", GTK_STOCK_DND_MULTIPLE, N_("Generate _Directory of Images..."), NULL,  N_("Generate _Directory of Images"),                (GCallback)draw_to_image_dir_cb },
   { "Print",    GTK_STOCK_PRINT,        N_("_Print..."),          NULL,         N_("Print maps"), (GCallback)print_cb },
@@ -4414,6 +4542,8 @@ static GtkActionEntry debug_entries[] = {
 
 static GtkActionEntry entries_gpsbabel[] = {
   { "ExportKML", NULL,                   N_("_KML..."),                      NULL,         N_("Export as KML"),                                (GCallback)export_to_kml },
+  { "AcquireGPS",   NULL,                N_("From _GPS..."),                     NULL,         N_("Transfer data from a GPS device"),              (GCallback)acquire_from_gps      },
+  { "AcquireGPSBabel", NULL,             N_("Import File With GPS_Babel..."), NULL,     N_("Import file via GPSBabel converter"),           (GCallback)acquire_from_file },
 };
 
 static GtkActionEntry entries_geojson[] = {
@@ -4519,10 +4649,16 @@ static void window_create_ui( VikWindow *window )
 
   // Use this to see if GPSBabel is available:
   if ( a_babel_available () ) {
-       // If going to add more entries then might be worth creating a menu_gpsbabel.xml.h file
-       if ( gtk_ui_manager_add_ui_from_string ( uim,
-         "<ui><menubar name='MainMenu'><menu action='File'><menu action='Export'><menuitem action='ExportKML'/></menu></menu></menubar></ui>",
-         -1, &error ) )
+    // If going to add more entries then might be worth creating a menu_gpsbabel.xml.h file
+    if ( gtk_ui_manager_add_ui_from_string ( uim,
+         "<ui>" \
+         "<menubar name='MainMenu'>" \
+         "<menu action='File'><menu action='Export'><menuitem action='ExportKML'/></menu></menu>" \
+         "<menu action='File'><menu action='Acquire'><menuitem action='AcquireGPS'/></menu></menu>" \
+         "<menu action='File'><menu action='Acquire'><menuitem action='AcquireGPSBabel'/></menu></menu>" \
+         "</menubar>" \
+         "</ui>",
+         -1, &error ) )
       gtk_action_group_add_actions ( action_group, entries_gpsbabel, G_N_ELEMENTS (entries_gpsbabel), window );
   }
 
@@ -4563,7 +4699,7 @@ static void window_create_ui( VikWindow *window )
 
     action.name = vik_layer_get_interface(i)->name;
     action.stock_id = vik_layer_get_interface(i)->name;
-    action.label = g_strdup_printf( _("New _%s Layer"), vik_layer_get_interface(i)->name);
+    action.label = g_strdup_printf( _("New _%s Layer"), _(vik_layer_get_interface(i)->name));
     action.accelerator = vik_layer_get_interface(i)->accelerator;
     action.tooltip = NULL;
     action.callback = (GCallback)menu_addlayer_cb;
@@ -4606,7 +4742,7 @@ static void window_create_ui( VikWindow *window )
     // This is to avoid clashing with just the layer name used above for the tool actions
     action_dl.name = g_strconcat("Layer", vik_layer_get_interface(i)->fixed_layer_name, NULL);
     action_dl.stock_id = NULL;
-    action_dl.label = g_strconcat("_", vik_layer_get_interface(i)->name, "...", NULL); // Prepend marker for keyboard accelerator
+    action_dl.label = g_strconcat(_(vik_layer_get_interface(i)->name), _("..."), NULL);
     action_dl.accelerator = NULL;
     action_dl.tooltip = NULL;
     action_dl.callback = (GCallback)layer_defaults_cb;
@@ -4639,6 +4775,14 @@ static void window_create_ui( VikWindow *window )
   gtk_ui_manager_ensure_update (uim);
   
   setup_recent_files(window);
+
+  if ( vik_routing_number_of_engines(VIK_ROUTING_METHOD_DIRECTIONS) == 0 ) {
+    GtkWidget *widget = gtk_ui_manager_get_widget ( uim, "/ui/MainMenu/File/Acquire/AcquireRouting" );
+    if ( widget ) {
+      g_object_set ( widget, "sensitive", FALSE, NULL );
+    }
+    g_warning ( "No direction routing engines available" );
+  }
 }
 
 
@@ -4770,6 +4914,7 @@ void vik_window_set_selected_waypoint ( VikWindow *vw, gpointer *vwp, gpointer v
 gboolean vik_window_clear_highlight ( VikWindow *vw )
 {
   gboolean need_redraw = FALSE;
+  vw->containing_vtl = NULL;
   if ( vw->selected_vtl != NULL ) {
     vw->selected_vtl = NULL;
     need_redraw = TRUE;