From 51c5063377bfa5d8d7440b236a1e752deccddf71 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Tue, 8 Jun 2021 18:10:12 +0200 Subject: [PATCH] I#1527 - Calendar: Implement "Delete this and future occurrences" Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/1527 --- data/ui/evolution-calendars.ui | 2 ++ src/calendar/gui/e-calendar-view.c | 30 ++++++++++++++----- src/calendar/gui/e-calendar-view.h | 3 +- .../calendar/e-cal-base-shell-content.h | 3 +- src/modules/calendar/e-cal-shell-content.c | 6 ++++ .../calendar/e-cal-shell-view-actions.c | 26 +++++++++++++++- .../calendar/e-cal-shell-view-actions.h | 2 ++ src/modules/calendar/e-cal-shell-view.c | 11 +++++++ 8 files changed, 72 insertions(+), 11 deletions(-) diff --git a/data/ui/evolution-calendars.ui b/data/ui/evolution-calendars.ui index e33af2e726..4349c68e56 100644 --- a/data/ui/evolution-calendars.ui +++ b/data/ui/evolution-calendars.ui @@ -14,6 +14,7 @@ + @@ -128,6 +129,7 @@ + diff --git a/src/calendar/gui/e-calendar-view.c b/src/calendar/gui/e-calendar-view.c index 540a73f4f7..867e77c426 100644 --- a/src/calendar/gui/e-calendar-view.c +++ b/src/calendar/gui/e-calendar-view.c @@ -113,6 +113,8 @@ calendar_view_add_retract_data (ECalComponent *comp, if (mod == E_CAL_OBJ_MOD_ALL) prop = i_cal_property_new_x ("All"); + else if (mod == E_CAL_OBJ_MOD_THIS_AND_FUTURE) + prop = i_cal_property_new_x ("ThisAndFuture"); else prop = i_cal_property_new_x ("This"); i_cal_property_set_x_name (prop, "X-EVOLUTION-RECUR-MOD"); @@ -154,7 +156,8 @@ calendar_view_check_for_retract (ECalComponent *comp, static void calendar_view_delete_event (ECalendarView *cal_view, ECalendarViewEvent *event, - gboolean only_occurrence) + gboolean only_occurrence, + ECalObjModType mod) { ECalModel *model; ECalComponent *comp; @@ -193,7 +196,7 @@ calendar_view_delete_event (ECalendarView *cal_view, if (retract) { ICalComponent *icomp; - calendar_view_add_retract_data (comp, retract_comment, E_CAL_OBJ_MOD_ALL); + calendar_view_add_retract_data (comp, retract_comment, mod); icomp = e_cal_component_get_icalcomponent (comp); i_cal_component_set_method (icomp, I_CAL_METHOD_CANCEL); @@ -223,9 +226,17 @@ calendar_view_delete_event (ECalendarView *cal_view, i_cal_time_set_is_date (e_cal_component_datetime_get_value (dtstart), 1); /* set the recurrence ID of the object we send */ - range = e_cal_component_range_new_take (E_CAL_COMPONENT_RANGE_SINGLE, dtstart); + range = e_cal_component_range_new_take (mod == E_CAL_OBJ_MOD_THIS_AND_FUTURE ? + E_CAL_COMPONENT_RANGE_THISFUTURE : E_CAL_COMPONENT_RANGE_SINGLE, dtstart); e_cal_component_set_recurid (comp, range); + e_cal_component_range_free (range); + } else if (only_occurrence && mod == E_CAL_OBJ_MOD_THIS_AND_FUTURE) { + ECalComponentRange *range; + + range = e_cal_component_get_recurid (comp); + e_cal_component_range_set_kind (range, E_CAL_COMPONENT_RANGE_THISFUTURE); + e_cal_component_set_recurid (comp, range); e_cal_component_range_free (range); } @@ -243,7 +254,7 @@ calendar_view_delete_event (ECalendarView *cal_view, if (only_occurrence) { if (e_cal_component_is_instance (comp)) { - e_cal_ops_remove_component (model, client, uid, rid, E_CAL_OBJ_MOD_THIS, FALSE); + e_cal_ops_remove_component (model, client, uid, rid, mod, FALSE); } else { ICalTime *instance_rid; ICalTimezone *zone = NULL; @@ -271,7 +282,7 @@ calendar_view_delete_event (ECalendarView *cal_view, instance_rid = i_cal_time_new_from_timet_with_zone ( instance_start, TRUE, zone ? zone : i_cal_timezone_get_utc_timezone ()); - e_cal_util_remove_instances_ex (icalcomp, instance_rid, E_CAL_OBJ_MOD_THIS, + e_cal_util_remove_instances_ex (icalcomp, instance_rid, mod, e_cal_client_tzlookup_cb, client); e_cal_ops_modify_component (model, client, icalcomp, E_CAL_OBJ_MOD_THIS, E_CAL_OPS_SEND_FLAG_DONT_SEND); @@ -1114,7 +1125,7 @@ calendar_view_delete_selection (ESelectable *selectable) if (event == NULL) continue; - calendar_view_delete_event (cal_view, event, FALSE); + calendar_view_delete_event (cal_view, event, FALSE, E_CAL_OBJ_MOD_ALL); } g_list_free (selected); @@ -1567,18 +1578,21 @@ e_calendar_view_update_query (ECalendarView *cal_view) } void -e_calendar_view_delete_selected_occurrence (ECalendarView *cal_view) +e_calendar_view_delete_selected_occurrence (ECalendarView *cal_view, + ECalObjModType mod) { ECalendarViewEvent *event; GList *selected; + g_return_if_fail (mod == E_CAL_OBJ_MOD_THIS || mod == E_CAL_OBJ_MOD_THIS_AND_FUTURE); + selected = e_calendar_view_get_selected_events (cal_view); if (!selected) return; event = (ECalendarViewEvent *) selected->data; if (is_comp_data_valid (event)) { - calendar_view_delete_event (cal_view, event, TRUE); + calendar_view_delete_event (cal_view, event, TRUE, mod); } g_list_free (selected); diff --git a/src/calendar/gui/e-calendar-view.h b/src/calendar/gui/e-calendar-view.h index 3ec133d1ed..ba9cfaac53 100644 --- a/src/calendar/gui/e-calendar-view.h +++ b/src/calendar/gui/e-calendar-view.h @@ -226,7 +226,8 @@ void e_calendar_view_precalc_visible_time_range void e_calendar_view_update_query (ECalendarView *cal_view); void e_calendar_view_delete_selected_occurrence - (ECalendarView *cal_view); + (ECalendarView *cal_view, + ECalObjModType mod); ECompEditor * e_calendar_view_open_event_with_flags (ECalendarView *cal_view, ECalClient *client, diff --git a/src/modules/calendar/e-cal-base-shell-content.h b/src/modules/calendar/e-cal-base-shell-content.h index 541f77d000..d27f4b8ff2 100644 --- a/src/modules/calendar/e-cal-base-shell-content.h +++ b/src/modules/calendar/e-cal-base-shell-content.h @@ -64,7 +64,8 @@ enum { E_CAL_BASE_SHELL_CONTENT_SELECTION_HAS_COMPLETE = 1 << 9, E_CAL_BASE_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE = 1 << 10, E_CAL_BASE_SHELL_CONTENT_SELECTION_HAS_URL = 1 << 11, - E_CAL_BASE_SHELL_CONTENT_SELECTION_IS_ATTENDEE = 1 << 12 + E_CAL_BASE_SHELL_CONTENT_SELECTION_IS_ATTENDEE = 1 << 12, + E_CAL_BASE_SHELL_CONTENT_SELECTION_THIS_AND_FUTURE_SUPPORTED = 1 << 13 }; struct _ECalBaseShellContent { diff --git a/src/modules/calendar/e-cal-shell-content.c b/src/modules/calendar/e-cal-shell-content.c index ee926390d2..80f699741e 100644 --- a/src/modules/calendar/e-cal-shell-content.c +++ b/src/modules/calendar/e-cal-shell-content.c @@ -968,6 +968,7 @@ cal_shell_content_check_state (EShellContent *shell_content) gboolean selection_is_attendee = FALSE; gboolean selection_is_recurring = FALSE; gboolean selection_can_delegate = FALSE; + gboolean this_and_future_supported = FALSE; guint32 state = 0; GList *selected; GList *link; @@ -1048,6 +1049,9 @@ cal_shell_content_check_state (EShellContent *shell_content) e_client_check_capability ( E_CLIENT (client), capability); + this_and_future_supported = !e_client_check_capability ( + E_CLIENT (client), E_CAL_STATIC_CAPABILITY_NO_THISANDFUTURE); + icomp_is_delegated = user_email != NULL && cal_shell_content_icomp_is_delegated (icomp, user_email); @@ -1086,6 +1090,8 @@ cal_shell_content_check_state (EShellContent *shell_content) state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_IS_RECURRING; if (selection_can_delegate) state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_CAN_DELEGATE; + if (this_and_future_supported) + state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_THIS_AND_FUTURE_SUPPORTED; return state; } diff --git a/src/modules/calendar/e-cal-shell-view-actions.c b/src/modules/calendar/e-cal-shell-view-actions.c index 4e7a0b94ba..f433abb04a 100644 --- a/src/modules/calendar/e-cal-shell-view-actions.c +++ b/src/modules/calendar/e-cal-shell-view-actions.c @@ -722,7 +722,20 @@ action_event_delete_occurrence_cb (GtkAction *action, cal_shell_content = cal_shell_view->priv->cal_shell_content; calendar_view = e_cal_shell_content_get_current_calendar_view (cal_shell_content); - e_calendar_view_delete_selected_occurrence (calendar_view); + e_calendar_view_delete_selected_occurrence (calendar_view, E_CAL_OBJ_MOD_THIS); +} + +static void +action_event_delete_occurrence_this_and_future_cb (GtkAction *action, + ECalShellView *cal_shell_view) +{ + ECalShellContent *cal_shell_content; + ECalendarView *calendar_view; + + cal_shell_content = cal_shell_view->priv->cal_shell_content; + calendar_view = e_cal_shell_content_get_current_calendar_view (cal_shell_content); + + e_calendar_view_delete_selected_occurrence (calendar_view, E_CAL_OBJ_MOD_THIS_AND_FUTURE); } static void @@ -1426,6 +1439,13 @@ static GtkActionEntry calendar_entries[] = { N_("Delete this occurrence"), G_CALLBACK (action_event_delete_occurrence_cb) }, + { "event-delete-occurrence-this-and-future", + "edit-delete", + N_("Delete This and F_uture Occurrences"), + NULL, + N_("Delete this and any future occurrences"), + G_CALLBACK (action_event_delete_occurrence_this_and_future_cb) }, + { "event-delete-occurrence-all", "edit-delete", N_("Delete All Occ_urrences"), @@ -1649,6 +1669,10 @@ static EPopupActionEntry calendar_popup_entries[] = { NULL, "event-delete-occurrence" }, + { "event-popup-delete-occurrence-this-and-future", + NULL, + "event-delete-occurrence-this-and-future" }, + { "event-popup-delete-occurrence-all", NULL, "event-delete-occurrence-all" }, diff --git a/src/modules/calendar/e-cal-shell-view-actions.h b/src/modules/calendar/e-cal-shell-view-actions.h index ea47a0ce02..a8374b211d 100644 --- a/src/modules/calendar/e-cal-shell-view-actions.h +++ b/src/modules/calendar/e-cal-shell-view-actions.h @@ -80,6 +80,8 @@ E_SHELL_WINDOW_ACTION ((window), "event-delete") #define E_SHELL_WINDOW_ACTION_EVENT_DELETE_OCCURRENCE(window) \ E_SHELL_WINDOW_ACTION ((window), "event-delete-occurrence") +#define E_SHELL_WINDOW_ACTION_EVENT_DELETE_OCCURRENCE_THIS_AND_FUTURE(window) \ + E_SHELL_WINDOW_ACTION ((window), "event-delete-occurrence-this-and-future") #define E_SHELL_WINDOW_ACTION_EVENT_DELETE_OCCURRENCE_ALL(window) \ E_SHELL_WINDOW_ACTION ((window), "event-delete-occurrence-all") #define E_SHELL_WINDOW_ACTION_EVENT_EDIT_AS_NEW(window) \ diff --git a/src/modules/calendar/e-cal-shell-view.c b/src/modules/calendar/e-cal-shell-view.c index 1c8bb6ed9d..5684f1fc14 100644 --- a/src/modules/calendar/e-cal-shell-view.c +++ b/src/modules/calendar/e-cal-shell-view.c @@ -283,6 +283,7 @@ cal_shell_view_update_actions (EShellView *shell_view) gboolean all_sources_selected; gboolean clicked_source_is_primary; gboolean clicked_source_is_collection; + gboolean this_and_future_supported; /* Chain up to parent's update_actions() method. */ E_SHELL_VIEW_CLASS (e_cal_shell_view_parent_class)-> @@ -335,6 +336,8 @@ cal_shell_view_update_actions (EShellView *shell_view) (state & E_CAL_BASE_SHELL_CONTENT_SELECTION_IS_RECURRING); selection_can_delegate = (state & E_CAL_BASE_SHELL_CONTENT_SELECTION_CAN_DELEGATE); + this_and_future_supported = + (state & E_CAL_BASE_SHELL_CONTENT_SELECTION_THIS_AND_FUTURE_SUPPORTED); shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); state = e_shell_sidebar_check_state (shell_sidebar); @@ -436,6 +439,14 @@ cal_shell_view_update_actions (EShellView *shell_view) selection_is_recurring; gtk_action_set_sensitive (action, sensitive); + action = ACTION (EVENT_DELETE_OCCURRENCE_THIS_AND_FUTURE); + sensitive = + single_event_selected && + selection_is_editable && + selection_is_recurring && + this_and_future_supported; + gtk_action_set_sensitive (action, sensitive); + action = ACTION (EVENT_DELETE_OCCURRENCE_ALL); sensitive = any_events_selected &&