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 +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