From bea8def0740280804fc6c9399b5dd18eeeaf8c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Thu, 7 Jul 2016 18:29:37 +0200 Subject: [PATCH] calendar-server: Get recurrence ID from occurrences We use the triplet of source ID, UID and recurrence ID to create an ID to unambiguously identify an event, which we use to implement hiding dismissed events from the calendar. However we currently try to fetch the recurrence ID from the objects returned by e_cal_client_get_object_list_sync(), which are always the primary events with no recurrence ID. Instead, we need a recurrence ID associated with each occurrence. https://bugzilla.gnome.org/show_bug.cgi?id=748226 --- .../gnome-shell-calendar-server.c | 73 +++++++++---------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/src/calendar-server/gnome-shell-calendar-server.c b/src/calendar-server/gnome-shell-calendar-server.c index 35300c39a..83da77937 100644 --- a/src/calendar-server/gnome-shell-calendar-server.c +++ b/src/calendar-server/gnome-shell-calendar-server.c @@ -74,15 +74,15 @@ static App *_global_app = NULL; typedef struct { + char *rid; time_t start_time; time_t end_time; } CalendarOccurrence; typedef struct { - char *id; char *uid; - char *rid; + char *source_id; char *backend_name; char *summary; char *description; @@ -129,22 +129,6 @@ get_ical_uid (icalcomponent *ical) return g_strdup (icalcomponent_get_uid (ical)); } -static char * -get_ical_rid (icalcomponent *ical) -{ - icalproperty *prop; - struct icaltimetype ical_time; - - prop = icalcomponent_get_first_property (ical, ICAL_RECURRENCEID_PROPERTY); - if (!prop) - return NULL; - - ical_time = icalproperty_get_recurrenceid (prop); - - return icaltime_is_valid_time (ical_time) && !icaltime_is_null_time (ical_time) ? - g_strdup (icaltime_as_ical_string (ical_time)) : NULL; -} - static char * get_ical_summary (icalcomponent *ical) { @@ -324,12 +308,14 @@ calendar_appointment_equal (CalendarAppointment *a, CalendarOccurrence *ob = lb->data; if (oa->start_time != ob->start_time || - oa->end_time != ob->end_time) + oa->end_time != ob->end_time || + null_safe_strcmp (oa->rid, ob->rid) != 0) return FALSE; } return null_safe_strcmp (a->uid, b->uid) == 0 && + null_safe_strcmp (a->source_id, b->source_id) == 0 && null_safe_strcmp (a->backend_name, b->backend_name) == 0 && null_safe_strcmp (a->summary, b->summary) == 0 && null_safe_strcmp (a->description, b->description) == 0 && @@ -345,18 +331,15 @@ calendar_appointment_free (CalendarAppointment *appointment) GSList *l; for (l = appointment->occurrences; l; l = l->next) - g_free (l->data); - g_slist_free (appointment->occurrences); + g_free (((CalendarOccurrence *)l->data)->rid); + g_slist_free_full (appointment->occurrences, g_free); appointment->occurrences = NULL; - g_free (appointment->id); - appointment->id = NULL; - g_free (appointment->uid); appointment->uid = NULL; - g_free (appointment->rid); - appointment->rid = NULL; + g_free (appointment->source_id); + appointment->source_id = NULL; g_free (appointment->backend_name); appointment->backend_name = NULL; @@ -380,11 +363,13 @@ calendar_appointment_init (CalendarAppointment *appointment, ECalClient *cal) { icaltimezone *default_zone; + const char *source_id; + source_id = e_source_get_uid (e_client_get_source (E_CLIENT (cal))); default_zone = e_cal_client_get_default_timezone (cal); appointment->uid = get_ical_uid (ical); - appointment->rid = get_ical_rid (ical); + appointment->source_id = g_strdup (source_id); appointment->backend_name = get_source_backend_name (cal); appointment->summary = get_ical_summary (ical); appointment->description = get_ical_description (ical); @@ -394,16 +379,6 @@ calendar_appointment_init (CalendarAppointment *appointment, appointment->is_all_day = get_ical_is_all_day (ical, appointment->start_time, default_zone); - - /* While the UID is usually enough to identify an event, only the triple - * of (source,UID,RID) is fully unambiguous; neither may contain '\n', - * so we can safely use it to create a unique ID from the triple - */ - source_uid = e_source_get_uid (e_client_get_source (E_CLIENT (cal))); - appointment->id = g_strdup_printf ("%s\n%s\n%s", - source_uid, - appointment->uid, - appointment->rid ? appointment->rid : ""); } static icaltimezone * @@ -429,10 +404,21 @@ calendar_appointment_collect_occurrence (ECalComponent *component, { CalendarOccurrence *occurrence; GSList **collect_loc = data; + char *rid; + + /* HACK: component is the primary event, so we don't have access + * to the actual recur ID; fake one if the event has any + * recurrences + */ + if (e_cal_component_has_recurrences (component)) + rid = ctime (&occurrence_start); + else + rid = ""; occurrence = g_new0 (CalendarOccurrence, 1); occurrence->start_time = occurrence_start; occurrence->end_time = occurrence_end; + occurrence->rid = g_strdup (rid); *collect_loc = g_slist_prepend (*collect_loc, occurrence); @@ -928,16 +914,27 @@ handle_method_call (GDBusConnection *connection, (start_time <= app->since && (end_time - 1) > app->since)) { + /* While the UID is usually enough to identify an event, + * only the triple of (source,UID,RID) is fully unambiguous; + * neither may contain '\n', so we can safely use it to + * create a unique ID from the triple + */ + char *id = g_strdup_printf ("%s\n%s\n%s", + a->source_id, + a->uid, + o->rid); + g_variant_builder_init (&extras_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&builder, "(sssbxxa{sv})", - a->id, + id, a->summary != NULL ? a->summary : "", a->description != NULL ? a->description : "", (gboolean) a->is_all_day, (gint64) start_time, (gint64) end_time, extras_builder); + g_free (id); } } }