Merge lp:~karl-qdh/indicator-datetime/fixed-appointment-icon-colours into lp:indicator-datetime/0.3

Proposed by Karl Lattimer
Status: Merged
Approved by: Ted Gould
Approved revision: 59
Merged at revision: 53
Proposed branch: lp:~karl-qdh/indicator-datetime/fixed-appointment-icon-colours
Merge into: lp:indicator-datetime/0.3
Diff against target: 632 lines (+313/-149) (has conflicts)
1 file modified
src/datetime-service.c (+313/-149)
Text conflict in src/datetime-service.c
To merge this branch: bzr merge lp:~karl-qdh/indicator-datetime/fixed-appointment-icon-colours
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+52080@code.launchpad.net

Description of the change

Add coloured squares to the indicator appointments

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

  review approve
  merge approve

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/datetime-service.c'
2--- src/datetime-service.c 2011-03-01 04:05:10 +0000
3+++ src/datetime-service.c 2011-03-03 15:04:13 +0000
4@@ -73,6 +73,7 @@
5 static DbusmenuMenuitem * date = NULL;
6 static DbusmenuMenuitem * calendar = NULL;
7 static DbusmenuMenuitem * settings = NULL;
8+static DbusmenuMenuitem * events_separator = NULL;
9 static DbusmenuMenuitem * locations_separator = NULL;
10 static DbusmenuMenuitem * geo_location = NULL;
11 static DbusmenuMenuitem * current_location = NULL;
12@@ -80,6 +81,8 @@
13 static DbusmenuMenuitem * add_appointment = NULL;
14 static GList * appointments = NULL;
15 static GList * dconflocations = NULL;
16+static GList * comp_instances = NULL;
17+static gboolean updating_appointments = FALSE;
18 GSettings *conf;
19
20
21@@ -91,6 +94,13 @@
22 static gchar * current_timezone = NULL;
23 static gchar * geo_timezone = NULL;
24
25+struct comp_instance {
26+ ECalComponent *comp;
27+ time_t start;
28+ time_t end;
29+ ESource *source;
30+};
31+
32 static void
33 set_timezone_label (DbusmenuMenuitem * mi, const gchar * location)
34 {
35@@ -278,8 +288,50 @@
36 return TRUE;
37 }
38
39+static guint ecaltimer = 0;
40+
41+static void
42+start_ecal_timer(void)
43+{
44+ if (ecaltimer != 0) g_source_remove(ecaltimer);
45+ if (update_appointment_menu_items(NULL))
46+ ecaltimer = g_timeout_add_seconds(60*5, update_appointment_menu_items, NULL);
47+}
48+
49+static void
50+stop_ecal_timer(void)
51+{
52+ if (ecaltimer != 0) g_source_remove(ecaltimer);
53+}
54+
55+static void
56+show_events_changed (void)
57+{
58+ if (g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS_S)) {
59+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
60+ dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
61+ start_ecal_timer();
62+ } else {
63+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
64+ dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
65+ /* Remove all of the previous appointments */
66+ if (appointments != NULL) {
67+ g_debug("Freeing old appointments");
68+ while (appointments != NULL) {
69+ DbusmenuMenuitem * litem = DBUSMENU_MENUITEM(appointments->data);
70+ g_debug("Freeing old appointment: %p", litem);
71+ // Remove all the existing menu items which are in appointments.
72+ appointments = g_list_remove(appointments, litem);
73+ dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(litem));
74+ g_object_unref(G_OBJECT(litem));
75+ }
76+ }
77+ stop_ecal_timer();
78+ }
79+}
80+
81 /* Looks for the calendar application and enables the item if
82- we have one */
83+ we have one, starts ecal timer if events are turned on */
84 static gboolean
85 check_for_calendar (gpointer user_data)
86 {
87@@ -293,21 +345,26 @@
88 dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
89 dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
90
91- DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
92- dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
93- dbusmenu_menuitem_child_add_position(root, separator, 2);
94-
95+ events_separator = dbusmenu_menuitem_new();
96+ dbusmenu_menuitem_property_set(events_separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
97+ dbusmenu_menuitem_child_add_position(root, events_separator, 2);
98 add_appointment = dbusmenu_menuitem_new();
99- dbusmenu_menuitem_property_set (add_appointment, DBUSMENU_MENUITEM_PROP_LABEL, _("Add Appointment"));
100+ dbusmenu_menuitem_property_set (add_appointment, DBUSMENU_MENUITEM_PROP_LABEL, _("Add Appointment"));
101 dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
102- dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
103 g_signal_connect(G_OBJECT(add_appointment), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), "evolution -c calendar");
104 dbusmenu_menuitem_child_add_position (root, add_appointment, 3);
105
106- // Update the calendar items every 5 minutes if it updates the first time
107- if (update_appointment_menu_items(NULL))
108- g_timeout_add_seconds(60*5, update_appointment_menu_items, NULL);
109-
110+
111+ if (g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS_S)) {
112+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
113+ dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
114+ start_ecal_timer();
115+ } else {
116+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
117+ dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
118+ stop_ecal_timer();
119+ }
120+
121 // Connect to event::month-changed
122 g_signal_connect(calendar, "event::month-changed", G_CALLBACK(month_changed_cb), NULL);
123 g_free(evo);
124@@ -381,7 +438,11 @@
125
126 // Authentication function
127 static gchar *
128-auth_func (ECal *ecal, const gchar *prompt, const gchar *key, gpointer user_data) {
129+auth_func (ECal *ecal,
130+ const gchar *prompt,
131+ const gchar *key,
132+ gpointer user_data)
133+{
134 gboolean remember; // TODO: Is this useful? Should we be storing it somewhere?
135 ESource *source = e_cal_get_source (ecal);
136 gchar *auth_domain = e_source_get_duped_property (source, "auth-domain");
137@@ -407,47 +468,92 @@
138 return password;
139 }
140
141-
142-// Compare function for g_list_sort of ECalComponent objects
143-static gint
144-compare_appointment_items (ECalComponent *a,
145- ECalComponent *b) {
146-
147- ECalComponentDateTime datetime_a, datetime_b;
148- struct tm tm_a, tm_b;
149- time_t t_a, t_b;
150- gint retval = 0;
151-
152- if (a == NULL || b == NULL) return retval;
153-
154- ECalComponentVType vtype = e_cal_component_get_vtype (a);
155-
156- if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return -1;
157-
158- if (vtype == E_CAL_COMPONENT_EVENT)
159- e_cal_component_get_dtstart (a, &datetime_a);
160- else
161- e_cal_component_get_due (a, &datetime_a);
162- tm_a = icaltimetype_to_tm(datetime_a.value);
163- t_a = mktime(&tm_a);
164-
165- vtype = e_cal_component_get_vtype (b);
166- if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return 1;
167-
168- if (vtype == E_CAL_COMPONENT_EVENT)
169- e_cal_component_get_dtstart (b, &datetime_b);
170- else
171- e_cal_component_get_due (b, &datetime_b);
172- tm_b = icaltimetype_to_tm(datetime_b.value);
173- t_b = mktime(&tm_b);
174-
175- // Compare datetime_a and datetime_b, newest first in this sort.
176- if (t_a > t_b) retval = 1;
177- else if (t_a < t_b) retval = -1;
178-
179- e_cal_component_free_datetime (&datetime_a);
180- e_cal_component_free_datetime (&datetime_b);
181- return retval;
182+static gint
183+compare_comp_instances (gconstpointer a,
184+ gconstpointer b)
185+{
186+ const struct comp_instance *ci_a = a;
187+ const struct comp_instance *ci_b = b;
188+ time_t d = ci_a->start - ci_b->start;
189+ if (d < 0) return -1;
190+ else if (d > 0) return 1;
191+ return 0;
192+}
193+
194+static gboolean
195+populate_appointment_instances (ECalComponent *comp,
196+ time_t instance_start,
197+ time_t instance_end,
198+ gpointer data)
199+{
200+ g_debug("Appending item %p", comp);
201+
202+ ECalComponentVType vtype = e_cal_component_get_vtype (comp);
203+ if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return FALSE;
204+
205+ icalproperty_status status;
206+ e_cal_component_get_status (comp, &status);
207+ if (status == ICAL_STATUS_COMPLETED || status == ICAL_STATUS_CANCELLED) return FALSE;
208+
209+ g_object_ref(comp);
210+
211+ ECalComponentDateTime datetime;
212+ icaltimezone *appointment_zone = NULL;
213+ icaltimezone *current_zone = NULL;
214+
215+ if (vtype == E_CAL_COMPONENT_EVENT)
216+ e_cal_component_get_dtstart (comp, &datetime);
217+ else
218+ e_cal_component_get_due (comp, &datetime);
219+
220+ appointment_zone = icaltimezone_get_builtin_timezone_from_tzid(datetime.tzid);
221+ current_zone = icaltimezone_get_builtin_timezone_from_tzid(current_timezone);
222+ if (!appointment_zone || datetime.value->is_date) { // If it's today put in the current timezone?
223+ appointment_zone = current_zone;
224+ }
225+
226+ // TODO: Convert the timezone into a 3 letter abbreviation if it's different to current_timezone
227+ // TODO: Add the appointment timezone to the list if it's not already there.
228+
229+ GSList *period_list = NULL, *l;
230+ if (e_cal_component_has_recurrences (comp)) {
231+ e_cal_component_get_rdate_list (comp, &period_list);
232+ g_debug("ECalComponent has recurrences");
233+ } else {
234+ g_debug("ECalComponent doesn't have recurrences");
235+ }
236+
237+ struct comp_instance *ci;
238+ ci = g_new (struct comp_instance, 1);
239+
240+ // Do we get rdate_list?
241+ if (period_list != NULL) {
242+ g_debug("Got recurring periods");
243+ for (l = period_list; l; l = l->next) {
244+ ECalComponentPeriod *period = l->data;
245+ struct tm tmp_tm = icaltimetype_to_tm_with_zone (&period->start, appointment_zone, current_zone);
246+ time_t start = mktime(&tmp_tm);
247+ g_debug("period time: %d", (int)start);
248+
249+ tmp_tm = icaltimetype_to_tm_with_zone (&period->u.end, appointment_zone, current_zone);
250+ time_t end = mktime(&tmp_tm);
251+
252+ if (start >= instance_start && end < instance_end) {
253+ ci->start = start;
254+ ci->end = end;
255+ }
256+ }
257+ } else {
258+ ci->start = instance_start;
259+ ci->end = instance_end;
260+ g_debug("Got no recurring periods set time to start %s, end %s", ctime(&instance_start), ctime(&instance_end));
261+ }
262+
263+ ci->comp = comp;
264+ ci->source = E_SOURCE(data);
265+
266+ comp_instances = g_list_append(comp_instances, ci);
267+ return TRUE;
268 }
269
270 /* Populate the menu with todays, next 5 appointments.
271@@ -456,22 +562,38 @@
272 * this is a problem mainly on the EDS side of things, not ours.
273 */
274 static gboolean
275-update_appointment_menu_items (gpointer user_data) {
276+update_appointment_menu_items (gpointer user_data)
277+{
278 // FFR: we should take into account short term timers, for instance
279 // tea timers, pomodoro timers etc... that people may add, this is hinted to in the spec.
280 if (calendar == NULL) return FALSE;
281 if (!g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS_S)) return FALSE;
282+ if (updating_appointments) return TRUE;
283+ updating_appointments = TRUE;
284
285+<<<<<<< TREE
286 gchar *query, *ad;
287 GList *objects = NULL, *l;
288 GList *allobjects = NULL;
289+=======
290+ time_t t1, t2;
291+ gchar *ad;
292+ GList *l;
293+ //GList *allobjects = NULL;
294+>>>>>>> MERGE-SOURCE
295 GSList *g;
296 GError *gerror = NULL;
297 gint i;
298 gint width, height;
299 ESourceList * sources = NULL;
300
301+<<<<<<< TREE
302 gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
303+=======
304+ time(&t1);
305+ time(&t2);
306+ t2 += (time_t) (7 * 24 * 60 * 60); /* 7 days ahead of now, we actually need number_of_days_in_this_month */
307+>>>>>>> MERGE-SOURCE
308
309 /* Remove all of the previous appointments */
310 if (appointments != NULL) {
311@@ -487,15 +609,29 @@
312 }
313
314 // TODO Remove all highlights from the calendar widget
315+<<<<<<< TREE
316
317 // FIXME can we put a limit on the number of results? Or if not complete, or is event/todo? Or sort it by date?
318 query = g_strdup_printf("(occur-in-time-range? (time-now) (time-add-day (time-now) 7))");
319+=======
320+>>>>>>> MERGE-SOURCE
321
322 if (!e_cal_get_sources(&sources, E_CAL_SOURCE_TYPE_EVENT, &gerror)) {
323 g_debug("Failed to get ecal sources\n");
324 return FALSE;
325 }
326-
327+
328+ // Free comp_instances if not NULL
329+ if (comp_instances != NULL) {
330+ g_debug("Freeing comp_instances: may be an overlap\n");
331+ for (l = comp_instances; l; l = l->next) {
332+ const struct comp_instance *ci = l->data;
333+ g_object_unref(ci->comp);
334+ g_list_free(comp_instances);
335+ comp_instances = NULL;
336+ }
337+ }
338+
339 // iterate the query for all sources
340 for (g = e_source_list_peek_groups (sources); g; g = g->next) {
341 ESourceGroup *group = E_SOURCE_GROUP (g->data);
342@@ -503,7 +639,7 @@
343
344 for (s = e_source_group_peek_sources (group); s; s = s->next) {
345 ESource *source = E_SOURCE (s->data);
346- g_signal_connect (G_OBJECT(source), "changed", G_CALLBACK (update_appointment_menu_items), NULL);
347+ //g_signal_connect (G_OBJECT(source), "changed", G_CALLBACK (update_appointment_menu_items), NULL);
348 ECal *ecal = e_cal_new(source, E_CAL_SOURCE_TYPE_EVENT);
349 e_cal_set_auth_func (ecal, (ECalAuthFunc) auth_func, NULL);
350
351@@ -514,55 +650,35 @@
352 continue;
353 }
354
355- g_debug("Getting objects with query: %s", query);
356- if (!e_cal_get_object_list_as_comp(ecal, query, &objects, &gerror)) {
357- g_debug("Failed to get objects\n");
358- g_free(ecal);
359- gerror = NULL;
360- continue;
361- }
362- g_debug("Number of objects returned: %d", g_list_length(objects));
363-
364- if (allobjects == NULL) {
365- allobjects = objects;
366- } else if (objects != NULL) {
367- allobjects = g_list_concat(allobjects, objects);
368- g_object_unref(objects);
369- }
370+ g_debug("Generating instances");
371+ e_cal_generate_instances (ecal, t1, t2, (ECalRecurInstanceFn) populate_appointment_instances, (gpointer) source);
372+ g_debug("Number of objects returned: %d", g_list_length(comp_instances));
373 }
374 }
375-
376- // Sort the list see above FIXME regarding queries
377- g_debug("Sorting objects list");
378- allobjects = g_list_sort(allobjects, (GCompareFunc) compare_appointment_items);
379+ GList *sorted_comp_instances = g_list_sort(comp_instances, compare_comp_instances);
380+ comp_instances = NULL;
381 i = 0;
382- for (l = allobjects; l; l = l->next) {
383- ECalComponent *ecalcomp = l->data;
384+
385+ gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
386+ if (width == 0) width = 12;
387+ if (height == 0) height = 12;
388+ for (l = sorted_comp_instances; l; l = l->next) {
389+ struct comp_instance *ci = l->data;
390+ ECalComponent *ecalcomp = ci->comp;
391 ECalComponentText valuetext;
392- ECalComponentDateTime datetime;
393- icaltimezone *appointment_zone = NULL;
394- icaltimezone *current_zone = NULL;
395- icalproperty_status status;
396+ //ECalComponentDateTime datetime;
397 gchar *summary, *cmd;
398 char right[20];
399 //const gchar *uri;
400- struct tm tmp_tm;
401 DbusmenuMenuitem * item;
402
403- g_debug("Start Object");
404- ECalComponentVType vtype = e_cal_component_get_vtype (ecalcomp);
405-
406- // See above FIXME regarding query result
407- // If it's not an event or todo, continue no-increment
408- if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO)
409- continue;
410-
411- // See above FIXME regarding query result
412- // if the status is completed, continue no-increment
413- e_cal_component_get_status (ecalcomp, &status);
414- if (status == ICAL_STATUS_COMPLETED || status == ICAL_STATUS_CANCELLED)
415- continue;
416-
417+ g_debug("Start Object %p", ecalcomp);
418+
419+ // TODO Mark days
420+
421+ if (i >= 5) continue;
422+ i++;
423+
424 item = dbusmenu_menuitem_new();
425 dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, APPOINTMENT_MENUITEM_TYPE);
426 dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
427@@ -576,97 +692,143 @@
428 g_debug("Summary: %s", summary);
429 g_free (summary);
430
431- // Due text
432- if (vtype == E_CAL_COMPONENT_EVENT)
433- e_cal_component_get_dtstart (ecalcomp, &datetime);
434- else
435- e_cal_component_get_due (ecalcomp, &datetime);
436-
437+ //appointment_zone = icaltimezone_get_builtin_timezone_from_tzid(datetime.tzid);
438+ //current_zone = icaltimezone_get_builtin_timezone_from_tzid(current_timezone);
439+ //if (!appointment_zone || datetime.value->is_date) { // If it's today put in the current timezone?
440+ // appointment_zone = current_zone;
441+ //}
442 // FIXME need to get the timezone of the above datetime,
443 // and get the icaltimezone of the geoclue timezone/selected timezone (whichever is preferred)
444- if (!datetime.value) {
445- g_free(item);
446- continue;
447- }
448-
449- appointment_zone = icaltimezone_get_builtin_timezone_from_tzid(datetime.tzid);
450- current_zone = icaltimezone_get_builtin_timezone_from_tzid(current_timezone);
451- if (!appointment_zone || datetime.value->is_date) { // If it's today put in the current timezone?
452- appointment_zone = current_zone;
453- }
454 // TODO: Convert the timezone into a 3 letter abbreviation if it's different to current_timezone
455 // TODO: Add the appointment timezone to the list if it's not already there.
456
457- tmp_tm = icaltimetype_to_tm_with_zone (datetime.value, appointment_zone, current_zone);
458-
459- g_debug("Generate time string");
460+ //tmp_tm = icaltimetype_to_tm_with_zone (datetime.value, appointment_zone, current_zone);
461+
462+ // Due text
463+ ECalComponentVType vtype = e_cal_component_get_vtype (ecalcomp);
464+
465 // Get today
466 time_t curtime = time(NULL);
467- struct tm* today = localtime(&curtime);
468- if (today->tm_mday == tmp_tm.tm_mday &&
469- today->tm_mon == tmp_tm.tm_mon &&
470- today->tm_year == tmp_tm.tm_year)
471- strftime(right, 20, "%l:%M %P", &tmp_tm);
472+ struct tm *today = localtime(&curtime);
473+
474+ int mday = today->tm_mday;
475+ int mon = today->tm_mon;
476+ int year = today->tm_year;
477+
478+ struct tm *due;
479+ g_debug("Start time %s", ctime(&ci->start));
480+ if (vtype == E_CAL_COMPONENT_EVENT) due = localtime(&ci->start);
481+ else if (vtype == E_CAL_COMPONENT_TODO) due = localtime(&ci->end);
482+ else continue;
483+
484+ strftime(right, 20, "%a %l:%M %p", due);
485+ g_debug("Start time %s -> %s", asctime(due), right);
486+
487+ int dmday = due->tm_mday;
488+ int dmon = due->tm_mon;
489+ int dyear = due->tm_year;
490+
491+ if ((mday == dmday) && (mon == dmon) && (year == dyear))
492+ strftime(right, 20, "%l:%M %p", due);
493 else
494- strftime(right, 20, "%a %l:%M %P", &tmp_tm);
495+ strftime(right, 20, "%a %l:%M %p", due);
496
497 g_debug("Appointment time: %s", right);
498- g_debug("Appointment timezone: %s", datetime.tzid);
499- g_debug("Appointment timezone: %s", icaltimezone_get_tzid(appointment_zone)); // These two should be the same
500+ //g_debug("Appointment timezone: %s", datetime.tzid);
501+ //g_debug("Appointment timezone: %s", icaltimezone_get_tzid(appointment_zone)); // These two should be the same
502 //g_debug("Calendar timezone: %s", ecal_timezone);
503
504 dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, right);
505
506- e_cal_component_free_datetime (&datetime);
507+ //e_cal_component_free_datetime (&datetime);
508
509- ad = isodate_from_time_t(mktime(&tmp_tm));
510
511 // Now we pull out the URI for the calendar event and try to create a URI that'll work when we execute evolution
512 // FIXME Because the URI stuff is really broken, we're going to open the calendar at todays date instead
513-
514 //e_cal_component_get_uid(ecalcomp, &uri);
515+ ad = isodate_from_time_t(mktime(due));
516 cmd = g_strconcat("evolution calendar:///?startdate=", ad, NULL);
517 g_signal_connect (G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
518 G_CALLBACK (activate_cb), cmd);
519
520 g_debug("Command to Execute: %s", cmd);
521-
522- // FIXME This is now more difficult to get right with more sources, as we need to keep track
523- // of which ecal or source goes with each ECalComponent :/
524-
525- //ESource *source = e_cal_get_source (ecal);
526- //e_source_get_color (source, &source_color); api has been changed
527- const gchar *color_spec = NULL; //e_source_peek_color_spec(source);
528+
529+ const gchar *color_spec = e_source_peek_color_spec(ci->source);
530 g_debug("Colour to use: %s", color_spec);
531
532 // Draw the correct icon for the appointment type and then tint it using mask fill.
533 // For now we'll create a circle
534 if (color_spec != NULL) {
535+ // Fixme causes segfault, but we have colours now yay!
536 GdkColor color;
537- gdk_color_parse (color_spec, &color);
538-
539- cairo_surface_t *cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
540- cairo_t *cr = cairo_create(cs);
541- cairo_arc (cr, width/2, height/2, width/2, 0, 2 * M_PI);
542+ gdk_color_parse (color_spec, &color);
543+
544+ cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height );
545+ // Width keeps becoming zero!!
546+ if (width == 0) width = 12;
547+ if (height == 0) height = 12;
548+ cairo_t *cr = cairo_create(surface);
549 gdk_cairo_set_source_color(cr, &color);
550- cairo_fill(cr);
551-
552- GdkPixbuf * pixbuf = gdk_pixbuf_get_from_drawable(NULL, (GdkDrawable*)cs,
553- gdk_colormap_new(gdk_drawable_get_visual((GdkDrawable*)cs), TRUE), 0,0,0,0, width, height);
554- cairo_destroy(cr);
555+ cairo_paint(cr);
556+ cairo_set_source_rgba(cr, 0,0,0,0.5);
557+ cairo_set_line_width(cr, 1);
558+ cairo_rectangle (cr, 0.5, 0.5, width-1, height-1);
559+ cairo_stroke(cr);
560+ // Convert to pixbuf, in gtk3 this is done with gdk_pixbuf_get_from_surface
561+ cairo_content_t content = cairo_surface_get_content (surface) | CAIRO_CONTENT_COLOR;
562+ // Width keeps becoming zero!!
563+ if (width == 0) width = 12;
564+ if (height == 0) height = 12;
565+ GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
566+ !!(content & CAIRO_CONTENT_ALPHA),
567+ 8, width, height);
568+ if (pixbuf != NULL) {
569+ gint sstride = cairo_image_surface_get_stride( surface );
570+ gint dstride = gdk_pixbuf_get_rowstride (pixbuf);
571+ guchar *spixels = cairo_image_surface_get_data( surface );
572+ guchar *dpixels = gdk_pixbuf_get_pixels (pixbuf);
573+
574+ int x, y;
575+ for (y = 0; y < height; y++) {
576+ guint32 *src = (guint32 *) spixels;
577+
578+ for (x = 0; x < width; x++) {
579+ guint alpha = src[x] >> 24;
580+
581+ if (alpha == 0) {
582+ dpixels[x * 4 + 0] = 0;
583+ dpixels[x * 4 + 1] = 0;
584+ dpixels[x * 4 + 2] = 0;
585+ } else {
586+ dpixels[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
587+ dpixels[x * 4 + 1] = (((src[x] & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha;
588+ dpixels[x * 4 + 2] = (((src[x] & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha;
589+ }
590+ dpixels[x * 4 + 3] = alpha;
591+ }
592+ spixels += sstride;
593+ dpixels += dstride;
594+ }
595+
596+ cairo_surface_destroy (surface);
597+ cairo_destroy(cr);
598
599- dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf);
600+ dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf);
601+ }
602 }
603- dbusmenu_menuitem_child_add_position (root, item, 3+i);
604+ dbusmenu_menuitem_child_add_position (root, item, 2+i);
605 appointments = g_list_append (appointments, item); // Keep track of the items here to make them east to remove
606 g_debug("Adding appointment: %p", item);
607-
608- if (i == 4) break; // See above FIXME regarding query result limit
609- i++;
610 }
611
612 if (gerror != NULL) g_error_free(gerror);
613- g_object_unref(allobjects);
614+ for (l = sorted_comp_instances; l; l = l->next) {
615+ const struct comp_instance *ci = l->data;
616+ g_object_unref(ci->comp);
617+ g_list_free(sorted_comp_instances);
618+ }
619+
620+ updating_appointments = FALSE;
621 g_debug("End of objects");
622 return TRUE;
623 }
624@@ -748,6 +910,8 @@
625 check_timezone_sync();
626
627 g_signal_connect (conf, "changed::" SETTINGS_SHOW_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL);
628+ g_signal_connect (conf, "changed::" SETTINGS_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL);
629+ g_signal_connect (conf, "changed::" SETTINGS_SHOW_EVENTS_S, G_CALLBACK (show_events_changed), NULL);
630
631 DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
632 dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);

Subscribers

People subscribed via source and target branches