[gnome-initial-setup/shell/4765: 6/362] location: extend page to set up time and date as well



commit 09a518f34f2ec7dc0961c2952d9b60d9df045e30
Author: Cosimo Cecchi <cosimo endlessm com>
Date:   Thu Apr 17 15:51:08 2014 -0700

    location: extend page to set up time and date as well

 gnome-initial-setup/gis-driver.c                   |   16 +
 gnome-initial-setup/gis-driver.h                   |    2 +
 gnome-initial-setup/pages/location/Makefile.am     |    1 +
 gnome-initial-setup/pages/location/date-endian.c   |  172 +++++++++
 gnome-initial-setup/pages/location/date-endian.h   |   32 ++
 .../pages/location/gis-location-page.c             |  383 +++++++++++++++++++-
 .../pages/location/gis-location-page.ui            |  393 +++++++++++++++++++-
 7 files changed, 977 insertions(+), 22 deletions(-)
---
diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c
index 8836312..9aed9b2 100644
--- a/gnome-initial-setup/gis-driver.c
+++ b/gnome-initial-setup/gis-driver.c
@@ -35,6 +35,7 @@
 #define PERSONALITY_FILE_PATH "/etc/EndlessOS/personality.conf"
 #define INITIAL_CONFIG_GROUP "Setup"
 #define LANGUAGE_KEY "DefaultLanguage"
+#define TIMEZONE_KEY "DefaultTimezone"
 
 /* Statically include this for now. Maybe later
  * we'll generate this from glib-mkenums. */
@@ -78,6 +79,7 @@ struct _GisDriverPrivate {
 
   gchar *lang_id;
   gchar *lang_override;
+  gchar *default_timezone;
 
   GisDriverMode mode;
 };
@@ -93,6 +95,7 @@ gis_driver_finalize (GObject *object)
 
   g_free (priv->lang_id);
   g_free (priv->lang_override);
+  g_free (priv->default_timezone);
 
   G_OBJECT_CLASS (gis_driver_parent_class)->finalize (object);
 }
@@ -201,6 +204,13 @@ gis_driver_get_language_override (GisDriver *driver)
   return priv->lang_override;  
 }
 
+const gchar *
+gis_driver_get_default_timezone (GisDriver *driver)
+{
+  GisDriverPrivate *priv = gis_driver_get_instance_private (driver);
+  return priv->default_timezone;
+}
+
 static void
 gis_driver_get_property (GObject      *object,
                          guint         prop_id,
@@ -267,11 +277,14 @@ gis_driver_read_personality_file (GisDriver *driver)
   GisDriverPrivate *priv = gis_driver_get_instance_private (driver);
   GKeyFile *keyfile = g_key_file_new ();
   gchar *language = NULL;
+  gchar *timezone = NULL;
 
   if (g_key_file_load_from_file (keyfile, PERSONALITY_FILE_PATH,
                                  G_KEY_FILE_NONE, NULL)) {
     language = g_key_file_get_string (keyfile, INITIAL_CONFIG_GROUP,
                                       LANGUAGE_KEY, NULL);
+    timezone = g_key_file_get_string (keyfile, INITIAL_CONFIG_GROUP,
+                                      TIMEZONE_KEY, NULL);
   }
 
   g_free (priv->lang_override);
@@ -280,6 +293,9 @@ gis_driver_read_personality_file (GisDriver *driver)
     setlocale (LC_MESSAGES, language);
   }
 
+  g_free (priv->default_timezone);
+  priv->default_timezone = timezone;
+
   g_key_file_free (keyfile);
 }
 
diff --git a/gnome-initial-setup/gis-driver.h b/gnome-initial-setup/gis-driver.h
index f382a09..d8c092f 100644
--- a/gnome-initial-setup/gis-driver.h
+++ b/gnome-initial-setup/gis-driver.h
@@ -78,6 +78,8 @@ const gchar *gis_driver_get_user_language (GisDriver   *driver);
 
 const gchar *gis_driver_get_language_override (GisDriver *driver);
 
+const gchar *gis_driver_get_default_timezone (GisDriver *driver);
+
 GisDriverMode gis_driver_get_mode (GisDriver *driver);
 
 void gis_driver_add_page (GisDriver *driver,
diff --git a/gnome-initial-setup/pages/location/Makefile.am b/gnome-initial-setup/pages/location/Makefile.am
index 2c801e1..02fe6c1 100644
--- a/gnome-initial-setup/pages/location/Makefile.am
+++ b/gnome-initial-setup/pages/location/Makefile.am
@@ -32,6 +32,7 @@ libgislocation_la_SOURCES =   \
        tz.c tz.h \
        cc-timezone-map.c cc-timezone-map.h \
        gis-location-page.c gis-location-page.h \
+       date-endian.c date-endian.h \
        $(BUILT_SOURCES)
 
 libgislocation_la_CFLAGS = $(INITIAL_SETUP_CFLAGS) -I "$(srcdir)/../.."
diff --git a/gnome-initial-setup/pages/location/date-endian.c 
b/gnome-initial-setup/pages/location/date-endian.c
new file mode 100644
index 0000000..715d22b
--- /dev/null
+++ b/gnome-initial-setup/pages/location/date-endian.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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.
+ *
+ * Author: Bastien Nocera <hadess hadess net>
+ *
+ */
+
+#include <langinfo.h>
+#include <locale.h>
+#include <glib.h>
+#include <string.h>
+
+#include "date-endian.h"
+
+/* We default to returning DATE_ENDIANESS_MIDDLE because that's
+ * what 3.2 billion people use */
+#define DEFAULT_ENDIANESS DATE_ENDIANESS_LITTLE
+
+typedef enum {
+       ITEM_NONE = 0,
+       ITEM_DAY,
+       ITEM_MONTH,
+       ITEM_YEAR
+} Item;
+
+static gboolean
+has_item (Item *items,
+         Item  item)
+{
+       guint i;
+
+       for (i = 0; i < 3; i++) {
+               if (items[i] == ITEM_NONE)
+                       return FALSE;
+               if (items[i] == item)
+                       return TRUE;
+       }
+       return FALSE;
+}
+
+DateEndianess
+date_endian_get_default (gboolean verbose)
+{
+       const char *fmt;
+       const char *p;
+       Item items[3];
+       guint i;
+
+       fmt = nl_langinfo (D_FMT);
+       g_return_val_if_fail (fmt != NULL, DEFAULT_ENDIANESS);
+
+       if (verbose)
+               g_print ("%s", fmt);
+
+       if (g_str_equal (fmt, "%F"))
+               return DATE_ENDIANESS_BIG;
+
+       i = 0;
+       memset (&items, 0, sizeof(items));
+
+       /* Assume ASCII only */
+       for (p = fmt; *p != '\0'; p++) {
+               char c;
+
+               /* Look for '%' */
+               if (*p != '%')
+                       continue;
+
+               /* Only assert when we're sure we don't have another '%' */
+               if (i >= 4) {
+                       g_warning ("Could not parse format '%s', too many formats", fmt);
+                       return DEFAULT_ENDIANESS;
+               }
+
+               c = *(p + 1);
+               /* Ignore alternative formats */
+               if (c == 'O' || c == '-' || c == 'E')
+                       c = *(p + 2);
+               if (c == '\0') {
+                       g_warning ("Count not parse format '%s', unterminated '%%'", fmt);
+                       return DEFAULT_ENDIANESS;
+               }
+               switch (c) {
+               case 'd':
+               case 'e':
+                       if (has_item (items, ITEM_DAY) == FALSE) {
+                               items[i] = ITEM_DAY;
+                               i++;
+                       }
+                       break;
+               case 'm':
+               case 'b':
+               case 'B':
+                       if (has_item (items, ITEM_MONTH) == FALSE) {
+                               items[i] = ITEM_MONTH;
+                               i++;
+                       }
+                       break;
+               case 'y':
+               case 'Y':
+                       if (has_item (items, ITEM_YEAR) == FALSE) {
+                               items[i] = ITEM_YEAR;
+                               i++;
+                       }
+                       break;
+               case 'A':
+               case 'a':
+                       /* Ignore */
+                       ;
+               }
+       }
+
+       if (items[0] == ITEM_DAY &&
+           items[1] == ITEM_MONTH &&
+           items[2] == ITEM_YEAR)
+               return DATE_ENDIANESS_LITTLE;
+       if (items[0] == ITEM_YEAR &&
+           items[1] == ITEM_MONTH &&
+           items[2] == ITEM_DAY)
+               return DATE_ENDIANESS_BIG;
+       if (items[0] == ITEM_MONTH &&
+           items[1] == ITEM_DAY &&
+           items[2] == ITEM_YEAR)
+               return DATE_ENDIANESS_MIDDLE;
+
+       g_warning ("Could not parse format '%s'", fmt);
+
+       return DEFAULT_ENDIANESS;
+}
+
+DateEndianess
+date_endian_get_for_lang (const char *lang,
+                         gboolean    verbose)
+{
+       const char *old_lang;
+       DateEndianess endian;
+
+       old_lang = setlocale (LC_TIME, lang);
+       endian = date_endian_get_default (verbose);
+       setlocale (LC_TIME, old_lang);
+
+       return endian;
+}
+
+const char *
+date_endian_to_string (DateEndianess endianess)
+{
+       switch (endianess) {
+       case DATE_ENDIANESS_LITTLE:
+               return "Little (DD-MM-YYYY)";
+       case DATE_ENDIANESS_BIG:
+               return "Big (YYYY-MM-DD)";
+       case DATE_ENDIANESS_MIDDLE:
+               return "Middle (MM-DD-YYYY)";
+       default:
+               g_assert_not_reached ();
+       }
+}
diff --git a/gnome-initial-setup/pages/location/date-endian.h 
b/gnome-initial-setup/pages/location/date-endian.h
new file mode 100644
index 0000000..4916485
--- /dev/null
+++ b/gnome-initial-setup/pages/location/date-endian.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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.
+ *
+ * Author: Bastien Nocera <hadess hadess net>
+ *
+ */
+
+/* From http://en.wikipedia.org/wiki/Date_notation_by_country */
+typedef enum {
+  DATE_ENDIANESS_BIG,    /* Big-endian (year, month, day), e.g. 03-04-05 */
+  DATE_ENDIANESS_LITTLE, /* Little-endian (day, month, year), e.g. 05/04/03 */
+  DATE_ENDIANESS_MIDDLE  /* Middle-endian (month, day, year), e.g. 04/05/03 */
+} DateEndianess;
+
+DateEndianess date_endian_get_default  (gboolean verbose);
+DateEndianess date_endian_get_for_lang (const char *lang,
+                                       gboolean    verbose);
+const char  * date_endian_to_string    (DateEndianess endianess);
diff --git a/gnome-initial-setup/pages/location/gis-location-page.c 
b/gnome-initial-setup/pages/location/gis-location-page.c
index f93b96a..ee22b89 100644
--- a/gnome-initial-setup/pages/location/gis-location-page.c
+++ b/gnome-initial-setup/pages/location/gis-location-page.c
@@ -27,6 +27,7 @@
 
 #include "config.h"
 #include "cc-datetime-resources.h"
+#include "date-endian.h"
 #include "location-resources.h"
 #include "gis-location-page.h"
 
@@ -42,13 +43,21 @@
 #include "cc-timezone-map.h"
 #include "timedated.h"
 
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-wall-clock.h>
+
 #define DEFAULT_TZ "Europe/London"
 
 struct _GisLocationPagePrivate
 {
   CcTimezoneMap *map;
   TzLocation *current_location;
+
+  GDateTime *date;
+  GnomeWallClock *clock_tracker;
+
   Timedate1 *dtm;
+  GCancellable *cancellable;
 };
 typedef struct _GisLocationPagePrivate GisLocationPagePrivate;
 
@@ -57,6 +66,13 @@ G_DEFINE_TYPE_WITH_PRIVATE (GisLocationPage, gis_location_page, GIS_TYPE_PAGE);
 #define OBJ(type,name) ((type)gtk_builder_get_object(GIS_PAGE (page)->builder,(name)))
 #define WID(name) OBJ(GtkWidget*,name)
 
+/* Forward declarations to avoid calls before definitions */
+static void
+day_changed (GtkWidget *widget, GisLocationPage *page);
+
+static void
+month_year_changed (GtkWidget *widget, GisLocationPage *page);
+
 static void
 set_timezone_cb (GObject      *source,
                  GAsyncResult *res,
@@ -195,6 +211,289 @@ location_changed (GObject *object, GParamSpec *param, GisLocationPage *page)
   gweather_location_unref (gloc);
 }
 
+static void
+set_using_ntp_cb (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+  GisLocationPage *page = user_data;
+  GisLocationPagePrivate *priv = gis_location_page_get_instance_private (page);
+  GError *error = NULL;
+
+  if (!timedate1_call_set_ntp_finish (priv->dtm, res, &error))
+    {
+      g_warning ("Could not set system to use NTP: %s", error->message);
+      g_error_free (error);
+    }
+}
+
+static void
+queue_set_ntp (GisLocationPage *page)
+{
+  GisLocationPagePrivate *priv = gis_location_page_get_instance_private (page);
+  gboolean using_ntp;
+
+  using_ntp = gtk_switch_get_active (GTK_SWITCH (WID ("network_time_switch")));
+
+  timedate1_call_set_ntp (priv->dtm,
+                          using_ntp,
+                          TRUE,
+                          priv->cancellable,
+                          set_using_ntp_cb,
+                          page);
+}
+
+static void
+update_widget_state_for_ntp (GisLocationPage *page, gboolean using_ntp)
+{
+  gtk_widget_set_sensitive (WID ("time-grid"), !using_ntp);
+  gtk_widget_set_sensitive (WID ("date-box"), !using_ntp);
+}
+
+static void
+change_ntp (GObject *object, GParamSpec *pspec, GisLocationPage *page)
+{
+  update_widget_state_for_ntp (page, gtk_switch_get_active (GTK_SWITCH (object)));
+  queue_set_ntp (page);
+}
+
+
+static void
+update_ntp_switch_from_system (GisLocationPage *page)
+{
+  GisLocationPagePrivate *priv = gis_location_page_get_instance_private (page);
+  gboolean using_ntp;
+  GtkWidget *switch_widget;
+
+  using_ntp = timedate1_get_ntp (priv->dtm);
+
+  switch_widget = WID ("network_time_switch");
+  g_signal_handlers_block_by_func (switch_widget, change_ntp, page);
+  gtk_switch_set_active (GTK_SWITCH (switch_widget), using_ntp);
+  update_widget_state_for_ntp (page, using_ntp);
+  g_signal_handlers_unblock_by_func (switch_widget, change_ntp, page);
+}
+
+static void
+update_time (GisLocationPage *page)
+{
+  GisLocationPagePrivate *priv = gis_location_page_get_instance_private (page);
+  char *label;
+  gint i;
+
+  /* Update the hours label */
+  label = g_date_time_format (priv->date, "%H");
+  gtk_label_set_text (GTK_LABEL (WID ("hours_label")), label);
+  g_free (label);
+
+  /* Update the minutes label */
+  label = g_date_time_format (priv->date, "%M");
+  gtk_label_set_text (GTK_LABEL (WID ("minutes_label")), label);
+  g_free (label);
+}
+
+static void
+update_date (GisLocationPage *page)
+{
+  GtkWidget *day_widget = WID ("day-spinbutton");
+  GtkWidget *month_widget = WID ("month-combobox");
+  GtkWidget *year_widget = WID ("year-spinbutton");
+
+  /* Disable the system time updates while the UI is redrawn */
+  g_signal_handlers_block_by_func (day_widget, day_changed, page);
+  g_signal_handlers_block_by_func (month_widget, month_year_changed, page);
+  g_signal_handlers_block_by_func (year_widget, month_year_changed, page);
+
+  /* Update the UI */
+  GisLocationPagePrivate *priv = gis_location_page_get_instance_private (page);
+
+  gint day_of_month = g_date_time_get_day_of_month (priv->date);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (day_widget), day_of_month);
+
+  gint month = g_date_time_get_month (priv->date);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (month_widget), month - 1);
+
+  gint year = g_date_time_get_year (priv->date);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (year_widget), year);
+
+
+  /* Re-enable the system time updates from the UI */
+  g_signal_handlers_unblock_by_func (day_widget, day_changed, page);
+  g_signal_handlers_unblock_by_func (month_widget, month_year_changed, page);
+  g_signal_handlers_unblock_by_func (year_widget, month_year_changed, page);
+}
+
+static void
+set_time_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+  GisLocationPage *page = user_data;
+  GisLocationPagePrivate *priv = gis_location_page_get_instance_private (page);
+  GError *error = NULL;
+
+  if(!timedate1_call_set_time_finish (priv->dtm, res, &error))
+    {
+      g_warning ("Could not set system time: %s", error->message);
+      g_error_free (error);
+    }
+  else
+    {
+      update_time (page);
+      update_date (page);
+    }
+}
+
+static void
+queue_set_datetime (GisLocationPage *page)
+{
+  GisLocationPagePrivate *priv = gis_location_page_get_instance_private (page);
+  gint64 unixtime;
+
+  /* timedated expects number of microseconds since 1 Jan 1970 UTC */
+  unixtime = g_date_time_to_unix (priv->date);
+
+  timedate1_call_set_time (priv->dtm,
+                           unixtime * G_TIME_SPAN_SECOND,
+                           FALSE,
+                           TRUE,
+                           priv->cancellable,
+                           set_time_cb,
+                           page);
+}
+
+static void
+change_time (GtkButton *button, GisLocationPage *page)
+{
+  GDateTime *old_date;
+  GisLocationPagePrivate *priv = gis_location_page_get_instance_private (page);
+  const gchar *widget_name;
+  gint direction;
+
+  old_date = priv->date;
+  widget_name = gtk_buildable_get_name (GTK_BUILDABLE (button));
+
+  if (strstr (widget_name, "up"))
+    direction = 1;
+  else
+    direction = -1;
+
+  if (widget_name[0] == 'h')
+    {
+      priv->date = g_date_time_add_hours (old_date, direction);
+    }
+  else if (widget_name[0] == 'm')
+    {
+      priv->date = g_date_time_add_minutes (old_date, direction);
+    }
+  else
+    {
+      int hour;
+      hour = g_date_time_get_hour (old_date);
+      if (hour >= 12)
+        priv->date = g_date_time_add_hours (old_date, -12);
+      else
+        priv->date = g_date_time_add_hours (old_date, 12);
+    }
+
+  g_date_time_unref (old_date);
+
+  update_time (page);
+  queue_set_datetime (page);
+}
+
+static void
+reorder_date_widget (DateEndianess endianess, GisLocationPage *page)
+{
+  GtkBox *box;
+  GtkWidget *month, *day, *year;
+
+  if (endianess = DATE_ENDIANESS_MIDDLE)
+    return;
+
+  month = WID ("month-combobox");
+  day = WID ("day-spinbutton");
+  year = WID ("year-spinbutton");
+
+  box = GTK_BOX (WID ("date-box"));
+
+  switch (endianess)
+    {
+    case DATE_ENDIANESS_LITTLE:
+      gtk_box_reorder_child (box, month, 0);
+      gtk_box_reorder_child (box, day, 0);
+      gtk_box_reorder_child (box, year, -1);
+      break;
+
+    case DATE_ENDIANESS_BIG:
+      gtk_box_reorder_child (box, month, 0);
+      gtk_box_reorder_child (box, year, 0);
+      gtk_box_reorder_child (box, day, -1);
+      break;
+
+    case DATE_ENDIANESS_MIDDLE:
+      /* We already handle this case, but cover to avoid warnings in the compiler */
+      g_assert_not_reached();
+      break;
+    }
+}
+
+static void
+change_date (GisLocationPage *page)
+{
+  GisLocationPagePrivate *priv = gis_location_page_get_instance_private (page);
+  GDateTime *old_date = priv->date;
+  guint month, year, day;
+
+  month = 1 + gtk_combo_box_get_active (GTK_COMBO_BOX (WID ("month-combobox")));
+  year = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (WID ("year-spinbutton")));
+  day = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (WID ("day-spinbutton")));
+
+  priv->date = g_date_time_new_local (year, month, day,
+                                      g_date_time_get_hour (old_date),
+                                      g_date_time_get_minute (old_date),
+                                      g_date_time_get_second (old_date));
+  g_date_time_unref (old_date);
+  queue_set_datetime (page);
+}
+
+static void
+month_year_changed (GtkWidget *widget, GisLocationPage *page)
+{
+  GtkAdjustment *adj;
+  GtkSpinButton *day_spin;
+  guint month;
+  guint num_days;
+  guint year;
+
+  month = 1 + gtk_combo_box_get_active (GTK_COMBO_BOX (WID ("month-combobox")));
+  year = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (WID ("year-spinbutton")));
+
+  num_days = g_date_get_days_in_month (month, year);
+
+  day_spin = GTK_SPIN_BUTTON (WID ("day-spinbutton"));
+  adj = GTK_ADJUSTMENT (gtk_spin_button_get_adjustment (day_spin));
+  gtk_adjustment_set_upper (adj, num_days + 1);
+
+  if (gtk_spin_button_get_value_as_int (day_spin) > num_days)
+    gtk_spin_button_set_value (day_spin, num_days);
+
+  change_date (page);
+}
+
+static void
+day_changed (GtkWidget *widget, GisLocationPage *page)
+{
+  change_date (page);
+}
+
+static void
+clock_changed (GnomeWallClock *clock, GParamSpec *pspec, GisLocationPage *page)
+{
+  GisLocationPagePrivate *priv = gis_location_page_get_instance_private (page);
+
+  g_date_time_unref (priv->date);
+  priv->date = g_date_time_new_now_local ();
+  update_time (page);
+  update_date (page);
+}
+
 #define WANT_GEOCLUE 0
 
 #if WANT_GEOCLUE
@@ -271,6 +570,13 @@ gis_location_page_constructed (GObject *object)
   GWeatherLocation *world;
   GError *error;
   const gchar *timezone;
+  DateEndianess endianess;
+  GtkWidget *widget;
+  gint i;
+  guint num_days;
+  GtkAdjustment *adjustment;
+  gchar *time_buttons[] = { "hour_up_button", "hour_down_button",
+                            "min_up_button", "min_down_button" };
 
   G_OBJECT_CLASS (gis_location_page_parent_class)->constructed (object);
 
@@ -278,6 +584,7 @@ gis_location_page_constructed (GObject *object)
 
   frame = WID("location-map-frame");
 
+  priv->cancellable = g_cancellable_new ();
   error = NULL;
   priv->dtm = timedate1_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
                                                 G_DBUS_PROXY_FLAGS_NONE,
@@ -316,14 +623,25 @@ gis_location_page_constructed (GObject *object)
   timezone = timedate1_get_timezone (priv->dtm);
 
   if (!cc_timezone_map_set_timezone (priv->map, timezone)) {
-    g_warning ("Timezone '%s' is unhandled, setting %s as default", timezone, DEFAULT_TZ);
-    cc_timezone_map_set_timezone (priv->map, DEFAULT_TZ);
+    GisDriver *driver = GIS_PAGE (page)->driver;
+    const gchar *default_timezone = gis_driver_get_default_timezone (driver);
+
+    if (default_timezone == NULL) {
+      default_timezone = DEFAULT_TZ;
+    }
+
+    g_warning ("Timezone '%s' is unhandled, setting %s as default",
+               timezone, default_timezone);
+    cc_timezone_map_set_timezone (priv->map, default_timezone);
+
+    priv->current_location = cc_timezone_map_get_location (priv->map);
+    queue_set_timezone (page);
   }
   else {
     g_debug ("System timezone is '%s'", timezone);
+    priv->current_location = cc_timezone_map_get_location (priv->map);
   }
 
-  priv->current_location = cc_timezone_map_get_location (priv->map);
   update_timezone (page);
 
   g_signal_connect (G_OBJECT (entry), "notify::location",
@@ -339,6 +657,59 @@ gis_location_page_constructed (GObject *object)
   gtk_widget_hide (WID ("location-auto-button"));
 #endif
 
+  /* set up network time button */
+  update_ntp_switch_from_system (page);
+  g_signal_connect(WID ("network_time_switch"), "notify::active",
+                   G_CALLBACK (change_ntp), page);
+
+  /* set up time editing widgets */
+  for (i = 0; i < G_N_ELEMENTS (time_buttons); i++)
+    {
+      g_signal_connect (WID (time_buttons[i]), "clicked",
+                        G_CALLBACK (change_time), page);
+    }
+
+  /* set up date editing widgets */
+  priv->date = g_date_time_new_now_local ();
+  endianess = date_endian_get_default (FALSE);
+  reorder_date_widget (endianess, page);
+
+  /* Force the direction for the time, so that the time is presented
+     correctly for RTL languages */
+  gtk_widget_set_direction (WID ("time-grid"), GTK_TEXT_DIR_LTR);
+
+  widget = WID ("month-combobox");
+  gtk_combo_box_set_active (GTK_COMBO_BOX (widget),
+                            g_date_time_get_month (priv->date) - 1);
+  g_signal_connect (widget, "changed",
+                    G_CALLBACK (month_year_changed), page);
+
+  num_days = g_date_get_days_in_month (g_date_time_get_month (priv->date),
+                                       g_date_time_get_year (priv->date));
+  adjustment = (GtkAdjustment *) gtk_adjustment_new (g_date_time_get_day_of_month (priv->date),
+                                                     1, num_days, 1, 10, 1);
+  widget = WID ("day-spinbutton");
+  gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (widget), adjustment);
+
+  g_signal_connect (widget, "value-changed",
+                    G_CALLBACK (day_changed), page);
+
+  adjustment = (GtkAdjustment *) gtk_adjustment_new (g_date_time_get_year (priv->date),
+                                                     1900, 9999, 1, 10, 1);
+  widget = WID ("year-spinbutton");
+  gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (widget), adjustment);
+  g_signal_connect (widget, "value-changed",
+                    G_CALLBACK (month_year_changed), page);
+
+  month_year_changed(widget, page);
+
+  /* set up the time itself */
+  priv->clock_tracker = g_object_new (GNOME_TYPE_WALL_CLOCK, NULL);
+  g_signal_connect (priv->clock_tracker, "notify::clock",
+                    G_CALLBACK (clock_changed), page);
+
+  update_time (page);
+
   gis_page_set_complete (GIS_PAGE (page), TRUE);
 
   gtk_widget_show (GTK_WIDGET (page));
@@ -351,6 +722,12 @@ gis_location_page_dispose (GObject *object)
   GisLocationPagePrivate *priv = gis_location_page_get_instance_private (page);
 
   g_clear_object (&priv->dtm);
+  g_clear_object (&priv->clock_tracker);
+  g_clear_pointer (&priv->date, g_date_time_unref);
+  if (priv->cancellable) {
+    g_cancellable_cancel (priv->cancellable);
+    g_clear_object (&priv->cancellable);
+  }
 
   G_OBJECT_CLASS (gis_location_page_parent_class)->dispose (object);
 }
diff --git a/gnome-initial-setup/pages/location/gis-location-page.ui 
b/gnome-initial-setup/pages/location/gis-location-page.ui
index a4ed90a..cdb8a34 100644
--- a/gnome-initial-setup/pages/location/gis-location-page.ui
+++ b/gnome-initial-setup/pages/location/gis-location-page.ui
@@ -1,20 +1,20 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <requires lib="gtk+" version="3.0"/>
+  <!-- interface-requires gtk+ 3.0 -->
   <object class="GtkGrid" id="location-page">
-    <property name="name">location-page</property>
     <property name="visible">True</property>
+    <property name="can_focus">False</property>
     <property name="halign">center</property>
     <property name="valign">start</property>
     <property name="hexpand">True</property>
     <child>
       <object class="GtkLabel" id="location-title">
         <property name="visible">True</property>
-        <property name="label" translatable="yes">Choose Your Location</property>
-        <property name="hexpand">False</property>
+        <property name="can_focus">False</property>
         <property name="halign">start</property>
         <property name="valign">start</property>
-        <property name="margin-bottom">18</property>
+        <property name="margin_bottom">18</property>
+        <property name="label" translatable="yes">Choose Your Location</property>
         <attributes>
           <attribute name="weight" value="bold"/>
           <attribute name="scale" value="1.2"/>
@@ -29,11 +29,13 @@
     </child>
     <child>
       <object class="GtkButton" id="location-auto-button">
-        <property name="visible">True</property>
         <property name="label" translatable="yes">_Determine your location automatically</property>
-        <property name="use_underline">True</property>
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="receives_default">False</property>
         <property name="halign">start</property>
-        <property name="margin-right">24</property>
+        <property name="margin_right">24</property>
+        <property name="use_underline">True</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -45,12 +47,12 @@
     <child>
       <object class="GtkFrame" id="location-map-frame">
         <property name="visible">True</property>
-        <property name="halign">fill</property>
-        <property name="valign">fill</property>
+        <property name="can_focus">False</property>
+        <property name="margin_top">6</property>
+        <property name="margin_bottom">6</property>
         <property name="hexpand">True</property>
         <property name="vexpand">True</property>
-        <property name="margin-top">6</property>
-        <property name="margin-bottom">6</property>
+        <property name="label_xalign">0</property>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -62,15 +64,17 @@
     <child>
       <object class="GtkGrid" id="location-info-grid">
         <property name="visible">True</property>
+        <property name="can_focus">False</property>
         <property name="halign">start</property>
         <property name="valign">start</property>
-        <property name="row-spacing">6</property>
-        <property name="column-spacing">6</property>
+        <property name="row_spacing">6</property>
+        <property name="column_spacing">6</property>
         <child>
           <object class="GtkLabel" id="location-label">
             <property name="visible">True</property>
-            <property name="label" translatable="yes">Location</property>
+            <property name="can_focus">False</property>
             <property name="halign">end</property>
+            <property name="label" translatable="yes">Location</property>
             <style>
               <class name="dim-label"/>
             </style>
@@ -78,24 +82,30 @@
           <packing>
             <property name="left_attach">0</property>
             <property name="top_attach">0</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
           </packing>
         </child>
         <child>
           <object class="GtkLabel" id="current-location-label">
             <property name="visible">True</property>
-            <property name="label">Boston, MA</property>
+            <property name="can_focus">False</property>
             <property name="halign">start</property>
+            <property name="label">Boston, MA</property>
           </object>
           <packing>
             <property name="left_attach">1</property>
             <property name="top_attach">0</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
           </packing>
         </child>
         <child>
           <object class="GtkLabel" id="timezone-label">
             <property name="visible">True</property>
-            <property name="label" translatable="yes">Time Zone</property>
+            <property name="can_focus">False</property>
             <property name="halign">end</property>
+            <property name="label" translatable="yes">Time Zone</property>
             <style>
               <class name="dim-label"/>
             </style>
@@ -103,24 +113,369 @@
           <packing>
             <property name="left_attach">0</property>
             <property name="top_attach">1</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
           </packing>
         </child>
         <child>
           <object class="GtkLabel" id="current-timezone-label">
             <property name="visible">True</property>
-            <property name="label">America / New York</property>
+            <property name="can_focus">False</property>
             <property name="halign">start</property>
+            <property name="label">America / New York</property>
           </object>
           <packing>
             <property name="left_attach">1</property>
             <property name="top_attach">1</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
           </packing>
         </child>
       </object>
       <packing>
         <property name="left_attach">0</property>
         <property name="top_attach">3</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkAlignment" id="alignment1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="left_padding">12</property>
+        <child>
+          <object class="GtkBox" id="box1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">12</property>
+            <child>
+              <object class="GtkBox" id="box2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkLabel" id="label1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Network Time</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSwitch" id="network_time_switch">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="pack_type">end</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkAlignment" id="alignment2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xscale">0</property>
+                <child>
+                  <object class="GtkGrid" id="time-grid">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="row_spacing">6</property>
+                    <property name="column_spacing">12</property>
+                    <child>
+                      <object class="GtkButton" id="hour_up_button">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="receives_default">True</property>
+                        <property name="relief">none</property>
+                        <child>
+                          <object class="GtkArrow" id="arrow1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="arrow_type">up</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="min_up_button">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="receives_default">True</property>
+                        <property name="relief">none</property>
+                        <child>
+                          <object class="GtkArrow" id="arrow2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="arrow_type">up</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">2</property>
+                        <property name="top_attach">0</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="hour_down_button">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="receives_default">True</property>
+                        <property name="relief">none</property>
+                        <child>
+                          <object class="GtkArrow" id="arrow4">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="arrow_type">down</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">2</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="min_down_button">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="receives_default">True</property>
+                        <property name="relief">none</property>
+                        <child>
+                          <object class="GtkArrow" id="arrow6">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="arrow_type">down</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">2</property>
+                        <property name="top_attach">2</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="hours_label">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">16</property>
+                        <attributes>
+                          <attribute name="weight" value="bold"/>
+                          <attribute name="scale" value="2.5"/>
+                        </attributes>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">1</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="minutes_label">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">45</property>
+                        <attributes>
+                          <attribute name="weight" value="bold"/>
+                          <attribute name="scale" value="2.5"/>
+                        </attributes>
+                      </object>
+                      <packing>
+                        <property name="left_attach">2</property>
+                        <property name="top_attach">1</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">:</property>
+                        <attributes>
+                          <attribute name="weight" value="bold"/>
+                          <attribute name="scale" value="2.5"/>
+                        </attributes>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">1</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="date-box">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkComboBox" id="month-combobox">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="model">month-liststore</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="monthrenderertext"/>
+                      <attributes>
+                        <attribute name="text">0</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSpinButton" id="day-spinbutton">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="invisible_char">•</property>
+                    <property name="input_purpose">number</property>
+                    <property name="numeric">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSpinButton" id="year-spinbutton">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="invisible_char">•</property>
+                    <property name="input_purpose">number</property>
+                    <property name="numeric">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="pack_type">end</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="left_attach">2</property>
+        <property name="top_attach">2</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
       </packing>
     </child>
+    <child>
+      <placeholder/>
+    </child>
+    <child>
+      <placeholder/>
+    </child>
+    <child>
+      <placeholder/>
+    </child>
+    <child>
+      <placeholder/>
+    </child>
+    <child>
+      <placeholder/>
+    </child>
+  </object>
+  <object class="GtkListStore" id="month-liststore">
+    <columns>
+      <!-- column-name month -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">January</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">February</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">March</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">April</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">May</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">June</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">July</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">August</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">September</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">October</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">November</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">December</col>
+      </row>
+    </data>
   </object>
 </interface>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]