[gnome-control-center/wip/datetime-panel: 9/15] datetime: use the SettingsDaemon dbus service to set the system time



commit 1d60affa617ad4a18814382aefc0538fc74747cd
Author: Thomas Wood <thomas wood intel com>
Date:   Thu Jun 24 15:20:45 2010 +0100

    datetime: use the SettingsDaemon dbus service to set the system time
    
    Use the org.gnome.SettingsDaemon.DateTimeMechanism interface to set the
    current system time.

 panels/datetime/Makefile.am         |    4 +-
 panels/datetime/cc-datetime-panel.c |   51 ++++++
 panels/datetime/datetime.ui         |    8 +-
 panels/datetime/set-timezone.c      |  291 +++++++++++++++++++++++++++++++++++
 panels/datetime/set-timezone.h      |   40 +++++
 5 files changed, 386 insertions(+), 8 deletions(-)
---
diff --git a/panels/datetime/Makefile.am b/panels/datetime/Makefile.am
index 63049d9..f297c5d 100644
--- a/panels/datetime/Makefile.am
+++ b/panels/datetime/Makefile.am
@@ -59,7 +59,9 @@ libdate_time_la_SOURCES =		\
 	cc-datetime-panel.c	\
 	cc-datetime-panel.h	\
 	cc-timezone-map.c	\
-	cc-timezone-map.h
+	cc-timezone-map.h	\
+	set-timezone.c		\
+	set-timezone.h
 
 libdate_time_la_LIBADD = $(PANEL_LIBS)
 libdate_time_la_LDFLAGS = $(PANEL_LDFLAGS)
diff --git a/panels/datetime/cc-datetime-panel.c b/panels/datetime/cc-datetime-panel.c
index fa18c91..eb7d070 100644
--- a/panels/datetime/cc-datetime-panel.c
+++ b/panels/datetime/cc-datetime-panel.c
@@ -22,6 +22,7 @@
 #include "cc-datetime-panel.h"
 
 #include "cc-timezone-map.h"
+#include "set-timezone.h"
 
 G_DEFINE_DYNAMIC_TYPE (CcDateTimePanel, cc_date_time_panel, CC_TYPE_PANEL)
 
@@ -131,6 +132,51 @@ update_time (CcDateTimePanel *self)
   return FALSE;
 }
 
+static void
+cb (CcDateTimePanel *self,
+    GError          *error)
+{
+  /* TODO: display any error in a user friendly way */
+  if (error)
+    {
+      g_warning ("Could not set system time: %s", error->message);
+    }
+}
+
+static void
+apply_button_clicked_cb (GtkButton       *button,
+                         CcDateTimePanel *self)
+{
+  GtkWidget *widget;
+  CcDateTimePanelPrivate *priv = self->priv;
+  guint h, mon, s, y, min, d;
+  struct tm fulltime;
+  time_t unixtime;
+
+  widget = (GtkWidget *) gtk_builder_get_object (priv->builder, "spin_hour");
+  h = gtk_spin_button_get_value (GTK_SPIN_BUTTON (widget));
+  widget = (GtkWidget *) gtk_builder_get_object (priv->builder, "spin_minute");
+  min = gtk_spin_button_get_value (GTK_SPIN_BUTTON (widget));
+  widget = (GtkWidget *) gtk_builder_get_object (priv->builder, "spin_second");
+  s = gtk_spin_button_get_value (GTK_SPIN_BUTTON (widget));
+
+  widget = (GtkWidget *) gtk_builder_get_object (priv->builder, "calendar");
+  gtk_calendar_get_date (GTK_CALENDAR (widget), &y, &mon, &d);
+
+  fulltime.tm_sec = s;
+  fulltime.tm_min = min;
+  fulltime.tm_hour = h;
+  fulltime.tm_mday = d;
+  fulltime.tm_mon = mon;
+  fulltime.tm_year = y - 1900;
+  fulltime.tm_isdst = -1;
+
+
+  unixtime = mktime (&fulltime);
+
+  set_system_time_async (unixtime, (GFunc) cb, self, NULL);
+
+}
 
 static void
 cc_date_time_panel_init (CcDateTimePanel *self)
@@ -187,6 +233,11 @@ cc_date_time_panel_init (CcDateTimePanel *self)
   gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), ltime->tm_min);
   widget = (GtkWidget *) gtk_builder_get_object (priv->builder, "spin_second");
   gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), ltime->tm_sec);
+
+  g_signal_connect ((GtkWidget*) gtk_builder_get_object (priv->builder, "button_apply"),
+                    "clicked",
+                    G_CALLBACK (apply_button_clicked_cb),
+                    self);
 }
 
 void
diff --git a/panels/datetime/datetime.ui b/panels/datetime/datetime.ui
index 9e09681..ec80958 100644
--- a/panels/datetime/datetime.ui
+++ b/panels/datetime/datetime.ui
@@ -76,9 +76,9 @@
                 <child>
                   <object class="GtkCheckButton" id="check_auto_update">
                     <property name="label" translatable="yes">Keep date and time updated automatically</property>
-                    <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="receives_default">False</property>
+                    <property name="no_show_all">True</property>
                     <property name="draw_indicator">True</property>
                   </object>
                   <packing>
@@ -231,19 +231,13 @@
   <object class="GtkAdjustment" id="adjustment_hour">
     <property name="upper">23</property>
     <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-    <property name="page_size">10</property>
   </object>
   <object class="GtkAdjustment" id="adjustment_min">
     <property name="upper">60</property>
     <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-    <property name="page_size">10</property>
   </object>
   <object class="GtkAdjustment" id="adjustment_sec">
     <property name="upper">60</property>
     <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-    <property name="page_size">10</property>
   </object>
 </interface>
diff --git a/panels/datetime/set-timezone.c b/panels/datetime/set-timezone.c
new file mode 100644
index 0000000..91c80dd
--- /dev/null
+++ b/panels/datetime/set-timezone.c
@@ -0,0 +1,291 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david fubar dk>
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/wait.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "set-timezone.h"
+
+
+static DBusGConnection *
+get_system_bus (void)
+{
+        GError          *error;
+        static DBusGConnection *bus = NULL;
+
+	if (bus == NULL) {
+        	error = NULL;
+        	bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        	if (bus == NULL) {
+                	g_warning ("Couldn't connect to system bus: %s", 
+				   error->message);
+                	g_error_free (error);
+		}
+        }
+
+        return bus;
+}
+
+#define CACHE_VALIDITY_SEC 2
+
+typedef  void (*CanDoFunc) (gint value);
+
+static void
+notify_can_do (DBusGProxy     *proxy,
+	       DBusGProxyCall *call,
+	       void           *user_data)
+{
+	CanDoFunc callback = user_data;
+	GError *error = NULL;
+	gint value;
+
+	if (dbus_g_proxy_end_call (proxy, call,
+				   &error,
+				   G_TYPE_INT, &value,
+				   G_TYPE_INVALID)) {
+		callback (value);
+	}
+}
+
+static void
+refresh_can_do (const gchar *action, CanDoFunc callback)
+{
+        DBusGConnection *bus;
+        DBusGProxy      *proxy;
+
+        bus = get_system_bus ();
+        if (bus == NULL)
+                return;
+
+	proxy = dbus_g_proxy_new_for_name (bus,
+					   "org.gnome.SettingsDaemon.DateTimeMechanism",
+					   "/",
+					   "org.gnome.SettingsDaemon.DateTimeMechanism");
+
+	dbus_g_proxy_begin_call_with_timeout (proxy,
+					      action,
+					      notify_can_do,
+					      callback, NULL,
+					      INT_MAX,
+					      G_TYPE_INVALID);
+}
+
+static gint   settimezone_cache = 0;
+static time_t settimezone_stamp = 0;
+
+static void
+update_can_settimezone (gint res)
+{
+	settimezone_cache = res;
+	time (&settimezone_stamp);
+}
+
+gint
+can_set_system_timezone (void)
+{
+	time_t          now;
+
+	time (&now);
+	if (ABS (now - settimezone_stamp) > CACHE_VALIDITY_SEC) {
+		refresh_can_do ("CanSetTimezone", update_can_settimezone);
+		settimezone_stamp = now;
+	}
+
+	return settimezone_cache;
+}
+
+static gint   settime_cache = 0;
+static time_t settime_stamp = 0;
+
+static void
+update_can_settime (gint res)
+{
+	settime_cache = res;
+	time (&settime_stamp);
+}
+
+gint
+can_set_system_time (void)
+{
+	time_t now;
+
+	time (&now);
+	if (ABS (now - settime_stamp) > CACHE_VALIDITY_SEC) {
+		refresh_can_do ("CanSetTime", update_can_settime);
+		settime_stamp = now;
+	}
+
+	return settime_cache;
+}
+
+typedef struct {
+	gint ref_count;
+        gchar *call;
+	gint64 time;
+	gchar *filename;
+	GFunc callback;
+	gpointer data;
+	GDestroyNotify notify;
+} SetTimeCallbackData;
+
+static void
+free_data (gpointer d)
+{
+	SetTimeCallbackData *data = d;
+
+	data->ref_count--;
+	if (data->ref_count == 0) {
+		if (data->notify)
+			data->notify (data->data);
+		g_free (data->filename);
+		g_free (data);
+	}
+}
+
+static void
+set_time_notify (DBusGProxy     *proxy,
+		 DBusGProxyCall *call,
+		 void           *user_data)
+{
+	SetTimeCallbackData *data = user_data;
+	GError *error = NULL;
+
+	if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) {
+		if (data->callback) 
+			data->callback (data->data, NULL);
+	}
+	else {
+		if (error->domain == DBUS_GERROR &&
+		    error->code == DBUS_GERROR_NO_REPLY) {
+			/* these errors happen because dbus doesn't
+			 * use monotonic clocks
+			 */	
+			g_warning ("ignoring no-reply error when setting time");
+			g_error_free (error);
+			if (data->callback)
+				data->callback (data->data, NULL);
+		}
+		else {
+			if (data->callback)
+				data->callback (data->data, error);
+			else
+				g_error_free (error);
+		}		
+	}
+}
+
+static void
+set_time_async (SetTimeCallbackData *data)
+{
+        DBusGConnection *bus;
+        DBusGProxy      *proxy;
+
+        bus = get_system_bus ();
+        if (bus == NULL)
+                return;
+
+	proxy = dbus_g_proxy_new_for_name (bus,
+					   "org.gnome.SettingsDaemon.DateTimeMechanism",
+					   "/",
+					   "org.gnome.SettingsDaemon.DateTimeMechanism");
+
+	data->ref_count++;
+	if (strcmp (data->call, "SetTime") == 0)
+		dbus_g_proxy_begin_call_with_timeout (proxy, 
+						      "SetTime",
+						      set_time_notify,
+						      data, free_data,
+						      INT_MAX,
+						      /* parameters: */
+						      G_TYPE_INT64, data->time,
+						      G_TYPE_INVALID,
+						      /* return values: */
+						      G_TYPE_INVALID);
+	else 
+		dbus_g_proxy_begin_call_with_timeout (proxy, 
+						      "SetTimezone",
+						      set_time_notify,
+						      data, free_data,
+						      INT_MAX,
+						      /* parameters: */
+						      G_TYPE_STRING, data->filename,
+						      G_TYPE_INVALID,
+						      /* return values: */
+						      G_TYPE_INVALID);
+}
+
+void
+set_system_time_async (gint64         time,
+		       GFunc          callback,
+		       gpointer       d,
+		       GDestroyNotify notify)
+{
+	SetTimeCallbackData *data;
+
+	if (time == -1)
+		return;
+
+	data = g_new0 (SetTimeCallbackData, 1);
+	data->ref_count = 1;
+	data->call = "SetTime";
+	data->time = time;
+	data->filename = NULL;
+	data->callback = callback;
+	data->data = d;
+	data->notify = notify;
+
+	set_time_async (data);
+	free_data (data);
+}
+
+void
+set_system_timezone_async (const gchar    *filename,
+			   GFunc           callback,
+			   gpointer        d,
+			   GDestroyNotify  notify)
+{
+	SetTimeCallbackData *data;
+
+	if (filename == NULL)
+		return;
+
+	data = g_new0 (SetTimeCallbackData, 1);
+	data->ref_count = 1;
+	data->call = "SetTimezone";
+	data->time = -1;
+	data->filename = g_strdup (filename);
+	data->callback = callback;
+	data->data = d;
+	data->notify = notify;
+
+	set_time_async (data);
+	free_data (data);
+}
diff --git a/panels/datetime/set-timezone.h b/panels/datetime/set-timezone.h
new file mode 100644
index 0000000..5280b07
--- /dev/null
+++ b/panels/datetime/set-timezone.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david fubar dk>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __SET_SYSTEM_TIMEZONE_H__
+
+#include <glib.h>
+#include <time.h>
+
+gint     can_set_system_timezone (void);
+
+gint     can_set_system_time     (void);
+
+void     set_system_time_async   (gint64         time,
+                                  GFunc          callback,
+                                  gpointer       data,
+                                  GDestroyNotify notify);
+
+void     set_system_timezone_async   (const gchar    *filename,
+                                      GFunc           callback,
+                                      gpointer        data,
+                                      GDestroyNotify  notify);
+
+#endif



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