[gcr] Add functionality for renderers to populate tree models.
authorStef Walter <stef@memberwebs.com>
Fri, 15 Oct 2010 03:17:29 +0000 (03:17 +0000)
committerStef Walter <stefw@collabora.co.uk>
Tue, 5 Apr 2011 09:28:53 +0000 (11:28 +0200)
 * Add markup, icon and description properties to renderers.
 * Add GcrSimpleCollection which implements collections.
 * Use GIcon instead of stock ids.
 * Rough example test certificate selector.

14 files changed:
gcr/Makefile.am
gcr/gcr-certificate-renderer.c
gcr/gcr-collection-model.c
gcr/gcr-display-view.c
gcr/gcr-display-view.h
gcr/gcr-key-renderer.c
gcr/gcr-library.c
gcr/gcr-renderer.c
gcr/gcr-renderer.h
gcr/gcr-simple-collection.c [new file with mode: 0644]
gcr/gcr-simple-collection.h [new file with mode: 0644]
gcr/gcr.h
gcr/tests/Makefile.am
gcr/tests/test-ui-selector.c [new file with mode: 0644]

index 5740069..e50931b 100644 (file)
@@ -43,6 +43,7 @@ inc_HEADERS = \
        gcr-pkcs11-certificate.h \
        gcr-renderer.h \
        gcr-simple-certificate.h \
+       gcr-simple-collection.h \
        gcr-trust.h \
        gcr-types.h \
        gcr-unlock-options.h \
@@ -87,6 +88,7 @@ libgcr@GCR_VERSION_SUFFIX@_la_SOURCES = \
        gcr-pkcs11-certificate.c gcr-pkcs11-certificate.h \
        gcr-renderer.c gcr-renderer.h \
        gcr-simple-certificate.c gcr-simple-certificate.h \
+       gcr-simple-collection.c gcr-simple-collection.h \
        gcr-trust.c gcr-trust.h \
        gcr-types.h \
        gcr-unlock-options.h \
index f6710e4..592b69b 100644 (file)
@@ -42,7 +42,10 @@ enum {
        PROP_0,
        PROP_CERTIFICATE,
        PROP_LABEL,
-       PROP_ATTRIBUTES
+       PROP_ATTRIBUTES,
+       PROP_DESCRIPTION,
+       PROP_ICON,
+       PROP_MARKUP
 };
 
 struct _GcrCertificateRendererPrivate {
@@ -50,6 +53,7 @@ struct _GcrCertificateRendererPrivate {
        GckAttributes *opt_attrs;
        guint key_size;
        gchar *label;
+       GIcon *icon;
 };
 
 static void gcr_renderer_iface_init (GcrRendererIface *iface);
@@ -64,7 +68,7 @@ G_DEFINE_TYPE_WITH_CODE (GcrCertificateRenderer, gcr_certificate_renderer, G_TYP
  */
 
 static gchar*
-calculate_label (GcrCertificateRenderer *self, GNode *asn)
+calculate_label (GcrCertificateRenderer *self)
 {
        gchar *label;
 
@@ -76,15 +80,33 @@ calculate_label (GcrCertificateRenderer *self, GNode *asn)
                        return label;
        }
 
-       if (asn != NULL) {
-               label = egg_dn_read_part (egg_asn1x_node (asn, "tbsCertificate", "subject", "rdnSequence", NULL), "CN");
-               if (label != NULL)
-                       return label;
-       }
+       label = gcr_certificate_get_subject_cn (GCR_CERTIFICATE (self));
+       if (label != NULL)
+               return label;
 
        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)
@@ -218,13 +240,13 @@ on_certificate_export (GtkMenuItem *menuitem, gpointer user_data)
        gchar *label;
        GtkWidget *parent;
 
-       label = calculate_label (self, NULL);
+       label = calculate_label (self);
 
        parent = gtk_widget_get_toplevel (GTK_WIDGET (menuitem));
        if (parent && !GTK_IS_WINDOW (parent))
                parent = NULL;
 
-       exporter = _gcr_certificate_exporter_new (self->pv->certificate, label,
+       exporter = _gcr_certificate_exporter_new (GCR_CERTIFICATE (self), label,
                                                  GTK_WINDOW (parent));
 
        g_free (label);
@@ -241,6 +263,7 @@ 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
@@ -269,6 +292,10 @@ 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);
 }
 
@@ -308,11 +335,20 @@ gcr_certificate_renderer_get_property (GObject *obj, guint prop_id, GValue *valu
                g_value_set_object (value, self->pv->opt_cert);
                break;
        case PROP_LABEL:
-               g_value_take_string (value, calculate_label (self, NULL));
+               g_value_take_string (value, calculate_label (self));
                break;
        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;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
                break;
@@ -339,6 +375,9 @@ gcr_certificate_renderer_class_init (GcrCertificateRendererClass *klass)
 
        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");
 
        _gcr_icons_register ();
 
@@ -381,16 +420,16 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
        _gcr_display_view_clear (view, renderer);
        cert = GCR_CERTIFICATE (self);
 
-       _gcr_display_view_set_stock_image (view, GCR_RENDERER (self), GCR_ICON_CERTIFICATE);
-
        data = gcr_certificate_get_der_data (cert, &n_data);
        if (!data)
                return;
 
+       _gcr_display_view_set_icon (view, GCR_RENDERER (self), self->pv->icon);
+
        asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data, n_data);
        g_return_if_fail (asn);
 
-       display = calculate_label (self, asn);
+       display = calculate_label (self);
        _gcr_display_view_append_title (view, renderer, display);
        g_free (display);
 
@@ -539,12 +578,12 @@ gcr_certificate_renderer_populate_popup (GcrRenderer *self, GcrViewer *viewer,
 static void
 gcr_renderer_iface_init (GcrRendererIface *iface)
 {
-       iface->render = gcr_certificate_renderer_render;
        iface->populate_popup = gcr_certificate_renderer_populate_popup;
+       iface->render_view = gcr_certificate_renderer_render;
 }
 
 
-static const guchar*
+static gconstpointer
 gcr_certificate_renderer_real_get_der_data (GcrCertificate *cert, gsize *n_data)
 {
        GcrCertificateRenderer *self = GCR_CERTIFICATE_RENDERER (cert);
index 4be857c..1eac064 100644 (file)
@@ -64,7 +64,7 @@ index_for_iter (GcrCollectionModel *self, const GtkTreeIter *iter)
        g_return_val_if_fail (G_IS_OBJECT (iter->user_data), -1);
 
        index = GPOINTER_TO_INT (iter->user_data2);
-       g_assert (index > 0 && index < self->pv->objects->len);
+       g_assert (index >= 0 && index < self->pv->objects->len);
        return index;
 }
 
@@ -588,7 +588,7 @@ gcr_collection_model_new (GcrCollection *collection, ...)
 GcrCollectionModel*
 gcr_collection_model_new_full (GcrCollection *collection, const GcrCollectionModelColumn *columns, guint n_columns)
 {
-       GcrCollectionModel *self = g_object_new (GCR_TYPE_COLLECTION, "collection", collection, NULL);
+       GcrCollectionModel *self = g_object_new (GCR_TYPE_COLLECTION_MODEL, "collection", collection, NULL);
        gcr_collection_model_set_columns (self, columns, n_columns);
        return self;
 }
index ddf54b6..d93c268 100644 (file)
@@ -211,7 +211,7 @@ on_expander_expanded (GObject *object, GParamSpec *param_spec, gpointer user_dat
        GtkExpander *expander = GTK_EXPANDER (object);
        GcrDisplayItem *item = user_data;
        item->expanded = gtk_expander_get_expanded (expander);
-       gcr_renderer_render (item->renderer, GCR_VIEWER (item->display_view));
+       gcr_renderer_render_view (item->renderer, GCR_VIEWER (item->display_view));
        recalculate_and_resize (item->display_view);
 }
 
@@ -379,7 +379,7 @@ static void
 on_renderer_data_changed (GcrRenderer *renderer, GcrViewer *self)
 {
        /* Just ask the renderer to render itself on us */
-       gcr_renderer_render (renderer, self);
+       gcr_renderer_render_view (renderer, self);
 }
 
 static void
@@ -691,7 +691,7 @@ _gcr_display_view_real_add_renderer (GcrViewer *viewer, GcrRenderer *renderer)
        g_ptr_array_add (self->pv->renderers, g_object_ref (renderer));
        g_hash_table_insert (self->pv->items, renderer, item);
 
-       gcr_renderer_render (renderer, viewer);
+       gcr_renderer_render_view (renderer, viewer);
        item->data_changed_id = g_signal_connect (renderer, "data-changed",
                                                  G_CALLBACK (on_renderer_data_changed), self);
 }
@@ -962,10 +962,14 @@ _gcr_display_view_append_fingerprint (GcrDisplayView *self, GcrRenderer *rendere
 }
 
 void
-_gcr_display_view_set_stock_image (GcrDisplayView *self, GcrRenderer *renderer,
-                                   const gchar *stock_id)
+_gcr_display_view_set_icon (GcrDisplayView *self, GcrRenderer *renderer, GIcon *icon)
 {
        GcrDisplayItem *item;
+       GdkScreen *screen;
+       GtkIconTheme *icon_theme;
+       GtkSettings *settings;
+       gint width, height;
+       GtkIconInfo *info;
 
        g_return_if_fail (GCR_IS_DISPLAY_VIEW (self));
        item = lookup_display_item (self, renderer);
@@ -973,12 +977,28 @@ _gcr_display_view_set_stock_image (GcrDisplayView *self, GcrRenderer *renderer,
 
        if (item->pixbuf)
                g_object_unref (item->pixbuf);
-       if (stock_id)
-#if GTK_CHECK_VERSION (2,91,7)
-               item->pixbuf = gtk_widget_render_icon_pixbuf (GTK_WIDGET (self), stock_id, GTK_ICON_SIZE_DIALOG);
+       item->pixbuf = NULL;
+
+       if (!icon)
+               return;
+
+       screen = gtk_widget_get_screen (GTK_WIDGET (self));
+       icon_theme = gtk_icon_theme_get_for_screen (screen);
+       settings = gtk_settings_get_for_screen (screen);
+
+       if (!gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_DIALOG, &width, &height))
+               g_return_if_reached ();
+
+       info = gtk_icon_theme_lookup_by_gicon (icon_theme, icon, MIN (width, height),
+                                              GTK_ICON_LOOKUP_USE_BUILTIN);
+
+       if (info) {
+#if GTK_CHECK_VERSION (2,91,0)
+               GtkStyleContext *style = gtk_widget_get_style_context (GTK_WIDGET (self));
+               item->pixbuf = gtk_icon_info_load_symbolic_for_context (info, style, FALSE, NULL);
 #else
-               item->pixbuf = gtk_widget_render_icon (GTK_WIDGET (self), stock_id, GTK_ICON_SIZE_DIALOG, NULL);
+               item->pixbuf = gtk_icon_info_load_icon (info, NULL);
 #endif
-       else
-               item->pixbuf = NULL;
+               gtk_icon_info_free (info);
+       }
 }
index c5f83a6..be237bb 100644 (file)
@@ -85,9 +85,9 @@ void             _gcr_display_view_append_fingerprint          (GcrDisplayView *
                                                                 const gchar *name,
                                                                 GChecksumType type);
 
-void             _gcr_display_view_set_stock_image             (GcrDisplayView *self,
+void             _gcr_display_view_set_icon                    (GcrDisplayView *self,
                                                                 GcrRenderer *renderer,
-                                                                const gchar *stock_id);
+                                                                GIcon *icon);
 
 G_END_DECLS
 
index 7f2fb4c..0b018d5 100644 (file)
@@ -42,6 +42,7 @@ struct _GcrKeyRendererPrivate {
        guint key_size;
        gchar *label;
        GckAttributes *attributes;
+       GIcon *icon;
 };
 
 static void gcr_key_renderer_renderer_iface (GcrRendererIface *iface);
@@ -124,6 +125,7 @@ static void
 gcr_key_renderer_init (GcrKeyRenderer *self)
 {
        self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_KEY_RENDERER, GcrKeyRendererPrivate));
+       self->pv->icon = g_themed_icon_new (GCR_ICON_FOLDER);
 }
 
 static void
@@ -144,6 +146,10 @@ gcr_key_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_key_renderer_parent_class)->finalize (obj);
 }
 
@@ -243,14 +249,14 @@ gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
        if (!self->pv->attributes)
                return;
 
-       _gcr_display_view_set_stock_image (view, renderer, GTK_STOCK_DIALOG_AUTHENTICATION);
-
        if (!gck_attributes_find_ulong (self->pv->attributes, CKA_CLASS, &klass) ||
            !gck_attributes_find_ulong (self->pv->attributes, CKA_KEY_TYPE, &key_type)) {
                g_warning ("private key does not have the CKA_CLASS and CKA_KEY_TYPE attributes");
                return;
        }
 
+       _gcr_display_view_set_icon (view, renderer, self->pv->icon);
+
        display = calculate_label (self);
        _gcr_display_view_append_title (view, renderer, display);
        g_free (display);
@@ -306,7 +312,7 @@ gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 static void
 gcr_key_renderer_renderer_iface (GcrRendererIface *iface)
 {
-       iface->render = gcr_key_renderer_real_render;
+       iface->render_view = gcr_key_renderer_real_render;
 }
 
 /* -----------------------------------------------------------------------------
index 23f97a7..cfc4d1c 100644 (file)
 
 #include "config.h"
 
-#include "gcr-types.h"
+#include "gcr.h"
+#include "gcr-certificate-renderer.h"
 #include "gcr-internal.h"
 #include "gcr-library.h"
+#include "gcr-key-renderer.h"
+#include "gcr-types.h"
 
 #include "egg/egg-error.h"
 #include "egg/egg-libgcrypt.h"
@@ -176,6 +179,9 @@ _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);
        }
 }
index 28bc905..cbc8bbc 100644 (file)
@@ -56,6 +56,18 @@ 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);
@@ -81,11 +93,11 @@ gcr_renderer_get_type (void)
 }
 
 void
-gcr_renderer_render (GcrRenderer *self, GcrViewer *viewer)
+gcr_renderer_render_view (GcrRenderer *self, GcrViewer *viewer)
 {
        g_return_if_fail (GCR_IS_RENDERER (self));
-       g_return_if_fail (GCR_RENDERER_GET_INTERFACE (self)->render);
-       GCR_RENDERER_GET_INTERFACE (self)->render (self, viewer);
+       g_return_if_fail (GCR_RENDERER_GET_INTERFACE (self)->render_view);
+       GCR_RENDERER_GET_INTERFACE (self)->render_view (self, viewer);
 }
 
 void
index bf7e04a..e2e9234 100644 (file)
@@ -35,6 +35,7 @@ G_BEGIN_DECLS
 #define GCR_RENDERER_GET_INTERFACE(inst)  (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GCR_TYPE_RENDERER, GcrRendererIface))
 
 typedef struct _GcrRendererIface GcrRendererIface;
+typedef struct _GcrRendererColumn GcrRendererColumn;
 
 struct _GcrRendererIface {
        GTypeInterface parent;
@@ -43,7 +44,11 @@ struct _GcrRendererIface {
        void (*data_changed) (GcrRenderer *self);
 
        /* virtual */
-       void (*render) (GcrRenderer *self, GcrViewer *viewer);
+       void (*render_view) (GcrRenderer *self, GcrViewer *viewer);
+
+       const GcrRendererColumn* (*get_column_info) (GcrRenderer *self, gint *n_columns);
+
+       const void (*get_column_value) (GcrRenderer *self, GQuark column, GValue *value);
 
        void (*populate_popup) (GcrRenderer *self, GcrViewer *viewer, GtkMenu *menu);
 
@@ -57,15 +62,27 @@ struct _GcrRendererIface {
 
 };
 
+struct _GcrRendererColumn {
+       GQuark column;
+       GType type;
+       const gchar *description;
+};
+
 GType                  gcr_renderer_get_type                      (void) G_GNUC_CONST;
 
-void                   gcr_renderer_render                        (GcrRenderer *self,
+void                   gcr_renderer_render_view                   (GcrRenderer *self,
                                                                    GcrViewer *viewer);
 
 void                   gcr_renderer_popuplate_popup               (GcrRenderer *self,
                                                                    GcrViewer *viewer,
                                                                    GtkMenu *menu);
 
+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,
diff --git a/gcr/gcr-simple-collection.c b/gcr/gcr-simple-collection.c
new file mode 100644 (file)
index 0000000..b88467a
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * 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.h"
+#include "gcr-internal.h"
+#include "gcr-simple-collection.h"
+
+#include <string.h>
+
+struct _GcrSimpleCollectionPrivate {
+       GHashTable *items;
+};
+
+static void gcr_collection_iface (GcrCollectionIface *iface);
+G_DEFINE_TYPE_WITH_CODE (GcrSimpleCollection, gcr_simple_collection, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, gcr_collection_iface));
+
+#define UNUSED_VALUE  GUINT_TO_POINTER (1)
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gcr_simple_collection_init (GcrSimpleCollection *self)
+{
+       self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_SIMPLE_COLLECTION, GcrSimpleCollectionPrivate);
+       self->pv->items = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
+}
+
+static void
+gcr_simple_collection_dispose (GObject *obj)
+{
+       GcrSimpleCollection *self = GCR_SIMPLE_COLLECTION (obj);
+
+       g_hash_table_remove_all (self->pv->items);
+
+       G_OBJECT_CLASS (gcr_simple_collection_parent_class)->dispose (obj);
+}
+
+static void
+gcr_simple_collection_finalize (GObject *obj)
+{
+       GcrSimpleCollection *self = GCR_SIMPLE_COLLECTION (obj);
+
+       g_assert (self->pv->items);
+       g_assert (g_hash_table_size (self->pv->items) == 0);
+       g_hash_table_destroy (self->pv->items);
+       self->pv->items = NULL;
+
+       G_OBJECT_CLASS (gcr_simple_collection_parent_class)->finalize (obj);
+}
+
+static void
+gcr_simple_collection_class_init (GcrSimpleCollectionClass *klass)
+{
+       GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+       gobject_class->dispose = gcr_simple_collection_dispose;
+       gobject_class->finalize = gcr_simple_collection_finalize;
+       g_type_class_add_private (gobject_class, sizeof (GcrSimpleCollectionPrivate));
+       _gcr_initialize ();
+}
+
+static guint
+gcr_simple_collection_real_get_length (GcrCollection *coll)
+{
+       GcrSimpleCollection *self = GCR_SIMPLE_COLLECTION (coll);
+       return g_hash_table_size (self->pv->items);
+}
+
+static GList*
+gcr_simple_collection_real_get_objects (GcrCollection *coll)
+{
+       GcrSimpleCollection *self = GCR_SIMPLE_COLLECTION (coll);
+       return g_hash_table_get_keys (self->pv->items);
+}
+
+static void
+gcr_collection_iface (GcrCollectionIface *iface)
+{
+       iface->get_length = gcr_simple_collection_real_get_length;
+       iface->get_objects = gcr_simple_collection_real_get_objects;
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+GcrCollection*
+gcr_simple_collection_new (void)
+{
+       return g_object_new (GCR_TYPE_SIMPLE_COLLECTION, NULL);
+}
+
+void
+gcr_simple_collection_add (GcrSimpleCollection *self, GObject *object)
+{
+       g_return_if_fail (GCR_IS_SIMPLE_COLLECTION (self));
+       g_return_if_fail (G_IS_OBJECT (object));
+       g_return_if_fail (!g_hash_table_lookup (self->pv->items, object));
+       g_hash_table_insert (self->pv->items, g_object_ref (object), UNUSED_VALUE);
+       gcr_collection_emit_added (GCR_COLLECTION (self), object);
+}
+
+void
+gcr_simple_collection_remove (GcrSimpleCollection *self, GObject *object)
+{
+       g_return_if_fail (GCR_IS_SIMPLE_COLLECTION (self));
+       g_return_if_fail (G_IS_OBJECT (object));
+       g_return_if_fail (g_hash_table_lookup (self->pv->items, object));
+       g_object_ref (object);
+       g_hash_table_remove (self->pv->items, object);
+       gcr_collection_emit_removed (GCR_COLLECTION (self), object);
+       g_object_unref (object);
+}
+
+gboolean
+gcr_simple_collection_contains (GcrSimpleCollection *self, GObject *object)
+{
+       g_return_val_if_fail (GCR_IS_SIMPLE_COLLECTION (self), FALSE);
+       g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
+       return g_hash_table_lookup (self->pv->items, object) ? TRUE : FALSE;
+}
diff --git a/gcr/gcr-simple-collection.h b/gcr/gcr-simple-collection.h
new file mode 100644 (file)
index 0000000..beccb0b
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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_SIMPLE_COLLECTION_H__
+#define __GCR_SIMPLE_COLLECTION_H__
+
+#include "gcr.h"
+#include "gcr-collection.h"
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GCR_TYPE_SIMPLE_COLLECTION               (gcr_simple_collection_get_type ())
+#define GCR_SIMPLE_COLLECTION(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_COLLECTION, GcrSimpleCollection))
+#define GCR_SIMPLE_COLLECTION_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_COLLECTION, GcrSimpleCollectionClass))
+#define GCR_IS_SIMPLE_COLLECTION(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_COLLECTION))
+#define GCR_IS_SIMPLE_COLLECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_COLLECTION))
+#define GCR_SIMPLE_COLLECTION_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_COLLECTION, GcrSimpleCollectionClass))
+
+typedef struct _GcrSimpleCollection GcrSimpleCollection;
+typedef struct _GcrSimpleCollectionClass GcrSimpleCollectionClass;
+typedef struct _GcrSimpleCollectionPrivate GcrSimpleCollectionPrivate;
+
+struct _GcrSimpleCollection {
+       GObject parent;
+       GcrSimpleCollectionPrivate *pv;
+};
+
+struct _GcrSimpleCollectionClass {
+       GObjectClass parent_class;
+};
+
+GType               gcr_simple_collection_get_type                (void);
+
+GcrCollection*      gcr_simple_collection_new                     (void);
+
+void                gcr_simple_collection_add                     (GcrSimpleCollection *self,
+                                                                   GObject *object);
+
+void                gcr_simple_collection_remove                  (GcrSimpleCollection *self,
+                                                                   GObject *object);
+
+gboolean            gcr_simple_collection_contains                (GcrSimpleCollection *self,
+                                                                   GObject *object);
+
+G_END_DECLS
+
+#endif /* __GCR_SIMPLE_COLLECTION_H__ */
index e0aa175..8ac536b 100644 (file)
--- a/gcr/gcr.h
+++ b/gcr/gcr.h
 #include "gcr-certificate-chain.h"
 #include "gcr-certificate-renderer.h"
 #include "gcr-certificate-widget.h"
+#include "gcr-collection-model.h"
 #include "gcr-key-renderer.h"
 #include "gcr-key-widget.h"
 #include "gcr-importer.h"
 #include "gcr-library.h"
 #include "gcr-parser.h"
+#include "gcr-renderer.h"
 #include "gcr-pkcs11-certificate.h"
 #include "gcr-simple-certificate.h"
+#include "gcr-simple-collection.h"
 #include "gcr-trust.h"
 #include "gcr-unlock-options.h"
 #include "gcr-unlock-options-widget.h"
index fab95d8..7aa06c3 100644 (file)
@@ -25,46 +25,19 @@ EXTRA_DIST += \
 
 # ------------------------------------------------------------------
 
-noinst_PROGRAMS += \
-       ui-test-certificate \
-       ui-test-key \
-       ui-test-unlock-options
-
-ui_test_certificate_SOURCES = \
-       ui-test-certificate.c
-
-ui_test_certificate_CFLAGS = \
+INCLUDES += \
        -DGCR_API_SUBJECT_TO_CHANGE \
+       -DGCK_API_SUBJECT_TO_CHANGE \
        $(GTK_CFLAGS)
 
-ui_test_certificate_LDADD = \
+LIBS += \
        $(top_builddir)/gcr/libgcr@GCR_VERSION_SUFFIX@.la \
        $(top_builddir)/gck/libgck.la \
        $(GTK_LIBS) \
        $(LIBGCRYPT_LIBS)
 
-ui_test_unlock_options_SOURCES = \
-       ui-test-unlock-options.c
-
-ui_test_unlock_options_CFLAGS = \
-       -DGCR_API_SUBJECT_TO_CHANGE \
-       $(GTK_CFLAGS)
-
-ui_test_unlock_options_LDADD = \
-       $(top_builddir)/gcr/libgcr@GCR_VERSION_SUFFIX@.la \
-       $(top_builddir)/gck/libgck.la \
-       $(GTK_LIBS) \
-       $(LIBGCRYPT_LIBS)
-
-ui_test_key_SOURCES = \
-       ui-test-key.c
-
-ui_test_key_CFLAGS = \
-       -DGCR_API_SUBJECT_TO_CHANGE \
-       $(GTK_CFLAGS)
-
-ui_test_key_LDADD = \
-       $(top_builddir)/gcr/libgcr@GCR_VERSION_SUFFIX@.la \
-       $(top_builddir)/gck/libgck.la \
-       $(GTK_LIBS) \
-       $(LIBGCRYPT_LIBS)
+noinst_PROGRAMS += \
+       test-ui-selector \
+       ui-test-certificate \
+       ui-test-key \
+       ui-test-unlock-options
diff --git a/gcr/tests/test-ui-selector.c b/gcr/tests/test-ui-selector.c
new file mode 100644 (file)
index 0000000..d6933d5
--- /dev/null
@@ -0,0 +1,129 @@
+
+#include "config.h"
+
+#include "gcr.h"
+
+#include <gtk/gtk.h>
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+static void
+chdir_base_dir (char* argv0)
+{
+       gchar *dir, *base;
+
+       dir = g_path_get_dirname (argv0);
+       if (chdir (dir) < 0)
+               g_warning ("couldn't change directory to: %s: %s",
+                          dir, g_strerror (errno));
+
+       base = g_path_get_basename (dir);
+       if (strcmp (base, ".libs") == 0) {
+               if (chdir ("..") < 0)
+                       g_warning ("couldn't change directory to ..: %s",
+                                  g_strerror (errno));
+       }
+
+       g_free (base);
+       g_free (dir);
+}
+
+static void
+on_parser_parsed (GcrParser *parser, gpointer user_data)
+{
+       GcrSimpleCollection *collection = user_data;
+       GcrRenderer *renderer;
+
+       renderer = gcr_renderer_create (gcr_parser_get_parsed_label (parser),
+                                       gcr_parser_get_parsed_attributes (parser));
+
+       if (renderer) {
+               gcr_simple_collection_add (collection, G_OBJECT (renderer));
+               g_object_unref (renderer);
+       }
+}
+
+static void
+add_to_selector (GcrParser *parser, const gchar *path)
+{
+       GError *err = NULL;
+       guchar *data;
+       gsize n_data;
+
+       if (!g_file_get_contents (path, (gchar**)&data, &n_data, NULL))
+               g_error ("couldn't read file: %s", path);
+
+       if (!gcr_parser_parse_data (parser, data, n_data, &err))
+               g_error ("couldn't parse data: %s", err->message);
+
+       g_free (data);
+}
+
+int
+main (int argc, char *argv[])
+{
+       GcrCollectionModel *model;
+       GcrCollection *collection;
+       GtkDialog *dialog;
+       GtkWidget *combo;
+       GtkCellRenderer *cell;
+       GcrParser *parser;
+       int i;
+
+       gtk_init (&argc, &argv);
+
+       dialog = GTK_DIALOG (gtk_dialog_new ());
+       g_object_ref_sink (dialog);
+
+       collection = gcr_simple_collection_new ();
+       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);
+
+#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_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);
+
+       if (argc == 1) {
+               chdir_base_dir (argv[0]);
+               add_to_selector (parser, "test-data/ca-certificates.crt");
+       } else {
+               for (i = 1; i < argc; ++i)
+                       add_to_selector (parser, argv[i]);
+       }
+
+       g_object_unref (parser);
+
+       gtk_dialog_run (dialog);
+       gtk_widget_destroy (GTK_WIDGET (dialog));
+
+       g_object_unref (dialog);
+
+       return 0;
+}