aboutsummaryrefslogtreecommitdiff
path: root/src/datetime-service.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/datetime-service.c')
-rw-r--r--src/datetime-service.c283
1 files changed, 140 insertions, 143 deletions
diff --git a/src/datetime-service.c b/src/datetime-service.c
index b1b5b7f..710b7d6 100644
--- a/src/datetime-service.c
+++ b/src/datetime-service.c
@@ -68,6 +68,8 @@ static void geo_client_invalid (GeoclueMasterClient * client, gpointer user_data
static void geo_address_change (GeoclueMasterClient * client, gchar * a, gchar * b, gchar * c, gchar * d, gpointer user_data);
static gboolean get_greeter_mode (void);
+static void quick_set_tz (DbusmenuMenuitem * menuitem, guint timestamp, gpointer user_data);
+
static IndicatorService * service = NULL;
static GMainLoop * mainloop = NULL;
static DbusmenuServer * server = NULL;
@@ -109,114 +111,162 @@ struct comp_instance {
};
static void
-set_timezone_label (DbusmenuMenuitem * mi, const gchar * location)
+set_current_timezone_label (DbusmenuMenuitem * mi, const gchar * location)
{
- gchar * zone, * name;
- split_settings_location (location, &zone, &name);
+ gchar * name = get_current_zone_name (location);
dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_NAME, name);
- dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_ZONE, zone);
+ dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_ZONE, location);
- g_free (zone);
g_free (name);
}
+/**
+ * A temp struct used by update_location_menu_items() for pruning duplicates.
+ */
+struct NameAndOffset
+{
+ gchar * name;
+ gint32 offset;
+};
static void
-set_current_timezone_label (DbusmenuMenuitem * mi, const gchar * location)
+name_and_offset_free (struct NameAndOffset * nao)
{
- gchar * name = get_current_zone_name (location);
-
- dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_NAME, name);
- dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_ZONE, location);
-
- g_free (name);
+ g_free (nao->name);
+ g_free (nao);
}
+static struct NameAndOffset*
+name_and_offset_new (const char * zone, const char * name)
+{
+ struct NameAndOffset * nao = g_new (struct NameAndOffset, 1);
+ nao->name = g_strdup (name);
+ GTimeZone * tz = g_time_zone_new (zone);
+ nao->offset = g_time_zone_get_offset (tz, 0);
+ g_time_zone_unref (tz);
+ return nao;
+}
+static struct NameAndOffset*
+name_and_offset_new_from_item (DbusmenuMenuitem * mi)
+{
+ const char * zone = dbusmenu_menuitem_property_get (mi, TIMEZONE_MENUITEM_PROP_ZONE);
+ const char * name = dbusmenu_menuitem_property_get (mi, TIMEZONE_MENUITEM_PROP_NAME);
+ return name_and_offset_new (zone, name);
+}
+static int
+name_and_offset_compare (const struct NameAndOffset * a, const struct NameAndOffset * b)
+{
+ if (a->offset != b->offset)
+ return a->offset - b->offset;
+ return g_strcmp0 (a->name, b->name);
+}
+
-/* Check to see if our timezones are the same */
+/* Update the timezone entries: geo_location, current_location,
+ and the user-supplied custom locations */
static void
-check_timezone_sync (void) {
- gchar * label;
- gboolean in_sync = FALSE;
-
- if (geo_timezone == NULL) {
- in_sync = TRUE;
- }
+update_location_menu_items (void)
+{
+ if (get_greeter_mode ())
+ return;
- if (current_timezone == NULL) {
- in_sync = TRUE;
+ g_assert (locations_separator != NULL);
+ g_assert (geo_location != NULL);
+ g_assert (current_location != NULL);
+
+ GSList * visible_locations = NULL;
+ gchar ** locations = g_settings_get_strv(conf, SETTINGS_LOCATIONS_S);
+ const guint location_count = locations ? g_strv_length(locations) : 0;
+ g_debug ("%s Found %u locations from %s", G_STRLOC, location_count, SETTINGS_LOCATIONS_S);
+
+ const gboolean show_all = g_settings_get_boolean (conf, SETTINGS_SHOW_LOCATIONS_S);
+
+ /* the timezones are in sync if they don't disagree with each other */
+ const gboolean in_sync = !geo_timezone
+ || !current_timezone
+ || !g_strcmp0 (geo_timezone, current_timezone);
+
+ /* decide whether or not to show the builtin locations */
+ gboolean show_sep;
+ gboolean show_geo;
+ gboolean show_cur;
+ if (in_sync && !location_count) {
+ /* if the builtin timezones match, and there aren't any user user-specified locations,
+ then there's nothing interesting going on ... don't show anything */
+ show_sep = FALSE;
+ show_geo = FALSE;
+ show_cur = FALSE;
+ } else {
+ /* if there are user-specified locations, show at least one builtin.
+ if the two builtins disagree, show both of them. */
+ show_sep = TRUE;
+ show_geo = geo_timezone != NULL;
+ show_cur = (current_timezone != NULL) && (!in_sync || !show_geo);
}
- if (!in_sync && g_strcmp0(geo_timezone, current_timezone) == 0) {
- in_sync = TRUE;
+ /* maybe add the builtin locations */
+ if (show_geo) {
+ g_debug ("%s showing geo_timezone '%s'", G_STRLOC, geo_timezone);
+ set_current_timezone_label (geo_location, geo_timezone);
+ visible_locations = g_slist_prepend (visible_locations, name_and_offset_new_from_item (geo_location));
+ }
+ if (show_cur) {
+ g_debug ("%s showing current_timezone '%s'", G_STRLOC, current_timezone);
+ set_current_timezone_label (current_location, current_timezone);
+ visible_locations = g_slist_prepend (visible_locations, name_and_offset_new_from_item (current_location));
}
- if (in_sync) {
- g_debug("Timezones in sync");
- } else {
- g_debug("Timezones are different");
+ /* remove the previous user-specified locations */
+ while (location_menu_items != NULL) {
+ DbusmenuMenuitem * item = DBUSMENU_MENUITEM(location_menu_items->data);
+ location_menu_items = g_list_remove(location_menu_items, item);
+ dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(item));
+ g_object_unref(G_OBJECT(item));
}
- gboolean show = g_settings_get_boolean (conf, SETTINGS_SHOW_LOCATIONS_S);
-
- if (geo_location != NULL && current_location != NULL) {
- g_debug("Got timezone %s", current_timezone);
- g_debug("Got timezone %s", geo_timezone);
- // Show neither current location nor geo location if both are the same
- // however, we want to set their time and label accordingly
- if (in_sync) {
- if (current_timezone == NULL && geo_timezone == NULL) {
- dbusmenu_menuitem_property_set_bool(locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- update_location_menu_items();
- return;
- }
-
- dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
- dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
-
- if (current_timezone != NULL) {
- label = current_timezone;
+ /* add the user-specified locations */
+ if (locations != NULL) {
+ gint i;
+ gint offset = dbusmenu_menuitem_get_position (current_location, root)+1;
+ for (i=0; i<location_count; i++) {
+ gchar * zone;
+ gchar * name;
+ const char * location = locations[i];
+ split_settings_location (location, &zone, &name);
+
+ /* if it doesn't duplicate one that we've already got, add it */
+ struct NameAndOffset * nao = name_and_offset_new (zone, name);
+ if (g_slist_find_custom (visible_locations, nao, (GCompareFunc)name_and_offset_compare) != NULL) {
+ g_debug("%s Skipping duplicate timezone '%s'", G_STRLOC, location);
+ name_and_offset_free (nao);
} else {
- label = geo_timezone;
+ g_debug("%s Adding timezone '%s'", G_STRLOC, location);
+ DbusmenuMenuitem * item = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, TIMEZONE_MENUITEM_TYPE);
+ dbusmenu_menuitem_property_set (item, TIMEZONE_MENUITEM_PROP_NAME, name);
+ dbusmenu_menuitem_property_set (item, TIMEZONE_MENUITEM_PROP_ZONE, zone);
+ dbusmenu_menuitem_property_set_bool (item, TIMEZONE_MENUITEM_PROP_RADIO, FALSE);
+ dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
+ dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, show_all);
+ dbusmenu_menuitem_child_add_position (root, item, offset++);
+ g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(quick_set_tz), NULL);
+ visible_locations = g_slist_prepend (visible_locations, nao);
+ location_menu_items = g_list_append (location_menu_items, item);
}
-
- if (label != NULL) {
- // TODO work out the current location name in a nice way
- set_current_timezone_label (current_location, label);
- // TODO work out the current time at that location
- dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
- dbusmenu_menuitem_property_set_bool(current_location, TIMEZONE_MENUITEM_PROP_RADIO, TRUE);
- } else {
- g_debug("Label for current location is null, this shouldn't happen");
- }
- if (geo_timezone != NULL) {
- // TODO work out the geo location name in a nice way
- set_current_timezone_label (geo_location, geo_timezone);
- // TODO work out the current time at that location
- dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
- }
- } else {
- // TODO work out the geo location name in a nice way
- set_current_timezone_label (geo_location, geo_timezone);
- // TODO work out the current time at that location
- dbusmenu_menuitem_property_set_bool(geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
-
- // TODO work out the current location name in a nice way
- set_current_timezone_label (current_location, current_timezone);
- // TODO work out the current time at that location
- dbusmenu_menuitem_property_set_bool(current_location, TIMEZONE_MENUITEM_PROP_RADIO, TRUE);
- dbusmenu_menuitem_property_set_bool(current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
- dbusmenu_menuitem_property_set_bool(locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
+
+ g_free (name);
+ g_free (zone);
}
+ g_strfreev (locations);
}
- g_debug("Finished checking timezone sync");
- update_location_menu_items();
+ g_slist_free_full (visible_locations, (GDestroyNotify)name_and_offset_free);
- return;
+ dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, show_all && show_sep);
+ dbusmenu_menuitem_property_set_bool (geo_location, TIMEZONE_MENUITEM_PROP_RADIO, TRUE);
+ dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
+ dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show_all && show_geo);
+ dbusmenu_menuitem_property_set_bool (current_location, TIMEZONE_MENUITEM_PROP_RADIO, TRUE);
+ dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
+ dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show_all && show_cur);
}
/* Update the current timezone */
@@ -235,7 +285,7 @@ update_current_timezone (void) {
g_debug("System timezone is: %s", current_timezone);
- check_timezone_sync();
+ update_location_menu_items();
return;
}
@@ -566,59 +616,6 @@ check_for_calendar (gpointer user_data)
return FALSE;
}
-
-static void
-update_location_menu_items(void) {
- g_debug("Updating timezone menu items");
-
- if (locations_separator == NULL || current_location == NULL) {
- return;
- }
-
- gchar ** locations = g_settings_get_strv(conf, SETTINGS_LOCATIONS_S);
-
- if (locations == NULL) {
- g_debug("No locations configured (NULL)");
- return;
- }
- const guint len = g_strv_length(locations);
- g_debug("Found %u locations from %s", len, SETTINGS_LOCATIONS_S);
-
- /* Remove all of the previous locations */
- while (location_menu_items != NULL) {
- DbusmenuMenuitem * item = DBUSMENU_MENUITEM(location_menu_items->data);
- location_menu_items = g_list_remove(location_menu_items, item);
- dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(item));
- g_object_unref(G_OBJECT(item));
- }
-
- const gboolean show = g_settings_get_boolean (conf, SETTINGS_SHOW_LOCATIONS_S);
- dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
- dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
- dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
-
- gint i;
- gint offset = dbusmenu_menuitem_get_position (current_location, root)+1;
- for (i = 0; i < len; i++) {
- // Iterate over configured places and add any which aren't already listed
- if ((current_timezone == NULL || !g_str_has_prefix(locations[i], current_timezone)) &&
- (geo_timezone == NULL || !g_str_has_prefix(locations[i], geo_timezone))) {
- DbusmenuMenuitem *item;
- g_debug("Adding timezone in update_timezones %s", locations[i]);
- item = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, TIMEZONE_MENUITEM_TYPE);
- set_timezone_label (item, locations[i]);
- dbusmenu_menuitem_property_set_bool (item, TIMEZONE_MENUITEM_PROP_RADIO, FALSE);
- dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
- dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
- dbusmenu_menuitem_child_add_position (root, item, offset++);
- g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(quick_set_tz), NULL);
- location_menu_items = g_list_append(location_menu_items, item);
- }
- }
- g_strfreev (locations);
-}
-
// Authentication function
static gchar *
auth_func (ECal *ecal,
@@ -1095,7 +1092,7 @@ static void
show_locations_changed (void)
{
/* Re-calculate */
- check_timezone_sync();
+ update_location_menu_items();
}
static void
@@ -1153,7 +1150,7 @@ build_menus (DbusmenuMenuitem * root)
dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
dbusmenu_menuitem_child_append(root, current_location);
- check_timezone_sync();
+ update_location_menu_items();
g_signal_connect (conf, "changed::" SETTINGS_SHOW_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL);
g_signal_connect (conf, "changed::" SETTINGS_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL);
@@ -1294,7 +1291,7 @@ geo_address_cb (GeoclueAddress * address, int timestamp, GHashTable * addy_data,
geo_timezone = g_strdup((gchar *)tz_hash);
}
- check_timezone_sync();
+ update_location_menu_items();
return;
}
@@ -1391,7 +1388,7 @@ geo_client_invalid (GeoclueMasterClient * client, gpointer user_data)
geo_timezone = NULL;
}
- check_timezone_sync();
+ update_location_menu_items();
return;
}
@@ -1413,7 +1410,7 @@ geo_address_change (GeoclueMasterClient * client, gchar * a, gchar * b, gchar *
geo_timezone = NULL;
}
- check_timezone_sync();
+ update_location_menu_items();
return;
}