[gnome-calendar/gbsneto/importer-timezones] import-dialog: Also import timezones




commit 2697dac4607e9727967402015d495f21501b18ac
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Wed Dec 8 12:03:49 2021 -0300

    import-dialog: Also import timezones
    
    Some calendars provide custom timezones, and set events to
    them. We need to account for that when importing calendars.
    
    Original patch proposed by Milan Crha.
    
    Fixes https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/444

 src/gui/importer/gcal-import-dialog.c   | 97 ++++++++++++++++++++++++++++++---
 src/gui/importer/gcal-import-file-row.c | 44 +++++++++++++++
 src/gui/importer/gcal-import-file-row.h |  1 +
 3 files changed, 133 insertions(+), 9 deletions(-)
---
diff --git a/src/gui/importer/gcal-import-dialog.c b/src/gui/importer/gcal-import-dialog.c
index ef37e6bf..12bf8ce5 100644
--- a/src/gui/importer/gcal-import-dialog.c
+++ b/src/gui/importer/gcal-import-dialog.c
@@ -29,6 +29,13 @@
 
 #include <glib/gi18n.h>
 
+typedef struct
+{
+  ECalClient         *client;
+  GSList             *components;
+  GSList             *zones;
+} ImportData;
+
 struct _GcalImportDialog
 {
   HdyWindow           parent;
@@ -84,6 +91,20 @@ static GParamSpec *properties [N_PROPS];
  * Auxiliary methods
  */
 
+static void
+import_data_free (gpointer data)
+{
+  ImportData *import_data = data;
+
+  if (!import_data)
+    return;
+
+  g_clear_object (&import_data->client);
+  g_slist_free_full (import_data->components, g_object_unref);
+  g_slist_free_full (import_data->zones, g_object_unref);
+  g_free (import_data);
+}
+
 static GtkWidget*
 create_calendar_row (GcalManager  *manager,
                      GcalCalendar *calendar)
@@ -252,7 +273,7 @@ on_events_created_cb (GObject      *source_object,
 
   self = GCAL_IMPORT_DIALOG (user_data);
 
-  e_cal_client_create_objects_finish (E_CAL_CLIENT (source_object), result, NULL, &error);
+  g_task_propagate_boolean (G_TASK (result), &error);
   if (error)
     g_warning ("Error creating events: %s", error->message);
 
@@ -281,14 +302,54 @@ on_cancel_button_clicked_cb (GtkButton        *button,
   gtk_widget_destroy (GTK_WIDGET (self));
 }
 
+static void
+import_data_thread (GTask        *task,
+                    gpointer      source_object,
+                    gpointer      task_data,
+                    GCancellable *cancellable)
+{
+  ImportData *id = task_data;
+  GError *error = NULL;
+  GSList *uids = NULL;
+  GSList *l = NULL;
+
+  for (l = id->zones; l && !g_cancellable_is_cancelled (cancellable); l = l->next)
+    {
+      g_autoptr (GError) local_error = NULL;
+      ICalTimezone *zone = l->data;
+
+      e_cal_client_add_timezone_sync (id->client, zone, cancellable, &local_error);
+
+      if (local_error)
+        g_warning ("Import: Failed to add timezone: %s", local_error->message);
+    }
+
+  e_cal_client_create_objects_sync (id->client,
+                                    id->components,
+                                    E_CAL_OPERATION_FLAG_NONE,
+                                    &uids,
+                                    cancellable,
+                                    &error);
+
+  g_slist_free_full (uids, g_free);
+
+  if (error)
+    g_task_return_error (task, error);
+  else
+    g_task_return_boolean (task, TRUE);
+}
+
 static void
 on_import_button_clicked_cb (GtkButton        *button,
                              GcalImportDialog *self)
 {
   g_autoptr (GList) children = NULL;
+  g_autoptr (GTask) task = NULL;
   GcalCalendar *calendar;
+  ImportData *import_data;
   ECalClient *client;
-  GSList *slist;
+  GSList *slist = NULL;
+  GSList *zones = NULL;
   GList *l;
 
   GCAL_ENTRY;
@@ -302,6 +363,7 @@ on_import_button_clicked_cb (GtkButton        *button,
     {
       GcalImportFileRow *row = l->data;
       GPtrArray *ical_components;
+      GPtrArray *ical_timezones;
       guint i;
 
       ical_components = gcal_import_file_row_get_ical_components (row);
@@ -309,7 +371,20 @@ on_import_button_clicked_cb (GtkButton        *button,
         continue;
 
       for (i = 0; i < ical_components->len; i++)
-        slist = g_slist_prepend (slist, g_ptr_array_index (ical_components, i));
+        {
+          ICalComponent *comp = g_ptr_array_index (ical_components, i);
+          slist = g_slist_prepend (slist, g_object_ref (comp));
+        }
+
+      ical_timezones = gcal_import_file_row_get_timezones (row);
+      if (!ical_timezones)
+        continue;
+
+      for (i = 0; i < ical_timezones->len; i++)
+        {
+          ICalTimezone *zone = g_ptr_array_index (ical_timezones, i);
+          zones = g_slist_prepend (zones, g_object_ref (zone));
+        }
     }
 
   if (!slist)
@@ -320,12 +395,16 @@ on_import_button_clicked_cb (GtkButton        *button,
   gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
 
   client = gcal_calendar_get_client (calendar);
-  e_cal_client_create_objects (client,
-                               slist,
-                               E_CAL_OPERATION_FLAG_NONE,
-                               self->cancellable,
-                               on_events_created_cb,
-                               self);
+
+  import_data = g_new0 (ImportData, 1);
+  import_data->client = g_object_ref (client);
+  import_data->components = g_slist_reverse (slist);
+  import_data->zones = g_slist_reverse (zones);
+
+  task = g_task_new (NULL, self->cancellable, on_events_created_cb, self);
+  g_task_set_task_data (task, import_data, import_data_free);
+  g_task_set_source_tag (task, on_import_button_clicked_cb);
+  g_task_run_in_thread (task, import_data_thread);
 
   GCAL_EXIT;
 }
diff --git a/src/gui/importer/gcal-import-file-row.c b/src/gui/importer/gcal-import-file-row.c
index 5970aac3..0ed08bab 100644
--- a/src/gui/importer/gcal-import-file-row.c
+++ b/src/gui/importer/gcal-import-file-row.c
@@ -38,6 +38,7 @@ struct _GcalImportFileRow
   GCancellable       *cancellable;
   GFile              *file;
   GPtrArray          *ical_components;
+  GPtrArray          *ical_timezones;
 };
 
 static void          read_calendar_finished_cb                   (GObject            *source_object,
@@ -212,6 +213,37 @@ filter_event_components (ICalComponent *component)
   return g_steal_pointer (&event_components);
 }
 
+static GPtrArray*
+filter_timezones (ICalComponent *component)
+{
+  g_autoptr (GPtrArray) timezones = NULL;
+  ICalComponent *aux;
+
+  if (!component || i_cal_component_isa (component) != I_CAL_VCALENDAR_COMPONENT)
+    return NULL;
+
+  timezones = g_ptr_array_new_full (2, g_object_unref);
+  for (aux = i_cal_component_get_first_component (component, I_CAL_VTIMEZONE_COMPONENT);
+       aux;
+       aux = i_cal_component_get_next_component (component, I_CAL_VTIMEZONE_COMPONENT))
+    {
+      ICalTimezone *zone = i_cal_timezone_new ();
+      ICalComponent *clone = i_cal_component_clone (aux);
+
+      if (i_cal_timezone_set_component (zone, clone))
+         g_ptr_array_add (timezones, g_steal_pointer (&zone));
+
+      g_clear_object (&clone);
+      g_clear_object (&zone);
+      g_clear_object (&aux);
+    }
+
+  if (!timezones->len)
+    return NULL;
+
+  return g_steal_pointer (&timezones);
+}
+
 static void
 setup_file (GcalImportFileRow *self)
 {
@@ -237,6 +269,7 @@ read_calendar_finished_cb (GObject      *source_object,
                            gpointer      user_data)
 {
   g_autoptr (GPtrArray) event_components = NULL;
+  g_autoptr (GPtrArray) timezones = NULL;
   g_autoptr (GError) error = NULL;
   g_autofree gchar *subtitle = NULL;
   ICalComponent *component;
@@ -245,6 +278,7 @@ read_calendar_finished_cb (GObject      *source_object,
   self = GCAL_IMPORT_FILE_ROW (user_data);
   component = gcal_importer_import_file_finish (res, &error);
   event_components = filter_event_components (component);
+  timezones = filter_timezones (component);
 
   gtk_widget_set_sensitive (GTK_WIDGET (self), !error && event_components && event_components->len > 0);
 
@@ -254,6 +288,7 @@ read_calendar_finished_cb (GObject      *source_object,
   add_events_to_listbox (self, event_components);
 
   self->ical_components = g_ptr_array_ref (event_components);
+  self->ical_timezones = g_ptr_array_ref (timezones);
 
   g_signal_emit (self, signals[FILE_LOADED], 0, event_components);
 }
@@ -272,6 +307,7 @@ gcal_import_file_row_finalize (GObject *object)
   g_clear_object (&self->cancellable);
   g_clear_object (&self->file);
   g_clear_pointer (&self->ical_components, g_ptr_array_unref);
+  g_clear_pointer (&self->ical_timezones, g_ptr_array_unref);
 
   G_OBJECT_CLASS (gcal_import_file_row_parent_class)->finalize (object);
 }
@@ -386,3 +422,11 @@ gcal_import_file_row_get_ical_components (GcalImportFileRow *self)
 
   return self->ical_components;
 }
+
+GPtrArray*
+gcal_import_file_row_get_timezones (GcalImportFileRow *self)
+{
+  g_return_val_if_fail (GCAL_IS_IMPORT_FILE_ROW (self), NULL);
+
+  return self->ical_timezones;
+}
diff --git a/src/gui/importer/gcal-import-file-row.h b/src/gui/importer/gcal-import-file-row.h
index 0ebff738..e798997d 100644
--- a/src/gui/importer/gcal-import-file-row.h
+++ b/src/gui/importer/gcal-import-file-row.h
@@ -33,5 +33,6 @@ GtkWidget*           gcal_import_file_row_new                    (GFile
 void                 gcal_import_file_row_show_filename          (GcalImportFileRow  *self);
 
 GPtrArray*           gcal_import_file_row_get_ical_components    (GcalImportFileRow  *self);
+GPtrArray*           gcal_import_file_row_get_timezones          (GcalImportFileRow  *self);
 
 G_END_DECLS


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