[gnome-calendar] window: implement removing and undoing the removal of a calendar



commit 9df8b8077d8f64e2b9ffe4cf4d5e81f0ba8aafd1
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Tue Feb 10 11:21:53 2015 -0200

    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        |   96 ++++++++++++++++++++++++++++++++++++++++-----
 5 files changed, 92 insertions(+), 15 deletions(-)
---
diff --git a/data/ui/source-dialog.ui b/data/ui/source-dialog.ui
index c839c9a..883c473 100644
--- a/data/ui/source-dialog.ui
+++ b/data/ui/source-dialog.ui
@@ -100,6 +100,7 @@
                     <property name="receives_default">True</property>
                     <property name="halign">end</property>
                     <property name="margin_top">6</property>
+                    <signal name="clicked" handler="action_widget_activated" object="GcalSourceDialog" 
swapped="no"/>
                     <style>
                       <class name="destructive-action"/>
                     </style>
diff --git a/data/ui/window.ui b/data/ui/window.ui
index c5065e0..c98bc75 100644
--- a/data/ui/window.ui
+++ b/data/ui/window.ui
@@ -145,10 +145,7 @@
                         <property name="can_focus">True</property>
                         <property name="receives_default">True</property>
                         <property name="no_show_all">True</property>
-                        <signal name="clicked" handler="undo_remove_event" object="GcalWindow" swapped="no"/>
-                        <style>
-                          <class name="text-button"/>
-                        </style>
+                        <signal name="clicked" handler="undo_remove_action" object="GcalWindow" 
swapped="no"/>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
diff --git a/src/gcal-source-dialog.c b/src/gcal-source-dialog.c
index 8c315c1..2e99bf3 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 5e26aaa..b40bb3f 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 9ebde13..86b882b 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);


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