]> git.street.me.uk Git - andy/viking.git/blobdiff - src/viktrwlayer.c
Update libjpeg utilities from exif command line tool to version 0.6.21
[andy/viking.git] / src / viktrwlayer.c
index 163e5938d033b73a09e9fe3195697857e01e676b..7eeae31ca31ac9485e13c2e2942121de733909a1 100644 (file)
@@ -36,6 +36,8 @@
 #include "viktrwlayer_tpwin.h"
 #include "viktrwlayer_propwin.h"
 #include "viktrwlayer_analysis.h"
+#include "viktrwlayer_tracklist.h"
+#include "viktrwlayer_waypointlist.h"
 #ifdef VIK_CONFIG_GEOTAG
 #include "viktrwlayer_geotag.h"
 #include "geotag_exif.h"
@@ -261,8 +263,6 @@ static void trw_layer_free_track_gcs ( VikTrwLayer *vtl );
 static void trw_layer_draw_track_cb ( const gpointer id, VikTrack *track, struct DrawingParams *dp );
 static void trw_layer_draw_waypoint ( const gpointer id, VikWaypoint *wp, struct DrawingParams *dp );
 
-static void trw_layer_calculate_bounds_waypoints ( VikTrwLayer *vtl );
-
 static void goto_coord ( gpointer *vlp, gpointer vvp, gpointer vl, const VikCoord *coord );
 static void trw_layer_goto_track_startpoint ( gpointer pass_along[6] );
 static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] );
@@ -324,6 +324,10 @@ static void trw_layer_acquire_geotagged_cb ( gpointer lav[2] );
 static void trw_layer_acquire_file_cb ( gpointer lav[2] );
 static void trw_layer_gps_upload ( gpointer lav[2] );
 
+static void trw_layer_track_list_dialog_single ( gpointer pass_along[6] );
+static void trw_layer_track_list_dialog ( gpointer lav[2] );
+static void trw_layer_waypoint_list_dialog ( gpointer lav[2] );
+
 // Specific route versions:
 //  Most track handling functions can handle operating on the route list
 //  However these ones are easier in separate functions
@@ -2254,7 +2258,7 @@ static VikTrwLayer* trw_layer_create ( VikViewport *vp )
 /*
  * Can accept a null symbol, and may return null value
  */
-static GdkPixbuf* get_wp_sym_small ( gchar *symbol )
+GdkPixbuf* get_wp_sym_small ( gchar *symbol )
 {
   GdkPixbuf* wp_icon = a_get_wp_sym (symbol);
   // ATM a_get_wp_sym returns a cached icon, with the size dependent on the preferences.
@@ -2644,7 +2648,7 @@ static void set_statusbar_msg_info_trkpt ( VikTrwLayer *vtl, VikTrackpoint *trkp
   gboolean need2free = FALSE;
   if ( !a_settings_get_string ( VIK_SETTINGS_TRKPT_SELECTED_STATUSBAR_FORMAT, &statusbar_format_code ) ) {
     // Otherwise use default
-    statusbar_format_code = g_strdup ( "KATDN" );
+    statusbar_format_code = g_strdup ( "KEATDN" );
     need2free = TRUE;
   }
 
@@ -3159,12 +3163,7 @@ static void trw_layer_export_gpx_track ( gpointer pass_along[6] )
   g_free ( auto_save_name );
 }
 
-typedef struct {
-  VikWaypoint *wp; // input
-  gpointer uuid;   // output
-} wpu_udata;
-
-static gboolean trw_layer_waypoint_find_uuid ( const gpointer id, const VikWaypoint *wp, gpointer udata )
+gboolean trw_layer_waypoint_find_uuid ( const gpointer id, const VikWaypoint *wp, gpointer udata )
 {
   wpu_udata *user_data = udata;
   if ( wp == user_data->wp ) {
@@ -3312,9 +3311,20 @@ static void trw_layer_geotagging_track ( gpointer pass_along[6] )
   vtl->has_verified_thumbnails = FALSE;
 
   trw_layer_geotag_dialog ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
-                           vtl,
-                           track,
-                           track->name );
+                            vtl,
+                            NULL,
+                            track );
+}
+
+static void trw_layer_geotagging_waypoint ( gpointer pass_along[6] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
+  VikWaypoint *wpt = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->waypoints, pass_along[3] );
+
+  trw_layer_geotag_dialog ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                            vtl,
+                            wpt,
+                            NULL );
 }
 
 static void trw_layer_geotagging ( gpointer lav[2] )
@@ -3324,9 +3334,9 @@ static void trw_layer_geotagging ( gpointer lav[2] )
   vtl->has_verified_thumbnails = FALSE;
 
   trw_layer_geotag_dialog ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
-                           vtl,
-                           NULL,
-                           NULL);
+                            vtl,
+                            NULL,
+                            NULL );
 }
 #endif
 
@@ -3962,7 +3972,21 @@ static void trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer
   if ( item ) {
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
     gtk_widget_show ( item );
-  }  
+  }
+
+  item = gtk_image_menu_item_new_with_mnemonic ( _("Track _List...") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_track_list_dialog), pass_along );
+  gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+  gtk_widget_show ( item );
+  gtk_widget_set_sensitive ( item, (gboolean)(g_hash_table_size (vtl->tracks)+g_hash_table_size (vtl->routes)) );
+
+  item = gtk_image_menu_item_new_with_mnemonic ( _("_Waypoint List...") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_waypoint_list_dialog), pass_along );
+  gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+  gtk_widget_show ( item );
+  gtk_widget_set_sensitive ( item, (gboolean)(g_hash_table_size (vtl->waypoints)) );
 }
 
 // Fake Waypoint UUIDs vi simple increasing integer
@@ -4031,7 +4055,7 @@ void vik_trw_layer_add_track ( VikTrwLayer *vtl, gchar *name, VikTrack *t )
 
   g_hash_table_insert ( vtl->tracks, GUINT_TO_POINTER(tr_uuid), t );
 
-  trw_layer_update_treeview ( vtl, t, GUINT_TO_POINTER(tr_uuid) );
+  trw_layer_update_treeview ( vtl, t );
 }
 
 // Fake Route UUIDs vi simple increasing integer
@@ -4064,7 +4088,7 @@ void vik_trw_layer_add_route ( VikTrwLayer *vtl, gchar *name, VikTrack *t )
 
   g_hash_table_insert ( vtl->routes, GUINT_TO_POINTER(rt_uuid), t );
 
-  trw_layer_update_treeview ( vtl, t, GUINT_TO_POINTER(rt_uuid) );
+  trw_layer_update_treeview ( vtl, t );
 }
 
 /* to be called whenever a track has been deleted or may have been changed. */
@@ -4636,7 +4660,7 @@ static void trw_layer_delete_item ( gpointer pass_along[6] )
 /**
  *  Rename waypoint and maintain corresponding name of waypoint in the treeview
  */
-static void trw_layer_waypoint_rename ( VikTrwLayer *vtl, VikWaypoint *wp, const gchar *new_name )
+void trw_layer_waypoint_rename ( VikTrwLayer *vtl, VikWaypoint *wp, const gchar *new_name )
 {
   vik_waypoint_set_name ( wp, new_name );
 
@@ -4658,6 +4682,28 @@ static void trw_layer_waypoint_rename ( VikTrwLayer *vtl, VikWaypoint *wp, const
   }
 }
 
+/**
+ *  Maintain icon of waypoint in the treeview
+ */
+void trw_layer_waypoint_reset_icon ( VikTrwLayer *vtl, VikWaypoint *wp )
+{
+  // update the treeview
+  wpu_udata udataU;
+  udataU.wp   = wp;
+  udataU.uuid = NULL;
+
+  // Need key of it for treeview update
+  gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, &udataU );
+
+  if ( wpf && udataU.uuid ) {
+    GtkTreeIter *it = g_hash_table_lookup ( vtl->waypoints_iters, udataU.uuid );
+
+    if ( it ) {
+      vik_treeview_item_set_icon ( VIK_LAYER(vtl)->vt, it, get_wp_sym_small (wp->symbol) );
+    }
+  }
+}
+
 static void trw_layer_properties_item ( gpointer pass_along[7] )
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
@@ -4694,7 +4740,6 @@ static void trw_layer_properties_item ( gpointer pass_along[7] )
                                   tr,
                                  pass_along[1], /* vlp */
                                  pass_along[5], /* vvp */
-                                  pass_along[6], /* iter */
                                   FALSE );
     }
   }
@@ -4722,7 +4767,6 @@ static void trw_layer_track_statistics ( gpointer pass_along[7] )
                                 trk,
                                 pass_along[1], // vlp
                                 pass_along[5], // vvp
-                                pass_along[6], // iter
                                 TRUE );
   }
 }
@@ -4730,7 +4774,7 @@ static void trw_layer_track_statistics ( gpointer pass_along[7] )
 /*
  * Update the treeview of the track id - primarily to update the icon
  */
-void trw_layer_update_treeview ( VikTrwLayer *vtl, VikTrack *trk, gpointer *trk_id )
+void trw_layer_update_treeview ( VikTrwLayer *vtl, VikTrack *trk )
 {
   trku_udata udata;
   udata.trk  = trk;
@@ -6894,6 +6938,39 @@ static void trw_layer_routes_visibility_toggle ( gpointer lav[2] )
   vik_layer_emit_update ( VIK_LAYER(vtl) );
 }
 
+/**
+ * vik_trw_layer_build_waypoint_list_t:
+ *
+ * Helper function to construct a list of #vik_trw_waypoint_list_t
+ */
+GList *vik_trw_layer_build_waypoint_list_t ( VikTrwLayer *vtl, GList *waypoints )
+{
+  GList *waypoints_and_layers = NULL;
+  // build waypoints_and_layers list
+  while ( waypoints ) {
+    vik_trw_waypoint_list_t *vtdl = g_malloc (sizeof(vik_trw_waypoint_list_t));
+    vtdl->wpt = VIK_WAYPOINT(waypoints->data);
+    vtdl->vtl = vtl;
+    waypoints_and_layers = g_list_prepend ( waypoints_and_layers, vtdl );
+    waypoints = g_list_next ( waypoints );
+  }
+  return waypoints_and_layers;
+}
+
+/**
+ * trw_layer_create_waypoint_list:
+ *
+ * Create the latest list of waypoints with the associated layer(s)
+ *  Although this will always be from a single layer here
+ */
+static GList* trw_layer_create_waypoint_list ( VikLayer *vl, gpointer user_data )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(vl);
+  GList *waypoints = g_hash_table_get_values ( vik_trw_layer_get_waypoints(vtl) );
+
+  return vik_trw_layer_build_waypoint_list_t ( vtl, waypoints );
+}
+
 /**
  * trw_layer_analyse_close:
  *
@@ -7199,18 +7276,15 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men
 
     if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
     {
-      gboolean separator_created = FALSE;
+      // Always create separator as now there is always at least the transform menu option
+      item = gtk_menu_item_new ();
+      gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+      gtk_widget_show ( item );
 
       /* could be a right-click using the tool */
       if ( vlp != NULL ) {
-       item = gtk_menu_item_new ();
-       gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
-       gtk_widget_show ( item );
-
-       separator_created = TRUE;
-
         item = gtk_image_menu_item_new_with_mnemonic ( _("_Goto") );
-       gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
+        gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
         g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_waypoint), pass_along );
         gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
         gtk_widget_show ( item );
@@ -7220,30 +7294,22 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men
 
       if ( wp && wp->name ) {
         if ( is_valid_geocache_name ( wp->name ) ) {
-
-          if ( !separator_created ) {
-            item = gtk_menu_item_new ();
-            gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
-            gtk_widget_show ( item );
-            separator_created = TRUE;
-          }
-
           item = gtk_menu_item_new_with_mnemonic ( _("_Visit Geocache Webpage") );
           g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_waypoint_gc_webpage), pass_along );
           gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
           gtk_widget_show ( item );
         }
+#ifdef VIK_CONFIG_GEOTAG
+        item = gtk_menu_item_new_with_mnemonic ( _("Geotag _Images...") );
+        g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_geotagging_waypoint), pass_along );
+        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+        gtk_widget_set_tooltip_text (item, _("Geotag multiple images against this waypoint"));
+        gtk_widget_show ( item );
+#endif
       }
 
       if ( wp && wp->image )
       {
-       if ( !separator_created ) {
-         item = gtk_menu_item_new ();
-         gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
-         gtk_widget_show ( item );
-         separator_created = TRUE;
-       }
-
        // Set up image paramater
        pass_along[5] = wp->image;
 
@@ -7284,7 +7350,6 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men
           gtk_widget_show ( item );
         }
       }
-
     }
   }
 
@@ -7364,6 +7429,11 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_waypoints_visibility_toggle), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(vis_submenu), item );
     gtk_widget_show ( item );
+
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_List Waypoints...") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_waypoint_list_dialog), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
   }
 
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACKS )
@@ -7429,6 +7499,11 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men
     gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_tracks_visibility_toggle), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(vis_submenu), item );
+
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_List Tracks...") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_track_list_dialog_single), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
 
     item = gtk_menu_item_new_with_mnemonic ( _("_Statistics") );
@@ -7501,6 +7576,12 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men
     gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_routes_visibility_toggle), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(vis_submenu), item );
+
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_List Routes...") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_track_list_dialog_single), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+
     gtk_widget_show ( item );
 
     item = gtk_menu_item_new_with_mnemonic ( _("_Statistics") );
@@ -9740,7 +9821,7 @@ static void trw_layer_track_alloc_colors ( VikTrwLayer *vtl )
       VIK_TRACK(value)->has_color = TRUE;
     }
 
-    trw_layer_update_treeview ( vtl, VIK_TRACK(value), key );
+    trw_layer_update_treeview ( vtl, VIK_TRACK(value) );
 
     ii++;
     if (ii > VIK_TRW_LAYER_TRACK_GCS)
@@ -9762,7 +9843,7 @@ static void trw_layer_track_alloc_colors ( VikTrwLayer *vtl )
       VIK_TRACK(value)->has_color = TRUE;
     }
 
-    trw_layer_update_treeview ( vtl, VIK_TRACK(value), key );
+    trw_layer_update_treeview ( vtl, VIK_TRACK(value) );
 
     ii = !ii;
   }
@@ -9772,7 +9853,7 @@ static void trw_layer_track_alloc_colors ( VikTrwLayer *vtl )
  * (Re)Calculate the bounds of the waypoints in this layer,
  * This should be called whenever waypoints are changed
  */
-static void trw_layer_calculate_bounds_waypoints ( VikTrwLayer *vtl )
+void trw_layer_calculate_bounds_waypoints ( VikTrwLayer *vtl )
 {
   struct LatLon topleft = { 0.0, 0.0 };
   struct LatLon bottomright = { 0.0, 0.0 };
@@ -10179,3 +10260,52 @@ static gchar *highest_wp_number_get(VikTrwLayer *vtl)
   g_snprintf(buf,4,"%03d", vtl->highest_wp_number+1 );
   return g_strdup(buf);
 }
+
+/**
+ * trw_layer_create_track_list_both:
+ *
+ * Create the latest list of tracks and routes
+ */
+static GList* trw_layer_create_track_list_both ( VikLayer *vl, gpointer user_data )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(vl);
+  GList *tracks = NULL;
+  tracks = g_list_concat ( tracks, g_hash_table_get_values ( vik_trw_layer_get_tracks ( vtl ) ) );
+  tracks = g_list_concat ( tracks, g_hash_table_get_values ( vik_trw_layer_get_routes ( vtl ) ) );
+
+  return vik_trw_layer_build_track_list_t ( vtl, tracks );
+}
+
+static void trw_layer_track_list_dialog_single ( gpointer pass_along[6] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
+
+  gchar *title = NULL;
+  if ( GPOINTER_TO_INT(pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_TRACKS )
+    title = g_strdup_printf ( _("%s: Track List"), VIK_LAYER(vtl)->name );
+  else
+    title = g_strdup_printf ( _("%s: Route List"), VIK_LAYER(vtl)->name );
+
+  vik_trw_layer_track_list_show_dialog ( title, VIK_LAYER(vtl), pass_along[2], trw_layer_create_track_list, FALSE );
+  g_free ( title );
+}
+
+static void trw_layer_track_list_dialog ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  //VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+
+  gchar *title = g_strdup_printf ( _("%s: Track and Route List"), VIK_LAYER(vtl)->name );
+  vik_trw_layer_track_list_show_dialog ( title, VIK_LAYER(vtl), NULL, trw_layer_create_track_list_both, FALSE );
+  g_free ( title );
+}
+
+static void trw_layer_waypoint_list_dialog ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  //VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+
+  gchar *title = g_strdup_printf ( _("%s: Waypoint List"), VIK_LAYER(vtl)->name );
+  vik_trw_layer_waypoint_list_show_dialog ( title, VIK_LAYER(vtl), NULL, trw_layer_create_waypoint_list, FALSE );
+  g_free ( title );
+}