From 5d8b176ab3c072faa259bfc3de2b8de103437463 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 6 May 2013 14:49:34 -0700 Subject: make location-file (the /etc/timezone monitor) a sibling of location-geoclue (the geoclue service monitor) --- src/Makefile.am | 2 + src/datetime-service.c | 75 +++++----------- src/location-file.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++ src/location-file.h | 61 +++++++++++++ src/location-geoclue.h | 4 +- 5 files changed, 322 insertions(+), 55 deletions(-) create mode 100644 src/location-file.c create mode 100644 src/location-file.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index f9b8562..2efff8f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,8 @@ indicator_datetime_service_SOURCES = \ datetime-service.c \ location.c \ location.h \ + location-file.c \ + location-file.h \ location-geoclue.c \ location-geoclue.h \ utils.c \ diff --git a/src/datetime-service.c b/src/datetime-service.c index 7b7c2db..35a5e53 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -45,6 +45,7 @@ with this program. If not, see . #include "datetime-interface.h" #include "dbus-shared.h" +#include "location-file.h" #include "location-geoclue.h" #include "settings-shared.h" #include "utils.h" @@ -91,10 +92,7 @@ static GSettings * conf = NULL; static ESourceRegistry * source_registry = NULL; static GList * appointment_sources = NULL; static IndicatorDatetimeLocation * geo_location = NULL; - - -/* Our 2 important timezones */ -static gchar * current_timezone = NULL; +static IndicatorDatetimeLocation * tz_file = NULL; struct comp_instance { ECalComponent *comp; @@ -196,11 +194,14 @@ update_location_menu_items (void) } /* maybe add current_timezone */ - if (current_timezone != NULL) { - const gboolean visible = g_settings_get_boolean (conf, SETTINGS_SHOW_DETECTED_S); - gchar * name = get_current_zone_name (current_timezone); - locations = locations_add (locations, current_timezone, name, visible, now); - g_free (name); + if (tz_file != NULL) { + const char * tz = indicator_datetime_location_get_timezone (tz_file); + if (tz && *tz) { + const gboolean visible = g_settings_get_boolean (conf, SETTINGS_SHOW_DETECTED_S); + gchar * name = get_current_zone_name (tz); + locations = locations_add (locations, tz, name, visible, now); + g_free (name); + } } /* maybe add the user-specified custom locations */ @@ -250,27 +251,6 @@ update_location_menu_items (void) dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, have_visible_location); } -/* Update the current timezone */ -static void -update_current_timezone (void) { - /* Clear old data */ - if (current_timezone != NULL) { - g_free(current_timezone); - current_timezone = NULL; - } - - current_timezone = read_timezone (); - if (current_timezone == NULL) { - return; - } - - g_debug("System timezone is: %s", current_timezone); - - update_location_menu_items(); - - return; -} - static void quick_set_tz_cb (GObject *object, GAsyncResult *res, gpointer data) { @@ -687,6 +667,7 @@ update_appointment_menu_items (gpointer user_data __attribute__ ((unused))) const int mday = today->tm_mday; const int mon = today->tm_mon; const int year = today->tm_year; + const char * current_timezone; int start_month_saved = mon; @@ -723,6 +704,8 @@ update_appointment_menu_items (gpointer user_data __attribute__ ((unused))) g_list_free_full (comp_instances, (GDestroyNotify)comp_instance_free); comp_instances = NULL; + current_timezone = indicator_datetime_location_get_timezone (tz_file); + // Generate instances for all sources for (s=appointment_sources; s!=NULL; s=s->next) { @@ -1073,31 +1056,15 @@ on_clock_skew (void) return; } -/* Run when the timezone file changes */ static void -timezone_changed (GFileMonitor * monitor, GFile * file, GFile * otherfile, GFileMonitorEvent event, gpointer user_data) +on_timezone_changed (void) { - update_current_timezone(); - on_clock_skew(); - return; -} + update_location_menu_items (); -/* Set up monitoring the timezone file */ -static void -build_timezone (DatetimeInterface * dbus) -{ - GFile * timezonefile = g_file_new_for_path(TIMEZONE_FILE); - GFileMonitor * monitor = g_file_monitor_file(timezonefile, G_FILE_MONITOR_NONE, NULL, NULL); - if (monitor != NULL) { - g_signal_connect(G_OBJECT(monitor), "changed", G_CALLBACK(timezone_changed), dbus); - g_debug("Monitoring timezone file: '" TIMEZONE_FILE "'"); - } else { - g_warning("Unable to monitor timezone file: '" TIMEZONE_FILE "'"); - } - g_object_unref(timezonefile); - return; + on_clock_skew (); } + /* Source ID for the timer */ static guint day_timer = 0; @@ -1315,7 +1282,7 @@ main (int argc, char ** argv) build_menus(root); /* Cache the timezone */ - update_current_timezone(); + update_location_menu_items (); /* Setup geoclue */ on_use_geoclue_changed_cb (conf, NULL, NULL); @@ -1324,7 +1291,8 @@ main (int argc, char ** argv) dbus = g_object_new(DATETIME_INTERFACE_TYPE, NULL); /* Setup timezone watch */ - build_timezone(dbus); + tz_file = indicator_datetime_location_file_new (TIMEZONE_FILE); + g_signal_connect (tz_file, "notify::timezone", G_CALLBACK(on_timezone_changed), NULL); /* Set up the day timer */ day_timer_reset(); @@ -1357,7 +1325,8 @@ main (int argc, char ** argv) icaltimezone_free_builtin_timezones(); - g_clear_object (&geo_location); + g_object_unref (geo_location); + g_object_unref (tz_file); return 0; } diff --git a/src/location-file.c b/src/location-file.c new file mode 100644 index 0000000..ff6fd47 --- /dev/null +++ b/src/location-file.c @@ -0,0 +1,235 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . + */ + +#include "config.h" + +#include +#include +#include + +#include "location-file.h" + +enum +{ + PROP_0, + PROP_FILENAME, + PROP_LAST +}; + +static GParamSpec * properties[PROP_LAST] = { 0 }; + +struct _IndicatorDatetimeLocationFilePriv +{ + gchar * filename; + GFile * file; + GFileMonitor * monitor; + gchar * timezone; +}; + +typedef IndicatorDatetimeLocationFilePriv priv_t; + +G_DEFINE_TYPE (IndicatorDatetimeLocationFile, + indicator_datetime_location_file, + INDICATOR_TYPE_DATETIME_LOCATION) + +/*** +**** +***/ + +static void +reload (IndicatorDatetimeLocationFile * self) +{ + priv_t * p = self->priv; + + GError * err = NULL; + gchar * new_timezone = NULL; + + if (!g_file_get_contents (p->filename, &new_timezone, NULL, &err)) + { + g_warning ("Unable to read timezone file '%s': %s", p->filename, err->message); + g_error_free (err); + } + else + { + g_strstrip (new_timezone); + g_free (p->timezone); + p->timezone = new_timezone; + indicator_datetime_location_notify_timezone (INDICATOR_DATETIME_LOCATION(self)); + } +} + +static void +set_filename (IndicatorDatetimeLocationFile * self, const char * filename) +{ + GError * err; + priv_t * p = self->priv; + + g_clear_object (&p->monitor); + g_clear_object (&p->file); + g_free (p->filename); + + p->filename = g_strdup (filename); + p->file = g_file_new_for_path (p->filename); + + err = NULL; + p->monitor = g_file_monitor_file (p->file, G_FILE_MONITOR_NONE, NULL, &err); + if (err != NULL) + { + g_warning ("Unable to monitor timezone file '%s': %s", TIMEZONE_FILE, err->message); + g_error_free (err); + } + else + { + g_signal_connect_swapped (p->monitor, "changed", G_CALLBACK(reload), self); + g_debug ("Monitoring timezone file '%s'", p->filename); + } + + reload (self); +} + +/*** +**** IndicatorDatetimeLocationClass funcs +***/ + +static const char * +my_get_timezone (IndicatorDatetimeLocation * self) +{ + return INDICATOR_DATETIME_LOCATION_FILE(self)->priv->timezone; +} + +/*** +**** GObjectClass funcs +***/ + +static void +my_get_property (GObject * o, + guint property_id, + GValue * value, + GParamSpec * pspec) +{ + IndicatorDatetimeLocationFile * self = INDICATOR_DATETIME_LOCATION_FILE (o); + + switch (property_id) + { + case PROP_FILENAME: + g_value_set_string (value, self->priv->filename); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); + } +} + +static void +my_set_property (GObject * o, + guint property_id, + const GValue * value, + GParamSpec * pspec) +{ + IndicatorDatetimeLocationFile * self = INDICATOR_DATETIME_LOCATION_FILE (o); + + switch (property_id) + { + case PROP_FILENAME: + set_filename (self, g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); + } +} + +static void +my_dispose (GObject * o) +{ + IndicatorDatetimeLocationFile * self = INDICATOR_DATETIME_LOCATION_FILE (o); + priv_t * p = self->priv; + + g_clear_object (&p->monitor); + g_clear_object (&p->file); + + G_OBJECT_CLASS (indicator_datetime_location_file_parent_class)->dispose (o); +} + +static void +my_finalize (GObject * o) +{ + IndicatorDatetimeLocationFile * self = INDICATOR_DATETIME_LOCATION_FILE (o); + priv_t * p = self->priv; + + g_free (p->filename); + g_free (p->timezone); + + G_OBJECT_CLASS (indicator_datetime_location_file_parent_class)->finalize (o); +} + +/*** +**** +***/ + +static void +indicator_datetime_location_file_class_init (IndicatorDatetimeLocationFileClass * klass) +{ + GObjectClass * object_class; + IndicatorDatetimeLocationClass * location_class; + const GParamFlags flags = G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS; + + object_class = G_OBJECT_CLASS (klass); + object_class->dispose = my_dispose; + object_class->finalize = my_finalize; + object_class->set_property = my_set_property; + object_class->get_property = my_get_property; + + location_class = INDICATOR_DATETIME_LOCATION_CLASS (klass); + location_class->get_timezone = my_get_timezone; + + g_type_class_add_private (klass, sizeof (IndicatorDatetimeLocationFilePriv)); + + /* install properties */ + + properties[PROP_0] = NULL; + + properties[PROP_FILENAME] = g_param_spec_string ("filename", + "Filename", + "Filename to monitor for TZ changes", + "", + flags); + + g_object_class_install_properties (object_class, PROP_LAST, properties); +} + +static void +indicator_datetime_location_file_init (IndicatorDatetimeLocationFile * self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + INDICATOR_TYPE_DATETIME_LOCATION_FILE, + IndicatorDatetimeLocationFilePriv); +} + +/*** +**** Public +***/ + +IndicatorDatetimeLocation * +indicator_datetime_location_file_new (const char * filename) +{ + gpointer o = g_object_new (INDICATOR_TYPE_DATETIME_LOCATION_FILE, "filename", filename, NULL); + + return INDICATOR_DATETIME_LOCATION (o); +} diff --git a/src/location-file.h b/src/location-file.h new file mode 100644 index 0000000..8ed87ad --- /dev/null +++ b/src/location-file.h @@ -0,0 +1,61 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . + */ + +#ifndef __INDICATOR_DATETIME_LOCATION_FILE__H__ +#define __INDICATOR_DATETIME_LOCATION_FILE__H__ + +#include +#include + +#include "location.h" /* parent class */ + +G_BEGIN_DECLS + +#define INDICATOR_TYPE_DATETIME_LOCATION_FILE (indicator_datetime_location_file_get_type()) +#define INDICATOR_DATETIME_LOCATION_FILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_DATETIME_LOCATION_FILE, IndicatorDatetimeLocationFile)) +#define INDICATOR_DATETIME_LOCATION_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), INDICATOR_TYPE_DATETIME_LOCATION_FILE, IndicatorDatetimeLocationFileClass)) +#define INDICATOR_IS_DATETIME_LOCATION_FILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_DATETIME_LOCATION_FILE)) + +typedef struct _IndicatorDatetimeLocationFile IndicatorDatetimeLocationFile; +typedef struct _IndicatorDatetimeLocationFilePriv IndicatorDatetimeLocationFilePriv; +typedef struct _IndicatorDatetimeLocationFileClass IndicatorDatetimeLocationFileClass; + +GType indicator_datetime_location_file_get_type (void); + +/** + * An implementation of IndicatorDatetimeLocation which determines the timezone + * from monitoring a local file, such as /etc/timezone + */ +struct _IndicatorDatetimeLocationFile +{ + /*< private >*/ + IndicatorDatetimeLocation parent; + IndicatorDatetimeLocationFilePriv * priv; +}; + +struct _IndicatorDatetimeLocationFileClass +{ + IndicatorDatetimeLocationClass parent_class; +}; + +IndicatorDatetimeLocation * indicator_datetime_location_file_new (const char * filename); + +G_END_DECLS + +#endif /* __INDICATOR_DATETIME_LOCATION_FILE__H__ */ diff --git a/src/location-geoclue.h b/src/location-geoclue.h index 7b65917..5b6d232 100644 --- a/src/location-geoclue.h +++ b/src/location-geoclue.h @@ -39,8 +39,8 @@ typedef struct _IndicatorDatetimeLocationGeoclueClass IndicatorDatetimeLocatio GType indicator_datetime_location_geoclue_get_type (void); /** - * An implementation of IndicatorDatetimeLocation that gets its user information - * from org.freedesktop.ConsoleKit and org.freedesktop.Accounts over DBus. + * An implementation of IndicatorDatetimeLocation which determines the timezone + * from calling a GeoClue service over DBus. */ struct _IndicatorDatetimeLocationGeoclue { -- cgit v1.2.3