diff options
author | Georges Basile Stavracas Neto <georges.stavracas@gmail.com> | 2022-10-17 16:34:40 -0300 |
---|---|---|
committer | Georges Basile Stavracas Neto <georges.stavracas@gmail.com> | 2022-10-17 23:37:13 -0300 |
commit | 502b381975181407f6b1b4ee60a95be139e34784 (patch) | |
tree | 7318ffe65f3a332814472c801a6ce6f62a954084 | |
parent | 102346534a0454a3985632d6ddbf71f4602bb1c1 (diff) | |
download | gnome-calendar-502b381975181407f6b1b4ee60a95be139e34784.tar.gz |
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
-rw-r--r-- | src/gui/event-editor/gcal-event-editor-dialog.c | 119 |
1 files 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 |