Merge lp:~charlesk/indicator-datetime/fix-833337 into lp:indicator-datetime/0.4

Proposed by Ted Gould
Status: Merged
Approved by: Ted Gould
Approved revision: 169
Merged at revision: 156
Proposed branch: lp:~charlesk/indicator-datetime/fix-833337
Merge into: lp:indicator-datetime/0.4
Prerequisite: lp:~charlesk/indicator-datetime/fix-leaks
Diff against target: 406 lines (+141/-188)
1 file modified
src/datetime-service.c (+141/-188)
To merge this branch: bzr merge lp:~charlesk/indicator-datetime/fix-833337
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+95719@code.launchpad.net

This proposal supersedes a proposal from 2012-03-02.

Description of the change

This addresses Bug #833337 (Duplicate locations) and Bug #833325 (locations not in time order).

We have three sources that we draw location candidates from:
  - our geographic location, drawn from geoclue
  - our current location, drawn from /etc/timezone
  - the user-specified locations in g-c-c -> Time & Date -> Clock -> Time in other locations + Choose Locations

This patch builds a list from these three sources, and omits duplicates by testing for entries that have the same 'name' property *and* the same timezone offset from UTC. So if there were entries for Amsterdam NY and Amsterdam Netherlands, both would be used. But if there were two entries for Amsterdam NY, one would be omitted.

The list is then sorted in timezone order for Bug #833325, and DbusmenuMeuitems are created for each item in the list.

This code is branched from lp:~charlesk/indicator-datetime/fix-leaks, which does what it says on the tin.

To post a comment you must log in.
Revision history for this message
Ted Gould (ted) wrote :

Resubmitted to make the fix-leaks branch a prereq branch

Revision history for this message
Ted Gould (ted) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/datetime-service.c'
--- src/datetime-service.c 2012-03-03 04:10:23 +0000
+++ src/datetime-service.c 2012-03-03 04:10:24 +0000
@@ -68,6 +68,8 @@
68static void geo_address_change (GeoclueMasterClient * client, gchar * a, gchar * b, gchar * c, gchar * d, gpointer user_data);68static void geo_address_change (GeoclueMasterClient * client, gchar * a, gchar * b, gchar * c, gchar * d, gpointer user_data);
69static gboolean get_greeter_mode (void);69static gboolean get_greeter_mode (void);
7070
71static void quick_set_tz (DbusmenuMenuitem * menuitem, guint timestamp, gpointer user_data);
72
71static IndicatorService * service = NULL;73static IndicatorService * service = NULL;
72static GMainLoop * mainloop = NULL;74static GMainLoop * mainloop = NULL;
73static DbusmenuServer * server = NULL;75static DbusmenuServer * server = NULL;
@@ -80,12 +82,9 @@
80static DbusmenuMenuitem * settings = NULL;82static DbusmenuMenuitem * settings = NULL;
81static DbusmenuMenuitem * events_separator = NULL;83static DbusmenuMenuitem * events_separator = NULL;
82static DbusmenuMenuitem * locations_separator = NULL;84static DbusmenuMenuitem * locations_separator = NULL;
83static DbusmenuMenuitem * geo_location = NULL;
84static DbusmenuMenuitem * current_location = NULL;
85//static DbusmenuMenuitem * ecal_location = NULL;
86static DbusmenuMenuitem * add_appointment = NULL;85static DbusmenuMenuitem * add_appointment = NULL;
87static GList * appointments = NULL;86static GList * appointments = NULL;
88static GList * dconflocations = NULL;87static GList * location_menu_items = NULL;
89static GList * comp_instances = NULL;88static GList * comp_instances = NULL;
90static gboolean updating_appointments = FALSE;89static gboolean updating_appointments = FALSE;
91static time_t start_time_appointments = (time_t) 0;90static time_t start_time_appointments = (time_t) 0;
@@ -108,115 +107,140 @@
108 ESource *source;107 ESource *source;
109};108};
110109
111static void110/**
112set_timezone_label (DbusmenuMenuitem * mi, const gchar * location)111 * A temp struct used by update_location_menu_items() for pruning duplicates.
113{112 */
114 gchar * zone, * name;113struct TimeLocation
115 split_settings_location (location, &zone, &name);114{
116115 gint32 offset;
117 dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_NAME, name);116 gchar * zone;
118 dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_ZONE, zone);117 gchar * name;
119118};
120 g_free (zone);119static void
121 g_free (name);120time_location_free (struct TimeLocation * loc)
122}121{
123122 g_free (loc->name);
124static void123 g_free (loc->zone);
125set_current_timezone_label (DbusmenuMenuitem * mi, const gchar * location)124 g_free (loc);
126{125}
127 gchar * name = get_current_zone_name (location);126static struct TimeLocation*
128127time_location_new (const char * zone, const char * name)
129 dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_NAME, name);128{
130 dbusmenu_menuitem_property_set (mi, TIMEZONE_MENUITEM_PROP_ZONE, location);129 struct TimeLocation * loc = g_new (struct TimeLocation, 1);
131130 GTimeZone * tz = g_time_zone_new (zone);
132 g_free (name);131 loc->offset = g_time_zone_get_offset (tz, 0);
133}132 loc->zone = g_strdup (zone);
134133 loc->name = g_strdup (name);
135/* Check to see if our timezones are the same */134 g_time_zone_unref (tz);
136static void135 return loc;
137check_timezone_sync (void) {136}
138 gchar * label;137static int
139 gboolean in_sync = FALSE;138time_location_compare (const struct TimeLocation * a, const struct TimeLocation * b)
140 139{
141 if (geo_timezone == NULL) {140 int ret;
142 in_sync = TRUE;141 if (a->offset != b->offset)
143 }142 ret = a->offset - b->offset;
144143 else
145 if (current_timezone == NULL) {144 ret = g_strcmp0 (a->name, b->name);
146 in_sync = TRUE;145 g_debug ("%s comparing '%s' (%d) to '%s' (%d), returning %d", G_STRLOC, a->name, (int)a->offset, b->name, (int)b->offset, ret);
147 }146 return ret;
148147}
149 if (!in_sync && g_strcmp0(geo_timezone, current_timezone) == 0) {148static GSList*
150 in_sync = TRUE;149locations_add (GSList * locations, const char * zone, const char * name)
151 }150{
152151 struct TimeLocation * loc = time_location_new (zone, name);
153 if (in_sync) {152
154 g_debug("Timezones in sync");153 if (g_slist_find_custom (locations, loc, (GCompareFunc)time_location_compare) == NULL) {
154 g_debug ("%s Adding zone '%s', name '%s'", G_STRLOC, zone, name);
155 locations = g_slist_prepend (locations, loc);
155 } else {156 } else {
156 g_debug("Timezones are different");157 g_debug("%s Skipping duplicate zone '%s' name '%s'", G_STRLOC, zone, name);
157 }158 time_location_free (loc);
158159 }
159 gboolean show = g_settings_get_boolean (conf, SETTINGS_SHOW_LOCATIONS_S);160 return locations;
160161}
161 if (geo_location != NULL && current_location != NULL) {162
162 g_debug("Got timezone %s", current_timezone);163/* Update the timezone entries */
163 g_debug("Got timezone %s", geo_timezone);164static void
164 // Show neither current location nor geo location if both are the same165update_location_menu_items (void)
165 // however, we want to set their time and label accordingly166{
166 if (in_sync) {167 if (locations_separator == NULL)
167 if (current_timezone == NULL && geo_timezone == NULL) {168 return;
168 dbusmenu_menuitem_property_set_bool(locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);169
169 dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);170 GSList * locations = NULL;
170 dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);171
171 update_location_menu_items();172 /* remove the previous locations */
172 return;173 while (location_menu_items != NULL) {
173 }174 DbusmenuMenuitem * item = DBUSMENU_MENUITEM(location_menu_items->data);
174 175 location_menu_items = g_list_remove(location_menu_items, item);
175 dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);176 dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(item));
176 dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);177 g_object_unref(G_OBJECT(item));
177 dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);178 }
178 dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);179
179 dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);180 /***
180 181 **** Build a list of locations to add: use geo_timezone,
181 if (current_timezone != NULL) {182 **** current_timezone, and SETTINGS_LOCATIONS_S, but omit duplicates.
182 label = current_timezone;183 ***/
183 } else {184
184 label = geo_timezone;185 /* maybe add geo_timezone */
185 }186 if (geo_timezone != NULL) {
186 187 gchar * name = get_current_zone_name (geo_timezone);
187 if (label != NULL) {188 locations = locations_add (locations, geo_timezone, name);
188 // TODO work out the current location name in a nice way189 g_free (name);
189 set_current_timezone_label (current_location, label);190 }
190 // TODO work out the current time at that location 191
191 dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);192 /* maybe add current_timezone */
192 dbusmenu_menuitem_property_set_bool(current_location, TIMEZONE_MENUITEM_PROP_RADIO, TRUE);193 if (current_timezone != NULL) {
193 } else {194 gchar * name = get_current_zone_name (current_timezone);
194 g_debug("Label for current location is null, this shouldn't happen");195 locations = locations_add (locations, current_timezone, name);
195 }196 g_free (name);
196 if (geo_timezone != NULL) { 197 }
197 // TODO work out the geo location name in a nice way198
198 set_current_timezone_label (geo_location, geo_timezone);199 /* maybe add the user-specified custom locations */
199 // TODO work out the current time at that location 200 gchar ** user_locations = g_settings_get_strv(conf, SETTINGS_LOCATIONS_S);
200 dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);201 if (user_locations != NULL) {
201 }202 gint i;
202 } else {203 const guint location_count = g_strv_length(user_locations);
203 // TODO work out the geo location name in a nice way204 g_debug ("%s Found %u user-specified locations", G_STRLOC, location_count);
204 set_current_timezone_label (geo_location, geo_timezone);205 for (i=0; i<location_count; i++) {
205 // TODO work out the current time at that location 206 gchar * zone;
206 dbusmenu_menuitem_property_set_bool(geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);207 gchar * name;
207 208 split_settings_location (user_locations[i], &zone, &name);
208 // TODO work out the current location name in a nice way209 locations = locations_add (locations, zone, name);
209 set_current_timezone_label (current_location, current_timezone);210 g_free (name);
210 // TODO work out the current time at that location 211 g_free (zone);
211 dbusmenu_menuitem_property_set_bool(current_location, TIMEZONE_MENUITEM_PROP_RADIO, TRUE);
212 dbusmenu_menuitem_property_set_bool(current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
213 dbusmenu_menuitem_property_set_bool(locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
214 }212 }
215 }213 g_strfreev (user_locations);
216 g_debug("Finished checking timezone sync");214 user_locations = NULL;
217 update_location_menu_items();215 }
218216
219 return;217 /* sort the list by timezone offset */
218 locations = g_slist_sort (locations, (GCompareFunc)time_location_compare);
219
220 /* finally create menuitems for each location */
221 gint offset = dbusmenu_menuitem_get_position (locations_separator, root)+1;
222 const gboolean show_locations = g_settings_get_boolean (conf, SETTINGS_SHOW_LOCATIONS_S);
223 GSList * l;
224 for (l=locations; l!=NULL; l=l->next) {
225 struct TimeLocation * loc = l->data;
226 g_debug("%s Adding location: zone '%s', name '%s'", G_STRLOC, loc->zone, loc->name);
227 DbusmenuMenuitem * item = dbusmenu_menuitem_new();
228 dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, TIMEZONE_MENUITEM_TYPE);
229 dbusmenu_menuitem_property_set (item, TIMEZONE_MENUITEM_PROP_NAME, loc->name);
230 dbusmenu_menuitem_property_set (item, TIMEZONE_MENUITEM_PROP_ZONE, loc->zone);
231 dbusmenu_menuitem_property_set_bool (item, TIMEZONE_MENUITEM_PROP_RADIO, FALSE);
232 dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
233 dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, show_locations);
234 dbusmenu_menuitem_child_add_position (root, item, offset++);
235 g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(quick_set_tz), NULL);
236 location_menu_items = g_list_append (location_menu_items, item);
237 time_location_free (loc);
238 }
239 g_slist_free (locations);
240 locations = NULL;
241
242 /* if there's at least one item being shown, show the separator too */
243 dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, show_locations && (location_menu_items!=NULL));
220}244}
221245
222/* Update the current timezone */246/* Update the current timezone */
@@ -235,7 +259,7 @@
235259
236 g_debug("System timezone is: %s", current_timezone);260 g_debug("System timezone is: %s", current_timezone);
237261
238 check_timezone_sync();262 update_location_menu_items();
239263
240 return;264 return;
241}265}
@@ -566,62 +590,6 @@
566 return FALSE;590 return FALSE;
567}591}
568592
569
570static void
571update_location_menu_items(void) {
572 g_debug("Updating timezone menu items");
573
574 if (locations_separator == NULL || current_location == NULL) {
575 return;
576 }
577
578 gchar ** locations = g_settings_get_strv(conf, SETTINGS_LOCATIONS_S);
579
580 if (locations == NULL) {
581 g_debug("No locations configured (NULL)");
582 return;
583 }
584 const guint len = g_strv_length(locations);
585 g_debug("Found %u locations from %s", len, SETTINGS_LOCATIONS_S);
586
587 /* Remove all of the previous locations */
588 if (dconflocations != NULL) {
589 while (dconflocations != NULL) {
590 DbusmenuMenuitem * item = DBUSMENU_MENUITEM(dconflocations->data);
591 // Remove all the existing menu items which are in dconflocations.
592 dconflocations = g_list_remove(dconflocations, item);
593 dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(item));
594 g_object_unref(G_OBJECT(item));
595 }
596 }
597
598 const gboolean show = g_settings_get_boolean (conf, SETTINGS_SHOW_LOCATIONS_S);
599 dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
600 dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
601 dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
602
603 gint i;
604 gint offset = dbusmenu_menuitem_get_position (current_location, root)+1;
605 for (i = 0; i < len; i++) {
606 // Iterate over configured places and add any which aren't already listed
607 if ((current_timezone == NULL || !g_str_has_prefix(locations[i], current_timezone)) &&
608 (geo_timezone == NULL || !g_str_has_prefix(locations[i], geo_timezone))) {
609 DbusmenuMenuitem *item;
610 g_debug("Adding timezone in update_timezones %s", locations[i]);
611 item = dbusmenu_menuitem_new();
612 dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, TIMEZONE_MENUITEM_TYPE);
613 set_timezone_label (item, locations[i]);
614 dbusmenu_menuitem_property_set_bool (item, TIMEZONE_MENUITEM_PROP_RADIO, FALSE);
615 dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
616 dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, show);
617 dbusmenu_menuitem_child_add_position (root, item, offset++);
618 g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(quick_set_tz), NULL);
619 dconflocations = g_list_append(dconflocations, item);
620 }
621 }
622 g_strfreev (locations);
623}
624
625// Authentication function593// Authentication function
626static gchar *594static gchar *
627auth_func (ECal *ecal, 595auth_func (ECal *ecal,
@@ -1098,7 +1066,7 @@
1098show_locations_changed (void)1066show_locations_changed (void)
1099{1067{
1100 /* Re-calculate */1068 /* Re-calculate */
1101 check_timezone_sync();1069 update_location_menu_items();
1102}1070}
11031071
1104static void1072static void
@@ -1141,22 +1109,7 @@
1141 dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);1109 dbusmenu_menuitem_property_set_bool (locations_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
1142 dbusmenu_menuitem_child_append(root, locations_separator);1110 dbusmenu_menuitem_child_append(root, locations_separator);
11431111
1144 geo_location = dbusmenu_menuitem_new();1112 update_location_menu_items();
1145 dbusmenu_menuitem_property_set (geo_location, DBUSMENU_MENUITEM_PROP_TYPE, TIMEZONE_MENUITEM_TYPE);
1146 set_current_timezone_label (geo_location, "");
1147 dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
1148 dbusmenu_menuitem_property_set_bool (geo_location, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
1149 g_signal_connect(G_OBJECT(geo_location), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(quick_set_tz), NULL);
1150 dbusmenu_menuitem_child_append(root, geo_location);
1151
1152 current_location = dbusmenu_menuitem_new();
1153 dbusmenu_menuitem_property_set (current_location, DBUSMENU_MENUITEM_PROP_TYPE, TIMEZONE_MENUITEM_TYPE);
1154 set_current_timezone_label (current_location, "");
1155 dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
1156 dbusmenu_menuitem_property_set_bool (current_location, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
1157 dbusmenu_menuitem_child_append(root, current_location);
1158
1159 check_timezone_sync();
1160 1113
1161 g_signal_connect (conf, "changed::" SETTINGS_SHOW_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL);1114 g_signal_connect (conf, "changed::" SETTINGS_SHOW_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL);
1162 g_signal_connect (conf, "changed::" SETTINGS_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL);1115 g_signal_connect (conf, "changed::" SETTINGS_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL);
@@ -1297,7 +1250,7 @@
1297 geo_timezone = g_strdup((gchar *)tz_hash);1250 geo_timezone = g_strdup((gchar *)tz_hash);
1298 }1251 }
12991252
1300 check_timezone_sync();1253 update_location_menu_items();
13011254
1302 return;1255 return;
1303}1256}
@@ -1394,7 +1347,7 @@
1394 geo_timezone = NULL;1347 geo_timezone = NULL;
1395 }1348 }
13961349
1397 check_timezone_sync();1350 update_location_menu_items();
13981351
1399 return;1352 return;
1400}1353}
@@ -1416,7 +1369,7 @@
1416 geo_timezone = NULL;1369 geo_timezone = NULL;
1417 }1370 }
14181371
1419 check_timezone_sync();1372 update_location_menu_items();
14201373
1421 return;1374 return;
1422}1375}

Subscribers

People subscribed via source and target branches