summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2022-10-14 17:09:28 -0400
committerRay Strode <rstrode@redhat.com>2022-10-15 10:02:42 -0400
commit7d7c27d0750279a1ac2560358187f20951c7a505 (patch)
tree3f140f53cfdc2026541db55be9d08f6b4b066716
parentd071c5e2b02859f469657a40391e2c625dd74612 (diff)
downloadgnome-calendar-fix-shifting-events.tar.gz
core: Handle exceptions in event listfix-shifting-events
If a recurrence of events is set up and one of the events gets deleted, that event needs to be marked as an exception on the main event so that it doesn't get recreated any time the main event is edited. This commit adds code to manage setting up this exception.
-rw-r--r--src/core/gcal-event.c81
-rw-r--r--src/core/gcal-event.h8
-rw-r--r--src/core/gcal-manager.c18
-rw-r--r--src/core/gcal-timeline.c11
4 files changed, 114 insertions, 4 deletions
diff --git a/src/core/gcal-event.c b/src/core/gcal-event.c
index 88087337..e03ab82b 100644
--- a/src/core/gcal-event.c
+++ b/src/core/gcal-event.c
@@ -95,6 +95,7 @@ struct _GcalEvent
GBinding *color_binding;
gboolean all_day;
+ gboolean excluded;
/* A map of GcalAlarmType */
GHashTable *alarms;
@@ -138,10 +139,40 @@ static GParamSpec* properties[N_PROPS] = { NULL, };
*/
static void
+check_if_excluded (GcalEvent *self)
+{
+ ECalComponentDateTime *date;
+ GSList *exclusion_dates, *node;
+
+ GCAL_TRACE_MSG ("Checking if event should be excluded");
+
+ self->excluded = FALSE;
+
+ date = e_cal_component_get_dtstart (self->component);
+ exclusion_dates = e_cal_component_get_exdates (self->component);
+ for (node = exclusion_dates; node != NULL; node = node->next)
+ {
+ ECalComponentDateTime *exclusion_date = node->data;
+
+ if (i_cal_time_compare (e_cal_component_datetime_get_value (exclusion_date),
+ e_cal_component_datetime_get_value (date)) == 0)
+ {
+ self->excluded = TRUE;
+ break;
+ }
+ }
+ g_slist_free_full (exclusion_dates, e_cal_component_datetime_free);
+
+ g_clear_pointer (&date, e_cal_component_datetime_free);
+}
+
+static void
clear_range (GcalEvent *self)
{
g_clear_pointer (&self->range, gcal_range_unref);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_RANGE]);
+
+ check_if_excluded (self);
}
static GTimeZone*
@@ -392,6 +423,8 @@ setup_component (GcalEvent *self,
g_clear_object (&date);
}
+ check_if_excluded (self);
+
/* Summary */
text = e_cal_component_get_summary (self->component);
if (text && e_cal_component_text_get_value (text))
@@ -1002,6 +1035,38 @@ gcal_event_apply_instance (GcalEvent *self,
}
/**
+ * gcal_event_remove_instance:
+ * @self: a #GcalEvent
+ *
+ * Marks the given instance as an exception in the main event recurrence list,
+ * so it essentially gets removed
+ */
+void
+gcal_event_remove_instance (GcalEvent *self,
+ GcalEvent *instance)
+{
+ GSList *exceptions;
+ ECalComponentDateTime *instance_date;
+
+ g_return_if_fail (GCAL_IS_EVENT (self));
+
+ if (e_cal_component_is_instance (self->component))
+ return;
+
+ if (!e_cal_component_is_instance (instance->component))
+ return;
+
+ instance_date = e_cal_component_get_dtstart (instance->component);
+ exceptions = e_cal_component_get_exdates (self->component);
+ exceptions = g_slist_prepend (exceptions, instance_date);
+
+ e_cal_component_set_exdates (self->component, exceptions);
+ e_cal_component_commit_sequence (self->component);
+
+ g_slist_free_full (exceptions, e_cal_component_datetime_free);
+}
+
+/**
* gcal_event_get_all_day:
* @self: a #GcalEvent
*
@@ -1209,12 +1274,26 @@ gcal_event_get_range (GcalEvent *self)
self->range = gcal_range_new (gcal_event_get_date_start (self),
gcal_event_get_date_end (self),
self->all_day ? GCAL_RANGE_DATE_ONLY : GCAL_RANGE_DEFAULT);
+
+ check_if_excluded (self);
}
return self->range;
}
/**
+ * gcal_event_get_excluded:
+ * @self: a #GcalEvent
+ *
+ * Retrieves whether or not the event has been excluded by an exdate.
+ */
+gboolean
+gcal_event_get_excluded (GcalEvent *self)
+{
+ return self->excluded;
+}
+
+/**
* gcal_event_get_description:
* @self a #GcalEvent
*
@@ -1847,6 +1926,8 @@ gcal_event_set_recurrence (GcalEvent *self,
g_clear_object (&rrule);
g_clear_object (&prop);
+
+ check_if_excluded (self);
}
/**
diff --git a/src/core/gcal-event.h b/src/core/gcal-event.h
index c124bc55..e24e79d6 100644
--- a/src/core/gcal-event.h
+++ b/src/core/gcal-event.h
@@ -57,8 +57,11 @@ GcalEvent* gcal_event_new_from_event (GcalEvent
GcalEvent* gcal_event_new_main_event_from_instance_event (GcalEvent *self);
-void gcal_event_apply_instance (GcalEvent *self,
- GcalEvent *instance);
+void gcal_event_apply_instance (GcalEvent *self,
+ GcalEvent *instance);
+
+void gcal_event_remove_instance (GcalEvent *self,
+ GcalEvent *instance);
gboolean gcal_event_get_all_day (GcalEvent *self);
@@ -83,6 +86,7 @@ void gcal_event_set_date_start (GcalEvent
GDateTime *dt);
GcalRange* gcal_event_get_range (GcalEvent *self);
+gboolean gcal_event_get_excluded (GcalEvent *self);
const gchar* gcal_event_get_description (GcalEvent *self);
diff --git a/src/core/gcal-manager.c b/src/core/gcal-manager.c
index cf9284d6..3538963e 100644
--- a/src/core/gcal-manager.c
+++ b/src/core/gcal-manager.c
@@ -1115,6 +1115,24 @@ gcal_manager_remove_event (GcalManager *self,
on_event_removed,
g_object_ref (event));
+ if (mod != GCAL_RECURRENCE_MOD_ALL)
+ {
+ g_autoptr (GcalEvent) main_event = NULL;
+
+ main_event = gcal_event_new_main_event_from_instance_event (event);
+ component = gcal_event_get_component (main_event);
+
+ gcal_event_remove_instance (main_event, event);
+
+ e_cal_client_modify_object (gcal_calendar_get_client (calendar),
+ e_cal_component_get_icalcomponent (component),
+ (ECalObjModType) GCAL_RECURRENCE_MOD_ALL,
+ E_CAL_OPERATION_FLAG_NONE,
+ NULL,
+ on_event_updated,
+ g_object_ref (component));
+ }
+
g_free (rid);
GCAL_EXIT;
diff --git a/src/core/gcal-timeline.c b/src/core/gcal-timeline.c
index dcec4cb3..fbad9fc6 100644
--- a/src/core/gcal-timeline.c
+++ b/src/core/gcal-timeline.c
@@ -679,7 +679,8 @@ timeline_source_dispatch (GSource *source,
if (subscriber)
{
- add_event_to_subscriber (subscriber, event);
+ if (!gcal_event_get_excluded (event))
+ add_event_to_subscriber (subscriber, event);
g_hash_table_remove (self->queued_adds, subscriber_event_id);
}
break;
@@ -703,7 +704,13 @@ timeline_source_dispatch (GSource *source,
}
if (subscriber)
- update_subscriber_event (subscriber, event);
+ {
+
+ if (!gcal_event_get_excluded (event))
+ update_subscriber_event (subscriber, event);
+ else
+ remove_event_from_subscriber (subscriber, event);
+ }
}
break;