[PATCH 1/1] Timezone selection

Viktor Semykin thesame.ml at gmail.com
Sun Jun 18 05:16:50 CEST 2017


Signed-off-by: Viktor Semykin <thesame.ml at gmail.com>
---
 configure.ac.in                |  3 +-
 panel-plugin/Makefile.am       |  5 ++-
 panel-plugin/datetime-dialog.c | 72 ++++++++++++++++++++++++++++++++++++++++++
 panel-plugin/datetime.c        | 53 +++++++++++++++++++++++++------
 panel-plugin/datetime.h        |  5 +++
 panel-plugin/timezones.c       | 60 +++++++++++++++++++++++++++++++++++
 panel-plugin/timezones.h       | 27 ++++++++++++++++
 7 files changed, 213 insertions(+), 12 deletions(-)
 create mode 100644 panel-plugin/timezones.c
 create mode 100644 panel-plugin/timezones.h

diff --git a/configure.ac.in b/configure.ac.in
index 679522e..9bab4be 100644
--- a/configure.ac.in
+++ b/configure.ac.in
@@ -8,7 +8,8 @@ dnl Initialize autoconf
 AC_COPYRIGHT([Copyright (c) 2006-2016
         Remco den Breeje <remco at sx.mine.nu>
         Diego Ongaro <ongardie at gmail.com>
-        Landry Breuil <landry at xfce.org>])
+        Landry Breuil <landry at xfce.org>
+        Viktor Semykin <thesame.ml at gmail.com>])
 AC_INIT([xfce4-datetime-plugin], [datetime_version], [goodies-dev at xfce.org])
 
 dnl Initialize automake
diff --git a/panel-plugin/Makefile.am b/panel-plugin/Makefile.am
index 97cd1cf..0b2fc2f 100644
--- a/panel-plugin/Makefile.am
+++ b/panel-plugin/Makefile.am
@@ -7,11 +7,14 @@ libdatetime_la_SOURCES = 			\
 	datetime.h				\
 	datetime.c				\
 	datetime-dialog.h			\
-	datetime-dialog.c
+	datetime-dialog.c			\
+	timezones.c				\
+	timezones.h
 
 libdatetime_la_CFLAGS = 			\
 	-I$(top_srcdir)				\
 	-DLOCALEDIR=\"$(localedir)\"		\
+	-DDATADIR=\"${datadir}\"		\
 	$(LIBXFCE4PANEL_CFLAGS)			\
 	$(LIBXFCE4UI_CFLAGS)
 
diff --git a/panel-plugin/datetime-dialog.c b/panel-plugin/datetime-dialog.c
index 93b3c72..8563238 100644
--- a/panel-plugin/datetime-dialog.c
+++ b/panel-plugin/datetime-dialog.c
@@ -4,6 +4,7 @@
  *  Copyright (c) 2006 Remco den Breeje <remco at sx.mine.nu>
  *  Copyright (c) 2008 Diego Ongaro <ongardie at gmail.com>
  *  Copyright (c) 2016 Landry Breuil <landry at xfce.org>
+ *  Copyright (c) 2017 Viktor Semykin <thesame.ml at gmail.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU Library General Public License as published
@@ -35,6 +36,7 @@
 
 #include "datetime.h"
 #include "datetime-dialog.h"
+#include "timezones.h"
 
 #define PLUGIN_WEBSITE  "http://goodies.xfce.org/projects/panel-plugins/xfce4-datetime-plugin"
 
@@ -161,6 +163,13 @@ static void datetime_font_selection_cb(GtkWidget *widget, t_datetime *dt)
   gtk_widget_destroy(dialog);
 }
 
+static void
+datetime_timezone_changed(GtkEntry *entry, t_datetime *dt)
+{
+    datetime_apply_timezone (dt, gtk_entry_get_text (entry));
+    datetime_update (dt);
+}
+
 /*
  * Read layout from combobox and set sensitivity
  */
@@ -323,6 +332,26 @@ datetime_dialog_response(GtkWidget *dlg, int response, t_datetime *dt)
   }
 }
 
+static void
+list_timezones_callback (const char *timezone, gpointer data)
+{
+    GtkTreeIter iter;
+    gtk_list_store_append (GTK_LIST_STORE (data), &iter);
+    gtk_list_store_set (GTK_LIST_STORE (data), &iter, 0, timezone, -1);
+}
+
+static gboolean
+match_any (GtkEntryCompletion *completion, const gchar *key, GtkTreeIter *iter, gpointer data)
+{
+    gchar *str;
+    if (strlen (key) < 2)
+        return FALSE;
+    gtk_tree_model_get (GTK_TREE_MODEL (data), iter, 0, &str, -1);
+    if (strcasestr (str, key))
+        return TRUE;
+    return FALSE;
+}
+
 /*
  * show datetime properties dialog
  */
@@ -337,6 +366,7 @@ datetime_properties_dialog(XfcePanelPlugin *plugin, t_datetime * datetime)
             *vbox,
             *hbox,
             *layout_combobox,
+            *timezone_entry,
             *time_combobox,
             *date_combobox,
             *label,
@@ -344,6 +374,8 @@ datetime_properties_dialog(XfcePanelPlugin *plugin, t_datetime * datetime)
             *entry,
             *bin;
   GtkSizeGroup  *sg;
+  GtkEntryCompletion *tz_completion;
+  GtkListStore *tz_store;
   gint i_custom; /* index of custom menu item */
 
   xfce_textdomain (GETTEXT_PACKAGE, LOCALEDIR, "UTF-8");
@@ -398,6 +430,46 @@ datetime_properties_dialog(XfcePanelPlugin *plugin, t_datetime * datetime)
   /* show frame */
   gtk_widget_show_all(frame);
 
+
+  /*
+   * timezone frame
+   */
+  frame = xfce_gtk_frame_box_new(_("Timezone"), &bin);
+  gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dlg))), frame,
+      FALSE, FALSE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(frame), 6);
+
+  /* vbox */
+  vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+  gtk_container_add(GTK_CONTAINER(bin),vbox);
+
+  /* hbox */
+  hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
+  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+  /* Timezone label */
+  label = gtk_label_new(_("Timezone:"));
+  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+  gtk_size_group_add_widget(sg, label);
+
+
+  /* Timezone combobox */
+  tz_store = gtk_list_store_new (1, G_TYPE_STRING);
+  list_timezones (list_timezones_callback, tz_store);
+
+  timezone_entry = gtk_entry_new();
+  tz_completion = gtk_entry_completion_new();
+  gtk_entry_completion_set_model (tz_completion, GTK_TREE_MODEL (tz_store));
+  gtk_entry_completion_set_text_column (tz_completion, 0);
+  gtk_entry_completion_set_match_func (tz_completion, match_any, tz_store, NULL);
+  gtk_entry_set_completion (GTK_ENTRY (timezone_entry), tz_completion);
+  gtk_entry_set_text (GTK_ENTRY (timezone_entry), datetime->timezone);
+  g_signal_connect(G_OBJECT(timezone_entry), "focus-out-event",
+      G_CALLBACK(datetime_timezone_changed), datetime);
+  gtk_box_pack_start(GTK_BOX(hbox), timezone_entry, TRUE, TRUE, 0);
+
+  /* show frame */
+  gtk_widget_show_all(frame);
   /*
    * Date frame
    */
diff --git a/panel-plugin/datetime.c b/panel-plugin/datetime.c
index 1722dd1..19773e8 100644
--- a/panel-plugin/datetime.c
+++ b/panel-plugin/datetime.c
@@ -127,6 +127,25 @@ static gboolean datetime_format_has_seconds(const gchar *format)
   return len1 != len2 || strcmp(buf1, buf2) != 0;
 }
 
+void
+datetime_get_tm (t_datetime *datetime, struct tm *out)
+{
+  GTimeZone *tz;
+  gint64 time_;
+  gint interval;
+  gint32 offset;
+  time_t timestamp;
+
+  tz = g_time_zone_new (strlen (datetime->timezone) ? datetime->timezone : NULL);
+  time_ = g_get_real_time();
+  interval = g_time_zone_find_interval (tz, G_TIME_TYPE_UNIVERSAL, time_);
+  offset = g_time_zone_get_offset (tz, interval);
+
+  timestamp = (time_ / 1000000) + offset;
+  gmtime_r (&timestamp, out);
+  g_time_zone_unref (tz);
+}
+
 /*
  * set date and time labels
  */
@@ -134,7 +153,7 @@ gboolean datetime_update(t_datetime *datetime)
 {
   GTimeVal timeval;
   gchar *utf8str;
-  struct tm *current;
+  struct tm current;
   guint wake_interval;  /* milliseconds to next update */
 
   DBG("wake");
@@ -145,13 +164,12 @@ gboolean datetime_update(t_datetime *datetime)
     g_source_remove(datetime->timeout_id);
   }
 
-  g_get_current_time(&timeval);
-  current = localtime((time_t *)&timeval.tv_sec);
+  datetime_get_tm (datetime, &current);
 
   if (datetime->layout != LAYOUT_TIME &&
       datetime->date_format != NULL && GTK_IS_LABEL(datetime->date_label))
   {
-    utf8str = datetime_do_utf8strftime(datetime->date_format, current);
+    utf8str = datetime_do_utf8strftime(datetime->date_format, &current);
     gtk_label_set_text(GTK_LABEL(datetime->date_label), utf8str);
     g_free(utf8str);
   }
@@ -159,12 +177,13 @@ gboolean datetime_update(t_datetime *datetime)
   if (datetime->layout != LAYOUT_DATE &&
       datetime->time_format != NULL && GTK_IS_LABEL(datetime->time_label))
   {
-    utf8str = datetime_do_utf8strftime(datetime->time_format, current);
+    utf8str = datetime_do_utf8strftime(datetime->time_format, &current);
     gtk_label_set_text(GTK_LABEL(datetime->time_label), utf8str);
     g_free(utf8str);
   }
 
   /* Compute the time to the next update and start the timer. */
+  g_get_current_time(&timeval);
   wake_interval = datetime_wake_interval(timeval, datetime->update_interval);
   datetime->timeout_id = g_timeout_add(wake_interval, (GSourceFunc) datetime_update, datetime);
 
@@ -196,7 +215,7 @@ static gboolean datetime_query_tooltip(GtkWidget *widget,
                                        t_datetime *datetime)
 {
   GTimeVal timeval;
-  struct tm *current;
+  struct tm current;
   gchar *utf8str;
   gchar *format = NULL;
   guint wake_interval;  /* milliseconds to next update */
@@ -216,10 +235,9 @@ static gboolean datetime_query_tooltip(GtkWidget *widget,
   if (format == NULL)
     return FALSE;
 
-  g_get_current_time(&timeval);
-  current = localtime((time_t *)&timeval.tv_sec);
+  datetime_get_tm (datetime, &current);
 
-  utf8str = datetime_do_utf8strftime(format, current);
+  utf8str = datetime_do_utf8strftime(format, &current);
   gtk_tooltip_set_text(tooltip, utf8str);
   g_free(utf8str);
 
@@ -230,6 +248,7 @@ static gboolean datetime_query_tooltip(GtkWidget *widget,
      * I think we can afford to inefficiently poll every
      * second while the user keeps the mouse here.
      */
+    g_get_current_time(&timeval);
     wake_interval = datetime_wake_interval(timeval, 1000);
     datetime->tooltip_timeout_id = g_timeout_add(wake_interval,
       (GSourceFunc) datetime_tooltip_timer, datetime);
@@ -567,6 +586,14 @@ void datetime_apply_format(t_datetime *datetime,
   datetime_set_update_interval(datetime);
 }
 
+void datetime_apply_timezone (t_datetime *datetime,
+    const gchar *timezone)
+{
+  g_free (datetime->timezone);
+  datetime->timezone = g_strdup (timezone);
+  datetime_set_update_interval(datetime);
+}
+
 /*
  * Function only called by the signal handler.
  */
@@ -586,7 +613,7 @@ static void datetime_read_rc_file(XfcePanelPlugin *plugin, t_datetime *dt)
   gchar *file;
   XfceRc *rc = NULL;
   t_layout layout;
-  const gchar *date_font, *time_font, *date_format, *time_format;
+  const gchar *date_font, *time_font, *date_format, *time_format, *timezone;
 
   /* load defaults */
   layout = LAYOUT_DATE_TIME;
@@ -594,6 +621,7 @@ static void datetime_read_rc_file(XfcePanelPlugin *plugin, t_datetime *dt)
   time_font = "Bitstream Vera Sans 8";
   date_format = "%Y-%m-%d";
   time_format = "%H:%M";
+  timezone = "";
 
   /* open file */
   if((file = xfce_panel_plugin_lookup_rc_file(plugin)) != NULL)
@@ -608,6 +636,7 @@ static void datetime_read_rc_file(XfcePanelPlugin *plugin, t_datetime *dt)
       time_font   = xfce_rc_read_entry(rc, "time_font", time_font);
       date_format = xfce_rc_read_entry(rc, "date_format", date_format);
       time_format = xfce_rc_read_entry(rc, "time_format", time_format);
+      timezone    = xfce_rc_read_entry(rc, "timezone", timezone);
     }
   }
 
@@ -615,6 +644,7 @@ static void datetime_read_rc_file(XfcePanelPlugin *plugin, t_datetime *dt)
   time_font   = g_strdup(time_font);
   date_format = g_strdup(date_format);
   time_format = g_strdup(time_format);
+  timezone = g_strdup(timezone);
 
   if(rc != NULL)
     xfce_rc_close(rc);
@@ -623,6 +653,7 @@ static void datetime_read_rc_file(XfcePanelPlugin *plugin, t_datetime *dt)
   datetime_apply_layout(dt, layout);
   datetime_apply_font(dt, date_font, time_font);
   datetime_apply_format(dt, date_format, time_format);
+  datetime_apply_timezone(dt, timezone);
 }
 
 /*
@@ -646,6 +677,7 @@ void datetime_write_rc_file(XfcePanelPlugin *plugin, t_datetime *dt)
     xfce_rc_write_entry(rc, "time_font", dt->time_font);
     xfce_rc_write_entry(rc, "date_format", dt->date_format);
     xfce_rc_write_entry(rc, "time_format", dt->time_format);
+    xfce_rc_write_entry(rc, "timezone", dt->timezone);
 
     xfce_rc_close(rc);
   }
@@ -761,6 +793,7 @@ static void datetime_free(XfcePanelPlugin *plugin, t_datetime *datetime)
   g_free(datetime->time_font);
   g_free(datetime->date_format);
   g_free(datetime->time_format);
+  g_free(datetime->timezone);
 
   panel_slice_free(t_datetime, datetime);
 }
diff --git a/panel-plugin/datetime.h b/panel-plugin/datetime.h
index 5f09f83..611f67d 100644
--- a/panel-plugin/datetime.h
+++ b/panel-plugin/datetime.h
@@ -54,6 +54,7 @@ typedef struct {
   gchar *time_font;
   gchar *date_format;
   gchar *time_format;
+  gchar *timezone;
   t_layout layout;
 
   /* option widgets */
@@ -93,6 +94,10 @@ datetime_apply_format(t_datetime *datetime,
     const gchar *time_format);
 
 void
+datetime_apply_timezone(t_datetime *datetime,
+    const gchar *date_font_name);
+
+void
 datetime_apply_layout(t_datetime *datetime,
     t_layout layout);
 
diff --git a/panel-plugin/timezones.c b/panel-plugin/timezones.c
new file mode 100644
index 0000000..b837843
--- /dev/null
+++ b/panel-plugin/timezones.c
@@ -0,0 +1,60 @@
+/*  $Id$
+ *
+ *  Copyright (c) 2017 Viktor Semykin <thesame.ml at gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published
+ *  by the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gio/gio.h>
+
+#include "timezones.h"
+
+void
+list_timezones (list_timezones_callback_t timezone_cb, gpointer data)
+{
+    GFile *file;
+    GFileInputStream *file_stream;
+    GDataInputStream *data_stream;
+    gsize len;
+    char *line;
+    gchar **columns;
+
+    file = g_file_new_for_path (DATADIR "/zoneinfo/zone1970.tab");
+    file_stream = g_file_read (file, NULL, NULL);
+    g_object_unref (file);
+    if (!file_stream)
+        return;
+
+    data_stream = g_data_input_stream_new (G_INPUT_STREAM (file_stream));
+    g_object_unref (file_stream);
+
+    while (line = g_data_input_stream_read_line (data_stream, &len, NULL, NULL))
+    {
+        if (line[0] != '#')
+        {
+            columns = g_strsplit (line, "\t", 4);
+            if (g_strv_length (columns) >= 3)
+                timezone_cb (columns[2], data);
+            g_strfreev (columns);
+        }
+        g_free (line);
+    }
+
+    g_object_unref (data_stream);
+}
diff --git a/panel-plugin/timezones.h b/panel-plugin/timezones.h
new file mode 100644
index 0000000..935bef5
--- /dev/null
+++ b/panel-plugin/timezones.h
@@ -0,0 +1,27 @@
+/*  $Id$
+ *
+ *  Copyright (c) 2017 Viktor Semykin <thesame.ml at gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published
+ *  by the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _TIMEZONES_H
+#define _TIMEZONES_H
+
+typedef void (*list_timezones_callback_t) (const char *timezone, gpointer data);
+
+void list_timezones (list_timezones_callback_t timezone_cb, gpointer data);
+
+#endif /* _TIMEZONES_H */
-- 
2.13.1



More information about the Xfce4-dev mailing list