From 8ada46de3691a9d89c4fba390cecc67cf71acf81 Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Fri, 2 May 2014 00:32:45 +0100 Subject: [PATCH] SF Features#95 - Part 1: Allow and use configuration of an alternative time display. Add an option consisting of none, UTC, or (Object's) Positional Local Time. For several places where a time is displayed, show a tooltip of the time in the manner specified by the alternate time option. Places with times shown with this tooltip option are: Trackpoint Properties Waypoint Properties Track Properties The 'Positional Local Time' setting will attempt to work out the timezone at the position of the point (or Track's center) For the first stage of implementation a simple longitude to hours offset calculation is used (longitude/15). This will become the fallback when the real lookup implementation is added. --- src/dialog.c | 14 ++++++------ src/globals.c | 13 ++++++++++- src/globals.h | 9 ++++++++ src/viktrwlayer.c | 36 +++++++++++++++++++++---------- src/viktrwlayer_propwin.c | 20 ++++++++++++----- src/viktrwlayer_tpwin.c | 34 ++++++++++++++--------------- src/vikutils.c | 45 +++++++++++++++++++++++++++++++++++++++ src/vikutils.h | 2 ++ 8 files changed, 133 insertions(+), 40 deletions(-) diff --git a/src/dialog.c b/src/dialog.c index 67a6a8f4..1f590ee5 100644 --- a/src/dialog.c +++ b/src/dialog.c @@ -32,6 +32,7 @@ #include "authors.h" #include "documenters.h" #include "vikgoto.h" +#include "vikutils.h" #include "util.h" #include "geotag_exif.h" #include "vikdatetime_edit_dialog.h" @@ -181,11 +182,11 @@ void a_dialog_response_accept ( GtkDialog *dialog ) gtk_dialog_response ( dialog, GTK_RESPONSE_ACCEPT ); } -static void update_time ( GtkWidget *widget, time_t timestamp ) +static void update_time ( GtkWidget *widget, VikWaypoint *wp ) { - gchar tmp_str[64]; - strftime ( tmp_str, sizeof(tmp_str), "%c", localtime(&(timestamp)) ); - gtk_button_set_label ( GTK_BUTTON(widget), tmp_str ); + gchar *msg = vu_get_time_string ( &(wp->timestamp), "%c", &(wp->coord), NULL ); + gtk_button_set_label ( GTK_BUTTON(widget), msg ); + g_free ( msg ); } static VikWaypoint *edit_wp; @@ -210,7 +211,7 @@ static void time_edit_click ( GtkWidget *widget, VikWaypoint *wp ) if ( gtk_button_get_image ( GTK_BUTTON(widget) ) ) gtk_button_set_image ( GTK_BUTTON(widget), NULL ); - update_time ( widget, edit_wp->timestamp ); + update_time ( widget, edit_wp ); } static void symbol_entry_changed_cb(GtkWidget *combo, GtkListStore *store) @@ -385,11 +386,12 @@ gchar *a_dialog_waypoint ( GtkWindow *parent, gchar *default_name, VikTrwLayer * if ( !edit_wp ) edit_wp = vik_waypoint_new (); + edit_wp = vik_waypoint_copy ( wp ); // TODO: Consider if there should be a remove time button... if ( !is_new && wp->has_timestamp ) { - update_time ( timevaluebutton, wp->timestamp ); + update_time ( timevaluebutton, wp ); } else { GtkWidget *img = gtk_image_new_from_stock ( GTK_STOCK_ADD, GTK_ICON_SIZE_MENU ); diff --git a/src/globals.c b/src/globals.c index 9f7f042a..b4f2ab27 100644 --- a/src/globals.c +++ b/src/globals.c @@ -70,7 +70,7 @@ static gchar * params_units_speed[] = {"km/h", "mph", "m/s", "knots", NULL}; static gchar * params_units_height[] = {"Metres", "Feet", NULL}; static VikLayerParamScale params_scales_lat[] = { {-90.0, 90.0, 0.05, 2} }; static VikLayerParamScale params_scales_long[] = { {-180.0, 180.0, 0.05, 2} }; -static gchar * params_vik_fileref[] = {N_("Absolute"), N_("Relative"), NULL}; +static gchar * params_time_ref_frame[] = {N_("Locale"), N_("World"), N_("UTC"), NULL}; static VikLayerParam general_prefs[] = { { VIK_LAYER_NUM_TYPES, VIKING_PREFERENCES_NAMESPACE "degree_format", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Degree format:"), VIK_LAYER_WIDGET_COMBOBOX, params_degree_formats, NULL, NULL, NULL, NULL, NULL }, @@ -80,6 +80,8 @@ static VikLayerParam general_prefs[] = { { VIK_LAYER_NUM_TYPES, VIKING_PREFERENCES_NAMESPACE "use_large_waypoint_icons", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Use large waypoint icons:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, NULL, NULL, NULL }, { VIK_LAYER_NUM_TYPES, VIKING_PREFERENCES_NAMESPACE "default_latitude", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_GROUP_NONE, N_("Default latitude:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales_lat, NULL, NULL, NULL, NULL, NULL }, { VIK_LAYER_NUM_TYPES, VIKING_PREFERENCES_NAMESPACE "default_longitude", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_GROUP_NONE, N_("Default longitude:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales_long, NULL, NULL, NULL, NULL, NULL }, + { VIK_LAYER_NUM_TYPES, VIKING_PREFERENCES_NAMESPACE "time_reference_frame", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Time Display:"), VIK_LAYER_WIDGET_COMBOBOX, params_time_ref_frame, NULL, + N_("Display times according to the reference frame. Locale is the user's system setting. World is relative to the location of the object."), NULL, NULL, NULL }, }; /* External/Export Options */ @@ -106,6 +108,7 @@ static VikLayerParam io_prefs_external_gpx[] = { { VIK_LAYER_NUM_TYPES, VIKING_PREFERENCES_IO_NAMESPACE "external_gpx_2", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("External GPX Program 2:"), VIK_LAYER_WIDGET_FILEENTRY, NULL, NULL, NULL, NULL, NULL, NULL }, }; +static gchar * params_vik_fileref[] = {N_("Absolute"), N_("Relative"), NULL}; static VikLayerParamScale params_recent_files[] = { {-1, 25, 1, 0} }; static VikLayerParam prefs_advanced[] = { @@ -189,6 +192,9 @@ void a_vik_preferences_init () tmp.d = -74.007130; a_preferences_register(&general_prefs[6], tmp, VIKING_PREFERENCES_GROUP_KEY); + tmp.u = VIK_TIME_REF_LOCALE; + a_preferences_register(&general_prefs[7], tmp, VIKING_PREFERENCES_GROUP_KEY); + // New Tab a_preferences_register_group ( VIKING_PREFERENCES_STARTUP_GROUP_KEY, _("Startup") ); @@ -296,6 +302,11 @@ gdouble a_vik_get_default_long ( ) return data; } +vik_time_ref_frame_t a_vik_get_time_ref_frame ( ) +{ + return a_preferences_get(VIKING_PREFERENCES_NAMESPACE "time_reference_frame")->u; +} + /* External/Export Options */ vik_kml_export_units_t a_vik_get_kml_export_units ( ) diff --git a/src/globals.h b/src/globals.h index d81bfec3..29a5b49e 100644 --- a/src/globals.h +++ b/src/globals.h @@ -132,6 +132,15 @@ typedef enum { gdouble a_vik_get_default_lat ( ); gdouble a_vik_get_default_long ( ); +// Time display format +typedef enum { + VIK_TIME_REF_LOCALE, // User's locale + VIK_TIME_REF_WORLD, // Derive the local timezone at the object's position + VIK_TIME_REF_UTC, +} vik_time_ref_frame_t; + +vik_time_ref_frame_t a_vik_get_time_ref_frame ( ); + /* KML export preferences */ typedef enum { VIK_KML_EXPORT_UNITS_METRIC, diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index 09e30fb7..da2e3922 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -8495,6 +8495,16 @@ static void trw_layer_cancel_current_tp ( VikTrwLayer *vtl, gboolean destroy ) } } +static void my_tpwin_set_tp ( VikTrwLayer *vtl ) +{ + VikTrack *trk = vtl->current_tp_track; + VikCoord vc; + // Notional center of a track is simply an average of the bounding box extremities + struct LatLon center = { (trk->bbox.north+trk->bbox.south)/2, (trk->bbox.east+trk->bbox.west)/2 }; + vik_coord_load_from_latlon ( &vc, vtl->coord_mode, ¢er ); + vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, trk->name, vtl->current_tp_track->is_route ); +} + static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response ) { g_assert ( vtl->tpwin != NULL ); @@ -8507,7 +8517,7 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response ) if ( response == VIK_TRW_LAYER_TPWIN_SPLIT && vtl->current_tpl->next && vtl->current_tpl->prev ) { trw_layer_split_at_selected_trackpoint ( vtl, vtl->current_tp_track->is_route ? VIK_TRW_LAYER_SUBLAYER_ROUTE : VIK_TRW_LAYER_SUBLAYER_TRACK ); - vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name, vtl->current_tp_track->is_route ); + my_tpwin_set_tp ( vtl ); } else if ( response == VIK_TRW_LAYER_TPWIN_DELETE ) { @@ -8521,20 +8531,24 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response ) if ( vtl->current_tpl ) // Reset dialog with the available adjacent trackpoint - vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name, vtl->current_tp_track->is_route ); + my_tpwin_set_tp ( vtl ); vik_layer_emit_update(VIK_LAYER(vtl)); } else if ( response == VIK_TRW_LAYER_TPWIN_FORWARD && vtl->current_tpl->next ) { - if ( vtl->current_tp_track ) - vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl = vtl->current_tpl->next, vtl->current_tp_track->name, vtl->current_tp_track->is_route ); + if ( vtl->current_tp_track ) { + vtl->current_tpl = vtl->current_tpl->next; + my_tpwin_set_tp ( vtl ); + } vik_layer_emit_update(VIK_LAYER(vtl)); /* TODO longone: either move or only update if tp is inside drawing window */ } else if ( response == VIK_TRW_LAYER_TPWIN_BACK && vtl->current_tpl->prev ) { - if ( vtl->current_tp_track ) - vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl = vtl->current_tpl->prev, vtl->current_tp_track->name, vtl->current_tp_track->is_route ); + if ( vtl->current_tp_track ) { + vtl->current_tpl = vtl->current_tpl->prev; + my_tpwin_set_tp ( vtl ); + } vik_layer_emit_update(VIK_LAYER(vtl)); } else if ( response == VIK_TRW_LAYER_TPWIN_INSERT && vtl->current_tpl->next ) @@ -8661,7 +8675,7 @@ static void trw_layer_tpwin_init ( VikTrwLayer *vtl ) if ( vtl->current_tpl ) if ( vtl->current_tp_track ) - vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name, vtl->current_tp_track->is_route ); + my_tpwin_set_tp ( vtl ); /* set layer name and TP data */ } @@ -8869,7 +8883,7 @@ static gboolean trw_layer_select_release ( VikTrwLayer *vtl, GdkEventButton *eve if ( vtl->tpwin ) if ( vtl->current_tp_track ) - vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name, vtl->current_tp_track->is_route ); + my_tpwin_set_tp ( vtl ); // NB don't reset the selected trackpoint, thus ensuring it's still in the tpwin } } @@ -8984,7 +8998,7 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event set_statusbar_msg_info_trkpt ( vtl, tp_params.closest_tp ); if ( vtl->tpwin ) - vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name, vtl->current_tp_track->is_route ); + my_tpwin_set_tp ( vtl ); vik_layer_emit_update ( VIK_LAYER(vtl) ); return TRUE; @@ -9019,7 +9033,7 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event set_statusbar_msg_info_trkpt ( vtl, tp_params.closest_tp ); if ( vtl->tpwin ) - vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name, vtl->current_tp_track->is_route ); + my_tpwin_set_tp ( vtl ); vik_layer_emit_update ( VIK_LAYER(vtl) ); return TRUE; @@ -9936,7 +9950,7 @@ static gboolean tool_edit_trackpoint_release ( VikTrwLayer *vtl, GdkEventButton /* diff dist is diff from orig */ if ( vtl->tpwin ) - vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name, vtl->current_tp_track->is_route ); + my_tpwin_set_tp ( vtl ); vik_layer_emit_update ( VIK_LAYER(vtl) ); return TRUE; diff --git a/src/viktrwlayer_propwin.c b/src/viktrwlayer_propwin.c index 446e2958..46d8dca9 100644 --- a/src/viktrwlayer_propwin.c +++ b/src/viktrwlayer_propwin.c @@ -41,6 +41,7 @@ #include "dems.h" #include "viking.h" #include "vikviewport.h" /* ugh */ +#include "vikutils.h" #include typedef enum { @@ -890,10 +891,11 @@ static void time_label_update (GtkWidget *widget, time_t seconds_from_start) static void real_time_label_update (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); @@ -3302,11 +3304,19 @@ 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); + 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), ¢er ); + + gchar *msg; + msg = vu_get_time_string ( &t1, "%c", &vc, NULL ); + widgets->w_time_start = content[cnt++] = gtk_label_new(msg); + g_free ( msg ); - strftime (tmp_buf, sizeof(tmp_buf), "%c", localtime(&(t2))); - widgets->w_time_end = content[cnt++] = gtk_label_new(tmp_buf); + msg = vu_get_time_string ( &t2, "%c", &vc, NULL ); + widgets->w_time_end = content[cnt++] = gtk_label_new(msg); + g_free ( msg ); g_snprintf(tmp_buf, sizeof(tmp_buf), _("%d minutes"), (int)(t2-t1)/60); widgets->w_time_dur = content[cnt++] = gtk_label_new(tmp_buf); diff --git a/src/viktrwlayer_tpwin.c b/src/viktrwlayer_tpwin.c index 8cf4a970..84f91071 100644 --- a/src/viktrwlayer_tpwin.c +++ b/src/viktrwlayer_tpwin.c @@ -33,6 +33,7 @@ #include "viktrack.h" #include "viktrwlayer_tpwin.h" #include "vikwaypoint.h" +#include "vikutils.h" #include "dialog.h" #include "globals.h" #include "vikdatetime_edit_dialog.h" @@ -41,7 +42,7 @@ struct _VikTrwLayerTpwin { GtkDialog parent; GtkSpinButton *lat, *lon, *alt, *ts; GtkWidget *trkpt_name; - GtkWidget *localtime; + GtkWidget *time; GtkLabel *course, *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 @@ -84,16 +85,15 @@ GType vik_trw_layer_tpwin_get_type (void) */ static void tpwin_update_times ( VikTrwLayerTpwin *tpwin, VikTrackpoint *tp ) { - char tmp_str[64]; - if ( tp->has_timestamp ) { gtk_spin_button_set_value ( tpwin->ts, tp->timestamp ); - strftime ( tmp_str, sizeof(tmp_str), "%c", localtime(&(tp->timestamp)) ); - gtk_button_set_label ( GTK_BUTTON(tpwin->localtime), tmp_str ); + gchar *msg = vu_get_time_string ( &(tp->timestamp), "%c", &(tp->coord), NULL ); + gtk_button_set_label ( GTK_BUTTON(tpwin->time), msg ); + g_free ( msg ); } else { gtk_spin_button_set_value ( tpwin->ts, 0 ); - gtk_button_set_label ( GTK_BUTTON(tpwin->localtime), "" ); + gtk_button_set_label ( GTK_BUTTON(tpwin->time), "" ); } } @@ -180,8 +180,8 @@ static void tpwin_sync_time_to_tp ( VikTrwLayerTpwin *tpwin ) // TODO: consider warning about unsorted times? // Clear the previous 'Add' image as now a time is set - if ( gtk_button_get_image ( GTK_BUTTON(tpwin->localtime) ) ) - gtk_button_set_image ( GTK_BUTTON(tpwin->localtime), NULL ); + if ( gtk_button_get_image ( GTK_BUTTON(tpwin->time) ) ) + gtk_button_set_image ( GTK_BUTTON(tpwin->time), NULL ); tpwin_update_times ( tpwin, tpwin->cur_tp ); } @@ -245,9 +245,9 @@ VikTrwLayerTpwin *vik_trw_layer_tpwin_new ( GtkWindow *parent ) 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->localtime = gtk_button_new(); - gtk_button_set_relief ( GTK_BUTTON(tpwin->localtime), GTK_RELIEF_NONE ); - g_signal_connect_swapped ( G_OBJECT(tpwin->localtime), "clicked", G_CALLBACK(tpwin_sync_time_to_tp), tpwin ); + tpwin->time = gtk_button_new(); + gtk_button_set_relief ( GTK_BUTTON(tpwin->time), GTK_RELIEF_NONE ); + g_signal_connect_swapped ( G_OBJECT(tpwin->time), "clicked", G_CALLBACK(tpwin_sync_time_to_tp), tpwin ); tpwin->lat = GTK_SPIN_BUTTON(gtk_spin_button_new( GTK_ADJUSTMENT(gtk_adjustment_new ( 0, -90, 90, 0.00005, 0.01, 0 )), 0.00005, 6)); @@ -273,7 +273,7 @@ VikTrwLayerTpwin *vik_trw_layer_tpwin_new ( GtkWindow *parent ) gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->alt), FALSE, FALSE, 3 ); gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->course), FALSE, FALSE, 3 ); gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->ts), FALSE, FALSE, 3 ); - gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->localtime), FALSE, FALSE, 3 ); + gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->time), FALSE, FALSE, 3 ); /* diff info */ diff_left_vbox = a_dialog_create_label_vbox ( right_label_texts, G_N_ELEMENTS(right_label_texts), 1, 3 ); @@ -324,14 +324,14 @@ void vik_trw_layer_tpwin_set_empty ( VikTrwLayerTpwin *tpwin ) gtk_editable_delete_text ( GTK_EDITABLE(tpwin->trkpt_name), 0, -1 ); gtk_widget_set_sensitive ( tpwin->trkpt_name, FALSE ); - gtk_button_set_label ( GTK_BUTTON(tpwin->localtime), "" ); + gtk_button_set_label ( GTK_BUTTON(tpwin->time), "" ); gtk_label_set_text ( tpwin->course, NULL ); gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->lat), FALSE ); gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->lon), FALSE ); gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->alt), FALSE ); gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->ts), FALSE ); - gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->localtime), FALSE ); + gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->time), FALSE ); // Only keep close button enabled gtk_widget_set_sensitive ( tpwin->button_insert, FALSE ); @@ -388,12 +388,12 @@ 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_widget_set_sensitive ( GTK_WIDGET(tpwin->ts), tp->has_timestamp ); - gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->localtime), tp->has_timestamp ); + gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->time), tp->has_timestamp ); // Enable adding timestamps - but not on routepoints if ( !tp->has_timestamp && !is_route ) { - gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->localtime), TRUE ); + gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->time), TRUE ); GtkWidget *img = gtk_image_new_from_stock ( GTK_STOCK_ADD, GTK_ICON_SIZE_MENU ); - gtk_button_set_image ( GTK_BUTTON(tpwin->localtime), img ); + gtk_button_set_image ( GTK_BUTTON(tpwin->time), img ); } else diff --git a/src/vikutils.c b/src/vikutils.c index 4d793b86..4c9e4733 100644 --- a/src/vikutils.c +++ b/src/vikutils.c @@ -480,3 +480,48 @@ gchar *vu_get_canonical_filename ( VikLayer *vl, const gchar *filename ) return canonical; } + +/** + * vu_get_time_string: + * + * @time_t: The time of which the string is wanted + * @format The format of the time string - such as "%c" + * @vc: Position of object for the time output - maybe NULL + * (only applicable for VIK_TIME_REF_WORLD) + * @tz: TimeZone string - maybe NULL. + * (only applicable for VIK_TIME_REF_WORLD) + * + * Returns: A string of the time according to the time display property + */ +gchar* vu_get_time_string ( time_t *time, const gchar *format, const VikCoord* vc, const gchar *tz ) +{ + if ( !format ) return NULL; + gchar *str = NULL; + switch ( a_vik_get_time_ref_frame() ) { + case VIK_TIME_REF_UTC: + str = g_malloc ( 64 ); + strftime ( str, 64, format, gmtime(time) ); // Always 'GMT' + break; + case VIK_TIME_REF_WORLD: + // Highly simplistic method that doesn't take into account Timezones of countries. + // This will become the fallback method when a Timezone lookup is implemented. + if ( vc ) { + struct LatLon ll; + vik_coord_to_latlon ( vc, &ll ); + gint offset_hours = round ( ll.lon / 15.0 ); + str = g_malloc ( 64 ); + struct tm* mytime = gmtime(time); + mytime->tm_hour = mytime->tm_hour + offset_hours; + // Normalize result + mktime(mytime); + // Append asterisks to indicate use of simplistic model + strftime ( str, 64, "%a %X %x **", mytime ); + } + break; + default: // VIK_TIME_REF_LOCALE + str = g_malloc ( 64 ); + strftime ( str, 64, format, localtime(time) ); + break; + } + return str; +} diff --git a/src/vikutils.h b/src/vikutils.h index 93c65127..1cd4b77f 100644 --- a/src/vikutils.h +++ b/src/vikutils.h @@ -35,6 +35,8 @@ void vu_set_auto_features_on_first_run ( void ); gchar *vu_get_canonical_filename ( VikLayer *vl, const gchar *filename ); +gchar* vu_get_time_string ( time_t *time, const gchar *format, const VikCoord *vc, const gchar *gtz ); + G_END_DECLS #endif -- 2.39.5