[gnome-keyring/selector: 3/5] [gcr] Add functionality for renderers to populate tree models.



commit d00b64b06be24c7defb4d5cad273129eff7d5778
Author: Stef Walter <stef memberwebs com>
Date:   Fri Oct 15 03:17:29 2010 +0000

    [gcr] Add functionality for renderers to populate tree models.
    
     * Add markup, icon and description properties to renderers.
     * Add GcrSimpleCollection which implements collections.
     * Use GIcon instead of stock ids.
     * Rough example test certificate selector.

 gcr/Makefile.am                |    2 +
 gcr/gcr-certificate-renderer.c |   63 ++++++++++++++----
 gcr/gcr-collection-model.c     |    4 +-
 gcr/gcr-display-view.c         |   44 ++++++++++---
 gcr/gcr-display-view.h         |    4 +-
 gcr/gcr-key-renderer.c         |   12 +++-
 gcr/gcr-library.c              |    8 ++-
 gcr/gcr-renderer.c             |   18 ++++-
 gcr/gcr-renderer.h             |   21 +++++-
 gcr/gcr-simple-collection.c    |  143 ++++++++++++++++++++++++++++++++++++++++
 gcr/gcr-simple-collection.h    |   67 +++++++++++++++++++
 gcr/tests/.gitignore           |    1 +
 gcr/tests/Makefile.am          |   43 ++----------
 gcr/tests/test-ui-selector.c   |  131 ++++++++++++++++++++++++++++++++++++
 14 files changed, 492 insertions(+), 69 deletions(-)
---
diff --git a/gcr/Makefile.am b/gcr/Makefile.am
index a777d2a..7a2113d 100644
--- a/gcr/Makefile.am
+++ b/gcr/Makefile.am
@@ -26,6 +26,7 @@ inc_HEADERS = \
 	gcr-parser.h \
 	gcr-renderer.h \
 	gcr-simple-certificate.h \
+	gcr-simple-collection.h \
 	gcr-types.h \
 	gcr-unlock-options.h \
 	gcr-unlock-options-widget.h \
@@ -65,6 +66,7 @@ libgcr GCR_VERSION_SUFFIX@_la_SOURCES = \
 	gcr-parser.c gcr-parser.h \
 	gcr-renderer.c gcr-renderer.h \
 	gcr-simple-certificate.c gcr-simple-certificate.h \
+	gcr-simple-collection.c gcr-simple-collection.h \
 	gcr-types.h \
 	gcr-unlock-options.h \
 	gcr-unlock-options-widget.c gcr-unlock-options-widget.h \
diff --git a/gcr/gcr-certificate-renderer.c b/gcr/gcr-certificate-renderer.c
index 512becd..be55a29 100644
--- a/gcr/gcr-certificate-renderer.c
+++ b/gcr/gcr-certificate-renderer.c
@@ -41,7 +41,10 @@ enum {
 	PROP_0,
 	PROP_CERTIFICATE,
 	PROP_LABEL,
-	PROP_ATTRIBUTES
+	PROP_ATTRIBUTES,
+	PROP_DESCRIPTION,
+	PROP_ICON,
+	PROP_MARKUP
 };
 
 struct _GcrCertificateRendererPrivate {
@@ -49,6 +52,7 @@ struct _GcrCertificateRendererPrivate {
 	GckAttributes *opt_attrs;
 	guint key_size;
 	gchar *label;
+	GIcon *icon;
 };
 
 static void gcr_renderer_iface_init (GcrRendererIface *iface);
@@ -63,7 +67,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;
 
@@ -75,15 +79,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)
@@ -184,6 +206,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
@@ -212,6 +235,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);
 }
 
@@ -251,11 +278,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;
@@ -282,6 +318,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 ();
 
@@ -324,16 +363,16 @@ gcr_certificate_renderer_real_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);
 
@@ -465,7 +504,7 @@ gcr_certificate_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 static void
 gcr_renderer_iface_init (GcrRendererIface *iface)
 {
-	iface->render = gcr_certificate_renderer_real_render;
+	iface->render_view = gcr_certificate_renderer_real_render;
 }
 
 
diff --git a/gcr/gcr-collection-model.c b/gcr/gcr-collection-model.c
index 4be857c..1eac064 100644
--- a/gcr/gcr-collection-model.c
+++ b/gcr/gcr-collection-model.c
@@ -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;
 }
diff --git a/gcr/gcr-display-view.c b/gcr/gcr-display-view.c
index 3f0807d..10001c0 100644
--- a/gcr/gcr-display-view.c
+++ b/gcr/gcr-display-view.c
@@ -130,7 +130,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));
 }
 
 static void
@@ -256,7 +256,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
@@ -495,7 +495,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);
 }
@@ -766,19 +766,45 @@ _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;
+	GtkStyle *style;
 
 	g_return_if_fail (GCR_IS_DISPLAY_VIEW (self));
 	item = lookup_display_item (self, renderer);
 	g_return_if_fail (item);
 
-	if (item->pixbuf)
+	if (item->pixbuf) {
 		g_object_unref (item->pixbuf);
-	if (stock_id)
-		item->pixbuf = gtk_widget_render_icon (GTK_WIDGET (self), stock_id, GTK_ICON_SIZE_DIALOG, NULL);
-	else
 		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) {
+		style = gtk_widget_get_style (GTK_WIDGET (self));
+#if GTK_CHECK_VERSION (2,91,0)
+		item->pixbuf = gtk_icon_info_load_symbolic_for_style (info, style, GTK_STATE_NORMAL, NULL, NULL);
+#else
+		item->pixbuf = gtk_icon_info_load_icon (info, NULL);
+#endif
+		gtk_icon_info_free (info);
+	}
 }
diff --git a/gcr/gcr-display-view.h b/gcr/gcr-display-view.h
index c5f83a6..be237bb 100644
--- a/gcr/gcr-display-view.h
+++ b/gcr/gcr-display-view.h
@@ -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
 
diff --git a/gcr/gcr-key-renderer.c b/gcr/gcr-key-renderer.c
index 3b7bc9a..daf4f48 100644
--- a/gcr/gcr-key-renderer.c
+++ b/gcr/gcr-key-renderer.c
@@ -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;
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/gcr/gcr-library.c b/gcr/gcr-library.c
index 1aa413b..53d529f 100644
--- a/gcr/gcr-library.c
+++ b/gcr/gcr-library.c
@@ -22,8 +22,10 @@
 #include "config.h"
 
 #include "gcr.h"
-#include "gcr-types.h"
+#include "gcr-certificate-renderer.h"
 #include "gcr-internal.h"
+#include "gcr-key-renderer.h"
+#include "gcr-types.h"
 
 #include "egg/egg-error.h"
 #include "egg/egg-libgcrypt.h"
@@ -120,6 +122,10 @@ _gcr_initialize (void)
 
 	if (g_once_init_enter (&gcr_initialized)) {
 		all_modules = gck_modules_initialize_registered (0);
+
+		g_type_class_unref (g_type_class_ref (GCR_TYPE_CERTIFICATE_RENDERER));
+		g_type_class_unref (g_type_class_ref (GCR_TYPE_KEY_RENDERER));
+
 		g_once_init_leave (&gcr_initialized, 1);
 	}
 }
diff --git a/gcr/gcr-renderer.c b/gcr/gcr-renderer.c
index 59ca30a..37434f1 100644
--- a/gcr/gcr-renderer.c
+++ b/gcr/gcr-renderer.c
@@ -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
diff --git a/gcr/gcr-renderer.h b/gcr/gcr-renderer.h
index 9c4800a..1ce6688 100644
--- a/gcr/gcr-renderer.h
+++ b/gcr/gcr-renderer.h
@@ -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);
 
 	gpointer dummy1;
 	gpointer dummy2;
@@ -55,11 +60,23 @@ 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);
 
+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
index 0000000..b88467a
--- /dev/null
+++ b/gcr/gcr-simple-collection.c
@@ -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
index 0000000..beccb0b
--- /dev/null
+++ b/gcr/gcr-simple-collection.h
@@ -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__ */
diff --git a/gcr/tests/.gitignore b/gcr/tests/.gitignore
index 652f4c0..f30fd7b 100644
--- a/gcr/tests/.gitignore
+++ b/gcr/tests/.gitignore
@@ -2,3 +2,4 @@
 /ui-test-details
 /ui-test-key
 /ui-test-unlock-options
+/test-ui-selector
diff --git a/gcr/tests/Makefile.am b/gcr/tests/Makefile.am
index 1ef2396..7d37d02 100644
--- a/gcr/tests/Makefile.am
+++ b/gcr/tests/Makefile.am
@@ -21,46 +21,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
\ No newline at end of file
diff --git a/gcr/tests/test-ui-selector.c b/gcr/tests/test-ui-selector.c
new file mode 100644
index 0000000..935528e
--- /dev/null
+++ b/gcr/tests/test-ui-selector.c
@@ -0,0 +1,131 @@
+
+#include "config.h"
+
+#include "gcr-renderer.h"
+#include "gcr-simple-collection.h"
+#include "gcr-collection-model.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;
+}



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