[seahorse/refactor: 5/33] Refactor core of seahorse



commit 0d8af302a2adc5d16874b24a7eac6ab7eed0e5fe
Author: Stef Walter <stefw collabora co uk>
Date:   Wed Sep 7 13:02:56 2011 +0200

    Refactor core of seahorse
    
     * Objects are owned by sources not by the SeahorseContext
     * No more unique identifiers for objects, since these don't
       fit well with PKCS#11 objects at all.
     * Cleanup SeahorseSource and remove server stuff.
     * All server related stuff goes into the pgp backend.
     * More well defined backends
     * DNS-SD stuff goes into the pgp backend

 Makefile.am                                        |    2 +-
 gkr/Makefile.am                                    |    7 +-
 gkr/seahorse-gkr-add-item.c                        |   13 +-
 gkr/seahorse-gkr-add-keyring.c                     |    5 +-
 gkr/seahorse-gkr-backend.c                         |  409 ++++++
 gkr/seahorse-gkr-backend.h                         |   69 +
 gkr/seahorse-gkr-item-commands.c                   |    6 +-
 gkr/seahorse-gkr-item-properties.c                 |    1 -
 gkr/seahorse-gkr-item.c                            |   18 +-
 gkr/seahorse-gkr-item.h                            |    5 +-
 gkr/seahorse-gkr-keyring-commands.c                |   17 +-
 gkr/seahorse-gkr-keyring.c                         |   60 +-
 gkr/seahorse-gkr-keyring.h                         |    9 +
 gkr/seahorse-gkr-module.c                          |   47 -
 gkr/seahorse-gkr-module.h                          |   30 -
 gkr/seahorse-gkr-operation.c                       |   18 +-
 gkr/seahorse-gkr-operation.h                       |    1 -
 gkr/seahorse-gkr-source.c                          |  382 ------
 gkr/seahorse-gkr-source.h                          |   66 -
 gkr/seahorse-gkr.h                                 |    5 +-
 libseahorse/Makefile.am                            |    9 +-
 libseahorse/seahorse-collection.c                  |  127 ++-
 libseahorse/seahorse-collection.h                  |    3 +-
 libseahorse/seahorse-context.c                     | 1445 +-------------------
 libseahorse/seahorse-context.h                     |  144 +--
 libseahorse/seahorse-dns-sd.c                      |  459 -------
 libseahorse/seahorse-dns-sd.h                      |   83 --
 {src => libseahorse}/seahorse-key-manager-store.c  |  158 ++--
 {src => libseahorse}/seahorse-key-manager-store.h  |    4 +-
 libseahorse/seahorse-object-widget.c               |   21 +-
 libseahorse/seahorse-object.c                      |  266 +----
 libseahorse/seahorse-object.h                      |   19 -
 libseahorse/seahorse-predicate.h                   |    4 -
 {src => libseahorse}/seahorse-preferences.c        |    4 +-
 {src => libseahorse}/seahorse-preferences.h        |    0
 libseahorse/seahorse-prefs.c                       |    1 -
 libseahorse/seahorse-prefs.h                       |    1 -
 libseahorse/seahorse-registry.c                    |   50 -
 libseahorse/seahorse-registry.h                    |    8 -
 libseahorse/seahorse-source.c                      |  188 +---
 libseahorse/seahorse-source.h                      |   64 -
 libseahorse/seahorse-types.c                       |   19 -
 libseahorse/seahorse-types.h                       |   14 -
 libseahorse/seahorse-unknown-source.c              |  191 ---
 libseahorse/seahorse-util.c                        |    4 +-
 libseahorse/seahorse-util.h                        |    2 -
 libseahorse/seahorse-view.h                        |    2 +
 {src => libseahorse}/seahorse-viewer.c             |  276 ++--
 {src => libseahorse}/seahorse-viewer.h             |   56 +-
 pgp/Makefile.am                                    |   11 +-
 {libseahorse => pgp}/seahorse-combo-keys.c         |   56 +-
 {libseahorse => pgp}/seahorse-combo-keys.h         |   16 +-
 pgp/seahorse-discovery.c                           |  453 ++++++
 pgp/seahorse-discovery.h                           |   83 ++
 pgp/seahorse-gpg-options.c                         |    1 -
 pgp/seahorse-gpgme-dialogs.h                       |    6 +-
 pgp/seahorse-gpgme-generate.c                      |   46 +-
 pgp/seahorse-gpgme-key-op.c                        |   58 +-
 pgp/seahorse-gpgme-key-op.h                        |    6 +-
 pgp/seahorse-gpgme-key.c                           |   87 +-
 ...rse-gpgme-source.c => seahorse-gpgme-keyring.c} |  645 +++++-----
 pgp/seahorse-gpgme-keyring.h                       |   91 ++
 pgp/seahorse-gpgme-sign.c                          |    5 +-
 pgp/seahorse-gpgme-source.h                        |   74 -
 pgp/seahorse-gpgme-uid.c                           |   15 -
 pgp/seahorse-hkp-source.c                          |  180 +--
 {src => pgp}/seahorse-keyserver-results.c          |  213 ++--
 {src => pgp}/seahorse-keyserver-results.h          |   12 +-
 {src => pgp}/seahorse-keyserver-search.c           |   48 +-
 .../seahorse-keyserver-search.h                    |   22 +-
 {src => pgp}/seahorse-keyserver-sync.c             |   74 +-
 {src => pgp}/seahorse-keyserver-sync.h             |    6 +-
 pgp/seahorse-ldap-source.c                         |  147 +--
 pgp/seahorse-ldap-source.h                         |    2 +-
 pgp/seahorse-pgp-backend.c                         |  646 +++++++++
 pgp/seahorse-pgp-backend.h                         |  110 ++
 pgp/seahorse-pgp-commands.c                        |   79 +-
 pgp/seahorse-pgp-key-properties.c                  |  102 +-
 pgp/seahorse-pgp-key.c                             |  124 +-
 pgp/seahorse-pgp-key.h                             |   14 +-
 pgp/seahorse-pgp-keysets.c                         |   39 +-
 pgp/seahorse-pgp-module.c                          |   58 -
 pgp/seahorse-pgp-module.h                          |   30 -
 pgp/seahorse-pgp-signature.c                       |   25 +-
 pgp/seahorse-pgp-signature.h                       |    2 -
 pgp/seahorse-pgp-uid.c                             |    1 -
 pgp/seahorse-pgp.h                                 |    9 +
 pgp/seahorse-server-source.c                       |  112 +-
 pgp/seahorse-server-source.h                       |   48 +-
 pgp/seahorse-signer.c                              |   25 +-
 {libseahorse => pgp}/seahorse-transfer.c           |   55 +-
 {libseahorse => pgp}/seahorse-transfer.h           |    4 +-
 pgp/seahorse-unknown-source.c                      |  115 ++
 {libseahorse => pgp}/seahorse-unknown-source.h     |   32 +-
 {libseahorse => pgp}/seahorse-unknown.c            |   21 +-
 {libseahorse => pgp}/seahorse-unknown.h            |    2 +-
 pkcs11/Makefile.am                                 |    2 +-
 pkcs11/seahorse-pkcs11-backend.c                   |  168 +++
 pkcs11/seahorse-pkcs11-backend.h                   |   46 +
 pkcs11/seahorse-pkcs11-certificate.c               |    1 -
 pkcs11/seahorse-pkcs11-helpers.c                   |  129 +--
 pkcs11/seahorse-pkcs11-helpers.h                   |    6 +-
 pkcs11/seahorse-pkcs11-module.c                    |   63 -
 pkcs11/seahorse-pkcs11-module.h                    |   30 -
 pkcs11/seahorse-pkcs11-object.c                    |   31 +-
 pkcs11/seahorse-pkcs11-object.h                    |    2 -
 pkcs11/seahorse-pkcs11-operations.c                |   36 +-
 pkcs11/seahorse-pkcs11-source.c                    |  128 ++-
 pkcs11/seahorse-pkcs11-source.h                    |    4 +
 pkcs11/seahorse-pkcs11.h                           |    8 +
 src/Makefile.am                                    |   11 -
 src/seahorse-generate-select.h                     |    2 +-
 src/seahorse-key-manager.c                         |  219 +--
 src/seahorse-key-manager.h                         |    9 +-
 src/seahorse-key-manager.ui                        |    6 +-
 src/seahorse-main.c                                |   49 +-
 ssh/Makefile.am                                    |    2 +-
 ssh/seahorse-ssh-backend.c                         |  141 ++
 ssh/seahorse-ssh-backend.h                         |   48 +
 ssh/seahorse-ssh-commands.c                        |    1 -
 ssh/seahorse-ssh-generate.c                        |   11 +-
 ssh/seahorse-ssh-key.c                             |   32 -
 ssh/seahorse-ssh-key.h                             |    5 +-
 ssh/seahorse-ssh-module.c                          |   45 -
 ssh/seahorse-ssh-module.h                          |   30 -
 ssh/seahorse-ssh-operation.c                       |    9 +-
 ssh/seahorse-ssh-source.c                          |  192 ++--
 ssh/seahorse-ssh-source.h                          |   11 +
 ssh/seahorse-ssh.h                                 |    7 +
 129 files changed, 4302 insertions(+), 5984 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 4ec1902..9defb88 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,8 +23,8 @@ endif
 SUBDIRS = libegg \
 	libseahorse \
 	gkr \
-	$(PKCS11_DIR) \
 	$(PGP_DIR) \
+	$(PKCS11_DIR) \
 	$(SSH_DIR) \
 	src \
 	po \
diff --git a/gkr/Makefile.am b/gkr/Makefile.am
index 3576e47..06f02cd 100644
--- a/gkr/Makefile.am
+++ b/gkr/Makefile.am
@@ -19,6 +19,7 @@ libseahorse_gkr_la_SOURCES = \
 	seahorse-gkr.c seahorse-gkr.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 \
@@ -26,10 +27,8 @@ libseahorse_gkr_la_SOURCES = \
 	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-module.c seahorse-gkr-module.h \
-	seahorse-gkr-operation.c seahorse-gkr-operation.h \
-	seahorse-gkr-source.c seahorse-gkr-source.h
-	
+	seahorse-gkr-operation.c seahorse-gkr-operation.h
+
 libseahorse_gkr_la_LIBADD = \
 	$(top_builddir)/libseahorse/libseahorse.la
 
diff --git a/gkr/seahorse-gkr-add-item.c b/gkr/seahorse-gkr-add-item.c
index db4c13f..e58fb31 100644
--- a/gkr/seahorse-gkr-add-item.c
+++ b/gkr/seahorse-gkr-add-item.c
@@ -20,9 +20,9 @@
  */
 #include "config.h"
 
+#include "seahorse-gkr-backend.h"
 #include "seahorse-gkr-dialogs.h"
 #include "seahorse-gkr-keyring.h"
-#include "seahorse-gkr-source.h"
 
 #include "seahorse-secure-buffer.h"
 #include "seahorse-widget.h"
@@ -52,8 +52,7 @@ item_add_done (GnomeKeyringResult result, guint32 item, gpointer data)
 
 	/* Successful. Update the listings and stuff. */
 	if (result == GNOME_KEYRING_RESULT_OK) {
-		seahorse_source_load_async (SEAHORSE_SOURCE (seahorse_gkr_source_default ()),
-		                            NULL, NULL, NULL);
+		seahorse_gkr_backend_load_async (NULL, NULL, NULL, NULL);
 
 	/* Setting the default keyring failed */
 	} else if (result != GNOME_KEYRING_RESULT_CANCELLED) {     
@@ -154,16 +153,16 @@ seahorse_gkr_add_item_show (GtkWindow *parent)
 	cell = gtk_cell_renderer_text_new ();
 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), cell, TRUE);
 	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (widget), cell, "text", 0);
-	                                    
-	keyrings = seahorse_context_find_objects (NULL, SEAHORSE_GKR, SEAHORSE_USAGE_OTHER, 
-	                                          SEAHORSE_LOCATION_LOCAL);
+
+	keyrings = seahorse_gkr_backend_get_keyrings (NULL);
 	for (l = keyrings; l; l = g_list_next (l)) {
 		gtk_list_store_append (store, &iter);
 		gtk_list_store_set (store, &iter, 0, seahorse_gkr_keyring_get_name (l->data), -1);
 		if (seahorse_gkr_keyring_get_is_default (l->data))
 			gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter);
 	}
-	
+	g_list_free (keyrings);
+
 	g_object_unref (store);
 
 	widget = seahorse_widget_get_widget (swidget, "item-label");
diff --git a/gkr/seahorse-gkr-add-keyring.c b/gkr/seahorse-gkr-add-keyring.c
index eddc805..fe76bb8 100644
--- a/gkr/seahorse-gkr-add-keyring.c
+++ b/gkr/seahorse-gkr-add-keyring.c
@@ -21,9 +21,9 @@
  */
 #include "config.h"
 
+#include "seahorse-gkr-backend.h"
 #include "seahorse-gkr-dialogs.h"
 #include "seahorse-gkr-keyring.h"
-#include "seahorse-gkr-source.h"
 
 #include "seahorse-widget.h"
 #include "seahorse-util.h"
@@ -63,8 +63,7 @@ keyring_add_done (GnomeKeyringResult result, gpointer data)
 
 	/* Successful. Update the listings and stuff. */
 	if (result == GNOME_KEYRING_RESULT_OK) {
-		seahorse_source_load_async (SEAHORSE_SOURCE (seahorse_gkr_source_default ()),
-		                            NULL, NULL, NULL);
+		seahorse_gkr_backend_load_async (NULL, NULL, NULL, NULL);
 
 	/* Setting the default keyring failed */
 	} else if (result != GNOME_KEYRING_RESULT_CANCELLED) {     
diff --git a/gkr/seahorse-gkr-backend.c b/gkr/seahorse-gkr-backend.c
new file mode 100644
index 0000000..3c9db11
--- /dev/null
+++ b/gkr/seahorse-gkr-backend.c
@@ -0,0 +1,409 @@
+/*
+ * 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.
+ */
+
+#include "config.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-progress.h"
+
+#include <gnome-keyring.h>
+
+static SeahorseGkrBackend *gkr_backend = NULL;
+
+struct _SeahorseGkrBackend {
+	GObject parent;
+	GHashTable *keyrings;
+};
+
+struct _SeahorseGkrBackendClass {
+	GObjectClass parent_class;
+};
+
+static void         seahorse_gkr_backend_collection_init  (GcrCollectionIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (SeahorseGkrBackend, seahorse_gkr_backend, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_gkr_backend_collection_init));
+
+static void
+seahorse_gkr_backend_init (SeahorseGkrBackend *self)
+{
+	g_return_if_fail (gkr_backend == NULL);
+	gkr_backend = self;
+
+	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
+seahorse_gkr_backend_constructed (GObject *obj)
+{
+	SeahorseGkrBackend *self = SEAHORSE_GKR_BACKEND (obj);
+
+	G_OBJECT_CLASS (seahorse_gkr_backend_parent_class)->constructed (obj);
+
+	seahorse_gkr_backend_load_async (self, NULL, NULL, NULL);
+}
+
+static void
+seahorse_gkr_backend_dispose (GObject *obj)
+{
+	SeahorseGkrBackend *self = SEAHORSE_GKR_BACKEND (obj);
+
+	g_hash_table_remove_all (self->keyrings);
+
+	G_OBJECT_CLASS (seahorse_gkr_backend_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_gkr_backend_finalize (GObject *obj)
+{
+	SeahorseGkrBackend *self = SEAHORSE_GKR_BACKEND (obj);
+
+	g_hash_table_destroy (self->keyrings);
+	g_return_if_fail (gkr_backend == self);
+	gkr_backend = NULL;
+
+	G_OBJECT_CLASS (seahorse_gkr_backend_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_gkr_backend_class_init (SeahorseGkrBackendClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+	gobject_class->constructed = seahorse_gkr_backend_constructed;
+	gobject_class->dispose = seahorse_gkr_backend_dispose;
+	gobject_class->finalize = seahorse_gkr_backend_finalize;
+}
+
+static guint
+seahorse_gkr_backend_get_length (GcrCollection *collection)
+{
+	SeahorseGkrBackend *self = SEAHORSE_GKR_BACKEND (collection);
+	return g_hash_table_size (self->keyrings);
+}
+
+static GList *
+seahorse_gkr_backend_get_objects (GcrCollection *collection)
+{
+	SeahorseGkrBackend *self = SEAHORSE_GKR_BACKEND (collection);
+	return seahorse_gkr_backend_get_keyrings (self);
+}
+
+static gboolean
+seahorse_gkr_backend_contains (GcrCollection *collection,
+                               GObject *object)
+{
+	SeahorseGkrBackend *self = SEAHORSE_GKR_BACKEND (collection);
+	const gchar *keyring_name;
+
+	if (!SEAHORSE_IS_GKR_KEYRING (object))
+		return FALSE;
+
+	keyring_name = seahorse_gkr_keyring_get_name (SEAHORSE_GKR_KEYRING (object));
+	return g_hash_table_lookup (self->keyrings, keyring_name) == object;
+}
+
+static void
+seahorse_gkr_backend_collection_init (GcrCollectionIface *iface)
+{
+	iface->contains = seahorse_gkr_backend_contains;
+	iface->get_length = seahorse_gkr_backend_get_length;
+	iface->get_objects = seahorse_gkr_backend_get_objects;
+}
+
+GcrCollection *
+seahorse_gkr_backend_initialize (void)
+{
+	SeahorseGkrBackend *self;
+	GcrCollection *collection;
+
+	self = g_object_new (SEAHORSE_TYPE_GKR_BACKEND, NULL);
+
+	/*
+	 * For now, the keyrings themselves are the objects, so the
+	 * backend is the source
+	 */
+
+	collection = gcr_simple_collection_new ();
+	gcr_simple_collection_add (GCR_SIMPLE_COLLECTION (collection), G_OBJECT (self));
+	g_object_unref (self);
+
+	return collection;
+}
+
+SeahorseGkrBackend *
+seahorse_gkr_backend_get (void)
+{
+	g_return_val_if_fail (gkr_backend, NULL);
+	return gkr_backend;
+}
+
+SeahorseGkrKeyring *
+seahorse_gkr_backend_get_keyring (SeahorseGkrBackend *self,
+                                 const gchar *keyring_name)
+{
+	self = self ? self : seahorse_gkr_backend_get ();
+	g_return_val_if_fail (SEAHORSE_IS_GKR_BACKEND (self), NULL);
+	g_return_val_if_fail (keyring_name != NULL, NULL);
+	return g_hash_table_lookup (self->keyrings, keyring_name);
+}
+
+GList *
+seahorse_gkr_backend_get_keyrings (SeahorseGkrBackend *self)
+{
+	self = self ? self : seahorse_gkr_backend_get ();
+	g_return_val_if_fail (SEAHORSE_IS_GKR_BACKEND (self), NULL);
+	return g_hash_table_get_values (self->keyrings);
+}
+
+void
+seahorse_gkr_backend_remove_keyring (SeahorseGkrBackend *self,
+                                     SeahorseGkrKeyring *keyring)
+{
+	const gchar *keyring_name;
+
+	self = self ? self : seahorse_gkr_backend_get ();
+	g_return_if_fail (SEAHORSE_IS_GKR_BACKEND (self));
+	g_return_if_fail (SEAHORSE_IS_GKR_KEYRING (keyring));
+
+	keyring_name = seahorse_gkr_keyring_get_name (keyring);
+	g_return_if_fail (g_hash_table_lookup (self->keyrings, keyring_name) == keyring);
+
+	g_object_ref (keyring);
+
+	g_hash_table_remove (self->keyrings, keyring_name);
+	gcr_collection_emit_removed (GCR_COLLECTION (self), G_OBJECT (keyring));
+
+	g_object_unref (keyring);
+}
+
+
+typedef struct {
+	SeahorseGkrBackend *backend;
+	GCancellable *cancellable;
+	gulong cancelled_sig;
+	gpointer request;
+	gint num_loads;
+} backend_load_closure;
+
+static void
+backend_load_free (gpointer data)
+{
+	backend_load_closure *closure = data;
+	g_assert (closure->request == NULL);
+	g_assert (closure->num_loads == 0);
+	if (closure->cancellable && closure->cancelled_sig)
+		g_signal_handler_disconnect (closure->cancellable,
+		                             closure->cancelled_sig);
+	g_clear_object (&closure->cancellable);
+	g_clear_object (&closure->backend);
+	g_free (closure);
+}
+
+static void
+on_backend_load_default_keyring (GnomeKeyringResult result,
+                                 const gchar *default_name,
+                                 gpointer user_data)
+{
+	SeahorseGkrBackend *self = SEAHORSE_GKR_BACKEND (user_data);
+	const gchar *keyring_name;
+	gboolean is_default;
+	GList *keyrings, *l;
+
+	if (result != GNOME_KEYRING_RESULT_OK) {
+		if (result != GNOME_KEYRING_RESULT_CANCELLED)
+			g_warning ("couldn't get default keyring name: %s", gnome_keyring_result_to_message (result));
+		return;
+	}
+
+	keyrings = seahorse_gkr_backend_get_keyrings (self);
+	for (l = keyrings; l != NULL; l = g_list_next (l)) {
+		keyring_name = seahorse_gkr_keyring_get_name (l->data);
+		g_return_if_fail (keyring_name);
+
+		/* Remember default keyring could be null in strange circumstances */
+		is_default = default_name && g_str_equal (keyring_name, default_name);
+		g_object_set (l->data, "is-default", is_default, NULL);
+	}
+	g_list_free (keyrings);
+}
+
+static void
+on_backend_load_keyring_complete (GObject *object,
+                                  GAsyncResult *result,
+                                  gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	SeahorseGkrKeyring *keyring = SEAHORSE_GKR_KEYRING (object);
+	backend_load_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	GError *error = NULL;
+
+	g_assert (closure->num_loads > 0);
+	closure->num_loads--;
+	seahorse_progress_end (closure->cancellable, keyring);
+
+	if (!seahorse_gkr_keyring_load_finish (keyring, result, &error))
+		g_simple_async_result_take_error (res, error);
+
+	if (closure->num_loads == 0)
+		g_simple_async_result_complete (res);
+
+	g_object_unref (res);
+}
+
+static void
+on_backend_load_list_keyring_names_complete (GnomeKeyringResult result,
+                                            GList *list,
+                                            gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	backend_load_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	SeahorseGkrKeyring *keyring;
+	GError *error = NULL;
+	gchar *keyring_name;
+	GHashTableIter iter;
+	GHashTable *checks;
+	GList *l;
+
+	closure->request = NULL;
+
+	if (seahorse_gkr_propagate_error (result, &error)) {
+		g_simple_async_result_take_error (res, error);
+		g_simple_async_result_complete_in_idle (res);
+		return;
+	}
+
+	/* Load up a list of all the current names */
+	checks = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+	g_hash_table_iter_init (&iter, closure->backend->keyrings);
+	while (g_hash_table_iter_next (&iter, (gpointer *)&keyring_name, (gpointer *)&keyring))
+		g_hash_table_insert (checks, g_strdup (keyring_name), g_object_ref (keyring));
+
+	for (l = list; l; l = g_list_next (l)) {
+		keyring_name = l->data;
+
+		/* Don't show the 'session' keyring */
+		if (g_str_equal (keyring_name, "session"))
+			continue;
+
+		keyring = g_hash_table_lookup (checks, keyring_name);
+
+		/* Already have a keyring */
+		if (keyring != NULL) {
+			g_object_ref (keyring);
+			g_hash_table_remove (checks, keyring_name);
+
+		/* Create a new keyring for this one */
+		} else {
+			keyring = seahorse_gkr_keyring_new (keyring_name);
+			g_hash_table_insert (closure->backend->keyrings,
+			                     g_strdup (keyring_name),
+			                     g_object_ref (keyring));
+			gcr_collection_emit_added (GCR_COLLECTION (closure->backend),
+			                           G_OBJECT (keyring));
+		}
+
+		/* Refresh the keyring as well, and track the load */
+		seahorse_gkr_keyring_load_async (keyring, closure->cancellable,
+		                                 on_backend_load_keyring_complete,
+		                                 g_object_ref (res));
+		seahorse_progress_prep_and_begin (closure->cancellable, keyring, NULL);
+		closure->num_loads++;
+		g_object_unref (keyring);
+	}
+
+	g_hash_table_iter_init (&iter, checks);
+	while (g_hash_table_iter_next (&iter, (gpointer *)&keyring_name, (gpointer *)&keyring))
+		seahorse_gkr_backend_remove_keyring (closure->backend, keyring);
+	g_hash_table_destroy (checks);
+
+	if (list == NULL)
+		g_simple_async_result_complete_in_idle (res);
+
+	/* Get the default keyring in the background */
+	gnome_keyring_get_default_keyring (on_backend_load_default_keyring,
+	                                   g_object_ref (closure->backend),
+	                                   g_object_unref);
+}
+
+static void
+on_backend_load_cancelled (GCancellable *cancellable,
+                           gpointer user_data)
+{
+	backend_load_closure *closure = user_data;
+
+	if (closure->request)
+		gnome_keyring_cancel_request (closure->request);
+}
+void
+seahorse_gkr_backend_load_async (SeahorseGkrBackend *self,
+                                 GCancellable *cancellable,
+                                 GAsyncReadyCallback callback,
+                                 gpointer user_data)
+{
+	backend_load_closure *closure;
+	GSimpleAsyncResult *res;
+
+	self = self ? self : seahorse_gkr_backend_get ();
+
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+	                                 seahorse_gkr_backend_load_async);
+	closure = g_new0 (backend_load_closure, 1);
+	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+	closure->backend = g_object_ref (self);
+	g_simple_async_result_set_op_res_gpointer (res, closure, backend_load_free);
+
+	closure->request = gnome_keyring_list_keyring_names (on_backend_load_list_keyring_names_complete,
+	                                                     g_object_ref (res), g_object_unref);
+
+	if (cancellable)
+		closure->cancelled_sig = g_cancellable_connect (cancellable,
+		                                                G_CALLBACK (on_backend_load_cancelled),
+		                                                closure, NULL);
+
+	g_object_unref (res);
+}
+
+gboolean
+seahorse_gkr_backend_load_finish (SeahorseGkrBackend *self,
+                                  GAsyncResult *result,
+                                  GError **error)
+{
+	self = self ? self : seahorse_gkr_backend_get ();
+
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      seahorse_gkr_backend_load_async), FALSE);
+
+	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+		return FALSE;
+
+	return TRUE;
+}
diff --git a/gkr/seahorse-gkr-backend.h b/gkr/seahorse-gkr-backend.h
new file mode 100644
index 0000000..6f34ba1
--- /dev/null
+++ b/gkr/seahorse-gkr-backend.h
@@ -0,0 +1,69 @@
+/*
+ * Seahorse
+ *
+ * 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.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#ifndef SEAHORSE_GKR_BACKEND_H_
+#define SEAHORSE_GKR_BACKEND_H_
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gcr/gcr.h>
+
+#include "seahorse-gkr-keyring.h"
+
+G_BEGIN_DECLS
+
+#define SEAHORSE_TYPE_GKR_BACKEND            (seahorse_gkr_backend_get_type ())
+#define SEAHORSE_GKR_BACKEND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_GKR_BACKEND, SeahorseGkrBackend))
+#define SEAHORSE_GKR_BACKEND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_GKR_BACKEND, SeahorseGkrBackendClass))
+#define SEAHORSE_IS_GKR_BACKEND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_GKR_BACKEND))
+#define SEAHORSE_IS_GKR_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_GKR_BACKEND))
+#define SEAHORSE_GKR_BACKEND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_GKR_BACKEND, SeahorseGkrBackendClass))
+
+typedef struct _SeahorseGkrBackend SeahorseGkrBackend;
+typedef struct _SeahorseGkrBackendClass SeahorseGkrBackendClass;
+
+GType                 seahorse_gkr_backend_get_type        (void) G_GNUC_CONST;
+
+SeahorseGkrBackend *  seahorse_gkr_backend_get             (void);
+
+SeahorseGkrKeyring *  seahorse_gkr_backend_get_keyring     (SeahorseGkrBackend *self,
+                                                            const gchar *keyring_name);
+
+GList *               seahorse_gkr_backend_get_keyrings    (SeahorseGkrBackend *self);
+
+void                  seahorse_gkr_backend_remove_keyring  (SeahorseGkrBackend *self,
+                                                            SeahorseGkrKeyring *keyring);
+
+void                  seahorse_gkr_backend_load_async      (SeahorseGkrBackend *self,
+                                                            GCancellable *cancellable,
+                                                            GAsyncReadyCallback callback,
+                                                            gpointer user_data);
+
+gboolean              seahorse_gkr_backend_load_finish     (SeahorseGkrBackend *self,
+                                                            GAsyncResult *result,
+                                                            GError **error);
+
+G_END_DECLS
+
+#endif /*SEAHORSE_GKR_BACKEND_H_*/
diff --git a/gkr/seahorse-gkr-item-commands.c b/gkr/seahorse-gkr-item-commands.c
index 2a7ad1b..552819e 100644
--- a/gkr/seahorse-gkr-item-commands.c
+++ b/gkr/seahorse-gkr-item-commands.c
@@ -54,7 +54,6 @@ seahorse_gkr_item_commands_show_properties (SeahorseCommands* base, SeahorseObje
 	GtkWindow *window;
 
 	g_return_if_fail (SEAHORSE_IS_OBJECT (object));
-	g_return_if_fail (seahorse_object_get_tag (object) == SEAHORSE_GKR_TYPE);
 
 	window = seahorse_commands_get_window (base);
 	if (G_OBJECT_TYPE (object) == SEAHORSE_TYPE_GKR_ITEM) 
@@ -159,8 +158,9 @@ seahorse_gkr_item_commands_class_init (SeahorseGkrItemCommandsClass *klass)
 	commands_predicate.type = SEAHORSE_TYPE_GKR_ITEM;
 
 	/* Register this class as a commands */
-	seahorse_registry_register_type (seahorse_registry_get (), SEAHORSE_TYPE_GKR_ITEM_COMMANDS, 
-	                                 SEAHORSE_GKR_TYPE_STR, "commands", NULL, NULL);
+	seahorse_registry_register_type (seahorse_registry_get (),
+	                                 SEAHORSE_TYPE_GKR_ITEM_COMMANDS,
+	                                 "commands", NULL);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/gkr/seahorse-gkr-item-properties.c b/gkr/seahorse-gkr-item-properties.c
index 91fcc0d..afb36c8 100644
--- a/gkr/seahorse-gkr-item-properties.c
+++ b/gkr/seahorse-gkr-item-properties.c
@@ -25,7 +25,6 @@
 
 #include "seahorse-gkr-dialogs.h"
 #include "seahorse-gkr-item.h"
-#include "seahorse-gkr-source.h"
 #include "seahorse-gkr-operation.h"
 
 #include "seahorse-bind.h"
diff --git a/gkr/seahorse-gkr-item.c b/gkr/seahorse-gkr-item.c
index a5604b8..b3c3596 100644
--- a/gkr/seahorse-gkr-item.c
+++ b/gkr/seahorse-gkr-item.c
@@ -26,7 +26,6 @@
 
 #include <glib/gi18n.h>
 
-#include "seahorse-context.h"
 #include "seahorse-icons.h"
 #include "seahorse-source.h"
 #include "seahorse-util.h"
@@ -475,22 +474,16 @@ static void
 seahorse_gkr_item_init (SeahorseGkrItem *self)
 {
 	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_GKR_ITEM, SeahorseGkrItemPrivate);
-	g_object_set (self, "usage", SEAHORSE_USAGE_CREDENTIALS, "tag", SEAHORSE_GKR_TYPE, "location", SEAHORSE_LOCATION_LOCAL, NULL);
+	g_object_set (self, "usage", SEAHORSE_USAGE_CREDENTIALS, NULL);
 }
 
 static void
 seahorse_gkr_item_constructed (GObject *object)
 {
 	SeahorseGkrItem *self = SEAHORSE_GKR_ITEM (object);
-	GQuark id;
 
 	G_OBJECT_CLASS (seahorse_gkr_item_parent_class)->constructed (object);
 
-	id = seahorse_gkr_item_get_cannonical (self->pv->keyring_name,
-	                                       self->pv->item_id);
-	g_object_set (self, "id", id,
-	              "usage", SEAHORSE_USAGE_CREDENTIALS, NULL);
-
 	seahorse_gkr_item_realize (self);
 }
 
@@ -771,15 +764,6 @@ seahorse_gkr_find_string_attribute (GnomeKeyringAttributeList *attrs, const gcha
 	return NULL;	
 }
 
-GQuark
-seahorse_gkr_item_get_cannonical (const gchar *keyring_name, guint32 item_id)
-{
-	gchar *buf = g_strdup_printf ("%s:%s-%08X", SEAHORSE_GKR_STR, keyring_name, item_id);
-	GQuark id = g_quark_from_string (buf);
-	g_free (buf);
-	return id;
-}
-
 SeahorseGkrUse
 seahorse_gkr_item_get_use (SeahorseGkrItem *self)
 {
diff --git a/gkr/seahorse-gkr-item.h b/gkr/seahorse-gkr-item.h
index d5a676f..10f7405 100644
--- a/gkr/seahorse-gkr-item.h
+++ b/gkr/seahorse-gkr-item.h
@@ -26,7 +26,7 @@
 #include <gtk/gtk.h>
 #include <gnome-keyring.h>
 
-#include "seahorse-gkr-module.h"
+#include "seahorse-gkr.h"
 #include "seahorse-gkr-keyring.h"
 
 #include "seahorse-object.h"
@@ -96,9 +96,6 @@ const gchar*                 seahorse_gkr_item_get_attribute      (SeahorseGkrIt
 const gchar* 		     seahorse_gkr_find_string_attribute   (GnomeKeyringAttributeList *attrs, 
              		                                           const gchar *name);
 
-GQuark                       seahorse_gkr_item_get_cannonical     (const gchar *keyring_name, 
-                                                                   guint32 item_id);
-
 SeahorseGkrUse               seahorse_gkr_item_get_use            (SeahorseGkrItem *self);
 
 #endif /* __SEAHORSE_GKR_ITEM_H__ */
diff --git a/gkr/seahorse-gkr-keyring-commands.c b/gkr/seahorse-gkr-keyring-commands.c
index a92f4c9..6d2c0bc 100644
--- a/gkr/seahorse-gkr-keyring-commands.c
+++ b/gkr/seahorse-gkr-keyring-commands.c
@@ -24,11 +24,10 @@
 
 #include "seahorse-gkr-keyring-commands.h"
 
-#include "seahorse-gkr.h"
+#include "seahorse-gkr-backend.h"
 #include "seahorse-gkr-keyring.h"
 #include "seahorse-gkr-dialogs.h"
 #include "seahorse-gkr-operation.h"
-#include "seahorse-gkr-source.h"
 
 #include "seahorse-progress.h"
 #include "seahorse-registry.h"
@@ -83,9 +82,9 @@ on_refresh_all_keyrings_complete (GObject *source,
 static void
 refresh_all_keyrings (SeahorseCommands *commands)
 {
-	seahorse_source_load_async (SEAHORSE_SOURCE (seahorse_gkr_source_default ()),
-	                            NULL, on_refresh_all_keyrings_complete,
-	                            g_object_ref (commands));
+	seahorse_gkr_backend_load_async (NULL, NULL,
+	                                 on_refresh_all_keyrings_complete,
+	                                 g_object_ref (commands));
 }
 
 /**
@@ -318,7 +317,6 @@ seahorse_gkr_keyring_commands_show_properties (SeahorseCommands* base, SeahorseO
 	GtkWindow *window;
 
 	g_return_if_fail (SEAHORSE_IS_OBJECT (object));
-	g_return_if_fail (seahorse_object_get_tag (object) == SEAHORSE_GKR_TYPE);
 
 	window = seahorse_commands_get_window (base);
 	if (G_OBJECT_TYPE (object) == SEAHORSE_TYPE_GKR_KEYRING) 
@@ -446,14 +444,15 @@ seahorse_gkr_keyring_commands_class_init (SeahorseGkrKeyringCommandsClass *klass
 	keyring_predicate.type = SEAHORSE_TYPE_GKR_KEYRING;
 	
 	/* Register this class as a commands */
-	seahorse_registry_register_type (seahorse_registry_get (), SEAHORSE_TYPE_GKR_KEYRING_COMMANDS, 
-	                                 SEAHORSE_GKR_TYPE_STR, "commands", NULL, NULL);
+	seahorse_registry_register_type (seahorse_registry_get (),
+	                                 SEAHORSE_TYPE_GKR_KEYRING_COMMANDS,
+	                                 "commands", NULL, NULL);
 	
 	/* Register this as a generator */
 	actions = gtk_action_group_new ("gkr-generate");
 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
 	gtk_action_group_add_actions (actions, ENTRIES_NEW, G_N_ELEMENTS (ENTRIES_NEW), NULL);
-	seahorse_registry_register_object (NULL, G_OBJECT (actions), SEAHORSE_GKR_TYPE_STR, "generator", NULL);
+	seahorse_registry_register_object (NULL, G_OBJECT (actions), "generator", NULL);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/gkr/seahorse-gkr-keyring.c b/gkr/seahorse-gkr-keyring.c
index 3412eea..f724e95 100644
--- a/gkr/seahorse-gkr-keyring.c
+++ b/gkr/seahorse-gkr-keyring.c
@@ -36,8 +36,6 @@
 
 enum {
 	PROP_0,
-	PROP_SOURCE_TAG,
-	PROP_SOURCE_LOCATION,
 	PROP_KEYRING_NAME,
 	PROP_KEYRING_INFO,
 	PROP_IS_DEFAULT
@@ -299,19 +297,14 @@ on_keyring_load_cancelled (GCancellable *cancellable,
 		gnome_keyring_cancel_request (closure->request);
 }
 
-static void
-seahorse_gkr_keyring_load_async (SeahorseSource *source,
+void
+seahorse_gkr_keyring_load_async (SeahorseGkrKeyring *self,
                                  GCancellable *cancellable,
                                  GAsyncReadyCallback callback,
                                  gpointer user_data)
 {
-	SeahorseGkrKeyring *self = SEAHORSE_GKR_KEYRING (source);
 	keyring_load_closure *closure;
 	GSimpleAsyncResult *res;
-#if TODO
-/* cancellable = g_cancellable_new ();
-g_cancellable_cancel (cancellable); */
-#endif
 
 	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
 	                                 seahorse_gkr_keyring_load_async);
@@ -334,12 +327,12 @@ g_cancellable_cancel (cancellable); */
 	g_object_unref (res);
 }
 
-static gboolean
-seahorse_gkr_keyring_load_finish (SeahorseSource *source,
+gboolean
+seahorse_gkr_keyring_load_finish (SeahorseGkrKeyring *self,
                                   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 (self),
 	                      seahorse_gkr_keyring_load_async), FALSE);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
@@ -348,26 +341,15 @@ seahorse_gkr_keyring_load_finish (SeahorseSource *source,
 	return TRUE;
 }
 
-static GObject* 
-seahorse_gkr_keyring_constructor (GType type, guint n_props, GObjectConstructParam *props) 
+static void
+seahorse_gkr_keyring_constructed (GObject *obj)
 {
-	GObject *obj = G_OBJECT_CLASS (seahorse_gkr_keyring_parent_class)->constructor (type, n_props, props);
-	SeahorseGkrKeyring *self = NULL;
-	gchar *id;
-	
-	if (obj) {
-		self = SEAHORSE_GKR_KEYRING (obj);
-		
-		g_return_val_if_fail (self->pv->keyring_name, obj);
-		id = g_strdup_printf ("%s:%s", SEAHORSE_GKR_TYPE_STR, self->pv->keyring_name);
-		g_object_set (self, 
-		              "id", g_quark_from_string (id), 
-		              "usage", SEAHORSE_USAGE_NONE, 
-		              NULL);
-		g_free (id);
-	}
-	
-	return obj;
+	SeahorseGkrKeyring *self = SEAHORSE_GKR_KEYRING (obj);
+
+	G_OBJECT_CLASS (seahorse_gkr_keyring_parent_class)->constructed (obj);
+
+	g_return_if_fail (self->pv->keyring_name);
+	g_object_set (self, "usage", SEAHORSE_USAGE_NONE, NULL);
 }
 
 static void
@@ -375,7 +357,6 @@ seahorse_gkr_keyring_init (SeahorseGkrKeyring *self)
 {
 	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_GKR_KEYRING, SeahorseGkrKeyringPrivate);
 	self->pv->items = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
-	g_object_set (self, "tag", SEAHORSE_GKR_TYPE, "location", SEAHORSE_LOCATION_LOCAL, NULL);
 }
 
 static void
@@ -431,12 +412,6 @@ seahorse_gkr_keyring_get_property (GObject *obj, guint prop_id, GValue *value,
 	SeahorseGkrKeyring *self = SEAHORSE_GKR_KEYRING (obj);
 	
 	switch (prop_id) {
-	case PROP_SOURCE_TAG:
-		g_value_set_uint (value, SEAHORSE_GKR_TYPE);
-		break;
-	case PROP_SOURCE_LOCATION:
-		g_value_set_enum (value, SEAHORSE_LOCATION_LOCAL);
-		break;
 	case PROP_KEYRING_NAME:
 		g_value_set_string (value, seahorse_gkr_keyring_get_name (self));
 		break;
@@ -457,17 +432,13 @@ seahorse_gkr_keyring_class_init (SeahorseGkrKeyringClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-	seahorse_gkr_keyring_parent_class = g_type_class_peek_parent (klass);
 	g_type_class_add_private (klass, sizeof (SeahorseGkrKeyringPrivate));
 
-	gobject_class->constructor = seahorse_gkr_keyring_constructor;
+	gobject_class->constructed = seahorse_gkr_keyring_constructed;
 	gobject_class->finalize = seahorse_gkr_keyring_finalize;
 	gobject_class->set_property = seahorse_gkr_keyring_set_property;
 	gobject_class->get_property = seahorse_gkr_keyring_get_property;
 
-	g_object_class_override_property (gobject_class, PROP_SOURCE_TAG, "source-tag");
-	g_object_class_override_property (gobject_class, PROP_SOURCE_LOCATION, "source-location");
-
 	g_object_class_install_property (gobject_class, PROP_KEYRING_NAME,
 	           g_param_spec_string ("keyring-name", "Gnome Keyring Name", "Name of keyring.", 
 	                                "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -484,8 +455,7 @@ seahorse_gkr_keyring_class_init (SeahorseGkrKeyringClass *klass)
 static void
 seahorse_keyring_source_iface (SeahorseSourceIface *iface)
 {
-	iface->load_async = seahorse_gkr_keyring_load_async;
-	iface->load_finish = seahorse_gkr_keyring_load_finish;
+
 }
 
 static guint
diff --git a/gkr/seahorse-gkr-keyring.h b/gkr/seahorse-gkr-keyring.h
index ff61e80..d040ec1 100644
--- a/gkr/seahorse-gkr-keyring.h
+++ b/gkr/seahorse-gkr-keyring.h
@@ -71,4 +71,13 @@ gboolean             seahorse_gkr_keyring_get_is_default   (SeahorseGkrKeyring *
 void                 seahorse_gkr_keyring_set_is_default   (SeahorseGkrKeyring *self,
                                                             gboolean is_default);
 
+void                 seahorse_gkr_keyring_load_async       (SeahorseGkrKeyring *self,
+                                                            GCancellable *cancellable,
+                                                            GAsyncReadyCallback callback,
+                                                            gpointer user_data);
+
+gboolean             seahorse_gkr_keyring_load_finish      (SeahorseGkrKeyring *self,
+                                                            GAsyncResult *result,
+                                                            GError **error);
+
 #endif /* __SEAHORSE_GKR_KEYRING_H__ */
diff --git a/gkr/seahorse-gkr-operation.c b/gkr/seahorse-gkr-operation.c
index 775c2ba..0387c76 100644
--- a/gkr/seahorse-gkr-operation.c
+++ b/gkr/seahorse-gkr-operation.c
@@ -28,10 +28,12 @@
 
 #include <glib/gi18n.h>
 
+#include "seahorse-gkr-backend.h"
 #include "seahorse-gkr-operation.h"
+
+#include "seahorse-passphrase.h"
 #include "seahorse-progress.h"
 #include "seahorse-util.h"
-#include "seahorse-passphrase.h"
 
 #include <gnome-keyring.h>
 #include <gnome-keyring-memory.h>
@@ -390,6 +392,8 @@ on_delete_gkr_complete (GnomeKeyringResult result,
 	delete_gkr_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GError *error = NULL;
 	SeahorseObject *object;
+	SeahorseGkrKeyring *keyring;
+	SeahorseGkrItem *item;
 
 	closure->request = NULL;
 	object = g_queue_pop_head (closure->objects);
@@ -399,8 +403,16 @@ on_delete_gkr_complete (GnomeKeyringResult result,
 		g_simple_async_result_take_error (res, error);
 		g_simple_async_result_complete_in_idle (res);
 
-	} else {
-		g_object_run_dispose (G_OBJECT (object));
+	} else if (SEAHORSE_IS_GKR_ITEM (object)) {
+		keyring = SEAHORSE_GKR_KEYRING (seahorse_object_get_source (object));
+		item = SEAHORSE_GKR_ITEM (object);
+		seahorse_gkr_keyring_remove_item (keyring, seahorse_gkr_item_get_item_id (item));
+
+		delete_gkr_one_object (res);
+	} else if (SEAHORSE_IS_GKR_KEYRING (object)) {
+		keyring = SEAHORSE_GKR_KEYRING (object);
+		seahorse_gkr_backend_remove_keyring (NULL, keyring);
+
 		delete_gkr_one_object (res);
 	}
 
diff --git a/gkr/seahorse-gkr-operation.h b/gkr/seahorse-gkr-operation.h
index 890371a..3f398ed 100644
--- a/gkr/seahorse-gkr-operation.h
+++ b/gkr/seahorse-gkr-operation.h
@@ -23,7 +23,6 @@
 #ifndef __SEAHORSE_GKR_OPERATION_H__
 #define __SEAHORSE_GKR_OPERATION_H__
 
-#include "seahorse-gkr-source.h"
 #include "seahorse-gkr-item.h"
 #include "seahorse-gkr-keyring.h"
 
diff --git a/gkr/seahorse-gkr.h b/gkr/seahorse-gkr.h
index 4496c81..7c13f9d 100644
--- a/gkr/seahorse-gkr.h
+++ b/gkr/seahorse-gkr.h
@@ -25,10 +25,11 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include <gcr/gcr.h>
+
 G_BEGIN_DECLS
 
-#define SEAHORSE_GKR_TYPE_STR "gnome-keyring"
-#define SEAHORSE_GKR_TYPE g_quark_from_string ("gnome-keyring")
+GcrCollection *       seahorse_gkr_backend_initialize    (void);
 
 G_END_DECLS
 
diff --git a/libseahorse/Makefile.am b/libseahorse/Makefile.am
index 43c2716..15a19ca 100644
--- a/libseahorse/Makefile.am
+++ b/libseahorse/Makefile.am
@@ -5,6 +5,7 @@ seahorselibexecbindir = $(libdir)/seahorse/
 
 INCLUDES = -I$(top_builddir) \
 	-I$(top_srcdir) \
+	-I$(top_srcdir)/libegg \
 	$(SEAHORSE_CFLAGS) \
 	-DPKGDATADIR=\""$(pkgdatadir)/"\" \
 	-DDATA_DIR=\""$(datadir)"\" \
@@ -30,12 +31,11 @@ libseahorse_la_SOURCES = \
 	seahorse-bind.c seahorse-bind.h \
 	seahorse-cleanup.c seahorse-cleanup.h \
 	seahorse-collection.c seahorse-collection.h \
-	seahorse-combo-keys.c seahorse-combo-keys.h \
 	seahorse-commands.c seahorse-commands.h \
 	seahorse-context.c seahorse-context.h \
 	seahorse-debug.c seahorse-debug.h \
-	seahorse-dns-sd.c seahorse-dns-sd.h \
 	seahorse-icons.c seahorse-icons.h \
+	seahorse-key-manager-store.c seahorse-key-manager-store.h \
 	seahorse-object.c seahorse-object.h \
 	seahorse-object-list.c seahorse-object-list.h \
 	seahorse-object-model.c seahorse-object-model.h \
@@ -43,19 +43,18 @@ libseahorse_la_SOURCES = \
 	seahorse-passphrase.c seahorse-passphrase.h \
 	seahorse-predicate.h \
 	seahorse-prefs.c seahorse-prefs.h \
+	seahorse-preferences.c seahorse-preferences.h \
 	seahorse-progress.c seahorse-progress.h \
 	seahorse-registry.c seahorse-registry.h \
 	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-transfer.c seahorse-transfer.h \
 	seahorse-types.c seahorse-types.h \
-	seahorse-unknown.c seahorse-unknown.h \
-	seahorse-unknown-source.c seahorse-unknown-source.h \
 	seahorse-util.c seahorse-util.h \
 	seahorse-validity.c seahorse-validity.h \
 	seahorse-view.c seahorse-view.h \
+	seahorse-viewer.c seahorse-viewer.h \
 	seahorse-widget.c seahorse-widget.h \
 	$(MARSHAL_SRCS) \
 	$(KEYSERVER_SRCS)
diff --git a/libseahorse/seahorse-collection.c b/libseahorse/seahorse-collection.c
index f24faad..dd579aa 100644
--- a/libseahorse/seahorse-collection.c
+++ b/libseahorse/seahorse-collection.c
@@ -26,10 +26,12 @@
 
 enum {
 	PROP_0,
+	PROP_BASE,
 	PROP_PREDICATE
 };
 
 struct _SeahorseCollectionPrivate {
+	GcrCollection *base;
 	GHashTable *objects;
 	SeahorsePredicate *pred;
 	GDestroyNotify destroy_func;
@@ -37,6 +39,12 @@ struct _SeahorseCollectionPrivate {
 
 static void      seahorse_collection_iface_init     (GcrCollectionIface *iface);
 
+static gboolean  maybe_add_object                   (SeahorseCollection *self,
+                                                     SeahorseObject *object);
+
+static gboolean  maybe_remove_object                (SeahorseCollection *self,
+                                                     SeahorseObject *object);
+
 G_DEFINE_TYPE_WITH_CODE (SeahorseCollection, seahorse_collection, G_TYPE_OBJECT,
                          G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_collection_iface_init);
 );
@@ -50,6 +58,19 @@ remove_update (SeahorseObject *object,
 	return TRUE;
 }
 
+
+static void
+on_object_changed (SeahorseObject *object,
+                   GParamSpec *spec,
+                   gpointer user_data)
+{
+	SeahorseCollection *self = SEAHORSE_COLLECTION (user_data);
+	if (g_hash_table_lookup (self->pv->objects, object))
+		maybe_remove_object (self, object);
+	else
+		maybe_add_object (self, object);
+}
+
 static void
 remove_object (gpointer key,
                gpointer value,
@@ -58,6 +79,7 @@ remove_object (gpointer key,
 	SeahorseCollection *self = SEAHORSE_COLLECTION (user_data);
 	SeahorseObject *object = SEAHORSE_OBJECT (key);
 	g_hash_table_remove (self->pv->objects, object);
+	g_signal_handlers_disconnect_by_func (object, on_object_changed, self);
 	remove_update (object, NULL, self);
 }
 
@@ -72,6 +94,7 @@ maybe_add_object (SeahorseCollection *self,
 		return FALSE;
 
 	g_hash_table_replace (self->pv->objects, object, GINT_TO_POINTER (TRUE));
+	g_signal_connect (object, "notify", G_CALLBACK (on_object_changed), self);
 	gcr_collection_emit_added (GCR_COLLECTION (self), G_OBJECT (object));
 	return TRUE;
 }
@@ -91,9 +114,9 @@ maybe_remove_object (SeahorseCollection *self,
 }
 
 static void
-on_context_object_added (SeahorseContext *context,
-                         SeahorseObject *object,
-                         gpointer user_data)
+on_base_added (GcrCollection *base,
+               SeahorseObject *object,
+               gpointer user_data)
 {
 	SeahorseCollection *self = SEAHORSE_COLLECTION (user_data);
 
@@ -101,9 +124,9 @@ on_context_object_added (SeahorseContext *context,
 }
 
 static void
-on_context_object_removed (SeahorseContext *context,
-                           SeahorseObject *object,
-                           gpointer user_data)
+on_base_removed (GcrCollection *base,
+                 SeahorseObject *object,
+                 gpointer user_data)
 {
 	SeahorseCollection *self = SEAHORSE_COLLECTION (user_data);
 
@@ -112,18 +135,6 @@ on_context_object_removed (SeahorseContext *context,
 }
 
 static void
-on_context_object_changed (SeahorseContext *context,
-                           SeahorseObject *object,
-                           gpointer user_data)
-{
-	SeahorseCollection *self = SEAHORSE_COLLECTION (user_data);
-	if (g_hash_table_lookup (self->pv->objects, object))
-		maybe_remove_object (self, object);
-	else
-		maybe_add_object (self, object);
-}
-
-static void
 objects_to_list (SeahorseObject *sobj, gpointer *c, GList **l)
 {
 	*l = g_list_append (*l, sobj);
@@ -136,16 +147,33 @@ objects_to_hash (SeahorseObject *sobj, gpointer *c, GHashTable *ht)
 }
 
 static void
+seahorse_collection_init (SeahorseCollection *self)
+{
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_COLLECTION,
+	                                        SeahorseCollectionPrivate);
+	self->pv->objects = g_hash_table_new (g_direct_hash, g_direct_equal);
+}
+
+static void
+seahorse_collection_constructed (GObject *obj)
+{
+	SeahorseCollection *self = SEAHORSE_COLLECTION (obj);
+
+	g_return_if_fail (self->pv->base);
+
+	G_OBJECT_CLASS (seahorse_collection_parent_class)->constructed (obj);
+
+	g_signal_connect (self->pv->base, "added", G_CALLBACK (on_base_added), self);
+	g_signal_connect (self->pv->base, "removed", G_CALLBACK (on_base_removed), self);
+}
+
+static void
 seahorse_collection_dispose (GObject *obj)
 {
 	SeahorseCollection *self = SEAHORSE_COLLECTION (obj);
 
-	g_signal_handlers_disconnect_by_func (seahorse_context_instance (),
-	                                      on_context_object_added, self);
-	g_signal_handlers_disconnect_by_func (seahorse_context_instance (),
-	                                      on_context_object_removed, self);
-	g_signal_handlers_disconnect_by_func (seahorse_context_instance (),
-	                                      on_context_object_changed, self);
+	g_signal_handlers_disconnect_by_func (self->pv->base, on_base_added, self);
+	g_signal_handlers_disconnect_by_func (self->pv->base, on_base_removed, self);
 
 	/* Release all our pointers and stuff */
 	g_hash_table_foreach_remove (self->pv->objects, (GHRFunc)remove_update, self);
@@ -158,6 +186,7 @@ seahorse_collection_finalize (GObject *obj)
 {
 	SeahorseCollection *self = SEAHORSE_COLLECTION (obj);
 
+	g_clear_object (&self->pv->base);
 	g_hash_table_destroy (self->pv->objects);
 
 	if (self->pv->destroy_func)
@@ -175,10 +204,19 @@ seahorse_collection_set_property (GObject *obj,
 	SeahorseCollection *self = SEAHORSE_COLLECTION (obj);
 
 	switch (prop_id) {
+	case PROP_BASE:
+		g_return_if_fail (self->pv->base == NULL);
+		self->pv->base = g_value_dup_object (value);
+		g_return_if_fail (self->pv->base != NULL);
+		if (self->pv->pred)
+			seahorse_collection_refresh (self);
+		break;
 	case PROP_PREDICATE:
 		g_return_if_fail (self->pv->pred == NULL);
 		self->pv->pred = g_value_get_pointer (value);
-		seahorse_collection_refresh (self);
+		g_return_if_fail (self->pv->pred != NULL);
+		if (self->pv->base)
+			seahorse_collection_refresh (self);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
@@ -195,6 +233,9 @@ seahorse_collection_get_property (GObject *obj,
 	SeahorseCollection *self = SEAHORSE_COLLECTION (obj);
 
 	switch (prop_id) {
+	case PROP_BASE:
+		g_value_set_object (value, self->pv->base);
+		break;
 	case PROP_PREDICATE:
 		g_value_set_pointer (value, self->pv->pred);
 		break;
@@ -205,31 +246,21 @@ seahorse_collection_get_property (GObject *obj,
 }
 
 static void
-seahorse_collection_init (SeahorseCollection *self)
-{
-	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_COLLECTION,
-	                                        SeahorseCollectionPrivate);
-
-	self->pv->objects = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-	g_signal_connect (seahorse_context_instance (), "added",
-	                  G_CALLBACK (on_context_object_added), self);
-	g_signal_connect (seahorse_context_instance (), "removed",
-	                  G_CALLBACK (on_context_object_removed), self);
-	g_signal_connect (seahorse_context_instance (), "changed",
-	                  G_CALLBACK (on_context_object_changed), self);
-}
-
-static void
 seahorse_collection_class_init (SeahorseCollectionClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
+	gobject_class->constructed = seahorse_collection_constructed;
 	gobject_class->dispose = seahorse_collection_dispose;
 	gobject_class->finalize = seahorse_collection_finalize;
 	gobject_class->set_property = seahorse_collection_set_property;
 	gobject_class->get_property = seahorse_collection_get_property;
 
+	g_object_class_install_property (gobject_class, PROP_BASE,
+	          g_param_spec_object ("base", "Base", "Base collection",
+	                               GCR_TYPE_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+
 	g_object_class_install_property (gobject_class, PROP_PREDICATE,
 	          g_param_spec_pointer ("predicate", "Predicate", "Predicate for matching objects into this set.",
 	                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -272,12 +303,16 @@ seahorse_collection_iface_init (GcrCollectionIface *iface)
 }
 
 SeahorseCollection *
-seahorse_collection_new_for_predicate (SeahorsePredicate *pred,
+seahorse_collection_new_for_predicate (GcrCollection *base,
+                                       SeahorsePredicate *pred,
                                        GDestroyNotify destroy_func)
 {
 	SeahorseCollection *collection;
 
+	g_return_val_if_fail (GCR_IS_COLLECTION (base), NULL);
+
 	collection = g_object_new (SEAHORSE_TYPE_COLLECTION,
+	                           "base", base,
 	                           "predicate", pred,
 	                           NULL);
 
@@ -291,13 +326,12 @@ seahorse_collection_refresh (SeahorseCollection *self)
 	GHashTable *check = g_hash_table_new (g_direct_hash, g_direct_equal);
 	GList *l, *objects = NULL;
 
+	g_return_if_fail (SEAHORSE_IS_COLLECTION (self));
+
 	/* Make note of all the objects we had prior to refresh */
 	g_hash_table_foreach (self->pv->objects, (GHFunc)objects_to_hash, check);
 
-	if (self->pv->pred)
-		objects = seahorse_context_find_objects_full (seahorse_context_instance (),
-		                                              self->pv->pred);
-
+	objects = gcr_collection_get_objects (self->pv->base);
 	for (l = objects; l != NULL; l = g_list_next (l)) {
 
 		/* Make note that we've seen this object */
@@ -306,7 +340,6 @@ seahorse_collection_refresh (SeahorseCollection *self)
 		/* This will add to set */
 		maybe_add_object (self, l->data);
 	}
-
 	g_list_free (objects);
 
 	g_hash_table_foreach (check, remove_object, self);
diff --git a/libseahorse/seahorse-collection.h b/libseahorse/seahorse-collection.h
index 6b20eb7..ed8e176 100644
--- a/libseahorse/seahorse-collection.h
+++ b/libseahorse/seahorse-collection.h
@@ -51,7 +51,8 @@ struct _SeahorseCollectionClass {
 
 GType                seahorse_collection_get_type             (void);
 
-SeahorseCollection * seahorse_collection_new_for_predicate    (SeahorsePredicate *predicate,
+SeahorseCollection * seahorse_collection_new_for_predicate    (GcrCollection *base,
+                                                               SeahorsePredicate *predicate,
                                                                GDestroyNotify destroy_func);
 
 SeahorsePredicate *  seahorse_collection_get_predicate        (SeahorseCollection *self);
diff --git a/libseahorse/seahorse-context.c b/libseahorse/seahorse-context.c
index 5c84710..6f80f22 100644
--- a/libseahorse/seahorse-context.c
+++ b/libseahorse/seahorse-context.c
@@ -29,15 +29,11 @@
 
 #include "seahorse-bind.h"
 #include "seahorse-context.h"
-#include "seahorse-dns-sd.h"
 #include "seahorse-marshal.h"
 #include "seahorse-predicate.h"
 #include "seahorse-progress.h"
 #include "seahorse-registry.h"
 #include "seahorse-servers.h"
-#include "seahorse-transfer.h"
-#include "seahorse-unknown.h"
-#include "seahorse-unknown-source.h"
 #include "seahorse-util.h"
 
 #ifdef WITH_PGP
@@ -54,10 +50,8 @@
 /* The application main context */
 SeahorseContext* app_context = NULL;
 
+
 enum {
-    ADDED,
-    REMOVED,
-    CHANGED,
     DESTROY,
     LAST_SIGNAL
 };
@@ -78,11 +72,6 @@ G_DEFINE_TYPE (SeahorseContext, seahorse_context, G_TYPE_OBJECT);
  */
 
 struct _SeahorseContextPrivate {
-    GList *sources;                         /* Sources which add keys to this context */
-    GHashTable *auto_sources;               /* Automatically added sources (keyservers) */
-    GHashTable *objects_by_source;          /* See explanation above */
-    GHashTable *objects_by_type;            /* See explanation above */
-    SeahorseServiceDiscovery *discovery;    /* Adds sources from DNS-SD */
     gboolean in_destruction;                /* In destroy signal */
     GSettings *seahorse_settings;
     GSettings *crypto_pgp_settings;
@@ -91,62 +80,6 @@ struct _SeahorseContextPrivate {
 static void seahorse_context_dispose    (GObject *gobject);
 static void seahorse_context_finalize   (GObject *gobject);
 
-#ifdef WITH_KEYSERVER
-
-static void
-on_settings_keyservers_changed (GSettings *settings, gchar *key, gpointer user_data)
-{
-#ifdef WITH_PGP
-	SeahorseContext *self = SEAHORSE_CONTEXT (user_data);
-	SeahorseServerSource *source;
-	gchar **keyservers;
-	GHashTable *check;
-	const gchar *uri;
-	GHashTableIter iter;
-	guint i;
-
-	if (!self->pv->auto_sources)
-		return;
-
-	/* Make a light copy of the auto_source table */
-	check = g_hash_table_new (g_str_hash, g_str_equal);
-	g_hash_table_iter_init (&iter, self->pv->auto_sources);
-	while (g_hash_table_iter_next (&iter, (gpointer*)&uri, (gpointer*)&source))
-		g_hash_table_replace (check, (gpointer)uri, source);
-
-	/* Load and strip names from keyserver list */
-	keyservers = seahorse_servers_get_uris ();
-
-	for (i = 0; keyservers[i] != NULL; i++) {
-		uri = keyservers[i];
-
-		/* If we don't have a keysource then add it */
-		if (!g_hash_table_lookup (self->pv->auto_sources, uri)) {
-			source = seahorse_server_source_new (uri);
-			if (source != NULL) {
-				seahorse_context_take_source (self, SEAHORSE_SOURCE (source));
-				g_hash_table_replace (self->pv->auto_sources, g_strdup (uri), source);
-			}
-		}
-
-		/* Mark this one as present */
-		g_hash_table_remove (check, uri);
-	}
-
-	/* Now remove any extras */
-	g_hash_table_iter_init (&iter, check);
-	while (g_hash_table_iter_next (&iter, (gpointer*)&uri, (gpointer*)&source)) {
-		g_hash_table_remove (self->pv->auto_sources, uri);
-		seahorse_context_remove_source (self, SEAHORSE_SOURCE (source));
-	}
-
-	g_hash_table_destroy (check);
-	g_strfreev (keyservers);
-#endif /* WITH_PGP */
-}
-
-#endif /* WITH_KEYSERVER */
-
 static void
 seahorse_context_constructed (GObject *obj)
 {
@@ -158,27 +91,11 @@ seahorse_context_constructed (GObject *obj)
 
 	app_context = self;
 
-	/* DNS-SD discovery */
-	self->pv->discovery = seahorse_service_discovery_new ();
-
-	/* Automatically added remote key sources */
-	self->pv->auto_sources = g_hash_table_new_full (g_str_hash, g_str_equal,
-	                                                g_free, NULL);
-
 	self->pv->seahorse_settings = g_settings_new ("org.gnome.seahorse");
 
 #ifdef WITH_PGP
 	/* This is installed by gnome-keyring */
 	self->pv->crypto_pgp_settings = g_settings_new ("org.gnome.crypto.pgp");
-
-#ifdef WITH_KEYSERVER
-	g_signal_connect (self->pv->crypto_pgp_settings, "changed::keyservers",
-	                  G_CALLBACK (on_settings_keyservers_changed), self);
-
-	/* Initial loading */
-	on_settings_keyservers_changed (self->pv->crypto_pgp_settings, "keyservers", self);
-#endif
-
 #endif
 }
 /**
@@ -189,24 +106,12 @@ seahorse_context_constructed (GObject *obj)
 static void
 seahorse_context_class_init (SeahorseContextClass *klass)
 {
-    GObjectClass *gobject_class;
-    
-    seahorse_context_parent_class = g_type_class_peek_parent (klass);
-    gobject_class = G_OBJECT_CLASS (klass);
+    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
     gobject_class->constructed = seahorse_context_constructed;
     gobject_class->dispose = seahorse_context_dispose;
     gobject_class->finalize = seahorse_context_finalize;
 
-    signals[ADDED] = g_signal_new ("added", SEAHORSE_TYPE_CONTEXT, 
-                G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SeahorseContextClass, added),
-                NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, SEAHORSE_TYPE_OBJECT);
-    signals[REMOVED] = g_signal_new ("removed", SEAHORSE_TYPE_CONTEXT, 
-                G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SeahorseContextClass, removed),
-                NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, SEAHORSE_TYPE_OBJECT);    
-    signals[CHANGED] = g_signal_new ("changed", SEAHORSE_TYPE_CONTEXT, 
-                G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SeahorseContextClass, changed),
-                NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, SEAHORSE_TYPE_OBJECT);    
     signals[DESTROY] = g_signal_new ("destroy", SEAHORSE_TYPE_CONTEXT,
                 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SeahorseContextClass, destroy),
                 NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
@@ -224,34 +129,9 @@ seahorse_context_init (SeahorseContext *sctx)
 {
     /* init private vars */
     sctx->pv = g_new0 (SeahorseContextPrivate, 1);
-
-    /* A list of sources */
-    sctx->pv->sources = NULL;
-    
-    /* A table of objects */
-    sctx->pv->objects_by_source = g_hash_table_new_full (g_direct_hash, g_direct_equal, 
-                                                         NULL, g_object_unref);
-    
-    sctx->pv->objects_by_type = g_hash_table_new_full (g_direct_hash, g_direct_equal, 
-                                                       NULL, NULL);
 }
 
 /**
-* object: ignored
-* value: the value to prepend
-* user_data: GList ** to prepend to
-*
-* Prepends #value to #user_data
-*
-**/
-static void
-hash_to_ref_list (gpointer object, gpointer value, gpointer user_data)
-{
-	*((GList**)user_data) = g_list_prepend (*((GList**)user_data), g_object_ref (value));
-}
-
-
-/**
 * gobject: the object to dispose (#SeahorseContext)
 *
 * release all references
@@ -260,44 +140,7 @@ hash_to_ref_list (gpointer object, gpointer value, gpointer user_data)
 static void
 seahorse_context_dispose (GObject *gobject)
 {
-    SeahorseContext *sctx;
-    GList *objects, *l;
-    
-    sctx = SEAHORSE_CONTEXT (gobject);
-    
-    /* Release all the objects */
-    objects = NULL;
-    g_hash_table_foreach (sctx->pv->objects_by_source, hash_to_ref_list, &objects);
-    for (l = objects; l; l = g_list_next (l)) {
-            seahorse_context_remove_object (sctx, l->data);
-            g_object_unref (G_OBJECT (l->data));
-    }
-    g_list_free (objects);
-
-#ifdef WITH_KEYSERVER
-	if (sctx->pv->crypto_pgp_settings) {
-		g_signal_handlers_disconnect_by_func (sctx->pv->crypto_pgp_settings,
-		                                      on_settings_keyservers_changed, sctx);
-		g_clear_object (&sctx->pv->crypto_pgp_settings);
-	}
-#endif
-	g_clear_object (&sctx->pv->seahorse_settings);
-
-    /* Auto sources */
-    if (sctx->pv->auto_sources) 
-        g_hash_table_destroy (sctx->pv->auto_sources);
-    sctx->pv->auto_sources = NULL;
-        
-    /* DNS-SD */    
-    if (sctx->pv->discovery) 
-        g_object_unref (sctx->pv->discovery);
-    sctx->pv->discovery = NULL;
-        
-    /* Release all the sources */
-    for (l = sctx->pv->sources; l; l = g_list_next (l))
-        g_object_unref (SEAHORSE_SOURCE (l->data));
-    g_list_free (sctx->pv->sources);
-    sctx->pv->sources = NULL;
+	SeahorseContext *sctx = SEAHORSE_CONTEXT (gobject);
 
 	if (!sctx->pv->in_destruction) {
 		sctx->pv->in_destruction = TRUE;
@@ -318,21 +161,16 @@ seahorse_context_dispose (GObject *gobject)
 static void
 seahorse_context_finalize (GObject *gobject)
 {
-    SeahorseContext *sctx = SEAHORSE_CONTEXT (gobject);
-    
-    /* Destroy the hash table */        
-    if (sctx->pv->objects_by_source)
-        g_hash_table_destroy (sctx->pv->objects_by_source);
-    if (sctx->pv->objects_by_type)
-        g_hash_table_destroy (sctx->pv->objects_by_type);
-    
-    /* Other stuff already done in dispose */
-    g_assert (sctx->pv->sources == NULL);
-    g_assert (sctx->pv->auto_sources == NULL);
-    g_assert (sctx->pv->discovery == NULL);
-    g_free (sctx->pv);
-    
-    G_OBJECT_CLASS (seahorse_context_parent_class)->finalize (gobject);
+	SeahorseContext *sctx = SEAHORSE_CONTEXT (gobject);
+	app_context = NULL;
+
+#ifdef WITH_KEYSERVER
+	g_clear_object (&sctx->pv->crypto_pgp_settings);
+#endif
+	g_clear_object (&sctx->pv->seahorse_settings);
+
+	g_free (sctx->pv);
+	G_OBJECT_CLASS (seahorse_context_parent_class)->finalize (gobject);
 }
 
 /**
@@ -375,1263 +213,6 @@ seahorse_context_destroy (SeahorseContext *sctx)
 	g_return_if_fail (sctx == app_context);
 	g_object_run_dispose (G_OBJECT (sctx));
 	g_object_unref (sctx);
-	app_context = NULL;
-}
-
-/**
-* sctx: #SeahorseContext to add the source to
-* sksrc: #SeahorseSource to add
-*
-* Adds the source to the context
-*
-* Returns TRUE if the source was added, FALSE if it was already there
-**/
-static gboolean                
-take_source (SeahorseContext *sctx, SeahorseSource *sksrc)
-{
-	g_return_val_if_fail (SEAHORSE_IS_SOURCE (sksrc), FALSE);
-	if (!g_list_find (sctx->pv->sources, sksrc)) {
-		sctx->pv->sources = g_list_append (sctx->pv->sources, sksrc);
-		return TRUE;
-	}
-	
-	return FALSE;
-}
-
-/**
- * seahorse_context_take_source:
- * @sctx: A context to add a source to, can be NULL
- * @sksrc: The source to add
- *
- * Adds @sksrc to the @sctx. If @sctx is NULL it will use the application context.
- *
- */
-void                
-seahorse_context_take_source (SeahorseContext *sctx, SeahorseSource *sksrc)
-{
-	g_return_if_fail (SEAHORSE_IS_SOURCE (sksrc));
-    
-	if (!sctx)
-		sctx = seahorse_context_instance ();
-	g_return_if_fail (SEAHORSE_IS_CONTEXT (sctx));
-
-	take_source (sctx, sksrc);
-}
-
-/**
- * seahorse_context_add_source:
- * @sctx: A context to add a source to, can be NULL
- * @sksrc: The source to add
- *
- * Adds @sksrc to the @sctx. If @sctx is NULL it will use the application context.
- * It also adds a reference to the new added source.
- */
-void
-seahorse_context_add_source (SeahorseContext *sctx, SeahorseSource *sksrc)
-{
-	g_return_if_fail (SEAHORSE_IS_SOURCE (sksrc));
-    
-	if (!sctx)
-		sctx = seahorse_context_instance ();
-	g_return_if_fail (SEAHORSE_IS_CONTEXT (sctx));
-
-	if (take_source (sctx, sksrc))
-		g_object_ref (sksrc);
-}
-    
-/**
- * seahorse_context_remove_source:
- * @sctx: Context to remove objects from
- * @sksrc: The source to remove
- *
- * Remove all objects from source @sksrc from the #SeahorseContext @sctx
- *
- */
-void
-seahorse_context_remove_source (SeahorseContext *sctx, SeahorseSource *sksrc)
-{
-    GList *l, *objects;
-    
-    g_return_if_fail (SEAHORSE_IS_SOURCE (sksrc));
-
-    if (!sctx)
-        sctx = seahorse_context_instance ();
-    g_return_if_fail (SEAHORSE_IS_CONTEXT (sctx));
-
-    if (!g_list_find (sctx->pv->sources, sksrc))
-        return;
-
-    /* Remove all objects from this source */    
-    objects = seahorse_context_get_objects (sctx, sksrc);
-    for (l = objects; l; l = g_list_next (l)) 
-        seahorse_context_remove_object (sctx, SEAHORSE_OBJECT (l->data));
-    
-    /* Remove the source itself */
-    sctx->pv->sources = g_list_remove (sctx->pv->sources, sksrc);
-    g_object_unref (sksrc);
-}
-
-/**
- * seahorse_context_find_source:
- * @sctx: A #SeahorseContext
- * @ktype: A seahorse tag (SEAHORSE_TAG_INVALID is wildcard)
- * @location: A location (SEAHORSE_LOCATION_INVALID is wildcard)
- *
- * Finds a context where @ktype and @location match
- *
- * Returns: The context
- */
-SeahorseSource*  
-seahorse_context_find_source (SeahorseContext *sctx, GQuark ktype,
-                              SeahorseLocation location)
-{
-    SeahorseSource *ks;
-    GList *l;
-    
-    if (!sctx)
-        sctx = seahorse_context_instance ();
-    g_return_val_if_fail (SEAHORSE_IS_CONTEXT (sctx), NULL);
-
-    for (l = sctx->pv->sources; l; l = g_list_next (l)) {
-        ks = SEAHORSE_SOURCE (l->data);
-        
-        if (ktype != SEAHORSE_TAG_INVALID && 
-            seahorse_source_get_tag (ks) != ktype)
-            continue;
-        
-        if (location != SEAHORSE_LOCATION_INVALID && 
-            seahorse_source_get_location (ks) != location)
-            continue;
-        
-        return ks;
-    }
-    
-    /* If we don't have an unknown source for this type, create it */
-    if (location == SEAHORSE_LOCATION_MISSING && location != SEAHORSE_TAG_INVALID) {
-        ks = SEAHORSE_SOURCE (seahorse_unknown_source_new (ktype));
-        seahorse_context_add_source (sctx, ks);
-        return ks;
-    }
-    
-    return NULL;
-}
-
-
-/**
-* seahorse_context_find_sources:
-* @sctx: the context to work with
-* @ktype: the type of the key to match. Or SEAHORSE_TAG_INVALID
-* @location: the location to match. Or SEAHORSE_LOCATION_INVALID
-*
-* Returns: A list of seahorse sources matching @ktype and @location as #GList. Must
-*  be freed with #g_list_free
-*/
-GList*
-seahorse_context_find_sources (SeahorseContext *sctx, GQuark ktype,
-                               SeahorseLocation location)
-{
-    SeahorseSource *ks;
-    GList *sources = NULL;
-    GList *l;
-    
-    if (!sctx)
-        sctx = seahorse_context_instance ();
-    g_return_val_if_fail (SEAHORSE_IS_CONTEXT (sctx), NULL);
-
-    for (l = sctx->pv->sources; l; l = g_list_next (l)) {
-        ks = SEAHORSE_SOURCE (l->data);
-        
-        if (ktype != SEAHORSE_TAG_INVALID && 
-            seahorse_source_get_tag (ks) != ktype)
-            continue;
-        
-        if (location != SEAHORSE_LOCATION_INVALID && 
-            seahorse_source_get_location (ks) != location)
-            continue;
-        
-        sources = g_list_append (sources, ks);
-    }
-    
-    return sources;
-}
-
-/**
- * seahorse_context_remote_source:
- * @sctx: the context to add the source to (can be NULL)
- * @uri: An URI to add as remote source
- *
- * Add a remote source to the Context @sctx. If it already exists, the source
- * object will be returned.
- *
- * Returns: The #SeahorseSource with this URI
- */
-SeahorseSource*  
-seahorse_context_remote_source (SeahorseContext *sctx, const gchar *uri)
-{
-    SeahorseSource *ks = NULL;
-    gboolean found = FALSE;
-    gchar *ks_uri;
-    GList *l;
-    
-    g_return_val_if_fail (uri && *uri, NULL);
-
-    if (!sctx)
-        sctx = seahorse_context_instance ();
-    g_return_val_if_fail (SEAHORSE_IS_CONTEXT (sctx), NULL);
-
-    for (l = sctx->pv->sources; l; l = g_list_next (l)) {
-        ks = SEAHORSE_SOURCE (l->data);
-        
-        if (seahorse_source_get_location (ks) != SEAHORSE_LOCATION_REMOTE)
-            continue;
-        
-        g_object_get (ks, "uri", &ks_uri, NULL);
-        if (ks_uri && g_str_equal (ks_uri, uri)) 
-            found = TRUE;
-        g_free (ks_uri);
-        
-        if (found)
-            return ks;
-    }
-    
-    /* TODO: We need to decouple this properly */
-#ifdef WITH_KEYSERVER
-#ifdef WITH_PGP
-    /* Auto generate one if possible */
-    if (sctx->pv->auto_sources) {
-        ks = SEAHORSE_SOURCE (seahorse_server_source_new (uri));
-        if (ks != NULL) {
-            seahorse_context_take_source (sctx, ks);
-            g_hash_table_replace (sctx->pv->auto_sources, g_strdup (uri), ks);
-        }
-    }
-#endif /* WITH_PGP */
-#endif /* WITH_KEYSERVER */	
-    
-    return ks;
-}
-
-
-/**
-* sobj: SeahorseObject, sending the signal
-* spec: ignored
-* sctx: The instance to emit the signal on (#SeahorseContext)
-*
-* Emits a changed signal.
-*
-**/
-static void
-object_notify (SeahorseObject *sobj, GParamSpec *spec, SeahorseContext *sctx)
-{
-	g_signal_emit (sctx, signals[CHANGED], 0, sobj);
-}
-
-/**
-* sksrc: a #SeahorseSource, part of the hash
-* id: an id, part of the hash
-*
-* Creates a hash out of @sksrc and @id
-*
-* Returns an int stored in a pointer, representing the hash
-**/
-static gpointer                 
-hashkey_by_source (SeahorseSource *sksrc, GQuark id)
-
-{
-    return GINT_TO_POINTER (g_direct_hash (sksrc) ^ 
-                            g_str_hash (g_quark_to_string (id)));
-}
-
-/**
-* a: the first #SeahorseObject
-* b: the second #SeahorseObject
-*
-* Compares the locations of the two objects
-*
-* Returns 0 if a==b, -1 or 1 on difference
-**/
-static gint
-sort_by_location (gconstpointer a, gconstpointer b)
-{
-    guint aloc, bloc;
-    
-    g_assert (SEAHORSE_IS_OBJECT (a));
-    g_assert (SEAHORSE_IS_OBJECT (b));
-    
-    aloc = seahorse_object_get_location (SEAHORSE_OBJECT (a));
-    bloc = seahorse_object_get_location (SEAHORSE_OBJECT (b));
-    
-    if (aloc == bloc)
-        return 0;
-    return aloc > bloc ? -1 : 1;
-}
-
-/**
-* sctx: The seahorse context to manipulate
-* sobj: The object to add/remove
-* add: TRUE if the object should be added
-*
-* Either adds or removes an object from sctx->pv->objects_by_type.
-* The new list will be sorted by location.
-*
-**/
-static void
-setup_objects_by_type (SeahorseContext *sctx, SeahorseObject *sobj, gboolean add)
-{
-    GList *l, *objects = NULL;
-    SeahorseObject *aobj, *next;
-    gpointer kt = GUINT_TO_POINTER (seahorse_object_get_id (sobj));
-    gboolean first;
-    
-    /* Get current set of objects in this tag/id */
-    if (add)
-        objects = g_list_prepend (objects, sobj);
-    
-    for (aobj = g_hash_table_lookup (sctx->pv->objects_by_type, kt); 
-         aobj; aobj = seahorse_object_get_preferred (aobj))
-    {
-        if (aobj != sobj)
-            objects = g_list_prepend (objects, aobj);
-    }
-    
-    /* No objects just remove */
-    if (!objects) {
-        g_hash_table_remove (sctx->pv->objects_by_type, kt);
-        return;
-    }
-
-    /* Sort and add back */
-    objects = g_list_sort (objects, sort_by_location);
-    for (l = objects, first = TRUE; l; l = g_list_next (l), first = FALSE) {
-        
-        aobj = SEAHORSE_OBJECT (l->data);
-        
-        /* Set first as start of list */
-        if (first)
-            g_hash_table_replace (sctx->pv->objects_by_type, kt, aobj);
-            
-        /* Set next one as preferred */
-        else {
-            next = g_list_next (l) ? SEAHORSE_OBJECT (g_list_next (l)->data) : NULL;
-            seahorse_object_set_preferred (aobj, next);
-        }
-    }
-    
-    g_list_free (objects);
-}
-
-/**
- * seahorse_context_add_object:
- * @sctx: The context to add the object to
- * @sobj: The object to add
- *
- * Adds @sobj to @sctx. References @sobj
- *
- */
-void
-seahorse_context_add_object (SeahorseContext *sctx, SeahorseObject *sobj)
-{
-    if (!sctx)
-        sctx = seahorse_context_instance ();
-    g_return_if_fail (SEAHORSE_IS_CONTEXT (sctx));
-
-    g_object_ref (sobj);
-    seahorse_context_take_object (sctx, sobj);
-}
-
-/**
- * seahorse_context_take_object:
- * @sctx: The #SeahorseContext context to add an object to
- * @sobj: The #SeahorseObject object to add
- *
- * Adds @sobj to @sctx. If a similar object exists, it will be overwritten.
- * Emits the "added" signal.
- */
-void
-seahorse_context_take_object (SeahorseContext *sctx, SeahorseObject *sobj)
-{
-    gpointer ks;
-    
-    if (!sctx)
-        sctx = seahorse_context_instance ();
-    g_return_if_fail (SEAHORSE_IS_CONTEXT (sctx));
-    g_return_if_fail (SEAHORSE_IS_OBJECT (sobj));
-    g_return_if_fail (seahorse_object_get_id (sobj) != 0);
-    
-    ks = hashkey_by_source (seahorse_object_get_source (sobj), 
-                            seahorse_object_get_id (sobj));
-    
-    g_return_if_fail (!g_hash_table_lookup (sctx->pv->objects_by_source, ks));
-
-    g_object_ref (sobj);
-
-    g_object_set (sobj, "context", sctx, NULL);
-    g_hash_table_replace (sctx->pv->objects_by_source, ks, sobj);
-    setup_objects_by_type (sctx, sobj, TRUE);
-    g_signal_emit (sctx, signals[ADDED], 0, sobj);
-    g_object_unref (sobj);
-    
-    g_signal_connect (sobj, "notify", G_CALLBACK (object_notify), sctx);
-}
-
-/**
- * seahorse_context_get_count:
- * @sctx: The context. If NULL is passed it will take the application context
- *
- *
- *
- * Returns: The number of objects in this context
- */
-guint
-seahorse_context_get_count (SeahorseContext *sctx)
-{
-    if (!sctx)
-        sctx = seahorse_context_instance ();
-    g_return_val_if_fail (SEAHORSE_IS_CONTEXT (sctx), 0);
-    return g_hash_table_size (sctx->pv->objects_by_source);
-}
-
-/**
- * seahorse_context_get_object:
- * @sctx: The #SeahorseContext to look in
- * @sksrc: The source to match
- * @id: the id to match
- *
- * Finds the object with the source @sksrc and @id in the context and returns it
- *
- * Returns: The matching object
- */
-SeahorseObject*        
-seahorse_context_get_object (SeahorseContext *sctx, SeahorseSource *sksrc,
-                             GQuark id)
-{
-    gconstpointer k;
-    
-    if (!sctx)
-        sctx = seahorse_context_instance ();
-    g_return_val_if_fail (SEAHORSE_IS_CONTEXT (sctx), NULL);
-    g_return_val_if_fail (SEAHORSE_IS_SOURCE (sksrc), NULL);
-    
-    k = hashkey_by_source (sksrc, id);
-    return SEAHORSE_OBJECT (g_hash_table_lookup (sctx->pv->objects_by_source, k));
-}
-
-/**
- * ObjectMatcher:
- * @kp: A #SeahorseObjectPredicate to compare an object to
- * @many: TRUE if there can be several matches
- * @func: A function to call for every match
- * @user_data: user data to pass to the function
- *
- *
- **/
-typedef struct _ObjectMatcher {
-	SeahorsePredicate *kp;
-	gboolean many;
-	SeahorseObjectFunc func;
-	gpointer user_data;
-} ObjectMatcher;
-
-/**
- * find_matching_objects:
- * @key: ignored
- * @sobj: the object to match
- * @km: an #ObjectMatcher
- *
- * Calls km->func for every matched object
- *
- * Returns: TRUE if the search terminates, FALSE if there could be another
- * match or nothing was found
- */
-static gboolean
-find_matching_objects (gpointer key, SeahorseObject *sobj, ObjectMatcher *km)
-{
-	gboolean matched;
-
-	if (km->kp && seahorse_predicate_match (km->kp, SEAHORSE_OBJECT (sobj))) {
-		matched = TRUE;
-		(km->func) (sobj, km->user_data);
-	}
-
-	/* Terminate search */
-	if (!km->many && matched)
-		return TRUE;
-
-	/* Keep going */
-	return FALSE;
-}
-
-/**
-* object: A #SeahorseObject to add to the list
-* user_data: a #GList to add the object to
-*
-* Does not return anything....
-*
-**/
-static void
-add_object_to_list (SeahorseObject *object, gpointer user_data)
-{
-	GList** list = (GList**)user_data;
-	*list = g_list_prepend (*list, object);
-}
-
-/**
- * seahorse_context_find_objects_full:
- * @self: The #SeahorseContext to match objects in
- * @pred: #SeahorseObjectPredicate containing some data to match
- *
- * Finds matching objects and adds them to the list
- *
- * Returns: a #GList list containing the matching objects
- */
-GList*
-seahorse_context_find_objects_full (SeahorseContext *self,
-                                    SeahorsePredicate *pred)
-{
-	GList *list = NULL;
-	ObjectMatcher km;
-
-	if (!self)
-		self = seahorse_context_instance ();
-	g_return_val_if_fail (SEAHORSE_IS_CONTEXT (self), NULL);
-	g_return_val_if_fail (pred, NULL);
-
-	memset (&km, 0, sizeof (km));
-	km.kp = pred;
-	km.many = TRUE;
-	km.func = add_object_to_list;
-	km.user_data = &list;
-
-	g_hash_table_find (self->pv->objects_by_source, (GHRFunc)find_matching_objects, &km);
-	return list; 
-}
-
-/**
- * seahorse_context_for_objects_full:
- * @self: #SeahorseContext to work with
- * @pred: #SeahorseObjectPredicate to match
- * @func: Function to call for matching objects
- * @user_data: Data to pass to this function
- *
- * Calls @func for every object in @self matching the criteria in @pred. @user_data
- * is passed to this function
- */
-void
-seahorse_context_for_objects_full (SeahorseContext *self,
-                                   SeahorsePredicate *pred,
-                                   SeahorseObjectFunc func,
-                                   gpointer user_data)
-{
-	ObjectMatcher km;
-
-	if (!self)
-		self = seahorse_context_instance ();
-	g_return_if_fail (SEAHORSE_IS_CONTEXT (self));
-	g_return_if_fail (pred);
-	g_return_if_fail (func);
-
-	memset (&km, 0, sizeof (km));
-	km.kp = pred;
-	km.many = TRUE;
-	km.func = func;
-	km.user_data = user_data;
-
-	g_hash_table_find (self->pv->objects_by_source, (GHRFunc)find_matching_objects, &km);
-}
-
-/**
- * seahorse_context_get_objects:
- * @self: A #SeahorseContext to find objects in
- * @source: A #SeahorseSource that must match
- *
- *
- *
- * Returns: A #GList of objects from @self that match the source @source
- */
-GList*
-seahorse_context_get_objects (SeahorseContext *self, SeahorseSource *source)
-{
-	SeahorsePredicate pred;
-
-	if (!self)
-		self = seahorse_context_instance ();
-	g_return_val_if_fail (SEAHORSE_IS_CONTEXT (self), NULL);
-	g_return_val_if_fail (source == NULL || SEAHORSE_IS_SOURCE (source), NULL);
-
-	seahorse_predicate_clear (&pred);
-	pred.source = source;
-	
-	return seahorse_context_find_objects_full (self, &pred);
-}
-
-/**
- * seahorse_context_find_object:
- * @sctx: The #SeahorseContext to work with (can be NULL)
- * @id: The id to look for
- * @location: The location to look for (at least)
- *
- * Finds the object with the id @id at location @location or better.
- * Local is better than remote...
- *
- * Returns: the matching #SeahorseObject or NULL if none is found
- */
-SeahorseObject*        
-seahorse_context_find_object (SeahorseContext *sctx, GQuark id, SeahorseLocation location)
-{
-    SeahorseObject *sobj; 
-
-    if (!sctx)
-        sctx = seahorse_context_instance ();
-    g_return_val_if_fail (SEAHORSE_IS_CONTEXT (sctx), NULL);
-
-    sobj = (SeahorseObject*)g_hash_table_lookup (sctx->pv->objects_by_type, GUINT_TO_POINTER (id));
-    while (sobj) {
-        
-        /* If at the end and no more objects in list, return */
-        if (location == SEAHORSE_LOCATION_INVALID && !seahorse_object_get_preferred (sobj))
-            return sobj;
-        
-        if (location >= seahorse_object_get_location (sobj))
-            return sobj;
-        
-        /* Look down the list for this location */
-        sobj = seahorse_object_get_preferred (sobj);
-    }
-    
-    return NULL;
-}
-
-
-/**
- * seahorse_context_find_objects:
- * @sctx: A #SeahorseContext to look in (can be NULL)
- * @ktype: The tag to look for
- * @usage: the usage (#SeahorseUsage)
- * @location: the location to look for
- *
- *
- *
- * Returns: A list of matching objects
- */
-GList*
-seahorse_context_find_objects (SeahorseContext *sctx, GQuark ktype, 
-                               SeahorseUsage usage, SeahorseLocation location)
-{
-    SeahorsePredicate pred;
-    memset (&pred, 0, sizeof (pred));
-
-    if (!sctx)
-        sctx = seahorse_context_instance ();
-    g_return_val_if_fail (SEAHORSE_IS_CONTEXT (sctx), NULL);
-    
-    pred.tag = ktype;
-    pred.usage = usage;
-    pred.location = location;
-    
-    return seahorse_context_find_objects_full (sctx, &pred);
-}
-
-/**
- * seahorse_context_remove_object:
- * @sctx: The #SeahorseContext (can be NULL)
- * @sobj: The #SeahorseObject to remove
- *
- * Removes the object from the context
- *
- */
-void 
-seahorse_context_remove_object (SeahorseContext *sctx, SeahorseObject *sobj)
-{
-    gconstpointer k;
-    
-    if (!sctx)
-        sctx = seahorse_context_instance ();
-    g_return_if_fail (SEAHORSE_IS_CONTEXT (sctx));
-    g_return_if_fail (SEAHORSE_IS_OBJECT (sobj));
-    g_return_if_fail (seahorse_object_get_id (sobj) != 0);
-    
-    k = hashkey_by_source (seahorse_object_get_source (sobj), 
-                           seahorse_object_get_id (sobj));
-    
-    if (g_hash_table_lookup (sctx->pv->objects_by_source, k)) {
-        g_return_if_fail (seahorse_object_get_context (sobj) == sctx);
-
-        g_object_ref (sobj);
-        g_signal_handlers_disconnect_by_func (sobj, object_notify, sctx);
-        g_object_set (sobj, "context", NULL, NULL);
-        g_hash_table_remove (sctx->pv->objects_by_source, k);
-        setup_objects_by_type (sctx, sobj, FALSE);
-        g_signal_emit (sctx, signals[REMOVED], 0, sobj);    
-        g_object_unref (sobj);
-    }
-}
-
-
-/* -----------------------------------------------------------------------------
- * DEPRECATED 
- */
-
-/**
- * seahorse_context_get_default_key:
- * @sctx: Current #SeahorseContext
- *
- * Returns: the PGP secret key that's the default key
- *
- * Deprecated: No replacement
- */
-SeahorseObject*
-seahorse_context_get_default_key (SeahorseContext *self)
-{
-	SeahorseObject *key = NULL;
-	gchar *keyid;
-
-	if (self == NULL)
-		self = seahorse_context_instance ();
-	g_return_val_if_fail (SEAHORSE_IS_CONTEXT (self), NULL);
-
-	if (self->pv->crypto_pgp_settings) {
-		keyid = g_settings_get_string (self->pv->crypto_pgp_settings, "default-key");
-		if (keyid != NULL && keyid[0]) {
-			key = seahorse_context_find_object (self, g_quark_from_string (keyid),
-			                                    SEAHORSE_LOCATION_LOCAL);
-		}
-		g_free (keyid);
-	}
-
-	return key;
-}
-
-/**
- * seahorse_context_get_discovery:
- * @sctx: #SeahorseContext object
- *
- * Gets the Service Discovery object for this context.
- *
- * Returns: The Service Discovery object.
- *
- * Deprecated: No replacement
- */
-SeahorseServiceDiscovery*
-seahorse_context_get_discovery (SeahorseContext *sctx)
-{
-    if (!sctx)
-        sctx = seahorse_context_instance ();
-    g_return_val_if_fail (SEAHORSE_IS_CONTEXT (sctx), NULL);
-    g_return_val_if_fail (sctx->pv->discovery != NULL, NULL);
-    
-    return sctx->pv->discovery;
-}
-
-static void
-on_source_refresh_load_ready (GObject *object, GAsyncResult *result, gpointer user_data)
-{
-	GError *error = NULL;
-
-	if (!seahorse_source_load_finish (SEAHORSE_SOURCE (object), result, &error)) {
-		g_message ("failed to refresh: %s", error->message);
-		g_clear_error (&error);
-	}
-}
-
-/**
- * seahorse_context_refresh_auto:
- * @sctx: A #SeahorseContext (can be NULL)
- *
- * Starts a new refresh operation
- *
- */
-void
-seahorse_context_refresh_auto (SeahorseContext *sctx)
-{
-	SeahorseSource *ks;
-	GList *l;
-
-	if (!sctx)
-		sctx = seahorse_context_instance ();
-	g_return_if_fail (SEAHORSE_IS_CONTEXT (sctx));
-
-	for (l = sctx->pv->sources; l; l = g_list_next (l)) {
-		ks = SEAHORSE_SOURCE (l->data);
-		if (seahorse_source_get_location (ks) == SEAHORSE_LOCATION_LOCAL)
-			seahorse_source_load_async (ks, NULL,
-			                            on_source_refresh_load_ready, NULL);
-	}
-}
-
-typedef struct {
-	GCancellable *cancellable;
-	gint num_searches;
-	GList *objects;
-} seahorse_context_search_remote_closure;
-
-static void
-seahorse_context_search_remote_free (gpointer user_data)
-{
-	seahorse_context_search_remote_closure *closure = user_data;
-	g_clear_object (&closure->cancellable);
-	g_list_free (closure->objects);
-	g_free (closure);
-}
-
-static void
-on_source_search_ready (GObject *source,
-                        GAsyncResult *result,
-                        gpointer user_data)
-{
-	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	seahorse_context_search_remote_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
-	GError *error = NULL;
-	GList *objects;
-
-	g_return_if_fail (closure->num_searches > 0);
-
-	objects = seahorse_source_search_finish (SEAHORSE_SOURCE (source), result, &error);
-	closure->objects = g_list_concat (closure->objects, objects);
-
-	if (error != NULL)
-		g_simple_async_result_take_error (res, error);
-
-	closure->num_searches--;
-	seahorse_progress_end (closure->cancellable, GINT_TO_POINTER (closure->num_searches));
-
-	if (closure->num_searches == 0)
-		g_simple_async_result_complete (res);
-
-	g_object_unref (user_data);
-}
-
-void
-seahorse_context_search_remote_async (SeahorseContext *self,
-                                      const gchar *search,
-                                      GCancellable *cancellable,
-                                      GAsyncReadyCallback callback,
-                                      gpointer user_data)
-{
-	seahorse_context_search_remote_closure *closure;
-	GSimpleAsyncResult *res;
-	SeahorseSource *source;
-	GHashTable *servers = NULL;
-	gchar **names;
-	gchar *uri;
-	GList *l;
-	guint i;
-
-	if (self == NULL)
-		self = seahorse_context_instance ();
-
-	g_return_if_fail (SEAHORSE_IS_CONTEXT (self));
-
-	/* Get a list of all selected key servers */
-	names = g_settings_get_strv (self->pv->seahorse_settings, "last-search-servers");
-	if (names != NULL && names[0] != NULL) {
-		servers = g_hash_table_new (g_str_hash, g_str_equal);
-		for (i = 0; names[i] != NULL; i++)
-			g_hash_table_insert (servers, names[i], GINT_TO_POINTER (TRUE));
-		g_strfreev (names);
-	}
-
-	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 seahorse_context_search_remote_async);
-	closure = g_new0 (seahorse_context_search_remote_closure, 1);
-	g_simple_async_result_set_op_res_gpointer (res, closure,
-	                                           seahorse_context_search_remote_free);
-	if (cancellable)
-		closure->cancellable = g_object_ref (cancellable);
-
-	for (l = self->pv->sources; l; l = g_list_next (l)) {
-		source = SEAHORSE_SOURCE (l->data);
-
-		if (seahorse_source_get_location (source) != SEAHORSE_LOCATION_REMOTE)
-			continue;
-
-		if (servers) {
-			g_object_get (source, "uri", &uri, NULL);
-			if (!g_hash_table_lookup (servers, uri)) {
-				g_free (uri);
-				continue;
-			}
-			g_free (uri);
-		}
-
-		seahorse_progress_prep_and_begin (closure->cancellable, GINT_TO_POINTER (closure->num_searches), NULL);
-		seahorse_source_search_async (source, search, closure->cancellable,
-		                              on_source_search_ready, g_object_ref (res));
-		closure->num_searches++;
-	}
-
-	if (closure->num_searches == 0)
-		g_simple_async_result_complete_in_idle (res);
-
-	g_object_unref (res);
-}
-
-GList *
-seahorse_context_search_remote_finish (SeahorseContext *self,
-                                       GAsyncResult *result,
-                                       GError **error)
-{
-	seahorse_context_search_remote_closure *closure;
-	GSimpleAsyncResult *res;
-	GList *results;
-
-	if (self == NULL)
-		self = seahorse_context_instance ();
-	g_return_val_if_fail (SEAHORSE_IS_CONTEXT (self), NULL);
-
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                      seahorse_context_search_remote_async), NULL);
-
-	res = G_SIMPLE_ASYNC_RESULT (result);
-
-	if (g_simple_async_result_propagate_error (res, error))
-		return NULL;
-
-	closure = g_simple_async_result_get_op_res_gpointer (res);
-	results = closure->objects;
-	closure->objects = NULL;
-
-	return results;
-}
-
-typedef struct {
-	GCancellable *cancellable;
-	gint num_transfers;
-} seahorse_context_transfer_closure;
-
-static void
-seahorse_context_transfer_free (gpointer user_data)
-{
-	seahorse_context_search_remote_closure *closure = user_data;
-	g_clear_object (&closure->cancellable);
-	g_free (closure);
-}
-
-static void
-on_source_transfer_ready (GObject *source,
-                          GAsyncResult *result,
-                          gpointer user_data)
-{
-	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	seahorse_context_transfer_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
-	GError *error = NULL;
-
-	g_return_if_fail (closure->num_transfers > 0);
-
-	seahorse_transfer_finish (result, &error);
-	if (error != NULL)
-		g_simple_async_result_take_error (res, error);
-
-	closure->num_transfers--;
-	seahorse_progress_end (closure->cancellable, GINT_TO_POINTER (closure->num_transfers));
-
-	if (closure->num_transfers == 0) {
-		g_simple_async_result_complete (res);
-	}
-
-	g_object_unref (user_data);
-}
-
-
-void
-seahorse_context_transfer_objects_async (SeahorseContext *self,
-                                         GList *objects,
-                                         SeahorseSource *to,
-                                         GCancellable *cancellable,
-                                         GAsyncReadyCallback callback,
-                                         gpointer user_data)
-{
-	seahorse_context_transfer_closure *closure;
-	SeahorseObject *object;
-	GSimpleAsyncResult *res;
-	SeahorseSource *from;
-	GQuark ktype;
-	GList *next, *l;
-	GList *ids = NULL;
-
-	if (self == NULL)
-		self = seahorse_context_instance ();
-	g_return_if_fail (SEAHORSE_IS_CONTEXT (self));
-
-	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 seahorse_context_transfer_objects_async);
-	closure = g_new0 (seahorse_context_transfer_closure, 1);
-	g_simple_async_result_set_op_res_gpointer (res, closure,
-	                                           seahorse_context_transfer_free);
-	if (cancellable)
-		closure->cancellable = g_object_ref (cancellable);
-
-	objects = g_list_copy (objects);
-
-	/* Sort by key source */
-	objects = seahorse_util_objects_sort (objects);
-
-	while (objects) {
-
-		/* break off one set (same keysource) */
-		next = seahorse_util_objects_splice (objects);
-
-		g_assert (SEAHORSE_IS_OBJECT (objects->data));
-		object = SEAHORSE_OBJECT (objects->data);
-
-		/* Export from this key source */
-		from = seahorse_object_get_source (object);
-		g_return_if_fail (from != NULL);
-		ktype = seahorse_source_get_tag (from);
-
-		/* Find a local keysource to import to */
-		if (!to) {
-			to = seahorse_context_find_source (self, ktype, SEAHORSE_LOCATION_LOCAL);
-			if (!to) {
-				/* TODO: How can we warn caller about this. Do we need to? */
-				g_warning ("couldn't find a local source for: %s",
-				           g_quark_to_string (ktype));
-			}
-		}
-
-		/* Make sure it's the same type */
-		if (ktype != seahorse_source_get_tag (to)) {
-			/* TODO: How can we warn caller about this. Do we need to? */
-			g_warning ("destination is not of type: %s",
-			           g_quark_to_string (ktype));
-		}
-
-		if (to != NULL && from != to) {
-
-			/* Build id list */
-			for (l = objects; l; l = g_list_next (l))
-				ids = g_list_prepend (ids, GUINT_TO_POINTER (seahorse_object_get_id (l->data)));
-			ids = g_list_reverse (ids);
-
-			/* Start a new transfer operation between the two sources */
-			seahorse_progress_prep_and_begin (cancellable, GINT_TO_POINTER (closure->num_transfers), NULL);
-			seahorse_transfer_async (from, to, ids, cancellable,
-			                         on_source_transfer_ready, g_object_ref (res));
-			closure->num_transfers++;
-
-			g_list_free (ids);
-			ids = NULL;
-		}
-
-		g_list_free (objects);
-		objects = next;
-	}
-
-	if (closure->num_transfers == 0)
-		g_simple_async_result_complete_in_idle (res);
-
-	g_object_unref (res);
-}
-
-gboolean
-seahorse_context_transfer_objects_finish (SeahorseContext *self,
-                                          GAsyncResult *result,
-                                          GError **error)
-{
-	GSimpleAsyncResult *res;
-
-	if (self == NULL)
-		self = seahorse_context_instance ();
-	g_return_val_if_fail (SEAHORSE_IS_CONTEXT (self), FALSE);
-
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                      seahorse_context_transfer_objects_async), FALSE);
-
-	res = G_SIMPLE_ASYNC_RESULT (result);
-
-	if (g_simple_async_result_propagate_error (res, error))
-		return FALSE;
-
-	return TRUE;
-}
-
-void
-seahorse_context_retrieve_objects_async (SeahorseContext *self,
-                                         GQuark ktype,
-                                         GList *ids,
-                                         SeahorseSource *to,
-                                         GCancellable *cancellable,
-                                         GAsyncReadyCallback callback,
-                                         gpointer user_data)
-{
-	seahorse_context_transfer_closure *closure;
-	GSimpleAsyncResult *res;
-	SeahorseSource *source;
-	GList *sources, *l;
-
-	if (self == NULL)
-		self = seahorse_context_instance ();
-	g_return_if_fail (SEAHORSE_IS_CONTEXT (self));
-
-	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 seahorse_context_retrieve_objects_async);
-	closure = g_new0 (seahorse_context_transfer_closure, 1);
-	g_simple_async_result_set_op_res_gpointer (res, closure,
-	                                           seahorse_context_transfer_free);
-	if (cancellable)
-		closure->cancellable = g_object_ref (cancellable);
-
-	if (to == NULL) {
-		to = seahorse_context_find_source (self, ktype, SEAHORSE_LOCATION_LOCAL);
-		if (to == NULL) {
-			/* TODO: How can we warn caller about this. Do we need to? */
-			g_warning ("couldn't find a local source for: %s",
-			           g_quark_to_string (ktype));
-		}
-	}
-
-	sources = seahorse_context_find_sources (self, ktype, SEAHORSE_LOCATION_REMOTE);
-	for (l = sources; to != NULL && l != NULL; l = g_list_next (l)) {
-		source = SEAHORSE_SOURCE (l->data);
-
-		/* Start a new transfer operation between the two key sources */
-		seahorse_progress_prep_and_begin (cancellable, GINT_TO_POINTER (closure->num_transfers), NULL);
-		seahorse_transfer_async (source, to, ids, cancellable,
-		                         on_source_transfer_ready, g_object_ref (res));
-		closure->num_transfers++;
-	}
-
-	if (closure->num_transfers == 0)
-		g_simple_async_result_complete_in_idle (res);
-
-	g_object_unref (res);
-}
-
-
-gboolean
-seahorse_context_retrieve_objects_finish  (SeahorseContext *self,
-                                           GAsyncResult *result,
-                                           GError **error)
-{
-	GSimpleAsyncResult *res;
-
-	if (self == NULL)
-		self = seahorse_context_instance ();
-	g_return_val_if_fail (SEAHORSE_IS_CONTEXT (self), FALSE);
-
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
-	                      seahorse_context_retrieve_objects_async), FALSE);
-
-	res = G_SIMPLE_ASYNC_RESULT (result);
-
-	if (g_simple_async_result_propagate_error (res, error))
-		return FALSE;
-
-	return TRUE;
-}
-
-GList*
-seahorse_context_discover_objects (SeahorseContext *self,
-                                   GQuark ktype,
-                                   GList *rawids,
-                                   GCancellable *cancellable)
-{
-	GList *robjects = NULL;
-	GQuark id = 0;
-	GList *todiscover = NULL;
-	GList *toimport = NULL;
-	SeahorseSource *source;
-	SeahorseObject* object;
-	SeahorseLocation loc;
-	GList *l;
-
-	if (self == NULL)
-		self = seahorse_context_instance ();
-	g_return_val_if_fail (SEAHORSE_IS_CONTEXT (self), NULL);
-
-	/* Check all the ids */
-	for (l = rawids; l != NULL; l = g_list_next (l)) {
-
-		id = seahorse_context_canonize_id (ktype, (gchar*)l->data);
-		if (!id) {
-			/* TODO: Try and match this partial id */
-			g_warning ("invalid id: %s", (gchar*)l->data);
-			continue;
-		}
-
-		/* Do we know about this object? */
-		object = seahorse_context_find_object (self, id, SEAHORSE_LOCATION_INVALID);
-
-		/* No such object anywhere, discover it */
-		if (object == NULL) {
-			todiscover = g_list_prepend (todiscover, GUINT_TO_POINTER (id));
-			id = 0;
-			continue;
-		}
-
-		/* Our return value */
-		robjects = g_list_prepend (robjects, object);
-
-		/* We know about this object, check where it is */
-		loc = seahorse_object_get_location (object);
-		g_assert (loc != SEAHORSE_LOCATION_INVALID);
-
-		/* Do nothing for local objects */
-		if (loc >= SEAHORSE_LOCATION_LOCAL)
-			continue;
-
-		/* Remote objects get imported */
-		else if (loc >= SEAHORSE_LOCATION_REMOTE)
-			toimport = g_list_prepend (toimport, object);
-
-		/* Searching objects are ignored */
-		else if (loc >= SEAHORSE_LOCATION_SEARCHING)
-			continue;
-
-		/* TODO: Should we try SEAHORSE_LOCATION_MISSING objects again? */
-	}
-
-	/* Start an import process on all toimport */
-	if (toimport) {
-		seahorse_context_transfer_objects_async (self, toimport, NULL,
-		                                         cancellable, NULL, NULL);
-
-		g_list_free (toimport);
-	}
-
-	/* Start a discover process on all todiscover */
-	if (todiscover != NULL &&
-	    g_settings_get_boolean (self->pv->seahorse_settings, "server-auto-retrieve")) {
-		seahorse_context_retrieve_objects_async (self, ktype, todiscover, NULL,
-		                                         cancellable, NULL, NULL);
-	}
-
-	/* Add unknown objects for all these */
-	source = seahorse_context_find_source (self, ktype, SEAHORSE_LOCATION_MISSING);
-	for (l = todiscover; l != NULL; l = g_list_next (l)) {
-		if (source) {
-			object = seahorse_unknown_source_add_object (SEAHORSE_UNKNOWN_SOURCE (source),
-			                                             GPOINTER_TO_UINT (l->data),
-			                                             cancellable);
-			robjects = g_list_prepend (robjects, object);
-		}
-	}
-
-	g_list_free (todiscover);
-
-	return robjects;
-}
-
-/**
- * seahorse_context_canonize_id:
- * @ktype: a keytype defining the canonization function
- * @id: The id to canonize
- *
- *
- *
- * Returns: A canonized GQuark
- */
-GQuark
-seahorse_context_canonize_id (GQuark ktype, const gchar *id)
-{
-	SeahorseCanonizeFunc canonize;
-
-	g_return_val_if_fail (id != NULL, 0);
-
-	canonize = seahorse_registry_lookup_function (NULL, "canonize", g_quark_to_string (ktype), NULL);
-	if (!canonize)
-		return 0;
-
-	return (canonize) (id);
 }
 
 GSettings *
diff --git a/libseahorse/seahorse-context.h b/libseahorse/seahorse-context.h
index 00b9a98..f3a3498 100644
--- a/libseahorse/seahorse-context.h
+++ b/libseahorse/seahorse-context.h
@@ -27,7 +27,6 @@
 #include <gtk/gtk.h>
 
 #include "seahorse-source.h"
-#include "seahorse-dns-sd.h"
 
 #define SEAHORSE_TYPE_CONTEXT			(seahorse_context_get_type ())
 #define SEAHORSE_CONTEXT(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_CONTEXT, SeahorseContext))
@@ -36,10 +35,6 @@
 #define SEAHORSE_IS_CONTEXT_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_CONTEXT))
 #define SEAHORSE_CONTEXT_GET_CLASS(obj)		(G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_CONTEXT, SeahorseContextClass))
 
-struct _SeahorseKey;
-struct _SeahorseObject;
-struct _SeahorsePredicate;
-
 typedef struct _SeahorseContext SeahorseContext;
 typedef struct _SeahorseContextClass SeahorseContextClass;
 typedef struct _SeahorseContextPrivate SeahorseContextPrivate;
@@ -47,31 +42,18 @@ typedef struct _SeahorseContextPrivate SeahorseContextPrivate;
 /**
  * SeahorseContext:
  * @parent: The parent #GtkObject
- * @is_daemon: a #gboolean indicating whether the context is being used in a
- *             program that is daemonized
- *
- * This is where all the action in a Seahorse process comes together.
  *
  * - Usually there's only one #SeahorseContext per process created by passing
  *   %SEAHORSE_CONTEXT_APP to seahorse_context_new(), and accessed via
  *   the %SCTX_APP macro.
- * - Retains the list of all valid struct _SeahorseObject objects.
- * - Has a collection of #SeahorseSource objects which add objects to the
- *   #SeahorseContext.
  *
  * Signals:
- *   added: A object was added to the context.
- *   removed: A object was removed from the context.
- *   changed: A object changed.
  *   destroy: The context was destroyed.
  */
 
 struct _SeahorseContext {
 	GObject parent;
 
-	/*< public >*/
-	gboolean is_daemon;
-
 	/*< private >*/
 	SeahorseContextPrivate  *pv;
 };
@@ -79,20 +61,6 @@ struct _SeahorseContext {
 struct _SeahorseContextClass {
 	GObjectClass parent_class;
 
-	/* signals --------------------------------------------------------- */
-
-	/* A object was added to this source */
-	void     (*added)              (SeahorseContext *self,
-	                                struct _SeahorseObject *sobj);
-
-	/* Removed a object from this source */
-	void     (*removed)            (SeahorseContext *self,
-	                                struct _SeahorseObject *sobj);
-
-	/* This object has changed */
-	void     (*changed)            (SeahorseContext *self,
-	                                struct _SeahorseObject *sobj);
-
 	void     (*destroy)            (SeahorseContext *self);
 };
 
@@ -109,116 +77,8 @@ void                seahorse_context_create                  (void);
 
 void                seahorse_context_destroy                 (SeahorseContext *self);
 
-#define             seahorse_context_is_daemon(ctx)          ((ctx)->is_daemon)
-
-void                seahorse_context_add_source              (SeahorseContext *self,
-                                                              SeahorseSource *sksrc);
-
-void                seahorse_context_take_source             (SeahorseContext *self,
-                                                              SeahorseSource *sksrc);
-
-void                seahorse_context_remove_source           (SeahorseContext *self,
-                                                              SeahorseSource *sksrc);
-
-SeahorseSource*     seahorse_context_find_source             (SeahorseContext *self,
-                                                              GQuark ktype,
-                                                              SeahorseLocation location);
-
-GList*             seahorse_context_find_sources             (SeahorseContext    *sctx,
-                                                              GQuark             ktype,
-                                                              SeahorseLocation   location);
-
-SeahorseSource*     seahorse_context_remote_source           (SeahorseContext *self,
-                                                              const gchar *uri);
-
-void                seahorse_context_add_object              (SeahorseContext *self,
-                                                              struct _SeahorseObject *sobj);
-
-void                seahorse_context_take_object             (SeahorseContext *self,
-                                                              struct _SeahorseObject *sobj);
-
-guint               seahorse_context_get_count               (SeahorseContext *self);
-
-struct _SeahorseObject*     seahorse_context_get_object      (SeahorseContext *self,
-                                                              SeahorseSource *sksrc,
-                                                              GQuark id);
-
-GList*              seahorse_context_get_objects             (SeahorseContext *self,
-                                                              SeahorseSource *sksrc);
-
-struct _SeahorseObject*     seahorse_context_find_object     (SeahorseContext *self,
-                                                              GQuark id,
-                                                              SeahorseLocation location);
-
-GList*              seahorse_context_find_objects            (SeahorseContext *self,
-                                                              GQuark ktype,
-                                                              SeahorseUsage usage,
-                                                              SeahorseLocation location);
-
-GList*              seahorse_context_find_objects_full       (SeahorseContext *self,
-                                                              struct _SeahorsePredicate *skpred);
-
-void                seahorse_context_for_objects_full        (SeahorseContext *self,
-                                                              struct _SeahorsePredicate *skpred,
-                                                              SeahorseObjectFunc func,
-                                                              gpointer user_data);
-
-void                seahorse_context_remove_object           (SeahorseContext *self,
-                                                              struct _SeahorseObject *sobj);
-
-SeahorseServiceDiscovery*
-                    seahorse_context_get_discovery           (SeahorseContext    *self);
-
-struct _SeahorseObject*   
-                    seahorse_context_get_default_key         (SeahorseContext    *self);
-
-void                seahorse_context_refresh_auto            (SeahorseContext *self);
-
-void                seahorse_context_search_remote_async     (SeahorseContext *self,
-                                                              const gchar *search,
-                                                              GCancellable *cancellable,
-                                                              GAsyncReadyCallback callback,
-                                                              gpointer user_data);
-
-GList *             seahorse_context_search_remote_finish    (SeahorseContext *self,
-                                                              GAsyncResult *result,
-                                                              GError **error);
-
-void                seahorse_context_transfer_objects_async  (SeahorseContext *self,
-                                                              GList *objects,
-                                                              SeahorseSource *to,
-                                                              GCancellable *cancellable,
-                                                              GAsyncReadyCallback callback,
-                                                              gpointer user_data);
-
-gboolean            seahorse_context_transfer_objects_finish (SeahorseContext *self,
-                                                              GAsyncResult *result,
-                                                              GError **error);
-
-void                seahorse_context_retrieve_objects_async  (SeahorseContext *self,
-                                                              GQuark ktype,
-                                                              GList *ids,
-                                                              SeahorseSource *to,
-                                                              GCancellable *cancellable,
-                                                              GAsyncReadyCallback callback,
-                                                              gpointer user_data);
-
-gboolean            seahorse_context_retrieve_objects_finish (SeahorseContext *self,
-                                                              GAsyncResult *result,
-                                                              GError **error);
-
-GList*              seahorse_context_discover_objects        (SeahorseContext *self,
-                                                              GQuark ktype,
-                                                              GList *rawids,
-                                                              GCancellable *cancellable);
-
-typedef GQuark     (*SeahorseCanonizeFunc)                   (const gchar *id);
-
-GQuark              seahorse_context_canonize_id             (GQuark ktype,
-                                                              const gchar *id);
-
-GSettings *         seahorse_context_settings           (SeahorseContext *self);
+GSettings *         seahorse_context_settings                (SeahorseContext *self);
 
-GSettings *         seahorse_context_pgp_settings       (SeahorseContext *self);
+GSettings *         seahorse_context_pgp_settings            (SeahorseContext *self);
 
 #endif /* __SEAHORSE_CONTEXT_H__ */
diff --git a/src/seahorse-key-manager-store.c b/libseahorse/seahorse-key-manager-store.c
similarity index 96%
rename from src/seahorse-key-manager-store.c
rename to libseahorse/seahorse-key-manager-store.c
index 4a7757c..f9a5b69 100644
--- a/src/seahorse-key-manager-store.c
+++ b/libseahorse/seahorse-key-manager-store.c
@@ -139,7 +139,7 @@ struct _SeahorseKeyManagerStorePriv {
     SeahorseKeyManagerStoreMode    filter_mode;
     gchar*                  filter_text;
     guint                   filter_stag;
-    
+
 	gchar *drag_destination;
 	GError *drag_error;
 	GList *drag_objects;
@@ -245,21 +245,21 @@ set_sort_to (SeahorseKeyManagerStore *skstore, const gchar *name)
     gint i, id = -1;
     GtkSortType ord = GTK_SORT_ASCENDING;
     const gchar* n;
-    
+
     g_return_if_fail (name != NULL);
-    
+
     /* Prefix with a minus means descending */
     if (name[0] == '-') {
         ord = GTK_SORT_DESCENDING;
         name++;
     }
-    
+
     /* Prefix with a plus means ascending */
     else if (name[0] == '+') {
         ord = GTK_SORT_ASCENDING;
         name++;
     }
-    
+
     /* Find the column sort id */
     for (i = N_COLS - 1; i >= 0 ; i--) {
         n = columns[i].user_data;
@@ -338,18 +338,18 @@ on_manager_settings_changed (GSettings *settings, const gchar *key, gpointer use
 }
 
 static GtkTreeViewColumn*
-append_text_column (SeahorseKeyManagerStore *skstore, GtkTreeView *view, 
+append_text_column (SeahorseKeyManagerStore *skstore, GtkTreeView *view,
                     const gchar *label, const gint index)
 {
     GtkTreeViewColumn *column;
     GtkCellRenderer *renderer;
-    
+
     renderer = gtk_cell_renderer_text_new ();
     g_object_set (renderer, "xpad", 3, NULL);
     column = gtk_tree_view_column_new_with_attributes (label, renderer, "text", index, NULL);
     gtk_tree_view_column_set_resizable (column, TRUE);
     gtk_tree_view_append_column (view, column);
-    
+
     return column;
 }
 
@@ -415,9 +415,9 @@ drag_begin (GtkWidget *widget, GdkDragContext *context, SeahorseKeyManagerStore
 
 	g_free (skstore->priv->drag_destination);
 	skstore->priv->drag_destination = NULL;
-	
+
 	g_clear_error (&skstore->priv->drag_error);
-	
+
 	g_list_free (skstore->priv->drag_objects);
 	skstore->priv->drag_objects = seahorse_key_manager_store_get_selected_objects (view);
 
@@ -458,15 +458,15 @@ export_to_text (SeahorseKeyManagerStore *skstore,
 
 	if (ret) {
 		seahorse_debug ("setting selection text");
-		gtk_selection_data_set_text (selection_data, 
-		                             g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (output)), 
+		gtk_selection_data_set_text (selection_data,
+		                             g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (output)),
 		                             g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (output)));
 	} else {
-		g_message ("error occurred on export: %s", 
-		           skstore->priv->drag_error && skstore->priv->drag_error->message ? 
+		g_message ("error occurred on export: %s",
+		           skstore->priv->drag_error && skstore->priv->drag_error->message ?
 		                      skstore->priv->drag_error->message : "");
 	}
-	
+
 	g_object_unref (output);
 	return ret;
 }
@@ -485,16 +485,16 @@ export_to_filename (SeahorseKeyManagerStore *skstore, const gchar *filename)
 	ret = FALSE;
 	g_return_val_if_fail (skstore->priv->drag_objects, FALSE);
 	keys = g_list_copy (skstore->priv->drag_objects);
-	
+
 	uri = seahorse_util_uri_unique (filename);
 
 	/* Create output file */
 	file = g_file_new_for_uri (uri);
 	g_free (uri);
-	output = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, 
+	output = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE,
 	                                          NULL, &skstore->priv->drag_error));
 	g_object_unref (file);
-	
+
 	if (output) {
 		/* This modifies and frees keys */
 		ret = seahorse_source_export_auto_wait (keys, output, &skstore->priv->drag_error) &&
@@ -502,44 +502,44 @@ export_to_filename (SeahorseKeyManagerStore *skstore, const gchar *filename)
 
 		g_object_unref (output);
 	}
-	
+
 	return ret;
 }
 
 static gboolean
-drag_data_get (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, 
+drag_data_get (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data,
                guint info, guint time, SeahorseKeyManagerStore *skstore)
 {
 	gchar *destination;
 	gboolean ret;
 
 	seahorse_debug ("drag_data_get %d -->", info);
-	
+
 	g_return_val_if_fail (skstore->priv->drag_objects, FALSE);
 
 	/* The caller wants plain text */
 	if (info == DRAG_INFO_TEXT) {
 		seahorse_debug ("returning object text");
 		export_to_text (skstore, selection_data);
-		
+
 	/* The caller wants XDS */
 	} else if (info == DRAG_INFO_XDS) {
-		
+
 		if (xds_is_dnd_valid_context (context)) {
 			destination = xds_get_atom_value (context);
 			g_return_val_if_fail (destination, FALSE);
 			skstore->priv->drag_destination = g_path_get_dirname (destination);
 			g_free (destination);
-		
+
 			gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), 8, (guchar*)"S", 1);
 			ret = TRUE;
 		}
-		
+
 	/* Unrecognized format */
 	} else {
 		seahorse_debug ("Unrecognized format: %d", info);
 	}
-	
+
 	seahorse_debug ("drag_data_get <--");
 	return ret;
 }
@@ -553,22 +553,22 @@ drag_end (GtkWidget *widget, GdkDragContext *context, SeahorseKeyManagerStore *s
 
 	if (skstore->priv->drag_destination && !skstore->priv->drag_error) {
 		g_return_if_fail (skstore->priv->drag_objects);
-	
+
 		name = seahorse_util_filename_for_objects (skstore->priv->drag_objects);
 		g_return_if_fail (name);
-	
+
 		filename = g_build_filename (skstore->priv->drag_destination, name, NULL);
 		g_free (name);
-	
+
 		export_to_filename (skstore, filename);
 		g_free (filename);
 	}
-	
+
 	if (skstore->priv->drag_error) {
 		seahorse_util_show_error (widget, _("Couldn't export keys"),
 		                          skstore->priv->drag_error->message);
 	}
-	
+
 	g_clear_error (&skstore->priv->drag_error);
 	g_list_free (skstore->priv->drag_objects);
 	skstore->priv->drag_objects = NULL;
@@ -578,7 +578,7 @@ drag_end (GtkWidget *widget, GdkDragContext *context, SeahorseKeyManagerStore *s
 	seahorse_debug ("drag_end <--");
 }
 
-static gint 
+static gint
 compare_pointers (gconstpointer a, gconstpointer b)
 {
     if (a == b)
@@ -587,7 +587,7 @@ compare_pointers (gconstpointer a, gconstpointer b)
 }
 
 /* -----------------------------------------------------------------------------
- * OBJECT 
+ * OBJECT
  */
 
 static void
@@ -602,7 +602,7 @@ seahorse_key_manager_store_get_property (GObject *gobject, guint prop_id,
                                          GValue *value, GParamSpec *pspec)
 {
     SeahorseKeyManagerStore *skstore = SEAHORSE_KEY_MANAGER_STORE (gobject);
-    
+
     switch (prop_id) {
 
     /* The filtering mode */
@@ -614,13 +614,13 @@ seahorse_key_manager_store_get_property (GObject *gobject, guint prop_id,
         g_value_set_object (value, skstore->priv->settings);
         break;
 
-    /* The filter text. Note that we act as if we don't have any 
+    /* The filter text. Note that we act as if we don't have any
      * filter text when not in filtering mode */
     case PROP_FILTER:
-        g_value_set_string (value, 
+        g_value_set_string (value,
             skstore->priv->filter_mode == KEY_STORE_MODE_FILTERED ? skstore->priv->filter_text : "");
         break;
-    
+
     default:
         break;
     }
@@ -632,7 +632,7 @@ seahorse_key_manager_store_set_property (GObject *gobject, guint prop_id,
 {
     SeahorseKeyManagerStore *skstore = SEAHORSE_KEY_MANAGER_STORE (gobject);
     const gchar* t;
-    
+
     switch (prop_id) {
 
     /* The filtering mode */
@@ -650,8 +650,8 @@ seahorse_key_manager_store_set_property (GObject *gobject, guint prop_id,
     /* The filter text */
     case PROP_FILTER:
         t = g_value_get_string (value);
-            
-        /* 
+
+        /*
          * If we're not in filtered mode and there is text OR
          * we're in filtered mode (regardless of text or not)
          * then update the filter
@@ -660,13 +660,13 @@ seahorse_key_manager_store_set_property (GObject *gobject, guint prop_id,
             (skstore->priv->filter_mode == KEY_STORE_MODE_FILTERED)) {
             skstore->priv->filter_mode = KEY_STORE_MODE_FILTERED;
             g_free (skstore->priv->filter_text);
-                
+
             /* We always use lower case text (see filter_callback) */
             skstore->priv->filter_text = g_utf8_strdown (t, -1);
             refilter_later (skstore);
         }
         break;
-        
+
     default:
         break;
     }
@@ -680,8 +680,8 @@ seahorse_key_manager_store_finalize (GObject *gobject)
     g_signal_handlers_disconnect_by_func (skstore, on_sort_column_changed, skstore);
 
     /* Allocated in property setter */
-    g_free (skstore->priv->filter_text); 
-    
+    g_free (skstore->priv->filter_text);
+
     G_OBJECT_CLASS (seahorse_key_manager_store_parent_class)->finalize (gobject);
 }
 
@@ -716,34 +716,36 @@ seahorse_key_manager_store_class_init (SeahorseKeyManagerStoreClass *klass)
 }
 
 /* -----------------------------------------------------------------------------
- * PUBLIC 
+ * PUBLIC
  */
 
 SeahorseKeyManagerStore*
-seahorse_key_manager_store_new (SeahorseCollection *collection,
+seahorse_key_manager_store_new (GcrCollection *collection,
                                 GtkTreeView *view,
                                 GSettings *settings)
 {
 	SeahorseKeyManagerStore *self;
 	GtkTreeViewColumn *col;
 	SeahorsePredicate *pred;
+	SeahorseCollection *filtered;
 	GtkCellRenderer *renderer;
 	gchar *sort_by;
 	guint last;
 
+	pred = g_new0 (SeahorsePredicate, 1);
+	filtered = seahorse_collection_new_for_predicate (collection, pred, g_free);
+	pred->custom = on_filter_visible;
+
 	self = g_object_new (SEAHORSE_TYPE_KEY_MANAGER_STORE,
-	                     "collection", collection,
+	                     "collection", filtered,
 	                     "settings", settings,
 	                     NULL);
+	pred->custom_target = self;
+	g_object_unref (filtered);
+
 	last = gcr_collection_model_set_columns (GCR_COLLECTION_MODEL (self), columns);
 	g_return_val_if_fail (last == N_COLS, NULL);
 
-	/* We assume we're the only user for this collection :( */
-	pred = seahorse_collection_get_predicate (collection);
-	g_assert (pred->custom == NULL);
-	pred->custom = on_filter_visible;
-	pred->custom_target = self;
-
 	/* The sorted model is the top level model */
 	gtk_tree_view_set_model (view, GTK_TREE_MODEL (self));
 
@@ -766,17 +768,19 @@ seahorse_key_manager_store_new (SeahorseCollection *collection,
 	gtk_tree_view_column_set_sort_column_id (col, COL_NAME);
 
 	/* Use predicate to figure out which columns to add */
-	pred = seahorse_collection_get_predicate (collection);
-	g_return_val_if_fail (pred != NULL, NULL);
+	if (SEAHORSE_IS_COLLECTION (collection))
+		pred = seahorse_collection_get_predicate (SEAHORSE_COLLECTION (collection));
+	else
+		pred = NULL;
 
 	/* Key ID column, don't show for passwords */
-	if (pred->usage != SEAHORSE_USAGE_CREDENTIALS) {
+	if (!pred || pred->usage != SEAHORSE_USAGE_CREDENTIALS) {
 		col = append_text_column (self, view, _("Key ID"), COL_KEYID);
 		gtk_tree_view_column_set_sort_column_id (col, COL_KEYID);
 	}
 
 	/* Public keys show validity */
-	if (pred->usage == SEAHORSE_USAGE_PUBLIC_KEY) {
+	if (pred && pred->usage == SEAHORSE_USAGE_PUBLIC_KEY) {
 		col = append_text_column (self, view, _("Validity"), COL_VALIDITY);
 		g_object_set_data (G_OBJECT (col), "settings-key", "show-validity");
 		gtk_tree_view_column_set_visible (col, g_settings_get_boolean (settings, "show-validity"));
@@ -832,10 +836,10 @@ seahorse_key_manager_store_get_object_from_path (GtkTreeView *view, GtkTreePath
 {
     GtkTreeModel *model;
     GtkTreeIter iter;
-    
+
     g_return_val_if_fail (GTK_IS_TREE_VIEW (view), NULL);
     g_return_val_if_fail (path != NULL, NULL);
-    
+
     model = gtk_tree_view_get_model (view);
     g_return_val_if_fail (gtk_tree_model_get_iter (model, &iter, path), NULL);
     return SEAHORSE_OBJECT (gcr_collection_model_object_for_iter (GCR_COLLECTION_MODEL (model), &iter));
@@ -845,7 +849,7 @@ GList*
 seahorse_key_manager_store_get_all_objects (GtkTreeView *view)
 {
     SeahorseKeyManagerStore* skstore;
-    
+
     g_return_val_if_fail (GTK_IS_TREE_VIEW (view), NULL);
     skstore = SEAHORSE_KEY_MANAGER_STORE (gtk_tree_view_get_model (view));
     g_return_val_if_fail (SEAHORSE_IS_KEY_MANAGER_STORE (skstore), NULL);
@@ -859,12 +863,12 @@ seahorse_key_manager_store_get_selected_objects (GtkTreeView *view)
     GList *l, *objects = NULL;
     SeahorseKeyManagerStore* skstore;
     GList *list, *paths = NULL;
-    GtkTreeSelection *selection;    
-    
+    GtkTreeSelection *selection;
+
     g_return_val_if_fail (GTK_IS_TREE_VIEW (view), NULL);
     skstore = SEAHORSE_KEY_MANAGER_STORE (gtk_tree_view_get_model (view));
     g_return_val_if_fail (SEAHORSE_IS_KEY_MANAGER_STORE (skstore), NULL);
-    
+
     selection = gtk_tree_view_get_selection (view);
     paths = gtk_tree_selection_get_selected_rows (selection, NULL);
 
@@ -874,18 +878,18 @@ seahorse_key_manager_store_get_selected_objects (GtkTreeView *view)
         if (sobj != NULL)
             objects = g_list_append (objects, sobj);
     }
-        
+
     /* free selected paths */
     g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
     g_list_free (paths);
-    
+
     /* Remove duplicates */
     objects = g_list_sort (objects, compare_pointers);
     for (l = objects; l; l = g_list_next (l)) {
         while (l->next && l->data == l->next->data)
             objects = g_list_delete_link (objects, l->next);
-    }    
-    
+    }
+
     return objects;
 }
 
@@ -897,23 +901,23 @@ seahorse_key_manager_store_set_selected_objects (GtkTreeView *view, GList* objec
 	gboolean first = TRUE;
 	GtkTreePath *path;
 	GList *l;
-	GtkTreeIter iter, upper;
-    
+	GtkTreeIter iter;
+
 	g_return_if_fail (GTK_IS_TREE_VIEW (view));
 	selection = gtk_tree_view_get_selection (view);
 	gtk_tree_selection_unselect_all (selection);
 
 	skstore = SEAHORSE_KEY_MANAGER_STORE (gtk_tree_view_get_model (view));
 	g_return_if_fail (SEAHORSE_IS_KEY_MANAGER_STORE (skstore));
-    
+
 	for (l = objects; l; l = g_list_next (l)) {
 		if (gcr_collection_model_iter_for_object (GCR_COLLECTION_MODEL (skstore),
 		                                          l->data, &iter)) {
-			gtk_tree_selection_select_iter (selection, &upper);
+			gtk_tree_selection_select_iter (selection, &iter);
 
 			/* Scroll the first row selected into view */
 			if (first) {
-				path = gtk_tree_model_get_path (gtk_tree_view_get_model (view), &upper);
+				path = gtk_tree_model_get_path (gtk_tree_view_get_model (view), &iter);
 				gtk_tree_view_scroll_to_cell (view, path, NULL, FALSE, 0.0, 0.0);
 				gtk_tree_path_free (path);
 				first = FALSE;
@@ -929,22 +933,22 @@ seahorse_key_manager_store_get_selected_object (GtkTreeView *view)
 	SeahorseObject *sobj = NULL;
 	GList *paths = NULL;
 	GtkTreeSelection *selection;
-    
+
 	g_return_val_if_fail (GTK_IS_TREE_VIEW (view), NULL);
 	skstore = SEAHORSE_KEY_MANAGER_STORE (gtk_tree_view_get_model (view));
 	g_return_val_if_fail (SEAHORSE_IS_KEY_MANAGER_STORE (skstore), NULL);
-    
+
 	selection = gtk_tree_view_get_selection (view);
 	paths = gtk_tree_selection_get_selected_rows (selection, NULL);
-    
+
 	/* choose first object */
 	if (paths != NULL) {
 		sobj = seahorse_key_manager_store_get_object_from_path (view, paths->data);
-            
+
 		/* free selected paths */
 		g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
 		g_list_free (paths);
 	}
-    
+
 	return sobj;
 }
diff --git a/src/seahorse-key-manager-store.h b/libseahorse/seahorse-key-manager-store.h
similarity index 96%
rename from src/seahorse-key-manager-store.h
rename to libseahorse/seahorse-key-manager-store.h
index 36c1856..19495ca 100644
--- a/src/seahorse-key-manager-store.h
+++ b/libseahorse/seahorse-key-manager-store.h
@@ -58,7 +58,7 @@ struct _SeahorseKeyManagerStoreClass {
 
 GType                      seahorse_key_manager_store_get_type               (void) G_GNUC_CONST;
 
-SeahorseKeyManagerStore*   seahorse_key_manager_store_new                    (SeahorseCollection *collection,
+SeahorseKeyManagerStore*   seahorse_key_manager_store_new                    (GcrCollection *collection,
                                                                               GtkTreeView *view,
                                                                               GSettings *settings);
 
@@ -69,7 +69,7 @@ GList*                     seahorse_key_manager_store_get_all_objects        (Gt
 
 void                       seahorse_key_manager_store_set_selected_objects   (GtkTreeView *view,
                                                                               GList* objects);
-                                                             
+
 GList*                     seahorse_key_manager_store_get_selected_objects   (GtkTreeView *view);
 
 SeahorseObject*            seahorse_key_manager_store_get_selected_object    (GtkTreeView *view);
diff --git a/libseahorse/seahorse-object-widget.c b/libseahorse/seahorse-object-widget.c
index 024e17d..c62d248 100644
--- a/libseahorse/seahorse-object-widget.c
+++ b/libseahorse/seahorse-object-widget.c
@@ -99,23 +99,21 @@ seahorse_object_widget_finalize (GObject *gobject)
     SeahorseWidget *swidget;
     SeahorseObjectWidget *self;
     GHashTable *widgets = NULL;
-    GQuark id;
     GtkWidget *widget;
     
     self = SEAHORSE_OBJECT_WIDGET (gobject);
     swidget = SEAHORSE_WIDGET (self);
     
     g_return_if_fail (SEAHORSE_IS_OBJECT (self->object));
-    id = seahorse_object_get_id (self->object);
-    
+
     /* get widgets hash from types */
-    widgets = g_hash_table_lookup (types, GUINT_TO_POINTER (id));
+    widgets = g_hash_table_lookup (types, self->object);
     /* if have a widgets hash, remove the widget */
     if (widgets != NULL) {
         g_hash_table_remove (widgets, swidget->name);
         /* if there are no more widgets, remove the hash */
         if (g_hash_table_size (widgets) == 0) {
-            g_hash_table_remove (types, GUINT_TO_POINTER (id));
+            g_hash_table_remove (types, self->object);
             /* if there are no more objects, destroy types */
             if (g_hash_table_size (types) == 0) {
                 g_hash_table_destroy (types);
@@ -193,12 +191,9 @@ seahorse_object_widget_create (gchar *name, GtkWindow *parent, SeahorseObject *o
 {
     SeahorseWidget *swidget = NULL;     // widget to lookup or create
     GHashTable *widgets = NULL;         // hash of widgets from types
-    GQuark id;                          // hash key
     GtkWindowGroup *group = NULL;       // window group from groups
     GtkWidget *widget;                  // main window widget of swidget
-    
-    id = seahorse_object_get_id (object);
-    
+
     /* if don't have a types hash, create one */
     if (types == NULL)
         types = g_hash_table_new_full (g_direct_hash, g_direct_equal,
@@ -206,12 +201,12 @@ seahorse_object_widget_create (gchar *name, GtkWindow *parent, SeahorseObject *o
     
     /* otherwise lookup the widgets hash for the object */
     else
-        widgets = g_hash_table_lookup (types, GUINT_TO_POINTER (id));
+        widgets = g_hash_table_lookup (types, object);
     
     /* if don't have a widgets hash for a object, create one and insert it */
     if (widgets == NULL) {
         widgets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-        g_hash_table_insert (types, GUINT_TO_POINTER (id), widgets);
+        g_hash_table_insert (types, object, widgets);
         
     /* otherwise lookup the widget */
     } else {
@@ -236,12 +231,12 @@ seahorse_object_widget_create (gchar *name, GtkWindow *parent, SeahorseObject *o
     
     /* otherwise lookup the group for that object */
     else
-        group = g_hash_table_lookup (groups, GUINT_TO_POINTER (id));
+        group = g_hash_table_lookup (groups, object);
     
     /* if don't have a group for the object, create one and insert it */
     if (group == NULL) {
         group = gtk_window_group_new ();
-        g_hash_table_insert (groups, GUINT_TO_POINTER (id), group);
+        g_hash_table_insert (groups, object, group);
     }
     
     /* get window, add it to the group, return it */
diff --git a/libseahorse/seahorse-object.c b/libseahorse/seahorse-object.c
index e56373a..2e36faa 100644
--- a/libseahorse/seahorse-object.c
+++ b/libseahorse/seahorse-object.c
@@ -22,7 +22,6 @@
 
 #include "config.h"
 
-#include "seahorse-context.h"
 #include "seahorse-object.h"
 #include "seahorse-predicate.h"
 #include "seahorse-source.h"
@@ -34,48 +33,30 @@
 /**
  * _SeahorseObjectProps:
  * @PROP_0:
- * @PROP_CONTEXT:
  * @PROP_SOURCE:
- * @PROP_PREFERRED:
- * @PROP_PARENT:
- * @PROP_ID:
- * @PROP_TAG:
  * @PROP_LABEL:
  * @PROP_MARKUP:
  * @PROP_NICKNAME:
  * @PROP_ICON:
  * @PROP_IDENTIFIER:
- * @PROP_LOCATION:
  * @PROP_USAGE:
  * @PROP_FLAGS:
  */
 enum _SeahorseObjectProps {
 	PROP_0,
-	PROP_CONTEXT,
 	PROP_SOURCE,
-	PROP_PREFERRED,
-	PROP_PARENT,
-	PROP_ID,
-	PROP_TAG,
 	PROP_LABEL,
 	PROP_MARKUP,
 	PROP_NICKNAME,
 	PROP_ICON,
 	PROP_IDENTIFIER,
-	PROP_LOCATION,
 	PROP_USAGE,
 	PROP_FLAGS
 };
 
 /**
  * _SeahorseObjectPrivate:
- * @id: the id of the object
- * @tag: DBUS: "ktype"
- * @tag_explicit: If TRUE the tag will not be set automatically
  * @source: Where did the object come from ?
- * @context:
- * @preferred: Points to the object to prefer over this one
- * @parent: the object's parent
  * @label: DBUS: "display-name"
  * @markup: Markup text
  * @markup_explicit: If TRUE the markup will not be set automatically
@@ -89,13 +70,7 @@ enum _SeahorseObjectProps {
  * @flags:
  */
 struct _SeahorseObjectPrivate {
-	GQuark id;
-	GQuark tag;
-	gboolean tag_explicit;
-
 	SeahorseSource *source;
-	SeahorseContext *context;
-	SeahorseObject *preferred;
 
     gchar *label;             
     gchar *markup;
@@ -106,7 +81,6 @@ struct _SeahorseObjectPrivate {
     gchar *identifier;
     gboolean identifier_explicit;
 
-    SeahorseLocation location;
     SeahorseUsage usage;
     guint flags;
 };
@@ -171,58 +145,6 @@ take_string_storage (gchar *value, gchar **storage)
 }
 
 /**
- * recalculate_id:
- * @self: object to calculate for
- *
- * recalculates tag and identifier from id
- *
- */
-static void
-recalculate_id (SeahorseObject *self)
-{
-	const gchar *str;
-	const gchar *at;
-	GQuark tag;
-	gchar *result;
-	gsize len;
-
-	/* No id, clear any tag and auto generated identifer */
-	if (!self->pv->id) {
-		if (!self->pv->tag_explicit) {
-			self->pv->tag = 0;
-			g_object_notify (G_OBJECT (self), "tag");
-		}
-			
-		if (!self->pv->identifier_explicit) {
-			if (set_string_storage ("", &self->pv->identifier))
-				g_object_notify (G_OBJECT (self), "identifier");
-		}
-		
-	/* Have hande, configure tag and auto generated identifer */
-	} else {
-		str = g_quark_to_string (self->pv->id);
-		len = strlen (str);
-		at = strchr (str, ':');
-		
-		if (!self->pv->tag_explicit) {
-			result = g_strndup (str, at ? at - str : len);
-			tag = g_quark_from_string (result);
-			g_free (result);
-			
-			if (tag != self->pv->tag) {
-				self->pv->tag = tag;
-				g_object_notify (G_OBJECT (self), "tag");
-			}
-		}
-		
-		if (!self->pv->identifier_explicit) {
-			if (set_string_storage (at ? at + 1 : "", &self->pv->identifier))
-				g_object_notify (G_OBJECT (self), "identifier");
-		}
-	}
-}
-
-/**
  * recalculate_label:
  * @self: object to recalculate label for
  *
@@ -264,7 +186,6 @@ seahorse_object_init (SeahorseObject *self)
 	self->pv->markup = g_strdup ("");
 	self->pv->icon = g_themed_icon_new ("gtk-missing-image");
 	self->pv->identifier = g_strdup ("");
-	self->pv->location = SEAHORSE_LOCATION_INVALID;
 	self->pv->usage = SEAHORSE_USAGE_NONE;
 }
 
@@ -280,20 +201,10 @@ seahorse_object_dispose (GObject *obj)
 {
 	SeahorseObject *self = SEAHORSE_OBJECT (obj);
 
-	if (self->pv->context != NULL) {
-		seahorse_context_remove_object (self->pv->context, self);
-		g_assert (self->pv->context == NULL);
-	}
-	
 	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->preferred != NULL) {
-		g_object_remove_weak_pointer (G_OBJECT (self->pv->source), (gpointer*)&self->pv->preferred);
-		self->pv->preferred = NULL;
-	}
 
 	G_OBJECT_CLASS (seahorse_object_parent_class)->dispose (obj);	
 }
@@ -309,8 +220,6 @@ seahorse_object_finalize (GObject *obj)
 	SeahorseObject *self = SEAHORSE_OBJECT (obj);
 	
 	g_assert (self->pv->source == NULL);
-	g_assert (self->pv->preferred == NULL);
-	g_assert (self->pv->context == NULL);
 
 	g_free (self->pv->label);
 	self->pv->label = NULL;
@@ -347,21 +256,9 @@ seahorse_object_get_property (GObject *obj, guint prop_id, GValue *value,
 	SeahorseObject *self = SEAHORSE_OBJECT (obj);
 	
 	switch (prop_id) {
-	case PROP_CONTEXT:
-		g_value_set_object (value, seahorse_object_get_context (self));
-		break;
 	case PROP_SOURCE:
 		g_value_set_object (value, seahorse_object_get_source (self));
 		break;
-	case PROP_PREFERRED:
-		g_value_set_object (value, seahorse_object_get_preferred (self));
-		break;
-	case PROP_ID:
-		g_value_set_uint (value, seahorse_object_get_id (self));
-		break;
-	case PROP_TAG:
-		g_value_set_uint (value, seahorse_object_get_tag (self));
-		break;
 	case PROP_LABEL:
 		g_value_set_string (value, seahorse_object_get_label (self));
 		break;
@@ -377,9 +274,6 @@ seahorse_object_get_property (GObject *obj, guint prop_id, GValue *value,
 	case PROP_IDENTIFIER:
 		g_value_set_string (value, seahorse_object_get_identifier (self));
 		break;
-	case PROP_LOCATION:
-		g_value_set_enum (value, seahorse_object_get_location (self));
-		break;
 	case PROP_USAGE:
 		g_value_set_enum (value, seahorse_object_get_usage (self));
 		break;
@@ -407,44 +301,13 @@ seahorse_object_set_property (GObject *obj, guint prop_id, const GValue *value,
                               GParamSpec *pspec)
 {
 	SeahorseObject *self = SEAHORSE_OBJECT (obj);
-	SeahorseLocation loc;
 	SeahorseUsage usage;
 	guint flags;
-	GQuark quark;
-	
+
 	switch (prop_id) {
-	case PROP_CONTEXT:
-		if (self->pv->context) 
-			g_object_remove_weak_pointer (G_OBJECT (self->pv->context), (gpointer*)&self->pv->context);
-		self->pv->context = SEAHORSE_CONTEXT (g_value_get_object (value));
-		if (self->pv->context != NULL)
-			g_object_add_weak_pointer (G_OBJECT (self->pv->context), (gpointer*)&self->pv->context);
-		g_object_notify (G_OBJECT (self), "context");
-		break;
 	case PROP_SOURCE:
 		seahorse_object_set_source (self, SEAHORSE_SOURCE (g_value_get_object (value)));
 		break;
-	case PROP_PREFERRED:
-		seahorse_object_set_preferred (self, SEAHORSE_OBJECT (g_value_get_object (value)));
-		break;
-	case PROP_ID:
-		quark = g_value_get_uint (value);
-		if (quark != self->pv->id) {
-			self->pv->id = quark;
-			g_object_freeze_notify (obj);
-			g_object_notify (obj, "id");
-			recalculate_id (self);
-			g_object_thaw_notify (obj);
-		}
-		break;
-	case PROP_TAG:
-		quark = g_value_get_uint (value);
-		if (quark != self->pv->tag) {
-			self->pv->tag = quark;
-			self->pv->tag_explicit = TRUE;
-			g_object_notify (obj, "tag");
-		}
-		break;
 	case PROP_LABEL:
 		if (set_string_storage (g_value_get_string (value), &self->pv->label)) {
 			g_object_freeze_notify (obj);
@@ -476,13 +339,6 @@ seahorse_object_set_property (GObject *obj, guint prop_id, const GValue *value,
 			g_object_notify (obj, "identifier");
 		}
 		break;
-	case PROP_LOCATION:
-		loc = g_value_get_enum (value);
-		if (loc != self->pv->location) {
-			self->pv->location = loc;
-			g_object_notify (obj, "location");
-		}
-		break;
 	case PROP_USAGE:
 		usage = g_value_get_enum (value);
 		if (usage != self->pv->usage) {
@@ -529,22 +385,6 @@ seahorse_object_class_init (SeahorseObjectClass *klass)
 	           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_CONTEXT,
-	           g_param_spec_object ("context", "Context for object", "Object that this context belongs to", 
-	                                SEAHORSE_TYPE_CONTEXT, G_PARAM_READWRITE));
-
-	g_object_class_install_property (gobject_class, PROP_PREFERRED,
-	           g_param_spec_object ("preferred", "Preferred Object", "An object to prefer over this one", 
-	                                SEAHORSE_TYPE_OBJECT, G_PARAM_READWRITE));
-
-	g_object_class_install_property (gobject_class, PROP_ID,
-	           g_param_spec_uint ("id", "Object ID", "This object's ID.", 
-	                              0, G_MAXUINT, 0, G_PARAM_READWRITE));
-	
-	g_object_class_install_property (gobject_class, PROP_TAG,
-	           g_param_spec_uint ("tag", "Object Type Tag", "This object's type tag.", 
-	                              0, G_MAXUINT, 0, 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.", 
 	                                "", G_PARAM_READWRITE));
@@ -564,11 +404,7 @@ seahorse_object_class_init (SeahorseObjectClass *klass)
 	g_object_class_install_property (gobject_class, PROP_IDENTIFIER,
 	           g_param_spec_string ("identifier", "Object Identifier", "Displayable ID for the object.", 
 	                                "", G_PARAM_READWRITE));
-	
-	g_object_class_install_property (gobject_class, PROP_LOCATION,
-	           g_param_spec_enum ("location", "Object Location", "Where the object is located.", 
-	                              SEAHORSE_TYPE_LOCATION, SEAHORSE_LOCATION_INVALID, G_PARAM_READWRITE));
-	
+
 	g_object_class_install_property (gobject_class, PROP_USAGE,
 	           g_param_spec_enum ("usage", "Object Usage", "How this object is used.", 
 	                              SEAHORSE_TYPE_USAGE, SEAHORSE_USAGE_NONE, G_PARAM_READWRITE));
@@ -583,32 +419,6 @@ seahorse_object_class_init (SeahorseObjectClass *klass)
  */
 
 /**
- * seahorse_object_get_id:
- * @self: Object
- *
- * Returns: the id of the object @self
- */
-GQuark
-seahorse_object_get_id (SeahorseObject *self)
-{
-	g_return_val_if_fail (SEAHORSE_IS_OBJECT (self), 0);
-	return self->pv->id;
-}
-
-/**
- * seahorse_object_get_tag:
- * @self: Object
- *
- * Returns: the tag of the object @self
- */
-GQuark
-seahorse_object_get_tag (SeahorseObject *self)
-{
-	g_return_val_if_fail (SEAHORSE_IS_OBJECT (self), 0);
-	return self->pv->tag;
-}
-
-/**
  * seahorse_object_get_source:
  * @self: Object
  *
@@ -648,57 +458,6 @@ seahorse_object_set_source (SeahorseObject *self, SeahorseSource *value)
 }
 
 /**
- * seahorse_object_get_context:
- * @self: Object
- *
- * Returns: the context of the object @self
- */
-SeahorseContext*
-seahorse_object_get_context (SeahorseObject *self)
-{
-	g_return_val_if_fail (SEAHORSE_IS_OBJECT (self), NULL);
-	return self->pv->context;
-}
-
-/**
- * seahorse_object_get_preferred:
- * @self: Object
- *
- * Returns: the preferred of the object @self
- */
-SeahorseObject*
-seahorse_object_get_preferred (SeahorseObject *self)
-{
-	g_return_val_if_fail (SEAHORSE_IS_OBJECT (self), NULL);
-	return self->pv->preferred;
-}
-
-/**
- * seahorse_object_set_preferred:
- * @self: the object to set the preferred object for
- * @value: the preferred object
- *
- *
- */
-void
-seahorse_object_set_preferred (SeahorseObject *self, SeahorseObject *value)
-{
-	g_return_if_fail (SEAHORSE_IS_OBJECT (self));
-	
-	if (self->pv->preferred == value)
-		return;
-
-	if (self->pv->preferred)
-		g_object_remove_weak_pointer (G_OBJECT (self->pv->preferred), (gpointer*)&self->pv->preferred);
-
-	self->pv->preferred = value;
-	if (self->pv->preferred != NULL)
-		g_object_add_weak_pointer (G_OBJECT (self->pv->preferred), (gpointer*)&self->pv->preferred);
-
-	g_object_notify (G_OBJECT (self), "preferred");
-}
-
-/**
  * seahorse_object_get_label:
  * @self: Object
  *
@@ -751,19 +510,6 @@ seahorse_object_get_identifier (SeahorseObject *self)
 }
 
 /**
- * seahorse_object_get_location:
- * @self: Object
- *
- * Returns: the location of the object @self
- */
-SeahorseLocation
-seahorse_object_get_location (SeahorseObject *self)
-{
-	g_return_val_if_fail (SEAHORSE_IS_OBJECT (self), SEAHORSE_LOCATION_INVALID);
-	return self->pv->location;
-}
-
-/**
  * seahorse_object_get_usage:
  * @self: Object
  *
@@ -808,13 +554,7 @@ seahorse_predicate_match (SeahorsePredicate *self,
 	pv = object->pv;
 
 	/* Check all the fields */
-	if (self->tag != 0 && self->tag != pv->tag)
-		return FALSE;
-	if (self->id != 0 && self->id != pv->id)
-		return FALSE;
-	if (self->type != 0 && self->type != G_OBJECT_TYPE (object))
-		return FALSE;
-	if (self->location != 0 && self->location != pv->location)
+	if (self->type != 0 && !G_TYPE_CHECK_INSTANCE_TYPE (object, self->type))
 		return FALSE;
 	if (self->usage != 0 && self->usage != pv->usage)
 		return FALSE;
diff --git a/libseahorse/seahorse-object.h b/libseahorse/seahorse-object.h
index 8eb819f..61ed495 100644
--- a/libseahorse/seahorse-object.h
+++ b/libseahorse/seahorse-object.h
@@ -26,8 +26,6 @@
 /* 
  * Derived classes must set the following properties:
  * 
- * id: GQuark: Unique identifier for this object.
- * tag: GQuark: The module (openpgp, pkcs11, etc...) that handles this object. 
  * label: string: The displayable string label of this object.
  * icon: A GIcon.
  * usage: SeahorseUsage: The usage of this object.
@@ -43,7 +41,6 @@
  * flags: guint: Flags from the SEAHORSE_FLAG_ set. 
  */
 
-#include "seahorse-context.h"
 #include "seahorse-source.h"
 #include "seahorse-types.h"
 
@@ -73,25 +70,11 @@ GType               seahorse_object_get_type               (void);
 
 SeahorseObject*     seahorse_object_new                    (void);
 
-GQuark              seahorse_object_get_id                 (SeahorseObject *self);
-
-GQuark              seahorse_object_get_tag                (SeahorseObject *self);
-
 SeahorseSource*     seahorse_object_get_source             (SeahorseObject *self);
 
 void                seahorse_object_set_source             (SeahorseObject *self, 
                                                             SeahorseSource *value);
 
-SeahorseContext*    seahorse_object_get_context            (SeahorseObject *self);
-
-SeahorseObject*     seahorse_object_get_preferred          (SeahorseObject *self);
-
-void                seahorse_object_set_preferred          (SeahorseObject *self, 
-                                                            SeahorseObject *value);
- 
-SeahorseObject*     seahorse_object_get_nth_child          (SeahorseObject *self,
-                                                            guint index);
-
 const gchar*        seahorse_object_get_label              (SeahorseObject *self);
 
 const gchar*        seahorse_object_get_markup             (SeahorseObject *self);
@@ -100,8 +83,6 @@ const gchar*        seahorse_object_get_identifier         (SeahorseObject *self
 
 const gchar*        seahorse_object_get_nickname           (SeahorseObject *self);
 
-SeahorseLocation    seahorse_object_get_location           (SeahorseObject *self);
-
 SeahorseUsage       seahorse_object_get_usage              (SeahorseObject *self);
 
 guint               seahorse_object_get_flags              (SeahorseObject *self);
diff --git a/libseahorse/seahorse-predicate.h b/libseahorse/seahorse-predicate.h
index 332d723..5511165 100644
--- a/libseahorse/seahorse-predicate.h
+++ b/libseahorse/seahorse-predicate.h
@@ -23,7 +23,6 @@
 #ifndef __SEAHORSE_PREDICATE_H__
 #define __SEAHORSE_PREDICATE_H__
 
-#include "seahorse-context.h"
 #include "seahorse-object.h"
 #include "seahorse-source.h"
 #include "seahorse-types.h"
@@ -36,10 +35,7 @@ typedef gboolean (*SeahorsePredicateFunc) (SeahorseObject *object,
 typedef struct _SeahorsePredicate SeahorsePredicate;
 
 struct _SeahorsePredicate {
-	GQuark tag;
-	GQuark id;
 	GType type;
-	SeahorseLocation location;
 	SeahorseUsage usage;
 	guint flags;
 	guint nflags;
diff --git a/src/seahorse-preferences.c b/libseahorse/seahorse-preferences.c
similarity index 99%
rename from src/seahorse-preferences.c
rename to libseahorse/seahorse-preferences.c
index 0379a180..a52a7c5 100644
--- a/src/seahorse-preferences.c
+++ b/libseahorse/seahorse-preferences.c
@@ -32,10 +32,10 @@
  **/
 void
 seahorse_preferences_show (GtkWindow *parent, const gchar *tabid)
-{   
+{
     SeahorseWidget *swidget = seahorse_prefs_new (parent);
     GtkWidget *tab;
-    
+
     if (tabid) {
         tab = seahorse_widget_get_widget (swidget, tabid);
         g_return_if_fail (tab);
diff --git a/src/seahorse-preferences.h b/libseahorse/seahorse-preferences.h
similarity index 100%
rename from src/seahorse-preferences.h
rename to libseahorse/seahorse-preferences.h
diff --git a/libseahorse/seahorse-prefs.c b/libseahorse/seahorse-prefs.c
index 3c7954e..ca3bd0b 100644
--- a/libseahorse/seahorse-prefs.c
+++ b/libseahorse/seahorse-prefs.c
@@ -22,7 +22,6 @@
 
 #include <glib/gi18n.h>
 
-#include "seahorse-combo-keys.h"
 #include "seahorse-icons.h"
 #include "seahorse-keyserver-control.h"
 #include "seahorse-prefs.h"
diff --git a/libseahorse/seahorse-prefs.h b/libseahorse/seahorse-prefs.h
index 9832316..5d7b785 100644
--- a/libseahorse/seahorse-prefs.h
+++ b/libseahorse/seahorse-prefs.h
@@ -26,7 +26,6 @@
 #ifndef __SEAHORSE_PREFS_H__
 #define __SEAHORSE_PREFS_H__
 
-#include "seahorse-context.h"
 #include "seahorse-widget.h"
 
 SeahorseWidget *    seahorse_prefs_new          (GtkWindow *parent);
diff --git a/libseahorse/seahorse-registry.c b/libseahorse/seahorse-registry.c
index 62e81d3..44fc13a 100644
--- a/libseahorse/seahorse-registry.c
+++ b/libseahorse/seahorse-registry.c
@@ -27,7 +27,6 @@ typedef struct _SeahorseRegistryPrivate SeahorseRegistryPrivate;
 struct _SeahorseRegistryPrivate {
 	GHashTable *types;
 	GHashTable *objects;
-	GHashTable *functions;
 };
 
 #define SEAHORSE_REGISTRY_GET_PRIVATE(o) \
@@ -159,8 +158,6 @@ seahorse_registry_init (SeahorseRegistry *obj)
 	                                   NULL, (GDestroyNotify)g_hash_table_destroy);
 	pv->objects = g_hash_table_new_full (g_direct_hash, g_direct_equal, 
 	                                     NULL, (GDestroyNotify)g_hash_table_destroy);
-	pv->functions = g_hash_table_new_full (g_direct_hash, g_direct_equal, 
-	                                       NULL, (GDestroyNotify)g_hash_table_destroy);
 }
 
 static void
@@ -261,33 +258,6 @@ seahorse_registry_register_object (SeahorseRegistry *registry, GObject *object,
 	va_end (cats);
 }
 
-void
-seahorse_registry_register_function (SeahorseRegistry *registry, gpointer func, 
-                                     const gchar *category, ...)
-{
-	SeahorseRegistryPrivate *pv;
-	va_list cats;
-
-	if (!registry)
-		registry = seahorse_registry_get ();
-	
-	g_return_if_fail (SEAHORSE_IS_REGISTRY (registry));
-	g_return_if_fail (func);
-	g_return_if_fail (category);
-
-	pv = SEAHORSE_REGISTRY_GET_PRIVATE (registry);
-	register_value_for_category (pv->functions, g_quark_from_string (category), func, NULL);
-	
-	va_start (cats, category);
-	for (;;) {
-		category = va_arg (cats, const gchar*);
-		if (!category)
-			break;
-		register_value_for_category (pv->functions, g_quark_from_string (category), func, NULL);
-	}
-	va_end (cats);
-}
-
 GType
 seahorse_registry_object_type (SeahorseRegistry *registry, const gchar *category, ...)
 {
@@ -387,23 +357,3 @@ seahorse_registry_object_instances (SeahorseRegistry *registry, const gchar *cat
 	g_list_free (types);
 	return objects;
 }
-
-gpointer
-seahorse_registry_lookup_function (SeahorseRegistry *registry, const gchar *category, ...)
-{
-	SeahorseRegistryPrivate *pv;
-	va_list cats;
-	gpointer func;
-	
-	if (!registry)
-		registry = seahorse_registry_get ();
-	
-	g_return_val_if_fail (SEAHORSE_IS_REGISTRY (registry), 0);
-	pv = SEAHORSE_REGISTRY_GET_PRIVATE (registry);
-
-	va_start (cats, category);
-	func = lookup_category_value (pv->functions, category, cats);
-	va_end (cats);
-
-	return func;
-}
diff --git a/libseahorse/seahorse-registry.h b/libseahorse/seahorse-registry.h
index 3285adc..554e15e 100644
--- a/libseahorse/seahorse-registry.h
+++ b/libseahorse/seahorse-registry.h
@@ -57,10 +57,6 @@ void                 seahorse_registry_register_object   (SeahorseRegistry *regi
                                                           GObject *object, const gchar *category, 
                                                           ...) G_GNUC_NULL_TERMINATED;
 
-void                 seahorse_registry_register_function (SeahorseRegistry *registry, 
-                                                          gpointer func, const gchar *category, 
-                                                          ...) G_GNUC_NULL_TERMINATED;
-
 GType                seahorse_registry_object_type       (SeahorseRegistry *registry, 
                                                           const gchar *category,
                                                           ...) G_GNUC_NULL_TERMINATED;
@@ -77,10 +73,6 @@ GList*               seahorse_registry_object_instances  (SeahorseRegistry *regi
                                                           const gchar *category,
                                                           ...) G_GNUC_NULL_TERMINATED;
 
-gpointer             seahorse_registry_lookup_function   (SeahorseRegistry *registry, 
-                                                          const gchar *category, 
-                                                          ...) G_GNUC_NULL_TERMINATED;
-
 G_END_DECLS
 
 #endif /*SEAHORSEREGISTRY_H_*/
diff --git a/libseahorse/seahorse-source.c b/libseahorse/seahorse-source.c
index c86632b..8adb763 100644
--- a/libseahorse/seahorse-source.c
+++ b/libseahorse/seahorse-source.c
@@ -44,24 +44,12 @@
 /**
 * gobject_class: The object class to init
 *
-* Adds the interfaces "source-tag" and "source-location"
-*
 **/
 static void
 seahorse_source_base_init (gpointer gobject_class)
 {
 	static gboolean initialized = FALSE;
 	if (!initialized) {
-		
-		/* Add properties and signals to the interface */
-		g_object_interface_install_property (gobject_class,
-		        g_param_spec_uint ("source-tag", "Source Tag", "Tag of objects that come from this source.", 
-		                           0, G_MAXUINT, SEAHORSE_TAG_INVALID, G_PARAM_READABLE));
-
-		g_object_interface_install_property (gobject_class, 
-		        g_param_spec_enum ("source-location", "Source Location", "Objects in this source are at this location. See SeahorseLocation", 
-		                           SEAHORSE_TYPE_LOCATION, SEAHORSE_LOCATION_LOCAL, G_PARAM_READABLE));
-		
 		initialized = TRUE;
 	}
 }
@@ -101,57 +89,6 @@ seahorse_source_get_type (void)
  */
 
 void
-seahorse_source_load_async (SeahorseSource *source,
-                            GCancellable *cancellable,
-                            GAsyncReadyCallback callback,
-                            gpointer user_data)
-{
-	g_return_if_fail (SEAHORSE_IS_SOURCE (source));
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-	g_return_if_fail (SEAHORSE_SOURCE_GET_INTERFACE (source)->load_async);
-	SEAHORSE_SOURCE_GET_INTERFACE (source)->load_async (source, cancellable,
-	                                                  callback, user_data);
-}
-
-gboolean
-seahorse_source_load_finish (SeahorseSource *source,
-                             GAsyncResult *result,
-                             GError **error)
-{
-	g_return_val_if_fail (SEAHORSE_IS_SOURCE (source), FALSE);
-	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-	g_return_val_if_fail (SEAHORSE_SOURCE_GET_INTERFACE (source)->load_finish, FALSE);
-	return SEAHORSE_SOURCE_GET_INTERFACE (source)->load_finish (source, result, error);
-}
-
-void
-seahorse_source_search_async (SeahorseSource *source,
-                              const gchar *match,
-                              GCancellable *cancellable,
-                              GAsyncReadyCallback callback,
-                              gpointer user_data)
-{
-	g_return_if_fail (SEAHORSE_IS_SOURCE (source));
-	g_return_if_fail (match != NULL);
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-	g_return_if_fail (SEAHORSE_SOURCE_GET_INTERFACE (source)->search_async);
-	SEAHORSE_SOURCE_GET_INTERFACE (source)->search_async (source, match, cancellable,
-	                                                    callback, user_data);
-}
-
-GList *
-seahorse_source_search_finish (SeahorseSource *source, GAsyncResult *result,
-                               GError **error)
-{
-	g_return_val_if_fail (SEAHORSE_IS_SOURCE (source), 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)->search_finish, NULL);
-	return SEAHORSE_SOURCE_GET_INTERFACE (source)->search_finish (source, result, error);
-}
-
-void
 seahorse_source_import_async (SeahorseSource *source,
                               GInputStream *input,
                               GCancellable *cancellable,
@@ -187,28 +124,16 @@ seahorse_source_export_async (SeahorseSource *source,
                               gpointer user_data)
 {
 	SeahorseSourceIface *iface;
-	GList *l;
-	GList *ids;
 
 	g_return_if_fail (SEAHORSE_IS_SOURCE (source));
 	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);
-	g_return_if_fail (iface->export_async != NULL || iface->export_raw_async != NULL);
-
-	if (iface->export_async) {
-		iface->export_async (source, objects, output,
-		                     cancellable, callback, user_data);
-		return;
-	}
-
-	for (l = objects; l != NULL; l = g_list_next (l))
-		ids = g_list_prepend (ids, GUINT_TO_POINTER (seahorse_object_get_id (l->data)));
+	g_return_if_fail (iface->export_async != NULL);
 
-	ids = g_list_reverse (ids);
-	(iface->export_raw_async) (source, ids, output, cancellable, callback, user_data);
-	g_list_free (ids);
+	iface->export_async (source, objects, output,
+	                     cancellable, callback, user_data);
 }
 
 GOutputStream *
@@ -223,15 +148,9 @@ seahorse_source_export_finish (SeahorseSource *source,
 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	iface = SEAHORSE_SOURCE_GET_INTERFACE (source);
-	g_return_val_if_fail (iface->export_async != NULL || iface->export_raw_async != NULL, NULL);
-
-	if (iface->export_async) {
-		g_return_val_if_fail (iface->export_finish, NULL);
-		return (iface->export_finish) (source, result, error);
-	} else {
-		g_return_val_if_fail (iface->export_raw_finish, NULL);
-		return (iface->export_raw_finish) (source, result, error);
-	}
+	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);
 }
 
 typedef struct {
@@ -362,98 +281,3 @@ seahorse_source_export_auto_wait (GList *objects,
 	g_object_unref (result);
 	return ret;
 }
-
-void
-seahorse_source_export_raw_async (SeahorseSource *source,
-                                  GList *ids,
-                                  GOutputStream *output,
-                                  GCancellable *cancellable,
-                                  GAsyncReadyCallback callback,
-                                  gpointer user_data)
-{
-	SeahorseSourceIface *iface;
-	SeahorseObject *object;
-	GList *objects = NULL;
-	GList *l;
-
-	g_return_if_fail (SEAHORSE_IS_SOURCE (source));
-	g_return_if_fail (output == NULL || G_IS_OUTPUT_STREAM (output));
-	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
-
-	iface = SEAHORSE_SOURCE_GET_INTERFACE (source);
-
-	/* Either export or export_raw must be implemented */
-	if (iface->export_raw_async) {
-		(iface->export_raw_async) (source, ids, output, cancellable, callback, user_data);
-		return;
-	}
-
-	g_return_if_fail (iface->export_async != NULL);
-
-	for (l = ids; l != NULL; l = g_list_next (l)) {
-		object = seahorse_context_get_object (seahorse_context_instance (),
-		                                      source, GPOINTER_TO_UINT (l->data));
-
-		/* TODO: A proper error message here 'not found' */
-		if (object != NULL)
-			objects = g_list_prepend (objects, object);
-	}
-
-	objects = g_list_reverse (objects);
-	(iface->export_async) (source, objects, output, cancellable, callback, user_data);
-	g_list_free (objects);
-}
-
-GOutputStream *
-seahorse_source_export_raw_finish (SeahorseSource *source,
-                                   GAsyncResult *result,
-                                   GError **error)
-{
-	SeahorseSourceIface *iface;
-
-	g_return_val_if_fail (SEAHORSE_IS_SOURCE (source), 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);
-	g_return_val_if_fail (iface->export_async != NULL || iface->export_raw_async != NULL, NULL);
-
-	if (iface->export_raw_async) {
-		g_return_val_if_fail (iface->export_raw_finish, NULL);
-		return (iface->export_raw_finish) (source, result, error);
-	} else {
-		g_return_val_if_fail (iface->export_finish, NULL);
-		return (iface->export_finish) (source, result, error);
-	}
-}
-
-/**
-* seahorse_source_get_tag:
-* @sksrc: The seahorse source object
-*
-*
-* Returns: The source-tag property of the object. As #GQuark
-*/
-GQuark              
-seahorse_source_get_tag (SeahorseSource *sksrc)
-{
-    GQuark ktype;
-    g_object_get (sksrc, "source-tag", &ktype, NULL);
-    return ktype;
-}
-
-/**
- * seahorse_source_get_location:
- * @sksrc: The seahorse source object
- *
- *
- *
- * Returns: The location (#SeahorseLocation) of this object
- */
-SeahorseLocation   
-seahorse_source_get_location (SeahorseSource *sksrc)
-{
-    SeahorseLocation loc;
-    g_object_get (sksrc, "source-location", &loc, NULL);
-    return loc;
-}
diff --git a/libseahorse/seahorse-source.h b/libseahorse/seahorse-source.h
index 93dba51..aeec9b1 100644
--- a/libseahorse/seahorse-source.h
+++ b/libseahorse/seahorse-source.h
@@ -62,25 +62,6 @@ struct _SeahorseSourceIface {
 
 	/* virtual methods ------------------------------------------------- */
 
-	void            (*load_async)                (SeahorseSource *source,
-	                                              GCancellable *cancellable,
-	                                              GAsyncReadyCallback callback,
-	                                              gpointer user_data);
-
-	gboolean        (*load_finish)               (SeahorseSource *source,
-	                                              GAsyncResult *result,
-	                                              GError **error);
-
-	void            (*search_async)              (SeahorseSource *source,
-	                                              const gchar *match,
-	                                              GCancellable *cancellable,
-	                                              GAsyncReadyCallback callback,
-	                                              gpointer user_data);
-
-	GList *         (*search_finish)             (SeahorseSource *source,
-	                                              GAsyncResult *result,
-	                                              GError **error);
-
 	void            (*import_async)              (SeahorseSource *source,
 	                                              GInputStream *input,
 	                                              GCancellable *cancellable,
@@ -101,42 +82,12 @@ struct _SeahorseSourceIface {
 	GOutputStream * (*export_finish)             (SeahorseSource *source,
 	                                              GAsyncResult *result,
 	                                              GError **error);
-
-	void            (*export_raw_async)          (SeahorseSource *source,
-	                                              GList *ids,
-	                                              GOutputStream *output,
-	                                              GCancellable *cancellable,
-	                                              GAsyncReadyCallback callback,
-	                                              gpointer user_data);
-
-	GOutputStream * (*export_raw_finish)         (SeahorseSource *source,
-	                                              GAsyncResult *result,
-	                                              GError **error);
 };
 
 GType            seahorse_source_get_type             (void) G_GNUC_CONST;
 
 /* Method helper functions ------------------------------------------- */
 
-void             seahorse_source_load_async           (SeahorseSource *source,
-                                                       GCancellable *cancellable,
-                                                       GAsyncReadyCallback callback,
-                                                       gpointer user_data);
-
-gboolean         seahorse_source_load_finish          (SeahorseSource *source,
-                                                       GAsyncResult *result,
-                                                       GError **error);
-
-void             seahorse_source_search_async         (SeahorseSource *source,
-                                                       const gchar *match,
-                                                       GCancellable *cancellable,
-                                                       GAsyncReadyCallback callback,
-                                                       gpointer user_data);
-
-GList *          seahorse_source_search_finish        (SeahorseSource *source,
-                                                       GAsyncResult *result,
-                                                       GError **error);
-
 void             seahorse_source_import_async         (SeahorseSource *source,
                                                        GInputStream *input,
                                                        GCancellable *cancellable,
@@ -171,19 +122,4 @@ gboolean         seahorse_source_export_auto_wait     (GList *objects,
                                                        GOutputStream *output,
                                                        GError **error);
 
-void             seahorse_source_export_raw_async     (SeahorseSource *source,
-                                                       GList *ids,
-                                                       GOutputStream *output,
-                                                       GCancellable *cancellable,
-                                                       GAsyncReadyCallback callback,
-                                                       gpointer user_data);
-
-GOutputStream *  seahorse_source_export_raw_finish    (SeahorseSource *source,
-                                                       GAsyncResult *result,
-                                                       GError **error);
-
-GQuark           seahorse_source_get_tag              (SeahorseSource *source);
-
-SeahorseLocation seahorse_source_get_location         (SeahorseSource *source);
-
 #endif /* __SEAHORSE_SOURCE_H__ */
diff --git a/libseahorse/seahorse-types.c b/libseahorse/seahorse-types.c
index f3bbc0f..4f412d2 100644
--- a/libseahorse/seahorse-types.c
+++ b/libseahorse/seahorse-types.c
@@ -23,25 +23,6 @@
 
 #include "seahorse-types.h"
 
-GType seahorse_location_get_type (void) 
-{
-	static GType seahorse_location_type_id = 0;
-	if (!seahorse_location_type_id) {
-		static const GEnumValue values[] = {
-			{ SEAHORSE_LOCATION_INVALID, "SEAHORSE_LOCATION_INVALID", "invalid" }, 
-			{ SEAHORSE_LOCATION_MISSING, "SEAHORSE_LOCATION_MISSING", "missing" }, 
-			{ SEAHORSE_LOCATION_SEARCHING, "SEAHORSE_LOCATION_SEARCHING", "searching" }, 
-			{ SEAHORSE_LOCATION_REMOTE, "SEAHORSE_LOCATION_REMOTE", "remote" }, 
-			{ SEAHORSE_LOCATION_LOCAL, "SEAHORSE_LOCATION_LOCAL", "local" }, 
-			{ 0, NULL, NULL }
-		};
-		seahorse_location_type_id = g_enum_register_static ("SeahorseLocation", values);
-	}
-	return seahorse_location_type_id;
-}
-
-
-
 GType seahorse_usage_get_type (void) 
 {
 	static GType seahorse_usage_type_id = 0;
diff --git a/libseahorse/seahorse-types.h b/libseahorse/seahorse-types.h
index a8e3c85..dece1ab 100644
--- a/libseahorse/seahorse-types.h
+++ b/libseahorse/seahorse-types.h
@@ -28,22 +28,8 @@
 G_BEGIN_DECLS
 
 
-#define SEAHORSE_TYPE_LOCATION (seahorse_location_get_type ())
-
 #define SEAHORSE_TYPE_USAGE (seahorse_usage_get_type ())
 
-/* 
- * These types should never change. These values are exported. In the
- * case of a key being in multiple locations, the highest location always 'wins'.
- */
-typedef enum  {
-	SEAHORSE_LOCATION_INVALID = 0,
-	SEAHORSE_LOCATION_MISSING = 10,
-	SEAHORSE_LOCATION_SEARCHING = 20,
-	SEAHORSE_LOCATION_REMOTE = 50,
-	SEAHORSE_LOCATION_LOCAL = 100
-} SeahorseLocation;
-
 GType seahorse_location_get_type (void);
 
 /* Again, never change these values */
diff --git a/libseahorse/seahorse-util.c b/libseahorse/seahorse-util.c
index e89e1f9..979b542 100644
--- a/libseahorse/seahorse-util.c
+++ b/libseahorse/seahorse-util.c
@@ -27,9 +27,9 @@
 #include "seahorse-util.h"
 #include "seahorse-widget.h"
 
-#include "pgp/seahorse-pgp-module.h"
+#include "pgp/seahorse-pgp.h"
 
-#include "ssh/seahorse-ssh-module.h"
+#include "ssh/seahorse-ssh.h"
 
 #include <gio/gio.h>
 #include <glib/gstdio.h>
diff --git a/libseahorse/seahorse-util.h b/libseahorse/seahorse-util.h
index 2148264..93b24a1 100644
--- a/libseahorse/seahorse-util.h
+++ b/libseahorse/seahorse-util.h
@@ -31,8 +31,6 @@
 #include <gtk/gtk.h>
 #include <time.h>
 
-#include "seahorse-context.h"
-
 #ifdef WITH_SHARING
 #include <avahi-client/client.h>
 const AvahiPoll* seahorse_util_dns_sd_get_poll (void);
diff --git a/libseahorse/seahorse-view.h b/libseahorse/seahorse-view.h
index ad7f8ec..46b5598 100644
--- a/libseahorse/seahorse-view.h
+++ b/libseahorse/seahorse-view.h
@@ -25,6 +25,8 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include <gtk/gtk.h>
+
 #include "seahorse-object.h"
 #include "seahorse-predicate.h"
 
diff --git a/src/seahorse-viewer.c b/libseahorse/seahorse-viewer.c
similarity index 93%
rename from src/seahorse-viewer.c
rename to libseahorse/seahorse-viewer.c
index 92a5f9a..2753c8b 100644
--- a/src/seahorse-viewer.c
+++ b/libseahorse/seahorse-viewer.c
@@ -1,23 +1,23 @@
-/* 
+/*
  * Seahorse
- * 
+ *
  * Copyright (C) 2008 Stefan Walter
  * Copyright (C) 2011 Collabora Ltd.
  *
- * This program is free software; you can redistribute it and/or modify 
+ * 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.  
+ * 02111-1307, USA.
  */
 
 #include "config.h"
@@ -72,10 +72,9 @@ G_DEFINE_TYPE_EXTENDED (SeahorseViewer, seahorse_viewer, SEAHORSE_TYPE_WIDGET, 0
 static SeahorsePredicate exportable_predicate = { 0, };
 static SeahorsePredicate deletable_predicate = { 0, };
 static SeahorsePredicate importable_predicate = { 0, };
-static SeahorsePredicate remote_predicate = { 0, };
 
 /* -----------------------------------------------------------------------------
- * INTERNAL 
+ * INTERNAL
  */
 
 typedef gboolean     (*ForEachCommandsFunc)     (SeahorseViewer *self,
@@ -89,12 +88,12 @@ for_each_commands (SeahorseViewer *self, ForEachCommandsFunc func, gpointer user
 	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), 
+			if (!(func) (self, SEAHORSE_COMMANDS (predicate->commands_or_actions),
 			            &predicate->pred, user_data))
 				return;
 		}
@@ -102,7 +101,7 @@ for_each_commands (SeahorseViewer *self, ForEachCommandsFunc func, gpointer user
 }
 
 G_MODULE_EXPORT void
-on_app_preferences (GtkAction* action, SeahorseViewer* self) 
+on_app_preferences (GtkAction* action, SeahorseViewer* self)
 {
 	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
 	g_return_if_fail (GTK_IS_ACTION (action));
@@ -110,12 +109,12 @@ on_app_preferences (GtkAction* action, SeahorseViewer* self)
 	seahorse_preferences_show (seahorse_viewer_get_window (self), NULL);
 }
 
-static void 
-on_app_about (GtkAction* action, SeahorseViewer* self) 
+static void
+on_app_about (GtkAction* action, SeahorseViewer* self)
 {
 	GtkAboutDialog *about;
-	
-	const gchar *authors[] = { 
+
+	const gchar *authors[] = {
 		"Jacob Perkins <jap1 users sourceforge net>",
 		"Jose Carlos Garcia Sogo <jsogo users sourceforge net>",
 		"Jean Schurger <yshark schurger org>",
@@ -127,14 +126,14 @@ on_app_about (GtkAction* action, SeahorseViewer* self)
 		"Jim Pharis <binbrain gmail com>",
 		NULL
 	};
-	
+
 	const gchar *documenters[] = {
 		"Jacob Perkins <jap1 users sourceforge net>",
 		"Adam Schreiber <sadam clemson edu>",
 		"Milo Casagrande <milo_casagrande yahoo it>",
 		NULL
 	};
-	
+
 	const gchar *artists[] = {
 		"Jacob Perkins <jap1 users sourceforge net>",
 		"Stef Walter <stef memberwebs com>",
@@ -152,16 +151,16 @@ on_app_about (GtkAction* action, SeahorseViewer* self)
 	gtk_about_dialog_set_logo_icon_name (about, "seahorse");
 	gtk_about_dialog_set_website (about, "http://www.gnome.org/projects/seahorse";);
 	gtk_about_dialog_set_website_label (about, _("Seahorse Project Homepage"));
-	
+
 	g_signal_connect (about, "response", G_CALLBACK (gtk_widget_hide), NULL);
 	gtk_window_set_transient_for (GTK_WINDOW (about), seahorse_viewer_get_window (self));
-	
+
 	gtk_dialog_run (GTK_DIALOG (about));
 	gtk_widget_destroy (GTK_WIDGET (about));
 }
 
-static void 
-on_help_show (GtkAction* action, SeahorseViewer* self) 
+static void
+on_help_show (GtkAction* action, SeahorseViewer* self)
 {
 	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
 	g_return_if_fail (GTK_IS_ACTION (action));
@@ -179,18 +178,18 @@ static const GtkActionEntry UI_ENTRIES[] = {
 	{ "app-preferences", GTK_STOCK_PREFERENCES, N_("Prefere_nces"), NULL,
 	  N_("Change preferences for this program"), G_CALLBACK (on_app_preferences) },
 #endif
-	{ "app-about", GTK_STOCK_ABOUT, NULL, NULL, 
-	  N_("About this program"), G_CALLBACK (on_app_about) }, 
+	{ "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) } 
+	  N_("Show Seahorse help"), G_CALLBACK (on_help_show) }
 };
 
-static void 
-on_key_properties (GtkAction* action, SeahorseViewer* self) 
+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));
 }
@@ -200,12 +199,12 @@ objects_prune_non_exportable (GList *objects)
 {
 	GList *exportable = NULL;
 	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);
 	}
-	
+
 	g_list_free (objects);
 	return exportable;
 }
@@ -216,9 +215,9 @@ filter_matching_objects (SeahorsePredicate *pred,
 {
 	GList *results, *next, *here;
 	SeahorseObject *object;
-	
+
 	results = NULL;
-	
+
 	next = *all_objects;
 	while ((here = next) != NULL) {
 		g_return_val_if_fail (SEAHORSE_IS_OBJECT (here->data), NULL);
@@ -231,7 +230,7 @@ filter_matching_objects (SeahorsePredicate *pred,
 			*all_objects = g_list_delete_link (*all_objects, here);
 		}
 	}
-	
+
 	return results;
 }
 
@@ -250,11 +249,11 @@ has_matching_objects (SeahorsePredicate *pred,
 		if (seahorse_predicate_match (pred, object))
 			return TRUE;
 	}
-	
+
 	return FALSE;
 }
 
-static void 
+static void
 on_file_export_completed (GObject *source,
                           GAsyncResult *result,
                           gpointer user_data)
@@ -269,23 +268,23 @@ on_file_export_completed (GObject *source,
 	g_object_unref (self);
 }
 
-static void 
-on_key_export_file (GtkAction* action, SeahorseViewer* self) 
+static void
+on_key_export_file (GtkAction* action, SeahorseViewer* self)
 {
 	GError *error = NULL;
 	GList *objects;
 	GtkDialog *dialog;
 	gchar *uri, *unesc_uri;
-	
+
 	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
 	g_return_if_fail (GTK_IS_ACTION (action));
-	
+
 	objects = seahorse_viewer_get_selected_objects (self);
 	objects = objects_prune_non_exportable (objects);
 	if (objects == NULL)
 		return;
 
-	dialog = seahorse_util_chooser_save_new (_("Export public key"), 
+	dialog = seahorse_util_chooser_save_new (_("Export public key"),
 	                                         seahorse_viewer_get_window (self));
 	seahorse_util_chooser_show_key_files (dialog);
 	seahorse_util_chooser_set_filename_full (dialog, objects);
@@ -309,7 +308,7 @@ on_key_export_file (GtkAction* action, SeahorseViewer* self)
 			seahorse_progress_show (cancellable, _("Exporting keys"), TRUE);
 			g_object_unref (cancellable);
 		}
-		
+
 
 		g_object_unref (file);
 		g_object_unref (output);
@@ -319,7 +318,7 @@ on_key_export_file (GtkAction* action, SeahorseViewer* self)
 	g_list_free (objects);
 }
 
-static void 
+static void
 on_copy_export_complete (GObject *source,
                          GAsyncResult *result,
                          gpointer user_data)
@@ -352,8 +351,8 @@ on_copy_export_complete (GObject *source,
 	g_object_unref (self);
 }
 
-static void 
-on_key_export_clipboard (GtkAction* action, SeahorseViewer* self) 
+static void
+on_key_export_clipboard (GtkAction* action, SeahorseViewer* self)
 {
 	GList* objects;
 	GOutputStream* output;
@@ -390,17 +389,17 @@ delete_objects_for_selected (SeahorseViewer *self,
 	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) 
+	if (!objects)
 		return TRUE;
-	
+
 	/* Indicate to our users what is being operated on */
 	seahorse_viewer_set_selected_objects (self, objects);
 
@@ -411,7 +410,7 @@ delete_objects_for_selected (SeahorseViewer *self,
 }
 
 static void
-on_key_delete (GtkAction* action, SeahorseViewer* self) 
+on_key_delete (GtkAction* action, SeahorseViewer* self)
 {
 	GList *objects = NULL;
 	GList *all_objects = NULL;
@@ -427,9 +426,9 @@ on_key_delete (GtkAction* action, SeahorseViewer* self)
 	/* Check for private objects */
 	for (l = objects; l; l = g_list_next (l)) {
 		SeahorseObject* object = l->data;
-		
+
 		if (seahorse_object_get_usage (object) == SEAHORSE_USAGE_PRIVATE_KEY) {
-			gchar* prompt = g_strdup_printf (_("%s is a private key. Are you sure you want to proceed?"), 
+			gchar* prompt = g_strdup_printf (_("%s is a private key. Are you sure you want to proceed?"),
 			                                 seahorse_object_get_label (object));
 			if (!seahorse_util_prompt_delete (prompt, GTK_WIDGET (seahorse_viewer_get_window (self)))) {
 				g_free (prompt);
@@ -438,14 +437,15 @@ on_key_delete (GtkAction* action, SeahorseViewer* self)
 			}
 		}
 	}
-	
+
 	/* Go through the list of predicates, and call each one */
 	for_each_commands (self, delete_objects_for_selected, &objects);
 
 	g_list_free (objects);
 }
 
-static void 
+#if REFACTOR_IMPORT
+static void
 on_import_complete (GObject *source,
                     GAsyncResult *result,
                     gpointer user_data)
@@ -462,10 +462,12 @@ on_import_complete (GObject *source,
 
 	g_object_unref (self);
 }
+#endif
 
-static void 
-on_key_import_keyring (GtkAction* action, SeahorseViewer* self) 
+static void
+on_key_import_keyring (GtkAction* action, SeahorseViewer* self)
 {
+#ifdef REFACTOR_IMPORT
 	GCancellable *cancellable;
 	GList* objects;
 
@@ -474,9 +476,9 @@ on_key_import_keyring (GtkAction* action, SeahorseViewer* self)
 
 	objects = seahorse_viewer_get_selected_objects (self);
 	objects = objects_prune_non_exportable (objects);
-		
+
 	/* No objects, nothing to do */
-	if (objects == NULL) 
+	if (objects == NULL)
 		return;
 
 	cancellable = g_cancellable_new ();
@@ -487,9 +489,9 @@ on_key_import_keyring (GtkAction* action, SeahorseViewer* self)
 	g_object_unref (cancellable);
 
 	g_list_free (objects);
+#endif
 }
 
-
 static gboolean
 show_properties_for_selected (SeahorseViewer *self,
                               SeahorseCommands *commands,
@@ -497,17 +499,17 @@ show_properties_for_selected (SeahorseViewer *self,
                               gpointer user_data)
 {
 	g_return_val_if_fail (SEAHORSE_IS_OBJECT (user_data), FALSE);
-	
+
 	/* 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;
 }
-		
+
 static const GtkActionEntry KEY_ENTRIES[] = {
 	{ "show-properties", GTK_STOCK_PROPERTIES, NULL, NULL,
 	  N_("Show properties"), G_CALLBACK (on_key_properties) },
@@ -523,24 +525,24 @@ static const GtkActionEntry EXPORT_ENTRIES[] = {
 };
 
 static const GtkActionEntry IMPORT_ENTRIES[] = {
-	{ "key-import-keyring", GTK_STOCK_ADD, N_("_Import"), "", 
+	{ "key-import-keyring", GTK_STOCK_ADD, N_("_Import"), "",
 	  N_("Import selected keys to local key ring"), G_CALLBACK (on_key_import_keyring) }
 };
-		
-static void 
-include_basic_actions (SeahorseViewer* self) 
+
+static void
+include_basic_actions (SeahorseViewer* self)
 {
 	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);
-	
+
 	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);
@@ -550,12 +552,12 @@ include_basic_actions (SeahorseViewer* self)
 	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);
-	
+
 	pv->import_actions = gtk_action_group_new ("import");
 	gtk_action_group_set_translation_domain (pv->import_actions, GETTEXT_PACKAGE);
 	gtk_action_group_add_actions (pv->import_actions, IMPORT_ENTRIES, G_N_ELEMENTS (IMPORT_ENTRIES), self);
@@ -563,34 +565,34 @@ include_basic_actions (SeahorseViewer* self)
 	seahorse_viewer_include_actions (self, pv->import_actions);
 }
 
-static void 
-on_selection_changed (SeahorseView* view, SeahorseViewer* self) 
+static void
+on_selection_changed (SeahorseView* view, SeahorseViewer* self)
 {
 	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE (self);
 	ViewerPredicate *predicate;
 	GList *objects;
 	guint i;
-	
+
 	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
 	g_return_if_fail (SEAHORSE_IS_VIEW (view));
-	
+
 	/* Enable if anything is selected */
 	gtk_action_group_set_sensitive (pv->object_actions, seahorse_view_get_selected (view) != NULL);
-	
+
 	objects = seahorse_viewer_get_selected_objects (self);
-	
+
 	/* Enable if any exportable objects are selected */
-	gtk_action_group_set_sensitive (pv->export_actions, 
+	gtk_action_group_set_sensitive (pv->export_actions,
 	                                has_matching_objects (&exportable_predicate, objects));
-	                                
+
     /* Enable if any importable objects are selected */
-    gtk_action_group_set_sensitive (pv->import_actions, 
+    gtk_action_group_set_sensitive (pv->import_actions,
 	                                has_matching_objects (&importable_predicate, objects));
-	
+
 	/* Enable if any deletable objects are selected */
-	gtk_action_set_sensitive (pv->delete_action, 
+	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);
@@ -599,29 +601,29 @@ on_selection_changed (SeahorseView* view, SeahorseViewer* self)
 		gtk_action_group_set_visible (GTK_ACTION_GROUP (predicate->commands_or_actions),
 		                              has_matching_objects (&predicate->pred, objects));
 	}
-	
+
 	g_list_free (objects);
 }
 
-static void 
-on_add_widget (GtkUIManager* ui, GtkWidget* widget, SeahorseViewer* self) 
+static void
+on_add_widget (GtkUIManager* ui, GtkWidget* widget, SeahorseViewer* self)
 {
 	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"; 
+		name = "menu-placeholder";
 	else if (GTK_IS_TOOLBAR (widget))
 		name = "toolbar-placeholder";
 	else
 		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
 		g_warning ("no place holder found for: %s", name);
@@ -629,7 +631,7 @@ on_add_widget (GtkUIManager* ui, GtkWidget* widget, SeahorseViewer* self)
 
 
 /* -----------------------------------------------------------------------------
- * OBJECT 
+ * OBJECT
  */
 
 static GList*
@@ -638,19 +640,19 @@ seahorse_viewer_get_selected_matching (SeahorseView *base,
 {
 	GList *all_objects;
 	GList *objects;
-	
+
 	g_return_val_if_fail (SEAHORSE_IS_VIEW (base), NULL);
 	g_return_val_if_fail (pred, NULL);
-	
+
 	all_objects = seahorse_view_get_selected_objects (base);
 	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 GObject*
+seahorse_viewer_constructor (GType type, guint n_props, GObjectConstructParam *props)
 {
 	GObject *obj = G_OBJECT_CLASS (seahorse_viewer_parent_class)->constructor (type, n_props, props);
 	SeahorseViewer *self = NULL;
@@ -660,7 +662,7 @@ seahorse_viewer_constructor (GType type, guint n_props, GObjectConstructParam *p
 	const gchar *name;
 	gchar *path;
 	GList *types, *l;
-	
+
 	if (obj) {
 		pv = SEAHORSE_VIEWER_GET_PRIVATE (obj);
 		self = SEAHORSE_VIEWER (obj);
@@ -674,15 +676,15 @@ seahorse_viewer_constructor (GType type, guint n_props, GObjectConstructParam *p
 		}
 
 		g_free (path);
-		
+
 		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_window_add_accel_group (GTK_WINDOW (win),
 			                            gtk_ui_manager_get_accel_group (pv->ui_manager));
 
 		include_basic_actions (self);
-		
-		g_signal_connect (SEAHORSE_VIEW (self), "selection-changed", 
+
+		g_signal_connect (SEAHORSE_VIEW (self), "selection-changed",
 		                  G_CALLBACK (on_selection_changed), self);
 
 		/* Setup the commands */
@@ -690,13 +692,13 @@ seahorse_viewer_constructor (GType type, guint n_props, GObjectConstructParam *p
 		for (l = types; l; l = g_list_next (l)) {
 			GType typ = GPOINTER_TO_SIZE (l->data);
 			SeahorseCommands *commands;
-			
+
 			commands = g_object_new (typ, "view", self, NULL);
 			pv->all_commands = seahorse_object_list_prepend (pv->all_commands, commands);
 			g_object_unref (commands);
 		}
 	}
-	
+
 	return obj;
 }
 
@@ -705,7 +707,7 @@ 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);
 
@@ -718,19 +720,19 @@ 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;
-	
+
 	if (pv->export_actions)
 		g_object_unref (pv->export_actions);
 	pv->export_actions = NULL;
-	
+
 	if (pv->delete_action)
 		g_object_unref (pv->delete_action);
 	pv->delete_action = NULL;
@@ -740,10 +742,10 @@ seahorse_viewer_dispose (GObject *obj)
 		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_OBJECT_CLASS (seahorse_viewer_parent_class)->dispose (obj);
 }
 
@@ -751,7 +753,7 @@ static void
 seahorse_viewer_finalize (GObject *obj)
 {
 	SeahorseViewerPrivate *pv = SEAHORSE_VIEWER_GET_PRIVATE(obj);
-	
+
 	g_assert (pv->object_actions == NULL);
 	g_assert (pv->export_actions == NULL);
 	g_assert (pv->delete_action == NULL);
@@ -763,11 +765,11 @@ seahorse_viewer_finalize (GObject *obj)
 }
 
 static void
-seahorse_viewer_get_property (GObject *obj, guint prop_id, GValue *value, 
+seahorse_viewer_get_property (GObject *obj, guint prop_id, GValue *value,
                               GParamSpec *pspec)
 {
 	SeahorseViewer *self = SEAHORSE_VIEWER (obj);
-	
+
 	switch (prop_id) {
 	case PROP_SELECTED:
 		g_value_set_object (value, seahorse_viewer_get_selected (self));
@@ -782,11 +784,11 @@ 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, 
+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));
@@ -801,7 +803,7 @@ 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));
 
@@ -810,11 +812,11 @@ seahorse_viewer_class_init (SeahorseViewerClass *klass)
 	gobject_class->finalize = seahorse_viewer_finalize;
 	gobject_class->set_property = seahorse_viewer_set_property;
 	gobject_class->get_property = seahorse_viewer_get_property;
-	
+
 	g_object_class_install_property (gobject_class, PROP_SELECTED,
-	           g_param_spec_object ("selected", "Selected", "Selected Object", 
+	           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));
@@ -822,12 +824,10 @@ seahorse_viewer_class_init (SeahorseViewerClass *klass)
 	exportable_predicate.flags = SEAHORSE_FLAG_EXPORTABLE;
 	deletable_predicate.flags = SEAHORSE_FLAG_DELETABLE;
 	importable_predicate.flags = SEAHORSE_FLAG_EXPORTABLE;
-	importable_predicate.location = SEAHORSE_LOCATION_REMOTE;
-	remote_predicate.location = SEAHORSE_LOCATION_REMOTE;
 }
 
-static void 
-seahorse_viewer_implement_view (SeahorseViewIface *iface) 
+static void
+seahorse_viewer_implement_view (SeahorseViewIface *iface)
 {
 	iface->get_selected_objects = (gpointer)seahorse_viewer_get_selected_objects;
 	iface->set_selected_objects = (gpointer)seahorse_viewer_set_selected_objects;
@@ -840,7 +840,7 @@ seahorse_viewer_implement_view (SeahorseViewIface *iface)
 }
 
 /* -----------------------------------------------------------------------------
- * PUBLIC 
+ * PUBLIC
  */
 
 void
@@ -848,7 +848,7 @@ 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);
 
 }
@@ -867,7 +867,7 @@ 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);
 }
 
@@ -876,7 +876,7 @@ 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);
 }
 
@@ -885,7 +885,7 @@ seahorse_viewer_get_selected_object_and_uid (SeahorseViewer* self, guint* uid)
 {
 	g_return_val_if_fail (SEAHORSE_IS_VIEWER (self), NULL);
 	g_return_val_if_fail (SEAHORSE_VIEWER_GET_CLASS (self)->get_selected_object_and_uid, NULL);
-	
+
 	return SEAHORSE_VIEWER_GET_CLASS (self)->get_selected_object_and_uid (self, uid);
 }
 
@@ -899,7 +899,7 @@ seahorse_viewer_show_context_menu (SeahorseViewer* self, guint button, guint tim
 
 	menu = GTK_MENU (gtk_ui_manager_get_widget (pv->ui_manager, "/KeyPopup"));
 	g_return_if_fail (GTK_IS_MENU (menu));
-	
+
 	gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, time);
 	gtk_widget_show (GTK_WIDGET (menu));
 }
@@ -909,7 +909,7 @@ seahorse_viewer_show_properties (SeahorseViewer* self, SeahorseObject* obj)
 {
 	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
 	g_return_if_fail (SEAHORSE_IS_OBJECT (obj));
-	
+
 	for_each_commands (self, show_properties_for_selected, obj);
 }
 
@@ -921,7 +921,7 @@ seahorse_viewer_set_status (SeahorseViewer* self, const char* text)
 
 	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
 	g_return_if_fail (text != NULL);
-	
+
 	status = GTK_STATUSBAR (seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "status"));
 	g_return_if_fail (GTK_IS_STATUSBAR (status));
 
@@ -937,7 +937,7 @@ seahorse_viewer_set_numbered_status (SeahorseViewer* self, const char* text, gin
 
 	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);
@@ -957,12 +957,12 @@ seahorse_viewer_set_selected (SeahorseViewer* self, SeahorseObject* 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);
 }
 
-GtkWindow* 
-seahorse_viewer_get_window (SeahorseViewer* self) 
+GtkWindow*
+seahorse_viewer_get_window (SeahorseViewer* self)
 {
 	g_return_val_if_fail (SEAHORSE_IS_VIEWER (self), NULL);
 	return GTK_WINDOW (seahorse_widget_get_toplevel (SEAHORSE_WIDGET (self)));
@@ -977,12 +977,12 @@ seahorse_viewer_register_ui (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)
@@ -992,7 +992,7 @@ seahorse_viewer_register_ui (SeahorseViewer *self,
 		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);
@@ -1008,7 +1008,7 @@ seahorse_viewer_register_commands (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));
 
diff --git a/src/seahorse-viewer.h b/libseahorse/seahorse-viewer.h
similarity index 91%
rename from src/seahorse-viewer.h
rename to libseahorse/seahorse-viewer.h
index 699addd..6b5ef27 100644
--- a/src/seahorse-viewer.h
+++ b/libseahorse/seahorse-viewer.h
@@ -1,22 +1,22 @@
-/* 
+/*
  * Seahorse
- * 
+ *
  * Copyright (C) 2008 Stefan Walter
- * 
- * This program is free software; you can redistribute it and/or modify 
+ *
+ * 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.  
+ * 02111-1307, USA.
  */
 
 #ifndef __SEAHORSE_VIEWER_H__
@@ -38,28 +38,28 @@
 typedef struct _SeahorseViewer SeahorseViewer;
 typedef struct _SeahorseViewerClass SeahorseViewerClass;
 typedef struct _SeahorseViewerPrivate SeahorseViewerPrivate;
-    
+
 struct _SeahorseViewer {
 	SeahorseWidget parent;
 };
 
 struct _SeahorseViewerClass {
 	SeahorseWidgetClass parent;
-    
+
 	/* virtual -------------------------------------------------------- */
-    
+
 	GList* (*get_selected_objects) (SeahorseViewer* self);
-	
+
 	void (*set_selected_objects) (SeahorseViewer* self, GList* objects);
-	
+
 	SeahorseObject* (*get_selected_object_and_uid) (SeahorseViewer* self, guint* uid);
-	
+
 	SeahorseObject* (*get_selected) (SeahorseViewer* self);
-	
+
 	void (*set_selected) (SeahorseViewer* self, SeahorseObject* value);
 
 	/* signals --------------------------------------------------------- */
-    
+
 	void (*signal)   (SeahorseViewer *viewer);
 };
 
@@ -67,44 +67,44 @@ GType               seahorse_viewer_get_type                        (void);
 
 void                seahorse_viewer_ensure_updated                  (SeahorseViewer* self);
 
-void                seahorse_viewer_include_actions                 (SeahorseViewer* self, 
+void                seahorse_viewer_include_actions                 (SeahorseViewer* self,
                                                                      GtkActionGroup* actions);
 
 GList*              seahorse_viewer_get_selected_objects            (SeahorseViewer* self);
 
-void                seahorse_viewer_set_selected_objects            (SeahorseViewer* self, 
+void                seahorse_viewer_set_selected_objects            (SeahorseViewer* self,
                                                                      GList* objects);
 
-SeahorseObject*     seahorse_viewer_get_selected_object_and_uid     (SeahorseViewer* self, 
+SeahorseObject*     seahorse_viewer_get_selected_object_and_uid     (SeahorseViewer* self,
                                                                      guint* uid);
 
-void                seahorse_viewer_show_context_menu               (SeahorseViewer* self, 
-                                                                     guint button, 
+void                seahorse_viewer_show_context_menu               (SeahorseViewer* self,
+                                                                     guint button,
                                                                      guint time);
 
-void                seahorse_viewer_show_properties                 (SeahorseViewer* self, 
+void                seahorse_viewer_show_properties                 (SeahorseViewer* self,
                                                                      SeahorseObject* obj);
 
-void                seahorse_viewer_set_status                      (SeahorseViewer* self, 
+void                seahorse_viewer_set_status                      (SeahorseViewer* self,
                                                                      const char* text);
 
-void                seahorse_viewer_set_numbered_status             (SeahorseViewer* self, 
-                                                                     const char* text, 
+void                seahorse_viewer_set_numbered_status             (SeahorseViewer* self,
+                                                                     const char* text,
                                                                      gint num);
 
 SeahorseObject*     seahorse_viewer_get_selected                    (SeahorseViewer* self);
 
-void                seahorse_viewer_set_selected                    (SeahorseViewer* self, 
+void                seahorse_viewer_set_selected                    (SeahorseViewer* self,
                                                                      SeahorseObject* value);
 
 GtkWindow*          seahorse_viewer_get_window                      (SeahorseViewer* self);
 
-void                seahorse_viewer_register_ui                     (SeahorseViewer *self, 
+void                seahorse_viewer_register_ui                     (SeahorseViewer *self,
                                                                      SeahorsePredicate *pred,
-                                                                     const gchar *uidef, 
+                                                                     const gchar *uidef,
                                                                      GtkActionGroup *actions);
 
-void                seahorse_viewer_register_commands               (SeahorseViewer *self, 
+void                seahorse_viewer_register_commands               (SeahorseViewer *self,
                                                                      SeahorsePredicate *pred,
                                                                      SeahorseCommands *commands);
 
diff --git a/pgp/Makefile.am b/pgp/Makefile.am
index fe90dec..89a48b1 100644
--- a/pgp/Makefile.am
+++ b/pgp/Makefile.am
@@ -30,11 +30,15 @@ endif
 
 if WITH_KEYSERVER
 KEYSERVER_SRCS = seahorse-server-source.c seahorse-server-source.h 
+KEYSERVER_SRCS += seahorse-keyserver-search.c seahorse-keyserver-sync.c seahorse-keyserver-sync.h
+KEYSERVER_SRCS += seahorse-keyserver-results.c seahorse-keyserver-results.h
 else
 KEYSERVER_SRCS = 
 endif
 
 libseahorse_pgp_la_SOURCES = \
+	seahorse-combo-keys.c seahorse-combo-keys.h \
+	seahorse-discovery.c seahorse-discovery.h \
 	seahorse-gpgme.c seahorse-gpgme.h \
 	seahorse-gpgme-add-subkey.c \
 	seahorse-gpgme-add-uid.c \
@@ -44,26 +48,29 @@ libseahorse_pgp_la_SOURCES = \
 	seahorse-gpgme-generate.c \
 	seahorse-gpgme-key.c seahorse-gpgme-key.h \
 	seahorse-gpgme-key-op.c seahorse-gpgme-key-op.h \
+	seahorse-gpgme-keyring.c seahorse-gpgme-keyring.h \
 	seahorse-gpgme-photo.c seahorse-gpgme-photo.h \
 	seahorse-gpgme-photos.c \
 	seahorse-gpgme-revoke.c \
 	seahorse-gpgme-sign.c \
-	seahorse-gpgme-source.c seahorse-gpgme-source.h \
 	seahorse-gpgme-subkey.c seahorse-gpgme-subkey.h \
 	seahorse-gpgme-uid.c seahorse-gpgme-uid.h \
 	seahorse-gpg-op.h seahorse-gpg-op.c \
 	seahorse-gpg-options.c seahorse-gpg-options.h \
 	seahorse-pgp.c seahorse-pgp.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 \
 	seahorse-pgp-photo.c seahorse-pgp-photo.h \
-	seahorse-pgp-module.c seahorse-pgp-module.h \
 	seahorse-pgp-signature.c seahorse-pgp-signature.h \
 	seahorse-pgp-subkey.c seahorse-pgp-subkey.h \
 	seahorse-pgp-uid.c seahorse-pgp-uid.h \
 	seahorse-signer.c seahorse-pgp-dialogs.h \
+	seahorse-transfer.c seahorse-transfer.h \
+	seahorse-unknown.c seahorse-unknown.h \
+	seahorse-unknown-source.c seahorse-unknown-source.h \
 	$(VALA_CFILES) $(VALA_HFILES) \
 	$(KEYSERVER_SRCS) \
 	$(LDAP_SRCS) \
diff --git a/libseahorse/seahorse-combo-keys.c b/pgp/seahorse-combo-keys.c
similarity index 90%
rename from libseahorse/seahorse-combo-keys.c
rename to pgp/seahorse-combo-keys.c
index 8b2bf35..d3b4034 100644
--- a/libseahorse/seahorse-combo-keys.c
+++ b/pgp/seahorse-combo-keys.c
@@ -32,7 +32,7 @@ enum {
 };
 
 /* -----------------------------------------------------------------------------
- * HELPERS 
+ * HELPERS
  */
 
 static void
@@ -145,7 +145,7 @@ on_combo_destroy (GtkComboBox *combo,
  * PUBLIC CALLS
  */
 
-void 
+void
 seahorse_combo_keys_attach (GtkComboBox *combo,
                             GcrCollection *collection,
                             const gchar *none_option)
@@ -194,37 +194,38 @@ seahorse_combo_keys_attach (GtkComboBox *combo,
 }
 
 void
-seahorse_combo_keys_set_active_id (GtkComboBox *combo, GQuark id)
+seahorse_combo_keys_set_active_id (GtkComboBox *combo,
+                                   const gchar *keyid)
 {
-    SeahorseObject *object;
+    SeahorsePgpKey *key;
     GtkTreeModel *model;
     GtkTreeIter iter;
     gboolean valid;
     gpointer pointer;
     guint i;
-    
+
     g_return_if_fail (GTK_IS_COMBO_BOX (combo));
 
     model = gtk_combo_box_get_model (combo);
     g_return_if_fail (model != NULL);
-    
+
     valid = gtk_tree_model_get_iter_first (model, &iter);
     i = 0;
-    
+
     while (valid) {
         gtk_tree_model_get (model, &iter,
                             COMBO_POINTER, &pointer,
                             -1);
-                            
-        object = SEAHORSE_OBJECT (pointer);
-        
-        if (!id) {
-            if (!object) {
+
+        key = SEAHORSE_PGP_KEY (pointer);
+
+        if (!keyid) {
+            if (!key) {
                 gtk_combo_box_set_active_iter (combo, &iter);
                 break;
             }
-        } else if (object != NULL) {
-            if (id == seahorse_object_get_id (object)) {
+        } else if (key != NULL) {
+            if (g_strcmp0 (seahorse_pgp_key_get_keyid (key), keyid) == 0) {
                 gtk_combo_box_set_active_iter (combo, &iter);
                 break;
             }
@@ -235,37 +236,38 @@ seahorse_combo_keys_set_active_id (GtkComboBox *combo, GQuark id)
     }
 }
 
-void 
-seahorse_combo_keys_set_active (GtkComboBox *combo, SeahorseObject *object)
+void
+seahorse_combo_keys_set_active (GtkComboBox *combo,
+                                SeahorsePgpKey *key)
 {
-    seahorse_combo_keys_set_active_id (combo, 
-                object == NULL ? 0 : seahorse_object_get_id (object));
+	seahorse_combo_keys_set_active_id (combo,
+	          key == NULL ? NULL : seahorse_pgp_key_get_keyid (key));
 }
 
-SeahorseObject* 
+SeahorsePgpKey *
 seahorse_combo_keys_get_active (GtkComboBox *combo)
 {
     GtkTreeModel *model;
     GtkTreeIter iter;
     gpointer pointer;
-    
+
     g_return_val_if_fail (GTK_IS_COMBO_BOX (combo), NULL);
-    
+
     model = gtk_combo_box_get_model (combo);
     g_return_val_if_fail (model != NULL, NULL);
-    
+
     gtk_combo_box_get_active_iter(combo, &iter);
-    
+
     gtk_tree_model_get (model, &iter,
                         COMBO_POINTER, &pointer,
                         -1);
 
-    return SEAHORSE_OBJECT (pointer);
+    return SEAHORSE_PGP_KEY (pointer);
 }
 
-GQuark 
+const gchar *
 seahorse_combo_keys_get_active_id (GtkComboBox *combo)
 {
-    SeahorseObject *object = seahorse_combo_keys_get_active (combo);
-    return object == NULL ? 0 : seahorse_object_get_id (object);
+	SeahorsePgpKey *key = seahorse_combo_keys_get_active (combo);
+	return key == NULL ? 0 : seahorse_pgp_key_get_keyid (key);
 }
diff --git a/libseahorse/seahorse-combo-keys.h b/pgp/seahorse-combo-keys.h
similarity index 88%
rename from libseahorse/seahorse-combo-keys.h
rename to pgp/seahorse-combo-keys.h
index 9e6f928..a9ff4ce 100644
--- a/libseahorse/seahorse-combo-keys.h
+++ b/pgp/seahorse-combo-keys.h
@@ -19,17 +19,17 @@
  * Boston, MA 02111-1307, USA.
  */
 
-/** 
+/**
  * seahorse_combo_keys_*: Shows a list of keys in a dropdown for selection.
- * 
+ *
  * - Attaches to a GtkComboBox
  * - Gets its list of keys from a SeahorseSet.
  */
- 
+
 #ifndef __SEAHORSE_COMBO_KEYS_H__
 #define __SEAHORSE_COMBO_KEYS_H__
 
-#include "seahorse-object.h"
+#include "seahorse-pgp-key.h"
 
 #include <gtk/gtk.h>
 #include <gcr/gcr.h>
@@ -39,13 +39,13 @@ void                        seahorse_combo_keys_attach              (GtkComboBox
                                                                      const gchar *none_option);
 
 void                        seahorse_combo_keys_set_active_id       (GtkComboBox *combo,
-                                                                     GQuark keyid);
+                                                                     const gchar *keyid);
 
 void                        seahorse_combo_keys_set_active          (GtkComboBox *combo,
-                                                                     SeahorseObject *object);
+                                                                     SeahorsePgpKey *key);
 
-SeahorseObject*             seahorse_combo_keys_get_active          (GtkComboBox *combo);
+SeahorsePgpKey *            seahorse_combo_keys_get_active          (GtkComboBox *combo);
 
-GQuark                      seahorse_combo_keys_get_active_id       (GtkComboBox *combo);
+const gchar *               seahorse_combo_keys_get_active_id       (GtkComboBox *combo);
 
 #endif /* __SEAHORSE_COMBO_KEYS_H__ */
diff --git a/pgp/seahorse-discovery.c b/pgp/seahorse-discovery.c
new file mode 100644
index 0000000..3985eb5
--- /dev/null
+++ b/pgp/seahorse-discovery.c
@@ -0,0 +1,453 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2005 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU 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-discovery.h"
+#include "seahorse-pgp-backend.h"
+#include "seahorse-server-source.h"
+
+#ifdef WITH_SHARING
+#include <avahi-client/client.h>
+#include <avahi-client/lookup.h>
+#include <avahi-common/error.h>
+#endif /* WITH_SHARING */
+
+#include "seahorse-util.h"
+
+#define DEBUG_FLAG SEAHORSE_DEBUG_DNSSD
+#include "seahorse-debug.h"
+
+#define HKP_SERVICE_TYPE "_pgpkey-hkp._tcp."
+
+/*
+ * DEBUG: Define if we want to show discoveries from this
+ * host. Normally these are suppressed
+ */
+/* #define DISCOVER_THIS_HOST 1 */
+
+
+/**
+ * SECTION:seahorse-dns-sd
+ * @short_description: Seahorse Service Discovery handles (finds, removes,...) Avahi services
+ * @include:libseahorse/seahorse-dns-sd.h
+ *
+ **/
+
+
+struct _SeahorseDiscoveryPriv {
+#ifdef WITH_SHARING
+	AvahiClient *client;
+	AvahiServiceBrowser *browser;
+#else
+	char no_use;
+#endif
+};
+
+enum {
+	ADDED,
+	REMOVED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (SeahorseDiscovery, seahorse_discovery, G_TYPE_OBJECT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+#ifdef WITH_SHARING
+
+/**
+* self: A SeahorseDiscovery object
+*
+* Disconnects avahi
+*
+**/
+static void
+disconnect (SeahorseDiscovery *self)
+{
+	if (self->priv->browser && self->priv->client)
+		avahi_service_browser_free (self->priv->browser);
+	self->priv->browser = NULL;
+
+	if (self->priv->client)
+		avahi_client_free (self->priv->client);
+	self->priv->client = NULL;
+}
+
+/**
+* resolver: The avahi resolver
+* iface: The avahi interface
+* proto: The avahi protocol
+* event: the avahi event
+* name: name of the service
+* type: must be HKP_SERVICE_TYPE
+* domain: ignored
+* host_name: ignored
+* address: address of the service
+* port: port of the service
+* txt: ignored
+* flags:
+* data: userdata
+*
+* Resolves the avahi callback (AvahiServiceResolverCallback)
+*
+**/
+static void
+resolve_callback (AvahiServiceResolver *resolver, AvahiIfIndex iface, AvahiProtocol proto,
+                  AvahiResolverEvent event, const char *name, const char *type, const char *domain,
+                  const char *host_name, const AvahiAddress *address, uint16_t port,
+                  AvahiStringList *txt, AvahiLookupResultFlags flags, void *data)
+{
+	SeahorseDiscovery *self = SEAHORSE_DISCOVERY (data);
+	gchar *service_name;
+	gchar *service_uri;
+	gchar *ipname;
+
+	g_assert (SEAHORSE_IS_DISCOVERY (self));
+
+	switch(event) {
+	case AVAHI_RESOLVER_FAILURE:
+		g_warning ("couldn't resolve service '%s': %s", name,
+		           avahi_strerror (avahi_client_errno (self->priv->client)));
+		break;
+
+	case AVAHI_RESOLVER_FOUND:
+		/* Make sure it's our type ... */
+		/* XXX Is the service always guaranteed to be ascii? */
+		if (g_ascii_strcasecmp (HKP_SERVICE_TYPE, type) != 0)
+			break;
+
+#ifndef DISCOVER_THIS_HOST
+		/* And that it's local */
+		if (flags & AVAHI_LOOKUP_RESULT_LOCAL)
+			break;
+#endif
+
+		ipname = g_new0(gchar, AVAHI_ADDRESS_STR_MAX);
+		avahi_address_snprint (ipname, AVAHI_ADDRESS_STR_MAX, address);
+
+		service_uri = g_strdup_printf ("hkp://%s:%d", ipname, (int)port);
+		service_name = g_strdup (name);
+
+		g_hash_table_replace (self->services, service_name, service_uri);
+		g_signal_emit (self, signals[ADDED], 0, service_name);
+
+		/* Add it to the context */
+		if (!seahorse_pgp_backend_lookup_remote (NULL, service_uri)) {
+			SeahorseServerSource *ssrc = seahorse_server_source_new (service_uri);
+			g_return_if_fail (ssrc != NULL);
+			seahorse_pgp_backend_add_remote (NULL, service_uri, ssrc);
+			g_object_unref (ssrc);
+		}
+
+		seahorse_debug ("added: %s %s\n", service_name, service_uri);
+		break;
+
+	default:
+		break;
+	};
+
+	/* One result is enough for us */
+	avahi_service_resolver_free (resolver);
+}
+
+/**
+* browser: The avahi browser
+* iface: the interface
+* proto: the protocol
+* event: the event that happened while browsing (failure, new, remove)
+* name: name of the service
+* type: HKP_SERVICE_TYPE is expected
+* domain: domain of the service
+* flags: ignored
+* data: userdata, type SeahorseDiscovery
+*
+* Called when a service is discovered while browsing.
+* It is a AvahiServiceBrowserCallback
+*
+**/
+static void
+browse_callback(AvahiServiceBrowser *browser, AvahiIfIndex iface, AvahiProtocol proto,
+                AvahiBrowserEvent event, const char *name, const char *type,
+                const char *domain, AvahiLookupResultFlags flags, void* data)
+{
+	SeahorseDiscovery *self = SEAHORSE_DISCOVERY (data);
+	const gchar *uri;
+
+	g_assert (SEAHORSE_IS_DISCOVERY (self));
+	g_assert (browser == self->priv->browser);
+
+	/* XXX Is the service always guaranteed to be ascii? */
+	if (g_ascii_strcasecmp (HKP_SERVICE_TYPE, type) != 0)
+		return;
+
+	switch (event) {
+	case AVAHI_BROWSER_FAILURE:
+		g_warning ("failure browsing for services: %s",
+		           avahi_strerror (avahi_client_errno (self->priv->client)));
+		disconnect (self);
+		break;
+
+	case AVAHI_BROWSER_NEW:
+		if (!avahi_service_resolver_new (self->priv->client, iface, proto, name, type,
+		                                 domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, self))
+			g_warning ("couldn't start resolver for service '%s': %s\n", name,
+			           avahi_strerror (avahi_client_errno (self->priv->client)));
+		break;
+
+	case AVAHI_BROWSER_REMOVE:
+		uri = g_hash_table_lookup (self->services, name);
+		if (uri != NULL) {
+			/* Remove it from the main context */
+			seahorse_pgp_backend_remove_remote (NULL, uri);
+		}
+
+		/* And remove it from our tables */
+		g_hash_table_remove (self->services, name);
+		g_signal_emit (self, signals[REMOVED], 0, name);
+		seahorse_debug ("removed: %s\n", name);
+		break;
+
+	default:
+		break;
+	}
+}
+
+/**
+* client: Will be part of a potential error message
+* state: the state of the avahi connection
+* data: A SeahorseDiscovery object
+*
+* Handles AVAHI_CLIENT_FAILURE errors in state
+*
+**/
+static void
+client_callback (AvahiClient *client, AvahiClientState state, void *data)
+{
+	SeahorseDiscovery *self = SEAHORSE_DISCOVERY (data);
+
+	g_assert (SEAHORSE_IS_DISCOVERY (self));
+
+	/* Disconnect when failed */
+	if (state == AVAHI_CLIENT_FAILURE) {
+		g_return_if_fail (client == self->priv->client);
+		g_warning ("failure communicating with to avahi: %s",
+		           avahi_strerror (avahi_client_errno (client)));
+		disconnect (self);
+	}
+}
+
+#endif /* WITH_SHARING */
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+
+/**
+* self: The SeahorseDiscovery to init
+*
+* When compiled WITH_SHARING avahi will also be initialised and it will browse
+* for avahi services.
+**/
+static void
+seahorse_discovery_init (SeahorseDiscovery *self)
+{
+	self->priv = g_new0 (SeahorseDiscoveryPriv, 1);
+	self->services = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+#ifdef WITH_SHARING
+	{
+		int aerr;
+		self->priv->client = avahi_client_new (seahorse_util_dns_sd_get_poll (),
+		                                       0, client_callback, self, &aerr);
+		if (!self->priv->client) {
+			g_message ("DNS-SD initialization failed: %s", avahi_strerror (aerr));
+			return;
+		}
+
+		self->priv->browser = avahi_service_browser_new (self->priv->client, AVAHI_IF_UNSPEC,
+		                                                 AVAHI_PROTO_UNSPEC, HKP_SERVICE_TYPE, NULL, 0,
+		                                                 browse_callback, self);
+		if (!self->priv->browser) {
+			g_message ("Browsing for DNS-SD services failed: %s",
+			           avahi_strerror (avahi_client_errno (self->priv->client)));
+			return;
+		}
+	}
+#endif /* WITH_SHARING */
+}
+
+/**
+* gobject: A SeahorseDiscovery object
+*
+* Disposes the object
+*
+**/
+static void
+seahorse_discovery_dispose (GObject *gobject)
+{
+#ifdef WITH_SHARING
+	SeahorseDiscovery *self = SEAHORSE_DISCOVERY (gobject);
+	disconnect (self);
+#endif
+
+	G_OBJECT_CLASS (seahorse_discovery_parent_class)->dispose (gobject);
+}
+
+
+/**
+* gobject: A SeahorseDiscovery object
+*
+* free private vars
+*
+**/
+static void
+seahorse_discovery_finalize (GObject *gobject)
+{
+	SeahorseDiscovery *self = SEAHORSE_DISCOVERY (gobject);
+
+#ifdef WITH_SHARING
+	g_assert (self->priv->browser == NULL);
+	g_assert (self->priv->client == NULL);
+#endif
+
+	if (self->services)
+		g_hash_table_destroy (self->services);
+	self->services = NULL;
+
+	g_free (self->priv);
+	self->priv = NULL;
+
+	G_OBJECT_CLASS (seahorse_discovery_parent_class)->finalize (gobject);
+}
+
+/**
+* klass: The SeahorseDiscoveryClass to initialise
+*
+* The class will use the signals "added" and "removed"
+*
+**/
+static void
+seahorse_discovery_class_init (SeahorseDiscoveryClass *klass)
+{
+	GObjectClass *gclass;
+
+	seahorse_discovery_parent_class = g_type_class_peek_parent (klass);
+	gclass = G_OBJECT_CLASS (klass);
+
+	gclass->dispose = seahorse_discovery_dispose;
+	gclass->finalize = seahorse_discovery_finalize;
+
+	signals[ADDED] = g_signal_new ("added", SEAHORSE_TYPE_DISCOVERY,
+	                               G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SeahorseDiscoveryClass, added),
+	                               NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
+	signals[REMOVED] = g_signal_new ("removed", SEAHORSE_TYPE_DISCOVERY,
+	                                 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SeahorseDiscoveryClass, removed),
+	                                 NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+/**
+ * seahorse_discovery_new:
+ *
+ *
+ *
+ * Returns: A new #SeahorseDiscovery object
+ */
+SeahorseDiscovery*
+seahorse_discovery_new (void)
+{
+	return g_object_new (SEAHORSE_TYPE_DISCOVERY, NULL);
+}
+
+/**
+ * seahorse_discovery_list:
+ * @self:  A #SeahorseDiscovery. It's services will be added to the list
+ *
+ *
+ *
+ * Returns: the services in @self
+ */
+gchar **
+seahorse_discovery_list (SeahorseDiscovery *self)
+{
+	GHashTableIter iter;
+	GPtrArray *result = g_ptr_array_new ();
+	gpointer key;
+
+	g_return_val_if_fail (SEAHORSE_IS_DISCOVERY (self), NULL);
+	g_hash_table_iter_init (&iter, self->services);
+	while (g_hash_table_iter_next (&iter, &key, NULL))
+		g_ptr_array_add (result, g_strdup (key));
+
+	return (gchar **)g_ptr_array_free (result, FALSE);
+}
+
+/**
+ * seahorse_discovery_get_uri:
+ * @self: Service discovery object
+ * @service: The service to get the uri for
+ *
+ *
+ *
+ * Returns: The URI of the service @service in @self
+ */
+const gchar*
+seahorse_discovery_get_uri (SeahorseDiscovery *self,
+                            const gchar *service)
+{
+	g_return_val_if_fail (SEAHORSE_IS_DISCOVERY (self), NULL);
+	return (const gchar*)g_hash_table_lookup (self->services, service);
+}
+
+/**
+ * seahorse_discovery_get_uris:
+ * @self: The service discovery object
+ * @services: A list of services
+ *
+ * The returned uris in the list are copied and must be freed with g_free.
+ *
+ * Returns: uris for the services
+ */
+gchar **
+seahorse_discovery_get_uris (SeahorseDiscovery *self,
+                             const gchar **services)
+{
+	GPtrArray *result = g_ptr_array_new ();
+	const gchar *uri;
+	guint i;
+
+	for (i = 0; services && services[i] != NULL; i++) {
+		uri = g_hash_table_lookup (self->services, services[i]);
+		g_ptr_array_add (result, g_strdup (uri));
+	}
+
+	g_ptr_array_add (result, NULL);
+	return (gchar **)g_ptr_array_free (result, FALSE);
+}
diff --git a/pgp/seahorse-discovery.h b/pgp/seahorse-discovery.h
new file mode 100644
index 0000000..78ab6be
--- /dev/null
+++ b/pgp/seahorse-discovery.h
@@ -0,0 +1,83 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2005 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU 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_DNS_SD_H__
+#define __SEAHORSE_DNS_SD_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#define SEAHORSE_TYPE_DISCOVERY             (seahorse_discovery_get_type ())
+#define SEAHORSE_DISCOVERY(obj)	            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_DISCOVERY, SeahorseDiscovery))
+#define SEAHORSE_DISCOVERY_CLASS(klass)	    (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_DISCOVERY, SeahorseDiscoveryClass))
+#define SEAHORSE_IS_DISCOVERY(obj)		    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_DISCOVERY))
+#define SEAHORSE_IS_DISCOVERY_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_DISCOVERY))
+#define SEAHORSE_DISCOVERY_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_DISCOVERY, SeahorseDiscoveryClass))
+
+typedef struct _SeahorseDiscovery SeahorseDiscovery;
+typedef struct _SeahorseDiscoveryClass SeahorseDiscoveryClass;
+typedef struct _SeahorseDiscoveryPriv SeahorseDiscoveryPriv;
+
+/**
+ * SeahorseDiscovery:
+ * @parent: The parent #GObject
+ * @services: A #GHashTable of known services
+ *
+ * Listens for DNS-SD shared keys on the network and
+ * adds SeahorseKeySoruce objects to the SeahorseContext as necessary.
+ *
+ * Signals:
+ *   added: A new shared key source was found.
+ *   removed: A shared key source went away.
+ */
+
+struct _SeahorseDiscovery {
+	GObject parent;
+
+	GHashTable  *services;
+	SeahorseDiscoveryPriv *priv;
+};
+
+struct _SeahorseDiscoveryClass {
+	GObjectClass parent_class;
+
+	/* A relevant service appeared on the network */
+	void    (*added)    (SeahorseDiscovery *ssd,
+	                     const gchar* service);
+
+	/* A service disappeared */
+	void    (*removed)  (SeahorseDiscovery *ssd,
+	                     const gchar* service);
+};
+
+GType                       seahorse_discovery_get_type  (void);
+
+SeahorseDiscovery*          seahorse_discovery_new       (void);
+
+gchar **                    seahorse_discovery_list      (SeahorseDiscovery *ssd);
+
+const gchar*                seahorse_discovery_get_uri   (SeahorseDiscovery *ssd,
+                                                          const gchar *service);
+
+gchar **                    seahorse_discovery_get_uris  (SeahorseDiscovery *ssd,
+                                                          const gchar **services);
+
+#endif /* __SEAHORSE_DISCOVERY_H__ */
diff --git a/pgp/seahorse-gpg-options.c b/pgp/seahorse-gpg-options.c
index cdc0f70..f73bef4 100644
--- a/pgp/seahorse-gpg-options.c
+++ b/pgp/seahorse-gpg-options.c
@@ -34,7 +34,6 @@
 #include <sys/stat.h>
 
 #include "seahorse-util.h"
-#include "seahorse-context.h"
 
 #include "pgp/seahorse-gpgme.h"
 #include "pgp/seahorse-gpg-options.h"
diff --git a/pgp/seahorse-gpgme-dialogs.h b/pgp/seahorse-gpgme-dialogs.h
index 5aa48cc..4cfe64a 100644
--- a/pgp/seahorse-gpgme-dialogs.h
+++ b/pgp/seahorse-gpgme-dialogs.h
@@ -32,7 +32,7 @@
 #include "pgp/seahorse-gpgme-key.h"
 #include "pgp/seahorse-gpgme-photo.h"
 #include "pgp/seahorse-gpgme-subkey.h"
-#include "pgp/seahorse-gpgme-source.h"
+#include "pgp/seahorse-gpgme-keyring.h"
 #include "pgp/seahorse-gpgme-uid.h"
 #include "libseahorse/seahorse-widget.h"
 
@@ -44,13 +44,13 @@ void            seahorse_gpgme_sign_prompt_uid     (SeahorseGpgmeUid *uid,
 
 void            seahorse_gpgme_generate_register    (void);
 
-void            seahorse_gpgme_generate_show        (SeahorseGpgmeSource *sksrc,
+void            seahorse_gpgme_generate_show        (SeahorseGpgmeKeyring *keyring,
                                                      GtkWindow *parent,
                                                      const char * name,
                                                      const char *email,
                                                      const gchar *comment);
 
-void            seahorse_gpgme_generate_key         (SeahorseGpgmeSource *sksrc,
+void            seahorse_gpgme_generate_key         (SeahorseGpgmeKeyring *keyring,
                                                      const gchar *name,
                                                      const gchar *email,
                                                      const gchar *comment,
diff --git a/pgp/seahorse-gpgme-generate.c b/pgp/seahorse-gpgme-generate.c
index 6476002..33783a1 100644
--- a/pgp/seahorse-gpgme-generate.c
+++ b/pgp/seahorse-gpgme-generate.c
@@ -37,11 +37,12 @@
 #include "seahorse-widget.h"
 
 #include "seahorse-pgp.h"
+#include "seahorse-pgp-backend.h"
 #include "seahorse-gpgme.h"
 #include "seahorse-gpgme-dialogs.h"
 #include "seahorse-gpgme-key.h"
 #include "seahorse-gpgme-key-op.h"
-#include "seahorse-gpgme-source.h"
+#include "seahorse-gpgme-keyring.h"
 
 /**
  * SECTION:seahorse-gpgme-generate
@@ -77,14 +78,14 @@ void           on_gpgme_generate_algorithm_changed           (GtkComboBox *combo
 static void
 on_pgp_generate_key (GtkAction *action, gpointer unused)
 {
-	SeahorseSource* sksrc;
-	
+	SeahorseGpgmeKeyring* keyring;
+
 	g_return_if_fail (GTK_IS_ACTION (action));
-	
-	sksrc = seahorse_context_find_source (seahorse_context_instance (), SEAHORSE_PGP_TYPE, SEAHORSE_LOCATION_LOCAL);
-	g_return_if_fail (sksrc != NULL);
-	
-	seahorse_gpgme_generate_show (SEAHORSE_GPGME_SOURCE (sksrc), NULL, NULL, NULL, NULL);
+
+	keyring = seahorse_pgp_backend_get_default_keyring (NULL);
+	g_return_if_fail (keyring != NULL);
+
+	seahorse_gpgme_generate_show (keyring, NULL, NULL, NULL, NULL);
 }
 
 static const GtkActionEntry ACTION_ENTRIES[] = {
@@ -174,7 +175,7 @@ on_generate_key_complete (GObject *source,
 {
 	GError *error = NULL;
 
-	if (!seahorse_gpgme_key_op_generate_finish (SEAHORSE_GPGME_SOURCE (source), result, &error))
+	if (!seahorse_gpgme_key_op_generate_finish (SEAHORSE_GPGME_KEYRING (source), result, &error))
 		seahorse_util_handle_error (&error, NULL, _("Couldn't generate PGP key"));
 }
 
@@ -194,7 +195,7 @@ on_generate_key_complete (GObject *source,
  *
  */
 void
-seahorse_gpgme_generate_key (SeahorseGpgmeSource *source,
+seahorse_gpgme_generate_key (SeahorseGpgmeKeyring *keyring,
                              const gchar *name,
                              const gchar *email,
                              const gchar *comment,
@@ -212,7 +213,7 @@ seahorse_gpgme_generate_key (SeahorseGpgmeSource *source,
 	if (gtk_dialog_run (dialog) == GTK_RESPONSE_ACCEPT) {
 		pass = seahorse_passphrase_prompt_get (dialog);
 		cancellable = g_cancellable_new ();
-		seahorse_gpgme_key_op_generate_async (source, name, email, comment,
+		seahorse_gpgme_key_op_generate_async (keyring, name, email, comment,
 		                                      pass, type, bits, expires,
 		                                      cancellable, on_generate_key_complete,
 		                                      NULL);
@@ -240,7 +241,7 @@ on_gpgme_generate_response (GtkDialog *dialog,
                             gpointer user_data)
 {
     SeahorseWidget *swidget = SEAHORSE_WIDGET (user_data);
-    SeahorseGpgmeSource *sksrc;
+    SeahorseGpgmeKeyring *keyring;
     GtkWidget *widget;
     gchar *name;
     const gchar *email;
@@ -308,13 +309,13 @@ on_gpgme_generate_response (GtkDialog *dialog,
         egg_datetime_get_as_time_t (EGG_DATETIME (widget), &expires);
     }
 
-    sksrc = SEAHORSE_GPGME_SOURCE (g_object_get_data (G_OBJECT (swidget), "source"));
-    g_assert (SEAHORSE_IS_GPGME_SOURCE (sksrc));
+    keyring = SEAHORSE_GPGME_KEYRING (g_object_get_data (G_OBJECT (swidget), "source"));
+    g_assert (SEAHORSE_IS_GPGME_KEYRING (keyring));
 
     /* Less confusing with less on the screen */
     gtk_widget_hide (seahorse_widget_get_toplevel (swidget));
 
-    seahorse_gpgme_generate_key (sksrc, name, email, comment, type, bits, expires);
+    seahorse_gpgme_generate_key (keyring, name, email, comment, type, bits, expires);
 
 
     seahorse_widget_destroy (swidget);
@@ -404,7 +405,7 @@ on_gpgme_generate_algorithm_changed (GtkComboBox *combo,
 
 /**
  * seahorse_gpgme_generate_show:
- * @sksrc: the gpgme source
+ * @keyring: the gpgme source
  * @parent: the parent window
  * @name: The user name, can be NULL if not available
  * @email: The user's email address, can be NULL if not available
@@ -414,7 +415,11 @@ on_gpgme_generate_algorithm_changed (GtkComboBox *combo,
  *
  */
 void
-seahorse_gpgme_generate_show (SeahorseGpgmeSource *sksrc, GtkWindow *parent, const gchar * name, const gchar *email, const gchar *comment)
+seahorse_gpgme_generate_show (SeahorseGpgmeKeyring *keyring,
+                              GtkWindow *parent,
+                              const gchar * name,
+                              const gchar *email,
+                              const gchar *comment)
 {
     SeahorseWidget *swidget;
     GtkWidget *widget, *datetime;
@@ -472,9 +477,8 @@ seahorse_gpgme_generate_show (SeahorseGpgmeSource *sksrc, GtkWindow *parent, con
     gtk_box_pack_start (GTK_BOX (widget), datetime, TRUE, TRUE, 0);
     gtk_widget_set_sensitive (datetime, FALSE);
     gtk_widget_show_all (widget);
-    
-    g_object_ref (sksrc);
-    g_object_set_data_full (G_OBJECT (swidget), "source", sksrc, g_object_unref);
-	
+
+    g_object_set_data_full (G_OBJECT (swidget), "source", g_object_ref (keyring), g_object_unref);
+
     on_gpgme_generate_entry_changed (NULL, swidget);
 }
diff --git a/pgp/seahorse-gpgme-key-op.c b/pgp/seahorse-gpgme-key-op.c
index 735a978..a7a0ba0 100644
--- a/pgp/seahorse-gpgme-key-op.c
+++ b/pgp/seahorse-gpgme-key-op.c
@@ -117,7 +117,7 @@ on_key_op_generate_complete (gpgme_error_t gerr,
  * Tries to generate a new key based on given parameters.
  **/
 void
-seahorse_gpgme_key_op_generate_async (SeahorseGpgmeSource *source,
+seahorse_gpgme_key_op_generate_async (SeahorseGpgmeKeyring *keyring,
                                       const gchar *name,
                                       const gchar *email,
                                       const gchar *comment,
@@ -137,7 +137,7 @@ seahorse_gpgme_key_op_generate_async (SeahorseGpgmeSource *source,
 	gpgme_error_t gerr;
 	GSource *gsource;
 
-	g_return_if_fail (SEAHORSE_IS_GPGME_SOURCE (source));
+	g_return_if_fail (SEAHORSE_IS_GPGME_KEYRING (keyring));
 	g_return_if_fail (name);
 	g_return_if_fail (strlen (name) > 4);
 	g_return_if_fail (passphrase);
@@ -189,11 +189,11 @@ seahorse_gpgme_key_op_generate_async (SeahorseGpgmeSource *source,
 	else
 		parms = g_strdup_printf ("%s%d\n%s", start, length, common);
 
-	res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+	res = g_simple_async_result_new (G_OBJECT (keyring), callback, user_data,
 	                                 seahorse_gpgme_key_op_generate_async);
 
 	closure = g_new0 (key_op_generate_closure, 1);
-	closure->gctx = seahorse_gpgme_source_new_context ();
+	closure->gctx = seahorse_gpgme_keyring_new_context ();
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
 	gpgme_set_progress_cb (closure->gctx, on_key_op_generate_progress, res);
 	g_simple_async_result_set_op_res_gpointer (res, closure, key_op_generate_free);
@@ -222,11 +222,11 @@ seahorse_gpgme_key_op_generate_async (SeahorseGpgmeSource *source,
 }
 
 gboolean
-seahorse_gpgme_key_op_generate_finish (SeahorseGpgmeSource *source,
+seahorse_gpgme_key_op_generate_finish (SeahorseGpgmeKeyring *keyring,
                                        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 (keyring),
 	                      seahorse_gpgme_key_op_generate_async), FALSE);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
@@ -239,21 +239,21 @@ seahorse_gpgme_key_op_generate_finish (SeahorseGpgmeSource *source,
 static gpgme_error_t
 op_delete (SeahorseGpgmeKey *pkey, gboolean secret)
 {
-	SeahorseGpgmeSource *psrc;
+	SeahorseGpgmeKeyring *keyring;
 	gpgme_error_t err;
 	gpgme_key_t key;
-    
-	psrc = SEAHORSE_GPGME_SOURCE (seahorse_object_get_source (SEAHORSE_OBJECT (pkey)));
-	g_return_val_if_fail (psrc && SEAHORSE_IS_GPGME_SOURCE (psrc), GPG_E (GPG_ERR_INV_KEYRING));
-	
+
+	keyring = SEAHORSE_GPGME_KEYRING (seahorse_object_get_source (SEAHORSE_OBJECT (pkey)));
+	g_return_val_if_fail (SEAHORSE_IS_GPGME_KEYRING (keyring), GPG_E (GPG_ERR_INV_KEYRING));
+
 	g_object_ref (pkey);
 	
 	seahorse_util_wait_until ((key = seahorse_gpgme_key_get_public (pkey)) != NULL);
-	
-	err = gpgme_op_delete (psrc->gctx, key, secret);
+
+	err = gpgme_op_delete (keyring->gctx, key, secret);
 	if (GPG_IS_OK (err))
-             seahorse_context_remove_object (SCTX_APP (), SEAHORSE_OBJECT (pkey));
-	
+		seahorse_gpgme_keyring_remove_key (keyring, pkey);
+
 	g_object_unref (pkey);
 	
 	return err;
@@ -356,7 +356,7 @@ edit_gpgme_key (gpgme_ctx_t ctx, gpgme_key_t key, SeahorseEditParm *parms)
 	gpgme_key_ref (key);
     
 	if (!ctx) {
-		ctx = seahorse_gpgme_source_new_context ();
+		ctx = seahorse_gpgme_keyring_new_context ();
 		g_return_val_if_fail (ctx, GPG_E (GPG_ERR_GENERAL));
 		own_context = TRUE;
 	}
@@ -395,18 +395,18 @@ edit_refresh_gpgme_key (gpgme_ctx_t ctx, gpgme_key_t key, SeahorseEditParm *parm
 static gpgme_error_t
 edit_key (SeahorseGpgmeKey *pkey, SeahorseEditParm *parms)
 {
-	SeahorseGpgmeSource *psrc;
+	SeahorseGpgmeKeyring *keyring;
 	gpgme_error_t err;
 	gpgme_key_t key;
-    
-	psrc = SEAHORSE_GPGME_SOURCE (seahorse_object_get_source (SEAHORSE_OBJECT (pkey)));
-	g_return_val_if_fail (psrc && SEAHORSE_IS_GPGME_SOURCE (psrc), GPG_E (GPG_ERR_INV_KEYRING));
+
+	keyring = SEAHORSE_GPGME_KEYRING (seahorse_object_get_source (SEAHORSE_OBJECT (pkey)));
+	g_return_val_if_fail (SEAHORSE_IS_GPGME_KEYRING (keyring), GPG_E (GPG_ERR_INV_KEYRING));
 
 	g_object_ref (pkey);
 	
 	seahorse_util_wait_until ((key = seahorse_gpgme_key_get_public (pkey)) != NULL);
   
-	err = edit_refresh_gpgme_key (psrc->gctx, key, parms);
+	err = edit_refresh_gpgme_key (keyring->gctx, key, parms);
 
 	g_object_unref (pkey);
     
@@ -586,7 +586,7 @@ sign_process (gpgme_key_t signed_key, gpgme_key_t signing_key, guint sign_index,
 	gpgme_ctx_t ctx;
 	gpgme_error_t gerr;
 
-	ctx = seahorse_gpgme_source_new_context ();
+	ctx = seahorse_gpgme_keyring_new_context ();
 	g_return_val_if_fail (ctx, GPG_E (GPG_ERR_GENERAL));
 	
         gerr = gpgme_signers_add (ctx, signing_key);
@@ -1290,19 +1290,19 @@ gpgme_error_t
 seahorse_gpgme_key_op_add_revoker (SeahorseGpgmeKey *pkey, SeahorseGpgmeKey *revoker)
 {
 	SeahorseEditParm *parms;
-	GQuark id;
-	
+	const gchar *keyid;
+
 	g_return_val_if_fail (SEAHORSE_IS_GPGME_KEY (pkey), GPG_E (GPG_ERR_WRONG_KEY_USAGE));    
 	g_return_val_if_fail (SEAHORSE_IS_GPGME_KEY (revoker), GPG_E (GPG_ERR_WRONG_KEY_USAGE));    
 	g_return_val_if_fail (seahorse_object_get_usage (SEAHORSE_OBJECT (pkey)) == SEAHORSE_USAGE_PRIVATE_KEY, GPG_E (GPG_ERR_WRONG_KEY_USAGE));
 	g_return_val_if_fail (seahorse_object_get_usage (SEAHORSE_OBJECT (revoker)) == SEAHORSE_USAGE_PRIVATE_KEY, GPG_E (GPG_ERR_WRONG_KEY_USAGE));
 
-	id = seahorse_object_get_id (SEAHORSE_OBJECT (revoker));
-	g_return_val_if_fail (id, GPG_E (GPG_ERR_INV_VALUE));
-	
+	keyid = seahorse_pgp_key_get_keyid (SEAHORSE_PGP_KEY (pkey));
+	g_return_val_if_fail (keyid, GPG_E (GPG_ERR_INV_VALUE));
+
 	parms = seahorse_edit_parm_new (ADD_REVOKER_START, add_revoker_action,
-	                                add_revoker_transit, (gpointer)seahorse_pgp_key_calc_rawid (id));
-	
+	                                add_revoker_transit, (gpointer)keyid);
+
 	return edit_key (pkey, parms);
 }
 
diff --git a/pgp/seahorse-gpgme-key-op.h b/pgp/seahorse-gpgme-key-op.h
index 39017f9..74953d4 100644
--- a/pgp/seahorse-gpgme-key-op.h
+++ b/pgp/seahorse-gpgme-key-op.h
@@ -27,9 +27,9 @@
 #include <time.h>
 
 #include "pgp/seahorse-gpgme-key.h"
+#include "pgp/seahorse-gpgme-keyring.h"
 #include "pgp/seahorse-gpgme-subkey.h"
 #include "pgp/seahorse-gpgme-uid.h"
-#include "pgp/seahorse-gpgme-source.h"
 #include "pgp/seahorse-gpgme-photo.h"
 
 /* 
@@ -135,7 +135,7 @@ typedef enum {
 	REVOKE_NOT_USED = 3
 } SeahorseRevokeReason;
 
-void                  seahorse_gpgme_key_op_generate_async   (SeahorseGpgmeSource *source,
+void                  seahorse_gpgme_key_op_generate_async   (SeahorseGpgmeKeyring *keyring,
                                                               const gchar *name,
                                                               const gchar *email,
                                                               const gchar *comment,
@@ -147,7 +147,7 @@ void                  seahorse_gpgme_key_op_generate_async   (SeahorseGpgmeSourc
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-gboolean              seahorse_gpgme_key_op_generate_finish  (SeahorseGpgmeSource *source,
+gboolean              seahorse_gpgme_key_op_generate_finish  (SeahorseGpgmeKeyring *keyring,
                                                               GAsyncResult *Result,
                                                               GError **error);
 
diff --git a/pgp/seahorse-gpgme-key.c b/pgp/seahorse-gpgme-key.c
index dcdc340..01a255a 100644
--- a/pgp/seahorse-gpgme-key.c
+++ b/pgp/seahorse-gpgme-key.c
@@ -25,18 +25,18 @@
 
 #include <glib/gi18n.h>
 
-#include "seahorse-context.h"
 #include "seahorse-icons.h"
 #include "seahorse-predicate.h"
 #include "seahorse-object-list.h"
 #include "seahorse-source.h"
 #include "seahorse-util.h"
 
+#include "seahorse-pgp-backend.h"
 #include "pgp/seahorse-pgp-key.h"
 #include "pgp/seahorse-gpgme.h"
 #include "pgp/seahorse-gpgme-key-op.h"
 #include "pgp/seahorse-gpgme-photo.h"
-#include "pgp/seahorse-gpgme-source.h"
+#include "pgp/seahorse-gpgme-keyring.h"
 #include "pgp/seahorse-gpgme-uid.h"
 
 enum {
@@ -67,15 +67,18 @@ struct _SeahorseGpgmeKeyPrivate {
  */
 
 static gboolean 
-load_gpgme_key (GQuark id, int mode, int secret, gpgme_key_t *key)
+load_gpgme_key (const gchar *keyid,
+                int mode,
+                int secret,
+                gpgme_key_t *key)
 {
 	GError *error = NULL;
 	gpgme_ctx_t ctx;
 	gpgme_error_t gerr;
-	
-	ctx = seahorse_gpgme_source_new_context ();
+
+	ctx = seahorse_gpgme_keyring_new_context ();
 	gpgme_set_keylist_mode (ctx, mode);
-	gerr = gpgme_op_keylist_start (ctx, seahorse_pgp_key_calc_rawid (id), secret);
+	gerr = gpgme_op_keylist_start (ctx, keyid, secret);
 	if (GPG_IS_OK (gerr)) {
 		gerr = gpgme_op_keylist_next (ctx, key);
 		gpgme_op_keylist_end (ctx);
@@ -96,18 +99,16 @@ static void
 load_key_public (SeahorseGpgmeKey *self, int list_mode)
 {
 	gpgme_key_t key = NULL;
+	const gchar *keyid;
 	gboolean ret;
-	GQuark id;
-	
+
 	if (self->pv->block_loading)
 		return;
 	
 	list_mode |= self->pv->list_mode;
-	
-	id = seahorse_object_get_id (SEAHORSE_OBJECT (self));
-	g_return_if_fail (id);
-	
-	ret = load_gpgme_key (id, list_mode, FALSE, &key);
+
+	keyid = seahorse_pgp_key_get_keyid (SEAHORSE_PGP_KEY (self));
+	ret = load_gpgme_key (keyid, list_mode, FALSE, &key);
 	if (ret) {
 		self->pv->list_mode = list_mode;
 		seahorse_gpgme_key_set_public (self, key);
@@ -127,16 +128,14 @@ static void
 load_key_private (SeahorseGpgmeKey *self)
 {
 	gpgme_key_t key = NULL;
+	const gchar *keyid;
 	gboolean ret;
-	GQuark id;
-	
+
 	if (!self->pv->has_secret || self->pv->block_loading)
 		return;
-	
-	id = seahorse_object_get_id (SEAHORSE_OBJECT (self));
-	g_return_if_fail (id);
-	
-	ret = load_gpgme_key (id, GPGME_KEYLIST_MODE_LOCAL, TRUE, &key);
+
+	keyid = seahorse_pgp_key_get_keyid (SEAHORSE_PGP_KEY (self));
+	ret = load_gpgme_key (keyid, GPGME_KEYLIST_MODE_LOCAL, TRUE, &key);
 	if (ret) {
 		seahorse_gpgme_key_set_private (self, key);
 		gpgme_key_unref (key);
@@ -294,16 +293,6 @@ realize_subkeys (SeahorseGpgmeKey *self)
 	seahorse_object_list_free (list);
 }
 
-static void
-refresh_each_gpgme_key (SeahorseObject *object, gpointer data)
-{
-	seahorse_gpgme_key_refresh (SEAHORSE_GPGME_KEY (object));
-}
-
-/* -----------------------------------------------------------------------------
- * OBJECT 
- */
-
 void
 seahorse_gpgme_key_realize (SeahorseGpgmeKey *self)
 {
@@ -386,21 +375,12 @@ static void
 seahorse_gpgme_key_set_uids (SeahorsePgpKey *base, GList *uids)
 {
 	SeahorseGpgmeKey *self = SEAHORSE_GPGME_KEY (base);
-	GList *l;
-	
+
 	SEAHORSE_PGP_KEY_CLASS (seahorse_gpgme_key_parent_class)->set_uids (base, uids);
-	
-	/* Remove the parent on each old one */
-	for (l = self->pv->uids; l; l = g_list_next (l))
-		seahorse_context_remove_object (seahorse_context_instance (), l->data);
 
 	/* Keep our own copy of the UID list */
 	seahorse_object_list_free (self->pv->uids);
 	self->pv->uids = seahorse_object_list_copy (uids);
-	
-	/* Add UIDS to context so that they show up */
-	for (l = self->pv->uids; l; l = g_list_next (l))
-		seahorse_context_add_object (seahorse_context_instance (), l->data);
 
 	renumber_actual_uids (self);
 }
@@ -434,7 +414,6 @@ static void
 seahorse_gpgme_key_init (SeahorseGpgmeKey *self)
 {
 	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_GPGME_KEY, SeahorseGpgmeKeyPrivate);
-	g_object_set (self, "location", SEAHORSE_LOCATION_LOCAL, NULL);
 }
 
 static void
@@ -489,11 +468,6 @@ static void
 seahorse_gpgme_key_object_dispose (GObject *obj)
 {
 	SeahorseGpgmeKey *self = SEAHORSE_GPGME_KEY (obj);
-	GList *l;
-	
-	/* Remove the attached UIDs */
-	for (l = self->pv->uids; l; l = g_list_next (l))
-		seahorse_context_remove_object (seahorse_context_instance (), l->data);
 
 	if (self->pv->pubkey)
 		gpgme_key_unref (self->pv->pubkey);
@@ -562,17 +536,9 @@ SeahorseGpgmeKey*
 seahorse_gpgme_key_new (SeahorseSource *sksrc, gpgme_key_t pubkey, 
                         gpgme_key_t seckey)
 {
-	const gchar *keyid;
-
 	g_return_val_if_fail (pubkey || seckey, NULL);
-	
-	if (pubkey != NULL)
-		keyid = pubkey->subkeys->keyid;
-	else
-		keyid = seckey->subkeys->keyid;
-	
+
 	return g_object_new (SEAHORSE_TYPE_GPGME_KEY, "source", sksrc,
-	                     "id", seahorse_pgp_key_canonize_id (keyid),
 	                     "pubkey", pubkey, "seckey", seckey, 
 	                     NULL);
 }
@@ -672,13 +638,12 @@ seahorse_gpgme_key_get_trust (SeahorseGpgmeKey *self)
 void
 seahorse_gpgme_key_refresh_matching (gpgme_key_t key)
 {
-	SeahorsePredicate pred;
+	SeahorseGpgmeKey *gkey;
 
 	g_return_if_fail (key->subkeys->keyid);
-	
-	memset (&pred, 0, sizeof (pred));
-	pred.type = SEAHORSE_TYPE_GPGME_KEY;
-	pred.id = seahorse_pgp_key_canonize_id (key->subkeys->keyid);
 
-	seahorse_context_for_objects_full (NULL, &pred, refresh_each_gpgme_key, NULL);
+	gkey = seahorse_gpgme_keyring_lookup (seahorse_pgp_backend_get_default_keyring (NULL),
+	                                      key->subkeys->keyid);
+	if (gkey != NULL)
+		seahorse_gpgme_key_refresh (gkey);
 }
diff --git a/pgp/seahorse-gpgme-source.c b/pgp/seahorse-gpgme-keyring.c
similarity index 57%
rename from pgp/seahorse-gpgme-source.c
rename to pgp/seahorse-gpgme-keyring.c
index 5ec9b76..7db728f 100644
--- a/pgp/seahorse-gpgme-source.c
+++ b/pgp/seahorse-gpgme-keyring.c
@@ -22,9 +22,7 @@
 
 #include "config.h"
 
-#include <glib/gi18n.h>
-#include <string.h>
-#include "seahorse-gpgme-source.h"
+#include "seahorse-gpgme-keyring.h"
 
 #include "seahorse-gpgme-data.h"
 #include "seahorse-gpgme.h"
@@ -37,9 +35,13 @@
 #include "seahorse-util.h"
 #include "seahorse-passphrase.h"
 
+#include <gcr/gcr.h>
+
 #include <gio/gio.h>
+#include <glib/gi18n.h>
 
 #include <stdlib.h>
+#include <string.h>
 #include <libintl.h>
 #include <locale.h>
 
@@ -52,152 +54,148 @@
 #define DEFAULT_LOAD_BATCH 200
 
 enum {
-    LOAD_FULL = 0x01,
-    LOAD_PHOTOS = 0x02
-};
-
-enum {
-    PROP_0,
-    PROP_SOURCE_TAG,
-    PROP_SOURCE_LOCATION
+	LOAD_FULL = 0x01,
+	LOAD_PHOTOS = 0x02
 };
 
 static gpgme_error_t
-passphrase_get (gconstpointer dummy, const gchar *passphrase_hint, 
+passphrase_get (gconstpointer dummy, const gchar *passphrase_hint,
                 const char* passphrase_info, int flags, int fd)
 {
-    GtkDialog *dialog;
-    gpgme_error_t err;
-    gchar **split_uid = NULL;
-    gchar *label = NULL;
-    gchar *errmsg = NULL;
-    const gchar *pass;
-    gboolean confirm = FALSE;
-
-    if (passphrase_info && strlen(passphrase_info) < 16) {
-        flags |= SEAHORSE_PASS_NEW;
-        confirm = TRUE;
-    }
-
-    if (passphrase_hint)
-        split_uid = g_strsplit (passphrase_hint, " ", 2);
-
-    if (flags & SEAHORSE_PASS_BAD) 
-        errmsg = g_strdup_printf (_("Wrong passphrase."));
-    
-    if (split_uid && split_uid[0] && split_uid[1]) {
-        if (flags & SEAHORSE_PASS_NEW) 
-            label = g_strdup_printf (_("Enter new passphrase for '%s'"), split_uid[1]);
-        else 
-            label = g_strdup_printf (_("Enter passphrase for '%s'"), split_uid[1]);
-    } else {
-        if (flags & SEAHORSE_PASS_NEW) 
-            label = g_strdup (_("Enter new passphrase"));
-        else 
-            label = g_strdup (_("Enter passphrase"));
-    }
-
-    g_strfreev (split_uid);
-
-    dialog = seahorse_passphrase_prompt_show (NULL, errmsg ? errmsg : label, 
-                                              NULL, NULL, confirm);
-    g_free (label);
-    g_free (errmsg);
-    
-    switch (gtk_dialog_run (dialog)) {
-    case GTK_RESPONSE_ACCEPT:
-        pass = seahorse_passphrase_prompt_get (dialog);
-        seahorse_util_printf_fd (fd, "%s\n", pass);
-        err = GPG_OK;
-        break;
-    default:
-        err = GPG_E (GPG_ERR_CANCELED);
-        break;
-    };
-    
-    gtk_widget_destroy (GTK_WIDGET (dialog));
-    return err;
+	GtkDialog *dialog;
+	gpgme_error_t err;
+	gchar **split_uid = NULL;
+	gchar *label = NULL;
+	gchar *errmsg = NULL;
+	const gchar *pass;
+	gboolean confirm = FALSE;
+
+	if (passphrase_info && strlen(passphrase_info) < 16) {
+		flags |= SEAHORSE_PASS_NEW;
+		confirm = TRUE;
+	}
+
+	if (passphrase_hint)
+		split_uid = g_strsplit (passphrase_hint, " ", 2);
+
+	if (flags & SEAHORSE_PASS_BAD)
+		errmsg = g_strdup_printf (_("Wrong passphrase."));
+
+	if (split_uid && split_uid[0] && split_uid[1]) {
+		if (flags & SEAHORSE_PASS_NEW)
+			label = g_strdup_printf (_("Enter new passphrase for '%s'"), split_uid[1]);
+		else
+			label = g_strdup_printf (_("Enter passphrase for '%s'"), split_uid[1]);
+	} else {
+		if (flags & SEAHORSE_PASS_NEW)
+			label = g_strdup (_("Enter new passphrase"));
+		else
+			label = g_strdup (_("Enter passphrase"));
+	}
+
+	g_strfreev (split_uid);
+
+	dialog = seahorse_passphrase_prompt_show (NULL, errmsg ? errmsg : label,
+	                                          NULL, NULL, confirm);
+	g_free (label);
+	g_free (errmsg);
+
+	switch (gtk_dialog_run (dialog)) {
+	case GTK_RESPONSE_ACCEPT:
+		pass = seahorse_passphrase_prompt_get (dialog);
+		seahorse_util_printf_fd (fd, "%s\n", pass);
+		err = GPG_OK;
+		break;
+	default:
+		err = GPG_E (GPG_ERR_CANCELED);
+		break;
+	};
+
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+	return err;
 }
 
 /* Initialise a GPGME context for PGP keys */
 static gpgme_error_t
 init_gpgme (gpgme_ctx_t *ctx)
 {
-    gpgme_protocol_t proto = GPGME_PROTOCOL_OpenPGP;
-    gpgme_error_t err;
- 
-    err = gpgme_engine_check_version (proto);
-    g_return_val_if_fail (GPG_IS_OK (err), err);
-   
-    err = gpgme_new (ctx);
-    g_return_val_if_fail (GPG_IS_OK (err), err);
-   
-    err = gpgme_set_protocol (*ctx, proto);
-    g_return_val_if_fail (GPG_IS_OK (err), err);
-    
-    gpgme_set_passphrase_cb (*ctx, (gpgme_passphrase_cb_t)passphrase_get, 
-                             NULL);
-   
-    gpgme_set_keylist_mode (*ctx, GPGME_KEYLIST_MODE_LOCAL);
-    return err;
+	gpgme_protocol_t proto = GPGME_PROTOCOL_OpenPGP;
+	gpgme_error_t err;
+
+	err = gpgme_engine_check_version (proto);
+	g_return_val_if_fail (GPG_IS_OK (err), err);
+
+	err = gpgme_new (ctx);
+	g_return_val_if_fail (GPG_IS_OK (err), err);
+
+	err = gpgme_set_protocol (*ctx, proto);
+	g_return_val_if_fail (GPG_IS_OK (err), err);
+
+	gpgme_set_passphrase_cb (*ctx, (gpgme_passphrase_cb_t)passphrase_get,
+	                         NULL);
+
+	gpgme_set_keylist_mode (*ctx, GPGME_KEYLIST_MODE_LOCAL);
+	return err;
 }
 
-struct _SeahorseGpgmeSourcePrivate {
+struct _SeahorseGpgmeKeyringPrivate {
+	GHashTable *keys;
 	guint scheduled_refresh;                /* Source for refresh timeout */
 	GFileMonitor *monitor_handle;           /* For monitoring the .gnupg directory */
 	GList *orphan_secret;                   /* Orphan secret keys */
 };
 
-static void seahorse_source_iface (SeahorseSourceIface *iface);
+static void     seahorse_gpgme_keyring_source_iface       (SeahorseSourceIface *iface);
+
+static void     seahorse_gpgme_keyring_collection_iface   (GcrCollectionIface *iface);
 
-G_DEFINE_TYPE_EXTENDED (SeahorseGpgmeSource, seahorse_gpgme_source, G_TYPE_OBJECT, 0,
-                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_source_iface));
+G_DEFINE_TYPE_WITH_CODE (SeahorseGpgmeKeyring, seahorse_gpgme_keyring, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_gpgme_keyring_source_iface);
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_gpgme_keyring_collection_iface);
+);
 
 typedef struct {
-	SeahorseGpgmeSource *source;
+	SeahorseGpgmeKeyring *keyring;
 	GCancellable *cancellable;
 	gulong cancelled_sig;
 	gpgme_ctx_t gctx;
 	GHashTable *checks;
 	gint parts;
 	gint loaded;
-} source_list_closure;
+} keyring_list_closure;
 
 static void
-source_list_free (gpointer data)
+keyring_list_free (gpointer data)
 {
-	source_list_closure *closure = data;
+	keyring_list_closure *closure = data;
 	gpgme_release (closure->gctx);
 	if (closure->checks)
 		g_hash_table_destroy (closure->checks);
 	g_cancellable_disconnect (closure->cancellable,
 	                          closure->cancelled_sig);
 	g_clear_object (&closure->cancellable);
-	g_clear_object (&closure->source);
+	g_clear_object (&closure->keyring);
 	g_free (closure);
 }
 
 /* Add a key to the context  */
 static SeahorseGpgmeKey*
-add_key_to_context (SeahorseGpgmeSource *self,
+add_key_to_context (SeahorseGpgmeKeyring *self,
                     gpgme_key_t key)
 {
 	SeahorseGpgmeKey *pkey = NULL;
 	SeahorseGpgmeKey *prev;
-	const gchar *id;
+	const gchar *keyid;
 	gpgme_key_t seckey;
-	GQuark keyid;
 	GList *l;
 
 	g_return_val_if_fail (key->subkeys && key->subkeys->keyid, NULL);
 
-	id = key->subkeys->keyid;
-	keyid = seahorse_pgp_key_canonize_id (id);
+	keyid = key->subkeys->keyid;
 	g_return_val_if_fail (keyid, NULL);
 
-	g_assert (SEAHORSE_IS_GPGME_SOURCE (self));
-	prev = SEAHORSE_GPGME_KEY (seahorse_context_get_object (seahorse_context_instance (),
-	                                                        SEAHORSE_SOURCE (self), keyid));
+	g_assert (SEAHORSE_IS_GPGME_KEYRING (self));
+	prev = seahorse_gpgme_keyring_lookup (self, keyid);
 
 	/* Check if we can just replace the key on the object */
 	if (prev != NULL) {
@@ -229,7 +227,7 @@ add_key_to_context (SeahorseGpgmeSource *self,
 		g_assert (seckey);
 
 		/* Look for a matching key */
-		if (g_str_equal (id, seckey->subkeys->keyid)) {
+		if (g_str_equal (keyid, seckey->subkeys->keyid)) {
 
 			/* Set it up properly */
 			pkey = SEAHORSE_GPGME_KEY (l->data);
@@ -246,25 +244,23 @@ add_key_to_context (SeahorseGpgmeSource *self,
 		pkey = seahorse_gpgme_key_new (SEAHORSE_SOURCE (self), key, NULL);
 
 	/* Add to context */
-	seahorse_context_take_object (SCTX_APP (), SEAHORSE_OBJECT (pkey));
+	g_hash_table_insert (self->pv->keys, g_strdup (keyid), pkey);
+	gcr_collection_emit_added (GCR_COLLECTION (self), G_OBJECT (pkey));
 
 	return pkey;
 }
 
+
 /* Remove the given key from the context */
 static void
-remove_key_from_context (gpointer hash_key,
-                         SeahorseObject *dummy,
-                         SeahorseGpgmeSource *self)
+remove_key (SeahorseGpgmeKeyring *self,
+            const gchar *keyid)
 {
-	/* This function gets called as a GHRFunc on the lctx->checks hashtable. */
-	GQuark keyid = GPOINTER_TO_UINT (hash_key);
-	SeahorseObject *object;
+	SeahorseGpgmeKey *key;
 
-	object = seahorse_context_get_object (seahorse_context_instance (),
-	                                      SEAHORSE_SOURCE (self), keyid);
-	if (object != NULL)
-		seahorse_context_remove_object (seahorse_context_instance (), object);
+	key = g_hash_table_lookup (self->pv->keys, keyid);
+	if (key != NULL)
+		seahorse_gpgme_keyring_remove_key (self, key);
 }
 
 /* Completes one batch of key loading */
@@ -272,12 +268,13 @@ static gboolean
 on_idle_list_batch_of_keys (gpointer data)
 {
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (data);
-	source_list_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	keyring_list_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	SeahorseGpgmeKey *pkey;
+	GHashTableIter iter;
 	gpgme_key_t key;
 	guint batch;
-	GQuark keyid;
 	gchar *detail;
+	const gchar *keyid;
 
 	/* We load until done if batch is zero */
 	batch = DEFAULT_LOAD_BATCH;
@@ -289,9 +286,11 @@ on_idle_list_batch_of_keys (gpointer data)
 			gpgme_op_keylist_end (closure->gctx);
 
 			/* If we were a refresh loader, then we remove the keys we didn't find */
-			if (closure->checks)
-				g_hash_table_foreach (closure->checks, (GHFunc)remove_key_from_context,
-				                      closure->source);
+			if (closure->checks) {
+				g_hash_table_iter_init (&iter, closure->checks);
+				while (g_hash_table_iter_next (&iter, (gpointer *)&keyid, NULL))
+					remove_key (closure->keyring, keyid);
+			}
 
 			seahorse_progress_end (closure->cancellable, res);
 			g_simple_async_result_complete (res);
@@ -299,23 +298,16 @@ on_idle_list_batch_of_keys (gpointer data)
 		}
 
 		g_return_val_if_fail (key->subkeys && key->subkeys->keyid, FALSE);
-		keyid = seahorse_pgp_key_canonize_id (key->subkeys->keyid);
-
-		/* Invalid id from GPG ? */
-		if (keyid == 0) {
-			gpgme_key_unref (key);
-			continue;
-		}
 
 		/* During a refresh if only new or removed keys */
 		if (closure->checks) {
 
 			/* Make note that this key exists in key ring */
-			g_hash_table_remove (closure->checks, GUINT_TO_POINTER (keyid));
+			g_hash_table_remove (closure->checks, key->subkeys->keyid);
 
 		}
 
-		pkey = add_key_to_context (closure->source, key);
+		pkey = add_key_to_context (closure->keyring, key);
 
 		/* Load additional info */
 		if (pkey && closure->parts & LOAD_PHOTOS)
@@ -333,38 +325,40 @@ on_idle_list_batch_of_keys (gpointer data)
 }
 
 static void
-on_source_list_cancelled (GCancellable *cancellable, gpointer user_data)
+on_keyring_list_cancelled (GCancellable *cancellable,
+                           gpointer user_data)
 {
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	source_list_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	keyring_list_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 
 	gpgme_op_keylist_end (closure->gctx);
 }
 
 static void
-seahorse_gpgme_source_list_async (SeahorseGpgmeSource *self,
-                                  const gchar **patterns,
-                                  gint parts,
-                                  gboolean secret,
-                                  GCancellable *cancellable,
-                                  GAsyncReadyCallback callback,
-                                  gpointer user_data)
+seahorse_gpgme_keyring_list_async (SeahorseGpgmeKeyring *self,
+                                   const gchar **patterns,
+                                   gint parts,
+                                   gboolean secret,
+                                   GCancellable *cancellable,
+                                   GAsyncReadyCallback callback,
+                                   gpointer user_data)
 {
-	source_list_closure *closure;
+	keyring_list_closure *closure;
 	GSimpleAsyncResult *res;
 	SeahorseObject *object;
 	gpgme_error_t gerr;
-	GList *keys, *l;
+	GHashTableIter iter;
+	gchar *keyid;
 
 	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 seahorse_gpgme_source_list_async);
+	                                 seahorse_gpgme_keyring_list_async);
 
-	closure = g_new0 (source_list_closure, 1);
+	closure = g_new0 (keyring_list_closure, 1);
 	closure->parts = parts;
-	closure->gctx = seahorse_gpgme_source_new_context ();
+	closure->gctx = seahorse_gpgme_keyring_new_context ();
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-	closure->source = g_object_ref (self);
-	g_simple_async_result_set_op_res_gpointer (res, closure, source_list_free);
+	closure->keyring = g_object_ref (self);
+	g_simple_async_result_set_op_res_gpointer (res, closure, keyring_list_free);
 
 	if (parts & LOAD_FULL) {
 		gpgme_set_keylist_mode (closure->gctx, GPGME_KEYLIST_MODE_SIGS |
@@ -381,26 +375,23 @@ seahorse_gpgme_source_list_async (SeahorseGpgmeSource *self,
 	/* Loading all the keys? */
 	if (patterns == NULL) {
 
-		closure->checks = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
-		keys = seahorse_context_get_objects (seahorse_context_instance (),
-		                                     SEAHORSE_SOURCE (self));
-		for (l = keys; l != NULL; l = g_list_next (l)) {
-			object = SEAHORSE_OBJECT (l->data);
+		closure->checks = g_hash_table_new_full (seahorse_pgp_keyid_hash,
+		                                         seahorse_pgp_keyid_equal,
+		                                         g_free, NULL);
+		g_hash_table_iter_init (&iter, self->pv->keys);
+		while (g_hash_table_iter_next (&iter, (gpointer *)&keyid, (gpointer *)&object)) {
 			if ((secret && seahorse_object_get_usage (object) == SEAHORSE_USAGE_PRIVATE_KEY) ||
 			    (!secret && seahorse_object_get_usage (object) == SEAHORSE_USAGE_PUBLIC_KEY)) {
-				g_hash_table_insert (closure->checks,
-				                     GUINT_TO_POINTER (seahorse_object_get_id (l->data)),
-				                     GUINT_TO_POINTER (TRUE));
+				keyid = g_strdup (keyid);
+				g_hash_table_insert (closure->checks, keyid, keyid);
 			}
 		}
-		g_list_free (keys);
-
 	}
 
 	seahorse_progress_prep_and_begin (cancellable, res, NULL);
 	if (cancellable)
 		closure->cancelled_sig = g_cancellable_connect (cancellable,
-		                                                G_CALLBACK (on_source_list_cancelled),
+		                                                G_CALLBACK (on_keyring_list_cancelled),
 		                                                res, NULL);
 
 	g_idle_add_full (G_PRIORITY_DEFAULT, on_idle_list_batch_of_keys,
@@ -410,12 +401,12 @@ seahorse_gpgme_source_list_async (SeahorseGpgmeSource *self,
 }
 
 static gboolean
-seahorse_gpgme_source_list_finish (SeahorseGpgmeSource *source,
-                                   GAsyncResult *result,
-                                   GError **error)
+seahorse_gpgme_keyring_list_finish (SeahorseGpgmeKeyring *keyring,
+                                    GAsyncResult *result,
+                                    GError **error)
 {
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
-	                      seahorse_gpgme_source_list_async), FALSE);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (keyring),
+	                      seahorse_gpgme_keyring_list_async), FALSE);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return FALSE;
@@ -424,7 +415,7 @@ seahorse_gpgme_source_list_finish (SeahorseGpgmeSource *source,
 }
 
 static void
-cancel_scheduled_refresh (SeahorseGpgmeSource *self)
+cancel_scheduled_refresh (SeahorseGpgmeKeyring *self)
 {
 	if (self->pv->scheduled_refresh != 0) {
 		seahorse_debug ("cancelling scheduled refresh event");
@@ -436,7 +427,7 @@ cancel_scheduled_refresh (SeahorseGpgmeSource *self)
 static gboolean
 scheduled_dummy (gpointer user_data)
 {
-	SeahorseGpgmeSource *self = SEAHORSE_GPGME_SOURCE (user_data);
+	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (user_data);
 	seahorse_debug ("dummy refresh event occurring now");
 	self->pv->scheduled_refresh = 0;
 	return FALSE; /* don't run again */
@@ -445,19 +436,19 @@ scheduled_dummy (gpointer user_data)
 typedef struct {
 	gboolean public_done;
 	gboolean secret_done;
-} source_load_closure;
+} keyring_load_closure;
 
 static void
-on_source_secret_list_complete (GObject *source,
-                                GAsyncResult *result,
-                                gpointer user_data)
+on_keyring_secret_list_complete (GObject *source,
+                                 GAsyncResult *result,
+                                 gpointer user_data)
 {
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	source_load_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	keyring_load_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GError *error = NULL;
 
-	if (!seahorse_gpgme_source_list_finish (SEAHORSE_GPGME_SOURCE (source),
-	                                        result, &error))
+	if (!seahorse_gpgme_keyring_list_finish (SEAHORSE_GPGME_KEYRING (source),
+	                                         result, &error))
 		g_simple_async_result_take_error (res, error);
 
 	closure->secret_done = TRUE;
@@ -468,16 +459,16 @@ on_source_secret_list_complete (GObject *source,
 }
 
 static void
-on_source_public_list_complete (GObject *source,
-                                GAsyncResult *result,
-                                gpointer user_data)
+on_keyring_public_list_complete (GObject *source,
+                                 GAsyncResult *result,
+                                 gpointer user_data)
 {
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	source_load_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	keyring_load_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GError *error = NULL;
 
-	if (!seahorse_gpgme_source_list_finish (SEAHORSE_GPGME_SOURCE (source),
-	                                        result, &error))
+	if (!seahorse_gpgme_keyring_list_finish (SEAHORSE_GPGME_KEYRING (source),
+	                                         result, &error))
 		g_simple_async_result_take_error (res, error);
 
 	closure->public_done = TRUE;
@@ -488,16 +479,15 @@ on_source_public_list_complete (GObject *source,
 }
 
 static void
-seahorse_gpgme_source_load_full_async (SeahorseGpgmeSource *source,
-                                       const gchar **patterns,
-                                       gint parts,
-                                       GCancellable *cancellable,
-                                       GAsyncReadyCallback callback,
-                                       gpointer user_data)
+seahorse_gpgme_keyring_load_full_async (SeahorseGpgmeKeyring *self,
+                                        const gchar **patterns,
+                                        gint parts,
+                                        GCancellable *cancellable,
+                                        GAsyncReadyCallback callback,
+                                        gpointer user_data)
 {
-	SeahorseGpgmeSource *self = SEAHORSE_GPGME_SOURCE (source);
 	GSimpleAsyncResult *res;
-	source_load_closure *closure;
+	keyring_load_closure *closure;
 
 	/* Schedule a dummy refresh. This blocks all monitoring for a while */
 	cancel_scheduled_refresh (self);
@@ -506,42 +496,70 @@ seahorse_gpgme_source_load_full_async (SeahorseGpgmeSource *source,
 
 	seahorse_debug ("refreshing keys...");
 
-	res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
-	                                 seahorse_gpgme_source_load_full_async);
-	closure = g_new0 (source_load_closure, 1);
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+	                                 seahorse_gpgme_keyring_load_full_async);
+	closure = g_new0 (keyring_load_closure, 1);
 	g_simple_async_result_set_op_res_gpointer (res, closure, g_free);
 
 	/* Secret keys */
-	seahorse_gpgme_source_list_async (self, patterns, 0, TRUE, cancellable,
-	                                  on_source_secret_list_complete,
+	seahorse_gpgme_keyring_list_async (self, patterns, 0, TRUE, cancellable,
+	                                  on_keyring_secret_list_complete,
 	                                  g_object_ref (res));
 
 	/* Public keys */
-	seahorse_gpgme_source_list_async (self, patterns, 0, FALSE, cancellable,
-	                                  on_source_public_list_complete,
+	seahorse_gpgme_keyring_list_async (self, patterns, 0, FALSE, cancellable,
+	                                  on_keyring_public_list_complete,
 	                                  g_object_ref (res));
 
 	g_object_unref (res);
 }
 
-static void
-seahorse_gpgme_source_load_async (SeahorseSource *source,
-                                  GCancellable *cancellable,
-                                  GAsyncReadyCallback callback,
-                                  gpointer user_data)
+SeahorseGpgmeKey *
+seahorse_gpgme_keyring_lookup (SeahorseGpgmeKeyring *self,
+                               const gchar *keyid)
 {
-	seahorse_gpgme_source_load_full_async (SEAHORSE_GPGME_SOURCE (source),
-	                                       NULL, 0, cancellable, callback,
-	                                       user_data);
+	g_return_val_if_fail (SEAHORSE_IS_GPGME_KEYRING (self), NULL);
+	g_return_val_if_fail (keyid != NULL, NULL);
+
+	return g_hash_table_lookup (self->pv->keys, keyid);
 }
 
-static gboolean
-seahorse_gpgme_source_load_finish (SeahorseSource *source,
-                                   GAsyncResult *result,
-                                   GError **error)
+void
+seahorse_gpgme_keyring_remove_key (SeahorseGpgmeKeyring *self,
+                                   SeahorseGpgmeKey *key)
 {
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
-	                      seahorse_gpgme_source_load_full_async), FALSE);
+	const gchar *keyid;
+
+	g_return_if_fail (SEAHORSE_IS_GPGME_KEYRING (self));
+	g_return_if_fail (SEAHORSE_IS_GPGME_KEY (key));
+
+	keyid = seahorse_pgp_key_get_keyid (SEAHORSE_PGP_KEY (key));
+	g_return_if_fail (g_hash_table_lookup (self->pv->keys, keyid) == key);
+
+	g_object_ref (key);
+	g_hash_table_remove (self->pv->keys, keyid);
+	gcr_collection_emit_removed (GCR_COLLECTION (self), G_OBJECT (key));
+	g_object_unref (key);
+
+}
+
+void
+seahorse_gpgme_keyring_load_async (SeahorseGpgmeKeyring *self,
+                                   GCancellable *cancellable,
+                                   GAsyncReadyCallback callback,
+                                   gpointer user_data)
+{
+	seahorse_gpgme_keyring_load_full_async (self, NULL, 0, cancellable,
+	                                        callback, user_data);
+}
+
+gboolean
+seahorse_gpgme_keyring_load_finish (SeahorseGpgmeKeyring *self,
+                                    GAsyncResult *result,
+                                    GError **error)
+{
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      seahorse_gpgme_keyring_load_full_async), FALSE);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return FALSE;
@@ -551,48 +569,38 @@ seahorse_gpgme_source_load_finish (SeahorseSource *source,
 
 typedef struct {
 	GCancellable *cancellable;
-	SeahorseGpgmeSource *source;
+	SeahorseGpgmeKeyring *keyring;
 	gpgme_ctx_t gctx;
 	gpgme_data_t data;
 	gchar **patterns;
 	GList *keys;
-} source_import_closure;
+} keyring_import_closure;
 
 static void
-source_import_free (gpointer data)
+keyring_import_free (gpointer data)
 {
-	source_import_closure *closure = data;
+	keyring_import_closure *closure = data;
 	g_clear_object (&closure->cancellable);
 	gpgme_release (closure->gctx);
 	gpgme_data_release (closure->data);
-	g_object_unref (closure->source);
+	g_object_unref (closure->keyring);
 	g_strfreev (closure->patterns);
 	g_list_free (closure->keys);
 	g_free (closure);
 }
 
 static void
-on_source_import_loaded (GObject *source,
+on_keyring_import_loaded (GObject *source,
                          GAsyncResult *result,
                          gpointer user_data)
 {
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	source_import_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	keyring_import_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	SeahorseObject *object;
-	GQuark keyid;
 	guint i;
 
 	for (i = 0; closure->patterns[i] != NULL; i++) {
-		keyid = seahorse_pgp_key_canonize_id (closure->patterns[i]);
-		if (!keyid) {
-			g_warning ("imported non key with strange keyid: %s",
-			           closure->patterns[i]);
-			continue;
-		}
-
-		object = seahorse_context_get_object (seahorse_context_instance (),
-		                                      SEAHORSE_SOURCE (closure->source),
-		                                      keyid);
+		object = g_hash_table_lookup (closure->keyring->pv->keys, closure->patterns[i]);
 		if (object == NULL) {
 			g_warning ("imported key but then couldn't find it in keyring: %s",
 			           closure->patterns[i]);
@@ -608,11 +616,11 @@ on_source_import_loaded (GObject *source,
 }
 
 static gboolean
-on_source_import_complete (gpgme_error_t gerr,
+on_keyring_import_complete (gpgme_error_t gerr,
                            gpointer user_data)
 {
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	source_import_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	keyring_import_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	gpgme_import_result_t results;
 	gpgme_import_status_t import;
 	GError *error = NULL;
@@ -655,39 +663,39 @@ on_source_import_complete (gpgme_error_t gerr,
 	}
 
 	/* Reload public keys */
-	seahorse_gpgme_source_load_full_async (closure->source, (const gchar **)closure->patterns,
-	                                       LOAD_FULL, closure->cancellable,
-	                                       on_source_import_loaded, g_object_ref (res));
+	seahorse_gpgme_keyring_load_full_async (closure->keyring, (const gchar **)closure->patterns,
+	                                        LOAD_FULL, closure->cancellable,
+	                                        on_keyring_import_loaded, g_object_ref (res));
 
 	return FALSE; /* don't call again */
 }
 
 static void
-seahorse_gpgme_source_import_async (SeahorseSource *source,
+seahorse_gpgme_keyring_import_async (SeahorseSource *source,
                                     GInputStream *input,
                                     GCancellable *cancellable,
                                     GAsyncReadyCallback callback,
                                     gpointer user_data)
 {
-	SeahorseGpgmeSource *self = SEAHORSE_GPGME_SOURCE (source);
+	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (source);
 	GSimpleAsyncResult *res;
-	source_import_closure *closure;
+	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,
-	                                 seahorse_gpgme_source_import_async);
-	closure = g_new0 (source_import_closure, 1);
+	                                 seahorse_gpgme_keyring_import_async);
+	closure = g_new0 (keyring_import_closure, 1);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-	closure->gctx = seahorse_gpgme_source_new_context ();
+	closure->gctx = seahorse_gpgme_keyring_new_context ();
 	closure->data = seahorse_gpgme_data_input (input);
-	closure->source = g_object_ref (self);
-	g_simple_async_result_set_op_res_gpointer (res, closure, source_import_free);
+	closure->keyring = g_object_ref (self);
+	g_simple_async_result_set_op_res_gpointer (res, closure, keyring_import_free);
 
 	seahorse_progress_prep_and_begin (cancellable, res, NULL);
 	gsource = seahorse_gpgme_gsource_new (closure->gctx, cancellable);
-	g_source_set_callback (gsource, (GSourceFunc)on_source_import_complete,
+	g_source_set_callback (gsource, (GSourceFunc)on_keyring_import_complete,
 	                       g_object_ref (res), g_object_unref);
 
 	gerr = gpgme_op_import_start (closure->gctx, closure->data);
@@ -705,15 +713,15 @@ seahorse_gpgme_source_import_async (SeahorseSource *source,
 }
 
 static GList *
-seahorse_gpgme_source_import_finish (SeahorseSource *source,
+seahorse_gpgme_keyring_import_finish (SeahorseSource *source,
                                      GAsyncResult *result,
                                      GError **error)
 {
-	source_import_closure *closure;
+	keyring_import_closure *closure;
 	GList *results;
 
 	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
-	                      seahorse_gpgme_source_import_async), NULL);
+	                      seahorse_gpgme_keyring_import_async), NULL);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return NULL;
@@ -732,12 +740,12 @@ typedef struct {
 	GOutputStream *output;
 	GCancellable *cancellable;
 	gulong cancelled_sig;
-} source_export_closure;
+} keyring_export_closure;
 
 static void
-source_export_free (gpointer data)
+keyring_export_free (gpointer data)
 {
-	source_export_closure *closure = data;
+	keyring_export_closure *closure = data;
 	g_cancellable_disconnect (closure->cancellable, closure->cancelled_sig);
 	g_clear_object (&closure->cancellable);
 	gpgme_data_release (closure->data);
@@ -748,11 +756,11 @@ source_export_free (gpointer data)
 }
 
 static gboolean
-on_source_export_complete (gpgme_error_t gerr,
+on_keyring_export_complete (gpgme_error_t gerr,
                            gpointer user_data)
 {
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	source_export_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	keyring_export_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GError *error = NULL;
 
 	if (seahorse_gpgme_propagate_error (gerr, &error)) {
@@ -789,7 +797,7 @@ on_source_export_complete (gpgme_error_t gerr,
 }
 
 static void
-seahorse_gpgme_source_export_async (SeahorseSource *source,
+seahorse_gpgme_keyring_export_async (SeahorseSource *source,
                                     GList *objects,
                                     GOutputStream *output,
                                     GCancellable *cancellable,
@@ -797,22 +805,22 @@ seahorse_gpgme_source_export_async (SeahorseSource *source,
                                     gpointer user_data)
 {
 	GSimpleAsyncResult *res;
-	source_export_closure *closure;
+	keyring_export_closure *closure;
 	SeahorsePgpKey *key;
 	gchar *keyid;
 	GSource *gsource;
 	GList *l;
 
 	res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
-	                                 seahorse_gpgme_source_export_async);
-	closure = g_new0 (source_export_closure, 1);
+	                                 seahorse_gpgme_keyring_export_async);
+	closure = g_new0 (keyring_export_closure, 1);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-	closure->gctx = seahorse_gpgme_source_new_context ();
+	closure->gctx = seahorse_gpgme_keyring_new_context ();
 	closure->data = seahorse_gpgme_data_output (output);
 	closure->keyids = g_ptr_array_new_with_free_func (g_free);
 	closure->output = g_object_ref (output);
 	closure->at = -1;
-	g_simple_async_result_set_op_res_gpointer (res, closure, source_export_free);
+	g_simple_async_result_set_op_res_gpointer (res, closure, keyring_export_free);
 
 	gpgme_set_armor (closure->gctx, TRUE);
 	gpgme_set_textmode (closure->gctx, TRUE);
@@ -834,11 +842,11 @@ seahorse_gpgme_source_export_async (SeahorseSource *source,
 	}
 
 	gsource = seahorse_gpgme_gsource_new (closure->gctx, cancellable);
-	g_source_set_callback (gsource, (GSourceFunc)on_source_export_complete,
+	g_source_set_callback (gsource, (GSourceFunc)on_keyring_export_complete,
 	                       g_object_ref (res), g_object_unref);
 
 	/* Get things started */
-	if (on_source_export_complete (0, res))
+	if (on_keyring_export_complete (0, res))
 		g_source_attach (gsource, g_main_context_default ());
 
 	g_source_unref (gsource);
@@ -846,14 +854,14 @@ seahorse_gpgme_source_export_async (SeahorseSource *source,
 }
 
 static GOutputStream *
-seahorse_gpgme_source_export_finish (SeahorseSource *source,
+seahorse_gpgme_keyring_export_finish (SeahorseSource *source,
                                      GAsyncResult *result,
                                      GError **error)
 {
-	source_export_closure *closure;
+	keyring_export_closure *closure;
 
 	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
-	                      seahorse_gpgme_source_export_async), NULL);
+	                      seahorse_gpgme_keyring_export_async), NULL);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return NULL;
@@ -865,11 +873,11 @@ seahorse_gpgme_source_export_finish (SeahorseSource *source,
 static gboolean
 scheduled_refresh (gpointer user_data)
 {
-	SeahorseGpgmeSource *self = SEAHORSE_GPGME_SOURCE (user_data);
+	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (user_data);
 
 	seahorse_debug ("scheduled refresh event ocurring now");
 	cancel_scheduled_refresh (self);
-	seahorse_source_load_async (SEAHORSE_SOURCE (self), NULL, NULL, NULL);
+	seahorse_gpgme_keyring_load_async (self, NULL, NULL, NULL);
 
 	return FALSE; /* don't run again */
 }
@@ -878,7 +886,7 @@ static void
 monitor_gpg_homedir (GFileMonitor *handle, GFile *file, GFile *other_file,
                      GFileMonitorEvent event_type, gpointer user_data)
 {
-	SeahorseGpgmeSource *self = SEAHORSE_GPGME_SOURCE (user_data);
+	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (user_data);
 	gchar *name;
 
 	if (event_type == G_FILE_MONITOR_EVENT_CHANGED ||
@@ -896,18 +904,26 @@ monitor_gpg_homedir (GFileMonitor *handle, GFile *file, GFile *other_file,
 }
 
 static void
-seahorse_gpgme_source_init (SeahorseGpgmeSource *self)
+seahorse_gpgme_keyring_init (SeahorseGpgmeKeyring *self)
 {
 	gpgme_error_t gerr;
 	GError *err = NULL;
 	const gchar *gpg_homedir;
 	GFile *file;
 
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_GPGME_KEYRING,
+	                                        SeahorseGpgmeKeyringPrivate);
+
+	self->pv->keys = g_hash_table_new_full (seahorse_pgp_keyid_hash,
+	                                        seahorse_pgp_keyid_equal,
+	                                        g_free, g_object_unref);
+
 	gerr = init_gpgme (&self->gctx);
 	g_return_if_fail (GPG_IS_OK (gerr));
 
 	/* init private vars */
-	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_GPGME_SOURCE, SeahorseGpgmeSourcePrivate);
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_GPGME_KEYRING,
+	                                        SeahorseGpgmeKeyringPrivate);
 
 	self->pv->scheduled_refresh = 0;
 	self->pv->monitor_handle = NULL;
@@ -923,24 +939,18 @@ seahorse_gpgme_source_init (SeahorseGpgmeSource *self)
 		g_signal_connect (self->pv->monitor_handle, "changed",
 		                  G_CALLBACK (monitor_gpg_homedir), self);
 	} else {
-		g_warning ("couldn't monitor the GPG home directory: %s: %s", 
+		g_warning ("couldn't monitor the GPG home directory: %s: %s",
 		           gpg_homedir, err && err->message ? err->message : "");
 	}
 }
 
 static void
-seahorse_gpgme_source_dispose (GObject *object)
+seahorse_gpgme_keyring_dispose (GObject *object)
 {
-	SeahorseGpgmeSource *self = SEAHORSE_GPGME_SOURCE (object);
+	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (object);
 	GList *l;
 
-	/*
-	 * Note that after this executes the rest of the object should
-	 * still work without a segfault. This basically nullifies the
-	 * object, but doesn't free it.
-	 *
-	 * This function should also be able to run multiple times.
-	 */
+	g_hash_table_remove_all (self->pv->keys);
 
 	cancel_scheduled_refresh (self);
 	if (self->pv->monitor_handle) {
@@ -956,42 +966,25 @@ seahorse_gpgme_source_dispose (GObject *object)
 	if (self->gctx)
 		gpgme_release (self->gctx);
 
-	G_OBJECT_CLASS (seahorse_gpgme_source_parent_class)->dispose (object);
+	G_OBJECT_CLASS (seahorse_gpgme_keyring_parent_class)->dispose (object);
 }
 
 static void
-seahorse_gpgme_source_finalize (GObject *object)
+seahorse_gpgme_keyring_finalize (GObject *object)
 {
-	SeahorseGpgmeSource *self = SEAHORSE_GPGME_SOURCE (object);
+	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (object);
+
+	g_hash_table_destroy (self->pv->keys);
 
 	/* All monitoring and scheduling should be done */
 	g_assert (self->pv->scheduled_refresh == 0);
 	g_assert (self->pv->monitor_handle == 0);
 
-	G_OBJECT_CLASS (seahorse_gpgme_source_parent_class)->finalize (object);
-}
-
-static void 
-seahorse_gpgme_source_get_property (GObject *object,
-                                    guint prop_id,
-                                    GValue *value,
-                                    GParamSpec *pspec)
-{
-	switch (prop_id) {
-	case PROP_SOURCE_TAG:
-		g_value_set_uint (value, SEAHORSE_PGP);
-		break;
-	case PROP_SOURCE_LOCATION:
-		g_value_set_enum (value, SEAHORSE_LOCATION_LOCAL);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
+	G_OBJECT_CLASS (seahorse_gpgme_keyring_parent_class)->finalize (object);
 }
 
 static void
-seahorse_gpgme_source_class_init (SeahorseGpgmeSourceClass *klass)
+seahorse_gpgme_keyring_class_init (SeahorseGpgmeKeyringClass *klass)
 {
 	GObjectClass *gobject_class;
 
@@ -1003,45 +996,75 @@ seahorse_gpgme_source_class_init (SeahorseGpgmeSourceClass *klass)
 #endif
 
 	gobject_class = G_OBJECT_CLASS (klass);
-	gobject_class->dispose = seahorse_gpgme_source_dispose;
-	gobject_class->finalize = seahorse_gpgme_source_finalize;
-	gobject_class->get_property = seahorse_gpgme_source_get_property;
+	gobject_class->dispose = seahorse_gpgme_keyring_dispose;
+	gobject_class->finalize = seahorse_gpgme_keyring_finalize;
+
+	g_type_class_add_private (klass, sizeof (SeahorseGpgmeKeyringPrivate));
+
+	seahorse_registry_register_type (NULL, SEAHORSE_TYPE_GPGME_KEYRING,
+	                                 "source", "local", NULL);
+}
+
+static void
+seahorse_gpgme_keyring_source_iface (SeahorseSourceIface *iface)
+{
+	iface->import_async = seahorse_gpgme_keyring_import_async;
+	iface->import_finish = seahorse_gpgme_keyring_import_finish;
+	iface->export_async = seahorse_gpgme_keyring_export_async;
+	iface->export_finish = seahorse_gpgme_keyring_export_finish;
+}
+
+static guint
+seahorse_gpgme_keyring_get_length (GcrCollection *collection)
+{
+	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (collection);
+	return g_hash_table_size (self->pv->keys);
+}
 
-	g_object_class_override_property (gobject_class, PROP_SOURCE_TAG, "source-tag");
-	g_object_class_override_property (gobject_class, PROP_SOURCE_LOCATION, "source-location");
+static GList *
+seahorse_gpgme_keyring_get_objects (GcrCollection *collection)
+{
+	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (collection);
+	return g_hash_table_get_values (self->pv->keys);
+}
 
-	g_type_class_add_private (klass, sizeof (SeahorseGpgmeSourcePrivate));
+static gboolean
+seahorse_gpgme_keyring_contains (GcrCollection *collection,
+                                 GObject *object)
+{
+	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (collection);
+	const gchar *keyid;
+
+	if (!SEAHORSE_IS_GPGME_KEY (object))
+		return FALSE;
 
-	seahorse_registry_register_type (NULL, SEAHORSE_TYPE_GPGME_SOURCE, "source", "local", SEAHORSE_PGP_STR, NULL);
-	seahorse_registry_register_function (NULL, seahorse_pgp_key_canonize_id, "canonize", SEAHORSE_PGP_STR, NULL);
+	keyid = seahorse_pgp_key_get_keyid (SEAHORSE_PGP_KEY (object));
+	return g_hash_table_lookup (self->pv->keys, keyid) == object;
 }
 
 static void
-seahorse_source_iface (SeahorseSourceIface *iface)
+seahorse_gpgme_keyring_collection_iface (GcrCollectionIface *iface)
 {
-	iface->load_async = seahorse_gpgme_source_load_async;
-	iface->load_finish = seahorse_gpgme_source_load_finish;
-	iface->import_async = seahorse_gpgme_source_import_async;
-	iface->import_finish = seahorse_gpgme_source_import_finish;
-	iface->export_async = seahorse_gpgme_source_export_async;
-	iface->export_finish = seahorse_gpgme_source_export_finish;
+	iface->get_objects = seahorse_gpgme_keyring_get_objects;
+	iface->get_length = seahorse_gpgme_keyring_get_length;
+	iface->contains = seahorse_gpgme_keyring_contains;
 }
 
 /**
- * seahorse_gpgme_source_new
- * 
+ * seahorse_gpgme_keyring_new
+ *
  * Creates a new PGP key source
- * 
+ *
  * Returns: The key source.
  **/
-SeahorseGpgmeSource *
-seahorse_gpgme_source_new (void)
+SeahorseGpgmeKeyring *
+seahorse_gpgme_keyring_new (void)
 {
-	return g_object_new (SEAHORSE_TYPE_GPGME_SOURCE, NULL);
+	return g_object_new (SEAHORSE_TYPE_GPGME_KEYRING, NULL);
 }
 
 gpgme_ctx_t
-seahorse_gpgme_source_new_context (void)
+seahorse_gpgme_keyring_new_context (void)
 {
 	gpgme_ctx_t ctx = NULL;
 	g_return_val_if_fail (GPG_IS_OK (init_gpgme (&ctx)), NULL);
diff --git a/pgp/seahorse-gpgme-keyring.h b/pgp/seahorse-gpgme-keyring.h
new file mode 100644
index 0000000..5a4b0c5
--- /dev/null
+++ b/pgp/seahorse-gpgme-keyring.h
@@ -0,0 +1,91 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2004 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU 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.
+ */
+
+/**
+ * SeahorseGpgmeKeyring: A key keyring for PGP keys retrieved from GPGME.
+ *
+ * - Derived from SeahorseKeyring
+ * - Since GPGME represents secret keys as seperate from public keys, this
+ *   class takes care to combine them into one logical SeahorsePGPKey object.
+ * - Adds the keys it loads to the SeahorseContext.
+ * - Eventually a lot of stuff from seahorse-op.* should probably be merged
+ *   into this class.
+ * - Monitors ~/.gnupg for changes and reloads the key ring as necessary.
+ *
+ * Properties:
+ *  location: (SeahorseLocation) The location of keys that come from this
+ *         keyring. (ie: SEAHORSE_LOCATION_LOCAL, SEAHORSE_LOCATION_REMOTE)
+ */
+
+#ifndef __SEAHORSE_GPGME_KEYRING_H__
+#define __SEAHORSE_GPGME_KEYRING_H__
+
+#include <gpgme.h>
+
+#include <glib-object.h>
+
+#include <gio/gio.h>
+
+#include "seahorse-gpgme-key.h"
+
+#define SEAHORSE_TYPE_GPGME_KEYRING            (seahorse_gpgme_keyring_get_type ())
+#define SEAHORSE_GPGME_KEYRING(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_GPGME_KEYRING, SeahorseGpgmeKeyring))
+#define SEAHORSE_GPGME_KEYRING_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_GPGME_KEYRING, SeahorseGpgmeKeyringClass))
+#define SEAHORSE_IS_GPGME_KEYRING(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_GPGME_KEYRING))
+#define SEAHORSE_IS_GPGME_KEYRING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_GPGME_KEYRING))
+#define SEAHORSE_GPGME_KEYRING_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_GPGME_KEYRING, SeahorseGpgmeKeyringClass))
+
+typedef struct _SeahorseGpgmeKeyring SeahorseGpgmeKeyring;
+typedef struct _SeahorseGpgmeKeyringClass SeahorseGpgmeKeyringClass;
+typedef struct _SeahorseGpgmeKeyringPrivate SeahorseGpgmeKeyringPrivate;
+
+struct _SeahorseGpgmeKeyring {
+	GObject parent;
+	gpgme_ctx_t gctx;
+	SeahorseGpgmeKeyringPrivate *pv;
+};
+
+struct _SeahorseGpgmeKeyringClass {
+	GObjectClass parent_class;
+};
+
+GType                  seahorse_gpgme_keyring_get_type       (void);
+
+SeahorseGpgmeKeyring * seahorse_gpgme_keyring_new            (void);
+
+gpgme_ctx_t            seahorse_gpgme_keyring_new_context    (void);
+
+SeahorseGpgmeKey *     seahorse_gpgme_keyring_lookup         (SeahorseGpgmeKeyring *self,
+                                                              const gchar *keyid);
+
+void                   seahorse_gpgme_keyring_remove_key     (SeahorseGpgmeKeyring *self,
+                                                              SeahorseGpgmeKey *key);
+
+void                   seahorse_gpgme_keyring_load_async     (SeahorseGpgmeKeyring *self,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+gboolean               seahorse_gpgme_keyring_load_finish    (SeahorseGpgmeKeyring *self,
+                                                              GAsyncResult *result,
+                                                              GError **error);
+
+#endif /* __SEAHORSE_GPGME_KEYRING_H__ */
diff --git a/pgp/seahorse-gpgme-sign.c b/pgp/seahorse-gpgme-sign.c
index d00eb27..e54ac03 100644
--- a/pgp/seahorse-gpgme-sign.c
+++ b/pgp/seahorse-gpgme-sign.c
@@ -41,7 +41,7 @@ sign_ok_clicked (SeahorseWidget *swidget, GtkWindow *parent)
 {
     SeahorseSignCheck check;
     SeahorseSignOptions options = 0;
-    SeahorseObject *signer;
+    SeahorsePgpKey *signer;
     GtkWidget *w;
     gpgme_error_t err;
     SeahorseObject *to_sign;
@@ -97,7 +97,8 @@ sign_ok_clicked (SeahorseWidget *swidget, GtkWindow *parent)
     if (!GPG_IS_OK (err)) {
         if (gpgme_err_code (err) == GPG_ERR_EALREADY) {
             w = gtk_message_dialog_new (parent, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
-                                        _("This key was already signed by\n\"%s\""), seahorse_object_get_label (signer));
+                                        _("This key was already signed by\n\"%s\""),
+                                        seahorse_object_get_label (SEAHORSE_OBJECT (signer)));
             gtk_dialog_run (GTK_DIALOG (w));
             gtk_widget_destroy (w);
         } else
diff --git a/pgp/seahorse-gpgme-uid.c b/pgp/seahorse-gpgme-uid.c
index b324429..4d8f88d 100644
--- a/pgp/seahorse-gpgme-uid.c
+++ b/pgp/seahorse-gpgme-uid.c
@@ -138,20 +138,6 @@ seahorse_gpgme_uid_init (SeahorseGpgmeUid *self)
 	self->pv->actual_index = -1;
 }
 
-static GObject*
-seahorse_gpgme_uid_constructor (GType type, guint n_props, GObjectConstructParam *props)
-{
-	GObject *obj = G_OBJECT_CLASS (seahorse_gpgme_uid_parent_class)->constructor (type, n_props, props);
-	SeahorseGpgmeUid *self = NULL;
-	
-	if (obj) {
-		self = SEAHORSE_GPGME_UID (obj);
-		g_object_set (self, "location", SEAHORSE_LOCATION_LOCAL, NULL);
-	}
-	
-	return obj;
-}
-
 static void
 seahorse_gpgme_uid_get_property (GObject *object, guint prop_id,
                                GValue *value, GParamSpec *pspec)
@@ -233,7 +219,6 @@ seahorse_gpgme_uid_class_init (SeahorseGpgmeUidClass *klass)
 	seahorse_gpgme_uid_parent_class = g_type_class_peek_parent (klass);
 	g_type_class_add_private (klass, sizeof (SeahorseGpgmeUidPrivate));
 
-	gobject_class->constructor = seahorse_gpgme_uid_constructor;
 	gobject_class->finalize = seahorse_gpgme_uid_object_finalize;
 	gobject_class->set_property = seahorse_gpgme_uid_set_property;
 	gobject_class->get_property = seahorse_gpgme_uid_get_property;
diff --git a/pgp/seahorse-hkp-source.c b/pgp/seahorse-hkp-source.c
index eb6046b..b27de48 100644
--- a/pgp/seahorse-hkp-source.c
+++ b/pgp/seahorse-hkp-source.c
@@ -363,7 +363,7 @@ parse_hkp_index (const gchar *response)
             
 			v = g_strsplit_set (t, " ", 3);
 			if (!v[0] || !v[1] || !v[2]) {
-				g_warning ("Invalid key line from server: %s", line);
+				g_message ("Invalid key line from server: %s", line);
                 
 			} else {
 				gchar *fingerprint, *fpr = NULL;
@@ -376,7 +376,7 @@ parse_hkp_index (const gchar *response)
 				/* Cut the length and fingerprint */
 				fpr = strchr (v[0], '/');
 				if (fpr == NULL) {
-					g_warning ("couldn't find key fingerprint in line from server: %s", line);
+					g_message ("couldn't find key fingerprint in line from server: %s", line);
 					fpr = "";
 				} else {
 					*(fpr++) = 0;
@@ -411,15 +411,15 @@ parse_hkp_index (const gchar *response)
 					seahorse_object_list_free (uids);
 					seahorse_pgp_key_set_subkeys (SEAHORSE_PGP_KEY (key), subkeys);
 					seahorse_object_list_free (subkeys);
+					seahorse_pgp_key_realize (SEAHORSE_PGP_KEY (key));
 					uids = subkeys = NULL;
 					key = NULL;
 				}
 
 				key = seahorse_pgp_key_new ();
 				keys = g_list_prepend (keys, key);
-		        	g_object_set (key, "location", SEAHORSE_LOCATION_REMOTE, "flags", 
-		        	              flags, NULL);
-		        	
+				g_object_set (key, "flags", flags, NULL);
+
 				/* Add all the info to the key */
 				subkey = seahorse_pgp_subkey_new ();
 				seahorse_pgp_subkey_set_keyid (subkey, fpr);
@@ -465,39 +465,13 @@ parse_hkp_index (const gchar *response)
 		seahorse_object_list_free (uids);
 		seahorse_pgp_key_set_subkeys (SEAHORSE_PGP_KEY (key), g_list_reverse (subkeys));
 		seahorse_object_list_free (subkeys);
+		seahorse_pgp_key_realize (SEAHORSE_PGP_KEY (key));
 	}
 	
 	return keys; 
 }
 
 /**
-* ssrc: The SeahorseHKPSource to add
-* key: The SeahorsePgpKey to add
-*
-* Adds the key with the source ssrc to the application context
-*
-**/
-static void
-add_key (SeahorseHKPSource *ssrc, SeahorsePgpKey *key)
-{
-	SeahorseObject *prev;
-	GQuark keyid;
-       
-	keyid = seahorse_pgp_key_canonize_id (seahorse_pgp_key_get_keyid (key));
-	prev = seahorse_context_get_object (SCTX_APP (), SEAHORSE_SOURCE (ssrc), keyid);
-	if (prev != NULL) {
-		g_return_if_fail (SEAHORSE_IS_PGP_KEY (prev));
-		seahorse_pgp_key_set_uids (SEAHORSE_PGP_KEY (prev), seahorse_pgp_key_get_uids (key));
-		seahorse_pgp_key_set_subkeys (SEAHORSE_PGP_KEY (prev), seahorse_pgp_key_get_subkeys (key));
-		return;
-	}
-
-	/* Add to context */ 
-	seahorse_object_set_source (SEAHORSE_OBJECT (key), SEAHORSE_SOURCE (ssrc));
-	seahorse_context_add_object (SCTX_APP (), SEAHORSE_OBJECT (key));
-}
-
-/**
 * response: The server response
 *
 * Parses the response and extracts an error message
@@ -585,12 +559,6 @@ detect_key (const gchar *text, gint len, const gchar **start, const gchar **end)
  *  SEAHORSE HKP SOURCE
  */
 
-enum {
-    PROP_0,
-    PROP_SOURCE_TAG,
-    PROP_SOURCE_LOCATION
-};
-
 static void seahorse_source_iface (SeahorseSourceIface *iface);
 
 G_DEFINE_TYPE_EXTENDED (SeahorseHKPSource, seahorse_hkp_source, SEAHORSE_TYPE_SERVER_SOURCE, 0,
@@ -602,51 +570,6 @@ seahorse_hkp_source_init (SeahorseHKPSource *hsrc)
 
 }
 
-/**
-* object: ignored
-* prop_id: id of the property
-* value: the resulting value
-* pspec: ignored
-*
-* Returns data for PROP_SOURCE_TAG and PROP_SOURCE_LOCATION
-*
-**/
-static void 
-seahorse_hkp_source_get_property (GObject *object, guint prop_id, GValue *value,
-                                  GParamSpec *pspec)
-{
-    switch (prop_id) {
-    case PROP_SOURCE_TAG:
-        g_value_set_uint (value, SEAHORSE_PGP);
-        break;
-    case PROP_SOURCE_LOCATION:
-        g_value_set_enum (value, SEAHORSE_LOCATION_REMOTE);
-        break;
-    };
-}
-
-/**
-* klass:
-*
-* Initialize the basic class stuff
-*
-**/
-static void
-seahorse_hkp_source_class_init (SeahorseHKPSourceClass *klass)
-{
-	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-	gobject_class->get_property = seahorse_hkp_source_get_property;
-
-	g_object_class_override_property (gobject_class, PROP_SOURCE_TAG, "source-tag");
-	g_object_class_override_property (gobject_class, PROP_SOURCE_LOCATION, "source-location");
-
-	seahorse_registry_register_type (NULL, SEAHORSE_TYPE_HKP_SOURCE, "source", "remote", SEAHORSE_PGP_STR, NULL);
-	seahorse_servers_register_type ("hkp", _("HTTP Key Server"), seahorse_hkp_is_valid_uri);
-
-	seahorse_registry_register_function (NULL, seahorse_pgp_key_canonize_id, "canonize", SEAHORSE_PGP_STR, NULL);
-}
-
 static gboolean
 hkp_message_propagate_error (SeahorseHKPSource *self,
                              SoupMessage *message,
@@ -702,7 +625,7 @@ typedef struct {
 	gulong cancelled_sig;
 	SoupSession *session;
 	gint requests;
-	GList *keys;
+	GcrSimpleCollection *results;
 } source_search_closure;
 
 static void
@@ -713,7 +636,7 @@ source_search_free (gpointer data)
 	g_cancellable_disconnect (closure->cancellable, closure->cancelled_sig);
 	g_clear_object (&closure->cancellable);
 	g_object_unref (closure->session);
-	seahorse_object_list_free (closure->keys);
+	g_clear_object (&closure->results);
 	g_free (closure);
 }
 
@@ -735,8 +658,8 @@ on_search_message_complete (SoupSession *session,
 	} else {
 		keys = parse_hkp_index (message->response_body->data);
 		for (l = keys; l; l = g_list_next (l))
-			add_key (closure->source, SEAHORSE_PGP_KEY (l->data));
-		closure->keys = keys;
+			gcr_simple_collection_add (closure->results, l->data);
+		g_list_free_full (keys, g_object_unref);
 	}
 
 	g_simple_async_result_complete_in_idle (res);
@@ -762,8 +685,9 @@ is_hex_keyid (const gchar *match)
 	return TRUE;
 }
 static void
-seahorse_hkp_source_search_async (SeahorseSource *source,
+seahorse_hkp_source_search_async (SeahorseServerSource *source,
                                   const gchar *match,
+                                  GcrSimpleCollection *results,
                                   GCancellable *cancellable,
                                   GAsyncReadyCallback callback,
                                   gpointer user_data)
@@ -782,6 +706,7 @@ seahorse_hkp_source_search_async (SeahorseSource *source,
 	closure->source = g_object_ref (self);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
 	closure->session = create_hkp_soup_session ();
+	closure->results = g_object_ref (results);
 	g_simple_async_result_set_op_res_gpointer (res, closure, source_search_free);
 
 	uri = get_http_server_uri (self, "/pks/lookup");
@@ -816,24 +741,18 @@ seahorse_hkp_source_search_async (SeahorseSource *source,
 	g_object_unref (res);
 }
 
-static GList *
-seahorse_hkp_source_search_finish (SeahorseSource *source,
+static gboolean
+seahorse_hkp_source_search_finish (SeahorseServerSource *source,
                                    GAsyncResult *result,
                                    GError **error)
 {
-	source_search_closure *closure;
-	GList *keys;
-
 	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
-	                      seahorse_hkp_source_search_async), NULL);
+	                      seahorse_hkp_source_search_async), FALSE);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
-		return NULL;
+		return FALSE;
 
-	closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
-	keys = closure->keys;
-	closure->keys = NULL;
-	return keys;
+	return TRUE;
 }
 
 typedef struct {
@@ -1010,12 +929,12 @@ typedef struct {
 	gulong cancelled_sig;
 	SoupSession *session;
 	gint requests;
-} source_export_raw_closure;
+} source_export_closure;
 
 static void
-source_export_raw_free (gpointer data)
+source_export_free (gpointer data)
 {
-	source_export_raw_closure *closure = data;
+	source_export_closure *closure = data;
 	g_object_unref (closure->source);
 	g_object_unref (closure->output);
 	g_cancellable_disconnect (closure->cancellable, closure->cancelled_sig);
@@ -1030,7 +949,7 @@ on_export_message_complete (SoupSession *session,
                             gpointer user_data)
 {
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
-	source_export_raw_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	source_export_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GError *error = NULL;
 	const gchar *start;
 	const gchar *end;
@@ -1088,15 +1007,15 @@ on_export_message_complete (SoupSession *session,
 * Gets data from the keyserver, writes it to the output stream
 **/
 static void
-seahorse_hkp_source_export_raw_async (SeahorseSource *source,
-                                      GList *keyids,
-                                      GOutputStream *output,
-                                      GCancellable *cancellable,
-                                      GAsyncReadyCallback callback,
-                                      gpointer user_data)
+seahorse_hkp_source_export_async (SeahorseServerSource *source,
+                                  GList *keyids,
+                                  GOutputStream *output,
+                                  GCancellable *cancellable,
+                                  GAsyncReadyCallback callback,
+                                  gpointer user_data)
 {
 	SeahorseHKPSource *self = SEAHORSE_HKP_SOURCE (source);
-	source_export_raw_closure *closure;
+	source_export_closure *closure;
 	GSimpleAsyncResult *res;
 	SoupMessage *message;
 	SoupURI *uri;
@@ -1107,13 +1026,13 @@ seahorse_hkp_source_export_raw_async (SeahorseSource *source,
 	GList *l;
 
 	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 seahorse_hkp_source_export_raw_async);
-	closure = g_new0 (source_export_raw_closure, 1);
+	                                 seahorse_hkp_source_export_async);
+	closure = g_new0 (source_export_closure, 1);
 	closure->source = g_object_ref (self);
 	closure->output = g_object_ref (output);
 	closure->session = create_hkp_soup_session ();
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-	g_simple_async_result_set_op_res_gpointer (res, closure, source_export_raw_free);
+	g_simple_async_result_set_op_res_gpointer (res, closure, source_export_free);
 
 	if (g_list_length (keyids) == 0) {
 		g_simple_async_result_complete_in_idle (res);
@@ -1133,7 +1052,7 @@ seahorse_hkp_source_export_raw_async (SeahorseSource *source,
 		g_hash_table_remove_all (form);
 
 		/* Get the key id and limit it to 8 characters */
-		fpr = seahorse_pgp_key_calc_rawid (GPOINTER_TO_UINT (l->data));
+		fpr = l->data;
 		len = strlen (fpr);
 		if (len > 8)
 			fpr += (len - 8);
@@ -1165,14 +1084,14 @@ seahorse_hkp_source_export_raw_async (SeahorseSource *source,
 }
 
 static GOutputStream *
-seahorse_hkp_source_export_raw_finish (SeahorseSource *source,
-                                       GAsyncResult *result,
-                                       GError **error)
+seahorse_hkp_source_export_finish (SeahorseServerSource *source,
+                                   GAsyncResult *result,
+                                   GError **error)
 {
-	source_export_raw_closure *closure;
+	source_export_closure *closure;
 
 	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
-	                      seahorse_hkp_source_export_raw_async), NULL);
+	                      seahorse_hkp_source_export_async), NULL);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return NULL;
@@ -1190,15 +1109,30 @@ seahorse_hkp_source_export_raw_finish (SeahorseSource *source,
 static void 
 seahorse_source_iface (SeahorseSourceIface *iface)
 {
-	iface->search_async = seahorse_hkp_source_search_async;
-	iface->search_finish = seahorse_hkp_source_search_finish;
 	iface->import_async = seahorse_hkp_source_import_async;
 	iface->import_finish = seahorse_hkp_source_import_finish;
-	iface->export_raw_async = seahorse_hkp_source_export_raw_async;
-	iface->export_raw_finish = seahorse_hkp_source_export_raw_finish;
 }
 
 /**
+* klass:
+*
+* Initialize the basic class stuff
+*
+**/
+static void
+seahorse_hkp_source_class_init (SeahorseHKPSourceClass *klass)
+{
+	SeahorseServerSourceClass *server_class = SEAHORSE_SERVER_SOURCE_CLASS (klass);
+
+	server_class->search_async = seahorse_hkp_source_search_async;
+	server_class->search_finish = seahorse_hkp_source_search_finish;
+	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);
+}
+/**
  * seahorse_hkp_source_new
  * @uri: The server to connect to 
  * 
diff --git a/src/seahorse-keyserver-results.c b/pgp/seahorse-keyserver-results.c
similarity index 83%
rename from src/seahorse-keyserver-results.c
rename to pgp/seahorse-keyserver-results.c
index bdf9b08..b672b85 100644
--- a/src/seahorse-keyserver-results.c
+++ b/pgp/seahorse-keyserver-results.c
@@ -1,31 +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 
+ * 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.  
+ * 02111-1307, USA.
  */
 
 #include "config.h"
 
+#include "seahorse-pgp-backend.h"
+#include "seahorse-keyserver-search.h"
 #include "seahorse-keyserver-results.h"
-#include "seahorse-key-manager-store.h"
-#include "seahorse-windows.h"
 
+#include "seahorse-key-manager-store.h"
 #include "seahorse-progress.h"
 
 #include <glib/gi18n.h>
@@ -48,64 +49,21 @@ enum {
 struct _SeahorseKeyserverResultsPrivate {
 	char *search_string;
 	GtkTreeView *view;
+	GcrSimpleCollection *collection;
 	GtkActionGroup *object_actions;
 	SeahorseKeyManagerStore *store;
-	SeahorseCollection *collection;
-	SeahorsePredicate pred;
 	GSettings *settings;
 };
 
 G_DEFINE_TYPE (SeahorseKeyserverResults, seahorse_keyserver_results, SEAHORSE_TYPE_VIEWER);
 
 /* -----------------------------------------------------------------------------
- * INTERNAL 
+ * INTERNAL
  */
 
 
-static gboolean 
-on_filter_objects (SeahorseObject *obj, SeahorseKeyserverResults *self) 
-{
-	const gchar *match;
-	gboolean ret = FALSE;
-	gchar* value;
-	gsize n_value, n_match;
-
-	g_return_val_if_fail (SEAHORSE_IS_KEYSERVER_RESULTS (self), FALSE);
-	g_return_val_if_fail (SEAHORSE_IS_OBJECT (obj), FALSE);
-
-	match = self->pv->search_string;
-	if (g_utf8_strlen (match, -1) == 0)
-		ret = TRUE;
-
-	/* Match against the label */
-	if (ret != TRUE) {
-		value = g_utf8_casefold (seahorse_object_get_label (obj), -1);
-		ret = strstr (value, match) != NULL;
-		g_free (value);
-	}
-	
-	/* Match against the key identifier */
-	if (ret != TRUE) {
-		if (strncmp (match, "0x", 2) == 0)
-			match += 2;
-		value = g_utf8_casefold (seahorse_object_get_identifier (obj), -1);
-		
-		/* Only compare as many bytes as exist in the key id */
-		n_value = strlen (value);
-		n_match = strlen (match);
-		if (n_value > n_match)
-			match += (n_value - n_match);
-		ret = strstr (value, match) != NULL;
-		
-		g_free (value);
-	}
-	
-	return ret;
-}
-
-
-static gboolean 
-fire_selection_changed (SeahorseKeyserverResults* self) 
+static gboolean
+fire_selection_changed (SeahorseKeyserverResults* self)
 {
 	gint rows;
 	GtkTreeSelection* selection;
@@ -127,16 +85,16 @@ fire_selection_changed (SeahorseKeyserverResults* self)
 * Adds fire_selection_changed as idle function
 *
 **/
-static void 
-on_view_selection_changed (GtkTreeSelection *selection, SeahorseKeyserverResults *self) 
+static void
+on_view_selection_changed (GtkTreeSelection *selection, SeahorseKeyserverResults *self)
 {
 	g_return_if_fail (SEAHORSE_IS_KEYSERVER_RESULTS (self));
 	g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
 	g_idle_add ((GSourceFunc)fire_selection_changed, self);
 }
 
-static void 
-on_row_activated (GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column, SeahorseKeyserverResults *self) 
+static void
+on_row_activated (GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column, SeahorseKeyserverResults *self)
 {
 	SeahorseObject *obj;
 
@@ -146,12 +104,12 @@ on_row_activated (GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *colum
 	g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
 
 	obj = seahorse_key_manager_store_get_object_from_path (view, path);
-	if (obj != NULL) 
+	if (obj != NULL)
 		seahorse_viewer_show_properties (SEAHORSE_VIEWER (self), obj);
 }
 
-G_MODULE_EXPORT gboolean 
-on_key_list_button_pressed (GtkTreeView* view, GdkEventButton* event, SeahorseKeyserverResults* self) 
+G_MODULE_EXPORT gboolean
+on_key_list_button_pressed (GtkTreeView* view, GdkEventButton* event, SeahorseKeyserverResults* self)
 {
 	g_return_val_if_fail (SEAHORSE_IS_KEYSERVER_RESULTS (self), FALSE);
 	g_return_val_if_fail (GTK_IS_TREE_VIEW (view), FALSE);
@@ -160,8 +118,8 @@ on_key_list_button_pressed (GtkTreeView* view, GdkEventButton* event, SeahorseKe
 	return FALSE;
 }
 
-G_MODULE_EXPORT gboolean 
-on_key_list_popup_menu (GtkTreeView* view, SeahorseKeyserverResults* self) 
+G_MODULE_EXPORT gboolean
+on_key_list_popup_menu (GtkTreeView* view, SeahorseKeyserverResults* self)
 {
 	SeahorseObject* key;
 
@@ -182,8 +140,8 @@ on_key_list_popup_menu (GtkTreeView* view, SeahorseKeyserverResults* self)
 * Expands all the nodes in the view of the object
 *
 **/
-static void 
-on_view_expand_all (GtkAction* action, SeahorseKeyserverResults* self) 
+static void
+on_view_expand_all (GtkAction* action, SeahorseKeyserverResults* self)
 {
 	g_return_if_fail (SEAHORSE_IS_KEYSERVER_RESULTS (self));
 	g_return_if_fail (GTK_IS_ACTION (action));
@@ -198,8 +156,8 @@ on_view_expand_all (GtkAction* action, SeahorseKeyserverResults* self)
 * Collapses all the nodes in the view of the object
 *
 **/
-static void 
-on_view_collapse_all (GtkAction* action, SeahorseKeyserverResults* self) 
+static void
+on_view_collapse_all (GtkAction* action, SeahorseKeyserverResults* self)
 
 {
 	g_return_if_fail (SEAHORSE_IS_KEYSERVER_RESULTS (self));
@@ -214,16 +172,16 @@ on_view_collapse_all (GtkAction* action, SeahorseKeyserverResults* self)
 * destroys the widget
 *
 **/
-static void 
-on_app_close (GtkAction* action, SeahorseKeyserverResults* self) 
+static void
+on_app_close (GtkAction* action, SeahorseKeyserverResults* self)
 {
 	g_return_if_fail (SEAHORSE_IS_KEYSERVER_RESULTS (self));
 	g_return_if_fail (action == NULL || GTK_IS_ACTION (action));
 	seahorse_widget_destroy (SEAHORSE_WIDGET (self));
 }
 
-static void 
-on_remote_find (GtkAction* action, SeahorseKeyserverResults* self) 
+static void
+on_remote_find (GtkAction* action, SeahorseKeyserverResults* self)
 {
 	g_return_if_fail (SEAHORSE_IS_KEYSERVER_RESULTS (self));
 	g_return_if_fail (GTK_IS_ACTION (action));
@@ -241,8 +199,8 @@ on_remote_find (GtkAction* action, SeahorseKeyserverResults* self)
 *
 * Returns TRUE on success
 **/
-static gboolean 
-on_delete_event (GtkWidget* widget, GdkEvent* event, SeahorseKeyserverResults* self) 
+static gboolean
+on_delete_event (GtkWidget* widget, GdkEvent* event, SeahorseKeyserverResults* self)
 {
 	g_return_val_if_fail (SEAHORSE_IS_KEYSERVER_RESULTS (self), FALSE);
 	g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
@@ -251,48 +209,48 @@ on_delete_event (GtkWidget* widget, GdkEvent* event, SeahorseKeyserverResults* s
 }
 
 static const GtkActionEntry GENERAL_ENTRIES[] = {
-	{ "remote-menu", NULL, N_("_Remote") }, 
-	{ "app-close", GTK_STOCK_CLOSE, NULL, "<control>W", 
-	  N_("Close this window"), G_CALLBACK (on_app_close) }, 
-	{ "view-expand-all", GTK_STOCK_ADD, N_("_Expand All"), NULL, 
-	  N_("Expand all listings"), G_CALLBACK (on_view_expand_all) }, 
-	{ "view-collapse-all", GTK_STOCK_REMOVE, N_("_Collapse All"), NULL, 
-	  N_("Collapse all listings"), G_CALLBACK (on_view_collapse_all) } 
+	{ "remote-menu", NULL, N_("_Remote") },
+	{ "app-close", GTK_STOCK_CLOSE, NULL, "<control>W",
+	  N_("Close this window"), G_CALLBACK (on_app_close) },
+	{ "view-expand-all", GTK_STOCK_ADD, N_("_Expand All"), NULL,
+	  N_("Expand all listings"), G_CALLBACK (on_view_expand_all) },
+	{ "view-collapse-all", GTK_STOCK_REMOVE, N_("_Collapse All"), NULL,
+	  N_("Collapse all listings"), G_CALLBACK (on_view_collapse_all) }
 };
 
 static const GtkActionEntry SERVER_ENTRIES[] = {
-	{ "remote-find", GTK_STOCK_FIND, N_("_Find Remote Keys..."), "", 
+	{ "remote-find", GTK_STOCK_FIND, N_("_Find Remote Keys..."), "",
 	  N_("Search for keys on a key server"), G_CALLBACK (on_remote_find) }
 };
 
 /* -----------------------------------------------------------------------------
- * OBJECT 
+ * OBJECT
  */
 
-static GList* 
-seahorse_keyserver_results_get_selected_objects (SeahorseViewer* base) 
+static GList*
+seahorse_keyserver_results_get_selected_objects (SeahorseViewer* base)
 {
 	SeahorseKeyserverResults * self = SEAHORSE_KEYSERVER_RESULTS (base);
 	return seahorse_key_manager_store_get_selected_objects (self->pv->view);
 }
 
-static void 
-seahorse_keyserver_results_set_selected_objects (SeahorseViewer* base, GList* keys) 
+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 SeahorseObject* 
-seahorse_keyserver_results_get_selected (SeahorseViewer* base) 
+static SeahorseObject*
+seahorse_keyserver_results_get_selected (SeahorseViewer* base)
 {
 	SeahorseKeyserverResults* self;
 	self = SEAHORSE_KEYSERVER_RESULTS (base);
 	return seahorse_key_manager_store_get_selected_object (self->pv->view);
 }
 
-static void 
-seahorse_keyserver_results_set_selected (SeahorseViewer* base, SeahorseObject* value) 
+static void
+seahorse_keyserver_results_set_selected (SeahorseViewer* base, SeahorseObject* value)
 {
 	SeahorseKeyserverResults* self = SEAHORSE_KEYSERVER_RESULTS (base);
 	GList* keys = NULL;
@@ -315,8 +273,8 @@ seahorse_keyserver_results_set_selected (SeahorseViewer* base, SeahorseObject* v
 *
 * Returns The SeahorseKeyserverResults object as GObject
 **/
-static GObject* 
-seahorse_keyserver_results_constructor (GType type, guint n_props, GObjectConstructParam *props) 
+static GObject*
+seahorse_keyserver_results_constructor (GType type, guint n_props, GObjectConstructParam *props)
 {
 	SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (G_OBJECT_CLASS (seahorse_keyserver_results_parent_class)->constructor(type, n_props, props));
 	GtkActionGroup* actions;
@@ -324,7 +282,7 @@ seahorse_keyserver_results_constructor (GType type, guint n_props, GObjectConstr
 	GtkWindow *window;
 	char* title;
 
-	g_return_val_if_fail (self, NULL);	
+	g_return_val_if_fail (self, NULL);
 
 
 	if (g_utf8_strlen (self->pv->search_string, -1) == 0) {
@@ -336,9 +294,9 @@ seahorse_keyserver_results_constructor (GType type, guint n_props, GObjectConstr
 	window = seahorse_viewer_get_window (SEAHORSE_VIEWER (self));
 	gtk_window_set_title (window, title);
 	g_free (title);
-	
+
 	g_signal_connect (window, "delete-event", G_CALLBACK (on_delete_event), self);
-	
+
 	actions = gtk_action_group_new ("general");
 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
 	gtk_action_group_add_actions (actions, GENERAL_ENTRIES, G_N_ELEMENTS (GENERAL_ENTRIES), self);
@@ -358,26 +316,19 @@ seahorse_keyserver_results_constructor (GType type, guint n_props, GObjectConstr
 	g_signal_connect_object (self->pv->view, "button-press-event", G_CALLBACK (on_key_list_button_pressed), self, 0);
 	g_signal_connect_object (self->pv->view, "popup-menu", G_CALLBACK (on_key_list_popup_menu), self, 0);
 	gtk_widget_realize (GTK_WIDGET (self->pv->view));
-	
+
 	/* Set focus to the current key list */
 	gtk_widget_grab_focus (GTK_WIDGET (self->pv->view));
-	
+
 	/* To avoid flicker */
 	seahorse_viewer_ensure_updated (SEAHORSE_VIEWER (self));
 	seahorse_widget_show (SEAHORSE_WIDGET (SEAHORSE_VIEWER (self)));
-	
-	/* Our predicate for filtering keys */
-	self->pv->pred.tag = g_quark_from_string ("openpgp");
-	self->pv->pred.location = SEAHORSE_LOCATION_REMOTE;
-	self->pv->pred.custom = (SeahorsePredicateFunc)on_filter_objects;
-	self->pv->pred.custom_target = self;
-	
-	/* Our set all nicely filtered */
-	self->pv->collection = seahorse_collection_new_for_predicate (&self->pv->pred, NULL);
-	self->pv->store = seahorse_key_manager_store_new (self->pv->collection, self->pv->view,
+
+	self->pv->store = seahorse_key_manager_store_new (GCR_COLLECTION (self->pv->collection),
+	                                                  self->pv->view,
 	                                                  self->pv->settings);
 	on_view_selection_changed (selection, self);
-	
+
 	return G_OBJECT (self);
 }
 
@@ -392,6 +343,7 @@ seahorse_keyserver_results_init (SeahorseKeyserverResults *self)
 {
 	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_KEYSERVER_RESULTS, SeahorseKeyserverResultsPrivate);
 	self->pv->settings = g_settings_new ("org.gnome.seahorse.manager");
+	self->pv->collection = GCR_SIMPLE_COLLECTION (gcr_simple_collection_new ());
 }
 
 /**
@@ -407,7 +359,7 @@ seahorse_keyserver_results_finalize (GObject *obj)
 
 	g_free (self->pv->search_string);
 	self->pv->search_string = NULL;
-	
+
 	if (self->pv->object_actions)
 		g_object_unref (self->pv->object_actions);
 	self->pv->object_actions = NULL;
@@ -417,12 +369,13 @@ seahorse_keyserver_results_finalize (GObject *obj)
 	if (self->pv->store)
 		g_object_unref (self->pv->store);
 	self->pv->store = NULL;
-	
+
 	if (self->pv->view)
 		gtk_tree_view_set_model (self->pv->view, NULL);
 	self->pv->view = NULL;
 
 	g_clear_object (&self->pv->settings);
+	g_clear_object (&self->pv->collection);
 
 	G_OBJECT_CLASS (seahorse_keyserver_results_parent_class)->finalize (obj);
 }
@@ -437,12 +390,12 @@ seahorse_keyserver_results_finalize (GObject *obj)
 *
 **/
 static void
-seahorse_keyserver_results_set_property (GObject *obj, guint prop_id, const GValue *value, 
+seahorse_keyserver_results_set_property (GObject *obj, guint prop_id, const GValue *value,
                            GParamSpec *pspec)
 {
 	SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (obj);
 	const gchar* str;
-	
+
 	switch (prop_id) {
 	case PROP_SEARCH:
 		/* Many key servers ignore spaces at the beginning and end, so we do too */
@@ -451,7 +404,7 @@ seahorse_keyserver_results_set_property (GObject *obj, guint prop_id, const GVal
 			str = "";
 		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;
@@ -472,11 +425,11 @@ seahorse_keyserver_results_set_property (GObject *obj, guint prop_id, const GVal
 *
 **/
 static void
-seahorse_keyserver_results_get_property (GObject *obj, guint prop_id, GValue *value, 
+seahorse_keyserver_results_get_property (GObject *obj, guint prop_id, GValue *value,
                            GParamSpec *pspec)
 {
 	SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (obj);
-	
+
 	switch (prop_id) {
 	case PROP_SEARCH:
 		g_value_set_string (value, seahorse_keyserver_results_get_search (self));
@@ -500,7 +453,7 @@ static void
 seahorse_keyserver_results_class_init (SeahorseKeyserverResultsClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-    
+
 	seahorse_keyserver_results_parent_class = g_type_class_peek_parent (klass);
 	g_type_class_add_private (klass, sizeof (SeahorseKeyserverResultsPrivate));
 
@@ -508,14 +461,14 @@ seahorse_keyserver_results_class_init (SeahorseKeyserverResultsClass *klass)
 	gobject_class->finalize = seahorse_keyserver_results_finalize;
 	gobject_class->set_property = seahorse_keyserver_results_set_property;
 	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;
-	
-	g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEARCH, 
-	         g_param_spec_string ("search", "search", "search", NULL, 
+
+	g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEARCH,
+	         g_param_spec_string ("search", "search", "search", NULL,
 	                              G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
 
 	g_object_class_override_property (G_OBJECT_CLASS (klass), PROP_SELECTED, "selected");
@@ -529,8 +482,7 @@ on_search_completed (GObject *source,
 	SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (user_data);
 	GError *error = NULL;
 
-	seahorse_context_search_remote_finish (seahorse_context_instance (),
-	                                       result, &error);
+	seahorse_pgp_backend_search_remote_finish (NULL, result, &error);
 	if (error != NULL) {
 		seahorse_viewer_set_status (SEAHORSE_VIEWER (self), error->message);
 		g_error_free (error);
@@ -546,7 +498,7 @@ on_search_completed (GObject *source,
  * Creates a search results window and adds the operation to it's progress status.
  *
  */
-void 
+void
 seahorse_keyserver_results_show (const char* search_text)
 {
 	SeahorseKeyserverResults* self;
@@ -563,10 +515,11 @@ seahorse_keyserver_results_show (const char* search_text)
 	g_object_ref_sink (self);
 
 	cancellable = g_cancellable_new ();
-	seahorse_context_search_remote_async (seahorse_context_instance (),
-	                                      search_text, cancellable,
-	                                      on_search_completed,
-	                                      g_object_ref (self));
+
+	seahorse_pgp_backend_search_remote_async (NULL, search_text,
+	                                          self->pv->collection,
+	                                          cancellable, on_search_completed,
+	                                          g_object_ref (self));
 
 	seahorse_progress_attach (cancellable, SEAHORSE_WIDGET (self));
 
@@ -581,8 +534,8 @@ seahorse_keyserver_results_show (const char* search_text)
  *
  * Returns: The search string in from the results
  */
-const gchar* 
-seahorse_keyserver_results_get_search (SeahorseKeyserverResults* self) 
+const gchar*
+seahorse_keyserver_results_get_search (SeahorseKeyserverResults* self)
 {
 	g_return_val_if_fail (SEAHORSE_IS_KEYSERVER_RESULTS (self), NULL);
 	return self->pv->search_string;
diff --git a/src/seahorse-keyserver-results.h b/pgp/seahorse-keyserver-results.h
similarity index 98%
rename from src/seahorse-keyserver-results.h
rename to pgp/seahorse-keyserver-results.h
index 1c81b5c..e544f60 100644
--- a/src/seahorse-keyserver-results.h
+++ b/pgp/seahorse-keyserver-results.h
@@ -1,23 +1,23 @@
-/* 
+/*
  * Seahorse
- * 
+ *
  * Copyright (C) 2008 Stefan Walter
  * Copyright (C) 2011 Collabora Ltd.
  *
- * This program is free software; you can redistribute it and/or modify 
+ * 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.  
+ * 02111-1307, USA.
  */
 
 #ifndef __SEAHORSE_KEYSERVER_RESULTS_H__
diff --git a/src/seahorse-keyserver-search.c b/pgp/seahorse-keyserver-search.c
similarity index 95%
rename from src/seahorse-keyserver-search.c
rename to pgp/seahorse-keyserver-search.c
index 25e7c3a..a3f08d3 100644
--- a/src/seahorse-keyserver-search.c
+++ b/pgp/seahorse-keyserver-search.c
@@ -22,15 +22,17 @@
 
 #include <config.h>
 
-#include "seahorse-context.h"
-#include "seahorse-dns-sd.h"
+#include "seahorse-discovery.h"
+#include "seahorse-keyserver-search.h"
+#include "seahorse-keyserver-results.h"
+#include "seahorse-pgp-backend.h"
+
 #include "seahorse-preferences.h"
 #include "seahorse-servers.h"
 #include "seahorse-util.h"
 #include "seahorse-widget.h"
 
 #include "seahorse-keyserver-results.h"
-#include "seahorse-windows.h"
 
 /**
  * SECTION:seahorse-keyserver-search
@@ -163,7 +165,7 @@ have_keyserver_selection (SeahorseWidget *swidget)
 {
     GtkWidget *w;
     gboolean checked = FALSE;
-    
+
     /* Key servers */
     w = GTK_WIDGET (seahorse_widget_get_widget (swidget, "key-server-list"));
     g_return_val_if_fail (w != NULL, FALSE);
@@ -172,8 +174,8 @@ have_keyserver_selection (SeahorseWidget *swidget)
     /* Shared keys */
     w = GTK_WIDGET (seahorse_widget_get_widget (swidget, "shared-keys-list"));
     g_return_val_if_fail (w != NULL, FALSE);
-    gtk_container_foreach (GTK_CONTAINER (w), (GtkCallback)have_checks, &checked);        
-    
+    gtk_container_foreach (GTK_CONTAINER (w), (GtkCallback)have_checks, &checked);
+
     return checked;
 }
 
@@ -192,11 +194,11 @@ on_keyserver_search_control_changed (GtkWidget *widget, SeahorseWidget *swidget)
     gboolean enabled = TRUE;
     GtkWidget *w;
     gchar *text;
-    
+
     /* Need to have at least one key server selected ... */
     if (!have_keyserver_selection (swidget))
         enabled = FALSE;
-    
+
     /* ... and some search text */
     else {
         w = GTK_WIDGET (seahorse_widget_get_widget (swidget, "search-text"));
@@ -205,7 +207,7 @@ on_keyserver_search_control_changed (GtkWidget *widget, SeahorseWidget *swidget)
             enabled = FALSE;
         g_free (text);
     }
-        
+
     w = GTK_WIDGET (seahorse_widget_get_widget (swidget, "search"));
     gtk_widget_set_sensitive (w, enabled);
 }
@@ -285,11 +287,11 @@ static void
 remove_checks (GtkWidget *widget, GHashTable *unchecked)
 {
     if (GTK_IS_CHECK_BUTTON (widget)) {
-    
-        if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) 
-            g_hash_table_replace (unchecked, 
+
+        if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+            g_hash_table_replace (unchecked,
                 g_strdup (gtk_button_get_label (GTK_BUTTON (widget))), "");
-        
+
         gtk_widget_destroy (widget);
     }
 }
@@ -371,8 +373,10 @@ on_settings_keyservers_changed (GSettings *settings, const gchar *key, gpointer
 * refreshes the "shared-keys-list"
 *
 **/
-static void 
-refresh_shared_keys (SeahorseServiceDiscovery *ssd, const gchar *name, SeahorseWidget *swidget)
+static void
+refresh_shared_keys (SeahorseDiscovery *ssd,
+                     const gchar *name,
+                     SeahorseWidget *swidget)
 {
 	gchar **keyservers;
 	gchar **names;
@@ -381,8 +385,8 @@ refresh_shared_keys (SeahorseServiceDiscovery *ssd, const gchar *name, SeahorseW
 	widget = seahorse_widget_get_widget (swidget, "shared-keys-list");
 	g_return_if_fail (widget != NULL);
 
-	names = seahorse_service_discovery_list (ssd);
-	keyservers = seahorse_service_discovery_get_uris (ssd, (const gchar **)names);
+	names = seahorse_discovery_list (ssd);
+	keyservers = seahorse_discovery_get_uris (ssd, (const gchar **)names);
 	populate_keyserver_list (swidget, widget, keyservers, names);
 
 	g_strfreev (keyservers);
@@ -390,7 +394,7 @@ refresh_shared_keys (SeahorseServiceDiscovery *ssd, const gchar *name, SeahorseW
 }
 
 /* -------------------------------------------------------------------------- */
- 
+
 /**
  * on_keyserver_search_ok_clicked:
  * @button: ignored
@@ -439,8 +443,8 @@ on_keyserver_search_ok_clicked (GtkButton *button, SeahorseWidget *swidget)
 static void
 cleanup_signals (GtkWidget *widget, SeahorseWidget *swidget)
 {
-    SeahorseServiceDiscovery *ssd = seahorse_context_get_discovery (SCTX_APP());
-    g_signal_handlers_disconnect_by_func (ssd, refresh_shared_keys, swidget);
+	SeahorseDiscovery *ssd = seahorse_pgp_backend_get_discovery (NULL);
+	g_signal_handlers_disconnect_by_func (ssd, refresh_shared_keys, swidget);
 }
 
 
@@ -455,7 +459,7 @@ cleanup_signals (GtkWidget *widget, SeahorseWidget *swidget)
 GtkWindow*
 seahorse_keyserver_search_show (GtkWindow *parent)
 {
-	SeahorseServiceDiscovery *ssd;
+	SeahorseDiscovery *ssd;
 	SeahorseWidget *swidget;
 	GtkWindow *window;
 	GtkWidget *widget;
@@ -485,7 +489,7 @@ seahorse_keyserver_search_show (GtkWindow *parent)
 	                         G_CALLBACK (on_settings_keyservers_changed), swidget, 0);
 
 	/* Any shared keys to list */
-	ssd = seahorse_context_get_discovery (NULL);
+	ssd = seahorse_pgp_backend_get_discovery (NULL);
 	refresh_shared_keys (ssd, NULL, swidget);
 	g_signal_connect (ssd, "added", G_CALLBACK (refresh_shared_keys), swidget);
 	g_signal_connect (ssd, "removed", G_CALLBACK (refresh_shared_keys), swidget);
diff --git a/src/seahorse-windows.h b/pgp/seahorse-keyserver-search.h
similarity index 58%
rename from src/seahorse-windows.h
rename to pgp/seahorse-keyserver-search.h
index 92eb026..d298de9 100644
--- a/src/seahorse-windows.h
+++ b/pgp/seahorse-keyserver-search.h
@@ -1,8 +1,7 @@
 /*
  * Seahorse
  *
- * Copyright (C) 2003 Jacob Perkins
- * Copyright (C) 2005 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 General Public License as published by
@@ -18,20 +17,15 @@
  * Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
  */
 
-#ifndef __SEAHORSE_WINDOWS_H__
-#define __SEAHORSE_WINDOWS_H__
-
-#include "seahorse-context.h"
-
-GtkWindow*  seahorse_keyserver_search_show      (GtkWindow *parent);
-
-GtkWindow*  seahorse_keyserver_sync_show        (GList *keys,
-                                                 GtkWindow *parent);
+#ifndef __SEAHORSE_KEYSERVER_SEARCH_H__
+#define __SEAHORSE_KEYSERVER_SEARCH_H__
 
-void        seahorse_generate_select_show       (GtkWindow *parent);
+#include <gtk/gtk.h>
 
-void        seahorse_delete_show                (GList *keys);
+GtkWindow *  seahorse_keyserver_search_show      (GtkWindow *parent);
 
-#endif /* __SEAHORSE_WINDOWS_H__ */
+#endif
diff --git a/src/seahorse-keyserver-sync.c b/pgp/seahorse-keyserver-sync.c
similarity index 80%
rename from src/seahorse-keyserver-sync.c
rename to pgp/seahorse-keyserver-sync.c
index 5cf63ab..1bf90dc 100644
--- a/src/seahorse-keyserver-sync.c
+++ b/pgp/seahorse-keyserver-sync.c
@@ -24,16 +24,16 @@
 
 #include <glib/gi18n.h>
 
-#include "seahorse-context.h"
-#include "seahorse-keyserver-sync.h"
 #include "seahorse-object.h"
 #include "seahorse-progress.h"
 #include "seahorse-preferences.h"
 #include "seahorse-servers.h"
-#include "seahorse-transfer.h"
 #include "seahorse-util.h"
 #include "seahorse-widget.h"
-#include "seahorse-windows.h"
+
+#include "seahorse-keyserver-sync.h"
+#include "seahorse-pgp-backend.h"
+#include "seahorse-transfer.h"
 
 void            on_sync_ok_clicked                (GtkButton *button,
                                                    SeahorseWidget *swidget);
@@ -50,8 +50,7 @@ on_transfer_upload_complete (GObject *object,
 	GError *error = NULL;
 	gchar *publish_to;
 
-	if (!seahorse_context_transfer_objects_finish (SEAHORSE_CONTEXT (object),
-	                                               result, &error)) {
+	if (!seahorse_pgp_backend_transfer_finish (SEAHORSE_PGP_BACKEND (object), result, &error)) {
 		publish_to = g_settings_get_string (seahorse_context_settings (NULL),
 		                                    "server-publish-to");
 		seahorse_util_handle_error (&error, NULL,
@@ -85,12 +84,12 @@ G_MODULE_EXPORT void
 on_sync_ok_clicked (GtkButton *button, SeahorseWidget *swidget)
 {
     GList *keys;
-    
+
     keys = (GList*)g_object_get_data (G_OBJECT (swidget), "publish-keys");
     keys = g_list_copy (keys);
-    
+
     seahorse_widget_destroy (swidget);
-   
+
     seahorse_keyserver_sync (keys);
     g_list_free (keys);
 }
@@ -137,9 +136,9 @@ on_settings_publish_to_changed (GSettings *settings, const gchar *key, gpointer
 /**
  * seahorse_keyserver_sync_show
  * @keys: The keys to synchronize
- * 
+ *
  * Shows a synchronize window.
- * 
+ *
  * Returns the new window.
  **/
 GtkWindow*
@@ -150,17 +149,17 @@ seahorse_keyserver_sync_show (GList *keys, GtkWindow *parent)
     GtkWidget *w;
     guint n;
     gchar *t;
-    
+
     swidget = seahorse_widget_new_allow_multiple ("keyserver-sync", parent);
     g_return_val_if_fail (swidget != NULL, NULL);
-    
+
     win = GTK_WINDOW (seahorse_widget_get_widget (swidget, swidget->name));
-    
+
     /* The details message */
     n = g_list_length (keys);
-    t = g_strdup_printf (ngettext ("<b>%d key is selected for synchronizing</b>", 
+    t = g_strdup_printf (ngettext ("<b>%d key is selected for synchronizing</b>",
                                    "<b>%d keys are selected for synchronizing</b>", n), n);
-    
+
     w = GTK_WIDGET (seahorse_widget_get_widget (swidget, "detail-message"));
     g_return_val_if_fail (swidget != NULL, win);
     gtk_label_set_markup (GTK_LABEL (w), t);
@@ -173,19 +172,18 @@ seahorse_keyserver_sync_show (GList *keys, GtkWindow *parent)
 
     keys = g_list_copy (keys);
     g_return_val_if_fail (!keys || SEAHORSE_IS_OBJECT (keys->data), win);
-    g_object_set_data_full (G_OBJECT (swidget), "publish-keys", keys, 
+    g_object_set_data_full (G_OBJECT (swidget), "publish-keys", keys,
                             (GDestroyNotify)g_list_free);
-    
+
     return win;
 }
 
 void
 seahorse_keyserver_sync (GList *keys)
 {
-	SeahorseSource *source;
-	SeahorseSource *local_source;
+	SeahorseServerSource *source;
+	SeahorseGpgmeKeyring *keyring;
 	gchar *keyserver;
-	GList *k, *keyids = NULL;
 	GCancellable *cancellable;
 	gchar **keyservers;
 	guint i;
@@ -193,32 +191,21 @@ seahorse_keyserver_sync (GList *keys)
 	if (!keys)
 		return;
 
-	/* Build a keyid list */
-	for (k = keys; k != NULL; k = g_list_next (k))
-		keyids = g_list_prepend (keyids,
-		                         GUINT_TO_POINTER (seahorse_object_get_id (k->data)));
-
 	cancellable = g_cancellable_new ();
 
 	/* And now synchronizing keys from the servers */
 	keyservers = seahorse_servers_get_uris ();
 	for (i = 0; keyservers[i] != NULL; i++) {
-		source = seahorse_context_remote_source (seahorse_context_instance (),
-		                                         keyservers[i]);
+		source = seahorse_pgp_backend_lookup_remote (NULL, keyservers[i]);
 
 		/* This can happen if the URI scheme is not supported */
 		if (source == NULL)
 			continue;
 
-		local_source = seahorse_context_find_source (seahorse_context_instance (),
-		                                             seahorse_source_get_tag (source),
-		                                             SEAHORSE_LOCATION_LOCAL);
-
-		if (local_source) {
-			seahorse_transfer_async (source, local_source, keyids,
-			                         cancellable, on_transfer_download_complete,
-			                         g_object_ref (source));
-		}
+		keyring = seahorse_pgp_backend_get_default_keyring (NULL);
+		seahorse_transfer_async (SEAHORSE_SOURCE (source), SEAHORSE_SOURCE (keyring),
+		                         keys, cancellable, on_transfer_download_complete,
+		                         g_object_ref (source));
 	}
 
 	g_strfreev (keyservers);
@@ -227,23 +214,18 @@ seahorse_keyserver_sync (GList *keys)
 	keyserver = g_settings_get_string (seahorse_context_settings (NULL),
 	                                   "server-publish-to");
 	if (keyserver && keyserver[0]) {
-		source = seahorse_context_remote_source (seahorse_context_instance (),
-		                                         keyserver);
+		source = seahorse_pgp_backend_lookup_remote (NULL, keyserver);
 
 		/* This can happen if the URI scheme is not supported */
 		if (source != NULL) {
-
-			seahorse_context_transfer_objects_async (seahorse_context_instance (),
-			                                         keys, source, cancellable,
-			                                         on_transfer_upload_complete,
-			                                         g_object_ref (source));
+			seahorse_pgp_backend_transfer_async (NULL, keys, SEAHORSE_SOURCE (source),
+			                                     cancellable, on_transfer_upload_complete,
+			                                     g_object_ref (source));
 		}
 	}
 
 	g_free (keyserver);
 
-	g_list_free (keyids);
-
 	seahorse_progress_show (cancellable, _("Synchronizing keys..."), FALSE);
 	g_object_unref (cancellable);
 }
diff --git a/src/seahorse-keyserver-sync.h b/pgp/seahorse-keyserver-sync.h
similarity index 81%
rename from src/seahorse-keyserver-sync.h
rename to pgp/seahorse-keyserver-sync.h
index 9425f6d..1f966e9 100644
--- a/src/seahorse-keyserver-sync.h
+++ b/pgp/seahorse-keyserver-sync.h
@@ -22,6 +22,10 @@
 #ifndef __SEAHORSE_KEYSERVER_SYNC_H__
 #define __SEAHORSE_KEYSERVER_SYNC_H__
 
-void    seahorse_keyserver_sync (GList *keys);
+void        seahorse_keyserver_sync             (GList *keys);
+
+
+GtkWindow*  seahorse_keyserver_sync_show        (GList *keys,
+                                                 GtkWindow *parent);
 
 #endif
diff --git a/pgp/seahorse-ldap-source.c b/pgp/seahorse-ldap-source.c
index 0520a44..a672bbc 100644
--- a/pgp/seahorse-ldap-source.c
+++ b/pgp/seahorse-ldap-source.c
@@ -735,58 +735,22 @@ seahorse_ldap_source_connect_finish (SeahorseLDAPSource *source,
 	return ldap;
 }
 
-enum {
-	PROP_0,
-	PROP_SOURCE_TAG,
-	PROP_SOURCE_LOCATION
-};
-
 static void seahorse_source_iface (SeahorseSourceIface *iface);
 
 G_DEFINE_TYPE_EXTENDED (SeahorseLDAPSource, seahorse_ldap_source, SEAHORSE_TYPE_SERVER_SOURCE, 0,
                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_source_iface));
 
 static void 
-seahorse_ldap_source_init (SeahorseLDAPSource *lsrc)
+seahorse_ldap_source_init (SeahorseLDAPSource *self)
 {
 
 }
 
-static void 
-seahorse_ldap_source_get_property (GObject *object, guint prop_id, GValue *value,
-                                   GParamSpec *pspec)
-{
-    switch (prop_id) {
-    case PROP_SOURCE_TAG:
-        g_value_set_uint (value, SEAHORSE_PGP);
-        break;
-    case PROP_SOURCE_LOCATION:
-        g_value_set_enum (value, SEAHORSE_LOCATION_REMOTE);
-        break;
-    };        
-}
-
-/* Initialize the basic class stuff */
-static void
-seahorse_ldap_source_class_init (SeahorseLDAPSourceClass *klass)
-{
-	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-	gobject_class->get_property = seahorse_ldap_source_get_property;
-
-	g_object_class_override_property (gobject_class, PROP_SOURCE_TAG, "source-tag");
-	g_object_class_override_property (gobject_class, PROP_SOURCE_LOCATION, "source-location");
-
-	seahorse_registry_register_type (NULL, SEAHORSE_TYPE_LDAP_SOURCE, "source", "remote", SEAHORSE_PGP_STR, NULL);
-	seahorse_servers_register_type ("ldap", _("LDAP Key Server"), seahorse_ldap_is_valid_uri);
-	seahorse_registry_register_function (NULL, seahorse_pgp_key_canonize_id, "canonize", SEAHORSE_PGP_STR, NULL);
-}
-
 typedef struct {
 	GCancellable *cancellable;
 	gchar *filter;
 	LDAP *ldap;
-	GList *results;
+	GcrSimpleCollection *results;
 } source_search_closure;
 
 static void
@@ -794,7 +758,7 @@ source_search_free (gpointer data)
 {
 	source_search_closure *closure = data;
 	g_clear_object (&closure->cancellable);
-	g_list_free (closure->results);
+	g_clear_object (&closure->results);
 	g_free (closure->filter);
 	if (closure->ldap)
 		ldap_unbind_ext (closure->ldap, NULL, NULL);
@@ -813,34 +777,13 @@ static const char *PGP_ATTRIBUTES[] = {
 	NULL
 };
 
-static void
-add_key (SeahorseLDAPSource *ssrc, SeahorsePgpKey *key)
-{
-	SeahorseObject *prev;
-	GQuark keyid;
-
-	keyid = seahorse_pgp_key_canonize_id (seahorse_pgp_key_get_keyid (key));
-	prev = seahorse_context_get_object (SCTX_APP (), SEAHORSE_SOURCE (ssrc), keyid);
-
-	if (prev != NULL) {
-		g_return_if_fail (SEAHORSE_IS_PGP_KEY (prev));
-		seahorse_pgp_key_set_uids (SEAHORSE_PGP_KEY (prev), seahorse_pgp_key_get_uids (key));
-		seahorse_pgp_key_set_subkeys (SEAHORSE_PGP_KEY (prev), seahorse_pgp_key_get_subkeys (key));
-		return;
-	}
-
-	/* Add to context */
-	seahorse_object_set_source (SEAHORSE_OBJECT (key), SEAHORSE_SOURCE (ssrc));
-	seahorse_context_add_object (SCTX_APP (), SEAHORSE_OBJECT (key));
-}
-
 /* Add a key to the key source from an LDAP entry */
-static SeahorseObject *
+static void
 search_parse_key_from_ldap_entry (SeahorseLDAPSource *self,
+                                  GcrSimpleCollection *results,
                                   LDAP *ldap,
                                   LDAPMessage *res)
 {
-	SeahorseObject *result = NULL;
 	const gchar *algo;
 	long int timestamp;
 	long int expires;
@@ -850,7 +793,7 @@ search_parse_key_from_ldap_entry (SeahorseLDAPSource *self,
 	gboolean disabled;
 	int length;
 
-	g_return_val_if_fail (ldap_msgtype (res) == LDAP_RES_SEARCH_ENTRY, NULL);
+	g_return_if_fail (ldap_msgtype (res) == LDAP_RES_SEARCH_ENTRY);
 
 	fpr = get_string_attribute (ldap, res, "pgpcertid");
 	uidstr = get_string_attribute (ldap, res, "pgpuserid");
@@ -900,18 +843,15 @@ 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, "location", SEAHORSE_LOCATION_REMOTE,
-		              "flags", flags, NULL);
+		g_object_set (key, "flags", flags, NULL);
 
-		add_key (self, key);
+		seahorse_pgp_key_realize (key);
+		gcr_simple_collection_add (results, G_OBJECT (key));
 		g_object_unref (key);
-		result = SEAHORSE_OBJECT (key);
 	}
 
 	g_free (fpr);
 	g_free (uidstr);
-
-	return result;
 }
 
 static gboolean
@@ -922,7 +862,6 @@ on_search_search_completed (LDAPMessage *result,
 	source_search_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (g_async_result_get_source_object (user_data));
 	GError *error = NULL;
-	SeahorseObject *key;
 	char *message;
 	int code;
 	int type;
@@ -939,9 +878,8 @@ on_search_search_completed (LDAPMessage *result,
 			dump_ldap_entry (closure->ldap, result);
 #endif
 
-		key = search_parse_key_from_ldap_entry (self, closure->ldap, result);
-		if (key != NULL)
-			closure->results = g_list_prepend (closure->results, key);
+		search_parse_key_from_ldap_entry (self, closure->results,
+		                                  closure->ldap, result);
 		return TRUE; /* keep calling this callback */
 
 	/* All entries done */
@@ -1020,8 +958,9 @@ on_search_connect_completed (GObject *source,
 
 
 static void
-seahorse_ldap_source_search_async (SeahorseSource *source,
+seahorse_ldap_source_search_async (SeahorseServerSource *source,
                                    const gchar *match,
+                                   GcrSimpleCollection *results,
                                    GCancellable *cancellable,
                                    GAsyncReadyCallback callback,
                                    gpointer user_data)
@@ -1035,6 +974,7 @@ seahorse_ldap_source_search_async (SeahorseSource *source,
 	                                 seahorse_ldap_source_search_async);
 	closure = g_new0 (source_search_closure, 1);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+	closure->results = g_object_ref (results);
 	text = escape_ldap_value (match);
 	closure->filter = g_strdup_printf ("(pgpuserid=*%s*)", text);
 	g_free (text);
@@ -1049,24 +989,18 @@ seahorse_ldap_source_search_async (SeahorseSource *source,
 	g_object_unref (res);
 }
 
-static GList *
-seahorse_ldap_source_search_finish (SeahorseSource *source,
+static gboolean
+seahorse_ldap_source_search_finish (SeahorseServerSource *source,
                                     GAsyncResult *result,
                                     GError **error)
 {
-	source_search_closure *closure;
-	GList *keys;
-
 	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
-	                      seahorse_ldap_source_search_async), NULL);
+	                      seahorse_ldap_source_search_async), FALSE);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
-		return NULL;
+		return FALSE;
 
-	closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
-	keys = closure->results;
-	closure->results = NULL;
-	return keys;
+	return TRUE;
 }
 
 typedef struct {
@@ -1441,12 +1375,12 @@ on_export_connect_completed (GObject *source,
 }
 
 static void
-seahorse_ldap_source_export_raw_async (SeahorseSource *source,
-                                       GList *keyids,
-                                       GOutputStream *output,
-                                       GCancellable *cancellable,
-                                       GAsyncReadyCallback callback,
-                                       gpointer user_data)
+seahorse_ldap_source_export_async (SeahorseServerSource *source,
+                                   GList *keyids,
+                                   GOutputStream *output,
+                                   GCancellable *cancellable,
+                                   GAsyncReadyCallback callback,
+                                   gpointer user_data)
 {
 	SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (source);
 	source_export_closure *closure;
@@ -1455,13 +1389,13 @@ seahorse_ldap_source_export_raw_async (SeahorseSource *source,
 	GList *l;
 
 	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
-	                                 seahorse_ldap_source_export_raw_async);
+	                                 seahorse_ldap_source_export_async);
 	closure = g_new0 (source_export_closure, 1);
 	closure->output = g_object_ref (output);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
 	closure->fingerprints = g_ptr_array_new_with_free_func (g_free);
 	for (l = keyids; l; l = g_list_next (l)) {
-		fingerprint = g_strdup (seahorse_pgp_key_calc_rawid (GPOINTER_TO_UINT (l->data)));
+		fingerprint = g_strdup (l->data);
 		g_ptr_array_add (closure->fingerprints, fingerprint);
 		seahorse_progress_prep (closure->cancellable, fingerprint, NULL);
 	}
@@ -1476,14 +1410,14 @@ seahorse_ldap_source_export_raw_async (SeahorseSource *source,
 }
 
 static GOutputStream *
-seahorse_ldap_source_export_raw_finish (SeahorseSource *source,
-                                        GAsyncResult *result,
-                                        GError **error)
+seahorse_ldap_source_export_finish (SeahorseServerSource *source,
+                                    GAsyncResult *result,
+                                    GError **error)
 {
 	source_export_closure *closure;
 
 	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
-	                      seahorse_ldap_source_export_raw_async), FALSE);
+	                      seahorse_ldap_source_export_async), FALSE);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
 		return FALSE;
@@ -1495,12 +1429,23 @@ seahorse_ldap_source_export_raw_finish (SeahorseSource *source,
 static void 
 seahorse_source_iface (SeahorseSourceIface *iface)
 {
-	iface->search_async = seahorse_ldap_source_search_async;
-	iface->search_finish = seahorse_ldap_source_search_finish;
 	iface->import_async = seahorse_ldap_source_import_async;
 	iface->import_finish = seahorse_ldap_source_import_finish;
-	iface->export_raw_async = seahorse_ldap_source_export_raw_async;
-	iface->export_raw_finish = seahorse_ldap_source_export_raw_finish;
+}
+
+/* Initialize the basic class stuff */
+static void
+seahorse_ldap_source_class_init (SeahorseLDAPSourceClass *klass)
+{
+	SeahorseServerSourceClass *server_class = SEAHORSE_SERVER_SOURCE_CLASS (klass);
+
+	server_class->search_async = seahorse_ldap_source_search_async;
+	server_class->search_finish = seahorse_ldap_source_search_finish;
+	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-ldap-source.h b/pgp/seahorse-ldap-source.h
index 27d7f0a..f81c963 100644
--- a/pgp/seahorse-ldap-source.h
+++ b/pgp/seahorse-ldap-source.h
@@ -45,7 +45,7 @@ typedef struct _SeahorseLDAPSourceClass SeahorseLDAPSourceClass;
 
 struct _SeahorseLDAPSource {
     SeahorseServerSource parent;
-    
+
     /*< private >*/
 };
 
diff --git a/pgp/seahorse-pgp-backend.c b/pgp/seahorse-pgp-backend.c
new file mode 100644
index 0000000..0e6cfda
--- /dev/null
+++ b/pgp/seahorse-pgp-backend.c
@@ -0,0 +1,646 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include "seahorse-gpgme-dialogs.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"
+
+#include "seahorse-progress.h"
+#include "seahorse-servers.h"
+#include "seahorse-util.h"
+
+#include <gnome-keyring.h>
+
+#include <string.h>
+
+static SeahorsePgpBackend *pgp_backend = NULL;
+
+struct _SeahorsePgpBackend {
+	GObject parent;
+	SeahorseGpgmeKeyring *keyring;
+	SeahorseDiscovery *discovery;
+	SeahorseUnknownSource *unknown;
+	GHashTable *remotes;
+};
+
+struct _SeahorsePgpBackendClass {
+	GObjectClass parent_class;
+};
+
+static void         seahorse_pgp_backend_collection_init  (GcrCollectionIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (SeahorsePgpBackend, seahorse_pgp_backend, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_pgp_backend_collection_init);
+);
+
+static void
+seahorse_pgp_backend_init (SeahorsePgpBackend *self)
+{
+	g_return_if_fail (pgp_backend == NULL);
+	pgp_backend = 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));
+
+	seahorse_gpgme_generate_register ();
+}
+
+#ifdef WITH_KEYSERVER
+
+static void
+on_settings_keyservers_changed (GSettings *settings,
+                                gchar *key,
+                                gpointer user_data)
+{
+	SeahorsePgpBackend *self = SEAHORSE_PGP_BACKEND (user_data);
+	SeahorseServerSource *source;
+	gchar **keyservers;
+	GHashTable *check;
+	const gchar *uri;
+	GHashTableIter iter;
+	guint i;
+
+	check = g_hash_table_new (g_str_hash, g_str_equal);
+	g_hash_table_iter_init (&iter, self->remotes);
+	while (g_hash_table_iter_next (&iter, (gpointer*)&uri, (gpointer*)&source))
+		g_hash_table_replace (check, (gpointer)uri, source);
+
+	/* Load and strip names from keyserver list */
+	keyservers = seahorse_servers_get_uris ();
+
+	for (i = 0; keyservers[i] != NULL; i++) {
+		uri = keyservers[i];
+
+		/* If we don't have a keysource then add it */
+		if (!g_hash_table_lookup (self->remotes, uri)) {
+			source = seahorse_server_source_new (uri);
+			if (source != NULL) {
+				seahorse_pgp_backend_add_remote (self, uri, source);
+				g_object_unref (source);
+			}
+		}
+
+		/* Mark this one as present */
+		g_hash_table_remove (check, uri);
+	}
+
+	/* Now remove any extras */
+	g_hash_table_iter_init (&iter, check);
+	while (g_hash_table_iter_next (&iter, (gpointer*)&uri, NULL))
+		seahorse_pgp_backend_remove_remote (self, uri);
+
+	g_hash_table_destroy (check);
+	g_strfreev (keyservers);
+}
+
+#endif /* WITH_KEYSERVER */
+
+static void
+seahorse_pgp_backend_constructed (GObject *obj)
+{
+	SeahorsePgpBackend *self = SEAHORSE_PGP_BACKEND (obj);
+
+	G_OBJECT_CLASS (seahorse_pgp_backend_parent_class)->constructed (obj);
+
+	self->keyring = seahorse_gpgme_keyring_new ();
+	seahorse_gpgme_keyring_load_async (self->keyring, NULL, NULL, NULL);
+
+	self->discovery = seahorse_discovery_new ();
+	self->unknown = seahorse_unknown_source_new ();
+
+#ifdef WITH_KEYSERVER
+	g_signal_connect (seahorse_context_pgp_settings (NULL), "changed::keyservers",
+	                  G_CALLBACK (on_settings_keyservers_changed), self);
+
+	/* Initial loading */
+	on_settings_keyservers_changed (seahorse_context_pgp_settings (NULL), "keyservers", self);
+#endif
+}
+
+static void
+seahorse_pgp_backend_finalize (GObject *obj)
+{
+	SeahorsePgpBackend *self = SEAHORSE_PGP_BACKEND (obj);
+
+#ifdef WITH_KEYSERVER
+	g_signal_handlers_disconnect_by_func (seahorse_context_pgp_settings (NULL),
+	                                      on_settings_keyservers_changed, self);
+#endif
+
+	g_clear_object (&self->keyring);
+	g_clear_object (&self->discovery);
+	g_clear_object (&self->unknown);
+	g_hash_table_destroy (self->remotes);
+	pgp_backend = NULL;
+
+	G_OBJECT_CLASS (seahorse_pgp_backend_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_pgp_backend_class_init (SeahorsePgpBackendClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+	gobject_class->constructed = seahorse_pgp_backend_constructed;
+	gobject_class->finalize = seahorse_pgp_backend_finalize;
+}
+
+static guint
+seahorse_pgp_backend_get_length (GcrCollection *collection)
+{
+	return 1;
+}
+
+static GList *
+seahorse_pgp_backend_get_objects (GcrCollection *collection)
+{
+	SeahorsePgpBackend *self = SEAHORSE_PGP_BACKEND (collection);
+	return g_list_append (NULL, self->keyring);
+}
+
+static gboolean
+seahorse_pgp_backend_contains (GcrCollection *collection,
+                               GObject *object)
+{
+	SeahorsePgpBackend *self = SEAHORSE_PGP_BACKEND (collection);
+	return G_OBJECT (self->keyring) == object;
+}
+
+static void
+seahorse_pgp_backend_collection_init (GcrCollectionIface *iface)
+{
+	iface->contains = seahorse_pgp_backend_contains;
+	iface->get_length = seahorse_pgp_backend_get_length;
+	iface->get_objects = seahorse_pgp_backend_get_objects;
+}
+
+SeahorsePgpBackend *
+seahorse_pgp_backend_get (void)
+{
+	g_return_val_if_fail (pgp_backend, NULL);
+	return pgp_backend;
+}
+
+GcrCollection *
+seahorse_pgp_backend_initialize (void)
+{
+	SeahorsePgpBackend *self;
+
+	self = g_object_new (SEAHORSE_TYPE_PGP_BACKEND, NULL);
+
+	return GCR_COLLECTION (self);
+}
+
+SeahorseGpgmeKeyring *
+seahorse_pgp_backend_get_default_keyring (SeahorsePgpBackend *self)
+{
+	self = self ? self : seahorse_pgp_backend_get ();
+	g_return_val_if_fail (SEAHORSE_IS_PGP_BACKEND (self), NULL);
+	g_return_val_if_fail (self->keyring, NULL);
+	return self->keyring;
+}
+
+SeahorsePgpKey *
+seahorse_pgp_backend_get_default_key (SeahorsePgpBackend *self)
+{
+	SeahorsePgpKey *key = NULL;
+	GSettings *settings;
+	const gchar *keyid;
+	gchar *value;
+
+	self = self ? self : seahorse_pgp_backend_get ();
+	g_return_val_if_fail (SEAHORSE_IS_PGP_BACKEND (self), NULL);
+
+	settings = seahorse_context_pgp_settings (NULL);
+	if (settings != NULL) {
+		value = g_settings_get_string (settings, "default-key");
+		if (value != NULL && value[0]) {
+			if (g_str_has_prefix (value, "openpgp:"))
+				keyid = value + strlen ("openpgp:");
+			else
+				keyid = value;
+			key = SEAHORSE_PGP_KEY (seahorse_gpgme_keyring_lookup (self->keyring, keyid));
+		}
+		g_free (value);
+	}
+
+	return key;
+}
+
+SeahorseDiscovery *
+seahorse_pgp_backend_get_discovery (SeahorsePgpBackend *self)
+{
+	self = self ? self : seahorse_pgp_backend_get ();
+	g_return_val_if_fail (SEAHORSE_IS_PGP_BACKEND (self), NULL);
+	g_return_val_if_fail (self->discovery, NULL);
+	return self->discovery;
+}
+
+SeahorseServerSource *
+seahorse_pgp_backend_lookup_remote (SeahorsePgpBackend *self,
+                                    const gchar *uri)
+{
+	self = self ? self : seahorse_pgp_backend_get ();
+	g_return_val_if_fail (SEAHORSE_IS_PGP_BACKEND (self), NULL);
+
+	return g_hash_table_lookup (self->remotes, uri);
+}
+
+void
+seahorse_pgp_backend_add_remote (SeahorsePgpBackend *self,
+                                 const gchar *uri,
+                                 SeahorseServerSource *source)
+{
+	self = self ? self : seahorse_pgp_backend_get ();
+	g_return_if_fail (SEAHORSE_IS_PGP_BACKEND (self));
+	g_return_if_fail (uri != NULL);
+	g_return_if_fail (SEAHORSE_IS_SERVER_SOURCE (source));
+	g_return_if_fail (g_hash_table_lookup (self->remotes, uri) == NULL);
+
+	g_hash_table_insert (self->remotes, g_strdup (uri), g_object_ref (source));
+}
+
+void
+seahorse_pgp_backend_remove_remote (SeahorsePgpBackend *self,
+                                    const gchar *uri)
+{
+	self = self ? self : seahorse_pgp_backend_get ();
+	g_return_if_fail (SEAHORSE_IS_PGP_BACKEND (self));
+	g_return_if_fail (uri != NULL);
+
+	g_hash_table_remove (self->remotes, uri);
+}
+
+typedef struct {
+	GCancellable *cancellable;
+	gint num_searches;
+	GList *objects;
+} search_remote_closure;
+
+static void
+search_remote_closure_free (gpointer user_data)
+{
+	search_remote_closure *closure = user_data;
+	g_clear_object (&closure->cancellable);
+	g_list_free (closure->objects);
+	g_free (closure);
+}
+
+static void
+on_source_search_ready (GObject *source,
+                        GAsyncResult *result,
+                        gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	search_remote_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	GError *error = NULL;
+
+	g_return_if_fail (closure->num_searches > 0);
+
+	if (!seahorse_server_source_search_finish (SEAHORSE_SERVER_SOURCE (source),
+	                                           result, &error))
+		g_simple_async_result_take_error (res, error);
+
+	closure->num_searches--;
+	seahorse_progress_end (closure->cancellable, GINT_TO_POINTER (closure->num_searches));
+
+	if (closure->num_searches == 0)
+		g_simple_async_result_complete (res);
+
+	g_object_unref (user_data);
+}
+
+void
+seahorse_pgp_backend_search_remote_async (SeahorsePgpBackend *self,
+                                          const gchar *search,
+                                          GcrSimpleCollection *results,
+                                          GCancellable *cancellable,
+                                          GAsyncReadyCallback callback,
+                                          gpointer user_data)
+{
+	search_remote_closure *closure;
+	GSimpleAsyncResult *res;
+	SeahorseServerSource *source;
+	GHashTable *servers = NULL;
+	GHashTableIter iter;
+	gchar **names;
+	gchar *uri;
+	guint i;
+
+	self = self ? self : seahorse_pgp_backend_get ();
+	g_return_if_fail (SEAHORSE_IS_PGP_BACKEND (self));
+
+	/* Get a list of all selected key servers */
+	names = g_settings_get_strv (seahorse_context_settings (NULL), "last-search-servers");
+	if (names != NULL && names[0] != NULL) {
+		servers = g_hash_table_new (g_str_hash, g_str_equal);
+		for (i = 0; names[i] != NULL; i++)
+			g_hash_table_insert (servers, names[i], GINT_TO_POINTER (TRUE));
+		g_strfreev (names);
+	}
+
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+	                                 seahorse_pgp_backend_search_remote_async);
+	closure = g_new0 (search_remote_closure, 1);
+	g_simple_async_result_set_op_res_gpointer (res, closure,
+	                                           search_remote_closure_free);
+	if (cancellable)
+		closure->cancellable = g_object_ref (cancellable);
+
+	g_hash_table_iter_init (&iter, self->remotes);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&source)) {
+		if (servers) {
+			g_object_get (source, "uri", &uri, NULL);
+			if (!g_hash_table_lookup (servers, uri)) {
+				g_free (uri);
+				continue;
+			}
+			g_free (uri);
+		}
+
+		seahorse_progress_prep_and_begin (closure->cancellable, GINT_TO_POINTER (closure->num_searches), NULL);
+		seahorse_server_source_search_async (source, search, results, closure->cancellable,
+		                                     on_source_search_ready, g_object_ref (res));
+		closure->num_searches++;
+	}
+
+	if (closure->num_searches == 0)
+		g_simple_async_result_complete_in_idle (res);
+
+	g_object_unref (res);
+}
+
+gboolean
+seahorse_pgp_backend_search_remote_finish (SeahorsePgpBackend *self,
+                                           GAsyncResult *result,
+                                           GError **error)
+{
+	GSimpleAsyncResult *res;
+
+	self = self ? self : seahorse_pgp_backend_get ();
+	g_return_val_if_fail (SEAHORSE_IS_PGP_BACKEND (self), FALSE);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      seahorse_pgp_backend_search_remote_async), FALSE);
+
+	res = G_SIMPLE_ASYNC_RESULT (result);
+
+	if (g_simple_async_result_propagate_error (res, error))
+		return FALSE;
+
+	return TRUE;
+}
+
+typedef struct {
+	GCancellable *cancellable;
+	gint num_transfers;
+} transfer_closure;
+
+static void
+transfer_closure_free (gpointer user_data)
+{
+	transfer_closure *closure = user_data;
+	g_clear_object (&closure->cancellable);
+	g_free (closure);
+}
+
+static void
+on_source_transfer_ready (GObject *source,
+                          GAsyncResult *result,
+                          gpointer user_data)
+{
+	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+	transfer_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+	GError *error = NULL;
+
+	g_return_if_fail (closure->num_transfers > 0);
+
+	seahorse_transfer_finish (result, &error);
+	if (error != NULL)
+		g_simple_async_result_take_error (res, error);
+
+	closure->num_transfers--;
+	seahorse_progress_end (closure->cancellable, GINT_TO_POINTER (closure->num_transfers));
+
+	if (closure->num_transfers == 0) {
+		g_simple_async_result_complete (res);
+	}
+
+	g_object_unref (user_data);
+}
+
+void
+seahorse_pgp_backend_transfer_async (SeahorsePgpBackend *self,
+                                     GList *keys,
+                                     SeahorseSource *to,
+                                     GCancellable *cancellable,
+                                     GAsyncReadyCallback callback,
+                                     gpointer user_data)
+{
+	transfer_closure *closure;
+	SeahorseObject *object;
+	GSimpleAsyncResult *res;
+	SeahorseSource *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));
+
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+	                                 seahorse_pgp_backend_transfer_async);
+	closure = g_new0 (transfer_closure, 1);
+	g_simple_async_result_set_op_res_gpointer (res, closure,
+	                                           transfer_closure_free);
+	if (cancellable)
+		closure->cancellable = g_object_ref (cancellable);
+
+	keys = g_list_copy (keys);
+
+	/* Sort by key source */
+	keys = seahorse_util_objects_sort (keys);
+
+	while (keys) {
+
+		/* break off one set (same keysource) */
+		next = seahorse_util_objects_splice (keys);
+
+		g_assert (SEAHORSE_IS_OBJECT (keys->data));
+		object = SEAHORSE_OBJECT (keys->data);
+
+		/* Export from this key source */
+		from = seahorse_object_get_source (object);
+		g_return_if_fail (from != NULL);
+
+		if (from != to) {
+			/* Start a new transfer operation between the two sources */
+			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));
+			closure->num_transfers++;
+		}
+
+		g_list_free (keys);
+		keys = next;
+	}
+
+	if (closure->num_transfers == 0)
+		g_simple_async_result_complete_in_idle (res);
+
+	g_object_unref (res);
+}
+
+gboolean
+seahorse_pgp_backend_transfer_finish (SeahorsePgpBackend *self,
+                                      GAsyncResult *result,
+                                      GError **error)
+{
+	GSimpleAsyncResult *res;
+
+	self = self ? self : seahorse_pgp_backend_get ();
+	g_return_val_if_fail (SEAHORSE_IS_PGP_BACKEND (self), FALSE);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      seahorse_pgp_backend_transfer_async), FALSE);
+
+	res = G_SIMPLE_ASYNC_RESULT (result);
+
+	if (g_simple_async_result_propagate_error (res, error))
+		return FALSE;
+
+	return TRUE;
+}
+
+void
+seahorse_pgp_backend_retrieve_async (SeahorsePgpBackend *self,
+                                     GList *keyids,
+                                     SeahorseSource *to,
+                                     GCancellable *cancellable,
+                                     GAsyncReadyCallback callback,
+                                     gpointer user_data)
+{
+	transfer_closure *closure;
+	GSimpleAsyncResult *res;
+	SeahorseSource *source;
+	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));
+
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+	                                 seahorse_pgp_backend_retrieve_async);
+	closure = g_new0 (transfer_closure, 1);
+	g_simple_async_result_set_op_res_gpointer (res, closure,
+	                                           transfer_closure_free);
+	if (cancellable)
+		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 */
+		seahorse_progress_prep_and_begin (cancellable, GINT_TO_POINTER (closure->num_transfers), NULL);
+		seahorse_transfer_async (source, to, keyids, cancellable,
+		                         on_source_transfer_ready, g_object_ref (res));
+		closure->num_transfers++;
+	}
+
+	if (closure->num_transfers == 0)
+		g_simple_async_result_complete_in_idle (res);
+
+	g_object_unref (res);
+}
+
+gboolean
+seahorse_pgp_backend_retrieve_finish (SeahorsePgpBackend *self,
+                                      GAsyncResult *result,
+                                      GError **error)
+{
+	GSimpleAsyncResult *res;
+
+	self = self ? self : seahorse_pgp_backend_get ();
+	g_return_val_if_fail (SEAHORSE_IS_PGP_BACKEND (self), FALSE);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+	                      seahorse_pgp_backend_retrieve_async), FALSE);
+
+	res = G_SIMPLE_ASYNC_RESULT (result);
+
+	if (g_simple_async_result_propagate_error (res, error))
+		return FALSE;
+
+	return TRUE;
+}
+
+GList *
+seahorse_pgp_backend_discover_keys (SeahorsePgpBackend *self,
+                                    GList *keyids,
+                                    GCancellable *cancellable)
+{
+	GList *robjects = NULL;
+	const gchar *keyid;
+	GList *todiscover = NULL;
+	SeahorseGpgmeKey *key;
+	SeahorseObject *object;
+	GList *l;
+
+	self = self ? self : seahorse_pgp_backend_get ();
+	g_return_val_if_fail (SEAHORSE_IS_PGP_BACKEND (self), NULL);
+
+	/* Check all the ids */
+	for (l = keyids; l != NULL; l = g_list_next (l)) {
+		keyid = l->data;
+
+		/* Do we know about this object? */
+		key = seahorse_gpgme_keyring_lookup (self->keyring, keyid);
+
+		/* No such object anywhere, discover it */
+		if (key == NULL) {
+			todiscover = g_list_prepend (todiscover, (gpointer)keyid);
+			continue;
+		}
+
+		/* Our return value */
+		robjects = g_list_prepend (robjects, key);
+	}
+
+	/* 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),
+		                                     cancellable, NULL, NULL);
+	}
+
+	/* Add unknown objects for all these */
+	for (l = todiscover; l != NULL; l = g_list_next (l)) {
+		object = seahorse_unknown_source_add_object (self->unknown, keyid, cancellable);
+		robjects = g_list_prepend (robjects, object);
+	}
+
+	g_list_free (todiscover);
+
+	return robjects;
+}
diff --git a/pgp/seahorse-pgp-backend.h b/pgp/seahorse-pgp-backend.h
new file mode 100644
index 0000000..8923bcc
--- /dev/null
+++ b/pgp/seahorse-pgp-backend.h
@@ -0,0 +1,110 @@
+/*
+ * Seahorse
+ *
+ * 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.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#ifndef SEAHORSE_PGP_BACKEND_H_
+#define SEAHORSE_PGP_BACKEND_H_
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gcr/gcr.h>
+
+#include "seahorse-discovery.h"
+#include "seahorse-gpgme-keyring.h"
+#include "seahorse-pgp-key.h"
+#include "seahorse-server-source.h"
+
+G_BEGIN_DECLS
+
+#define SEAHORSE_TYPE_PGP_BACKEND            (seahorse_pgp_backend_get_type ())
+#define SEAHORSE_PGP_BACKEND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PGP_BACKEND, SeahorsePgpBackend))
+#define SEAHORSE_PGP_BACKEND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_PGP_BACKEND, SeahorsePgpBackendClass))
+#define SEAHORSE_IS_PGP_BACKEND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_PGP_BACKEND))
+#define SEAHORSE_IS_PGP_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_PGP_BACKEND))
+#define SEAHORSE_PGP_BACKEND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_PGP_BACKEND, SeahorsePgpBackendClass))
+
+typedef struct _SeahorsePgpBackend SeahorsePgpBackend;
+typedef struct _SeahorsePgpBackendClass SeahorsePgpBackendClass;
+
+GType                  seahorse_pgp_backend_get_type             (void) G_GNUC_CONST;
+
+GcrCollection *        seahorse_pgp_backend_initialize           (void);
+
+SeahorsePgpBackend *   seahorse_pgp_backend_get                  (void);
+
+SeahorseGpgmeKeyring * seahorse_pgp_backend_get_default_keyring  (SeahorsePgpBackend *self);
+
+SeahorsePgpKey *       seahorse_pgp_backend_get_default_key      (SeahorsePgpBackend *self);
+
+SeahorseDiscovery *    seahorse_pgp_backend_get_discovery        (SeahorsePgpBackend *self);
+
+SeahorseServerSource * seahorse_pgp_backend_lookup_remote        (SeahorsePgpBackend *self,
+                                                                  const gchar *uri);
+
+void                   seahorse_pgp_backend_add_remote           (SeahorsePgpBackend *self,
+                                                                  const gchar *uri,
+                                                                  SeahorseServerSource *source);
+
+void                   seahorse_pgp_backend_remove_remote        (SeahorsePgpBackend *self,
+                                                                  const gchar *uri);
+
+void                   seahorse_pgp_backend_search_remote_async  (SeahorsePgpBackend *self,
+                                                                  const gchar *search,
+                                                                  GcrSimpleCollection *results,
+                                                                  GCancellable *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer user_data);
+
+gboolean               seahorse_pgp_backend_search_remote_finish (SeahorsePgpBackend *self,
+                                                                  GAsyncResult *result,
+                                                                  GError **error);
+
+void                   seahorse_pgp_backend_transfer_async       (SeahorsePgpBackend *self,
+                                                                  GList *keys,
+                                                                  SeahorseSource *to,
+                                                                  GCancellable *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer user_data);
+
+gboolean               seahorse_pgp_backend_transfer_finish      (SeahorsePgpBackend *self,
+                                                                  GAsyncResult *result,
+                                                                  GError **error);
+
+void                   seahorse_pgp_backend_retrieve_async       (SeahorsePgpBackend *self,
+                                                                  GList *keyids,
+                                                                  SeahorseSource *to,
+                                                                  GCancellable *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer user_data);
+
+gboolean               seahorse_pgp_backend_retrieve_finish      (SeahorsePgpBackend *self,
+                                                                  GAsyncResult *result,
+                                                                  GError **error);
+
+GList*                 seahorse_pgp_backend_discover_keys        (SeahorsePgpBackend *self,
+                                                                  GList *keyids,
+                                                                  GCancellable *cancellable);
+
+G_END_DECLS
+
+#endif /*SEAHORSE_PGP_BACKEND_H_*/
diff --git a/pgp/seahorse-pgp-commands.c b/pgp/seahorse-pgp-commands.c
index 1df23c2..f7511be 100644
--- a/pgp/seahorse-pgp-commands.c
+++ b/pgp/seahorse-pgp-commands.c
@@ -28,9 +28,11 @@
 #include "seahorse-gpgme-key.h"
 #include "seahorse-gpgme-key-op.h"
 #include "seahorse-gpgme-uid.h"
-#include "seahorse-pgp.h"
+#include "seahorse-pgp-backend.h"
 #include "seahorse-pgp-commands.h"
 #include "seahorse-pgp-dialogs.h"
+#include "seahorse-keyserver-search.h"
+#include "seahorse-keyserver-sync.h"
 
 #include "seahorse-object.h"
 #include "seahorse-registry.h"
@@ -49,11 +51,17 @@ G_DEFINE_TYPE (SeahorsePgpCommands, seahorse_pgp_commands, SEAHORSE_TYPE_COMMAND
 static const char* UI_DEFINITION = ""\
 "<ui>"\
 "	<menubar>"\
-"		<menu name='File' action='file-menu'> "\
+"		<menu name='File' action='file-menu'>"\
 "			<placeholder name='FileCommands'>"\
 "				<menuitem action='key-sign'/>"\
 "			</placeholder>"\
 "		</menu>"\
+"		<placeholder name='RemoteMenu'>"\
+"			<menu name='Remote' action='remote-menu'>"\
+"				<menuitem action='remote-find'/>"\
+"				<menuitem action='remote-sync'/>"\
+"			</menu>"\
+"		</placeholder>"\
 "	</menubar>"\
 "	<toolbar name='MainToolbar'>"\
 "		<placeholder name='ToolItems'>"\
@@ -65,8 +73,10 @@ static const char* UI_DEFINITION = ""\
 "	</popup>"\
 "</ui>";
 
-static SeahorsePredicate actions_predicate = { 0 };
-static SeahorsePredicate commands_predicate = { 0 };
+static SeahorsePredicate actions_key_predicate = { 0 };
+static SeahorsePredicate actions_uid_predicate = { 0 };
+static SeahorsePredicate commands_key_predicate = { 0 };
+static SeahorsePredicate commands_uid_predicate = { 0 };
 
 /* -----------------------------------------------------------------------------
  * INTERNAL 
@@ -83,10 +93,13 @@ on_key_sign (GtkAction* action, SeahorsePgpCommands* self)
 	g_return_if_fail (GTK_IS_ACTION (action));
 	
 	view = seahorse_commands_get_view (SEAHORSE_COMMANDS (self));
-	keys = seahorse_view_get_selected_matching (view, &actions_predicate);
-	
-	if (keys == NULL)
-		return;
+	keys = seahorse_view_get_selected_matching (view, &actions_key_predicate);
+
+	if (keys == NULL) {
+		keys = seahorse_view_get_selected_matching (view, &actions_uid_predicate);
+		if (keys == NULL)
+			return;
+	}
 
 	/* Indicate what we're actually going to operate on */
 	seahorse_view_set_selected (view, keys->data);
@@ -100,8 +113,40 @@ on_key_sign (GtkAction* action, SeahorsePgpCommands* self)
 	}
 }
 
+static void
+on_remote_find (GtkAction* action,
+                gpointer user_data)
+{
+	SeahorseCommands *commands = SEAHORSE_COMMANDS (user_data);
+	seahorse_keyserver_search_show (seahorse_commands_get_window (commands));
+}
+
+static void
+on_remote_sync (GtkAction* action,
+                gpointer user_data)
+{
+	SeahorseCommands *commands = SEAHORSE_COMMANDS (user_data);
+	SeahorseView *view = seahorse_commands_get_view (commands);
+	SeahorseGpgmeKeyring *keyring;
+	GList* objects;
+
+	objects = seahorse_view_get_selected_objects (view);
+	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_commands_get_window (commands));
+	g_list_free (objects);
+}
+
 static const GtkActionEntry COMMAND_ENTRIES[] = {
-	{ "key-sign", GTK_STOCK_INDEX, N_("_Sign Key..."), "", N_("Sign public key"), G_CALLBACK (on_key_sign) }
+	{ "key-sign", GTK_STOCK_INDEX, N_("_Sign Key..."), "",
+	  N_("Sign public key"), G_CALLBACK (on_key_sign) },
+	{ "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) }
 };
 
 
@@ -236,9 +281,10 @@ seahorse_pgp_commands_constructor (GType type, guint n_props, GObjectConstructPa
 		gtk_action_group_set_translation_domain (self->pv->command_actions, GETTEXT_PACKAGE);
 		gtk_action_group_add_actions (self->pv->command_actions, COMMAND_ENTRIES, 
 		                              G_N_ELEMENTS (COMMAND_ENTRIES), self);
-		
-		seahorse_view_register_commands (view, &commands_predicate, base);
-		seahorse_view_register_ui (view, &actions_predicate, UI_DEFINITION, self->pv->command_actions);
+
+		seahorse_view_register_commands (view, &commands_key_predicate, base);
+		seahorse_view_register_commands (view, &commands_uid_predicate, base);
+		seahorse_view_register_ui (view, &actions_key_predicate, UI_DEFINITION, self->pv->command_actions);
 	}
 	
 	return obj;
@@ -313,13 +359,14 @@ seahorse_pgp_commands_class_init (SeahorsePgpCommandsClass *klass)
 	SEAHORSE_COMMANDS_CLASS (klass)->delete_objects = seahorse_pgp_commands_delete_objects;
 	
 	/* Setup predicate for matching entries for these commands */
-	commands_predicate.tag = SEAHORSE_PGP_TYPE;
-	actions_predicate.tag = SEAHORSE_PGP_TYPE;
-	actions_predicate.location = SEAHORSE_LOCATION_LOCAL;
+	commands_key_predicate.type = SEAHORSE_TYPE_PGP_KEY;
+	commands_uid_predicate.type = SEAHORSE_TYPE_PGP_UID;
+	actions_key_predicate.type = SEAHORSE_TYPE_PGP_KEY;
+	actions_uid_predicate.type = SEAHORSE_TYPE_PGP_UID;
 
 	/* Register this class as a commands */
 	seahorse_registry_register_type (seahorse_registry_get (), SEAHORSE_TYPE_PGP_COMMANDS, 
-	                                 SEAHORSE_PGP_TYPE_STR, "commands", NULL, NULL);
+	                                 "commands", NULL, NULL);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/pgp/seahorse-pgp-key-properties.c b/pgp/seahorse-pgp-key-properties.c
index a2686d3..9f01800 100644
--- a/pgp/seahorse-pgp-key-properties.c
+++ b/pgp/seahorse-pgp-key-properties.c
@@ -40,6 +40,7 @@
 #include "seahorse-gpgme-dialogs.h"
 #include "seahorse-gpgme-key.h"
 #include "seahorse-gpgme-key-op.h"
+#include "seahorse-pgp-backend.h"
 #include "seahorse-gpg-op.h"
 #include "seahorse-pgp-dialogs.h"
 #include "seahorse-pgp-key.h"
@@ -410,22 +411,11 @@ static void
 names_update_row (SeahorseObjectModel *skmodel, SeahorseObject *object, 
                   GtkTreeIter *iter, SeahorseWidget *swidget)
 {
-	SeahorseObject *preferred;
 	GIcon *icon;
 	const gchar *name, *id;
-    
-	/* Always use the most preferred key for this keyid */
-	preferred = seahorse_object_get_preferred (object);
-	if (preferred) {
-		while (SEAHORSE_IS_OBJECT (preferred)) {
-			object = SEAHORSE_OBJECT (preferred);
-			preferred = seahorse_object_get_preferred (preferred);
-		}
-		seahorse_object_model_set_row_object (skmodel, iter, object);
-	}
 
-	icon = g_themed_icon_new (seahorse_object_get_location (object) < SEAHORSE_LOCATION_LOCAL ?
-	                          GTK_STOCK_DIALOG_QUESTION : SEAHORSE_ICON_SIGN);
+	icon = g_themed_icon_new (SEAHORSE_IS_PGP_KEY (object) ?
+	                               SEAHORSE_ICON_SIGN : GTK_STOCK_DIALOG_QUESTION);
 	name = seahorse_object_get_markup (object);
 	id = seahorse_object_get_identifier (object);
 	
@@ -442,7 +432,7 @@ names_populate (SeahorseWidget *swidget, GtkTreeStore *store, SeahorsePgpKey *pk
 {
 	SeahorseObject *object;
 	GtkTreeIter uiditer, sigiter;
-	GList *rawids = NULL;
+	GList *keyids = NULL;
 	SeahorsePgpUid *uid;
 	GList *keys, *l;
 	GList *uids, *u;
@@ -471,7 +461,7 @@ names_populate (SeahorseWidget *swidget, GtkTreeStore *store, SeahorsePgpKey *pk
 			/* Never show self signatures, they're implied */
 			if (seahorse_pgp_key_has_keyid (pkey, seahorse_pgp_signature_get_keyid (s->data)))
 				continue;
-			rawids = g_list_prepend (rawids, (gpointer)seahorse_pgp_signature_get_keyid (s->data));
+			keyids = g_list_prepend (keyids, (gpointer)seahorse_pgp_signature_get_keyid (s->data));
 		}
 
 		/*
@@ -479,11 +469,10 @@ names_populate (SeahorseWidget *swidget, GtkTreeStore *store, SeahorsePgpKey *pk
 		 * ties search scope together
 		 */
 		cancellable = g_cancellable_new ();
-		keys = seahorse_context_discover_objects (seahorse_context_instance (),
-		                                          SEAHORSE_PGP, rawids, cancellable);
+		keys = seahorse_pgp_backend_discover_keys (NULL, keyids, cancellable);
 		g_object_unref (cancellable);
-		g_list_free (rawids);
-		rawids = NULL;
+		g_list_free (keyids);
+		keyids = NULL;
         
 		/* Add the keys to the store */
 		for (l = keys; l; l = g_list_next (l)) {
@@ -1192,7 +1181,7 @@ on_pgp_details_export_button (GtkWidget *widget,
 	/* Export to a data block */
 	gerr = gpgme_data_new (&data);
 	g_return_if_fail (GPG_IS_OK (gerr));
-	ctx = seahorse_gpgme_source_new_context ();
+	ctx = seahorse_gpgme_keyring_new_context ();
 	g_return_if_fail (ctx);
 	gerr = seahorse_gpg_op_export_secret (ctx, seckey->subkeys->keyid, data);
 	gpgme_release (ctx);
@@ -1363,7 +1352,6 @@ do_details (SeahorseWidget *swidget)
     const gchar *label;
     gint trust;
     GList *subkeys, *l;
-    guint keyloc;
     gboolean valid;
 
     object = SEAHORSE_OBJECT_WIDGET (swidget)->object;
@@ -1372,8 +1360,6 @@ do_details (SeahorseWidget *swidget)
     subkeys = seahorse_pgp_key_get_subkeys (pkey);
     g_return_if_fail (subkeys && subkeys->data);
     subkey = SEAHORSE_PGP_SUBKEY (subkeys->data);
-    
-    keyloc = seahorse_object_get_location (object);
 
     widget = GTK_WIDGET (gtk_builder_get_object (swidget->gtkbuilder, "details-id-label"));
     if (widget) {
@@ -1412,7 +1398,7 @@ do_details (SeahorseWidget *swidget)
     widget = GTK_WIDGET (gtk_builder_get_object (swidget->gtkbuilder, "details-expires-label"));
     if (widget) {
         gulong expires = seahorse_pgp_subkey_get_expires (subkey);
-        if (seahorse_object_get_location (object) == SEAHORSE_LOCATION_REMOTE)
+        if (!SEAHORSE_IS_GPGME_KEY (object))
             fp_label = NULL;
         else if (expires == 0)
             fp_label = g_strdup (C_("Expires", "Never"));
@@ -1422,7 +1408,7 @@ do_details (SeahorseWidget *swidget)
         g_free (fp_label);
     }
 
-    show_gtkbuilder_widget (swidget, "details-trust-combobox", keyloc == SEAHORSE_LOCATION_LOCAL);
+    show_gtkbuilder_widget (swidget, "details-trust-combobox", SEAHORSE_IS_GPGME_KEY (object));
     widget = GTK_WIDGET (gtk_builder_get_object (swidget->gtkbuilder, "details-trust-combobox"));
     
     if (widget) {
@@ -1538,10 +1524,10 @@ enum {
     SIGN_N_COLUMNS
 };
 
-const GType sign_columns[] = {
-    G_TYPE_STRING,
+static GType sign_columns[] = {
     0 /* later */,
     G_TYPE_STRING,
+    G_TYPE_STRING,
     G_TYPE_BOOLEAN
 };
 
@@ -1584,29 +1570,17 @@ static void
 trust_update_row (SeahorseObjectModel *skmodel, SeahorseObject *object, 
                   GtkTreeIter *iter, SeahorseWidget *swidget)
 {
-	SeahorseObject *preferred;
 	gboolean trusted = FALSE;
 	GIcon *icon;
 	const gchar *name, *id;
-    
-    	/* Always use the most preferred key for this keyid */
-	preferred = seahorse_object_get_preferred (object);
-	if (SEAHORSE_IS_OBJECT (preferred)) {
-		while (SEAHORSE_IS_OBJECT (preferred)) {
-			object = SEAHORSE_OBJECT (preferred);
-			preferred = seahorse_object_get_preferred (preferred);
-		}
-		seahorse_object_model_set_row_object (skmodel, iter, object);
-	}
-
 
 	if (seahorse_object_get_usage (object) == SEAHORSE_USAGE_PRIVATE_KEY) 
 		trusted = TRUE;
 	else if (seahorse_object_get_flags (object) & SEAHORSE_FLAG_TRUSTED)
 		trusted = TRUE;
 
-	icon = g_themed_icon_new (seahorse_object_get_location (object) < SEAHORSE_LOCATION_LOCAL ?
-	                          GTK_STOCK_DIALOG_QUESTION : SEAHORSE_ICON_SIGN);
+	icon = g_themed_icon_new (SEAHORSE_IS_PGP_KEY (object) ?
+	                               SEAHORSE_ICON_SIGN : GTK_STOCK_DIALOG_QUESTION);
 	name = seahorse_object_get_label (object);
 	id = seahorse_object_get_identifier (object);
 
@@ -1664,8 +1638,7 @@ signatures_populate_model (SeahorseWidget *swidget, SeahorseObjectModel *skmodel
 		 * search scope together
 		 */
 		cancellable = g_cancellable_new ();
-		keys = seahorse_context_discover_objects (seahorse_context_instance (), SEAHORSE_PGP,
-		                                          rawids, cancellable);
+		keys = seahorse_pgp_backend_discover_keys (NULL, rawids, cancellable);
 		g_object_unref (cancellable);
 		g_list_free (rawids);
 		rawids = NULL;
@@ -1773,18 +1746,15 @@ do_trust (SeahorseWidget *swidget)
     GtkTreeModelFilter *filter;
     gboolean sigpersonal;
     GtkCellRenderer *renderer;
-    guint keyloc;
-    
+
     object = SEAHORSE_OBJECT_WIDGET (swidget)->object;
     pkey = SEAHORSE_PGP_KEY (object);
-    keyloc = seahorse_object_get_location (object);
-    
+
     if (seahorse_object_get_usage (object) != SEAHORSE_USAGE_PUBLIC_KEY)
         return;
     
     /* Remote keys */
-    if (keyloc < SEAHORSE_LOCATION_LOCAL) {
-        
+    if (!SEAHORSE_IS_GPGME_KEY (object)) {
         show_gtkbuilder_widget (swidget, "manual-trust-area", FALSE);
         show_gtkbuilder_widget (swidget, "manage-trust-area", TRUE);
         show_gtkbuilder_widget (swidget, "sign-area", FALSE);
@@ -1879,6 +1849,7 @@ do_trust (SeahorseWidget *swidget)
 		} else {
         
 			/* Create a new SeahorseObjectModel store.... */
+			sign_columns[SIGN_ICON] = G_TYPE_ICON;
 			store = GTK_TREE_STORE (seahorse_object_model_new (SIGN_N_COLUMNS, (GType*)sign_columns));
 			g_signal_connect (store, "update-row", G_CALLBACK (trust_update_row), swidget);
         
@@ -2007,27 +1978,16 @@ setup_private_properties (SeahorsePgpKey *pkey, GtkWindow *parent)
 void
 seahorse_pgp_key_properties_show (SeahorsePgpKey *pkey, GtkWindow *parent)
 {
-    SeahorseObject *sobj = SEAHORSE_OBJECT (pkey);
-    SeahorseSource *sksrc;
-    SeahorseWidget *swidget;
+	SeahorseWidget *swidget;
 
-    /* Reload the key to make sure to get all the props */
-    sksrc = seahorse_object_get_source (sobj);
-    g_return_if_fail (sksrc != NULL);
-    
-    /* Don't trigger the import of remote keys if possible */
-    if (SEAHORSE_IS_GPGME_KEY (pkey)) {
-        /* This causes the key source to get any specific info about the key */
-        seahorse_gpgme_key_refresh (SEAHORSE_GPGME_KEY (pkey));
-        sobj = seahorse_context_get_object (SCTX_APP(), sksrc, seahorse_object_get_id (sobj));
-        g_return_if_fail (sobj != NULL);
-    }
-    
-    if (seahorse_object_get_usage (sobj) == SEAHORSE_USAGE_PUBLIC_KEY)
-        swidget = setup_public_properties (pkey, parent);
-    else
-        swidget = setup_private_properties (pkey, parent);       
-    
-    if (swidget)
-        seahorse_widget_show (swidget);
+	/* This causes the key source to get any specific info about the key */
+	if (SEAHORSE_IS_GPGME_KEY (pkey))
+		seahorse_gpgme_key_refresh (SEAHORSE_GPGME_KEY (pkey));
+
+	if (seahorse_object_get_usage (SEAHORSE_OBJECT (pkey)) == SEAHORSE_USAGE_PUBLIC_KEY)
+		swidget = setup_public_properties (pkey, parent);
+	else
+		swidget = setup_private_properties (pkey, parent);
+	if (swidget)
+		seahorse_widget_show (swidget);
 }
diff --git a/pgp/seahorse-pgp-key.c b/pgp/seahorse-pgp-key.c
index e3d23c7..c0a9cb9 100644
--- a/pgp/seahorse-pgp-key.c
+++ b/pgp/seahorse-pgp-key.c
@@ -56,11 +56,44 @@ G_DEFINE_TYPE_WITH_CODE (SeahorsePgpKey, seahorse_pgp_key, SEAHORSE_TYPE_OBJECT,
 );
 
 struct _SeahorsePgpKeyPrivate {
+	gchar *keyid;
 	GList *uids;			/* All the UID objects */
 	GList *subkeys;                 /* All the Subkey objects */
 	GList *photos;                  /* List of photos */
 };
 
+/*
+ * PGP key ids can be of varying lengths. Shorter keyids are the last
+ * characters of the longer ones. When hashing match on the last 8
+ * characters.
+ */
+
+guint
+seahorse_pgp_keyid_hash (gconstpointer v)
+{
+	const gchar *keyid = v;
+	gsize len = strlen (keyid);
+	if (len > 8)
+		keyid += len - 8;
+	return g_str_hash (keyid);
+}
+
+gboolean
+seahorse_pgp_keyid_equal (gconstpointer v1,
+                          gconstpointer v2)
+{
+	const gchar *keyid_1 = v1;
+	const gchar *keyid_2 = v2;
+	gsize len_1 = strlen (keyid_1);
+	gsize len_2 = strlen (keyid_2);
+
+	if (len_1 != len_2 && len_1 >= 8 && len_2 >= 8) {
+		keyid_1 += len_1 - 8;
+		keyid_2 += len_2 - 8;
+	}
+	return g_str_equal (keyid_1, keyid_2);
+}
+
 /* -----------------------------------------------------------------------------
  * INTERNAL HELPERS
  */
@@ -107,26 +140,21 @@ _seahorse_pgp_key_set_uids (SeahorsePgpKey *self, GList *uids)
 	GHashTable *checks;
 	GHashTableIter iter;
 	GObject *uid;
-	guint index;
-	GQuark id;
 	GList *l;
 
 	g_return_if_fail (SEAHORSE_IS_PGP_KEY (self));
 
-	id = seahorse_object_get_id (SEAHORSE_OBJECT (self));
-
-	checks = g_hash_table_new (g_direct_hash, g_direct_equal);
-	for (l = self->pv->uids; l; l = g_list_next (l)) {
-		g_hash_table_insert (checks, l->data, l->data);
-	}
+	checks = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+	                                g_object_unref, NULL);
+	for (l = self->pv->uids; l; l = g_list_next (l))
+		g_hash_table_insert (checks, g_object_ref (l->data), l->data);
 
 	seahorse_object_list_free (self->pv->uids);
 	self->pv->uids = seahorse_object_list_copy (uids);
 	
 	/* Set parent and source on each new one, except the first */
-	for (l = self->pv->uids, index = 0; l; l = g_list_next (l), ++index) {
+	for (l = self->pv->uids; l; l = g_list_next (l)) {
 		uid = l->data;
-		g_object_set (uid, "id", seahorse_pgp_uid_calc_id (id, index), NULL);
 		if (!g_hash_table_remove (checks, uid))
 			gcr_collection_emit_added (GCR_COLLECTION (self), uid);
 	}
@@ -149,17 +177,30 @@ _seahorse_pgp_key_get_subkeys (SeahorsePgpKey *self)
 static void
 _seahorse_pgp_key_set_subkeys (SeahorsePgpKey *self, GList *subkeys)
 {
-	GQuark id;
-	
+	const gchar *keyid = NULL;
+
 	g_return_if_fail (SEAHORSE_IS_PGP_KEY (self));
 	g_return_if_fail (subkeys);
-	
+
+	keyid = seahorse_pgp_subkey_get_keyid (subkeys->data);
+	g_return_if_fail (keyid);
+
+	/* The keyid can't change */
+	if (self->pv->keyid) {
+		if (g_strcmp0 (self->pv->keyid, keyid) != 0) {
+			g_warning ("The keyid of a SeahorsePgpKey changed by "
+			           "setting a different subkey on it: %s != %s",
+			           self->pv->keyid, keyid);
+			return;
+		}
+
+	} else {
+		self->pv->keyid = g_strdup (keyid);
+	}
+
 	seahorse_object_list_free (self->pv->subkeys);
 	self->pv->subkeys = seahorse_object_list_copy (subkeys);
-	
-	id = seahorse_pgp_key_canonize_id (seahorse_pgp_subkey_get_keyid (subkeys->data));
-	g_object_set (self, "id", id, NULL); 
-	
+
 	g_object_notify (G_OBJECT (self), "subkeys");
 }
 
@@ -315,6 +356,7 @@ seahorse_pgp_key_object_finalize (GObject *obj)
 {
 	SeahorsePgpKey *self = SEAHORSE_PGP_KEY (obj);
 
+	g_free (self->pv->keyid);
 	g_assert (self->pv->uids == NULL);
 	g_assert (self->pv->photos == NULL);
 	g_assert (self->pv->subkeys == NULL);
@@ -327,7 +369,6 @@ seahorse_pgp_key_class_init (SeahorsePgpKeyClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-	seahorse_pgp_key_parent_class = g_type_class_peek_parent (klass);
 	g_type_class_add_private (klass, sizeof (SeahorsePgpKeyPrivate));
 
 	gobject_class->dispose = seahorse_pgp_key_object_dispose;
@@ -421,53 +462,6 @@ seahorse_pgp_key_collection_iface_init (GcrCollectionIface *iface)
  * PUBLIC 
  */
 
-GQuark
-seahorse_pgp_key_canonize_id (const gchar *keyid)
-{
-	gchar *str;
-	GQuark id;
-	
-	str = seahorse_pgp_key_calc_id (keyid, 0);
-	g_return_val_if_fail (str, 0);
-	
-	id = g_quark_from_string (str);
-	g_free (str);
-	
-	return id;
-}
-
-gchar*
-seahorse_pgp_key_calc_id (const gchar *keyid, guint index)
-{
-	guint len;
-	
-	g_return_val_if_fail (keyid, 0);
-	len = strlen (keyid);
-    
-	if (len < 16)
-		g_message ("invalid keyid (less than 16 chars): %s", keyid);
-    
-	if (len > 16)
-		keyid += len - 16;
-    
-	if (index == 0)
-		return g_strdup_printf ("%s:%s", SEAHORSE_PGP_STR, keyid);
-	else
-		return g_strdup_printf ("%s:%s:%u", SEAHORSE_PGP_STR, keyid, index);
-}
-
-const gchar* 
-seahorse_pgp_key_calc_rawid (GQuark id)
-{
-	const gchar* keyid, *strid;
-	
-	strid = g_quark_to_string (id);
-	g_return_val_if_fail (strid != NULL, NULL);
-	
-	keyid = strchr (strid, ':');
-	return keyid ? keyid + 1 : strid;
-}
-
 gchar*
 seahorse_pgp_key_calc_identifier (const gchar *keyid)
 {
diff --git a/pgp/seahorse-pgp-key.h b/pgp/seahorse-pgp-key.h
index 5fb54cd..2c88b5c 100644
--- a/pgp/seahorse-pgp-key.h
+++ b/pgp/seahorse-pgp-key.h
@@ -24,8 +24,6 @@
 
 #include <glib-object.h>
 
-#include "pgp/seahorse-pgp-module.h"
-
 #include "seahorse-object.h"
 #include "seahorse-validity.h"
 
@@ -53,7 +51,7 @@ struct _SeahorsePgpKey {
 
 struct _SeahorsePgpKeyClass {
 	SeahorseObjectClass parent_class;
-	
+
 	/* virtual methods */
 	GList* (*get_uids) (SeahorsePgpKey *self);
 	void   (*set_uids) (SeahorsePgpKey *self, GList *uids);
@@ -67,7 +65,7 @@ struct _SeahorsePgpKeyClass {
 
 GType             seahorse_pgp_key_get_type             (void);
 
-SeahorsePgpKey*   seahorse_pgp_key_new                  (void);
+SeahorsePgpKey *  seahorse_pgp_key_new                  (void);
 
 void              seahorse_pgp_key_realize              (SeahorsePgpKey *self);
 
@@ -105,11 +103,9 @@ gboolean          seahorse_pgp_key_has_keyid            (SeahorsePgpKey *self,
 
 gchar*            seahorse_pgp_key_calc_identifier      (const gchar *keyid);
 
-gchar*            seahorse_pgp_key_calc_id              (const gchar *keyid,
-                                                         guint index);
-
-const gchar*      seahorse_pgp_key_calc_rawid           (GQuark id);
+guint             seahorse_pgp_keyid_hash               (gconstpointer v);
 
-GQuark            seahorse_pgp_key_canonize_id          (const gchar *keyid);
+gboolean          seahorse_pgp_keyid_equal              (gconstpointer v1,
+                                                         gconstpointer v2);
 
 #endif /* __SEAHORSE_KEY_H__ */
diff --git a/pgp/seahorse-pgp-keysets.c b/pgp/seahorse-pgp-keysets.c
index 8eda89b..2670174 100644
--- a/pgp/seahorse-pgp-keysets.c
+++ b/pgp/seahorse-pgp-keysets.c
@@ -21,11 +21,14 @@
 
 #include "config.h"
 
+#include "seahorse-context.h"
 #include "seahorse-collection.h"
 #include "seahorse-object.h"
 #include "seahorse-predicate.h"
 
-#include "seahorse-pgp-module.h"
+#include "seahorse-gpgme-key.h"
+#include "seahorse-pgp-backend.h"
+#include "seahorse-pgp-key.h"
 #include "seahorse-pgp-keysets.h"
 
 /* -----------------------------------------------------------------------------
@@ -43,18 +46,20 @@ static gboolean
 pgp_signers_match (SeahorseObject *obj,
                    gpointer data)
 {
-    SeahorseObject *defkey;
-    
-    if (!SEAHORSE_IS_OBJECT (obj))
-	    return FALSE;
-    
-    defkey = seahorse_context_get_default_key (SCTX_APP ());
-    
-    /* Default key overrides all, and becomes the only signer available*/
-    if (defkey && seahorse_object_get_id (obj) != seahorse_object_get_id (defkey))
-        return FALSE;
-    
-    return TRUE;
+	SeahorsePgpKey *defkey;
+
+	if (!SEAHORSE_IS_PGP_KEY (obj))
+		return FALSE;
+
+	defkey = seahorse_pgp_backend_get_default_key (NULL);
+
+	/* Default key overrides all, and becomes the only signer available*/
+	if (defkey != NULL &&
+	    g_strcmp0 (seahorse_pgp_key_get_keyid (defkey),
+	               seahorse_pgp_key_get_keyid (SEAHORSE_PGP_KEY (obj))) != 0)
+		return FALSE;
+
+	return TRUE;
 }
 
 GcrCollection *
@@ -62,15 +67,17 @@ seahorse_keyset_pgp_signers_new (void)
 {
 	SeahorsePredicate *predicate = g_new0 (SeahorsePredicate, 1);
 	SeahorseCollection *collection;
+	SeahorseGpgmeKeyring *keyring;
 
-	predicate->location = SEAHORSE_LOCATION_LOCAL;
-	predicate->tag = SEAHORSE_PGP;
+	predicate->type = SEAHORSE_TYPE_GPGME_KEY;
 	predicate->usage = SEAHORSE_USAGE_PRIVATE_KEY;
 	predicate->flags = SEAHORSE_FLAG_CAN_SIGN;
 	predicate->nflags = SEAHORSE_FLAG_EXPIRED | SEAHORSE_FLAG_REVOKED | SEAHORSE_FLAG_DISABLED;
 	predicate->custom = pgp_signers_match;
 
-	collection = seahorse_collection_new_for_predicate (predicate, g_free);
+	keyring = seahorse_pgp_backend_get_default_keyring (NULL);
+	collection = seahorse_collection_new_for_predicate (GCR_COLLECTION (keyring),
+	                                                    predicate, g_free);
 
 	g_signal_connect_object (seahorse_context_pgp_settings (NULL), "changed::default-key",
 	                         G_CALLBACK (on_settings_default_key_changed), collection, 0);
diff --git a/pgp/seahorse-pgp-signature.c b/pgp/seahorse-pgp-signature.c
index b1fbed1..a22af7f 100644
--- a/pgp/seahorse-pgp-signature.c
+++ b/pgp/seahorse-pgp-signature.c
@@ -21,11 +21,12 @@
 
 #include "config.h"
 
-#include "seahorse-pgp.h"
+#include "seahorse-gpgme-key.h"
+#include "seahorse-gpgme-keyring.h"
+#include "seahorse-pgp-backend.h"
 #include "seahorse-pgp-key.h"
 #include "seahorse-pgp-signature.h"
 
-#include "seahorse-context.h"
 #include "seahorse-object.h"
 
 #include <string.h>
@@ -185,18 +186,20 @@ seahorse_pgp_signature_set_keyid (SeahorsePgpSignature *self, const gchar *keyid
 guint
 seahorse_pgp_signature_get_sigtype (SeahorsePgpSignature *self)
 {
-	SeahorseObject *sobj;
-	GQuark id;
+	SeahorseGpgmeKeyring *keyring;
+	SeahorseGpgmeKey *key;
+	SeahorseObject *obj;
 
 	g_return_val_if_fail (SEAHORSE_IS_PGP_SIGNATURE (self), 0);
-    
-	id = seahorse_pgp_key_canonize_id (self->pv->keyid);
-	sobj = seahorse_context_find_object (SCTX_APP (), id, SEAHORSE_LOCATION_LOCAL);
-    
-	if (sobj) {
-		if (seahorse_object_get_usage (sobj) == SEAHORSE_USAGE_PRIVATE_KEY) 
+
+	keyring = seahorse_pgp_backend_get_default_keyring (NULL);
+	key = seahorse_gpgme_keyring_lookup (keyring, self->pv->keyid);
+
+	if (key != NULL) {
+		obj = SEAHORSE_OBJECT (key);
+		if (seahorse_object_get_usage (obj) == SEAHORSE_USAGE_PRIVATE_KEY)
 			return SKEY_PGPSIG_TRUSTED | SKEY_PGPSIG_PERSONAL;
-		if (seahorse_object_get_flags (sobj) & SEAHORSE_FLAG_TRUSTED)
+		if (seahorse_object_get_flags (obj) & SEAHORSE_FLAG_TRUSTED)
 			return SKEY_PGPSIG_TRUSTED;
 	}
 
diff --git a/pgp/seahorse-pgp-signature.h b/pgp/seahorse-pgp-signature.h
index ac92e81..8b4eb29 100644
--- a/pgp/seahorse-pgp-signature.h
+++ b/pgp/seahorse-pgp-signature.h
@@ -24,8 +24,6 @@
 
 #include <glib-object.h>
 
-#include "pgp/seahorse-pgp-module.h"
-
 #include "seahorse-validity.h"
 
 #define SEAHORSE_TYPE_PGP_SIGNATURE            (seahorse_pgp_signature_get_type ())
diff --git a/pgp/seahorse-pgp-uid.c b/pgp/seahorse-pgp-uid.c
index 7959480..cb041a0 100644
--- a/pgp/seahorse-pgp-uid.c
+++ b/pgp/seahorse-pgp-uid.c
@@ -224,7 +224,6 @@ seahorse_pgp_uid_init (SeahorsePgpUid *self)
 {
 	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_PGP_UID, SeahorsePgpUidPrivate);
 	g_object_set (self, "icon", NULL, "usage", SEAHORSE_USAGE_IDENTITY, NULL);
-	g_object_set (self, "tag", SEAHORSE_PGP_TYPE, NULL);
 }
 
 static void
diff --git a/pgp/seahorse-pgp.h b/pgp/seahorse-pgp.h
index 1f70a69..c486cf6 100644
--- a/pgp/seahorse-pgp.h
+++ b/pgp/seahorse-pgp.h
@@ -25,12 +25,21 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include <gcr/gcr.h>
+
 G_BEGIN_DECLS
 
+#ifdef WITH_PGP
+
+#define SEAHORSE_PGP g_quark_from_string ("openpgp")
 #define SEAHORSE_PGP_TYPE_STR "openpgp"
 #define SEAHORSE_PGP_TYPE g_quark_from_string ("openpgp")
 #define SEAHORSE_PGP_STOCK_ICON "seahorse-key-personal"
 
+GcrCollection *       seahorse_pgp_backend_initialize    (void);
+
+#endif /* WITH_PGP */
+
 G_END_DECLS
 
 #endif
diff --git a/pgp/seahorse-server-source.c b/pgp/seahorse-server-source.c
index 1792a5b..342d01a 100644
--- a/pgp/seahorse-server-source.c
+++ b/pgp/seahorse-server-source.c
@@ -44,8 +44,6 @@
 
 enum {
     PROP_0,
-    PROP_SOURCE_TAG,
-    PROP_SOURCE_LOCATION,
     PROP_KEY_SERVER,
     PROP_URI
 };
@@ -88,9 +86,6 @@ seahorse_server_source_class_init (SeahorseServerSourceClass *klass)
     gobject_class->set_property = seahorse_server_set_property;
     gobject_class->get_property = seahorse_server_get_property;
 
-	g_object_class_override_property (gobject_class, PROP_SOURCE_TAG, "source-tag");
-	g_object_class_override_property (gobject_class, PROP_SOURCE_LOCATION, "source-location");
-	
     g_object_class_install_property (gobject_class, PROP_KEY_SERVER,
             g_param_spec_string ("key-server", "Key Server",
                                  "Key Server to search on", "",
@@ -100,36 +95,6 @@ seahorse_server_source_class_init (SeahorseServerSourceClass *klass)
             g_param_spec_string ("uri", "Key Server URI",
                                  "Key Server full URI", "",
                                  G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
-    
-	seahorse_registry_register_function (NULL, seahorse_pgp_key_canonize_id, "canonize", SEAHORSE_PGP_STR, NULL);
-}
-
-static void
-seahorse_server_source_load_async (SeahorseSource *source,
-                                   GCancellable *cancellable,
-                                   GAsyncReadyCallback callback,
-                                   gpointer user_data)
-{
-	GSimpleAsyncResult *res;
-
-	res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
-	                                 seahorse_server_source_load_async);
-	g_simple_async_result_complete_in_idle (res);
-	g_object_unref (res);
-}
-
-static gboolean
-seahorse_server_source_load_finish (SeahorseSource *source,
-                                    GAsyncResult *result,
-                                    GError **error)
-{
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source),
-	                      seahorse_server_source_load_async), FALSE);
-
-	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
-		return FALSE;
-
-	return TRUE;
 }
 
 /**
@@ -143,8 +108,7 @@ seahorse_server_source_load_finish (SeahorseSource *source,
 static void 
 seahorse_source_iface (SeahorseSourceIface *iface)
 {
-	iface->load_async = seahorse_server_source_load_async;
-	iface->load_finish = seahorse_server_source_load_finish;
+
 }
 
 /**
@@ -221,7 +185,7 @@ seahorse_server_set_property (GObject *object, guint prop_id,
 * pspec: ignored
 *
 * The properties that can be read are:
-* PROP_KEY_SERVER, PROP_URI, PROP_SOURCE_TAG, PROP_SOURCE_LOCATION
+* PROP_KEY_SERVER, PROP_URI
 *
 **/
 static void 
@@ -237,13 +201,7 @@ seahorse_server_get_property (GObject *object, guint prop_id, GValue *value,
     case PROP_URI:
         g_value_set_string (value, ssrc->priv->uri);
         break;
-    case PROP_SOURCE_TAG:
-        g_value_set_uint (value, SEAHORSE_PGP);
-        break;
-    case PROP_SOURCE_LOCATION:
-        g_value_set_enum (value, SEAHORSE_LOCATION_REMOTE);
-        break;
-    }        
+    }
 }
 
 /* --------------------------------------------------------------------------
@@ -366,3 +324,67 @@ seahorse_server_source_new (const gchar *server)
     g_free (uri);
     return ssrc;
 }
+
+void
+seahorse_server_source_search_async (SeahorseServerSource *self,
+                                     const gchar *match,
+                                     GcrSimpleCollection *results,
+                                     GCancellable *cancellable,
+                                     GAsyncReadyCallback callback,
+                                     gpointer user_data)
+{
+	g_return_if_fail (SEAHORSE_IS_SERVER_SOURCE (self));
+	g_return_if_fail (match != NULL);
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+	g_return_if_fail (SEAHORSE_SERVER_SOURCE_GET_CLASS (self)->search_async);
+	SEAHORSE_SERVER_SOURCE_GET_CLASS (self)->search_async (self, match, results,
+	                                                       cancellable, callback, user_data);
+}
+
+gboolean
+seahorse_server_source_search_finish (SeahorseServerSource *self,
+                                      GAsyncResult *result,
+                                      GError **error)
+{
+	g_return_val_if_fail (SEAHORSE_IS_SERVER_SOURCE (self), FALSE);
+	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+	g_return_val_if_fail (SEAHORSE_SERVER_SOURCE_GET_CLASS (self)->search_finish, FALSE);
+	return SEAHORSE_SERVER_SOURCE_GET_CLASS (self)->search_finish (self, result, error);
+}
+
+void
+seahorse_server_source_export_async (SeahorseServerSource *self,
+                                     GList *keyids,
+                                     GOutputStream *output,
+                                     GCancellable *cancellable,
+                                     GAsyncReadyCallback callback,
+                                     gpointer user_data)
+{
+	SeahorseServerSourceClass *klass;
+
+	g_return_if_fail (SEAHORSE_IS_SERVER_SOURCE (self));
+	g_return_if_fail (output == NULL || G_IS_OUTPUT_STREAM (output));
+	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+	klass = SEAHORSE_SERVER_SOURCE_GET_CLASS (self);
+	g_return_if_fail (klass->export_async);
+	(klass->export_async) (self, keyids, output, cancellable, callback, user_data);
+}
+
+GOutputStream *
+seahorse_server_source_export_finish (SeahorseServerSource *self,
+                                      GAsyncResult *result,
+                                      GError **error)
+{
+	SeahorseServerSourceClass *klass;
+
+	g_return_val_if_fail (SEAHORSE_IS_SERVER_SOURCE (self), NULL);
+	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+	klass = SEAHORSE_SERVER_SOURCE_GET_CLASS (self);
+	g_return_val_if_fail (klass->export_async != NULL, NULL);
+	g_return_val_if_fail (klass->export_finish != NULL, NULL);
+	return (klass->export_finish) (self, result, error);
+}
diff --git a/pgp/seahorse-server-source.h b/pgp/seahorse-server-source.h
index 7cd0e51..e701d03 100644
--- a/pgp/seahorse-server-source.h
+++ b/pgp/seahorse-server-source.h
@@ -41,7 +41,9 @@
 #ifndef __SEAHORSE_SERVER_SOURCE_H__
 #define __SEAHORSE_SERVER_SOURCE_H__
 
-#include "seahorse-source.h"
+#include "seahorse-pgp-key.h"
+
+#include <gcr/gcr.h>
 
 #define SEAHORSE_TYPE_SERVER_SOURCE            (seahorse_server_source_get_type ())
 #define SEAHORSE_SERVER_SOURCE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_SERVER_SOURCE, SeahorseServerSource))
@@ -61,10 +63,54 @@ struct _SeahorseServerSource {
 
 struct _SeahorseServerSourceClass {
 	GObjectClass parent_class;
+
+	void            (*export_async)          (SeahorseServerSource *source,
+	                                          GList *ids,
+	                                          GOutputStream *output,
+	                                          GCancellable *cancellable,
+	                                          GAsyncReadyCallback callback,
+	                                          gpointer user_data);
+
+	GOutputStream * (*export_finish)         (SeahorseServerSource *source,
+	                                          GAsyncResult *result,
+	                                          GError **error);
+
+	void            (*search_async)          (SeahorseServerSource *source,
+	                                          const gchar *match,
+	                                          GcrSimpleCollection *results,
+	                                          GCancellable *cancellable,
+	                                          GAsyncReadyCallback callback,
+	                                          gpointer user_data);
+
+	gboolean        (*search_finish)         (SeahorseServerSource *source,
+	                                          GAsyncResult *result,
+	                                          GError **error);
 };
 
 GType                  seahorse_server_source_get_type         (void);
 
 SeahorseServerSource*  seahorse_server_source_new              (const gchar *uri);
 
+void                   seahorse_server_source_search_async     (SeahorseServerSource *self,
+                                                                const gchar *match,
+                                                                GcrSimpleCollection *results,
+                                                                GCancellable *cancellable,
+                                                                GAsyncReadyCallback callback,
+                                                                gpointer user_data);
+
+gboolean               seahorse_server_source_search_finish    (SeahorseServerSource *self,
+                                                                GAsyncResult *result,
+                                                                GError **error);
+
+void                   seahorse_server_source_export_async     (SeahorseServerSource *self,
+                                                                GList *ids,
+                                                                GOutputStream *output,
+                                                                GCancellable *cancellable,
+                                                                GAsyncReadyCallback callback,
+                                                                gpointer user_data);
+
+GOutputStream *        seahorse_server_source_export_finish    (SeahorseServerSource *self,
+                                                                GAsyncResult *result,
+                                                                GError **error);
+
 #endif /* __SEAHORSE_SERVER_SOURCE_H__ */
diff --git a/pgp/seahorse-signer.c b/pgp/seahorse-signer.c
index de2b97c..2da3641 100755
--- a/pgp/seahorse-signer.c
+++ b/pgp/seahorse-signer.c
@@ -41,13 +41,14 @@ seahorse_signer_get (GtkWindow *parent)
 {
     SeahorseWidget *swidget;
     GcrCollection *collection;
-    SeahorseObject *object = NULL;
+    SeahorsePgpKey *key = NULL;
     GtkWidget *combo;
     GtkWidget *widget;
     gint response;
     gboolean done = FALSE;
     gboolean ok = FALSE;
     GSettings *settings;
+    const gchar *keyid;
     gchar *id;
     guint nkeys;
 
@@ -66,13 +67,10 @@ seahorse_signer_get (GtkWindow *parent)
     /* If only one key (probably default) then return it immediately */
     if (nkeys == 1) {
         GList *keys = gcr_collection_get_objects (collection);
-        object = SEAHORSE_OBJECT (keys->data);
-        
+        key = keys->data;
         g_list_free (keys);
         g_object_unref (collection);
-
-        g_assert (SEAHORSE_IS_PGP_KEY (object));
-        return SEAHORSE_PGP_KEY (object);
+        return key;
     }
     
     swidget = seahorse_widget_new ("signer", parent);
@@ -87,7 +85,13 @@ seahorse_signer_get (GtkWindow *parent)
 
     /* Select the last key used */
     id = g_settings_get_string (settings, "last-signer");
-    seahorse_combo_keys_set_active_id (GTK_COMBO_BOX (combo), g_quark_from_string (id));
+    if (!id || !id[0])
+        keyid = NULL;
+    else if (g_str_has_prefix (id, "openpgp:"))
+        keyid = id + strlen ("openpgp:");
+    else
+        keyid = id;
+    seahorse_combo_keys_set_active_id (GTK_COMBO_BOX (combo), keyid);
     g_free (id); 
     
     widget = seahorse_widget_get_toplevel (swidget);
@@ -107,14 +111,13 @@ seahorse_signer_get (GtkWindow *parent)
     }
 
     if (ok) {
-        object = seahorse_combo_keys_get_active (GTK_COMBO_BOX (combo));
-        g_return_val_if_fail (SEAHORSE_IS_PGP_KEY (object), NULL);
+        key = seahorse_combo_keys_get_active (GTK_COMBO_BOX (combo));
 
         /* Save this as the last key signed with */
         g_settings_set_string (settings, "last-signer",
-                               object == NULL ? "" : g_quark_to_string (seahorse_object_get_id (object)));
+                               key ? seahorse_pgp_key_get_keyid (key) : NULL);
     }
     
     seahorse_widget_destroy (swidget);
-    return SEAHORSE_PGP_KEY (object);
+    return key;
 }
diff --git a/libseahorse/seahorse-transfer.c b/pgp/seahorse-transfer.c
similarity index 78%
rename from libseahorse/seahorse-transfer.c
rename to pgp/seahorse-transfer.c
index 9b699e9..93e17d3 100644
--- a/libseahorse/seahorse-transfer.c
+++ b/pgp/seahorse-transfer.c
@@ -22,9 +22,13 @@
 
 #include "config.h"
 
+#include "seahorse-server-source.h"
+#include "seahorse-gpgme-keyring.h"
+
 #include <stdlib.h>
 #include <glib/gi18n.h>
 
+#include "seahorse-object-list.h"
 #include "seahorse-transfer.h"
 #include "seahorse-progress.h"
 #include "seahorse-util.h"
@@ -37,7 +41,7 @@ typedef struct {
 	SeahorseSource *from;
 	SeahorseSource *to;
 	GOutputStream *output;
-	GList *keyids;
+	GList *keys;
 } transfer_closure;
 
 static void
@@ -49,7 +53,7 @@ transfer_closure_free (gpointer user_data)
 	g_clear_object (&closure->to);
 	g_clear_object (&closure->output);
 	g_clear_object (&closure->cancellable);
-	g_list_free (closure->keyids);
+	seahorse_object_list_free (closure->keys);
 	g_free (closure);
 }
 
@@ -90,7 +94,15 @@ on_source_export_ready (GObject *object,
 	seahorse_debug ("[transfer] export done");
 	seahorse_progress_end (closure->cancellable, &closure->from);
 
-	if (seahorse_source_export_raw_finish (closure->from, result, &error))
+	if (SEAHORSE_IS_SERVER_SOURCE (closure->from)) {
+		seahorse_server_source_export_finish (SEAHORSE_SERVER_SOURCE (closure->from),
+		                                      result, &error);
+
+	} else {
+		seahorse_source_export_finish (closure->from, result, &error);
+	}
+
+	if (error == NULL)
 		g_cancellable_set_error_if_cancelled (closure->cancellable, &error);
 
 	if (error == NULL) {
@@ -128,14 +140,26 @@ on_timeout_start_transfer (gpointer user_data)
 {
 	GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (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 (closure->keyids);
+	g_assert (closure->keys);
 
 	seahorse_progress_begin (closure->cancellable, &closure->from);
-	seahorse_source_export_raw_async (closure->from, closure->keyids, closure->output,
-	                                  closure->cancellable, on_source_export_ready,
-	                                  g_object_ref (res));
+	if (SEAHORSE_IS_SERVER_SOURCE (closure->from)) {
+		keyids = NULL;
+		for (l = closure->keys; l != NULL; l = g_list_next (l))
+			keyids = g_list_prepend (keyids, (gpointer)seahorse_pgp_key_get_keyid (l->data));
+		keyids = g_list_reverse (keyids);
+		seahorse_server_source_export_async (SEAHORSE_SERVER_SOURCE (closure->from),
+		                                     keyids, closure->output, closure->cancellable,
+		                                     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));
+	}
 
 	return FALSE; /* Don't run again */
 }
@@ -143,14 +167,13 @@ on_timeout_start_transfer (gpointer user_data)
 void
 seahorse_transfer_async (SeahorseSource *from,
                          SeahorseSource *to,
-                         GList *keyids,
+                         GList *keys,
                          GCancellable *cancellable,
                          GAsyncReadyCallback callback,
                          gpointer user_data)
 {
 	GSimpleAsyncResult *res;
 	transfer_closure *closure = NULL;
-	SeahorseLocation location;
 
 	g_return_if_fail (SEAHORSE_SOURCE (from));
 	g_return_if_fail (SEAHORSE_SOURCE (to));
@@ -158,7 +181,7 @@ seahorse_transfer_async (SeahorseSource *from,
 	res = g_simple_async_result_new (NULL, callback, user_data,
 	                                 seahorse_transfer_async);
 
-	if (!keyids) {
+	if (!keys) {
 		g_simple_async_result_complete_in_idle (res);
 		g_object_unref (res);
 		return;
@@ -168,18 +191,16 @@ seahorse_transfer_async (SeahorseSource *from,
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
 	closure->from = g_object_ref (from);
 	closure->to = g_object_ref (to);
-	closure->keyids = g_list_copy (keyids);
+	closure->keys = seahorse_object_list_copy (keys);
 	closure->output = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
 	g_simple_async_result_set_op_res_gpointer (res, closure, transfer_closure_free);
 
-	location = seahorse_source_get_location (from);
 	seahorse_progress_prep (cancellable, &closure->from,
-	                        (location == SEAHORSE_LOCATION_REMOTE) ?
-	                        _("Retrieving data") : _("Exporting data"));
-	location = seahorse_source_get_location (to);
+	                        SEAHORSE_IS_GPGME_KEYRING (closure->from) ?
+	                        _("Exporting data") : _("Retrieving data"));
 	seahorse_progress_prep (cancellable, &closure->to,
-	                        (location == SEAHORSE_LOCATION_REMOTE) ?
-	                        _("Importing data") : _("Sending data"));
+	                        SEAHORSE_IS_GPGME_KEYRING (closure->to) ?
+	                        _("Sending data") : _("Importing data"));
 
 	seahorse_debug ("starting export");
 
diff --git a/libseahorse/seahorse-transfer.h b/pgp/seahorse-transfer.h
similarity index 93%
rename from libseahorse/seahorse-transfer.h
rename to pgp/seahorse-transfer.h
index 3906631..f4b67a5 100644
--- a/libseahorse/seahorse-transfer.h
+++ b/pgp/seahorse-transfer.h
@@ -25,9 +25,11 @@
 
 #include "seahorse-source.h"
 
+#include "seahorse-server-source.h"
+
 void            seahorse_transfer_async         (SeahorseSource *from,
                                                  SeahorseSource *to,
-                                                 GList *keyids,
+                                                 GList *keys,
                                                  GCancellable *cancellable,
                                                  GAsyncReadyCallback callback,
                                                  gpointer user_data);
diff --git a/pgp/seahorse-unknown-source.c b/pgp/seahorse-unknown-source.c
new file mode 100644
index 0000000..bf6c173
--- /dev/null
+++ b/pgp/seahorse-unknown-source.c
@@ -0,0 +1,115 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2006 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ * You should have received a copy of the GNU 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-pgp-key.h"
+#include "seahorse-unknown-source.h"
+
+#include "seahorse-registry.h"
+#include "seahorse-unknown.h"
+
+struct _SeahorseUnknownSource {
+	GObject parent;
+	GHashTable *keys;
+};
+
+struct _SeahorseUnknownSourceClass {
+	GObjectClass parent_class;
+};
+
+static void     seahorse_source_iface    (SeahorseSourceIface *iface);
+
+G_DEFINE_TYPE_EXTENDED (SeahorseUnknownSource, seahorse_unknown_source, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_source_iface));
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+seahorse_unknown_source_init (SeahorseUnknownSource *self)
+{
+	self->keys = g_hash_table_new_full (seahorse_pgp_keyid_hash,
+	                                    seahorse_pgp_keyid_equal,
+	                                    g_free, g_object_unref);
+}
+
+static void
+seahorse_unknown_source_finalize (GObject *obj)
+{
+	SeahorseUnknownSource *self = SEAHORSE_UNKNOWN_SOURCE (obj);
+
+	g_hash_table_destroy (self->keys);
+
+	G_OBJECT_CLASS (seahorse_unknown_source_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_unknown_source_class_init (SeahorseUnknownSourceClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	gobject_class->finalize = seahorse_unknown_source_finalize;
+}
+
+static void
+seahorse_source_iface (SeahorseSourceIface *iface)
+{
+
+}
+
+SeahorseUnknownSource*
+seahorse_unknown_source_new (void)
+{
+	return g_object_new (SEAHORSE_TYPE_UNKNOWN_SOURCE, NULL);
+}
+
+static void
+on_cancellable_gone (gpointer user_data,
+                     GObject *where_the_object_was)
+{
+	/* TODO: Change the icon */
+}
+
+SeahorseObject *
+seahorse_unknown_source_add_object (SeahorseUnknownSource *self,
+                                    const gchar *keyid,
+                                    GCancellable *cancellable)
+{
+	SeahorseObject *object;
+
+	g_return_val_if_fail (keyid != NULL, NULL);
+	g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
+
+	object = g_hash_table_lookup (self->keys, keyid);
+	if (object == NULL) {
+		object = SEAHORSE_OBJECT (seahorse_unknown_new (self, keyid, NULL));
+		g_hash_table_insert (self->keys, g_strdup (keyid), object);
+	}
+
+	if (cancellable)
+		g_object_weak_ref (G_OBJECT (cancellable), on_cancellable_gone, object);
+
+	return object;
+}
diff --git a/libseahorse/seahorse-unknown-source.h b/pgp/seahorse-unknown-source.h
similarity index 77%
rename from libseahorse/seahorse-unknown-source.h
rename to pgp/seahorse-unknown-source.h
index fdfeadb..239afe4 100644
--- a/libseahorse/seahorse-unknown-source.h
+++ b/pgp/seahorse-unknown-source.h
@@ -19,7 +19,7 @@
  * 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  */
- 
+
 #ifndef __SEAHORSE_UNKNOWN_SOURCE_H__
 #define __SEAHORSE_UNKNOWN_SOURCE_H__
 
@@ -37,38 +37,12 @@ typedef struct _SeahorseUnknownSource SeahorseUnknownSource;
 typedef struct _SeahorseUnknownSourceClass SeahorseUnknownSourceClass;
 typedef struct _SeahorseUnknownSourcePrivate SeahorseUnknownSourcePrivate;
 
-/**
- * SeahorseUnknownSource:
- * @parent: The parent #GObject
- * @ktype: The #GQuark key type for the source
- *
- * A  source for unknown objects
- *
- * - Derived from SeahorseSource
- * - Is used for objects that haven't been found on a key server.
- *
- * Properties:
- *  ktype: (GQuark) The ktype (ie: SKEY_UNKNOWN) of keys originating from this
-           key source.
- *  location: (SeahorseLocation) The location of objects that come from this
- *         source. (ie: SEAHORSE_LOCATION_MISSING)
- */
-
-struct _SeahorseUnknownSource {
-	GObject parent;
-	GQuark ktype;
-};
-
-struct _SeahorseUnknownSourceClass {
-	GObjectClass parent_class;
-};
-
 GType                    seahorse_unknown_source_get_type      (void);
 
-SeahorseUnknownSource*   seahorse_unknown_source_new           (GQuark ktype);
+SeahorseUnknownSource*   seahorse_unknown_source_new           (void);
 
 SeahorseObject*          seahorse_unknown_source_add_object    (SeahorseUnknownSource *self,
-                                                                GQuark id,
+                                                                const gchar *keyid,
                                                                 GCancellable *cancellable);
 
 #endif /* __SEAHORSE_UNKNOWN_SOURCE_H__ */
diff --git a/libseahorse/seahorse-unknown.c b/pgp/seahorse-unknown.c
similarity index 73%
rename from libseahorse/seahorse-unknown.c
rename to pgp/seahorse-unknown.c
index f7c17cb..ecd9dd0 100644
--- a/libseahorse/seahorse-unknown.c
+++ b/pgp/seahorse-unknown.c
@@ -21,8 +21,8 @@
 
 #include "config.h"
 
+#include "seahorse-pgp-key.h"
 #include "seahorse-unknown.h"
-
 #include "seahorse-unknown-source.h"
 
 #include <glib/gi18n.h>
@@ -30,7 +30,7 @@
 G_DEFINE_TYPE (SeahorseUnknown, seahorse_unknown, SEAHORSE_TYPE_OBJECT);
 
 /* -----------------------------------------------------------------------------
- * OBJECT 
+ * OBJECT
  */
 
 
@@ -50,15 +50,20 @@ seahorse_unknown_class_init (SeahorseUnknownClass *klass)
  * PUBLIC METHODS
  */
 
-SeahorseUnknown* 
-seahorse_unknown_new (SeahorseUnknownSource *source, GQuark id, const gchar *display)
+SeahorseUnknown*
+seahorse_unknown_new (SeahorseUnknownSource *source,
+                      const gchar *keyid,
+                      const gchar *display)
 {
-	SeahorseUnknown *self;
+	gchar *identifier;
 
 	if (!display)
 		display = _("Unavailable");
+	identifier = seahorse_pgp_key_calc_identifier (keyid);
 
-	self = g_object_new (SEAHORSE_TYPE_UNKNOWN, "source", source, 
-	                     "label", display, "id", id, NULL);
-	return self;
+	return g_object_new (SEAHORSE_TYPE_UNKNOWN,
+	                     "source", source,
+	                     "label", display,
+	                     "identifier", identifier,
+	                     NULL);
 }
diff --git a/libseahorse/seahorse-unknown.h b/pgp/seahorse-unknown.h
similarity index 96%
rename from libseahorse/seahorse-unknown.h
rename to pgp/seahorse-unknown.h
index a5f0798..4a381d8 100644
--- a/libseahorse/seahorse-unknown.h
+++ b/pgp/seahorse-unknown.h
@@ -51,7 +51,7 @@ struct _SeahorseUnknownClass {
 GType                seahorse_unknown_get_type         (void);
 
 SeahorseUnknown*     seahorse_unknown_new              (SeahorseUnknownSource *usrc,
-                                                        GQuark id, 
+                                                        const gchar *keyid,
                                                         const gchar *display);
 
 #endif /* __SEAHORSE_UNKNOWN_H__ */
diff --git a/pkcs11/Makefile.am b/pkcs11/Makefile.am
index 7adf2d7..a6a76b0 100644
--- a/pkcs11/Makefile.am
+++ b/pkcs11/Makefile.am
@@ -15,10 +15,10 @@ INCLUDES = -I$(top_builddir) \
 noinst_LTLIBRARIES = libseahorse-pkcs11.la
 
 libseahorse_pkcs11_la_SOURCES = \
+	seahorse-pkcs11-backend.c seahorse-pkcs11-backend.h \
 	seahorse-pkcs11-certificate.c seahorse-pkcs11-certificate.h \
 	seahorse-pkcs11-certificate-props.c seahorse-pkcs11-certificate-props.h \
 	seahorse-pkcs11-commands.c seahorse-pkcs11-commands.h \
-	seahorse-pkcs11-module.c seahorse-pkcs11-module.h \
 	seahorse-pkcs11-helpers.c seahorse-pkcs11-helpers.h \
 	seahorse-pkcs11-object.c seahorse-pkcs11-object.h \
 	seahorse-pkcs11-operations.c seahorse-pkcs11-operations.h \
diff --git a/pkcs11/seahorse-pkcs11-backend.c b/pkcs11/seahorse-pkcs11-backend.c
new file mode 100644
index 0000000..4a35e23
--- /dev/null
+++ b/pkcs11/seahorse-pkcs11-backend.c
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include "seahorse-pkcs11-backend.h"
+#include "seahorse-pkcs11-commands.h"
+#include "seahorse-pkcs11-source.h"
+
+#include "seahorse-util.h"
+
+#include <gck/gck.h>
+
+static SeahorsePkcs11Backend *pkcs11_backend = NULL;
+
+struct _SeahorsePkcs11Backend {
+	GObject parent;
+	GList *slots;
+};
+
+struct _SeahorsePkcs11BackendClass {
+	GObjectClass parent_class;
+};
+
+static void         seahorse_pkcs11_backend_collection_init  (GcrCollectionIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (SeahorsePkcs11Backend, seahorse_pkcs11_backend, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_pkcs11_backend_collection_init));
+
+static void
+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));
+}
+
+static void
+seahorse_pkcs11_backend_constructed (GObject *obj)
+{
+	SeahorsePkcs11Backend *self = SEAHORSE_PKCS11_BACKEND (obj);
+	SeahorseSource *source;
+	GList *slots, *s;
+	GList *modules, *m;
+	GError *error = NULL;
+
+	G_OBJECT_CLASS (seahorse_pkcs11_backend_parent_class)->constructed (obj);
+
+	modules = gck_modules_initialize_registered (NULL, &error);
+	if (error != NULL) {
+		g_warning ("%s", error->message);
+		g_clear_error (&error);
+	}
+
+	for (m = modules; m != NULL; m = g_list_next (m)) {
+		slots = gck_module_get_slots (m->data, FALSE);
+		for (s = slots; s; s = g_list_next (s)) {
+			source = SEAHORSE_SOURCE (seahorse_pkcs11_source_new (s->data));
+			self->slots = g_list_append (self->slots, source);
+		}
+
+		/* These will have been refed by the source above */
+		gck_list_unref_free (slots);
+	}
+
+	gck_list_unref_free (modules);
+
+}
+
+static void
+seahorse_pkcs11_backend_dispose (GObject *obj)
+{
+	SeahorsePkcs11Backend *self = SEAHORSE_PKCS11_BACKEND (obj);
+
+	g_list_free_full (self->slots, g_object_unref);
+	self->slots = NULL;
+
+	G_OBJECT_CLASS (seahorse_pkcs11_backend_parent_class)->dispose (obj);
+}
+
+static void
+seahorse_pkcs11_backend_finalize (GObject *obj)
+{
+	SeahorsePkcs11Backend *self = SEAHORSE_PKCS11_BACKEND (obj);
+
+	g_assert (self->slots == NULL);
+	g_return_if_fail (pkcs11_backend == self);
+	pkcs11_backend = NULL;
+
+	G_OBJECT_CLASS (seahorse_pkcs11_backend_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_pkcs11_backend_class_init (SeahorsePkcs11BackendClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+	gobject_class->constructed = seahorse_pkcs11_backend_constructed;
+	gobject_class->dispose = seahorse_pkcs11_backend_dispose;
+	gobject_class->finalize = seahorse_pkcs11_backend_finalize;
+}
+
+static guint
+seahorse_pkcs11_backend_get_length (GcrCollection *collection)
+{
+	SeahorsePkcs11Backend *self = SEAHORSE_PKCS11_BACKEND (collection);
+	return g_list_length (self->slots);
+}
+
+static GList *
+seahorse_pkcs11_backend_get_objects (GcrCollection *collection)
+{
+	SeahorsePkcs11Backend *self = SEAHORSE_PKCS11_BACKEND (collection);
+	return g_list_copy (self->slots);
+}
+
+static gboolean
+seahorse_pkcs11_backend_contains (GcrCollection *collection,
+                                  GObject *object)
+{
+	SeahorsePkcs11Backend *self = SEAHORSE_PKCS11_BACKEND (collection);
+	return g_list_find (self->slots, object) != NULL;
+}
+
+static void
+seahorse_pkcs11_backend_collection_init (GcrCollectionIface *iface)
+{
+	iface->contains = seahorse_pkcs11_backend_contains;
+	iface->get_length = seahorse_pkcs11_backend_get_length;
+	iface->get_objects = seahorse_pkcs11_backend_get_objects;
+}
+
+GcrCollection *
+seahorse_pkcs11_backend_initialize (void)
+{
+	SeahorsePkcs11Backend *self;
+
+	self = g_object_new (SEAHORSE_TYPE_PKCS11_BACKEND, NULL);
+
+	return GCR_COLLECTION (self);
+}
+
+SeahorsePkcs11Backend *
+seahorse_pkcs11_backend_get (void)
+{
+	g_return_val_if_fail (pkcs11_backend, NULL);
+	return pkcs11_backend;
+}
diff --git a/pkcs11/seahorse-pkcs11-backend.h b/pkcs11/seahorse-pkcs11-backend.h
new file mode 100644
index 0000000..b4b040e
--- /dev/null
+++ b/pkcs11/seahorse-pkcs11-backend.h
@@ -0,0 +1,46 @@
+/*
+ * 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_BACKEND_H_
+#define SEAHORSE_PKCS11_BACKEND_H_
+
+#include "seahorse-pkcs11.h"
+
+#include <gcr/gcr.h>
+
+#define SEAHORSE_PKCS11_STR                    "pkcs11"
+#define SEAHORSE_PKCS11                         (g_quark_from_static_string (SEAHORSE_PKCS11_STR))
+
+#define SEAHORSE_TYPE_PKCS11_BACKEND            (seahorse_pkcs11_backend_get_type ())
+#define SEAHORSE_PKCS11_BACKEND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PKCS11_BACKEND, SeahorsePkcs11Backend))
+#define SEAHORSE_PKCS11_BACKEND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_PKCS11_BACKEND, SeahorsePkcs11BackendClass))
+#define SEAHORSE_IS_PKCS11_BACKEND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_PKCS11_BACKEND))
+#define SEAHORSE_IS_PKCS11_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_PKCS11_BACKEND))
+#define SEAHORSE_PKCS11_BACKEND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_PKCS11_BACKEND, SeahorsePkcs11BackendClass))
+
+typedef struct _SeahorsePkcs11Backend SeahorsePkcs11Backend;
+typedef struct _SeahorsePkcs11BackendClass SeahorsePkcs11BackendClass;
+
+GType                    seahorse_pkcs11_backend_get_type      (void) G_GNUC_CONST;
+
+SeahorsePkcs11Backend *  seahorse_pkcs11_backend_get           (void);
+
+#endif /* SEAHORSE_PKCS11_BACKEND_H_ */
diff --git a/pkcs11/seahorse-pkcs11-certificate.c b/pkcs11/seahorse-pkcs11-certificate.c
index 03f4c13..b371ead 100644
--- a/pkcs11/seahorse-pkcs11-certificate.c
+++ b/pkcs11/seahorse-pkcs11-certificate.c
@@ -111,7 +111,6 @@ seahorse_pkcs11_certificate_realize (SeahorsePkcs11Certificate *self)
 	identifier = calc_display_id (self);
 
 	g_object_set (self,
-		      "location", SEAHORSE_LOCATION_LOCAL,
 		      "usage", SEAHORSE_USAGE_PUBLIC_KEY,
 		      "flags", flags,
 		      "identifier", identifier,
diff --git a/pkcs11/seahorse-pkcs11-helpers.c b/pkcs11/seahorse-pkcs11-helpers.c
index d516e7d..332ecae 100644
--- a/pkcs11/seahorse-pkcs11-helpers.c
+++ b/pkcs11/seahorse-pkcs11-helpers.c
@@ -25,129 +25,22 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <gck/pkcs11.h>
-
-static char* 
-seahorse_pkcs11_klass_to_string (gulong klass) 
+guint
+seahorse_pkcs11_ulong_hash (gconstpointer v)
 {
-	switch (klass)
-	{
-	case CKO_DATA:
-		return g_strdup ("data");
-	case CKO_CERTIFICATE:
-		return g_strdup ("certificate");
-	case CKO_PRIVATE_KEY:
-		return g_strdup ("private-key");
-	case CKO_PUBLIC_KEY:
-		return g_strdup ("public-key");
-	default:
-		return g_strdup_printf ("%lu", klass);
-	}
-}
+	const signed char *p = v;
+	guint32 i, h = *p;
 
-static gulong 
-seahorse_pkcs11_string_to_klass (const char* str) 
-{
-	gulong klass;
-	gchar *end;
-	
-	g_return_val_if_fail (str != NULL, 0UL);
-	
-	if (g_str_equal (str, "data"))
-		return CKO_DATA;
-	if (g_str_equal (str, "certificate"))
-		return CKO_CERTIFICATE;
-	if (g_str_equal (str, "private-key"))
-		return CKO_PRIVATE_KEY;
-	if (g_str_equal (str, "public-key"))
-		return CKO_PUBLIC_KEY;
-	
-	klass = strtoul (str, &end, 10);
-	if (!*end) {
-		g_warning ("unrecognized and unparsable PKCS#11 class: %s", str);
-		return (gulong)-1;
-	}
-	
-	return klass;
-}
+	for(i = 0; i < sizeof (gulong); ++i)
+		h = (h << 5) - h + *(p++);
 
-GQuark 
-seahorse_pkcs11_id_from_attributes (GckAttributes* attrs)
-{
-	gulong klass;
-	GckAttribute* attr;
-	gchar *id, *encoded, *klass_str;
-	GQuark quark;
-	
-	g_return_val_if_fail (attrs != NULL, 0U);
-	
-	/* These cases should have been covered by the programmer */
-
-	klass = 0;
-	if (!gck_attributes_find_ulong (attrs, CKA_CLASS, &klass)) {
-		g_warning ("Cannot create object id. PKCS#11 attribute set did not contain CKA_CLASS.");
-		return 0;
-	}
-	
-	attr = gck_attributes_find (attrs, CKA_ID);
-	if (attr == NULL) {
-		g_warning ("Cannot create object id. PKCS#11 attribute set did not contain CKA_ID");
-		return 0;
-	}
-	
-	encoded = g_base64_encode (attr->value, attr->length);
-	klass_str = seahorse_pkcs11_klass_to_string (klass);
-	id = g_strdup_printf ("%s:%s/%s", SEAHORSE_PKCS11_TYPE_STR, klass_str, encoded);
-	g_free (encoded);
-	g_free (klass_str);
-	
-	quark = g_quark_from_string (id);
-	g_free (id);
-	
-	return quark;
+	return h;
 }
 
-
-gboolean 
-seahorse_pkcs11_id_to_attributes (GQuark id, GckAttributes* attrs)
+gboolean
+seahorse_pkcs11_ulong_equal (gconstpointer v1,
+                             gconstpointer v2)
 {
-	const gchar* value;
-	guchar *ckid;
-	gsize n_ckid;
-	gulong klass;
-	gchar **parts;
-
-	g_return_val_if_fail (attrs != NULL, FALSE);
-	
-	if (id == 0)
-		return FALSE;
-
-	value = g_quark_to_string (id);
-	
-	parts = g_strsplit_set (value, ":/", 3);
-	if (!parts[0] || !g_str_equal (parts[0], SEAHORSE_PKCS11_TYPE_STR) ||
-	    !parts[1] || !parts[2]) {
-		g_strfreev (parts);
-		return FALSE;
-	}
-	
-	klass = seahorse_pkcs11_string_to_klass (parts[1]);
-	if (klass == -1) {
-		g_strfreev (parts);
-		return FALSE;
-	}
-
-	ckid = g_base64_decode (parts[2], &n_ckid);
-	g_strfreev (parts);
-
-	if (!id) 
-		return FALSE;
-		
-	gck_attributes_add_ulong (attrs, CKA_CLASS, klass);
-	gck_attributes_add_data (attrs, CKA_ID, ckid, n_ckid);
-	g_free (ckid);
-
-	return TRUE;
+	return *((const gulong*)v1) == *((const gulong*)v2);
 }
 
-
diff --git a/pkcs11/seahorse-pkcs11-helpers.h b/pkcs11/seahorse-pkcs11-helpers.h
index f967409..5115bd1 100644
--- a/pkcs11/seahorse-pkcs11-helpers.h
+++ b/pkcs11/seahorse-pkcs11-helpers.h
@@ -25,8 +25,10 @@
 #include <glib.h>
 #include <gck/gck.h>
 
-GQuark seahorse_pkcs11_id_from_attributes (GckAttributes* attrs);
-gboolean seahorse_pkcs11_id_to_attributes (GQuark id, GckAttributes* attrs);
+guint               seahorse_pkcs11_ulong_hash              (gconstpointer v);
+
+gboolean            seahorse_pkcs11_ulong_equal             (gconstpointer v1,
+                                                             gconstpointer v2);
 
 
 #endif
diff --git a/pkcs11/seahorse-pkcs11-object.c b/pkcs11/seahorse-pkcs11-object.c
index da8bd14..1dd030e 100644
--- a/pkcs11/seahorse-pkcs11-object.c
+++ b/pkcs11/seahorse-pkcs11-object.c
@@ -156,7 +156,6 @@ seahorse_pkcs11_object_realize (SeahorsePkcs11Object *self)
 	gck_attributes_find_string (self->pv->pkcs11_attributes, CKA_LABEL, &label);
 	g_object_set (self,
 		      "label", label,
-		      "location", SEAHORSE_LOCATION_LOCAL,
 		      "flags", flags,
 		      NULL);
 
@@ -174,12 +173,9 @@ static GObject*
 seahorse_pkcs11_object_constructor (GType type, guint n_props, GObjectConstructParam *props) 
 {
 	SeahorsePkcs11Object *self = SEAHORSE_PKCS11_OBJECT (G_OBJECT_CLASS (seahorse_pkcs11_object_parent_class)->constructor(type, n_props, props));
-	
-	g_return_val_if_fail (self, NULL);	
 
 	g_return_val_if_fail (self->pv->pkcs11_object, NULL);
-	g_object_set (self, "id", seahorse_pkcs11_object_cannonical_id (self->pv->pkcs11_object), NULL);
-	
+
 	return G_OBJECT (self);
 }
 
@@ -382,28 +378,3 @@ seahorse_pkcs11_object_require_attributes (SeahorsePkcs11Object *self, const gul
 	load_object_attributes (self, attr_types, n_attr_types);
 	return FALSE;
 }
-
-GQuark
-seahorse_pkcs11_object_cannonical_id (GckObject *object)
-{
-	GckSession *session;
-	GckSlot *slot;
-	GQuark quark;
-	gchar *text;
-
-	/* TODO: This whole ID thing needs rethinking */
-
-	session = gck_object_get_session (object);
-	slot = gck_session_get_slot (session);
-
-	text = g_strdup_printf("%s:%lu/%lu", SEAHORSE_PKCS11_TYPE_STR, 
-	                       gck_slot_get_handle (slot),
-	                       gck_object_get_handle (object));
-
-	g_object_unref (session);
-	g_object_unref (slot);
-
-	quark = g_quark_from_string (text);
-	g_free (text);
-	return quark;	
-}
diff --git a/pkcs11/seahorse-pkcs11-object.h b/pkcs11/seahorse-pkcs11-object.h
index b3612a8..1b110bb 100644
--- a/pkcs11/seahorse-pkcs11-object.h
+++ b/pkcs11/seahorse-pkcs11-object.h
@@ -72,6 +72,4 @@ gboolean                    seahorse_pkcs11_object_require_attributes     (Seaho
                                                                            const gulong *attr_types,
                                                                            gsize n_attr_types);
 
-GQuark                      seahorse_pkcs11_object_cannonical_id          (GckObject *object);
-
 #endif /* __SEAHORSE_PKCS11_OBJECT_H__ */
diff --git a/pkcs11/seahorse-pkcs11-operations.c b/pkcs11/seahorse-pkcs11-operations.c
index 85b4fcf..f5fc3c4 100644
--- a/pkcs11/seahorse-pkcs11-operations.c
+++ b/pkcs11/seahorse-pkcs11-operations.c
@@ -22,6 +22,7 @@
 
 #include "config.h"
 
+#include "seahorse-pkcs11-helpers.h"
 #include "seahorse-pkcs11-object.h"
 #include "seahorse-pkcs11-operations.h"
 #include "seahorse-pkcs11-source.h"
@@ -33,6 +34,8 @@
 
 #include <glib/gi18n.h>
 
+#include <gcr/gcr.h>
+
 typedef struct {
 	SeahorsePkcs11Source *source;
 	GCancellable *cancellable;
@@ -51,22 +54,14 @@ pkcs11_refresh_free (gpointer data)
 	g_free (closure);
 }
 
-static guint
-ulong_hash (gconstpointer k)
-{
-	return (guint)*((gulong*)k); 
-}
-
-static gboolean
-ulong_equal (gconstpointer a, gconstpointer b)
-{
-	return *((gulong*)a) == *((gulong*)b); 
-}
-
 static gboolean
-remove_each_object (gpointer key, gpointer value, gpointer data)
+remove_each_object (gpointer key,
+                    gpointer value,
+                    gpointer user_data)
 {
-	seahorse_context_remove_object (NULL, value);
+	SeahorsePkcs11Source *source = SEAHORSE_PKCS11_SOURCE (user_data);
+	SeahorsePkcs11Object *object = SEAHORSE_PKCS11_OBJECT (value);
+	seahorse_pkcs11_source_remove_object (source, object);
 	return TRUE;
 }
 
@@ -94,7 +89,7 @@ on_refresh_find_objects (GckSession *session,
 		}
 
 		/* Remove everything not found from the context */
-		g_hash_table_foreach_remove (closure->checks, remove_each_object, NULL);
+		g_hash_table_foreach_remove (closure->checks, remove_each_object, closure->source);
 	}
 
 	g_simple_async_result_complete (res);
@@ -145,15 +140,15 @@ seahorse_pkcs11_refresh_async (SeahorsePkcs11Source *source,
 	res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
 	                                 seahorse_pkcs11_refresh_async);
 	closure = g_new0 (pkcs11_refresh_closure, 1);
-	closure->checks = g_hash_table_new_full (ulong_hash, ulong_equal,
+	closure->checks = g_hash_table_new_full (seahorse_pkcs11_ulong_hash,
+	                                         seahorse_pkcs11_ulong_equal,
 	                                         g_free, g_object_unref);
 	closure->source = g_object_ref (source);
 	closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
 	g_simple_async_result_set_op_res_gpointer (res, closure, pkcs11_refresh_free);
 
 	/* Make note of all the objects that were there */
-	objects = seahorse_context_get_objects (seahorse_context_instance (),
-	                                        SEAHORSE_SOURCE (source));
+	objects = gcr_collection_get_objects (GCR_COLLECTION (source));
 	for (l = objects; l; l = g_list_next (l)) {
 		if (g_object_class_find_property (G_OBJECT_GET_CLASS (l->data), "pkcs11-handle")) {
 			g_object_get (l->data, "pkcs11-handle", &handle, NULL);
@@ -213,6 +208,7 @@ on_delete_object_completed (GObject *source,
 	pkcs11_delete_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
 	GError *error = NULL;
 	SeahorseObject *object;
+	SeahorsePkcs11Source *pkcs11_source;
 
 	object = g_queue_pop_head (closure->objects);
 	seahorse_progress_end (closure->cancellable, object);
@@ -230,8 +226,8 @@ on_delete_object_completed (GObject *source,
 	}
 
 	if (error == NULL) {
-		seahorse_context_remove_object (seahorse_context_instance (),
-		                                object);
+		pkcs11_source = SEAHORSE_PKCS11_SOURCE (seahorse_object_get_source (object));
+		seahorse_pkcs11_source_remove_object (pkcs11_source, SEAHORSE_PKCS11_OBJECT (object));
 		pkcs11_delete_one_object (res);
 	}
 
diff --git a/pkcs11/seahorse-pkcs11-source.c b/pkcs11/seahorse-pkcs11-source.c
index 4320d4d..5a58d52 100644
--- a/pkcs11/seahorse-pkcs11-source.c
+++ b/pkcs11/seahorse-pkcs11-source.c
@@ -34,6 +34,7 @@
 
 #include "seahorse-pkcs11.h"
 #include "seahorse-pkcs11-certificate.h"
+#include "seahorse-pkcs11-helpers.h"
 #include "seahorse-pkcs11-object.h"
 #include "seahorse-pkcs11-operations.h"
 #include "seahorse-pkcs11-source.h"
@@ -43,19 +44,22 @@
 enum {
     PROP_0,
     PROP_SLOT,
-    PROP_SOURCE_TAG,
-    PROP_SOURCE_LOCATION,
     PROP_FLAGS
 };
 
 struct _SeahorsePkcs11SourcePrivate {
 	GckSlot *slot;
+	GHashTable *objects;
 };
 
-static void seahorse_source_iface (SeahorseSourceIface *iface);
+static void          seahorse_pkcs11_source_iface      (SeahorseSourceIface *iface);
+
+static void          seahorse_pkcs11_collection_iface  (GcrCollectionIface *iface);
 
 G_DEFINE_TYPE_EXTENDED (SeahorsePkcs11Source, seahorse_pkcs11_source, G_TYPE_OBJECT, 0,
-                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_source_iface));
+                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_pkcs11_source_iface);
+                        G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_pkcs11_collection_iface);
+);
 
 /* -----------------------------------------------------------------------------
  * OBJECT
@@ -65,6 +69,9 @@ static void
 seahorse_pkcs11_source_init (SeahorsePkcs11Source *self)
 {
 	self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_PKCS11_SOURCE, SeahorsePkcs11SourcePrivate));
+	self->pv->objects = g_hash_table_new_full (seahorse_pkcs11_ulong_hash,
+	                                           seahorse_pkcs11_ulong_equal,
+	                                           g_free, g_object_unref);
 }
 
 static GObject*  
@@ -91,12 +98,6 @@ seahorse_pkcs11_source_get_property (GObject *object, guint prop_id, GValue *val
 	case PROP_SLOT:
 		g_value_set_object (value, self->pv->slot);
 		break;
-	case PROP_SOURCE_TAG:
-		g_value_set_uint (value, SEAHORSE_PKCS11_TYPE);
-		break;
-	case PROP_SOURCE_LOCATION:
-		g_value_set_enum (value, SEAHORSE_LOCATION_LOCAL);
-		break;
 	case PROP_FLAGS:
 		g_value_set_uint (value, 0);
 		break;
@@ -120,25 +121,6 @@ seahorse_pkcs11_source_set_property (GObject *object, guint prop_id, const GValu
 }
 
 static void
-seahorse_pkcs11_source_load_async (SeahorseSource *source,
-                                   GCancellable *cancellable,
-                                   GAsyncReadyCallback callback,
-                                   gpointer user_data)
-{
-	seahorse_pkcs11_refresh_async (SEAHORSE_PKCS11_SOURCE (source),
-	                               cancellable, callback, user_data);
-}
-
-static gboolean
-seahorse_pkcs11_source_load_finish (SeahorseSource *source,
-                                    GAsyncResult *result,
-                                    GError **error)
-{
-	return seahorse_pkcs11_refresh_finish (SEAHORSE_PKCS11_SOURCE (source),
-	                                       result, error);
-}
-
-static void
 seahorse_pkcs11_source_dispose (GObject *obj)
 {
 	SeahorsePkcs11Source *self = SEAHORSE_PKCS11_SOURCE (obj);
@@ -155,7 +137,8 @@ static void
 seahorse_pkcs11_source_finalize (GObject *obj)
 {
 	SeahorsePkcs11Source *self = SEAHORSE_PKCS11_SOURCE (obj);
-  
+
+	g_hash_table_destroy (self->pv->objects);
 	g_assert (self->pv->slot == NULL);
     
 	G_OBJECT_CLASS (seahorse_pkcs11_source_parent_class)->finalize (obj);
@@ -184,17 +167,50 @@ seahorse_pkcs11_source_class_init (SeahorsePkcs11SourceClass *klass)
 	         g_param_spec_uint ("flags", "Flags", "Object Source flags.", 
 	                            0, G_MAXUINT, 0, G_PARAM_READABLE));
 
-	g_object_class_override_property (gobject_class, PROP_SOURCE_TAG, "source-tag");
-	g_object_class_override_property (gobject_class, PROP_SOURCE_LOCATION, "source-location");
-    
 	seahorse_registry_register_type (NULL, SEAHORSE_TYPE_PKCS11_SOURCE, "source", "local", SEAHORSE_PKCS11_TYPE_STR, NULL);
 }
 
 static void 
-seahorse_source_iface (SeahorseSourceIface *iface)
+seahorse_pkcs11_source_iface (SeahorseSourceIface *iface)
+{
+
+}
+
+
+static guint
+seahorse_pkcs11_source_get_length (GcrCollection *collection)
 {
-	iface->load_async = seahorse_pkcs11_source_load_async;
-	iface->load_finish = seahorse_pkcs11_source_load_finish;
+	SeahorsePkcs11Source *self = SEAHORSE_PKCS11_SOURCE (collection);
+	return g_hash_table_size (self->pv->objects);
+}
+
+static GList *
+seahorse_pkcs11_source_get_objects (GcrCollection *collection)
+{
+	SeahorsePkcs11Source *self = SEAHORSE_PKCS11_SOURCE (collection);
+	return g_hash_table_get_values (self->pv->objects);
+}
+
+static gboolean
+seahorse_pkcs11_source_contains (GcrCollection *collection,
+                                 GObject *object)
+{
+	SeahorsePkcs11Source *self = SEAHORSE_PKCS11_SOURCE (collection);
+	gulong handle;
+
+	if (!SEAHORSE_PKCS11_IS_OBJECT (object))
+		return FALSE;
+
+	handle = seahorse_pkcs11_object_get_pkcs11_handle (SEAHORSE_PKCS11_OBJECT (object));
+	return g_hash_table_lookup (self->pv->objects, &handle) == object;
+}
+
+static void
+seahorse_pkcs11_collection_iface (GcrCollectionIface *iface)
+{
+	iface->get_length = seahorse_pkcs11_source_get_length;
+	iface->get_objects = seahorse_pkcs11_source_get_objects;
+	iface->contains = seahorse_pkcs11_source_contains;
 }
 
 /* -------------------------------------------------------------------------- 
@@ -215,18 +231,18 @@ seahorse_pkcs11_source_get_slot (SeahorsePkcs11Source *self)
 }
 
 void
-seahorse_pkcs11_source_receive_object (SeahorsePkcs11Source *self, GckObject *obj)
+seahorse_pkcs11_source_receive_object (SeahorsePkcs11Source *self,
+                                       GckObject *obj)
 {
-	GQuark id = seahorse_pkcs11_object_cannonical_id (obj);
 	SeahorsePkcs11Certificate *cert;
 	SeahorseObject *prev;
-	
+	gulong handle;
+
 	g_return_if_fail (SEAHORSE_IS_PKCS11_SOURCE (self));
-	
-	/* TODO: This will need to change once we get other kinds of objects */
-	
-	prev = seahorse_context_get_object (NULL, SEAHORSE_SOURCE (self), id);
-	if (prev) {
+
+	handle = gck_object_get_handle (obj);
+	prev = g_hash_table_lookup (self->pv->objects, &handle);
+	if (prev != NULL) {
 		seahorse_pkcs11_object_refresh (SEAHORSE_PKCS11_OBJECT (prev));
 		g_object_unref (obj);
 		return;
@@ -234,5 +250,27 @@ seahorse_pkcs11_source_receive_object (SeahorsePkcs11Source *self, GckObject *ob
 
 	cert = seahorse_pkcs11_certificate_new (obj);
 	g_object_set (cert, "source", self, NULL);
-	seahorse_context_add_object (NULL, SEAHORSE_OBJECT (cert));
+
+	g_hash_table_insert (self->pv->objects, g_memdup (&handle, sizeof (handle)), cert);
+	gcr_collection_emit_added (GCR_COLLECTION (self), G_OBJECT (cert));
+}
+
+void
+seahorse_pkcs11_source_remove_object (SeahorsePkcs11Source *self,
+                                      SeahorsePkcs11Object *object)
+{
+	gulong handle;
+
+	g_return_if_fail (SEAHORSE_IS_PKCS11_SOURCE (self));
+	g_return_if_fail (SEAHORSE_PKCS11_IS_OBJECT (object));
+
+	g_object_ref (object);
+
+	handle = seahorse_pkcs11_object_get_pkcs11_handle (object);
+	g_return_if_fail (g_hash_table_lookup (self->pv->objects, &handle) == object);
+
+	g_hash_table_remove (self->pv->objects, &handle);
+	gcr_collection_emit_removed (GCR_COLLECTION (self), G_OBJECT (object));
+
+	g_object_unref (object);
 }
diff --git a/pkcs11/seahorse-pkcs11-source.h b/pkcs11/seahorse-pkcs11-source.h
index e3102cf..5a84b26 100644
--- a/pkcs11/seahorse-pkcs11-source.h
+++ b/pkcs11/seahorse-pkcs11-source.h
@@ -24,6 +24,7 @@
 #define __SEAHORSE_PKCS11_SOURCE_H__
 
 #include "seahorse-source.h"
+#include "seahorse-pkcs11-object.h"
 
 #include <gck/gck.h>
 
@@ -55,4 +56,7 @@ GckSlot*               seahorse_pkcs11_source_get_slot          (SeahorsePkcs11S
 
 void                   seahorse_pkcs11_source_receive_object    (SeahorsePkcs11Source *self, GckObject *obj);
 
+void                   seahorse_pkcs11_source_remove_object     (SeahorsePkcs11Source *self,
+                                                                 SeahorsePkcs11Object *object);
+
 #endif /* __SEAHORSE_PKCS11_SOURCE_H__ */
diff --git a/pkcs11/seahorse-pkcs11.h b/pkcs11/seahorse-pkcs11.h
index 70e69ef..b324330 100644
--- a/pkcs11/seahorse-pkcs11.h
+++ b/pkcs11/seahorse-pkcs11.h
@@ -22,9 +22,17 @@
 #ifndef __SEAHORSE_PKCS11_H__
 #define __SEAHORSE_PKCS11_H__
 
+#ifdef WITH_PKCS11
+
 #include <glib.h>
 
+#include <gcr/gcr.h>
+
 #define SEAHORSE_PKCS11_TYPE_STR "pkcs11"
 #define SEAHORSE_PKCS11_TYPE g_quark_from_string ("pkcs11")
 
+GcrCollection *       seahorse_pkcs11_backend_initialize    (void);
+
+#endif /* WITH_PKCS11 */
+
 #endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 3cb5505..05bcc2f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,20 +4,12 @@ localedir = $(datadir)/locale
 
 INCLUDES = -I$(top_builddir) \
 	-I$(top_srcdir) \
-	-I$(top_srcdir)/libegg \
 	-I$(top_srcdir)/libseahorse \
 	$(SEAHORSE_CFLAGS) \
 	-DSEAHORSE_UIDIR=\""$(uidir)"\" \
 	-DLOCALEDIR=\"$(localedir)\" \
 	-DGETTEXT_PACKAGE=\""seahorse\""
 
-if WITH_KEYSERVER
-KEYSERVER_SRCS = seahorse-keyserver-search.c seahorse-keyserver-sync.c seahorse-keyserver-sync.h
-KEYSERVER_SRCS += seahorse-keyserver-results.c seahorse-keyserver-results.h
-else
-KEYSERVER_SRCS = 
-endif
-
 if WITH_PGP
 PGP_LDADD = $(top_builddir)/pgp/libseahorse-pgp.la
 else
@@ -39,12 +31,9 @@ endif
 bin_PROGRAMS = seahorse
 
 seahorse_SOURCES = \
-	seahorse-preferences.c seahorse-preferences.h \
 	seahorse-generate-select.c seahorse-generate-select.h \
 	seahorse-key-manager.c seahorse-key-manager.h \
-	seahorse-key-manager-store.c seahorse-key-manager-store.h \
 	seahorse-main.c \
-	seahorse-viewer.c seahorse-viewer.h \
 	seahorse-windows.h \
 	$(KEYSERVER_SRCS)
 
diff --git a/src/seahorse-generate-select.h b/src/seahorse-generate-select.h
index 680f97b..c843124 100644
--- a/src/seahorse-generate-select.h
+++ b/src/seahorse-generate-select.h
@@ -47,9 +47,9 @@ struct _SeahorseGenerateSelectClass {
 	SeahorseWidgetClass parent_class;
 };
 
-void seahorse_generate_select_show (GtkWindow* parent);
 GType seahorse_generate_select_get_type (void);
 
+void        seahorse_generate_select_show       (GtkWindow *parent);
 
 G_END_DECLS
 
diff --git a/src/seahorse-key-manager.c b/src/seahorse-key-manager.c
index 8577c65..e65dc52 100644
--- a/src/seahorse-key-manager.c
+++ b/src/seahorse-key-manager.c
@@ -27,13 +27,11 @@
 #include "seahorse-key-manager.h"
 #include "seahorse-key-manager-store.h"
 #include "seahorse-preferences.h"
-#include "seahorse-windows.h"
-#include "seahorse-keyserver-results.h"
 
 #include "seahorse-progress.h"
 #include "seahorse-util.h"
 
-#include "gkr/seahorse-gkr.h"
+#include "gkr/seahorse-gkr-item.h"
 
 #include <glib/gi18n.h>
 
@@ -57,23 +55,24 @@ void           on_keymanager_import_button              (GtkButton* button,
 
 enum {
 	PROP_0,
+	PROP_SOURCES,
 	PROP_SELECTED
 };
 typedef struct _TabInfo {
 	guint id;
 	gint page;
 	GtkTreeView* view;
-	SeahorseCollection* collection;
+	SeahorseCollection *collection;
 	GtkWidget* widget;
 	SeahorseKeyManagerStore* store;
 } TabInfo;
 
 struct _SeahorseKeyManagerPrivate {
+	GcrCollection *sources;
+	GcrUnionCollection *collection;
 	GtkNotebook* notebook;
 	GtkActionGroup* view_actions;
 	GtkEntry* filter_entry;
-	GQuark track_selected_id;
-	guint track_selected_tab;
 	TabInfo* tabs;
 	GSettings *settings;
 };
@@ -91,10 +90,7 @@ enum  {
 } SeahorseKeyManagerTabs;
 
 static SeahorsePredicate pred_public = {
-	0, 
-	0, 
-	0, 
-	SEAHORSE_LOCATION_LOCAL, 
+	0,
 	SEAHORSE_USAGE_PUBLIC_KEY, 
 	0, 
 	0, 
@@ -102,10 +98,7 @@ static SeahorsePredicate pred_public = {
 };
 
 static SeahorsePredicate pred_private = {
-	0, 
-	0, 
-	0, 
-	SEAHORSE_LOCATION_LOCAL, 
+	0,
 	SEAHORSE_USAGE_PRIVATE_KEY, 
 	0, 
 	0, 
@@ -113,10 +106,7 @@ static SeahorsePredicate pred_private = {
 };
 
 static SeahorsePredicate pred_password = {
-	0, 
-	0, /* Tag filled in later */ 
-	0, 
-	SEAHORSE_LOCATION_LOCAL, 
+	0, /* type filled in later */
 	0, 
 	0, 
 	0, 
@@ -180,15 +170,6 @@ get_current_view (SeahorseKeyManager* self)
 	return tab->view;
 }
 
-static guint 
-get_tab_id (SeahorseKeyManager* self, TabInfo* tab) 
-{
-	g_return_val_if_fail (SEAHORSE_IS_KEY_MANAGER (self), 0U);
-	if (tab == NULL) 
-		return 0;
-	return tab->id;
-}
-
 static void 
 set_tab_current (SeahorseKeyManager* self, TabInfo* tab) 
 {
@@ -198,67 +179,9 @@ set_tab_current (SeahorseKeyManager* self, TabInfo* tab)
 }
 
 static gboolean 
-fire_selection_changed (SeahorseKeyManager* self) 
+fire_selection_changed (gpointer user_data)
 {
-	gboolean selected;
-	gint rows;
-	GtkTreeView* view;
-	gboolean dotracking;
-	guint tabid;
-	GQuark keyid;
-	GList* objects;
-
-	g_return_val_if_fail (SEAHORSE_IS_KEY_MANAGER (self), FALSE);
-
-	selected = FALSE;
-	rows = 0;
-
-	view = get_current_view (self);
-	
-	if (view != NULL) {
-		GtkTreeSelection* selection = gtk_tree_view_get_selection (view);
-		rows = gtk_tree_selection_count_selected_rows (selection);
-		selected = rows > 0;
-	}
-	
-	dotracking = TRUE;
-	
-	/* See which tab we're on, if different from previous, no tracking */
-	tabid = get_tab_id (self, get_tab_info (self, -1));
-	if (tabid != self->pv->track_selected_tab) {
-		dotracking = FALSE;
-		self->pv->track_selected_tab = tabid;
-	}
-	
-	/* Retrieve currently tracked, and reset tracking */
-	keyid = self->pv->track_selected_id;
-	self->pv->track_selected_id = 0;
-	
-	/* no selection, see if selected key moved to another tab */
-	if (dotracking && rows == 0 && keyid != 0) {
-		/* Find it */
-		SeahorseObject* obj = seahorse_context_find_object (NULL, keyid, SEAHORSE_LOCATION_LOCAL);
-		if (obj != NULL) {
-			/* If it's still around, then select it */
-			TabInfo* tab = get_tab_for_object (self, obj);
-			if (tab != NULL && tab != get_tab_info (self, -1)) {
-				/* Make sure we don't end up in a loop  */
-				g_assert (self->pv->track_selected_id == 0);
-				seahorse_viewer_set_selected (SEAHORSE_VIEWER (self), obj);
-			}
-		}
-	}
-
-	if (selected) {
-		seahorse_viewer_set_numbered_status (SEAHORSE_VIEWER (self), ngettext ("Selected %d key", "Selected %d keys", rows), rows);
-		objects = seahorse_viewer_get_selected_objects (SEAHORSE_VIEWER (self));
-		
-		/* If one key is selected then mark it down for following across tabs */
-		if (objects->data)
-			self->pv->track_selected_id = seahorse_object_get_id (objects->data);
-		
-		g_list_free (objects);
-	}
+	SeahorseKeyManager* self = SEAHORSE_KEY_MANAGER (user_data);
 
 	/* Fire the signal */
 	g_signal_emit_by_name (self, "selection-changed");
@@ -273,10 +196,7 @@ on_tab_changed (GtkNotebook* notebook, void* unused, guint page_num, SeahorseKey
 	g_return_if_fail (SEAHORSE_IS_KEY_MANAGER (self));
 	g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
 	gtk_entry_set_text (self->pv->filter_entry, "");
-	
-	/* Don't track the selected key when tab is changed on purpose */
-	self->pv->track_selected_id = 0;
-	
+
 	fire_selection_changed (self);
 }
 
@@ -363,7 +283,8 @@ initialize_tab (SeahorseKeyManager* self, const char* tabwidget, guint tabid, co
 	self->pv->tabs[tabid].page = gtk_notebook_page_num (self->pv->notebook, self->pv->tabs[tabid].widget);
 	g_return_if_fail (self->pv->tabs[tabid].page >= 0);
 
-	collection = seahorse_collection_new_for_predicate ((SeahorsePredicate*)pred, NULL);
+	collection = seahorse_collection_new_for_predicate (GCR_COLLECTION (self->pv->collection),
+	                                                    (SeahorsePredicate*)pred, NULL);
 	self->pv->tabs[tabid].collection = SEAHORSE_COLLECTION (collection);
 
 	/* Init key list & selection settings */
@@ -377,8 +298,8 @@ initialize_tab (SeahorseKeyManager* self, const char* tabwidget, guint tabid, co
 	gtk_widget_realize (GTK_WIDGET (view));
 
 	/* Add new key store and associate it */
-	self->pv->tabs[tabid].store = seahorse_key_manager_store_new (collection, view,
-	                                                              self->pv->settings);
+	self->pv->tabs[tabid].store = seahorse_key_manager_store_new (GCR_COLLECTION (collection),
+	                                                              view, self->pv->settings);
 }
 
 static gboolean 
@@ -392,8 +313,8 @@ on_first_timer (SeahorseKeyManager* self)
 	 * Although not all the keys have completed we'll know whether we have 
 	 * any or not at this point 
 	 */
-	
-	if (seahorse_context_get_count (NULL) == 0) {
+
+	if (gcr_collection_get_length (GCR_COLLECTION (self->pv->collection)) == 0) {
 		widget = seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "first-time-box");
 		gtk_widget_show (widget);
 	}
@@ -421,6 +342,8 @@ on_filter_changed (GtkEntry* entry, SeahorseKeyManager* self)
 		g_object_set (self->pv->tabs[i].store, "filter", text, NULL);
 }
 
+#ifdef REFACTOR_IMPORT
+
 static void 
 on_import_complete (GObject *source,
                     GAsyncResult *result,
@@ -518,22 +441,30 @@ import_prompt (SeahorseKeyManager* self)
 	g_free (uri);
 }
 
+#endif /* REFACTOR_IMPORT */
+
 static void 
 on_key_import_file (GtkAction* action, SeahorseKeyManager* self) 
 {
+#ifdef REFACTOR_IMPORT
 	g_return_if_fail (SEAHORSE_IS_KEY_MANAGER (self));
 	g_return_if_fail (GTK_IS_ACTION (action));
 	import_prompt (self);
+#endif
 }
 
 G_MODULE_EXPORT void 
 on_keymanager_import_button (GtkButton* button, SeahorseKeyManager* self) 
 {
+#ifdef REFACTOR_IMPORT
 	g_return_if_fail (SEAHORSE_IS_KEY_MANAGER (self));
 	g_return_if_fail (GTK_IS_BUTTON (button));
 	import_prompt (self);
+#endif
 }
 
+#ifdef REFACTOR_IMPORT
+
 static void 
 import_text (SeahorseKeyManager* self, const char* text) 
 {
@@ -613,9 +544,12 @@ on_clipboard_received (GtkClipboard* board, const char* text, SeahorseKeyManager
     		import_text (self, text);
 }
 
+#endif /* REFACTOR_IMPORT */
+
 static void 
 on_key_import_clipboard (GtkAction* action, SeahorseKeyManager* self) 
 {
+#ifdef REFACTOR_IMPORT
 	GdkAtom atom;
 	GtkClipboard* board;
 	
@@ -625,32 +559,8 @@ on_key_import_clipboard (GtkAction* action, SeahorseKeyManager* self)
 	atom = gdk_atom_intern ("CLIPBOARD", FALSE);
 	board = gtk_clipboard_get (atom);
 	gtk_clipboard_request_text (board, (GtkClipboardTextReceivedFunc)on_clipboard_received, self);
-}
-
-#ifdef WITH_KEYSERVER
-static void 
-on_remote_find (GtkAction* action, SeahorseKeyManager* self) 
-{
-	g_return_if_fail (SEAHORSE_IS_KEY_MANAGER (self));
-	g_return_if_fail (GTK_IS_ACTION (action));
-	seahorse_keyserver_search_show (seahorse_viewer_get_window (SEAHORSE_VIEWER (self)));
-}
-
-static void 
-on_remote_sync (GtkAction* action, SeahorseKeyManager* self) 
-{
-	GList* objects;
-
-	g_return_if_fail (SEAHORSE_IS_KEY_MANAGER (self));
-	g_return_if_fail (GTK_IS_ACTION (action));
-	
-	objects = seahorse_viewer_get_selected_objects (SEAHORSE_VIEWER (self));
-	if (objects == NULL)
-		objects = seahorse_context_find_objects (NULL, 0, 0, SEAHORSE_LOCATION_LOCAL);
-	seahorse_keyserver_sync_show (objects, seahorse_viewer_get_window (SEAHORSE_VIEWER (self)));
-	g_list_free (objects);
-}
 #endif
+}
 
 static gboolean
 quit_app_later (gpointer unused)
@@ -741,22 +651,13 @@ static const GtkActionEntry GENERAL_ENTRIES[] = {
 	{ "app-quit", GTK_STOCK_QUIT, NULL, "<control>Q", 
 	  N_("Close this program"), G_CALLBACK (on_app_quit) }, 
 	{ "file-new", GTK_STOCK_NEW, N_("_New..."), "<control>N", 
-	  N_("Create a new key or item"), G_CALLBACK (on_file_new) }, 
+	  N_("Create a new key or item"), G_CALLBACK (on_file_new) },
 	{ "file-import", GTK_STOCK_OPEN, N_("_Import..."), "<control>I", 
 	  N_("Import from a file"), G_CALLBACK (on_key_import_file) }, 
 	{ "edit-import-clipboard", GTK_STOCK_PASTE, NULL, "<control>V", 
 	  N_("Import from the clipboard"), G_CALLBACK (on_key_import_clipboard) }
 };
 
-#ifdef WITH_KEYSERVER
-static const GtkActionEntry SERVER_ENTRIES[] = {
-	{ "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) }
-};
-#endif
-
 static const GtkToggleActionEntry VIEW_ENTRIES[] = {
 	{ "view-type", NULL, N_("T_ypes"), NULL, N_("Show type column"), 
 	  G_CALLBACK (on_view_type_activate), FALSE }, 
@@ -875,13 +776,6 @@ seahorse_key_manager_constructed (GObject *object)
 	gtk_action_group_add_actions (actions, GENERAL_ENTRIES, G_N_ELEMENTS (GENERAL_ENTRIES), self);
 	seahorse_viewer_include_actions (SEAHORSE_VIEWER (self), actions);
 
-#ifdef WITH_KEYSERVER	
-	actions = gtk_action_group_new ("keyserver");
-	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
-	gtk_action_group_add_actions (actions, SERVER_ENTRIES, G_N_ELEMENTS (SERVER_ENTRIES), self);
-	seahorse_viewer_include_actions (SEAHORSE_VIEWER (self), actions);
-#endif /* WITH_KEYSERVER */
-	
 	self->pv->view_actions = gtk_action_group_new ("view");
 	gtk_action_group_set_translation_domain (self->pv->view_actions, GETTEXT_PACKAGE);
 	gtk_action_group_add_toggle_actions (self->pv->view_actions, VIEW_ENTRIES, G_N_ELEMENTS (VIEW_ENTRIES), self);
@@ -901,10 +795,11 @@ seahorse_key_manager_constructed (GObject *object)
 	/* close event */
 	g_signal_connect_object (seahorse_widget_get_toplevel (SEAHORSE_WIDGET (self)), 
 	                         "delete-event", G_CALLBACK (on_delete_event), self, 0);
-	
+
 	/* first time signals */
 	g_signal_connect_object (seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "import-button"), 
 	                         "clicked", G_CALLBACK (on_keymanager_import_button), self, 0);
+
 	g_signal_connect_object (seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "new-button"), 
 	                         "clicked", G_CALLBACK (on_keymanager_new_button), self, 0);
 	
@@ -981,7 +876,7 @@ seahorse_key_manager_constructed (GObject *object)
 	/* Initialize the tabs, and associate them up */
 	initialize_tab (self, "pub-key-tab", TAB_PUBLIC, "pub-key-list", &pred_public);
 	initialize_tab (self, "sec-key-tab", TAB_PRIVATE, "sec-key-list", &pred_private);
-	pred_password.tag = SEAHORSE_GKR_TYPE;
+	pred_password.type = SEAHORSE_TYPE_GKR_KEYRING;
 	initialize_tab (self, "password-tab", TAB_PASSWORD, "password-list", &pred_password);
 	
 	/* Set focus to the current key list */
@@ -1000,10 +895,12 @@ seahorse_key_manager_constructed (GObject *object)
 	gtk_target_list_add_uri_targets (targets, TARGETS_URIS);
 	gtk_target_list_add_text_targets (targets, TARGETS_PLAIN);
 	gtk_drag_dest_set_target_list (GTK_WIDGET (seahorse_viewer_get_window (SEAHORSE_VIEWER (self))), targets);
-	
+
+#ifdef REFACTOR_IMPORT
 	g_signal_connect_object (seahorse_viewer_get_window (SEAHORSE_VIEWER (self)), "drag-data-received", 
 	                         G_CALLBACK (on_target_drag_data_received), self, 0);
-	
+#endif
+
 	/* To show first time dialog */
 	g_timeout_add_seconds (1, (GSourceFunc)on_first_timer, self);
 }
@@ -1013,6 +910,7 @@ seahorse_key_manager_init (SeahorseKeyManager *self)
 {
 	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_KEY_MANAGER, SeahorseKeyManagerPrivate);
 	self->pv->settings = g_settings_new ("org.gnome.seahorse.manager");
+	self->pv->collection = GCR_UNION_COLLECTION (gcr_union_collection_new ());
 }
 
 static void
@@ -1020,7 +918,7 @@ seahorse_key_manager_finalize (GObject *obj)
 {
 	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (obj);
 	gint i;
-	
+
 	if (self->pv->view_actions)
 		g_object_unref (self->pv->view_actions);
 	self->pv->view_actions = NULL;
@@ -1037,6 +935,8 @@ seahorse_key_manager_finalize (GObject *obj)
 	}
 
 	g_clear_object (&self->pv->settings);
+	g_object_unref (self->pv->collection);
+	g_clear_object (&self->pv->sources);
 
 	G_OBJECT_CLASS (seahorse_key_manager_parent_class)->finalize (obj);
 }
@@ -1046,8 +946,17 @@ seahorse_key_manager_set_property (GObject *obj, guint prop_id, const GValue *va
                            GParamSpec *pspec)
 {
 	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (obj);
-	
+	GList *collections, *l;
+
 	switch (prop_id) {
+	case PROP_SOURCES:
+		g_return_if_fail (self->pv->sources == NULL);
+		self->pv->sources = g_value_dup_object (value);
+		collections = gcr_collection_get_objects (self->pv->sources);
+		for (l = collections; l != NULL; l = g_list_next (l))
+			gcr_union_collection_add (self->pv->collection, l->data);
+		g_list_free (collections);
+		break;
 	case PROP_SELECTED:
 		seahorse_viewer_set_selected (SEAHORSE_VIEWER (self), g_value_get_object (value));
 		break;
@@ -1062,8 +971,11 @@ 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_SOURCES:
+		g_value_set_object (value, self->pv->sources);
+		break;
 	case PROP_SELECTED:
 		g_value_set_object (value, seahorse_viewer_get_selected (SEAHORSE_VIEWER (self)));
 		break;
@@ -1091,7 +1003,11 @@ seahorse_key_manager_class_init (SeahorseKeyManagerClass *klass)
 	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 (G_OBJECT_CLASS (klass), PROP_SELECTED, "selected");
+	g_object_class_install_property (gobject_class, PROP_SOURCES,
+	               g_param_spec_object ("sources", "Sources" , "Collection of Sources",
+	                                    GCR_TYPE_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_override_property (gobject_class, PROP_SELECTED, "selected");
 }
 
 /* -----------------------------------------------------------------------------
@@ -1099,10 +1015,13 @@ seahorse_key_manager_class_init (SeahorseKeyManagerClass *klass)
  */
 
 
-GtkWindow* 
-seahorse_key_manager_show (void) 
+SeahorseWidget *
+seahorse_key_manager_show (GcrCollection *sources)
 {
-	SeahorseKeyManager *man = g_object_new (SEAHORSE_TYPE_KEY_MANAGER, "name", "key-manager", NULL);
+	SeahorseKeyManager *man = g_object_new (SEAHORSE_TYPE_KEY_MANAGER,
+	                                        "name", "key-manager",
+	                                        "sources", sources,
+	                                        NULL);
 	g_object_ref_sink (man);
-	return GTK_WINDOW (seahorse_widget_get_toplevel (SEAHORSE_WIDGET (man)));
+	return SEAHORSE_WIDGET (man);
 }
diff --git a/src/seahorse-key-manager.h b/src/seahorse-key-manager.h
index 495f8b0..c49fe2a 100644
--- a/src/seahorse-key-manager.h
+++ b/src/seahorse-key-manager.h
@@ -26,11 +26,12 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
+#include <gcr/gcr.h>
+
 #include "seahorse-viewer.h"
 
 G_BEGIN_DECLS
 
-
 #define SEAHORSE_TYPE_KEY_MANAGER 	      (seahorse_key_manager_get_type ())
 #define SEAHORSE_KEY_MANAGER(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_KEY_MANAGER, SeahorseKeyManager))
 #define SEAHORSE_KEY_MANAGER_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_KEY_MANAGER, SeahorseKeyManagerClass))
@@ -51,12 +52,8 @@ struct _SeahorseKeyManagerClass {
 	SeahorseViewerClass parent_class;
 };
 
-/* 
- * The various tabs. If adding a tab be sure to fix 
- * logic throughout this file. 
- */
+SeahorseWidget * seahorse_key_manager_show         (GcrCollection *sources);
 
-GtkWindow*       seahorse_key_manager_show         (void);
 GType            seahorse_key_manager_get_type     (void);
 
 
diff --git a/src/seahorse-key-manager.ui b/src/seahorse-key-manager.ui
index c51f01a..2527dd1 100644
--- a/src/seahorse-key-manager.ui
+++ b/src/seahorse-key-manager.ui
@@ -17,10 +17,8 @@
 			<separator/>
 			<menuitem action="app-preferences"/>
 		</menu>
-		<menu name="Remote" action="remote-menu">
-			<menuitem action="remote-find"/>
-			<menuitem action="remote-sync"/>
-		</menu>
+		<placeholder name="RemoteMenu">
+		</placeholder>
 		<menu name="View" action="view-menu">
 			<menuitem action="view-type"/>
 			<menuitem action="view-expires"/>
diff --git a/src/seahorse-main.c b/src/seahorse-main.c
index e4ec256..7f70309 100644
--- a/src/seahorse-main.c
+++ b/src/seahorse-main.c
@@ -31,19 +31,10 @@
 
 #include "seahorse-key-manager.h"
 
-#ifdef WITH_PGP
-#include "pgp/seahorse-pgp-module.h"
-#endif
-
-#ifdef WITH_SSH
-#include "ssh/seahorse-ssh-module.h"
-#endif
-
-#ifdef WITH_PKCS11
-#include "pkcs11/seahorse-pkcs11-module.h"
-#endif
-
-#include "gkr/seahorse-gkr-module.h"
+#include "gkr/seahorse-gkr.h"
+#include "pgp/seahorse-pgp.h"
+#include "ssh/seahorse-ssh.h"
+#include "pkcs11/seahorse-pkcs11.h"
 
 #include <locale.h>
 #include <stdlib.h>
@@ -56,6 +47,10 @@ static gboolean show_version = FALSE;
 int
 main (int argc, char **argv)
 {
+	SeahorseWidget *swidget;
+	GcrUnionCollection *sources;
+	SeahorseContext *context;
+
     static GOptionEntry options[] = {
         { "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL },
         { NULL, 0, 0, 0, NULL, NULL, NULL }
@@ -90,28 +85,26 @@ main (int argc, char **argv)
 
     /* Make the default SeahorseContext */
     seahorse_context_create ();
+    context = seahorse_context_instance ();
+
+    sources = GCR_UNION_COLLECTION (gcr_union_collection_new ());
 
     /* Initialize the various components */
-#ifdef WITH_PGP
-    seahorse_pgp_module_init ();
-#endif
-#ifdef WITH_SSH
-    seahorse_ssh_module_init ();
-#endif
-#ifdef WITH_PKCS11
-    seahorse_pkcs11_module_init ();
-#endif
-    seahorse_gkr_module_init ();
+    gcr_union_collection_take (sources, seahorse_pgp_backend_initialize ());
+    gcr_union_collection_take (sources, seahorse_ssh_backend_initialize ());
+    gcr_union_collection_take (sources, seahorse_pkcs11_backend_initialize ());
+    gcr_union_collection_take (sources, seahorse_gkr_backend_initialize ());
 
-    seahorse_key_manager_show ();
+    swidget = seahorse_key_manager_show (GCR_COLLECTION (sources));
+    g_object_unref (sources);
 
-    /* Start the refreshing of the keys */
-    seahorse_context_refresh_auto (NULL);
+    g_object_ref (context);
+    g_signal_connect_after (context, "destroy", gtk_main_quit, NULL);
 
-    g_signal_connect_after (SCTX_APP (), "destroy", gtk_main_quit, NULL);
-    
     gtk_main ();
 
+    g_object_unref (swidget);
+    g_object_unref (context);
 
     seahorse_cleanup_perform ();
     return ret;
diff --git a/ssh/Makefile.am b/ssh/Makefile.am
index a5a08f6..3ac27ec 100644
--- a/ssh/Makefile.am
+++ b/ssh/Makefile.am
@@ -18,7 +18,7 @@ noinst_LTLIBRARIES = libseahorse-ssh.la
 
 libseahorse_ssh_la_SOURCES = \
 	seahorse-ssh.h seahorse-ssh.c \
-	seahorse-ssh-module.c seahorse-ssh-module.h \
+	seahorse-ssh-backend.c seahorse-ssh-backend.h \
 	seahorse-algo.c seahorse-algo.h \
 	seahorse-ssh-commands.c seahorse-ssh-commands.h \
 	seahorse-ssh-dialogs.h \
diff --git a/ssh/seahorse-ssh-backend.c b/ssh/seahorse-ssh-backend.c
new file mode 100644
index 0000000..98821a1
--- /dev/null
+++ b/ssh/seahorse-ssh-backend.c
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include "seahorse-ssh-backend.h"
+#include "seahorse-ssh-commands.h"
+#include "seahorse-ssh-dialogs.h"
+#include "seahorse-ssh-source.h"
+
+static SeahorseSshBackend *ssh_backend = NULL;
+
+struct _SeahorseSshBackend {
+	GObject parent;
+	SeahorseSSHSource *dot_ssh;
+};
+
+struct _SeahorseSshBackendClass {
+	GObjectClass parent_class;
+};
+
+static void         seahorse_ssh_backend_collection_init  (GcrCollectionIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (SeahorseSshBackend, seahorse_ssh_backend, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_ssh_backend_collection_init));
+
+static void
+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 ();
+}
+
+static void
+seahorse_ssh_backend_constructed (GObject *obj)
+{
+	SeahorseSshBackend *self = SEAHORSE_SSH_BACKEND (obj);
+
+	G_OBJECT_CLASS (seahorse_ssh_backend_parent_class)->constructed (obj);
+
+	self->dot_ssh = seahorse_ssh_source_new ();
+	seahorse_ssh_source_load_async (self->dot_ssh, NULL, NULL, NULL);
+}
+
+static void
+seahorse_ssh_backend_finalize (GObject *obj)
+{
+	SeahorseSshBackend *self = SEAHORSE_SSH_BACKEND (obj);
+
+	g_clear_object (&self->dot_ssh);
+	g_return_if_fail (ssh_backend == self);
+	ssh_backend = NULL;
+
+	G_OBJECT_CLASS (seahorse_ssh_backend_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_ssh_backend_class_init (SeahorseSshBackendClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	gobject_class->constructed = seahorse_ssh_backend_constructed;
+	gobject_class->finalize = seahorse_ssh_backend_finalize;
+}
+
+static guint
+seahorse_ssh_backend_get_length (GcrCollection *collection)
+{
+	return 1;
+}
+
+static GList *
+seahorse_ssh_backend_get_objects (GcrCollection *collection)
+{
+	SeahorseSshBackend *self = SEAHORSE_SSH_BACKEND (collection);
+	return g_list_append (NULL, self->dot_ssh);
+}
+
+static gboolean
+seahorse_ssh_backend_contains (GcrCollection *collection,
+                               GObject *object)
+{
+	SeahorseSshBackend *self = SEAHORSE_SSH_BACKEND (collection);
+	return G_OBJECT (self->dot_ssh) == object;
+}
+
+static void
+seahorse_ssh_backend_collection_init (GcrCollectionIface *iface)
+{
+	iface->contains = seahorse_ssh_backend_contains;
+	iface->get_length = seahorse_ssh_backend_get_length;
+	iface->get_objects = seahorse_ssh_backend_get_objects;
+}
+
+GcrCollection *
+seahorse_ssh_backend_initialize (void)
+{
+	SeahorseSshBackend *self;
+
+	self = g_object_new (SEAHORSE_TYPE_SSH_BACKEND, NULL);
+
+	return GCR_COLLECTION (self);
+}
+
+SeahorseSshBackend *
+seahorse_ssh_backend_get (void)
+{
+	g_return_val_if_fail (ssh_backend, NULL);
+	return ssh_backend;
+}
+
+SeahorseSSHSource *
+seahorse_ssh_backend_get_dot_ssh (SeahorseSshBackend *self)
+{
+	self = self ? self : seahorse_ssh_backend_get ();
+	g_return_val_if_fail (SEAHORSE_IS_SSH_BACKEND (self), NULL);
+	g_return_val_if_fail (self->dot_ssh, NULL);
+	return self->dot_ssh;
+}
diff --git a/ssh/seahorse-ssh-backend.h b/ssh/seahorse-ssh-backend.h
new file mode 100644
index 0000000..518082a
--- /dev/null
+++ b/ssh/seahorse-ssh-backend.h
@@ -0,0 +1,48 @@
+/*
+ * 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_SSH_BACKEND_H_
+#define SEAHORSE_SSH_BACKEND_H_
+
+#include "seahorse-ssh.h"
+#include "seahorse-ssh-source.h"
+
+G_BEGIN_DECLS
+
+#define SEAHORSE_SSH_STR                     "openssh"
+
+#define SEAHORSE_TYPE_SSH_BACKEND            (seahorse_ssh_backend_get_type ())
+#define SEAHORSE_SSH_BACKEND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_SSH_BACKEND, SeahorseSshBackend))
+#define SEAHORSE_SSH_BACKEND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_SSH_BACKEND, SeahorseSshBackendClass))
+#define SEAHORSE_IS_SSH_BACKEND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_SSH_BACKEND))
+#define SEAHORSE_IS_SSH_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_SSH_BACKEND))
+#define SEAHORSE_SSH_BACKEND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_SSH_BACKEND, SeahorseSshBackendClass))
+
+typedef struct _SeahorseSshBackend SeahorseSshBackend;
+typedef struct _SeahorseSshBackendClass SeahorseSshBackendClass;
+
+GType                 seahorse_ssh_backend_get_type      (void) G_GNUC_CONST;
+
+SeahorseSshBackend *  seahorse_ssh_backend_get           (void);
+
+SeahorseSSHSource *   seahorse_ssh_backend_get_dot_ssh   (SeahorseSshBackend *self);
+
+#endif /*SEAHORSE_SSH_BACKEND_H_*/
diff --git a/ssh/seahorse-ssh-commands.c b/ssh/seahorse-ssh-commands.c
index 6fdc514..aec8068 100644
--- a/ssh/seahorse-ssh-commands.c
+++ b/ssh/seahorse-ssh-commands.c
@@ -96,7 +96,6 @@ static void
 seahorse_ssh_commands_show_properties (SeahorseCommands* base, SeahorseObject* obj) 
 {
 	g_return_if_fail (SEAHORSE_IS_OBJECT (obj));
-	g_return_if_fail (seahorse_object_get_tag (obj) == SEAHORSE_SSH_TYPE);
 	g_return_if_fail (G_TYPE_FROM_INSTANCE (G_OBJECT (obj)) == SEAHORSE_SSH_TYPE_KEY);
 	
 	seahorse_ssh_key_properties_show (SEAHORSE_SSH_KEY (obj), seahorse_commands_get_window (base));
diff --git a/ssh/seahorse-ssh-generate.c b/ssh/seahorse-ssh-generate.c
index 314d3bf..4121100 100644
--- a/ssh/seahorse-ssh-generate.c
+++ b/ssh/seahorse-ssh-generate.c
@@ -26,10 +26,10 @@
  
 #include <glib/gi18n.h>
 
+#include "seahorse-ssh-backend.h"
 #include "seahorse-ssh-dialogs.h"
 #include "seahorse-ssh-source.h"
 #include "seahorse-ssh-key.h"
-#include "seahorse-ssh.h"
 #include "seahorse-ssh-operation.h"
 
 #include "seahorse-icons.h"
@@ -46,14 +46,7 @@
 static void
 on_ssh_generate_key (GtkAction *action, gpointer unused)
 {
-	SeahorseSource* sksrc;
-	
-	g_return_if_fail (GTK_IS_ACTION (action));
-	
-	sksrc = seahorse_context_find_source (seahorse_context_instance (), SEAHORSE_SSH_TYPE, SEAHORSE_LOCATION_LOCAL);
-	g_return_if_fail (sksrc != NULL);
-	
-	seahorse_ssh_generate_show (SEAHORSE_SSH_SOURCE (sksrc), NULL);
+	seahorse_ssh_generate_show (seahorse_ssh_backend_get_dot_ssh (NULL), NULL);
 }
 
 static const GtkActionEntry ACTION_ENTRIES[] = {
diff --git a/ssh/seahorse-ssh-key.c b/ssh/seahorse-ssh-key.c
index f51652f..d8ab2d5 100644
--- a/ssh/seahorse-ssh-key.c
+++ b/ssh/seahorse-ssh-key.c
@@ -31,7 +31,6 @@
 
 #include <errno.h>
 
-#include "seahorse-context.h"
 #include "seahorse-source.h"
 #include "seahorse-ssh-source.h"
 #include "seahorse-ssh-key.h"
@@ -99,12 +98,10 @@ changed_key (SeahorseSSHKey *self)
 	if (!self->keydata || !self->keydata->fingerprint) {
         
 		g_object_set (self,
-		              "id", 0,
 		              "label", "",
 		              "icon", NULL,
 		              "usage", SEAHORSE_USAGE_NONE,
 		              "nickname", "",
-		              "location", SEAHORSE_LOCATION_INVALID,
 		              "flags", SEAHORSE_FLAG_DISABLED,
 		              NULL);
 		return;
@@ -120,12 +117,10 @@ changed_key (SeahorseSSHKey *self)
 
 	icon = g_themed_icon_new (SEAHORSE_ICON_KEY_SSH);
 	g_object_set (obj,
-	              "id", seahorse_ssh_key_calc_cannonical_id (self->keydata->fingerprint),
 	              "label", display,
 	              "icon", icon,
 	              "usage", usage,
 	              "nickname", simple,
-	              "location", SEAHORSE_LOCATION_LOCAL,
 	              "identifier", identifier,
 	              "flags", (self->keydata->authorized ? SEAHORSE_FLAG_TRUSTED : 0) | SEAHORSE_FLAG_EXPORTABLE | SEAHORSE_FLAG_DELETABLE,
 	              NULL);
@@ -314,33 +309,6 @@ seahorse_ssh_key_get_location (SeahorseSSHKey *skey)
                     skey->keydata->privfile : skey->keydata->pubfile;
 }
 
-GQuark
-seahorse_ssh_key_calc_cannonical_id (const gchar *id)
-{
-    #define SSH_ID_SIZE 16
-    gchar *hex, *canonical_id = g_malloc0 (SSH_ID_SIZE + 1);
-    gint i, off, len = strlen (id);
-    GQuark ret;
-
-    /* Strip out all non alpha numeric chars and limit length to SSH_ID_SIZE */
-    for (i = len, off = SSH_ID_SIZE; i >= 0 && off > 0; --i) {
-         if (g_ascii_isalnum (id[i]))
-             canonical_id[--off] = g_ascii_toupper (id[i]);
-    }
-    
-    /* Not enough characters */
-    g_return_val_if_fail (off == 0, 0);
-
-    hex = g_strdup_printf ("%s:%s", SEAHORSE_SSH_STR, canonical_id);
-    ret = g_quark_from_string (hex);
-    
-    g_free (canonical_id);
-    g_free (hex);
-    
-    return ret;
-}
-
-
 gchar*
 seahorse_ssh_key_calc_identifier (const gchar *id)
 {
diff --git a/ssh/seahorse-ssh-key.h b/ssh/seahorse-ssh-key.h
index 3cfd01e..6ba26c8 100644
--- a/ssh/seahorse-ssh-key.h
+++ b/ssh/seahorse-ssh-key.h
@@ -29,7 +29,6 @@
 #include "seahorse-source.h"
 #include "seahorse-validity.h"
 
-#include "seahorse-ssh-module.h"
 #include "seahorse-ssh-key-data.h"
 
 /* For vala's sake */
@@ -89,8 +88,6 @@ SeahorseValidity        seahorse_ssh_key_get_trust            (SeahorseSSHKey *s
 
 gchar*                  seahorse_ssh_key_get_fingerprint      (SeahorseSSHKey *self);
 
-GQuark                  seahorse_ssh_key_calc_cannonical_id    (const gchar *id);
-
 gchar*                  seahorse_ssh_key_calc_identifier      (const gchar *id);
 
-#endif /* __SEAHORSE_KEY_H__ */
+#endif /* __SEAHORSE_SSH_KEY_H__ */
diff --git a/ssh/seahorse-ssh-operation.c b/ssh/seahorse-ssh-operation.c
index a065260..d685c34 100644
--- a/ssh/seahorse-ssh-operation.c
+++ b/ssh/seahorse-ssh-operation.c
@@ -1364,6 +1364,7 @@ seahorse_ssh_op_delete_sync (SeahorseSSHKey *key,
                              GError **error)
 {
 	SeahorseSSHKeyData *keydata = NULL;
+	SeahorseSSHSource *source;
 	gboolean ret = TRUE;
 
 	g_return_val_if_fail (SEAHORSE_IS_SSH_KEY (key), FALSE);
@@ -1396,10 +1397,10 @@ seahorse_ssh_op_delete_sync (SeahorseSSHKey *key,
 		}
 	}
 
-	if (ret)
-		seahorse_context_remove_object (seahorse_context_instance (),
-		                                SEAHORSE_OBJECT (key));
+	if (ret) {
+		source = SEAHORSE_SSH_SOURCE (seahorse_object_get_source (SEAHORSE_OBJECT (key)));
+		seahorse_ssh_source_remove_object (source, key);
+	}
 
 	return ret;
 }
-
diff --git a/ssh/seahorse-ssh-source.c b/ssh/seahorse-ssh-source.c
index 0f44520..7685259 100644
--- a/ssh/seahorse-ssh-source.c
+++ b/ssh/seahorse-ssh-source.c
@@ -31,6 +31,9 @@
 #include "seahorse-registry.h"
 #include "seahorse-util.h"
 
+#include <gcr/gcr.h>
+
+#include <glib/gi18n.h>
 #include <glib/gstdio.h>
 
 #include <string.h>
@@ -38,15 +41,11 @@
 #include <fcntl.h>
 #include <errno.h>
 
-#include <glib/gi18n.h>
-
 #define DEBUG_FLAG SEAHORSE_DEBUG_LOAD
 #include "seahorse-debug.h"
 
 enum {
     PROP_0,
-    PROP_SOURCE_TAG,
-    PROP_SOURCE_LOCATION,
     PROP_BASE_DIRECTORY
 };
 
@@ -54,12 +53,17 @@ struct _SeahorseSSHSourcePrivate {
     gchar *ssh_homedir;                     /* Home directory for SSH keys */
     guint scheduled_refresh;                /* Source for refresh timeout */
     GFileMonitor *monitor_handle;           /* For monitoring the .ssh directory */
+    GHashTable *keys;
 };
 
-static void seahorse_source_iface (SeahorseSourceIface *iface);
+static void       seahorse_ssh_source_iface             (SeahorseSourceIface *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 (SEAHORSE_TYPE_SOURCE, seahorse_source_iface));
+                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_ssh_source_iface)
+                        G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_ssh_source_collection_iface);
+);
 
 #define AUTHORIZED_KEYS_FILE    "authorized_keys"
 #define OTHER_KEYS_FILE         "other_keys.seahorse"
@@ -123,23 +127,24 @@ cancel_scheduled_refresh (SeahorseSSHSource *ssrc)
 }
 
 static void
-remove_key_from_context (gpointer hkey, SeahorseObject *dummy, SeahorseSSHSource *ssrc)
+remove_key_from_context (gpointer key,
+                         SeahorseObject *dummy,
+                         SeahorseSSHSource *self)
 {
-    GQuark keyid = GPOINTER_TO_UINT (hkey);
-    SeahorseObject *sobj;
-    
-    sobj = seahorse_context_get_object (SCTX_APP (), SEAHORSE_SOURCE (ssrc), keyid);
-    if (sobj != NULL)
-        seahorse_context_remove_object (SCTX_APP (), sobj);
-}
+	const gchar *filename = key;
+	SeahorseSSHKey *skey;
 
+	skey = g_hash_table_lookup (self->priv->keys, filename);
+	if (skey != NULL)
+		seahorse_ssh_source_remove_object (self, skey);
+}
 
 static gboolean
 scheduled_refresh (SeahorseSSHSource *ssrc)
 {
     seahorse_debug ("scheduled refresh event ocurring now");
     cancel_scheduled_refresh (ssrc);
-    seahorse_source_load_async (SEAHORSE_SOURCE (ssrc), NULL, NULL, NULL);
+    seahorse_ssh_source_load_async (ssrc, NULL, NULL, NULL);
     return FALSE; /* don't run again */    
 }
 
@@ -215,12 +220,6 @@ seahorse_ssh_source_get_property (GObject *object, guint prop_id, GValue *value,
     SeahorseSSHSource *ssrc = SEAHORSE_SSH_SOURCE (object);
     
     switch (prop_id) {
-    case PROP_SOURCE_TAG:
-        g_value_set_uint (value, SEAHORSE_SSH);
-        break;
-    case PROP_SOURCE_LOCATION:
-        g_value_set_enum (value, SEAHORSE_LOCATION_LOCAL);
-        break;
     case PROP_BASE_DIRECTORY:
         g_value_set_string (value, ssrc->priv->ssh_homedir);
         break;
@@ -234,6 +233,7 @@ seahorse_ssh_source_dispose (GObject *gobject)
     
 	g_assert (ssrc->priv);
 
+	g_hash_table_remove_all (ssrc->priv->keys);
 	cancel_scheduled_refresh (ssrc);    
     
 	if (ssrc->priv->monitor_handle) {
@@ -249,7 +249,9 @@ seahorse_ssh_source_finalize (GObject *gobject)
 {
     SeahorseSSHSource *ssrc = SEAHORSE_SSH_SOURCE (gobject);
     g_assert (ssrc->priv);
-    
+
+    g_hash_table_destroy (ssrc->priv->keys);
+
     /* All monitoring and scheduling should be done */
     g_assert (ssrc->priv->scheduled_refresh == 0);
     g_assert (ssrc->priv->monitor_handle == 0);
@@ -267,12 +269,15 @@ seahorse_ssh_source_init (SeahorseSSHSource *ssrc)
 
 	/* init private vars */
 	ssrc->priv = g_new0 (SeahorseSSHSourcePrivate, 1);
-    
+
+	ssrc->priv->keys = g_hash_table_new_full (g_str_hash, g_str_equal,
+	                                          g_free, g_object_unref);
+
 	ssrc->priv->scheduled_refresh = 0;
 	ssrc->priv->monitor_handle = NULL;
 
 	ssrc->priv->ssh_homedir = g_strdup_printf ("%s/.ssh/", g_get_home_dir ());
-    
+
 	/* Make the .ssh directory if it doesn't exist */
 	if (!g_file_test (ssrc->priv->ssh_homedir, G_FILE_TEST_EXISTS)) {
 		if (g_mkdir (ssrc->priv->ssh_homedir, 0700) == -1)
@@ -302,19 +307,46 @@ seahorse_ssh_source_class_init (SeahorseSSHSourceClass *klass)
     gobject_class->dispose = seahorse_ssh_source_dispose;
     gobject_class->finalize = seahorse_ssh_source_finalize;
     gobject_class->get_property = seahorse_ssh_source_get_property;
-    
-	g_object_class_override_property (gobject_class, PROP_SOURCE_TAG, "source-tag");
-	g_object_class_override_property (gobject_class, PROP_SOURCE_LOCATION, "source-location");
 
     g_object_class_install_property (gobject_class, PROP_BASE_DIRECTORY,
         g_param_spec_string ("base-directory", "Key directory", "Directory where the keys are stored",
                              NULL, G_PARAM_READABLE));
-    
-	seahorse_registry_register_type (NULL, SEAHORSE_TYPE_SSH_SOURCE, "source", "local", SEAHORSE_SSH_STR, NULL);
-	
-	seahorse_registry_register_function (NULL, seahorse_ssh_key_calc_cannonical_id, "canonize", SEAHORSE_SSH_STR, NULL);
 }
 
+static guint
+seahorse_ssh_source_get_length (GcrCollection *collection)
+{
+	SeahorseSSHSource *self = SEAHORSE_SSH_SOURCE (collection);
+	return g_hash_table_size (self->priv->keys);
+}
+
+static GList *
+seahorse_ssh_source_get_objects (GcrCollection *collection)
+{
+	SeahorseSSHSource *self = SEAHORSE_SSH_SOURCE (collection);
+	return g_hash_table_get_values (self->priv->keys);
+}
+
+static gboolean
+seahorse_ssh_source_contains (GcrCollection *collection,
+                              GObject *object)
+{
+	SeahorseSSHSource *self = SEAHORSE_SSH_SOURCE (collection);
+	const gchar *filename;
+
+	if (!SEAHORSE_IS_SSH_KEY (object))
+		return FALSE;
+	filename = seahorse_ssh_key_get_location (SEAHORSE_SSH_KEY (object));
+	return g_hash_table_lookup (self->priv->keys, filename) == object;
+}
+
+static void
+seahorse_ssh_source_collection_iface (GcrCollectionIface *iface)
+{
+	iface->get_length = seahorse_ssh_source_get_length;
+	iface->get_objects = seahorse_ssh_source_get_objects;
+	iface->contains = seahorse_ssh_source_contains;
+}
 
 typedef struct {
 	SeahorseSSHSource *source;
@@ -344,28 +376,27 @@ ssh_key_from_data (SeahorseSSHSource *self,
 	SeahorseSource *source = SEAHORSE_SOURCE (self);
 	SeahorseSSHKey *skey;
 	SeahorseObject *prev;
-	GQuark keyid;
+	const gchar *location;
 
 	if (!seahorse_ssh_key_data_is_valid (keydata)) {
 		seahorse_ssh_key_data_free (keydata);
 		return NULL;
 	}
 
-	/* Make sure it's valid */
-	keyid = seahorse_ssh_key_calc_cannonical_id (keydata->fingerprint);
-	g_return_val_if_fail (keyid, NULL);
+	location = keydata->privfile ? keydata->privfile : keydata->pubfile;
+	g_return_val_if_fail (location, NULL);
 
 	/* Does this key exist in the context? */
-	prev = seahorse_context_get_object (SCTX_APP (), source, keyid);
+	prev = g_hash_table_lookup (self->priv->keys, location);
 
 	/* Mark this key as seen */
 	if (closure->checks)
-		g_hash_table_remove (closure->checks, GUINT_TO_POINTER (keyid));
+		g_hash_table_remove (closure->checks, location);
 
 	if (closure->loaded) {
 
 		/* See if we've already gotten a key like this in this load batch */
-		if (g_hash_table_lookup (closure->loaded, GUINT_TO_POINTER (keyid))) {
+		if (g_hash_table_lookup (closure->loaded, location)) {
 
 			/*
 			 * Sometimes later keys loaded have more information (for
@@ -378,7 +409,7 @@ ssh_key_from_data (SeahorseSSHSource *self,
 		}
 
 		/* Mark this key as loaded */
-		g_hash_table_insert (closure->loaded, GUINT_TO_POINTER (keyid),
+		g_hash_table_insert (closure->loaded, g_strdup (location),
 		                     GUINT_TO_POINTER (TRUE));
 	}
 
@@ -391,26 +422,26 @@ ssh_key_from_data (SeahorseSSHSource *self,
 	/* Create a new key */
 	g_assert (keydata);
 	skey = seahorse_ssh_key_new (source, keydata);
+	g_assert (g_strcmp0 (seahorse_ssh_key_get_location (skey), location) == 0);
+
+	g_hash_table_insert (self->priv->keys, g_strdup (location), skey);
+	gcr_collection_emit_added (GCR_COLLECTION (self), G_OBJECT (skey));
 
-	seahorse_context_take_object (seahorse_context_instance (),
-	                              SEAHORSE_OBJECT (skey));
 	return skey;
 }
 
 static GHashTable*
 load_present_keys (SeahorseSSHSource *self)
 {
-	GList *keys, *l;
+	const gchar *filename;
 	GHashTable *checks;
+	GHashTableIter iter;
+
+	checks = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	g_hash_table_iter_init (&iter, self->priv->keys);
+	while (g_hash_table_iter_next (&iter, (gpointer*)&filename, NULL))
+		g_hash_table_insert (checks, g_strdup (filename), "PRESENT");
 
-	checks = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
-	keys = seahorse_context_get_objects (seahorse_context_instance (),
-	                                     SEAHORSE_SOURCE (self));
-	for (l = keys; l != NULL; l = g_list_next (l))
-		g_hash_table_insert (checks,
-		                     GUINT_TO_POINTER (seahorse_object_get_id (l->data)),
-		                     GUINT_TO_POINTER (TRUE));
-	g_list_free (keys);
 	return checks;
 }
 
@@ -459,26 +490,26 @@ on_load_found_public_key (SeahorseSSHKeyData *data,
 	return TRUE;
 }
 
-static void
-seahorse_ssh_source_load_async (SeahorseSource *source,
+void
+seahorse_ssh_source_load_async (SeahorseSSHSource *self,
                                 GCancellable *cancellable,
                                 GAsyncReadyCallback callback,
                                 gpointer user_data)
 {
-	SeahorseSSHSource *self = SEAHORSE_SSH_SOURCE (source);
 	GSimpleAsyncResult *res;
 	source_load_closure *closure;
 	GError *error = NULL;
 	const gchar *filename;
 	GDir *dir;
 
-	res = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+	res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
 	                                 seahorse_ssh_source_load_async);
 	closure = g_new0 (source_load_closure, 1);
 	closure->source = g_object_ref (self);
 
 	/* Since we can find duplicate keys, limit them with this hash */
-	closure->loaded = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+	closure->loaded = g_hash_table_new_full (g_str_hash, g_str_equal,
+	                                         g_free, NULL);
 
 	/* Keys that currently exist, so we can remove any that disappeared */
 	closure->checks = load_present_keys (self);
@@ -569,12 +600,12 @@ seahorse_ssh_source_load_async (SeahorseSource *source,
 	g_object_unref (res);
 }
 
-static gboolean
-seahorse_ssh_source_load_finish (SeahorseSource *source,
+gboolean
+seahorse_ssh_source_load_finish (SeahorseSSHSource *self,
                                  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 (self),
 	                      seahorse_ssh_source_load_async), FALSE);
 
 	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
@@ -807,10 +838,8 @@ seahorse_ssh_source_export_finish (SeahorseSource *source,
 }
 
 static void 
-seahorse_source_iface (SeahorseSourceIface *iface)
+seahorse_ssh_source_iface (SeahorseSourceIface *iface)
 {
-	iface->load_async = seahorse_ssh_source_load_async;
-	iface->load_finish = seahorse_ssh_source_load_finish;
 	iface->import_async = seahorse_ssh_source_import_async;
 	iface->import_finish = seahorse_ssh_source_import_finish;
 	iface->export_async = seahorse_ssh_source_export_async;
@@ -828,28 +857,13 @@ seahorse_ssh_source_new (void)
 }
 
 SeahorseSSHKey*
-seahorse_ssh_source_key_for_filename (SeahorseSSHSource *ssrc,
+seahorse_ssh_source_key_for_filename (SeahorseSSHSource *self,
                                       const gchar *privfile)
 {
-	SeahorseSSHKeyData *data;
-	GList *keys, *l;
-
+	g_return_val_if_fail (SEAHORSE_IS_SSH_SOURCE (self), NULL);
 	g_return_val_if_fail (privfile, NULL);
-	g_return_val_if_fail (SEAHORSE_IS_SSH_SOURCE (ssrc), NULL);
-
-	/* Try to find it first */
-	keys = seahorse_context_get_objects (SCTX_APP (), SEAHORSE_SOURCE (ssrc));
-	for (l = keys; l; l = g_list_next (l)) {
 
-		g_object_get (l->data, "key-data", &data, NULL);
-		g_return_val_if_fail (data, NULL);
-
-		/* If it's already loaded then just leave it at that */
-		if (data->privfile && strcmp (privfile, data->privfile) == 0)
-			return SEAHORSE_SSH_KEY (l->data);
-	}
-
-	return NULL;
+	return g_hash_table_lookup (self->priv->keys, privfile);
 }
 
 gchar*
@@ -896,6 +910,26 @@ seahorse_ssh_source_file_for_public (SeahorseSSHSource *ssrc, gboolean authorize
             authorized ? AUTHORIZED_KEYS_FILE : OTHER_KEYS_FILE, NULL);
 }
 
+void
+seahorse_ssh_source_remove_object (SeahorseSSHSource *self,
+                                   SeahorseSSHKey *skey)
+{
+	const gchar *filename;
+
+	g_return_if_fail (SEAHORSE_SSH_SOURCE (self));
+	g_return_if_fail (SEAHORSE_SSH_KEY (skey));
+
+	filename = seahorse_ssh_key_get_location (skey);
+	g_return_if_fail (filename != NULL);
+	g_return_if_fail (g_hash_table_lookup (self->priv->keys, filename) == skey);
+
+	g_object_ref (skey);
+	g_hash_table_remove (self->priv->keys, filename);
+	gcr_collection_emit_removed (GCR_COLLECTION (self), G_OBJECT (skey));
+	g_object_unref (skey);
+}
+
+
 guchar*
 seahorse_ssh_source_export_private (SeahorseSSHSource *ssrc, SeahorseSSHKey *skey,
                                     gsize *n_results, GError **err)
diff --git a/ssh/seahorse-ssh-source.h b/ssh/seahorse-ssh-source.h
index dc41564..7124b4c 100644
--- a/ssh/seahorse-ssh-source.h
+++ b/ssh/seahorse-ssh-source.h
@@ -77,10 +77,21 @@ gchar*               seahorse_ssh_source_file_for_public    (SeahorseSSHSource *
 gchar*               seahorse_ssh_source_file_for_algorithm (SeahorseSSHSource *ssrc,
                                                              guint algo);
 
+void                 seahorse_ssh_source_remove_object      (SeahorseSSHSource *self,
+                                                             SeahorseSSHKey *skey);
+
 guchar*              seahorse_ssh_source_export_private     (SeahorseSSHSource *ssrc,
                                                              SeahorseSSHKey *skey,
                                                              gsize *n_results,
                                                              GError **err);
 
+void                 seahorse_ssh_source_load_async         (SeahorseSSHSource *self,
+                                                             GCancellable *cancellable,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+gboolean             seahorse_ssh_source_load_finish        (SeahorseSSHSource *self,
+                                                             GAsyncResult *result,
+                                                             GError **error);
 
 #endif /* __SEAHORSE_SSH_SOURCE_H__ */
diff --git a/ssh/seahorse-ssh.h b/ssh/seahorse-ssh.h
index 469a98b..ba76603 100644
--- a/ssh/seahorse-ssh.h
+++ b/ssh/seahorse-ssh.h
@@ -22,13 +22,20 @@
 #ifndef __SEAHORSE_SSH_H__
 #define __SEAHORSE_SSH_H__
 
+#ifdef WITH_SSH
+
 #include <glib.h>
 #include <glib-object.h>
 
+#include <gcr/gcr.h>
 
+#define SEAHORSE_SSH                         (g_quark_from_static_string ("openssh"))
 #define SEAHORSE_SSH_TYPE_STR "openssh"
 #define SEAHORSE_SSH_TYPE g_quark_from_string ("openssh")
 #define SEAHORSE_SSH_STOCK_ICON "seahorse-key-ssh"
 
+GcrCollection *       seahorse_ssh_backend_initialize    (void);
+
+#endif /* WITH_SSH */
 
 #endif



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