[gcr] More implementation of selector widget.
authorStef Walter <stef@memberwebs.com>
Wed, 20 Oct 2010 20:47:39 +0000 (20:47 +0000)
committerStef Walter <stefw@collabora.co.uk>
Tue, 5 Apr 2011 09:29:41 +0000 (11:29 +0200)
 * Add a certificate base class to augment interface with default props.
 * All properties come from certificate rather than renderer.
 * Certificates are comparable.

20 files changed:
docs/reference/gcr/gcr-sections.txt
gcr/Makefile.am
gcr/gcr-certificate-renderer.c
gcr/gcr-certificate-renderer.h
gcr/gcr-certificate.c
gcr/gcr-certificate.h
gcr/gcr-collection-model.c
gcr/gcr-collection-model.h
gcr/gcr-column.h
gcr/gcr-comparable.c [new file with mode: 0644]
gcr/gcr-comparable.h [new file with mode: 0644]
gcr/gcr-library.c
gcr/gcr-pkcs11-certificate.c
gcr/gcr-renderer.c
gcr/gcr-renderer.h
gcr/gcr-selector.c [new file with mode: 0644]
gcr/gcr-selector.h [new file with mode: 0644]
gcr/gcr-simple-certificate.c
gcr/gcr.h
gcr/tests/test-ui-selector.c

index 95ba401..43deadf 100644 (file)
@@ -58,6 +58,10 @@ gcr_certificate_get_serial_number_hex
 gcr_certificate_get_key_size
 gcr_certificate_get_fingerprint
 gcr_certificate_get_fingerprint_hex
+gcr_certificate_mixin_class_init
+gcr_certificate_mixin_get_property
+GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE
+gcr_certificate_mixin_comparable_init
 <SUBSECTION Standard>
 GCR_CERTIFICATE
 GCR_IS_CERTIFICATE
index e50931b..f3b3949 100644 (file)
@@ -35,6 +35,8 @@ 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 \
@@ -42,6 +44,7 @@ inc_HEADERS = \
        gcr-parser.h \
        gcr-pkcs11-certificate.h \
        gcr-renderer.h \
+       gcr-selector.h \
        gcr-simple-certificate.h \
        gcr-simple-collection.h \
        gcr-trust.h \
@@ -76,6 +79,7 @@ libgcr@GCR_VERSION_SUFFIX@_la_SOURCES = \
        gcr-collection.c gcr-collection.h \
        gcr-collection-model.c gcr-collection-model.h \
        gcr-display-scrolled.c gcr-display-scrolled.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 \
@@ -87,6 +91,7 @@ libgcr@GCR_VERSION_SUFFIX@_la_SOURCES = \
        gcr-parser.c gcr-parser.h \
        gcr-pkcs11-certificate.c gcr-pkcs11-certificate.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-trust.c gcr-trust.h \
index 8b923c0..6029e58 100644 (file)
@@ -42,13 +42,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 {
@@ -56,15 +50,16 @@ 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);
+static void gcr_renderer_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_IMPLEMENT_INTERFACE (GCR_TYPE_RENDERER, gcr_renderer_iface_init);
+       GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE ();
+       G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, gcr_renderer_certificate_iface_init);
+);
 
 /* -----------------------------------------------------------------------------
  * INTERNAL
@@ -90,26 +85,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)
@@ -266,7 +241,6 @@ 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 void
@@ -295,10 +269,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);
 }
 
@@ -343,26 +313,8 @@ 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);
+               gcr_certificate_mixin_get_property (obj, prop_id, value, pspec);
                break;
        }
 }
@@ -383,27 +335,18 @@ gcr_certificate_renderer_class_init (GcrCertificateRendererClass *klass)
 
        g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
                   g_param_spec_object ("certificate", "Certificate", "Certificate to display.",
-                                      GCR_TYPE_CERTIFICATE, G_PARAM_READWRITE));
+                                       GCR_TYPE_CERTIFICATE, G_PARAM_READWRITE));
 
-       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_ATTRIBUTES,
+                  g_param_spec_boxed ("attributes", "Attributes", "Certificate pkcs11 attributes",
+                                      GCK_TYPE_ATTRIBUTES, G_PARAM_READWRITE));
 
-       g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
-                  g_param_spec_string ("issuer", "Issuer", "Common name of issuer",
-                                       "", G_PARAM_READABLE));
-
-       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_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 ();
+       gcr_certificate_mixin_class_init (gobject_class);
 
        /* Register this as a renderer which can be loaded */
        registered = gck_attributes_new ();
@@ -429,6 +372,7 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
        GNode *asn;
        GQuark oid;
        GDate date;
+       GIcon *icon;
 
        self = GCR_CERTIFICATE_RENDERER (renderer);
 
@@ -448,7 +392,9 @@ gcr_certificate_renderer_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);
@@ -602,25 +548,12 @@ gcr_certificate_renderer_populate_popup (GcrRenderer *self, 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->populate_popup = gcr_certificate_renderer_populate_popup;
        iface->render_view = gcr_certificate_renderer_render;
-       iface->column_info = columns;
 }
 
 static gconstpointer
-gcr_certificate_renderer_real_get_der_data (GcrCertificate *cert, gsize *n_data)
+gcr_certificate_renderer_get_der_data (GcrCertificate *cert, gsize *n_data)
 {
        GcrCertificateRenderer *self = GCR_CERTIFICATE_RENDERER (cert);
        GckAttribute *attr;
@@ -641,9 +574,9 @@ gcr_certificate_renderer_real_get_der_data (GcrCertificate *cert, gsize *n_data)
 }
 
 static void
-gcr_certificate_iface_init (GcrCertificateIface *iface)
+gcr_renderer_certificate_iface_init (GcrCertificateIface *iface)
 {
-       iface->get_der_data = gcr_certificate_renderer_real_get_der_data;
+       iface->get_der_data = gcr_certificate_renderer_get_der_data;
 }
 
 /* -----------------------------------------------------------------------------
index ff58ce3..2cc225b 100644 (file)
@@ -57,8 +57,6 @@ struct _GcrCertificateRendererClass {
 
 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,
index e412991..f877738 100644 (file)
 
 #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
  *
  * You can use #GcrSimpleCertificate to simply load a certificate for which
  * you already have the raw certificate data.
+ *
+ * The #GcrCertificate interface has several properties that must be implemented.
+ * You can use a mixin to implement these properties if desired. See the
+ * gcr_certificate_mixin_class_init() and gcr_certificate_mixin_get_property()
+ * functions.
+ *
+ * All certificates are comparable. If implementing a #GcrCertificate, you can
+ * use GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE() to implement the #GcrComparable
+ * interface.
  */
 
 /*
@@ -71,6 +83,17 @@ typedef struct _GcrCertificateInfo {
 static gconstpointer _gcr_certificate_get_subject_const (GcrCertificate *self, gsize *n_data);
 static gconstpointer _gcr_certificate_get_issuer_const (GcrCertificate *self, gsize *n_data);
 
+enum {
+       PROP_FIRST = 0x0007000,
+       PROP_LABEL,
+       PROP_MARKUP,
+       PROP_DESCRIPTION,
+       PROP_ICON,
+       PROP_SUBJECT,
+       PROP_ISSUER,
+       PROP_EXPIRY
+};
+
 /* -----------------------------------------------------------------------------
  * INTERNAL
  */
@@ -223,12 +246,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;
 
@@ -237,7 +296,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);
        }
@@ -250,7 +335,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 */
@@ -260,17 +345,58 @@ 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;
 }
 
-
 /* -----------------------------------------------------------------------------
  * 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
@@ -752,3 +878,148 @@ 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);
+}
+
+/* -----------------------------------------------------------------------------
+ * MIXIN
+ */
+
+/**
+ * GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE:
+ *
+ * Implement the GcrComparable interface. Use this macro like this:
+ *
+ * <informalexample><programlisting>
+ * G_DEFINE_TYPE_WITH_CODE (MyCertificate, my_certificate, G_TYPE_OBJECT,
+ *     GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE ();
+ *     G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, my_certificate_iface_init);
+ * );
+ * </programlisting></informalexample>
+ */
+
+/**
+ * gcr_certificate_mixin_comparable_init:
+ * @iface: The interface
+ *
+ * Initialize a #GcrComparableIface to compare the current certificate.
+ * In general it's easier to use the GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE()
+ * macro instead of this function.
+ */
+void
+gcr_certificate_mixin_comparable_init (GcrComparableIface *iface)
+{
+       iface->compare = gcr_certificate_compare;
+}
+
+/**
+ * gcr_certificate_mixin_class_init:
+ * @object_class: The GObjectClass for this class
+ *
+ * Initialize the certificate mixin for the class. This mixin implements the
+ * various required properties for the certificate.
+ *
+ * Call this function near the end of your derived class_init() function. The
+ * derived class must implement the #GcrCertificate interface.
+ */
+void
+gcr_certificate_mixin_class_init (GObjectClass *object_class)
+{
+       if (!g_object_class_find_property (object_class, "description"))
+               g_object_class_override_property (object_class, PROP_DESCRIPTION, "description");
+       if (!g_object_class_find_property (object_class, "markup"))
+               g_object_class_override_property (object_class, PROP_MARKUP, "markup");
+       if (!g_object_class_find_property (object_class, "label"))
+               g_object_class_override_property (object_class, PROP_LABEL, "label");
+       if (!g_object_class_find_property (object_class, "icon"))
+               g_object_class_override_property (object_class, PROP_ICON, "icon");
+       if (!g_object_class_find_property (object_class, "subject"))
+               g_object_class_override_property (object_class, PROP_SUBJECT, "subject");
+       if (!g_object_class_find_property (object_class, "issuer"))
+               g_object_class_override_property (object_class, PROP_ISSUER, "issuer");
+       if (!g_object_class_find_property (object_class, "expiry"))
+               g_object_class_override_property (object_class, PROP_EXPIRY, "expiry");
+
+       _gcr_initialize ();
+}
+
+/**
+ * gcr_certificate_mixin_get_property:
+ * @obj: The object
+ * @prop_id: The property id
+ * @value: The value to fill in.
+ * @pspec: The param specification.
+ *
+ * Implementation to get various required certificate properties. This should
+ * be called from your derived class get_property function, or used as a
+ * get_property virtual function.
+ *
+ * Example of use as called from derived class get_property function:
+ *
+ * <informalexample><programlisting>
+ * static void
+ * my_get_property (GObject *obj, guint prop_id, GValue *value, GParamSpec *pspec)
+ * {
+ *     switch (prop_id) {
+ *
+ *     ...
+ *
+ *     default:
+ *             gcr_certificate_mixin_get_property (obj, prop_id, value, pspec);
+ *             break;
+ *     }
+ *}
+ * </programlisting></informalexample>
+ *
+ * Example of use as get_property function:
+ *
+ * <informalexample><programlisting>
+ * static void
+ * my_class_init (MyClass *klass)
+ * {
+ *     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ *     gobject_class->get_property = gcr_certificate_mixin_get_property;
+ *
+ *     ...
+ * }
+ * </programlisting></informalexample>
+
+ */
+void
+gcr_certificate_mixin_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;
+       }
+}
index 056171e..09c74b1 100644 (file)
 #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;
+typedef struct _GcrCertificate          GcrCertificate;
+typedef struct _GcrCertificateIface     GcrCertificateIface;
 
 struct _GcrCertificateIface {
        GTypeInterface parent;
 
-       gconstpointer (*get_der_data)   (GcrCertificate *self, gsize *n_data);
+       gconstpointer (*get_der_data) (GcrCertificate *self, gsize *n_data);
 
        gpointer dummy1;
        gpointer dummy2;
@@ -59,6 +63,11 @@ GType               gcr_certificate_get_type               (void);
 gconstpointer       gcr_certificate_get_der_data           (GcrCertificate *self,
                                                             gsize *n_data);
 
+const GcrColumn*    gcr_certificate_get_columns            (void);
+
+gint                gcr_certificate_compare                (GcrComparable *self,
+                                                            GcrComparable *other);
+
 gchar*              gcr_certificate_get_issuer_cn          (GcrCertificate *self);
 
 gchar*              gcr_certificate_get_issuer_dn          (GcrCertificate *self);
@@ -100,6 +109,20 @@ guchar*             gcr_certificate_get_fingerprint        (GcrCertificate *self
 gchar*              gcr_certificate_get_fingerprint_hex    (GcrCertificate *self,
                                                             GChecksumType type);
 
+GIcon*              gcr_certificate_get_icon               (GcrCertificate *self);
+
+#define GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE() \
+       G_IMPLEMENT_INTERFACE (GCR_TYPE_COMPARABLE, gcr_certificate_mixin_comparable_init)
+
+void                gcr_certificate_mixin_comparable_init  (GcrComparableIface *iface);
+
+void                gcr_certificate_mixin_class_init       (GObjectClass *object_class);
+
+void                gcr_certificate_mixin_get_property     (GObject *obj,
+                                                            guint prop_id,
+                                                            GValue *value,
+                                                            GParamSpec *pspec);
+
 G_END_DECLS
 
 #endif /* __GCR_CERTIFICATE_H__ */
index db05bea..5c8d753 100644 (file)
@@ -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;
+}
index fb750d2..1765126 100644 (file)
@@ -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__ */
index ce26da7..53a3530 100644 (file)
 
 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 (file)
index 0000000..3f4d513
--- /dev/null
@@ -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 (file)
index 0000000..39f1d8a
--- /dev/null
@@ -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__ */
index cfc4d1c..cd95be7 100644 (file)
@@ -179,11 +179,11 @@ _gcr_initialize (void)
                trust_lookup_uris[1] = g_strdup ("pkcs11:library-manufacturer=GNOME%20Keyring;serial=1:XDG:DEFAULT");
                trust_lookup_uris[2] = NULL;
 
-               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));
 }
 
 /**
index e8dbd31..998c89b 100644 (file)
@@ -60,7 +60,9 @@ struct _GcrPkcs11CertificatePrivate {
 
 static void gcr_certificate_iface (GcrCertificateIface *iface);
 G_DEFINE_TYPE_WITH_CODE (GcrPkcs11Certificate, gcr_pkcs11_certificate, GCK_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, gcr_certificate_iface));
+       GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE ();
+       G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, gcr_certificate_iface);
+);
 
 /* ----------------------------------------------------------------------------
  * INTERAL
@@ -235,7 +237,7 @@ gcr_pkcs11_certificate_get_property (GObject *obj, guint prop_id, GValue *value,
                g_value_set_boxed (value, gcr_pkcs11_certificate_get_attributes (self));
                break;
        default:
-               G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+               gcr_certificate_mixin_get_property (obj, prop_id, value, pspec);
                break;
        }
 }
@@ -271,13 +273,14 @@ gcr_pkcs11_certificate_class_init (GcrPkcs11CertificateClass *klass)
 
        g_type_class_add_private (gobject_class, sizeof (GcrPkcs11CertificatePrivate));
 
+       gcr_certificate_mixin_class_init (gobject_class);
        _gcr_initialize ();
 }
 
 static gconstpointer
-gcr_pkcs11_certificate_real_get_der_data (GcrCertificate *base, gsize *n_data)
+gcr_pkcs11_certificate_get_der_data (GcrCertificate *cert, gsize *n_data)
 {
-       GcrPkcs11Certificate *self = GCR_PKCS11_CERTIFICATE (base);
+       GcrPkcs11Certificate *self = GCR_PKCS11_CERTIFICATE (cert);
        GckAttribute *attr;
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL);
@@ -293,7 +296,7 @@ gcr_pkcs11_certificate_real_get_der_data (GcrCertificate *base, gsize *n_data)
 static void
 gcr_certificate_iface (GcrCertificateIface *iface)
 {
-       iface->get_der_data = (gpointer)gcr_pkcs11_certificate_real_get_der_data;
+       iface->get_der_data = gcr_pkcs11_certificate_get_der_data;
 }
 
 /* -----------------------------------------------------------------------------
index 46afac1..8d96dd9 100644 (file)
@@ -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);
@@ -188,24 +176,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;
-}
index 2676dd2..e262508 100644 (file)
@@ -40,9 +40,6 @@ typedef struct _GcrRendererIface GcrRendererIface;
 struct _GcrRendererIface {
        GTypeInterface parent;
 
-       /* data */
-       const GcrModelColumn *column_info;
-
        /* signals */
        void (*data_changed) (GcrRenderer *self);
 
@@ -84,8 +81,6 @@ void                      gcr_renderer_emit_data_changed          (GcrRenderer *
 GcrRenderer*              gcr_renderer_create                     (const gchar *label,
                                                                    GckAttributes *attrs);
 
-const GcrModelColumn*     gcr_renderer_columns                    (GType renderer_type);
-
 void                      gcr_renderer_register                   (GType renderer_type,
                                                                    GckAttributes *attrs);
 
diff --git a/gcr/gcr-selector.c b/gcr/gcr-selector.c
new file mode 100644 (file)
index 0000000..334c2d3
--- /dev/null
@@ -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 (file)
index 0000000..88fba51
--- /dev/null
@@ -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__ */
index dfa6023..217e341 100644 (file)
@@ -22,6 +22,7 @@
 #include "config.h"
 
 #include "gcr-certificate.h"
+#include "gcr-comparable.h"
 #include "gcr-internal.h"
 #include "gcr-simple-certificate.h"
 
@@ -46,9 +47,13 @@ struct _GcrSimpleCertificatePrivate {
        guchar *owned;
 };
 
-static void gcr_certificate_iface (GcrCertificateIface *iface);
+/* Forward declarations */
+static void gcr_simple_certificate_iface_init (GcrCertificateIface *iface);
+
 G_DEFINE_TYPE_WITH_CODE (GcrSimpleCertificate, gcr_simple_certificate, G_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, gcr_certificate_iface));
+       GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE ();
+       G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, gcr_simple_certificate_iface_init);
+);
 
 /* -----------------------------------------------------------------------------
  * OBJECT
@@ -61,7 +66,7 @@ gcr_simple_certificate_init (GcrSimpleCertificate *self)
 }
 
 static void
-gcr_simple_certificate_finalize (GObject *obj)
+gcr_simple_certificate_real_finalize (GObject *obj)
 {
        GcrSimpleCertificate *self = GCR_SIMPLE_CERTIFICATE (obj);
 
@@ -77,15 +82,20 @@ static void
 gcr_simple_certificate_class_init (GcrSimpleCertificateClass *klass)
 {
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-       gobject_class->finalize = gcr_simple_certificate_finalize;
+
+       gobject_class->finalize = gcr_simple_certificate_real_finalize;
+       gobject_class->get_property = gcr_certificate_mixin_get_property;
+
        g_type_class_add_private (gobject_class, sizeof (GcrSimpleCertificatePrivate));
+
+       gcr_certificate_mixin_class_init (gobject_class);
        _gcr_initialize ();
 }
 
 static gconstpointer
-gcr_simple_certificate_real_get_der_data (GcrCertificate *base, gsize *n_data)
+gcr_simple_certificate_get_der_data (GcrCertificate *cert, gsize *n_data)
 {
-       GcrSimpleCertificate *self = GCR_SIMPLE_CERTIFICATE (base);
+       GcrSimpleCertificate *self = GCR_SIMPLE_CERTIFICATE (cert);
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL);
        g_return_val_if_fail (n_data, NULL);
@@ -97,9 +107,9 @@ gcr_simple_certificate_real_get_der_data (GcrCertificate *base, gsize *n_data)
 }
 
 static void
-gcr_certificate_iface (GcrCertificateIface *iface)
+gcr_simple_certificate_iface_init (GcrCertificateIface *iface)
 {
-       iface->get_der_data = (gpointer)gcr_simple_certificate_real_get_der_data;
+       iface->get_der_data = gcr_simple_certificate_get_der_data;
 }
 
 /* -----------------------------------------------------------------------------
index 8ac536b..9987dc7 100644 (file)
--- a/gcr/gcr.h
+++ b/gcr/gcr.h
@@ -46,6 +46,7 @@
 #include "gcr-parser.h"
 #include "gcr-renderer.h"
 #include "gcr-pkcs11-certificate.h"
+#include "gcr-selector.h"
 #include "gcr-simple-certificate.h"
 #include "gcr-simple-collection.h"
 #include "gcr-trust.h"
index a9e717e..9aea8b9 100644 (file)
@@ -61,77 +61,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;
@@ -142,15 +76,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);