[gnome-calendar/gbsneto/recurring-event-editing-fixes: 17/18] event-editor/dialog: Properly handle editing recurrent events




commit 92cb50a6f21378f04abe07504db7b92bc6ef5ed4
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Mon Oct 17 16:34:40 2022 -0300

    event-editor/dialog: Properly handle editing recurrent events
    
    When a recurrent event is edited, we now are able to only offer the
    MOD_ALL option when it actually will work. However, we're still left
    with the problem that we end up applying the instance-specific data
    onto the main event, through an old hack.
    
    The views already aren't able to offer the MOD_ALL property, since
    they all change the dates of events, but GcalEventEditorDialog can,
    and it must handle that properly.
    
    For now, do the simplest possible approach, which is: retrive the
    template event and apply all properties that can be applied to it,
    without letting the start and end days leak into it. We already only
    allow passing MOD_ALL on situations where the dates aren't really
    modified, so it should be safe.
    
    Fixes https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/882

 src/gui/event-editor/gcal-event-editor-dialog.c | 119 +++++++++++++++++++++++-
 1 file changed, 116 insertions(+), 3 deletions(-)
---
diff --git a/src/gui/event-editor/gcal-event-editor-dialog.c b/src/gui/event-editor/gcal-event-editor-dialog.c
index 6c3527db..40b1d16e 100644
--- a/src/gui/event-editor/gcal-event-editor-dialog.c
+++ b/src/gui/event-editor/gcal-event-editor-dialog.c
@@ -207,6 +207,64 @@ clear_and_hide_dialog (GcalEventEditorDialog *self)
   gtk_widget_hide (GTK_WIDGET (self));
 }
 
+static void
+apply_event_properties_to_template_event (GcalEvent *template_event,
+                                          GcalEvent *event)
+{
+  g_autoptr (GDateTime) start_date = NULL;
+  g_autoptr (GDateTime) end_date = NULL;
+  GDateTime *template_start_date;
+  GDateTime *event_start_date;
+  GDateTime *template_end_date;
+  GDateTime *event_end_date;
+  gboolean was_all_day;
+  gboolean is_all_day;
+
+  is_all_day = gcal_event_get_all_day (event);
+  was_all_day = gcal_event_get_all_day (template_event);
+
+  template_start_date = gcal_event_get_date_start (template_event);
+  template_end_date = gcal_event_get_date_end (template_event);
+  event_start_date = gcal_event_get_date_start (event);
+  event_end_date = gcal_event_get_date_end (event);
+
+  start_date = g_date_time_new (g_date_time_get_timezone (event_start_date),
+                                g_date_time_get_year (template_start_date),
+                                g_date_time_get_month (template_start_date),
+                                g_date_time_get_day_of_month (template_start_date),
+                                g_date_time_get_hour (event_start_date),
+                                g_date_time_get_minute (event_start_date),
+                                g_date_time_get_second (event_start_date));
+
+  end_date = g_date_time_new (g_date_time_get_timezone (event_end_date),
+                              g_date_time_get_year (template_end_date),
+                              g_date_time_get_month (template_end_date),
+                              g_date_time_get_day_of_month (template_end_date),
+                              g_date_time_get_hour (event_end_date),
+                              g_date_time_get_minute (event_end_date),
+                              g_date_time_get_second (event_end_date));
+
+  if (was_all_day != is_all_day)
+    {
+      g_autoptr (GDateTime) fake_end_date = NULL;
+
+      if (is_all_day)
+        fake_end_date = g_date_time_add_days (end_date, -1);
+      else
+        fake_end_date = g_date_time_add_days (end_date, 1);
+
+      gcal_set_date_time (&end_date, fake_end_date);
+    }
+
+  gcal_event_set_summary (template_event, gcal_event_get_summary (event));
+  gcal_event_set_location (template_event, gcal_event_get_location (event));
+  gcal_event_set_description (template_event, gcal_event_get_description (event));
+  gcal_event_set_recurrence (template_event, gcal_event_get_recurrence (event));
+  gcal_event_set_all_day (template_event, gcal_event_get_all_day (event));
+  gcal_event_set_date_start (template_event, start_date);
+  gcal_event_set_date_end (template_event, end_date);
+}
+
 
 /*
  * Callbacks
@@ -315,13 +373,68 @@ on_ask_recurrence_response_save_cb (GcalEvent             *event,
   GcalEventEditorDialog *self = GCAL_EVENT_EDITOR_DIALOG (user_data);
   GcalManager *manager;
 
-  if (mod_type == GCAL_RECURRENCE_MOD_NONE)
-    return;
+  GCAL_ENTRY;
 
   manager = gcal_context_get_manager (self->context);
 
-  gcal_manager_update_event (manager, self->event, mod_type);
+  switch (mod_type)
+    {
+    case GCAL_RECURRENCE_MOD_NONE:
+      GCAL_RETURN ();
+
+    case GCAL_RECURRENCE_MOD_ALL:
+      {
+        g_autoptr (GcalEvent) template_event = NULL;
+        g_autoptr (GError) error = NULL;
+        ECalComponentId *component_id;
+        ICalComponent *template_icomponent;
+        ECalComponent *template_ecomponent;
+        ECalComponent *component;
+        GcalCalendar *calendar;
+        ECalClient *client;
+
+        calendar = gcal_event_get_calendar (event);
+        client = gcal_calendar_get_client (calendar);
+        component = gcal_event_get_component (event);
+        component_id = e_cal_component_get_id (component);
+
+        e_cal_client_get_object_sync (client,
+                                      e_cal_component_id_get_uid (component_id),
+                                      NULL,
+                                      &template_icomponent,
+                                      NULL,
+                                      &error);
+
+        g_clear_pointer (&component_id, e_cal_component_id_free);
+
+        if (error)
+          {
+            g_warning ("Error updating event: %s", error->message);
+            break;
+          }
+
+        template_ecomponent = e_cal_component_new_from_icalcomponent (template_icomponent);
+        template_event = gcal_event_new (calendar, template_ecomponent, &error);
+        if (error)
+          {
+            g_warning ("Error updating event: %s", error->message);
+            break;
+          }
+
+        apply_event_properties_to_template_event (template_event, event);
+        gcal_manager_update_event (manager, template_event, mod_type);
+      }
+      break;
+
+    case GCAL_RECURRENCE_MOD_THIS_AND_FUTURE:
+    case GCAL_RECURRENCE_MOD_THIS_ONLY:
+      gcal_manager_update_event (manager, self->event, mod_type);
+      break;
+    }
+
   clear_and_hide_dialog (self);
+
+  GCAL_EXIT;
 }
 
 static void


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