Merge lp:~karl-qdh/indicator-datetime/fixed-appointment-icon-colours into lp:indicator-datetime/0.3
- fixed-appointment-icon-colours
- Merge into trunk
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 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ted Gould (community) | Approve | ||
Review via email: mp+52080@code.launchpad.net |
Commit message
Description of the change
Add coloured squares to the indicator appointments
To post a comment you must log in.
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); |
review approve
merge approve