#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"
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] );
static void trw_layer_split_by_n_points ( gpointer pass_along[6] );
static void trw_layer_split_at_trackpoint ( gpointer pass_along[6] );
static void trw_layer_split_segments ( gpointer pass_along[6] );
+static void trw_layer_delete_point_selected ( gpointer pass_along[6] );
static void trw_layer_delete_points_same_position ( gpointer pass_along[6] );
static void trw_layer_delete_points_same_time ( gpointer pass_along[6] );
static void trw_layer_reverse ( gpointer pass_along[6] );
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
static void trw_layer_realize_track ( gpointer id, VikTrack *track, gpointer pass_along[5] );
static void init_drawing_params ( struct DrawingParams *dp, VikTrwLayer *vtl, VikViewport *vp );
-static void trw_layer_insert_tp_after_current_tp ( VikTrwLayer *vtl );
+static void trw_layer_insert_tp_beside_current_tp ( VikTrwLayer *vtl, gboolean );
static void trw_layer_cancel_current_tp ( VikTrwLayer *vtl, gboolean destroy );
static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response );
static void trw_layer_tpwin_init ( VikTrwLayer *vtl );
/*
* 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.
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;
}
return l->waypoints;
}
+GHashTable *vik_trw_layer_get_tracks_iters ( VikTrwLayer *vtl )
+{
+ return vtl->tracks_iters;
+}
+
+GHashTable *vik_trw_layer_get_routes_iters ( VikTrwLayer *vtl )
+{
+ return vtl->routes_iters;
+}
+
+GHashTable *vik_trw_layer_get_waypoints_iters ( VikTrwLayer *vtl )
+{
+ return vtl->waypoints;
+}
+
gboolean vik_trw_layer_is_empty ( VikTrwLayer *vtl )
{
return ! ( g_hash_table_size ( vtl->tracks ) ||
a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("This layer has no waypoints or trackpoints.") );
}
-static void trw_layer_zoom_to_show_latlons ( VikTrwLayer *vtl, VikViewport *vvp, struct LatLon maxmin[2] )
+void trw_layer_zoom_to_show_latlons ( VikTrwLayer *vtl, VikViewport *vvp, struct LatLon maxmin[2] )
{
/* First set the center [in case previously viewing from elsewhere] */
/* Then loop through zoom levels until provided positions are in view */
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 ) {
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] )
vtl->has_verified_thumbnails = FALSE;
trw_layer_geotag_dialog ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
- vtl,
- NULL,
- NULL);
+ vtl,
+ NULL,
+ NULL );
}
#endif
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
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
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. */
}
}
-typedef struct {
- VikTrack *trk; // input
- gpointer uuid; // output
-} trku_udata;
-
-static gboolean trw_layer_track_find_uuid ( const gpointer id, const VikTrack *trk, gpointer udata )
+gboolean trw_layer_track_find_uuid ( const gpointer id, const VikTrack *trk, gpointer udata )
{
trku_udata *user_data = udata;
if ( trk == user_data->trk ) {
/**
* 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 );
}
}
+/**
+ * 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]);
tr,
pass_along[1], /* vlp */
pass_along[5], /* vvp */
- pass_along[6], /* iter */
FALSE );
}
}
trk,
pass_along[1], // vlp
pass_along[5], // vvp
- pass_along[6], // iter
TRUE );
}
}
/*
* 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;
}
/* end of split/merge routines */
+static void trw_layer_trackpoint_selected_delete ( VikTrwLayer *vtl, VikTrack *trk )
+{
+ GList *new_tpl;
+
+ // Find available adjacent trackpoint
+ if ( (new_tpl = vtl->current_tpl->next) || (new_tpl = vtl->current_tpl->prev) ) {
+ if ( VIK_TRACKPOINT(vtl->current_tpl->data)->newsegment && vtl->current_tpl->next )
+ VIK_TRACKPOINT(vtl->current_tpl->next->data)->newsegment = TRUE; /* don't concat segments on del */
+
+ // Delete current trackpoint
+ vik_trackpoint_free ( vtl->current_tpl->data );
+ trk->trackpoints = g_list_delete_link ( trk->trackpoints, vtl->current_tpl );
+
+ // Set to current to the available adjacent trackpoint
+ vtl->current_tpl = new_tpl;
+
+ if ( vtl->current_tp_track ) {
+ vik_track_calculate_bounds ( vtl->current_tp_track );
+ }
+ }
+ else {
+ // Delete current trackpoint
+ vik_trackpoint_free ( vtl->current_tpl->data );
+ trk->trackpoints = g_list_delete_link ( trk->trackpoints, vtl->current_tpl );
+ trw_layer_cancel_current_tp ( vtl, FALSE );
+ }
+}
+
+/**
+ * Delete the selected point
+ */
+static void trw_layer_delete_point_selected ( gpointer pass_along[6] )
+{
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *trk;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !trk )
+ return;
+
+ if ( !vtl->current_tpl )
+ return;
+
+ trw_layer_trackpoint_selected_delete ( vtl, trk );
+
+ // Track has been updated so update tps:
+ trw_layer_cancel_tps_of_track ( vtl, trk );
+
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+}
+
/**
* Delete adjacent track points at the same position
* AKA Delete Dulplicates on the Properties Window
vik_layer_emit_update ( VIK_LAYER(vtl) );
}
+/**
+ * Insert a point
+ */
+static void trw_layer_insert_point_after ( gpointer pass_along[6] )
+{
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( ! track )
+ return;
+
+ trw_layer_insert_tp_beside_current_tp ( vtl, FALSE );
+
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+}
+
+static void trw_layer_insert_point_before ( gpointer pass_along[6] )
+{
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( ! track )
+ return;
+
+ trw_layer_insert_tp_beside_current_tp ( vtl, TRUE );
+
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+}
+
/**
* Reverse a track
*/
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:
*
}
/**
- * trw_layer_analyse_create_list:
+ * vik_trw_layer_build_track_list_t:
*
- * Create the latest list of tracks with the associated layer(s)
- * Although this will always be from a single layer here
+ * Helper function to construct a list of #vik_trw_track_list_t
*/
-static GList* trw_layer_analyse_create_list ( VikLayer *vl, gpointer user_data )
+GList *vik_trw_layer_build_track_list_t ( VikTrwLayer *vtl, GList *tracks )
{
- VikTrwLayer *vtl = VIK_TRW_LAYER(vl);
- GList *tracks = NULL;
- if ( GPOINTER_TO_INT(user_data) == VIK_TRW_LAYER_SUBLAYER_TRACKS )
- tracks = g_hash_table_get_values ( vik_trw_layer_get_tracks(vtl) );
- else
- tracks = g_hash_table_get_values ( vik_trw_layer_get_routes(vtl) );
-
GList *tracks_and_layers = NULL;
// build tracks_and_layers list
- tracks = g_list_first ( tracks );
while ( tracks ) {
vik_trw_track_list_t *vtdl = g_malloc (sizeof(vik_trw_track_list_t));
vtdl->trk = VIK_TRACK(tracks->data);
tracks_and_layers = g_list_prepend ( tracks_and_layers, vtdl );
tracks = g_list_next ( tracks );
}
-
return tracks_and_layers;
}
+/**
+ * trw_layer_create_track_list:
+ *
+ * Create the latest list of tracks with the associated layer(s)
+ * Although this will always be from a single layer here
+ */
+static GList* trw_layer_create_track_list ( VikLayer *vl, gpointer user_data )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(vl);
+ GList *tracks = NULL;
+ if ( GPOINTER_TO_INT(user_data) == VIK_TRW_LAYER_SUBLAYER_TRACKS )
+ tracks = g_hash_table_get_values ( vik_trw_layer_get_tracks(vtl) );
+ else
+ 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_tracks_stats ( gpointer lav[2] )
{
VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
VIK_LAYER(vtl)->name,
VIK_LAYER(vtl),
GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_TRACKS),
- trw_layer_analyse_create_list,
+ trw_layer_create_track_list,
trw_layer_analyse_close );
}
VIK_LAYER(vtl)->name,
VIK_LAYER(vtl),
GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_ROUTES),
- trw_layer_analyse_create_list,
+ trw_layer_create_track_list,
trw_layer_analyse_close );
}
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 );
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;
gtk_widget_show ( item );
}
}
-
}
}
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 )
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") );
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") );
// Make it available only when a trackpoint is selected.
gtk_widget_set_sensitive ( item, (gboolean)GPOINTER_TO_INT(l->current_tpl) );
+ GtkWidget *insert_submenu = gtk_menu_new ();
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Insert Points") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), insert_submenu );
+
+ item = gtk_menu_item_new_with_mnemonic ( _("Insert Point _Before Selected Point") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_insert_point_before), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(insert_submenu), item );
+ gtk_widget_show ( item );
+ // Make it available only when a point is selected
+ gtk_widget_set_sensitive ( item, (gboolean)GPOINTER_TO_INT(l->current_tpl) );
+
+ item = gtk_menu_item_new_with_mnemonic ( _("Insert Point _After Selected Point") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_insert_point_after), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(insert_submenu), item );
+ gtk_widget_show ( item );
+ // Make it available only when a point is selected
+ gtk_widget_set_sensitive ( item, (gboolean)GPOINTER_TO_INT(l->current_tpl) );
+
GtkWidget *delete_submenu;
delete_submenu = gtk_menu_new ();
item = gtk_image_menu_item_new_with_mnemonic ( _("Delete Poi_nts") );
gtk_widget_show ( item );
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), delete_submenu );
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Delete _Selected Point") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_DELETE, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_point_selected), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(delete_submenu), item );
+ gtk_widget_show ( item );
+ // Make it available only when a point is selected
+ gtk_widget_set_sensitive ( item, (gboolean)GPOINTER_TO_INT(l->current_tpl) );
+
item = gtk_menu_item_new_with_mnemonic ( _("Delete Points With The Same _Position") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_points_same_position), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(delete_submenu), item );
return rv;
}
-static void trw_layer_insert_tp_after_current_tp ( VikTrwLayer *vtl )
+// TODO: Probably better to rework this track manipulation in viktrack.c
+static void trw_layer_insert_tp_beside_current_tp ( VikTrwLayer *vtl, gboolean before )
{
- /* sanity checks */
+ // sanity check
if (!vtl->current_tpl)
return;
- if (!vtl->current_tpl->next)
- return;
VikTrackpoint *tp_current = VIK_TRACKPOINT(vtl->current_tpl->data);
- VikTrackpoint *tp_next = VIK_TRACKPOINT(vtl->current_tpl->next->data);
+ VikTrackpoint *tp_other = NULL;
- /* Use current and next trackpoints to form a new track point which is inserted into the tracklist */
- if ( tp_next ) {
+ if ( before ) {
+ if (!vtl->current_tpl->prev)
+ return;
+ tp_other = VIK_TRACKPOINT(vtl->current_tpl->prev->data);
+ } else {
+ if (!vtl->current_tpl->next)
+ return;
+ tp_other = VIK_TRACKPOINT(vtl->current_tpl->next->data);
+ }
+
+ // Use current and other trackpoints to form a new track point which is inserted into the tracklist
+ if ( tp_other ) {
VikTrackpoint *tp_new = vik_trackpoint_new();
- struct LatLon ll_current, ll_next;
+ struct LatLon ll_current, ll_other;
vik_coord_to_latlon ( &tp_current->coord, &ll_current );
- vik_coord_to_latlon ( &tp_next->coord, &ll_next );
+ vik_coord_to_latlon ( &tp_other->coord, &ll_other );
/* main positional interpolation */
- struct LatLon ll_new = { (ll_current.lat+ll_next.lat)/2, (ll_current.lon+ll_next.lon)/2 };
+ struct LatLon ll_new = { (ll_current.lat+ll_other.lat)/2, (ll_current.lon+ll_other.lon)/2 };
vik_coord_load_from_latlon ( &(tp_new->coord), vtl->coord_mode, &ll_new );
/* Now other properties that can be interpolated */
- tp_new->altitude = (tp_current->altitude + tp_next->altitude) / 2;
+ tp_new->altitude = (tp_current->altitude + tp_other->altitude) / 2;
- if (tp_current->has_timestamp && tp_next->has_timestamp) {
+ if (tp_current->has_timestamp && tp_other->has_timestamp) {
/* Note here the division is applied to each part, then added
This is to avoid potential overflow issues with a 32 time_t for dates after midpoint of this Unix time on 2004/01/04 */
- tp_new->timestamp = (tp_current->timestamp/2) + (tp_next->timestamp/2);
+ tp_new->timestamp = (tp_current->timestamp/2) + (tp_other->timestamp/2);
tp_new->has_timestamp = TRUE;
}
- if (tp_current->speed != NAN && tp_next->speed != NAN)
- tp_new->speed = (tp_current->speed + tp_next->speed)/2;
+ if (tp_current->speed != NAN && tp_other->speed != NAN)
+ tp_new->speed = (tp_current->speed + tp_other->speed)/2;
/* TODO - improve interpolation of course, as it may not be correct.
if courses in degrees are 350 + 020, the mid course more likely to be 005 (not 185)
[similar applies if value is in radians] */
- if (tp_current->course != NAN && tp_next->course != NAN)
- tp_new->course = (tp_current->course + tp_next->course)/2;
+ if (tp_current->course != NAN && tp_other->course != NAN)
+ tp_new->course = (tp_current->course + tp_other->course)/2;
/* DOP / sat values remain at defaults as not they do not seem applicable to a dreamt up point */
- /* Insert new point into the trackpoints list after the current TP */
+ // Insert new point into the appropriate trackpoint list, either before or after the current trackpoint as directed
VikTrack *trk = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_id );
if ( !trk )
// Otherwise try routes
gint index = g_list_index ( trk->trackpoints, tp_current );
if ( index > -1 ) {
+ if ( !before )
+ index = index + 1;
// NB no recalculation of bounds since it is inserted between points
- trk->trackpoints = g_list_insert ( trk->trackpoints, tp_new, index+1 );
+ trk->trackpoints = g_list_insert ( trk->trackpoints, tp_new, index );
}
}
}
if ( tr == NULL )
return;
- GList *new_tpl;
-
- // Find available adjacent trackpoint
- if ( (new_tpl = vtl->current_tpl->next) || (new_tpl = vtl->current_tpl->prev) )
- {
- if ( VIK_TRACKPOINT(vtl->current_tpl->data)->newsegment && vtl->current_tpl->next )
- VIK_TRACKPOINT(vtl->current_tpl->next->data)->newsegment = TRUE; /* don't concat segments on del */
-
- // Delete current trackpoint
- vik_trackpoint_free ( vtl->current_tpl->data );
- tr->trackpoints = g_list_delete_link ( tr->trackpoints, vtl->current_tpl );
-
- // Set to current to the available adjacent trackpoint
- vtl->current_tpl = new_tpl;
+ trw_layer_trackpoint_selected_delete ( vtl, tr );
+ if ( vtl->current_tpl )
// Reset dialog with the available adjacent trackpoint
- if ( vtl->current_tp_track ) {
- vik_track_calculate_bounds ( vtl->current_tp_track );
- vik_trw_layer_tpwin_set_tp ( vtl->tpwin, new_tpl, vtl->current_tp_track->name );
- }
+ vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
- vik_layer_emit_update(VIK_LAYER(vtl));
- }
- else
- {
- // Delete current trackpoint
- vik_trackpoint_free ( vtl->current_tpl->data );
- tr->trackpoints = g_list_delete_link ( tr->trackpoints, vtl->current_tpl );
- trw_layer_cancel_current_tp ( vtl, FALSE );
- }
+ vik_layer_emit_update(VIK_LAYER(vtl));
}
else if ( response == VIK_TRW_LAYER_TPWIN_FORWARD && vtl->current_tpl->next )
{
}
else if ( response == VIK_TRW_LAYER_TPWIN_INSERT && vtl->current_tpl->next )
{
- trw_layer_insert_tp_after_current_tp ( vtl );
+ trw_layer_insert_tp_beside_current_tp ( vtl, FALSE );
vik_layer_emit_update(VIK_LAYER(vtl));
}
else if ( response == VIK_TRW_LAYER_TPWIN_DATA_CHANGED )
// Determine if working on a waypoint or a trackpoint
if ( t->is_waypoint ) {
+ // Update waypoint position
vtl->current_wp->coord = new_coord;
trw_layer_calculate_bounds_waypoints ( vtl );
+ // Reset waypoint pointer
+ vtl->current_wp = NULL;
+ vtl->current_wp_id = NULL;
}
else {
if ( vtl->current_tpl ) {
if ( vtl->current_tp_track )
vik_track_calculate_bounds ( vtl->current_tp_track );
- if ( vtl->tpwin )
+ if ( vtl->tpwin )
if ( vtl->current_tp_track )
vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
+ // NB don't reset the selected trackpoint, thus ensuring it's still in the tpwin
}
}
- // Reset
- vtl->current_wp = NULL;
- vtl->current_wp_id = NULL;
- trw_layer_cancel_current_tp ( vtl, FALSE );
-
vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
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)
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;
}
* (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 };
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 );
+}