diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | configure.ac | 9 | ||||
-rw-r--r-- | data/Makefile.am | 1 | ||||
-rw-r--r-- | data/org.gnome.settings-daemon.plugins.datetime.gschema.xml.in.in | 14 | ||||
-rw-r--r-- | data/org.gnome.settings-daemon.plugins.gschema.xml.in.in | 1 | ||||
-rw-r--r-- | plugins/Makefile.am | 1 | ||||
-rw-r--r-- | plugins/datetime/Makefile.am | 104 | ||||
-rw-r--r-- | plugins/datetime/backward | 118 | ||||
-rw-r--r-- | plugins/datetime/datetime.gnome-settings-plugin.in | 10 | ||||
-rw-r--r-- | plugins/datetime/geoclue-interface.xml | 25 | ||||
-rw-r--r-- | plugins/datetime/gsd-datetime-manager.c | 152 | ||||
-rw-r--r-- | plugins/datetime/gsd-datetime-manager.h | 57 | ||||
-rw-r--r-- | plugins/datetime/gsd-datetime-plugin.c | 29 | ||||
-rw-r--r-- | plugins/datetime/gsd-timezone-monitor.c | 355 | ||||
-rw-r--r-- | plugins/datetime/gsd-timezone-monitor.h | 54 | ||||
-rw-r--r-- | plugins/datetime/test-datetime.c | 7 | ||||
-rw-r--r-- | plugins/datetime/timedated1-interface.xml | 28 | ||||
-rw-r--r-- | plugins/datetime/tz.c | 482 | ||||
-rw-r--r-- | plugins/datetime/tz.h | 89 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | po/POTFILES.skip | 1 |
21 files changed, 1543 insertions, 0 deletions
@@ -56,6 +56,11 @@ plugins/background/test-background plugins/common/gsd-test-input-helper plugins/common/test-egg-key-parsing plugins/cursor/gsd-test-cursor +plugins/datetime/gsd-test-datetime +plugins/datetime/geoclue.c +plugins/datetime/geoclue.h +plugins/datetime/timedated.c +plugins/datetime/timedated.h plugins/housekeeping/gsd-disk-space-test plugins/housekeeping/gsd-empty-trash-test plugins/housekeeping/gsd-test-housekeeping diff --git a/configure.ac b/configure.ac index 41b748b4..47710ef9 100644 --- a/configure.ac +++ b/configure.ac @@ -245,6 +245,13 @@ dnl --------------------------------------------------------------------------- PKG_CHECK_MODULES(COLOR, [colord >= 1.0.2 gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION libcanberra-gtk3]) dnl --------------------------------------------------------------------------- +dnl - datetime +dnl --------------------------------------------------------------------------- + +AC_CHECK_LIBM +AC_SUBST(LIBM) + +dnl --------------------------------------------------------------------------- dnl - wacom (disabled for s390/s390x and non Linux platforms) dnl --------------------------------------------------------------------------- @@ -508,6 +515,7 @@ plugins/clipboard/Makefile plugins/color/Makefile plugins/common/Makefile plugins/cursor/Makefile +plugins/datetime/Makefile plugins/dummy/Makefile plugins/power/Makefile plugins/housekeeping/Makefile @@ -534,6 +542,7 @@ data/org.gnome.settings-daemon.plugins.xsettings.gschema.xml.in data/org.gnome.settings-daemon.plugins.keyboard.gschema.xml.in data/org.gnome.settings-daemon.plugins.power.gschema.xml.in data/org.gnome.settings-daemon.plugins.color.gschema.xml.in +data/org.gnome.settings-daemon.plugins.datetime.gschema.xml.in data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in data/org.gnome.settings-daemon.peripherals.gschema.xml.in data/org.gnome.settings-daemon.plugins.housekeeping.gschema.xml.in diff --git a/data/Makefile.am b/data/Makefile.am index ecfe00a9..c1522db0 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -12,6 +12,7 @@ gsettings_SCHEMAS = \ org.gnome.settings-daemon.plugins.keyboard.gschema.xml \ org.gnome.settings-daemon.plugins.power.gschema.xml \ org.gnome.settings-daemon.plugins.color.gschema.xml \ + org.gnome.settings-daemon.plugins.datetime.gschema.xml \ org.gnome.settings-daemon.plugins.media-keys.gschema.xml \ org.gnome.settings-daemon.plugins.xsettings.gschema.xml \ org.gnome.settings-daemon.plugins.housekeeping.gschema.xml \ diff --git a/data/org.gnome.settings-daemon.plugins.datetime.gschema.xml.in.in b/data/org.gnome.settings-daemon.plugins.datetime.gschema.xml.in.in new file mode 100644 index 00000000..eacc4a0d --- /dev/null +++ b/data/org.gnome.settings-daemon.plugins.datetime.gschema.xml.in.in @@ -0,0 +1,14 @@ +<schemalist> + <schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.settings-daemon.plugins.datetime" path="/org/gnome/settings-daemon/plugins/datetime/"> + <key name="active" type="b"> + <default>true</default> + <_summary>Activation of this plugin</_summary> + <_description>Whether this plugin would be activated by gnome-settings-daemon or not</_description> + </key> + <key name="priority" type="i"> + <default>0</default> + <_summary>Priority to use for this plugin</_summary> + <_description>Priority to use for this plugin in gnome-settings-daemon startup queue</_description> + </key> + </schema> +</schemalist> diff --git a/data/org.gnome.settings-daemon.plugins.gschema.xml.in.in b/data/org.gnome.settings-daemon.plugins.gschema.xml.in.in index bea64f3e..57a058db 100644 --- a/data/org.gnome.settings-daemon.plugins.gschema.xml.in.in +++ b/data/org.gnome.settings-daemon.plugins.gschema.xml.in.in @@ -14,6 +14,7 @@ <child name="clipboard" schema="org.gnome.settings-daemon.plugins.clipboard"/> <child name="color" schema="org.gnome.settings-daemon.plugins.color"/> <child name="cursor" schema="org.gnome.settings-daemon.plugins.cursor"/> + <child name="datetime" schema="org.gnome.settings-daemon.plugins.datetime"/> <child name="gsdwacom" schema="org.gnome.settings-daemon.plugins.gsdwacom"/> <child name="housekeeping" schema="org.gnome.settings-daemon.plugins.housekeeping"/> <child name="keyboard" schema="org.gnome.settings-daemon.plugins.keyboard"/> diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 787fd141..2f4840de 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -6,6 +6,7 @@ enabled_plugins = \ clipboard \ color \ cursor \ + datetime \ dummy \ power \ housekeeping \ diff --git a/plugins/datetime/Makefile.am b/plugins/datetime/Makefile.am new file mode 100644 index 00000000..f8cdbe2d --- /dev/null +++ b/plugins/datetime/Makefile.am @@ -0,0 +1,104 @@ +plugin_name = datetime + +geoclue.c: geoclue.h +geoclue.h: Makefile.am geoclue-interface.xml + gdbus-codegen \ + --interface-prefix org.freedesktop.GeoClue2 \ + --generate-c-code geoclue \ + --c-namespace Geoclue \ + $(srcdir)/geoclue-interface.xml + +timedated.c: timedated.h +timedated.h: Makefile.am timedated1-interface.xml + gdbus-codegen \ + --interface-prefix org.freedesktop. \ + --generate-c-code timedated \ + $(srcdir)/timedated1-interface.xml + +BUILT_SOURCES = \ + geoclue.c \ + geoclue.h \ + timedated.c \ + timedated.h + +tzdatadir = $(pkgdatadir)/datetime +dist_tzdata_DATA = backward + +libexec_PROGRAMS = gsd-test-datetime + +gsd_test_datetime_SOURCES = \ + $(BUILT_SOURCES) \ + gsd-datetime-manager.c \ + gsd-datetime-manager.h \ + gsd-timezone-monitor.c \ + gsd-timezone-monitor.h \ + test-datetime.c \ + tz.c \ + tz.h + +gsd_test_datetime_CFLAGS = \ + -I$(top_srcdir)/gnome-settings-daemon \ + -I$(top_builddir)/gnome-settings-daemon \ + -I$(top_srcdir)/plugins/common \ + -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ + -DGNOMECC_DATA_DIR="\"$(pkgdatadir)\"" \ + $(DATETIME_CFLAGS) \ + $(PLUGIN_CFLAGS) \ + $(SETTINGS_PLUGIN_CFLAGS) \ + $(AM_CFLAGS) + +gsd_test_datetime_LDADD = \ + $(top_builddir)/gnome-settings-daemon/libgsd.la \ + $(top_builddir)/plugins/common/libcommon.la \ + $(LIBM) \ + $(SETTINGS_PLUGIN_LIBS) + +plugin_LTLIBRARIES = \ + libdatetime.la + +libdatetime_la_SOURCES = \ + $(BUILT_SOURCES) \ + gsd-datetime-plugin.c \ + gsd-datetime-manager.h \ + gsd-datetime-manager.c \ + gsd-timezone-monitor.h \ + gsd-timezone-monitor.c \ + tz.h \ + tz.c + +libdatetime_la_CPPFLAGS = \ + -I$(top_srcdir)/gnome-settings-daemon \ + -I$(top_builddir)/gnome-settings-daemon \ + -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ + -DGNOMECC_DATA_DIR="\"$(pkgdatadir)\"" \ + $(AM_CPPFLAGS) + +libdatetime_la_CFLAGS = \ + $(PLUGIN_CFLAGS) \ + $(SETTINGS_PLUGIN_CFLAGS) \ + $(AM_CFLAGS) + +libdatetime_la_LDFLAGS = \ + $(GSD_PLUGIN_LDFLAGS) + +libdatetime_la_LIBADD = \ + $(LIBM) \ + $(SETTINGS_PLUGIN_LIBS) + +plugin_in_files = \ + datetime.gnome-settings-plugin.in + +plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) + +EXTRA_DIST = \ + geoclue-interface.xml \ + timedated1-interface.xml \ + $(plugin_in_files) + +CLEANFILES = \ + $(plugin_DATA) + +DISTCLEANFILES = \ + $(plugin_DATA) + +@GSD_INTLTOOL_PLUGIN_RULE@ diff --git a/plugins/datetime/backward b/plugins/datetime/backward new file mode 100644 index 00000000..f1f95a89 --- /dev/null +++ b/plugins/datetime/backward @@ -0,0 +1,118 @@ +# <pre> +# @(#)backward 8.9 +# This file is in the public domain, so clarified as of +# 2009-05-17 by Arthur David Olson. + +# This file provides links between current names for time zones +# and their old names. Many names changed in late 1993. + +Link Africa/Asmara Africa/Asmera +Link Africa/Bamako Africa/Timbuktu +Link America/Argentina/Catamarca America/Argentina/ComodRivadavia +Link America/Adak America/Atka +Link America/Argentina/Buenos_Aires America/Buenos_Aires +Link America/Argentina/Catamarca America/Catamarca +Link America/Atikokan America/Coral_Harbour +Link America/Argentina/Cordoba America/Cordoba +Link America/Tijuana America/Ensenada +Link America/Indiana/Indianapolis America/Fort_Wayne +Link America/Indiana/Indianapolis America/Indianapolis +Link America/Argentina/Jujuy America/Jujuy +Link America/Indiana/Knox America/Knox_IN +Link America/Kentucky/Louisville America/Louisville +Link America/Argentina/Mendoza America/Mendoza +Link America/Rio_Branco America/Porto_Acre +Link America/Argentina/Cordoba America/Rosario +Link America/St_Thomas America/Virgin +Link Asia/Ashgabat Asia/Ashkhabad +Link Asia/Chongqing Asia/Chungking +Link Asia/Dhaka Asia/Dacca +Link Asia/Kathmandu Asia/Katmandu +Link Asia/Kolkata Asia/Calcutta +Link Asia/Macau Asia/Macao +Link Asia/Jerusalem Asia/Tel_Aviv +Link Asia/Ho_Chi_Minh Asia/Saigon +Link Asia/Thimphu Asia/Thimbu +Link Asia/Makassar Asia/Ujung_Pandang +Link Asia/Ulaanbaatar Asia/Ulan_Bator +Link Atlantic/Faroe Atlantic/Faeroe +Link Europe/Oslo Atlantic/Jan_Mayen +Link Australia/Sydney Australia/ACT +Link Australia/Sydney Australia/Canberra +Link Australia/Lord_Howe Australia/LHI +Link Australia/Sydney Australia/NSW +Link Australia/Darwin Australia/North +Link Australia/Brisbane Australia/Queensland +Link Australia/Adelaide Australia/South +Link Australia/Hobart Australia/Tasmania +Link Australia/Melbourne Australia/Victoria +Link Australia/Perth Australia/West +Link Australia/Broken_Hill Australia/Yancowinna +Link America/Rio_Branco Brazil/Acre +Link America/Noronha Brazil/DeNoronha +Link America/Sao_Paulo Brazil/East +Link America/Manaus Brazil/West +Link America/Halifax Canada/Atlantic +Link America/Winnipeg Canada/Central +Link America/Regina Canada/East-Saskatchewan +Link America/Toronto Canada/Eastern +Link America/Edmonton Canada/Mountain +Link America/St_Johns Canada/Newfoundland +Link America/Vancouver Canada/Pacific +Link America/Regina Canada/Saskatchewan +Link America/Whitehorse Canada/Yukon +Link America/Santiago Chile/Continental +Link Pacific/Easter Chile/EasterIsland +Link America/Havana Cuba +Link Africa/Cairo Egypt +Link Europe/Dublin Eire +Link Europe/London Europe/Belfast +Link Europe/Chisinau Europe/Tiraspol +Link Europe/London GB +Link Europe/London GB-Eire +Link Etc/GMT GMT+0 +Link Etc/GMT GMT-0 +Link Etc/GMT GMT0 +Link Etc/GMT Greenwich +Link Asia/Hong_Kong Hongkong +Link Atlantic/Reykjavik Iceland +Link Asia/Tehran Iran +Link Asia/Jerusalem Israel +Link America/Jamaica Jamaica +Link Asia/Tokyo Japan +Link Pacific/Kwajalein Kwajalein +Link Africa/Tripoli Libya +Link America/Tijuana Mexico/BajaNorte +Link America/Mazatlan Mexico/BajaSur +Link America/Mexico_City Mexico/General +Link Pacific/Auckland NZ +Link Pacific/Chatham NZ-CHAT +Link America/Denver Navajo +Link Asia/Shanghai PRC +Link Pacific/Pago_Pago Pacific/Samoa +Link Pacific/Chuuk Pacific/Yap +Link Pacific/Chuuk Pacific/Truk +Link Pacific/Pohnpei Pacific/Ponape +Link Europe/Warsaw Poland +Link Europe/Lisbon Portugal +Link Asia/Taipei ROC +Link Asia/Seoul ROK +Link Asia/Singapore Singapore +Link Europe/Istanbul Turkey +Link Etc/UCT UCT +Link America/Anchorage US/Alaska +Link America/Adak US/Aleutian +Link America/Phoenix US/Arizona +Link America/Chicago US/Central +Link America/Indiana/Indianapolis US/East-Indiana +Link America/New_York US/Eastern +Link Pacific/Honolulu US/Hawaii +Link America/Indiana/Knox US/Indiana-Starke +Link America/Detroit US/Michigan +Link America/Denver US/Mountain +Link America/Los_Angeles US/Pacific +Link Pacific/Pago_Pago US/Samoa +Link Etc/UTC UTC +Link Etc/UTC Universal +Link Europe/Moscow W-SU +Link Etc/UTC Zulu diff --git a/plugins/datetime/datetime.gnome-settings-plugin.in b/plugins/datetime/datetime.gnome-settings-plugin.in new file mode 100644 index 00000000..f7b8b5a1 --- /dev/null +++ b/plugins/datetime/datetime.gnome-settings-plugin.in @@ -0,0 +1,10 @@ +[GNOME Settings Plugin] +Module=datetime +IAge=0 +# Default Priority +# Priority=100 +_Name=Date and Time +_Description=Automatically update timezone and display notifications +Authors=Kalev Lember +Copyright=Copyright © 2013 +Website= diff --git a/plugins/datetime/geoclue-interface.xml b/plugins/datetime/geoclue-interface.xml new file mode 100644 index 00000000..3bf956b3 --- /dev/null +++ b/plugins/datetime/geoclue-interface.xml @@ -0,0 +1,25 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" +"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.freedesktop.GeoClue2.Manager"> + <method name="GetClient"> + <arg name="client" type="o" direction="out"/> + </method> + </interface> + <interface name="org.freedesktop.GeoClue2.Client"> + <property name="Location" type="o" access="read"/> + <property name="DistanceThreshold" type="u" access="readwrite"/> + <method name="Start"/> + <method name="Stop"/> + <signal name="LocationUpdated"> + <arg name="old" type="o"/> + <arg name="new" type="o"/> + </signal> + </interface> + <interface name="org.freedesktop.GeoClue2.Location"> + <property name="latitude" type="d" access="read"/> + <property name="longitude" type="d" access="read"/> + <property name="accuracy" type="d" access="read"/> + <property name="description" type="s" access="read"/> + </interface> +</node> diff --git a/plugins/datetime/gsd-datetime-manager.c b/plugins/datetime/gsd-datetime-manager.c new file mode 100644 index 00000000..e08203b1 --- /dev/null +++ b/plugins/datetime/gsd-datetime-manager.c @@ -0,0 +1,152 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2013 Kalev Lember <kalevlember@gmail.com> + * + * 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. + * + */ + +#include "config.h" + +#include <gio/gio.h> + +#include "gsd-datetime-manager.h" +#include "gsd-timezone-monitor.h" +#include "gnome-settings-profile.h" + +#define GSD_DATETIME_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_DATETIME_MANAGER, GsdDatetimeManagerPrivate)) + +#define DATETIME_SCHEMA "org.gnome.desktop.datetime" +#define AUTO_TIMEZONE_KEY "automatic-timezone" + +struct GsdDatetimeManagerPrivate +{ + GSettings *settings; + GsdTimezoneMonitor *timezone_monitor; +}; + +static void gsd_datetime_manager_class_init (GsdDatetimeManagerClass *klass); +static void gsd_datetime_manager_init (GsdDatetimeManager *manager); +static void gsd_datetime_manager_finalize (GObject *object); + +G_DEFINE_TYPE (GsdDatetimeManager, gsd_datetime_manager, G_TYPE_OBJECT) + +static gpointer manager_object = NULL; + +static void +auto_timezone_settings_changed_cb (GSettings *settings, + const char *key, + GsdDatetimeManager *self) +{ + gboolean enabled; + + enabled = g_settings_get_boolean (settings, key); + if (enabled && self->priv->timezone_monitor == NULL) { + g_debug ("Automatic timezone enabled"); + self->priv->timezone_monitor = gsd_timezone_monitor_new (); + } else { + g_debug ("Automatic timezone disabled"); + g_clear_object (&self->priv->timezone_monitor); + } +} + +gboolean +gsd_datetime_manager_start (GsdDatetimeManager *self, + GError **error) +{ + g_debug ("Starting datetime manager"); + gnome_settings_profile_start (NULL); + + self->priv->settings = g_settings_new (DATETIME_SCHEMA); + + auto_timezone_settings_changed_cb (self->priv->settings, AUTO_TIMEZONE_KEY, self); + g_signal_connect (self->priv->settings, "changed::" AUTO_TIMEZONE_KEY, + G_CALLBACK (auto_timezone_settings_changed_cb), self); + + gnome_settings_profile_end (NULL); + + return TRUE; +} + +void +gsd_datetime_manager_stop (GsdDatetimeManager *self) +{ + g_debug ("Stopping datetime manager"); + + g_clear_object (&self->priv->settings); + g_clear_object (&self->priv->timezone_monitor); +} + +static GObject * +gsd_datetime_manager_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GsdDatetimeManager *m; + + m = GSD_DATETIME_MANAGER (G_OBJECT_CLASS (gsd_datetime_manager_parent_class)->constructor (type, + n_construct_properties, + construct_properties)); + + return G_OBJECT (m); +} + +static void +gsd_datetime_manager_class_init (GsdDatetimeManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructor = gsd_datetime_manager_constructor; + object_class->finalize = gsd_datetime_manager_finalize; + + g_type_class_add_private (klass, sizeof (GsdDatetimeManagerPrivate)); +} + +static void +gsd_datetime_manager_init (GsdDatetimeManager *manager) +{ + manager->priv = GSD_DATETIME_MANAGER_GET_PRIVATE (manager); +} + +static void +gsd_datetime_manager_finalize (GObject *object) +{ + GsdDatetimeManager *manager; + + g_return_if_fail (object != NULL); + g_return_if_fail (GSD_IS_DATETIME_MANAGER (object)); + + manager = GSD_DATETIME_MANAGER (object); + + g_return_if_fail (manager->priv != NULL); + + gsd_datetime_manager_stop (manager); + + G_OBJECT_CLASS (gsd_datetime_manager_parent_class)->finalize (object); +} + +GsdDatetimeManager * +gsd_datetime_manager_new (void) +{ + if (manager_object != NULL) { + g_object_ref (manager_object); + } else { + manager_object = g_object_new (GSD_TYPE_DATETIME_MANAGER, NULL); + g_object_add_weak_pointer (manager_object, + (gpointer *) &manager_object); + } + + return GSD_DATETIME_MANAGER (manager_object); +} diff --git a/plugins/datetime/gsd-datetime-manager.h b/plugins/datetime/gsd-datetime-manager.h new file mode 100644 index 00000000..2125d3c0 --- /dev/null +++ b/plugins/datetime/gsd-datetime-manager.h @@ -0,0 +1,57 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2013 Kalev Lember <kalevlember@gmail.com> + * + * 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 __GSD_DATETIME_MANAGER_H +#define __GSD_DATETIME_MANAGER_H + +#include <glib.h> +#include <glib-object.h> + +G_BEGIN_DECLS + +#define GSD_TYPE_DATETIME_MANAGER (gsd_datetime_manager_get_type ()) +#define GSD_DATETIME_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_DATETIME_MANAGER, GsdDatetimeManager)) +#define GSD_DATETIME_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSD_TYPE_DATETIME_MANAGER, GsdDatetimeManagerClass)) +#define GSD_IS_DATETIME_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_DATETIME_MANAGER)) +#define GSD_IS_DATETIME_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_DATETIME_MANAGER)) +#define GSD_DATETIME_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_DATETIME_MANAGER, GsdDatetimeManagerClass)) + +typedef struct GsdDatetimeManagerPrivate GsdDatetimeManagerPrivate; + +typedef struct +{ + GObject parent; + GsdDatetimeManagerPrivate *priv; +} GsdDatetimeManager; + +typedef struct +{ + GObjectClass parent_class; +} GsdDatetimeManagerClass; + +GType gsd_datetime_manager_get_type (void) G_GNUC_CONST; + +GsdDatetimeManager *gsd_datetime_manager_new (void); +gboolean gsd_datetime_manager_start (GsdDatetimeManager *manager, GError **error); +void gsd_datetime_manager_stop (GsdDatetimeManager *manager); + +G_END_DECLS + +#endif /* __GSD_DATETIME_MANAGER_H */ diff --git a/plugins/datetime/gsd-datetime-plugin.c b/plugins/datetime/gsd-datetime-plugin.c new file mode 100644 index 00000000..af5564c8 --- /dev/null +++ b/plugins/datetime/gsd-datetime-plugin.c @@ -0,0 +1,29 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2013 Kalev Lember <kalevlember@gmail.com> + * + * 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, 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. + * + */ + +#include "config.h" + +#include <glib/gi18n-lib.h> +#include <gmodule.h> + +#include "gnome-settings-plugin.h" +#include "gsd-datetime-manager.h" + +GNOME_SETTINGS_PLUGIN_REGISTER (GsdDatetime, gsd_datetime) diff --git a/plugins/datetime/gsd-timezone-monitor.c b/plugins/datetime/gsd-timezone-monitor.c new file mode 100644 index 00000000..f283d692 --- /dev/null +++ b/plugins/datetime/gsd-timezone-monitor.c @@ -0,0 +1,355 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2013 Kalev Lember <kalevlember@gmail.com> + * + * 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. + * + */ + +#include "config.h" + +#include "gsd-timezone-monitor.h" + +#include "geoclue.h" +#include "timedated.h" +#include "tz.h" + +#include <math.h> + +typedef struct +{ + GCancellable *cancellable; + GeoclueClient *geoclue_client; + GeoclueManager *geoclue_manager; + Timedate1 *dtm; + + TzDB *tzdb; + gchar *current_timezone; +} GsdTimezoneMonitorPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (GsdTimezoneMonitor, gsd_timezone_monitor, G_TYPE_OBJECT) + +static void +set_timezone_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + GsdTimezoneMonitor *self = user_data; + GsdTimezoneMonitorPrivate *priv = gsd_timezone_monitor_get_instance_private (self); + GError *error = NULL; + + if (!timedate1_call_set_timezone_finish (priv->dtm, + res, + &error)) { + g_warning ("Could not set system timezone: %s", error->message); + g_error_free (error); + } +} + +static void +queue_set_timezone (GsdTimezoneMonitor *self, + const char *timezone) +{ + GsdTimezoneMonitorPrivate *priv = gsd_timezone_monitor_get_instance_private (self); + + timedate1_call_set_timezone (priv->dtm, + timezone, + TRUE, + priv->cancellable, + set_timezone_cb, + self); +} + + +#define EARTH_RADIUS_KM 6372.795 + +/* Copy of geocode_location_get_distance_from() from geocode-glib */ +static double +distance_between (gdouble loca_latitude, gdouble loca_longitude, + gdouble locb_latitude, gdouble locb_longitude) +{ + gdouble dlat, dlon, lat1, lat2; + gdouble a, c; + + /* Algorithm from: + * http://www.movable-type.co.uk/scripts/latlong.html */ + + dlat = (locb_latitude - loca_latitude) * M_PI / 180.0; + dlon = (locb_longitude - loca_longitude) * M_PI / 180.0; + lat1 = loca_latitude * M_PI / 180.0; + lat2 = locb_latitude * M_PI / 180.0; + + a = sin (dlat / 2) * sin (dlat / 2) + + sin (dlon / 2) * sin (dlon / 2) * cos (lat1) * cos (lat2); + c = 2 * atan2 (sqrt (a), sqrt (1-a)); + return EARTH_RADIUS_KM * c; +} + +static gint +compare_locations (TzLocation *a, + TzLocation *b) +{ + if (a->dist > b->dist) + return 1; + + if (a->dist < b->dist) + return -1; + + return 0; +} + +static void +process_location (GsdTimezoneMonitor *self, + gdouble latitude, + gdouble longitude) +{ + GsdTimezoneMonitorPrivate *priv = gsd_timezone_monitor_get_instance_private (self); + GPtrArray *array; + GList *distances = NULL; + TzLocation *closest_tz_location; + gint i; + + array = tz_get_locations (priv->tzdb); + + for (i = 0; i < array->len; i++) { + TzLocation *loc = array->pdata[i]; + + loc->dist = distance_between (latitude, longitude, + loc->latitude, loc->longitude); + distances = g_list_prepend (distances, loc); + + } + distances = g_list_sort (distances, (GCompareFunc) compare_locations); + + closest_tz_location = (TzLocation*) distances->data; + if (g_strcmp0 (priv->current_timezone, closest_tz_location->zone) != 0) { + g_debug ("Changing timezone to %s", closest_tz_location->zone); + queue_set_timezone (self, closest_tz_location->zone); + } + + g_list_free (distances); +} + +static void +on_location_proxy_ready (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GeoclueLocation *location; + gdouble latitude, longitude; + GError *error = NULL; + GsdTimezoneMonitor *self = user_data; + + location = geoclue_location_proxy_new_for_bus_finish (res, &error); + if (error != NULL) { + g_critical ("Failed to connect to GeoClue2 service: %s", error->message); + g_error_free (error); + return; + } + + latitude = geoclue_location_get_latitude (location); + longitude = geoclue_location_get_longitude (location); + + process_location (self, latitude, longitude); + + g_object_unref (location); +} + +static void +on_location_updated (GDBusProxy *client, + gchar *location_path_old, + gchar *location_path_new, + gpointer user_data) +{ + GsdTimezoneMonitor *self = user_data; + GsdTimezoneMonitorPrivate *priv = gsd_timezone_monitor_get_instance_private (self); + + geoclue_location_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.GeoClue2", + location_path_new, + priv->cancellable, + on_location_proxy_ready, + self); +} + +static void +on_start_ready (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + + if (!geoclue_client_call_start_finish (GEOCLUE_CLIENT (source_object), + res, + &error)) { + g_critical ("Failed to start GeoClue2 client: %s", error->message); + g_error_free (error); + return; + } +} + +static void +on_client_proxy_ready (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + GsdTimezoneMonitor *self = user_data; + GsdTimezoneMonitorPrivate *priv = gsd_timezone_monitor_get_instance_private (self); + + priv->geoclue_client = geoclue_client_proxy_new_for_bus_finish (res, &error); + if (error != NULL) { + g_critical ("Failed to connect to GeoClue2 service: %s", error->message); + g_error_free (error); + return; + } + + g_signal_connect (priv->geoclue_client, "location-updated", + G_CALLBACK (on_location_updated), self); + + geoclue_client_call_start (priv->geoclue_client, + priv->cancellable, + on_start_ready, + self); +} + +static void +on_get_client_ready (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + gchar *client_path; + GError *error = NULL; + GsdTimezoneMonitor *self = user_data; + GsdTimezoneMonitorPrivate *priv = gsd_timezone_monitor_get_instance_private (self); + + if (!geoclue_manager_call_get_client_finish (GEOCLUE_MANAGER (source_object), + &client_path, + res, + &error)) { + g_critical ("Failed to connect to GeoClue2 service: %s", error->message); + g_error_free (error); + return; + } + + geoclue_client_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.GeoClue2", + client_path, + priv->cancellable, + on_client_proxy_ready, + self); +} + +static void +on_manager_proxy_ready (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + + GError *error = NULL; + GsdTimezoneMonitor *self = user_data; + GsdTimezoneMonitorPrivate *priv = gsd_timezone_monitor_get_instance_private (self); + + priv->geoclue_manager = geoclue_manager_proxy_new_for_bus_finish (res, &error); + if (error != NULL) { + g_critical ("Failed to connect to GeoClue2 service: %s", error->message); + g_error_free (error); + return; + } + + geoclue_manager_call_get_client (priv->geoclue_manager, + priv->cancellable, + on_get_client_ready, + self); +} + +static void +register_geoclue (GsdTimezoneMonitor *self) +{ + GsdTimezoneMonitorPrivate *priv = gsd_timezone_monitor_get_instance_private (self); + + geoclue_manager_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.GeoClue2", + "/org/freedesktop/GeoClue2/Manager", + priv->cancellable, + on_manager_proxy_ready, + self); +} + +GsdTimezoneMonitor * +gsd_timezone_monitor_new (void) +{ + return g_object_new (GSD_TYPE_TIMEZONE_MONITOR, NULL); +} + +static void +gsd_timezone_monitor_finalize (GObject *obj) +{ + GsdTimezoneMonitor *monitor = GSD_TIMEZONE_MONITOR (obj); + GsdTimezoneMonitorPrivate *priv = gsd_timezone_monitor_get_instance_private (monitor); + + g_debug ("Stopping timezone monitor"); + + if (priv->cancellable) { + g_cancellable_cancel (priv->cancellable); + g_clear_object (&priv->cancellable); + } + + g_clear_object (&priv->dtm); + g_clear_object (&priv->geoclue_client); + g_clear_object (&priv->geoclue_manager); + g_clear_pointer (&priv->current_timezone, g_free); + g_clear_pointer (&priv->tzdb, tz_db_free); + + G_OBJECT_CLASS (gsd_timezone_monitor_parent_class)->finalize (obj); +} + +static void +gsd_timezone_monitor_class_init (GsdTimezoneMonitorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gsd_timezone_monitor_finalize; +} + +static void +gsd_timezone_monitor_init (GsdTimezoneMonitor *self) +{ + GError *error = NULL; + GsdTimezoneMonitorPrivate *priv = gsd_timezone_monitor_get_instance_private (self); + + g_debug ("Starting timezone monitor"); + + priv->cancellable = g_cancellable_new (); + priv->dtm = timedate1_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.timedate1", + "/org/freedesktop/timedate1", + priv->cancellable, + &error); + if (priv->dtm == NULL) { + g_warning ("Could not get proxy for DateTimeMechanism: %s", error->message); + g_error_free (error); + return; + } + + priv->current_timezone = timedate1_dup_timezone (priv->dtm); + priv->tzdb = tz_load_db (); + + register_geoclue (self); +} diff --git a/plugins/datetime/gsd-timezone-monitor.h b/plugins/datetime/gsd-timezone-monitor.h new file mode 100644 index 00000000..d3aa3b35 --- /dev/null +++ b/plugins/datetime/gsd-timezone-monitor.h @@ -0,0 +1,54 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2013 Kalev Lember <kalevlember@gmail.com> + * + * 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 __GSD_TIMEZONE_MONITOR_H +#define __GSD_TIMEZONE_MONITOR_H + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define GSD_TYPE_TIMEZONE_MONITOR (gsd_timezone_monitor_get_type ()) +#define GSD_TIMEZONE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_TIMEZONE_MONITOR, GsdTimezoneMonitor)) +#define GSD_IS_TIMEZONE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_TIMEZONE_MONITOR)) +#define GSD_TIMEZONE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_TIMEZONE_MONITOR, GsdTimezoneMonitorClass)) +#define GSD_IS_TIMEZONE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_TIMEZONE_MONITOR)) +#define GSD_TIMEZONE_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_TIMEZONE_MONITOR, GsdTimezoneMonitorClass)) + +typedef struct _GsdTimezoneMonitor GsdTimezoneMonitor; +typedef struct _GsdTimezoneMonitorClass GsdTimezoneMonitorClass; + +struct _GsdTimezoneMonitor +{ + GObject parent_instance; +}; + +struct _GsdTimezoneMonitorClass +{ + GObjectClass parent_class; +}; + +GType gsd_timezone_monitor_get_type (void) G_GNUC_CONST; + +GsdTimezoneMonitor *gsd_timezone_monitor_new (void); + +G_END_DECLS + +#endif /* __GSD_TIMEZONE_MONITOR_H */ diff --git a/plugins/datetime/test-datetime.c b/plugins/datetime/test-datetime.c new file mode 100644 index 00000000..0a55ba22 --- /dev/null +++ b/plugins/datetime/test-datetime.c @@ -0,0 +1,7 @@ +#define NEW gsd_datetime_manager_new +#define START gsd_datetime_manager_start +#define STOP gsd_datetime_manager_stop +#define MANAGER GsdDatetimeManager +#include "gsd-datetime-manager.h" + +#include "test-plugin.h" diff --git a/plugins/datetime/timedated1-interface.xml b/plugins/datetime/timedated1-interface.xml new file mode 100644 index 00000000..3370e0e2 --- /dev/null +++ b/plugins/datetime/timedated1-interface.xml @@ -0,0 +1,28 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" +"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.freedesktop.timedate1"> + <property name="Timezone" type="s" access="read"/> + <property name="LocalRTC" type="b" access="read"/> + <property name="CanNTP" type="b" access="read"/> + <property name="NTP" type="b" access="read"/> + <method name="SetTime"> + <arg name="usec_utc" type="x" direction="in"/> + <arg name="relative" type="b" direction="in"/> + <arg name="user_interaction" type="b" direction="in"/> + </method> + <method name="SetTimezone"> + <arg name="timezone" type="s" direction="in"/> + <arg name="user_interaction" type="b" direction="in"/> + </method> + <method name="SetLocalRTC"> + <arg name="local_rtc" type="b" direction="in"/> + <arg name="fix_system" type="b" direction="in"/> + <arg name="user_interaction" type="b" direction="in"/> + </method> + <method name="SetNTP"> + <arg name="use_ntp" type="b" direction="in"/> + <arg name="user_interaction" type="b" direction="in"/> + </method> + </interface> +</node> diff --git a/plugins/datetime/tz.c b/plugins/datetime/tz.c new file mode 100644 index 00000000..c539d59d --- /dev/null +++ b/plugins/datetime/tz.c @@ -0,0 +1,482 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* Generic timezone utilities. + * + * Copyright (C) 2000-2001 Ximian, Inc. + * + * Authors: Hans Petter Jansson <hpj@ximian.com> + * + * Largely based on Michael Fulbright's work on Anaconda. + * + * 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. + */ + + +#include <glib.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <math.h> +#include <string.h> +#include "tz.h" + + +/* Forward declarations for private functions */ + +static float convert_pos (gchar *pos, int digits); +static int compare_country_names (const void *a, const void *b); +static void sort_locations_by_country (GPtrArray *locations); +static gchar * tz_data_file_get (void); +static void load_backward_tz (TzDB *tz_db); + +/* ---------------- * + * Public interface * + * ---------------- */ +TzDB * +tz_load_db (void) +{ + gchar *tz_data_file; + TzDB *tz_db; + FILE *tzfile; + char buf[4096]; + + tz_data_file = tz_data_file_get (); + if (!tz_data_file) { + g_warning ("Could not get the TimeZone data file name"); + return NULL; + } + tzfile = fopen (tz_data_file, "r"); + if (!tzfile) { + g_warning ("Could not open *%s*\n", tz_data_file); + g_free (tz_data_file); + return NULL; + } + + tz_db = g_new0 (TzDB, 1); + tz_db->locations = g_ptr_array_new (); + + while (fgets (buf, sizeof(buf), tzfile)) + { + gchar **tmpstrarr; + gchar *latstr, *lngstr, *p; + TzLocation *loc; + + if (*buf == '#') continue; + + g_strchomp(buf); + tmpstrarr = g_strsplit(buf,"\t", 6); + + latstr = g_strdup (tmpstrarr[1]); + p = latstr + 1; + while (*p != '-' && *p != '+') p++; + lngstr = g_strdup (p); + *p = '\0'; + + loc = g_new0 (TzLocation, 1); + loc->country = g_strdup (tmpstrarr[0]); + loc->zone = g_strdup (tmpstrarr[2]); + loc->latitude = convert_pos (latstr, 2); + loc->longitude = convert_pos (lngstr, 3); + +#ifdef __sun + if (tmpstrarr[3] && *tmpstrarr[3] == '-' && tmpstrarr[4]) + loc->comment = g_strdup (tmpstrarr[4]); + + if (tmpstrarr[3] && *tmpstrarr[3] != '-' && !islower(loc->zone)) { + TzLocation *locgrp; + + /* duplicate entry */ + locgrp = g_new0 (TzLocation, 1); + locgrp->country = g_strdup (tmpstrarr[0]); + locgrp->zone = g_strdup (tmpstrarr[3]); + locgrp->latitude = convert_pos (latstr, 2); + locgrp->longitude = convert_pos (lngstr, 3); + locgrp->comment = (tmpstrarr[4]) ? g_strdup (tmpstrarr[4]) : NULL; + + g_ptr_array_add (tz_db->locations, (gpointer) locgrp); + } +#else + loc->comment = (tmpstrarr[3]) ? g_strdup(tmpstrarr[3]) : NULL; +#endif + + g_ptr_array_add (tz_db->locations, (gpointer) loc); + + g_free (latstr); + g_free (lngstr); + g_strfreev (tmpstrarr); + } + + fclose (tzfile); + + /* now sort by country */ + sort_locations_by_country (tz_db->locations); + + g_free (tz_data_file); + + /* Load up the hashtable of backward links */ + load_backward_tz (tz_db); + + return tz_db; +} + +static void +tz_location_free (TzLocation *loc) +{ + g_free (loc->country); + g_free (loc->zone); + g_free (loc->comment); + + g_free (loc); +} + +void +tz_db_free (TzDB *db) +{ + g_ptr_array_foreach (db->locations, (GFunc) tz_location_free, NULL); + g_ptr_array_free (db->locations, TRUE); + g_hash_table_destroy (db->backward); + g_free (db); +} + +GPtrArray * +tz_get_locations (TzDB *db) +{ + return db->locations; +} + + +gchar * +tz_location_get_country (TzLocation *loc) +{ + return loc->country; +} + + +gchar * +tz_location_get_zone (TzLocation *loc) +{ + return loc->zone; +} + + +gchar * +tz_location_get_comment (TzLocation *loc) +{ + return loc->comment; +} + + +void +tz_location_get_position (TzLocation *loc, double *longitude, double *latitude) +{ + *longitude = loc->longitude; + *latitude = loc->latitude; +} + +glong +tz_location_get_utc_offset (TzLocation *loc) +{ + TzInfo *tz_info; + glong offset; + + tz_info = tz_info_from_location (loc); + offset = tz_info->utc_offset; + tz_info_free (tz_info); + return offset; +} + +TzInfo * +tz_info_from_location (TzLocation *loc) +{ + TzInfo *tzinfo; + time_t curtime; + struct tm *curzone; + gchar *tz_env_value; + + g_return_val_if_fail (loc != NULL, NULL); + g_return_val_if_fail (loc->zone != NULL, NULL); + + tz_env_value = g_strdup (getenv ("TZ")); + setenv ("TZ", loc->zone, 1); + +#if 0 + tzset (); +#endif + tzinfo = g_new0 (TzInfo, 1); + + curtime = time (NULL); + curzone = localtime (&curtime); + +#ifndef __sun + /* Currently this solution doesnt seem to work - I get that */ + /* America/Phoenix uses daylight savings, which is wrong */ + tzinfo->tzname_normal = g_strdup (curzone->tm_zone); + if (curzone->tm_isdst) + tzinfo->tzname_daylight = + g_strdup (&curzone->tm_zone[curzone->tm_isdst]); + else + tzinfo->tzname_daylight = NULL; + + tzinfo->utc_offset = curzone->tm_gmtoff; +#else + tzinfo->tzname_normal = NULL; + tzinfo->tzname_daylight = NULL; + tzinfo->utc_offset = 0; +#endif + + tzinfo->daylight = curzone->tm_isdst; + + if (tz_env_value) + setenv ("TZ", tz_env_value, 1); + else + unsetenv ("TZ"); + + g_free (tz_env_value); + + return tzinfo; +} + + +void +tz_info_free (TzInfo *tzinfo) +{ + g_return_if_fail (tzinfo != NULL); + + if (tzinfo->tzname_normal) g_free (tzinfo->tzname_normal); + if (tzinfo->tzname_daylight) g_free (tzinfo->tzname_daylight); + g_free (tzinfo); +} + +struct { + const char *orig; + const char *dest; +} aliases[] = { + { "Asia/Istanbul", "Europe/Istanbul" }, /* Istanbul is in both Europe and Asia */ + { "Europe/Nicosia", "Asia/Nicosia" }, /* Ditto */ + { "EET", "Europe/Istanbul" }, /* Same tz as the 2 above */ + { "HST", "Pacific/Honolulu" }, + { "WET", "Europe/Brussels" }, /* Other name for the mainland Europe tz */ + { "CET", "Europe/Brussels" }, /* ditto */ + { "MET", "Europe/Brussels" }, + { "Etc/Zulu", "Etc/GMT" }, + { "Etc/UTC", "Etc/GMT" }, + { "GMT", "Etc/GMT" }, + { "Greenwich", "Etc/GMT" }, + { "Etc/UCT", "Etc/GMT" }, + { "Etc/GMT0", "Etc/GMT" }, + { "Etc/GMT+0", "Etc/GMT" }, + { "Etc/GMT-0", "Etc/GMT" }, + { "Etc/Universal", "Etc/GMT" }, + { "PST8PDT", "America/Los_Angeles" }, /* Other name for the Atlantic tz */ + { "EST", "America/New_York" }, /* Other name for the Eastern tz */ + { "EST5EDT", "America/New_York" }, /* ditto */ + { "CST6CDT", "America/Chicago" }, /* Other name for the Central tz */ + { "MST", "America/Denver" }, /* Other name for the mountain tz */ + { "MST7MDT", "America/Denver" }, /* ditto */ +}; + +static gboolean +compare_timezones (const char *a, + const char *b) +{ + if (g_str_equal (a, b)) + return TRUE; + if (strchr (b, '/') == NULL) { + char *prefixed; + + prefixed = g_strdup_printf ("/%s", b); + if (g_str_has_suffix (a, prefixed)) { + g_free (prefixed); + return TRUE; + } + g_free (prefixed); + } + + return FALSE; +} + +char * +tz_info_get_clean_name (TzDB *tz_db, + const char *tz) +{ + char *ret; + const char *timezone; + guint i; + gboolean replaced; + + /* Remove useless prefixes */ + if (g_str_has_prefix (tz, "right/")) + tz = tz + strlen ("right/"); + else if (g_str_has_prefix (tz, "posix/")) + tz = tz + strlen ("posix/"); + + /* Here start the crazies */ + replaced = FALSE; + + for (i = 0; i < G_N_ELEMENTS (aliases); i++) { + if (compare_timezones (tz, aliases[i].orig)) { + replaced = TRUE; + timezone = aliases[i].dest; + break; + } + } + + /* Try again! */ + if (!replaced) { + /* Ignore crazy solar times from the '80s */ + if (g_str_has_prefix (tz, "Asia/Riyadh") || + g_str_has_prefix (tz, "Mideast/Riyadh")) { + timezone = "Asia/Riyadh"; + replaced = TRUE; + } + } + + if (!replaced) + timezone = tz; + + ret = g_hash_table_lookup (tz_db->backward, timezone); + if (ret == NULL) + return g_strdup (timezone); + return g_strdup (ret); +} + +/* ----------------- * + * Private functions * + * ----------------- */ + +static gchar * +tz_data_file_get (void) +{ + gchar *file; + + file = g_strdup (TZ_DATA_FILE); + + return file; +} + +static float +convert_pos (gchar *pos, int digits) +{ + gchar whole[10]; + gchar *fraction; + gint i; + float t1, t2; + + if (!pos || strlen(pos) < 4 || digits > 9) return 0.0; + + for (i = 0; i < digits + 1; i++) whole[i] = pos[i]; + whole[i] = '\0'; + fraction = pos + digits + 1; + + t1 = g_strtod (whole, NULL); + t2 = g_strtod (fraction, NULL); + + if (t1 >= 0.0) return t1 + t2/pow (10.0, strlen(fraction)); + else return t1 - t2/pow (10.0, strlen(fraction)); +} + + +#if 0 + +/* Currently not working */ +static void +free_tzdata (TzLocation *tz) +{ + + if (tz->country) + g_free(tz->country); + if (tz->zone) + g_free(tz->zone); + if (tz->comment) + g_free(tz->comment); + + g_free(tz); +} +#endif + + +static int +compare_country_names (const void *a, const void *b) +{ + const TzLocation *tza = * (TzLocation **) a; + const TzLocation *tzb = * (TzLocation **) b; + + return strcmp (tza->zone, tzb->zone); +} + + +static void +sort_locations_by_country (GPtrArray *locations) +{ + qsort (locations->pdata, locations->len, sizeof (gpointer), + compare_country_names); +} + +static void +load_backward_tz (TzDB *tz_db) +{ + GError *error = NULL; + char **lines, *contents; + guint i; + + tz_db->backward = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + if (g_file_get_contents (GNOMECC_DATA_DIR "/datetime/backward", &contents, NULL, &error) == FALSE) + { + g_warning ("Failed to load 'backward' file: %s", error->message); + return; + } + lines = g_strsplit (contents, "\n", -1); + g_free (contents); + for (i = 0; lines[i] != NULL; i++) + { + char **items; + guint j; + char *real, *alias; + + if (g_ascii_strncasecmp (lines[i], "Link\t", 5) != 0) + continue; + + items = g_strsplit (lines[i], "\t", -1); + real = NULL; + alias = NULL; + /* Skip the "Link<tab>" part */ + for (j = 1; items[j] != NULL; j++) + { + if (items[j][0] == '\0') + continue; + if (real == NULL) + { + real = items[j]; + continue; + } + alias = items[j]; + break; + } + + if (real == NULL || alias == NULL) + g_warning ("Could not parse line: %s", lines[i]); + + /* We don't need more than one name for it */ + if (g_str_equal (real, "Etc/UTC") || + g_str_equal (real, "Etc/UCT")) + real = "Etc/GMT"; + + g_hash_table_insert (tz_db->backward, g_strdup (alias), g_strdup (real)); + g_strfreev (items); + } + g_strfreev (lines); +} + diff --git a/plugins/datetime/tz.h b/plugins/datetime/tz.h new file mode 100644 index 00000000..71c1c231 --- /dev/null +++ b/plugins/datetime/tz.h @@ -0,0 +1,89 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* Generic timezone utilities. + * + * Copyright (C) 2000-2001 Ximian, Inc. + * + * Authors: Hans Petter Jansson <hpj@ximian.com> + * + * Largely based on Michael Fulbright's work on Anaconda. + * + * 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 _E_TZ_H +#define _E_TZ_H + +#include <glib.h> + +#ifndef __sun +# define TZ_DATA_FILE "/usr/share/zoneinfo/zone.tab" +#else +# define TZ_DATA_FILE "/usr/share/lib/zoneinfo/tab/zone_sun.tab" +#endif + +typedef struct _TzDB TzDB; +typedef struct _TzLocation TzLocation; +typedef struct _TzInfo TzInfo; + + +struct _TzDB +{ + GPtrArray *locations; + GHashTable *backward; +}; + +struct _TzLocation +{ + gchar *country; + gdouble latitude; + gdouble longitude; + gchar *zone; + gchar *comment; + + gdouble dist; /* distance to clicked point for comparison */ +}; + +/* see the glibc info page information on time zone information */ +/* tzname_normal is the default name for the timezone */ +/* tzname_daylight is the name of the zone when in daylight savings */ +/* utc_offset is offset in seconds from utc */ +/* daylight if non-zero then location obeys daylight savings */ + +struct _TzInfo +{ + gchar *tzname_normal; + gchar *tzname_daylight; + glong utc_offset; + gint daylight; +}; + + +TzDB *tz_load_db (void); +void tz_db_free (TzDB *db); +char * tz_info_get_clean_name (TzDB *tz_db, + const char *tz); +GPtrArray *tz_get_locations (TzDB *db); +void tz_location_get_position (TzLocation *loc, + double *longitude, double *latitude); +char *tz_location_get_country (TzLocation *loc); +gchar *tz_location_get_zone (TzLocation *loc); +gchar *tz_location_get_comment (TzLocation *loc); +glong tz_location_get_utc_offset (TzLocation *loc); +gint tz_location_set_locally (TzLocation *loc); +TzInfo *tz_info_from_location (TzLocation *loc); +void tz_info_free (TzInfo *tz_info); + +#endif diff --git a/po/POTFILES.in b/po/POTFILES.in index 93d00755..9f05c02f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -4,6 +4,7 @@ data/gnome-settings-daemon.desktop.in.in data/org.gnome.settings-daemon.peripherals.gschema.xml.in.in data/org.gnome.settings-daemon.peripherals.wacom.gschema.xml.in.in data/org.gnome.settings-daemon.plugins.color.gschema.xml.in.in +data/org.gnome.settings-daemon.plugins.datetime.gschema.xml.in.in data/org.gnome.settings-daemon.plugins.gschema.xml.in.in data/org.gnome.settings-daemon.plugins.housekeeping.gschema.xml.in.in data/org.gnome.settings-daemon.plugins.keyboard.gschema.xml.in.in diff --git a/po/POTFILES.skip b/po/POTFILES.skip index 69411934..132d3a54 100644 --- a/po/POTFILES.skip +++ b/po/POTFILES.skip @@ -10,6 +10,7 @@ data/gnome-settings-daemon.desktop.in data/org.gnome.settings-daemon.peripherals.gschema.xml.in data/org.gnome.settings-daemon.peripherals.wacom.gschema.xml.in data/org.gnome.settings-daemon.plugins.color.gschema.xml.in +data/org.gnome.settings-daemon.plugins.datetime.gschema.xml.in data/org.gnome.settings-daemon.plugins.gschema.xml.in data/org.gnome.settings-daemon.plugins.housekeeping.gschema.xml.in data/org.gnome.settings-daemon.plugins.keyboard.gschema.xml.in |