[seahorse/refactor] Make delete actions work properly again



commit 9a9747d43b8fecd770440cdd21220cc3a1d61b3d
Author: Stef Walter <stefw collabora co uk>
Date:   Thu Oct 20 13:56:23 2011 +0200

    Make delete actions work properly again
    
     * We sort the selected items by deleting action
     * Invoke those actions in turn
     * Allow cancellation of one, to cancel all the remaining

 gkr/seahorse-gkr-actions.c       |    5 ++
 libseahorse/seahorse-action.c    |   53 ++++++++++++++++++-----
 libseahorse/seahorse-action.h    |    9 +++-
 libseahorse/seahorse-viewer.c    |   87 +++++++++++++++++++-------------------
 pgp/seahorse-pgp-actions.c       |    1 +
 pkcs11/seahorse-pkcs11-actions.c |    2 +
 src/seahorse-key-manager.ui      |    3 +-
 ssh/seahorse-ssh-actions.c       |    2 +
 8 files changed, 103 insertions(+), 59 deletions(-)
---
diff --git a/gkr/seahorse-gkr-actions.c b/gkr/seahorse-gkr-actions.c
index bfc18fa..d8b0358 100644
--- a/gkr/seahorse-gkr-actions.c
+++ b/gkr/seahorse-gkr-actions.c
@@ -333,6 +333,8 @@ on_keyring_delete (GtkAction* action,
 		seahorse_progress_show (cancellable, ngettext ("Deleting keyring", "Deleting keyrings",
 		                                               g_list_length (objects)), TRUE);
 		g_object_unref (cancellable);
+	} else {
+		seahorse_action_cancel (action);
 	}
 
 	g_free (prompt);
@@ -521,6 +523,9 @@ on_delete_passwords (GtkAction *action,
 		seahorse_gkr_delete_async (objects, cancellable, on_delete_objects, g_object_ref (parent));
 		seahorse_progress_show (cancellable, ngettext ("Deleting item", "Deleting items", num), TRUE);
 		g_object_unref (cancellable);
+	} else {
+		seahorse_action_cancel (action);
+
 	}
 
 	g_free (prompt);
diff --git a/libseahorse/seahorse-action.c b/libseahorse/seahorse-action.c
index 89fafc9..8f81653 100644
--- a/libseahorse/seahorse-action.c
+++ b/libseahorse/seahorse-action.c
@@ -29,36 +29,64 @@
 typedef struct {
 	GtkWindow *window;
 	GList *objects;
+	GCancellable *cancellable;
 } SeahorseActionInfo;
 
+static GQuark   seahorse_action_info_quark (void) G_GNUC_CONST;
+
 static void
 seahorse_action_info_free (gpointer data)
 {
 	SeahorseActionInfo *info = data;
 	g_clear_object (&info->window);
+	g_clear_object (&info->cancellable);
 	gck_list_unref_free (info->objects);
 	g_slice_free (SeahorseActionInfo, info);
 }
 
+static GQuark
+seahorse_action_info_quark (void)
+{
+	static GQuark quark = 0;
+	if (quark == 0)
+		quark = g_quark_from_static_string ("seahorse-action-info");
+	return quark;
+}
+
 static SeahorseActionInfo *
 seahorse_action_info_lookup (GtkAction *action)
 {
 	SeahorseActionInfo *info;
-	static GQuark QUARK_INFO = 0;
-
-	if (QUARK_INFO == 0)
-		QUARK_INFO = g_quark_from_static_string ("seahorse-action-info");
 
-	info = g_object_get_qdata (G_OBJECT (action), QUARK_INFO);
+	info = g_object_get_qdata (G_OBJECT (action), seahorse_action_info_quark ());
 	if (info == NULL) {
 		info = g_slice_new0 (SeahorseActionInfo);
-		g_object_set_qdata_full (G_OBJECT (action), QUARK_INFO, info,
-		                         seahorse_action_info_free);
+		g_object_set_qdata_full (G_OBJECT (action), seahorse_action_info_quark (),
+		                         info, seahorse_action_info_free);
 	}
 
 	return info;
 }
 
+void
+seahorse_action_reset (GtkAction *action)
+{
+	g_return_if_fail (GTK_IS_ACTION (action));
+	g_object_set_qdata (G_OBJECT (action), seahorse_action_info_quark (), NULL);
+}
+
+void
+seahorse_action_cancel (GtkAction *action)
+{
+	SeahorseActionInfo *info;
+
+	g_return_if_fail (GTK_IS_ACTION (action));
+
+	info = seahorse_action_info_lookup (action);
+	if (info->cancellable)
+		g_cancellable_cancel (info->cancellable);
+}
+
 GtkWindow *
 seahorse_action_get_window (GtkAction *action)
 {
@@ -118,13 +146,16 @@ seahorse_action_set_objects (GtkAction *action,
 	info->objects = gck_list_ref_copy (objects);
 }
 
-gboolean
-seahorse_action_have_objects (GtkAction *action)
+void
+seahorse_action_set_cancellable (GtkAction *action,
+                                 GCancellable *cancellable)
 {
 	SeahorseActionInfo *info;
 
-	g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
+	g_return_if_fail (cancellable == NULL ||
+	                  G_IS_CANCELLABLE (cancellable));
 
 	info = seahorse_action_info_lookup (action);
-	return info->objects ? TRUE : FALSE;
+	g_clear_object (&info->cancellable);
+	info->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
 }
diff --git a/libseahorse/seahorse-action.h b/libseahorse/seahorse-action.h
index 6acb948..f9df96e 100644
--- a/libseahorse/seahorse-action.h
+++ b/libseahorse/seahorse-action.h
@@ -25,6 +25,13 @@
 
 #include <gtk/gtk.h>
 
+void                  seahorse_action_reset                     (GtkAction *action);
+
+void                  seahorse_action_set_cancellable           (GtkAction *action,
+                                                                 GCancellable *cancellable);
+
+void                  seahorse_action_cancel                    (GtkAction *action);
+
 GtkWindow *           seahorse_action_get_window                (GtkAction *action);
 
 gpointer              seahorse_action_get_object                (GtkAction *action);
@@ -37,6 +44,4 @@ void                  seahorse_action_set_window                (GtkAction *acti
 void                  seahorse_action_set_objects               (GtkAction *action,
                                                                  GList *objects);
 
-gboolean              seahorse_action_have_objects              (GtkAction *action);
-
 #endif
diff --git a/libseahorse/seahorse-viewer.c b/libseahorse/seahorse-viewer.c
index 79849b6..a8b8575 100644
--- a/libseahorse/seahorse-viewer.c
+++ b/libseahorse/seahorse-viewer.c
@@ -133,34 +133,52 @@ on_object_delete (GtkAction *action,
                   gpointer user_data)
 {
 	SeahorseViewer *self = SEAHORSE_VIEWER (user_data);
+	GCancellable *cancellable;
 	GtkActionGroup *actions;
+	GtkAction *delete_action;
 	GList *objects;
-	GList *selected;
-	const gchar *name;
+	GHashTable *perform;
+	GHashTableIter iter;
+	GQueue *queue;
 	GList *l;
 
-	if (seahorse_action_have_objects (action))
-		return;
+	cancellable = g_cancellable_new ();
+	perform = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+	                                 NULL, (GDestroyNotify)g_queue_free);
 
 	objects = seahorse_viewer_get_selected_objects (self);
-	objects = g_list_concat (objects, seahorse_viewer_get_selected_places (self));
-	objects = g_list_concat (objects, seahorse_viewer_get_selected_backends (self));
-	name = gtk_action_get_name (action);
-
 	for (l = objects; l != NULL; l = g_list_next (l)) {
-		actions = NULL;
 		g_object_get (l->data, "actions", &actions, NULL);
-		if (actions && gtk_action_group_get_action (actions, name) == action)
-			selected = g_list_prepend (selected, l->data);
-		g_object_ref (actions);
-	}
+		delete_action = gtk_action_group_get_action (actions, "delete");
+		g_object_unref (actions);
 
-	selected = g_list_reverse (selected);
-	seahorse_action_set_objects (action, selected);
-	seahorse_action_set_window (action, seahorse_viewer_get_window (self));
+		if (delete_action == NULL)
+			continue;
 
-	g_list_free (selected);
+		queue = g_hash_table_lookup (perform, delete_action);
+		if (queue == NULL) {
+			queue = g_queue_new ();
+			g_hash_table_insert (perform, delete_action, queue);
+		}
+		g_queue_push_tail (queue, l->data);
+	}
 	g_list_free (objects);
+
+	/* Now go through and execute the deletes */
+	g_hash_table_iter_init (&iter, perform);
+	while (!g_cancellable_is_cancelled (cancellable) &&
+	       g_hash_table_iter_next (&iter, (gpointer *)&delete_action, (gpointer *)&queue)) {
+		seahorse_action_set_window (delete_action, seahorse_viewer_get_window (self));
+		seahorse_action_set_objects (delete_action, queue->head);
+		seahorse_action_set_cancellable (delete_action, cancellable);
+
+		gtk_action_activate (delete_action);
+
+		seahorse_action_reset (delete_action);
+	}
+
+	g_object_unref (cancellable);
+	g_hash_table_destroy (perform);
 }
 
 static GtkAction *
@@ -388,7 +406,7 @@ on_ui_manager_pre_activate (GtkUIManager *ui_manager,
 	g_return_if_fail (name != NULL);
 
 	/* These guys do their own object selection */
-	if (seahorse_action_have_objects (action) ||
+	if (seahorse_action_get_object (action) ||
 	    action == self->pv->properties_object ||
 	    action == self->pv->properties_place ||
 	    action == self->pv->properties_backend ||
@@ -422,8 +440,7 @@ on_ui_manager_post_activate (GtkUIManager *ui_manager,
                              GtkAction *action,
                              gpointer user_data)
 {
-	seahorse_action_set_objects (action, NULL);
-	seahorse_action_set_window (action, NULL);
+	seahorse_action_reset (action);
 }
 
 static void
@@ -460,11 +477,11 @@ seahorse_viewer_real_selection_changed (SeahorseViewer *self)
 {
 	GHashTableIter iter;
 	GHashTable *seen;
-	GPtrArray *deletes;
 	GList *objects;
 	GPtrArray *selected;
 	GtkActionGroup *actions;
 	GtkAction *action;
+	gboolean deletes;
 	guint i;
 
 	seen = g_hash_table_new_full (g_direct_hash, g_direct_equal,
@@ -482,33 +499,16 @@ seahorse_viewer_real_selection_changed (SeahorseViewer *self)
 	 * in the delete logic here.
 	 */
 
-	deletes = g_ptr_array_new ();
+	deletes = FALSE;
 
 	g_hash_table_iter_init (&iter, seen);
-	while (g_hash_table_iter_next (&iter, (gpointer *)&actions, (gpointer *)&selected)) {
+	while (g_hash_table_iter_next (&iter, (gpointer *)&actions, NULL)) {
 		action = gtk_action_group_get_action (actions, "delete");
 		if (action != NULL)
-			g_ptr_array_add (deletes, action);
-	}
-
-	/* If there's no delete command, then disable ours */
-	if (deletes->len == 0) {
-		gtk_action_set_sensitive (self->pv->edit_delete, FALSE);
-
-	/* If there's one delete command, then hide ours, and show it */
-	} else if (deletes->len == 1) {
-		gtk_action_set_visible (self->pv->edit_delete, FALSE);
-		gtk_action_set_visible (deletes->pdata[0], TRUE);
-
-	/* If there's more than one delete command, then show ours, and hide others */
-	} else {
-		gtk_action_set_sensitive (self->pv->edit_delete, TRUE);
-		gtk_action_set_visible (self->pv->edit_delete, TRUE);
-		for (i = 0; i < deletes->len; i++)
-			gtk_action_set_visible (deletes->pdata[i], FALSE);
+			deletes = TRUE;
 	}
 
-	g_ptr_array_unref (deletes);
+	gtk_action_set_sensitive (self->pv->edit_delete, deletes);
 
 	/* Now proceed to bring in the other commands */
 	objects = seahorse_viewer_get_selected_places (self);
@@ -776,8 +776,7 @@ seahorse_viewer_show_properties (SeahorseViewer* self,
 
 	gtk_action_activate (action);
 
-	seahorse_action_set_objects (action, NULL);
-	seahorse_action_set_window (action, NULL);
+	seahorse_action_reset (action);
 }
 
 GtkWindow *
diff --git a/pgp/seahorse-pgp-actions.c b/pgp/seahorse-pgp-actions.c
index 403f0b1..9a2b7db 100644
--- a/pgp/seahorse-pgp-actions.c
+++ b/pgp/seahorse-pgp-actions.c
@@ -260,6 +260,7 @@ on_delete_objects (GtkAction *action,
 	parent = GTK_WIDGET (seahorse_action_get_window (action));
 	if (!seahorse_util_prompt_delete (message, parent)) {
 		g_free (message);
+		seahorse_action_cancel (action);
 		return;
 	}
 
diff --git a/pkcs11/seahorse-pkcs11-actions.c b/pkcs11/seahorse-pkcs11-actions.c
index 2b4919f..94599d3 100644
--- a/pkcs11/seahorse-pkcs11-actions.c
+++ b/pkcs11/seahorse-pkcs11-actions.c
@@ -139,6 +139,8 @@ on_delete_objects (GtkAction *action,
 		                              on_delete_completed, g_object_ref (parent));
 		seahorse_progress_show (cancellable, _("Deleting"), TRUE);
 		g_object_unref (cancellable);
+	} else {
+		seahorse_action_cancel (action);
 	}
 }
 
diff --git a/src/seahorse-key-manager.ui b/src/seahorse-key-manager.ui
index 7f19a9c..ea72e35 100644
--- a/src/seahorse-key-manager.ui
+++ b/src/seahorse-key-manager.ui
@@ -36,9 +36,8 @@
 	</toolbar>
 
 	<popup name="ObjectPopup">
-		<menuitem action="properties-object"/>
-		<separator/>
 		<menuitem action="edit-delete"/>
 		<separator/>
+		<menuitem action="properties-object"/>
 	</popup>
 </ui>
diff --git a/ssh/seahorse-ssh-actions.c b/ssh/seahorse-ssh-actions.c
index ddb47fd..917518c 100644
--- a/ssh/seahorse-ssh-actions.c
+++ b/ssh/seahorse-ssh-actions.c
@@ -120,6 +120,8 @@ on_delete_objects (GtkAction *action,
 				seahorse_util_handle_error (&error, parent, _("Couldn't delete key"));
 			}
 		}
+	} else {
+		seahorse_action_cancel (action);
 	}
 
 	g_free (prompt);



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