[gnome-keyring/selector: 5/5] [gcr] More implementation of selector widget.



commit a62de30b072ff2e1eef7401c793c6cba7b3df67c
Author: Stef Walter <stef memberwebs com>
Date:   Wed Oct 20 20:47:39 2010 +0000

    [gcr] More implementation of selector widget.
    
     * Add a certificate base class to augment interface with default props.
     * All properties come from certificate rather than renderer.
     * Certificates are comparable.

 gcr/Makefile.am                |    5 +
 gcr/gcr-certificate-renderer.c |  151 ++++-------------
 gcr/gcr-certificate-renderer.h |    6 +-
 gcr/gcr-certificate.c          |  232 +++++++++++++++++++++++++-
 gcr/gcr-certificate.h          |   59 ++++++-
 gcr/gcr-collection-model.c     |  106 +++++++++++-
 gcr/gcr-collection-model.h     |   16 ++-
 gcr/gcr-column.h               |    5 +-
 gcr/gcr-comparable.c           |  103 +++++++++++
 gcr/gcr-comparable.h           |   54 ++++++
 gcr/gcr-library.c              |    7 +-
 gcr/gcr-renderer.c             |   33 ----
 gcr/gcr-renderer.h             |   11 --
 gcr/gcr-selector.c             |  364 ++++++++++++++++++++++++++++++++++++++++
 gcr/gcr-selector.h             |   82 +++++++++
 gcr/gcr-simple-certificate.c   |   47 +++---
 gcr/gcr-simple-certificate.h   |    4 +-
 gcr/tests/test-ui-selector.c   |   83 +--------
 18 files changed, 1074 insertions(+), 294 deletions(-)
---
diff --git a/gcr/Makefile.am b/gcr/Makefile.am
index 7a2113d..1ac8b1d 100644
--- a/gcr/Makefile.am
+++ b/gcr/Makefile.am
@@ -20,11 +20,14 @@ inc_HEADERS = \
 	gcr-certificate-widget.h \
 	gcr-collection.h \
 	gcr-collection-model.h \
+	gcr-column.h \
+	gcr-comparable.h \
 	gcr-key-renderer.h \
 	gcr-key-widget.h \
 	gcr-importer.h \
 	gcr-parser.h \
 	gcr-renderer.h \
+	gcr-selector.h \
 	gcr-simple-certificate.h \
 	gcr-simple-collection.h \
 	gcr-types.h \
@@ -55,6 +58,7 @@ libgcr GCR_VERSION_SUFFIX@_la_SOURCES = \
 	gcr-certificate-widget.c gcr-certificate-widget.h \
 	gcr-collection.c gcr-collection.h \
 	gcr-collection-model.c gcr-collection-model.h \
+	gcr-comparable.c gcr-comparable.h \
 	gcr-display-view.c gcr-display-view.h \
 	gcr-icons.c gcr-icons.h \
 	gcr-import-dialog.c gcr-import-dialog.h \
@@ -65,6 +69,7 @@ libgcr GCR_VERSION_SUFFIX@_la_SOURCES = \
 	gcr-library.c \
 	gcr-parser.c gcr-parser.h \
 	gcr-renderer.c gcr-renderer.h \
+	gcr-selector.c gcr-selector.h \
 	gcr-simple-certificate.c gcr-simple-certificate.h \
 	gcr-simple-collection.c gcr-simple-collection.h \
 	gcr-types.h \
diff --git a/gcr/gcr-certificate-renderer.c b/gcr/gcr-certificate-renderer.c
index 84f829f..5691327 100644
--- a/gcr/gcr-certificate-renderer.c
+++ b/gcr/gcr-certificate-renderer.c
@@ -41,13 +41,7 @@ enum {
 	PROP_0,
 	PROP_CERTIFICATE,
 	PROP_LABEL,
-	PROP_ATTRIBUTES,
-	PROP_DESCRIPTION,
-	PROP_ICON,
-	PROP_MARKUP,
-	PROP_SUBJECT,
-	PROP_ISSUER,
-	PROP_EXPIRY
+	PROP_ATTRIBUTES
 };
 
 struct _GcrCertificateRendererPrivate {
@@ -55,15 +49,12 @@ struct _GcrCertificateRendererPrivate {
 	GckAttributes *opt_attrs;
 	guint key_size;
 	gchar *label;
-	GIcon *icon;
 };
 
 static void gcr_renderer_iface_init (GcrRendererIface *iface);
-static void gcr_certificate_iface_init (GcrCertificateIface *iface);
 
-G_DEFINE_TYPE_WITH_CODE (GcrCertificateRenderer, gcr_certificate_renderer, G_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (GCR_TYPE_RENDERER, gcr_renderer_iface_init)
-                         G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, gcr_certificate_iface_init));
+G_DEFINE_TYPE_WITH_CODE (GcrCertificateRenderer, gcr_certificate_renderer, GCR_TYPE_CERTIFICATE_BASE,
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_RENDERER, gcr_renderer_iface_init));
 
 /* -----------------------------------------------------------------------------
  * INTERNAL
@@ -89,26 +80,6 @@ calculate_label (GcrCertificateRenderer *self)
 	return g_strdup (_("Certificate"));
 }
 
-static gchar*
-calculate_markup (GcrCertificateRenderer *self)
-{
-	gchar *label;
-	gchar *issuer;
-	gchar *markup;
-
-	label = calculate_label (self);
-	issuer = gcr_certificate_get_issuer_cn (GCR_CERTIFICATE (self));
-
-	if (issuer)
-		markup = g_markup_printf_escaped ("%s\n<small>Issued by: %s</small>", label, issuer);
-	else
-		markup = g_markup_printf_escaped ("%s\n<small>Issued by: <i>No name</i></small>", label);
-
-	g_free (label);
-	g_free (issuer);
-	return markup;
-}
-
 static gboolean
 append_extension (GcrCertificateRenderer *self, GcrDisplayView *view,
                   GNode *asn, const guchar *data, gsize n_data, gint index)
@@ -209,7 +180,27 @@ static void
 gcr_certificate_renderer_init (GcrCertificateRenderer *self)
 {
 	self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_CERTIFICATE_RENDERER, GcrCertificateRendererPrivate));
-	self->pv->icon = g_themed_icon_new (GCR_ICON_CERTIFICATE);
+}
+
+static gconstpointer
+gcr_certificate_renderer_real_get_der_data (GcrCertificateBase *cert, gsize *n_data)
+{
+	GcrCertificateRenderer *self = GCR_CERTIFICATE_RENDERER (cert);
+	GckAttribute *attr;
+
+	g_assert (n_data);
+
+	if (self->pv->opt_cert)
+		return gcr_certificate_get_der_data (self->pv->opt_cert, n_data);
+
+	if (self->pv->opt_attrs) {
+		attr = gck_attributes_find (self->pv->opt_attrs, CKA_VALUE);
+		g_return_val_if_fail (attr, NULL);
+		*n_data = attr->length;
+		return attr->value;
+	}
+
+	return NULL;
 }
 
 static void
@@ -238,10 +229,6 @@ gcr_certificate_renderer_finalize (GObject *obj)
 	g_free (self->pv->label);
 	self->pv->label = NULL;
 
-	if (self->pv->icon)
-		g_object_unref (self->pv->icon);
-	self->pv->icon = NULL;
-
 	G_OBJECT_CLASS (gcr_certificate_renderer_parent_class)->finalize (obj);
 }
 
@@ -286,24 +273,6 @@ gcr_certificate_renderer_get_property (GObject *obj, guint prop_id, GValue *valu
 	case PROP_ATTRIBUTES:
 		g_value_set_boxed (value, self->pv->opt_attrs);
 		break;
-	case PROP_ICON:
-		g_value_set_object (value, self->pv->icon);
-		break;
-	case PROP_DESCRIPTION:
-		g_value_set_string (value, _("Certificate"));
-		break;
-	case PROP_MARKUP:
-		g_value_take_string (value, calculate_markup (self));
-		break;
-	case PROP_SUBJECT:
-		g_value_take_string (value, gcr_certificate_get_subject_cn (GCR_CERTIFICATE (self)));
-		break;
-	case PROP_ISSUER:
-		g_value_take_string (value, gcr_certificate_get_issuer_cn (GCR_CERTIFICATE (self)));
-		break;
-	case PROP_EXPIRY:
-		g_value_take_boxed (value, gcr_certificate_get_expiry_date (GCR_CERTIFICATE (self)));
-		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -314,6 +283,7 @@ static void
 gcr_certificate_renderer_class_init (GcrCertificateRendererClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GcrCertificateBaseClass *cert_class = GCR_CERTIFICATE_BASE_CLASS (klass);
 	GckAttributes *registered;
 
 	gcr_certificate_renderer_parent_class = g_type_class_peek_parent (klass);
@@ -324,27 +294,19 @@ gcr_certificate_renderer_class_init (GcrCertificateRendererClass *klass)
 	gobject_class->set_property = gcr_certificate_renderer_set_property;
 	gobject_class->get_property = gcr_certificate_renderer_get_property;
 
-	g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
-	           g_param_spec_object ("certificate", "Certificate", "Certificate to display.",
-	                               GCR_TYPE_CERTIFICATE, G_PARAM_READWRITE));
+	cert_class->get_der_data = gcr_certificate_renderer_real_get_der_data;
 
 	g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
-	           g_param_spec_string ("subject", "Subject", "Common name of subject",
-	                                "", G_PARAM_READABLE));
-
-	g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
-	           g_param_spec_string ("issuer", "Issuer", "Common name of issuer",
-	                                "", G_PARAM_READABLE));
+	           g_param_spec_object ("certificate", "Certificate", "Certificate to display.",
+	                                GCR_TYPE_CERTIFICATE, G_PARAM_READWRITE));
 
-	g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
-	           g_param_spec_boxed ("expiry", "Expiry", "Certificate expiry",
-	                               G_TYPE_DATE, G_PARAM_READABLE));
+	g_object_class_install_property (gobject_class, PROP_ATTRIBUTES,
+	           g_param_spec_boxed ("attributes", "Attributes", "Certificate pkcs11 attributes",
+	                               GCK_TYPE_ATTRIBUTES, G_PARAM_READWRITE));
 
-	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
-	g_object_class_override_property (gobject_class, PROP_ATTRIBUTES, "attributes");
-	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
-	g_object_class_override_property (gobject_class, PROP_ICON, "icon");
-	g_object_class_override_property (gobject_class, PROP_MARKUP, "markup");
+	g_object_class_install_property (gobject_class, PROP_LABEL,
+	           g_param_spec_string ("label", "Label", "Certificate Label",
+	                                "", G_PARAM_READWRITE));
 
 	_gcr_icons_register ();
 
@@ -372,6 +334,7 @@ gcr_certificate_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 	GNode *asn;
 	GQuark oid;
 	GDate date;
+	GIcon *icon;
 
 	self = GCR_CERTIFICATE_RENDERER (renderer);
 
@@ -391,7 +354,9 @@ gcr_certificate_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 	if (!data)
 		return;
 
-	_gcr_display_view_set_icon (view, GCR_RENDERER (self), self->pv->icon);
+	icon = gcr_certificate_get_icon (cert);
+	_gcr_display_view_set_icon (view, GCR_RENDERER (self), icon);
+	g_object_unref (icon);
 
 	asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data, n_data);
 	g_return_if_fail (asn);
@@ -528,47 +493,7 @@ gcr_certificate_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 static void
 gcr_renderer_iface_init (GcrRendererIface *iface)
 {
-	static GcrModelColumn columns[] = {
-		{ "expiry", /* Below */ 0, N_("Expires"), 0 },
-		{ "label", G_TYPE_STRING, N_("Name"), 0 },
-		{ "description", G_TYPE_STRING, N_("Type"), 0 },
-		{ "subject", G_TYPE_STRING, N_("Subject"), 0 },
-		{ "issuer", G_TYPE_STRING, N_("Issued By"), 0 },
-		{ NULL }
-	};
-
-	/* Not constant so fill it in here */
-	columns[0].type = G_TYPE_DATE;
-
 	iface->render_view = gcr_certificate_renderer_real_render;
-	iface->column_info = columns;
-}
-
-static const guchar*
-gcr_certificate_renderer_real_get_der_data (GcrCertificate *cert, gsize *n_data)
-{
-	GcrCertificateRenderer *self = GCR_CERTIFICATE_RENDERER (cert);
-	GckAttribute *attr;
-
-	g_assert (n_data);
-
-	if (self->pv->opt_cert)
-		return gcr_certificate_get_der_data (self->pv->opt_cert, n_data);
-
-	if (self->pv->opt_attrs) {
-		attr = gck_attributes_find (self->pv->opt_attrs, CKA_VALUE);
-		g_return_val_if_fail (attr, NULL);
-		*n_data = attr->length;
-		return attr->value;
-	}
-
-	return NULL;
-}
-
-static void
-gcr_certificate_iface_init (GcrCertificateIface *iface)
-{
-	iface->get_der_data = gcr_certificate_renderer_real_get_der_data;
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/gcr/gcr-certificate-renderer.h b/gcr/gcr-certificate-renderer.h
index 7633b4c..a8be0c8 100644
--- a/gcr/gcr-certificate-renderer.h
+++ b/gcr/gcr-certificate-renderer.h
@@ -43,18 +43,16 @@ typedef struct _GcrCertificateRendererClass GcrCertificateRendererClass;
 typedef struct _GcrCertificateRendererPrivate GcrCertificateRendererPrivate;
 
 struct _GcrCertificateRenderer {
-	GObject parent;
+	GcrCertificateBase parent;
 	GcrCertificateRendererPrivate *pv;
 };
 
 struct _GcrCertificateRendererClass {
-	GObjectClass parent_class;
+	GcrCertificateBaseClass parent_class;
 };
 
 GType                     gcr_certificate_renderer_get_type           (void);
 
-const GcrModelColumn*     gcr_certificate_renderer_get_columns        (void);
-
 GcrCertificateRenderer*   gcr_certificate_renderer_new                (GcrCertificate *cert);
 
 GcrCertificateRenderer*   gcr_certificate_renderer_new_for_attributes (const gchar *label,
diff --git a/gcr/gcr-certificate.c b/gcr/gcr-certificate.c
index 8a8abd7..13f5d55 100644
--- a/gcr/gcr-certificate.c
+++ b/gcr/gcr-certificate.c
@@ -21,8 +21,10 @@
 
 #include "config.h"
 
-#include "gcr-internal.h"
 #include "gcr-certificate.h"
+#include "gcr-comparable.h"
+#include "gcr-icons.h"
+#include "gcr-internal.h"
 
 #include "egg/egg-asn1x.h"
 #include "egg/egg-asn1-defs.h"
@@ -30,6 +32,7 @@
 #include "egg/egg-hex.h"
 
 #include <string.h>
+#include <glib/gi18n-lib.h>
 
 /**
  * SECTION:gcr-certificate
@@ -61,6 +64,24 @@ typedef struct _GcrCertificateInfo {
 	guint key_size;
 } GcrCertificateInfo;
 
+enum {
+	PROP_0,
+	PROP_LABEL,
+	PROP_MARKUP,
+	PROP_DESCRIPTION,
+	PROP_ICON,
+	PROP_SUBJECT,
+	PROP_ISSUER,
+	PROP_EXPIRY
+};
+
+static void gcr_comparable_init (GcrComparableIface *iface);
+static void gcr_certificate_init (GcrCertificateIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GcrCertificateBase, gcr_certificate_base, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COMPARABLE, gcr_comparable_init)
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, gcr_certificate_init));
+
 /* -----------------------------------------------------------------------------
  * INTERNAL 
  */
@@ -213,12 +234,48 @@ digest_certificate (GcrCertificate *self, GChecksumType type)
 	return digest;
 }
 
+static gchar*
+calculate_markup (GcrCertificate *self)
+{
+	gchar *label = NULL;
+	gchar *issuer;
+	gchar *markup;
+
+	g_object_get (self, "label", &label, NULL);
+	issuer = gcr_certificate_get_issuer_cn (self);
+
+	if (issuer)
+		markup = g_markup_printf_escaped ("%s\n<small>Issued by: %s</small>", label, issuer);
+	else
+		markup = g_markup_printf_escaped ("%s\n<small>Issued by: <i>No name</i></small>", label);
+
+	g_free (label);
+	g_free (issuer);
+	return markup;
+}
+
+static gchar*
+calculate_expiry (GcrCertificate *self)
+{
+	GDate *date;
+	gchar *result;
+
+	date = gcr_certificate_get_expiry_date (self);
+	result = g_malloc0 (256);
+	if (!g_date_strftime (result, 256, "%s", date)) {
+		g_free (result);
+		result = NULL;
+	}
+	g_date_free (date);
+	return result;
+}
+
 /* ---------------------------------------------------------------------------------
  * INTERFACE
  */
 
 static void
-gcr_certificate_base_init (gpointer g_class)
+gcr_certificate_iface_init (gpointer gobject_iface)
 {
 	static volatile gsize initialized = 0;
 
@@ -227,7 +284,33 @@ gcr_certificate_base_init (gpointer g_class)
 		OID_RSA_KEY = g_quark_from_static_string ("1.2.840.113549.1.1.1");
 		OID_DSA_KEY = g_quark_from_static_string ("1.2.840.10040.4.1");
 
-		/* Add properties and signals to the interface */
+		g_object_interface_install_property (gobject_iface,
+		         g_param_spec_string ("label", "Label", "Certificate label",
+		                              "", G_PARAM_READABLE));
+
+		g_object_interface_install_property (gobject_iface,
+		         g_param_spec_string ("description", "Description", "Description of object being rendered",
+		                              "", G_PARAM_READABLE));
+
+		g_object_interface_install_property (gobject_iface,
+		         g_param_spec_string ("markup", "Markup", "Markup which describes object being rendered",
+		                              "", G_PARAM_READABLE));
+
+		g_object_interface_install_property (gobject_iface,
+		         g_param_spec_object ("icon", "Icon", "Icon for the object being rendered",
+		                              G_TYPE_ICON, G_PARAM_READABLE));
+
+		g_object_interface_install_property (gobject_iface,
+		           g_param_spec_string ("subject", "Subject", "Common name of subject",
+		                                "", G_PARAM_READABLE));
+
+		g_object_interface_install_property (gobject_iface,
+		           g_param_spec_string ("issuer", "Issuer", "Common name of issuer",
+		                                "", G_PARAM_READABLE));
+
+		g_object_interface_install_property (gobject_iface,
+		           g_param_spec_string ("expiry", "Expiry", "Certificate expiry",
+		                                "", G_PARAM_READABLE));
 
 		g_once_init_leave (&initialized, 1);
 	}
@@ -240,7 +323,7 @@ gcr_certificate_get_type (void)
 	if (!type) {
 		static const GTypeInfo info = {
 			sizeof (GcrCertificateIface),
-			gcr_certificate_base_init,               /* base init */
+			gcr_certificate_iface_init,               /* base init */
 			NULL,             /* base finalize */
 			NULL,             /* class_init */
 			NULL,             /* class finalize */
@@ -250,17 +333,149 @@ gcr_certificate_get_type (void)
 			NULL,             /* instance init */
 		};
 		type = g_type_register_static (G_TYPE_INTERFACE, "GcrCertificateIface", &info, 0);
-		g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+		g_type_interface_add_prerequisite (type, GCR_TYPE_COMPARABLE);
 	}
 	
 	return type;
 }
 
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gcr_certificate_base_init (GcrCertificateBase *self)
+{
+
+}
+
+static void
+gcr_certificate_base_real_get_property (GObject *obj, guint prop_id,
+                                        GValue *value, GParamSpec *pspec)
+{
+	GcrCertificate *cert = GCR_CERTIFICATE (obj);
+
+	switch (prop_id) {
+	case PROP_LABEL:
+		g_value_take_string (value, gcr_certificate_get_subject_cn (cert));
+		break;
+	case PROP_SUBJECT:
+		g_value_take_string (value, gcr_certificate_get_subject_cn (cert));
+		break;
+	case PROP_ICON:
+		g_value_set_object (value, gcr_certificate_get_icon (cert));
+		break;
+	case PROP_DESCRIPTION:
+		g_value_set_string (value, _("Certificate"));
+		break;
+	case PROP_MARKUP:
+		g_value_take_string (value, calculate_markup (cert));
+		break;
+	case PROP_ISSUER:
+		g_value_take_string (value, gcr_certificate_get_issuer_cn (cert));
+		break;
+	case PROP_EXPIRY:
+		g_value_take_string (value, calculate_expiry (cert));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static gconstpointer
+gcr_certificate_base_real_get_der_data (GcrCertificateBase *self, gsize *n_data)
+{
+	g_warning ("Derived class '%s' did not GcrCerificateBase::get_der_data",
+	           G_OBJECT_TYPE_NAME (self));
+	return NULL;
+}
+
+static gconstpointer
+gcr_certificate_base_delegate_get_der_data (GcrCertificate *cert, gsize *n_data)
+{
+	GcrCertificateBase *self = GCR_CERTIFICATE_BASE (cert);
+	g_return_val_if_fail (GCR_CERTIFICATE_BASE_GET_CLASS (self)->get_der_data, NULL);
+	return GCR_CERTIFICATE_BASE_GET_CLASS (self)->get_der_data (self, n_data);
+}
+
+static void
+gcr_certificate_base_class_init (GcrCertificateBaseClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+	klass->get_der_data = gcr_certificate_base_real_get_der_data;
+	gobject_class->get_property = gcr_certificate_base_real_get_property;
+
+	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
+	g_object_class_override_property (gobject_class, PROP_MARKUP, "markup");
+	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
+	g_object_class_override_property (gobject_class, PROP_ICON, "icon");
+	g_object_class_override_property (gobject_class, PROP_SUBJECT, "subject");
+	g_object_class_override_property (gobject_class, PROP_ISSUER, "issuer");
+	g_object_class_override_property (gobject_class, PROP_EXPIRY, "expiry");
+
+	_gcr_initialize ();
+}
+
+static void
+gcr_certificate_init (GcrCertificateIface *iface)
+{
+	iface->get_der_data = gcr_certificate_base_delegate_get_der_data;
+}
+
+static void
+gcr_comparable_init (GcrComparableIface *iface)
+{
+	iface->compare = gcr_certificate_compare;
+}
 
 /* -----------------------------------------------------------------------------
  * PUBLIC 
  */
 
+const GcrColumn*
+gcr_certificate_get_columns (void)
+{
+	static GcrColumn columns[] = {
+		{ "icon", 0, NULL, 0 },
+		{ "label", G_TYPE_STRING, N_("Name"), 0 },
+		{ "description", G_TYPE_STRING, N_("Type"), 0 },
+		{ "subject", G_TYPE_STRING, N_("Subject"), 0 },
+		{ "issuer", G_TYPE_STRING, N_("Issued By"), 0 },
+		{ "expiry", G_TYPE_STRING, N_("Expires"), 0 },
+		{ NULL }
+	};
+
+	columns[0].type = G_TYPE_ICON;
+	return columns;
+}
+
+gint
+gcr_certificate_compare (GcrComparable *first, GcrComparable *other)
+{
+	gconstpointer data1, data2;
+	gsize size1, size2;
+
+	if (!GCR_IS_CERTIFICATE (first))
+		first = NULL;
+	if (!GCR_IS_CERTIFICATE (other))
+		other = NULL;
+
+	if (first == other)
+		return TRUE;
+	if (!first)
+		return 1;
+	if (!other)
+		return -1;
+
+	data1 = gcr_certificate_get_der_data (GCR_CERTIFICATE (first), &size1);
+	data2 = gcr_certificate_get_der_data (GCR_CERTIFICATE (other), &size2);
+
+	return gcr_comparable_memcmp (data1, size1, data2, size2);
+}
+
+
 /**
  * gcr_certificate_get_der_data:
  * @self: a #GcrCertificate
@@ -641,3 +856,10 @@ gcr_certificate_get_serial_number_hex (GcrCertificate *self)
 	g_free (serial);
 	return hex;
 }
+
+GIcon*
+gcr_certificate_get_icon (GcrCertificate *self)
+{
+	g_return_val_if_fail (GCR_IS_CERTIFICATE (self), FALSE);
+	return g_themed_icon_new (GCR_ICON_CERTIFICATE);
+}
diff --git a/gcr/gcr-certificate.h b/gcr/gcr-certificate.h
index d4eccca..bb6a8e6 100644
--- a/gcr/gcr-certificate.h
+++ b/gcr/gcr-certificate.h
@@ -23,24 +23,56 @@
 #define __GCR_CERTIFICATE_H__
 
 #include "gcr-types.h"
+#include "gcr-column.h"
+#include "gcr-comparable.h"
 
 #include <glib-object.h>
+#include <gio/gio.h>
 
 G_BEGIN_DECLS
 
-#define GCR_TYPE_CERTIFICATE                 (gcr_certificate_get_type())
-#define GCR_CERTIFICATE(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_CERTIFICATE, GcrCertificate))
-#define GCR_IS_CERTIFICATE(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_CERTIFICATE))
-#define GCR_CERTIFICATE_GET_INTERFACE(inst)  (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GCR_TYPE_CERTIFICATE, GcrCertificateIface))
+#define GCR_CERTIFICATE_COLUMNS                 (gcr_certificate_get_columns ())
+#define GCR_TYPE_CERTIFICATE                    (gcr_certificate_get_type ())
+#define GCR_CERTIFICATE(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_CERTIFICATE, GcrCertificate))
+#define GCR_IS_CERTIFICATE(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_CERTIFICATE))
+#define GCR_CERTIFICATE_GET_INTERFACE(inst)     (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GCR_TYPE_CERTIFICATE, GcrCertificateIface))
 
-typedef struct _GcrCertificate      GcrCertificate;
-typedef struct _GcrCertificateIface GcrCertificateIface;
+#define GCR_TYPE_CERTIFICATE_BASE               (gcr_certificate_base_get_type ())
+#define GCR_CERTIFICATE_BASE(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_CERTIFICATE_BASE, GcrCertificateBase))
+#define GCR_CERTIFICATE_BASE_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_CERTIFICATE_BASE, GcrCertificateBaseClass))
+#define GCR_IS_CERTIFICATE_BASE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_CERTIFICATE_BASE))
+#define GCR_IS_CERTIFICATE_BASE_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_CERTIFICATE_BASE))
+#define GCR_CERTIFICATE_BASE_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_CERTIFICATE_BASE, GcrCertificateBaseClass))
+
+typedef struct _GcrCertificate          GcrCertificate;
+typedef struct _GcrCertificateIface     GcrCertificateIface;
+typedef struct _GcrCertificateBase      GcrCertificateBase;
+typedef struct _GcrCertificateBaseClass GcrCertificateBaseClass;
 
 struct _GcrCertificateIface {
 	GTypeInterface parent;
-	
-	const guchar* (*get_der_data)   (GcrCertificate *self, gsize *n_data);
-	
+
+	gconstpointer (*get_der_data) (GcrCertificate *self, gsize *n_data);
+
+	gpointer dummy1;
+	gpointer dummy2;
+	gpointer dummy3;
+	gpointer dummy5;
+	gpointer dummy6;
+	gpointer dummy7;
+	gpointer dummy8;
+};
+
+struct _GcrCertificateBase {
+	GObject parent;
+	gpointer reserved;
+};
+
+struct _GcrCertificateBaseClass {
+	GObjectClass parent_class;
+
+	gconstpointer (*get_der_data) (GcrCertificateBase *self, gsize *n_data);
+
 	gpointer dummy1;
 	gpointer dummy2;
 	gpointer dummy3;
@@ -52,6 +84,13 @@ struct _GcrCertificateIface {
 
 GType               gcr_certificate_get_type               (void);
 
+GType               gcr_certificate_base_get_type          (void);
+
+const GcrColumn*    gcr_certificate_get_columns            (void);
+
+gint                gcr_certificate_compare                (GcrComparable *self,
+                                                            GcrComparable *other);
+
 const guchar*       gcr_certificate_get_der_data           (GcrCertificate *self, 
                                                             gsize *n_data);
 
@@ -87,6 +126,8 @@ guchar*             gcr_certificate_get_fingerprint        (GcrCertificate *self
 gchar*              gcr_certificate_get_fingerprint_hex    (GcrCertificate *self, 
                                                             GChecksumType type);
 
+GIcon*              gcr_certificate_get_icon               (GcrCertificate *self);
+
 G_END_DECLS
 
 #endif /* __GCR_CERTIFICATE_H__ */
diff --git a/gcr/gcr-collection-model.c b/gcr/gcr-collection-model.c
index db05bea..5c8d753 100644
--- a/gcr/gcr-collection-model.c
+++ b/gcr/gcr-collection-model.c
@@ -33,6 +33,7 @@ enum {
 struct _GcrCollectionModelPrivate {
 	GcrCollection *collection;
 	GHashTable *object_to_index;
+	GHashTable *toggled_active;
 
 	gint cache_stamp;
 	gint last_stamp;
@@ -50,6 +51,8 @@ static void gcr_collection_model_tree_model (GtkTreeModelIface *iface);
 G_DEFINE_TYPE_EXTENDED (GcrCollectionModel, gcr_collection_model, G_TYPE_OBJECT, 0,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, gcr_collection_model_tree_model));
 
+#define UNUSED_VALUE GUINT_TO_POINTER (1)
+
 /* -----------------------------------------------------------------------------
  * INTERNAL
  */
@@ -304,6 +307,15 @@ gcr_collection_model_real_get_value (GtkTreeModel *model, GtkTreeIter *iter,
 	g_return_if_fail (G_IS_OBJECT (object));
 	g_return_if_fail (column >= 0 && column < self->pv->n_columns);
 
+	/* The selected column? */
+	if (column == self->pv->n_columns - 1) {
+		g_assert (!self->pv->column_names[column]);
+		g_assert (self->pv->column_types[column] == G_TYPE_BOOLEAN);
+		g_value_init (value, G_TYPE_BOOLEAN);
+		g_value_set_boolean (value, gcr_collection_model_get_selected (self, iter));
+		return;
+	}
+
 	/* Figure out which property */
 	type = self->pv->column_types[column];
 	property = self->pv->column_names[column];
@@ -494,7 +506,7 @@ gcr_collection_model_dispose (GObject *object)
 	/* Disconnect from all rows */
 	for (i = self->pv->objects->len; i > 0; --i) {
 		obj = g_ptr_array_index (self->pv->objects, i - 1);
-		disconnect_object (self, object);
+		disconnect_object (self, obj);
 	}
 
 	/* Disconnect from the collection */
@@ -505,6 +517,9 @@ gcr_collection_model_dispose (GObject *object)
 		self->pv->collection = NULL;
 	}
 
+	if (self->pv->toggled_active)
+		g_hash_table_remove_all (self->pv->toggled_active);
+
 	G_OBJECT_CLASS (gcr_collection_model_parent_class)->dispose (object);
 }
 
@@ -524,6 +539,10 @@ gcr_collection_model_finalize (GObject *object)
 	g_ptr_array_free (self->pv->objects, TRUE);
 	self->pv->objects = NULL;
 
+	if (self->pv->toggled_active)
+		g_hash_table_destroy (self->pv->toggled_active);
+	self->pv->toggled_active = NULL;
+
 	if (self->pv->column_names) {
 		g_strfreev (self->pv->column_names);
 		self->pv->column_names = NULL;
@@ -563,14 +582,14 @@ gcr_collection_model_class_init (GcrCollectionModelClass *klass)
 GcrCollectionModel*
 gcr_collection_model_new (GcrCollection *collection, ...)
 {
-	GcrModelColumn column;
+	GcrColumn column;
 	GcrCollectionModel *self;
 	const gchar *arg;
 	GArray *array;
 	va_list va;
 
 	/* With a null terminator */
-	array = g_array_new (TRUE, TRUE, sizeof (GcrModelColumn));
+	array = g_array_new (TRUE, TRUE, sizeof (GcrColumn));
 
 	va_start (va, collection);
 	while ((arg = va_arg (va, const gchar*)) != NULL) {
@@ -582,13 +601,13 @@ gcr_collection_model_new (GcrCollection *collection, ...)
 	}
 	va_end (va);
 
-	self = gcr_collection_model_new_full (collection, (GcrModelColumn*)array->data);
+	self = gcr_collection_model_new_full (collection, (GcrColumn*)array->data);
 	g_array_free (array, TRUE);
 	return self;
 }
 
 GcrCollectionModel*
-gcr_collection_model_new_full (GcrCollection *collection, const GcrModelColumn *columns)
+gcr_collection_model_new_full (GcrCollection *collection, const GcrColumn *columns)
 {
 	GcrCollectionModel *self = g_object_new (GCR_TYPE_COLLECTION_MODEL, "collection", collection, NULL);
 	gcr_collection_model_set_columns (self, columns);
@@ -596,27 +615,32 @@ gcr_collection_model_new_full (GcrCollection *collection, const GcrModelColumn *
 }
 
 gint
-gcr_collection_model_set_columns (GcrCollectionModel *self, const GcrModelColumn *columns)
+gcr_collection_model_set_columns (GcrCollectionModel *self, const GcrColumn *columns)
 {
-	const GcrModelColumn *col;
+	const GcrColumn *col;
 	guint i, n_columns;
 
 	g_return_val_if_fail (GCR_IS_COLLECTION_MODEL (self), -1);
 	g_return_val_if_fail (self->pv->n_columns == 0, -1);
 
-	/* Count the number of columns */
-	for (col = columns, n_columns = 0; col->property; ++col)
+	/* Count the number of columns, extra column for selected */
+	for (col = columns, n_columns = 1; col->property; ++col)
 		++n_columns;
 
 	self->pv->column_names = g_new0 (gchar*, n_columns + 1);
 	self->pv->column_types = g_new0 (GType, n_columns + 1);
 	self->pv->n_columns = n_columns;
 
-	for (i = 0; i < n_columns; ++i) {
+	/* All the columns, except the selected column */
+	for (i = 0; i < n_columns - 1; ++i) {
 		self->pv->column_names[i] = g_strdup (columns[i].property);
 		self->pv->column_types[i] = columns[i].type;
 	}
 
+	/* The selected column */
+	self->pv->column_names[i] = NULL;
+	self->pv->column_types[i] = G_TYPE_BOOLEAN;
+
 	return n_columns - 1;
 }
 
@@ -647,3 +671,65 @@ gcr_collection_model_iter_for_object (GcrCollectionModel *self, GObject *object,
 
 	return iter_for_index (self, index, iter);
 }
+
+guint
+gcr_collection_model_column_selected (GcrCollectionModel *self)
+{
+	g_return_val_if_fail (GCR_IS_COLLECTION_MODEL (self), 0);
+	g_assert (self->pv->n_columns > 0);
+	return self->pv->n_columns - 1;
+}
+
+void
+gcr_collection_model_toggle_selected (GcrCollectionModel *self, GtkTreeIter *iter)
+{
+	GObject *object;
+
+	g_return_if_fail (GCR_IS_COLLECTION_MODEL (self));
+
+	object = gcr_collection_model_object_for_iter (self, iter);
+	g_return_if_fail (G_IS_OBJECT (object));
+
+	if (!self->pv->toggled_active)
+		self->pv->toggled_active = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+	if (g_hash_table_lookup (self->pv->toggled_active, object))
+		g_hash_table_remove (self->pv->toggled_active, object);
+	else
+		g_hash_table_insert (self->pv->toggled_active, object, UNUSED_VALUE);
+}
+
+void
+gcr_collection_model_set_selected (GcrCollectionModel *self, GtkTreeIter *iter, gboolean selected)
+{
+	GObject *object;
+
+	g_return_if_fail (GCR_IS_COLLECTION_MODEL (self));
+
+	object = gcr_collection_model_object_for_iter (self, iter);
+	g_return_if_fail (G_IS_OBJECT (object));
+
+	if (!self->pv->toggled_active)
+		self->pv->toggled_active = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+	if (selected)
+		g_hash_table_insert (self->pv->toggled_active, object, UNUSED_VALUE);
+	else
+		g_hash_table_remove (self->pv->toggled_active, object);
+}
+
+gboolean
+gcr_collection_model_get_selected (GcrCollectionModel *self, GtkTreeIter *iter)
+{
+	GObject *object;
+
+	g_return_val_if_fail (GCR_IS_COLLECTION_MODEL (self), FALSE);
+
+	object = gcr_collection_model_object_for_iter (self, iter);
+	g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
+
+	if (!self->pv->toggled_active)
+		return FALSE;
+
+	return g_hash_table_lookup (self->pv->toggled_active, object) ? TRUE : FALSE;
+}
diff --git a/gcr/gcr-collection-model.h b/gcr/gcr-collection-model.h
index fb750d2..1765126 100644
--- a/gcr/gcr-collection-model.h
+++ b/gcr/gcr-collection-model.h
@@ -54,10 +54,10 @@ GcrCollectionModel*   gcr_collection_model_new                 (GcrCollection *c
                                                                 ...) G_GNUC_NULL_TERMINATED;
 
 GcrCollectionModel*   gcr_collection_model_new_full            (GcrCollection *collection,
-                                                                const GcrModelColumn *columns);
+                                                                const GcrColumn *columns);
 
 gint                  gcr_collection_model_set_columns         (GcrCollectionModel *self,
-                                                                const GcrModelColumn *columns);
+                                                                const GcrColumn *columns);
 
 GObject*              gcr_collection_model_object_for_iter     (GcrCollectionModel *self,
                                                                 const GtkTreeIter *iter);
@@ -66,4 +66,16 @@ gboolean              gcr_collection_model_iter_for_object     (GcrCollectionMod
                                                                 GObject *object,
                                                                 GtkTreeIter *iter);
 
+guint                 gcr_collection_model_column_selected     (GcrCollectionModel *self);
+
+void                  gcr_collection_model_toggle_selected     (GcrCollectionModel *self,
+                                                                GtkTreeIter *iter);
+
+void                  gcr_collection_model_set_selected        (GcrCollectionModel *self,
+                                                                GtkTreeIter *iter,
+                                                                gboolean selected);
+
+gboolean              gcr_collection_model_get_selected        (GcrCollectionModel *self,
+                                                                GtkTreeIter *iter);
+
 #endif /* __GCR_COLLECTION_MODEL_H__ */
diff --git a/gcr/gcr-column.h b/gcr/gcr-column.h
index ce26da7..53a3530 100644
--- a/gcr/gcr-column.h
+++ b/gcr/gcr-column.h
@@ -28,12 +28,13 @@
 
 G_BEGIN_DECLS
 
-typedef struct _GcrModelColumn {
+typedef struct _GcrColumn {
 	const gchar *property;
 	GType type;
 	const gchar *label;
+	gpointer user_data;
 	gpointer reserved;
-} GcrModelColumn;
+} GcrColumn;
 
 G_END_DECLS
 
diff --git a/gcr/gcr-comparable.c b/gcr/gcr-comparable.c
new file mode 100644
index 0000000..3f4d513
--- /dev/null
+++ b/gcr/gcr-comparable.c
@@ -0,0 +1,103 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gcr-comparable.h"
+
+#include <string.h>
+
+/* ---------------------------------------------------------------------------------
+ * INTERFACE
+ */
+
+static void
+gcr_comparable_base_init (gpointer g_class)
+{
+	static volatile gsize initialized = 0;
+
+	if (g_once_init_enter (&initialized)) {
+		/* Add properties and signals to the interface */
+		g_once_init_leave (&initialized, 1);
+	}
+}
+
+GType
+gcr_comparable_get_type (void)
+{
+	static GType type = 0;
+	if (!type) {
+		static const GTypeInfo info = {
+			sizeof (GcrComparableIface),
+			gcr_comparable_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, "GcrComparableIface", &info, 0);
+		g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+	}
+
+	return type;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+gint
+gcr_comparable_compare (GcrComparable *self, GcrComparable *other)
+{
+	g_return_val_if_fail (GCR_IS_COMPARABLE (self), -1);
+	g_return_val_if_fail (GCR_COMPARABLE_GET_INTERFACE (self)->compare, -1);
+	g_return_val_if_fail (G_IS_OBJECT (self), -1);
+	return GCR_COMPARABLE_GET_INTERFACE (self)->compare (self, other);
+}
+
+gint
+gcr_comparable_memcmp (gconstpointer mem1, gsize size1,
+                       gconstpointer mem2, gsize size2)
+{
+	gint result;
+
+	if (mem1 == mem2 && size1 == size2)
+		return 0;
+
+	if (!mem1)
+		return 1;
+	if (!mem2)
+		return -1;
+
+	result = memcmp (mem1, mem2, MIN (size1, size2));
+	if (result != 0)
+		return result;
+
+	if (size1 == size2)
+		return 0;
+	if (size1 < size2)
+		return -1;
+	return 1;
+}
diff --git a/gcr/gcr-comparable.h b/gcr/gcr-comparable.h
new file mode 100644
index 0000000..39f1d8a
--- /dev/null
+++ b/gcr/gcr-comparable.h
@@ -0,0 +1,54 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __GCR_COMPARABLE_H__
+#define __GCR_COMPARABLE_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GCR_TYPE_COMPARABLE                 (gcr_comparable_get_type())
+#define GCR_COMPARABLE(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_COMPARABLE, GcrComparable))
+#define GCR_IS_COMPARABLE(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_COMPARABLE))
+#define GCR_COMPARABLE_GET_INTERFACE(inst)  (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GCR_TYPE_COMPARABLE, GcrComparableIface))
+
+typedef struct _GcrComparable      GcrComparable;
+typedef struct _GcrComparableIface GcrComparableIface;
+
+struct _GcrComparableIface {
+	GTypeInterface parent;
+	gint (*compare) (GcrComparable *self, GcrComparable *other);
+};
+
+GType               gcr_comparable_get_type               (void);
+
+gint                gcr_comparable_compare                (GcrComparable *self,
+                                                           GcrComparable *other);
+
+gint                gcr_comparable_memcmp                 (gconstpointer mem1,
+                                                           gsize size1,
+                                                           gconstpointer mem2,
+                                                           gsize size2);
+
+G_END_DECLS
+
+#endif /* __GCR_COMPARABLE_H__ */
diff --git a/gcr/gcr-library.c b/gcr/gcr-library.c
index 53d529f..e4e7826 100644
--- a/gcr/gcr-library.c
+++ b/gcr/gcr-library.c
@@ -122,12 +122,11 @@ _gcr_initialize (void)
 
 	if (g_once_init_enter (&gcr_initialized)) {
 		all_modules = gck_modules_initialize_registered (0);
-
-		g_type_class_unref (g_type_class_ref (GCR_TYPE_CERTIFICATE_RENDERER));
-		g_type_class_unref (g_type_class_ref (GCR_TYPE_KEY_RENDERER));
-
 		g_once_init_leave (&gcr_initialized, 1);
 	}
+
+	g_type_class_unref (g_type_class_ref (GCR_TYPE_CERTIFICATE_RENDERER));
+	g_type_class_unref (g_type_class_ref (GCR_TYPE_KEY_RENDERER));
 }
 
 GList*
diff --git a/gcr/gcr-renderer.c b/gcr/gcr-renderer.c
index 09eb48a..ce77cad 100644
--- a/gcr/gcr-renderer.c
+++ b/gcr/gcr-renderer.c
@@ -56,18 +56,6 @@ gcr_renderer_base_init (gpointer gobject_iface)
 		         g_param_spec_boxed ("attributes", "Attributes", "The data displayed in the renderer",
 		                             GCK_TYPE_ATTRIBUTES, G_PARAM_READWRITE));
 
-		g_object_interface_install_property (gobject_iface,
-		         g_param_spec_string ("description", "Description", "Description of object being rendered",
-		                              "", G_PARAM_READABLE));
-
-		g_object_interface_install_property (gobject_iface,
-		         g_param_spec_string ("markup", "Markup", "Markup which describes object being rendered",
-		                              "", G_PARAM_READABLE));
-
-		g_object_interface_install_property (gobject_iface,
-		         g_param_spec_object ("icon", "Icon", "Icon for the object being rendered",
-		                              G_TYPE_ICON, G_PARAM_READABLE));
-
 		signals[DATA_CHANGED] = g_signal_new ("data-changed", GCR_TYPE_RENDERER, G_SIGNAL_RUN_LAST,
 		                                      G_STRUCT_OFFSET (GcrRendererIface, data_changed),
 		                                      NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
@@ -179,24 +167,3 @@ gcr_renderer_register (GType renderer_type, GckAttributes *attrs)
 	g_array_append_val (registered_renderers, registered);
 	registered_sorted = FALSE;
 }
-
-const GcrModelColumn*
-gcr_renderer_columns (GType renderer_type)
-{
-	const GcrModelColumn *columns;
-	GcrRendererIface *renderer;
-	GTypeClass *klass;
-
-	klass = g_type_class_ref (renderer_type);
-	g_return_val_if_fail (klass, NULL);
-
-	renderer = g_type_interface_peek (klass, GCR_TYPE_RENDERER);
-	g_return_val_if_fail (renderer, NULL);
-
-	columns = renderer->column_info;
-	g_return_val_if_fail (columns, NULL);
-
-	g_type_class_unref (klass);
-
-	return columns;
-}
diff --git a/gcr/gcr-renderer.h b/gcr/gcr-renderer.h
index 3366bea..5183fb9 100644
--- a/gcr/gcr-renderer.h
+++ b/gcr/gcr-renderer.h
@@ -40,9 +40,6 @@ typedef struct _GcrRendererIface GcrRendererIface;
 struct _GcrRendererIface {
 	GTypeInterface parent;
 
-	/* data */
-	const GcrModelColumn *column_info;
-
 	/* signals */
 	void (*data_changed) (GcrRenderer *self);
 
@@ -64,19 +61,11 @@ GType                     gcr_renderer_get_type                   (void) G_GNUC_
 void                      gcr_renderer_render_view                (GcrRenderer *self,
                                                                    GcrViewer *viewer);
 
-gchar*                    gcr_renderer_get_markup                 (GcrRenderer *self);
-
-gchar*                    gcr_renderer_get_description            (GcrRenderer *self);
-
-gchar*                    gcr_renderer_get_stock_icon             (GcrRenderer *self);
-
 void                      gcr_renderer_emit_data_changed          (GcrRenderer *self);
 
 GcrRenderer*              gcr_renderer_create                     (const gchar *label,
                                                                    struct _GckAttributes *attrs);
 
-const GcrModelColumn*     gcr_renderer_columns                    (GType renderer_type);
-
 void                      gcr_renderer_register                   (GType renderer_type,
                                                                    struct _GckAttributes *attrs);
 
diff --git a/gcr/gcr-selector.c b/gcr/gcr-selector.c
new file mode 100644
index 0000000..334c2d3
--- /dev/null
+++ b/gcr/gcr-selector.c
@@ -0,0 +1,364 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gcr-collection-model.h"
+#include "gcr-internal.h"
+#include "gcr-selector.h"
+
+enum {
+	PROP_0,
+	PROP_COLLECTION,
+	PROP_COLUMNS,
+	PROP_MODE
+};
+
+#if 0
+enum {
+	XXXX,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+#endif
+
+struct _GcrSelectorPrivate {
+	GtkComboBox *combo;
+	GtkTreeView *tree;
+	GcrCollection *collection;
+	const GcrColumn *columns;
+	GcrCollectionModel *model;
+	GcrSelectorMode mode;
+};
+
+G_DEFINE_TYPE (GcrSelector, gcr_selector, GTK_TYPE_ALIGNMENT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static void
+on_check_column_toggled (GtkCellRendererToggle *cell, gchar *path, GcrCollectionModel *model)
+{
+	GtkTreeIter iter;
+
+	g_assert (path != NULL);
+
+	if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (model), &iter, path))
+		gcr_collection_model_toggle_selected (model, &iter);
+}
+
+static void
+add_string_column (GcrSelector *self, const GcrColumn *column, guint index)
+{
+	GtkCellRenderer *cell;
+	GtkTreeViewColumn *col;
+
+	g_assert (column->type == G_TYPE_STRING);
+
+	cell = gtk_cell_renderer_text_new ();
+	g_object_set (G_OBJECT (cell), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+	col = gtk_tree_view_column_new_with_attributes (column->label, cell, "text", index, NULL);
+	gtk_tree_view_column_set_resizable (col, TRUE);
+	gtk_tree_view_append_column (self->pv->tree, col);
+}
+
+static void
+add_icon_column (GcrSelector *self, const GcrColumn *column, guint index)
+{
+	GtkCellRenderer *cell;
+	GtkTreeViewColumn *col;
+
+	g_assert (column->type == G_TYPE_ICON);
+
+	cell = gtk_cell_renderer_pixbuf_new ();
+	g_object_set (cell, "stock-size", GTK_ICON_SIZE_BUTTON, NULL);
+	col = gtk_tree_view_column_new_with_attributes (column->label, cell, "gicon", index, NULL);
+	gtk_tree_view_column_set_resizable (col, TRUE);
+	gtk_tree_view_append_column (self->pv->tree, col);
+}
+
+static void
+add_check_column (GcrSelector *self, guint index)
+{
+	GtkCellRenderer *cell;
+	GtkTreeViewColumn *col;
+
+	cell = gtk_cell_renderer_toggle_new ();
+	g_signal_connect (cell, "toggled", G_CALLBACK (on_check_column_toggled), self->pv->model);
+
+	col = gtk_tree_view_column_new_with_attributes ("", cell, "active", index, NULL);
+	gtk_tree_view_column_set_resizable (col, FALSE);
+	gtk_tree_view_append_column (self->pv->tree, col);
+}
+
+static void
+construct_single_selector (GcrSelector *self)
+{
+	GtkCellRenderer *cell;
+	GtkWidget *widget;
+
+	self->pv->model = gcr_collection_model_new (self->pv->collection,
+	                                            "icon", G_TYPE_ICON,
+	                                            "markup", G_TYPE_STRING,
+	                                            NULL);
+
+	widget = gtk_combo_box_new_with_model (GTK_TREE_MODEL (self->pv->model));
+	self->pv->combo = GTK_COMBO_BOX (widget);
+
+	/* The icon */
+	cell = gtk_cell_renderer_pixbuf_new ();
+	g_object_set (cell, "stock-size", GTK_ICON_SIZE_DND, NULL);
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), cell, FALSE);
+	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (widget), cell, "gicon", 0);
+
+	/* The markup */
+	cell = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), cell, TRUE);
+	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (widget), cell, "markup", 1);
+
+	gtk_widget_show (widget);
+	gtk_container_add (GTK_CONTAINER (self), widget);
+}
+
+static void
+construct_multiple_selector (GcrSelector *self)
+{
+	const GcrColumn *column;
+	GtkWidget *widget, *scroll;
+	guint i;
+
+	self->pv->model = gcr_collection_model_new_full (self->pv->collection,
+	                                                 self->pv->columns);
+
+	widget = gtk_tree_view_new_with_model (GTK_TREE_MODEL (self->pv->model));
+	self->pv->tree = GTK_TREE_VIEW (widget);
+
+	/* First add the check mark column */
+	add_check_column (self, gcr_collection_model_column_selected (self->pv->model));
+
+	for (column = self->pv->columns, i = 0; column->property; ++column, ++i) {
+		if (column->type == G_TYPE_STRING)
+			add_string_column (self, column, i);
+		else if (column->type == G_TYPE_ICON)
+			add_icon_column (self, column, i);
+		else {
+			g_warning ("skipping unsupported column '%s' of type: %s",
+			           column->label, g_type_name (column->type));
+		}
+	}
+
+	scroll = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_ETCHED_IN);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_container_add (GTK_CONTAINER (scroll), widget);
+	gtk_container_add (GTK_CONTAINER (self), scroll);
+
+	gtk_widget_show_all (scroll);
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+GType
+gcr_selector_mode_get_type (void)
+{
+	static GType type = 0;
+	static GEnumValue values[] = {
+		{ GCR_SELECTOR_MODE_SINGLE, "single", "Single"},
+		{ GCR_SELECTOR_MODE_MULTIPLE, "multiple", "Multiple"},
+		{ 0, NULL, NULL }
+	};
+	if (!type)
+		type = g_enum_register_static ("GcrSelectorMode", values);
+	return type;
+}
+
+static GObject*
+gcr_selector_constructor (GType type, guint n_props, GObjectConstructParam *props)
+{
+	GcrSelector *self = GCR_SELECTOR (G_OBJECT_CLASS (gcr_selector_parent_class)->constructor(type, n_props, props));
+	g_return_val_if_fail (self, NULL);
+
+	g_return_val_if_fail (self->pv->columns, NULL);
+
+	switch (self->pv->mode) {
+	case GCR_SELECTOR_MODE_SINGLE:
+		construct_single_selector (self);
+		break;
+	case GCR_SELECTOR_MODE_MULTIPLE:
+		construct_multiple_selector (self);
+		break;
+	default:
+		g_assert_not_reached ();
+		break;
+	}
+
+	return G_OBJECT (self);
+}
+
+static void
+gcr_selector_init (GcrSelector *self)
+{
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_SELECTOR, GcrSelectorPrivate);
+}
+
+static void
+gcr_selector_dispose (GObject *obj)
+{
+	GcrSelector *self = GCR_SELECTOR (obj);
+
+	if (self->pv->model)
+		g_object_unref (self->pv->model);
+	self->pv->model = NULL;
+
+	if (self->pv->collection)
+		g_object_unref (self->pv->collection);
+	self->pv->collection = NULL;
+
+	G_OBJECT_CLASS (gcr_selector_parent_class)->dispose (obj);
+}
+
+static void
+gcr_selector_finalize (GObject *obj)
+{
+	GcrSelector *self = GCR_SELECTOR (obj);
+
+	g_assert (!self->pv->collection);
+	g_assert (!self->pv->model);
+	self->pv->combo = NULL;
+	self->pv->tree = NULL;
+
+	G_OBJECT_CLASS (gcr_selector_parent_class)->finalize (obj);
+}
+
+static void
+gcr_selector_set_property (GObject *obj, guint prop_id, const GValue *value,
+                           GParamSpec *pspec)
+{
+	GcrSelector *self = GCR_SELECTOR (obj);
+	switch (prop_id) {
+	case PROP_COLLECTION:
+		g_return_if_fail (!self->pv->collection);
+		self->pv->collection = g_value_dup_object (value);
+		g_return_if_fail (self->pv->collection);
+		break;
+	case PROP_COLUMNS:
+		g_return_if_fail (!self->pv->columns);
+		self->pv->columns = g_value_get_pointer (value);
+		g_return_if_fail (self->pv->columns);
+		break;
+	case PROP_MODE:
+		self->pv->mode = g_value_get_enum (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gcr_selector_get_property (GObject *obj, guint prop_id, GValue *value,
+                         GParamSpec *pspec)
+{
+	GcrSelector *self = GCR_SELECTOR (obj);
+
+	switch (prop_id) {
+	case PROP_COLLECTION:
+		g_value_set_object (value, gcr_selector_get_collection (self));
+		break;
+	case PROP_COLUMNS:
+		g_value_set_pointer (value, (gpointer)gcr_selector_get_columns (self));
+		break;
+	case PROP_MODE:
+		g_value_set_enum (value, gcr_selector_get_mode (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gcr_selector_class_init (GcrSelectorClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+	gobject_class->constructor = gcr_selector_constructor;
+	gobject_class->dispose = gcr_selector_dispose;
+	gobject_class->finalize = gcr_selector_finalize;
+	gobject_class->set_property = gcr_selector_set_property;
+	gobject_class->get_property = gcr_selector_get_property;
+
+	g_type_class_add_private (gobject_class, sizeof (GcrSelectorPrivate));
+
+	g_object_class_install_property (gobject_class, PROP_COLLECTION,
+	           g_param_spec_object ("collection", "Collection", "Collection to select from",
+	                                GCR_TYPE_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (gobject_class, PROP_COLUMNS,
+	           g_param_spec_pointer ("columns", "Columns", "Columns to display in multiple selector",
+	                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (gobject_class, PROP_MODE,
+	           g_param_spec_enum ("mode", "Mode", "The mode of the selector",
+	                              GCR_TYPE_SELECTOR_MODE, GCR_SELECTOR_MODE_SINGLE,
+	                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	_gcr_initialize ();
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+GcrSelector*
+gcr_selector_new (GcrCollection *collection, const GcrColumn *columns, GcrSelectorMode mode)
+{
+	return g_object_new (GCR_TYPE_SELECTOR,
+	                     "collection", collection,
+	                     "columns", columns,
+	                     "mode", mode,
+	                     NULL);
+}
+
+GcrCollection*
+gcr_selector_get_collection (GcrSelector *self)
+{
+	g_return_val_if_fail (GCR_IS_SELECTOR (self), NULL);
+	return self->pv->collection;
+}
+
+const GcrColumn*
+gcr_selector_get_columns (GcrSelector *self)
+{
+	g_return_val_if_fail (GCR_IS_SELECTOR (self), NULL);
+	return self->pv->columns;
+}
+
+GcrSelectorMode
+gcr_selector_get_mode (GcrSelector *self)
+{
+	g_return_val_if_fail (GCR_IS_SELECTOR (self), 0);
+	return self->pv->mode;
+}
diff --git a/gcr/gcr-selector.h b/gcr/gcr-selector.h
new file mode 100644
index 0000000..88fba51
--- /dev/null
+++ b/gcr/gcr-selector.h
@@ -0,0 +1,82 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2010 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __GCR_SELECTOR_H__
+#define __GCR_SELECTOR_H__
+
+#include "gcr-types.h"
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GCR_TYPE_SELECTOR               (gcr_selector_get_type ())
+#define GCR_TYPE_SELECTOR_MODE          (gcr_selector_mode_get_type ())
+#define GCR_SELECTOR(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_SELECTOR, GcrSelector))
+#define GCR_SELECTOR_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_SELECTOR, GcrSelectorClass))
+#define GCR_IS_SELECTOR(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_SELECTOR))
+#define GCR_IS_SELECTOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_SELECTOR))
+#define GCR_SELECTOR_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_SELECTOR, GcrSelectorClass))
+
+typedef struct _GcrSelector GcrSelector;
+typedef struct _GcrSelectorClass GcrSelectorClass;
+typedef struct _GcrSelectorPrivate GcrSelectorPrivate;
+
+typedef enum _GcrSelectorMode {
+	GCR_SELECTOR_MODE_SINGLE = 1,
+	GCR_SELECTOR_MODE_MULTIPLE
+} GcrSelectorMode;
+
+struct _GcrSelector {
+	GtkAlignment parent;
+	GcrSelectorPrivate *pv;
+};
+
+struct _GcrSelectorClass {
+	GtkAlignmentClass parent_class;
+
+#if 0
+	/* signals --------------------------------------------------------- */
+
+	/* A callback for each password needed */
+	gboolean (*authenticate) (GcrSelector *self, gint count);
+
+	void     (*parsed) (GcrSelector *self);
+#endif
+};
+
+GType                    gcr_selector_get_type               (void);
+
+GType                    gcr_selector_mode_get_type          (void);
+
+GcrSelector*             gcr_selector_new                    (GcrCollection *collection,
+                                                              const GcrColumn *columns,
+                                                              GcrSelectorMode mode);
+
+GcrCollection*           gcr_selector_get_collection         (GcrSelector *self);
+
+const GcrColumn*         gcr_selector_get_columns            (GcrSelector *self);
+
+GcrSelectorMode          gcr_selector_get_mode               (GcrSelector *self);
+
+G_END_DECLS
+
+#endif /* __GCR_SELECTOR_H__ */
diff --git a/gcr/gcr-simple-certificate.c b/gcr/gcr-simple-certificate.c
index b3dd691..1d8baea 100644
--- a/gcr/gcr-simple-certificate.c
+++ b/gcr/gcr-simple-certificate.c
@@ -22,6 +22,7 @@
 #include "config.h"
 
 #include "gcr-certificate.h"
+#include "gcr-comparable.h"
 #include "gcr-internal.h"
 #include "gcr-simple-certificate.h"
 
@@ -35,9 +36,7 @@ struct _GcrSimpleCertificatePrivate {
 	guchar *owned;
 };
 
-static void gcr_certificate_iface (GcrCertificateIface *iface); 
-G_DEFINE_TYPE_WITH_CODE (GcrSimpleCertificate, gcr_simple_certificate, G_TYPE_OBJECT, 
-                         G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, gcr_certificate_iface));
+G_DEFINE_TYPE (GcrSimpleCertificate, gcr_simple_certificate, GCR_TYPE_CERTIFICATE_BASE);
 
 /* -----------------------------------------------------------------------------
  * OBJECT 
@@ -49,8 +48,22 @@ gcr_simple_certificate_init (GcrSimpleCertificate *self)
 	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_SIMPLE_CERTIFICATE, GcrSimpleCertificatePrivate);
 }
 
+static gconstpointer
+gcr_simple_certificate_real_get_der_data (GcrCertificateBase *base, gsize *n_data)
+{
+	GcrSimpleCertificate *self = GCR_SIMPLE_CERTIFICATE (base);
+
+	g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL);
+	g_return_val_if_fail (n_data, NULL);
+	g_return_val_if_fail (self->pv->data, NULL);
+
+	/* This is called when we're not a base class */
+	*n_data = self->pv->n_data;
+	return self->pv->data;
+}
+
 static void
-gcr_simple_certificate_finalize (GObject *obj)
+gcr_simple_certificate_real_finalize (GObject *obj)
 {
 	GcrSimpleCertificate *self = GCR_SIMPLE_CERTIFICATE (obj);
 
@@ -66,29 +79,15 @@ static void
 gcr_simple_certificate_class_init (GcrSimpleCertificateClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-	gobject_class->finalize = gcr_simple_certificate_finalize;
-	g_type_class_add_private (gobject_class, sizeof (GcrSimpleCertificatePrivate));
-	_gcr_initialize ();
-}
+	GcrCertificateBaseClass *cert_class = GCR_CERTIFICATE_BASE_CLASS (klass);
 
-static const guchar* 
-gcr_simple_certificate_real_get_der_data (GcrCertificate *base, gsize *n_data)
-{
-	GcrSimpleCertificate *self = GCR_SIMPLE_CERTIFICATE (base);
-	
-	g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL);
-	g_return_val_if_fail (n_data, NULL);
-	g_return_val_if_fail (self->pv->data, NULL);
+	gobject_class->finalize = gcr_simple_certificate_real_finalize;
 
-	/* This is called when we're not a base class */
-	*n_data = self->pv->n_data;
-	return self->pv->data;
-}
+	cert_class->get_der_data = gcr_simple_certificate_real_get_der_data;
 
-static void 
-gcr_certificate_iface (GcrCertificateIface *iface) 
-{
-	iface->get_der_data = (gpointer)gcr_simple_certificate_real_get_der_data;
+	g_type_class_add_private (gobject_class, sizeof (GcrSimpleCertificatePrivate));
+
+	_gcr_initialize ();
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/gcr/gcr-simple-certificate.h b/gcr/gcr-simple-certificate.h
index 7089af9..a92fda5 100644
--- a/gcr/gcr-simple-certificate.h
+++ b/gcr/gcr-simple-certificate.h
@@ -40,12 +40,12 @@ typedef struct _GcrSimpleCertificateClass GcrSimpleCertificateClass;
 typedef struct _GcrSimpleCertificatePrivate GcrSimpleCertificatePrivate;
 
 struct _GcrSimpleCertificate {
-	GObject parent;
+	GcrCertificateBase parent;
 	GcrSimpleCertificatePrivate *pv;
 };
 
 struct _GcrSimpleCertificateClass {
-	GObjectClass parent_class;
+	GcrCertificateBaseClass parent_class;
 };
 
 GType               gcr_simple_certificate_get_type               (void);
diff --git a/gcr/tests/test-ui-selector.c b/gcr/tests/test-ui-selector.c
index db89fa0..4547f9f 100644
--- a/gcr/tests/test-ui-selector.c
+++ b/gcr/tests/test-ui-selector.c
@@ -5,6 +5,7 @@
 #include "gcr-column.h"
 #include "gcr-collection-model.h"
 #include "gcr-renderer.h"
+#include "gcr-selector.h"
 #include "gcr-simple-collection.h"
 
 #include <gtk/gtk.h>
@@ -65,77 +66,11 @@ add_to_selector (GcrParser *parser, const gchar *path)
 	g_free (data);
 }
 
-#if 1
-static void
-build_selector (GtkDialog *dialog, GcrCollection *collection)
-{
-	GcrCollectionModel *model;
-	GtkWidget *combo;
-	GtkCellRenderer *cell;
-
-	model = gcr_collection_model_new (collection,
-	                                  "icon", G_TYPE_ICON,
-	                                  "markup", G_TYPE_STRING,
-	                                  NULL);
-
-	combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (model));
-	cell = gtk_cell_renderer_pixbuf_new ();
-	g_object_set (cell, "stock-size", GTK_ICON_SIZE_DND, NULL);
-	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, FALSE);
-	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cell, "gicon", 0);
-
-	cell = gtk_cell_renderer_text_new ();
-	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
-	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cell, "markup", 1);
-
-	gtk_widget_show (GTK_WIDGET (combo));
-	gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (dialog)), combo);
-
-	gtk_window_set_default_size (GTK_WINDOW (dialog), 550, 400);
-	gtk_container_set_border_width (GTK_CONTAINER (dialog), 20);
-
-	g_object_unref (model);
-}
-#endif
-
-#if 0
-static void
-build_selector (GtkDialog *dialog, GcrCollection *collection)
-{
-	GcrCollectionModel *model;
-	const GcrModelColumn *columns;
-	GtkWidget *combo;
-	GtkCellRenderer *cell;
-
-	columns = gcr_renderer_columns (GCR_TYPE_CERTIFICATE_RENDERER);
-	model = gcr_collection_model_new_full (collection, columns);
-
-	gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
-
-	combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (model));
-	cell = gtk_cell_renderer_pixbuf_new ();
-	g_object_set (cell, "stock-size", GTK_ICON_SIZE_DND, NULL);
-	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, FALSE);
-	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cell, "gicon", 0);
-
-	cell = gtk_cell_renderer_text_new ();
-	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
-	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cell, "markup", 1);
-
-	gtk_widget_show (GTK_WIDGET (combo));
-	gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (dialog)), combo);
-
-	gtk_window_set_default_size (GTK_WINDOW (dialog), 550, 400);
-	gtk_container_set_border_width (GTK_CONTAINER (dialog), 20);
-
-	g_object_unref (model);
-}
-#endif
-
 int
 main (int argc, char *argv[])
 {
 	GcrCollection *collection;
+	GcrSelector *selector;
 	GtkDialog *dialog;
 	GcrParser *parser;
 	int i;
@@ -146,15 +81,13 @@ main (int argc, char *argv[])
 	g_object_ref_sink (dialog);
 
 	collection = gcr_simple_collection_new ();
-	build_selector (dialog, collection);
+	selector = gcr_selector_new (collection, GCR_CERTIFICATE_COLUMNS, GCR_SELECTOR_MODE_MULTIPLE);
 
-#if 0
-	{
-		GtkWidget *widget = gtk_file_chooser_button_new ("Tester", GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
-		gtk_widget_show (widget);
-		gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (dialog)), widget);
-	}
-#endif
+	gtk_widget_show (GTK_WIDGET (selector));
+	gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (dialog)), GTK_WIDGET (selector));
+
+	gtk_window_set_default_size (GTK_WINDOW (dialog), 550, 400);
+	gtk_container_set_border_width (GTK_CONTAINER (dialog), 20);
 
 	parser = gcr_parser_new ();
 	g_signal_connect (parser, "parsed", G_CALLBACK (on_parser_parsed), collection);



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