[gnome-keyring] [gcr] Add collection iface for objects lists and GtkTreeModel
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring] [gcr] Add collection iface for objects lists and GtkTreeModel
- Date: Tue, 5 Apr 2011 13:11:54 +0000 (UTC)
commit 8917f27be36d0bb1e9ba4f224a17461edf5251e5
Author: Stef Walter <stef memberwebs com>
Date: Wed Oct 6 18:42:18 2010 +0000
[gcr] Add collection iface for objects lists and GtkTreeModel
Will be used in various selectors to provide a list of things
to select from.
gcr/Makefile.am | 6 +-
gcr/gcr-collection-model.c | 643 ++++++++++++++++++++++++++++++++++++++++++++
gcr/gcr-collection-model.h | 76 ++++++
gcr/gcr-collection.c | 128 +++++++++
gcr/gcr-collection.h | 75 +++++
5 files changed, 927 insertions(+), 1 deletions(-)
---
diff --git a/gcr/Makefile.am b/gcr/Makefile.am
index 630157a..5f4aad1 100644
--- a/gcr/Makefile.am
+++ b/gcr/Makefile.am
@@ -33,6 +33,8 @@ inc_HEADERS = \
gcr-certificate-details-widget.h \
gcr-certificate-renderer.h \
gcr-certificate-widget.h \
+ gcr-collection.h \
+ gcr-collection-model.h \
gcr-key-renderer.h \
gcr-key-widget.h \
gcr-importer.h \
@@ -70,6 +72,8 @@ libgcr GCR_VERSION_SUFFIX@_la_SOURCES = \
gcr-certificate-renderer.c gcr-certificate-renderer.h \
gcr-certificate-exporter.c gcr-certificate-exporter.h \
gcr-certificate-widget.c gcr-certificate-widget.h \
+ gcr-collection.c gcr-collection.h \
+ gcr-collection-model.c gcr-collection-model.h \
gcr-display-scrolled.c gcr-display-scrolled.h \
gcr-display-view.c gcr-display-view.h \
gcr-icons.c gcr-icons.h \
@@ -136,4 +140,4 @@ CLEANFILES = \
$(pkgconfig_DATA)
DISTCLEANFILES = \
- $(pkgconfig_DATA)
\ No newline at end of file
+ $(pkgconfig_DATA)
diff --git a/gcr/gcr-collection-model.c b/gcr/gcr-collection-model.c
new file mode 100644
index 0000000..4be857c
--- /dev/null
+++ b/gcr/gcr-collection-model.c
@@ -0,0 +1,643 @@
+/*
+ * 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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gcr-collection-model.h"
+
+#include <string.h>
+
+enum {
+ PROP_0,
+ PROP_COLLECTION
+};
+
+struct _GcrCollectionModelPrivate {
+ GcrCollection *collection;
+ GHashTable *object_to_index;
+
+ gint cache_stamp;
+ gint last_stamp;
+
+ GPtrArray *objects;
+
+ gchar **column_names;
+ guint n_columns;
+ GType *column_types;
+};
+
+/* Forward declarations */
+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));
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static gint
+index_for_iter (GcrCollectionModel *self, const GtkTreeIter *iter)
+{
+ gint index;
+
+ g_return_val_if_fail (iter, -1);
+ g_return_val_if_fail (iter->stamp == self->pv->last_stamp, -1);
+ 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);
+ return index;
+}
+
+static gboolean
+iter_for_index (GcrCollectionModel *self, gint index, GtkTreeIter *iter)
+{
+ GObject *object;
+
+ if (index < 0 || index >= self->pv->objects->len)
+ return FALSE;
+
+ object = g_ptr_array_index (self->pv->objects, index);
+ g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
+
+ memset (iter, 0, sizeof (*iter));
+ iter->stamp = self->pv->last_stamp;
+ iter->user_data = object;
+ iter->user_data2 = GINT_TO_POINTER (index);
+ return TRUE;
+}
+
+static gint
+index_for_object (GcrCollectionModel *self, GObject *object)
+{
+ gpointer value;
+ guint i;
+
+ /* Build the index if not valid */
+ if (self->pv->cache_stamp != self->pv->last_stamp) {
+ g_hash_table_remove_all (self->pv->object_to_index);
+ for (i = 0; i < self->pv->objects->len; ++i) {
+ g_hash_table_insert (self->pv->object_to_index,
+ g_ptr_array_index (self->pv->objects, i),
+ GUINT_TO_POINTER (i));
+ }
+ self->pv->cache_stamp = self->pv->last_stamp;
+ }
+
+ if (!g_hash_table_lookup_extended (self->pv->object_to_index, object, NULL, &value))
+ return -1;
+
+ return GPOINTER_TO_INT (value);
+}
+
+static void
+on_object_notify (GObject *object, GParamSpec *spec, GcrCollectionModel *self)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ guint i;
+
+ g_return_if_fail (spec->name);
+
+ for (i = 0; i < self->pv->n_columns; ++i) {
+ g_assert (self->pv->column_names[i]);
+ if (g_str_equal (self->pv->column_names[i], spec->name)) {
+ if (!gcr_collection_model_iter_for_object (self, object, &iter))
+ g_return_if_reached ();
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (self), &iter);
+ g_return_if_fail (path);
+
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (self), path, &iter);
+ gtk_tree_path_free (path);
+
+ return;
+ }
+ }
+}
+
+static void
+on_object_gone (gpointer unused, GObject *was_object)
+{
+ g_warning ("object contained in GcrCollection and included in GcrCollectionModel "
+ "was destroyed before it was removed from the collection");
+}
+
+static gint
+add_object (GcrCollectionModel *self, GObject *object)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ gint index;
+
+ g_assert (GCR_IS_COLLECTION_MODEL (self));
+ g_assert (G_IS_OBJECT (object));
+
+ index = self->pv->objects->len;
+
+ g_ptr_array_add (self->pv->objects, object);
+ g_object_weak_ref (G_OBJECT (object), (GWeakNotify)on_object_gone, self);
+ g_signal_connect (object, "notify", G_CALLBACK (on_object_notify), self);
+
+ self->pv->last_stamp++;
+
+ /* Fire signal for this added row */
+ if (!iter_for_index (self, self->pv->objects->len - 1, &iter))
+ g_assert_not_reached ();
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (self), &iter);
+ g_return_val_if_fail (path, -1);
+
+ gtk_tree_model_row_inserted (GTK_TREE_MODEL (self), path, &iter);
+ gtk_tree_path_free (path);
+
+ return index;
+}
+
+static void
+disconnect_object (GcrCollectionModel *self, GObject *object)
+{
+ g_object_weak_unref (G_OBJECT (object), on_object_gone, self);
+ g_signal_handlers_disconnect_by_func (object, on_object_notify, self);
+}
+
+static void
+remove_object (GcrCollectionModel *self, gint index, GObject *object)
+{
+ GtkTreePath *path;
+
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, index);
+
+ disconnect_object (self, object);
+ g_assert (g_ptr_array_index (self->pv->objects, index) == object);
+ g_ptr_array_remove_index (self->pv->objects, index);
+
+ self->pv->last_stamp++;
+
+ /* Fire signal for this removed row */
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (self), path);
+ gtk_tree_path_free (path);
+}
+
+static void
+on_collection_added (GcrCollection *collection, GObject *object, GcrCollectionModel *self)
+{
+ g_return_if_fail (GCR_COLLECTION_MODEL (self));
+ g_return_if_fail (G_IS_OBJECT (object));
+
+ add_object (self, object);
+}
+
+static void
+on_collection_removed (GcrCollection *collection, GObject *object,
+ GcrCollectionModel *self)
+{
+ gint index;
+
+ g_return_if_fail (GCR_COLLECTION_MODEL (self));
+ g_return_if_fail (G_IS_OBJECT (object));
+
+ index = index_for_object (self, object);
+ g_return_if_fail (index < 0);
+
+ remove_object (self, index, object);
+}
+
+static void
+populate_model (GcrCollectionModel *self)
+{
+ GList *objects, *l;
+ objects = gcr_collection_get_objects (self->pv->collection);
+ for (l = objects; l; l = g_list_next (l))
+ on_collection_added (self->pv->collection, G_OBJECT (l->data), self);
+ g_list_free (objects);
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static GtkTreeModelFlags
+gcr_collection_model_real_get_flags (GtkTreeModel *model)
+{
+ /* TODO: Maybe we can eventually GTK_TREE_MODEL_ITERS_PERSIST */
+ return 0;
+}
+
+static gint
+gcr_collection_model_real_get_n_columns (GtkTreeModel *model)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (model);
+ return self->pv->n_columns;
+}
+
+static GType
+gcr_collection_model_real_get_column_type (GtkTreeModel *model, gint index)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (model);
+ g_return_val_if_fail (index >= 0 && index < self->pv->n_columns, 0);
+ return self->pv->column_types[index];
+}
+
+static gboolean
+gcr_collection_model_real_get_iter (GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (model);
+ const gint *indices;
+ gint count;
+
+ count = gtk_tree_path_get_depth (path);
+ if (count != 1)
+ return FALSE;
+
+ indices = gtk_tree_path_get_indices (path);
+ return iter_for_index (self, indices[0], iter);
+}
+
+static GtkTreePath*
+gcr_collection_model_real_get_path (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (model);
+ GtkTreePath *path;
+ gint index;
+
+ index = index_for_iter (self, iter);
+ g_return_val_if_fail (index >= 0, NULL);
+
+ path = gtk_tree_path_new ();
+ gtk_tree_path_prepend_index (path, index);
+ return path;
+}
+
+static void
+gcr_collection_model_real_get_value (GtkTreeModel *model, GtkTreeIter *iter,
+ gint column, GValue *value)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (model);
+ const gchar *property;
+ GParamSpec *spec;
+ GObject *object;
+ GValue original;
+ GType type;
+
+ object = gcr_collection_model_object_for_iter (self, iter);
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (column >= 0 && column < self->pv->n_columns);
+
+ /* Figure out which property */
+ type = self->pv->column_types[column];
+ property = self->pv->column_names[column];
+ g_assert (property);
+ g_value_init (value, type);
+
+ /* Lookup the property on the object */
+ spec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property);
+ if (spec) {
+
+ /* Simple, no transformation necessary */
+ if (spec->value_type == type) {
+ g_object_get_property (object, property, value);
+
+ /* Not the same type, try to transform */
+ } else {
+
+ memset (&original, 0, sizeof (original));
+ g_value_init (&original, spec->value_type);
+
+ g_object_get_property (object, property, &original);
+ if (!g_value_transform (&original, value)) {
+ g_warning ("%s property of %s class was of type %s instead of type %s"
+ " and cannot be converted", property, G_OBJECT_TYPE_NAME (object),
+ g_type_name (spec->value_type), g_type_name (type));
+ spec = NULL;
+ }
+ }
+ }
+
+ /* No property present */
+ if (spec == NULL) {
+
+ /* All the number types have sane defaults */
+ if (type == G_TYPE_STRING)
+ g_value_set_string (value, "");
+ }
+}
+
+static gboolean
+gcr_collection_model_real_iter_next (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (model);
+ gint index;
+
+ index = index_for_iter (self, iter);
+ g_return_val_if_fail (index >= 0, FALSE);
+
+ return iter_for_index (self, index + 1, iter);
+}
+
+static gboolean
+gcr_collection_model_real_iter_children (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *parent)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (model);
+
+ if (parent != NULL)
+ return FALSE;
+
+ return iter_for_index (self, 0, iter);
+}
+
+static gboolean
+gcr_collection_model_real_iter_has_child (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (model);
+ if (iter == NULL)
+ return self->pv->objects->len > 0;
+ return FALSE;
+}
+
+static gint
+gcr_collection_model_real_iter_n_children (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (model);
+ if (iter == NULL)
+ return self->pv->objects->len;
+ return 0;
+}
+
+static gboolean
+gcr_collection_model_real_iter_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
+ GtkTreeIter *parent, gint n)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (model);
+ if (parent != NULL)
+ return FALSE;
+ return iter_for_index (self, n, iter);
+}
+
+static gboolean
+gcr_collection_model_real_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child)
+{
+ return FALSE;
+}
+
+static void
+gcr_collection_model_real_ref_node (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ /* Nothing to do */
+}
+
+static void
+gcr_collection_model_real_unref_node (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ /* Nothing to do */
+}
+
+static void
+gcr_collection_model_tree_model (GtkTreeModelIface *iface)
+{
+ iface->get_flags = gcr_collection_model_real_get_flags;
+ iface->get_n_columns = gcr_collection_model_real_get_n_columns;
+ iface->get_column_type = gcr_collection_model_real_get_column_type;
+ iface->get_iter = gcr_collection_model_real_get_iter;
+ iface->get_path = gcr_collection_model_real_get_path;
+ iface->get_value = gcr_collection_model_real_get_value;
+ iface->iter_next = gcr_collection_model_real_iter_next;
+ iface->iter_children = gcr_collection_model_real_iter_children;
+ iface->iter_has_child = gcr_collection_model_real_iter_has_child;
+ iface->iter_n_children = gcr_collection_model_real_iter_n_children;
+ iface->iter_nth_child = gcr_collection_model_real_iter_nth_child;
+ iface->iter_parent = gcr_collection_model_real_iter_parent;
+ iface->ref_node = gcr_collection_model_real_ref_node;
+ iface->unref_node = gcr_collection_model_real_unref_node;
+}
+
+static void
+gcr_collection_model_init (GcrCollectionModel *self)
+{
+ self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_COLLECTION_MODEL, GcrCollectionModelPrivate);
+
+ self->pv->object_to_index = g_hash_table_new (g_direct_hash, g_direct_equal);
+ self->pv->objects = g_ptr_array_new ();
+ self->pv->column_names = NULL;
+ self->pv->n_columns = 0;
+ self->pv->column_types = NULL;
+ self->pv->last_stamp = 0x1000;
+}
+
+static void
+gcr_collection_model_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (object);
+
+ switch (prop_id) {
+ case PROP_COLLECTION:
+ g_return_if_fail (self->pv->collection == NULL);
+ self->pv->collection = g_value_dup_object (value);
+ if (self->pv->collection) {
+ g_signal_connect_after (self->pv->collection, "added", G_CALLBACK (on_collection_added), self);
+ g_signal_connect_after (self->pv->collection, "removed", G_CALLBACK (on_collection_removed), self);
+ populate_model (self);
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gcr_collection_model_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (object);
+
+ switch (prop_id) {
+ case PROP_COLLECTION:
+ g_value_set_object (value, self->pv->collection);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gcr_collection_model_dispose (GObject *object)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (object);
+ GObject *obj;
+ guint i;
+
+ /* 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 from the collection */
+ if (self->pv->collection) {
+ g_signal_handlers_disconnect_by_func (self->pv->collection, on_collection_added, self);
+ g_signal_handlers_disconnect_by_func (self->pv->collection, on_collection_removed, self);
+ g_object_unref (self->pv->collection);
+ self->pv->collection = NULL;
+ }
+
+ G_OBJECT_CLASS (gcr_collection_model_parent_class)->dispose (object);
+}
+
+static void
+gcr_collection_model_finalize (GObject *object)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (object);
+
+ g_assert (!self->pv->collection);
+
+ g_assert (self->pv->object_to_index);
+ g_assert (g_hash_table_size (self->pv->object_to_index) == 0);
+ g_hash_table_destroy (self->pv->object_to_index);
+ self->pv->object_to_index = NULL;
+
+ g_assert (self->pv->objects);
+ g_ptr_array_free (self->pv->objects, TRUE);
+ self->pv->objects = NULL;
+
+ if (self->pv->column_names) {
+ g_strfreev (self->pv->column_names);
+ self->pv->column_names = NULL;
+ self->pv->n_columns = 0;
+ }
+
+ if (self->pv->column_types) {
+ g_free (self->pv->column_types);
+ self->pv->column_types = NULL;
+ }
+
+ G_OBJECT_CLASS (gcr_collection_model_parent_class)->finalize (object);
+}
+
+static void
+gcr_collection_model_class_init (GcrCollectionModelClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ gcr_collection_model_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->dispose = gcr_collection_model_dispose;
+ gobject_class->finalize = gcr_collection_model_finalize;
+ gobject_class->set_property = gcr_collection_model_set_property;
+ gobject_class->get_property = gcr_collection_model_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_COLLECTION,
+ g_param_spec_object ("collection", "Object Collection", "Collection to get objects from",
+ GCR_TYPE_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (klass, sizeof (GcrCollectionModelPrivate));
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+GcrCollectionModel*
+gcr_collection_model_new (GcrCollection *collection, ...)
+{
+ GcrCollectionModelColumn column;
+ GcrCollectionModel *self;
+ const gchar *arg;
+ GArray *array;
+ va_list va;
+
+ array = g_array_new (TRUE, TRUE, sizeof (GcrCollectionModelColumn));
+
+ va_start (va, collection);
+ while ((arg = va_arg (va, const gchar*)) != NULL) {
+ column.property = arg;
+ column.type = va_arg (va, GType);
+ column.data = NULL;
+ g_array_append_val (array, column);
+ }
+ va_end (va);
+
+ self = gcr_collection_model_new_full (collection, (GcrCollectionModelColumn*)array->data, array->len);
+ g_array_free (array, TRUE);
+ return self;
+}
+
+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);
+ gcr_collection_model_set_columns (self, columns, n_columns);
+ return self;
+}
+
+gint
+gcr_collection_model_set_columns (GcrCollectionModel *self, const GcrCollectionModelColumn *columns,
+ guint n_columns)
+{
+ guint i;
+
+ g_return_val_if_fail (GCR_IS_COLLECTION_MODEL (self), -1);
+ g_return_val_if_fail (self->pv->n_columns == 0, -1);
+
+ 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) {
+ self->pv->column_names[i] = g_strdup (columns[i].property);
+ self->pv->column_types[i] = columns[i].type;
+ }
+
+ return n_columns - 1;
+}
+
+GObject*
+gcr_collection_model_object_for_iter (GcrCollectionModel *self, const GtkTreeIter *iter)
+{
+ g_return_val_if_fail (GCR_IS_COLLECTION_MODEL (self), NULL);
+ g_return_val_if_fail (iter, NULL);
+ g_return_val_if_fail (iter->stamp == self->pv->last_stamp, NULL);
+ g_return_val_if_fail (G_IS_OBJECT (iter->user_data), NULL);
+
+ return G_OBJECT (iter->user_data);
+}
+
+gboolean
+gcr_collection_model_iter_for_object (GcrCollectionModel *self, GObject *object,
+ GtkTreeIter *iter)
+{
+ gint index;
+
+ g_return_val_if_fail (GCR_IS_COLLECTION_MODEL (self), FALSE);
+ g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
+ g_return_val_if_fail (iter, FALSE);
+
+ index = index_for_object (self, object);
+ if (index < 0)
+ return FALSE;
+
+ return iter_for_index (self, index, iter);
+}
diff --git a/gcr/gcr-collection-model.h b/gcr/gcr-collection-model.h
new file mode 100644
index 0000000..60a5754
--- /dev/null
+++ b/gcr/gcr-collection-model.h
@@ -0,0 +1,76 @@
+/*
+ * 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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GCR_COLLECTION_MODEL_H__
+#define __GCR_COLLECTION_MODEL_H__
+
+#include <gtk/gtk.h>
+
+#include "gcr-collection.h"
+
+typedef struct _GcrCollectionModelColumn {
+ const gchar *property;
+ GType type;
+ gpointer data;
+} GcrCollectionModelColumn;
+
+#define GCR_TYPE_COLLECTION_MODEL (gcr_collection_model_get_type ())
+#define GCR_COLLECTION_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_COLLECTION_MODEL, GcrCollectionModel))
+#define GCR_COLLECTION_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_COLLECTION_MODEL, GcrCollectionModelClass))
+#define GCR_IS_COLLECTION_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_COLLECTION_MODEL))
+#define GCR_IS_COLLECTION_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_COLLECTION_MODEL))
+#define GCR_COLLECTION_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_COLLECTION_MODEL, GcrCollectionModelClass))
+
+typedef struct _GcrCollectionModel GcrCollectionModel;
+typedef struct _GcrCollectionModelClass GcrCollectionModelClass;
+typedef struct _GcrCollectionModelPrivate GcrCollectionModelPrivate;
+
+struct _GcrCollectionModel {
+ GObject parent;
+
+ GcrCollectionModelPrivate *pv;
+};
+
+struct _GcrCollectionModelClass {
+ GObjectClass parent_class;
+};
+
+GType gcr_collection_model_get_type (void);
+
+GcrCollectionModel* gcr_collection_model_new (GcrCollection *collection,
+ ...) G_GNUC_NULL_TERMINATED;
+
+GcrCollectionModel* gcr_collection_model_new_full (GcrCollection *collection,
+ const GcrCollectionModelColumn *columns,
+ guint n_columns);
+
+gint gcr_collection_model_set_columns (GcrCollectionModel *self,
+ const GcrCollectionModelColumn *columns,
+ guint n_columns);
+
+GObject* gcr_collection_model_object_for_iter (GcrCollectionModel *self,
+ const GtkTreeIter *iter);
+
+gboolean gcr_collection_model_iter_for_object (GcrCollectionModel *self,
+ GObject *object,
+ GtkTreeIter *iter);
+
+#endif /* __GCR_COLLECTION_MODEL_H__ */
diff --git a/gcr/gcr-collection.c b/gcr/gcr-collection.c
new file mode 100644
index 0000000..e7f962d
--- /dev/null
+++ b/gcr/gcr-collection.c
@@ -0,0 +1,128 @@
+/*
+ * 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"
+
+/**
+ * SECTION:gcr-collection
+ * @title: GcrCollection
+ * @short_description: A collection of objects.
+ *
+ * Xxxxx
+ */
+
+enum {
+ ADDED,
+ REMOVED,
+ LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+/* ---------------------------------------------------------------------------------
+ * INTERFACE
+ */
+
+static void
+gcr_collection_base_init (gpointer g_class)
+{
+ static volatile gsize initialized = 0;
+
+ if (g_once_init_enter (&initialized)) {
+
+ signals[ADDED] = g_signal_new ("added", GCR_TYPE_COLLECTION,
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcrCollectionIface, added),
+ NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+ signals[REMOVED] = g_signal_new ("removed", GCR_TYPE_COLLECTION,
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcrCollectionIface, removed),
+ NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+ g_once_init_leave (&initialized, 1);
+ }
+}
+
+GType
+gcr_collection_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (GcrCollectionIface),
+ gcr_collection_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, "GcrCollectionIface", &info, 0);
+ g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+ }
+
+ return type;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+
+guint
+gcr_collection_get_length (GcrCollection *self)
+{
+ g_return_val_if_fail (GCR_IS_COLLECTION (self), 0);
+ g_return_val_if_fail (GCR_COLLECTION_GET_INTERFACE (self)->get_length, 0);
+ return GCR_COLLECTION_GET_INTERFACE (self)->get_length (self);
+}
+
+GList*
+gcr_collection_get_objects (GcrCollection *self)
+{
+ g_return_val_if_fail (GCR_IS_COLLECTION (self), 0);
+ g_return_val_if_fail (GCR_COLLECTION_GET_INTERFACE (self)->get_objects, 0);
+ return GCR_COLLECTION_GET_INTERFACE (self)->get_objects (self);
+}
+
+void
+gcr_collection_emit_added (GcrCollection *self, GObject *object)
+{
+ g_return_if_fail (GCR_IS_COLLECTION (self));
+ g_signal_emit (self, signals[ADDED], 0, object);
+}
+
+void
+gcr_collection_emit_removed (GcrCollection *self, GObject *object)
+{
+ g_return_if_fail (GCR_IS_COLLECTION (self));
+ g_signal_emit (self, signals[REMOVED], 0, object);
+}
diff --git a/gcr/gcr-collection.h b/gcr/gcr-collection.h
new file mode 100644
index 0000000..e00bcd4
--- /dev/null
+++ b/gcr/gcr-collection.h
@@ -0,0 +1,75 @@
+/*
+ * 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_COLLECTION_H__
+#define __GCR_COLLECTION_H__
+
+#include "gcr-types.h"
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GCR_TYPE_COLLECTION (gcr_collection_get_type())
+#define GCR_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_COLLECTION, GcrCollection))
+#define GCR_IS_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_COLLECTION))
+#define GCR_COLLECTION_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GCR_TYPE_COLLECTION, GcrCollectionIface))
+
+typedef struct _GcrCollection GcrCollection;
+typedef struct _GcrCollectionIface GcrCollectionIface;
+
+struct _GcrCollectionIface {
+ GTypeInterface parent;
+
+ /* signals */
+ void (*added) (GcrCollection *self, GObject *object);
+
+ void (*removed) (GcrCollection *self, GObject *object);
+
+ /* virtual */
+ guint (*get_length) (GcrCollection *self);
+
+ GList* (*get_objects) (GcrCollection *self);
+
+ gpointer dummy1;
+ gpointer dummy2;
+ gpointer dummy3;
+ gpointer dummy5;
+ gpointer dummy6;
+ gpointer dummy7;
+ gpointer dummy8;
+};
+
+GType gcr_collection_get_type (void);
+
+guint gcr_collection_get_length (GcrCollection *self);
+
+GList* gcr_collection_get_objects (GcrCollection *self);
+
+void gcr_collection_emit_added (GcrCollection *self,
+ GObject *object);
+
+void gcr_collection_emit_removed (GcrCollection *self,
+ GObject *object);
+
+G_END_DECLS
+
+#endif /* __GCR_COLLECTION_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]