From 9df8b8077d8f64e2b9ffe4cf4d5e81f0ba8aafd1 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Tue, 10 Feb 2015 11:21:53 -0200 Subject: [PATCH] window: implement removing and undoing the removal of a calendar We're still facing the bug where the just-added calendar segfaults when removed. --- data/ui/source-dialog.ui | 1 + data/ui/window.ui | 5 +- src/gcal-source-dialog.c | 3 ++ src/gcal-source-dialog.h | 2 + src/gcal-window.c | 98 +++++++++++++++++++++++++++++++++++----- 5 files changed, 93 insertions(+), 16 deletions(-) diff --git a/data/ui/source-dialog.ui b/data/ui/source-dialog.ui index c839c9ab..883c473b 100644 --- a/data/ui/source-dialog.ui +++ b/data/ui/source-dialog.ui @@ -100,6 +100,7 @@ True end 6 + diff --git a/data/ui/window.ui b/data/ui/window.ui index c5065e03..c98bc754 100644 --- a/data/ui/window.ui +++ b/data/ui/window.ui @@ -145,10 +145,7 @@ True True True - - + 1 diff --git a/src/gcal-source-dialog.c b/src/gcal-source-dialog.c index 8c315c13..2e99bf34 100644 --- a/src/gcal-source-dialog.c +++ b/src/gcal-source-dialog.c @@ -33,6 +33,7 @@ typedef struct GtkWidget *headerbar; GtkWidget *name_entry; GtkWidget *notebook; + GtkWidget *remove_button; GtkWidget *select_file_button; GtkWidget *stack; @@ -382,6 +383,7 @@ gcal_source_dialog_constructed (GObject *object) g_object_set_data (G_OBJECT (priv->add_button), "response", GINT_TO_POINTER (GTK_RESPONSE_APPLY)); g_object_set_data (G_OBJECT (priv->cancel_button), "response", GINT_TO_POINTER (GTK_RESPONSE_CANCEL)); + g_object_set_data (G_OBJECT (priv->remove_button), "response", GINT_TO_POINTER (GCAL_RESPONSE_REMOVE_SOURCE)); /* setup titlebar */ gtk_window_set_titlebar (GTK_WINDOW (object), priv->headerbar); @@ -450,6 +452,7 @@ gcal_source_dialog_class_init (GcalSourceDialogClass *klass) gtk_widget_class_bind_template_child_private (widget_class, GcalSourceDialog, headerbar); gtk_widget_class_bind_template_child_private (widget_class, GcalSourceDialog, name_entry); gtk_widget_class_bind_template_child_private (widget_class, GcalSourceDialog, notebook); + gtk_widget_class_bind_template_child_private (widget_class, GcalSourceDialog, remove_button); gtk_widget_class_bind_template_child_private (widget_class, GcalSourceDialog, select_file_button); gtk_widget_class_bind_template_child_private (widget_class, GcalSourceDialog, stack); diff --git a/src/gcal-source-dialog.h b/src/gcal-source-dialog.h index 5e26aaae..b40bb3f2 100644 --- a/src/gcal-source-dialog.h +++ b/src/gcal-source-dialog.h @@ -28,6 +28,8 @@ G_BEGIN_DECLS +#define GCAL_RESPONSE_REMOVE_SOURCE 2 + #define GCAL_TYPE_SOURCE_DIALOG (gcal_source_dialog_get_type()) G_DECLARE_FINAL_TYPE (GcalSourceDialog, gcal_source_dialog, GCAL, SOURCE_DIALOG, GtkDialog) diff --git a/src/gcal-window.c b/src/gcal-window.c index 9ebde138..86b882b4 100644 --- a/src/gcal-window.c +++ b/src/gcal-window.c @@ -115,6 +115,8 @@ typedef struct gint refresh_timeout; gint refresh_timeout_id; + ESource *removed_source; + GHashTable *calendar_source_to_row; /* temp to keep event_creation */ @@ -250,7 +252,7 @@ static void remove_event (GtkWidget *n GParamSpec *spec, gpointer user_data); -static void undo_remove_event (GtkButton *button, +static void undo_remove_action (GtkButton *button, gpointer user_data); static void gcal_window_constructed (GObject *object); @@ -923,9 +925,11 @@ source_row_activated (GtkListBox *listbox, GcalWindowPrivate *priv = gcal_window_get_instance_private (GCAL_WINDOW (user_data)); GtkWidget *new_row; ESource *source; + gint response; GList *l, *aux; l = g_hash_table_get_keys (priv->calendar_source_to_row); + source = NULL; for (aux = l; aux != NULL; aux = aux->next) { @@ -941,21 +945,44 @@ source_row_activated (GtkListBox *listbox, } } + /* double check the source */ + if (source == NULL) + return; + gcal_source_dialog_set_mode (GCAL_SOURCE_DIALOG (priv->source_dialog), GCAL_SOURCE_DIALOG_MODE_EDIT); gcal_source_dialog_set_source (GCAL_SOURCE_DIALOG (priv->source_dialog), source); gtk_widget_hide (priv->calendar_popover); - gtk_dialog_run (GTK_DIALOG (priv->source_dialog)); + response = gtk_dialog_run (GTK_DIALOG (priv->source_dialog)); + gtk_widget_hide (priv->source_dialog); /* update the source */ - new_row = make_row_for_source (GCAL_WINDOW (user_data), source); - g_hash_table_remove (priv->calendar_source_to_row, source); - g_hash_table_insert (priv->calendar_source_to_row, source, new_row); - gtk_container_add (GTK_CONTAINER (priv->calendar_listbox), new_row); + if (response == GCAL_RESPONSE_REMOVE_SOURCE) + { + gchar *str; + + str = g_strdup_printf (_("Calendar '%s' removed"), e_source_get_display_name (source)); + priv->removed_source = source; + + create_notification (GCAL_WINDOW (user_data), str, _("Undo")); + gtk_revealer_set_reveal_child (GTK_REVEALER (priv->notification), TRUE); + + gcal_manager_disable_source (priv->manager, source); + + g_free (str); + } + else + { + new_row = make_row_for_source (GCAL_WINDOW (user_data), source); + + g_hash_table_insert (priv->calendar_source_to_row, source, new_row); + + gtk_container_add (GTK_CONTAINER (priv->calendar_listbox), new_row); + } g_list_free (l); } @@ -1283,11 +1310,39 @@ remove_event (GtkWidget *notification, g_clear_pointer (&(priv->event_to_delete), g_free); } + + /* If we have any removed source, finally delete it */ + if (priv->removed_source != NULL) + { + GError *error = NULL; + + /* We don't really want to remove non-removable sources */ + if (!e_source_get_removable (priv->removed_source)) + return; + + e_source_remove_sync (priv->removed_source, NULL, &error); + + /** + * If something goes wrong, throw + * an alert and add the source back. + */ + if (error != NULL) + { + g_warning ("Error removing source: %s", error->message); + + add_source (priv->manager, priv->removed_source, + gcal_manager_source_enabled (priv->manager, priv->removed_source), user_data); + + gcal_manager_enable_source (priv->manager, priv->removed_source); + + g_error_free (error); + } + } } static void -undo_remove_event (GtkButton *button, - gpointer user_data) +undo_remove_action (GtkButton *button, + gpointer user_data) { GcalWindowPrivate *priv; gchar *uuid; @@ -1305,11 +1360,30 @@ undo_remove_event (GtkButton *button, g_clear_pointer (&(priv->event_to_delete), g_free); g_list_free (widgets); g_free (uuid); - - g_source_remove (priv->notification_timeout); - hide_notification (GCAL_WINDOW (user_data), NULL); } + /* if there's any set source, unremove it */ + if (priv->removed_source != NULL) + { + /** + * Enable the source before adding it again to + * avoid an enabled source with unchecked check + * button. + */ + gcal_manager_enable_source (priv->manager, priv->removed_source); + + add_source (priv->manager, priv->removed_source, + gcal_manager_source_enabled (priv->manager, priv->removed_source), user_data); + + /** + * Don't clear the pointer, since we don't + * want to erase the source at all. + */ + priv->removed_source = NULL; + } + + gtk_revealer_set_reveal_child (GTK_REVEALER (priv->notification), FALSE); + } static gboolean @@ -1433,7 +1507,7 @@ gcal_window_class_init(GcalWindowClass *klass) /* Event removal related */ gtk_widget_class_bind_template_callback (widget_class, hide_notification); gtk_widget_class_bind_template_callback (widget_class, remove_event); - gtk_widget_class_bind_template_callback (widget_class, undo_remove_event); + gtk_widget_class_bind_template_callback (widget_class, undo_remove_action); /* Event creation related */ gtk_widget_class_bind_template_callback (widget_class, create_event);