[gnome-calendar/fix-shifting-events: 2/2] core: Handle exceptions in event list




commit 2b33aa28713a00405ce80514d84648c0ecfda4b5
Author: Ray Strode <rstrode redhat com>
Date:   Fri Oct 14 17:09:28 2022 -0400

    core: Handle exceptions in event list
    
    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.

 src/core/gcal-event.c    | 81 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/core/gcal-event.h    |  8 +++--
 src/core/gcal-manager.c  | 18 +++++++++++
 src/core/gcal-timeline.c | 11 +++++--
 4 files changed, 114 insertions(+), 4 deletions(-)
---
diff --git a/src/core/gcal-event.c b/src/core/gcal-event.c
index 88087337..5d8e480f 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            hidden;
 
   /* A map of GcalAlarmType */
   GHashTable         *alarms;
@@ -137,11 +138,41 @@ static GParamSpec* properties[N_PROPS] = { NULL, };
  * Auxiliary methods
  */
 
+static void
+check_if_hidden (GcalEvent  *self)
+{
+  ECalComponentDateTime *date;
+  GSList *exceptions, *node;
+
+  GCAL_TRACE_MSG ("Checking if event should be hidden");
+
+  self->hidden = FALSE;
+
+  date = e_cal_component_get_dtstart (self->component);
+  exceptions = e_cal_component_get_exdates (self->component);
+  for (node = exceptions; node != NULL; node = node->next)
+    {
+      ECalComponentDateTime *exception = node->data;
+
+      if (i_cal_time_compare (e_cal_component_datetime_get_value (exception),
+                              e_cal_component_datetime_get_value (date)) == 0)
+        {
+          self->hidden = TRUE;
+          break;
+        }
+    }
+  g_slist_free_full (exceptions, 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_hidden (self);
 }
 
 static GTimeZone*
@@ -392,6 +423,8 @@ setup_component (GcalEvent  *self,
       g_clear_object (&date);
     }
 
+  check_if_hidden (self);
+
   /* Summary */
   text = e_cal_component_get_summary (self->component);
   if (text && e_cal_component_text_get_value (text))
@@ -1001,6 +1034,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,11 +1274,25 @@ 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_hidden (self);
     }
 
   return self->range;
 }
 
+/**
+ * gcal_event_get_hidden:
+ * @self: a #GcalEvent
+ *
+ * Retrieves whether or not the event has been hidden by an exdate.
+ */
+gboolean
+gcal_event_get_hidden (GcalEvent *self)
+{
+  return self->hidden;
+}
+
 /**
  * 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_hidden (self);
 }
 
 /**
diff --git a/src/core/gcal-event.h b/src/core/gcal-event.h
index c124bc55..58e83ee8 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_hidden                       (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..c6e4b4e6 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_hidden (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_hidden (event))
+                  update_subscriber_event (subscriber, event);
+                else
+                  remove_event_from_subscriber (subscriber, event);
+              }
           }
           break;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]