[evolution/gnome-3-36] ews-I#99 - All-day events date shown by one day off



commit 8c8506491395bd7108caeb8cfec00848378ed33e
Author: Milan Crha <mcrha redhat com>
Date:   Wed May 13 17:30:06 2020 +0200

    ews-I#99 - All-day events date shown by one day off
    
    Related to https://gitlab.gnome.org/GNOME/evolution-ews/-/issues/99

 src/calendar/gui/comp-util.c           | 97 ++++++++++++++++++++++++++++++++++
 src/calendar/gui/comp-util.h           |  7 +++
 src/calendar/gui/e-cal-ops.c           | 19 ++++++-
 src/calendar/gui/e-comp-editor-event.c | 15 ++----
 4 files changed, 125 insertions(+), 13 deletions(-)
---
diff --git a/src/calendar/gui/comp-util.c b/src/calendar/gui/comp-util.c
index 4fb3dc3092..d285bf9c21 100644
--- a/src/calendar/gui/comp-util.c
+++ b/src/calendar/gui/comp-util.c
@@ -1732,3 +1732,100 @@ cal_comp_util_get_status_list_for_kind (ICalComponentKind kind)
 
        return g_list_reverse (items);
 }
+
+/**
+ * cal_comp_util_ensure_allday_timezone:
+ * @itime: an #ICalTime to update
+ * @zone: (nullable): an #ICalTimezone to set, or %NULL for UTC
+ *
+ * Changes DATE value of @itime to DATETIME using the @zone.
+ * The @itime is not converted to the @zone, the @zone is
+ * assigned to it.
+ *
+ * Returns: whether made any change
+ *
+ * Since: 3.36.3
+ **/
+gboolean
+cal_comp_util_ensure_allday_timezone (ICalTime *itime,
+                                     ICalTimezone *zone)
+{
+       g_return_val_if_fail (I_CAL_IS_TIME (itime), FALSE);
+
+       if (i_cal_time_is_date (itime)) {
+               if (!zone)
+                       zone = i_cal_timezone_get_utc_timezone ();
+
+               i_cal_time_set_is_date (itime, FALSE);
+               i_cal_time_set_time (itime, 0, 0, 0);
+               i_cal_time_set_timezone (itime, zone);
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static void
+ensure_allday_timezone_property (ICalComponent *icomp,
+                                ICalTimezone *zone,
+                                ICalPropertyKind prop_kind,
+                                ICalTime *(* get_func) (ICalComponent *icomp),
+                                void (* set_func) (ICalComponent *icomp,
+                                                   ICalTime *dtvalue))
+{
+       ICalProperty *prop;
+
+       g_return_if_fail (I_CAL_IS_COMPONENT (icomp));
+       g_return_if_fail (get_func != NULL);
+       g_return_if_fail (set_func != NULL);
+
+       prop = i_cal_component_get_first_property (icomp, prop_kind);
+
+       if (prop) {
+               ICalTime *dtvalue;
+
+               dtvalue = get_func (icomp);
+
+               if (dtvalue && cal_comp_util_ensure_allday_timezone (dtvalue, zone)) {
+                       /* Remove the VALUE parameter, to correspond to the actual value being set */
+                       i_cal_property_remove_parameter_by_kind (prop, I_CAL_VALUE_PARAMETER);
+               }
+
+               set_func (icomp, dtvalue);
+               cal_comp_util_update_tzid_parameter (prop, dtvalue);
+
+               g_clear_object (&dtvalue);
+               g_clear_object (&prop);
+       }
+}
+
+/**
+ * cal_comp_util_maybe_ensure_allday_timezone_properties:
+ * @client: (nullable): an #ECalClient, or NULL, to change it always
+ * @icomp: an #ICalComponent to update
+ * @zone: (nullable): an #ICalTimezone to eventually set, or %NULL for floating time
+ *
+ * When the @client is not specified, or when it has set %E_CAL_STATIC_CAPABILITY_ALL_DAY_EVENT_AS_TIME,
+ * calls cal_comp_util_ensure_allday_timezone() for DTSTART
+ * and DTEND properties, if such exist in the @icomp, and updates
+ * those accordingly.
+ *
+ * Since: 3.36.3
+ **/
+void
+cal_comp_util_maybe_ensure_allday_timezone_properties (ECalClient *client,
+                                                      ICalComponent *icomp,
+                                                      ICalTimezone *zone)
+{
+       if (client)
+               g_return_if_fail (E_IS_CAL_CLIENT (client));
+
+       g_return_if_fail (I_CAL_IS_COMPONENT (icomp));
+
+       if (client && !e_client_check_capability (E_CLIENT (client), 
E_CAL_STATIC_CAPABILITY_ALL_DAY_EVENT_AS_TIME))
+               return;
+
+       ensure_allday_timezone_property (icomp, zone, I_CAL_DTSTART_PROPERTY, i_cal_component_get_dtstart, 
i_cal_component_set_dtstart);
+       ensure_allday_timezone_property (icomp, zone, I_CAL_DTEND_PROPERTY, i_cal_component_get_dtend, 
i_cal_component_set_dtend);
+}
diff --git a/src/calendar/gui/comp-util.h b/src/calendar/gui/comp-util.h
index c1ee0a7e04..1c9702deea 100644
--- a/src/calendar/gui/comp-util.h
+++ b/src/calendar/gui/comp-util.h
@@ -165,4 +165,11 @@ ICalPropertyStatus
                                                 gpointer user_data);
 GList *                cal_comp_util_get_status_list_for_kind /* const gchar * */
                                                (ICalComponentKind kind);
+gboolean       cal_comp_util_ensure_allday_timezone
+                                               (ICalTime *itime,
+                                                ICalTimezone *zone);
+void           cal_comp_util_maybe_ensure_allday_timezone_properties
+                                               (ECalClient *client,
+                                                ICalComponent *icomp,
+                                                ICalTimezone *zone);
 #endif
diff --git a/src/calendar/gui/e-cal-ops.c b/src/calendar/gui/e-cal-ops.c
index d735b24ca1..609b705423 100644
--- a/src/calendar/gui/e-cal-ops.c
+++ b/src/calendar/gui/e-cal-ops.c
@@ -215,6 +215,9 @@ e_cal_ops_create_component (ECalModel *model,
        bod->user_data = user_data;
        bod->user_data_free = user_data_free;
 
+       cal_comp_util_maybe_ensure_allday_timezone_properties (client, bod->icomp,
+               e_cal_model_get_timezone (model));
+
        prop = i_cal_component_get_first_property (bod->icomp, I_CAL_CLASS_PROPERTY);
        if (!prop || i_cal_property_get_class (prop) == I_CAL_CLASS_NONE) {
                ICalProperty_Class ical_class = I_CAL_CLASS_PUBLIC;
@@ -335,6 +338,9 @@ e_cal_ops_modify_component (ECalModel *model,
        bod->send_flags = send_flags;
        bod->is_modify = TRUE;
 
+       cal_comp_util_maybe_ensure_allday_timezone_properties (client, bod->icomp,
+               e_cal_model_get_timezone (model));
+
        display_name = e_util_get_source_full_name (e_cal_model_get_registry (model), source);
        cancellable = e_cal_data_model_submit_thread_job (data_model, description, alert_ident,
                display_name, cal_ops_modify_component_thread,
@@ -538,6 +544,7 @@ e_cal_ops_delete_ecalmodel_components (ECalModel *model,
 static gboolean
 cal_ops_create_comp_with_new_uid_sync (ECalClient *cal_client,
                                       ICalComponent *icomp,
+                                      ICalTimezone *zone,
                                       GCancellable *cancellable,
                                       GError **error)
 {
@@ -554,6 +561,8 @@ cal_ops_create_comp_with_new_uid_sync (ECalClient *cal_client,
        i_cal_component_set_uid (clone, uid);
        g_free (uid);
 
+       cal_comp_util_maybe_ensure_allday_timezone_properties (cal_client, clone, zone);
+
        success = e_cal_client_create_object_sync (cal_client, clone, E_CAL_OPERATION_FLAG_NONE, NULL, 
cancellable, error);
 
        g_clear_object (&clone);
@@ -565,6 +574,7 @@ typedef struct {
        ECalModel *model;
        ICalComponent *icomp;
        ICalComponentKind kind;
+       ICalTimezone *zone;
        const gchar *extension_name;
        gboolean success;
 } PasteComponentsData;
@@ -580,6 +590,7 @@ paste_components_data_free (gpointer ptr)
 
                g_clear_object (&pcd->model);
                g_clear_object (&pcd->icomp);
+               g_clear_object (&pcd->zone);
                g_slice_free (PasteComponentsData, pcd);
        }
 }
@@ -656,7 +667,7 @@ cal_ops_update_components_thread (EAlertSinkThreadJobData *job_data,
                for (subcomp = i_cal_component_get_first_component (pcd->icomp, pcd->kind);
                     subcomp && !g_cancellable_is_cancelled (cancellable) && success;
                     g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (pcd->icomp, 
pcd->kind)) {
-                       if (!cal_ops_create_comp_with_new_uid_sync (cal_client, subcomp, cancellable, error)) 
{
+                       if (!cal_ops_create_comp_with_new_uid_sync (cal_client, subcomp, pcd->zone, 
cancellable, error)) {
                                success = FALSE;
                                break;
                        }
@@ -666,7 +677,7 @@ cal_ops_update_components_thread (EAlertSinkThreadJobData *job_data,
 
                g_clear_object (&subcomp);
        } else if (i_cal_component_isa (pcd->icomp) == pcd->kind) {
-               success = cal_ops_create_comp_with_new_uid_sync (cal_client, pcd->icomp, cancellable, error);
+               success = cal_ops_create_comp_with_new_uid_sync (cal_client, pcd->icomp, pcd->zone, 
cancellable, error);
                any_copied = success;
        }
 
@@ -772,9 +783,13 @@ e_cal_ops_paste_components (ECalModel *model,
        pcd->model = g_object_ref (model);
        pcd->icomp = icomp;
        pcd->kind = kind;
+       pcd->zone = e_cal_model_get_timezone (model);
        pcd->extension_name = extension_name;
        pcd->success = FALSE;
 
+       if (pcd->zone)
+               g_object_ref (pcd->zone);
+
        data_model = e_cal_model_get_data_model (model);
 
        cancellable = e_cal_data_model_submit_thread_job (data_model, description, alert_ident,
diff --git a/src/calendar/gui/e-comp-editor-event.c b/src/calendar/gui/e-comp-editor-event.c
index 0c566d056b..bd9d13a3fc 100644
--- a/src/calendar/gui/e-comp-editor-event.c
+++ b/src/calendar/gui/e-comp-editor-event.c
@@ -549,20 +549,13 @@ ece_event_fill_component (ECompEditor *comp_editor,
                        if (ece_event_client_needs_all_day_as_time (comp_editor)) {
                                ECompEditorEvent *event_editor = E_COMP_EDITOR_EVENT (comp_editor);
                                GtkWidget *timezone_entry;
-
-                               i_cal_time_set_is_date (dtstart, FALSE);
-                               i_cal_time_set_time (dtstart, 0, 0, 0);
-
-                               i_cal_time_set_is_date (dtend, FALSE);
-                               i_cal_time_set_time (dtend, 0, 0, 0);
+                               ICalTimezone *zone;
 
                                timezone_entry = e_comp_editor_property_part_get_edit_widget 
(event_editor->priv->timezone);
+                               zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (timezone_entry));
 
-                               i_cal_time_set_timezone (dtstart, e_timezone_entry_get_timezone 
(E_TIMEZONE_ENTRY (timezone_entry)));
-                               if (!i_cal_time_get_timezone (dtstart))
-                                       i_cal_time_set_timezone (dtstart, i_cal_timezone_get_utc_timezone ());
-
-                               i_cal_time_set_timezone (dtend, i_cal_time_get_timezone (dtstart));
+                               cal_comp_util_ensure_allday_timezone (dtstart, zone);
+                               cal_comp_util_ensure_allday_timezone (dtend, zone);
 
                                set_dtstart = TRUE;
                        }


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