[seahorse] Rework how actions work for places



commit e186f1245eaf000bb7e92385b126cd17c0e87a05
Author: Stef Walter <stefw collabora co uk>
Date:   Tue Dec 13 07:59:38 2011 +0100

    Rework how actions work for places
    
     * Create menu ourselves, and use SeahorseDeletable, SeahorseLockable
       and other interfaces to create popup menu.
     * Remove the clone_for_objects strangeness in SeahorseActions
     * In the future we may move away from SeahorseActions all together

 gkr/seahorse-gkr-actions.c       |  340 ++++----------------------------------
 gkr/seahorse-gkr-actions.h       |    6 +-
 gkr/seahorse-gkr-item.c          |   10 +-
 gkr/seahorse-gkr-keyring.c       |    7 +-
 gkr/seahorse-gkr-keyring.h       |    5 +-
 libseahorse/seahorse-action.c    |   42 ++++-
 libseahorse/seahorse-action.h    |    8 +-
 libseahorse/seahorse-actions.c   |   96 +++++++++--
 libseahorse/seahorse-actions.h   |   13 +-
 libseahorse/seahorse-catalog.c   |   30 ++--
 libseahorse/seahorse-catalog.h   |    4 +-
 pgp/seahorse-keyserver-results.c |    9 +-
 pgp/seahorse-pgp-actions.c       |   68 +-------
 pkcs11/Makefile.am               |    1 -
 pkcs11/seahorse-certificate.c    |    7 +-
 pkcs11/seahorse-pkcs11-actions.c |  248 ---------------------------
 pkcs11/seahorse-pkcs11-actions.h |   31 ----
 pkcs11/seahorse-private-key.c    |    6 +-
 pkcs11/seahorse-token.c          |    6 +-
 src/seahorse-generate-select.c   |    4 +-
 src/seahorse-key-manager.c       |   11 +-
 src/seahorse-sidebar.c           |  285 +++++++++++++++++++++++++++-----
 src/seahorse-sidebar.h           |    4 +
 ssh/seahorse-ssh-actions.c       |   23 +---
 24 files changed, 448 insertions(+), 816 deletions(-)
---
diff --git a/gkr/seahorse-gkr-actions.c b/gkr/seahorse-gkr-actions.c
index 112f1b5..8477415 100644
--- a/gkr/seahorse-gkr-actions.c
+++ b/gkr/seahorse-gkr-actions.c
@@ -139,106 +139,6 @@ seahorse_gkr_backend_actions_instance (void)
 	return actions;
 }
 
-#define SEAHORSE_TYPE_GKR_KEYRING_ACTIONS            (seahorse_gkr_keyring_actions_get_type ())
-#define SEAHORSE_GKR_KEYRING_ACTIONS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_GKR_KEYRING_ACTIONS, SeahorseGkrKeyringActions))
-#define SEAHORSE_GKR_KEYRING_ACTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_GKR_KEYRING_ACTIONS, SeahorseGkrKeyringActionsClass))
-#define SEAHORSE_IS_GKR_KEYRING_ACTIONS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_GKR_KEYRING_ACTIONS))
-#define SEAHORSE_IS_GKR_KEYRING_ACTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_GKR_KEYRING_ACTIONS))
-#define SEAHORSE_GKR_KEYRING_ACTIONS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_GKR_KEYRING_ACTIONS, SeahorseGkrKeyringActionsClass))
-
-typedef struct {
-	SeahorseActions parent;
-} SeahorseGkrKeyringActions;
-
-typedef struct {
-	SeahorseActionsClass parent_class;
-} SeahorseGkrKeyringActionsClass;
-
-GType     seahorse_gkr_keyring_actions_get_type (void) G_GNUC_CONST;
-
-G_DEFINE_TYPE (SeahorseGkrKeyringActions, seahorse_gkr_keyring_actions, SEAHORSE_TYPE_ACTIONS);
-
-static void
-on_keyring_unlock_done (GnomeKeyringResult result,
-                        gpointer user_data)
-{
-	GtkWindow *parent = GTK_WINDOW (user_data);
-
-	if (result != GNOME_KEYRING_RESULT_OK &&
-	    result != GNOME_KEYRING_RESULT_DENIED &&
-	    result != GNOME_KEYRING_RESULT_CANCELLED) {
-		seahorse_util_show_error (parent, _("Couldn't unlock keyring"),
-		                          gnome_keyring_result_to_message (result));
-	}
-
-	refresh_all_keyrings ();
-}
-
-static void
-on_keyrings_unlock (GtkAction *action,
-                    gpointer user_data)
-{
-	GList *keys = user_data;
-	GtkWindow *parent;
-	GList *l;
-
-	parent = seahorse_action_get_window (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,
-		                      on_keyring_unlock_done, g_object_ref (parent), g_object_unref);
-	}
-}
-
-static void
-on_keyring_unlock (GtkAction *action,
-                   gpointer user_data)
-{
-	GtkWindow *parent = seahorse_action_get_window (action);
-	gnome_keyring_unlock (seahorse_gkr_keyring_get_name (SEAHORSE_GKR_KEYRING (user_data)), NULL,
-	                      on_keyring_unlock_done, g_object_ref (parent), g_object_unref);
-}
-
-static void
-on_keyring_lock_done (GnomeKeyringResult result, gpointer user_data)
-{
-	GtkWindow *parent = GTK_WINDOW (user_data);
-
-	if (result != GNOME_KEYRING_RESULT_OK &&
-	    result != GNOME_KEYRING_RESULT_DENIED &&
-	    result != GNOME_KEYRING_RESULT_CANCELLED) {
-		seahorse_util_show_error (parent, _("Couldn't lock keyring"),
-		                          gnome_keyring_result_to_message (result));
-	}
-
-	refresh_all_keyrings ();
-}
-
-static void
-on_keyrings_lock (GtkAction *action,
-                  gpointer user_data)
-{
-	GList *keyrings = user_data;
-	GtkWindow *parent;
-	GList *l;
-
-	parent = seahorse_action_get_window (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),
-		                    on_keyring_lock_done, g_object_ref (parent), g_object_unref);
-	}
-}
-
-static void
-on_keyring_lock (GtkAction *action,
-                 gpointer user_data)
-{
-	GtkWindow *parent = seahorse_action_get_window (action);
-	gnome_keyring_lock (seahorse_gkr_keyring_get_name (SEAHORSE_GKR_KEYRING (user_data)),
-	                    on_keyring_lock_done, g_object_ref (parent), g_object_unref);
-}
-
 static void
 on_set_default_keyring_done (GnomeKeyringResult result,
                              gpointer user_data)
@@ -261,9 +161,15 @@ on_keyring_default (GtkAction *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);
+
+	if (parent == NULL)
+		gnome_keyring_set_default_keyring (seahorse_gkr_keyring_get_name (keyring),
+		                                   on_set_default_keyring_done,
+		                                   NULL, NULL);
+	else
+		gnome_keyring_set_default_keyring (seahorse_gkr_keyring_get_name (keyring),
+		                                   on_set_default_keyring_done,
+		                                   g_object_ref (parent), g_object_unref);
 }
 
 static void
@@ -288,226 +194,42 @@ on_keyring_password (GtkAction *action,
 	SeahorseGkrKeyring *keyring = SEAHORSE_GKR_KEYRING (user_data);
 	GtkWindow *window = seahorse_action_get_window (action);
 
-	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_GKR_KEYRING (user_data),
-	                                      seahorse_action_get_window (action));
-}
-
-static void
-on_delete_keyring_complete (GObject *source,
-                            GAsyncResult *result,
-                            gpointer user_data)
-{
-	GtkWindow *parent = GTK_WINDOW (user_data);
-	GError *error = NULL;
-
-	if (!seahorse_deleter_delete_finish (SEAHORSE_DELETER (source), result, &error)) {
-		seahorse_util_show_error (parent, _("Couldn't delete keyring"), error->message);
-		g_error_free (error);
-	}
+	if (window == NULL)
+		gnome_keyring_change_password (seahorse_gkr_keyring_get_name (keyring),
+		                               NULL, NULL, on_change_password_done,
+		                               NULL, NULL);
+	else
+		gnome_keyring_change_password (seahorse_gkr_keyring_get_name (keyring),
+		                               NULL, NULL, on_change_password_done,
+		                               g_object_ref (window), g_object_unref);
 
-	g_object_unref (parent);
 }
 
-static void
-on_keyrings_delete (GtkAction* action,
-                    gpointer user_data)
-{
-	SeahorseGkrKeyring *keyring = SEAHORSE_GKR_KEYRING (user_data);
-	GtkWindow *parent = seahorse_action_get_window (action);
-	SeahorseDeleter *deleter;
-
-	deleter = seahorse_gkr_keyring_deleter_new (keyring);
-
-	if (seahorse_deleter_prompt (deleter, parent))
-		seahorse_deleter_delete_async (deleter, NULL, on_delete_keyring_complete,
-		                               g_object_ref (parent));
-	g_object_unref (deleter);
-}
-
-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) },
-};
-
 static const GtkActionEntry KEYRING_ACTIONS[] = {
-	{ "keyring-default", NULL, N_("_Set as default"), "",
+	{ "keyring-default", NULL, N_("_Set as default"), NULL,
 	  N_("Applications usually store new passwords in the default keyring."), G_CALLBACK (on_keyring_default) },
-	{ "keyring-password", NULL, N_("Change _Password"), "",
+	{ "keyring-password", NULL, N_("Change _Password"), NULL,
 	  N_("Change the unlock password of the password storage keyring"), G_CALLBACK (on_keyring_password) },
-	{ "keyring-properties", GTK_STOCK_PROPERTIES, NULL, NULL,
-	  N_("Properties of the keyring."), G_CALLBACK (on_keyring_properties) },
-	{ "keyring-delete", GTK_STOCK_DELETE, NULL, NULL,
-	  N_("Delete the keyring."), G_CALLBACK (on_keyrings_delete) },
-
-	/* Generic actions used by the sidebar for the current selection */
-	{ "lock", NULL, NULL, "",
-	  N_("Lock the password storage keyring."), G_CALLBACK (on_keyring_lock) },
-	{ "unlock", NULL, NULL, "",
-	  N_("Unlock the password storage keyring."), G_CALLBACK (on_keyring_unlock) },
 };
 
-static const gchar* KEYRING_UI =
-"<ui>"
-"	<popup name='SeahorseGkrKeyring'>"
-"		<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>";
-
-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, 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 GtkActionGroup *
-seahorse_gkr_keyring_actions_clone_for_objects (SeahorseActions *actions,
-                                                GList *objects)
-{
-	gboolean locked = FALSE;
-	gboolean unlocked = FALSE;
-	GtkActionGroup *cloned;
-	GList *l;
-
-	g_return_val_if_fail (objects != NULL, NULL);
-
-	for (l = objects; l; l = g_list_next (l)) {
-		if (seahorse_gkr_keyring_get_locked (l->data))
-			locked = TRUE;
-		else
-			unlocked = TRUE;
-	}
-
-	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);
-		g_object_bind_property (objects->data, "is-default",
-		                        gtk_action_group_get_action (cloned, "keyring-default"), "sensitive",
-		                        G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE);
-		g_object_bind_property (objects->data, "locked",
-		                        gtk_action_group_get_action (cloned, "lock"), "sensitive",
-		                        G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE);
-		g_object_bind_property (objects->data, "locked",
-		                        gtk_action_group_get_action (cloned, "unlock"), "sensitive",
-		                        G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
-	}
-
-	return cloned;
-}
-
-static void
-seahorse_gkr_keyring_actions_class_init (SeahorseGkrKeyringActionsClass *klass)
-{
-	SeahorseActionsClass *actions_class = SEAHORSE_ACTIONS_CLASS (klass);
-	actions_class->clone_for_objects = seahorse_gkr_keyring_actions_clone_for_objects;
-}
-
 GtkActionGroup *
-seahorse_gkr_keyring_actions_instance (void)
+seahorse_gkr_keyring_actions_new (SeahorseGkrKeyring *keyring)
 {
-	static GtkActionGroup *actions = NULL;
+	GtkActionGroup *actions;
+	GtkAction *action;
 
-	if (actions == NULL) {
-		actions = g_object_new (SEAHORSE_TYPE_GKR_KEYRING_ACTIONS,
-		                        "name", "gkr-keyring",
-		                        NULL);
-		g_object_add_weak_pointer (G_OBJECT (actions),
-		                           (gpointer *)&actions);
-	} else {
-		g_object_ref (actions);
-	}
-
-	return actions;
-}
-
-GType   seahorse_gkr_item_actions_get_type        (void);
-#define SEAHORSE_TYPE_GKR_ITEM_ACTIONS            (seahorse_gkr_item_actions_get_type ())
-#define SEAHORSE_GKR_ITEM_ACTIONS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_GKR_ITEM_ACTIONS, SeahorseGkrItemActions))
-#define SEAHORSE_GKR_ITEM_ACTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_GKR_ITEM_ACTIONS, SeahorseGkrItemActionsClass))
-#define SEAHORSE_IS_GKR_ITEM_ACTIONS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_GKR_ITEM_ACTIONS))
-#define SEAHORSE_IS_GKR_ITEM_ACTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_GKR_ITEM_ACTIONS))
-#define SEAHORSE_GKR_ITEM_ACTIONS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_GKR_ITEM_ACTIONS, SeahorseGkrItemActionsClass))
-
-typedef struct {
-	SeahorseActions parent;
-} SeahorseGkrItemActions;
+	g_return_val_if_fail (SEAHORSE_IS_GKR_KEYRING (keyring), NULL);
 
-typedef struct {
-	SeahorseActionsClass parent_class;
-} SeahorseGkrItemActionsClass;
-
-G_DEFINE_TYPE (SeahorseGkrItemActions, seahorse_gkr_item_actions, SEAHORSE_TYPE_ACTIONS);
-
-static void
-seahorse_gkr_item_actions_init (SeahorseGkrItemActions *self)
-{
+	actions = gtk_action_group_new ("KeyringActions");
 
-}
-
-static GtkActionGroup *
-seahorse_gkr_item_actions_clone_for_objects (SeahorseActions *actions,
-                                             GList *objects)
-{
-	return NULL;
-}
-
-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 *
-seahorse_gkr_item_actions_instance (void)
-{
-	static GtkActionGroup *actions = NULL;
+	/* 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_full (actions, KEYRING_ACTIONS, G_N_ELEMENTS (KEYRING_ACTIONS),
+	                                   g_object_ref (keyring), g_object_unref);
 
-	if (actions == NULL) {
-		actions = g_object_new (SEAHORSE_TYPE_GKR_ITEM_ACTIONS,
-		                        "name", "KeyringItem",
-		                        NULL);
-		g_object_add_weak_pointer (G_OBJECT (actions),
-		                           (gpointer *)&actions);
-	} else {
-		g_object_ref (actions);
-	}
+	action = gtk_action_group_get_action (actions, "keyring-default");
+	g_object_bind_property (keyring, "is-default", action, "sensitive",
+	                        G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE);
 
 	return actions;
 }
diff --git a/gkr/seahorse-gkr-actions.h b/gkr/seahorse-gkr-actions.h
index 7db0064..bacdeb0 100644
--- a/gkr/seahorse-gkr-actions.h
+++ b/gkr/seahorse-gkr-actions.h
@@ -22,12 +22,12 @@
 #ifndef __SEAHORSE_GKR_ACTIONS_H__
 #define __SEAHORSE_GKR_ACTIONS_H__
 
+#include "seahorse-gkr-keyring.h"
+
 #include <gtk/gtk.h>
 
 GtkActionGroup *     seahorse_gkr_backend_actions_instance      (void);
 
-GtkActionGroup *     seahorse_gkr_keyring_actions_instance      (void);
-
-GtkActionGroup *     seahorse_gkr_item_actions_instance         (void);
+GtkActionGroup *     seahorse_gkr_keyring_actions_new           (SeahorseGkrKeyring *keyring);
 
 #endif /* __SEAHORSE_GKR_ACTIONS_H__ */
diff --git a/gkr/seahorse-gkr-item.c b/gkr/seahorse-gkr-item.c
index a11de08..e9a0211 100644
--- a/gkr/seahorse-gkr-item.c
+++ b/gkr/seahorse-gkr-item.c
@@ -747,16 +747,8 @@ seahorse_gkr_item_refresh (SeahorseGkrItem *self)
 static void
 seahorse_gkr_item_init (SeahorseGkrItem *self)
 {
-	GtkActionGroup *actions;
-
 	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_GKR_ITEM, SeahorseGkrItemPrivate);
-
-	actions = seahorse_gkr_item_actions_instance ();
-	g_object_set (self,
-	              "usage", SEAHORSE_USAGE_CREDENTIALS,
-	              "actions", actions,
-	              NULL);
-	g_object_unref (actions);
+	g_object_set (self, "usage", SEAHORSE_USAGE_CREDENTIALS, NULL);
 }
 
 static void
diff --git a/gkr/seahorse-gkr-keyring.c b/gkr/seahorse-gkr-keyring.c
index db936b6..5b58383 100644
--- a/gkr/seahorse-gkr-keyring.c
+++ b/gkr/seahorse-gkr-keyring.c
@@ -62,8 +62,6 @@ struct _SeahorseGkrKeyringPrivate {
 
 	gpointer req_info;
 	GnomeKeyringInfo *keyring_info;
-
-	GtkActionGroup *actions;
 };
 
 static void     seahorse_keyring_place_iface        (SeahorsePlaceIface *iface);
@@ -376,7 +374,6 @@ seahorse_gkr_keyring_init (SeahorseGkrKeyring *self)
 {
 	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_GKR_KEYRING, SeahorseGkrKeyringPrivate);
 	self->pv->items = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
-	self->pv->actions = seahorse_gkr_keyring_actions_instance ();
 }
 
 static void
@@ -398,8 +395,6 @@ seahorse_gkr_keyring_finalize (GObject *obj)
 		gnome_keyring_info_free (self->pv->keyring_info);
 	self->pv->keyring_info = NULL;
 
-	g_object_unref (self->pv->actions);
-
 	G_OBJECT_CLASS (seahorse_gkr_keyring_parent_class)->finalize (obj);
 }
 
@@ -452,7 +447,7 @@ seahorse_gkr_keyring_get_property (GObject *obj, guint prop_id, GValue *value,
 		g_value_take_string (value, text);
 		break;
 	case PROP_ACTIONS:
-		g_value_set_object (value, self->pv->actions);
+		g_value_take_object (value, seahorse_gkr_keyring_actions_new (self));
 		break;
 	case PROP_LOCKED:
 		g_value_set_boolean (value, seahorse_gkr_keyring_get_locked (self));
diff --git a/gkr/seahorse-gkr-keyring.h b/gkr/seahorse-gkr-keyring.h
index 121509b..8e61323 100644
--- a/gkr/seahorse-gkr-keyring.h
+++ b/gkr/seahorse-gkr-keyring.h
@@ -22,10 +22,11 @@
 #ifndef __SEAHORSE_GKR_KEYRING_H__
 #define __SEAHORSE_GKR_KEYRING_H__
 
-#include <glib-object.h>
-
 #include "seahorse-object.h"
 
+#include <glib-object.h>
+#include <gio/gio.h>
+
 #include <gnome-keyring.h>
 
 #define SEAHORSE_TYPE_GKR_KEYRING               (seahorse_gkr_keyring_get_type ())
diff --git a/libseahorse/seahorse-action.c b/libseahorse/seahorse-action.c
index ea42f24..72e22d4 100644
--- a/libseahorse/seahorse-action.c
+++ b/libseahorse/seahorse-action.c
@@ -27,10 +27,12 @@
 
 #include <gck/gck.h>
 
-static GQuark   seahorse_action_info_quark (void) G_GNUC_CONST;
+static GQuark   seahorse_action_window_quark   (void) G_GNUC_CONST;
+
+static GQuark   seahorse_action_catalog_quark  (void) G_GNUC_CONST;
 
 static GQuark
-seahorse_action_info_quark (void)
+seahorse_action_window_quark (void)
 {
 	static GQuark quark = 0;
 	if (quark == 0)
@@ -38,19 +40,33 @@ seahorse_action_info_quark (void)
 	return quark;
 }
 
+static GQuark
+seahorse_action_catalog_quark (void)
+{
+	static GQuark quark = 0;
+	if (quark == 0)
+		quark = g_quark_from_static_string ("seahorse-action-catalog");
+	return quark;
+}
+
 void
-seahorse_action_pre_activate_with_window (GtkAction *action,
-                                          GtkWindow *window)
+seahorse_action_pre_activate (GtkAction *action,
+                              SeahorseCatalog *catalog,
+                              GtkWindow *window)
 {
 	g_return_if_fail (GTK_IS_ACTION (action));
-	g_return_if_fail (window != NULL || GTK_IS_WINDOW (window));
+	g_return_if_fail (catalog == NULL || SEAHORSE_IS_CATALOG (catalog));
+	g_return_if_fail (window == NULL || GTK_IS_WINDOW (window));
 
-	g_object_set_qdata_full (G_OBJECT (action), seahorse_action_info_quark (),
+	g_object_set_qdata_full (G_OBJECT (action), seahorse_action_window_quark (),
 	                         window ? g_object_ref (window) : NULL, g_object_unref);
+	g_object_set_qdata_full (G_OBJECT (action), seahorse_action_catalog_quark (),
+	                         catalog ? g_object_ref (catalog) : NULL, g_object_unref);
 }
 
 void
 seahorse_action_activate_with_window (GtkAction *action,
+                                      SeahorseCatalog *catalog,
                                       GtkWindow *window)
 {
 	g_return_if_fail (GTK_IS_ACTION (action));
@@ -58,7 +74,7 @@ seahorse_action_activate_with_window (GtkAction *action,
 
 	g_object_ref (action);
 
-	seahorse_action_pre_activate_with_window (action, window);
+	seahorse_action_pre_activate (action, catalog, window);
 	gtk_action_activate (action);
 	seahorse_action_post_activate (action);
 
@@ -70,7 +86,8 @@ seahorse_action_post_activate (GtkAction *action)
 {
 	g_return_if_fail (GTK_IS_ACTION (action));
 
-	g_object_set_qdata (G_OBJECT (action), seahorse_action_info_quark (), NULL);
+	g_object_set_qdata (G_OBJECT (action), seahorse_action_window_quark (), NULL);
+	g_object_set_qdata (G_OBJECT (action), seahorse_action_catalog_quark (), NULL);
 }
 
 
@@ -78,5 +95,12 @@ GtkWindow *
 seahorse_action_get_window (GtkAction *action)
 {
 	g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
-	return g_object_get_qdata (G_OBJECT (action), seahorse_action_info_quark ());
+	return g_object_get_qdata (G_OBJECT (action), seahorse_action_window_quark ());
+}
+
+SeahorseCatalog *
+seahorse_action_get_catalog (GtkAction *action)
+{
+	g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+	return g_object_get_qdata (G_OBJECT (action), seahorse_action_catalog_quark ());
 }
diff --git a/libseahorse/seahorse-action.h b/libseahorse/seahorse-action.h
index 7eceafb..147d84d 100644
--- a/libseahorse/seahorse-action.h
+++ b/libseahorse/seahorse-action.h
@@ -23,16 +23,22 @@
 #ifndef __SEAHORSE_ACTION_H__
 #define __SEAHORSE_ACTION_H__
 
+#include "seahorse-catalog.h"
+
 #include <gtk/gtk.h>
 
-void                  seahorse_action_pre_activate_with_window  (GtkAction *action,
+void                  seahorse_action_pre_activate              (GtkAction *action,
+                                                                 SeahorseCatalog *catalog,
                                                                  GtkWindow *window);
 
 void                  seahorse_action_activate_with_window      (GtkAction *action,
+                                                                 SeahorseCatalog *catalog,
                                                                  GtkWindow *window);
 
 void                  seahorse_action_post_activate             (GtkAction *action);
 
 GtkWindow *           seahorse_action_get_window                (GtkAction *action);
 
+SeahorseCatalog *     seahorse_action_get_catalog               (GtkAction *action);
+
 #endif
diff --git a/libseahorse/seahorse-actions.c b/libseahorse/seahorse-actions.c
index 8af7f89..61fcb57 100644
--- a/libseahorse/seahorse-actions.c
+++ b/libseahorse/seahorse-actions.c
@@ -26,15 +26,17 @@
 
 struct _SeahorseActionsPrivate {
 	const gchar *definition;
+	SeahorseCatalog *catalog;
+	guint catalog_sig;
 };
 
 G_DEFINE_TYPE (SeahorseActions, seahorse_actions, GTK_TYPE_ACTION_GROUP);
 
-static GtkActionGroup *
-seahorse_actions_real_clone_for_objects (SeahorseActions *self,
-                                         GList *selected)
+static void
+seahorse_actions_real_update (SeahorseActions *self,
+                              SeahorseCatalog *catalog)
 {
-	return gtk_action_group_new ("internal");
+	/* Nothing to do */
 }
 
 static void
@@ -44,6 +46,28 @@ seahorse_actions_init (SeahorseActions *self)
 	                                         SeahorseActionsPrivate));
 }
 
+static void
+seahorse_actions_finalize (GObject *obj)
+{
+	SeahorseActions *actions = SEAHORSE_ACTIONS (obj);
+
+	seahorse_actions_set_catalog (actions, NULL);
+
+	G_OBJECT_CLASS (seahorse_actions_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_actions_class_init (SeahorseActionsClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = seahorse_actions_finalize;
+
+	klass->update = seahorse_actions_real_update;
+
+	g_type_class_add_private (klass, sizeof (SeahorseActionsPrivate));
+}
+
 GtkActionGroup *
 seahorse_actions_new (const gchar *name)
 {
@@ -53,11 +77,54 @@ seahorse_actions_new (const gchar *name)
 	                     NULL);
 }
 
+SeahorseCatalog *
+seahorse_actions_get_catalog (SeahorseActions *self)
+{
+	g_return_val_if_fail (SEAHORSE_IS_ACTIONS (self), NULL);
+	return self->pv->catalog;
+}
+
 static void
-seahorse_actions_class_init (SeahorseActionsClass *klass)
+on_catalog_gone (gpointer data,
+                 GObject *where_the_object_was)
 {
-	g_type_class_add_private (klass, sizeof (SeahorseActionsPrivate));
-	klass->clone_for_objects = seahorse_actions_real_clone_for_objects;
+	SeahorseActions *self = SEAHORSE_ACTIONS (data);
+
+	self->pv->catalog = NULL;
+	self->pv->catalog_sig = 0;
+}
+
+static void
+on_catalog_selection (SeahorseCatalog *catalog,
+                      gpointer user_data)
+{
+	SeahorseActions *self = SEAHORSE_ACTIONS (user_data);
+	seahorse_actions_update (GTK_ACTION_GROUP (self), catalog);
+}
+
+void
+seahorse_actions_set_catalog (SeahorseActions *self,
+                              SeahorseCatalog *catalog)
+{
+	g_return_if_fail (SEAHORSE_IS_ACTIONS (self));
+	g_return_if_fail (catalog == NULL || SEAHORSE_IS_CATALOG (catalog));
+
+	if (self->pv->catalog) {
+		g_signal_handler_disconnect (self->pv->catalog,
+		                             self->pv->catalog_sig);
+		g_object_weak_unref (G_OBJECT (self->pv->catalog),
+		                     on_catalog_gone, self);
+	}
+
+	self->pv->catalog = catalog;
+	if (self->pv->catalog) {
+		self->pv->catalog_sig = g_signal_connect (self->pv->catalog,
+		                                          "selection-changed",
+		                                          G_CALLBACK (on_catalog_selection),
+		                                          self);
+		g_object_weak_ref (G_OBJECT (self->pv->catalog),
+		                   on_catalog_gone, self);
+	}
 }
 
 const gchar *
@@ -76,17 +143,18 @@ seahorse_actions_register_definition (SeahorseActions *self,
 	self->pv->definition = definition;
 }
 
-GtkActionGroup *
-seahorse_actions_clone_for_objects (GtkActionGroup *actions,
-                                    GList *objects)
+void
+seahorse_actions_update (GtkActionGroup *actions,
+                         SeahorseCatalog *catalog)
 {
 	SeahorseActionsClass *klass;
 
-	g_return_val_if_fail (GTK_IS_ACTION_GROUP (actions), NULL);
+	g_return_if_fail (GTK_IS_ACTION_GROUP (actions));
 
 	if (!SEAHORSE_IS_ACTIONS (actions))
-		return g_object_ref (actions);
+		return;
+
 	klass = SEAHORSE_ACTIONS_GET_CLASS (actions);
-	g_assert (klass->clone_for_objects != NULL);
-	return (klass->clone_for_objects) (SEAHORSE_ACTIONS (actions), objects);
+	g_assert (klass->update != NULL);
+	(klass->update) (SEAHORSE_ACTIONS (actions), catalog);
 }
diff --git a/libseahorse/seahorse-actions.h b/libseahorse/seahorse-actions.h
index a4c9cd9..fc8e04f 100644
--- a/libseahorse/seahorse-actions.h
+++ b/libseahorse/seahorse-actions.h
@@ -47,20 +47,25 @@ struct _SeahorseActions {
 struct _SeahorseActionsClass {
 	GtkActionGroupClass parent_class;
 
-	GtkActionGroup *  (*clone_for_objects)  (SeahorseActions *actions,
-	                                         GList *objects);
+	void              (* update)  (SeahorseActions *actions,
+	                               SeahorseCatalog *catalog);
 };
 
 GType                 seahorse_actions_get_type                 (void);
 
 GtkActionGroup *      seahorse_actions_new                      (const gchar *name);
 
+SeahorseCatalog *     seahorse_actions_get_catalog              (SeahorseActions *self);
+
+void                  seahorse_actions_set_catalog              (SeahorseActions *self,
+                                                                 SeahorseCatalog *catalog);
+
 const gchar *         seahorse_actions_get_definition           (SeahorseActions *self);
 
 void                  seahorse_actions_register_definition      (SeahorseActions *self,
                                                                  const gchar *definition);
 
-GtkActionGroup *      seahorse_actions_clone_for_objects        (GtkActionGroup *actions,
-                                                                 GList *objects);
+void                  seahorse_actions_update                   (GtkActionGroup *actions,
+                                                                 SeahorseCatalog *catalog);
 
 #endif
diff --git a/libseahorse/seahorse-catalog.c b/libseahorse/seahorse-catalog.c
index 65b2d32..b016d11 100644
--- a/libseahorse/seahorse-catalog.c
+++ b/libseahorse/seahorse-catalog.c
@@ -137,7 +137,6 @@ lookup_actions_for_objects (SeahorseCatalog *self,
                             GList *objects)
 {
 	GtkActionGroup *actions;
-	GtkActionGroup *cloned;
 	GHashTableIter iter;
 	GList *results;
 	GHashTable *table;
@@ -167,9 +166,8 @@ lookup_actions_for_objects (SeahorseCatalog *self,
 	results = NULL;
 	g_hash_table_iter_init (&iter, table);
 	while (g_hash_table_iter_next (&iter, (gpointer *)&actions, (gpointer *)&queue)) {
-		cloned = seahorse_actions_clone_for_objects (actions, queue->head);
-		if (cloned != NULL)
-			results = g_list_prepend (results, cloned);
+		seahorse_actions_update (actions, self);
+		results = g_list_prepend (results, g_object_ref (actions));
 	}
 
 	g_hash_table_destroy (table);
@@ -213,12 +211,11 @@ on_properties_place (GtkAction *action,
                      gpointer user_data)
 {
 	SeahorseCatalog *self = SEAHORSE_CATALOG (user_data);
-	GList *objects;
+	SeahorsePlace *place;
 
-	objects = seahorse_catalog_get_selected_places (self);
-	if (objects != NULL)
-		seahorse_catalog_show_properties (self, objects->data);
-	g_list_free (objects);
+	place = seahorse_catalog_get_focused_place (self);
+	if (place != NULL)
+		seahorse_catalog_show_properties (self, G_OBJECT (place));
 }
 
 static void
@@ -306,8 +303,7 @@ on_ui_manager_pre_activate (GtkUIManager *ui_manager,
                             gpointer user_data)
 {
 	SeahorseCatalog *self = SEAHORSE_CATALOG (user_data);
-	seahorse_action_pre_activate_with_window (action,
-	                                          seahorse_catalog_get_window (self));
+	seahorse_action_pre_activate (action, self, seahorse_catalog_get_window (self));
 }
 
 static void
@@ -353,10 +349,6 @@ seahorse_catalog_real_selection_changed (SeahorseCatalog *self)
 	gtk_action_set_sensitive (self->pv->edit_copy, can_export);
 	gtk_action_set_sensitive (self->pv->file_export, can_export);
 
-	objects = seahorse_catalog_get_selected_places (self);
-	groups = g_list_concat (groups, lookup_actions_for_objects (self, objects));
-	g_list_free (objects);
-
 	previous = self->pv->selection_actions;
 	self->pv->selection_actions = groups;
 
@@ -612,12 +604,12 @@ seahorse_catalog_get_selected_objects (SeahorseCatalog *self)
 	return SEAHORSE_CATALOG_GET_CLASS (self)->get_selected_objects (self);
 }
 
-GList *
-seahorse_catalog_get_selected_places (SeahorseCatalog *self)
+SeahorsePlace *
+seahorse_catalog_get_focused_place (SeahorseCatalog *self)
 {
 	g_return_val_if_fail (SEAHORSE_IS_CATALOG (self), NULL);
-	g_return_val_if_fail (SEAHORSE_CATALOG_GET_CLASS (self)->get_selected_places, NULL);
-	return SEAHORSE_CATALOG_GET_CLASS (self)->get_selected_places (self);
+	g_return_val_if_fail (SEAHORSE_CATALOG_GET_CLASS (self)->get_focused_place, NULL);
+	return SEAHORSE_CATALOG_GET_CLASS (self)->get_focused_place (self);
 }
 
 GList *
diff --git a/libseahorse/seahorse-catalog.h b/libseahorse/seahorse-catalog.h
index 9b1ab39..86760c2 100644
--- a/libseahorse/seahorse-catalog.h
+++ b/libseahorse/seahorse-catalog.h
@@ -49,7 +49,7 @@ struct _SeahorseCatalogClass {
 
 	GList *          (*get_backends)                  (SeahorseCatalog *self);
 
-	GList *          (*get_selected_places)           (SeahorseCatalog *self);
+	SeahorsePlace *  (*get_focused_place)             (SeahorseCatalog *self);
 
 	GList *          (*get_selected_objects)          (SeahorseCatalog *self);
 
@@ -65,7 +65,7 @@ void                seahorse_catalog_include_actions             (SeahorseCatalo
 
 GList *             seahorse_catalog_get_selected_objects        (SeahorseCatalog* self);
 
-GList *             seahorse_catalog_get_selected_places         (SeahorseCatalog* self);
+SeahorsePlace *     seahorse_catalog_get_focused_place           (SeahorseCatalog* self);
 
 GList *             seahorse_catalog_get_backends                (SeahorseCatalog* self);
 
diff --git a/pgp/seahorse-keyserver-results.c b/pgp/seahorse-keyserver-results.c
index f527498..95455bc 100644
--- a/pgp/seahorse-keyserver-results.c
+++ b/pgp/seahorse-keyserver-results.c
@@ -263,8 +263,8 @@ seahorse_keyserver_results_get_selected_objects (SeahorseCatalog *catalog)
 	return seahorse_key_manager_store_get_selected_objects (self->pv->view);
 }
 
-static GList *
-seahorse_keyserver_results_get_selected_places (SeahorseCatalog *catalog)
+static SeahorsePlace *
+seahorse_keyserver_results_get_focused_place (SeahorseCatalog *catalog)
 {
 	return NULL;
 }
@@ -462,6 +462,7 @@ static void
 seahorse_keyserver_results_class_init (SeahorseKeyserverResultsClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	SeahorseCatalogClass *catalog_class = SEAHORSE_CATALOG_CLASS (klass);
 
 	seahorse_keyserver_results_parent_class = g_type_class_peek_parent (klass);
 	g_type_class_add_private (klass, sizeof (SeahorseKeyserverResultsPrivate));
@@ -471,8 +472,8 @@ seahorse_keyserver_results_class_init (SeahorseKeyserverResultsClass *klass)
 	gobject_class->set_property = seahorse_keyserver_results_set_property;
 	gobject_class->get_property = seahorse_keyserver_results_get_property;
 
-	SEAHORSE_CATALOG_CLASS (klass)->get_selected_objects = seahorse_keyserver_results_get_selected_objects;
-	SEAHORSE_CATALOG_CLASS (klass)->get_selected_places = seahorse_keyserver_results_get_selected_places;
+	catalog_class->get_selected_objects = seahorse_keyserver_results_get_selected_objects;
+	catalog_class->get_focused_place = seahorse_keyserver_results_get_focused_place;
 
 	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 43a60e9..c897b60 100644
--- a/pgp/seahorse-pgp-actions.c
+++ b/pgp/seahorse-pgp-actions.c
@@ -161,81 +161,19 @@ typedef struct {
 
 G_DEFINE_TYPE (SeahorseGpgmeKeyActions, seahorse_gpgme_key_actions, SEAHORSE_TYPE_ACTIONS);
 
-static const char* KEY_DEFINITION = ""\
-"<ui>"\
-"	<menubar>"\
-"		<menu name='File' action='file-menu'>"\
-"			<placeholder name='FileActions'>"\
-"				<menuitem action='key-sign'/>"\
-"			</placeholder>"\
-"		</menu>"\
-"	</menubar>"\
-"	<popup name='ObjectPopup'>"\
-"		<menuitem action='key-sign'/>"\
-"	</popup>"\
-"</ui>";
-
-static void
-on_key_sign (GtkAction* action,
-             gpointer user_data)
-{
-	GtkWindow *window;
-	GList *objects = user_data;
-
-	g_return_if_fail (objects->data);
-
-	window = seahorse_action_get_window (action);
-
-	seahorse_gpgme_sign_prompt (SEAHORSE_GPGME_KEY (objects->data), window);
-}
-
-static const GtkActionEntry KEY_ACTIONS[] = {
-	{ "key-sign", GTK_STOCK_INDEX, N_("_Sign Key..."), "",
-	  N_("Sign public key"), G_CALLBACK (on_key_sign) },
-};
-
 static void
 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), 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, 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;
+	gtk_action_group_add_actions (actions, SYNC_ACTIONS,
+	                              G_N_ELEMENTS (SYNC_ACTIONS), NULL);
 }
 
 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/Makefile.am b/pkcs11/Makefile.am
index 844aac9..909cd77 100644
--- a/pkcs11/Makefile.am
+++ b/pkcs11/Makefile.am
@@ -17,7 +17,6 @@ noinst_LTLIBRARIES = libseahorse-pkcs11.la
 libseahorse_pkcs11_la_SOURCES = \
 	seahorse-certificate.c seahorse-certificate.h \
 	seahorse-certificate-der-exporter.c seahorse-certificate-der-exporter.h \
-	seahorse-pkcs11-actions.c seahorse-pkcs11-actions.h \
 	seahorse-pkcs11-backend.c seahorse-pkcs11-backend.h \
 	seahorse-pkcs11-deleter.c seahorse-pkcs11-deleter.h \
 	seahorse-pkcs11-helpers.c seahorse-pkcs11-helpers.h \
diff --git a/pkcs11/seahorse-certificate.c b/pkcs11/seahorse-certificate.c
index 42b3d44..f9c0af7 100644
--- a/pkcs11/seahorse-certificate.c
+++ b/pkcs11/seahorse-certificate.c
@@ -25,7 +25,6 @@
 #include "seahorse-certificate.h"
 #include "seahorse-certificate-der-exporter.h"
 #include "seahorse-pkcs11.h"
-#include "seahorse-pkcs11-actions.h"
 #include "seahorse-pkcs11-deleter.h"
 #include "seahorse-pkcs11-helpers.h"
 #include "seahorse-pkcs11-properties.h"
@@ -71,7 +70,6 @@ struct _SeahorseCertificatePrivate {
 	SeahorseToken *token;
 	GckAttributes *attributes;
 	const GckAttribute *value;
-	GtkActionGroup *actions;
 	SeahorsePrivateKey *private_key;
 	GIcon *icon;
 	guint flags;
@@ -121,7 +119,6 @@ static void
 seahorse_certificate_init (SeahorseCertificate *self)
 {
 	self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_CERTIFICATE, SeahorseCertificatePrivate));
-	self->pv->actions = seahorse_pkcs11_object_actions_instance ();
 	self->pv->value = NULL;
 	self->pv->flags = G_MAXUINT;
 }
@@ -153,8 +150,6 @@ seahorse_certificate_finalize (GObject *obj)
 {
 	SeahorseCertificate *self = SEAHORSE_CERTIFICATE (obj);
 
-	g_clear_object (&self->pv->actions);
-
 	if (self->pv->attributes)
 		gck_attributes_unref (self->pv->attributes);
 	self->pv->value = NULL;
@@ -215,7 +210,7 @@ seahorse_certificate_get_property (GObject *obj,
 		g_value_set_flags (value, self->pv->flags);
 		break;
 	case PROP_ACTIONS:
-		g_value_set_object (value, self->pv->actions);
+		g_value_set_object (value, NULL);
 		break;
 	case PROP_PARTNER:
 		g_value_set_object (value, seahorse_certificate_get_partner (self));
diff --git a/pkcs11/seahorse-private-key.c b/pkcs11/seahorse-private-key.c
index 804e591..f5d1cfe 100644
--- a/pkcs11/seahorse-private-key.c
+++ b/pkcs11/seahorse-private-key.c
@@ -24,7 +24,6 @@
 
 #include "seahorse-private-key.h"
 #include "seahorse-pkcs11.h"
-#include "seahorse-pkcs11-actions.h"
 #include "seahorse-pkcs11-helpers.h"
 #include "seahorse-pkcs11-key-deleter.h"
 #include "seahorse-pkcs11-properties.h"
@@ -70,7 +69,6 @@ enum {
 struct _SeahorsePrivateKeyPrivate {
 	SeahorseToken *token;
 	GckAttributes *attributes;
-	GtkActionGroup *actions;
 	SeahorseCertificate *certificate;
 	GIcon *icon;
 };
@@ -101,7 +99,6 @@ static void
 seahorse_private_key_init (SeahorsePrivateKey *self)
 {
 	self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_PRIVATE_KEY, SeahorsePrivateKeyPrivate));
-	self->pv->actions = seahorse_pkcs11_object_actions_instance ();
 }
 
 static void
@@ -109,7 +106,6 @@ seahorse_private_key_finalize (GObject *obj)
 {
 	SeahorsePrivateKey *self = SEAHORSE_PRIVATE_KEY (obj);
 
-	g_clear_object (&self->pv->actions);
 	g_clear_object (&self->pv->icon);
 
 	if (self->pv->attributes)
@@ -162,7 +158,7 @@ seahorse_private_key_get_property (GObject *obj,
 		g_value_set_flags (value, SEAHORSE_FLAG_PERSONAL);
 		break;
 	case PROP_ACTIONS:
-		g_value_set_object (value, self->pv->actions);
+		g_value_set_object (value, NULL);
 		break;
 	case PROP_PARTNER:
 		g_value_set_object (value, seahorse_private_key_get_partner (self));
diff --git a/pkcs11/seahorse-token.c b/pkcs11/seahorse-token.c
index c4128ca..3041638 100644
--- a/pkcs11/seahorse-token.c
+++ b/pkcs11/seahorse-token.c
@@ -30,7 +30,6 @@
 
 #include "seahorse-certificate.h"
 #include "seahorse-pkcs11.h"
-#include "seahorse-pkcs11-actions.h"
 #include "seahorse-pkcs11-helpers.h"
 #include "seahorse-private-key.h"
 #include "seahorse-token.h"
@@ -61,7 +60,6 @@ struct _SeahorseTokenPrivate {
 	GckTokenInfo *info;
 	GArray *mechanisms;
 	GckSession *session;
-	GtkActionGroup *actions;
 	GHashTable *object_for_handle;
 	GHashTable *objects_for_id;
 	GHashTable *id_for_object;
@@ -533,7 +531,6 @@ static void
 seahorse_token_init (SeahorseToken *self)
 {
 	self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_TOKEN, SeahorseTokenPrivate));
-	self->pv->actions = seahorse_pkcs11_token_actions_instance ();
 	self->pv->object_for_handle = g_hash_table_new_full (seahorse_pkcs11_ulong_hash,
 	                                                     seahorse_pkcs11_ulong_equal,
 	                                                     g_free, g_object_unref);
@@ -608,7 +605,7 @@ seahorse_token_get_property (GObject *object,
 		g_value_set_string (value, self->pv->uri);
 		break;
 	case PROP_ACTIONS:
-		g_value_set_object (value, self->pv->actions);
+		g_value_set_object (value, NULL);
 		break;
 	case PROP_INFO:
 		g_value_set_boxed (value, self->pv->info);
@@ -677,7 +674,6 @@ seahorse_token_finalize (GObject *obj)
 	g_hash_table_destroy (self->pv->objects_for_id);
 	g_hash_table_destroy (self->pv->id_for_object);
 	g_assert (self->pv->slot == NULL);
-	g_clear_object (&self->pv->actions);
 	g_free (self->pv->uri);
 
 	G_OBJECT_CLASS (seahorse_token_parent_class)->finalize (obj);
diff --git a/src/seahorse-generate-select.c b/src/seahorse-generate-select.c
index 28f4824..aedada0 100644
--- a/src/seahorse-generate-select.c
+++ b/src/seahorse-generate-select.c
@@ -100,7 +100,7 @@ on_row_activated (GtkTreeView *view,
 		g_object_ref (action);
 		gtk_widget_destroy (GTK_WIDGET (self));
 
-		seahorse_action_activate_with_window (action, parent);
+		seahorse_action_activate_with_window (action, NULL, parent);
 
 		g_clear_object (&parent);
 		g_object_unref (action);
@@ -128,7 +128,7 @@ on_response (GtkDialog *dialog,
 	gtk_widget_destroy (GTK_WIDGET (self));
 
 	if (action != NULL) {
-		seahorse_action_activate_with_window (action, parent);
+		seahorse_action_activate_with_window (action, NULL, parent);
 		g_object_unref (action);
 		g_clear_object (&parent);
 	}
diff --git a/src/seahorse-key-manager.c b/src/seahorse-key-manager.c
index 3c2fede..b666e0a 100644
--- a/src/seahorse-key-manager.c
+++ b/src/seahorse-key-manager.c
@@ -480,11 +480,11 @@ seahorse_key_manager_get_selected_objects (SeahorseCatalog *catalog)
 	return seahorse_key_manager_store_get_selected_objects (self->pv->view);
 }
 
-static GList *
-seahorse_key_manager_get_selected_places (SeahorseCatalog *catalog)
+static SeahorsePlace *
+seahorse_key_manager_get_focused_place (SeahorseCatalog *catalog)
 {
 	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (catalog);
-	return seahorse_sidebar_get_selected_places (self->pv->sidebar);
+	return seahorse_sidebar_get_focused_place (self->pv->sidebar);
 }
 
 static gboolean
@@ -768,14 +768,15 @@ static void
 seahorse_key_manager_class_init (SeahorseKeyManagerClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	SeahorseCatalogClass *catalog_class = SEAHORSE_CATALOG_CLASS (klass);
 
 	g_type_class_add_private (klass, sizeof (SeahorseKeyManagerPrivate));
 
 	gobject_class->constructed = seahorse_key_manager_constructed;
 	gobject_class->finalize = seahorse_key_manager_finalize;
 
-	SEAHORSE_CATALOG_CLASS (klass)->get_selected_objects = seahorse_key_manager_get_selected_objects;
-	SEAHORSE_CATALOG_CLASS (klass)->get_selected_places = seahorse_key_manager_get_selected_places;
+	catalog_class->get_selected_objects = seahorse_key_manager_get_selected_objects;
+	catalog_class->get_focused_place = seahorse_key_manager_get_focused_place;
 }
 
 SeahorseWidget *
diff --git a/src/seahorse-sidebar.c b/src/seahorse-sidebar.c
index 58d791c..481da2f 100644
--- a/src/seahorse-sidebar.c
+++ b/src/seahorse-sidebar.c
@@ -26,11 +26,13 @@
 #include "seahorse-action.h"
 #include "seahorse-actions.h"
 #include "seahorse-backend.h"
+#include "seahorse-deletable.h"
 #include "seahorse-interaction.h"
 #include "seahorse-lockable.h"
 #include "seahorse-place.h"
 #include "seahorse-registry.h"
 #include "seahorse-util.h"
+#include "seahorse-viewable.h"
 
 #include "gkr/seahorse-gkr.h"
 #include "pgp/seahorse-pgp.h"
@@ -64,6 +66,7 @@ struct _SeahorseSidebar {
 	GtkTreePath *action_highlight_path;
 	GtkCellRenderer *action_cell_renderer;
 	gint action_button_size;
+	GtkAccelGroup *accel_group;
 
 	guint update_places_sig;
 };
@@ -130,6 +133,8 @@ seahorse_sidebar_init (SeahorseSidebar *self)
 	self->selection = g_hash_table_new (g_direct_hash, g_direct_equal);
 	self->objects = GCR_UNION_COLLECTION (gcr_union_collection_new ());
 	self->chosen = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+	self->accel_group = gtk_accel_group_new ();
 }
 
 static guchar
@@ -781,6 +786,204 @@ load_backends (SeahorseSidebar *self)
 }
 
 static void
+on_place_locked (GObject *source,
+                 GAsyncResult *result,
+                 gpointer user_data)
+{
+	GtkWindow *parent = GTK_WINDOW (user_data);
+	GError *error = NULL;
+
+	if (!seahorse_lockable_lock_finish (SEAHORSE_LOCKABLE (source), result, &error))
+		seahorse_util_handle_error (&error, parent, _("Couldn't lock"));
+
+	g_object_unref (parent);
+}
+
+static void
+place_lock (SeahorseLockable *lockable,
+            GtkWindow *window)
+{
+	GCancellable *cancellable = g_cancellable_new ();
+	GTlsInteraction *interaction = seahorse_interaction_new (window);
+
+	seahorse_lockable_lock_async (lockable, interaction, cancellable,
+	                              on_place_locked, g_object_ref (window));
+
+	g_object_unref (cancellable);
+	g_object_unref (interaction);
+}
+
+static void
+on_place_lock (GtkMenuItem *item,
+               gpointer user_data)
+{
+	SeahorseLockable *lockable = SEAHORSE_LOCKABLE (user_data);
+	GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET (item));
+	place_lock (lockable, GTK_WINDOW (window));
+}
+
+static void
+on_place_unlocked (GObject *source,
+                 GAsyncResult *result,
+                 gpointer user_data)
+{
+	GtkWindow *parent = GTK_WINDOW (user_data);
+	GError *error = NULL;
+
+	if (!seahorse_lockable_unlock_finish (SEAHORSE_LOCKABLE (source), result, &error))
+		seahorse_util_handle_error (&error, parent, _("Couldn't unlock"));
+
+	g_object_unref (parent);
+}
+
+
+
+static void
+place_unlock (SeahorseLockable *lockable,
+              GtkWindow *window)
+{
+	GCancellable *cancellable = g_cancellable_new ();
+	GTlsInteraction *interaction = seahorse_interaction_new (window);
+
+	seahorse_lockable_unlock_async (lockable, interaction, cancellable,
+	                                on_place_unlocked, g_object_ref (window));
+
+	g_object_unref (cancellable);
+	g_object_unref (interaction);
+}
+
+static void
+on_place_unlock (GtkMenuItem *item,
+                 gpointer user_data)
+{
+	SeahorseLockable *lockable = SEAHORSE_LOCKABLE (user_data);
+	GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET (item));
+	place_unlock (lockable, GTK_WINDOW (window));
+}
+
+static void
+on_place_deleted (GObject *source,
+                  GAsyncResult *result,
+                  gpointer user_data)
+{
+	GtkWindow *parent = GTK_WINDOW (user_data);
+	GError *error = NULL;
+
+	if (!seahorse_deleter_delete_finish (SEAHORSE_DELETER (source), result, &error))
+		seahorse_util_handle_error (&error, parent, _("Couldn't delete"));
+
+	g_object_unref (parent);
+}
+
+static void
+on_place_delete (GtkMenuItem *item,
+                 gpointer user_data)
+{
+	SeahorseDeletable *deletable = SEAHORSE_DELETABLE (user_data);
+	GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET (item));
+	SeahorseDeleter *deleter;
+
+	deleter = seahorse_deletable_create_deleter (deletable);
+
+	if (seahorse_deleter_prompt (deleter, GTK_WINDOW (window)))
+		seahorse_deleter_delete_async (deleter, NULL, on_place_deleted,
+		                               g_object_ref (window));
+
+	g_object_unref (deleter);
+}
+
+static void
+on_place_properties (GtkMenuItem *item,
+                     gpointer user_data)
+{
+	SeahorseViewable *viewable = SEAHORSE_VIEWABLE (user_data);
+	GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET (item));
+	seahorse_viewable_show_viewer (viewable, GTK_WINDOW (window));
+}
+
+static void
+check_widget_visible (GtkWidget *widget,
+                      gpointer data)
+{
+	gboolean *visible = data;
+	if (gtk_widget_get_visible (widget))
+		*visible = TRUE;
+}
+
+static void
+popup_menu_for_place (SeahorseSidebar *self,
+                      SeahorsePlace *place,
+                      guint button,
+                      guint32 activate_time)
+{
+	GtkActionGroup *actions = NULL;
+	GtkMenu *menu;
+	GList *list, *l;
+	GtkWidget *item;
+	gboolean visible;
+
+	menu = GTK_MENU (gtk_menu_new ());
+
+	/* First add all the actions from the collection */
+	g_object_get (place, "actions", &actions, NULL);
+	list = actions ? gtk_action_group_list_actions (actions) : NULL;
+	if (list) {
+		for (l = list; l != NULL; l = g_list_next (l)) {
+			gtk_action_set_accel_group (l->data, self->accel_group);
+			item = gtk_action_create_menu_item (l->data);
+			gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+		}
+		g_list_free (list);
+	}
+	g_clear_object (&actions);
+
+	/* Lock and unlock items */
+	if (SEAHORSE_IS_LOCKABLE (place)) {
+		item = gtk_menu_item_new_with_mnemonic (_("_Lock"));
+		g_signal_connect (item, "activate", G_CALLBACK (on_place_lock), place);
+		g_object_bind_property (place, "lockable", item, "visible", G_BINDING_SYNC_CREATE);
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+		item = gtk_menu_item_new_with_mnemonic (_("_Unlock"));
+		g_signal_connect (item, "activate", G_CALLBACK (on_place_unlock), place);
+		g_object_bind_property (place, "unlockable", item, "visible", G_BINDING_SYNC_CREATE);
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+	}
+
+	/* Delete item */
+	if (SEAHORSE_IS_DELETABLE (place)) {
+		item = gtk_image_menu_item_new_with_mnemonic (_("_Delete"));
+		gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
+		                               gtk_image_new_from_stock (GTK_STOCK_DELETE, GTK_ICON_SIZE_MENU));
+		g_signal_connect (item, "activate", G_CALLBACK (on_place_delete), place);
+		g_object_bind_property (place, "deletable", item, "sensitive", G_BINDING_SYNC_CREATE);
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+		gtk_widget_show (item);
+	}
+
+	/* Properties item */
+	if (SEAHORSE_IS_VIEWABLE (place)) {
+		item = gtk_image_menu_item_new_with_mnemonic (_("_Properties"));
+		gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
+		                               gtk_image_new_from_stock (GTK_STOCK_PROPERTIES, GTK_ICON_SIZE_MENU));
+		g_signal_connect (item, "activate", G_CALLBACK (on_place_properties), place);
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+		gtk_widget_show (item);
+	}
+
+	visible = FALSE;
+	gtk_container_foreach (GTK_CONTAINER (menu), check_widget_visible, &visible);
+
+	if (visible) {
+		gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, activate_time);
+		gtk_menu_attach_to_widget (menu, GTK_WIDGET (self), NULL);
+		gtk_widget_show (GTK_WIDGET (menu));
+	} else {
+		gtk_widget_destroy (GTK_WIDGET (menu));
+	}
+}
+
+static void
 on_tree_view_popup_menu (GtkWidget *widget,
                          gpointer user_data)
 {
@@ -802,7 +1005,8 @@ on_tree_view_popup_menu (GtkWidget *widget,
 	                    SIDEBAR_COLLECTION, &collection,
 	                    -1);
 
-	g_signal_emit (self, signals[CONTEXT_MENU], 0, collection);
+	if (SEAHORSE_IS_PLACE (collection))
+		popup_menu_for_place (self, SEAHORSE_PLACE (collection), 0, gtk_get_current_event_time ());
 
 	g_clear_object (&collection);
 }
@@ -934,48 +1138,19 @@ on_tree_view_button_press_event (GtkWidget *widget,
 	                    SIDEBAR_COLLECTION, &collection,
 	                    -1);
 
-	g_signal_emit (self, signals[CONTEXT_MENU], 0, collection);
+	if (SEAHORSE_IS_PLACE (collection))
+		popup_menu_for_place (self, SEAHORSE_PLACE (collection), event->button, event->time);
 
 	g_clear_object (&collection);
 	return TRUE;
 }
 
-static void
-on_place_lock (GObject *source,
-               GAsyncResult *result,
-               gpointer user_data)
-{
-	GtkWindow *parent = GTK_WINDOW (user_data);
-	GError *error = NULL;
-
-	if (!seahorse_lockable_lock_finish (SEAHORSE_LOCKABLE (source), result, &error))
-		seahorse_util_handle_error (&error, parent, _("Couldn't lock"));
-
-	g_object_unref (parent);
-}
-
-static void
-on_place_unlock (GObject *source,
-                 GAsyncResult *result,
-                 gpointer user_data)
-{
-	GtkWindow *parent = GTK_WINDOW (user_data);
-	GError *error = NULL;
-
-	if (!seahorse_lockable_unlock_finish (SEAHORSE_LOCKABLE (source), result, &error))
-		seahorse_util_handle_error (&error, parent, _("Couldn't unlock"));
-
-	g_object_unref (parent);
-}
-
 static gboolean
 on_tree_view_button_release_event (GtkWidget *widget,
                                    GdkEventButton *event,
                                    gpointer user_data)
 {
 	SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
-	GTlsInteraction *interaction;
-	GCancellable *cancellable;
 	SeahorseLockable *lockable;
 	GtkTreePath *path;
 	GtkTreeModel *model;
@@ -998,24 +1173,16 @@ on_tree_view_button_release_event (GtkWidget *widget,
 		return FALSE;
 
 	window = gtk_widget_get_toplevel (widget);
-	cancellable = g_cancellable_new ();
-	interaction = seahorse_interaction_new (GTK_WINDOW (window));
 	ret = FALSE;
 
 	lockable = lookup_lockable_for_iter (model, &iter);
 	if (lockable) {
-		if (seahorse_lockable_can_lock (lockable)) {
-			seahorse_lockable_lock_async (lockable, interaction, cancellable,
-			                              on_place_lock, g_object_ref (window));
-		} else if (seahorse_lockable_can_unlock (lockable)) {
-			seahorse_lockable_unlock_async (lockable, interaction, cancellable,
-			                                on_place_unlock, g_object_ref (window));
-		}
+		if (seahorse_lockable_can_lock (lockable))
+			place_lock (lockable, GTK_WINDOW (window));
+		else if (seahorse_lockable_can_unlock (lockable))
+			place_unlock (lockable, GTK_WINDOW (window));
 	}
 
-	g_object_unref (cancellable);
-	g_object_unref (interaction);
-
 	return TRUE;
 }
 
@@ -1225,6 +1392,8 @@ seahorse_sidebar_finalize (GObject *obj)
 	if (self->action_highlight_path)
 		gtk_tree_path_free (self->action_highlight_path);
 
+	g_object_unref (self->accel_group);
+
 	G_OBJECT_CLASS (seahorse_sidebar_parent_class)->finalize (obj);
 }
 
@@ -1361,6 +1530,34 @@ seahorse_sidebar_get_selected_places (SeahorseSidebar *self)
 	return places;
 }
 
+SeahorsePlace *
+seahorse_sidebar_get_focused_place (SeahorseSidebar *self)
+{
+	GcrCollection *collection;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	RowType row_type;
+
+	g_return_val_if_fail (SEAHORSE_IS_SIDEBAR (self), NULL);
+
+	gtk_tree_view_get_cursor (self->tree_view, &path, NULL);
+	if (path != NULL) {
+		if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (self->store), &iter, path))
+			g_return_val_if_reached (NULL);
+		gtk_tree_path_free (path);
+
+		gtk_tree_model_get (GTK_TREE_MODEL (self->store), &iter,
+		                    SIDEBAR_ROW_TYPE, &row_type,
+		                    SIDEBAR_COLLECTION, &collection,
+		                    -1);
+
+		if (row_type == TYPE_PLACE)
+			return SEAHORSE_PLACE (collection);
+	}
+
+	return NULL;
+}
+
 GList *
 seahorse_sidebar_get_backends (SeahorseSidebar *self)
 {
diff --git a/src/seahorse-sidebar.h b/src/seahorse-sidebar.h
index aa41e99..c0d326a 100644
--- a/src/seahorse-sidebar.h
+++ b/src/seahorse-sidebar.h
@@ -22,6 +22,8 @@
 #ifndef __SEAHORSE_SIDEBAR_H__
 #define __SEAHORSE_SIDEBAR_H__
 
+#include "seahorse-place.h"
+
 #include <gcr/gcr.h>
 
 #include <gtk/gtk.h>
@@ -54,6 +56,8 @@ void                         seahorse_sidebar_set_selected_uris  (SeahorseSideba
 
 GList *                 seahorse_sidebar_get_selected_places     (SeahorseSidebar *self);
 
+SeahorsePlace *         seahorse_sidebar_get_focused_place       (SeahorseSidebar *self);
+
 GList *                 seahorse_sidebar_get_backends            (SeahorseSidebar *self);
 
 #endif /* __SEAHORSE_SIDEBAR_H__ */
diff --git a/ssh/seahorse-ssh-actions.c b/ssh/seahorse-ssh-actions.c
index 44f6e14..cf8137c 100644
--- a/ssh/seahorse-ssh-actions.c
+++ b/ssh/seahorse-ssh-actions.c
@@ -94,34 +94,13 @@ 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, 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);
-
-	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 *



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