[seahorse] Rework actions again



commit 700ae51c40e90cef388dab0cf89c5e82933b4757
Author: Stef Walter <stefw collabora co uk>
Date:   Tue Oct 25 09:44:42 2011 +0200

    Rework actions again
    
     * We clone action groups for the current selection, that clone
       contains a reference to the current selection.

 gkr/seahorse-gkr-actions.c         |  202 ++++++++++++++-----------
 libseahorse/seahorse-action.c      |  123 +++-------------
 libseahorse/seahorse-action.h      |   19 +--
 libseahorse/seahorse-actions.c     |   35 +++--
 libseahorse/seahorse-actions.h     |    8 +-
 libseahorse/seahorse-object-list.c |    5 +-
 libseahorse/seahorse-object-list.h |    2 +-
 libseahorse/seahorse-viewer.c      |  289 ++++++++++++------------------------
 libseahorse/seahorse-viewer.h      |   24 +---
 pgp/seahorse-keyserver-results.c   |   13 +-
 pgp/seahorse-pgp-actions.c         |   68 +++++++--
 pkcs11/seahorse-pkcs11-actions.c   |   50 +++++--
 src/seahorse-generate-select.c     |   24 ++-
 src/seahorse-key-manager.c         |   21 ++-
 ssh/seahorse-ssh-actions.c         |   53 +++++--
 ssh/seahorse-ssh-actions.h         |    2 +
 ssh/seahorse-ssh-key.c             |   14 ++-
 17 files changed, 445 insertions(+), 507 deletions(-)
---
diff --git a/gkr/seahorse-gkr-actions.c b/gkr/seahorse-gkr-actions.c
index d8b0358..9e5e71b 100644
--- a/gkr/seahorse-gkr-actions.c
+++ b/gkr/seahorse-gkr-actions.c
@@ -30,6 +30,7 @@
 
 #include "seahorse-action.h"
 #include "seahorse-actions.h"
+#include "seahorse-object-list.h"
 #include "seahorse-progress.h"
 #include "seahorse-registry.h"
 #include "seahorse-util.h"
@@ -69,29 +70,29 @@ on_new_keyring (GtkAction *action,
 
 static void
 on_new_item (GtkAction *action,
-                 gpointer unused)
+             gpointer unused)
 {
 	seahorse_gkr_add_item_show (seahorse_action_get_window (action));
 }
 
 static const GtkActionEntry BACKEND_ACTIONS[] = {
-	{ "gkr-keyring-new", NULL, N_("New password keyring"), "",
+	{ "keyring-new", NULL, N_("New password keyring"), "",
 	  N_("Used to store application and network passwords"), G_CALLBACK (on_new_keyring) },
-	{ "gkr-item-new", NULL, N_("New password..."), "",
+	{ "keyring-item-new", NULL, N_("New password..."), "",
 	  N_("Safely store a password or secret."), G_CALLBACK (on_new_item) },
 };
 
 static const GtkActionEntry ENTRIES_NEW[] = {
-	{ "gkr-add-keyring", "folder", N_("Password Keyring"), "",
+	{ "keyring-new", "folder", N_("Password Keyring"), "",
 	  N_("Used to store application and network passwords"), G_CALLBACK (on_new_keyring) },
-	{ "gkr-add-item", GCR_ICON_PASSWORD, N_("Stored Password"), "",
+	{ "keyring-item-new", GCR_ICON_PASSWORD, N_("Stored Password"), "",
 	  N_("Safely store a password or secret."), G_CALLBACK (on_new_item) }
 };
 
 static const gchar* BACKEND_UI =
 "<ui>"
 "	<popup name='SeahorseGkrBackend'>"
-"		<menuitem action='gkr-keyring-new'/>"
+"		<menuitem action='keyring-new'/>"
 "	</popup>"\
 "</ui>";
 
@@ -101,7 +102,7 @@ seahorse_gkr_backend_actions_init (SeahorseGkrBackendActions *self)
 	GtkActionGroup *actions = GTK_ACTION_GROUP (self);
 
 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
-	gtk_action_group_add_actions (actions, BACKEND_ACTIONS, G_N_ELEMENTS (BACKEND_ACTIONS), self);
+	gtk_action_group_add_actions (actions, BACKEND_ACTIONS, G_N_ELEMENTS (BACKEND_ACTIONS), NULL);
 	seahorse_actions_register_definition (SEAHORSE_ACTIONS (self), BACKEND_UI);
 
 	/* Register another set of actions as a generator */
@@ -125,7 +126,7 @@ seahorse_gkr_backend_actions_instance (void)
 
 	if (actions == NULL) {
 		actions = g_object_new (SEAHORSE_TYPE_GKR_BACKEND_ACTIONS,
-		                        "name", "gkr-backend",
+		                        "name", "KeyringBackend",
 		                        NULL);
 		g_object_add_weak_pointer (G_OBJECT (actions),
 		                           (gpointer *)&actions);
@@ -145,17 +146,13 @@ seahorse_gkr_backend_actions_instance (void)
 
 typedef struct {
 	SeahorseActions parent;
-	GtkAction *action_lock;
-	GtkAction *action_unlock;
-	GtkAction *action_default;
 } SeahorseGkrKeyringActions;
 
 typedef struct {
 	SeahorseActionsClass parent_class;
 } SeahorseGkrKeyringActionsClass;
 
-GType                      seahorse_gkr_keyring_actions_get_type               (void);
-
+GType     seahorse_gkr_keyring_actions_get_type (void) G_GNUC_CONST;
 
 G_DEFINE_TYPE (SeahorseGkrKeyringActions, seahorse_gkr_keyring_actions, SEAHORSE_TYPE_ACTIONS);
 
@@ -176,14 +173,14 @@ on_keyring_unlock_done (GnomeKeyringResult result,
 }
 
 static void
-on_keyring_unlock (GtkAction *action,
-                   gpointer user_data)
+on_keyrings_unlock (GtkAction *action,
+                    gpointer user_data)
 {
-	GList *keys, *l;
+	GList *keys = user_data;
 	GtkWindow *parent;
+	GList *l;
 
 	parent = seahorse_action_get_window (action);
-	keys = seahorse_action_get_objects (action);
 	for (l = keys; l; l = g_list_next (l)) {
 		g_return_if_fail (SEAHORSE_IS_GKR_KEYRING (l->data));
 		gnome_keyring_unlock (seahorse_gkr_keyring_get_name (l->data), NULL,
@@ -207,14 +204,14 @@ on_keyring_lock_done (GnomeKeyringResult result, gpointer user_data)
 }
 
 static void
-on_keyring_lock (GtkAction *action,
-                 gpointer user_data)
+on_keyrings_lock (GtkAction *action,
+                  gpointer user_data)
 {
-	GList *keyrings, *l;
+	GList *keyrings = user_data;
 	GtkWindow *parent;
+	GList *l;
 
 	parent = seahorse_action_get_window (action);
-	keyrings = seahorse_action_get_objects (action);
 	for (l = keyrings; l; l = g_list_next (l)) {
 		g_return_if_fail (SEAHORSE_IS_GKR_KEYRING (l->data));
 		gnome_keyring_lock (seahorse_gkr_keyring_get_name (l->data),
@@ -242,11 +239,8 @@ static void
 on_keyring_default (GtkAction *action,
                     gpointer user_data)
 {
-	SeahorseGkrKeyring *keyring;
-	GtkWindow *parent;
-
-	parent = seahorse_action_get_window (action);
-	keyring = seahorse_action_get_object (action);
+	SeahorseGkrKeyring *keyring = SEAHORSE_GKR_KEYRING (user_data);
+	GtkWindow *parent = seahorse_action_get_window (action);
 	gnome_keyring_set_default_keyring (seahorse_gkr_keyring_get_name (keyring),
 	                                   on_set_default_keyring_done,
 	                                   g_object_ref (parent), g_object_unref);
@@ -271,24 +265,19 @@ static void
 on_keyring_password (GtkAction *action,
                      gpointer user_data)
 {
-	GtkWindow *window;
-	GList *keys, *l;
+	SeahorseGkrKeyring *keyring = SEAHORSE_GKR_KEYRING (user_data);
+	GtkWindow *window = seahorse_action_get_window (action);
 
-	window = seahorse_action_get_window (action);
-	keys = seahorse_action_get_objects (action);
-	for (l = keys; l; l = g_list_next (l)) {
-		g_return_if_fail (SEAHORSE_IS_GKR_KEYRING (l->data));
-		gnome_keyring_change_password (seahorse_gkr_keyring_get_name (l->data), NULL, NULL,
-		                               on_change_password_done, g_object_ref (window), g_object_unref);
-	}
+	gnome_keyring_change_password (seahorse_gkr_keyring_get_name (keyring),
+	                               NULL, NULL, on_change_password_done,
+	                               g_object_ref (window), g_object_unref);
 }
 
-
 static void
 on_keyring_properties (GtkAction* action,
                        gpointer user_data)
 {
-	seahorse_gkr_keyring_properties_show (seahorse_action_get_object (action),
+	seahorse_gkr_keyring_properties_show (SEAHORSE_GKR_KEYRING (user_data),
 	                                      seahorse_action_get_window (action));
 }
 
@@ -307,16 +296,15 @@ on_delete_objects_complete (GObject *source, GAsyncResult *result, gpointer user
 }
 
 static void
-on_keyring_delete (GtkAction* action,
-                   gpointer user_data)
+on_keyrings_delete (GtkAction* action,
+                    gpointer user_data)
 {
+	GList *objects = user_data;
 	GCancellable *cancellable;
 	GtkWindow *parent;
 	gchar *prompt;
 	gboolean ret;
-	GList *objects;
 
-	objects = seahorse_action_get_objects (action);
 	if (!objects)
 		return;
 
@@ -334,37 +322,39 @@ on_keyring_delete (GtkAction* action,
 		                                               g_list_length (objects)), TRUE);
 		g_object_unref (cancellable);
 	} else {
-		seahorse_action_cancel (action);
+		g_cancellable_cancel (g_cancellable_get_current ());
 	}
 
 	g_free (prompt);
 }
 
+static const GtkActionEntry KEYRINGS_ACTIONS[] = {
+	{ "keyring-lock", NULL, N_("_Lock"), "",
+	  N_("Lock the password storage keyring so a master password is required to unlock it."), G_CALLBACK (on_keyrings_lock) },
+	{ "keyring-unlock", NULL, N_("_Unlock"), "",
+	  N_("Unlock the password storage keyring with a master password so it is available for use."), G_CALLBACK (on_keyrings_unlock) },
+	{ "keyring-delete", GTK_STOCK_DELETE, NULL, NULL,
+	  N_("Delete the keyring."), G_CALLBACK (on_keyrings_delete) },
+};
 
 static const GtkActionEntry KEYRING_ACTIONS[] = {
-	{ "gkr-keyring-lock", NULL, N_("_Lock"), "",
-	  N_("Lock the password storage keyring so a master password is required to unlock it."), G_CALLBACK (on_keyring_lock) },
-	{ "gkr-keyring-unlock", NULL, N_("_Unlock"), "",
-	  N_("Unlock the password storage keyring with a master password so it is available for use."), G_CALLBACK (on_keyring_unlock) },
-	{ "gkr-keyring-default", NULL, N_("_Set as default"), "",
+	{ "keyring-default", NULL, N_("_Set as default"), "",
 	  N_("Applications usually store new passwords in the default keyring."), G_CALLBACK (on_keyring_default) },
-	{ "gkr-keyring-password", NULL, N_("Change _Password"), "",
+	{ "keyring-password", NULL, N_("Change _Password"), "",
 	  N_("Change the unlock password of the password storage keyring"), G_CALLBACK (on_keyring_password) },
-	{ "gkr-keyring-properties", GTK_STOCK_PROPERTIES, NULL, NULL,
+	{ "keyring-properties", GTK_STOCK_PROPERTIES, NULL, NULL,
 	  N_("Properties of the keyring."), G_CALLBACK (on_keyring_properties) },
-	{ "gkr-keyring-delete", GTK_STOCK_DELETE, NULL, NULL,
-	  N_("Delete the keyring."), G_CALLBACK (on_keyring_delete) },
 };
 
 static const gchar* KEYRING_UI =
 "<ui>"
 "	<popup name='SeahorseGkrKeyring'>"
-"		<menuitem action='gkr-keyring-unlock'/>"
-"		<menuitem action='gkr-keyring-lock'/>"
-"		<menuitem action='gkr-keyring-default'/>"
-"		<menuitem action='gkr-keyring-password'/>"
-"		<menuitem action='gkr-keyring-delete'/>"
-"		<menuitem action='gkr-keyring-properties'/>"
+"		<menuitem action='keyring-unlock'/>"
+"		<menuitem action='keyring-lock'/>"
+"		<menuitem action='keyring-default'/>"
+"		<menuitem action='keyring-password'/>"
+"		<menuitem action='keyring-delete'/>"
+"		<menuitem action='keyring-properties'/>"
 "	</popup>"\
 "</ui>";
 
@@ -372,25 +362,29 @@ static void
 seahorse_gkr_keyring_actions_init (SeahorseGkrKeyringActions *self)
 {
 	GtkActionGroup *actions = GTK_ACTION_GROUP (self);
+
+	/* Add these actions, but none of them are visible until cloned */
 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
-	gtk_action_group_add_actions (actions, KEYRING_ACTIONS, G_N_ELEMENTS (KEYRING_ACTIONS), self);
-	self->action_lock = g_object_ref (gtk_action_group_get_action (actions, "gkr-keyring-lock"));
-	self->action_unlock = g_object_ref (gtk_action_group_get_action (actions, "gkr-keyring-unlock"));
-	self->action_default = g_object_ref (gtk_action_group_get_action (actions, "gkr-keyring-default"));
+	gtk_action_group_add_actions (actions, KEYRINGS_ACTIONS, G_N_ELEMENTS (KEYRINGS_ACTIONS), NULL);
+	gtk_action_group_add_actions (actions, KEYRING_ACTIONS, G_N_ELEMENTS (KEYRING_ACTIONS), NULL);
+	gtk_action_group_set_sensitive (actions, FALSE);
+
 	seahorse_actions_register_definition (SEAHORSE_ACTIONS (self), KEYRING_UI);
 }
 
-static void
-seahorse_gkr_keyring_actions_update (SeahorseActions *actions,
-                                     GList *objects)
+static GtkActionGroup *
+seahorse_gkr_keyring_actions_clone_for_objects (SeahorseActions *actions,
+                                                GList *objects)
 {
-	SeahorseGkrKeyringActions *self = SEAHORSE_GKR_KEYRING_ACTIONS (actions);
 	GnomeKeyringInfo *info;
 	gboolean locked = FALSE;
 	gboolean unlocked = FALSE;
 	gboolean can_default = FALSE;
+	GtkActionGroup *cloned;
 	GList *l;
 
+	g_return_val_if_fail (objects != NULL, NULL);
+
 	for (l = objects; l; l = g_list_next (l)) {
 		info = seahorse_gkr_keyring_get_info (l->data);
 		if (info != NULL) {
@@ -403,31 +397,33 @@ seahorse_gkr_keyring_actions_update (SeahorseActions *actions,
 		}
 	}
 
-	gtk_action_set_sensitive (self->action_lock, unlocked);
-	gtk_action_set_sensitive (self->action_unlock, locked);
-	gtk_action_set_sensitive (self->action_default, can_default);
-}
-
-static void
-seahorse_gkr_keyring_actions_finalize (GObject *obj)
-{
-	SeahorseGkrKeyringActions *self = SEAHORSE_GKR_KEYRING_ACTIONS (obj);
-
-	g_clear_object (&self->action_lock);
-	g_clear_object (&self->action_unlock);
-	g_clear_object (&self->action_default);
+	cloned = gtk_action_group_new ("KeyringObject");
+	gtk_action_group_set_translation_domain (cloned, GETTEXT_PACKAGE);
+
+	gtk_action_group_add_actions_full (cloned, KEYRINGS_ACTIONS,
+	                                   G_N_ELEMENTS (KEYRINGS_ACTIONS),
+	                                   seahorse_object_list_copy (objects),
+	                                   seahorse_object_list_free);
+	gtk_action_set_sensitive (gtk_action_group_get_action (cloned, "keyring-lock"), unlocked);
+	gtk_action_set_sensitive (gtk_action_group_get_action (cloned, "keyring-unlock"), locked);
+
+	/* Single object */
+	if (!objects->next) {
+		gtk_action_group_add_actions_full (cloned, KEYRING_ACTIONS,
+		                                   G_N_ELEMENTS (KEYRING_ACTIONS),
+		                                   g_object_ref (objects->data),
+		                                   g_object_unref);
+		gtk_action_set_sensitive (gtk_action_group_get_action (cloned, "keyring-default"), can_default);
+	}
 
-	G_OBJECT_CLASS (seahorse_gkr_keyring_actions_parent_class)->finalize (obj);
+	return cloned;
 }
 
 static void
 seahorse_gkr_keyring_actions_class_init (SeahorseGkrKeyringActionsClass *klass)
 {
 	SeahorseActionsClass *actions_class = SEAHORSE_ACTIONS_CLASS (klass);
-	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-	gobject_class->finalize = seahorse_gkr_keyring_actions_finalize;
-	actions_class->update = seahorse_gkr_keyring_actions_update;
+	actions_class->clone_for_objects = seahorse_gkr_keyring_actions_clone_for_objects;
 }
 
 GtkActionGroup *
@@ -470,7 +466,7 @@ static void
 on_password_properties (GtkAction *action,
                         gpointer user_data)
 {
-	seahorse_gkr_item_properties_show (seahorse_action_get_object (action),
+	seahorse_gkr_item_properties_show (SEAHORSE_GKR_ITEM (user_data),
 	                                   seahorse_action_get_window (action));
 }
 
@@ -501,7 +497,7 @@ on_delete_passwords (GtkAction *action,
 	gboolean ret;
 	guint num;
 
-	objects = seahorse_action_get_objects (action);
+	objects = user_data;
 	if (objects == NULL)
 		return;
 
@@ -524,7 +520,7 @@ on_delete_passwords (GtkAction *action,
 		seahorse_progress_show (cancellable, ngettext ("Deleting item", "Deleting items", num), TRUE);
 		g_object_unref (cancellable);
 	} else {
-		seahorse_action_cancel (action);
+		g_cancellable_cancel (g_cancellable_get_current ());
 
 	}
 
@@ -534,6 +530,9 @@ on_delete_passwords (GtkAction *action,
 static const GtkActionEntry ITEM_ACTIONS[] = {
 	{ "properties", GTK_STOCK_PROPERTIES, NULL, NULL,
 	  N_("Properties of the password."), G_CALLBACK (on_password_properties) },
+};
+
+static const GtkActionEntry ITEMS_ACTIONS[] = {
 	{ "delete", GTK_STOCK_DELETE, NULL, NULL,
 	  N_("Delete the password."), G_CALLBACK (on_delete_passwords) },
 };
@@ -541,15 +540,36 @@ static const GtkActionEntry ITEM_ACTIONS[] = {
 static void
 seahorse_gkr_item_actions_init (SeahorseGkrItemActions *self)
 {
-	GtkActionGroup *actions = GTK_ACTION_GROUP (self);
-	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
-	gtk_action_group_add_actions (actions, ITEM_ACTIONS, G_N_ELEMENTS (ITEM_ACTIONS), self);
+
+}
+
+static GtkActionGroup *
+seahorse_gkr_item_actions_clone_for_objects (SeahorseActions *actions,
+                                             GList *objects)
+{
+	GtkActionGroup *cloned;
+
+	cloned = gtk_action_group_new ("KeyringItem");
+	gtk_action_group_set_translation_domain (cloned, GETTEXT_PACKAGE);
+	gtk_action_group_add_actions_full (cloned, ITEMS_ACTIONS,
+	                                   G_N_ELEMENTS (ITEMS_ACTIONS),
+	                                   seahorse_object_list_copy (objects),
+	                                   seahorse_object_list_free);
+
+	if (!objects->next)
+		gtk_action_group_add_actions_full (cloned, ITEM_ACTIONS,
+		                                   G_N_ELEMENTS (ITEM_ACTIONS),
+		                                   g_object_ref (objects->data),
+		                                   g_object_unref);
+
+	return cloned;
 }
 
 static void
 seahorse_gkr_item_actions_class_init (SeahorseGkrItemActionsClass *klass)
 {
-
+	SeahorseActionsClass *actions_class = SEAHORSE_ACTIONS_CLASS (klass);
+	actions_class->clone_for_objects = seahorse_gkr_item_actions_clone_for_objects;
 }
 
 GtkActionGroup *
@@ -559,7 +579,7 @@ seahorse_gkr_item_actions_instance (void)
 
 	if (actions == NULL) {
 		actions = g_object_new (SEAHORSE_TYPE_GKR_ITEM_ACTIONS,
-		                        "name", "gkr-item",
+		                        "name", "KeyringItem",
 		                        NULL);
 		g_object_add_weak_pointer (G_OBJECT (actions),
 		                           (gpointer *)&actions);
diff --git a/libseahorse/seahorse-action.c b/libseahorse/seahorse-action.c
index 8f81653..ea42f24 100644
--- a/libseahorse/seahorse-action.c
+++ b/libseahorse/seahorse-action.c
@@ -23,139 +23,60 @@
 #include "config.h"
 
 #include "seahorse-action.h"
+#include "seahorse-actions.h"
 
 #include <gck/gck.h>
 
-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");
+		quark = g_quark_from_static_string ("seahorse-action-window");
 	return quark;
 }
 
-static SeahorseActionInfo *
-seahorse_action_info_lookup (GtkAction *action)
-{
-	SeahorseActionInfo *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), seahorse_action_info_quark (),
-		                         info, seahorse_action_info_free);
-	}
-
-	return info;
-}
-
 void
-seahorse_action_reset (GtkAction *action)
+seahorse_action_pre_activate_with_window (GtkAction *action,
+                                          GtkWindow *window)
 {
 	g_return_if_fail (GTK_IS_ACTION (action));
-	g_object_set_qdata (G_OBJECT (action), seahorse_action_info_quark (), NULL);
+	g_return_if_fail (window != NULL || GTK_IS_WINDOW (window));
+
+	g_object_set_qdata_full (G_OBJECT (action), seahorse_action_info_quark (),
+	                         window ? g_object_ref (window) : NULL, g_object_unref);
 }
 
 void
-seahorse_action_cancel (GtkAction *action)
+seahorse_action_activate_with_window (GtkAction *action,
+                                      GtkWindow *window)
 {
-	SeahorseActionInfo *info;
-
 	g_return_if_fail (GTK_IS_ACTION (action));
+	g_return_if_fail (window != NULL || GTK_IS_WINDOW (window));
 
-	info = seahorse_action_info_lookup (action);
-	if (info->cancellable)
-		g_cancellable_cancel (info->cancellable);
-}
-
-GtkWindow *
-seahorse_action_get_window (GtkAction *action)
-{
-	SeahorseActionInfo *info;
-
-	g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
-
-	info = seahorse_action_info_lookup (action);
-	return info->window;
-}
-
-gpointer
-seahorse_action_get_object (GtkAction *action)
-{
-	SeahorseActionInfo *info;
+	g_object_ref (action);
 
-	g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+	seahorse_action_pre_activate_with_window (action, window);
+	gtk_action_activate (action);
+	seahorse_action_post_activate (action);
 
-	info = seahorse_action_info_lookup (action);
-	return info->objects ? info->objects->data : NULL;
-}
-
-GList *
-seahorse_action_get_objects (GtkAction *action)
-{
-	SeahorseActionInfo *info;
-
-	g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
-
-	info = seahorse_action_info_lookup (action);
-	return info->objects;
+	g_object_unref (action);
 }
 
 void
-seahorse_action_set_window (GtkAction *action,
-                            GtkWindow *window)
+seahorse_action_post_activate (GtkAction *action)
 {
-	SeahorseActionInfo *info;
-
 	g_return_if_fail (GTK_IS_ACTION (action));
 
-	info = seahorse_action_info_lookup (action);
-	g_clear_object (&info->window);
-	info->window = window ? g_object_ref (window) : NULL;
+	g_object_set_qdata (G_OBJECT (action), seahorse_action_info_quark (), NULL);
 }
 
-void
-seahorse_action_set_objects (GtkAction *action,
-                             GList *objects)
-{
-	SeahorseActionInfo *info;
-
-	g_return_if_fail (GTK_IS_ACTION (action));
-
-	info = seahorse_action_info_lookup (action);
-	gck_list_unref_free (info->objects);
-	info->objects = gck_list_ref_copy (objects);
-}
 
-void
-seahorse_action_set_cancellable (GtkAction *action,
-                                 GCancellable *cancellable)
+GtkWindow *
+seahorse_action_get_window (GtkAction *action)
 {
-	SeahorseActionInfo *info;
-
-	g_return_if_fail (cancellable == NULL ||
-	                  G_IS_CANCELLABLE (cancellable));
-
-	info = seahorse_action_info_lookup (action);
-	g_clear_object (&info->cancellable);
-	info->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+	g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+	return g_object_get_qdata (G_OBJECT (action), seahorse_action_info_quark ());
 }
diff --git a/libseahorse/seahorse-action.h b/libseahorse/seahorse-action.h
index f9df96e..7eceafb 100644
--- a/libseahorse/seahorse-action.h
+++ b/libseahorse/seahorse-action.h
@@ -25,23 +25,14 @@
 
 #include <gtk/gtk.h>
 
-void                  seahorse_action_reset                     (GtkAction *action);
+void                  seahorse_action_pre_activate_with_window  (GtkAction *action,
+                                                                 GtkWindow *window);
 
-void                  seahorse_action_set_cancellable           (GtkAction *action,
-                                                                 GCancellable *cancellable);
+void                  seahorse_action_activate_with_window      (GtkAction *action,
+                                                                 GtkWindow *window);
 
-void                  seahorse_action_cancel                    (GtkAction *action);
+void                  seahorse_action_post_activate             (GtkAction *action);
 
 GtkWindow *           seahorse_action_get_window                (GtkAction *action);
 
-gpointer              seahorse_action_get_object                (GtkAction *action);
-
-GList *               seahorse_action_get_objects               (GtkAction *action);
-
-void                  seahorse_action_set_window                (GtkAction *action,
-                                                                 GtkWindow *window);
-
-void                  seahorse_action_set_objects               (GtkAction *action,
-                                                                 GList *objects);
-
 #endif
diff --git a/libseahorse/seahorse-actions.c b/libseahorse/seahorse-actions.c
index 50abfd1..8af7f89 100644
--- a/libseahorse/seahorse-actions.c
+++ b/libseahorse/seahorse-actions.c
@@ -30,11 +30,11 @@ struct _SeahorseActionsPrivate {
 
 G_DEFINE_TYPE (SeahorseActions, seahorse_actions, GTK_TYPE_ACTION_GROUP);
 
-static void
-seahorse_actions_real_update (SeahorseActions *self,
-                              GList *selected)
+static GtkActionGroup *
+seahorse_actions_real_clone_for_objects (SeahorseActions *self,
+                                         GList *selected)
 {
-
+	return gtk_action_group_new ("internal");
 }
 
 static void
@@ -57,8 +57,7 @@ static void
 seahorse_actions_class_init (SeahorseActionsClass *klass)
 {
 	g_type_class_add_private (klass, sizeof (SeahorseActionsPrivate));
-
-	klass->update = seahorse_actions_real_update;
+	klass->clone_for_objects = seahorse_actions_real_clone_for_objects;
 }
 
 const gchar *
@@ -69,15 +68,6 @@ seahorse_actions_get_definition (SeahorseActions* self)
 }
 
 void
-seahorse_actions_update (SeahorseActions *self,
-                         GList *selected)
-{
-	g_return_if_fail (SEAHORSE_IS_ACTIONS (self));
-	g_return_if_fail (SEAHORSE_ACTIONS_GET_CLASS (self)->update);
-	SEAHORSE_ACTIONS_GET_CLASS (self)->update (self, selected);
-}
-
-void
 seahorse_actions_register_definition (SeahorseActions *self,
                                       const gchar *definition)
 {
@@ -85,3 +75,18 @@ seahorse_actions_register_definition (SeahorseActions *self,
 	g_return_if_fail (self->pv->definition == NULL);
 	self->pv->definition = definition;
 }
+
+GtkActionGroup *
+seahorse_actions_clone_for_objects (GtkActionGroup *actions,
+                                    GList *objects)
+{
+	SeahorseActionsClass *klass;
+
+	g_return_val_if_fail (GTK_IS_ACTION_GROUP (actions), NULL);
+
+	if (!SEAHORSE_IS_ACTIONS (actions))
+		return g_object_ref (actions);
+	klass = SEAHORSE_ACTIONS_GET_CLASS (actions);
+	g_assert (klass->clone_for_objects != NULL);
+	return (klass->clone_for_objects) (SEAHORSE_ACTIONS (actions), objects);
+}
diff --git a/libseahorse/seahorse-actions.h b/libseahorse/seahorse-actions.h
index c67c101..9fdcce1 100644
--- a/libseahorse/seahorse-actions.h
+++ b/libseahorse/seahorse-actions.h
@@ -47,8 +47,8 @@ struct _SeahorseActions {
 struct _SeahorseActionsClass {
 	GtkActionGroupClass parent_class;
 
-	void        (*update)            (SeahorseActions *self,
-	                                  GList *selected);
+	GtkActionGroup *  (*clone_for_objects)  (SeahorseActions *actions,
+	                                         GList *objects);
 };
 
 GType                 seahorse_actions_get_type                 (void);
@@ -60,7 +60,7 @@ const gchar *         seahorse_actions_get_definition           (SeahorseActions
 void                  seahorse_actions_register_definition      (SeahorseActions *self,
                                                                  const gchar *definition);
 
-void                  seahorse_actions_update                   (SeahorseActions *actions,
-                                                                 GList *selected);
+GtkActionGroup *      seahorse_actions_clone_for_objects        (GtkActionGroup *actions,
+                                                                 GList *objects);
 
 #endif
diff --git a/libseahorse/seahorse-object-list.c b/libseahorse/seahorse-object-list.c
index 2435317..5d46088 100644
--- a/libseahorse/seahorse-object-list.c
+++ b/libseahorse/seahorse-object-list.c
@@ -64,12 +64,13 @@ seahorse_object_list_copy (GList *original)
 }
 
 void
-seahorse_object_list_free (GList *list)
+seahorse_object_list_free (gpointer list)
 {
 	GList *l;
-	
+
 	for (l = list; l; l = g_list_next (l))
 		g_object_unref (l->data);
+	g_list_free (list);
 }
 
 GType
diff --git a/libseahorse/seahorse-object-list.h b/libseahorse/seahorse-object-list.h
index b77068c..8a64916 100644
--- a/libseahorse/seahorse-object-list.h
+++ b/libseahorse/seahorse-object-list.h
@@ -37,6 +37,6 @@ GList*     seahorse_object_list_remove       (GList *original, gpointer object);
 
 GList*     seahorse_object_list_copy         (GList *original);
 
-void       seahorse_object_list_free         (GList *list);
+void       seahorse_object_list_free         (gpointer list);
 
 #endif /* SEAHORSEOBJECTLIST_H_ */
diff --git a/libseahorse/seahorse-viewer.c b/libseahorse/seahorse-viewer.c
index a8b8575..5be8b5b 100644
--- a/libseahorse/seahorse-viewer.c
+++ b/libseahorse/seahorse-viewer.c
@@ -50,8 +50,7 @@ struct _SeahorseViewerPrivate {
 	GHashTable *actions;
 	GtkAction *edit_delete;
 	GtkAction *properties_object;
-	GtkAction *properties_place;
-	GtkAction *properties_backend;
+	GList *selection_actions;
 };
 
 G_DEFINE_TYPE (SeahorseViewer, seahorse_viewer, SEAHORSE_TYPE_WIDGET);
@@ -128,73 +127,74 @@ on_help_show (GtkAction *action,
 	seahorse_widget_show_help (SEAHORSE_WIDGET (self));
 }
 
-static void
-on_object_delete (GtkAction *action,
-                  gpointer user_data)
+static GList *
+lookup_actions_for_objects (SeahorseViewer *self,
+                            GList *objects)
 {
-	SeahorseViewer *self = SEAHORSE_VIEWER (user_data);
-	GCancellable *cancellable;
 	GtkActionGroup *actions;
-	GtkAction *delete_action;
-	GList *objects;
-	GHashTable *perform;
 	GHashTableIter iter;
+	GList *results;
+	GHashTable *table;
 	GQueue *queue;
 	GList *l;
 
-	cancellable = g_cancellable_new ();
-	perform = g_hash_table_new_full (g_direct_hash, g_direct_equal,
-	                                 NULL, (GDestroyNotify)g_queue_free);
+	table = g_hash_table_new_full (g_direct_hash,
+	                               g_direct_equal,
+	                               g_object_unref,
+	                               (GDestroyNotify)g_queue_free);
 
-	objects = seahorse_viewer_get_selected_objects (self);
 	for (l = objects; l != NULL; l = g_list_next (l)) {
 		g_object_get (l->data, "actions", &actions, NULL);
-		delete_action = gtk_action_group_get_action (actions, "delete");
-		g_object_unref (actions);
-
-		if (delete_action == NULL)
+		if (actions == NULL)
 			continue;
-
-		queue = g_hash_table_lookup (perform, delete_action);
+		if (g_hash_table_lookup (self->pv->actions, actions) == NULL)
+			seahorse_viewer_include_actions (self, actions);
+		queue = g_hash_table_lookup (table, actions);
 		if (queue == NULL) {
 			queue = g_queue_new ();
-			g_hash_table_insert (perform, delete_action, queue);
+			g_hash_table_insert (table, g_object_ref (actions), queue);
 		}
 		g_queue_push_tail (queue, l->data);
+		g_object_unref (actions);
 	}
-	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);
+	results = NULL;
+	g_hash_table_iter_init (&iter, table);
+	while (g_hash_table_iter_next (&iter, (gpointer *)&actions, (gpointer *)&queue)) {
+		results = g_list_prepend (results,
+		      seahorse_actions_clone_for_objects (actions, queue->head));
 	}
 
-	g_object_unref (cancellable);
-	g_hash_table_destroy (perform);
+	g_hash_table_destroy (table);
+	return results;
 }
 
-static GtkAction *
-properties_action_for_object (GObject *object)
+static void
+on_object_delete (GtkAction *action,
+                  gpointer user_data)
 {
-	GtkActionGroup *actions = NULL;
-	GtkAction *action;
+	SeahorseViewer *self = SEAHORSE_VIEWER (user_data);
+	GCancellable *cancellable;
+	GtkAction *delete_action;
+	GtkWindow *window;
+	GList *l;
 
-	g_object_get (object, "actions", &actions, NULL);
-	if (actions == NULL)
-		return NULL;
+	cancellable = g_cancellable_new ();
 
-	action = gtk_action_group_get_action (actions, "properties");
-	g_object_unref (actions);
+	g_cancellable_push_current (cancellable);
+	window = seahorse_viewer_get_window (self);
+
+	/* Now go through and clone for the selection */
+	for (l = self->pv->selection_actions;
+	     l != NULL && !g_cancellable_is_cancelled (cancellable);
+	     l = g_list_next (l)) {
+		delete_action = gtk_action_group_get_action (l->data, "delete");
+		if (delete_action != NULL && gtk_action_is_sensitive (delete_action))
+			seahorse_action_activate_with_window (delete_action, window);
+	}
 
-	return action;
+	g_cancellable_pop_current (cancellable);
+	g_object_unref (cancellable);
 }
 
 static void
@@ -223,19 +223,6 @@ on_properties_place (GtkAction *action,
 	g_list_free (objects);
 }
 
-static void
-on_properties_backend (GtkAction *action,
-                       gpointer user_data)
-{
-	SeahorseViewer *self = SEAHORSE_VIEWER (user_data);
-	GList *objects;
-
-	objects = seahorse_viewer_get_selected_backends (self);
-	if (objects != NULL)
-		seahorse_viewer_show_properties (self, objects->data);
-	g_list_free (objects);
-}
-
 static const GtkActionEntry UI_ENTRIES[] = {
 
 	/* Top menu items */
@@ -247,8 +234,6 @@ static const GtkActionEntry UI_ENTRIES[] = {
 	  N_("Show the properties of this item"), G_CALLBACK (on_properties_object) },
 	{ "properties-place", GTK_STOCK_PROPERTIES, NULL, NULL,
 	  N_("Show the properties of this place"), G_CALLBACK (on_properties_place) },
-	{ "properties-backend", GTK_STOCK_PROPERTIES, NULL, NULL,
-	  N_("Show the properties of this backend"), G_CALLBACK (on_properties_backend) },
 	{ "app-preferences", GTK_STOCK_PREFERENCES, N_("Prefere_nces"), NULL,
 	  N_("Change preferences for this program"), G_CALLBACK (on_app_preferences) },
 	{ "view-menu", NULL, N_("_View") },
@@ -396,43 +381,8 @@ on_ui_manager_pre_activate (GtkUIManager *ui_manager,
                             gpointer user_data)
 {
 	SeahorseViewer *self = SEAHORSE_VIEWER (user_data);
-	GtkActionGroup *actions;
-	GList *selected = NULL;
-	GList *objects;
-	const gchar *name;
-	GList *l;
-
-	name = gtk_action_get_name (action);
-	g_return_if_fail (name != NULL);
-
-	/* These guys do their own object selection */
-	if (seahorse_action_get_object (action) ||
-	    action == self->pv->properties_object ||
-	    action == self->pv->properties_place ||
-	    action == self->pv->properties_backend ||
-	    action == self->pv->edit_delete)
-		return;
-
-	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));
-
-	for (l = objects; l != NULL; l = g_list_next (l)) {
-		actions = NULL;
-		g_object_get (l->data, "actions", &actions, NULL);
-		if (actions != NULL) {
-			if (gtk_action_group_get_action (actions, name) == action)
-				selected = g_list_prepend (selected, l->data);
-			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));
-
-	g_list_free (selected);
-	g_list_free (objects);
+	seahorse_action_pre_activate_with_window (action,
+	                                          seahorse_viewer_get_window (self));
 }
 
 static void
@@ -440,108 +390,49 @@ on_ui_manager_post_activate (GtkUIManager *ui_manager,
                              GtkAction *action,
                              gpointer user_data)
 {
-	seahorse_action_reset (action);
-}
-
-static void
-viewer_find_actions_for_selection (SeahorseViewer *self,
-                                   GHashTable *found,
-                                   GList *objects)
-{
-	GtkActionGroup *actions;
-	GPtrArray *selected;
-	GList *l;
-
-	for (l = objects; l != NULL; l = g_list_next (l)) {
-		actions = NULL;
-		g_object_get (l->data, "actions", &actions, NULL);
-		if (actions != NULL) {
-			if (g_hash_table_lookup (self->pv->actions, actions) == NULL) {
-				g_hash_table_insert (self->pv->actions, g_object_ref (actions), actions);
-				seahorse_viewer_include_actions (self, actions);
-			}
-			selected = g_hash_table_lookup (found, actions);
-			if (selected == NULL) {
-				selected = g_ptr_array_new ();
-				g_hash_table_insert (found, actions, selected);
-			}
-			g_ptr_array_add (selected, l->data);
-			g_object_unref (actions);
-		}
-	}
+	seahorse_action_post_activate (action);
 }
 
-
 static void
 seahorse_viewer_real_selection_changed (SeahorseViewer *self)
 {
-	GHashTableIter iter;
-	GHashTable *seen;
+	GList *groups;
 	GList *objects;
-	GPtrArray *selected;
-	GtkActionGroup *actions;
-	GtkAction *action;
-	gboolean deletes;
-	guint i;
-
-	seen = g_hash_table_new_full (g_direct_hash, g_direct_equal,
-	                              NULL, (GDestroyNotify)g_ptr_array_unref);
+	GList *previous;
+	gboolean can_properties;
+	gboolean can_delete;
+	GList *l;
 
 	objects = seahorse_viewer_get_selected_objects (self);
-	viewer_find_actions_for_selection (self, seen, objects);
-	if (objects != NULL)
-		gtk_action_set_sensitive (self->pv->properties_object,
-		                          properties_action_for_object (objects->data) != NULL);
+	groups = lookup_actions_for_objects (self, objects);
 	g_list_free (objects);
 
-	/*
-	 * At this point we only have the actions for real objects, so hook
-	 * in the delete logic here.
-	 */
-
-	deletes = FALSE;
+	can_properties = FALSE;
+	can_delete = FALSE;
 
-	g_hash_table_iter_init (&iter, seen);
-	while (g_hash_table_iter_next (&iter, (gpointer *)&actions, NULL)) {
-		action = gtk_action_group_get_action (actions, "delete");
-		if (action != NULL)
-			deletes = TRUE;
+	/* Add all those actions */
+	for (l = groups; l != NULL; l = g_list_next (l)) {
+		if (gtk_action_group_get_action (l->data, "properties"))
+			can_properties = TRUE;
+		if (gtk_action_group_get_action (l->data, "delete"))
+			can_delete = TRUE;
 	}
 
-	gtk_action_set_sensitive (self->pv->edit_delete, deletes);
+	gtk_action_set_sensitive (self->pv->properties_object, can_properties);
+	gtk_action_set_sensitive (self->pv->edit_delete, can_delete);
 
-	/* Now proceed to bring in the other commands */
 	objects = seahorse_viewer_get_selected_places (self);
-	viewer_find_actions_for_selection (self, seen, objects);
-	if (objects != NULL)
-		gtk_action_set_sensitive (self->pv->properties_place,
-		                          properties_action_for_object (objects->data) != NULL);
+	groups = g_list_concat (groups, lookup_actions_for_objects (self, objects));
 	g_list_free (objects);
 
-	objects = seahorse_viewer_get_selected_backends (self);
-	viewer_find_actions_for_selection (self, seen, objects);
-	if (objects != NULL)
-		gtk_action_set_sensitive (self->pv->properties_backend,
-		                          properties_action_for_object (objects->data) != NULL);
-	g_list_free (objects);
-
-	g_hash_table_iter_init (&iter, self->pv->actions);
-	while (g_hash_table_iter_next (&iter, (gpointer *)&actions, NULL))
-		gtk_action_group_set_visible (actions, g_hash_table_lookup (seen, actions) != NULL);
-
-	g_hash_table_iter_init (&iter, seen);
-	while (g_hash_table_iter_next (&iter, (gpointer *)&actions, (gpointer *)&selected)) {
-		if (SEAHORSE_IS_ACTIONS (actions)) {
-			objects = NULL;
-			for (i = 0; i < selected->len; i++)
-				objects = g_list_prepend (objects, selected->pdata[i]);
-			objects = g_list_reverse (objects);
-			seahorse_actions_update (SEAHORSE_ACTIONS (actions), objects);
-			g_list_free (objects);
-		}
-	}
+	previous = self->pv->selection_actions;
+	self->pv->selection_actions = groups;
 
-	g_hash_table_destroy (seen);
+	for (l = self->pv->selection_actions; l != NULL; l = g_list_next (l))
+		gtk_ui_manager_insert_action_group (self->pv->ui_manager, l->data, 5);
+	for (l = previous; l != NULL; l = g_list_next (l))
+		gtk_ui_manager_remove_action_group (self->pv->ui_manager, l->data);
+	g_list_free_full (previous, g_object_unref);
 }
 
 static void
@@ -603,10 +494,6 @@ seahorse_viewer_constructed (GObject *obj)
 	g_object_ref (self->pv->edit_delete);
 	self->pv->properties_object = gtk_action_group_get_action (actions, "properties-object");
 	g_object_ref (self->pv->properties_object);
-	self->pv->properties_place = gtk_action_group_get_action (actions, "properties-place");
-	g_object_ref (self->pv->properties_place);
-	self->pv->properties_backend = gtk_action_group_get_action (actions, "properties-backend");
-	g_object_ref (self->pv->properties_backend);
 	gtk_ui_manager_insert_action_group (self->pv->ui_manager, actions, 0);
 	g_object_unref (actions);
 }
@@ -632,11 +519,14 @@ static void
 seahorse_viewer_dispose (GObject *obj)
 {
 	SeahorseViewer *self = SEAHORSE_VIEWER (obj);
+	GList *l;
 
 	g_clear_object (&self->pv->edit_delete);
 	g_clear_object (&self->pv->properties_object);
-	g_clear_object (&self->pv->properties_place);
-	g_clear_object (&self->pv->properties_backend);
+
+	for (l = self->pv->selection_actions; l != NULL; l = g_list_next (l))
+		gtk_ui_manager_remove_action_group (self->pv->ui_manager, l->data);
+	g_list_free_full (self->pv->selection_actions, g_object_unref);
 
 	g_signal_handlers_disconnect_by_func (self->pv->ui_manager, on_ui_manager_add_widget, self);
 	g_signal_handlers_disconnect_by_func (self->pv->ui_manager, on_ui_manager_pre_activate, self);
@@ -716,7 +606,7 @@ seahorse_viewer_include_actions (SeahorseViewer* self,
 	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
 	g_return_if_fail (GTK_IS_ACTION_GROUP (actions));
 
-	gtk_ui_manager_insert_action_group (self->pv->ui_manager, actions, 0);
+	gtk_ui_manager_insert_action_group (self->pv->ui_manager, actions, 10);
 
 	if (SEAHORSE_IS_ACTIONS (actions)) {
 		definition = seahorse_actions_get_definition (SEAHORSE_ACTIONS (actions));
@@ -729,6 +619,8 @@ seahorse_viewer_include_actions (SeahorseViewer* self,
 			}
 		}
 	}
+
+	g_hash_table_insert (self->pv->actions, g_object_ref (actions), actions);
 }
 
 void
@@ -762,21 +654,24 @@ void
 seahorse_viewer_show_properties (SeahorseViewer* self,
                                  GObject* obj)
 {
+	GtkActionGroup *actions, *cloned;
 	GtkAction *action;
 	GList *objects;
 
-	action = properties_action_for_object (obj);
-	if (action == NULL)
+	g_object_get (obj, "actions", &actions, NULL);
+	if (actions == NULL)
 		return;
 
 	objects = g_list_append (NULL, obj);
-	seahorse_action_set_objects (action, objects);
-	seahorse_action_set_window (action, seahorse_viewer_get_window (self));
+	cloned = seahorse_actions_clone_for_objects (actions, objects);
+	g_object_unref (actions);
 	g_list_free (objects);
 
-	gtk_action_activate (action);
+	action = gtk_action_group_get_action (cloned, "properties");
+	if (action != NULL)
+		seahorse_action_activate_with_window (action, seahorse_viewer_get_window (self));
 
-	seahorse_action_reset (action);
+	g_object_unref (cloned);
 }
 
 GtkWindow *
@@ -803,9 +698,9 @@ seahorse_viewer_get_selected_places (SeahorseViewer* self)
 }
 
 GList *
-seahorse_viewer_get_selected_backends (SeahorseViewer* self)
+seahorse_viewer_get_backends (SeahorseViewer* self)
 {
 	g_return_val_if_fail (SEAHORSE_IS_VIEWER (self), NULL);
-	g_return_val_if_fail (SEAHORSE_VIEWER_GET_CLASS (self)->get_selected_backends, NULL);
-	return SEAHORSE_VIEWER_GET_CLASS (self)->get_selected_backends (self);
+	g_return_val_if_fail (SEAHORSE_VIEWER_GET_CLASS (self)->get_backends, NULL);
+	return SEAHORSE_VIEWER_GET_CLASS (self)->get_backends (self);
 }
diff --git a/libseahorse/seahorse-viewer.h b/libseahorse/seahorse-viewer.h
index 4a6508b..526bb1d 100644
--- a/libseahorse/seahorse-viewer.h
+++ b/libseahorse/seahorse-viewer.h
@@ -47,7 +47,7 @@ struct _SeahorseViewer {
 struct _SeahorseViewerClass {
 	SeahorseWidgetClass parent;
 
-	GList *          (*get_selected_backends)         (SeahorseViewer *self);
+	GList *          (*get_backends)                  (SeahorseViewer *self);
 
 	GList *          (*get_selected_places)           (SeahorseViewer *self);
 
@@ -67,7 +67,7 @@ GList *             seahorse_viewer_get_selected_objects            (SeahorseVie
 
 GList *             seahorse_viewer_get_selected_places             (SeahorseViewer* self);
 
-GList *             seahorse_viewer_get_selected_backends           (SeahorseViewer* self);
+GList *             seahorse_viewer_get_backends                    (SeahorseViewer* self);
 
 void                seahorse_viewer_show_context_menu               (SeahorseViewer* self,
                                                                      const gchar *which,
@@ -77,26 +77,6 @@ void                seahorse_viewer_show_context_menu               (SeahorseVie
 void                seahorse_viewer_show_properties                 (SeahorseViewer* self,
                                                                      GObject* obj);
 
-#if 0
-void                seahorse_viewer_set_status                      (SeahorseViewer* self,
-                                                                     const char* text);
-
-void                seahorse_viewer_set_numbered_status             (SeahorseViewer* self,
-                                                                     const char* text,
-                                                                     gint num);
-#endif
-
 GtkWindow *         seahorse_viewer_get_window                      (SeahorseViewer* self);
 
-#if 0
-void                seahorse_viewer_register_ui                     (SeahorseViewer *self,
-                                                                     SeahorsePredicate *pred,
-                                                                     const gchar *uidef,
-                                                                     GtkActionGroup *actions);
-
-void                seahorse_viewer_register_commands               (SeahorseViewer *self,
-                                                                     SeahorsePredicate *pred,
-                                                                     SeahorseCommands *commands);
-#endif
-
 #endif /* __SEAHORSE_VIEWER_H__ */
diff --git a/pgp/seahorse-keyserver-results.c b/pgp/seahorse-keyserver-results.c
index 7207749..6f74c00 100644
--- a/pgp/seahorse-keyserver-results.c
+++ b/pgp/seahorse-keyserver-results.c
@@ -264,12 +264,6 @@ seahorse_keyserver_results_get_selected_objects (SeahorseViewer* viewer)
 }
 
 static GList *
-seahorse_keyserver_results_get_selected_backends (SeahorseViewer* viewer)
-{
-	return NULL;
-}
-
-static GList *
 seahorse_keyserver_results_get_selected_places (SeahorseViewer* viewer)
 {
 	return NULL;
@@ -347,6 +341,12 @@ seahorse_keyserver_results_constructor (GType type, guint n_props, GObjectConstr
 	                                                  self->pv->settings);
 	on_view_selection_changed (selection, self);
 
+	/* Include actions from the backend */
+	actions = NULL;
+	g_object_get (seahorse_pgp_backend_get (), "actions", &actions, NULL);
+	seahorse_viewer_include_actions (SEAHORSE_VIEWER (self), actions);
+	g_object_unref (actions);
+
 	return G_OBJECT (self);
 }
 
@@ -473,7 +473,6 @@ seahorse_keyserver_results_class_init (SeahorseKeyserverResultsClass *klass)
 
 	SEAHORSE_VIEWER_CLASS (klass)->get_selected_objects = seahorse_keyserver_results_get_selected_objects;
 	SEAHORSE_VIEWER_CLASS (klass)->get_selected_places = seahorse_keyserver_results_get_selected_places;
-	SEAHORSE_VIEWER_CLASS (klass)->get_selected_backends = seahorse_keyserver_results_get_selected_backends;
 
 	g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEARCH,
 	         g_param_spec_string ("search", "search", "search", NULL,
diff --git a/pgp/seahorse-pgp-actions.c b/pgp/seahorse-pgp-actions.c
index 9a2b7db..f90786b 100644
--- a/pgp/seahorse-pgp-actions.c
+++ b/pgp/seahorse-pgp-actions.c
@@ -37,6 +37,7 @@
 #include "seahorse-action.h"
 #include "seahorse-actions.h"
 #include "seahorse-object.h"
+#include "seahorse-object-list.h"
 #include "seahorse-registry.h"
 #include "seahorse-util.h"
 
@@ -82,9 +83,8 @@ on_remote_sync (GtkAction* action,
                 gpointer user_data)
 {
 	SeahorseGpgmeKeyring *keyring;
-	GList* objects;
+	GList* objects = user_data;
 
-	objects = seahorse_action_get_objects (action);
 	if (objects == NULL) {
 		keyring = seahorse_pgp_backend_get_default_keyring (NULL);
 		objects = gcr_collection_get_objects (GCR_COLLECTION (keyring));
@@ -96,9 +96,12 @@ on_remote_sync (GtkAction* action,
 	g_list_free (objects);
 }
 
-static const GtkActionEntry BACKEND_ACTIONS[] = {
+static const GtkActionEntry FIND_ACTIONS[] = {
 	{ "remote-find", GTK_STOCK_FIND, N_("_Find Remote Keys..."), "",
 	  N_("Search for keys on a key server"), G_CALLBACK (on_remote_find) },
+};
+
+static const GtkActionEntry SYNC_ACTIONS[] = {
 	{ "remote-sync", GTK_STOCK_REFRESH, N_("_Sync and Publish Keys..."), "",
 	  N_("Publish and/or synchronize your keys with those online."), G_CALLBACK (on_remote_sync) }
 };
@@ -108,8 +111,10 @@ seahorse_pgp_backend_actions_init (SeahorsePgpBackendActions *self)
 {
 	GtkActionGroup *actions = GTK_ACTION_GROUP (self);
 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
-	gtk_action_group_add_actions (actions, BACKEND_ACTIONS,
-	                              G_N_ELEMENTS (BACKEND_ACTIONS), self);
+	gtk_action_group_add_actions (actions, FIND_ACTIONS,
+	                              G_N_ELEMENTS (FIND_ACTIONS), NULL);
+	gtk_action_group_add_actions (actions, SYNC_ACTIONS,
+	                              G_N_ELEMENTS (SYNC_ACTIONS), NULL);
 	seahorse_actions_register_definition (SEAHORSE_ACTIONS (self), BACKEND_DEFINITION);
 }
 
@@ -174,19 +179,20 @@ on_key_sign (GtkAction* action,
              gpointer user_data)
 {
 	GtkWindow *window;
-	GObject *key;
+	GList *objects = user_data;
+
+	g_return_if_fail (objects->data);
 
-	key = seahorse_action_get_object (action);
 	window = seahorse_action_get_window (action);
 
-	seahorse_gpgme_sign_prompt (SEAHORSE_GPGME_KEY (key), window);
+	seahorse_gpgme_sign_prompt (SEAHORSE_GPGME_KEY (objects->data), window);
 }
 
 static void
 on_show_properties (GtkAction *action,
                     gpointer user_data)
 {
-	seahorse_pgp_key_properties_show (seahorse_action_get_object (action),
+	seahorse_pgp_key_properties_show (SEAHORSE_PGP_KEY (user_data),
 	                                  seahorse_action_get_window (action));
 }
 
@@ -206,7 +212,7 @@ on_delete_objects (GtkAction *action,
 	GError *error = NULL;
 	GList *objects;
 
-	objects = seahorse_action_get_objects (action);
+	objects = user_data;
 	num = g_list_length (objects);
 	if (num == 0)
 		return;
@@ -260,7 +266,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);
+		g_cancellable_cancel (g_cancellable_get_current ());
 		return;
 	}
 
@@ -292,6 +298,9 @@ static const GtkActionEntry KEY_ACTIONS[] = {
 	  N_("Sign public key"), G_CALLBACK (on_key_sign) },
 	{ "properties", GTK_STOCK_PROPERTIES, NULL, NULL,
 	  N_("Properties of the key."), G_CALLBACK (on_show_properties) },
+};
+
+static const GtkActionEntry KEYS_ACTIONS[] = {
 	{ "delete", GTK_STOCK_DELETE, NULL, NULL,
 	  N_("Delete the key."), G_CALLBACK (on_delete_objects) },
 };
@@ -302,15 +311,48 @@ seahorse_gpgme_key_actions_init (SeahorseGpgmeKeyActions *self)
 	GtkActionGroup *actions = GTK_ACTION_GROUP (self);
 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
 	gtk_action_group_add_actions (actions, KEY_ACTIONS,
-	                              G_N_ELEMENTS (KEY_ACTIONS), self);
+	                              G_N_ELEMENTS (KEY_ACTIONS), NULL);
+	gtk_action_group_add_actions (actions, KEYS_ACTIONS,
+	                              G_N_ELEMENTS (KEYS_ACTIONS), NULL);
+	gtk_action_group_set_visible (actions, FALSE);
 	seahorse_actions_register_definition (SEAHORSE_ACTIONS (self), KEY_DEFINITION);
 
 }
 
+static GtkActionGroup *
+seahorse_gpgme_key_actions_clone_for_objects (SeahorseActions *actions,
+                                              GList *objects)
+{
+	GtkActionGroup *cloned;
+
+	g_return_val_if_fail (objects != NULL, NULL);
+
+	cloned = gtk_action_group_new ("GpgmeKey");
+	gtk_action_group_add_actions_full (cloned, KEYS_ACTIONS,
+	                                   G_N_ELEMENTS (KEYS_ACTIONS),
+	                                   seahorse_object_list_copy (objects),
+	                                   seahorse_object_list_free);
+	gtk_action_group_add_actions_full (cloned, SYNC_ACTIONS,
+	                                   G_N_ELEMENTS (SYNC_ACTIONS),
+	                                   seahorse_object_list_copy (objects),
+	                                   seahorse_object_list_free);
+
+	/* Single key */
+	if (!objects->next) {
+		gtk_action_group_add_actions_full (cloned, KEY_ACTIONS,
+		                                   G_N_ELEMENTS (KEY_ACTIONS),
+		                                   g_object_ref (objects->data),
+		                                   g_object_unref);
+	}
+
+	return cloned;
+}
+
 static void
 seahorse_gpgme_key_actions_class_init (SeahorseGpgmeKeyActionsClass *klass)
 {
-
+	SeahorseActionsClass *actions_class = SEAHORSE_ACTIONS_CLASS (klass);
+	actions_class->clone_for_objects = seahorse_gpgme_key_actions_clone_for_objects;
 }
 
 GtkActionGroup *
diff --git a/pkcs11/seahorse-pkcs11-actions.c b/pkcs11/seahorse-pkcs11-actions.c
index 94599d3..160080f 100644
--- a/pkcs11/seahorse-pkcs11-actions.c
+++ b/pkcs11/seahorse-pkcs11-actions.c
@@ -31,6 +31,7 @@
 
 #include "seahorse-action.h"
 #include "seahorse-actions.h"
+#include "seahorse-object-list.h"
 #include "seahorse-progress.h"
 #include "seahorse-registry.h"
 #include "seahorse-util.h"
@@ -69,10 +70,10 @@ on_show_properties (GtkAction *action,
 	gpointer previous;
 	GObject *object;
 
-	object = seahorse_action_get_object (action);
+	object = G_OBJECT (user_data);
 
 	/* Try to show an already present window */
-	previous = g_object_get_qdata (G_OBJECT (object), QUARK_WINDOW);
+	previous = g_object_get_qdata (object, QUARK_WINDOW);
 	if (GTK_IS_WINDOW (previous)) {
 		window = GTK_WINDOW (previous);
 		if (gtk_widget_get_visible (GTK_WIDGET (window))) {
@@ -111,17 +112,18 @@ on_delete_objects (GtkAction *action,
 {
 	GCancellable *cancellable;
 	gchar *prompt;
-	const gchar *display;
+	gchar *display;
 	GtkWidget *parent;
 	gboolean ret;
 	guint num;
 	GList *objects;
 
-	objects = seahorse_action_get_objects (action);
+	objects = user_data;
 	num = g_list_length (objects);
 	if (num == 1) {
-		display = seahorse_object_get_label (SEAHORSE_OBJECT (objects->data));
+		g_object_get (objects->data, "label", &display, NULL);
 		prompt = g_strdup_printf (_("Are you sure you want to delete the certificate '%s'?"), display);
+		g_free (display);
 	} else {
 		prompt = g_strdup_printf (ngettext (
 				"Are you sure you want to delete %d certificate?",
@@ -140,13 +142,16 @@ on_delete_objects (GtkAction *action,
 		seahorse_progress_show (cancellable, _("Deleting"), TRUE);
 		g_object_unref (cancellable);
 	} else {
-		seahorse_action_cancel (action);
+		g_cancellable_cancel (g_cancellable_get_current ());
 	}
 }
 
 static const GtkActionEntry CERTIFICATE_ACTIONS[] = {
 	{ "properties", GTK_STOCK_PROPERTIES, NULL, NULL,
 	  N_("Properties of the certificate."), G_CALLBACK (on_show_properties) },
+};
+
+static const GtkActionEntry CERTIFICATES_ACTIONS[] = {
 	{ "delete", GTK_STOCK_DELETE, NULL, NULL,
 	  N_("Delete the certificate."), G_CALLBACK (on_delete_objects) },
 };
@@ -154,15 +159,40 @@ static const GtkActionEntry CERTIFICATE_ACTIONS[] = {
 static void
 seahorse_pkcs11_actions_init (SeahorsePkcs11Actions *self)
 {
-	GtkActionGroup *actions = GTK_ACTION_GROUP (self);
-	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
-	gtk_action_group_add_actions (actions, CERTIFICATE_ACTIONS, G_N_ELEMENTS (CERTIFICATE_ACTIONS), self);
+
+}
+
+static GtkActionGroup *
+seahorse_pkcs11_actions_clone_for_objects (SeahorseActions *actions,
+                                           GList *objects)
+{
+	GtkActionGroup *cloned;
+
+	g_return_val_if_fail (objects != NULL, NULL);
+
+	cloned = gtk_action_group_new ("Certificate");
+	gtk_action_group_set_translation_domain (cloned, GETTEXT_PACKAGE);
+	gtk_action_group_add_actions_full (cloned, CERTIFICATES_ACTIONS,
+	                                   G_N_ELEMENTS (CERTIFICATES_ACTIONS),
+	                                   seahorse_object_list_copy (objects),
+	                                   seahorse_object_list_free);
+
+	/* Only one object? */
+	if (!objects->next)
+		gtk_action_group_add_actions_full (cloned, CERTIFICATE_ACTIONS,
+		                                   G_N_ELEMENTS (CERTIFICATE_ACTIONS),
+		                                   g_object_ref (objects->data),
+		                                   g_object_unref);
+
+	return cloned;
 }
 
 static void
 seahorse_pkcs11_actions_class_init (SeahorsePkcs11ActionsClass *klass)
 {
+	SeahorseActionsClass *actions_class = SEAHORSE_ACTIONS_CLASS (klass);
 	QUARK_WINDOW = g_quark_from_static_string ("seahorse-pkcs11-actions-window");
+	actions_class->clone_for_objects = seahorse_pkcs11_actions_clone_for_objects;
 }
 
 GtkActionGroup *
@@ -172,7 +202,7 @@ seahorse_pkcs11_actions_instance (void)
 
 	if (actions == NULL) {
 		actions = g_object_new (SEAHORSE_TYPE_PKCS11_ACTIONS,
-		                        "name", "pkcs11-certificate",
+		                        "name", "Certificate",
 		                        NULL);
 		g_object_add_weak_pointer (G_OBJECT (actions),
 		                           (gpointer *)&actions);
diff --git a/src/seahorse-generate-select.c b/src/seahorse-generate-select.c
index 7fdd201..28f4824 100644
--- a/src/seahorse-generate-select.c
+++ b/src/seahorse-generate-select.c
@@ -69,7 +69,6 @@ get_selected_action (SeahorseGenerateSelect *self)
 	GtkTreeIter iter;
 	GtkTreeModel *model;
 	GtkAction *action;
-	GtkWindow *parent;
 
 	selection = gtk_tree_view_get_selection (self->view);
 	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
@@ -79,9 +78,6 @@ get_selected_action (SeahorseGenerateSelect *self)
 	                    COLUMN_ACTION, &action, -1);
 	g_assert (action != NULL);
 
-	parent = gtk_window_get_transient_for (GTK_WINDOW (self));
-	seahorse_action_set_window (action, parent);
-
 	return action;
 }
 
@@ -93,12 +89,20 @@ on_row_activated (GtkTreeView *view,
 {
 	SeahorseGenerateSelect *self = SEAHORSE_GENERATE_SELECT (user_data);
 	GtkAction *action;
+	GtkWindow *parent;
 
 	action = get_selected_action (self);
 	if (action != NULL) {
+		parent = gtk_window_get_transient_for (GTK_WINDOW (self));
+		if (parent != NULL)
+			g_object_ref (parent);
+
 		g_object_ref (action);
 		gtk_widget_destroy (GTK_WIDGET (self));
-		gtk_action_activate (action);
+
+		seahorse_action_activate_with_window (action, parent);
+
+		g_clear_object (&parent);
 		g_object_unref (action);
 	}
 }
@@ -110,17 +114,23 @@ on_response (GtkDialog *dialog,
 {
 	SeahorseGenerateSelect *self = SEAHORSE_GENERATE_SELECT (user_data);
 	GtkAction *action = NULL;
+	GtkWindow *parent = NULL;
 
 	if (response == GTK_RESPONSE_OK) 
 		action = get_selected_action (self);
-	if (action != NULL)
+	if (action != NULL) {
 		g_object_ref (action);
+		parent = gtk_window_get_transient_for (GTK_WINDOW (self));
+		if (parent != NULL)
+			g_object_ref (parent);
+	}
 
 	gtk_widget_destroy (GTK_WIDGET (self));
 
 	if (action != NULL) {
-		gtk_action_activate (action);
+		seahorse_action_activate_with_window (action, parent);
 		g_object_unref (action);
+		g_clear_object (&parent);
 	}
 }
 
diff --git a/src/seahorse-key-manager.c b/src/seahorse-key-manager.c
index 0d88f61..c0e94c4 100644
--- a/src/seahorse-key-manager.c
+++ b/src/seahorse-key-manager.c
@@ -478,13 +478,6 @@ seahorse_key_manager_get_selected_places (SeahorseViewer* viewer)
 	return seahorse_sidebar_get_selected_places (self->pv->sidebar);
 }
 
-static GList *
-seahorse_key_manager_get_selected_backends (SeahorseViewer* viewer)
-{
-	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (viewer);
-	return seahorse_sidebar_get_backends (self->pv->sidebar);
-}
-
 static gboolean
 on_idle_save_sidebar_width (gpointer user_data)
 {
@@ -533,6 +526,7 @@ setup_sidebar (SeahorseKeyManager *self)
 	GtkWidget *area, *panes;
 	GtkActionGroup *actions;
 	GtkAction *action;
+	GList *backends, *l;
 
 	self->pv->sidebar = seahorse_sidebar_new ();
 	area = seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "sidebar-area");
@@ -566,6 +560,16 @@ setup_sidebar (SeahorseKeyManager *self)
 	g_signal_connect (self->pv->sidebar, "size_allocate", G_CALLBACK (on_sidebar_panes_size_allocate), self);
 	g_signal_connect (self->pv->sidebar, "context-menu", G_CALLBACK (on_sidebar_popup_menu), self);
 
+	backends = seahorse_sidebar_get_backends (self->pv->sidebar);
+	for (l = backends; l != NULL; l = g_list_next (l)) {
+		actions = NULL;
+		g_object_get (l->data, "actions", &actions, NULL);
+		if (actions != NULL) {
+			seahorse_viewer_include_actions (SEAHORSE_VIEWER (self), actions);
+			g_object_unref (actions);
+		}
+	}
+
 	return seahorse_sidebar_get_collection (self->pv->sidebar);
 }
 
@@ -584,7 +588,7 @@ seahorse_key_manager_constructed (GObject *object)
 	self->pv->collection = setup_sidebar (self);
 
 	gtk_window_set_title (seahorse_viewer_get_window (SEAHORSE_VIEWER (self)), _("Passwords and Keys"));
-	
+
 	actions = gtk_action_group_new ("general");
 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
 	gtk_action_group_add_actions (actions, GENERAL_ACTIONS, G_N_ELEMENTS (GENERAL_ACTIONS), self);
@@ -760,7 +764,6 @@ seahorse_key_manager_class_init (SeahorseKeyManagerClass *klass)
 
 	SEAHORSE_VIEWER_CLASS (klass)->get_selected_objects = seahorse_key_manager_get_selected_objects;
 	SEAHORSE_VIEWER_CLASS (klass)->get_selected_places = seahorse_key_manager_get_selected_places;
-	SEAHORSE_VIEWER_CLASS (klass)->get_selected_backends = seahorse_key_manager_get_selected_backends;
 }
 
 SeahorseWidget *
diff --git a/ssh/seahorse-ssh-actions.c b/ssh/seahorse-ssh-actions.c
index 917518c..2741a77 100644
--- a/ssh/seahorse-ssh-actions.c
+++ b/ssh/seahorse-ssh-actions.c
@@ -30,6 +30,7 @@
 #include "seahorse-action.h"
 #include "seahorse-actions.h"
 #include "seahorse-object.h"
+#include "seahorse-object-list.h"
 #include "seahorse-registry.h"
 #include "seahorse-util.h"
 
@@ -72,9 +73,8 @@ static void
 on_ssh_upload (GtkAction* action,
                gpointer user_data)
 {
-	GList *ssh_keys;
+	GList *ssh_keys = user_data;
 
-	ssh_keys = seahorse_action_get_objects (action);
 	if (ssh_keys == NULL)
 		return;
 
@@ -85,7 +85,7 @@ static void
 on_show_properties (GtkAction *action,
                     gpointer user_data)
 {
-	seahorse_ssh_key_properties_show (seahorse_action_get_object (action),
+	seahorse_ssh_key_properties_show (SEAHORSE_SSH_KEY (user_data),
 	                                  seahorse_action_get_window (action));
 }
 
@@ -100,7 +100,7 @@ on_delete_objects (GtkAction *action,
 	GError *error = NULL;
 	GList* objects;
 
-	objects = seahorse_action_get_objects (action);
+	objects = user_data;
 	num = g_list_length (objects);
 	if (num == 0) {
 		return;
@@ -121,36 +121,67 @@ on_delete_objects (GtkAction *action,
 			}
 		}
 	} else {
-		seahorse_action_cancel (action);
+		g_cancellable_cancel (g_cancellable_get_current ());
 	}
 
 	g_free (prompt);
 
 }
 
-static const GtkActionEntry KEY_ACTIONS[] = {
+static const GtkActionEntry KEYS_ACTIONS[] = {
 	{ "remote-ssh-upload", NULL, N_ ("Configure Key for _Secure Shell..."), "",
 		N_ ("Send public Secure Shell key to another machine, and enable logins using that key."),
 		G_CALLBACK (on_ssh_upload) },
-	{ "properties", GTK_STOCK_PROPERTIES, NULL, NULL,
-	  N_("Properties of the key."), G_CALLBACK (on_show_properties) },
 	{ "delete", GTK_STOCK_DELETE, NULL, NULL,
 	  N_("Delete the key."), G_CALLBACK (on_delete_objects) },
 };
 
+static const GtkActionEntry KEY_ACTIONS[] = {
+	{ "properties", GTK_STOCK_PROPERTIES, NULL, NULL,
+	  N_("Properties of the key."), G_CALLBACK (on_show_properties) },
+};
+
 static void
 seahorse_ssh_actions_init (SeahorseSshActions *self)
 {
 	GtkActionGroup *actions = GTK_ACTION_GROUP (self);
 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
-	gtk_action_group_add_actions (actions, KEY_ACTIONS, G_N_ELEMENTS (KEY_ACTIONS), self);
+	gtk_action_group_add_actions (actions, KEYS_ACTIONS, G_N_ELEMENTS (KEYS_ACTIONS), NULL);
+	gtk_action_group_set_visible (actions, FALSE);
 	seahorse_actions_register_definition (SEAHORSE_ACTIONS (self), UI_DEFINITION);
 }
 
+static GtkActionGroup *
+seahorse_ssh_actions_clone_for_objects (SeahorseActions *actions,
+                                        GList *objects)
+{
+	GtkActionGroup *cloned;
+
+	g_return_val_if_fail (actions, NULL);
+
+	cloned = gtk_action_group_new ("SshKey");
+	gtk_action_group_set_translation_domain (cloned, GETTEXT_PACKAGE);
+
+	gtk_action_group_add_actions_full (cloned, KEYS_ACTIONS,
+	                                   G_N_ELEMENTS (KEYS_ACTIONS),
+	                                   seahorse_object_list_copy (objects),
+	                                   seahorse_object_list_free);
+
+	/* A single object */
+	if (!objects->next)
+		gtk_action_group_add_actions_full (cloned, KEY_ACTIONS,
+		                                   G_N_ELEMENTS (KEY_ACTIONS),
+		                                   g_object_ref (objects->data),
+		                                   g_object_unref);
+
+	return cloned;
+}
+
 static void
 seahorse_ssh_actions_class_init (SeahorseSshActionsClass *klass)
 {
-
+	SeahorseActionsClass *actions_class = SEAHORSE_ACTIONS_CLASS (klass);
+	actions_class->clone_for_objects = seahorse_ssh_actions_clone_for_objects;
 }
 
 GtkActionGroup *
@@ -160,7 +191,7 @@ seahorse_ssh_actions_instance (void)
 
 	if (actions == NULL) {
 		actions = g_object_new (SEAHORSE_TYPE_SSH_ACTIONS,
-		                        "name", "ssh-key",
+		                        "name", "SshKey",
 		                        NULL);
 		g_object_add_weak_pointer (G_OBJECT (actions),
 		                           (gpointer *)&actions);
diff --git a/ssh/seahorse-ssh-actions.h b/ssh/seahorse-ssh-actions.h
index 53732b1..63f19c7 100644
--- a/ssh/seahorse-ssh-actions.h
+++ b/ssh/seahorse-ssh-actions.h
@@ -23,6 +23,8 @@
 #ifndef __SEAHORSE_SSH_ACTIONS_H__
 #define __SEAHORSE_SSH_ACTIONS_H__
 
+#include <gtk/gtk.h>
+
 GtkActionGroup *       seahorse_ssh_actions_instance           (void);
 
 #endif
diff --git a/ssh/seahorse-ssh-key.c b/ssh/seahorse-ssh-key.c
index d2811b9..0078dff 100644
--- a/ssh/seahorse-ssh-key.c
+++ b/ssh/seahorse-ssh-key.c
@@ -22,6 +22,11 @@
 
 #include "config.h"
 
+#include "seahorse-ssh-actions.h"
+#include "seahorse-ssh-key.h"
+#include "seahorse-ssh-operation.h"
+#include "seahorse-ssh-source.h"
+
 #include <gcr/gcr.h>
 
 #include <glib.h>
@@ -31,10 +36,8 @@
 #include <errno.h>
 #include <string.h>
 
+
 #include "seahorse-place.h"
-#include "seahorse-ssh-source.h"
-#include "seahorse-ssh-key.h"
-#include "seahorse-ssh-operation.h"
 #include "seahorse-icons.h"
 #include "seahorse-validity.h"
 
@@ -75,6 +78,7 @@ changed_key (SeahorseSSHKey *self)
 	const gchar *display = NULL;
 	gchar *identifier;
 	gchar *simple = NULL;
+	GtkActionGroup *actions;
 	GIcon *icon;
 	gchar *filename;
 	gchar *markup;
@@ -131,11 +135,13 @@ changed_key (SeahorseSSHKey *self)
 	                                  display, filename);
 
 	identifier = seahorse_ssh_key_calc_identifier (self->keydata->fingerprint);
+	actions = seahorse_ssh_actions_instance ();
 
 	if (self->keydata->authorized)
 		flags |= SEAHORSE_FLAG_TRUSTED;
 
 	g_object_set (obj,
+	              "actions", actions,
 	              "markup", markup,
 	              "label", display,
 	              "icon", icon,
@@ -144,6 +150,8 @@ changed_key (SeahorseSSHKey *self)
 	              "identifier", identifier,
 	              "flags", flags,
 	              NULL);
+
+	g_object_unref (actions);
 	g_object_unref (icon);
 	g_free (identifier);
 	g_free (markup);



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