From b45865b4d393f3ec0353bd5cc634cf1784f68a39 Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Mon, 9 Sep 2013 23:53:19 +0100 Subject: [PATCH] SF Features#76: Add ability to handle and name trackpoints. Normally these are more useful for named routepoints, but applies to trackpoints as well. Process named points in GPX files. Extend .vik files to save named trackpoints. Rework Trackpoint dialog to display and make trackpoint name editable. Shift the TrackWaypoint name into Trackpoint dialog title. Extend the statusbar to display trackpoint name when selected trackpoint has a name. --- help/C/viking.xml | 3 ++- src/gpspoint.c | 7 ++++++ src/gpx.c | 16 ++++++++++++++ src/viktrack.c | 16 ++++++++++++++ src/viktrack.h | 3 +++ src/viktrwlayer.c | 2 +- src/viktrwlayer_tpwin.c | 49 ++++++++++++++++++++++++++++++++--------- src/vikutils.c | 7 ++++++ 8 files changed, 90 insertions(+), 13 deletions(-) diff --git a/help/C/viking.xml b/help/C/viking.xml index 95c089d4..0c811f73 100644 --- a/help/C/viking.xml +++ b/help/C/viking.xml @@ -2652,7 +2652,7 @@ Accept: */* This string is in the Message Format Code - trkpt_selected_statusbar_format=KATDN + trkpt_selected_statusbar_format=KEATDN This string is in the Message Format Code @@ -2679,6 +2679,7 @@ Accept: */* D = Distance of the trackpoint from the start of a track (following along the track) P = Distance difference of the trackpoint from the previous trackpoint N = Name of track to which the trackpoint belongs + E = Name of the trackpoint diff --git a/src/gpspoint.c b/src/gpspoint.c index 77d1f6eb..3c095a14 100644 --- a/src/gpspoint.c +++ b/src/gpspoint.c @@ -285,6 +285,7 @@ gboolean a_gpspoint_read_file(VikTrwLayer *trw, FILE *f ) { tp->has_timestamp = line_has_timestamp; tp->timestamp = line_timestamp; tp->altitude = line_altitude; + vik_trackpoint_set_name ( tp, line_name ); if (line_extended) { tp->speed = line_speed; tp->course = line_course; @@ -575,6 +576,12 @@ static void a_gpspoint_write_trackpoint ( VikTrackpoint *tp, TP_write_info_type g_free ( s_lat ); g_free ( s_lon ); + if ( tp->name ) { + gchar *name = slashdup(tp->name); + fprintf ( f, " name=\"%s\"", name ); + g_free(name); + } + if ( tp->altitude != VIK_DEFAULT_ALTITUDE ) { gchar *s_alt = a_coords_dtostr(tp->altitude); fprintf ( f, " altitude=\"%s\"", s_alt ); diff --git a/src/gpx.c b/src/gpx.c index c1ddabf5..cd54ba9a 100644 --- a/src/gpx.c +++ b/src/gpx.c @@ -69,6 +69,7 @@ typedef enum { tt_trk_trkseg_trkpt, tt_trk_trkseg_trkpt_ele, tt_trk_trkseg_trkpt_time, + tt_trk_trkseg_trkpt_name, /* extended */ tt_trk_trkseg_trkpt_course, tt_trk_trkseg_trkpt_speed, @@ -125,6 +126,7 @@ tag_mapping tag_path_map[] = { { tt_trk_trkseg_trkpt, "/gpx/trk/trkseg/trkpt" }, { tt_trk_trkseg_trkpt_ele, "/gpx/trk/trkseg/trkpt/ele" }, { tt_trk_trkseg_trkpt_time, "/gpx/trk/trkseg/trkpt/time" }, + { tt_trk_trkseg_trkpt_name, "/gpx/trk/trkseg/trkpt/name" }, /* extended */ { tt_trk_trkseg_trkpt_course, "/gpx/trk/trkseg/trkpt/course" }, { tt_trk_trkseg_trkpt_speed, "/gpx/trk/trkseg/trkpt/speed" }, @@ -141,6 +143,7 @@ tag_mapping tag_path_map[] = { { tt_trk_cmt, "/gpx/rte/cmt" }, { tt_trk_desc, "/gpx/rte/desc" }, { tt_trk_trkseg_trkpt, "/gpx/rte/rtept" }, + { tt_trk_trkseg_trkpt_name, "/gpx/rte/rtept/name" }, { tt_trk_trkseg_trkpt_ele, "/gpx/rte/rtept/ele" }, {0} @@ -246,6 +249,7 @@ static void gpx_start(VikTrwLayer *vtl, const char *el, const char **attr) } break; + case tt_trk_trkseg_trkpt_name: case tt_trk_trkseg_trkpt_ele: case tt_trk_trkseg_trkpt_time: case tt_wpt_cmt: @@ -379,6 +383,11 @@ static void gpx_end(VikTrwLayer *vtl, const char *el) g_string_erase ( c_cdata, 0, -1 ); break; + case tt_trk_trkseg_trkpt_name: + vik_trackpoint_set_name ( c_tp, c_cdata->str ); + g_string_erase ( c_cdata, 0, -1 ); + break; + case tt_trk_trkseg_trkpt_time: if ( g_time_val_from_iso8601(c_cdata->str, &tp_time) ) { c_tp->timestamp = tp_time.tv_sec; @@ -448,6 +457,7 @@ static void gpx_cdata(void *dta, const XML_Char *s, int len) case tt_trk_desc: case tt_trk_trkseg_trkpt_time: case tt_wpt_time: + case tt_trk_trkseg_trkpt_name: case tt_trk_trkseg_trkpt_course: case tt_trk_trkseg_trkpt_speed: case tt_trk_trkseg_trkpt_fix: @@ -768,6 +778,12 @@ static void gpx_write_trackpoint ( VikTrackpoint *tp, GpxWritingContext *context g_free ( s_lat ); s_lat = NULL; g_free ( s_lon ); s_lon = NULL; + if (tp->name) { + gchar *s_name = entitize(tp->name); + fprintf ( f, " %s\n", s_name ); + g_free(s_name); + } + s_alt = NULL; if ( tp->altitude != VIK_DEFAULT_ALTITUDE ) { diff --git a/src/viktrack.c b/src/viktrack.c index 4d8c7f07..3ac95a98 100644 --- a/src/viktrack.c +++ b/src/viktrack.c @@ -155,6 +155,7 @@ VikTrack *vik_track_copy ( const VikTrack *tr, gboolean copy_points ) VikTrack *new_tr = vik_track_new(); VikTrackpoint *new_tp; GList *tp_iter = tr->trackpoints; + new_tr->name = g_strdup(tr->name); new_tr->visible = tr->visible; new_tr->is_route = tr->is_route; new_tr->draw_name_mode = tr->draw_name_mode; @@ -193,9 +194,24 @@ VikTrackpoint *vik_trackpoint_new() void vik_trackpoint_free(VikTrackpoint *tp) { + g_free(tp->name); g_free(tp); } +void vik_trackpoint_set_name(VikTrackpoint *tp, const gchar *name) +{ + if ( tp->name ) + g_free ( tp->name ); + + // If the name is blank then completely remove it + if ( name && name[0] == '\0' ) + tp->name = NULL; + else if ( name ) + tp->name = g_strdup(name); + else + tp->name = NULL; +} + VikTrackpoint *vik_trackpoint_copy(VikTrackpoint *tp) { VikTrackpoint *rv = vik_trackpoint_new(); diff --git a/src/viktrack.h b/src/viktrack.h index eac97b72..be7cb454 100644 --- a/src/viktrack.h +++ b/src/viktrack.h @@ -38,6 +38,7 @@ G_BEGIN_DECLS typedef struct _VikTrackpoint VikTrackpoint; struct _VikTrackpoint { + gchar* name; VikCoord coord; gboolean newsegment; gboolean has_timestamp; @@ -101,6 +102,8 @@ void vik_track_set_comment_no_copy(VikTrack *tr, gchar *comment); VikTrackpoint *vik_trackpoint_new(); void vik_trackpoint_free(VikTrackpoint *tp); VikTrackpoint *vik_trackpoint_copy(VikTrackpoint *tp); +void vik_trackpoint_set_name(VikTrackpoint *tp, const gchar *name); + void vik_track_add_trackpoint(VikTrack *tr, VikTrackpoint *tp, gboolean recalculate); gdouble vik_track_get_length_to_trackpoint (const VikTrack *tr, const VikTrackpoint *tp); gdouble vik_track_get_length(const VikTrack *tr); diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index 261ab454..b8b1a47f 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -2648,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; } diff --git a/src/viktrwlayer_tpwin.c b/src/viktrwlayer_tpwin.c index 3e741e25..ad290360 100644 --- a/src/viktrwlayer_tpwin.c +++ b/src/viktrwlayer_tpwin.c @@ -39,7 +39,8 @@ struct _VikTrwLayerTpwin { GtkDialog parent; GtkSpinButton *lat, *lon, *alt; - GtkLabel *track_name, *course, *ts, *localtime, *diff_dist, *diff_time, *diff_speed, *speed, *hdop, *vdop, *pdop, *sat; + GtkWidget *trkpt_name; + GtkLabel *course, *ts, *localtime, *diff_dist, *diff_time, *diff_speed, *speed, *hdop, *vdop, *pdop, *sat; // Previously these buttons were in a glist, however I think the ordering behaviour is implicit // thus control manually to ensure operating on the correct button GtkWidget *button_close; @@ -114,9 +115,16 @@ static void tpwin_sync_alt_to_tp ( VikTrwLayerTpwin *tpwin ) } } +static void tpwin_set_name ( VikTrwLayerTpwin *tpwin ) +{ + if ( tpwin->cur_tp && (!tpwin->sync_to_tp_block) ) { + vik_trackpoint_set_name ( tpwin->cur_tp, gtk_entry_get_text(GTK_ENTRY(tpwin->trkpt_name)) ); + } +} + VikTrwLayerTpwin *vik_trw_layer_tpwin_new ( GtkWindow *parent ) { - static gchar *left_label_texts[] = { N_("Part of Track:"), + static gchar *left_label_texts[] = { N_("Name:"), N_("Latitude:"), N_("Longitude:"), N_("Altitude:"), @@ -135,7 +143,6 @@ VikTrwLayerTpwin *vik_trw_layer_tpwin_new ( GtkWindow *parent ) VikTrwLayerTpwin *tpwin = VIK_TRW_LAYER_TPWIN ( g_object_new ( VIK_TRW_LAYER_TPWIN_TYPE, NULL ) ); GtkWidget *main_hbox, *left_vbox, *right_vbox; GtkWidget *diff_left_vbox, *diff_right_vbox; - gtk_window_set_transient_for ( GTK_WINDOW(tpwin), parent ); gtk_window_set_title ( GTK_WINDOW(tpwin), _("Trackpoint") ); @@ -162,7 +169,9 @@ VikTrwLayerTpwin *vik_trw_layer_tpwin_new ( GtkWindow *parent ) /* main track info */ left_vbox = a_dialog_create_label_vbox ( left_label_texts, G_N_ELEMENTS(left_label_texts), 1, 3 ); - tpwin->track_name = GTK_LABEL(gtk_label_new(NULL)); + tpwin->trkpt_name = gtk_entry_new(); + g_signal_connect_swapped ( G_OBJECT(tpwin->trkpt_name), "focus-out-event", G_CALLBACK(tpwin_set_name), tpwin ); + tpwin->course = GTK_LABEL(gtk_label_new(NULL)); tpwin->ts = GTK_LABEL(gtk_label_new(NULL)); tpwin->localtime = GTK_LABEL(gtk_label_new(NULL)); @@ -181,7 +190,7 @@ VikTrwLayerTpwin *vik_trw_layer_tpwin_new ( GtkWindow *parent ) g_signal_connect_swapped ( G_OBJECT(tpwin->alt), "value-changed", G_CALLBACK(tpwin_sync_alt_to_tp), tpwin ); right_vbox = gtk_vbox_new ( TRUE, 1 ); - gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->track_name), FALSE, FALSE, 3 ); + gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->trkpt_name), FALSE, FALSE, 3 ); gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->lat), FALSE, FALSE, 3 ); gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->lon), FALSE, FALSE, 3 ); gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->alt), FALSE, FALSE, 3 ); @@ -223,12 +232,21 @@ VikTrwLayerTpwin *vik_trw_layer_tpwin_new ( GtkWindow *parent ) tpwin->cur_tp = NULL; + GtkWidget *response_w = NULL; +#if GTK_CHECK_VERSION (2, 20, 0) + response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(tpwin), VIK_TRW_LAYER_TPWIN_CLOSE ); +#endif + if ( response_w ) + gtk_widget_grab_focus ( response_w ); + return tpwin; } void vik_trw_layer_tpwin_set_empty ( VikTrwLayerTpwin *tpwin ) { - gtk_label_set_text ( tpwin->track_name, NULL ); + gtk_editable_delete_text ( GTK_EDITABLE(tpwin->trkpt_name), 0, -1 ); + gtk_widget_set_sensitive ( tpwin->trkpt_name, FALSE ); + gtk_label_set_text ( tpwin->ts, NULL ); gtk_label_set_text ( tpwin->localtime, NULL ); gtk_label_set_text ( tpwin->course, NULL ); @@ -252,6 +270,8 @@ void vik_trw_layer_tpwin_set_empty ( VikTrwLayerTpwin *tpwin ) gtk_label_set_text ( tpwin->hdop, NULL ); gtk_label_set_text ( tpwin->pdop, NULL ); gtk_label_set_text ( tpwin->sat, NULL ); + + gtk_window_set_title ( GTK_WINDOW(tpwin), _("Trackpoint") ); } void vik_trw_layer_tpwin_set_tp ( VikTrwLayerTpwin *tpwin, GList *tpl, const gchar *track_name ) @@ -260,6 +280,12 @@ void vik_trw_layer_tpwin_set_tp ( VikTrwLayerTpwin *tpwin, GList *tpl, const gch static struct LatLon ll; VikTrackpoint *tp = VIK_TRACKPOINT(tpl->data); + if ( tp->name ) + gtk_entry_set_text ( GTK_ENTRY(tpwin->trkpt_name), tp->name ); + else + gtk_editable_delete_text ( GTK_EDITABLE(tpwin->trkpt_name), 0, -1 ); + gtk_widget_set_sensitive ( tpwin->trkpt_name, TRUE ); + /* Only can insert if not at the end (otherwise use extend track) */ gtk_widget_set_sensitive ( tpwin->button_insert, (gboolean) GPOINTER_TO_INT (tpl->next) ); gtk_widget_set_sensitive ( tpwin->button_delete, TRUE ); @@ -274,7 +300,7 @@ void vik_trw_layer_tpwin_set_tp ( VikTrwLayerTpwin *tpwin, GList *tpl, const gch gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->lon), TRUE ); gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->alt), TRUE ); - gtk_label_set_text ( tpwin->track_name, track_name ); + vik_trw_layer_tpwin_set_track_name ( tpwin, track_name ); tpwin->sync_to_tp_block = TRUE; /* don't update while setting data. */ @@ -294,9 +320,7 @@ void vik_trw_layer_tpwin_set_tp ( VikTrwLayerTpwin *tpwin, GList *tpl, const gch g_critical("Houston, we've had a problem. height=%d", height_units); } - - tpwin->sync_to_tp_block = FALSE; /* don't update whlie setting data. */ - + tpwin->sync_to_tp_block = FALSE; // don't update while setting data. if ( tp->has_timestamp ) { @@ -427,5 +451,8 @@ void vik_trw_layer_tpwin_set_tp ( VikTrwLayerTpwin *tpwin, GList *tpl, const gch void vik_trw_layer_tpwin_set_track_name ( VikTrwLayerTpwin *tpwin, const gchar *track_name ) { - gtk_label_set_text ( tpwin->track_name, track_name ); + gchar *tmp_name = g_strdup_printf ( "%s: %s", track_name, _("Trackpoint") ); + gtk_window_set_title ( GTK_WINDOW(tpwin), tmp_name ); + g_free ( tmp_name ); + //gtk_label_set_text ( tpwin->track_name, track_name ); } diff --git a/src/vikutils.c b/src/vikutils.c index b168af4c..e14e9b78 100644 --- a/src/vikutils.c +++ b/src/vikutils.c @@ -232,6 +232,13 @@ gchar* vu_trackpoint_formatted_message ( gchar *format_code, VikTrackpoint *trkp values[i] = g_strdup_printf ( _("%sTrack: %s"), separator, trk->name ); break; + case 'E': // Name of trackpoint if available + if ( trkpt->name ) + values[i] = g_strdup_printf ( "%s%s", separator, trkpt->name ); + else + values[i] = g_strdup ( "" ); + break; + default: break; } -- 2.39.5