datetime: use the SettingsDaemon dbus service to set the system time

Use the org.gnome.SettingsDaemon.DateTimeMechanism interface to set the
current system time.
This commit is contained in:
Thomas Wood 2010-06-24 15:20:45 +01:00
parent 12083b85b5
commit 1d60affa61
5 changed files with 386 additions and 8 deletions

View file

@ -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)

View file

@ -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

View file

@ -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>

View file

@ -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);
}

View file

@ -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