From 15f45edcafba17f39d76fc0b921299ef77e03623 Mon Sep 17 00:00:00 2001 From: Quy Tonthat Date: Tue, 18 Nov 2008 16:13:49 +0000 Subject: [PATCH] Merging track. Few safegards, enhance and bug fixes. Tracks can only be merged if they have timestamps. Make sure users won't cause damage to themselves by merging tracks without timestamps. Also a few fixes and optimisation. Signed-off-by: Quy Tonthat --- ChangeLog | 4 +++ src/dialog.c | 22 ++++------------ src/dialog.h | 2 +- src/viktrwlayer.c | 66 ++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 69 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index ddbb9c9b..7abb9f2a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ 2008-11-19 Quy Tonthat : * Merging tracks by name. As submitted by Hein Ragas + * Merging tracks by name. Tracks can only be merged if they have + timestamps. Make sure users won't cause damage to themselves by + merging tracks without timestamps. Also a few bug fixes and + optimisation. 2008-11-13 Quy Tonthat : diff --git a/src/dialog.c b/src/dialog.c index 89ccb196..a54c0c43 100644 --- a/src/dialog.c +++ b/src/dialog.c @@ -386,7 +386,7 @@ gboolean a_dialog_new_waypoint ( GtkWindow *parent, gchar **dest, VikWaypoint *w return FALSE; } -gchar *a_dialog_select_track ( GtkWindow *parent, GHashTable *tracks, gchar *orig_track_name ) +gchar *a_dialog_select_track ( GtkWindow *parent, GHashTable *tracks, const GList *track_names ) { GtkTreeIter iter; GtkCellRenderer *renderer; @@ -403,23 +403,13 @@ gchar *a_dialog_select_track ( GtkWindow *parent, GHashTable *tracks, gchar *ori GtkWidget *label = gtk_label_new ( _("Select track to merge with") ); GtkListStore *store = gtk_list_store_new(1, G_TYPE_STRING); - GList *track_names = g_hash_table_get_keys(tracks); GList *track_runner = track_names; while (track_runner) { - gchar *track_name = g_strdup(track_runner->data); - if (g_strcasecmp(track_name, orig_track_name) == 0) - { - g_free(track_name); - } - else - { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, track_name,-1); - } + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, track_runner->data, -1); track_runner = g_list_next(track_runner); } - g_list_free(track_names); view = gtk_tree_view_new(); renderer = gtk_cell_renderer_text_new(); @@ -437,14 +427,12 @@ gchar *a_dialog_select_track ( GtkWindow *parent, GHashTable *tracks, gchar *ori while ( gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT ) { GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); - if (gtk_tree_selection_get_selected(selection, &store, &iter)) + if (gtk_tree_selection_get_selected(selection, NULL, &iter)) { gchar *name; gtk_tree_model_get (GTK_TREE_MODEL(store), &iter, 0, &name, -1); - gchar *ret = g_strdup ( name ); gtk_widget_destroy ( dialog ); - g_free(name); - return (ret); + return (name); } } gtk_widget_destroy ( dialog ); diff --git a/src/dialog.h b/src/dialog.h index 567f1965..0953b91f 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -63,5 +63,5 @@ void a_dialog_choose_dir ( GtkWidget *entry ); gboolean a_dialog_map_n_zoom(GtkWindow *parent, gchar *mapnames[], gint default_map, gchar *zoom_list[], gint default_zoom, gint *selected_map, gint *selected_zoom); -gchar *a_dialog_select_track ( GtkWindow *parent, GHashTable *tracks, gchar *orig_track_name ); +gchar *a_dialog_select_track ( GtkWindow *parent, GHashTable *tracks, const GList *track_names ); #endif diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index f14c1f09..83914497 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -2073,6 +2073,39 @@ static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] ) * merge/split by time routines *************************************/ +/* called for each key in track hash table. + * If the current track has time stamp, add it to the result, + * except the one pointed by "exclude". + * set exclude to NULL if there is no exclude to check. + * Not that result is in reverse (for performance reason). + */ +typedef struct { + GList **result; + GList *exclude; +} twt_udata; +static void find_tracks_with_timestamp(gpointer key, gpointer value, gpointer udata) +{ + twt_udata *user_data = udata; + VikTrackpoint *p1, *p2; + + if (VIK_TRACK(value)->trackpoints == user_data->exclude) { + return; + } + + if (VIK_TRACK(value)->trackpoints) { + p1 = VIK_TRACKPOINT(VIK_TRACK(value)->trackpoints->data); + p2 = VIK_TRACKPOINT(g_list_last(VIK_TRACK(value)->trackpoints)->data); + + if (!p1->has_timestamp || !p2->has_timestamp) { + g_print("no timestamp\n"); + return; + } + + } + + *(user_data->result) = g_list_prepend(*(user_data->result), key); +} + /* called for each key in track hash table. if original track user_data[1] is close enough * to the passed one, add it to list in user_data[0] */ @@ -2146,14 +2179,36 @@ static gint trackpoint_compare(gconstpointer a, gconstpointer b) static void trw_layer_merge_with_other ( gpointer pass_along[6] ) { VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0]; - gchar *orig_track_name = strdup(pass_along[3]); + gchar *orig_track_name = pass_along[3]; gchar *merge_with; + GList *tracks_with_timestamp = NULL; + VikTrack *track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, orig_track_name ); - merge_with = a_dialog_select_track(VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->tracks, orig_track_name); + if (track->trackpoints && + !VIK_TRACKPOINT(track->trackpoints->data)->has_timestamp) { + a_dialog_error_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Failed. This track does not have timestamp")); + return; + } + + if (1) { + + twt_udata udata; + udata.result = &tracks_with_timestamp; + udata.exclude = track->trackpoints; + g_hash_table_foreach(vtl->tracks, find_tracks_with_timestamp, (gpointer)&udata); + tracks_with_timestamp = g_list_reverse(tracks_with_timestamp); + } + + if (!tracks_with_timestamp) { + a_dialog_error_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Failed. No other track in this layer has timestamp")); + return; + } + + merge_with = a_dialog_select_track(VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->tracks, tracks_with_timestamp); + g_list_free(tracks_with_timestamp); if (merge_with) { - VikTrack *track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, orig_track_name ); VikTrack *merge_track = (VikTrack *) g_hash_table_lookup (vtl->tracks, merge_with ); if (merge_track) { @@ -2163,11 +2218,8 @@ static void trw_layer_merge_with_other ( gpointer pass_along[6] ) track->trackpoints = g_list_sort(track->trackpoints, trackpoint_compare); } g_free(merge_with); + vik_layer_emit_update( VIK_LAYER(vtl) ); } - free(orig_track_name); - vik_layer_emit_update( VIK_LAYER(vtl) ); - - return; } /* merge by time routine */ -- 2.39.5