[seahorse/refactor: 34/37] Rework how actions come from the backends and various objects.



commit abb1b7a289405b2840935149477d369e5be555ac
Author: Stef Walter <stefw collabora co uk>
Date:   Wed Oct 19 11:21:47 2011 +0200

    Rework how actions come from the backends and various objects.
    
     * Rename SeahorseSourc to SeahorsePlace
     * Actions are exposed by having a GtkActionGroup on the various
       objects, places, backends

 gkr/Makefile.am                                    |    3 +-
 gkr/seahorse-gkr-actions.c                         |  548 ++++++++++++
 gkr/seahorse-gkr-actions.h                         |   33 +
 gkr/seahorse-gkr-backend.c                         |   22 +-
 gkr/seahorse-gkr-item-commands.c                   |  162 ----
 gkr/seahorse-gkr-item-commands.h                   |   49 --
 gkr/seahorse-gkr-item.c                            |   36 +-
 gkr/seahorse-gkr-item.h                            |    1 -
 gkr/seahorse-gkr-keyring-commands.c                |  458 ----------
 gkr/seahorse-gkr-keyring-commands.h                |   53 --
 gkr/seahorse-gkr-keyring.c                         |   36 +-
 gkr/seahorse-gkr-operation.c                       |    2 +-
 libseahorse/Makefile.am                            |    5 +-
 libseahorse/seahorse-action.c                      |  130 +++
 libseahorse/seahorse-action.h                      |   42 +
 libseahorse/seahorse-actions.c                     |   78 ++
 libseahorse/seahorse-actions.h                     |   66 ++
 libseahorse/seahorse-backend.c                     |    4 +
 libseahorse/seahorse-backend.h                     |    5 +-
 libseahorse/seahorse-commands.c                    |  218 -----
 libseahorse/seahorse-commands.h                    |   75 --
 libseahorse/seahorse-context.h                     |    2 +-
 libseahorse/seahorse-key-manager-store.c           |   18 +-
 libseahorse/seahorse-object-widget.c               |    2 -
 libseahorse/seahorse-object.c                      |   89 ++-
 libseahorse/seahorse-object.h                      |   10 +-
 .../{seahorse-source.c => seahorse-place.c}        |  140 ++--
 .../{seahorse-source.h => seahorse-place.h}        |   73 +-
 libseahorse/seahorse-predicate.c                   |    2 +-
 libseahorse/seahorse-predicate.h                   |    1 -
 libseahorse/seahorse-util.c                        |   79 +-
 libseahorse/seahorse-util.h                        |   10 +-
 libseahorse/seahorse-viewer.c                      |  885 +++++++++-----------
 libseahorse/seahorse-viewer.h                      |   41 +-
 pgp/Makefile.am                                    |    2 +-
 pgp/seahorse-gpgme-key-op.c                        |    4 +-
 pgp/seahorse-gpgme-key.c                           |   16 +-
 pgp/seahorse-gpgme-key.h                           |    2 +-
 pgp/seahorse-gpgme-keyring.c                       |   69 +-
 pgp/seahorse-hkp-source.c                          |   19 +-
 pgp/seahorse-keyserver-results.c                   |   78 +--
 pgp/seahorse-keyserver-results.ui                  |   14 +-
 pgp/seahorse-keyserver-sync.c                      |   14 +-
 pgp/seahorse-ldap-source.c                         |   23 +-
 pgp/seahorse-pgp-actions.c                         |  329 ++++++++
 pgp/seahorse-pgp-actions.h                         |   32 +
 pgp/seahorse-pgp-backend.c                         |   48 +-
 pgp/seahorse-pgp-backend.h                         |    4 +-
 pgp/seahorse-pgp-commands.c                        |  369 --------
 pgp/seahorse-pgp-commands.h                        |   57 --
 pgp/seahorse-pgp-key.c                             |    1 -
 pgp/seahorse-server-source.c                       |    9 +-
 pgp/seahorse-transfer.c                            |   28 +-
 pgp/seahorse-transfer.h                            |    6 +-
 pgp/seahorse-unknown-source.h                      |    1 -
 pgp/seahorse-unknown.c                             |    2 +-
 pkcs11/Makefile.am                                 |    2 +-
 pkcs11/seahorse-certificate.c                      |   25 +-
 pkcs11/seahorse-pkcs11-actions.c                   |  182 ++++
 pkcs11/seahorse-pkcs11-actions.h                   |   29 +
 pkcs11/seahorse-pkcs11-backend.c                   |   20 +-
 pkcs11/seahorse-pkcs11-commands.c                  |  253 ------
 pkcs11/seahorse-pkcs11-commands.h                  |   53 --
 pkcs11/seahorse-pkcs11-operations.c                |    2 +-
 pkcs11/seahorse-token.c                            |   15 +-
 src/seahorse-key-manager.c                         |  129 +---
 src/seahorse-key-manager.ui                        |   25 +-
 src/seahorse-sidebar.c                             |   21 +
 src/seahorse-sidebar.h                             |    4 +
 ssh/Makefile.am                                    |    2 +-
 ssh/seahorse-ssh-actions.c                         |  171 ++++
 ssh/seahorse-ssh-actions.h                         |   28 +
 ssh/seahorse-ssh-backend.c                         |   11 +-
 ssh/seahorse-ssh-commands.c                        |  238 ------
 ssh/seahorse-ssh-commands.h                        |   57 --
 ssh/seahorse-ssh-key-properties.c                  |    8 +-
 ssh/seahorse-ssh-key.c                             |   11 +-
 ssh/seahorse-ssh-key.h                             |    4 +-
 ssh/seahorse-ssh-operation.c                       |   16 +-
 ssh/seahorse-ssh-source.c                          |   39 +-
 ssh/seahorse-ssh-source.h                          |    1 -
 ssh/seahorse-ssh-upload.c                          |    2 +-
 82 files changed, 2692 insertions(+), 3161 deletions(-)
---
diff --git a/gkr/Makefile.am b/gkr/Makefile.am
index 06f02cd..ef1e392 100644
--- a/gkr/Makefile.am
+++ b/gkr/Makefile.am
@@ -17,15 +17,14 @@ noinst_LTLIBRARIES = libseahorse-gkr.la
 
 libseahorse_gkr_la_SOURCES = \
 	seahorse-gkr.c seahorse-gkr.h \
+	seahorse-gkr-actions.c seahorse-gkr-actions.h \
 	seahorse-gkr-add-item.c \
 	seahorse-gkr-add-keyring.c \
 	seahorse-gkr-backend.c seahorse-gkr-backend.h \
 	seahorse-gkr-dialogs.h seahorse-gkr-dialogs.c \
 	seahorse-gkr-item.c seahorse-gkr-item.h \
-	seahorse-gkr-item-commands.c seahorse-gkr-item-commands.h \
 	seahorse-gkr-item-properties.c \
 	seahorse-gkr-keyring.c seahorse-gkr-keyring.h \
-	seahorse-gkr-keyring-commands.c seahorse-gkr-keyring-commands.h \
 	seahorse-gkr-keyring-properties.c \
 	seahorse-gkr-operation.c seahorse-gkr-operation.h
 
diff --git a/gkr/seahorse-gkr-actions.c b/gkr/seahorse-gkr-actions.c
new file mode 100644
index 0000000..2479dba
--- /dev/null
+++ b/gkr/seahorse-gkr-actions.c
@@ -0,0 +1,548 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "seahorse-gkr-actions.h"
+#include "seahorse-gkr-backend.h"
+#include "seahorse-gkr-keyring.h"
+#include "seahorse-gkr-dialogs.h"
+#include "seahorse-gkr-operation.h"
+
+#include "seahorse-action.h"
+#include "seahorse-actions.h"
+#include "seahorse-progress.h"
+#include "seahorse-registry.h"
+#include "seahorse-util.h"
+
+#include <glib/gi18n.h>
+
+GType   seahorse_gkr_backend_actions_get_type           (void) G_GNUC_CONST;
+#define SEAHORSE_TYPE_GKR_BACKEND_ACTIONS               (seahorse_gkr_backend_actions_get_type ())
+#define SEAHORSE_GKR_BACKEND_ACTIONS(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_GKR_BACKEND_ACTIONS, SeahorseGkrBackendActions))
+#define SEAHORSE_GKR_BACKEND_ACTIONS_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_GKR_BACKEND_ACTIONS, SeahorseGkrBackendActionsClass))
+#define SEAHORSE_IS_GKR_BACKEND_ACTIONS(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_GKR_BACKEND_ACTIONS))
+#define SEAHORSE_IS_GKR_BACKEND_ACTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_GKR_BACKEND_ACTIONS))
+#define SEAHORSE_GKR_BACKEND_ACTIONS_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_GKR_BACKEND_ACTIONS, SeahorseGkrBackendActionsClass))
+
+typedef struct {
+	SeahorseActions parent;
+} SeahorseGkrBackendActions;
+
+typedef struct {
+	SeahorseActionsClass parent;
+} SeahorseGkrBackendActionsClass;
+
+G_DEFINE_TYPE (SeahorseGkrBackendActions, seahorse_gkr_backend_actions, SEAHORSE_TYPE_ACTIONS);
+
+static void
+refresh_all_keyrings (void)
+{
+	seahorse_gkr_backend_load_async (NULL, NULL, NULL, NULL);
+}
+
+static void
+on_new_keyring (GtkAction *action,
+                gpointer unused)
+{
+	seahorse_gkr_add_keyring_show (seahorse_action_get_window (action));
+}
+
+
+static const GtkActionEntry BACKEND_ACTIONS[] = {
+	{ "new-keyring", "folder", N_("New password keyring"), "",
+	  N_("Used to store application and network passwords"), G_CALLBACK (on_new_keyring) },
+};
+
+static const gchar* BACKEND_UI = ""\
+"<ui>"\
+"	<popup name='PlacePopup'>"\
+"		<menuitem action='keyring-default'/>"\
+"		<menuitem action='keyring-lock'/>"\
+"		<menuitem action='keyring-unlock'/>"\
+"		<menuitem action='keyring-password'/>"\
+"	</popup>"\
+"</ui>";
+
+static void
+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);
+}
+
+static void
+seahorse_gkr_backend_actions_class_init (SeahorseGkrBackendActionsClass *klass)
+{
+
+}
+
+GtkActionGroup *
+seahorse_gkr_backend_actions_instance (void)
+{
+	static GtkActionGroup *actions = NULL;
+
+	if (actions == NULL) {
+		actions = g_object_new (SEAHORSE_TYPE_GKR_BACKEND_ACTIONS,
+		                        "name", "gkr-backend",
+		                        NULL);
+		g_object_add_weak_pointer (G_OBJECT (actions),
+		                           (gpointer *)&actions);
+	} else {
+		g_object_ref (actions);
+	}
+
+	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;
+	GtkAction *action_lock;
+	GtkAction *action_unlock;
+	GtkAction *action_default;
+} SeahorseGkrKeyringActions;
+
+typedef struct {
+	SeahorseActionsClass parent_class;
+} SeahorseGkrKeyringActionsClass;
+
+GType                      seahorse_gkr_keyring_actions_get_type               (void);
+
+
+G_DEFINE_TYPE (SeahorseGkrKeyringActions, seahorse_gkr_keyring_actions, SEAHORSE_TYPE_ACTIONS);
+
+static void
+on_gkr_add_item (GtkAction *action,
+                 gpointer unused)
+{
+	seahorse_gkr_add_item_show (seahorse_action_get_window (action));
+}
+
+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_keyring_unlock (GtkAction *action,
+                   gpointer user_data)
+{
+	GList *keys, *l;
+	GtkWindow *parent;
+
+	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,
+		                      on_keyring_unlock_done, g_object_ref (parent), g_object_unref);
+	}
+	g_list_free (keys);
+}
+
+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_keyring_lock (GtkAction *action,
+                 gpointer user_data)
+{
+	GList *keyrings, *l;
+	GtkWindow *parent;
+
+	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),
+		                    on_keyring_lock_done, g_object_ref (parent), g_object_unref);
+	}
+	g_list_free (keyrings);
+}
+
+static void
+on_set_default_keyring_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 set default keyring"),
+		                          gnome_keyring_result_to_message (result));
+	}
+
+	refresh_all_keyrings ();
+}
+
+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);
+	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
+on_change_password_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 change keyring password"),
+		                          gnome_keyring_result_to_message (result));
+	}
+
+	refresh_all_keyrings ();
+}
+
+static void
+on_keyring_password (GtkAction *action,
+                     gpointer user_data)
+{
+	GtkWindow *window;
+	GList *keys, *l;
+
+	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);
+	}
+
+	g_list_free (keys);
+}
+
+
+static void
+on_keyring_properties (GtkAction* action,
+                       gpointer user_data)
+{
+	seahorse_gkr_keyring_properties_show (seahorse_action_get_object (action),
+	                                      seahorse_action_get_window (action));
+}
+
+static void
+on_delete_objects_complete (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+	GtkWindow *parent = GTK_WINDOW (user_data);
+	GError *error = NULL;
+
+	if (!seahorse_gkr_delete_finish (result, &error)) {
+		seahorse_util_show_error (parent, _("Couldn't delete keyring"), error->message);
+		g_error_free (error);
+	}
+
+	g_object_unref (parent);
+}
+
+static void
+on_keyring_delete (GtkAction* action,
+                   gpointer user_data)
+{
+	GCancellable *cancellable;
+	GtkWindow *parent;
+	gchar *prompt;
+	gboolean ret;
+	GList *objects;
+
+	objects = seahorse_action_get_objects (action);
+	if (!objects)
+		return;
+
+	prompt = g_strdup_printf (_ ("Are you sure you want to delete the password keyring '%s'?"),
+	                          seahorse_object_get_label (objects->data));
+	parent = seahorse_action_get_window (action);
+
+	ret = seahorse_util_prompt_delete (prompt, GTK_WIDGET (parent));
+	if (ret) {
+		cancellable = g_cancellable_new ();
+		seahorse_gkr_delete_async (objects, cancellable,
+		                           on_delete_objects_complete,
+		                           g_object_ref (parent));
+		seahorse_progress_show (cancellable, ngettext ("Deleting keyring", "Deleting keyrings",
+		                                               g_list_length (objects)), TRUE);
+		g_object_unref (cancellable);
+	}
+
+	g_free (prompt);
+	g_list_free (objects);
+}
+
+
+static const GtkActionEntry KEYRING_ACTIONS[] = {
+	{ "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) },
+	{ "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) },
+	{ "keyring-default", NULL, N_("_Set as default"), "",
+	  N_("Applications usually store new passwords in the default keyring."), G_CALLBACK (on_keyring_default) },
+	{ "keyring-password", NULL, N_("Change _Password"), "",
+	  N_("Change the unlock password of the password storage keyring"), G_CALLBACK (on_keyring_password) },
+	{ "properties", GTK_STOCK_PROPERTIES, NULL, NULL,
+	  N_("Properties of the keyring."), G_CALLBACK (on_keyring_properties) },
+	{ "delete", GTK_STOCK_DELETE, NULL, NULL,
+	  N_("Delete the keyring."), G_CALLBACK (on_keyring_delete) },
+	{ "new-password", "emblem-readonly", N_("New password..."), "",
+	  N_("Safely store a password or secret."), G_CALLBACK (on_gkr_add_item) },
+};
+
+static void
+seahorse_gkr_keyring_actions_init (SeahorseGkrKeyringActions *self)
+{
+	GtkActionGroup *actions = GTK_ACTION_GROUP (self);
+	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, "keyring-lock"));
+	self->action_unlock = g_object_ref (gtk_action_group_get_action (actions, "keyring-unlock"));
+	self->action_default = g_object_ref (gtk_action_group_get_action (actions, "keyring-default"));
+	seahorse_actions_register_definition (SEAHORSE_ACTIONS (self), BACKEND_UI);
+}
+
+static void
+seahorse_gkr_keyring_actions_update (SeahorseActions *actions,
+                                     GList *objects)
+{
+	SeahorseGkrKeyringActions *self = SEAHORSE_GKR_KEYRING_ACTIONS (actions);
+	GnomeKeyringInfo *info;
+	gboolean locked = FALSE;
+	gboolean unlocked = FALSE;
+	gboolean can_default = FALSE;
+	GList *l;
+
+	for (l = objects; l; l = g_list_next (l)) {
+		info = seahorse_gkr_keyring_get_info (l->data);
+		if (info != NULL) {
+			if (gnome_keyring_info_get_is_locked (info))
+				locked = TRUE;
+			else
+				unlocked = TRUE;
+			if (!seahorse_gkr_keyring_get_is_default (l->data))
+				can_default = TRUE;
+		}
+	}
+
+	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);
+
+	G_OBJECT_CLASS (seahorse_gkr_keyring_actions_parent_class)->finalize (obj);
+}
+
+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;
+}
+
+GtkActionGroup *
+seahorse_gkr_keyring_actions_instance (void)
+{
+	static GtkActionGroup *actions = NULL;
+
+	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;
+
+typedef struct {
+	SeahorseActionsClass parent_class;
+} SeahorseGkrItemActionsClass;
+
+G_DEFINE_TYPE (SeahorseGkrItemActions, seahorse_gkr_item_actions, SEAHORSE_TYPE_ACTIONS);
+
+static void
+on_password_properties (GtkAction *action,
+                        gpointer user_data)
+{
+	seahorse_gkr_item_properties_show (seahorse_action_get_object (action),
+	                                   seahorse_action_get_window (action));
+}
+
+static void
+on_delete_objects (GObject *source,
+                   GAsyncResult *result,
+                   gpointer user_data)
+{
+	GtkWidget *parent = GTK_WIDGET (user_data);
+	GError *error = NULL;
+
+	if (!seahorse_gkr_delete_finish (result, &error)) {
+		seahorse_util_show_error (parent, _("Couldn't delete item"), error->message);
+		g_error_free (error);
+	}
+
+	g_object_unref (parent);
+}
+
+static void
+on_delete_passwords (GtkAction *action,
+                     gpointer user_data)
+{
+	GCancellable *cancellable;
+	GtkWidget *parent;
+	GList *objects;
+	gchar *prompt;
+	gboolean ret;
+	guint num;
+
+	objects = seahorse_action_get_objects (action);
+	if (objects == NULL)
+		return;
+
+	num = g_list_length (objects);
+	if (num == 1) {
+		prompt = g_strdup_printf (_ ("Are you sure you want to delete the password '%s'?"),
+		                          seahorse_object_get_label (SEAHORSE_OBJECT (objects->data)));
+	} else {
+		prompt = g_strdup_printf (ngettext ("Are you sure you want to delete %d password?",
+		                                    "Are you sure you want to delete %d passwords?",
+		                                    num), num);
+	}
+
+	parent = GTK_WIDGET (seahorse_action_get_window (action));
+	ret = seahorse_util_prompt_delete (prompt, parent);
+
+	if (ret) {
+		cancellable = g_cancellable_new ();
+		seahorse_gkr_delete_async (objects, cancellable, on_delete_objects, g_object_ref (parent));
+		seahorse_progress_show (cancellable, ngettext ("Deleting item", "Deleting items", num), TRUE);
+		g_object_unref (cancellable);
+	}
+
+	g_free (prompt);
+	g_list_free (objects);
+}
+
+static const GtkActionEntry ITEM_ACTIONS[] = {
+	{ "properties", GTK_STOCK_PROPERTIES, NULL, NULL,
+	  N_("Properties of the password."), G_CALLBACK (on_password_properties) },
+	{ "delete", GTK_STOCK_DELETE, NULL, NULL,
+	  N_("Delete the password."), G_CALLBACK (on_delete_passwords) },
+};
+
+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 void
+seahorse_gkr_item_actions_class_init (SeahorseGkrItemActionsClass *klass)
+{
+
+}
+
+GtkActionGroup *
+seahorse_gkr_item_actions_instance (void)
+{
+	static GtkActionGroup *actions = NULL;
+
+	if (actions == NULL) {
+		actions = g_object_new (SEAHORSE_TYPE_GKR_ITEM_ACTIONS,
+		                        "name", "gkr-item",
+		                        NULL);
+		g_object_add_weak_pointer (G_OBJECT (actions),
+		                           (gpointer *)&actions);
+	} else {
+		g_object_ref (actions);
+	}
+
+	return actions;
+}
diff --git a/gkr/seahorse-gkr-actions.h b/gkr/seahorse-gkr-actions.h
new file mode 100644
index 0000000..7db0064
--- /dev/null
+++ b/gkr/seahorse-gkr-actions.h
@@ -0,0 +1,33 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __SEAHORSE_GKR_ACTIONS_H__
+#define __SEAHORSE_GKR_ACTIONS_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);
+
+#endif /* __SEAHORSE_GKR_ACTIONS_H__ */
diff --git a/gkr/seahorse-gkr-backend.c b/gkr/seahorse-gkr-backend.c
index 9d90564..425c96f 100644
--- a/gkr/seahorse-gkr-backend.c
+++ b/gkr/seahorse-gkr-backend.c
@@ -21,15 +21,15 @@
 
 #include "config.h"
 
+#include "seahorse-gkr-actions.h"
 #include "seahorse-gkr-backend.h"
 #include "seahorse-gkr-dialogs.h"
-#include "seahorse-gkr-item-commands.h"
-#include "seahorse-gkr-keyring-commands.h"
 #include "seahorse-gkr-operation.h"
 
 #include "seahorse-backend.h"
 #include "seahorse-progress.h"
 #include "seahorse-registry.h"
+#include "seahorse-viewer.h"
 
 #include <gnome-keyring.h>
 
@@ -39,7 +39,8 @@ enum {
 	PROP_0,
 	PROP_NAME,
 	PROP_LABEL,
-	PROP_DESCRIPTION
+	PROP_DESCRIPTION,
+	PROP_ACTIONS
 };
 
 static SeahorseGkrBackend *gkr_backend = NULL;
@@ -47,6 +48,7 @@ static SeahorseGkrBackend *gkr_backend = NULL;
 struct _SeahorseGkrBackend {
 	GObject parent;
 	GHashTable *keyrings;
+	GtkActionGroup *actions;
 };
 
 struct _SeahorseGkrBackendClass {
@@ -68,12 +70,9 @@ seahorse_gkr_backend_init (SeahorseGkrBackend *self)
 	g_return_if_fail (gkr_backend == NULL);
 	gkr_backend = self;
 
+	self->actions = seahorse_gkr_backend_actions_instance ();
 	self->keyrings = g_hash_table_new_full (g_str_hash, g_str_equal,
 	                                        g_free, g_object_unref);
-
-	/* Let these classes register themselves, when the backend is created */
-	g_type_class_unref (g_type_class_ref (SEAHORSE_TYPE_GKR_ITEM_COMMANDS));
-	g_type_class_unref (g_type_class_ref (SEAHORSE_TYPE_GKR_KEYRING_COMMANDS));
 }
 
 static void
@@ -92,6 +91,8 @@ seahorse_gkr_backend_get_property (GObject *obj,
                                    GValue *value,
                                    GParamSpec *pspec)
 {
+	SeahorseGkrBackend *self = SEAHORSE_GKR_BACKEND (obj);
+
 	switch (prop_id) {
 	case PROP_NAME:
 		g_value_set_string (value, SEAHORSE_GKR_NAME);
@@ -102,6 +103,9 @@ seahorse_gkr_backend_get_property (GObject *obj,
 	case PROP_DESCRIPTION:
 		g_value_set_string (value, _("Stored personal passwords, credentials and secrets"));
 		break;
+	case PROP_ACTIONS:
+		g_value_set_object (value, self->actions);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -114,6 +118,7 @@ seahorse_gkr_backend_dispose (GObject *obj)
 	SeahorseGkrBackend *self = SEAHORSE_GKR_BACKEND (obj);
 
 	g_hash_table_remove_all (self->keyrings);
+	gtk_action_group_set_sensitive (self->actions, FALSE);
 
 	G_OBJECT_CLASS (seahorse_gkr_backend_parent_class)->finalize (obj);
 }
@@ -124,6 +129,8 @@ seahorse_gkr_backend_finalize (GObject *obj)
 	SeahorseGkrBackend *self = SEAHORSE_GKR_BACKEND (obj);
 
 	g_hash_table_destroy (self->keyrings);
+	g_clear_object (&self->actions);
+
 	g_return_if_fail (gkr_backend == self);
 	gkr_backend = NULL;
 
@@ -143,6 +150,7 @@ seahorse_gkr_backend_class_init (SeahorseGkrBackendClass *klass)
 	g_object_class_override_property (gobject_class, PROP_NAME, "name");
 	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
 	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
+	g_object_class_override_property (gobject_class, PROP_ACTIONS, "actions");
 }
 
 static guint
diff --git a/gkr/seahorse-gkr-item.c b/gkr/seahorse-gkr-item.c
index b6ca1a8..8c9e1ea 100644
--- a/gkr/seahorse-gkr-item.c
+++ b/gkr/seahorse-gkr-item.c
@@ -26,16 +26,17 @@
 
 #include <glib/gi18n.h>
 
-#include "seahorse-icons.h"
-#include "seahorse-source.h"
-#include "seahorse-util.h"
-#include "seahorse-secure-memory.h"
-
 #include "seahorse-gkr.h"
+#include "seahorse-gkr-actions.h"
 #include "seahorse-gkr-item.h"
 #include "seahorse-gkr-keyring.h"
 #include "seahorse-gkr-operation.h"
 
+#include "seahorse-icons.h"
+#include "seahorse-place.h"
+#include "seahorse-util.h"
+#include "seahorse-secure-memory.h"
+
 #define GENERIC_SECRET "org.freedesktop.Secret.Generic"
 #define NETWORK_PASSWORD "org.gnome.keyring.NetworkPassword"
 #define KEYRING_NOTE "org.gnome.keyring.Note"
@@ -735,8 +736,16 @@ 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);
-	g_object_set (self, "usage", SEAHORSE_USAGE_CREDENTIALS, NULL);
+
+	actions = seahorse_gkr_item_actions_instance ();
+	g_object_set (self,
+	              "usage", SEAHORSE_USAGE_CREDENTIALS,
+	              "actions", actions,
+	              NULL);
+	g_object_unref (actions);
 }
 
 static void
@@ -818,11 +827,11 @@ static void
 seahorse_gkr_item_dispose (GObject *obj)
 {
 	SeahorseGkrItem *self = SEAHORSE_GKR_ITEM (obj);
-	SeahorseSource *source;
+	SeahorsePlace *place;
 
-	source = seahorse_object_get_source (SEAHORSE_OBJECT (self));
-	if (source != NULL)
-		seahorse_gkr_keyring_remove_item (SEAHORSE_GKR_KEYRING (source),
+	place = seahorse_object_get_place (SEAHORSE_OBJECT (self));
+	if (place != NULL)
+		seahorse_gkr_keyring_remove_item (SEAHORSE_GKR_KEYRING (place),
 		                                  self->pv->item_id);
 
 	G_OBJECT_CLASS (seahorse_gkr_item_parent_class)->dispose (obj);
@@ -907,8 +916,11 @@ seahorse_gkr_item_new (SeahorseGkrKeyring *keyring,
                        const gchar *keyring_name,
                        guint32 item_id)
 {
-	return g_object_new (SEAHORSE_TYPE_GKR_ITEM, "source", keyring,
-	                     "item-id", item_id, "keyring-name", keyring_name, NULL);
+	return g_object_new (SEAHORSE_TYPE_GKR_ITEM,
+	                     "place", keyring,
+	                     "item-id", item_id,
+	                     "keyring-name", keyring_name,
+	                     NULL);
 }
 
 guint32
diff --git a/gkr/seahorse-gkr-item.h b/gkr/seahorse-gkr-item.h
index 10f7405..56d8adc 100644
--- a/gkr/seahorse-gkr-item.h
+++ b/gkr/seahorse-gkr-item.h
@@ -30,7 +30,6 @@
 #include "seahorse-gkr-keyring.h"
 
 #include "seahorse-object.h"
-#include "seahorse-source.h"
 
 typedef enum {
     SEAHORSE_GKR_USE_OTHER,
diff --git a/gkr/seahorse-gkr-keyring.c b/gkr/seahorse-gkr-keyring.c
index 5caab44..6de6a17 100644
--- a/gkr/seahorse-gkr-keyring.c
+++ b/gkr/seahorse-gkr-keyring.c
@@ -25,8 +25,9 @@
 #include "seahorse-gkr.h"
 #include "seahorse-gkr-keyring.h"
 #include "seahorse-gkr-operation.h"
+#include "seahorse-gkr-actions.h"
 
-#include "seahorse-predicate.h"
+#include "seahorse-action.h"
 #include "seahorse-progress.h"
 #include "seahorse-util.h"
 
@@ -41,6 +42,7 @@ enum {
 	PROP_KEYRING_INFO,
 	PROP_IS_DEFAULT,
 	PROP_URI,
+	PROP_ACTIONS,
 };
 
 struct _SeahorseGkrKeyringPrivate {
@@ -50,14 +52,16 @@ struct _SeahorseGkrKeyringPrivate {
 
 	gpointer req_info;
 	GnomeKeyringInfo *keyring_info;
+
+	GtkActionGroup *actions;
 };
 
-static void     seahorse_keyring_source_iface        (SeahorseSourceIface *iface);
-static void     seahorse_keyring_collection_iface    (GcrCollectionIface *iface);
+static void     seahorse_keyring_place_iface        (SeahorsePlaceIface *iface);
+static void     seahorse_keyring_collection_iface   (GcrCollectionIface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (SeahorseGkrKeyring, seahorse_gkr_keyring, SEAHORSE_TYPE_OBJECT,
                          G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_keyring_collection_iface);
-                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_keyring_source_iface);
+                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_PLACE, seahorse_keyring_place_iface);
 );
 
 static GType
@@ -71,10 +75,6 @@ boxed_type_keyring_info (void)
 	return type;
 }
 
-/* -----------------------------------------------------------------------------
- * INTERNAL 
- */
-
 static void
 received_keyring_info (GnomeKeyringResult result, GnomeKeyringInfo *info, gpointer data)
 {
@@ -162,7 +162,7 @@ seahorse_gkr_keyring_remove_item (SeahorseGkrKeyring *self,
 	item = g_hash_table_lookup (self->pv->items, GUINT_TO_POINTER (item_id));
 	if (item != NULL) {
 		g_object_ref (item);
-		g_object_set (item, "source", NULL, NULL);
+		g_object_set (item, "place", NULL, NULL);
 		g_hash_table_remove (self->pv->items, GUINT_TO_POINTER (item_id));
 		gcr_collection_emit_removed (GCR_COLLECTION (self), G_OBJECT (item));
 		g_object_unref (item);
@@ -248,9 +248,7 @@ on_keyring_load_list_item_ids (GnomeKeyringResult result,
 		list = g_list_next (list);
 	}
 
-	g_hash_table_foreach (checks, (GHFunc)remove_key_from_context,
-	                      SEAHORSE_SOURCE (closure->keyring));
-
+	g_hash_table_foreach (checks, (GHFunc)remove_key_from_context, closure->keyring);
 	g_hash_table_destroy (checks);
 
 	seahorse_progress_end (closure->cancellable, res);
@@ -358,6 +356,7 @@ 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
@@ -371,14 +370,16 @@ seahorse_gkr_keyring_finalize (GObject *obj)
 		gnome_keyring_info_free (self->pv->keyring_info);
 	self->pv->keyring_info = NULL;
 	g_assert (self->pv->req_info == NULL);
-    
+
 	g_free (self->pv->keyring_name);
 	self->pv->keyring_name = NULL;
 	
 	if (self->pv->keyring_info) 
 		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);
 }
 
@@ -430,6 +431,9 @@ seahorse_gkr_keyring_get_property (GObject *obj, guint prop_id, GValue *value,
 		text = g_strdup_printf ("secret-service://%s", self->pv->keyring_name);
 		g_value_take_string (value, text);
 		break;
+	case PROP_ACTIONS:
+		g_value_set_object (value, self->pv->actions);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -449,8 +453,8 @@ seahorse_gkr_keyring_class_init (SeahorseGkrKeyringClass *klass)
 	gobject_class->get_property = seahorse_gkr_keyring_get_property;
 
 	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
-
 	g_object_class_override_property (gobject_class, PROP_URI, "uri");
+	g_object_class_override_property (gobject_class, PROP_ACTIONS, "actions");
 
 	g_object_class_install_property (gobject_class, PROP_KEYRING_NAME,
 	           g_param_spec_string ("keyring-name", "Gnome Keyring Name", "Name of keyring.", 
@@ -466,7 +470,7 @@ seahorse_gkr_keyring_class_init (SeahorseGkrKeyringClass *klass)
 }
 
 static void
-seahorse_keyring_source_iface (SeahorseSourceIface *iface)
+seahorse_keyring_place_iface (SeahorsePlaceIface *iface)
 {
 
 }
diff --git a/gkr/seahorse-gkr-operation.c b/gkr/seahorse-gkr-operation.c
index c282fa4..46d7252 100644
--- a/gkr/seahorse-gkr-operation.c
+++ b/gkr/seahorse-gkr-operation.c
@@ -404,7 +404,7 @@ on_delete_gkr_complete (GnomeKeyringResult result,
 		g_simple_async_result_complete_in_idle (res);
 
 	} else if (SEAHORSE_IS_GKR_ITEM (object)) {
-		g_object_get (object, "source", &keyring, NULL);
+		g_object_get (object, "place", &keyring, NULL);
 		item = SEAHORSE_GKR_ITEM (object);
 		seahorse_gkr_keyring_remove_item (keyring, seahorse_gkr_item_get_item_id (item));
 
diff --git a/libseahorse/Makefile.am b/libseahorse/Makefile.am
index bc42164..89894f7 100644
--- a/libseahorse/Makefile.am
+++ b/libseahorse/Makefile.am
@@ -28,11 +28,12 @@ KEYSERVER_SRCS =
 endif
 
 libseahorse_la_SOURCES = \
+	seahorse-action.c seahorse-action.h \
+	seahorse-actions.c seahorse-actions.h \
 	seahorse-backend.c seahorse-backend.h \
 	seahorse-bind.c seahorse-bind.h \
 	seahorse-cleanup.c seahorse-cleanup.h \
 	seahorse-collection.c seahorse-collection.h \
-	seahorse-commands.c seahorse-commands.h \
 	seahorse-context.c seahorse-context.h \
 	seahorse-debug.c seahorse-debug.h \
 	seahorse-icons.c seahorse-icons.h \
@@ -42,6 +43,7 @@ libseahorse_la_SOURCES = \
 	seahorse-object-model.c seahorse-object-model.h \
 	seahorse-object-widget.c seahorse-object-widget.h \
 	seahorse-passphrase.c seahorse-passphrase.h \
+	seahorse-place.c seahorse-place.h \
 	seahorse-predicate.c seahorse-predicate.h \
 	seahorse-prefs.c seahorse-prefs.h \
 	seahorse-preferences.c seahorse-preferences.h \
@@ -50,7 +52,6 @@ libseahorse_la_SOURCES = \
 	seahorse-secure-memory.c seahorse-secure-memory.h \
 	seahorse-secure-buffer.c seahorse-secure-buffer.h \
 	seahorse-servers.c seahorse-servers.h \
-	seahorse-source.c seahorse-source.h \
 	seahorse-types.c seahorse-types.h \
 	seahorse-util.c seahorse-util.h \
 	seahorse-validity.c seahorse-validity.h \
diff --git a/libseahorse/seahorse-action.c b/libseahorse/seahorse-action.c
new file mode 100644
index 0000000..89fafc9
--- /dev/null
+++ b/libseahorse/seahorse-action.c
@@ -0,0 +1,130 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "seahorse-action.h"
+
+#include <gck/gck.h>
+
+typedef struct {
+	GtkWindow *window;
+	GList *objects;
+} SeahorseActionInfo;
+
+static void
+seahorse_action_info_free (gpointer data)
+{
+	SeahorseActionInfo *info = data;
+	g_clear_object (&info->window);
+	gck_list_unref_free (info->objects);
+	g_slice_free (SeahorseActionInfo, info);
+}
+
+static SeahorseActionInfo *
+seahorse_action_info_lookup (GtkAction *action)
+{
+	SeahorseActionInfo *info;
+	static GQuark QUARK_INFO = 0;
+
+	if (QUARK_INFO == 0)
+		QUARK_INFO = g_quark_from_static_string ("seahorse-action-info");
+
+	info = g_object_get_qdata (G_OBJECT (action), QUARK_INFO);
+	if (info == NULL) {
+		info = g_slice_new0 (SeahorseActionInfo);
+		g_object_set_qdata_full (G_OBJECT (action), QUARK_INFO, info,
+		                         seahorse_action_info_free);
+	}
+
+	return info;
+}
+
+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_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+	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;
+}
+
+void
+seahorse_action_set_window (GtkAction *action,
+                            GtkWindow *window)
+{
+	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;
+}
+
+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);
+}
+
+gboolean
+seahorse_action_have_objects (GtkAction *action)
+{
+	SeahorseActionInfo *info;
+
+	g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
+
+	info = seahorse_action_info_lookup (action);
+	return info->objects ? TRUE : FALSE;
+}
diff --git a/libseahorse/seahorse-action.h b/libseahorse/seahorse-action.h
new file mode 100644
index 0000000..6acb948
--- /dev/null
+++ b/libseahorse/seahorse-action.h
@@ -0,0 +1,42 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __SEAHORSE_ACTION_H__
+#define __SEAHORSE_ACTION_H__
+
+#include <gtk/gtk.h>
+
+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);
+
+gboolean              seahorse_action_have_objects              (GtkAction *action);
+
+#endif
diff --git a/libseahorse/seahorse-actions.c b/libseahorse/seahorse-actions.c
new file mode 100644
index 0000000..31465c6
--- /dev/null
+++ b/libseahorse/seahorse-actions.c
@@ -0,0 +1,78 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "seahorse-actions.h"
+
+struct _SeahorseActionsPrivate {
+	const gchar *definition;
+};
+
+G_DEFINE_TYPE (SeahorseActions, seahorse_actions, GTK_TYPE_ACTION_GROUP);
+
+static void
+seahorse_actions_real_update (SeahorseActions *self,
+                              GList *selected)
+{
+
+}
+
+static void
+seahorse_actions_init (SeahorseActions *self)
+{
+	self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_ACTIONS,
+	                                         SeahorseActionsPrivate));
+}
+
+static void
+seahorse_actions_class_init (SeahorseActionsClass *klass)
+{
+	g_type_class_add_private (klass, sizeof (SeahorseActionsPrivate));
+
+	klass->update = seahorse_actions_real_update;
+}
+
+const gchar *
+seahorse_actions_get_definition (SeahorseActions* self)
+{
+	g_return_val_if_fail (SEAHORSE_IS_ACTIONS (self), NULL);
+	return self->pv->definition;
+}
+
+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)
+{
+	g_return_if_fail (SEAHORSE_IS_ACTIONS (self));
+	g_return_if_fail (self->pv->definition == NULL);
+	self->pv->definition = definition;
+}
diff --git a/libseahorse/seahorse-actions.h b/libseahorse/seahorse-actions.h
new file mode 100644
index 0000000..34b3f3a
--- /dev/null
+++ b/libseahorse/seahorse-actions.h
@@ -0,0 +1,66 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __SEAHORSE_ACTIONS_H__
+#define __SEAHORSE_ACTIONS_H__
+
+#include <gtk/gtk.h>
+
+#include "seahorse-object.h"
+#include "seahorse-viewer.h"
+
+#define SEAHORSE_TYPE_ACTIONS                  (seahorse_actions_get_type ())
+#define SEAHORSE_ACTIONS(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_ACTIONS, SeahorseActions))
+#define SEAHORSE_ACTIONS_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_ACTIONS, SeahorseActionsClass))
+#define SEAHORSE_IS_ACTIONS(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_ACTIONS))
+#define SEAHORSE_IS_ACTIONS_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_ACTIONS))
+#define SEAHORSE_ACTIONS_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_ACTIONS, SeahorseActionsClass))
+
+typedef struct _SeahorseActions SeahorseActions;
+typedef struct _SeahorseActionsClass SeahorseActionsClass;
+typedef struct _SeahorseActionsPrivate SeahorseActionsPrivate;
+
+struct _SeahorseActions {
+	GtkActionGroup parent_instance;
+	SeahorseActionsPrivate *pv;
+};
+
+struct _SeahorseActionsClass {
+	GtkActionGroupClass parent_class;
+
+	void        (*update)            (SeahorseActions *self,
+	                                  GList *selected);
+};
+
+GType                 seahorse_actions_get_type                 (void);
+
+SeahorseViewer *      seahorse_actions_get_viewer               (SeahorseActions *self);
+
+const gchar *         seahorse_actions_get_definition           (SeahorseActions *self);
+
+void                  seahorse_actions_register_definition      (SeahorseActions *self,
+                                                                 const gchar *definition);
+
+void                  seahorse_actions_update                   (SeahorseActions *actions,
+                                                                 GList *selected);
+
+#endif
diff --git a/libseahorse/seahorse-backend.c b/libseahorse/seahorse-backend.c
index b907a87..0e7ddc2 100644
--- a/libseahorse/seahorse-backend.c
+++ b/libseahorse/seahorse-backend.c
@@ -46,6 +46,10 @@ seahorse_backend_default_init (SeahorseBackendIface *iface)
 		           g_param_spec_string ("description", "Description", "Description for the backend",
 		                                "", G_PARAM_READABLE));
 
+		g_object_interface_install_property (iface,
+		           g_param_spec_object ("actions", "Actions", "Backend actions",
+		                                GTK_TYPE_ACTION_GROUP, G_PARAM_READABLE));
+
 		initialized = TRUE;
 	}
 }
diff --git a/libseahorse/seahorse-backend.h b/libseahorse/seahorse-backend.h
index f7578d2..dcb335c 100644
--- a/libseahorse/seahorse-backend.h
+++ b/libseahorse/seahorse-backend.h
@@ -23,6 +23,7 @@
 #define __SEAHORSE_BACKEND_H__
 
 #include <glib-object.h>
+#include <gtk/gtk.h>
 
 #define SEAHORSE_TYPE_BACKEND                (seahorse_backend_get_type ())
 #define SEAHORSE_BACKEND(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_BACKEND, SeahorseBackend))
@@ -36,6 +37,8 @@ struct _SeahorseBackendIface {
 	GTypeInterface parent;
 };
 
-GType            seahorse_backend_get_type             (void) G_GNUC_CONST;
+GType               seahorse_backend_get_type           (void) G_GNUC_CONST;
+
+GtkActionGroup *    seahorse_backend_get_actions        (SeahorseBackend *backend);
 
 #endif /* __SEAHORSE_BACKEND_H__ */
diff --git a/libseahorse/seahorse-context.h b/libseahorse/seahorse-context.h
index 4424bb4..b1135c0 100644
--- a/libseahorse/seahorse-context.h
+++ b/libseahorse/seahorse-context.h
@@ -26,7 +26,7 @@
 
 #include <gtk/gtk.h>
 
-#include "seahorse-source.h"
+#include "seahorse-place.h"
 
 #define SEAHORSE_TYPE_CONTEXT			(seahorse_context_get_type ())
 #define SEAHORSE_CONTEXT(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_CONTEXT, SeahorseContext))
diff --git a/libseahorse/seahorse-key-manager-store.c b/libseahorse/seahorse-key-manager-store.c
index b2b2677..2765978 100644
--- a/libseahorse/seahorse-key-manager-store.c
+++ b/libseahorse/seahorse-key-manager-store.c
@@ -23,17 +23,19 @@
 
 #include "config.h"
 
+#include "seahorse-place.h"
+#include "seahorse-util.h"
+
+#include "seahorse-key-manager-store.h"
+#include "seahorse-preferences.h"
+#include "seahorse-validity.h"
+
 #include <string.h>
 #include <unistd.h>
 
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
 
-#include "seahorse-key-manager-store.h"
-#include "seahorse-preferences.h"
-#include "seahorse-util.h"
-#include "seahorse-validity.h"
-
 #define DEBUG_FLAG SEAHORSE_DEBUG_DRAG
 #include "seahorse-debug.h"
 
@@ -358,8 +360,8 @@ export_to_text (SeahorseKeyManagerStore *skstore,
 	output = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
 	g_return_val_if_fail (output, FALSE);
 
-	ret = seahorse_source_export_auto_wait (skstore->priv->drag_objects, output,
-	                                        &skstore->priv->drag_error) &&
+	ret = seahorse_place_export_auto_wait (skstore->priv->drag_objects, output,
+	                                       &skstore->priv->drag_error) &&
 	      g_output_stream_close (output, NULL, &skstore->priv->drag_error);
 
 	if (ret) {
@@ -403,7 +405,7 @@ export_to_filename (SeahorseKeyManagerStore *skstore, const gchar *filename)
 
 	if (output) {
 		/* This modifies and frees keys */
-		ret = seahorse_source_export_auto_wait (keys, output, &skstore->priv->drag_error) &&
+		ret = seahorse_place_export_auto_wait (keys, output, &skstore->priv->drag_error) &&
 		      g_output_stream_close (output, NULL, &skstore->priv->drag_error);
 
 		g_object_unref (output);
diff --git a/libseahorse/seahorse-object-widget.c b/libseahorse/seahorse-object-widget.c
index 9bcad8b..d15349d 100644
--- a/libseahorse/seahorse-object-widget.c
+++ b/libseahorse/seahorse-object-widget.c
@@ -23,8 +23,6 @@
 
 #include "seahorse-object-widget.h"
 
-#define PROPERTIES "object-properties"
-
 enum {
 	PROP_0,
 	PROP_OBJECT
diff --git a/libseahorse/seahorse-object.c b/libseahorse/seahorse-object.c
index 794d9cb..18c49bb 100644
--- a/libseahorse/seahorse-object.c
+++ b/libseahorse/seahorse-object.c
@@ -23,27 +23,17 @@
 #include "config.h"
 
 #include "seahorse-object.h"
+#include "seahorse-place.h"
 #include "seahorse-predicate.h"
-#include "seahorse-source.h"
 
 #include "string.h"
 
 #include <glib/gi18n.h>
 
-/*
- * @PROP_0:
- * @PROP_SOURCE:
- * @PROP_LABEL:
- * @PROP_MARKUP:
- * @PROP_NICKNAME:
- * @PROP_ICON:
- * @PROP_IDENTIFIER:
- * @PROP_USAGE:
- * @PROP_FLAGS:
- */
-enum _SeahorseObjectProps {
+enum {
 	PROP_0,
-	PROP_SOURCE,
+	PROP_PLACE,
+	PROP_ACTIONS,
 	PROP_LABEL,
 	PROP_MARKUP,
 	PROP_NICKNAME,
@@ -54,7 +44,7 @@ enum _SeahorseObjectProps {
 };
 
 /**
- * @source: Where did the object come from ?
+ * @place: Where did the object come from ?
  * @label: DBUS: "display-name"
  * @markup: Markup text
  * @markup_explicit: If TRUE the markup will not be set automatically
@@ -68,7 +58,8 @@ enum _SeahorseObjectProps {
  * @flags:
  */
 struct _SeahorseObjectPrivate {
-	SeahorseSource *source;
+	SeahorsePlace *place;
+	GtkActionGroup *actions;
 
     gchar *label;             
     gchar *markup;
@@ -199,9 +190,10 @@ seahorse_object_dispose (GObject *obj)
 {
 	SeahorseObject *self = SEAHORSE_OBJECT (obj);
 
-	if (self->pv->source != NULL) {
-		g_object_remove_weak_pointer (G_OBJECT (self->pv->source), (gpointer*)&self->pv->source);
-		self->pv->source = NULL;
+	if (self->pv->place != NULL) {
+		g_object_remove_weak_pointer (G_OBJECT (self->pv->place),
+		                              (gpointer*)&self->pv->place);
+		self->pv->place = NULL;
 	}
 
 	G_OBJECT_CLASS (seahorse_object_parent_class)->dispose (obj);	
@@ -216,8 +208,9 @@ static void
 seahorse_object_finalize (GObject *obj)
 {
 	SeahorseObject *self = SEAHORSE_OBJECT (obj);
-	
-	g_assert (self->pv->source == NULL);
+
+	g_assert (self->pv->place == NULL);
+	g_clear_object (&self->pv->actions);
 
 	g_free (self->pv->label);
 	self->pv->label = NULL;
@@ -252,10 +245,13 @@ seahorse_object_get_property (GObject *obj, guint prop_id, GValue *value,
                            GParamSpec *pspec)
 {
 	SeahorseObject *self = SEAHORSE_OBJECT (obj);
-	
+
 	switch (prop_id) {
-	case PROP_SOURCE:
-		g_value_set_object (value, seahorse_object_get_source (self));
+	case PROP_PLACE:
+		g_value_set_object (value, seahorse_object_get_place (self));
+		break;
+	case PROP_ACTIONS:
+		g_value_set_object (value, self->pv->actions);
 		break;
 	case PROP_LABEL:
 		g_value_set_string (value, seahorse_object_get_label (self));
@@ -303,8 +299,12 @@ seahorse_object_set_property (GObject *obj, guint prop_id, const GValue *value,
 	guint flags;
 
 	switch (prop_id) {
-	case PROP_SOURCE:
-		seahorse_object_set_source (self, SEAHORSE_SOURCE (g_value_get_object (value)));
+	case PROP_PLACE:
+		seahorse_object_set_place (self, g_value_get_object (value));
+		break;
+	case PROP_ACTIONS:
+		g_clear_object (&self->pv->actions);
+		self->pv->actions = g_value_dup_object (value);
 		break;
 	case PROP_LABEL:
 		if (set_string_storage (g_value_get_string (value), &self->pv->label)) {
@@ -379,9 +379,13 @@ seahorse_object_class_init (SeahorseObjectClass *klass)
 	gobject_class->set_property = seahorse_object_set_property;
 	gobject_class->get_property = seahorse_object_get_property;
 
-	g_object_class_install_property (gobject_class, PROP_SOURCE,
-	           g_param_spec_object ("source", "Object Source", "Source the Object came from", 
-	                                SEAHORSE_TYPE_SOURCE, G_PARAM_READWRITE));
+	g_object_class_install_property (gobject_class, PROP_PLACE,
+	           g_param_spec_object ("place", "Object Place", "Place the Object came from",
+	                                SEAHORSE_TYPE_PLACE, G_PARAM_READWRITE));
+
+	g_object_class_install_property (gobject_class, PROP_ACTIONS,
+	           g_param_spec_object ("actions", "Actions", "Actions for the object",
+	                                GTK_TYPE_ACTION_GROUP, G_PARAM_READWRITE));
 
 	g_object_class_install_property (gobject_class, PROP_LABEL,
 	           g_param_spec_string ("label", "Object Display Label", "This object's displayable label.", 
@@ -422,11 +426,11 @@ seahorse_object_class_init (SeahorseObjectClass *klass)
  *
  * Returns: the source of the object @self
  */
-SeahorseSource*
-seahorse_object_get_source (SeahorseObject *self)
+SeahorsePlace *
+seahorse_object_get_place (SeahorseObject *self)
 {
 	g_return_val_if_fail (SEAHORSE_IS_OBJECT (self), NULL);
-	return self->pv->source;	
+	return self->pv->place;
 }
 
 
@@ -438,21 +442,24 @@ seahorse_object_get_source (SeahorseObject *self)
  * sets the source for the object
  */
 void
-seahorse_object_set_source (SeahorseObject *self, SeahorseSource *value)
+seahorse_object_set_place (SeahorseObject *self,
+                           SeahorsePlace *value)
 {
 	g_return_if_fail (SEAHORSE_IS_OBJECT (self));
-	
-	if (value == self->pv->source)
+
+	if (value == self->pv->place)
 		return;
 
-	if (self->pv->source) 
-		g_object_remove_weak_pointer (G_OBJECT (self->pv->source), (gpointer*)&self->pv->source);
+	if (self->pv->place)
+		g_object_remove_weak_pointer (G_OBJECT (self->pv->place),
+		                              (gpointer*)&self->pv->place);
 
-	self->pv->source = value;
-	if (self->pv->source != NULL)
-		g_object_add_weak_pointer (G_OBJECT (self->pv->source), (gpointer*)&self->pv->source);
+	self->pv->place = value;
+	if (self->pv->place != NULL)
+		g_object_add_weak_pointer (G_OBJECT (self->pv->place),
+		                           (gpointer*)&self->pv->place);
 
-	g_object_notify (G_OBJECT (self), "source");
+	g_object_notify (G_OBJECT (self), "place");
 }
 
 /**
diff --git a/libseahorse/seahorse-object.h b/libseahorse/seahorse-object.h
index 61ed495..4b255db 100644
--- a/libseahorse/seahorse-object.h
+++ b/libseahorse/seahorse-object.h
@@ -41,7 +41,6 @@
  * flags: guint: Flags from the SEAHORSE_FLAG_ set. 
  */
 
-#include "seahorse-source.h"
 #include "seahorse-types.h"
 
 #include <glib-object.h>
@@ -53,6 +52,7 @@
 #define SEAHORSE_IS_OBJECT_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_OBJECT))
 #define SEAHORSE_OBJECT_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_OBJECT, SeahorseObjectClass))
 
+typedef struct _SeahorsePlace SeahorsePlace;
 typedef struct _SeahorseObject SeahorseObject;
 typedef struct _SeahorseObjectClass SeahorseObjectClass;
 typedef struct _SeahorseObjectPrivate SeahorseObjectPrivate;
@@ -68,12 +68,10 @@ struct _SeahorseObjectClass {
 
 GType               seahorse_object_get_type               (void);
 
-SeahorseObject*     seahorse_object_new                    (void);
+SeahorsePlace *     seahorse_object_get_place              (SeahorseObject *self);
 
-SeahorseSource*     seahorse_object_get_source             (SeahorseObject *self);
-
-void                seahorse_object_set_source             (SeahorseObject *self, 
-                                                            SeahorseSource *value);
+void                seahorse_object_set_place              (SeahorseObject *self,
+                                                            SeahorsePlace *value);
 
 const gchar*        seahorse_object_get_label              (SeahorseObject *self);
 
diff --git a/libseahorse/seahorse-source.c b/libseahorse/seahorse-place.c
similarity index 59%
rename from libseahorse/seahorse-source.c
rename to libseahorse/seahorse-place.c
index dfd562e..aaec3aa 100644
--- a/libseahorse/seahorse-source.c
+++ b/libseahorse/seahorse-place.c
@@ -19,28 +19,28 @@
  * 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  */
- 
+
 #include "config.h"
 
 #include "seahorse-context.h"
 #include "seahorse-marshal.h"
 #include "seahorse-object.h"
 #include "seahorse-registry.h"
-#include "seahorse-source.h"
+#include "seahorse-place.h"
 #include "seahorse-util.h"
 
 #include <gcr/gcr.h>
 
 /**
- * SECTION:seahorse-source
- * @short_description: This class stores and handles key sources
- * @include:seahorse-source.h
+ * SECTION:seahorse-place
+ * @short_description: This class stores and handles key places
+ * @include:seahorse-place.h
  *
  **/
 
-typedef SeahorseSourceIface SeahorseSourceInterface;
+typedef SeahorsePlaceIface SeahorsePlaceInterface;
 
-G_DEFINE_INTERFACE (SeahorseSource, seahorse_source, GCR_TYPE_COLLECTION);
+G_DEFINE_INTERFACE (SeahorsePlace, seahorse_place, GCR_TYPE_COLLECTION);
 
 /* ---------------------------------------------------------------------------------
  * INTERFACE
@@ -51,26 +51,30 @@ G_DEFINE_INTERFACE (SeahorseSource, seahorse_source, GCR_TYPE_COLLECTION);
 *
 **/
 static void
-seahorse_source_default_init (SeahorseSourceIface *iface)
+seahorse_place_default_init (SeahorsePlaceIface *iface)
 {
 	static gboolean initialized = FALSE;
 	if (!initialized) {
 		g_object_interface_install_property (iface,
-		           g_param_spec_string ("label", "Label", "Label for the source",
+		           g_param_spec_string ("label", "Label", "Label for the place",
 		                                "", G_PARAM_READABLE));
 
 		g_object_interface_install_property (iface,
-		           g_param_spec_string ("description", "Description", "Description for the source",
+		           g_param_spec_string ("description", "Description", "Description for the place",
 		                                "", G_PARAM_READABLE));
 
 		g_object_interface_install_property (iface,
-		           g_param_spec_string ("uri", "URI", "URI for the source",
+		           g_param_spec_string ("uri", "URI", "URI for the place",
 		                                "", G_PARAM_READABLE));
 
 		g_object_interface_install_property (iface,
-		           g_param_spec_object ("icon", "Icon", "Icon for this source",
+		           g_param_spec_object ("icon", "Icon", "Icon for this place",
 		                                G_TYPE_ICON, G_PARAM_READABLE));
 
+		g_object_interface_install_property (iface,
+		           g_param_spec_object ("actions", "Actions", "Actions for place",
+		                                GTK_TYPE_ACTION_GROUP, G_PARAM_READABLE));
+
 		initialized = TRUE;
 	}
 }
@@ -80,68 +84,68 @@ seahorse_source_default_init (SeahorseSourceIface *iface)
  */
 
 void
-seahorse_source_import_async (SeahorseSource *source,
-                              GInputStream *input,
-                              GCancellable *cancellable,
-                              GAsyncReadyCallback callback,
-                              gpointer user_data)
+seahorse_place_import_async (SeahorsePlace *place,
+                             GInputStream *input,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
 {
-	g_return_if_fail (SEAHORSE_IS_SOURCE (source));
+	g_return_if_fail (SEAHORSE_IS_PLACE (place));
 	g_return_if_fail (G_IS_INPUT_STREAM (input));
 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-	g_return_if_fail (SEAHORSE_SOURCE_GET_INTERFACE (source)->import_async);
-	SEAHORSE_SOURCE_GET_INTERFACE (source)->import_async (source, input, cancellable,
+	g_return_if_fail (SEAHORSE_PLACE_GET_INTERFACE (place)->import_async);
+	SEAHORSE_PLACE_GET_INTERFACE (place)->import_async (place, input, cancellable,
 	                                                    callback, user_data);
 }
 
 GList *
-seahorse_source_import_finish (SeahorseSource *source,
-                               GAsyncResult *result,
-                               GError **error)
+seahorse_place_import_finish (SeahorsePlace *place,
+                              GAsyncResult *result,
+                              GError **error)
 {
-	g_return_val_if_fail (SEAHORSE_IS_SOURCE (source), NULL);
+	g_return_val_if_fail (SEAHORSE_IS_PLACE (place), NULL);
 	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-	g_return_val_if_fail (SEAHORSE_SOURCE_GET_INTERFACE (source)->import_finish, NULL);
-	return SEAHORSE_SOURCE_GET_INTERFACE (source)->import_finish (source, result, error);
+	g_return_val_if_fail (SEAHORSE_PLACE_GET_INTERFACE (place)->import_finish, NULL);
+	return SEAHORSE_PLACE_GET_INTERFACE (place)->import_finish (place, result, error);
 }
 
 void
-seahorse_source_export_async (SeahorseSource *source,
-                              GList *objects,
-                              GOutputStream *output,
-                              GCancellable *cancellable,
-                              GAsyncReadyCallback callback,
-                              gpointer user_data)
+seahorse_place_export_async (SeahorsePlace *place,
+                             GList *objects,
+                             GOutputStream *output,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
 {
-	SeahorseSourceIface *iface;
+	SeahorsePlaceIface *iface;
 
-	g_return_if_fail (SEAHORSE_IS_SOURCE (source));
+	g_return_if_fail (SEAHORSE_IS_PLACE (place));
 	g_return_if_fail (G_IS_OUTPUT_STREAM (output));
 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 
-	iface = SEAHORSE_SOURCE_GET_INTERFACE (source);
+	iface = SEAHORSE_PLACE_GET_INTERFACE (place);
 	g_return_if_fail (iface->export_async != NULL);
 
-	iface->export_async (source, objects, output,
+	iface->export_async (place, objects, output,
 	                     cancellable, callback, user_data);
 }
 
 GOutputStream *
-seahorse_source_export_finish (SeahorseSource *source,
+seahorse_place_export_finish (SeahorsePlace *place,
                                GAsyncResult *result,
                                GError **error)
 {
-	SeahorseSourceIface *iface;
+	SeahorsePlaceIface *iface;
 
-	g_return_val_if_fail (SEAHORSE_IS_SOURCE (source), NULL);
+	g_return_val_if_fail (SEAHORSE_IS_PLACE (place), NULL);
 	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-	iface = SEAHORSE_SOURCE_GET_INTERFACE (source);
+	iface = SEAHORSE_PLACE_GET_INTERFACE (place);
 	g_return_val_if_fail (iface->export_async != NULL, NULL);
 	g_return_val_if_fail (iface->export_finish, NULL);
-	return (iface->export_finish) (source, result, error);
+	return (iface->export_finish) (place, result, error);
 }
 
 typedef struct {
@@ -158,7 +162,7 @@ export_auto_free (gpointer data)
 }
 
 static void
-on_export_auto_complete (GObject *source,
+on_export_auto_complete (GObject *place,
                          GAsyncResult *result,
                          gpointer user_data)
 {
@@ -166,7 +170,7 @@ on_export_auto_complete (GObject *source,
 	export_auto_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GError *error = NULL;
 
-	if (!seahorse_source_export_finish (SEAHORSE_SOURCE (source), result, &error))
+	if (!seahorse_place_export_finish (SEAHORSE_PLACE (place), result, &error))
 		g_simple_async_result_take_error (res, error);
 
 	g_assert (closure->exports > 0);
@@ -179,43 +183,43 @@ on_export_auto_complete (GObject *source,
 }
 
 void
-seahorse_source_export_auto_async (GList *objects,
-                                   GOutputStream *output,
-                                   GCancellable *cancellable,
-                                   GAsyncReadyCallback callback,
-                                   gpointer user_data)
+seahorse_place_export_auto_async (GList *objects,
+                                  GOutputStream *output,
+                                  GCancellable *cancellable,
+                                  GAsyncReadyCallback callback,
+                                  gpointer user_data)
 {
 	GSimpleAsyncResult *res;
 	export_auto_closure *closure;
-	SeahorseSource *source;
+	SeahorsePlace *place;
 	GObject *object;
 	GList *next;
 
 	res = g_simple_async_result_new (NULL, callback, user_data,
-	                                 seahorse_source_export_auto_async);
+	                                 seahorse_place_export_auto_async);
 	closure = g_new0 (export_auto_closure, 1);
 	closure->output = g_object_ref (output);
 	g_simple_async_result_set_op_res_gpointer (res, closure, export_auto_free);
 
-	/* Sort by object source */
+	/* Sort by object place */
 	objects = g_list_copy (objects);
-	objects = seahorse_util_objects_sort (objects);
+	objects = seahorse_util_objects_sort_by_place (objects);
 
 	while (objects) {
 
-		/* Break off one set (same source) */
-		next = seahorse_util_objects_splice (objects);
+		/* Break off one set (same place) */
+		next = seahorse_util_objects_splice_by_place (objects);
 
 		g_assert (G_IS_OBJECT (objects->data));
 		object = G_OBJECT (objects->data);
 
-		/* Export from this object source */
-		source = NULL;
-		g_object_get (object, "source", &source, NULL);
-		g_return_if_fail (source != NULL);
+		/* Export from this object place */
+		place = NULL;
+		g_object_get (object, "place", &place, NULL);
+		g_return_if_fail (place != NULL);
 
 		/* We pass our own data object, to which data is appended */
-		seahorse_source_export_async (source, objects, output, cancellable,
+		seahorse_place_export_async (place, objects, output, cancellable,
 		                              on_export_auto_complete, g_object_ref (res));
 		closure->exports++;
 
@@ -230,13 +234,13 @@ seahorse_source_export_auto_async (GList *objects,
 }
 
 GOutputStream *
-seahorse_source_export_auto_finish (GAsyncResult *result,
-                                    GError **error)
+seahorse_place_export_auto_finish (GAsyncResult *result,
+                                   GError **error)
 {
 	export_auto_closure *closure;
 
 	g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
-	                      seahorse_source_export_auto_async), NULL);
+	                      seahorse_place_export_auto_async), NULL);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return NULL;
@@ -247,7 +251,7 @@ seahorse_source_export_auto_finish (GAsyncResult *result,
 }
 
 static void
-on_export_auto_wait_complete (GObject *source,
+on_export_auto_wait_complete (GObject *place,
                               GAsyncResult *result,
                               gpointer user_data)
 {
@@ -256,20 +260,20 @@ on_export_auto_wait_complete (GObject *source,
 }
 
 gboolean
-seahorse_source_export_auto_wait (GList *objects,
-                                  GOutputStream *output,
-                                  GError **error)
+seahorse_place_export_auto_wait (GList *objects,
+                                 GOutputStream *output,
+                                 GError **error)
 {
 	GAsyncResult *result = NULL;
 	gboolean ret;
 
-	seahorse_source_export_auto_async (objects, output, NULL,
+	seahorse_place_export_auto_async (objects, output, NULL,
 	                                   on_export_auto_wait_complete,
 	                                   &result);
 
 	seahorse_util_wait_until (result != NULL);
 
-	ret = seahorse_source_export_auto_finish (result, error) != NULL;
+	ret = seahorse_place_export_auto_finish (result, error) != NULL;
 	g_object_unref (result);
 	return ret;
 }
diff --git a/libseahorse/seahorse-source.h b/libseahorse/seahorse-place.h
similarity index 56%
rename from libseahorse/seahorse-source.h
rename to libseahorse/seahorse-place.h
index 2f717c6..5b05d3e 100644
--- a/libseahorse/seahorse-source.h
+++ b/libseahorse/seahorse-place.h
@@ -19,93 +19,96 @@
  * 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  */
- 
+
 /**
- * - A generic interface for accessing sources.
- * - Eventually more functionality will be merged from seahorse-op.* into 
- *   this class and derived classes. 
+ * - A generic interface for accessing places.
+ * - Eventually more functionality will be merged from seahorse-op.* into
+ *   this class and derived classes.
  */
 
 
-#ifndef __SEAHORSE_SOURCE_H__
-#define __SEAHORSE_SOURCE_H__
+#ifndef __SEAHORSE_PLACE_H__
+#define __SEAHORSE_PLACE_H__
 
 #include "seahorse-types.h"
 
 #include <gio/gio.h>
-#include <glib-object.h>
 
-#define SEAHORSE_TYPE_SOURCE                (seahorse_source_get_type ())
-#define SEAHORSE_SOURCE(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_SOURCE, SeahorseSource))
-#define SEAHORSE_IS_SOURCE(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_SOURCE))
-#define SEAHORSE_SOURCE_GET_INTERFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SEAHORSE_TYPE_SOURCE, SeahorseSourceIface))
+#include <gtk/gtk.h>
+
+#define SEAHORSE_TYPE_PLACE                (seahorse_place_get_type ())
+#define SEAHORSE_PLACE(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PLACE, SeahorsePlace))
+#define SEAHORSE_IS_PLACE(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_PLACE))
+#define SEAHORSE_PLACE_GET_INTERFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SEAHORSE_TYPE_PLACE, SeahorsePlaceIface))
 
-typedef struct _SeahorseSource SeahorseSource;
-typedef struct _SeahorseSourceIface SeahorseSourceIface;
+typedef struct _SeahorsePlace SeahorsePlace;
+typedef struct _SeahorsePlaceIface SeahorsePlaceIface;
 
-struct _SeahorseSourceIface {
+struct _SeahorsePlaceIface {
 	GTypeInterface parent;
 
 	/* virtual methods ------------------------------------------------- */
 
-	void            (*import_async)              (SeahorseSource *source,
+	void            (*import_async)              (SeahorsePlace *place,
 	                                              GInputStream *input,
 	                                              GCancellable *cancellable,
 	                                              GAsyncReadyCallback callback,
 	                                              gpointer user_data);
 
-	GList *         (*import_finish)             (SeahorseSource *source,
+	GList *         (*import_finish)             (SeahorsePlace *place,
 	                                              GAsyncResult *result,
 	                                              GError **error);
 
-	void            (*export_async)              (SeahorseSource *source,
+	void            (*export_async)              (SeahorsePlace *place,
 	                                              GList *objects,
 	                                              GOutputStream *output,
 	                                              GCancellable *cancellable,
 	                                              GAsyncReadyCallback callback,
 	                                              gpointer user_data);
 
-	GOutputStream * (*export_finish)             (SeahorseSource *source,
+	GOutputStream * (*export_finish)             (SeahorsePlace *place,
 	                                              GAsyncResult *result,
 	                                              GError **error);
 };
 
-GType            seahorse_source_get_type             (void) G_GNUC_CONST;
+GType            seahorse_place_get_type             (void) G_GNUC_CONST;
+
+GtkActionGroup * seahorse_place_get_actions          (SeahorsePlace *self);
 
 /* Method helper functions ------------------------------------------- */
 
-void             seahorse_source_import_async         (SeahorseSource *source,
-                                                       GInputStream *input,
-                                                       GCancellable *cancellable,
-                                                       GAsyncReadyCallback callback,
-                                                       gpointer user_data);
+void             seahorse_place_import_async         (SeahorsePlace *place,
+                                                      GInputStream *input,
+                                                      GCancellable *cancellable,
+                                                      GAsyncReadyCallback callback,
+                                                      gpointer user_data);
 
-GList *          seahorse_source_import_finish        (SeahorseSource *source,
-                                                       GAsyncResult *result,
-                                                       GError **error);
+GList *          seahorse_place_import_finish        (SeahorsePlace *place,
+                                                      GAsyncResult *result,
+                                                      GError **error);
 
-void             seahorse_source_export_async         (SeahorseSource *source,
-                                                       GList *objects,
-                                                       GOutputStream *output,
+void             seahorse_place_export_async         (SeahorsePlace *place,
+                                                      GList *objects,
+                                                      GOutputStream *output,
                                                        GCancellable *cancellable,
                                                        GAsyncReadyCallback callback,
                                                        gpointer user_data);
 
-GOutputStream *  seahorse_source_export_finish        (SeahorseSource *source,
+GOutputStream *  seahorse_place_export_finish        (SeahorsePlace *place,
                                                        GAsyncResult *result,
                                                        GError **error);
 
-void             seahorse_source_export_auto_async    (GList *objects,
+void             seahorse_place_export_auto_async    (GList *objects,
                                                        GOutputStream *output,
                                                        GCancellable *cancellable,
                                                        GAsyncReadyCallback callback,
                                                        gpointer user_data);
 
-GOutputStream *  seahorse_source_export_auto_finish   (GAsyncResult *result,
+GOutputStream *  seahorse_place_export_auto_finish   (GAsyncResult *result,
                                                        GError **error);
 
-gboolean         seahorse_source_export_auto_wait     (GList *objects,
+gboolean         seahorse_place_export_auto_wait     (GList *objects,
                                                        GOutputStream *output,
                                                        GError **error);
 
-#endif /* __SEAHORSE_SOURCE_H__ */
+#endif /* __SEAHORSE_PLACE_H__ */
diff --git a/libseahorse/seahorse-predicate.c b/libseahorse/seahorse-predicate.c
index ad102fd..c9568d4 100644
--- a/libseahorse/seahorse-predicate.c
+++ b/libseahorse/seahorse-predicate.c
@@ -23,8 +23,8 @@
 #include "config.h"
 
 #include "seahorse-object.h"
+#include "seahorse-place.h"
 #include "seahorse-predicate.h"
-#include "seahorse-source.h"
 
 #include "string.h"
 
diff --git a/libseahorse/seahorse-predicate.h b/libseahorse/seahorse-predicate.h
index 1c8be77..4d29be8 100644
--- a/libseahorse/seahorse-predicate.h
+++ b/libseahorse/seahorse-predicate.h
@@ -24,7 +24,6 @@
 #define __SEAHORSE_PREDICATE_H__
 
 #include "seahorse-object.h"
-#include "seahorse-source.h"
 #include "seahorse-types.h"
 
 #include <glib-object.h>
diff --git a/libseahorse/seahorse-util.c b/libseahorse/seahorse-util.c
index 3d4d14c..86db6fa 100644
--- a/libseahorse/seahorse-util.c
+++ b/libseahorse/seahorse-util.c
@@ -66,7 +66,9 @@ static const gchar *bad_filename_chars = "/\\<>|";
  *
  */
 void
-seahorse_util_show_error (GtkWidget *parent, const gchar *heading, const gchar *message)
+seahorse_util_show_error (gpointer parent,
+                          const gchar *heading,
+                          const gchar *message)
 {
 	GtkWidget *dialog;
 
@@ -906,17 +908,17 @@ seahorse_util_chooser_open_prompt (GtkDialog *dialog)
  *          1 will be returned  if k1>k2. If the sources are equal it returns 0
  */
 static gint
-sort_objects_by_source (GObject *k1,
-                        GObject *k2)
+sort_objects_by_place (GObject *k1,
+                       GObject *k2)
 {
-	SeahorseSource *sk1 = NULL;
-	SeahorseSource *sk2 = NULL;
+	SeahorsePlace *sk1 = NULL;
+	SeahorsePlace *sk2 = NULL;
 
 	g_assert (G_IS_OBJECT (k1));
 	g_assert (G_IS_OBJECT (k2));
 
-	g_object_get (k1, "source", &sk1, NULL);
-	g_object_get (k2, "source", &sk2, NULL);
+	g_object_get (k1, "place", &sk1, NULL);
+	g_object_get (k2, "place", &sk2, NULL);
 
 	if (sk1 == sk2)
 		return 0;
@@ -931,10 +933,10 @@ sort_objects_by_source (GObject *k1,
  *
  * Returns: The sorted list
  */
-GList*        
-seahorse_util_objects_sort (GList *objects)
+GList *
+seahorse_util_objects_sort_by_place (GList *objects)
 {
-    return g_list_sort (objects, (GCompareFunc)sort_objects_by_source);
+	return g_list_sort (objects, (GCompareFunc)sort_objects_by_place);
 }
 
 
@@ -946,39 +948,36 @@ seahorse_util_objects_sort (GList *objects)
  *
  * Returns: The second part of the list.
  */
-GList*       
-seahorse_util_objects_splice (GList *objects)
+GList *
+seahorse_util_objects_splice_by_place (GList *objects)
 {
-    SeahorseSource *psk = NULL;
-    SeahorseSource *sk;
-    GList *prev = NULL;
-    
-    /* Note that the objects must be sorted */
-    
-    for ( ; objects; objects = g_list_next (objects)) {
-     
-        g_return_val_if_fail (G_IS_OBJECT (objects->data), NULL);
+	SeahorsePlace *psk = NULL;
+	SeahorsePlace *sk;
+	GList *prev = NULL;
+
+	/* Note that the objects must be sorted */
+	for ( ; objects; objects = g_list_next (objects)) {
+		g_return_val_if_fail (G_IS_OBJECT (objects->data), NULL);
+		sk = NULL;
+		g_object_get (objects->data, "place", &sk, NULL);
+		g_return_val_if_fail (sk != NULL, NULL);
+
+		/* Found a disconuity */
+		if (psk && sk != psk) {
+			g_assert (prev != NULL);
+
+			/* Break the list */
+			prev->next = NULL;
+
+			/* And return the new list */
+			return objects;
+		}
 
-        sk = NULL;
-        g_object_get (objects->data, "source", &sk, NULL);
-        g_return_val_if_fail (sk != NULL, NULL);
+		psk = sk;
+		prev = objects;
+	}
 
-        /* Found a disconuity */
-        if (psk && sk != psk) {
-            g_assert (prev != NULL);
-            
-            /* Break the list */
-            prev->next = NULL;
-            
-            /* And return the new list */
-            return objects;
-        }
-        
-        psk = sk;
-        prev = objects;
-    }
-    
-    return NULL;
+	return NULL;
 }
 
 /**
diff --git a/libseahorse/seahorse-util.h b/libseahorse/seahorse-util.h
index bd0f45e..1a9b290 100644
--- a/libseahorse/seahorse-util.h
+++ b/libseahorse/seahorse-util.h
@@ -49,9 +49,9 @@ gchar*      seahorse_util_get_display_date_string   (const time_t time);
 
 GQuark      seahorse_util_error_domain          (void);
 
-void        seahorse_util_show_error            (GtkWidget          *parent,
-                                                 const gchar        *heading,
-                                                 const gchar        *message);
+void        seahorse_util_show_error            (gpointer parent,
+                                                 const gchar *heading,
+                                                 const gchar *message);
 
 void        seahorse_util_handle_error          (GError **error,
                                                  gpointer parent,
@@ -114,9 +114,9 @@ gchar*      seahorse_util_chooser_open_prompt           (GtkDialog *dialog);
 
 gchar*      seahorse_util_chooser_save_prompt           (GtkDialog *dialog);
 
-GList*      seahorse_util_objects_sort       (GList *objects);
+GList *     seahorse_util_objects_sort_by_place         (GList *objects);
 
-GList*      seahorse_util_objects_splice     (GList *objects);
+GList *     seahorse_util_objects_splice_by_place       (GList *objects);
 
 gboolean    seahorse_util_string_equals       (const gchar *s1, const gchar *s2);
 
diff --git a/libseahorse/seahorse-viewer.c b/libseahorse/seahorse-viewer.c
index c0deada..c951bc2 100644
--- a/libseahorse/seahorse-viewer.c
+++ b/libseahorse/seahorse-viewer.c
@@ -22,84 +22,50 @@
 
 #include "config.h"
 
-#include "seahorse-commands.h"
+#include "seahorse-action.h"
+#include "seahorse-actions.h"
+#include "seahorse-backend.h"
 #include "seahorse-object.h"
-#include "seahorse-object-list.h"
 #include "seahorse-preferences.h"
 #include "seahorse-progress.h"
 #include "seahorse-registry.h"
 #include "seahorse-util.h"
 #include "seahorse-viewer.h"
 
+#include <gcr/gcr.h>
+
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
 
 void                on_app_preferences                (GtkAction* action,
-                                                       SeahorseViewer* self);
+                                                       gpointer user_data);
 
 enum {
 	PROP_0,
-	PROP_SELECTED,
 	PROP_WINDOW
 };
 
-typedef struct _ViewerPredicate {
-	SeahorsePredicate pred;
-	gboolean is_commands;
-	GObject *commands_or_actions;
-} ViewerPredicate;
-
 struct _SeahorseViewerPrivate {
 	GtkUIManager *ui_manager;
-	GtkActionGroup *object_actions;
-	GtkActionGroup *export_actions;
-	GtkAction *delete_action;
-	GArray *predicates;
-	GList *all_commands;
+	GHashTable *actions;
+	GtkAction *edit_delete;
+	GtkAction *properties_object;
+	GtkAction *properties_place;
+	GtkAction *properties_backend;
 };
 
 G_DEFINE_TYPE (SeahorseViewer, seahorse_viewer, SEAHORSE_TYPE_WIDGET);
 
-#define SEAHORSE_VIEWER_GET_PRIVATE(o) \
-	(G_TYPE_INSTANCE_GET_PRIVATE ((o), SEAHORSE_TYPE_VIEWER, SeahorseViewerPrivate))
-
-/* Predicates which control export and delete commands, inited in class_init */
-static SeahorsePredicate exportable_predicate = { 0, };
-static SeahorsePredicate deletable_predicate = { 0, };
-
 /* -----------------------------------------------------------------------------
  * INTERNAL
  */
 
-typedef gboolean     (*ForEachCommandsFunc)     (SeahorseViewer *self,
-                                                 SeahorseCommands *commands,
-                                                 SeahorsePredicate *predicate,
-                                                 gpointer user_data);
-
-static void
-for_each_commands (SeahorseViewer *self, ForEachCommandsFunc func, gpointer user_data)
-{
-	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE (self);
-	ViewerPredicate *predicate;
-	guint i;
-
-	for (i = 0; i < pv->predicates->len; ++i)
-	{
-		predicate = &g_array_index (pv->predicates, ViewerPredicate, i);
-		if (predicate->is_commands) {
-			if (!(func) (self, SEAHORSE_COMMANDS (predicate->commands_or_actions),
-			            &predicate->pred, user_data))
-				return;
-		}
-	}
-}
 
 G_MODULE_EXPORT void
-on_app_preferences (GtkAction* action, SeahorseViewer* self)
+on_app_preferences (GtkAction* action,
+                    gpointer user_data)
 {
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-	g_return_if_fail (GTK_IS_ACTION (action));
-
+	SeahorseViewer* self = SEAHORSE_VIEWER (user_data);
 	seahorse_preferences_show (seahorse_viewer_get_window (self), NULL);
 }
 
@@ -154,91 +120,128 @@ on_app_about (GtkAction* action, SeahorseViewer* self)
 }
 
 static void
-on_help_show (GtkAction* action, SeahorseViewer* self)
+on_help_show (GtkAction *action,
+              SeahorseViewer* self)
 {
 	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
 	g_return_if_fail (GTK_IS_ACTION (action));
 	seahorse_widget_show_help (SEAHORSE_WIDGET (self));
 }
 
-static const GtkActionEntry UI_ENTRIES[] = {
-
-	/* Top menu items */
-	{ "file-menu", NULL, N_("_File") },
-	{ "edit-menu", NULL, N_("_Edit") },
-	{ "view-menu", NULL, N_("_View") },
-	{ "help-menu", NULL, N_("_Help") },
-	{ "app-preferences", GTK_STOCK_PREFERENCES, N_("Prefere_nces"), NULL,
-	  N_("Change preferences for this program"), G_CALLBACK (on_app_preferences) },
-	{ "app-about", GTK_STOCK_ABOUT, NULL, NULL,
-	  N_("About this program"), G_CALLBACK (on_app_about) },
-	{ "help-show", GTK_STOCK_HELP, N_("_Contents"), "F1",
-	  N_("Show Seahorse help"), G_CALLBACK (on_help_show) }
-};
-
 static void
-on_key_properties (GtkAction* action, SeahorseViewer* self)
-{
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-	g_return_if_fail (GTK_IS_ACTION (action));
-
-	if (seahorse_viewer_get_selected (self) != NULL)
-		seahorse_viewer_show_properties (self, seahorse_viewer_get_selected (self));
-}
-
-static GList*
-objects_prune_non_exportable (GList *objects)
+on_object_delete (GtkAction *action,
+                  gpointer user_data)
 {
-	GList *exportable = NULL;
+	SeahorseViewer *self = SEAHORSE_VIEWER (user_data);
+	GtkActionGroup *actions;
+	GList *objects;
+	GList *selected;
+	const gchar *name;
 	GList *l;
 
-	for (l = objects; l; l = g_list_next (l)) {
-		if (seahorse_object_get_flags (l->data) & SEAHORSE_FLAG_EXPORTABLE)
-			exportable = g_list_append (exportable, l->data);
+	if (seahorse_action_have_objects (action))
+		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));
+	name = gtk_action_get_name (action);
+
+	for (l = objects; l != NULL; l = g_list_next (l)) {
+		actions = NULL;
+		g_object_get (l->data, "actions", &actions, NULL);
+		if (actions && gtk_action_group_get_action (actions, name) == action)
+			selected = g_list_prepend (selected, l->data);
+		g_object_ref (actions);
 	}
 
+	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);
-	return exportable;
 }
 
-static GList*
-filter_matching_objects (SeahorsePredicate *pred,
-                         GList** all_objects)
+static GtkAction *
+properties_action_for_object (GObject *object)
 {
-	GList *results, *next, *here;
-	GObject *obj;
+	GtkActionGroup *actions = NULL;
+	GtkAction *action;
 
-	results = NULL;
+	g_object_get (object, "actions", &actions, NULL);
+	if (actions == NULL)
+		return NULL;
 
-	next = *all_objects;
-	while ((here = next) != NULL) {
-		obj = G_OBJECT (here->data);
-		next = g_list_next (here);
+	action = gtk_action_group_get_action (actions, "properties");
+	g_object_unref (actions);
 
-		/* If it matches then separate it */
-		if (seahorse_predicate_match (pred, obj)) {
-			results = g_list_append (results, obj);
-			*all_objects = g_list_delete_link (*all_objects, here);
-		}
-	}
+	return action;
+}
 
-	return results;
+static void
+on_properties_object (GtkAction *action,
+                      gpointer user_data)
+{
+	SeahorseViewer *self = SEAHORSE_VIEWER (user_data);
+	GList *objects;
+
+	objects = seahorse_viewer_get_selected_objects (self);
+	if (objects != NULL)
+		seahorse_viewer_show_properties (self, objects->data);
+	g_list_free (objects);
 }
 
-static gboolean
-has_matching_objects (SeahorsePredicate *pred,
-                      GList *objects)
+static void
+on_properties_place (GtkAction *action,
+                     gpointer user_data)
 {
-	GList *l;
+	SeahorseViewer *self = SEAHORSE_VIEWER (user_data);
+	GList *objects;
 
-	for (l = objects; l; l = g_list_next (l)) {
-		if (seahorse_predicate_match (pred, l->data))
-			return TRUE;
-	}
+	objects = seahorse_viewer_get_selected_places (self);
+	if (objects != NULL)
+		seahorse_viewer_show_properties (self, objects->data);
+	g_list_free (objects);
+}
+
+static void
+on_properties_backend (GtkAction *action,
+                       gpointer user_data)
+{
+	SeahorseViewer *self = SEAHORSE_VIEWER (user_data);
+	GList *objects;
 
-	return FALSE;
+	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 */
+	{ "file-menu", NULL, N_("_File") },
+	{ "edit-menu", NULL, N_("_Edit") },
+	{ "edit-delete", GTK_STOCK_DELETE, NC_("This text refers to deleting an item from its type's backing store.", "_Delete"), NULL,
+	  N_("Delete selected items"), G_CALLBACK (on_object_delete) },
+	{ "properties-object", GTK_STOCK_PROPERTIES, NULL, NULL,
+	  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") },
+	{ "help-menu", NULL, N_("_Help") },
+	{ "app-about", GTK_STOCK_ABOUT, NULL, NULL,
+	  N_("About this program"), G_CALLBACK (on_app_about) },
+	{ "help-show", GTK_STOCK_HELP, N_("_Contents"), "F1",
+	  N_("Show Seahorse help"), G_CALLBACK (on_help_show) }
+};
+
+#if 0
 static void
 on_file_export_completed (GObject *source,
                           GAsyncResult *result,
@@ -247,7 +250,7 @@ on_file_export_completed (GObject *source,
 	SeahorseViewer* self = SEAHORSE_VIEWER (user_data);
 	GError *error = NULL;
 
-	if (!seahorse_source_export_auto_finish (result, &error))
+	if (!seahorse_place_export_auto_finish (result, &error))
 		seahorse_util_handle_error (&error, seahorse_viewer_get_window (self),
 		                            _("Couldn't export keys"));
 
@@ -289,8 +292,8 @@ on_key_export_file (GtkAction* action, SeahorseViewer* self)
 			g_free (unesc_uri);
 		} else {
 			cancellable = g_cancellable_new ();
-			seahorse_source_export_auto_async (objects, output, cancellable,
-			                                   on_file_export_completed, g_object_ref (self));
+			seahorse_place_export_auto_async (objects, output, cancellable,
+			                                  on_file_export_completed, g_object_ref (self));
 			seahorse_progress_show (cancellable, _("Exporting keys"), TRUE);
 			g_object_unref (cancellable);
 		}
@@ -317,7 +320,7 @@ on_copy_export_complete (GObject *source,
 	GdkAtom atom;
 	GtkClipboard* board;
 
-	output = seahorse_source_export_auto_finish (result, &error);
+	output = seahorse_place_export_auto_finish (result, &error);
 	if (error != NULL) {
 		seahorse_util_handle_error (&error, seahorse_viewer_get_window (self),
 		                            _("Couldn't retrieve data from key server"));
@@ -331,9 +334,6 @@ on_copy_export_complete (GObject *source,
 	board = gtk_clipboard_get (atom);
 	gtk_clipboard_set_text (board, text, (gint)size);
 
-	/* Translators: "Copied" is a verb (used as a status indicator), not an adjective for the word "keys" */
-	seahorse_viewer_set_status (self, _ ("Copied keys"));
-
 	g_object_unref (self);
 }
 
@@ -355,8 +355,8 @@ on_key_export_clipboard (GtkAction* action, SeahorseViewer* self)
 	output = G_OUTPUT_STREAM (g_memory_output_stream_new (NULL, 0, g_realloc, g_free));
 
 	cancellable = g_cancellable_new ();
-	seahorse_source_export_auto_async (objects, output, cancellable,
-	                                   on_copy_export_complete, g_object_ref (self));
+	seahorse_place_export_auto_async (objects, output, cancellable,
+	                                  on_copy_export_complete, g_object_ref (self));
 	seahorse_progress_show (cancellable, _ ("Retrieving keys"), TRUE);
 	g_object_unref (cancellable);
 
@@ -364,179 +364,195 @@ on_key_export_clipboard (GtkAction* action, SeahorseViewer* self)
 	g_object_unref (output);
 }
 
-static gboolean
-delete_objects_for_selected (SeahorseViewer *self,
-                             SeahorseCommands *commands,
-                             SeahorsePredicate *pred,
-                             gpointer user_data)
-{
-	GList **all_objects;
-	GList *objects;
-	gboolean ret;
-
-	all_objects = (GList**)user_data;
-
-	/* Stop the enumeration if nothing still selected */
-	if (!*all_objects)
-		return FALSE;
-
-	objects = filter_matching_objects (pred, all_objects);
-
-	/* No objects matched this predicate? */
-	if (!objects)
-		return TRUE;
-
-	/* Indicate to our users what is being operated on */
-	seahorse_viewer_set_selected_objects (self, objects);
-
-	ret = seahorse_commands_delete_objects (commands, objects);
-	g_list_free (objects);
-
-	return ret;
-}
+static const GtkActionEntry EXPORT_ENTRIES[] = {
+	{ "file-export", GTK_STOCK_SAVE_AS, N_("E_xport..."), NULL,
+	  N_("Export to a file"), G_CALLBACK (on_key_export_file) },
+	{ "edit-export-clipboard", GTK_STOCK_COPY, NULL, "<control>C",
+	  N_("Copy to the clipboard"), G_CALLBACK (on_key_export_clipboard) }
+};
+#endif
 
 static void
-on_key_delete (GtkAction* action, SeahorseViewer* self)
+on_ui_manager_pre_activate (GtkUIManager *ui_manager,
+                            GtkAction *action,
+                            gpointer user_data)
 {
-	GList *objects = NULL;
-	GList *all_objects = NULL;
+	SeahorseViewer *self = SEAHORSE_VIEWER (user_data);
+	GtkActionGroup *actions;
+	GList *selected = NULL;
+	GList *objects;
+	const gchar *name;
 	GList *l;
 
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-	g_return_if_fail (GTK_IS_ACTION (action));
+	name = gtk_action_get_name (action);
+	g_return_if_fail (name != NULL);
 
-	all_objects = seahorse_viewer_get_selected_objects (self);
-	objects = filter_matching_objects (&deletable_predicate, &all_objects);
-	g_list_free (all_objects);
-
-	/* Check for private objects */
-	for (l = objects; l; l = g_list_next (l)) {
-		GObject* object = l->data;
-
-		if (SEAHORSE_IS_OBJECT (object) &&
-		    seahorse_object_get_usage (SEAHORSE_OBJECT (object)) == SEAHORSE_USAGE_PRIVATE_KEY) {
-			gchar* prompt = g_strdup_printf (_("%s is a private key. Are you sure you want to proceed?"),
-			                                 seahorse_object_get_label (SEAHORSE_OBJECT (object)));
-			if (!seahorse_util_prompt_delete (prompt, GTK_WIDGET (seahorse_viewer_get_window (self)))) {
-				g_free (prompt);
-				g_list_free (objects);
-				return;
-			}
+	/* These guys do their own object selection */
+	if (seahorse_action_have_objects (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);
 		}
 	}
 
-	/* Go through the list of predicates, and call each one */
-	for_each_commands (self, delete_objects_for_selected, &objects);
+	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);
 }
 
-static gboolean
-show_properties_for_selected (SeahorseViewer *self,
-                              SeahorseCommands *commands,
-                              SeahorsePredicate *pred,
-                              gpointer user_data)
+static void
+on_ui_manager_post_activate (GtkUIManager *ui_manager,
+                             GtkAction *action,
+                             gpointer user_data)
 {
-	/* If not mactched, then continue enumeration */
-	if (!seahorse_predicate_match (pred, user_data))
-		return TRUE;
-
-	seahorse_commands_show_properties (commands, user_data);
-
-	/* Stop enumeration */
-	return FALSE;
+	seahorse_action_set_objects (action, NULL);
+	seahorse_action_set_window (action, NULL);
 }
 
-static const GtkActionEntry KEY_ENTRIES[] = {
-	{ "show-properties", GTK_STOCK_PROPERTIES, NULL, NULL,
-	  N_("Show properties"), G_CALLBACK (on_key_properties) },
-	{ "edit-delete", GTK_STOCK_DELETE, NC_("This text refers to deleting an item from its type's backing store.", "_Delete"), NULL,
-	  N_("Delete selected items"), G_CALLBACK (on_key_delete) }
-};
-
-static const GtkActionEntry EXPORT_ENTRIES[] = {
-	{ "file-export", GTK_STOCK_SAVE_AS, N_("E_xport..."), NULL,
-	  N_("Export to a file"), G_CALLBACK (on_key_export_file) },
-	{ "edit-export-clipboard", GTK_STOCK_COPY, NULL, "<control>C",
-	  N_("Copy to the clipboard"), G_CALLBACK (on_key_export_clipboard) }
-};
-
 static void
-include_basic_actions (SeahorseViewer* self)
+viewer_find_actions_for_selection (SeahorseViewer *self,
+                                   GHashTable *found,
+                                   GList *objects)
 {
-	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE (self);
-	GtkActionGroup* actions;
-
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-
-	actions = gtk_action_group_new ("main");
-	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
-	gtk_action_group_add_actions (actions, UI_ENTRIES, G_N_ELEMENTS (UI_ENTRIES), self);
-	seahorse_viewer_include_actions (self, actions);
-	g_object_unref (actions);
+	GtkActionGroup *actions;
+	GPtrArray *selected;
+	GList *l;
 
-	pv->object_actions = gtk_action_group_new ("key");
-	gtk_action_group_set_translation_domain (pv->object_actions, GETTEXT_PACKAGE);
-	gtk_action_group_add_actions (pv->object_actions, KEY_ENTRIES, G_N_ELEMENTS (KEY_ENTRIES), self);
-	/* Mark the properties toolbar button as important */
-	g_object_set (gtk_action_group_get_action (pv->object_actions, "show-properties"), "is-important", TRUE, NULL);
-	seahorse_viewer_include_actions (self, pv->object_actions);
-	pv->delete_action = gtk_action_group_get_action (pv->object_actions, "edit-delete");
-	g_return_if_fail (pv->delete_action);
-	g_object_ref (pv->delete_action);
-
-	pv->export_actions = gtk_action_group_new ("export");
-	gtk_action_group_set_translation_domain (pv->export_actions, GETTEXT_PACKAGE);
-	gtk_action_group_add_actions (pv->export_actions, EXPORT_ENTRIES, G_N_ELEMENTS (EXPORT_ENTRIES), self);
-	seahorse_viewer_include_actions (self, pv->export_actions);
+	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);
+		}
+	}
 }
 
+
 static void
 seahorse_viewer_real_selection_changed (SeahorseViewer *self)
 {
-	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE (self);
-	ViewerPredicate *predicate;
+	GHashTableIter iter;
+	GHashTable *seen;
+	GPtrArray *deletes;
 	GList *objects;
+	GPtrArray *selected;
+	GtkActionGroup *actions;
+	GtkAction *action;
 	guint i;
 
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-
-	/* Enable if anything is selected */
-	gtk_action_group_set_sensitive (pv->object_actions,
-	                                seahorse_viewer_get_selected (self) != NULL);
+	seen = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+	                              NULL, (GDestroyNotify)g_ptr_array_unref);
 
 	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);
+	g_list_free (objects);
+
+	/*
+	 * At this point we only have the actions for real objects, so hook
+	 * in the delete logic here.
+	 */
+
+	deletes = g_ptr_array_new ();
 
-	/* Enable if any exportable objects are selected */
-	gtk_action_group_set_sensitive (pv->export_actions,
-	                                has_matching_objects (&exportable_predicate, objects));
-
-	/* Enable if any deletable objects are selected */
-	gtk_action_set_sensitive (pv->delete_action,
-	                          has_matching_objects (&deletable_predicate, objects));
-
-	/* Go through the list of actions and disable all those which have no matches */
-	for (i = 0; i < pv->predicates->len; ++i) {
-		predicate = &g_array_index (pv->predicates, ViewerPredicate, i);
-		if (predicate->is_commands)
-			continue;
-		gtk_action_group_set_visible (GTK_ACTION_GROUP (predicate->commands_or_actions),
-		                              has_matching_objects (&predicate->pred, objects));
+	g_hash_table_iter_init (&iter, seen);
+	while (g_hash_table_iter_next (&iter, (gpointer *)&actions, (gpointer *)&selected)) {
+		action = gtk_action_group_get_action (actions, "delete");
+		if (action != NULL)
+			g_ptr_array_add (deletes, action);
 	}
 
+	/* If there's no delete command, then disable ours */
+	if (deletes->len == 0) {
+		gtk_action_set_sensitive (self->pv->edit_delete, FALSE);
+
+	/* If there's one delete command, then hide ours, and show it */
+	} else if (deletes->len == 1) {
+		gtk_action_set_visible (self->pv->edit_delete, FALSE);
+		gtk_action_set_visible (deletes->pdata[0], TRUE);
+
+	/* If there's more than one delete command, then show ours, and hide others */
+	} else {
+		gtk_action_set_sensitive (self->pv->edit_delete, TRUE);
+		gtk_action_set_visible (self->pv->edit_delete, TRUE);
+		for (i = 0; i < deletes->len; i++)
+			gtk_action_set_visible (deletes->pdata[i], FALSE);
+	}
+
+	g_ptr_array_unref (deletes);
+
+	/* 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);
+	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);
+		}
+	}
+
+	g_hash_table_destroy (seen);
 }
 
 static void
-on_add_widget (GtkUIManager* ui, GtkWidget* widget, SeahorseViewer* self)
+on_ui_manager_add_widget (GtkUIManager *ui_manager,
+                          GtkWidget *widget,
+                          gpointer user_data)
 {
+	SeahorseViewer* self = SEAHORSE_VIEWER (user_data);
 	const char* name = NULL;
 	GtkWidget* holder;
 
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-	g_return_if_fail (GTK_IS_UI_MANAGER (ui));
-	g_return_if_fail (GTK_IS_WIDGET (widget));
-
 	if (GTK_IS_MENU_BAR (widget))
 		name = "menu-placeholder";
 	else if (GTK_IS_TOOLBAR (widget))
@@ -545,120 +561,89 @@ on_add_widget (GtkUIManager* ui, GtkWidget* widget, SeahorseViewer* self)
 		name = NULL;
 
 	holder = seahorse_widget_get_widget (SEAHORSE_WIDGET (self), name);
-	if (holder != NULL)
+	if (holder != NULL) {
 		gtk_container_add ((GTK_CONTAINER (holder)), widget);
-	else
+		gtk_widget_show (widget);
+	} else {
 		g_warning ("no place holder found for: %s", name);
+	}
 }
 
-GList *
-seahorse_viewer_get_selected_matching (SeahorseViewer *self,
-                                       SeahorsePredicate *pred)
-{
-	GList *all_objects;
-	GList *objects;
-
-	g_return_val_if_fail (SEAHORSE_IS_VIEWER (self), NULL);
-	g_return_val_if_fail (pred != NULL, NULL);
-
-	all_objects = seahorse_viewer_get_selected_objects (self);
-	objects = filter_matching_objects (pred, &all_objects);
-	g_list_free (all_objects);
-
-	return objects;
-}
-
-static GObject*
-seahorse_viewer_constructor (GType type, guint n_props, GObjectConstructParam *props)
+static void
+seahorse_viewer_constructed (GObject *obj)
 {
-	GObject *obj = G_OBJECT_CLASS (seahorse_viewer_parent_class)->constructor (type, n_props, props);
-	SeahorseViewer *self = NULL;
-	SeahorseViewerPrivate *pv;
+	SeahorseViewer *self = SEAHORSE_VIEWER (obj);
 	GError *error = NULL;
 	GtkWidget *win;
 	const gchar *name;
 	gchar *path;
-	GList *types, *l;
-
-	if (obj) {
-		pv = SEAHORSE_VIEWER_GET_PRIVATE (obj);
-		self = SEAHORSE_VIEWER (obj);
-
-		/* The widgts get added in an idle loop later */
-		name = seahorse_widget_get_name (SEAHORSE_WIDGET (self));
-		path = g_strdup_printf ("%sseahorse-%s.ui", SEAHORSE_UIDIR, name);
-		if (!gtk_ui_manager_add_ui_from_file (pv->ui_manager, path, &error)) {
-			g_warning ("couldn't load ui description for '%s': %s", name, error->message);
-			g_clear_error (&error);
-		}
-
-		g_free (path);
+	GtkActionGroup *actions;
 
-		win = seahorse_widget_get_toplevel (SEAHORSE_WIDGET (self));
-		if (G_TYPE_FROM_INSTANCE (G_OBJECT (win)) == GTK_TYPE_WINDOW)
-			gtk_window_add_accel_group (GTK_WINDOW (win),
-			                            gtk_ui_manager_get_accel_group (pv->ui_manager));
+	G_OBJECT_CLASS (seahorse_viewer_parent_class)->constructed (obj);
 
-		include_basic_actions (self);
+	/* The widgts get added in an idle loop later */
+	name = seahorse_widget_get_name (SEAHORSE_WIDGET (self));
+	path = g_strdup_printf ("%sseahorse-%s.ui", SEAHORSE_UIDIR, name);
+	if (!gtk_ui_manager_add_ui_from_file (self->pv->ui_manager, path, &error)) {
+		g_warning ("couldn't load ui description for '%s': %s", name, error->message);
+		g_clear_error (&error);
+	}
 
-		/* Setup the commands */
-		types = seahorse_registry_object_types (seahorse_registry_get (), "commands", NULL, NULL);
-		for (l = types; l; l = g_list_next (l)) {
-			GType typ = GPOINTER_TO_SIZE (l->data);
-			SeahorseCommands *commands;
+	g_free (path);
 
-			commands = g_object_new (typ, "view", self, NULL);
-			pv->all_commands = seahorse_object_list_prepend (pv->all_commands, commands);
-			g_object_unref (commands);
-		}
-	}
+	win = seahorse_widget_get_toplevel (SEAHORSE_WIDGET (self));
+	if (G_TYPE_FROM_INSTANCE (G_OBJECT (win)) == GTK_TYPE_WINDOW)
+		gtk_window_add_accel_group (GTK_WINDOW (win),
+		                            gtk_ui_manager_get_accel_group (self->pv->ui_manager));
 
-	return obj;
+	actions = gtk_action_group_new ("main");
+	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
+	gtk_action_group_add_actions (actions, UI_ENTRIES, G_N_ELEMENTS (UI_ENTRIES), self);
+	self->pv->edit_delete = gtk_action_group_get_action (actions, "edit-delete");
+	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);
 }
 
-
 static void
 seahorse_viewer_init (SeahorseViewer *self)
 {
-	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE (self);
-
-	pv->ui_manager = gtk_ui_manager_new ();
-	g_signal_connect (pv->ui_manager, "add-widget", G_CALLBACK (on_add_widget), self);
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_VIEWER,
+	                                        SeahorseViewerPrivate);
+	self->pv->actions = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+	                                           g_object_unref, NULL);
 
-	pv->predicates = g_array_new (FALSE, TRUE, sizeof (ViewerPredicate));
+	self->pv->ui_manager = gtk_ui_manager_new ();
+	g_signal_connect (self->pv->ui_manager, "add-widget",
+	                  G_CALLBACK (on_ui_manager_add_widget), self);
+	g_signal_connect (self->pv->ui_manager, "pre-activate",
+	                  G_CALLBACK (on_ui_manager_pre_activate), self);
+	g_signal_connect (self->pv->ui_manager, "post-activate",
+	                  G_CALLBACK (on_ui_manager_post_activate), self);
 }
 
 static void
 seahorse_viewer_dispose (GObject *obj)
 {
-	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE (obj);
-	ViewerPredicate *predicate;
-	guint i;
-
-	if (pv->ui_manager)
-		g_object_unref (pv->ui_manager);
-	pv->ui_manager = NULL;
-
-	if (pv->object_actions)
-		g_object_unref (pv->object_actions);
-	pv->object_actions = NULL;
+	SeahorseViewer *self = SEAHORSE_VIEWER (obj);
 
-	if (pv->export_actions)
-		g_object_unref (pv->export_actions);
-	pv->export_actions = NULL;
+	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);
 
-	if (pv->delete_action)
-		g_object_unref (pv->delete_action);
-	pv->delete_action = NULL;
+	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);
+	g_signal_handlers_disconnect_by_func (self->pv->ui_manager, on_ui_manager_post_activate, self);
+	g_clear_object (&self->pv->ui_manager);
 
-	for (i = 0; i < pv->predicates->len; ++i) {
-		predicate = &g_array_index (pv->predicates, ViewerPredicate, i);
-		g_object_unref (predicate->commands_or_actions);
-	}
-	g_array_set_size (pv->predicates, 0);
-
-	seahorse_object_list_free (pv->all_commands);
-	pv->all_commands = NULL;
+	g_hash_table_remove_all (self->pv->actions);
 
 	G_OBJECT_CLASS (seahorse_viewer_parent_class)->dispose (obj);
 }
@@ -666,14 +651,11 @@ seahorse_viewer_dispose (GObject *obj)
 static void
 seahorse_viewer_finalize (GObject *obj)
 {
-	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE(obj);
+	SeahorseViewer *self = SEAHORSE_VIEWER (obj);
 
-	g_assert (pv->object_actions == NULL);
-	g_assert (pv->export_actions == NULL);
-	g_assert (pv->delete_action == NULL);
-	g_assert (pv->all_commands == NULL);
-	g_assert (pv->ui_manager == NULL);
-	g_array_free (pv->predicates, TRUE);
+	g_assert (self->pv->ui_manager == NULL);
+	g_assert (g_hash_table_size (self->pv->actions) == 0);
+	g_hash_table_destroy (self->pv->actions);
 
 	G_OBJECT_CLASS (seahorse_viewer_parent_class)->finalize (obj);
 }
@@ -685,9 +667,6 @@ seahorse_viewer_get_property (GObject *obj, guint prop_id, GValue *value,
 	SeahorseViewer *self = SEAHORSE_VIEWER (obj);
 
 	switch (prop_id) {
-	case PROP_SELECTED:
-		g_value_set_object (value, seahorse_viewer_get_selected (self));
-		break;
 	case PROP_WINDOW:
 		g_value_set_object (value, seahorse_viewer_get_window (self));
 		break;
@@ -698,41 +677,19 @@ seahorse_viewer_get_property (GObject *obj, guint prop_id, GValue *value,
 }
 
 static void
-seahorse_viewer_set_property (GObject *obj, guint prop_id, const GValue *value,
-                              GParamSpec *pspec)
-{
-	SeahorseViewer *self = SEAHORSE_VIEWER (obj);
-
-	switch (prop_id) {
-	case PROP_SELECTED:
-		seahorse_viewer_set_selected (self, g_value_get_object (value));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
-		break;
-	}
-}
-
-static void
 seahorse_viewer_class_init (SeahorseViewerClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-	seahorse_viewer_parent_class = g_type_class_peek_parent (klass);
 	g_type_class_add_private (klass, sizeof (SeahorseViewerPrivate));
 
-	gobject_class->constructor = seahorse_viewer_constructor;
+	gobject_class->constructed = seahorse_viewer_constructed;
 	gobject_class->dispose = seahorse_viewer_dispose;
 	gobject_class->finalize = seahorse_viewer_finalize;
-	gobject_class->set_property = seahorse_viewer_set_property;
 	gobject_class->get_property = seahorse_viewer_get_property;
 
 	klass->selection_changed = seahorse_viewer_real_selection_changed;
 
-	g_object_class_install_property (gobject_class, PROP_SELECTED,
-	           g_param_spec_object ("selected", "Selected", "Selected Object",
-	                                SEAHORSE_TYPE_OBJECT, G_PARAM_READWRITE));
-
 	g_object_class_install_property (gobject_class, PROP_WINDOW,
 	           g_param_spec_object ("window", "Window", "Window of View",
 	                                GTK_TYPE_WIDGET, G_PARAM_READABLE));
@@ -740,182 +697,110 @@ seahorse_viewer_class_init (SeahorseViewerClass *klass)
 	g_signal_new ("selection-changed", SEAHORSE_TYPE_VIEWER,
 	              G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (SeahorseViewerClass, selection_changed),
 	              NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
-	exportable_predicate.flags = SEAHORSE_FLAG_EXPORTABLE;
-	deletable_predicate.flags = SEAHORSE_FLAG_DELETABLE;
 }
 
-/* -----------------------------------------------------------------------------
- * PUBLIC
- */
-
 void
 seahorse_viewer_ensure_updated (SeahorseViewer* self)
 {
-	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE (self);
 	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-
-	gtk_ui_manager_ensure_update (pv->ui_manager);
-
+	gtk_ui_manager_ensure_update (self->pv->ui_manager);
 }
 
 void
-seahorse_viewer_include_actions (SeahorseViewer* self, GtkActionGroup* actions)
+seahorse_viewer_include_actions (SeahorseViewer* self,
+                                 GtkActionGroup* actions)
 {
-	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE (self);
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-
-	gtk_ui_manager_insert_action_group (pv->ui_manager, actions, -1);
-}
-
-GList*
-seahorse_viewer_get_selected_objects (SeahorseViewer* self)
-{
-	g_return_val_if_fail (SEAHORSE_IS_VIEWER (self), NULL);
-	g_return_val_if_fail (SEAHORSE_VIEWER_GET_CLASS (self)->get_selected_objects, NULL);
-
-	return SEAHORSE_VIEWER_GET_CLASS (self)->get_selected_objects (self);
-}
+	const gchar *definition;
+	GError *error = NULL;
 
-void
-seahorse_viewer_set_selected_objects (SeahorseViewer* self, GList* objects)
-{
 	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-	g_return_if_fail (SEAHORSE_VIEWER_GET_CLASS (self)->set_selected_objects);
-
-	SEAHORSE_VIEWER_GET_CLASS (self)->set_selected_objects (self, objects);
+	g_return_if_fail (GTK_IS_ACTION_GROUP (actions));
+
+	gtk_ui_manager_insert_action_group (self->pv->ui_manager, actions, 0);
+
+	if (SEAHORSE_IS_ACTIONS (actions)) {
+		definition = seahorse_actions_get_definition (SEAHORSE_ACTIONS (actions));
+		if (definition != NULL) {
+			gtk_ui_manager_add_ui_from_string (self->pv->ui_manager, definition, -1, &error);
+			if (error != NULL) {
+				g_warning ("couldn't add ui defintion for action group: %s: %s",
+				           gtk_action_group_get_name (actions), definition);
+				g_clear_error (&error);
+			}
+		}
+	}
 }
 
 void
-seahorse_viewer_show_context_menu (SeahorseViewer* self, guint button, guint time)
+seahorse_viewer_show_context_menu (SeahorseViewer* self,
+                                   const gchar *which,
+                                   guint button,
+                                   guint time)
 {
-	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE (self);
 	GtkMenu* menu;
 
 	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
+	g_return_if_fail (which != NULL);
 
-	menu = GTK_MENU (gtk_ui_manager_get_widget (pv->ui_manager, "/KeyPopup"));
-	g_return_if_fail (GTK_IS_MENU (menu));
+	menu = GTK_MENU (gtk_ui_manager_get_widget (self->pv->ui_manager, which));
+	if (!GTK_IS_MENU (menu)) {
+		g_warning ("couldn't find menu '%s' in UI", which);
+		return;
+	}
 
 	gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, time);
 	gtk_widget_show (GTK_WIDGET (menu));
 }
 
 void
-seahorse_viewer_show_properties (SeahorseViewer* self, GObject* obj)
+seahorse_viewer_show_properties (SeahorseViewer* self,
+                                 GObject* obj)
 {
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-	g_return_if_fail (G_IS_OBJECT (obj));
-
-	for_each_commands (self, show_properties_for_selected, obj);
-}
+	GtkAction *action;
+	GList *objects;
 
-void
-seahorse_viewer_set_status (SeahorseViewer* self, const char* text)
-{
-	GtkStatusbar* status;
-	guint id;
+	action = properties_action_for_object (obj);
+	if (action == NULL)
+		return;
 
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-	g_return_if_fail (text != NULL);
+	objects = g_list_append (NULL, obj);
+	seahorse_action_set_objects (action, objects);
+	seahorse_action_set_window (action, seahorse_viewer_get_window (self));
+	g_list_free (objects);
 
-	status = GTK_STATUSBAR (seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "status"));
-	g_return_if_fail (GTK_IS_STATUSBAR (status));
+	gtk_action_activate (action);
 
-	id = gtk_statusbar_get_context_id (status, "key-manager");
-	gtk_statusbar_pop (status, id);
-	gtk_statusbar_push (status, id, text);
+	seahorse_action_set_objects (action, NULL);
+	seahorse_action_set_window (action, NULL);
 }
 
-void
-seahorse_viewer_set_numbered_status (SeahorseViewer* self, const char* text, gint num)
-{
-	gchar* message;
-
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-	g_return_if_fail (text != NULL);
-
-	message = g_strdup_printf (text, num);
-	seahorse_viewer_set_status (self, message);
-	g_free (message);
-}
-
-GObject *
-seahorse_viewer_get_selected (SeahorseViewer* self)
+GtkWindow *
+seahorse_viewer_get_window (SeahorseViewer* self)
 {
 	g_return_val_if_fail (SEAHORSE_IS_VIEWER (self), NULL);
-	g_return_val_if_fail (SEAHORSE_VIEWER_GET_CLASS (self)->get_selected, NULL);
-
-	return SEAHORSE_VIEWER_GET_CLASS (self)->get_selected (self);
-}
-
-void
-seahorse_viewer_set_selected (SeahorseViewer *self,
-                              GObject *value)
-{
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-	g_return_if_fail (SEAHORSE_VIEWER_GET_CLASS (self)->set_selected);
-
-	SEAHORSE_VIEWER_GET_CLASS (self)->set_selected (self, value);
+	return GTK_WINDOW (seahorse_widget_get_toplevel (SEAHORSE_WIDGET (self)));
 }
 
-GtkWindow*
-seahorse_viewer_get_window (SeahorseViewer* self)
+GList *
+seahorse_viewer_get_selected_objects (SeahorseViewer* self)
 {
 	g_return_val_if_fail (SEAHORSE_IS_VIEWER (self), NULL);
-	return GTK_WINDOW (seahorse_widget_get_toplevel (SEAHORSE_WIDGET (self)));
+	g_return_val_if_fail (SEAHORSE_VIEWER_GET_CLASS (self)->get_selected_objects, NULL);
+	return SEAHORSE_VIEWER_GET_CLASS (self)->get_selected_objects (self);
 }
 
-void
-seahorse_viewer_register_ui (SeahorseViewer *self,
-                             SeahorsePredicate *pred,
-                             const gchar *uidef,
-                             GtkActionGroup *actions)
+GList *
+seahorse_viewer_get_selected_places (SeahorseViewer* self)
 {
-	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE (self);
-	GError *error = NULL;
-	ViewerPredicate predicate;
-
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-
-	if (actions != NULL) {
-		seahorse_viewer_include_actions (self, actions);
-
-		/* Add this to the list */
-		memset (&predicate, 0, sizeof (predicate));
-		if (pred)
-			predicate.pred = *pred;
-		predicate.is_commands = FALSE;
-		predicate.commands_or_actions = G_OBJECT (actions);
-		g_object_ref (actions);
-		g_array_append_val (pv->predicates, predicate);
-	}
-
-	if (uidef && uidef[0]) {
-		if (!gtk_ui_manager_add_ui_from_string (pv->ui_manager, uidef, -1, &error)) {
-			g_warning ("couldn't load UI description: %s", error->message);
-			g_clear_error (&error);
-		}
-	}
+	g_return_val_if_fail (SEAHORSE_IS_VIEWER (self), NULL);
+	g_return_val_if_fail (SEAHORSE_VIEWER_GET_CLASS (self)->get_selected_places, NULL);
+	return SEAHORSE_VIEWER_GET_CLASS (self)->get_selected_places (self);
 }
 
-void
-seahorse_viewer_register_commands (SeahorseViewer *self,
-                                   SeahorsePredicate *pred,
-                                   SeahorseCommands *commands)
+GList *
+seahorse_viewer_get_selected_backends (SeahorseViewer* self)
 {
-	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE (self);
-	ViewerPredicate predicate;
-
-	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-	g_return_if_fail (SEAHORSE_IS_COMMANDS (commands));
-
-	/* Add this to the list of commands */
-	memset (&predicate, 0, sizeof (predicate));
-	if (pred)
-		predicate.pred = *pred;
-	predicate.is_commands = TRUE;
-	predicate.commands_or_actions = G_OBJECT (commands);
-	g_object_ref (commands);
-	g_array_append_val (pv->predicates, predicate);
+	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);
 }
diff --git a/libseahorse/seahorse-viewer.h b/libseahorse/seahorse-viewer.h
index e582941..5ced3c6 100644
--- a/libseahorse/seahorse-viewer.h
+++ b/libseahorse/seahorse-viewer.h
@@ -24,9 +24,12 @@
 
 #include <glib-object.h>
 
-#include "seahorse-predicate.h"
 #include "seahorse-widget.h"
 
+#define SEAHORSE_VIEWER_MENU_BACKEND  "/BackendPopup"
+#define SEAHORSE_VIEWER_MENU_OBJECT   "/ObjectPopup"
+#define SEAHORSE_VIEWER_MENU_PLACE    "/PlacePopup"
+
 #define SEAHORSE_TYPE_VIEWER               (seahorse_viewer_get_type ())
 #define SEAHORSE_VIEWER(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_VIEWER, SeahorseViewer))
 #define SEAHORSE_VIEWER_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_VIEWER, SeahorseViewerClass))
@@ -34,31 +37,23 @@
 #define SEAHORSE_IS_VIEWER_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_VIEWER))
 #define SEAHORSE_VIEWER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_VIEWER, SeahorseViewerClass))
 
-typedef struct _SeahorseCommands SeahorseCommands;
 typedef struct _SeahorseViewer SeahorseViewer;
 typedef struct _SeahorseViewerClass SeahorseViewerClass;
 typedef struct _SeahorseViewerPrivate SeahorseViewerPrivate;
 
 struct _SeahorseViewer {
 	SeahorseWidget parent;
+	SeahorseViewerPrivate *pv;
 };
 
 struct _SeahorseViewerClass {
 	SeahorseWidgetClass parent;
 
-	/* virtual -------------------------------------------------------- */
-
-	GList *          (*get_selected_objects)          (SeahorseViewer *self);
-
-	void             (*set_selected_objects)          (SeahorseViewer *self,
-	                                                   GList *objects);
+	GList *          (*get_selected_backends)         (SeahorseViewer *self);
 
-	GObject *        (*get_selected)                  (SeahorseViewer* self);
+	GList *          (*get_selected_places)           (SeahorseViewer *self);
 
-	void             (*set_selected)                  (SeahorseViewer* self,
-	                                                   GObject* value);
-
-	/* signals --------------------------------------------------------- */
+	GList *          (*get_selected_objects)          (SeahorseViewer *self);
 
 	void             (*selection_changed)             (SeahorseViewer *viewer);
 };
@@ -70,35 +65,32 @@ void                seahorse_viewer_ensure_updated                  (SeahorseVie
 void                seahorse_viewer_include_actions                 (SeahorseViewer* self,
                                                                      GtkActionGroup* actions);
 
-GList*              seahorse_viewer_get_selected_objects            (SeahorseViewer* self);
+GList *             seahorse_viewer_get_selected_objects            (SeahorseViewer* self);
 
-void                seahorse_viewer_set_selected_objects            (SeahorseViewer* self,
-                                                                     GList* objects);
+GList *             seahorse_viewer_get_selected_places             (SeahorseViewer* self);
 
-GList *             seahorse_viewer_get_selected_matching           (SeahorseViewer *self,
-                                                                     SeahorsePredicate *pred);
+GList *             seahorse_viewer_get_selected_backends           (SeahorseViewer* self);
 
 void                seahorse_viewer_show_context_menu               (SeahorseViewer* self,
+                                                                     const gchar *which,
                                                                      guint button,
                                                                      guint time);
 
 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
 
-GObject *           seahorse_viewer_get_selected                    (SeahorseViewer *self);
-
-void                seahorse_viewer_set_selected                    (SeahorseViewer *self,
-                                                                     GObject *value);
-
-GtkWindow*          seahorse_viewer_get_window                      (SeahorseViewer* self);
+GtkWindow *         seahorse_viewer_get_window                      (SeahorseViewer* self);
 
+#if 0
 void                seahorse_viewer_register_ui                     (SeahorseViewer *self,
                                                                      SeahorsePredicate *pred,
                                                                      const gchar *uidef,
@@ -107,5 +99,6 @@ void                seahorse_viewer_register_ui                     (SeahorseVie
 void                seahorse_viewer_register_commands               (SeahorseViewer *self,
                                                                      SeahorsePredicate *pred,
                                                                      SeahorseCommands *commands);
+#endif
 
 #endif /* __SEAHORSE_VIEWER_H__ */
diff --git a/pgp/Makefile.am b/pgp/Makefile.am
index ab642e1..425809d 100644
--- a/pgp/Makefile.am
+++ b/pgp/Makefile.am
@@ -58,8 +58,8 @@ libseahorse_pgp_la_SOURCES = \
 	seahorse-gpg-op.h seahorse-gpg-op.c \
 	seahorse-gpg-options.c seahorse-gpg-options.h \
 	seahorse-pgp.c seahorse-pgp.h \
+	seahorse-pgp-actions.c seahorse-pgp-actions.h \
 	seahorse-pgp-backend.c seahorse-pgp-backend.h \
-	seahorse-pgp-commands.c seahorse-pgp-commands.h \
 	seahorse-pgp-key.c seahorse-pgp-key.h \
 	seahorse-pgp-key-properties.c \
 	seahorse-pgp-keysets.c seahorse-pgp-keysets.h \
diff --git a/pgp/seahorse-gpgme-key-op.c b/pgp/seahorse-gpgme-key-op.c
index a7a0ba0..13ce539 100644
--- a/pgp/seahorse-gpgme-key-op.c
+++ b/pgp/seahorse-gpgme-key-op.c
@@ -243,7 +243,7 @@ op_delete (SeahorseGpgmeKey *pkey, gboolean secret)
 	gpgme_error_t err;
 	gpgme_key_t key;
 
-	keyring = SEAHORSE_GPGME_KEYRING (seahorse_object_get_source (SEAHORSE_OBJECT (pkey)));
+	keyring = SEAHORSE_GPGME_KEYRING (seahorse_object_get_place (SEAHORSE_OBJECT (pkey)));
 	g_return_val_if_fail (SEAHORSE_IS_GPGME_KEYRING (keyring), GPG_E (GPG_ERR_INV_KEYRING));
 
 	g_object_ref (pkey);
@@ -399,7 +399,7 @@ edit_key (SeahorseGpgmeKey *pkey, SeahorseEditParm *parms)
 	gpgme_error_t err;
 	gpgme_key_t key;
 
-	keyring = SEAHORSE_GPGME_KEYRING (seahorse_object_get_source (SEAHORSE_OBJECT (pkey)));
+	keyring = SEAHORSE_GPGME_KEYRING (seahorse_object_get_place (SEAHORSE_OBJECT (pkey)));
 	g_return_val_if_fail (SEAHORSE_IS_GPGME_KEYRING (keyring), GPG_E (GPG_ERR_INV_KEYRING));
 
 	g_object_ref (pkey);
diff --git a/pgp/seahorse-gpgme-key.c b/pgp/seahorse-gpgme-key.c
index 81c62a2..f36793a 100644
--- a/pgp/seahorse-gpgme-key.c
+++ b/pgp/seahorse-gpgme-key.c
@@ -28,9 +28,10 @@
 #include "seahorse-icons.h"
 #include "seahorse-predicate.h"
 #include "seahorse-object-list.h"
-#include "seahorse-source.h"
+#include "seahorse-place.h"
 #include "seahorse-util.h"
 
+#include "seahorse-pgp-actions.h"
 #include "seahorse-pgp-backend.h"
 #include "pgp/seahorse-pgp-key.h"
 #include "pgp/seahorse-gpgme.h"
@@ -297,6 +298,7 @@ void
 seahorse_gpgme_key_realize (SeahorseGpgmeKey *self)
 {
 	SeahorseUsage usage;
+	GtkActionGroup *actions;
 	guint flags;
 
 	if (!self->pv->pubkey)
@@ -347,10 +349,13 @@ seahorse_gpgme_key_realize (SeahorseGpgmeKey *self)
 		usage = SEAHORSE_USAGE_PUBLIC_KEY;
 	}
 
+	actions = seahorse_gpgme_key_actions_instance ();
 	g_object_set (self,
 	              "usage", usage,
 	              "flags", flags,
+	              "actions", actions,
 	              NULL);
+	g_object_unref (actions);
 
 	seahorse_pgp_key_realize (SEAHORSE_PGP_KEY (self));
 }
@@ -536,13 +541,16 @@ seahorse_gpgme_key_class_init (SeahorseGpgmeKeyClass *klass)
  */
 
 SeahorseGpgmeKey* 
-seahorse_gpgme_key_new (SeahorseSource *sksrc, gpgme_key_t pubkey, 
+seahorse_gpgme_key_new (SeahorsePlace *sksrc,
+                        gpgme_key_t pubkey,
                         gpgme_key_t seckey)
 {
 	g_return_val_if_fail (pubkey || seckey, NULL);
 
-	return g_object_new (SEAHORSE_TYPE_GPGME_KEY, "source", sksrc,
-	                     "pubkey", pubkey, "seckey", seckey, 
+	return g_object_new (SEAHORSE_TYPE_GPGME_KEY,
+	                     "place", sksrc,
+	                     "pubkey", pubkey,
+	                     "seckey", seckey,
 	                     NULL);
 }
 
diff --git a/pgp/seahorse-gpgme-key.h b/pgp/seahorse-gpgme-key.h
index 2931b41..012d24c 100644
--- a/pgp/seahorse-gpgme-key.h
+++ b/pgp/seahorse-gpgme-key.h
@@ -49,7 +49,7 @@ struct _SeahorseGpgmeKeyClass {
 	SeahorsePgpKeyClass         parent_class;
 };
 
-SeahorseGpgmeKey* seahorse_gpgme_key_new                 (SeahorseSource *sksrc,
+SeahorseGpgmeKey* seahorse_gpgme_key_new                 (SeahorsePlace *sksrc,
                                                           gpgme_key_t pubkey,
                                                           gpgme_key_t seckey);
 
diff --git a/pgp/seahorse-gpgme-keyring.c b/pgp/seahorse-gpgme-keyring.c
index 585e6a8..11b2524 100644
--- a/pgp/seahorse-gpgme-keyring.c
+++ b/pgp/seahorse-gpgme-keyring.c
@@ -28,6 +28,7 @@
 #include "seahorse-gpgme.h"
 #include "seahorse-gpgme-key-op.h"
 #include "seahorse-gpg-options.h"
+#include "seahorse-pgp-actions.h"
 #include "seahorse-pgp-key.h"
 
 #include "seahorse-progress.h"
@@ -53,7 +54,8 @@ enum {
 	PROP_LABEL,
 	PROP_DESCRIPTION,
 	PROP_ICON,
-	PROP_URI
+	PROP_URI,
+	PROP_ACTIONS
 };
 
 /* Amount of keys to load in a batch */
@@ -149,15 +151,16 @@ struct _SeahorseGpgmeKeyringPrivate {
 	guint scheduled_refresh;                /* Source for refresh timeout */
 	GFileMonitor *monitor_handle;           /* For monitoring the .gnupg directory */
 	GList *orphan_secret;                   /* Orphan secret keys */
+	GtkActionGroup *actions;
 };
 
-static void     seahorse_gpgme_keyring_source_iface       (SeahorseSourceIface *iface);
+static void     seahorse_gpgme_keyring_place_iface        (SeahorsePlaceIface *iface);
 
 static void     seahorse_gpgme_keyring_collection_iface   (GcrCollectionIface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (SeahorseGpgmeKeyring, seahorse_gpgme_keyring, G_TYPE_OBJECT,
                          G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_gpgme_keyring_collection_iface);
-                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_gpgme_keyring_source_iface);
+                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_PLACE, seahorse_gpgme_keyring_place_iface);
 );
 
 typedef struct {
@@ -214,7 +217,7 @@ add_key_to_context (SeahorseGpgmeKeyring *self,
 
 	/* Create a new key with secret */
 	if (key->secret) {
-		pkey = seahorse_gpgme_key_new (SEAHORSE_SOURCE (self), NULL, key);
+		pkey = seahorse_gpgme_key_new (SEAHORSE_PLACE (self), NULL, key);
 
 		/* Since we don't have a public key yet, save this away */
 		self->pv->orphan_secret = g_list_append (self->pv->orphan_secret, pkey);
@@ -247,7 +250,7 @@ add_key_to_context (SeahorseGpgmeKeyring *self,
 	}
 
 	if (pkey == NULL)
-		pkey = seahorse_gpgme_key_new (SEAHORSE_SOURCE (self), key, NULL);
+		pkey = seahorse_gpgme_key_new (SEAHORSE_PLACE (self), key, NULL);
 
 	/* Add to context */
 	g_hash_table_insert (self->pv->keys, g_strdup (keyid), pkey);
@@ -677,20 +680,20 @@ on_keyring_import_complete (gpgme_error_t gerr,
 }
 
 static void
-seahorse_gpgme_keyring_import_async (SeahorseSource *source,
-                                    GInputStream *input,
-                                    GCancellable *cancellable,
-                                    GAsyncReadyCallback callback,
-                                    gpointer user_data)
+seahorse_gpgme_keyring_import_async (SeahorsePlace *place,
+                                     GInputStream *input,
+                                     GCancellable *cancellable,
+                                     GAsyncReadyCallback callback,
+                                     gpointer user_data)
 {
-	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (source);
+	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (place);
 	GSimpleAsyncResult *res;
 	keyring_import_closure *closure;
 	gpgme_error_t gerr;
 	GError *error = NULL;
 	GSource *gsource;
 
-	res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+	res = g_simple_async_result_new (G_OBJECT (place), callback, user_data,
 	                                 seahorse_gpgme_keyring_import_async);
 	closure = g_new0 (keyring_import_closure, 1);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
@@ -719,14 +722,14 @@ seahorse_gpgme_keyring_import_async (SeahorseSource *source,
 }
 
 static GList *
-seahorse_gpgme_keyring_import_finish (SeahorseSource *source,
-                                     GAsyncResult *result,
-                                     GError **error)
+seahorse_gpgme_keyring_import_finish (SeahorsePlace *place,
+                                      GAsyncResult *result,
+                                      GError **error)
 {
 	keyring_import_closure *closure;
 	GList *results;
 
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (place),
 	                      seahorse_gpgme_keyring_import_async), NULL);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
@@ -803,12 +806,12 @@ on_keyring_export_complete (gpgme_error_t gerr,
 }
 
 static void
-seahorse_gpgme_keyring_export_async (SeahorseSource *source,
-                                    GList *objects,
-                                    GOutputStream *output,
-                                    GCancellable *cancellable,
-                                    GAsyncReadyCallback callback,
-                                    gpointer user_data)
+seahorse_gpgme_keyring_export_async (SeahorsePlace *place,
+                                     GList *objects,
+                                     GOutputStream *output,
+                                     GCancellable *cancellable,
+                                     GAsyncReadyCallback callback,
+                                     gpointer user_data)
 {
 	GSimpleAsyncResult *res;
 	keyring_export_closure *closure;
@@ -817,7 +820,7 @@ seahorse_gpgme_keyring_export_async (SeahorseSource *source,
 	GSource *gsource;
 	GList *l;
 
-	res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+	res = g_simple_async_result_new (G_OBJECT (place), callback, user_data,
 	                                 seahorse_gpgme_keyring_export_async);
 	closure = g_new0 (keyring_export_closure, 1);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
@@ -839,7 +842,7 @@ seahorse_gpgme_keyring_export_async (SeahorseSource *source,
 
 		g_return_if_fail (SEAHORSE_IS_PGP_KEY (l->data));
 		key = SEAHORSE_PGP_KEY (l->data);
-		g_return_if_fail (seahorse_object_get_source (SEAHORSE_OBJECT (key)) == source);
+		g_return_if_fail (seahorse_object_get_place (SEAHORSE_OBJECT (key)) == place);
 
 		/* Building list */
 		keyid = g_strdup (seahorse_pgp_key_get_keyid (key));
@@ -860,13 +863,13 @@ seahorse_gpgme_keyring_export_async (SeahorseSource *source,
 }
 
 static GOutputStream *
-seahorse_gpgme_keyring_export_finish (SeahorseSource *source,
-                                     GAsyncResult *result,
-                                     GError **error)
+seahorse_gpgme_keyring_export_finish (SeahorsePlace *place,
+                                      GAsyncResult *result,
+                                      GError **error)
 {
 	keyring_export_closure *closure;
 
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (place),
 	                      seahorse_gpgme_keyring_export_async), NULL);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
@@ -956,6 +959,8 @@ seahorse_gpgme_keyring_get_property (GObject *obj,
                                      GValue *value,
                                      GParamSpec *pspec)
 {
+	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (obj);
+
 	switch (prop_id) {
 	case PROP_LABEL:
 		g_value_set_string (value, _("GnuPG keyring"));
@@ -969,6 +974,9 @@ seahorse_gpgme_keyring_get_property (GObject *obj,
 	case PROP_URI:
 		g_value_set_string (value, "gnupg://");
 		break;
+	case PROP_ACTIONS:
+		g_value_set_object (value, self->pv->actions);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -981,6 +989,7 @@ seahorse_gpgme_keyring_dispose (GObject *object)
 	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (object);
 	GList *l;
 
+	gtk_action_group_set_sensitive (self->pv->actions, TRUE);
 	g_hash_table_remove_all (self->pv->keys);
 
 	cancel_scheduled_refresh (self);
@@ -1005,6 +1014,7 @@ seahorse_gpgme_keyring_finalize (GObject *object)
 {
 	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (object);
 
+	g_clear_object (self->pv->actions);
 	g_hash_table_destroy (self->pv->keys);
 
 	/* All monitoring and scheduling should be done */
@@ -1037,10 +1047,11 @@ seahorse_gpgme_keyring_class_init (SeahorseGpgmeKeyringClass *klass)
 	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
 	g_object_class_override_property (gobject_class, PROP_URI, "uri");
 	g_object_class_override_property (gobject_class, PROP_ICON, "icon");
+	g_object_class_override_property (gobject_class, PROP_ACTIONS, "actions");
 }
 
 static void
-seahorse_gpgme_keyring_source_iface (SeahorseSourceIface *iface)
+seahorse_gpgme_keyring_place_iface (SeahorsePlaceIface *iface)
 {
 	iface->import_async = seahorse_gpgme_keyring_import_async;
 	iface->import_finish = seahorse_gpgme_keyring_import_finish;
diff --git a/pgp/seahorse-hkp-source.c b/pgp/seahorse-hkp-source.c
index 68f1002..2050f9f 100644
--- a/pgp/seahorse-hkp-source.c
+++ b/pgp/seahorse-hkp-source.c
@@ -559,10 +559,10 @@ detect_key (const gchar *text, gint len, const gchar **start, const gchar **end)
  *  SEAHORSE HKP SOURCE
  */
 
-static void seahorse_source_iface (SeahorseSourceIface *iface);
+static void seahorse_place_iface (SeahorsePlaceIface *iface);
 
 G_DEFINE_TYPE_EXTENDED (SeahorseHKPSource, seahorse_hkp_source, SEAHORSE_TYPE_SERVER_SOURCE, 0,
-                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_source_iface));
+                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_PLACE, seahorse_place_iface));
 
 static void 
 seahorse_hkp_source_init (SeahorseHKPSource *hsrc)
@@ -658,7 +658,7 @@ on_search_message_complete (SoupSession *session,
 	} else {
 		keys = parse_hkp_index (message->response_body->data);
 		for (l = keys; l; l = g_list_next (l)) {
-			g_object_set (l->data, "source", closure->source, NULL);
+			g_object_set (l->data, "place", closure->source, NULL);
 			gcr_simple_collection_add (closure->results, l->data);
 		}
 		g_list_free_full (keys, g_object_unref);
@@ -819,13 +819,13 @@ on_import_message_complete (SoupSession *session,
 * Imports a list of keys from the input stream to the keyserver
 **/
 static void
-seahorse_hkp_source_import_async (SeahorseSource *source,
+seahorse_hkp_source_import_async (SeahorsePlace *place,
                                   GInputStream *input,
                                   GCancellable *cancellable,
                                   GAsyncReadyCallback callback,
                                   gpointer user_data)
 {
-	SeahorseHKPSource *self = SEAHORSE_HKP_SOURCE (source);
+	SeahorseHKPSource *self = SEAHORSE_HKP_SOURCE (place);
 	GSimpleAsyncResult *res;
 	source_import_closure *closure;
 	SoupMessage *message;
@@ -837,7 +837,7 @@ seahorse_hkp_source_import_async (SeahorseSource *source,
 	GList *l;
 	guint len;
 
-	res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+	res = g_simple_async_result_new (G_OBJECT (place), callback, user_data,
 	                                 seahorse_hkp_source_import_async);
 	closure = g_new0 (source_import_closure, 1);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
@@ -909,11 +909,11 @@ seahorse_hkp_source_import_async (SeahorseSource *source,
 }
 
 static GList *
-seahorse_hkp_source_import_finish (SeahorseSource *source,
+seahorse_hkp_source_import_finish (SeahorsePlace *place,
                                    GAsyncResult *result,
                                    GError **error)
 {
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (place),
 	                      seahorse_hkp_source_import_async), NULL);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
@@ -1109,7 +1109,7 @@ seahorse_hkp_source_export_finish (SeahorseServerSource *source,
 *
 **/
 static void 
-seahorse_source_iface (SeahorseSourceIface *iface)
+seahorse_place_iface (SeahorsePlaceIface *iface)
 {
 	iface->import_async = seahorse_hkp_source_import_async;
 	iface->import_finish = seahorse_hkp_source_import_finish;
@@ -1131,7 +1131,6 @@ seahorse_hkp_source_class_init (SeahorseHKPSourceClass *klass)
 	server_class->export_async = seahorse_hkp_source_export_async;
 	server_class->export_finish = seahorse_hkp_source_export_finish;
 
-	seahorse_registry_register_type (NULL, SEAHORSE_TYPE_HKP_SOURCE, "source", "remote", NULL);
 	seahorse_servers_register_type ("hkp", _("HTTP Key Server"), seahorse_hkp_is_valid_uri);
 }
 /**
diff --git a/pgp/seahorse-keyserver-results.c b/pgp/seahorse-keyserver-results.c
index 3df5aa1..7207749 100644
--- a/pgp/seahorse-keyserver-results.c
+++ b/pgp/seahorse-keyserver-results.c
@@ -74,7 +74,6 @@ fire_selection_changed (SeahorseKeyserverResults* self)
 
 	selection = gtk_tree_view_get_selection (self->pv->view);
 	rows = gtk_tree_selection_count_selected_rows (selection);
-	seahorse_viewer_set_numbered_status (SEAHORSE_VIEWER (self), ngettext ("Selected %d key", "Selected %d keys", rows), rows);
 	if (self->pv->import_actions)
 		gtk_action_group_set_sensitive (self->pv->import_actions, rows > 0);
 	g_signal_emit_by_name (self, "selection-changed");
@@ -117,22 +116,26 @@ on_key_list_button_pressed (GtkTreeView* view, GdkEventButton* event, SeahorseKe
 	g_return_val_if_fail (SEAHORSE_IS_KEYSERVER_RESULTS (self), FALSE);
 	g_return_val_if_fail (GTK_IS_TREE_VIEW (view), FALSE);
 	if (event->button == 3)
-		seahorse_viewer_show_context_menu (SEAHORSE_VIEWER (self), event->button, event->time);
+		seahorse_viewer_show_context_menu (SEAHORSE_VIEWER (self),
+		                                   SEAHORSE_VIEWER_MENU_OBJECT,
+		                                   event->button, event->time);
 	return FALSE;
 }
 
 G_MODULE_EXPORT gboolean
 on_key_list_popup_menu (GtkTreeView* view, SeahorseKeyserverResults* self)
 {
-	GObject* key;
+	GList *objects;
 
 	g_return_val_if_fail (SEAHORSE_IS_KEYSERVER_RESULTS (self), FALSE);
 	g_return_val_if_fail (GTK_IS_TREE_VIEW (view), FALSE);
 
-	key = seahorse_viewer_get_selected (SEAHORSE_VIEWER (self));
-	if (key == NULL)
-		return FALSE;
-	seahorse_viewer_show_context_menu (SEAHORSE_VIEWER (self), 0, gtk_get_current_event_time ());
+	objects = seahorse_viewer_get_selected_objects (SEAHORSE_VIEWER (self));
+	if (objects != NULL)
+		seahorse_viewer_show_context_menu (SEAHORSE_VIEWER (self),
+		                                   SEAHORSE_VIEWER_MENU_OBJECT,
+		                                   0, gtk_get_current_event_time ());
+	g_list_free (objects);
 	return TRUE;
 }
 
@@ -171,8 +174,6 @@ on_import_complete (GObject *source,
 	                                           result, &error))
 		seahorse_util_handle_error (&error, seahorse_viewer_get_window (self),
 		                            _("Couldn't import keys"));
-	else
-		seahorse_viewer_set_status (self, _ ("Imported keys"));
 
 	g_object_unref (self);
 }
@@ -213,7 +214,7 @@ on_key_import_keyring (GtkAction* action, SeahorseViewer* self)
 	cancellable = g_cancellable_new ();
 	backend = seahorse_pgp_backend_get ();
 	keyring = seahorse_pgp_backend_get_default_keyring (NULL);
-	seahorse_pgp_backend_transfer_async (backend, objects, SEAHORSE_SOURCE (keyring),
+	seahorse_pgp_backend_transfer_async (backend, objects, SEAHORSE_PLACE (keyring),
 	                                     cancellable, on_import_complete, g_object_ref (self));
 	seahorse_progress_show (cancellable, _ ("Importing keys from key servers"), TRUE);
 	g_object_unref (cancellable);
@@ -255,48 +256,25 @@ static const GtkActionEntry IMPORT_ENTRIES[] = {
 	  N_("Import selected keys to local key ring"), G_CALLBACK (on_key_import_keyring) }
 };
 
-/* -----------------------------------------------------------------------------
- * OBJECT
- */
-
-static GList*
-seahorse_keyserver_results_get_selected_objects (SeahorseViewer* base)
+static GList *
+seahorse_keyserver_results_get_selected_objects (SeahorseViewer* viewer)
 {
-	SeahorseKeyserverResults * self = SEAHORSE_KEYSERVER_RESULTS (base);
+	SeahorseKeyserverResults * self = SEAHORSE_KEYSERVER_RESULTS (viewer);
 	return seahorse_key_manager_store_get_selected_objects (self->pv->view);
 }
 
-static void
-seahorse_keyserver_results_set_selected_objects (SeahorseViewer* base, GList* keys)
-{
-	SeahorseKeyserverResults * self = SEAHORSE_KEYSERVER_RESULTS (base);
-	seahorse_key_manager_store_set_selected_objects (self->pv->view, keys);
-}
-
-static GObject *
-seahorse_keyserver_results_get_selected (SeahorseViewer *base)
+static GList *
+seahorse_keyserver_results_get_selected_backends (SeahorseViewer* viewer)
 {
-	SeahorseKeyserverResults* self;
-	self = SEAHORSE_KEYSERVER_RESULTS (base);
-	return seahorse_key_manager_store_get_selected_object (self->pv->view);
+	return NULL;
 }
 
-static void
-seahorse_keyserver_results_set_selected (SeahorseViewer *base,
-                                         GObject *value)
+static GList *
+seahorse_keyserver_results_get_selected_places (SeahorseViewer* viewer)
 {
-	SeahorseKeyserverResults* self = SEAHORSE_KEYSERVER_RESULTS (base);
-	GList* keys = NULL;
-
-	if (value != NULL)
-		keys = g_list_prepend (keys, value);
-
-	seahorse_viewer_set_selected_objects (SEAHORSE_VIEWER (self), keys);
-	g_list_free (keys);;
-	g_object_notify (G_OBJECT (self), "selected");
+	return NULL;
 }
 
-
 /**
 * type: The type identifying this object
 * n_props: Number of properties
@@ -443,10 +421,6 @@ seahorse_keyserver_results_set_property (GObject *obj, guint prop_id, const GVal
 		self->pv->search_string = g_strstrip (g_utf8_casefold (str, -1));
 		break;
 
-	case PROP_SELECTED:
-		seahorse_viewer_set_selected (SEAHORSE_VIEWER (self), g_value_get_object (value));
-		break;
-
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -472,9 +446,6 @@ seahorse_keyserver_results_get_property (GObject *obj, guint prop_id, GValue *va
 	case PROP_SEARCH:
 		g_value_set_string (value, seahorse_keyserver_results_get_search (self));
 		break;
-	case PROP_SELECTED:
-		g_value_set_object (value, seahorse_viewer_get_selected (SEAHORSE_VIEWER (self)));
-		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -501,9 +472,8 @@ seahorse_keyserver_results_class_init (SeahorseKeyserverResultsClass *klass)
 	gobject_class->get_property = seahorse_keyserver_results_get_property;
 
 	SEAHORSE_VIEWER_CLASS (klass)->get_selected_objects = seahorse_keyserver_results_get_selected_objects;
-	SEAHORSE_VIEWER_CLASS (klass)->set_selected_objects = seahorse_keyserver_results_set_selected_objects;
-	SEAHORSE_VIEWER_CLASS (klass)->get_selected = seahorse_keyserver_results_get_selected;
-	SEAHORSE_VIEWER_CLASS (klass)->set_selected = seahorse_keyserver_results_set_selected;
+	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,
@@ -519,10 +489,12 @@ on_search_completed (GObject *source,
 {
 	SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (user_data);
 	GError *error = NULL;
+	GtkWindow *window;
 
 	seahorse_pgp_backend_search_remote_finish (NULL, result, &error);
 	if (error != NULL) {
-		seahorse_viewer_set_status (SEAHORSE_VIEWER (self), error->message);
+		window = seahorse_viewer_get_window (SEAHORSE_VIEWER (self));
+		seahorse_util_show_error (window, _("The search for keys failed."), error->message);
 		g_error_free (error);
 	}
 
diff --git a/pgp/seahorse-keyserver-results.ui b/pgp/seahorse-keyserver-results.ui
index 580eab9..d30c2b8 100644
--- a/pgp/seahorse-keyserver-results.ui
+++ b/pgp/seahorse-keyserver-results.ui
@@ -2,23 +2,20 @@
 	<menubar>
 		<menu name="File" action="file-menu">
 			<menuitem action="key-import-keyring"/>
-			<menuitem action="file-export"/>
 			<separator/>
 			<placeholder name="FileCommands">
-				<menuitem action="show-properties"/>
+				<menuitem action="properties-object"/>
 			</placeholder>
 			<separator/>
 			<menuitem action="app-close"/>
 		</menu>
 		<menu name="Edit" action="edit-menu">
-			<menuitem action="edit-export-clipboard"/>
 		</menu>
 		<menu name="Remote" action="remote-menu">
 			<menuitem action="remote-find"/>
 		</menu>
 		<menu name="Help" action="help-menu">
 			<menuitem action="help-show"/>
-<!--		<menuitem action="app-about"/> -->
 		</menu>
 
 	</menubar>
@@ -26,18 +23,15 @@
 	<toolbar name="MainToolbar">
 		<placeholder name="ToolItems">
 			<toolitem action="key-import-keyring"/>
-			<toolitem action="file-export"/>
-			<toolitem action="show-properties"/>
+			<toolitem action="properties-object"/>
 		</placeholder>
 	</toolbar>
 
-	<popup name="KeyPopup">
-		<menuitem action="edit-export-clipboard"/>
+	<popup name="ObjectPopup">
 		<separator/>
 		<menuitem action="key-import-keyring"/>
-		<menuitem action="file-export"/>
 		<separator/>
-		<menuitem action="show-properties"/>
+		<menuitem action="properties-object"/>
 	</popup>
 
 </ui>
diff --git a/pgp/seahorse-keyserver-sync.c b/pgp/seahorse-keyserver-sync.c
index 1bf90dc..6ec4827 100644
--- a/pgp/seahorse-keyserver-sync.c
+++ b/pgp/seahorse-keyserver-sync.c
@@ -46,7 +46,7 @@ on_transfer_upload_complete (GObject *object,
                              GAsyncResult *result,
                              gpointer user_data)
 {
-	SeahorseSource *source = SEAHORSE_SOURCE (user_data);
+	SeahorsePlace *place = SEAHORSE_PLACE (user_data);
 	GError *error = NULL;
 	gchar *publish_to;
 
@@ -58,7 +58,7 @@ on_transfer_upload_complete (GObject *object,
 		g_free (publish_to);
 	}
 
-	g_object_unref (source);
+	g_object_unref (place);
 }
 
 static void
@@ -66,18 +66,18 @@ on_transfer_download_complete (GObject *object,
                                GAsyncResult *result,
                                gpointer user_data)
 {
-	SeahorseSource *source = SEAHORSE_SOURCE (user_data);
+	SeahorsePlace *place = SEAHORSE_PLACE (user_data);
 	GError *error = NULL;
 	gchar *keyserver;
 
 	if (!seahorse_transfer_finish (result, &error)) {
-		g_object_get (source, "key-server", &keyserver, NULL);
+		g_object_get (place, "key-server", &keyserver, NULL);
 		seahorse_util_handle_error (&error, NULL,
 		                            _("Couldn't retrieve keys from server: %s"), keyserver);
 		g_free (keyserver);
 	}
 
-	g_object_unref (source);
+	g_object_unref (place);
 }
 
 G_MODULE_EXPORT void
@@ -203,7 +203,7 @@ seahorse_keyserver_sync (GList *keys)
 			continue;
 
 		keyring = seahorse_pgp_backend_get_default_keyring (NULL);
-		seahorse_transfer_async (SEAHORSE_SOURCE (source), SEAHORSE_SOURCE (keyring),
+		seahorse_transfer_async (SEAHORSE_PLACE (source), SEAHORSE_PLACE (keyring),
 		                         keys, cancellable, on_transfer_download_complete,
 		                         g_object_ref (source));
 	}
@@ -218,7 +218,7 @@ seahorse_keyserver_sync (GList *keys)
 
 		/* This can happen if the URI scheme is not supported */
 		if (source != NULL) {
-			seahorse_pgp_backend_transfer_async (NULL, keys, SEAHORSE_SOURCE (source),
+			seahorse_pgp_backend_transfer_async (NULL, keys, SEAHORSE_PLACE (source),
 			                                     cancellable, on_transfer_upload_complete,
 			                                     g_object_ref (source));
 		}
diff --git a/pgp/seahorse-ldap-source.c b/pgp/seahorse-ldap-source.c
index 03d8cb9..98c51fb 100644
--- a/pgp/seahorse-ldap-source.c
+++ b/pgp/seahorse-ldap-source.c
@@ -735,10 +735,10 @@ seahorse_ldap_source_connect_finish (SeahorseLDAPSource *source,
 	return ldap;
 }
 
-static void seahorse_source_iface (SeahorseSourceIface *iface);
+static void seahorse_place_iface (SeahorsePlaceIface *iface);
 
 G_DEFINE_TYPE_EXTENDED (SeahorseLDAPSource, seahorse_ldap_source, SEAHORSE_TYPE_SERVER_SOURCE, 0,
-                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_source_iface));
+                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_PLACE, seahorse_place_iface));
 
 static void 
 seahorse_ldap_source_init (SeahorseLDAPSource *self)
@@ -843,8 +843,10 @@ search_parse_key_from_ldap_entry (SeahorseLDAPSource *self,
 		list = g_list_prepend (NULL, subkey);
 		seahorse_pgp_key_set_subkeys (key, list);
 		seahorse_object_list_free (list);
-		g_object_set (key, "flags", flags, NULL);
-		g_object_set (key, "source", self, NULL);
+		g_object_set (key,
+		              "flags", flags,
+		              "place", self,
+		              NULL);
 
 		seahorse_pgp_key_realize (key);
 		gcr_simple_collection_add (results, G_OBJECT (key));
@@ -1143,19 +1145,19 @@ on_import_connect_completed (GObject *source,
 }
 
 static void
-seahorse_ldap_source_import_async (SeahorseSource *source,
+seahorse_ldap_source_import_async (SeahorsePlace *place,
                                    GInputStream *input,
                                    GCancellable *cancellable,
                                    GAsyncReadyCallback callback,
                                    gpointer user_data)
 {
-	SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (source);
+	SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (place);
 	source_import_closure *closure;
 	GSimpleAsyncResult *res;
 	gchar *keydata;
 	guint len;
 
-	res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+	res = g_simple_async_result_new (G_OBJECT (place), callback, user_data,
 	                                 seahorse_ldap_source_import_async);
 	closure = g_new0 (source_import_closure, 1);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
@@ -1185,11 +1187,11 @@ seahorse_ldap_source_import_async (SeahorseSource *source,
 }
 
 static GList *
-seahorse_ldap_source_import_finish (SeahorseSource *source,
+seahorse_ldap_source_import_finish (SeahorsePlace *place,
                                     GAsyncResult *result,
                                     GError **error)
 {
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (place),
 	                      seahorse_ldap_source_import_async), NULL);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
@@ -1428,7 +1430,7 @@ seahorse_ldap_source_export_finish (SeahorseServerSource *source,
 }
 
 static void 
-seahorse_source_iface (SeahorseSourceIface *iface)
+seahorse_place_iface (SeahorsePlaceIface *iface)
 {
 	iface->import_async = seahorse_ldap_source_import_async;
 	iface->import_finish = seahorse_ldap_source_import_finish;
@@ -1445,7 +1447,6 @@ seahorse_ldap_source_class_init (SeahorseLDAPSourceClass *klass)
 	server_class->export_async = seahorse_ldap_source_export_async;
 	server_class->export_finish = seahorse_ldap_source_export_finish;
 
-	seahorse_registry_register_type (NULL, SEAHORSE_TYPE_LDAP_SOURCE, "source", "remote", NULL);
 	seahorse_servers_register_type ("ldap", _("LDAP Key Server"), seahorse_ldap_is_valid_uri);
 }
 
diff --git a/pgp/seahorse-pgp-actions.c b/pgp/seahorse-pgp-actions.c
new file mode 100644
index 0000000..ad40639
--- /dev/null
+++ b/pgp/seahorse-pgp-actions.c
@@ -0,0 +1,329 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "seahorse-gpgme-dialogs.h"
+#include "seahorse-gpgme-key.h"
+#include "seahorse-gpgme-key-op.h"
+#include "seahorse-gpgme-uid.h"
+#include "seahorse-pgp-backend.h"
+#include "seahorse-pgp-actions.h"
+#include "seahorse-pgp-dialogs.h"
+#include "seahorse-keyserver-search.h"
+#include "seahorse-keyserver-sync.h"
+
+#include "seahorse-action.h"
+#include "seahorse-actions.h"
+#include "seahorse-object.h"
+#include "seahorse-registry.h"
+#include "seahorse-util.h"
+
+GType   seahorse_pgp_backend_actions_get_type         (void) G_GNUC_CONST;
+#define SEAHORSE_TYPE_PGP_BACKEND_ACTIONS             (seahorse_pgp_backend_actions_get_type ())
+#define SEAHORSE_PGP_BACKEND_ACTIONS(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PGP_BACKEND_ACTIONS, SeahorsePgpBackendActions))
+#define SEAHORSE_PGP_BACKEND_ACTIONS_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_PGP_BACKEND_ACTIONS, SeahorsePgpBackendActionsClass))
+#define SEAHORSE_IS_PGP_BACKEND_ACTIONS(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_PGP_BACKEND_ACTIONS))
+#define SEAHORSE_IS_PGP_BACKEND_ACTIONS_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_PGP_BACKEND_ACTIONS))
+#define SEAHORSE_PGP_BACKEND_ACTIONS_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_PGP_BACKEND_ACTIONS, SeahorsePgpBackendActionsClass))
+
+typedef struct {
+	SeahorseActions parent_instance;
+} SeahorsePgpBackendActions;
+
+typedef struct {
+	SeahorseActionsClass parent_class;
+} SeahorsePgpBackendActionsClass;
+
+G_DEFINE_TYPE (SeahorsePgpBackendActions, seahorse_pgp_backend_actions, SEAHORSE_TYPE_ACTIONS);
+
+static const gchar* BACKEND_DEFINITION = ""\
+"<ui>"\
+"	<menubar>"\
+"		<placeholder name='RemoteMenu'>"\
+"			<menu name='Remote' action='remote-menu'>"\
+"				<menuitem action='remote-find'/>"\
+"				<menuitem action='remote-sync'/>"\
+"			</menu>"\
+"		</placeholder>"\
+"	</menubar>"\
+"</ui>";
+
+static void
+on_remote_find (GtkAction* action,
+                gpointer user_data)
+{
+	seahorse_keyserver_search_show (seahorse_action_get_window (action));
+}
+
+static void
+on_remote_sync (GtkAction* action,
+                gpointer user_data)
+{
+	SeahorseGpgmeKeyring *keyring;
+	GList* objects;
+
+	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));
+	}
+
+	seahorse_keyserver_sync_show (objects, seahorse_action_get_window (action));
+	g_list_free (objects);
+}
+
+static const GtkActionEntry BACKEND_ACTIONS[] = {
+	{ "remote-find", GTK_STOCK_FIND, N_("_Find Remote Keys..."), "",
+	  N_("Search for keys on a key server"), G_CALLBACK (on_remote_find) },
+	{ "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) }
+};
+
+static void
+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);
+	seahorse_actions_register_definition (SEAHORSE_ACTIONS (self), BACKEND_DEFINITION);
+}
+
+static void
+seahorse_pgp_backend_actions_class_init (SeahorsePgpBackendActionsClass *klass)
+{
+
+}
+
+GtkActionGroup *
+seahorse_pgp_backend_actions_instance (void)
+{
+	static GtkActionGroup *actions = NULL;
+
+	if (actions == NULL) {
+		actions = g_object_new (SEAHORSE_TYPE_PGP_BACKEND_ACTIONS,
+		                        "name", "pgp-backend",
+		                        NULL);
+		g_object_add_weak_pointer (G_OBJECT (actions),
+		                           (gpointer *)&actions);
+	} else {
+		g_object_ref (actions);
+	}
+
+	return actions;
+}
+
+GType   seahorse_gpgme_key_actions_get_type       (void) G_GNUC_CONST;
+#define SEAHORSE_TYPE_GPGME_KEY_ACTIONS           (seahorse_gpgme_key_actions_get_type ())
+#define seahorse_gpgme_key_actions(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PGP_ACTIONS, SeahorseGpgmeKeyActions))
+#define seahorse_gpgme_key_actions_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_PGP_ACTIONS, SeahorseGpgmeKeyActionsClass))
+#define SEAHORSE_IS_PGP_ACTIONS(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_PGP_ACTIONS))
+#define SEAHORSE_IS_PGP_ACTIONS_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_PGP_ACTIONS))
+#define seahorse_gpgme_key_actions_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_PGP_ACTIONS, SeahorseGpgmeKeyActionsClass))
+
+typedef struct {
+	SeahorseActions parent_instance;
+} SeahorseGpgmeKeyActions;
+
+typedef struct {
+	SeahorseActionsClass parent_class;
+} SeahorseGpgmeKeyActionsClass;
+
+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;
+	GObject *key;
+
+	key = seahorse_action_get_object (action);
+	window = seahorse_action_get_window (action);
+
+	seahorse_gpgme_sign_prompt (SEAHORSE_GPGME_KEY (key), window);
+}
+
+static void
+on_show_properties (GtkAction *action,
+                    gpointer user_data)
+{
+	seahorse_pgp_key_properties_show (seahorse_action_get_object (action),
+	                                  seahorse_action_get_window (action));
+}
+
+static void
+on_delete_objects (GtkAction *action,
+                   gpointer user_data)
+{
+	guint num;
+	gint num_keys;
+	gint num_identities;
+	char* message;
+	SeahorseObject *obj;
+	GList* to_delete, *l;
+	GtkWidget *parent;
+	gpgme_error_t gerr;
+	guint length;
+	GError *error = NULL;
+	GList *objects;
+
+	objects = seahorse_action_get_objects (action);
+	num = g_list_length (objects);
+	if (num == 0)
+		return;
+
+	num_keys = 0;
+	num_identities = 0;
+	message = NULL;
+
+	/*
+	 * Go through and validate all what we have to delete,
+	 * removing UIDs where the parent Key is also on the
+	 * chopping block.
+	 */
+	to_delete = NULL;
+
+	for (l = objects; l; l = g_list_next (l)) {
+		obj = SEAHORSE_OBJECT (l->data);
+		if (SEAHORSE_IS_PGP_UID (obj)) {
+			if (g_list_find (objects, seahorse_pgp_uid_get_parent (SEAHORSE_PGP_UID (obj))) == NULL) {
+				to_delete = g_list_prepend (to_delete, obj);
+				++num_identities;
+			}
+		} else if (G_OBJECT_TYPE (obj) == SEAHORSE_TYPE_GPGME_KEY) {
+			to_delete = g_list_prepend (to_delete, obj);
+			++num_keys;
+		}
+	}
+
+	/* Figure out a good prompt message */
+	length = g_list_length (to_delete);
+	switch (length) {
+	case 0:
+		return;
+	case 1:
+		message = g_strdup_printf (_ ("Are you sure you want to permanently delete %s?"),
+		                           seahorse_object_get_label (to_delete->data));
+		break;
+	default:
+		if (num_keys > 0 && num_identities > 0) {
+			message = g_strdup_printf (_("Are you sure you want to permanently delete %d keys and identities?"), length);
+		} else if (num_keys > 0) {
+			message = g_strdup_printf (_("Are you sure you want to permanently delete %d keys?"), length);
+		} else if (num_identities > 0){
+			message = g_strdup_printf (_("Are you sure you want to permanently delete %d identities?"), length);
+		} else {
+			g_assert_not_reached ();
+		}
+		break;
+	}
+
+	parent = GTK_WIDGET (seahorse_action_get_window (action));
+	if (!seahorse_util_prompt_delete (message, parent)) {
+		g_free (message);
+		return;
+	}
+
+	gerr = 0;
+	for (l = objects; l; l = g_list_next (l)) {
+		obj = SEAHORSE_OBJECT (l->data);
+		if (SEAHORSE_IS_GPGME_UID (obj)) {
+			gerr = seahorse_gpgme_key_op_del_uid (SEAHORSE_GPGME_UID (obj));
+			message = _("Couldn't delete user ID");
+		} else if (SEAHORSE_IS_GPGME_KEY (obj)) {
+			if (seahorse_object_get_usage (obj) == SEAHORSE_USAGE_PRIVATE_KEY) {
+				gerr = seahorse_gpgme_key_op_delete_pair (SEAHORSE_GPGME_KEY (obj));
+				message = _("Couldn't delete private key");
+			} else {
+				gerr = seahorse_gpgme_key_op_delete (SEAHORSE_GPGME_KEY (obj));
+				message = _("Couldn't delete public key");
+			}
+		}
+
+		if (seahorse_gpgme_propagate_error (gerr, &error)) {
+			seahorse_util_handle_error (&error, parent, "%s", message);
+			return;
+		}
+	}
+}
+
+static const GtkActionEntry KEY_ACTIONS[] = {
+	{ "key-sign", GTK_STOCK_INDEX, N_("_Sign Key..."), "",
+	  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) },
+	{ "delete", GTK_STOCK_DELETE, NULL, NULL,
+	  N_("Delete the key."), G_CALLBACK (on_delete_objects) },
+};
+
+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), self);
+	seahorse_actions_register_definition (SEAHORSE_ACTIONS (self), KEY_DEFINITION);
+
+}
+
+static void
+seahorse_gpgme_key_actions_class_init (SeahorseGpgmeKeyActionsClass *klass)
+{
+
+}
+
+GtkActionGroup *
+seahorse_gpgme_key_actions_instance (void)
+{
+	static GtkActionGroup *actions = NULL;
+
+	if (actions == NULL) {
+		actions = g_object_new (SEAHORSE_TYPE_GPGME_KEY_ACTIONS,
+		                        "name", "gpgme-key",
+		                        NULL);
+		g_object_add_weak_pointer (G_OBJECT (actions),
+		                           (gpointer *)&actions);
+	} else {
+		g_object_ref (actions);
+	}
+
+	return actions;
+}
diff --git a/pgp/seahorse-pgp-actions.h b/pgp/seahorse-pgp-actions.h
new file mode 100644
index 0000000..412d2bb
--- /dev/null
+++ b/pgp/seahorse-pgp-actions.h
@@ -0,0 +1,32 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __SEAHORSE_PGP_ACTIONS_H__
+#define __SEAHORSE_PGP_ACTIONS_H__
+
+#include <gtk/gtk.h>
+
+GtkActionGroup *      seahorse_pgp_backend_actions_instance    (void);
+
+GtkActionGroup *      seahorse_gpgme_key_actions_instance      (void);
+
+#endif
diff --git a/pgp/seahorse-pgp-backend.c b/pgp/seahorse-pgp-backend.c
index e15d219..29d06ee 100644
--- a/pgp/seahorse-pgp-backend.c
+++ b/pgp/seahorse-pgp-backend.c
@@ -22,8 +22,8 @@
 #include "config.h"
 
 #include "seahorse-gpgme-dialogs.h"
+#include "seahorse-pgp-actions.h"
 #include "seahorse-pgp-backend.h"
-#include "seahorse-pgp-commands.h"
 #include "seahorse-server-source.h"
 #include "seahorse-transfer.h"
 #include "seahorse-unknown-source.h"
@@ -44,7 +44,8 @@ enum {
 	PROP_0,
 	PROP_NAME,
 	PROP_LABEL,
-	PROP_DESCRIPTION
+	PROP_DESCRIPTION,
+	PROP_ACTIONS
 };
 
 static SeahorsePgpBackend *pgp_backend = NULL;
@@ -55,6 +56,7 @@ struct _SeahorsePgpBackend {
 	SeahorseDiscovery *discovery;
 	SeahorseUnknownSource *unknown;
 	GHashTable *remotes;
+	GtkActionGroup *actions;
 };
 
 struct _SeahorsePgpBackendClass {
@@ -79,8 +81,7 @@ seahorse_pgp_backend_init (SeahorsePgpBackend *self)
 	self->remotes = g_hash_table_new_full (g_str_hash, g_str_equal,
 	                                       g_free, g_object_unref);
 
-	/* Let these classes register themselves, when the backend is created */
-	g_type_class_unref (g_type_class_ref (SEAHORSE_TYPE_PGP_COMMANDS));
+	self->actions = seahorse_pgp_backend_actions_instance ();
 
 	seahorse_gpgme_generate_register ();
 }
@@ -163,6 +164,8 @@ seahorse_pgp_backend_get_property (GObject *obj,
                                    GValue *value,
                                    GParamSpec *pspec)
 {
+	SeahorsePgpBackend *self = SEAHORSE_PGP_BACKEND (obj);
+
 	switch (prop_id) {
 	case PROP_NAME:
 		g_value_set_string (value, SEAHORSE_PGP_NAME);
@@ -173,6 +176,9 @@ seahorse_pgp_backend_get_property (GObject *obj,
 	case PROP_DESCRIPTION:
 		g_value_set_string (value, _("PGP keys are for encrypting email or files"));
 		break;
+	case PROP_ACTIONS:
+		g_value_set_object (value, self->actions);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -193,6 +199,7 @@ seahorse_pgp_backend_finalize (GObject *obj)
 	g_clear_object (&self->discovery);
 	g_clear_object (&self->unknown);
 	g_hash_table_destroy (self->remotes);
+	g_clear_object (&self->actions);
 	pgp_backend = NULL;
 
 	G_OBJECT_CLASS (seahorse_pgp_backend_parent_class)->finalize (obj);
@@ -210,6 +217,7 @@ seahorse_pgp_backend_class_init (SeahorsePgpBackendClass *klass)
 	g_object_class_override_property (gobject_class, PROP_NAME, "name");
 	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
 	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
+	g_object_class_override_property (gobject_class, PROP_ACTIONS, "actions");
 }
 
 static guint
@@ -508,7 +516,7 @@ on_source_transfer_ready (GObject *source,
 void
 seahorse_pgp_backend_transfer_async (SeahorsePgpBackend *self,
                                      GList *keys,
-                                     SeahorseSource *to,
+                                     SeahorsePlace *to,
                                      GCancellable *cancellable,
                                      GAsyncReadyCallback callback,
                                      gpointer user_data)
@@ -516,12 +524,12 @@ seahorse_pgp_backend_transfer_async (SeahorsePgpBackend *self,
 	transfer_closure *closure;
 	SeahorseObject *object;
 	GSimpleAsyncResult *res;
-	SeahorseSource *from;
+	SeahorsePlace *from;
 	GList *next;
 
 	self = self ? self : seahorse_pgp_backend_get ();
 	g_return_if_fail (SEAHORSE_IS_PGP_BACKEND (self));
-	g_return_if_fail (SEAHORSE_IS_SOURCE (to));
+	g_return_if_fail (SEAHORSE_IS_PLACE (to));
 
 	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
 	                                 seahorse_pgp_backend_transfer_async);
@@ -533,23 +541,23 @@ seahorse_pgp_backend_transfer_async (SeahorsePgpBackend *self,
 
 	keys = g_list_copy (keys);
 
-	/* Sort by key source */
-	keys = seahorse_util_objects_sort (keys);
+	/* Sort by key plage */
+	keys = seahorse_util_objects_sort_by_place (keys);
 
 	while (keys) {
 
 		/* break off one set (same keysource) */
-		next = seahorse_util_objects_splice (keys);
+		next = seahorse_util_objects_splice_by_place (keys);
 
 		g_assert (SEAHORSE_IS_OBJECT (keys->data));
 		object = SEAHORSE_OBJECT (keys->data);
 
-		/* Export from this key source */
-		from = seahorse_object_get_source (object);
+		/* Export from this key place */
+		from = seahorse_object_get_place (object);
 		g_return_if_fail (from != NULL);
 
 		if (from != to) {
-			/* Start a new transfer operation between the two sources */
+			/* Start a new transfer operation between the two places */
 			seahorse_progress_prep_and_begin (cancellable, GINT_TO_POINTER (closure->num_transfers), NULL);
 			seahorse_transfer_async (from, to, keys, cancellable,
 			                         on_source_transfer_ready, g_object_ref (res));
@@ -589,19 +597,19 @@ seahorse_pgp_backend_transfer_finish (SeahorsePgpBackend *self,
 void
 seahorse_pgp_backend_retrieve_async (SeahorsePgpBackend *self,
                                      GList *keyids,
-                                     SeahorseSource *to,
+                                     SeahorsePlace *to,
                                      GCancellable *cancellable,
                                      GAsyncReadyCallback callback,
                                      gpointer user_data)
 {
 	transfer_closure *closure;
 	GSimpleAsyncResult *res;
-	SeahorseSource *source;
+	SeahorsePlace *place;
 	GHashTableIter iter;
 
 	self = self ? self : seahorse_pgp_backend_get ();
 	g_return_if_fail (SEAHORSE_IS_PGP_BACKEND (self));
-	g_return_if_fail (SEAHORSE_IS_SOURCE (to));
+	g_return_if_fail (SEAHORSE_IS_PLACE (to));
 
 	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
 	                                 seahorse_pgp_backend_retrieve_async);
@@ -612,10 +620,10 @@ seahorse_pgp_backend_retrieve_async (SeahorsePgpBackend *self,
 		closure->cancellable = g_object_ref (cancellable);
 
 	g_hash_table_iter_init (&iter, self->remotes);
-	while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&source)) {
-		/* Start a new transfer operation between the two key sources */
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&place)) {
+		/* Start a new transfer operation between the two places */
 		seahorse_progress_prep_and_begin (cancellable, GINT_TO_POINTER (closure->num_transfers), NULL);
-		seahorse_transfer_async (source, to, keyids, cancellable,
+		seahorse_transfer_async (place, to, keyids, cancellable,
 		                         on_source_transfer_ready, g_object_ref (res));
 		closure->num_transfers++;
 	}
@@ -681,7 +689,7 @@ seahorse_pgp_backend_discover_keys (SeahorsePgpBackend *self,
 	/* Start a discover process on all todiscover */
 	if (todiscover != NULL &&
 	    g_settings_get_boolean (seahorse_context_settings (NULL), "server-auto-retrieve")) {
-		seahorse_pgp_backend_retrieve_async (self, todiscover, SEAHORSE_SOURCE (self->keyring),
+		seahorse_pgp_backend_retrieve_async (self, todiscover, SEAHORSE_PLACE (self->keyring),
 		                                     cancellable, NULL, NULL);
 	}
 
diff --git a/pgp/seahorse-pgp-backend.h b/pgp/seahorse-pgp-backend.h
index aea88fa..51afc81 100644
--- a/pgp/seahorse-pgp-backend.h
+++ b/pgp/seahorse-pgp-backend.h
@@ -80,7 +80,7 @@ gboolean               seahorse_pgp_backend_search_remote_finish (SeahorsePgpBac
 
 void                   seahorse_pgp_backend_transfer_async       (SeahorsePgpBackend *self,
                                                                   GList *keys,
-                                                                  SeahorseSource *to,
+                                                                  SeahorsePlace *to,
                                                                   GCancellable *cancellable,
                                                                   GAsyncReadyCallback callback,
                                                                   gpointer user_data);
@@ -91,7 +91,7 @@ gboolean               seahorse_pgp_backend_transfer_finish      (SeahorsePgpBac
 
 void                   seahorse_pgp_backend_retrieve_async       (SeahorsePgpBackend *self,
                                                                   GList *keyids,
-                                                                  SeahorseSource *to,
+                                                                  SeahorsePlace *to,
                                                                   GCancellable *cancellable,
                                                                   GAsyncReadyCallback callback,
                                                                   gpointer user_data);
diff --git a/pgp/seahorse-pgp-key.c b/pgp/seahorse-pgp-key.c
index 92b7c21..502efa2 100644
--- a/pgp/seahorse-pgp-key.c
+++ b/pgp/seahorse-pgp-key.c
@@ -26,7 +26,6 @@
 
 #include "seahorse-icons.h"
 #include "seahorse-object-list.h"
-#include "seahorse-source.h"
 #include "seahorse-util.h"
 
 #include "pgp/seahorse-pgp.h"
diff --git a/pgp/seahorse-server-source.c b/pgp/seahorse-server-source.c
index 387c10c..39d881e 100644
--- a/pgp/seahorse-server-source.c
+++ b/pgp/seahorse-server-source.c
@@ -48,7 +48,8 @@ enum {
     PROP_DESCRIPTION,
     PROP_ICON,
     PROP_KEY_SERVER,
-    PROP_URI
+    PROP_URI,
+    PROP_ACTIONS
 };
 
 /* -----------------------------------------------------------------------------
@@ -97,6 +98,9 @@ seahorse_server_source_class_init (SeahorseServerSourceClass *klass)
             g_param_spec_string ("description", "Description", "Description", "", G_PARAM_READABLE));
     g_object_class_install_property (gobject_class, PROP_ICON,
             g_param_spec_object ("icon", "icon", "Icon", G_TYPE_ICON, G_PARAM_READABLE));
+    g_object_class_install_property (gobject_class, PROP_ACTIONS,
+            g_param_spec_object ("actions", "actions", "Actions",
+                                 GTK_TYPE_ACTION_GROUP, G_PARAM_READABLE));
 
     g_object_class_install_property (gobject_class, PROP_KEY_SERVER,
             g_param_spec_string ("key-server", "Key Server",
@@ -206,6 +210,9 @@ seahorse_server_get_property (GObject *obj,
 	case PROP_ICON:
 		g_value_take_object (value, g_themed_icon_new (GTK_STOCK_DIALOG_QUESTION));
 		break;
+	case PROP_ACTIONS:
+		g_value_set_object (value, NULL);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
diff --git a/pgp/seahorse-transfer.c b/pgp/seahorse-transfer.c
index 7209a13..82afbd9 100644
--- a/pgp/seahorse-transfer.c
+++ b/pgp/seahorse-transfer.c
@@ -38,8 +38,8 @@
 
 typedef struct {
 	GCancellable *cancellable;
-	SeahorseSource *from;
-	SeahorseSource *to;
+	SeahorsePlace *from;
+	SeahorsePlace *to;
 	GOutputStream *output;
 	GList *keys;
 } transfer_closure;
@@ -69,7 +69,7 @@ on_source_import_ready (GObject *object,
 	seahorse_debug ("[transfer] import done");
 	seahorse_progress_end (closure->cancellable, &closure->to);
 
-	if (seahorse_source_import_finish (closure->to, result, &error))
+	if (seahorse_place_import_finish (closure->to, result, &error))
 		g_cancellable_set_error_if_cancelled (closure->cancellable, &error);
 
 	if (error != NULL)
@@ -99,7 +99,7 @@ on_source_export_ready (GObject *object,
 		                                      result, &error);
 
 	} else {
-		seahorse_source_export_finish (closure->from, result, &error);
+		seahorse_place_export_finish (closure->from, result, &error);
 	}
 
 	if (error == NULL)
@@ -121,8 +121,8 @@ on_source_export_ready (GObject *object,
 			                                             stream_size, g_free);
 
 			seahorse_debug ("[transfer] starting import");
-			seahorse_source_import_async (closure->to, input, closure->cancellable,
-			                              on_source_import_ready, g_object_ref (res));
+			seahorse_place_import_async (closure->to, input, closure->cancellable,
+			                             on_source_import_ready, g_object_ref (res));
 			g_object_unref (input);
 		}
 
@@ -142,7 +142,7 @@ on_timeout_start_transfer (gpointer user_data)
 	transfer_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GList *keyids, *l;
 
-	g_assert (SEAHORSE_IS_SOURCE (closure->from));
+	g_assert (SEAHORSE_IS_PLACE (closure->from));
 	g_assert (closure->keys);
 
 	seahorse_progress_begin (closure->cancellable, &closure->from);
@@ -156,17 +156,17 @@ on_timeout_start_transfer (gpointer user_data)
 		                                     on_source_export_ready, g_object_ref (res));
 		g_list_free (keyids);
 	} else {
-		seahorse_source_export_async (closure->from, closure->keys, closure->output,
-		                              closure->cancellable, on_source_export_ready,
-		                              g_object_ref (res));
+		seahorse_place_export_async (closure->from, closure->keys, closure->output,
+		                             closure->cancellable, on_source_export_ready,
+		                             g_object_ref (res));
 	}
 
 	return FALSE; /* Don't run again */
 }
 
 void
-seahorse_transfer_async (SeahorseSource *from,
-                         SeahorseSource *to,
+seahorse_transfer_async (SeahorsePlace *from,
+                         SeahorsePlace *to,
                          GList *keys,
                          GCancellable *cancellable,
                          GAsyncReadyCallback callback,
@@ -175,8 +175,8 @@ seahorse_transfer_async (SeahorseSource *from,
 	GSimpleAsyncResult *res;
 	transfer_closure *closure = NULL;
 
-	g_return_if_fail (SEAHORSE_SOURCE (from));
-	g_return_if_fail (SEAHORSE_SOURCE (to));
+	g_return_if_fail (SEAHORSE_PLACE (from));
+	g_return_if_fail (SEAHORSE_PLACE (to));
 
 	res = g_simple_async_result_new (NULL, callback, user_data,
 	                                 seahorse_transfer_async);
diff --git a/pgp/seahorse-transfer.h b/pgp/seahorse-transfer.h
index f4b67a5..671e415 100644
--- a/pgp/seahorse-transfer.h
+++ b/pgp/seahorse-transfer.h
@@ -23,12 +23,12 @@
 #ifndef __SEAHORSE_TRANSFER_H__
 #define __SEAHORSE_TRANSFER_H__
 
-#include "seahorse-source.h"
+#include "seahorse-place.h"
 
 #include "seahorse-server-source.h"
 
-void            seahorse_transfer_async         (SeahorseSource *from,
-                                                 SeahorseSource *to,
+void            seahorse_transfer_async         (SeahorsePlace *from,
+                                                 SeahorsePlace *to,
                                                  GList *keys,
                                                  GCancellable *cancellable,
                                                  GAsyncReadyCallback callback,
diff --git a/pgp/seahorse-unknown-source.h b/pgp/seahorse-unknown-source.h
index 239afe4..3c3b312 100644
--- a/pgp/seahorse-unknown-source.h
+++ b/pgp/seahorse-unknown-source.h
@@ -24,7 +24,6 @@
 #define __SEAHORSE_UNKNOWN_SOURCE_H__
 
 #include "seahorse-object.h"
-#include "seahorse-source.h"
 
 #define SEAHORSE_TYPE_UNKNOWN_SOURCE            (seahorse_unknown_source_get_type ())
 #define SEAHORSE_UNKNOWN_SOURCE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_UNKNOWN_SOURCE, SeahorseUnknownSource))
diff --git a/pgp/seahorse-unknown.c b/pgp/seahorse-unknown.c
index ecd9dd0..acca37a 100644
--- a/pgp/seahorse-unknown.c
+++ b/pgp/seahorse-unknown.c
@@ -62,7 +62,7 @@ seahorse_unknown_new (SeahorseUnknownSource *source,
 	identifier = seahorse_pgp_key_calc_identifier (keyid);
 
 	return g_object_new (SEAHORSE_TYPE_UNKNOWN,
-	                     "source", source,
+	                     "place", source,
 	                     "label", display,
 	                     "identifier", identifier,
 	                     NULL);
diff --git a/pkcs11/Makefile.am b/pkcs11/Makefile.am
index 4d4857a..c37f4f9 100644
--- a/pkcs11/Makefile.am
+++ b/pkcs11/Makefile.am
@@ -16,9 +16,9 @@ noinst_LTLIBRARIES = libseahorse-pkcs11.la
 
 libseahorse_pkcs11_la_SOURCES = \
 	seahorse-certificate.c seahorse-certificate.h \
+	seahorse-pkcs11-actions.c seahorse-pkcs11-actions.h \
 	seahorse-pkcs11-backend.c seahorse-pkcs11-backend.h \
 	seahorse-pkcs11-certificate-props.c seahorse-pkcs11-certificate-props.h \
-	seahorse-pkcs11-commands.c seahorse-pkcs11-commands.h \
 	seahorse-pkcs11-helpers.c seahorse-pkcs11-helpers.h \
 	seahorse-pkcs11-operations.c seahorse-pkcs11-operations.h \
 	seahorse-pkcs11.c seahorse-pkcs11.h \
diff --git a/pkcs11/seahorse-certificate.c b/pkcs11/seahorse-certificate.c
index db151bb..f0a7883 100644
--- a/pkcs11/seahorse-certificate.c
+++ b/pkcs11/seahorse-certificate.c
@@ -23,8 +23,9 @@
 #include "config.h"
 
 #include "seahorse-certificate.h"
-#include "seahorse-pkcs11-helpers.h"
 #include "seahorse-pkcs11.h"
+#include "seahorse-pkcs11-actions.h"
+#include "seahorse-pkcs11-helpers.h"
 #include "seahorse-token.h"
 #include "seahorse-types.h"
 
@@ -45,15 +46,17 @@ static const gulong REQUIRED_ATTRS[] = {
 
 enum {
 	PROP_0,
-	PROP_SOURCE,
+	PROP_PLACE,
 	PROP_ATTRIBUTES,
 	PROP_FLAGS,
+	PROP_ACTIONS
 };
 
 struct _SeahorseCertificatePrivate {
 	SeahorseToken *token;
 	GckAttributes *attributes;
 	GckAttribute der_value;
+	GtkActionGroup *actions;
 };
 
 static void seahorse_certificate_certificate_iface (GcrCertificateIface *iface);
@@ -69,6 +72,7 @@ static void
 seahorse_certificate_init (SeahorseCertificate *self)
 {
 	self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_CERTIFICATE, SeahorseCertificatePrivate));
+	self->pv->actions = seahorse_pkcs11_actions_instance ();
 	gck_attribute_init_invalid (&self->pv->der_value, CKA_VALUE);
 }
 
@@ -90,6 +94,8 @@ 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);
 	gck_attribute_clear (&self->pv->der_value);
@@ -106,7 +112,7 @@ seahorse_certificate_get_property (GObject *obj,
 	SeahorseCertificate *self = SEAHORSE_CERTIFICATE (obj);
 
 	switch (prop_id) {
-	case PROP_SOURCE:
+	case PROP_PLACE:
 		g_value_set_object (value, self->pv->token);
 		break;
 	case PROP_ATTRIBUTES:
@@ -116,6 +122,9 @@ seahorse_certificate_get_property (GObject *obj,
 		g_value_set_flags (value, SEAHORSE_FLAG_PERSONAL |
 		                          SEAHORSE_FLAG_EXPORTABLE);
 		break;
+	case PROP_ACTIONS:
+		g_value_set_object (value, self->pv->actions);
+		break;
 	default:
 		gcr_certificate_mixin_get_property (obj, prop_id, value, pspec);
 		break;
@@ -132,7 +141,7 @@ seahorse_certificate_set_property (GObject *obj,
 	GckAttribute *der_value = NULL;
 
 	switch (prop_id) {
-	case PROP_SOURCE:
+	case PROP_PLACE:
 		g_return_if_fail (self->pv->token == NULL);
 		self->pv->token = g_value_dup_object (value);
 		break;
@@ -166,14 +175,18 @@ seahorse_certificate_class_init (SeahorseCertificateClass *klass)
 	gobject_class->get_property = seahorse_certificate_get_property;
 	gobject_class->notify = seahorse_certificate_notify;
 
-	g_object_class_install_property (gobject_class, PROP_SOURCE,
-	         g_param_spec_object ("source", "source", "source", SEAHORSE_TYPE_TOKEN,
+	g_object_class_install_property (gobject_class, PROP_PLACE,
+	         g_param_spec_object ("place", "place", "place", SEAHORSE_TYPE_TOKEN,
 	                              G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
 
 	g_object_class_install_property (gobject_class, PROP_FLAGS,
 	         g_param_spec_flags ("flags", "flags", "flags", SEAHORSE_TYPE_FLAGS, SEAHORSE_FLAG_NONE,
 	                              G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
 
+	g_object_class_install_property (gobject_class, PROP_ACTIONS,
+	         g_param_spec_object ("actions", "Actions", "Actions", GTK_TYPE_ACTION_GROUP,
+	                              G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
+
 	g_object_class_override_property (gobject_class, PROP_ATTRIBUTES, "attributes");
 
 	gcr_certificate_mixin_class_init (gobject_class);
diff --git a/pkcs11/seahorse-pkcs11-actions.c b/pkcs11/seahorse-pkcs11-actions.c
new file mode 100644
index 0000000..2b4919f
--- /dev/null
+++ b/pkcs11/seahorse-pkcs11-actions.c
@@ -0,0 +1,182 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "seahorse-pkcs11-actions.h"
+
+#include "seahorse-certificate.h"
+#include "seahorse-pkcs11.h"
+#include "seahorse-pkcs11-certificate-props.h"
+#include "seahorse-pkcs11-operations.h"
+
+#include "seahorse-action.h"
+#include "seahorse-actions.h"
+#include "seahorse-progress.h"
+#include "seahorse-registry.h"
+#include "seahorse-util.h"
+
+GType   seahorse_pkcs11_actions_get_type           (void) G_GNUC_CONST;
+#define SEAHORSE_TYPE_PKCS11_ACTIONS               (seahorse_pkcs11_actions_get_type ())
+#define SEAHORSE_PKCS11_ACTIONS(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PKCS11_ACTIONS, SeahorsePkcs11Actions))
+#define SEAHORSE_PKCS11_ACTIONS_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_PKCS11_ACTIONS, SeahorsePkcs11ActionsClass))
+#define SEAHORSE_PKCS11_IS_ACTIONS(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_PKCS11_ACTIONS))
+#define SEAHORSE_PKCS11_IS_ACTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_PKCS11_ACTIONS))
+#define SEAHORSE_PKCS11_ACTIONS_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_PKCS11_ACTIONS, SeahorsePkcs11ActionsClass))
+
+typedef struct {
+	SeahorseActions parent;
+} SeahorsePkcs11Actions;
+
+typedef struct {
+	SeahorseActionsClass parent_class;
+} SeahorsePkcs11ActionsClass;
+
+static GQuark QUARK_WINDOW = 0;
+
+G_DEFINE_TYPE (SeahorsePkcs11Actions, seahorse_pkcs11_actions, SEAHORSE_TYPE_ACTIONS);
+
+static void
+properties_response (GtkDialog *dialog, gint response_id, gpointer user_data)
+{
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+on_show_properties (GtkAction *action,
+                    gpointer user_data)
+{
+	GtkWindow *window;
+	gpointer previous;
+	GObject *object;
+
+	object = seahorse_action_get_object (action);
+
+	/* Try to show an already present window */
+	previous = g_object_get_qdata (G_OBJECT (object), QUARK_WINDOW);
+	if (GTK_IS_WINDOW (previous)) {
+		window = GTK_WINDOW (previous);
+		if (gtk_widget_get_visible (GTK_WIDGET (window))) {
+			gtk_window_present (window);
+			return;
+		}
+	}
+
+	/* Create a new dialog for the certificate */
+	window = GTK_WINDOW (seahorse_pkcs11_certificate_props_new (GCR_CERTIFICATE (object)));
+	gtk_window_set_transient_for (window, seahorse_action_get_window (action));
+	g_object_set_qdata (G_OBJECT (object), QUARK_WINDOW, window);
+	gtk_widget_show (GTK_WIDGET (window));
+
+	/* Close the window when we get a response */
+	g_signal_connect (window, "response", G_CALLBACK (properties_response), NULL);
+}
+
+static void
+on_delete_completed (GObject *source,
+                     GAsyncResult *result,
+                     gpointer user_data)
+{
+	GtkWindow *parent = GTK_WINDOW (user_data);
+	GError *error = NULL;
+
+	if (!seahorse_pkcs11_delete_finish (result, &error))
+		seahorse_util_handle_error (&error, parent, _("Couldn't delete"));
+
+	g_object_unref (parent);
+}
+
+static void
+on_delete_objects (GtkAction *action,
+                   gpointer user_data)
+{
+	GCancellable *cancellable;
+	gchar *prompt;
+	const gchar *display;
+	GtkWidget *parent;
+	gboolean ret;
+	guint num;
+	GList *objects;
+
+	objects = seahorse_action_get_objects (action);
+	num = g_list_length (objects);
+	if (num == 1) {
+		display = seahorse_object_get_label (SEAHORSE_OBJECT (objects->data));
+		prompt = g_strdup_printf (_("Are you sure you want to delete the certificate '%s'?"), display);
+	} else {
+		prompt = g_strdup_printf (ngettext (
+				"Are you sure you want to delete %d certificate?",
+				"Are you sure you want to delete %d certificates?",
+				num), num);
+	}
+
+	parent = GTK_WIDGET (seahorse_action_get_window (action));
+	ret = seahorse_util_prompt_delete (prompt, parent);
+	g_free (prompt);
+
+	if (ret) {
+		cancellable = g_cancellable_new ();
+		seahorse_pkcs11_delete_async (objects, cancellable,
+		                              on_delete_completed, g_object_ref (parent));
+		seahorse_progress_show (cancellable, _("Deleting"), TRUE);
+		g_object_unref (cancellable);
+	}
+}
+
+static const GtkActionEntry CERTIFICATE_ACTIONS[] = {
+	{ "properties", GTK_STOCK_PROPERTIES, NULL, NULL,
+	  N_("Properties of the certificate."), G_CALLBACK (on_show_properties) },
+	{ "delete", GTK_STOCK_DELETE, NULL, NULL,
+	  N_("Delete the certificate."), G_CALLBACK (on_delete_objects) },
+};
+
+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 void
+seahorse_pkcs11_actions_class_init (SeahorsePkcs11ActionsClass *klass)
+{
+	QUARK_WINDOW = g_quark_from_static_string ("seahorse-pkcs11-actions-window");
+}
+
+GtkActionGroup *
+seahorse_pkcs11_actions_instance (void)
+{
+	static GtkActionGroup *actions = NULL;
+
+	if (actions == NULL) {
+		actions = g_object_new (SEAHORSE_TYPE_PKCS11_ACTIONS,
+		                        "name", "pkcs11-certificate",
+		                        NULL);
+		g_object_add_weak_pointer (G_OBJECT (actions),
+		                           (gpointer *)&actions);
+	} else {
+		g_object_ref (actions);
+	}
+
+	return actions;
+}
diff --git a/pkcs11/seahorse-pkcs11-actions.h b/pkcs11/seahorse-pkcs11-actions.h
new file mode 100644
index 0000000..fd50dc3
--- /dev/null
+++ b/pkcs11/seahorse-pkcs11-actions.h
@@ -0,0 +1,29 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __SEAHORSE_PKCS11_ACTIONS_H__
+#define __SEAHORSE_PKCS11_ACTIONS_H__
+
+#include <gtk/gtk.h>
+
+GtkActionGroup *      seahorse_pkcs11_actions_instance            (void);
+
+#endif /* __SEAHORSE_PKCS11_ACTIONS_H__ */
diff --git a/pkcs11/seahorse-pkcs11-backend.c b/pkcs11/seahorse-pkcs11-backend.c
index 93c84c9..273de7f 100644
--- a/pkcs11/seahorse-pkcs11-backend.c
+++ b/pkcs11/seahorse-pkcs11-backend.c
@@ -22,10 +22,10 @@
 #include "config.h"
 
 #include "seahorse-pkcs11-backend.h"
-#include "seahorse-pkcs11-commands.h"
 #include "seahorse-token.h"
 
 #include "seahorse-backend.h"
+#include "seahorse-place.h"
 #include "seahorse-registry.h"
 #include "seahorse-util.h"
 
@@ -37,7 +37,8 @@ enum {
 	PROP_0,
 	PROP_NAME,
 	PROP_LABEL,
-	PROP_DESCRIPTION
+	PROP_DESCRIPTION,
+	PROP_ACTIONS
 };
 
 static SeahorsePkcs11Backend *pkcs11_backend = NULL;
@@ -77,9 +78,6 @@ seahorse_pkcs11_backend_init (SeahorsePkcs11Backend *self)
 	g_return_if_fail (pkcs11_backend == NULL);
 	pkcs11_backend = self;
 
-	/* Let these classes register themselves, when the backend is created */
-	g_type_class_unref (g_type_class_ref (SEAHORSE_PKCS11_TYPE_COMMANDS));
-
 	for (i = 0; token_blacklist[i] != NULL; i++) {
 		uri = gck_uri_parse (token_blacklist[i], GCK_URI_FOR_TOKEN | GCK_URI_FOR_MODULE, &error);
 		if (uri == NULL) {
@@ -126,7 +124,7 @@ on_initialized_registered (GObject *unused,
                            gpointer user_data)
 {
 	SeahorsePkcs11Backend *self = SEAHORSE_PKCS11_BACKEND (user_data);
-	SeahorseSource *source;
+	SeahorsePlace *place;
 	GList *slots, *s;
 	GList *modules, *m;
 	GError *error = NULL;
@@ -145,9 +143,9 @@ on_initialized_registered (GObject *unused,
 			if (token == NULL)
 				continue;
 			if (is_token_usable (self, s->data, token)) {
-				source = SEAHORSE_SOURCE (seahorse_token_new (s->data));
-				self->slots = g_list_append (self->slots, source);
-				gcr_collection_emit_added (GCR_COLLECTION (self), G_OBJECT (source));
+				place = SEAHORSE_PLACE (seahorse_token_new (s->data));
+				self->slots = g_list_append (self->slots, place);
+				gcr_collection_emit_added (GCR_COLLECTION (self), G_OBJECT (place));
 			}
 			gck_token_info_free (token);
 		}
@@ -187,6 +185,9 @@ seahorse_pkcs11_backend_get_property (GObject *obj,
 	case PROP_DESCRIPTION:
 		g_value_set_string (value, _("X.509 certificates and related keys"));
 		break;
+	case PROP_ACTIONS:
+		g_value_set_object (value, NULL);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -230,6 +231,7 @@ seahorse_pkcs11_backend_class_init (SeahorsePkcs11BackendClass *klass)
 	g_object_class_override_property (gobject_class, PROP_NAME, "name");
 	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
 	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
+	g_object_class_override_property (gobject_class, PROP_ACTIONS, "actions");
 }
 
 static guint
diff --git a/pkcs11/seahorse-pkcs11-operations.c b/pkcs11/seahorse-pkcs11-operations.c
index f95039e..3a1bc0f 100644
--- a/pkcs11/seahorse-pkcs11-operations.c
+++ b/pkcs11/seahorse-pkcs11-operations.c
@@ -79,7 +79,7 @@ on_delete_object_completed (GObject *source,
 	}
 
 	if (error == NULL) {
-		g_object_get (object, "source", &pkcs11_token, NULL);
+		g_object_get (object, "place", &pkcs11_token, NULL);
 		g_return_if_fail (SEAHORSE_IS_TOKEN (pkcs11_token));
 		seahorse_token_remove_object (pkcs11_token, GCK_OBJECT (object));
 		pkcs11_delete_one_object (res);
diff --git a/pkcs11/seahorse-token.c b/pkcs11/seahorse-token.c
index 6b015d2..9a1f4de 100644
--- a/pkcs11/seahorse-token.c
+++ b/pkcs11/seahorse-token.c
@@ -34,7 +34,7 @@
 #include "seahorse-pkcs11-operations.h"
 #include "seahorse-token.h"
 
-#include "seahorse-source.h"
+#include "seahorse-place.h"
 #include "seahorse-registry.h"
 #include "seahorse-util.h"
 
@@ -46,6 +46,7 @@ enum {
 	PROP_SLOT,
 	PROP_FLAGS,
 	PROP_URI,
+	PROP_ACTIONS
 };
 
 struct _SeahorseTokenPrivate {
@@ -57,13 +58,13 @@ struct _SeahorseTokenPrivate {
 static void          receive_object                      (SeahorseToken *self,
                                                           GckObject *obj);
 
-static void          seahorse_token_source_iface  (SeahorseSourceIface *iface);
+static void          seahorse_token_place_iface          (SeahorsePlaceIface *iface);
 
-static void          seahorse_token_collection_iface    (GcrCollectionIface *iface);
+static void          seahorse_token_collection_iface     (GcrCollectionIface *iface);
 
 G_DEFINE_TYPE_EXTENDED (SeahorseToken, seahorse_token, G_TYPE_OBJECT, 0,
                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_token_collection_iface);
-                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_token_source_iface);
+                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_PLACE, seahorse_token_place_iface);
 );
 
 
@@ -275,6 +276,9 @@ seahorse_token_get_property (GObject *object,
 	case PROP_URI:
 		g_value_set_string (value, self->pv->uri);
 		break;
+	case PROP_ACTIONS:
+		g_value_set_object (value, NULL);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -341,6 +345,7 @@ seahorse_token_class_init (SeahorseTokenClass *klass)
 	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
 	g_object_class_override_property (gobject_class, PROP_URI, "uri");
 	g_object_class_override_property (gobject_class, PROP_ICON, "icon");
+	g_object_class_override_property (gobject_class, PROP_ACTIONS, "actions");
 
 	g_object_class_install_property (gobject_class, PROP_SLOT,
 	         g_param_spec_object ("slot", "Slot", "Pkcs#11 SLOT",
@@ -352,7 +357,7 @@ seahorse_token_class_init (SeahorseTokenClass *klass)
 }
 
 static void
-seahorse_token_source_iface (SeahorseSourceIface *iface)
+seahorse_token_place_iface (SeahorsePlaceIface *iface)
 {
 
 }
diff --git a/src/seahorse-key-manager.c b/src/seahorse-key-manager.c
index a7ddb6c..b6d8324 100644
--- a/src/seahorse-key-manager.c
+++ b/src/seahorse-key-manager.c
@@ -62,15 +62,11 @@ void           on_keymanager_new_button                 (GtkButton* button,
 void           on_keymanager_import_button              (GtkButton* button,
                                                          SeahorseKeyManager* self);
 
-enum {
-	PROP_0,
-	PROP_SELECTED
-};
-
 struct _SeahorseKeyManagerPrivate {
 	GtkActionGroup* view_actions;
 	GtkEntry* filter_entry;
 	SeahorsePredicate pred;
+	SeahorseSidebar *sidebar;
 
 	GtkTreeView* view;
 	GcrCollection *collection; /* owned by the sidebar */
@@ -135,7 +131,9 @@ on_keymanager_key_list_button_pressed (GtkTreeView* view, GdkEventButton* event,
 	g_return_val_if_fail (GTK_IS_TREE_VIEW (view), FALSE);
 	
 	if (event->button == 3)
-		seahorse_viewer_show_context_menu (SEAHORSE_VIEWER (self), event->button, event->time);
+		seahorse_viewer_show_context_menu (SEAHORSE_VIEWER (self),
+		                                   SEAHORSE_VIEWER_MENU_OBJECT,
+		                                   event->button, event->time);
 
 	return FALSE;
 }
@@ -143,14 +141,14 @@ on_keymanager_key_list_button_pressed (GtkTreeView* view, GdkEventButton* event,
 G_MODULE_EXPORT gboolean
 on_keymanager_key_list_popup_menu (GtkTreeView* view, SeahorseKeyManager* self) 
 {
-	GObject* obj;
-
-	g_return_val_if_fail (SEAHORSE_IS_KEY_MANAGER (self), FALSE);
-	g_return_val_if_fail (GTK_IS_TREE_VIEW (view), FALSE);
+	GList *objects;
 
-	obj = seahorse_viewer_get_selected (SEAHORSE_VIEWER (self));
-	if (obj != NULL) 
-		seahorse_viewer_show_context_menu (SEAHORSE_VIEWER (self), 0, gtk_get_current_event_time ());
+	objects = seahorse_viewer_get_selected_objects (SEAHORSE_VIEWER (self));
+	if (objects != NULL)
+		seahorse_viewer_show_context_menu (SEAHORSE_VIEWER (self),
+		                                   SEAHORSE_VIEWER_MENU_OBJECT,
+		                                   0, gtk_get_current_event_time ());
+	g_list_free (objects);
 	return FALSE;
 }
 
@@ -441,42 +439,25 @@ static const GtkRadioActionEntry VIEW_RADIO_ACTIONS[] = {
 	  N_("Show all keys, certificates and passwords"), SHOW_ANY },
 };
 
-/* -----------------------------------------------------------------------------
- * OBJECT 
- */
-
-static GList* 
-seahorse_key_manager_get_selected_objects (SeahorseViewer* base) 
+static GList *
+seahorse_key_manager_get_selected_objects (SeahorseViewer* viewer)
 {
-	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (base); 
+	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (viewer);
 	return seahorse_key_manager_store_get_selected_objects (self->pv->view);
 }
 
-static void 
-seahorse_key_manager_set_selected_objects (SeahorseViewer* base, GList* objects) 
+static GList *
+seahorse_key_manager_get_selected_places (SeahorseViewer* viewer)
 {
-	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (base);
-	seahorse_key_manager_store_set_selected_objects (self->pv->view, objects);
-
+	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (viewer);
+	return seahorse_sidebar_get_selected_places (self->pv->sidebar);
 }
 
-static GObject *
-seahorse_key_manager_get_selected (SeahorseViewer *base)
+static GList *
+seahorse_key_manager_get_selected_backends (SeahorseViewer* viewer)
 {
-	SeahorseKeyManager* self = SEAHORSE_KEY_MANAGER (base);
-	return seahorse_key_manager_store_get_selected_object (self->pv->view);
-}
-
-static void 
-seahorse_key_manager_set_selected (SeahorseViewer *base,
-                                   GObject *value)
-{
-	SeahorseKeyManager* self = SEAHORSE_KEY_MANAGER (base);
-	GList* objects = NULL; 
-	objects = g_list_prepend (objects, value);
-	seahorse_viewer_set_selected_objects (SEAHORSE_VIEWER (self), objects);
-	g_list_free (objects);
-	g_object_notify (G_OBJECT (self), "selected");
+	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (viewer);
+	return seahorse_sidebar_get_backends (self->pv->sidebar);
 }
 
 static gboolean
@@ -511,15 +492,14 @@ on_sidebar_panes_size_allocate (GtkWidget *widget,
 static GcrCollection *
 setup_sidebar (SeahorseKeyManager *self)
 {
-	SeahorseSidebar *sidebar;
 	GtkWidget *area, *panes;
 	GtkActionGroup *actions;
 	GtkAction *action;
 
-	sidebar = seahorse_sidebar_new ();
+	self->pv->sidebar = seahorse_sidebar_new ();
 	area = seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "sidebar-area");
-	gtk_container_add (GTK_CONTAINER (area), GTK_WIDGET (sidebar));
-	gtk_widget_show (GTK_WIDGET (sidebar));
+	gtk_container_add (GTK_CONTAINER (area), GTK_WIDGET (self->pv->sidebar));
+	gtk_widget_show (GTK_WIDGET (self->pv->sidebar));
 
 	actions = gtk_action_group_new ("sidebar");
 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
@@ -530,7 +510,7 @@ setup_sidebar (SeahorseKeyManager *self)
 	                        area, "visible",
 	                        G_BINDING_DEFAULT);
 	g_object_bind_property (action, "active",
-	                        sidebar, "combined",
+	                        self->pv->sidebar, "combined",
 	                        G_BINDING_INVERT_BOOLEAN);
 	g_settings_bind (self->pv->settings, "sidebar-visible",
 	                 action, "active",
@@ -539,15 +519,15 @@ setup_sidebar (SeahorseKeyManager *self)
 	g_object_unref (actions);
 
 	g_settings_bind (self->pv->settings, "places-selected",
-	                 sidebar, "selected-uris",
+	                 self->pv->sidebar, "selected-uris",
 	                 G_SETTINGS_BIND_DEFAULT);
 
 	self->pv->sidebar_width = g_settings_get_int (self->pv->settings, "sidebar-width");
 	panes = seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "sidebar-panes");
 	gtk_paned_set_position (GTK_PANED (panes), self->pv->sidebar_width);
-	g_signal_connect (sidebar, "size_allocate", G_CALLBACK (on_sidebar_panes_size_allocate), self);
+	g_signal_connect (self->pv->sidebar, "size_allocate", G_CALLBACK (on_sidebar_panes_size_allocate), self);
 
-	return seahorse_sidebar_get_collection (sidebar);
+	return seahorse_sidebar_get_collection (self->pv->sidebar);
 }
 
 static void
@@ -730,63 +710,20 @@ seahorse_key_manager_finalize (GObject *obj)
 }
 
 static void
-seahorse_key_manager_set_property (GObject *obj, guint prop_id, const GValue *value, 
-                           GParamSpec *pspec)
-{
-	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (obj);
-
-	switch (prop_id) {
-	case PROP_SELECTED:
-		seahorse_viewer_set_selected (SEAHORSE_VIEWER (self), g_value_get_object (value));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-seahorse_key_manager_get_property (GObject *obj, guint prop_id, GValue *value, 
-                           GParamSpec *pspec)
-{
-	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (obj);
-
-	switch (prop_id) {
-	case PROP_SELECTED:
-		g_value_set_object (value, seahorse_viewer_get_selected (SEAHORSE_VIEWER (self)));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
-		break;
-	}
-}
-
-static void
 seahorse_key_manager_class_init (SeahorseKeyManagerClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-    
-	seahorse_key_manager_parent_class = g_type_class_peek_parent (klass);
+
 	g_type_class_add_private (klass, sizeof (SeahorseKeyManagerPrivate));
 
 	gobject_class->constructed = seahorse_key_manager_constructed;
 	gobject_class->finalize = seahorse_key_manager_finalize;
-	gobject_class->set_property = seahorse_key_manager_set_property;
-	gobject_class->get_property = seahorse_key_manager_get_property;
-    
-	SEAHORSE_VIEWER_CLASS (klass)->get_selected_objects = seahorse_key_manager_get_selected_objects;
-	SEAHORSE_VIEWER_CLASS (klass)->set_selected_objects = seahorse_key_manager_set_selected_objects;
-	SEAHORSE_VIEWER_CLASS (klass)->get_selected = seahorse_key_manager_get_selected;
-	SEAHORSE_VIEWER_CLASS (klass)->set_selected = seahorse_key_manager_set_selected;
 
-	g_object_class_override_property (gobject_class, PROP_SELECTED, "selected");
+	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;
 }
 
-/* -----------------------------------------------------------------------------
- * PUBLIC 
- */
-
-
 SeahorseWidget *
 seahorse_key_manager_show (void)
 {
diff --git a/src/seahorse-key-manager.ui b/src/seahorse-key-manager.ui
index 7dbb80c..ba582de 100644
--- a/src/seahorse-key-manager.ui
+++ b/src/seahorse-key-manager.ui
@@ -3,7 +3,6 @@
 		<menu name="File" action="file-menu">
 			<menuitem action="file-new"/>
 			<menuitem action="file-import"/>
-			<menuitem action="file-export"/>
 			<separator/>
 			<placeholder name="FileCommands">
 			</placeholder>
@@ -11,7 +10,6 @@
 			<menuitem action="app-quit"/>
 		</menu>
 		<menu name="Edit" action="edit-menu">
-			<menuitem action="edit-export-clipboard"/>
 			<menuitem action="edit-import-clipboard"/>
 			<menuitem action="edit-delete"/>
 			<separator/>
@@ -34,21 +32,22 @@
 	</menubar>
   
 	<toolbar name="MainToolbar">
-		<placeholder name="ToolItems">
-			<toolitem action="show-properties"/>
-			<toolitem action="file-export"/>
-			<toolitem action="key-sign"/>
-			<toolitem action="remote-find"/>
-		</placeholder>
+		<toolitem action="properties-object"/>
 	</toolbar>
 	
-	<popup name="KeyPopup">
-		<menuitem action="show-properties"/>
+	<popup name="ObjectPopup">
+		<menuitem action="properties-object"/>
 		<separator/>
-		<menuitem action="file-export"/>
-		<menuitem action="edit-export-clipboard"/>
 		<menuitem action="edit-delete"/>
 		<separator/>
 	</popup>
-	
+
+	<popup name="PlacePopup">
+		<menuitem action="properties-object"/>
+	</popup>
+
+	<popup name="BackendPopup">
+		<menuitem action="properties-object"/>
+	</popup>
+
 </ui>
diff --git a/src/seahorse-sidebar.c b/src/seahorse-sidebar.c
index ab42602..a59b52a 100644
--- a/src/seahorse-sidebar.c
+++ b/src/seahorse-sidebar.c
@@ -1038,3 +1038,24 @@ seahorse_sidebar_set_selected_uris (SeahorseSidebar *self,
 
 	g_object_notify (G_OBJECT (self), "selected-uris");
 }
+
+GList *
+seahorse_sidebar_get_selected_places (SeahorseSidebar *self)
+{
+	g_return_val_if_fail (SEAHORSE_IS_SIDEBAR (self), NULL);
+	return gcr_union_collection_elements (self->objects);
+}
+
+GList *
+seahorse_sidebar_get_backends (SeahorseSidebar *self)
+{
+	GList *backends = NULL;
+	guint i;
+
+	g_return_val_if_fail (SEAHORSE_IS_SIDEBAR (self), NULL);
+
+	for (i = 0; i < self->backends->len; i++)
+		backends = g_list_prepend (backends, self->backends->pdata[i]);
+
+	return g_list_reverse (backends);
+}
diff --git a/src/seahorse-sidebar.h b/src/seahorse-sidebar.h
index fb59f36..aa41e99 100644
--- a/src/seahorse-sidebar.h
+++ b/src/seahorse-sidebar.h
@@ -52,4 +52,8 @@ gchar **                     seahorse_sidebar_get_selected_uris  (SeahorseSideba
 void                         seahorse_sidebar_set_selected_uris  (SeahorseSidebar *self,
                                                                   const gchar **value);
 
+GList *                 seahorse_sidebar_get_selected_places     (SeahorseSidebar *self);
+
+GList *                 seahorse_sidebar_get_backends            (SeahorseSidebar *self);
+
 #endif /* __SEAHORSE_SIDEBAR_H__ */
diff --git a/ssh/Makefile.am b/ssh/Makefile.am
index 793312a..0ff2116 100644
--- a/ssh/Makefile.am
+++ b/ssh/Makefile.am
@@ -18,8 +18,8 @@ noinst_LTLIBRARIES = libseahorse-ssh.la
 
 libseahorse_ssh_la_SOURCES = \
 	seahorse-ssh.h seahorse-ssh.c \
+	seahorse-ssh-actions.c seahorse-ssh-actions.h \
 	seahorse-ssh-backend.c seahorse-ssh-backend.h \
-	seahorse-ssh-commands.c seahorse-ssh-commands.h \
 	seahorse-ssh-dialogs.h \
 	seahorse-ssh-generate.c \
 	seahorse-ssh-key-data.c seahorse-ssh-key-data.h \
diff --git a/ssh/seahorse-ssh-actions.c b/ssh/seahorse-ssh-actions.c
new file mode 100644
index 0000000..eddaa3b
--- /dev/null
+++ b/ssh/seahorse-ssh-actions.c
@@ -0,0 +1,171 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "seahorse-ssh.h"
+#include "seahorse-ssh-actions.h"
+#include "seahorse-ssh-dialogs.h"
+#include "seahorse-ssh-operation.h"
+
+#include "seahorse-action.h"
+#include "seahorse-actions.h"
+#include "seahorse-object.h"
+#include "seahorse-registry.h"
+#include "seahorse-util.h"
+
+#include <glib/gi18n.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+GType   seahorse_ssh_actions_get_type             (void);
+#define SEAHORSE_TYPE_SSH_ACTIONS                 (seahorse_ssh_actions_get_type ())
+#define SEAHORSE_SSH_ACTIONS(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_SSH_ACTIONS, SeahorseSshActions))
+#define SEAHORSE_SSH_ACTIONS_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_SSH_ACTIONS, SeahorseSshActionsClass))
+#define SEAHORSE_IS_SSH_ACTIONS(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_SSH_ACTIONS))
+#define SEAHORSE_IS_SSH_ACTIONS_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_SSH_ACTIONS))
+#define SEAHORSE_SSH_ACTIONS_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_SSH_ACTIONS, SeahorseSshActionsClass))
+
+typedef struct {
+	SeahorseActions parent_instance;
+} SeahorseSshActions;
+
+typedef struct {
+	SeahorseActionsClass parent_class;
+} SeahorseSshActionsClass;
+
+G_DEFINE_TYPE (SeahorseSshActions, seahorse_ssh_actions, SEAHORSE_TYPE_ACTIONS);
+
+static const char* UI_DEFINITION = ""\
+"<ui>"\
+"	<menubar>"\
+"		<menu name='Remote' action='remote-menu'>"\
+"			<menuitem action='remote-ssh-upload'/>"\
+"		</menu>"\
+"	</menubar>"\
+"	<popup name='ObjectPopup'>"\
+"		<menuitem action='remote-ssh-upload'/>"\
+"	</popup>"\
+"</ui>";
+
+static void
+on_ssh_upload (GtkAction* action,
+               gpointer user_data)
+{
+	GList *ssh_keys;
+
+	ssh_keys = seahorse_action_get_objects (action);
+	if (ssh_keys == NULL)
+		return;
+
+	seahorse_ssh_upload_prompt (ssh_keys, seahorse_action_get_window (action));
+	g_list_free (ssh_keys);
+}
+
+static void
+on_show_properties (GtkAction *action,
+                    gpointer user_data)
+{
+	seahorse_ssh_key_properties_show (seahorse_action_get_object (action),
+	                                  seahorse_action_get_window (action));
+}
+
+static void
+on_delete_objects (GtkAction *action,
+                   gpointer user_data)
+{
+	guint num;
+	gchar* prompt;
+	GList *l;
+	GtkWidget *parent;
+	GError *error = NULL;
+	GList* objects;
+
+	objects = seahorse_action_get_objects (action);
+	num = g_list_length (objects);
+	if (num == 0) {
+		return;
+
+	} else if (num == 1) {
+		prompt = g_strdup_printf (_("Are you sure you want to delete the secure shell key '%s'?"),
+		                          seahorse_object_get_label (objects->data));
+
+	} else {
+		prompt = g_strdup_printf (_("Are you sure you want to delete %d secure shell keys?"), num);
+	}
+
+	parent = GTK_WIDGET (seahorse_action_get_window (action));
+	if (seahorse_util_prompt_delete (prompt, NULL)) {
+		for (l = objects; l != NULL; l = g_list_next (l)) {
+			if (!seahorse_ssh_op_delete_sync (l->data, &error)) {
+				seahorse_util_handle_error (&error, parent, _("Couldn't delete key"));
+			}
+		}
+	}
+
+	g_free (prompt);
+
+}
+
+static const GtkActionEntry KEY_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 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);
+	seahorse_actions_register_definition (SEAHORSE_ACTIONS (self), UI_DEFINITION);
+}
+
+static void
+seahorse_ssh_actions_class_init (SeahorseSshActionsClass *klass)
+{
+
+}
+
+GtkActionGroup *
+seahorse_ssh_actions_instance (void)
+{
+	static GtkActionGroup *actions = NULL;
+
+	if (actions == NULL) {
+		actions = g_object_new (SEAHORSE_TYPE_SSH_ACTIONS,
+		                        "name", "ssh-key",
+		                        NULL);
+		g_object_add_weak_pointer (G_OBJECT (actions),
+		                           (gpointer *)&actions);
+	} else {
+		g_object_ref (actions);
+	}
+
+	return actions;
+}
diff --git a/ssh/seahorse-ssh-actions.h b/ssh/seahorse-ssh-actions.h
new file mode 100644
index 0000000..53732b1
--- /dev/null
+++ b/ssh/seahorse-ssh-actions.h
@@ -0,0 +1,28 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __SEAHORSE_SSH_ACTIONS_H__
+#define __SEAHORSE_SSH_ACTIONS_H__
+
+GtkActionGroup *       seahorse_ssh_actions_instance           (void);
+
+#endif
diff --git a/ssh/seahorse-ssh-backend.c b/ssh/seahorse-ssh-backend.c
index c1ee70c..2733bc6 100644
--- a/ssh/seahorse-ssh-backend.c
+++ b/ssh/seahorse-ssh-backend.c
@@ -22,7 +22,6 @@
 #include "config.h"
 
 #include "seahorse-ssh-backend.h"
-#include "seahorse-ssh-commands.h"
 #include "seahorse-ssh-dialogs.h"
 #include "seahorse-ssh-source.h"
 
@@ -35,7 +34,8 @@ enum {
 	PROP_0,
 	PROP_NAME,
 	PROP_LABEL,
-	PROP_DESCRIPTION
+	PROP_DESCRIPTION,
+	PROP_ACTIONS
 };
 
 static SeahorseSshBackend *ssh_backend = NULL;
@@ -64,9 +64,6 @@ seahorse_ssh_backend_init (SeahorseSshBackend *self)
 	g_return_if_fail (ssh_backend == NULL);
 	ssh_backend = self;
 
-	/* Let these classes register themselves, when the backend is created */
-	g_type_class_unref (g_type_class_ref (SEAHORSE_TYPE_SSH_COMMANDS));
-
 	seahorse_ssh_generate_register ();
 }
 
@@ -97,6 +94,9 @@ seahorse_ssh_backend_get_property (GObject *obj,
 	case PROP_DESCRIPTION:
 		g_value_set_string (value, _("Keys used to connect securely to other computers"));
 		break;
+	case PROP_ACTIONS:
+		g_value_set_object (value, NULL);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -126,6 +126,7 @@ seahorse_ssh_backend_class_init (SeahorseSshBackendClass *klass)
 	g_object_class_override_property (gobject_class, PROP_NAME, "name");
 	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
 	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
+	g_object_class_override_property (gobject_class, PROP_ACTIONS, "actions");
 }
 
 static guint
diff --git a/ssh/seahorse-ssh-key-properties.c b/ssh/seahorse-ssh-key-properties.c
index 5ed60ef..902702b 100644
--- a/ssh/seahorse-ssh-key-properties.c
+++ b/ssh/seahorse-ssh-key-properties.c
@@ -94,7 +94,7 @@ on_ssh_comment_activate (GtkWidget *entry,
 	ssh_rename_closure *closure;
 
 	skey = SEAHORSE_SSH_KEY (SEAHORSE_OBJECT_WIDGET (swidget)->object);
-	source = SEAHORSE_SSH_SOURCE (seahorse_object_get_source (SEAHORSE_OBJECT (skey)));
+	source = SEAHORSE_SSH_SOURCE (seahorse_object_get_place (SEAHORSE_OBJECT (skey)));
 
 	text = gtk_entry_get_text (GTK_ENTRY (entry));
 
@@ -145,7 +145,7 @@ on_ssh_trust_toggled (GtkToggleButton *button,
 	gboolean authorize;
 
 	skey = SEAHORSE_SSH_KEY (SEAHORSE_OBJECT_WIDGET (swidget)->object);
-	source = SEAHORSE_SSH_SOURCE (seahorse_object_get_source (SEAHORSE_OBJECT (skey)));
+	source = SEAHORSE_SSH_SOURCE (seahorse_object_get_place (SEAHORSE_OBJECT (skey)));
 
 	authorize = gtk_toggle_button_get_active (button);
 	gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
@@ -208,7 +208,7 @@ export_complete (GFile *file, GAsyncResult *result, guchar *contents)
 G_MODULE_EXPORT void
 on_ssh_export_button_clicked (GtkWidget *widget, SeahorseWidget *swidget)
 {
-	SeahorseSource *sksrc;
+	SeahorsePlace *sksrc;
 	GObject *object;
 	GFile *file;
 	GtkDialog *dialog;
@@ -219,7 +219,7 @@ on_ssh_export_button_clicked (GtkWidget *widget, SeahorseWidget *swidget)
 
 	object = SEAHORSE_OBJECT_WIDGET (swidget)->object;
 	g_return_if_fail (SEAHORSE_IS_SSH_KEY (object));
-	g_object_get (object, "source", &sksrc, NULL);
+	g_object_get (object, "place", &sksrc, NULL);
 	g_return_if_fail (SEAHORSE_IS_SSH_SOURCE (sksrc));
 
 	dialog = seahorse_util_chooser_save_new (_("Export Complete Key"), 
diff --git a/ssh/seahorse-ssh-key.c b/ssh/seahorse-ssh-key.c
index 1d2fb96..d2811b9 100644
--- a/ssh/seahorse-ssh-key.c
+++ b/ssh/seahorse-ssh-key.c
@@ -31,7 +31,7 @@
 #include <errno.h>
 #include <string.h>
 
-#include "seahorse-source.h"
+#include "seahorse-place.h"
 #include "seahorse-ssh-source.h"
 #include "seahorse-ssh-key.h"
 #include "seahorse-ssh-operation.h"
@@ -292,11 +292,14 @@ seahorse_ssh_key_class_init (SeahorseSSHKeyClass *klass)
  */
 
 SeahorseSSHKey* 
-seahorse_ssh_key_new (SeahorseSource *sksrc, SeahorseSSHKeyData *data)
+seahorse_ssh_key_new (SeahorsePlace *place,
+                      SeahorseSSHKeyData *data)
 {
     SeahorseSSHKey *skey;
-    skey = g_object_new (SEAHORSE_TYPE_SSH_KEY, "source", sksrc, 
-                         "key-data", data, NULL);
+    skey = g_object_new (SEAHORSE_TYPE_SSH_KEY,
+                         "place", place,
+                         "key-data", data,
+                         NULL);
     return skey;
 }
 
diff --git a/ssh/seahorse-ssh-key.h b/ssh/seahorse-ssh-key.h
index 6ba26c8..46b6563 100644
--- a/ssh/seahorse-ssh-key.h
+++ b/ssh/seahorse-ssh-key.h
@@ -26,7 +26,7 @@
 #include <gtk/gtk.h>
 
 #include "seahorse-object.h"
-#include "seahorse-source.h"
+#include "seahorse-place.h"
 #include "seahorse-validity.h"
 
 #include "seahorse-ssh-key-data.h"
@@ -60,7 +60,7 @@ struct _SeahorseSSHKeyClass {
     SeahorseObjectClass            parent_class;
 };
 
-SeahorseSSHKey*         seahorse_ssh_key_new                  (SeahorseSource *sksrc, 
+SeahorseSSHKey*         seahorse_ssh_key_new                  (SeahorsePlace *sksrc,
                                                                SeahorseSSHKeyData *data);
 
 void                    seahorse_ssh_key_refresh              (SeahorseSSHKey *self);
diff --git a/ssh/seahorse-ssh-operation.c b/ssh/seahorse-ssh-operation.c
index 9d38809..25f762c 100644
--- a/ssh/seahorse-ssh-operation.c
+++ b/ssh/seahorse-ssh-operation.c
@@ -521,7 +521,7 @@ on_upload_export_complete (GObject *source,
 	size_t length;
 	gchar *cmd;
 
-	if (!seahorse_source_export_finish (SEAHORSE_SOURCE (source), result, &error)) {
+	if (!seahorse_place_export_finish (SEAHORSE_PLACE (source), result, &error)) {
 		g_simple_async_result_take_error (res, error);
 		g_simple_async_result_complete (res);
 		g_object_unref (res);
@@ -582,8 +582,8 @@ seahorse_ssh_op_upload_async (SeahorseSSHSource *source,
 	g_simple_async_result_set_op_res_gpointer (res, closure, ssh_upload_free);
 
 	/* Buffer for what we send to the server */
-	seahorse_source_export_async (SEAHORSE_SOURCE (source), keys, G_OUTPUT_STREAM (closure->output),
-	                              cancellable, on_upload_export_complete, g_object_ref (res));
+	seahorse_place_export_async (SEAHORSE_PLACE (source), keys, G_OUTPUT_STREAM (closure->output),
+	                             cancellable, on_upload_export_complete, g_object_ref (res));
 
 	g_object_unref (res);
 
@@ -633,14 +633,14 @@ seahorse_ssh_op_change_passphrase_async  (SeahorseSSHKey *key,
 {
 	SeahorseSshPromptInfo prompt = { _("Enter Key Passphrase"), NULL, NULL, NULL };
 	GSimpleAsyncResult *res;
-	SeahorseSource *source;
+	SeahorsePlace *place;
 	gchar *cmd;
 
 	g_return_if_fail (SEAHORSE_IS_SSH_KEY (key));
 	g_return_if_fail (key->keydata && key->keydata->privfile);
 
-	source = seahorse_object_get_source (SEAHORSE_OBJECT (key));
-	g_return_if_fail (SEAHORSE_IS_SSH_SOURCE (source));
+	place = seahorse_object_get_place (SEAHORSE_OBJECT (key));
+	g_return_if_fail (SEAHORSE_IS_SSH_SOURCE (place));
 
 	prompt.argument = seahorse_object_get_label (SEAHORSE_OBJECT (key));
 
@@ -649,7 +649,7 @@ seahorse_ssh_op_change_passphrase_async  (SeahorseSSHKey *key,
 	g_simple_async_result_set_op_res_gpointer (res, g_object_ref (key), g_object_unref);
 
 	cmd = g_strdup_printf (SSH_KEYGEN_PATH " -p -f '%s'", key->keydata->privfile);
-	seahorse_ssh_operation_async (SEAHORSE_SSH_SOURCE (source), cmd, NULL, 0, cancellable,
+	seahorse_ssh_operation_async (SEAHORSE_SSH_SOURCE (place), cmd, NULL, 0, cancellable,
 	                              on_change_passphrase_complete, &prompt, g_object_ref (res));
 
 	g_free (cmd);
@@ -1151,7 +1151,7 @@ seahorse_ssh_op_delete_sync (SeahorseSSHKey *key,
 	}
 
 	if (ret) {
-		source = SEAHORSE_SSH_SOURCE (seahorse_object_get_source (SEAHORSE_OBJECT (key)));
+		source = SEAHORSE_SSH_SOURCE (seahorse_object_get_place (SEAHORSE_OBJECT (key)));
 		seahorse_ssh_source_remove_object (source, key);
 	}
 
diff --git a/ssh/seahorse-ssh-source.c b/ssh/seahorse-ssh-source.c
index 0f283d9..514e852 100644
--- a/ssh/seahorse-ssh-source.c
+++ b/ssh/seahorse-ssh-source.c
@@ -23,11 +23,11 @@
 #include "config.h"
 
 
-#include "seahorse-ssh-source.h"
-
 #include "seahorse-ssh-key.h"
 #include "seahorse-ssh-operation.h"
+#include "seahorse-ssh-source.h"
 
+#include "seahorse-place.h"
 #include "seahorse-registry.h"
 #include "seahorse-util.h"
 
@@ -50,7 +50,8 @@ enum {
 	PROP_DESCRIPTION,
 	PROP_ICON,
 	PROP_BASE_DIRECTORY,
-	PROP_URI
+	PROP_URI,
+	PROP_ACTIONS
 };
 
 struct _SeahorseSSHSourcePrivate {
@@ -60,13 +61,13 @@ struct _SeahorseSSHSourcePrivate {
     GHashTable *keys;
 };
 
-static void       seahorse_ssh_source_iface             (SeahorseSourceIface *iface);
+static void       seahorse_ssh_source_place_iface       (SeahorsePlaceIface *iface);
 
 static void       seahorse_ssh_source_collection_iface  (GcrCollectionIface *iface);
 
 G_DEFINE_TYPE_EXTENDED (SeahorseSSHSource, seahorse_ssh_source, G_TYPE_OBJECT, 0,
                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_ssh_source_collection_iface);
-                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_ssh_source_iface)
+                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_PLACE, seahorse_ssh_source_place_iface)
 );
 
 #define AUTHORIZED_KEYS_FILE    "authorized_keys"
@@ -244,6 +245,9 @@ seahorse_ssh_source_get_property (GObject *obj,
 		g_value_take_string (value, g_strdup_printf ("openssh://%s",
 		                                             self->priv->ssh_homedir));
 		break;
+	case PROP_ACTIONS:
+		g_value_set_object (value, NULL);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -336,6 +340,7 @@ seahorse_ssh_source_class_init (SeahorseSSHSourceClass *klass)
     g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
     g_object_class_override_property (gobject_class, PROP_URI, "uri");
     g_object_class_override_property (gobject_class, PROP_ICON, "icon");
+    g_object_class_override_property (gobject_class, PROP_ACTIONS, "actions");
 
     g_object_class_install_property (gobject_class, PROP_BASE_DIRECTORY,
         g_param_spec_string ("base-directory", "Key directory", "Directory where the keys are stored",
@@ -405,7 +410,7 @@ ssh_key_from_data (SeahorseSSHSource *self,
                    source_load_closure *closure,
                    SeahorseSSHKeyData *keydata)
 {
-	SeahorseSource *source = SEAHORSE_SOURCE (self);
+	SeahorsePlace *place = SEAHORSE_PLACE (self);
 	SeahorseSSHKey *skey;
 	SeahorseObject *prev;
 	const gchar *location;
@@ -453,7 +458,7 @@ ssh_key_from_data (SeahorseSSHSource *self,
 
 	/* Create a new key */
 	g_assert (keydata);
-	skey = seahorse_ssh_key_new (source, keydata);
+	skey = seahorse_ssh_key_new (place, keydata);
 	g_assert (g_strcmp0 (seahorse_ssh_key_get_location (skey), location) == 0);
 
 	g_hash_table_insert (self->priv->keys, g_strdup (location), skey);
@@ -774,19 +779,19 @@ on_import_found_private_key (SeahorseSSHSecData *data,
 }
 
 static void
-seahorse_ssh_source_import_async (SeahorseSource *source,
+seahorse_ssh_source_import_async (SeahorsePlace *place,
                                   GInputStream *input,
                                   GCancellable *cancellable,
                                   GAsyncReadyCallback callback,
                                   gpointer user_data)
 {
-	SeahorseSSHSource *self = SEAHORSE_SSH_SOURCE (source);
+	SeahorseSSHSource *self = SEAHORSE_SSH_SOURCE (place);
 	source_import_closure *closure;
 	gchar *contents;
 	GSimpleAsyncResult *res;
 	guint count;
 
-	res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+	res = g_simple_async_result_new (G_OBJECT (place), callback, user_data,
 	                                 seahorse_ssh_source_import_async);
 	closure = g_new0 (source_import_closure, 1);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
@@ -805,11 +810,11 @@ seahorse_ssh_source_import_async (SeahorseSource *source,
 }
 
 static GList *
-seahorse_ssh_source_import_finish (SeahorseSource *source,
+seahorse_ssh_source_import_finish (SeahorsePlace *place,
                                    GAsyncResult *result,
                                    GError **error)
 {
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (place),
 	                      seahorse_ssh_source_import_async), NULL);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
@@ -820,7 +825,7 @@ seahorse_ssh_source_import_finish (SeahorseSource *source,
 }
 
 static void
-seahorse_ssh_source_export_async (SeahorseSource *source,
+seahorse_ssh_source_export_async (SeahorsePlace *place,
                                   GList *keys,
                                   GOutputStream *output,
                                   GCancellable *cancellable,
@@ -836,7 +841,7 @@ seahorse_ssh_source_export_async (SeahorseSource *source,
 	GList *l;
 	gsize written;
 
-	res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+	res = g_simple_async_result_new (G_OBJECT (place), callback, user_data,
 	                                 seahorse_ssh_source_export_async);
 
 	for (l = keys; l; l = g_list_next (l)) {
@@ -886,11 +891,11 @@ seahorse_ssh_source_export_async (SeahorseSource *source,
 }
 
 static GOutputStream *
-seahorse_ssh_source_export_finish (SeahorseSource *source,
+seahorse_ssh_source_export_finish (SeahorsePlace *place,
                                    GAsyncResult *result,
                                    GError **error)
 {
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (place),
 	                      seahorse_ssh_source_export_async), NULL);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
@@ -900,7 +905,7 @@ seahorse_ssh_source_export_finish (SeahorseSource *source,
 }
 
 static void 
-seahorse_ssh_source_iface (SeahorseSourceIface *iface)
+seahorse_ssh_source_place_iface (SeahorsePlaceIface *iface)
 {
 	iface->import_async = seahorse_ssh_source_import_async;
 	iface->import_finish = seahorse_ssh_source_import_finish;
diff --git a/ssh/seahorse-ssh-source.h b/ssh/seahorse-ssh-source.h
index 7124b4c..7a85d8c 100644
--- a/ssh/seahorse-ssh-source.h
+++ b/ssh/seahorse-ssh-source.h
@@ -40,7 +40,6 @@
 #define __SEAHORSE_SSH_SOURCE_H__
 
 #include "seahorse-ssh-key.h"
-#include "seahorse-source.h"
 
 #define SEAHORSE_TYPE_SSH_SOURCE            (seahorse_ssh_source_get_type ())
 #define SEAHORSE_SSH_SOURCE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_SSH_SOURCE, SeahorseSSHSource))
diff --git a/ssh/seahorse-ssh-upload.c b/ssh/seahorse-ssh-upload.c
index 6a7e543..53b0aa1 100644
--- a/ssh/seahorse-ssh-upload.c
+++ b/ssh/seahorse-ssh-upload.c
@@ -124,7 +124,7 @@ upload_keys (SeahorseWidget *swidget)
     cancellable = g_cancellable_new ();
 
     /* Start an upload process */
-    seahorse_ssh_op_upload_async (SEAHORSE_SSH_SOURCE (seahorse_object_get_source (keys->data)),
+    seahorse_ssh_op_upload_async (SEAHORSE_SSH_SOURCE (seahorse_object_get_place (keys->data)),
                                   keys, user, host, port, cancellable, on_upload_complete, NULL);
 
     g_free (host);



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