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
This commit is contained in:
@@ -29,6 +29,13 @@
|
|||||||
|
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ECalClient *client;
|
||||||
|
GSList *components;
|
||||||
|
GSList *zones;
|
||||||
|
} ImportData;
|
||||||
|
|
||||||
struct _GcalImportDialog
|
struct _GcalImportDialog
|
||||||
{
|
{
|
||||||
HdyWindow parent;
|
HdyWindow parent;
|
||||||
@@ -84,6 +91,20 @@ static GParamSpec *properties [N_PROPS];
|
|||||||
* Auxiliary methods
|
* 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*
|
static GtkWidget*
|
||||||
create_calendar_row (GcalManager *manager,
|
create_calendar_row (GcalManager *manager,
|
||||||
GcalCalendar *calendar)
|
GcalCalendar *calendar)
|
||||||
@@ -252,7 +273,7 @@ on_events_created_cb (GObject *source_object,
|
|||||||
|
|
||||||
self = GCAL_IMPORT_DIALOG (user_data);
|
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)
|
if (error)
|
||||||
g_warning ("Error creating events: %s", error->message);
|
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));
|
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
|
static void
|
||||||
on_import_button_clicked_cb (GtkButton *button,
|
on_import_button_clicked_cb (GtkButton *button,
|
||||||
GcalImportDialog *self)
|
GcalImportDialog *self)
|
||||||
{
|
{
|
||||||
g_autoptr (GList) children = NULL;
|
g_autoptr (GList) children = NULL;
|
||||||
|
g_autoptr (GTask) task = NULL;
|
||||||
GcalCalendar *calendar;
|
GcalCalendar *calendar;
|
||||||
|
ImportData *import_data;
|
||||||
ECalClient *client;
|
ECalClient *client;
|
||||||
GSList *slist;
|
GSList *slist = NULL;
|
||||||
|
GSList *zones = NULL;
|
||||||
GList *l;
|
GList *l;
|
||||||
|
|
||||||
GCAL_ENTRY;
|
GCAL_ENTRY;
|
||||||
@@ -302,6 +363,7 @@ on_import_button_clicked_cb (GtkButton *button,
|
|||||||
{
|
{
|
||||||
GcalImportFileRow *row = l->data;
|
GcalImportFileRow *row = l->data;
|
||||||
GPtrArray *ical_components;
|
GPtrArray *ical_components;
|
||||||
|
GPtrArray *ical_timezones;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
ical_components = gcal_import_file_row_get_ical_components (row);
|
ical_components = gcal_import_file_row_get_ical_components (row);
|
||||||
@@ -309,7 +371,20 @@ on_import_button_clicked_cb (GtkButton *button,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < ical_components->len; i++)
|
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)
|
if (!slist)
|
||||||
@@ -320,12 +395,16 @@ on_import_button_clicked_cb (GtkButton *button,
|
|||||||
gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
|
gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
|
||||||
|
|
||||||
client = gcal_calendar_get_client (calendar);
|
client = gcal_calendar_get_client (calendar);
|
||||||
e_cal_client_create_objects (client,
|
|
||||||
slist,
|
import_data = g_new0 (ImportData, 1);
|
||||||
E_CAL_OPERATION_FLAG_NONE,
|
import_data->client = g_object_ref (client);
|
||||||
self->cancellable,
|
import_data->components = g_slist_reverse (slist);
|
||||||
on_events_created_cb,
|
import_data->zones = g_slist_reverse (zones);
|
||||||
self);
|
|
||||||
|
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;
|
GCAL_EXIT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ struct _GcalImportFileRow
|
|||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
GFile *file;
|
GFile *file;
|
||||||
GPtrArray *ical_components;
|
GPtrArray *ical_components;
|
||||||
|
GPtrArray *ical_timezones;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void read_calendar_finished_cb (GObject *source_object,
|
static void read_calendar_finished_cb (GObject *source_object,
|
||||||
@@ -212,6 +213,37 @@ filter_event_components (ICalComponent *component)
|
|||||||
return g_steal_pointer (&event_components);
|
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
|
static void
|
||||||
setup_file (GcalImportFileRow *self)
|
setup_file (GcalImportFileRow *self)
|
||||||
{
|
{
|
||||||
@@ -237,6 +269,7 @@ read_calendar_finished_cb (GObject *source_object,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_autoptr (GPtrArray) event_components = NULL;
|
g_autoptr (GPtrArray) event_components = NULL;
|
||||||
|
g_autoptr (GPtrArray) timezones = NULL;
|
||||||
g_autoptr (GError) error = NULL;
|
g_autoptr (GError) error = NULL;
|
||||||
g_autofree gchar *subtitle = NULL;
|
g_autofree gchar *subtitle = NULL;
|
||||||
ICalComponent *component;
|
ICalComponent *component;
|
||||||
@@ -245,6 +278,7 @@ read_calendar_finished_cb (GObject *source_object,
|
|||||||
self = GCAL_IMPORT_FILE_ROW (user_data);
|
self = GCAL_IMPORT_FILE_ROW (user_data);
|
||||||
component = gcal_importer_import_file_finish (res, &error);
|
component = gcal_importer_import_file_finish (res, &error);
|
||||||
event_components = filter_event_components (component);
|
event_components = filter_event_components (component);
|
||||||
|
timezones = filter_timezones (component);
|
||||||
|
|
||||||
gtk_widget_set_sensitive (GTK_WIDGET (self), !error && event_components && event_components->len > 0);
|
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);
|
add_events_to_listbox (self, event_components);
|
||||||
|
|
||||||
self->ical_components = g_ptr_array_ref (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);
|
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->cancellable);
|
||||||
g_clear_object (&self->file);
|
g_clear_object (&self->file);
|
||||||
g_clear_pointer (&self->ical_components, g_ptr_array_unref);
|
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);
|
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;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,5 +33,6 @@ GtkWidget* gcal_import_file_row_new (GFile
|
|||||||
void gcal_import_file_row_show_filename (GcalImportFileRow *self);
|
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_ical_components (GcalImportFileRow *self);
|
||||||
|
GPtrArray* gcal_import_file_row_get_timezones (GcalImportFileRow *self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
Reference in New Issue
Block a user