[evolution/gnome-43] I#2031 - VEVENT components should not contain both DTEND and DURATION



commit 584eb8704a28888cec2a8b030abbccc9c4430f24
Author: Milan Crha <mcrha redhat com>
Date:   Fri Sep 16 09:14:31 2022 +0200

    I#2031 - VEVENT components should not contain both DTEND and DURATION
    
    Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/2031

 src/calendar/gui/e-cal-model-calendar.c         |  1 +
 src/calendar/gui/e-cal-model.c                  | 18 +++++++---
 src/calendar/gui/e-comp-editor-event.c          | 46 ++++++++++++++++++++++++-
 src/calendar/gui/e-comp-editor-property-parts.c | 19 ++++++++++
 4 files changed, 79 insertions(+), 5 deletions(-)
---
diff --git a/src/calendar/gui/e-cal-model-calendar.c b/src/calendar/gui/e-cal-model-calendar.c
index e30791124e..ef1d50b303 100644
--- a/src/calendar/gui/e-cal-model-calendar.c
+++ b/src/calendar/gui/e-cal-model-calendar.c
@@ -107,6 +107,7 @@ set_dtend (ECalModel *model,
            gconstpointer value)
 {
        e_cal_model_update_comp_time (model, comp_data, value, I_CAL_DTEND_PROPERTY, 
i_cal_property_set_dtend, i_cal_property_new_dtend);
+       e_cal_util_component_remove_property_by_kind (comp_data->icalcomp, I_CAL_DURATION_PROPERTY, TRUE);
 }
 
 static void
diff --git a/src/calendar/gui/e-cal-model.c b/src/calendar/gui/e-cal-model.c
index 8389a62043..27eed6649b 100644
--- a/src/calendar/gui/e-cal-model.c
+++ b/src/calendar/gui/e-cal-model.c
@@ -4303,10 +4303,20 @@ e_cal_model_util_get_datetime_value (ECalModel *model,
        g_return_val_if_fail (get_time_func != NULL, NULL);
 
        prop = i_cal_component_get_first_property (comp_data->icalcomp, kind);
-       if (!prop)
-               return NULL;
-
-       tt = get_time_func (prop);
+       if (!prop) {
+               if (kind == I_CAL_DTEND_PROPERTY &&
+                   e_cal_util_component_has_property (comp_data->icalcomp, I_CAL_DURATION_PROPERTY) &&
+                   e_cal_util_component_has_property (comp_data->icalcomp, I_CAL_DTSTART_PROPERTY)) {
+                       /* Get the TZID from the DTSTART */
+                       prop = i_cal_component_get_first_property (comp_data->icalcomp, 
I_CAL_DTSTART_PROPERTY);
+                       /* The libical calculates the DTEND from the DTSTART+DURATION */
+                       tt = i_cal_component_get_dtend (comp_data->icalcomp);
+               } else {
+                       return NULL;
+               }
+       } else {
+               tt = get_time_func (prop);
+       }
 
        if (!tt || !i_cal_time_is_valid_time (tt) || i_cal_time_is_null_time (tt)) {
                g_clear_object (&prop);
diff --git a/src/calendar/gui/e-comp-editor-event.c b/src/calendar/gui/e-comp-editor-event.c
index 52db318b11..ab94e4589b 100644
--- a/src/calendar/gui/e-comp-editor-event.c
+++ b/src/calendar/gui/e-comp-editor-event.c
@@ -424,9 +424,51 @@ ece_event_fill_widgets (ECompEditor *comp_editor,
 
        if (dtstart && i_cal_time_is_valid_time (dtstart) && !i_cal_time_is_null_time (dtstart) &&
            (!dtend || !i_cal_time_is_valid_time (dtend) || i_cal_time_is_null_time (dtend))) {
+               gboolean dtend_set = FALSE;
                g_clear_object (&dtend);
                dtend = i_cal_time_clone (dtstart);
-               if (i_cal_time_is_date (dtstart))
+
+               if (e_cal_util_component_has_property (component, I_CAL_DURATION_PROPERTY)) {
+                       ICalProperty *prop;
+
+                       prop = i_cal_component_get_first_property (component, I_CAL_DURATION_PROPERTY);
+                       if (prop) {
+                               ICalDuration *duration;
+
+                               g_clear_object (&prop);
+
+                               duration = i_cal_component_get_duration (component);
+                               if (!duration || i_cal_duration_is_null_duration (duration) || 
i_cal_duration_is_bad_duration (duration)) {
+                                       g_clear_object (&duration);
+                               /* The DURATION shouldn't be negative, but just return DTSTART if it
+                                * is, i.e. assume it is 0. */
+                               } else if (!i_cal_duration_is_neg (duration)) {
+                                       guint dur_days, dur_hours, dur_minutes, dur_seconds;
+
+                                       /* If DTSTART is a DATE value, then we need to check if the DURATION
+                                        * includes any hours, minutes or seconds. If it does, we need to
+                                        * make the DTEND/DUE a DATE-TIME value. */
+                                       dur_days = i_cal_duration_get_days (duration) + (7 * 
i_cal_duration_get_weeks (duration));
+                                       dur_hours = i_cal_duration_get_hours (duration);
+                                       dur_minutes = i_cal_duration_get_minutes (duration);
+                                       dur_seconds = i_cal_duration_get_seconds (duration);
+
+                                       if (i_cal_time_is_date (dtend) && (
+                                           dur_hours != 0 || dur_minutes != 0 || dur_seconds != 0)) {
+                                               i_cal_time_set_is_date (dtend, FALSE);
+                                       }
+
+                                       /* Add on the DURATION. */
+                                       i_cal_time_adjust (dtend, dur_days, dur_hours, dur_minutes, 
dur_seconds);
+
+                                       dtend_set = TRUE;
+                               }
+
+                               g_clear_object (&duration);
+                       }
+               }
+
+               if (!dtend_set && i_cal_time_is_date (dtstart))
                        i_cal_time_adjust (dtend, 1, 0, 0, 0);
        }
 
@@ -579,6 +621,8 @@ ece_event_fill_component (ECompEditor *comp_editor,
 
                        i_cal_property_set_dtend (dtend_prop, dtend);
                        cal_comp_util_update_tzid_parameter (dtend_prop, dtend);
+
+                       e_cal_util_component_remove_property_by_kind (component, I_CAL_DURATION_PROPERTY, 
TRUE);
                }
 
                g_clear_object (&dtstart);
diff --git a/src/calendar/gui/e-comp-editor-property-parts.c b/src/calendar/gui/e-comp-editor-property-parts.c
index 62db93f900..f86092c3dc 100644
--- a/src/calendar/gui/e-comp-editor-property-parts.c
+++ b/src/calendar/gui/e-comp-editor-property-parts.c
@@ -1546,6 +1546,21 @@ enum {
        PROP_DTEND_SHORTEN_END
 };
 
+static void
+e_comp_editor_property_part_dtend_fill_component (ECompEditorPropertyPart *property_part,
+                                                 ICalComponent *component)
+{
+       ECompEditorPropertyPartClass *part_class;
+
+       part_class = E_COMP_EDITOR_PROPERTY_PART_CLASS (e_comp_editor_property_part_dtend_parent_class);
+       g_return_if_fail (part_class != NULL);
+       g_return_if_fail (part_class->fill_component != NULL);
+
+       part_class->fill_component (property_part, component);
+
+       e_cal_util_component_remove_property_by_kind (component, I_CAL_DURATION_PROPERTY, TRUE);
+}
+
 static void
 e_comp_editor_property_part_dtend_init (ECompEditorPropertyPartDtend *part_dtend)
 {
@@ -1627,6 +1642,7 @@ static void
 e_comp_editor_property_part_dtend_class_init (ECompEditorPropertyPartDtendClass *klass)
 {
        ECompEditorPropertyPartDatetimeClass *part_datetime_class;
+       ECompEditorPropertyPartClass *property_part_class;
        GObjectClass *object_class;
 
        part_datetime_class = E_COMP_EDITOR_PROPERTY_PART_DATETIME_CLASS (klass);
@@ -1635,6 +1651,9 @@ e_comp_editor_property_part_dtend_class_init (ECompEditorPropertyPartDtendClass
        part_datetime_class->i_cal_set_func = i_cal_property_set_dtend;
        part_datetime_class->i_cal_get_func = i_cal_property_get_dtend;
 
+       property_part_class = E_COMP_EDITOR_PROPERTY_PART_CLASS (klass);
+       property_part_class->fill_component = e_comp_editor_property_part_dtend_fill_component;
+
        object_class = G_OBJECT_CLASS (klass);
        object_class->get_property = e_comp_editor_property_part_dtend_get_property;
        object_class->set_property = e_comp_editor_property_part_dtend_set_property;


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