diff --git a/src/core/gcal-calendar-monitor.c b/src/core/gcal-calendar-monitor.c index 6690cd4d..0a6dac79 100644 --- a/src/core/gcal-calendar-monitor.c +++ b/src/core/gcal-calendar-monitor.c @@ -81,6 +81,7 @@ struct _GcalCalendarMonitor GHashTable *events; /* gchar* -> GcalEvent* */ GcalRange *range; gchar *filter; + gboolean expand_recurrences; } shared; }; @@ -98,6 +99,7 @@ enum PROP_0, PROP_CALENDAR, PROP_COMPLETE, + PROP_EXPAND_RECURRENCES, N_PROPS }; @@ -383,14 +385,26 @@ on_client_view_objects_added_cb (ECalClientView *view, if (!icomponent || !i_cal_component_get_uid (icomponent)) continue; - /* Recurrent events will be processed later */ - if (e_cal_util_component_has_recurrences (icomponent) && - !e_cal_util_component_is_instance (icomponent)) + if (self->shared.expand_recurrences) { - GCAL_TRACE_MSG ("Component %s (%s) needs to be expanded", - i_cal_component_get_summary (icomponent), - i_cal_component_get_uid (icomponent)); - g_ptr_array_add (components_to_expand, icomponent); + /* Recurrent events will be processed later */ + if (e_cal_util_component_has_recurrences (icomponent) && + !e_cal_util_component_is_instance (icomponent)) + { + GCAL_TRACE_MSG ("Component %s (%s) needs to be expanded", + i_cal_component_get_summary (icomponent), + i_cal_component_get_uid (icomponent)); + g_ptr_array_add (components_to_expand, icomponent); + continue; + } + } + else if (e_cal_util_component_is_instance (icomponent)) + { + /* + * When recurrence expansion is disabled, ignore detached recurrence + * instances (components with a RECURRENCE-ID) returned by EDS so + * only the master recurring component is processed. + */ continue; } @@ -528,12 +542,17 @@ on_client_view_objects_modified_cb (ECalClientView *view, if (!icomponent || !i_cal_component_get_uid (icomponent)) continue; + /* Ignore modified detached recurrence instances when expansion is disabled */ + if (!self->shared.expand_recurrences && e_cal_util_component_is_instance (icomponent)) + continue; + ecomponent = e_cal_component_new_from_icalcomponent (i_cal_component_clone (icomponent)); if (!ecomponent) continue; - recurrence_main = e_cal_util_component_has_recurrences (icomponent) && + recurrence_main = self->shared.expand_recurrences && + e_cal_util_component_has_recurrences (icomponent) && !e_cal_util_component_is_instance (icomponent); /* @@ -1047,6 +1066,9 @@ remove_events_outside_range (GcalCalendarMonitor *self, { GcalRange *event_range = gcal_event_get_range (event); + if (!self->shared.expand_recurrences && gcal_event_has_recurrence (event)) + continue; + if (gcal_range_calculate_overlap (range, event_range, NULL) != GCAL_RANGE_NO_OVERLAP) continue; @@ -1326,6 +1348,10 @@ gcal_calendar_monitor_get_property (GObject *object, g_value_set_boolean (value, self->complete); break; + case PROP_EXPAND_RECURRENCES: + g_value_set_boolean (value, gcal_calendar_monitor_get_expand_recurrences (self)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -1350,6 +1376,10 @@ gcal_calendar_monitor_set_property (GObject *object, self); break; + case PROP_EXPAND_RECURRENCES: + self->shared.expand_recurrences = g_value_get_boolean (value); + break; + case PROP_COMPLETE: default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1374,12 +1404,24 @@ gcal_calendar_monitor_class_init (GcalCalendarMonitorClass *klass) FALSE, G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + /** + * GcalCalendarMonitor:expand-recurrences: + * + * Whether to expand recurrences into multiple instances. + */ + properties[PROP_EXPAND_RECURRENCES] = g_param_spec_boolean ("expand-recurrences", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, N_PROPS, properties); } static void gcal_calendar_monitor_init (GcalCalendarMonitor *self) { + self->shared.expand_recurrences = TRUE; self->shared.events = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); self->thread_context = g_main_context_new (); self->main_context = g_main_context_ref_thread_default (); @@ -1502,3 +1544,11 @@ gcal_calendar_monitor_is_complete (GcalCalendarMonitor *self) return self->complete; } +gboolean +gcal_calendar_monitor_get_expand_recurrences (GcalCalendarMonitor *self) +{ + g_return_val_if_fail (GCAL_IS_CALENDAR_MONITOR (self), TRUE); + + return self->shared.expand_recurrences; +} + diff --git a/src/core/gcal-calendar-monitor.h b/src/core/gcal-calendar-monitor.h index fb8577c9..74231a68 100644 --- a/src/core/gcal-calendar-monitor.h +++ b/src/core/gcal-calendar-monitor.h @@ -43,4 +43,6 @@ void gcal_calendar_monitor_set_filter (GcalCalendarMo gboolean gcal_calendar_monitor_is_complete (GcalCalendarMonitor *self); +gboolean gcal_calendar_monitor_get_expand_recurrences (GcalCalendarMonitor *self); + G_END_DECLS diff --git a/src/core/gcal-timeline.c b/src/core/gcal-timeline.c index 13d02771..404e92df 100644 --- a/src/core/gcal-timeline.c +++ b/src/core/gcal-timeline.c @@ -46,6 +46,7 @@ struct _GcalTimeline GHashTable *calendars; /* GcalCalendar* -> GcalCalendarMonitor* */ gboolean complete; + gboolean expand_recurrences; GListStore *calendar_monitors; GListModel *events_model; @@ -61,6 +62,7 @@ enum { PROP_0, PROP_COMPLETE, + PROP_EXPAND_RECURRENCES, PROP_FILTER, N_PROPS }; @@ -74,6 +76,7 @@ static GParamSpec *properties [N_PROPS] = { NULL, }; typedef struct { + GcalTimeline *timeline; GcalRange *range; GtkFilterListModel *events; GtkSortListModel *sorted_events; @@ -103,6 +106,9 @@ event_in_subscriber_range_func (gpointer item, if (!data->range) return FALSE; + if (!data->timeline->expand_recurrences && gcal_event_has_recurrence (item)) + return TRUE; + return gcal_event_overlaps (item, data->range); } @@ -159,6 +165,7 @@ subscriber_data_new (GcalTimeline *self, g_autoptr (SubscriberData) data = NULL; data = g_new0 (SubscriberData, 1); + data->timeline = self; data->range = gcal_timeline_subscriber_get_range (subscriber); filter = gtk_custom_filter_new (event_in_subscriber_range_func, data, NULL); @@ -502,6 +509,10 @@ gcal_timeline_get_property (GObject *object, g_value_set_boolean (value, self->complete); break; + case PROP_EXPAND_RECURRENCES: + g_value_set_boolean (value, self->expand_recurrences); + break; + case PROP_FILTER: g_value_set_string (value, self->filter); break; @@ -521,6 +532,10 @@ gcal_timeline_set_property (GObject *object, switch (prop_id) { + case PROP_EXPAND_RECURRENCES: + self->expand_recurrences = g_value_get_boolean (value); + break; + case PROP_FILTER: gcal_timeline_set_filter (self, g_value_get_string (value)); break; @@ -550,6 +565,17 @@ gcal_timeline_class_init (GcalTimelineClass *klass) FALSE, G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + /** + * GcalTimeline:expand-recurrences: + * + * Whether to expand recurrences into multiple instances. + */ + properties[PROP_EXPAND_RECURRENCES] = g_param_spec_boolean ("expand-recurrences", + "Expand recurrences", + "Expand recurrences", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + /** * GcalTimeline::filter: * @@ -568,6 +594,7 @@ static void gcal_timeline_init (GcalTimeline *self) { self->augmentation_factor = 1.0; + self->expand_recurrences = TRUE; self->cancellable = g_cancellable_new (); self->calendars = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref); @@ -635,7 +662,10 @@ gcal_timeline_add_calendar (GcalTimeline *self, GCAL_TRACE_MSG ("Adding calendar '%s' to timeline %p", gcal_calendar_get_name (calendar), self); - monitor = gcal_calendar_monitor_new (calendar); + monitor = g_object_new (GCAL_TYPE_CALENDAR_MONITOR, + "calendar", calendar, + "expand-recurrences", self->expand_recurrences, + NULL); g_signal_connect (monitor, "notify::complete", G_CALLBACK (on_calendar_monitor_completed_cb), self); g_hash_table_insert (self->calendars, calendar, g_object_ref (monitor)); g_list_store_append (self->calendar_monitors, monitor); @@ -768,3 +798,12 @@ gcal_timeline_is_complete (GcalTimeline *self) return self->complete; } + +gboolean +gcal_timeline_get_expand_recurrences (GcalTimeline *self) +{ + g_return_val_if_fail (GCAL_IS_TIMELINE (self), TRUE); + + return self->expand_recurrences; +} + diff --git a/src/core/gcal-timeline.h b/src/core/gcal-timeline.h index 6dbd581f..a07d5e13 100644 --- a/src/core/gcal-timeline.h +++ b/src/core/gcal-timeline.h @@ -56,4 +56,6 @@ void gcal_timeline_set_filter (GcalTimeline gboolean gcal_timeline_is_complete (GcalTimeline *self); +gboolean gcal_timeline_get_expand_recurrences (GcalTimeline *self); + G_END_DECLS