[seahorse/refactor: 6/32] Implement sidebar, structure backends and sources better



commit 1fad87592f0e03c967c170214b7cf469463df212
Author: Stef Walter <stefw collabora co uk>
Date:   Thu Sep 8 17:58:34 2011 +0200

    Implement sidebar, structure backends and sources better
    
     * Initial implementation of sidebar which shows all sources
     * Give SeahorseSource standard properties, so we can display
       them in the sidebar, such as icon, name etc.
     * Create SeahorseBackend interface with standard properties
       again for the sidebar.
     * Some of the values displayed are place holders.

 data/org.gnome.seahorse.manager.gschema.xml |    5 +
 gkr/seahorse-gkr-backend.c                  |   64 +++-
 gkr/seahorse-gkr-keyring.c                  |   27 +-
 gkr/seahorse-gkr-keyring.h                  |    2 +
 gkr/seahorse-gkr.h                          |    4 +-
 libseahorse/Makefile.am                     |    1 +
 libseahorse/seahorse-backend.c              |   51 +++
 libseahorse/seahorse-backend.h              |   41 ++
 libseahorse/seahorse-source.c               |   49 +--
 pgp/seahorse-gpgme-keyring.c                |   41 ++-
 pgp/seahorse-pgp-backend.c                  |   55 +++-
 pgp/seahorse-pgp-backend.h                  |    3 +-
 pgp/seahorse-pgp.h                          |    8 +-
 pgp/seahorse-server-source.c                |   92 +++--
 pgp/seahorse-unknown-source.c               |   11 +-
 pkcs11/seahorse-pkcs11-backend.c            |   59 +++-
 pkcs11/seahorse-pkcs11-commands.c           |    2 +-
 pkcs11/seahorse-pkcs11-source.c             |   28 +-
 pkcs11/seahorse-pkcs11.h                    |    5 +-
 src/Makefile.am                             |    1 +
 src/seahorse-key-manager.c                  |   88 ++++-
 src/seahorse-key-manager.h                  |    4 +-
 src/seahorse-key-manager.xml                |  542 ++++++++++++++-----------
 src/seahorse-main.c                         |   17 +-
 src/seahorse-sidebar.c                      |  586 +++++++++++++++++++++++++++
 src/seahorse-sidebar.h                      |   43 ++
 ssh/seahorse-ssh-backend.c                  |   59 +++-
 ssh/seahorse-ssh-source.c                   |   43 ++-
 ssh/seahorse-ssh.h                          |    8 +-
 29 files changed, 1553 insertions(+), 386 deletions(-)
---
diff --git a/data/org.gnome.seahorse.manager.gschema.xml b/data/org.gnome.seahorse.manager.gschema.xml
index 76d5c50..20579bd 100644
--- a/data/org.gnome.seahorse.manager.gschema.xml
+++ b/data/org.gnome.seahorse.manager.gschema.xml
@@ -25,5 +25,10 @@
 			<summary>The column to sort the seahorse keys by</summary>
 			<description>Specify the column to sort the seahorse key manager main window by. Columns are: 'name', 'id', 'validity', 'expires', 'trust', and 'type'. Put a '-' in front of the column name to sort in descending order.</description>
 		</key>
+		<key name="sidebar-width" type="i">
+			<default>148</default>
+			<summary>Width of the side pane</summary>
+			<description>The default width of the side pane.</description>
+		</key>
 	</schema>
 </schemalist>
diff --git a/gkr/seahorse-gkr-backend.c b/gkr/seahorse-gkr-backend.c
index 3c9db11..9d90564 100644
--- a/gkr/seahorse-gkr-backend.c
+++ b/gkr/seahorse-gkr-backend.c
@@ -27,10 +27,21 @@
 #include "seahorse-gkr-keyring-commands.h"
 #include "seahorse-gkr-operation.h"
 
+#include "seahorse-backend.h"
 #include "seahorse-progress.h"
+#include "seahorse-registry.h"
 
 #include <gnome-keyring.h>
 
+#include <glib/gi18n.h>
+
+enum {
+	PROP_0,
+	PROP_NAME,
+	PROP_LABEL,
+	PROP_DESCRIPTION
+};
+
 static SeahorseGkrBackend *gkr_backend = NULL;
 
 struct _SeahorseGkrBackend {
@@ -42,10 +53,14 @@ struct _SeahorseGkrBackendClass {
 	GObjectClass parent_class;
 };
 
+static void         seahorse_gkr_backend_iface_init       (SeahorseBackendIface *iface);
+
 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));
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_gkr_backend_collection_init);
+                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_BACKEND, seahorse_gkr_backend_iface_init);
+);
 
 static void
 seahorse_gkr_backend_init (SeahorseGkrBackend *self)
@@ -72,6 +87,28 @@ seahorse_gkr_backend_constructed (GObject *obj)
 }
 
 static void
+seahorse_gkr_backend_get_property (GObject *obj,
+                                   guint prop_id,
+                                   GValue *value,
+                                   GParamSpec *pspec)
+{
+	switch (prop_id) {
+	case PROP_NAME:
+		g_value_set_string (value, SEAHORSE_GKR_NAME);
+		break;
+	case PROP_LABEL:
+		g_value_set_string (value, _("Passwords"));
+		break;
+	case PROP_DESCRIPTION:
+		g_value_set_string (value, _("Stored personal passwords, credentials and secrets"));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
 seahorse_gkr_backend_dispose (GObject *obj)
 {
 	SeahorseGkrBackend *self = SEAHORSE_GKR_BACKEND (obj);
@@ -101,6 +138,11 @@ seahorse_gkr_backend_class_init (SeahorseGkrBackendClass *klass)
 	gobject_class->constructed = seahorse_gkr_backend_constructed;
 	gobject_class->dispose = seahorse_gkr_backend_dispose;
 	gobject_class->finalize = seahorse_gkr_backend_finalize;
+	gobject_class->get_property = seahorse_gkr_backend_get_property;
+
+	g_object_class_override_property (gobject_class, PROP_NAME, "name");
+	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
+	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
 }
 
 static guint
@@ -139,24 +181,24 @@ seahorse_gkr_backend_collection_init (GcrCollectionIface *iface)
 	iface->get_objects = seahorse_gkr_backend_get_objects;
 }
 
-GcrCollection *
+static void
+seahorse_gkr_backend_iface_init (SeahorseBackendIface *iface)
+{
+
+}
+
+void
 seahorse_gkr_backend_initialize (void)
 {
 	SeahorseGkrBackend *self;
-	GcrCollection *collection;
 
+	g_return_if_fail (gkr_backend == NULL);
 	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));
+	seahorse_registry_register_object (NULL, G_OBJECT (self), "backend", "gnome-keyring", NULL);
 	g_object_unref (self);
 
-	return collection;
+	g_return_if_fail (gkr_backend != NULL);
 }
 
 SeahorseGkrBackend *
diff --git a/gkr/seahorse-gkr-keyring.c b/gkr/seahorse-gkr-keyring.c
index f724e95..0dc116a 100644
--- a/gkr/seahorse-gkr-keyring.c
+++ b/gkr/seahorse-gkr-keyring.c
@@ -36,6 +36,7 @@
 
 enum {
 	PROP_0,
+	PROP_DESCRIPTION,
 	PROP_KEYRING_NAME,
 	PROP_KEYRING_INFO,
 	PROP_IS_DEFAULT
@@ -54,8 +55,8 @@ static void     seahorse_keyring_source_iface        (SeahorseSourceIface *iface
 static void     seahorse_keyring_collection_iface    (GcrCollectionIface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (SeahorseGkrKeyring, seahorse_gkr_keyring, SEAHORSE_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_keyring_source_iface);
                          G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_keyring_collection_iface);
+                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_keyring_source_iface);
 );
 
 static GType
@@ -120,16 +121,18 @@ require_keyring_info (SeahorseGkrKeyring *self)
 void
 seahorse_gkr_keyring_realize (SeahorseGkrKeyring *self)
 {
-	gchar *name, *markup;
+	const gchar *name;
 	GIcon *icon;
 
-	name = g_strdup_printf (_("Passwords: %s"), self->pv->keyring_name);
-	markup = g_markup_printf_escaped (_("<b>Passwords:</b> %s"), self->pv->keyring_name);
+	if (self->pv->keyring_name && g_str_equal (self->pv->keyring_name, "login"))
+		name = _("Login keyring");
+	else
+		name = self->pv->keyring_name;
+
 	icon = g_themed_icon_new ("folder");
 
 	g_object_set (self,
 	              "label", name,
-	              "markup", markup,
 	              "nickname", self->pv->keyring_name,
 	              "identifier", "",
 	              "flags", SEAHORSE_FLAG_DELETABLE,
@@ -138,8 +141,6 @@ seahorse_gkr_keyring_realize (SeahorseGkrKeyring *self)
 	              NULL);
 
 	g_object_unref (icon);
-	g_free (name);
-	g_free (markup);
 }
 
 void
@@ -412,6 +413,9 @@ seahorse_gkr_keyring_get_property (GObject *obj, guint prop_id, GValue *value,
 	SeahorseGkrKeyring *self = SEAHORSE_GKR_KEYRING (obj);
 	
 	switch (prop_id) {
+	case PROP_DESCRIPTION:
+		g_value_set_string (value, seahorse_gkr_keyring_get_description (self));
+		break;
 	case PROP_KEYRING_NAME:
 		g_value_set_string (value, seahorse_gkr_keyring_get_name (self));
 		break;
@@ -439,6 +443,8 @@ seahorse_gkr_keyring_class_init (SeahorseGkrKeyringClass *klass)
 	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_DESCRIPTION, "description");
+
 	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));
@@ -510,6 +516,13 @@ seahorse_gkr_keyring_get_name (SeahorseGkrKeyring *self)
 	return self->pv->keyring_name;
 }
 
+const gchar *
+seahorse_gkr_keyring_get_description (SeahorseGkrKeyring *self)
+{
+	g_return_val_if_fail (SEAHORSE_IS_GKR_KEYRING (self), NULL);
+	return _("To do Keyring");
+}
+
 GnomeKeyringInfo*
 seahorse_gkr_keyring_get_info (SeahorseGkrKeyring *self)
 {
diff --git a/gkr/seahorse-gkr-keyring.h b/gkr/seahorse-gkr-keyring.h
index d040ec1..4735ef5 100644
--- a/gkr/seahorse-gkr-keyring.h
+++ b/gkr/seahorse-gkr-keyring.h
@@ -61,6 +61,8 @@ void                 seahorse_gkr_keyring_remove_item      (SeahorseGkrKeyring *
 
 const gchar*         seahorse_gkr_keyring_get_name         (SeahorseGkrKeyring *self);
 
+const gchar *        seahorse_gkr_keyring_get_description  (SeahorseGkrKeyring *self);
+
 GnomeKeyringInfo*    seahorse_gkr_keyring_get_info         (SeahorseGkrKeyring *self);
 
 void                 seahorse_gkr_keyring_set_info         (SeahorseGkrKeyring *self,
diff --git a/gkr/seahorse-gkr.h b/gkr/seahorse-gkr.h
index 7c13f9d..73c332a 100644
--- a/gkr/seahorse-gkr.h
+++ b/gkr/seahorse-gkr.h
@@ -29,7 +29,9 @@
 
 G_BEGIN_DECLS
 
-GcrCollection *       seahorse_gkr_backend_initialize    (void);
+#define SEAHORSE_GKR_NAME "gkr"
+
+void       seahorse_gkr_backend_initialize    (void);
 
 G_END_DECLS
 
diff --git a/libseahorse/Makefile.am b/libseahorse/Makefile.am
index 15a19ca..3a1fb32 100644
--- a/libseahorse/Makefile.am
+++ b/libseahorse/Makefile.am
@@ -28,6 +28,7 @@ KEYSERVER_SRCS =
 endif
 
 libseahorse_la_SOURCES = \
+	seahorse-backend.c seahorse-backend.h \
 	seahorse-bind.c seahorse-bind.h \
 	seahorse-cleanup.c seahorse-cleanup.h \
 	seahorse-collection.c seahorse-collection.h \
diff --git a/libseahorse/seahorse-backend.c b/libseahorse/seahorse-backend.c
new file mode 100644
index 0000000..b907a87
--- /dev/null
+++ b/libseahorse/seahorse-backend.c
@@ -0,0 +1,51 @@
+/*
+ * 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 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-backend.h"
+
+#include <gcr/gcr.h>
+
+typedef SeahorseBackendIface SeahorseBackendInterface;
+
+G_DEFINE_INTERFACE (SeahorseBackend, seahorse_backend, GCR_TYPE_COLLECTION);
+
+static void
+seahorse_backend_default_init (SeahorseBackendIface *iface)
+{
+	static gboolean initialized = FALSE;
+	if (!initialized) {
+		g_object_interface_install_property (iface,
+		           g_param_spec_string ("name", "Name", "Name for the backend",
+		                                "", G_PARAM_READABLE));
+
+		g_object_interface_install_property (iface,
+		           g_param_spec_string ("label", "Label", "Label for the backend",
+		                                "", G_PARAM_READABLE));
+
+		g_object_interface_install_property (iface,
+		           g_param_spec_string ("description", "Description", "Description for the backend",
+		                                "", G_PARAM_READABLE));
+
+		initialized = TRUE;
+	}
+}
diff --git a/libseahorse/seahorse-backend.h b/libseahorse/seahorse-backend.h
new file mode 100644
index 0000000..f7578d2
--- /dev/null
+++ b/libseahorse/seahorse-backend.h
@@ -0,0 +1,41 @@
+/*
+ * 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 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_BACKEND_H__
+#define __SEAHORSE_BACKEND_H__
+
+#include <glib-object.h>
+
+#define SEAHORSE_TYPE_BACKEND                (seahorse_backend_get_type ())
+#define SEAHORSE_BACKEND(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_BACKEND, SeahorseBackend))
+#define SEAHORSE_IS_BACKEND(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_BACKEND))
+#define SEAHORSE_BACKEND_GET_INTERFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SEAHORSE_TYPE_BACKEND, SeahorseBackendIface))
+
+typedef struct _SeahorseBackend SeahorseBackend;
+typedef struct _SeahorseBackendIface SeahorseBackendIface;
+
+struct _SeahorseBackendIface {
+	GTypeInterface parent;
+};
+
+GType            seahorse_backend_get_type             (void) G_GNUC_CONST;
+
+#endif /* __SEAHORSE_BACKEND_H__ */
diff --git a/libseahorse/seahorse-source.c b/libseahorse/seahorse-source.c
index 8adb763..d88308f 100644
--- a/libseahorse/seahorse-source.c
+++ b/libseahorse/seahorse-source.c
@@ -29,6 +29,8 @@
 #include "seahorse-source.h"
 #include "seahorse-util.h"
 
+#include <gcr/gcr.h>
+
 /**
  * SECTION:seahorse-source
  * @short_description: This class stores and handles key sources
@@ -36,6 +38,9 @@
  *
  **/
 
+typedef SeahorseSourceIface SeahorseSourceInterface;
+
+G_DEFINE_INTERFACE (SeahorseSource, seahorse_source, GCR_TYPE_COLLECTION);
 
 /* ---------------------------------------------------------------------------------
  * INTERFACE
@@ -46,42 +51,24 @@
 *
 **/
 static void
-seahorse_source_base_init (gpointer gobject_class)
+seahorse_source_default_init (SeahorseSourceIface *iface)
 {
 	static gboolean initialized = FALSE;
 	if (!initialized) {
-		initialized = TRUE;
-	}
-}
+		g_object_interface_install_property (iface,
+		           g_param_spec_string ("label", "Label", "Label for the source",
+		                                "", G_PARAM_READABLE));
 
-/**
- * seahorse_source_get_type:
- *
- * Registers the type of G_TYPE_INTERFACE
- *
- * Returns: the type id
- */
-GType
-seahorse_source_get_type (void)
-{
-	static GType type = 0;
-	if (!type) {
-		static const GTypeInfo info = {
-			sizeof (SeahorseSourceIface),
-			seahorse_source_base_init,               /* base init */
-			NULL,             /* base finalize */
-			NULL,             /* class_init */
-			NULL,             /* class finalize */
-			NULL,             /* class data */
-			0,
-			0,                /* n_preallocs */
-			NULL,             /* instance init */
-		};
-		type = g_type_register_static (G_TYPE_INTERFACE, "SeahorseSourceIface", &info, 0);
-		g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+		g_object_interface_install_property (iface,
+		           g_param_spec_string ("description", "Description", "Description for the source",
+		                                "", G_PARAM_READABLE));
+
+		g_object_interface_install_property (iface,
+		           g_param_spec_object ("icon", "Icon", "Icon for this source",
+		                                G_TYPE_ICON, G_PARAM_READABLE));
+
+		initialized = TRUE;
 	}
-	
-	return type;
 }
 
 /* ---------------------------------------------------------------------------------
diff --git a/pgp/seahorse-gpgme-keyring.c b/pgp/seahorse-gpgme-keyring.c
index 7db728f..36e2ebc 100644
--- a/pgp/seahorse-gpgme-keyring.c
+++ b/pgp/seahorse-gpgme-keyring.c
@@ -48,7 +48,12 @@
 #define DEBUG_FLAG SEAHORSE_DEBUG_OPERATION
 #include "seahorse-debug.h"
 
-/* TODO: Verify properly that all keys we deal with are PGP keys */
+enum {
+	PROP_0,
+	PROP_LABEL,
+	PROP_DESCRIPTION,
+	PROP_ICON
+};
 
 /* Amount of keys to load in a batch */
 #define DEFAULT_LOAD_BATCH 200
@@ -150,8 +155,8 @@ static void     seahorse_gpgme_keyring_source_iface       (SeahorseSourceIface *
 static void     seahorse_gpgme_keyring_collection_iface   (GcrCollectionIface *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);
+                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_gpgme_keyring_source_iface);
 );
 
 typedef struct {
@@ -945,6 +950,32 @@ seahorse_gpgme_keyring_init (SeahorseGpgmeKeyring *self)
 }
 
 static void
+seahorse_gpgme_keyring_get_property (GObject *obj,
+                                     guint prop_id,
+                                     GValue *value,
+                                     GParamSpec *pspec)
+{
+#if 0
+	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (obj);
+#endif
+
+	switch (prop_id) {
+	case PROP_LABEL:
+		g_value_set_string (value, _("To Do Keys"));
+		break;
+	case PROP_DESCRIPTION:
+		g_value_set_string (value, _("To Do Description"));
+		break;
+	case PROP_ICON:
+		g_value_take_object (value, g_themed_icon_new (GTK_STOCK_DIALOG_QUESTION));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
 seahorse_gpgme_keyring_dispose (GObject *object)
 {
 	SeahorseGpgmeKeyring *self = SEAHORSE_GPGME_KEYRING (object);
@@ -996,13 +1027,15 @@ seahorse_gpgme_keyring_class_init (SeahorseGpgmeKeyringClass *klass)
 #endif
 
 	gobject_class = G_OBJECT_CLASS (klass);
+	gobject_class->get_property = seahorse_gpgme_keyring_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);
+	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
+	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
+	g_object_class_override_property (gobject_class, PROP_ICON, "icon");
 }
 
 static void
diff --git a/pgp/seahorse-pgp-backend.c b/pgp/seahorse-pgp-backend.c
index 0e6cfda..e15d219 100644
--- a/pgp/seahorse-pgp-backend.c
+++ b/pgp/seahorse-pgp-backend.c
@@ -28,14 +28,25 @@
 #include "seahorse-transfer.h"
 #include "seahorse-unknown-source.h"
 
+#include "seahorse-backend.h"
 #include "seahorse-progress.h"
+#include "seahorse-registry.h"
 #include "seahorse-servers.h"
 #include "seahorse-util.h"
 
 #include <gnome-keyring.h>
 
+#include <glib/gi18n.h>
+
 #include <string.h>
 
+enum {
+	PROP_0,
+	PROP_NAME,
+	PROP_LABEL,
+	PROP_DESCRIPTION
+};
+
 static SeahorsePgpBackend *pgp_backend = NULL;
 
 struct _SeahorsePgpBackend {
@@ -50,10 +61,13 @@ struct _SeahorsePgpBackendClass {
 	GObjectClass parent_class;
 };
 
+static void         seahorse_pgp_backend_iface_init       (SeahorseBackendIface *iface);
+
 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);
+                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_BACKEND, seahorse_pgp_backend_iface_init);
 );
 
 static void
@@ -144,6 +158,28 @@ seahorse_pgp_backend_constructed (GObject *obj)
 }
 
 static void
+seahorse_pgp_backend_get_property (GObject *obj,
+                                   guint prop_id,
+                                   GValue *value,
+                                   GParamSpec *pspec)
+{
+	switch (prop_id) {
+	case PROP_NAME:
+		g_value_set_string (value, SEAHORSE_PGP_NAME);
+		break;
+	case PROP_LABEL:
+		g_value_set_string (value, _("PGP Keys"));
+		break;
+	case PROP_DESCRIPTION:
+		g_value_set_string (value, _("PGP keys are for encrypting email or files"));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
 seahorse_pgp_backend_finalize (GObject *obj)
 {
 	SeahorsePgpBackend *self = SEAHORSE_PGP_BACKEND (obj);
@@ -169,6 +205,11 @@ seahorse_pgp_backend_class_init (SeahorsePgpBackendClass *klass)
 
 	gobject_class->constructed = seahorse_pgp_backend_constructed;
 	gobject_class->finalize = seahorse_pgp_backend_finalize;
+	gobject_class->get_property = seahorse_pgp_backend_get_property;
+
+	g_object_class_override_property (gobject_class, PROP_NAME, "name");
+	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
+	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
 }
 
 static guint
@@ -200,6 +241,12 @@ seahorse_pgp_backend_collection_init (GcrCollectionIface *iface)
 	iface->get_objects = seahorse_pgp_backend_get_objects;
 }
 
+static void
+seahorse_pgp_backend_iface_init (SeahorseBackendIface *iface)
+{
+
+}
+
 SeahorsePgpBackend *
 seahorse_pgp_backend_get (void)
 {
@@ -207,14 +254,18 @@ seahorse_pgp_backend_get (void)
 	return pgp_backend;
 }
 
-GcrCollection *
+void
 seahorse_pgp_backend_initialize (void)
 {
 	SeahorsePgpBackend *self;
 
+	g_return_if_fail (pgp_backend == NULL);
 	self = g_object_new (SEAHORSE_TYPE_PGP_BACKEND, NULL);
 
-	return GCR_COLLECTION (self);
+	seahorse_registry_register_object (NULL, G_OBJECT (self), "backend", "openpgp", NULL);
+	g_object_unref (self);
+
+	g_return_if_fail (pgp_backend != NULL);
 }
 
 SeahorseGpgmeKeyring *
diff --git a/pgp/seahorse-pgp-backend.h b/pgp/seahorse-pgp-backend.h
index 8923bcc..aea88fa 100644
--- a/pgp/seahorse-pgp-backend.h
+++ b/pgp/seahorse-pgp-backend.h
@@ -29,6 +29,7 @@
 
 #include <gcr/gcr.h>
 
+#include "seahorse-pgp.h"
 #include "seahorse-discovery.h"
 #include "seahorse-gpgme-keyring.h"
 #include "seahorse-pgp-key.h"
@@ -48,8 +49,6 @@ 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);
diff --git a/pgp/seahorse-pgp.h b/pgp/seahorse-pgp.h
index c486cf6..3509aa4 100644
--- a/pgp/seahorse-pgp.h
+++ b/pgp/seahorse-pgp.h
@@ -31,12 +31,12 @@ 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_NAME "openpgp"
+#define SEAHORSE_PGP_TYPE_STR SEAHORSE_PGP_NAME
+#define SEAHORSE_PGP g_quark_from_string (SEAHORSE_PGP_NAME)
 #define SEAHORSE_PGP_STOCK_ICON "seahorse-key-personal"
 
-GcrCollection *       seahorse_pgp_backend_initialize    (void);
+void       seahorse_pgp_backend_initialize    (void);
 
 #endif /* WITH_PGP */
 
diff --git a/pgp/seahorse-server-source.c b/pgp/seahorse-server-source.c
index 342d01a..91161b0 100644
--- a/pgp/seahorse-server-source.c
+++ b/pgp/seahorse-server-source.c
@@ -44,6 +44,9 @@
 
 enum {
     PROP_0,
+    PROP_LABEL,
+    PROP_DESCRIPTION,
+    PROP_ICON,
     PROP_KEY_SERVER,
     PROP_URI
 };
@@ -57,10 +60,11 @@ struct _SeahorseServerSourcePrivate {
     gchar *uri;
 };
 
-static void seahorse_source_iface (SeahorseSourceIface *iface);
+static void      seahorse_server_source_collection_init    (GcrCollectionIface *iface);
 
-G_DEFINE_TYPE_EXTENDED (SeahorseServerSource, seahorse_server_source, G_TYPE_OBJECT, 0,
-                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_source_iface));
+G_DEFINE_TYPE_WITH_CODE (SeahorseServerSource, seahorse_server_source, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_server_source_collection_init);
+);
 
 /* GObject handlers */
 static void seahorse_server_source_finalize   (GObject *gobject);
@@ -86,6 +90,14 @@ seahorse_server_source_class_init (SeahorseServerSourceClass *klass)
     gobject_class->set_property = seahorse_server_set_property;
     gobject_class->get_property = seahorse_server_get_property;
 
+    /* These properties are used to conform to SeahorseSource, but are not actually used */
+    g_object_class_install_property (gobject_class, PROP_LABEL,
+            g_param_spec_string ("label", "Label", "Label", "", G_PARAM_READABLE));
+    g_object_class_install_property (gobject_class, PROP_DESCRIPTION,
+            g_param_spec_string ("description", "Description", "Description", "", G_PARAM_READABLE));
+    g_object_class_install_property (gobject_class, PROP_ICON,
+            g_param_spec_object ("icon", "icon", "Icon", G_TYPE_ICON, G_PARAM_READABLE));
+
     g_object_class_install_property (gobject_class, PROP_KEY_SERVER,
             g_param_spec_string ("key-server", "Key Server",
                                  "Key Server to search on", "",
@@ -98,20 +110,6 @@ seahorse_server_source_class_init (SeahorseServerSourceClass *klass)
 }
 
 /**
-* iface: The #SeahorseSourceIface to init
-*
-* Sets the load function in @iface
-*
-* This is the init function of the interface SEAHORSE_TYPE_SOURCE
-*
-**/
-static void 
-seahorse_source_iface (SeahorseSourceIface *iface)
-{
-
-}
-
-/**
 * ssrc: A #SeahorseServerSource object
 *
 * init context, private vars, set prefs, connect signals
@@ -189,19 +187,57 @@ seahorse_server_set_property (GObject *object, guint prop_id,
 *
 **/
 static void 
-seahorse_server_get_property (GObject *object, guint prop_id, GValue *value,
+seahorse_server_get_property (GObject *obj,
+                              guint prop_id,
+                              GValue *value,
                               GParamSpec *pspec)
 {
-    SeahorseServerSource *ssrc = SEAHORSE_SERVER_SOURCE (object);
-  
-    switch (prop_id) {
-    case PROP_KEY_SERVER:
-        g_value_set_string (value, ssrc->priv->server);
-        break;
-    case PROP_URI:
-        g_value_set_string (value, ssrc->priv->uri);
-        break;
-    }
+	SeahorseServerSource *self = SEAHORSE_SERVER_SOURCE (obj);
+
+	switch (prop_id) {
+	case PROP_LABEL:
+	case PROP_KEY_SERVER:
+		g_value_set_string (value, self->priv->server);
+		break;
+	case PROP_DESCRIPTION:
+	case PROP_URI:
+		g_value_set_string (value, self->priv->uri);
+		break;
+	case PROP_ICON:
+		g_value_take_object (value, g_themed_icon_new (GTK_STOCK_DIALOG_QUESTION));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static guint
+seahorse_server_source_get_length (GcrCollection *collection)
+{
+	return 0;
+}
+
+static GList *
+seahorse_server_source_get_objects (GcrCollection *collection)
+{
+	return NULL;
+}
+
+static gboolean
+seahorse_server_source_contains (GcrCollection *collection,
+                                 GObject *object)
+{
+	return FALSE;
+}
+
+static void
+seahorse_server_source_collection_init (GcrCollectionIface *iface)
+{
+	/* This is implemented because SeahorseSource requires it */
+	iface->get_length = seahorse_server_source_get_length;
+	iface->get_objects = seahorse_server_source_get_objects;
+	iface->contains = seahorse_server_source_contains;
 }
 
 /* --------------------------------------------------------------------------
diff --git a/pgp/seahorse-unknown-source.c b/pgp/seahorse-unknown-source.c
index bf6c173..27f1d8f 100644
--- a/pgp/seahorse-unknown-source.c
+++ b/pgp/seahorse-unknown-source.c
@@ -39,10 +39,7 @@ 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));
+G_DEFINE_TYPE (SeahorseUnknownSource, seahorse_unknown_source, G_TYPE_OBJECT);
 
 /* -----------------------------------------------------------------------------
  * OBJECT
@@ -73,12 +70,6 @@ seahorse_unknown_source_class_init (SeahorseUnknownSourceClass *klass)
 	gobject_class->finalize = seahorse_unknown_source_finalize;
 }
 
-static void
-seahorse_source_iface (SeahorseSourceIface *iface)
-{
-
-}
-
 SeahorseUnknownSource*
 seahorse_unknown_source_new (void)
 {
diff --git a/pkcs11/seahorse-pkcs11-backend.c b/pkcs11/seahorse-pkcs11-backend.c
index 4a35e23..6cb0a76 100644
--- a/pkcs11/seahorse-pkcs11-backend.c
+++ b/pkcs11/seahorse-pkcs11-backend.c
@@ -25,10 +25,21 @@
 #include "seahorse-pkcs11-commands.h"
 #include "seahorse-pkcs11-source.h"
 
+#include "seahorse-backend.h"
+#include "seahorse-registry.h"
 #include "seahorse-util.h"
 
 #include <gck/gck.h>
 
+#include <glib/gi18n.h>
+
+enum {
+	PROP_0,
+	PROP_NAME,
+	PROP_LABEL,
+	PROP_DESCRIPTION
+};
+
 static SeahorsePkcs11Backend *pkcs11_backend = NULL;
 
 struct _SeahorsePkcs11Backend {
@@ -40,10 +51,14 @@ struct _SeahorsePkcs11BackendClass {
 	GObjectClass parent_class;
 };
 
+static void         seahorse_pkcs11_backend_iface_init       (SeahorseBackendIface *iface);
+
 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));
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_pkcs11_backend_collection_init)
+                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_BACKEND, seahorse_pkcs11_backend_iface_init);
+);
 
 static void
 seahorse_pkcs11_backend_init (SeahorsePkcs11Backend *self)
@@ -88,6 +103,28 @@ seahorse_pkcs11_backend_constructed (GObject *obj)
 }
 
 static void
+seahorse_pkcs11_backend_get_property (GObject *obj,
+                                      guint prop_id,
+                                      GValue *value,
+                                      GParamSpec *pspec)
+{
+	switch (prop_id) {
+	case PROP_NAME:
+		g_value_set_string (value, SEAHORSE_PKCS11_NAME);
+		break;
+	case PROP_LABEL:
+		g_value_set_string (value, _("Certificates"));
+		break;
+	case PROP_DESCRIPTION:
+		g_value_set_string (value, _("X.509 certificates and related keys"));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
 seahorse_pkcs11_backend_dispose (GObject *obj)
 {
 	SeahorsePkcs11Backend *self = SEAHORSE_PKCS11_BACKEND (obj);
@@ -118,6 +155,11 @@ seahorse_pkcs11_backend_class_init (SeahorsePkcs11BackendClass *klass)
 	gobject_class->constructed = seahorse_pkcs11_backend_constructed;
 	gobject_class->dispose = seahorse_pkcs11_backend_dispose;
 	gobject_class->finalize = seahorse_pkcs11_backend_finalize;
+	gobject_class->get_property = seahorse_pkcs11_backend_get_property;
+
+	g_object_class_override_property (gobject_class, PROP_NAME, "name");
+	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
+	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
 }
 
 static guint
@@ -150,14 +192,25 @@ seahorse_pkcs11_backend_collection_init (GcrCollectionIface *iface)
 	iface->get_objects = seahorse_pkcs11_backend_get_objects;
 }
 
-GcrCollection *
+
+static void
+seahorse_pkcs11_backend_iface_init (SeahorseBackendIface *iface)
+{
+
+}
+
+void
 seahorse_pkcs11_backend_initialize (void)
 {
 	SeahorsePkcs11Backend *self;
 
+	g_return_if_fail (pkcs11_backend == NULL);
 	self = g_object_new (SEAHORSE_TYPE_PKCS11_BACKEND, NULL);
 
-	return GCR_COLLECTION (self);
+	seahorse_registry_register_object (NULL, G_OBJECT (self), "backend", "pkcs11", NULL);
+	g_object_unref (self);
+
+	g_return_if_fail (pkcs11_backend != NULL);
 }
 
 SeahorsePkcs11Backend *
diff --git a/pkcs11/seahorse-pkcs11-commands.c b/pkcs11/seahorse-pkcs11-commands.c
index 77f7f1c..6d43eb3 100644
--- a/pkcs11/seahorse-pkcs11-commands.c
+++ b/pkcs11/seahorse-pkcs11-commands.c
@@ -248,7 +248,7 @@ seahorse_pkcs11_commands_class_init (SeahorsePkcs11CommandsClass *klass)
 		
 	/* Register this as a source of commands */
 	seahorse_registry_register_type (seahorse_registry_get (), SEAHORSE_PKCS11_TYPE_COMMANDS, 
-	                                 SEAHORSE_PKCS11_TYPE_STR, "commands", NULL);
+	                                 SEAHORSE_PKCS11_NAME, "commands", NULL);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/pkcs11/seahorse-pkcs11-source.c b/pkcs11/seahorse-pkcs11-source.c
index 5a58d52..162565f 100644
--- a/pkcs11/seahorse-pkcs11-source.c
+++ b/pkcs11/seahorse-pkcs11-source.c
@@ -42,9 +42,12 @@
 #include "seahorse-registry.h"
 
 enum {
-    PROP_0,
-    PROP_SLOT,
-    PROP_FLAGS
+	PROP_0,
+	PROP_LABEL,
+	PROP_DESCRIPTION,
+	PROP_ICON,
+	PROP_SLOT,
+	PROP_FLAGS
 };
 
 struct _SeahorsePkcs11SourcePrivate {
@@ -57,8 +60,8 @@ static void          seahorse_pkcs11_source_iface      (SeahorseSourceIface *ifa
 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_pkcs11_source_iface);
                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_pkcs11_collection_iface);
+                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_pkcs11_source_iface);
 );
 
 /* -----------------------------------------------------------------------------
@@ -95,6 +98,15 @@ seahorse_pkcs11_source_get_property (GObject *object, guint prop_id, GValue *val
 	SeahorsePkcs11Source *self = SEAHORSE_PKCS11_SOURCE (object);
 
 	switch (prop_id) {
+	case PROP_LABEL:
+		g_value_set_string (value, _("To Do Pkcs11"));
+		break;
+	case PROP_DESCRIPTION:
+		g_value_set_string (value, _("To Do Description"));
+		break;
+	case PROP_ICON:
+		g_value_take_object (value, g_themed_icon_new (GTK_STOCK_DIALOG_QUESTION));
+		break;
 	case PROP_SLOT:
 		g_value_set_object (value, self->pv->slot);
 		break;
@@ -158,7 +170,11 @@ seahorse_pkcs11_source_class_init (SeahorsePkcs11SourceClass *klass)
 	gobject_class->finalize = seahorse_pkcs11_source_finalize;
 	gobject_class->set_property = seahorse_pkcs11_source_set_property;
 	gobject_class->get_property = seahorse_pkcs11_source_get_property;
-    
+
+	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
+	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
+	g_object_class_override_property (gobject_class, PROP_ICON, "icon");
+
 	g_object_class_install_property (gobject_class, PROP_SLOT,
 	         g_param_spec_object ("slot", "Slot", "Pkcs#11 SLOT",
 	                              GCK_TYPE_SLOT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -166,8 +182,6 @@ seahorse_pkcs11_source_class_init (SeahorsePkcs11SourceClass *klass)
 	g_object_class_install_property (gobject_class, PROP_FLAGS,
 	         g_param_spec_uint ("flags", "Flags", "Object Source flags.", 
 	                            0, G_MAXUINT, 0, G_PARAM_READABLE));
-
-	seahorse_registry_register_type (NULL, SEAHORSE_TYPE_PKCS11_SOURCE, "source", "local", SEAHORSE_PKCS11_TYPE_STR, NULL);
 }
 
 static void 
diff --git a/pkcs11/seahorse-pkcs11.h b/pkcs11/seahorse-pkcs11.h
index b324330..9bfb0a4 100644
--- a/pkcs11/seahorse-pkcs11.h
+++ b/pkcs11/seahorse-pkcs11.h
@@ -28,10 +28,9 @@
 
 #include <gcr/gcr.h>
 
-#define SEAHORSE_PKCS11_TYPE_STR "pkcs11"
-#define SEAHORSE_PKCS11_TYPE g_quark_from_string ("pkcs11")
+#define SEAHORSE_PKCS11_NAME "pkcs11"
 
-GcrCollection *       seahorse_pkcs11_backend_initialize    (void);
+void       seahorse_pkcs11_backend_initialize    (void);
 
 #endif /* WITH_PKCS11 */
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 05bcc2f..4e6bfb5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,6 +34,7 @@ seahorse_SOURCES = \
 	seahorse-generate-select.c seahorse-generate-select.h \
 	seahorse-key-manager.c seahorse-key-manager.h \
 	seahorse-main.c \
+	seahorse-sidebar.c seahorse-sidebar.h \
 	seahorse-windows.h \
 	$(KEYSERVER_SRCS)
 
diff --git a/src/seahorse-key-manager.c b/src/seahorse-key-manager.c
index e65dc52..926facb 100644
--- a/src/seahorse-key-manager.c
+++ b/src/seahorse-key-manager.c
@@ -22,12 +22,14 @@
 
 #include "config.h"
 
-#include "seahorse-collection.h"
 #include "seahorse-generate-select.h"
 #include "seahorse-key-manager.h"
 #include "seahorse-key-manager-store.h"
 #include "seahorse-preferences.h"
+#include "seahorse-sidebar.h"
 
+#include "seahorse-collection.h"
+#include "seahorse-registry.h"
 #include "seahorse-progress.h"
 #include "seahorse-util.h"
 
@@ -74,7 +76,10 @@ struct _SeahorseKeyManagerPrivate {
 	GtkActionGroup* view_actions;
 	GtkEntry* filter_entry;
 	TabInfo* tabs;
+
 	GSettings *settings;
+	gint sidebar_width;
+	guint sidebar_width_sig;
 };
 
 enum  {
@@ -755,6 +760,52 @@ seahorse_key_manager_set_selected (SeahorseViewer* base, SeahorseObject* value)
 	g_object_notify (G_OBJECT (self), "selected");
 }
 
+static gboolean
+on_idle_save_sidebar_width (gpointer user_data)
+{
+	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (user_data);
+
+	self->pv->sidebar_width_sig = 0;
+	g_settings_set_int (self->pv->settings, "sidebar-width", self->pv->sidebar_width);
+
+	return FALSE;
+}
+
+static void
+on_sidebar_panes_size_allocate (GtkWidget *widget,
+                                GtkAllocation *allocation,
+                                gpointer user_data)
+{
+	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (user_data);
+
+	if (self->pv->sidebar_width_sig != 0) {
+		g_source_remove (self->pv->sidebar_width_sig);
+		self->pv->sidebar_width_sig = 0;
+	}
+
+	if (allocation->width != self->pv->sidebar_width && allocation->width > 1) {
+		self->pv->sidebar_width = allocation->width;
+		self->pv->sidebar_width_sig = g_idle_add (on_idle_save_sidebar_width, self);
+	}
+}
+
+static void
+setup_sidebar (SeahorseKeyManager *self)
+{
+	SeahorseSidebar *sidebar;
+	GtkWidget *widget;
+
+	sidebar = seahorse_sidebar_new ();
+	widget = seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "sidebar-area");
+	gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET (sidebar));
+	gtk_widget_show (GTK_WIDGET (sidebar));
+
+	self->pv->sidebar_width = g_settings_get_int (self->pv->settings, "sidebar-width");
+	widget = seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "sidebar-panes");
+	gtk_paned_set_position (GTK_PANED (widget), self->pv->sidebar_width);
+	g_signal_connect (sidebar, "size_allocate", G_CALLBACK (on_sidebar_panes_size_allocate), self);
+}
+
 static void
 seahorse_key_manager_constructed (GObject *object)
 {
@@ -766,6 +817,8 @@ seahorse_key_manager_constructed (GObject *object)
 
 	G_OBJECT_CLASS (seahorse_key_manager_parent_class)->constructed (object);
 
+	setup_sidebar (self);
+
 	self->pv->tabs = g_new0 (TabInfo, TAB_NUM_TABS);
 
 	self->pv->notebook = GTK_NOTEBOOK (seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "notebook"));
@@ -919,6 +972,11 @@ seahorse_key_manager_finalize (GObject *obj)
 	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (obj);
 	gint i;
 
+	if (self->pv->sidebar_width_sig != 0) {
+		g_source_remove (self->pv->sidebar_width_sig);
+		self->pv->sidebar_width_sig = 0;
+	}
+
 	if (self->pv->view_actions)
 		g_object_unref (self->pv->view_actions);
 	self->pv->view_actions = NULL;
@@ -1016,12 +1074,26 @@ seahorse_key_manager_class_init (SeahorseKeyManagerClass *klass)
 
 
 SeahorseWidget *
-seahorse_key_manager_show (GcrCollection *sources)
+seahorse_key_manager_show (void)
 {
-	SeahorseKeyManager *man = g_object_new (SEAHORSE_TYPE_KEY_MANAGER,
-	                                        "name", "key-manager",
-	                                        "sources", sources,
-	                                        NULL);
-	g_object_ref_sink (man);
-	return SEAHORSE_WIDGET (man);
+	SeahorseKeyManager *self;
+	GcrUnionCollection *sources;
+	GList *backends, *l;
+
+	sources = GCR_UNION_COLLECTION (gcr_union_collection_new ());
+
+	backends = seahorse_registry_object_instances (NULL, "backend", NULL);
+	for (l = backends; l != NULL; l = g_list_next (l))
+		gcr_union_collection_take (sources, GCR_COLLECTION (l->data));
+	g_list_free (backends);
+
+	self = g_object_new (SEAHORSE_TYPE_KEY_MANAGER,
+	                     "name", "key-manager",
+	                     "sources", sources,
+	                     NULL);
+
+	g_object_unref (sources);
+	g_object_ref_sink (self);
+
+	return SEAHORSE_WIDGET (self);
 }
diff --git a/src/seahorse-key-manager.h b/src/seahorse-key-manager.h
index c49fe2a..500a99c 100644
--- a/src/seahorse-key-manager.h
+++ b/src/seahorse-key-manager.h
@@ -52,9 +52,9 @@ struct _SeahorseKeyManagerClass {
 	SeahorseViewerClass parent_class;
 };
 
-SeahorseWidget * seahorse_key_manager_show         (GcrCollection *sources);
+GType            seahorse_key_manager_get_type     (void) G_GNUC_CONST;
 
-GType            seahorse_key_manager_get_type     (void);
+SeahorseWidget * seahorse_key_manager_show         (void);
 
 
 G_END_DECLS
diff --git a/src/seahorse-key-manager.xml b/src/seahorse-key-manager.xml
index 85f71ef..77285f8 100644
--- a/src/seahorse-key-manager.xml
+++ b/src/seahorse-key-manager.xml
@@ -1,336 +1,405 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="2.16"/>
-  <!-- interface-naming-policy toplevel-contextual -->
   <object class="GtkWindow" id="key-manager">
+    <property name="can_focus">False</property>
     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
     <property name="default_width">640</property>
     <property name="default_height">476</property>
     <child>
       <object class="GtkVBox" id="vbox1">
         <property name="visible">True</property>
+        <property name="can_focus">False</property>
         <child>
           <object class="GtkVBox" id="menu-placeholder">
             <property name="visible">True</property>
+            <property name="can_focus">False</property>
             <child>
               <placeholder/>
             </child>
           </object>
           <packing>
             <property name="expand">False</property>
+            <property name="fill">True</property>
             <property name="position">0</property>
           </packing>
         </child>
         <child>
-          <object class="GtkVBox" id="toolbar-placeholder">
-            <property name="visible">True</property>
-            <child>
-              <placeholder/>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkNotebook" id="notebook">
+          <object class="GtkPaned" id="sidebar-panes">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
-            <property name="border_width">3</property>
             <child>
-              <object class="GtkScrolledWindow" id="password-tab">
+              <object class="GtkAlignment" id="sidebar-area">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="border_width">3</property>
-                <property name="hscrollbar_policy">automatic</property>
+                <property name="can_focus">False</property>
                 <child>
-                  <object class="GtkTreeView" id="password-list">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="border_width">12</property>
-                    <property name="rules_hint">True</property>
-                    <signal name="button_press_event" handler="on_keymanager_key_list_button_pressed"/>
-                    <signal name="row_activated" handler="on_keymanager_row_activated"/>
-                    <signal name="popup_menu" handler="on_keymanager_key_list_popup_menu"/>
-                  </object>
+                  <placeholder/>
                 </child>
               </object>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label29">
-                <property name="visible">True</property>
-                <property name="xpad">3</property>
-                <property name="label" translatable="yes">_Passwords</property>
-                <property name="use_underline">True</property>
-              </object>
               <packing>
-                <property name="tab_fill">False</property>
+                <property name="resize">False</property>
+                <property name="shrink">True</property>
               </packing>
             </child>
             <child>
-              <object class="GtkScrolledWindow" id="sec-key-tab">
+              <object class="GtkBox" id="box1">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="border_width">3</property>
-                <property name="hscrollbar_policy">automatic</property>
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
                 <child>
-                  <object class="GtkTreeView" id="sec-key-list">
+                  <object class="GtkVBox" id="toolbar-placeholder">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="border_width">12</property>
-                    <property name="rules_hint">True</property>
-                    <signal name="button_press_event" handler="on_keymanager_key_list_button_pressed"/>
-                    <signal name="row_activated" handler="on_keymanager_row_activated"/>
-                    <signal name="popup_menu" handler="on_keymanager_key_list_popup_menu"/>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label26">
-                <property name="visible">True</property>
-                <property name="xpad">3</property>
-                <property name="label" translatable="yes">My _Personal Keys</property>
-                <property name="use_underline">True</property>
-              </object>
-              <packing>
-                <property name="position">1</property>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkScrolledWindow" id="pub-key-tab">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="border_width">3</property>
-                <property name="hscrollbar_policy">automatic</property>
-                <child>
-                  <object class="GtkTreeView" id="pub-key-list">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="border_width">12</property>
-                    <property name="rules_hint">True</property>
-                    <signal name="button_press_event" handler="on_keymanager_key_list_button_pressed"/>
-                    <signal name="row_activated" handler="on_keymanager_row_activated"/>
-                    <signal name="popup_menu" handler="on_keymanager_key_list_popup_menu"/>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label28">
-                <property name="visible">True</property>
-                <property name="xpad">3</property>
-                <property name="label" translatable="yes">Other _Keys</property>
-                <property name="use_underline">True</property>
-              </object>
-              <packing>
-                <property name="position">2</property>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="position">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="alignment5">
-            <property name="visible">True</property>
-            <property name="xalign">0</property>
-            <property name="yscale">0</property>
-            <child>
-              <object class="GtkVBox" id="first-time-box">
-                <property name="border_width">12</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkLabel" id="label17">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="xpad">6</property>
-                    <property name="label" translatable="yes">&lt;big&gt;&lt;b&gt;First time options:&lt;/b&gt;&lt;/big&gt;</property>
-                    <property name="use_markup">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <placeholder/>
+                    </child>
                   </object>
                   <packing>
                     <property name="expand">False</property>
-                    <property name="fill">False</property>
+                    <property name="fill">True</property>
                     <property name="position">0</property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkHSeparator" id="hseparator3">
+                  <object class="GtkNotebook" id="notebook">
                     <property name="visible">True</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkTable" id="table2">
-                    <property name="visible">True</property>
-                    <property name="border_width">6</property>
-                    <property name="n_rows">3</property>
-                    <property name="n_columns">2</property>
-                    <property name="column_spacing">12</property>
-                    <property name="row_spacing">6</property>
+                    <property name="can_focus">True</property>
+                    <property name="border_width">3</property>
                     <child>
-                      <object class="GtkButton" id="new-button">
-                        <property name="label">gtk-new</property>
+                      <object class="GtkScrolledWindow" id="password-tab">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="use_stock">True</property>
-                        <signal name="clicked" handler="on_keymanager_new_button"/>
+                        <property name="border_width">3</property>
+                        <child>
+                          <object class="GtkTreeView" id="password-list">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="border_width">12</property>
+                            <property name="rules_hint">True</property>
+                            <signal name="button-press-event" handler="on_keymanager_key_list_button_pressed" swapped="no"/>
+                            <signal name="row-activated" handler="on_keymanager_row_activated" swapped="no"/>
+                            <signal name="popup-menu" handler="on_keymanager_key_list_popup_menu" swapped="no"/>
+                            <child internal-child="selection">
+                              <object class="GtkTreeSelection" id="treeview-selection"/>
+                            </child>
+                          </object>
+                        </child>
                       </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                        <property name="x_options"></property>
-                        <property name="y_options"></property>
-                      </packing>
                     </child>
-                    <child>
-                      <object class="GtkLabel" id="label21">
+                    <child type="tab">
+                      <object class="GtkLabel" id="label29">
                         <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Generate a new key of your own: </property>
+                        <property name="can_focus">False</property>
+                        <property name="xpad">3</property>
+                        <property name="label" translatable="yes">_Passwords</property>
+                        <property name="use_underline">True</property>
                       </object>
                       <packing>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                        <property name="x_options"></property>
-                        <property name="y_options"></property>
+                        <property name="tab_fill">False</property>
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkButton" id="import-button">
+                      <object class="GtkScrolledWindow" id="sec-key-tab">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="has_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="has_default">True</property>
-                        <property name="receives_default">False</property>
-                        <signal name="clicked" handler="on_keymanager_import_button"/>
+                        <property name="border_width">3</property>
                         <child>
-                          <object class="GtkAlignment" id="alignment6">
+                          <object class="GtkTreeView" id="sec-key-list">
                             <property name="visible">True</property>
-                            <property name="xscale">0</property>
-                            <property name="yscale">0</property>
-                            <child>
-                              <object class="GtkHBox" id="hbox4">
-                                <property name="visible">True</property>
-                                <property name="spacing">2</property>
-                                <child>
-                                  <object class="GtkImage" id="image2">
-                                    <property name="visible">True</property>
-                                    <property name="stock">gtk-open</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label20">
-                                    <property name="visible">True</property>
-                                    <property name="label" translatable="yes">_Import</property>
-                                    <property name="use_underline">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
+                            <property name="can_focus">True</property>
+                            <property name="border_width">12</property>
+                            <property name="rules_hint">True</property>
+                            <signal name="button-press-event" handler="on_keymanager_key_list_button_pressed" swapped="no"/>
+                            <signal name="row-activated" handler="on_keymanager_row_activated" swapped="no"/>
+                            <signal name="popup-menu" handler="on_keymanager_key_list_popup_menu" swapped="no"/>
+                            <child internal-child="selection">
+                              <object class="GtkTreeSelection" id="treeview-selection1"/>
                             </child>
                           </object>
                         </child>
                       </object>
                       <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="x_options"></property>
-                        <property name="y_options"></property>
+                        <property name="position">1</property>
                       </packing>
                     </child>
-                    <child>
-                      <object class="GtkLabel" id="label19">
+                    <child type="tab">
+                      <object class="GtkLabel" id="label26">
                         <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Import existing keys from a file:</property>
+                        <property name="can_focus">False</property>
+                        <property name="xpad">3</property>
+                        <property name="label" translatable="yes">My _Personal Keys</property>
+                        <property name="use_underline">True</property>
                       </object>
                       <packing>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="x_options"></property>
-                        <property name="y_options"></property>
+                        <property name="position">1</property>
+                        <property name="tab_fill">False</property>
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkButton" id="help-button">
-                        <property name="label">gtk-help</property>
+                      <object class="GtkScrolledWindow" id="pub-key-tab">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="has_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="has_default">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="use_stock">True</property>
-                        <signal name="clicked" handler="on_widget_help"/>
+                        <property name="border_width">3</property>
+                        <child>
+                          <object class="GtkTreeView" id="pub-key-list">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="border_width">12</property>
+                            <property name="rules_hint">True</property>
+                            <signal name="button-press-event" handler="on_keymanager_key_list_button_pressed" swapped="no"/>
+                            <signal name="row-activated" handler="on_keymanager_row_activated" swapped="no"/>
+                            <signal name="popup-menu" handler="on_keymanager_key_list_popup_menu" swapped="no"/>
+                            <child internal-child="selection">
+                              <object class="GtkTreeSelection" id="treeview-selection2"/>
+                            </child>
+                          </object>
+                        </child>
                       </object>
                       <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="x_options"></property>
-                        <property name="y_options"></property>
+                        <property name="position">2</property>
                       </packing>
                     </child>
-                    <child>
-                      <object class="GtkLabel" id="label18">
+                    <child type="tab">
+                      <object class="GtkLabel" id="label28">
                         <property name="visible">True</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">To get started with encryption you will need keys.</property>
-                        <property name="wrap">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xpad">3</property>
+                        <property name="label" translatable="yes">Other _Keys</property>
+                        <property name="use_underline">True</property>
                       </object>
                       <packing>
-                        <property name="x_options"></property>
-                        <property name="y_options"></property>
+                        <property name="position">2</property>
+                        <property name="tab_fill">False</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkAlignment" id="alignment5">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="yscale">0</property>
+                    <child>
+                      <object class="GtkVBox" id="first-time-box">
+                        <property name="can_focus">False</property>
+                        <property name="border_width">12</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkLabel" id="label17">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">6</property>
+                            <property name="label" translatable="yes">&lt;big&gt;&lt;b&gt;First time options:&lt;/b&gt;&lt;/big&gt;</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkHSeparator" id="hseparator3">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkTable" id="table2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="border_width">6</property>
+                            <property name="n_rows">3</property>
+                            <property name="n_columns">2</property>
+                            <property name="column_spacing">12</property>
+                            <property name="row_spacing">6</property>
+                            <child>
+                              <object class="GtkButton" id="new-button">
+                                <property name="label">gtk-new</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">True</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="use_stock">True</property>
+                                <signal name="clicked" handler="on_keymanager_new_button" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">2</property>
+                                <property name="bottom_attach">3</property>
+                                <property name="x_options"></property>
+                                <property name="y_options"></property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label21">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Generate a new key of your own: </property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">2</property>
+                                <property name="bottom_attach">3</property>
+                                <property name="x_options"></property>
+                                <property name="y_options"></property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkButton" id="import-button">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="can_default">True</property>
+                                <property name="has_default">True</property>
+                                <property name="receives_default">True</property>
+                                <property name="use_action_appearance">False</property>
+                                <signal name="clicked" handler="on_keymanager_import_button" swapped="no"/>
+                                <child>
+                                  <object class="GtkAlignment" id="alignment6">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="xscale">0</property>
+                                    <property name="yscale">0</property>
+                                    <child>
+                                      <object class="GtkHBox" id="hbox4">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="spacing">2</property>
+                                        <child>
+                                          <object class="GtkImage" id="image2">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="stock">gtk-open</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">False</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel" id="label20">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">_Import</property>
+                                            <property name="use_underline">True</property>
+                                          </object>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">False</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                    </child>
+                                  </object>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                                <property name="x_options"></property>
+                                <property name="y_options"></property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label19">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Import existing keys from a file:</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                                <property name="x_options"></property>
+                                <property name="y_options"></property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkButton" id="help-button">
+                                <property name="label">gtk-help</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="can_default">True</property>
+                                <property name="has_default">True</property>
+                                <property name="receives_default">True</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="use_stock">True</property>
+                                <signal name="clicked" handler="on_widget_help" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="x_options"></property>
+                                <property name="y_options"></property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label18">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">To get started with encryption you will need keys.</property>
+                                <property name="wrap">True</property>
+                              </object>
+                              <packing>
+                                <property name="x_options"></property>
+                                <property name="y_options"></property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
                     <property name="position">2</property>
                   </packing>
                 </child>
               </object>
+              <packing>
+                <property name="resize">True</property>
+                <property name="shrink">True</property>
+              </packing>
             </child>
           </object>
           <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">3</property>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
           </packing>
         </child>
         <child>
           <object class="GtkHBox" id="status-bar-area">
             <property name="visible">True</property>
+            <property name="can_focus">False</property>
             <child>
               <object class="GtkProgressBar" id="progress">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
                 <property name="pulse_step">0.10000000149</property>
               </object>
               <packing>
@@ -342,15 +411,20 @@
             <child>
               <object class="GtkStatusbar" id="status">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="spacing">2</property>
               </object>
               <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
                 <property name="position">1</property>
               </packing>
             </child>
           </object>
           <packing>
             <property name="expand">False</property>
-            <property name="position">4</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
           </packing>
         </child>
       </object>
diff --git a/src/seahorse-main.c b/src/seahorse-main.c
index 7f70309..e2ebf6a 100644
--- a/src/seahorse-main.c
+++ b/src/seahorse-main.c
@@ -48,7 +48,6 @@ int
 main (int argc, char **argv)
 {
 	SeahorseWidget *swidget;
-	GcrUnionCollection *sources;
 	SeahorseContext *context;
 
     static GOptionEntry options[] = {
@@ -87,25 +86,23 @@ main (int argc, char **argv)
     seahorse_context_create ();
     context = seahorse_context_instance ();
 
-    sources = GCR_UNION_COLLECTION (gcr_union_collection_new ());
-
     /* Initialize the various components */
-    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_pgp_backend_initialize ();
+    seahorse_ssh_backend_initialize ();
+    seahorse_pkcs11_backend_initialize ();
+    seahorse_gkr_backend_initialize ();
 
-    swidget = seahorse_key_manager_show (GCR_COLLECTION (sources));
-    g_object_unref (sources);
+    swidget = seahorse_key_manager_show ();
 
     g_object_ref (context);
     g_signal_connect_after (context, "destroy", gtk_main_quit, NULL);
 
     gtk_main ();
 
+    seahorse_cleanup_perform ();
+
     g_object_unref (swidget);
     g_object_unref (context);
 
-    seahorse_cleanup_perform ();
     return ret;
 }
diff --git a/src/seahorse-sidebar.c b/src/seahorse-sidebar.c
new file mode 100644
index 0000000..39555a6
--- /dev/null
+++ b/src/seahorse-sidebar.c
@@ -0,0 +1,586 @@
+/*
+ * 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 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-sidebar.h"
+
+#include "seahorse-registry.h"
+
+#include "gkr/seahorse-gkr.h"
+#include "pgp/seahorse-pgp.h"
+#include "pkcs11/seahorse-pkcs11.h"
+#include "ssh/seahorse-ssh.h"
+
+#include <glib/gi18n.h>
+
+struct _SeahorseSidebar {
+	GtkScrolledWindow parent;
+
+	GtkTreeView *tree_view;
+
+	GtkListStore *store;
+	GPtrArray *backends;
+
+	guint update_places_sig;
+};
+
+struct _SeahorseSidebarClass {
+	GtkScrolledWindowClass parent_class;
+};
+
+enum {
+	PROP_0,
+};
+
+typedef enum {
+	PLACES_HEADING,
+	PLACES_COLLECTION,
+} PlaceType;
+
+enum {
+	SIDEBAR_ROW_TYPE,
+	SIDEBAR_ICON,
+	SIDEBAR_LABEL,
+	SIDEBAR_TOOLTIP,
+	SIDEBAR_EDITABLE,
+	SIDEBAR_CATEGORY,
+	SIDEBAR_COLLECTION,
+	SIDEBAR_N_COLUMNS
+};
+
+static GType column_types[] = {
+	G_TYPE_UINT,
+	0 /* later */,
+	G_TYPE_STRING,
+	G_TYPE_STRING,
+	G_TYPE_BOOLEAN,
+	G_TYPE_STRING,
+	0 /* later */
+};
+
+G_DEFINE_TYPE (SeahorseSidebar, seahorse_sidebar, GTK_TYPE_SCROLLED_WINDOW);
+
+static void
+seahorse_sidebar_init (SeahorseSidebar *self)
+{
+	g_assert (SIDEBAR_N_COLUMNS == G_N_ELEMENTS (column_types));
+	column_types[SIDEBAR_ICON] = G_TYPE_ICON;
+	column_types[SIDEBAR_COLLECTION] = GCR_TYPE_COLLECTION;
+	self->store = gtk_list_store_newv (SIDEBAR_N_COLUMNS, column_types);
+
+	self->backends = g_ptr_array_new_with_free_func (g_object_unref);
+}
+
+static void
+update_backend (SeahorseSidebar *self,
+                GcrCollection *backend)
+{
+	GList *collections, *l;
+	GtkTreeIter iter;
+	GParamSpec *spec;
+	gchar *category;
+	gchar *tooltip;
+	gchar *label;
+	GIcon *icon = NULL;
+
+	collections = gcr_collection_get_objects (backend);
+
+	/* Ignore categories that have nothing */
+	if (collections == NULL)
+		return;
+
+	g_object_get (backend,
+	              "name", &category,
+	              "label", &label,
+	              "description", &tooltip,
+	              NULL);
+
+	gtk_list_store_append (self->store, &iter);
+	gtk_list_store_set (self->store, &iter,
+	                    SIDEBAR_ROW_TYPE, PLACES_HEADING,
+	                    SIDEBAR_CATEGORY, category,
+	                    SIDEBAR_LABEL, label,
+	                    SIDEBAR_TOOLTIP, tooltip,
+	                    SIDEBAR_EDITABLE, FALSE,
+	                    -1);
+
+	g_free (label);
+	g_free (tooltip);
+
+	for (l = collections; l != NULL; l = g_list_next (l)) {
+
+		label = tooltip = NULL;
+		g_object_get (l->data,
+		              "label", &label,
+		              "description", &tooltip,
+		              "icon", &icon,
+		              NULL);
+
+		spec = g_object_class_find_property (G_OBJECT_GET_CLASS (l->data), "label");
+		g_return_if_fail (spec != NULL);
+
+		gtk_list_store_append (self->store, &iter);
+		gtk_list_store_set (self->store, &iter,
+		                    SIDEBAR_ROW_TYPE, PLACES_COLLECTION,
+		                    SIDEBAR_CATEGORY, category,
+		                    SIDEBAR_LABEL, label,
+		                    SIDEBAR_TOOLTIP, tooltip,
+		                    SIDEBAR_ICON, icon,
+		                    SIDEBAR_EDITABLE, (spec->flags & G_PARAM_WRITABLE) ? TRUE : FALSE,
+		                    SIDEBAR_COLLECTION, l->data,
+		                    -1);
+
+		g_clear_object (&icon);
+		g_free (label);
+		g_free (tooltip);
+	}
+
+	g_free (category);
+	g_list_free (collections);
+}
+
+static void
+update_places (SeahorseSidebar *self)
+{
+	guint i;
+
+	gtk_list_store_clear (self->store);
+
+	for (i = 0; i < self->backends->len; i++)
+		update_backend (self, GCR_COLLECTION (self->backends->pdata[i]));
+}
+
+static gboolean
+on_idle_update_places (gpointer user_data)
+{
+	SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
+
+	self->update_places_sig = 0;
+	update_places (self);
+
+	return FALSE; /* don't call again */
+}
+
+static void
+update_places_later (SeahorseSidebar *self)
+{
+	if (!self->update_places_sig)
+		self->update_places_sig = g_idle_add (on_idle_update_places, self);
+}
+
+static void
+on_cell_renderer_heading_visible (GtkTreeViewColumn *column,
+                                  GtkCellRenderer *cell,
+                                  GtkTreeModel *model,
+                                  GtkTreeIter *iter,
+                                  gpointer user_data)
+{
+	PlaceType type;
+	gtk_tree_model_get (model, iter,
+	                    SIDEBAR_ROW_TYPE, &type,
+	                    -1);
+	g_object_set (cell,
+	              "visible", (type == PLACES_HEADING),
+	              NULL);
+}
+
+static void
+on_padding_cell_renderer (GtkTreeViewColumn *column,
+                          GtkCellRenderer *cell,
+                          GtkTreeModel *model,
+                          GtkTreeIter *iter,
+                          gpointer user_data)
+{
+	PlaceType type;
+	gtk_tree_model_get (model, iter,
+	                    SIDEBAR_ROW_TYPE, &type,
+	                    -1);
+
+	if (type == PLACES_HEADING) {
+		g_object_set (cell,
+		              "visible", FALSE,
+		              "xpad", 0,
+		              "ypad", 0,
+		              NULL);
+	} else {
+		g_object_set (cell,
+		              "visible", TRUE,
+		              "xpad", 3,
+		              "ypad", 3,
+		              NULL);
+	}
+}
+
+static void
+on_cell_renderer_heading_not_visible (GtkTreeViewColumn *column,
+                                      GtkCellRenderer *cell,
+                                      GtkTreeModel *model,
+                                      GtkTreeIter *iter,
+                                      gpointer user_data)
+{
+	PlaceType type;
+	gtk_tree_model_get (model, iter,
+	                    SIDEBAR_ROW_TYPE, &type,
+	                    -1);
+	g_object_set (cell,
+	              "visible", (type != PLACES_HEADING),
+	              NULL);
+}
+
+static gboolean
+on_tree_selection (GtkTreeSelection *selection,
+                   GtkTreeModel *model,
+                   GtkTreePath *path,
+                   gboolean path_currently_selected,
+                   gpointer user_data)
+{
+	GtkTreeIter iter;
+	PlaceType row_type;
+
+	gtk_tree_model_get_iter (model, &iter, path);
+	gtk_tree_model_get (model, &iter,
+	                    SIDEBAR_ROW_TYPE, &row_type,
+	                    -1);
+	if (row_type == PLACES_HEADING)
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
+on_tree_view_button_press (GtkWidget *tree_view,
+                           GdkEventButton *event,
+                           gpointer data)
+{
+	GtkTreePath *path;
+	GtkTreeViewColumn *column;
+
+	if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+		if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (tree_view),
+		                                   event->x, event->y,
+		                                   &path,
+		                                   &column,
+		                                   NULL,
+		                                   NULL))
+			gtk_tree_view_row_activated (GTK_TREE_VIEW (tree_view), path, column);
+	}
+
+	return FALSE;
+}
+
+static void
+on_place_changed (GObject *obj,
+                  GParamSpec *spec,
+                  gpointer user_data)
+{
+	SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
+	update_places_later (self);
+}
+
+static void
+on_backend_changed (GObject *obj,
+                    GParamSpec *spec,
+                    gpointer user_data)
+{
+	SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
+	update_places_later (self);
+}
+
+static void
+on_place_added (GcrCollection *places,
+                GObject *object,
+                gpointer user_data)
+{
+	SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
+	g_signal_connect (object, "notify", G_CALLBACK (on_place_changed), self);
+	update_places_later (self);
+}
+
+static void
+on_place_removed (GcrCollection *places,
+                  GObject *object,
+                  gpointer user_data)
+{
+	SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
+	g_signal_handlers_disconnect_by_func (object, on_place_changed, self);
+	update_places_later (self);
+}
+
+static gint
+order_from_backend (GObject *backend)
+{
+	gchar *name;
+	gint order;
+
+	g_object_get (backend, "name", &name, NULL);
+
+	if (name == NULL)
+		order = 10;
+	else if (g_str_equal (name, SEAHORSE_GKR_NAME))
+		order = 0;
+	else if (g_str_equal (name, SEAHORSE_PGP_NAME))
+		order = 1;
+	else if (g_str_equal (name, SEAHORSE_PKCS11_NAME))
+		order = 2;
+	else if (g_str_equal (name, SEAHORSE_SSH_NAME))
+		order = 3;
+	else
+		order = 10;
+
+	g_free (name);
+	return order;
+}
+
+static gint
+on_sort_backends (gconstpointer a,
+                  gconstpointer b)
+{
+	gint ordera = order_from_backend (G_OBJECT (*((gpointer *)a)));
+	gint orderb = order_from_backend (G_OBJECT (*((gpointer *)b)));
+	return ordera - orderb;
+}
+
+static void
+load_backends (SeahorseSidebar *self)
+{
+	GList *backends, *l;
+	GList *places, *p;
+
+	backends = seahorse_registry_object_instances (NULL, "backend", NULL);
+	for (l = backends; l != NULL; l = g_list_next (l)) {
+		g_ptr_array_add (self->backends, l->data);
+		g_signal_connect (l->data, "added", G_CALLBACK (on_place_added), self);
+		g_signal_connect (l->data, "removed", G_CALLBACK (on_place_removed), self);
+		g_signal_connect (l->data, "notify", G_CALLBACK (on_backend_changed), self);
+
+		places = gcr_collection_get_objects (l->data);
+		for (p = places; p != NULL; p = g_list_next (p))
+			on_place_added (l->data, p->data, self);
+		g_list_free (places);
+	}
+	g_ptr_array_sort (self->backends, on_sort_backends);
+	g_list_free (backends);
+}
+
+static void
+seahorse_sidebar_constructed (GObject *obj)
+{
+	SeahorseSidebar *self = SEAHORSE_SIDEBAR (obj);
+	GtkTreeSelection *selection;
+	GtkTreeViewColumn *col;
+	GtkTreeView *tree_view;
+	GtkCellRenderer *cell;
+
+	G_OBJECT_CLASS (seahorse_sidebar_parent_class)->constructed (obj);
+
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self),
+	                                GTK_POLICY_NEVER,
+	                                GTK_POLICY_AUTOMATIC);
+	gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (self), NULL);
+	gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (self), NULL);
+	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (self), GTK_SHADOW_IN);
+	gtk_style_context_set_junction_sides (gtk_widget_get_style_context (GTK_WIDGET (self)),
+	                                      GTK_JUNCTION_RIGHT | GTK_JUNCTION_LEFT);
+
+	/* tree view */
+	tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
+	col = gtk_tree_view_column_new ();
+
+	/* initial padding */
+	cell = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_start (col, cell, FALSE);
+	g_object_set (cell,
+	              "xpad", 6,
+	              NULL);
+
+	/* headings */
+	cell = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_start (col, cell, FALSE);
+	gtk_tree_view_column_set_attributes (col, cell,
+	                                     "text", SIDEBAR_LABEL,
+	                                     NULL);
+	g_object_set (cell,
+	              "weight", PANGO_WEIGHT_BOLD,
+	              "weight-set", TRUE,
+	              "ypad", 6,
+	              "xpad", 0,
+	              NULL);
+	gtk_tree_view_column_set_cell_data_func (col, cell,
+	                                         on_cell_renderer_heading_visible,
+	                                         self, NULL);
+
+	/* icon padding */
+	cell = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_start (col, cell, FALSE);
+	gtk_tree_view_column_set_cell_data_func (col, cell,
+	                                         on_padding_cell_renderer,
+	                                         self, NULL);
+
+	/* icon renderer */
+	cell = gtk_cell_renderer_pixbuf_new ();
+	gtk_tree_view_column_pack_start (col, cell, FALSE);
+	gtk_tree_view_column_set_attributes (col, cell,
+	                                     "gicon", SIDEBAR_ICON,
+	                                     NULL);
+	gtk_tree_view_column_set_cell_data_func (col, cell,
+	                                         on_cell_renderer_heading_not_visible,
+	                                         self, NULL);
+
+	/* normal text renderer */
+	cell = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_start (col, cell, TRUE);
+	g_object_set (G_OBJECT (cell), "editable", FALSE, NULL);
+	gtk_tree_view_column_set_attributes (col, cell,
+	                                     "text", SIDEBAR_LABEL,
+	                                     NULL);
+	gtk_tree_view_column_set_cell_data_func (col, cell,
+	                                         on_cell_renderer_heading_not_visible,
+	                                         self, NULL);
+	g_object_set (cell,
+	              "ellipsize", PANGO_ELLIPSIZE_END,
+	              "ellipsize-set", TRUE,
+	              NULL);
+
+	/* this is required to align the eject buttons to the right */
+	gtk_tree_view_column_set_max_width (GTK_TREE_VIEW_COLUMN (col), 24);
+	gtk_tree_view_append_column (tree_view, col);
+
+	gtk_tree_view_set_headers_visible (tree_view, FALSE);
+	gtk_tree_view_set_tooltip_column (tree_view, SIDEBAR_TOOLTIP);
+	gtk_tree_view_set_search_column (tree_view, SIDEBAR_LABEL);
+	gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (self->store));
+
+	gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (tree_view));
+	gtk_widget_show (GTK_WIDGET (tree_view));
+	self->tree_view = tree_view;
+
+	selection = gtk_tree_view_get_selection (tree_view);
+	gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
+
+	gtk_tree_selection_set_select_function (selection, on_tree_selection,
+	                                        self, NULL);
+
+	g_signal_connect (tree_view, "button_press_event",
+	                  G_CALLBACK (on_tree_view_button_press), NULL);
+
+	load_backends (self);
+}
+
+#if 0
+
+static void
+seahorse_sidebar_get_property (GObject *obj,
+                               guint prop_id,
+                               GValue *value,
+                               GParamSpec *pspec)
+{
+	SeahorseSidebar *self = SEAHORSE_SIDEBAR (obj);
+
+	switch (prop_id) {
+	case PROP_PLACES:
+		g_value_set_object (value, self->places);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+seahorse_sidebar_set_property (GObject *obj,
+                               guint prop_id,
+                               const GValue *value,
+                               GParamSpec *pspec)
+{
+	SeahorseSidebar *self = SEAHORSE_SIDEBAR (obj);
+
+	switch (prop_id) {
+	case PROP_PLACES:
+		self->places = g_value_dup_object (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+#endif
+
+static void
+seahorse_sidebar_dispose (GObject *obj)
+{
+	SeahorseSidebar *self = SEAHORSE_SIDEBAR (obj);
+	GList *places, *l;
+	gint i;
+
+	for (i = 0; i < self->backends->len; i++) {
+		g_signal_handlers_disconnect_by_func (self->backends->pdata[i], on_place_added, self);
+		g_signal_handlers_disconnect_by_func (self->backends->pdata[i], on_place_removed, self);
+		g_signal_handlers_disconnect_by_func (self->backends->pdata[i], on_backend_changed, self);
+
+		places = gcr_collection_get_objects (self->backends->pdata[i]);
+		for (l = places; l != NULL; l = g_list_next (l))
+			on_place_removed (self->backends->pdata[i], l->data, self);
+		g_list_free (places);
+	}
+
+	G_OBJECT_CLASS (seahorse_sidebar_parent_class)->dispose (obj);
+}
+
+static void
+seahorse_sidebar_finalize (GObject *obj)
+{
+	SeahorseSidebar *self = SEAHORSE_SIDEBAR (obj);
+
+	if (self->update_places_sig)
+		g_source_remove (self->update_places_sig);
+
+	g_ptr_array_unref (self->backends);
+	g_object_unref (self->store);
+
+	G_OBJECT_CLASS (seahorse_sidebar_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_sidebar_class_init (SeahorseSidebarClass *klass)
+{
+	GObjectClass *gobject_class= G_OBJECT_CLASS (klass);
+
+	gobject_class->constructed = seahorse_sidebar_constructed;
+	gobject_class->dispose = seahorse_sidebar_dispose;
+	gobject_class->finalize = seahorse_sidebar_finalize;
+#if 0
+	gobject_class->set_property = seahorse_sidebar_set_property;
+	gobject_class->get_property = seahorse_sidebar_get_property;
+
+	g_object_class_install_property (gobject_class, PROP_PLACES,
+	        g_param_spec_object ("places", "Places", "Places for Items",
+	                             GCR_TYPE_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+#endif
+}
+
+SeahorseSidebar *
+seahorse_sidebar_new (void)
+{
+	return g_object_new (SEAHORSE_TYPE_SIDEBAR,
+	                     NULL);
+}
diff --git a/src/seahorse-sidebar.h b/src/seahorse-sidebar.h
new file mode 100644
index 0000000..e167e30
--- /dev/null
+++ b/src/seahorse-sidebar.h
@@ -0,0 +1,43 @@
+/*
+ * 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 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_SIDEBAR_H__
+#define __SEAHORSE_SIDEBAR_H__
+
+#include <gcr/gcr.h>
+
+#include <gtk/gtk.h>
+
+#define SEAHORSE_TYPE_SIDEBAR             (seahorse_sidebar_get_type ())
+#define SEAHORSE_SIDEBAR(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_SIDEBAR, SeahorseSidebar))
+#define SEAHORSE_SIDEBAR_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_SIDEBAR, SeahorseSidebarClass))
+#define SEAHORSE_IS_SIDEBAR(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_SIDEBAR))
+#define SEAHORSE_IS_SIDEBAR_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_SIDEBAR))
+#define SEAHORSE_SIDEBAR_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_SIDEBAR_KEY, SeahorseSidebarClass))
+
+typedef struct _SeahorseSidebar SeahorseSidebar;
+typedef struct _SeahorseSidebarClass SeahorseSidebarClass;
+
+GType                        seahorse_sidebar_get_type           (void);
+
+SeahorseSidebar *            seahorse_sidebar_new                (void);
+
+#endif /* __SEAHORSE_SIDEBAR_H__ */
diff --git a/ssh/seahorse-ssh-backend.c b/ssh/seahorse-ssh-backend.c
index 98821a1..c1ee70c 100644
--- a/ssh/seahorse-ssh-backend.c
+++ b/ssh/seahorse-ssh-backend.c
@@ -26,6 +26,18 @@
 #include "seahorse-ssh-dialogs.h"
 #include "seahorse-ssh-source.h"
 
+#include "seahorse-backend.h"
+#include "seahorse-registry.h"
+
+#include <glib/gi18n.h>
+
+enum {
+	PROP_0,
+	PROP_NAME,
+	PROP_LABEL,
+	PROP_DESCRIPTION
+};
+
 static SeahorseSshBackend *ssh_backend = NULL;
 
 struct _SeahorseSshBackend {
@@ -37,10 +49,14 @@ struct _SeahorseSshBackendClass {
 	GObjectClass parent_class;
 };
 
+static void         seahorse_ssh_backend_iface_init       (SeahorseBackendIface *iface);
+
 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));
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_ssh_backend_collection_init);
+                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_BACKEND, seahorse_ssh_backend_iface_init);
+);
 
 static void
 seahorse_ssh_backend_init (SeahorseSshBackend *self)
@@ -66,6 +82,28 @@ seahorse_ssh_backend_constructed (GObject *obj)
 }
 
 static void
+seahorse_ssh_backend_get_property (GObject *obj,
+                                   guint prop_id,
+                                   GValue *value,
+                                   GParamSpec *pspec)
+{
+	switch (prop_id) {
+	case PROP_NAME:
+		g_value_set_string (value, SEAHORSE_SSH_NAME);
+		break;
+	case PROP_LABEL:
+		g_value_set_string (value, _("Secure Shell"));
+		break;
+	case PROP_DESCRIPTION:
+		g_value_set_string (value, _("Keys used to connect securely to other computers"));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
 seahorse_ssh_backend_finalize (GObject *obj)
 {
 	SeahorseSshBackend *self = SEAHORSE_SSH_BACKEND (obj);
@@ -83,6 +121,11 @@ 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;
+	gobject_class->get_property = seahorse_ssh_backend_get_property;
+
+	g_object_class_override_property (gobject_class, PROP_NAME, "name");
+	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
+	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
 }
 
 static guint
@@ -114,14 +157,24 @@ seahorse_ssh_backend_collection_init (GcrCollectionIface *iface)
 	iface->get_objects = seahorse_ssh_backend_get_objects;
 }
 
-GcrCollection *
+static void
+seahorse_ssh_backend_iface_init (SeahorseBackendIface *iface)
+{
+
+}
+
+void
 seahorse_ssh_backend_initialize (void)
 {
 	SeahorseSshBackend *self;
 
+	g_return_if_fail (ssh_backend == NULL);
 	self = g_object_new (SEAHORSE_TYPE_SSH_BACKEND, NULL);
 
-	return GCR_COLLECTION (self);
+	seahorse_registry_register_object (NULL, G_OBJECT (self), "backend", "openssh", NULL);
+	g_object_unref (self);
+
+	g_return_if_fail (ssh_backend != NULL);
 }
 
 SeahorseSshBackend *
diff --git a/ssh/seahorse-ssh-source.c b/ssh/seahorse-ssh-source.c
index a2ad753..5bc7bad 100644
--- a/ssh/seahorse-ssh-source.c
+++ b/ssh/seahorse-ssh-source.c
@@ -45,8 +45,11 @@
 #include "seahorse-debug.h"
 
 enum {
-    PROP_0,
-    PROP_BASE_DIRECTORY
+	PROP_0,
+	PROP_LABEL,
+	PROP_DESCRIPTION,
+	PROP_ICON,
+	PROP_BASE_DIRECTORY
 };
 
 struct _SeahorseSSHSourcePrivate {
@@ -61,8 +64,8 @@ static void       seahorse_ssh_source_iface             (SeahorseSourceIface *if
 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_ssh_source_iface)
                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_ssh_source_collection_iface);
+                        G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_SOURCE, seahorse_ssh_source_iface)
 );
 
 #define AUTHORIZED_KEYS_FILE    "authorized_keys"
@@ -214,16 +217,30 @@ merge_keydata (SeahorseSSHKey *prev, SeahorseSSHKeyData *keydata)
 }
 
 static void 
-seahorse_ssh_source_get_property (GObject *object, guint prop_id, GValue *value, 
+seahorse_ssh_source_get_property (GObject *obj,
+                                  guint prop_id,
+                                  GValue *value,
                                   GParamSpec *pspec)
 {
-    SeahorseSSHSource *ssrc = SEAHORSE_SSH_SOURCE (object);
-    
-    switch (prop_id) {
-    case PROP_BASE_DIRECTORY:
-        g_value_set_string (value, ssrc->priv->ssh_homedir);
-        break;
-    }
+	SeahorseSSHSource *self = SEAHORSE_SSH_SOURCE (obj);
+
+	switch (prop_id) {
+	case PROP_LABEL:
+		g_value_set_string (value, _("To SSH Keys"));
+		break;
+	case PROP_DESCRIPTION:
+		g_value_set_string (value, _("To Do Description"));
+		break;
+	case PROP_ICON:
+		g_value_take_object (value, g_themed_icon_new (GTK_STOCK_DIALOG_QUESTION));
+		break;
+	case PROP_BASE_DIRECTORY:
+		g_value_set_string (value, self->priv->ssh_homedir);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
 }
 
 static void
@@ -308,6 +325,10 @@ seahorse_ssh_source_class_init (SeahorseSSHSourceClass *klass)
     gobject_class->finalize = seahorse_ssh_source_finalize;
     gobject_class->get_property = seahorse_ssh_source_get_property;
 
+    g_object_class_override_property (gobject_class, PROP_LABEL, "label");
+    g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
+    g_object_class_override_property (gobject_class, PROP_ICON, "icon");
+
     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));
diff --git a/ssh/seahorse-ssh.h b/ssh/seahorse-ssh.h
index ba76603..387b0cc 100644
--- a/ssh/seahorse-ssh.h
+++ b/ssh/seahorse-ssh.h
@@ -29,12 +29,12 @@
 
 #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_NAME "openssh"
+#define SEAHORSE_SSH_TYPE_STR SEAHORSE_SSH_NAME
+#define SEAHORSE_SSH (g_quark_from_static_string (SEAHORSE_PGP_NAME))
 #define SEAHORSE_SSH_STOCK_ICON "seahorse-key-ssh"
 
-GcrCollection *       seahorse_ssh_backend_initialize    (void);
+void       seahorse_ssh_backend_initialize    (void);
 
 #endif /* WITH_SSH */
 



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