diff options
-rw-r--r-- | docs/reference/gcr/gcr-sections.txt | 23 | ||||
-rw-r--r-- | gcr/Makefile.am | 2 | ||||
-rw-r--r-- | gcr/gcr-collection.c | 1 | ||||
-rw-r--r-- | gcr/gcr-union-collection.c | 307 | ||||
-rw-r--r-- | gcr/gcr-union-collection.h | 71 | ||||
-rw-r--r-- | gcr/gcr.h | 1 |
6 files changed, 403 insertions, 2 deletions
diff --git a/docs/reference/gcr/gcr-sections.txt b/docs/reference/gcr/gcr-sections.txt index ee7bd91d..7019ad3d 100644 --- a/docs/reference/gcr/gcr-sections.txt +++ b/docs/reference/gcr/gcr-sections.txt @@ -246,10 +246,10 @@ GcrCollectionIface <FILE>gcr-simple-collection</FILE> GcrSimpleCollection GcrSimpleCollectionClass -gcr_simple_collection_add -gcr_simple_collection_contains gcr_simple_collection_new +gcr_simple_collection_add gcr_simple_collection_remove +gcr_simple_collection_contains <SUBSECTION Standard> gcr_simple_collection_get_type GCR_IS_SIMPLE_COLLECTION @@ -262,6 +262,25 @@ GcrSimpleCollectionPrivate </SECTION> <SECTION> +<FILE>gcr-union-collection</FILE> +GcrUnionCollection +GcrUnionCollectionClass +gcr_union_collection_new +gcr_union_collection_add +gcr_union_collection_take +gcr_union_collection_remove +<SUBSECTION Standard> +GCR_IS_UNION_COLLECTION +GCR_IS_UNION_COLLECTION_CLASS +GCR_TYPE_UNION_COLLECTION +GCR_UNION_COLLECTION +GCR_UNION_COLLECTION_CLASS +GCR_UNION_COLLECTION_GET_CLASS +GcrUnionCollectionPrivate +gcr_union_collection_get_type +</SECTION> + +<SECTION> <FILE>gcr-collection-model</FILE> GcrCollectionModel GcrCollectionModelClass diff --git a/gcr/Makefile.am b/gcr/Makefile.am index 05d23fc6..d1b2d47c 100644 --- a/gcr/Makefile.am +++ b/gcr/Makefile.am @@ -49,6 +49,7 @@ HEADER_FILES = \ gcr-tree-selector.h \ gcr-trust.h \ gcr-types.h \ + gcr-union-collection.h \ gcr-unlock-options.h \ gcr-unlock-options-widget.h \ gcr-viewer.h \ @@ -122,6 +123,7 @@ libgcr_@GCR_MAJOR@_la_SOURCES = \ gcr-tree-selector.c gcr-tree-selector.h \ gcr-trust.c gcr-trust.h \ gcr-types.h \ + gcr-union-collection.c \ gcr-unlock-options.h \ gcr-unlock-options-widget.c gcr-unlock-options-widget.h \ gcr-unlock-renderer.c gcr-unlock-renderer.h \ diff --git a/gcr/gcr-collection.c b/gcr/gcr-collection.c index aa7a60f7..61b75cca 100644 --- a/gcr/gcr-collection.c +++ b/gcr/gcr-collection.c @@ -144,6 +144,7 @@ gcr_collection_get_objects (GcrCollection *self) /** * gcr_collection_contains: * @self: the collection + * @object: object to check * * Check whether the collection contains an object or not. * diff --git a/gcr/gcr-union-collection.c b/gcr/gcr-union-collection.c new file mode 100644 index 00000000..d331c679 --- /dev/null +++ b/gcr/gcr-union-collection.c @@ -0,0 +1,307 @@ +/* + * gnome-keyring + * + * Copyright (C) 2011 Collabora Ltd. + * + * 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. + * + * Author: Stef Walter <stefw@collabora.co.uk> + */ + +#include "config.h" + +#include "gcr-collection.h" +#include "gcr-internal.h" +#include "gcr-union-collection.h" + +#include <string.h> + +/** + * SECTION:gcr-union-collection + * @title: GcrUnionCollection + * @short_description: A GcrCollection which combines other collections + * + * An implementation of #GcrCollection, which combines the objects in + * other #GcrCollections. Use gcr_union_collection_add() to add and + * gcr_union_collection_remove() to remove them. + */ + +/** + * GcrUnionCollection: + * @parent: The parent object + * + * A union implementation of #GcrCollection. + */ + +/** + * GcrUnionCollectionClass: + * @parent_class: The parent class + * + * The class for #GcrUnionCollection. + */ + +struct _GcrUnionCollectionPrivate { + GHashTable *items; + GHashTable *collections; +}; + +static void gcr_collection_iface (GcrCollectionIface *iface); + +G_DEFINE_TYPE_WITH_CODE (GcrUnionCollection, gcr_union_collection, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, gcr_collection_iface)); + +static void +on_collection_added (GcrCollection *collection, + GObject *object, + gpointer user_data) +{ + GcrUnionCollection *self = GCR_UNION_COLLECTION (user_data); + gint *count; + + g_object_ref (object); + + count = g_hash_table_lookup (self->pv->items, object); + if (count == NULL) { + count = g_new0 (gint, 1); + *count = 1; + g_hash_table_insert (self->pv->items, object, count); + gcr_collection_emit_added (GCR_COLLECTION (self), object); + } else { + g_assert (*count > 0); + (*count)++; + } + + g_object_unref (object); +} + +static void +on_collection_removed (GcrCollection *collection, + GObject *object, + gpointer user_data) +{ + GcrUnionCollection *self = GCR_UNION_COLLECTION (user_data); + gint *count; + + g_object_ref (object); + + count = g_hash_table_lookup (self->pv->items, object); + if (count != NULL) { + g_assert (*count > 0); + (*count)--; + + if (*count == 0) { + g_hash_table_remove (self->pv->items, object); + gcr_collection_emit_removed (GCR_COLLECTION (self), object); + } + } else { + g_warning ("Object of type %s that exists in an underlying " + "collection of a GcrUnionCollection appeared without " + "emitting 'added' signal.", G_OBJECT_TYPE_NAME (object)); + } + + g_object_unref (object); + +} + +static void +connect_to_collection (GcrUnionCollection *self, + GcrCollection *collection) +{ + g_signal_connect (collection, "added", G_CALLBACK (on_collection_added), self); + g_signal_connect (collection, "removed", G_CALLBACK (on_collection_removed), self); +} + +static void +disconnect_from_collection (GcrUnionCollection *self, + GcrCollection *collection) +{ + g_signal_handlers_disconnect_by_func (collection, on_collection_added, self); + g_signal_handlers_disconnect_by_func (collection, on_collection_removed, self); +} + +static void +gcr_union_collection_init (GcrUnionCollection *self) +{ + self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_UNION_COLLECTION, GcrUnionCollectionPrivate); + self->pv->items = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, g_free); + self->pv->collections = g_hash_table_new_full (g_direct_hash, g_direct_equal, + g_object_unref, NULL); +} + +static void +gcr_union_collection_dispose (GObject *obj) +{ + GcrUnionCollection *self = GCR_UNION_COLLECTION (obj); + GHashTableIter iter; + GcrCollection *collection; + + g_hash_table_iter_init (&iter, self->pv->collections); + while (g_hash_table_iter_next (&iter, (gpointer *)&collection, NULL)) + disconnect_from_collection (self, collection); + g_hash_table_remove_all (self->pv->collections); + g_hash_table_remove_all (self->pv->items); + + G_OBJECT_CLASS (gcr_union_collection_parent_class)->dispose (obj); +} + +static void +gcr_union_collection_finalize (GObject *obj) +{ + GcrUnionCollection *self = GCR_UNION_COLLECTION (obj); + + g_assert (g_hash_table_size (self->pv->items) == 0); + g_hash_table_destroy (self->pv->items); + + g_assert (g_hash_table_size (self->pv->collections) == 0); + g_hash_table_destroy (self->pv->collections); + + G_OBJECT_CLASS (gcr_union_collection_parent_class)->finalize (obj); +} + +static void +gcr_union_collection_class_init (GcrUnionCollectionClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + gobject_class->dispose = gcr_union_collection_dispose; + gobject_class->finalize = gcr_union_collection_finalize; + g_type_class_add_private (gobject_class, sizeof (GcrUnionCollectionPrivate)); +} + +static guint +gcr_union_collection_real_get_length (GcrCollection *coll) +{ + GcrUnionCollection *self = GCR_UNION_COLLECTION (coll); + return g_hash_table_size (self->pv->items); +} + +static GList* +gcr_union_collection_real_get_objects (GcrCollection *coll) +{ + GcrUnionCollection *self = GCR_UNION_COLLECTION (coll); + return g_hash_table_get_keys (self->pv->items); +} + +static gboolean +gcr_union_collection_real_contains (GcrCollection *collection, + GObject *object) +{ + GcrUnionCollection *self = GCR_UNION_COLLECTION (collection); + return g_hash_table_lookup (self->pv->items, object) ? TRUE : FALSE; +} + +static void +gcr_collection_iface (GcrCollectionIface *iface) +{ + iface->get_length = gcr_union_collection_real_get_length; + iface->get_objects = gcr_union_collection_real_get_objects; + iface->contains = gcr_union_collection_real_contains; +} + +/* ----------------------------------------------------------------------------- + * PUBLIC + */ + +/** + * gcr_union_collection_new: + * + * Create a new #GcrUnionCollection. + * + * Returns: A newly allocated collection, which should be freed with + * g_object_unref(). + */ +GcrCollection* +gcr_union_collection_new (void) +{ + return g_object_new (GCR_TYPE_UNION_COLLECTION, NULL); +} + +/** + * gcr_union_collection_add: + * @self: The union collection + * @collection: The collection whose objects to add + * + * Add objects from this collection to the union + */ +void +gcr_union_collection_add (GcrUnionCollection *self, + GcrCollection *collection) +{ + g_return_if_fail (GCR_IS_UNION_COLLECTION (self)); + g_return_if_fail (GCR_IS_COLLECTION (collection)); + gcr_union_collection_take (self, g_object_ref (collection)); +} + +/** + * gcr_union_collection_take: + * @self: The union collection + * @collection: The collection whose objects to add + * + * Add objects from this collection to the union. Do not add an additional + * reference to the collection. + */ +void +gcr_union_collection_take (GcrUnionCollection *self, + GcrCollection *collection) +{ + GList *objects, *l; + + g_return_if_fail (GCR_IS_UNION_COLLECTION (self)); + g_return_if_fail (GCR_IS_COLLECTION (collection)); + g_return_if_fail (!g_hash_table_lookup (self->pv->collections, collection)); + + g_object_ref (collection); + + g_hash_table_insert (self->pv->collections, g_object_ref (collection), collection); + connect_to_collection (self, collection); + + objects = gcr_collection_get_objects (collection); + for (l = objects; l != NULL; l = g_list_next (l)) + on_collection_added (collection, l->data, self); + g_list_free (objects); + + g_object_unref (collection); +} + +/** + * gcr_union_collection_remove: + * @self: The collection + * @collection: The collection whose objects to remove + * + * Remove an object from the collection. + */ +void +gcr_union_collection_remove (GcrUnionCollection *self, + GcrCollection *collection) +{ + GList *objects, *l; + + g_return_if_fail (GCR_IS_UNION_COLLECTION (self)); + g_return_if_fail (GCR_IS_COLLECTION (collection)); + g_return_if_fail (g_hash_table_lookup (self->pv->collections, collection)); + + g_object_ref (collection); + + g_hash_table_remove (self->pv->collections, collection); + disconnect_from_collection (self, collection); + + objects = gcr_collection_get_objects (collection); + for (l = objects; l != NULL; l = g_list_next (l)) + on_collection_removed (collection, l->data, self); + g_list_free (objects); + + g_object_unref (collection); +} diff --git a/gcr/gcr-union-collection.h b/gcr/gcr-union-collection.h new file mode 100644 index 00000000..ac9a59da --- /dev/null +++ b/gcr/gcr-union-collection.h @@ -0,0 +1,71 @@ +/* + * gnome-keyring + * + * Copyright (C) 2011 Collabora Ltd. + * + * 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. + * + * Author: Stef Walter <stefw@collabora.co.uk> + */ + +#ifndef __GCR_UNION_COLLECTION_H__ +#define __GCR_UNION_COLLECTION_H__ + +#include "gcr.h" +#include "gcr-collection.h" + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define GCR_TYPE_UNION_COLLECTION (gcr_union_collection_get_type ()) +#define GCR_UNION_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_COLLECTION, GcrUnionCollection)) +#define GCR_UNION_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_COLLECTION, GcrUnionCollectionClass)) +#define GCR_IS_UNION_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_COLLECTION)) +#define GCR_IS_UNION_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_COLLECTION)) +#define GCR_UNION_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_COLLECTION, GcrUnionCollectionClass)) + +typedef struct _GcrUnionCollection GcrUnionCollection; +typedef struct _GcrUnionCollectionClass GcrUnionCollectionClass; +typedef struct _GcrUnionCollectionPrivate GcrUnionCollectionPrivate; + +struct _GcrUnionCollection { + GObject parent; + + /*< private >*/ + GcrUnionCollectionPrivate *pv; +}; + +struct _GcrUnionCollectionClass { + GObjectClass parent_class; +}; + +GType gcr_union_collection_get_type (void); + +GcrCollection* gcr_union_collection_new (void); + +void gcr_union_collection_add (GcrUnionCollection *self, + GcrCollection *collection); + +void gcr_union_collection_take (GcrUnionCollection *self, + GcrCollection *collection); + +void gcr_union_collection_remove (GcrUnionCollection *self, + GcrCollection *collection); + +G_END_DECLS + +#endif /* __GCR_UNION_COLLECTION_H__ */ @@ -55,6 +55,7 @@ #include "gcr-simple-collection.h" #include "gcr-tree-selector.h" #include "gcr-trust.h" +#include "gcr-union-collection.h" #include "gcr-unlock-options.h" #include "gcr-unlock-options-widget.h" #include "gcr-viewer.h" |