]> git.street.me.uk Git - andy/viking.git/blobdiff - src/viktrwlayer_propwin.c
Replace defunct IP to location lookup service.
[andy/viking.git] / src / viktrwlayer_propwin.c
index bcc722449ac3443a71aac1f36235b8191fb24f46..be0e3d6fb1931e35b16fa7316874e7897c3f1be1 100644 (file)
@@ -41,6 +41,8 @@
 #include "dems.h"
 #include "viking.h"
 #include "vikviewport.h" /* ugh */
+#include "vikutils.h"
+#include "ui_util.h"
 #include <gdk-pixbuf/gdk-pixdata.h>
 
 typedef enum {
@@ -99,6 +101,16 @@ static const time_t chunkst[] = {
   2419200,// 4 weeks
 };
 
+// Local show settings to restore on dialog opening
+static gboolean show_dem                = TRUE;
+static gboolean show_alt_gps_speed      = TRUE;
+static gboolean show_gps_speed          = TRUE;
+static gboolean show_gradient_gps_speed = TRUE;
+static gboolean show_dist_speed         = FALSE;
+static gboolean show_elev_speed         = FALSE;
+static gboolean show_elev_dem           = FALSE;
+static gboolean show_sd_gps_speed       = TRUE;
+
 typedef struct _propsaved {
   gboolean saved;
   GdkImage *img;
@@ -119,6 +131,8 @@ typedef struct _propwidgets {
   GtkWidget *dialog;
   GtkWidget *w_comment;
   GtkWidget *w_description;
+  GtkWidget *w_source;
+  GtkWidget *w_type;
   GtkWidget *w_track_length;
   GtkWidget *w_tp_count;
   GtkWidget *w_segment_count;
@@ -156,6 +170,7 @@ typedef struct _propwidgets {
   GtkWidget *w_show_gradient_gps_speed;
   GtkWidget *w_show_dist_speed;
   GtkWidget *w_show_elev_speed;
+  GtkWidget *w_show_elev_dem;
   GtkWidget *w_show_sd_gps_speed;
   gdouble   track_length;
   gdouble   track_length_inc_gaps;
@@ -201,6 +216,7 @@ typedef struct _propwidgets {
   VikTrackpoint *blob_tp;
   gboolean  is_blob_drawn;
   time_t    duration;
+  gchar     *tz; // TimeZone at track's location
 } PropWidgets;
 
 static PropWidgets *prop_widgets_new()
@@ -735,6 +751,9 @@ void track_profile_move( GtkWidget *event_box, GdkEventMotion *event, PropWidget
     case VIK_UNITS_DISTANCE_MILES:
       g_snprintf(tmp_buf, sizeof(tmp_buf), "%.2f miles", VIK_METERS_TO_MILES(meters_from_start) );
       break;
+    case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+      g_snprintf(tmp_buf, sizeof(tmp_buf), "%.2f NM", VIK_METERS_TO_NAUTICAL_MILES(meters_from_start) );
+      break;
     default:
       g_critical("Houston, we've had a problem. distance=%d", dist_units);
     }
@@ -815,6 +834,9 @@ void track_gradient_move( GtkWidget *event_box, GdkEventMotion *event, PropWidge
     case VIK_UNITS_DISTANCE_MILES:
       g_snprintf(tmp_buf, sizeof(tmp_buf), "%.2f miles", VIK_METERS_TO_MILES(meters_from_start) );
       break;
+    case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+      g_snprintf(tmp_buf, sizeof(tmp_buf), "%.2f NM", VIK_METERS_TO_NAUTICAL_MILES(meters_from_start) );
+      break;
     default:
       g_critical("Houston, we've had a problem. distance=%d", dist_units);
     }
@@ -876,13 +898,14 @@ static void time_label_update (GtkWidget *widget, time_t seconds_from_start)
 }
 
 //
-static void real_time_label_update (GtkWidget *widget, VikTrackpoint *trackpoint)
+static void real_time_label_update ( PropWidgets *widgets, GtkWidget *widget, VikTrackpoint *trackpoint)
 {
   static gchar tmp_buf[64];
-  if ( trackpoint->has_timestamp )
+  if ( trackpoint->has_timestamp ) {
     // Alternatively could use %c format but I prefer a slightly more compact form here
     //  The full date can of course be seen on the Statistics tab
     strftime (tmp_buf, sizeof(tmp_buf), "%X %x %Z", localtime(&(trackpoint->timestamp)));
+  }
   else
     g_snprintf (tmp_buf, sizeof(tmp_buf), _("No Data"));
   gtk_label_set_text(GTK_LABEL(widget), tmp_buf);
@@ -913,7 +936,7 @@ void track_vt_move( GtkWidget *event_box, GdkEventMotion *event, PropWidgets *wi
   }
 
   if (trackpoint && widgets->w_cur_time_real) {
-    real_time_label_update ( widgets->w_cur_time_real, trackpoint );
+    real_time_label_update ( widgets, widgets->w_cur_time_real, trackpoint );
   }
 
   gint ix = (gint)x;
@@ -1007,7 +1030,7 @@ void track_dt_move( GtkWidget *event_box, GdkEventMotion *event, PropWidgets *wi
   }
 
   if (trackpoint && widgets->w_cur_dist_time_real) {
-    real_time_label_update ( widgets->w_cur_dist_time_real, trackpoint );
+    real_time_label_update ( widgets, widgets->w_cur_dist_time_real, trackpoint );
   }
 
   gint ix = (gint)x;
@@ -1017,10 +1040,17 @@ void track_dt_move( GtkWidget *event_box, GdkEventMotion *event, PropWidgets *wi
 
   if (trackpoint && widgets->w_cur_dist_dist) {
     static gchar tmp_buf[20];
-    if ( a_vik_get_units_distance () == VIK_UNITS_DISTANCE_MILES )
+    switch ( a_vik_get_units_distance () ) {
+    case VIK_UNITS_DISTANCE_MILES:
       g_snprintf(tmp_buf, sizeof(tmp_buf), "%.2f miles", widgets->distances[ix]);
-    else
+      break;
+    case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+      g_snprintf(tmp_buf, sizeof(tmp_buf), "%.2f NM", widgets->distances[ix]);
+      break;
+    default:
       g_snprintf(tmp_buf, sizeof(tmp_buf), "%.2f km", widgets->distances[ix]);
+      break;
+    }
     gtk_label_set_text(GTK_LABEL(widgets->w_cur_dist_dist), tmp_buf);
   }
 
@@ -1086,7 +1116,7 @@ void track_et_move( GtkWidget *event_box, GdkEventMotion *event, PropWidgets *wi
   }
 
   if (trackpoint && widgets->w_cur_elev_time_real) {
-    real_time_label_update ( widgets->w_cur_elev_time_real, trackpoint );
+    real_time_label_update ( widgets, widgets->w_cur_elev_time_real, trackpoint );
   }
 
   gint ix = (gint)x;
@@ -1167,6 +1197,9 @@ void track_sd_move( GtkWidget *event_box, GdkEventMotion *event, PropWidgets *wi
     case VIK_UNITS_DISTANCE_MILES:
       g_snprintf(tmp_buf, sizeof(tmp_buf), "%.2f miles", VIK_METERS_TO_MILES(meters_from_start) );
       break;
+    case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+      g_snprintf(tmp_buf, sizeof(tmp_buf), "%.2f NM", VIK_METERS_TO_NAUTICAL_MILES(meters_from_start) );
+      break;
     default:
       g_critical("Houston, we've had a problem. distance=%d", dist_units);
     }
@@ -1272,13 +1305,15 @@ static void draw_dem_alt_speed_dist(VikTrack *tr,
     x = (width * dist)/total_length + margin;
     if (do_dem) {
       gint16 elev = a_dems_get_elev_by_coord(&(VIK_TRACKPOINT(iter->data)->coord), VIK_DEM_INTERPOL_BEST);
-      elev -= alt_offset;
       if ( elev != VIK_DEM_INVALID_ELEVATION ) {
        // Convert into height units
        if (a_vik_get_units_height () == VIK_UNITS_HEIGHT_FEET)
          elev =  VIK_METERS_TO_FEET(elev);
        // No conversion needed if already in metres
 
+        // offset is in current height units
+        elev -= alt_offset;
+
         // consider chunk size
         int y_alt = h2 - ((height * elev)/achunk );
         gdk_draw_rectangle(GDK_DRAWABLE(pix), alt_gc, TRUE, x-2, y_alt-2, 4, 4);
@@ -1395,16 +1430,27 @@ static void draw_grid_x_time ( GtkWidget *window, GtkWidget *image, PropWidgets
 static void draw_grid_x_distance ( GtkWidget *window, GtkWidget *image, PropWidgets *widgets, GdkPixmap *pix, guint ii, gdouble dd, guint xx, vik_units_distance_t dist_units )
 {
   gchar *label_markup = NULL;
-  if ( dist_units == VIK_UNITS_DISTANCE_MILES )
+  switch ( dist_units ) {
+  case VIK_UNITS_DISTANCE_MILES:
     if ( ii > 4 )
       label_markup = g_strdup_printf ( "<span size=\"small\">%d %s</span>", (guint)dd, _("miles") );
     else
       label_markup = g_strdup_printf ( "<span size=\"small\">%.1f %s</span>", dd, _("miles") );
-  else
+    break;
+  case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+    if ( ii > 4 )
+      label_markup = g_strdup_printf ( "<span size=\"small\">%d %s</span>", (guint)dd, _("NM") );
+    else
+      label_markup = g_strdup_printf ( "<span size=\"small\">%.1f %s</span>", dd, _("NM") );
+    break;
+  default:
+    // VIK_UNITS_DISTANCE_KILOMETRES:
     if ( ii > 4 )
       label_markup = g_strdup_printf ( "<span size=\"small\">%d %s</span>", (guint)dd, _("km") );
     else
       label_markup = g_strdup_printf ( "<span size=\"small\">%.1f %s</span>", dd, _("km") );
+    break;
+  }
 
   if ( label_markup ) {
     PangoLayout *pl = gtk_widget_create_pango_layout (GTK_WIDGET(image), NULL);
@@ -1442,12 +1488,18 @@ static void draw_distance_divisions ( GtkWidget *window, GtkWidget *image, GdkPi
 {
   // Set to display units from length in metres.
   gdouble length = widgets->track_length_inc_gaps;
-  if ( dist_units == VIK_UNITS_DISTANCE_MILES )
-    length = VIK_METERS_TO_MILES(length);
-  else
-    // KM
-    length = length/1000.0;
-
+  switch (dist_units) {
+    case VIK_UNITS_DISTANCE_MILES:
+      length = VIK_METERS_TO_MILES(length);
+      break;
+    case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+      length = VIK_METERS_TO_NAUTICAL_MILES(length);
+      break;
+    default:
+      // KM
+      length = length/1000.0;
+      break;
+  }
   guint index = get_distance_chunk_index ( length );
   gdouble dist_per_pixel = length/widgets->profile_width;
 
@@ -1491,7 +1543,6 @@ static void draw_elevations (GtkWidget *image, VikTrack *tr, PropWidgets *widget
 
   // Assign locally
   gdouble mina = widgets->draw_min_altitude;
-  gdouble maxa = widgets->max_altitude;
 
   GtkWidget *window = gtk_widget_get_toplevel (widgets->elev_box);
   GdkPixmap *pix = gdk_pixmap_new( gtk_widget_get_window(window), widgets->profile_width+MARGIN_X, widgets->profile_height+MARGIN_Y, -1 );
@@ -1558,7 +1609,7 @@ static void draw_elevations (GtkWidget *image, VikTrack *tr, PropWidgets *widget
                            dem_alt_gc,
                            gps_speed_gc,
                            mina,
-                           maxa - mina,
+                           widgets->max_altitude - mina,
                            widgets->max_speed,
                            widgets->cia,
                            widgets->profile_width,
@@ -1721,7 +1772,7 @@ static void draw_vt ( GtkWidget *image, VikTrack *tr, PropWidgets *widgets)
   if ( widgets->speeds == NULL )
     return;
 
-  widgets->duration = vik_track_get_duration ( tr );
+  widgets->duration = vik_track_get_duration ( tr, TRUE );
   // Negative time or other problem
   if ( widgets->duration <= 0 )
     return;
@@ -1862,19 +1913,26 @@ static void draw_dt ( GtkWidget *image, VikTrack *tr, PropWidgets *widgets )
 
   // Convert into appropriate units
   vik_units_distance_t dist_units = a_vik_get_units_distance ();
-  if ( dist_units == VIK_UNITS_DISTANCE_MILES ) {
-    for ( i = 0; i < widgets->profile_width; i++ ) {
-      widgets->distances[i] = VIK_METERS_TO_MILES(widgets->distances[i]);
-    }
-  }
-  else {
-    // Metres - but want in kms
-    for ( i = 0; i < widgets->profile_width; i++ ) {
-      widgets->distances[i] = widgets->distances[i]/1000.0;
-    }
+  switch ( dist_units ) {
+    case VIK_UNITS_DISTANCE_MILES:
+      for ( i = 0; i < widgets->profile_width; i++ ) {
+        widgets->distances[i] = VIK_METERS_TO_MILES(widgets->distances[i]);
+      }
+      break;
+    case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+      for ( i = 0; i < widgets->profile_width; i++ ) {
+        widgets->distances[i] = VIK_METERS_TO_NAUTICAL_MILES(widgets->distances[i]);
+      }
+      break;
+    default:
+      // Metres - but want in kms
+      for ( i = 0; i < widgets->profile_width; i++ ) {
+        widgets->distances[i] = widgets->distances[i]/1000.0;
+      }
+      break;
   }
 
-  widgets->duration = vik_track_get_duration ( widgets->tr );
+  widgets->duration = vik_track_get_duration ( widgets->tr, TRUE );
   // Negative time or other problem
   if ( widgets->duration <= 0 )
     return;
@@ -1888,10 +1946,17 @@ static void draw_dt ( GtkWidget *image, VikTrack *tr, PropWidgets *widgets )
   // Assign locally
   // mind = 0.0; - Thus not used
   gdouble maxd;
-  if ( dist_units == VIK_UNITS_DISTANCE_MILES )
+  switch ( dist_units ) {
+  case VIK_UNITS_DISTANCE_MILES:
     maxd = VIK_METERS_TO_MILES(vik_track_get_length_including_gaps (tr));
-  else
+    break;
+  case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+    maxd = VIK_METERS_TO_NAUTICAL_MILES(vik_track_get_length_including_gaps (tr));
+    break;
+  default:
     maxd = vik_track_get_length_including_gaps (tr) / 1000.0;
+    break;
+  }
 
   /* Find suitable chunk index */
   gdouble dummy = 0.0; // expect this to remain the same! (not that it's used)
@@ -1904,10 +1969,17 @@ static void draw_dt ( GtkWidget *image, VikTrack *tr, PropWidgets *widgets )
   for (i=0; i<=LINES; i++) {
     gchar s[32];
 
-    if ( dist_units == VIK_UNITS_DISTANCE_MILES )
+    switch ( dist_units ) {
+    case VIK_UNITS_DISTANCE_MILES:
       sprintf(s, _("%.1f miles"), ((LINES-i)*chunksd[widgets->cid]));
-    else
+      break;
+    case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+      sprintf(s, _("%.1f NM"), ((LINES-i)*chunksd[widgets->cid]));
+      break;
+    default:
       sprintf(s, _("%.1f km"), ((LINES-i)*chunksd[widgets->cid]));
+      break;
+    }
 
     draw_grid_y ( window, image, widgets, pix, s, i );
   }
@@ -1978,7 +2050,7 @@ static void draw_et ( GtkWidget *image, VikTrack *tr, PropWidgets *widgets )
   // Assign locally
   gdouble mina = widgets->draw_min_altitude_time;
 
-  widgets->duration = vik_track_get_duration ( widgets->tr );
+  widgets->duration = vik_track_get_duration ( widgets->tr, TRUE );
   // Negative time or other problem
   if ( widgets->duration <= 0 )
     return;
@@ -2019,21 +2091,54 @@ static void draw_et ( GtkWidget *image, VikTrack *tr, PropWidgets *widgets )
     gdk_draw_line ( GDK_DRAWABLE(pix), gtk_widget_get_style(window)->dark_gc[3],
                     i + MARGIN_X, height, i + MARGIN_X, height-widgets->profile_height*(widgets->ats[i]-mina)/(chunksa[widgets->ciat]*LINES) );
 
-  // Show speed indicator
+  // Show DEMS
+  if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets->w_show_elev_dem)) )  {
+    GdkColor color;
+    GdkGC *dem_alt_gc = gdk_gc_new ( gtk_widget_get_window(window) );
+    gdk_color_parse ( "green", &color );
+    gdk_gc_set_rgb_fg_color ( dem_alt_gc, &color);
+
+    gint h2 = widgets->profile_height + MARGIN_Y; // Adjust height for x axis labelling offset
+    gint achunk = chunksa[widgets->ciat]*LINES;
+
+    for ( i = 0; i < widgets->profile_width; i++ ) {
+      // This could be slow doing this each time...
+      VikTrackpoint *tp = vik_track_get_closest_tp_by_percentage_time ( widgets->tr, ((gdouble)i/(gdouble)widgets->profile_width), NULL );
+      if ( tp ) {
+        gint16 elev = a_dems_get_elev_by_coord(&(tp->coord), VIK_DEM_INTERPOL_SIMPLE);
+        if ( elev != VIK_DEM_INVALID_ELEVATION ) {
+          // Convert into height units
+          if ( a_vik_get_units_height () == VIK_UNITS_HEIGHT_FEET )
+            elev = VIK_METERS_TO_FEET(elev);
+          // No conversion needed if already in metres
+
+          // offset is in current height units
+          elev -= mina;
+
+          // consider chunk size
+          int y_alt = h2 - ((widgets->profile_height * elev)/achunk );
+          gdk_draw_rectangle(GDK_DRAWABLE(pix), dem_alt_gc, TRUE, i+MARGIN_X-2, y_alt-2, 4, 4);
+        }
+      }
+    }
+    g_object_unref ( G_OBJECT(dem_alt_gc) );
+  }
+
+  // Show speeds
   if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets->w_show_elev_speed)) ) {
-    GdkGC *elev_speed_gc = gdk_gc_new ( gtk_widget_get_window(window) );
     GdkColor color;
+    // This is just an indicator - no actual values can be inferred by user
+    GdkGC *elev_speed_gc = gdk_gc_new ( gtk_widget_get_window(window) );
     gdk_color_parse ( "red", &color );
     gdk_gc_set_rgb_fg_color ( elev_speed_gc, &color);
 
-    gdouble max_speed = 0;
-    max_speed = widgets->max_speed * 110 / 100;
+    gdouble max_speed = widgets->max_speed * 110 / 100;
 
-    // This is just an indicator - no actual values can be inferred by user
     for ( i = 0; i < widgets->profile_width; i++ ) {
       int y_speed = widgets->profile_height - (widgets->profile_height * widgets->speeds[i])/max_speed;
       gdk_draw_rectangle(GDK_DRAWABLE(pix), elev_speed_gc, TRUE, i+MARGIN_X-2, y_speed-2, 4, 4);
     }
+
     g_object_unref ( G_OBJECT(elev_speed_gc) );
   }
 
@@ -2734,8 +2839,27 @@ GtkWidget *vik_trw_layer_create_sddiag ( GtkWidget *window, PropWidgets *widgets
 
 static void save_values ( PropWidgets *widgets )
 {
+  // Session settings
   a_settings_set_integer ( VIK_SETTINGS_TRACK_PROFILE_WIDTH, widgets->profile_width );
   a_settings_set_integer ( VIK_SETTINGS_TRACK_PROFILE_HEIGHT, widgets->profile_height );
+
+  // Just for this session ATM
+  if ( widgets->w_show_dem )
+    show_dem                = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(widgets->w_show_dem) );
+  if ( widgets->w_show_alt_gps_speed )
+    show_alt_gps_speed      = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(widgets->w_show_alt_gps_speed) );
+  if ( widgets->w_show_gps_speed )
+    show_gps_speed          = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(widgets->w_show_gps_speed) );
+  if ( widgets->w_show_gradient_gps_speed )
+    show_gradient_gps_speed = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(widgets->w_show_gradient_gps_speed) );
+  if ( widgets->w_show_dist_speed )
+    show_dist_speed         = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(widgets->w_show_dist_speed) );
+  if ( widgets->w_show_elev_dem )
+    show_elev_dem           = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(widgets->w_show_elev_dem) );
+  if ( widgets->w_show_elev_speed )
+    show_elev_speed         = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(widgets->w_show_elev_speed) );
+  if ( widgets->w_show_sd_gps_speed )
+    show_sd_gps_speed       = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(widgets->w_show_sd_gps_speed) );
 }
 
 static void destroy_cb ( GtkDialog *dialog, PropWidgets *widgets )
@@ -2759,6 +2883,8 @@ static void propwin_response_cb( GtkDialog *dialog, gint resp, PropWidgets *widg
     case GTK_RESPONSE_ACCEPT:
       vik_track_set_comment(tr, gtk_entry_get_text(GTK_ENTRY(widgets->w_comment)));
       vik_track_set_description(tr, gtk_entry_get_text(GTK_ENTRY(widgets->w_description)));
+      vik_track_set_source(tr, gtk_entry_get_text(GTK_ENTRY(widgets->w_source)));
+      vik_track_set_type(tr, gtk_entry_get_text(GTK_ENTRY(widgets->w_type)));
       gtk_color_button_get_color ( GTK_COLOR_BUTTON(widgets->w_color), &(tr->color) );
       tr->draw_name_mode = gtk_combo_box_get_active ( GTK_COMBO_BOX(widgets->w_namelabel) );
       tr->max_number_dist_labels = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON(widgets->w_number_distlabels) );
@@ -3009,6 +3135,8 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
   static gchar *label_texts[] = {
     N_("<b>Comment:</b>"),
     N_("<b>Description:</b>"),
+    N_("<b>Source:</b>"),
+    N_("<b>Type:</b>"),
     N_("<b>Color:</b>"),
     N_("<b>Draw Name:</b>"),
     N_("<b>Distance Labels:</b>"),
@@ -3035,15 +3163,23 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
   widgets->w_comment = gtk_entry_new ();
   if ( tr->comment )
     gtk_entry_set_text ( GTK_ENTRY(widgets->w_comment), tr->comment );
-  g_signal_connect_swapped ( widgets->w_comment, "activate", G_CALLBACK(a_dialog_response_accept), GTK_DIALOG(dialog) );
   content_prop[cnt_prop++] = widgets->w_comment;
 
   widgets->w_description = gtk_entry_new ();
   if ( tr->description )
     gtk_entry_set_text ( GTK_ENTRY(widgets->w_description), tr->description );
-  g_signal_connect_swapped ( widgets->w_description, "activate", G_CALLBACK(a_dialog_response_accept), GTK_DIALOG(dialog) );
   content_prop[cnt_prop++] = widgets->w_description;
 
+  widgets->w_source = gtk_entry_new ();
+  if ( tr->source )
+    gtk_entry_set_text ( GTK_ENTRY(widgets->w_source), tr->source );
+  content_prop[cnt_prop++] = widgets->w_source;
+
+  widgets->w_type = gtk_entry_new ();
+  if ( tr->type )
+    gtk_entry_set_text ( GTK_ENTRY(widgets->w_type), tr->type );
+  content_prop[cnt_prop++] = widgets->w_type;
+
   widgets->w_color = content_prop[cnt_prop++] = gtk_color_button_new_with_color ( &(tr->color) );
 
   static gchar *draw_name_labels[] = {
@@ -3087,21 +3223,24 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
   case VIK_UNITS_DISTANCE_MILES:
     g_snprintf(tmp_buf, sizeof(tmp_buf), "%.2f miles", VIK_METERS_TO_MILES(tr_len) );
     break;
+  case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+    g_snprintf(tmp_buf, sizeof(tmp_buf), "%.2f NM", VIK_METERS_TO_NAUTICAL_MILES(tr_len) );
+    break;
   default:
     g_critical("Houston, we've had a problem. distance=%d", dist_units);
   }
-  widgets->w_track_length = content[cnt++] = gtk_label_new ( tmp_buf );
+  widgets->w_track_length = content[cnt++] = ui_label_new_selectable ( tmp_buf );
 
   tp_count = vik_track_get_tp_count(tr);
   g_snprintf(tmp_buf, sizeof(tmp_buf), "%lu", tp_count );
-  widgets->w_tp_count = content[cnt++] = gtk_label_new ( tmp_buf );
+  widgets->w_tp_count = content[cnt++] = ui_label_new_selectable ( tmp_buf );
 
   seg_count = vik_track_get_segment_count(tr) ;
   g_snprintf(tmp_buf, sizeof(tmp_buf), "%u", seg_count );
-  widgets->w_segment_count = content[cnt++] = gtk_label_new ( tmp_buf );
+  widgets->w_segment_count = content[cnt++] = ui_label_new_selectable ( tmp_buf );
 
   g_snprintf(tmp_buf, sizeof(tmp_buf), "%lu", vik_track_get_dup_point_count(tr) );
-  widgets->w_duptp_count = content[cnt++] = gtk_label_new ( tmp_buf );
+  widgets->w_duptp_count = content[cnt++] = ui_label_new_selectable ( tmp_buf );
 
   vik_units_speed_t speed_units = a_vik_get_units_speed ();
   tmp_speed = vik_track_get_max_speed(tr);
@@ -3126,7 +3265,7 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
       g_critical("Houston, we've had a problem. speed=%d", speed_units);
     }
   }
-  widgets->w_max_speed = content[cnt++] = gtk_label_new ( tmp_buf );
+  widgets->w_max_speed = content[cnt++] = ui_label_new_selectable ( tmp_buf );
 
   tmp_speed = vik_track_get_average_speed(tr);
   if ( tmp_speed == 0 )
@@ -3150,7 +3289,7 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
       g_critical("Houston, we've had a problem. speed=%d", speed_units);
     }
   }
-  widgets->w_avg_speed = content[cnt++] = gtk_label_new ( tmp_buf );
+  widgets->w_avg_speed = content[cnt++] = ui_label_new_selectable ( tmp_buf );
 
   // Use 60sec as the default period to be considered stopped
   //  this is the TrackWaypoint draw stops default value 'vtl->stop_length'
@@ -3178,7 +3317,7 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
       g_critical("Houston, we've had a problem. speed=%d", speed_units);
     }
   }
-  widgets->w_mvg_speed = content[cnt++] = gtk_label_new ( tmp_buf );
+  widgets->w_mvg_speed = content[cnt++] = ui_label_new_selectable ( tmp_buf );
 
   switch (dist_units) {
   case VIK_UNITS_DISTANCE_KILOMETRES:
@@ -3188,10 +3327,13 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
   case VIK_UNITS_DISTANCE_MILES:
     g_snprintf(tmp_buf, sizeof(tmp_buf), "%.3f miles", (tp_count - seg_count) == 0 ? 0 : VIK_METERS_TO_MILES(tr_len / ( tp_count - seg_count )) );
     break;
+  case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
+    g_snprintf(tmp_buf, sizeof(tmp_buf), "%.3f NM", (tp_count - seg_count) == 0 ? 0 : VIK_METERS_TO_NAUTICAL_MILES(tr_len / ( tp_count - seg_count )) );
+    break;
   default:
     g_critical("Houston, we've had a problem. distance=%d", dist_units);
   }
-  widgets->w_avg_dist = content[cnt++] = gtk_label_new ( tmp_buf );
+  widgets->w_avg_dist = content[cnt++] = ui_label_new_selectable ( tmp_buf );
 
   vik_units_height_t height_units = a_vik_get_units_height ();
   if ( min_alt == VIK_DEFAULT_ALTITUDE )
@@ -3209,7 +3351,7 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
       g_critical("Houston, we've had a problem. height=%d", height_units);
     }
   }
-  widgets->w_elev_range = content[cnt++] = gtk_label_new ( tmp_buf );
+  widgets->w_elev_range = content[cnt++] = ui_label_new_selectable ( tmp_buf );
 
   vik_track_get_total_elevation_gain(tr, &max_alt, &min_alt );
   if ( min_alt == VIK_DEFAULT_ALTITUDE )
@@ -3227,7 +3369,7 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
       g_critical("Houston, we've had a problem. height=%d", height_units);
     }
   }
-  widgets->w_elev_gain = content[cnt++] = gtk_label_new ( tmp_buf );
+  widgets->w_elev_gain = content[cnt++] = ui_label_new_selectable ( tmp_buf );
 
 #if 0
 #define PACK(w) gtk_box_pack_start (GTK_BOX(right_vbox), w, FALSE, FALSE, 0);
@@ -3250,14 +3392,41 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
     t1 = VIK_TRACKPOINT(tr->trackpoints->data)->timestamp;
     t2 = VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->timestamp;
 
-    strftime (tmp_buf, sizeof(tmp_buf), "%c", localtime(&(t1)));
-    widgets->w_time_start = content[cnt++] = gtk_label_new(tmp_buf);
-
-    strftime (tmp_buf, sizeof(tmp_buf), "%c", localtime(&(t2)));
-    widgets->w_time_end = content[cnt++] = gtk_label_new(tmp_buf);
-
-    g_snprintf(tmp_buf, sizeof(tmp_buf), _("%d minutes"), (int)(t2-t1)/60);
-    widgets->w_time_dur = content[cnt++] = gtk_label_new(tmp_buf);
+    VikCoord vc;
+    // Notional center of a track is simply an average of the bounding box extremities
+    struct LatLon center = { (tr->bbox.north+tr->bbox.south)/2, (tr->bbox.east+tr->bbox.west)/2 };
+    vik_coord_load_from_latlon ( &vc, vik_trw_layer_get_coord_mode(vtl), &center );
+
+    widgets->tz = vu_get_tz_at_location ( &vc );
+
+    gchar *msg;
+    msg = vu_get_time_string ( &t1, "%c", &vc, widgets->tz );
+    widgets->w_time_start = content[cnt++] = ui_label_new_selectable(msg);
+    g_free ( msg );
+
+    msg = vu_get_time_string ( &t2, "%c", &vc, widgets->tz );
+    widgets->w_time_end = content[cnt++] = ui_label_new_selectable(msg);
+    g_free ( msg );
+
+    gint total_duration_s = (gint)(t2-t1);
+    gint segments_duration_s = (gint)vik_track_get_duration(tr,FALSE);
+    gint total_duration_m = total_duration_s/60;
+    gint segments_duration_m = segments_duration_s/60;
+    g_snprintf(tmp_buf, sizeof(tmp_buf), _("%d minutes - %d minutes moving"), total_duration_m, segments_duration_m);
+    widgets->w_time_dur = content[cnt++] = ui_label_new_selectable(tmp_buf);
+
+    // A tooltip to show in more readable hours:minutes
+    gchar tip_buf_total[20];
+    guint h_tot = total_duration_s/3600;
+    guint m_tot = (total_duration_s - h_tot*3600)/60;
+    g_snprintf(tip_buf_total, sizeof(tip_buf_total), "%d:%02d", h_tot, m_tot);
+    gchar tip_buf_segments[20];
+    guint h_seg = segments_duration_s/3600;
+    guint m_seg = (segments_duration_s - h_seg*3600)/60;
+    g_snprintf(tip_buf_segments, sizeof(tip_buf_segments), "%d:%02d", h_seg, m_seg);
+    gchar *tip = g_strdup_printf (_("%s total - %s in segments"), tip_buf_total, tip_buf_segments);
+    gtk_widget_set_tooltip_text ( GTK_WIDGET(widgets->w_time_dur), tip );
+    g_free (tip);
   } else {
     widgets->w_time_start = content[cnt++] = gtk_label_new(_("No Data"));
     widgets->w_time_end = content[cnt++] = gtk_label_new(_("No Data"));
@@ -3270,16 +3439,16 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
 
   if ( widgets->elev_box ) {
     GtkWidget *page = NULL;
-    widgets->w_cur_dist = gtk_label_new(_("No Data"));
-    widgets->w_cur_elevation = gtk_label_new(_("No Data"));
+    widgets->w_cur_dist = ui_label_new_selectable(_("No Data"));
+    widgets->w_cur_elevation = ui_label_new_selectable(_("No Data"));
     widgets->w_show_dem = gtk_check_button_new_with_mnemonic(_("Show D_EM"));
     widgets->w_show_alt_gps_speed = gtk_check_button_new_with_mnemonic(_("Show _GPS Speed"));
     page = create_graph_page (widgets->elev_box,
                               _("<b>Track Distance:</b>"), widgets->w_cur_dist,
                               _("<b>Track Height:</b>"), widgets->w_cur_elevation,
                               NULL, NULL,
-                              widgets->w_show_dem, TRUE,
-                              widgets->w_show_alt_gps_speed, TRUE);
+                              widgets->w_show_dem, show_dem,
+                              widgets->w_show_alt_gps_speed, show_alt_gps_speed);
     g_signal_connect (widgets->w_show_dem, "toggled", G_CALLBACK (checkbutton_toggle_cb), widgets);
     g_signal_connect (widgets->w_show_alt_gps_speed, "toggled", G_CALLBACK (checkbutton_toggle_cb), widgets);
     gtk_notebook_append_page(GTK_NOTEBOOK(graphs), page, gtk_label_new(_("Elevation-distance")));
@@ -3287,14 +3456,14 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
 
   if ( widgets->gradient_box ) {
     GtkWidget *page = NULL;
-    widgets->w_cur_gradient_dist = gtk_label_new(_("No Data"));
-    widgets->w_cur_gradient_gradient = gtk_label_new(_("No Data"));
+    widgets->w_cur_gradient_dist = ui_label_new_selectable(_("No Data"));
+    widgets->w_cur_gradient_gradient = ui_label_new_selectable(_("No Data"));
     widgets->w_show_gradient_gps_speed = gtk_check_button_new_with_mnemonic(_("Show _GPS Speed"));
     page = create_graph_page (widgets->gradient_box,
                               _("<b>Track Distance:</b>"), widgets->w_cur_gradient_dist,
                               _("<b>Track Gradient:</b>"), widgets->w_cur_gradient_gradient,
                               NULL, NULL,
-                              widgets->w_show_gradient_gps_speed, TRUE,
+                              widgets->w_show_gradient_gps_speed, show_gradient_gps_speed,
                               NULL, FALSE);
     g_signal_connect (widgets->w_show_gradient_gps_speed, "toggled", G_CALLBACK (checkbutton_toggle_cb), widgets);
     gtk_notebook_append_page(GTK_NOTEBOOK(graphs), page, gtk_label_new(_("Gradient-distance")));
@@ -3302,15 +3471,15 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
 
   if ( widgets->speed_box ) {
     GtkWidget *page = NULL;
-    widgets->w_cur_time = gtk_label_new(_("No Data"));
-    widgets->w_cur_speed = gtk_label_new(_("No Data"));
-    widgets->w_cur_time_real = gtk_label_new(_("No Data"));
+    widgets->w_cur_time = ui_label_new_selectable(_("No Data"));
+    widgets->w_cur_speed = ui_label_new_selectable(_("No Data"));
+    widgets->w_cur_time_real = ui_label_new_selectable(_("No Data"));
     widgets->w_show_gps_speed = gtk_check_button_new_with_mnemonic(_("Show _GPS Speed"));
     page = create_graph_page (widgets->speed_box,
                               _("<b>Track Time:</b>"), widgets->w_cur_time,
                               _("<b>Track Speed:</b>"), widgets->w_cur_speed,
                               _("<b>Time/Date:</b>"), widgets->w_cur_time_real,
-                              widgets->w_show_gps_speed, TRUE,
+                              widgets->w_show_gps_speed, show_gps_speed,
                               NULL, FALSE);
     g_signal_connect (widgets->w_show_gps_speed, "toggled", G_CALLBACK (checkbutton_toggle_cb), widgets);
     gtk_notebook_append_page(GTK_NOTEBOOK(graphs), page, gtk_label_new(_("Speed-time")));
@@ -3318,15 +3487,15 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
 
   if ( widgets->dist_box ) {
     GtkWidget *page = NULL;
-    widgets->w_cur_dist_time = gtk_label_new(_("No Data"));
-    widgets->w_cur_dist_dist = gtk_label_new(_("No Data"));
-    widgets->w_cur_dist_time_real = gtk_label_new(_("No Data"));
+    widgets->w_cur_dist_time = ui_label_new_selectable(_("No Data"));
+    widgets->w_cur_dist_dist = ui_label_new_selectable(_("No Data"));
+    widgets->w_cur_dist_time_real = ui_label_new_selectable(_("No Data"));
     widgets->w_show_dist_speed = gtk_check_button_new_with_mnemonic(_("Show S_peed"));
     page = create_graph_page (widgets->dist_box,
                               _("<b>Track Distance:</b>"), widgets->w_cur_dist_dist,
                               _("<b>Track Time:</b>"), widgets->w_cur_dist_time,
                               _("<b>Time/Date:</b>"), widgets->w_cur_dist_time_real,
-                              widgets->w_show_dist_speed, FALSE,
+                              widgets->w_show_dist_speed, show_dist_speed,
                               NULL, FALSE);
     g_signal_connect (widgets->w_show_dist_speed, "toggled", G_CALLBACK (checkbutton_toggle_cb), widgets);
     gtk_notebook_append_page(GTK_NOTEBOOK(graphs), page, gtk_label_new(_("Distance-time")));
@@ -3334,30 +3503,32 @@ void vik_trw_layer_propwin_run ( GtkWindow *parent,
 
   if ( widgets->elev_time_box ) {
     GtkWidget *page = NULL;
-    widgets->w_cur_elev_time = gtk_label_new(_("No Data"));
-    widgets->w_cur_elev_elev = gtk_label_new(_("No Data"));
-    widgets->w_cur_elev_time_real = gtk_label_new(_("No Data"));
+    widgets->w_cur_elev_time = ui_label_new_selectable(_("No Data"));
+    widgets->w_cur_elev_elev = ui_label_new_selectable(_("No Data"));
+    widgets->w_cur_elev_time_real = ui_label_new_selectable(_("No Data"));
     widgets->w_show_elev_speed = gtk_check_button_new_with_mnemonic(_("Show S_peed"));
+    widgets->w_show_elev_dem = gtk_check_button_new_with_mnemonic(_("Show D_EM"));
     page = create_graph_page (widgets->elev_time_box,
                               _("<b>Track Time:</b>"), widgets->w_cur_elev_time,
                               _("<b>Track Height:</b>"), widgets->w_cur_elev_elev,
                               _("<b>Time/Date:</b>"), widgets->w_cur_elev_time_real,
-                              widgets->w_show_elev_speed, FALSE,
-                              NULL, FALSE);
+                              widgets->w_show_elev_dem, show_elev_dem,
+                              widgets->w_show_elev_speed, show_elev_speed);
+    g_signal_connect (widgets->w_show_elev_dem, "toggled", G_CALLBACK (checkbutton_toggle_cb), widgets);
     g_signal_connect (widgets->w_show_elev_speed, "toggled", G_CALLBACK (checkbutton_toggle_cb), widgets);
     gtk_notebook_append_page(GTK_NOTEBOOK(graphs), page, gtk_label_new(_("Elevation-time")));
   }
 
   if ( widgets->speed_dist_box ) {
     GtkWidget *page = NULL;
-    widgets->w_cur_speed_dist = gtk_label_new(_("No Data"));
-    widgets->w_cur_speed_speed = gtk_label_new(_("No Data"));
+    widgets->w_cur_speed_dist = ui_label_new_selectable(_("No Data"));
+    widgets->w_cur_speed_speed = ui_label_new_selectable(_("No Data"));
     widgets->w_show_sd_gps_speed = gtk_check_button_new_with_mnemonic(_("Show _GPS Speed"));
     page = create_graph_page (widgets->speed_dist_box,
                               _("<b>Track Distance:</b>"), widgets->w_cur_speed_dist,
                               _("<b>Track Speed:</b>"), widgets->w_cur_speed_speed,
                               NULL, NULL,
-                              widgets->w_show_sd_gps_speed, TRUE,
+                              widgets->w_show_sd_gps_speed, show_sd_gps_speed,
                               NULL, FALSE);
     g_signal_connect (widgets->w_show_sd_gps_speed, "toggled", G_CALLBACK (checkbutton_toggle_cb), widgets);
     gtk_notebook_append_page(GTK_NOTEBOOK(graphs), page, gtk_label_new(_("Speed-distance")));