[gimp] app: add GimpTaggedContainer



commit 051ef0ebcb826153d06725d4f4c48d61b39353da
Author: Michael Natterer <mitch gimp org>
Date:   Tue Mar 22 23:11:46 2011 +0100

    app: add GimpTaggedContainer
    
    which is a copy of GimpFilteredContainer with s/Filtered/Tagged/ and
    no other change. #if 0 GimpFilteredContainer for now and use
    GimpTaggedContainer instead all over the place.

 app/core/Makefile.am              |    2 +
 app/core/core-types.h             |    1 +
 app/core/gimpfilteredcontainer.c  |    2 +
 app/core/gimpfilteredcontainer.h  |    2 +
 app/core/gimptaggedcontainer.c    |  596 +++++++++++++++++++++++++++++++++++++
 app/core/gimptaggedcontainer.h    |   69 +++++
 app/widgets/gimpcombotagentry.c   |   54 ++--
 app/widgets/gimpcombotagentry.h   |    4 +-
 app/widgets/gimpdatafactoryview.c |   41 ++--
 app/widgets/gimptagentry.c        |   20 +-
 app/widgets/gimptagentry.h        |   43 ++--
 app/widgets/gimptagpopup.c        |   48 ++--
 12 files changed, 778 insertions(+), 104 deletions(-)
---
diff --git a/app/core/Makefile.am b/app/core/Makefile.am
index 5cbeaad..89e6253 100644
--- a/app/core/Makefile.am
+++ b/app/core/Makefile.am
@@ -353,6 +353,8 @@ libappcore_a_sources = \
 	gimptagcache.h				\
 	gimptagged.c				\
 	gimptagged.h				\
+	gimptaggedcontainer.c			\
+	gimptaggedcontainer.h			\
 	gimptemplate.c				\
 	gimptemplate.h				\
 	gimptoolinfo.c				\
diff --git a/app/core/core-types.h b/app/core/core-types.h
index ace5370..d164483 100644
--- a/app/core/core-types.h
+++ b/app/core/core-types.h
@@ -72,6 +72,7 @@ typedef struct _GimpDocumentList      GimpDocumentList;
 typedef struct _GimpDrawableStack     GimpDrawableStack;
 typedef struct _GimpFilteredContainer GimpFilteredContainer;
 typedef struct _GimpItemStack         GimpItemStack;
+typedef struct _GimpTaggedContainer   GimpTaggedContainer;
 typedef struct _GimpToolPresets       GimpToolPresets;
 
 
diff --git a/app/core/gimpfilteredcontainer.c b/app/core/gimpfilteredcontainer.c
index 1c7f169..db6ddaf 100644
--- a/app/core/gimpfilteredcontainer.c
+++ b/app/core/gimpfilteredcontainer.c
@@ -1,3 +1,4 @@
+#if 0
 /* GIMP - The GNU Image Manipulation Program
  * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
  *
@@ -594,3 +595,4 @@ gimp_filtered_container_get_tag_count (GimpFilteredContainer *container)
 
   return container->tag_count;
 }
+#endif
diff --git a/app/core/gimpfilteredcontainer.h b/app/core/gimpfilteredcontainer.h
index 0e5f097..d45013e 100644
--- a/app/core/gimpfilteredcontainer.h
+++ b/app/core/gimpfilteredcontainer.h
@@ -1,3 +1,4 @@
+#if 0
 /* GIMP - The GNU Image Manipulation Program
  * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
  *
@@ -67,3 +68,4 @@ gint            gimp_filtered_container_get_tag_count (GimpFilteredContainer *co
 
 
 #endif  /* __GIMP_FILTERED_CONTAINER_H__ */
+#endif
diff --git a/app/core/gimptaggedcontainer.c b/app/core/gimptaggedcontainer.c
new file mode 100644
index 0000000..cc9c26d
--- /dev/null
+++ b/app/core/gimptaggedcontainer.c
@@ -0,0 +1,596 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * gimptaggedcontainer.c
+ * Copyright (C) 2008 Aurimas Juška <aurisj svn gnome org>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "core-types.h"
+
+#include "gimp.h"
+#include "gimpmarshal.h"
+#include "gimptag.h"
+#include "gimptagged.h"
+#include "gimptaggedcontainer.h"
+
+
+enum
+{
+  TAG_COUNT_CHANGED,
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_SRC_CONTAINER
+};
+
+
+typedef struct _MatchParams
+{
+  GimpTaggedContainer *tagged_container;
+  GList               *items_to_add;
+  GList               *items_to_remove;
+} MatchParams;
+
+
+static void      gimp_tagged_container_constructed        (GObject             *object);
+static void      gimp_tagged_container_dispose            (GObject             *object);
+static void      gimp_tagged_container_set_property       (GObject             *object,
+                                                           guint                property_id,
+                                                           const GValue        *value,
+                                                           GParamSpec          *pspec);
+static void      gimp_tagged_container_get_property       (GObject             *object,
+                                                           guint                property_id,
+                                                           GValue              *value,
+                                                           GParamSpec          *pspec);
+
+static gint64    gimp_tagged_container_get_memsize        (GimpObject          *object,
+                                                           gint64              *gui_size);
+
+static gboolean  gimp_tagged_container_object_matches     (GimpTaggedContainer *tagged_container,
+                                                           GimpObject          *object);
+
+static void      gimp_tagged_container_filter             (GimpTaggedContainer *tagged_container);
+
+static void      gimp_tagged_container_src_add            (GimpContainer       *src_container,
+                                                           GimpObject          *obj,
+                                                           GimpTaggedContainer *tagged_container);
+static void      gimp_tagged_container_src_remove         (GimpContainer       *src_container,
+                                                           GimpObject          *obj,
+                                                           GimpTaggedContainer *tagged_container);
+static void      gimp_tagged_container_src_freeze         (GimpContainer       *src_container,
+                                                           GimpTaggedContainer *tagged_container);
+static void      gimp_tagged_container_src_thaw           (GimpContainer       *src_container,
+                                                           GimpTaggedContainer *tagged_container);
+static void      gimp_tagged_container_tag_added          (GimpTagged          *tagged,
+                                                           GimpTag             *tag,
+                                                           GimpTaggedContainer *tagged_container);
+static void      gimp_tagged_container_tag_removed        (GimpTagged          *tagged,
+                                                           GimpTag             *tag,
+                                                           GimpTaggedContainer *tagged_container);
+static void      gimp_tagged_container_tagged_item_added  (GimpTagged          *tagged,
+                                                           GimpTaggedContainer *tagged_container);
+static void      gimp_tagged_container_tagged_item_removed(GimpTagged          *tagged,
+                                                           GimpTaggedContainer *tagged_container);
+static void      gimp_tagged_container_tag_count_changed  (GimpTaggedContainer *tagged_container,
+                                                           gint                 tag_count);
+
+
+G_DEFINE_TYPE (GimpTaggedContainer, gimp_tagged_container, GIMP_TYPE_LIST)
+
+#define parent_class gimp_tagged_container_parent_class
+
+static guint gimp_tagged_container_signals[LAST_SIGNAL] = { 0, };
+
+
+static void
+gimp_tagged_container_class_init (GimpTaggedContainerClass *klass)
+{
+  GObjectClass    *g_object_class    = G_OBJECT_CLASS (klass);
+  GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
+
+  g_object_class->constructed    = gimp_tagged_container_constructed;
+  g_object_class->dispose        = gimp_tagged_container_dispose;
+  g_object_class->set_property   = gimp_tagged_container_set_property;
+  g_object_class->get_property   = gimp_tagged_container_get_property;
+
+  gimp_object_class->get_memsize = gimp_tagged_container_get_memsize;
+
+  klass->tag_count_changed       = gimp_tagged_container_tag_count_changed;
+
+  gimp_tagged_container_signals[TAG_COUNT_CHANGED] =
+    g_signal_new ("tag-count-changed",
+                  GIMP_TYPE_TAGGED_CONTAINER,
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GimpTaggedContainerClass, tag_count_changed),
+                  NULL, NULL,
+                  gimp_marshal_VOID__INT,
+                  G_TYPE_NONE, 1,
+                  G_TYPE_INT);
+
+  g_object_class_install_property (g_object_class, PROP_SRC_CONTAINER,
+                                   g_param_spec_object ("src-container",
+                                                        NULL, NULL,
+                                                        GIMP_TYPE_CONTAINER,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gimp_tagged_container_init (GimpTaggedContainer *tagged_container)
+{
+  tagged_container->src_container  = NULL;
+  tagged_container->filter         = NULL;
+  tagged_container->tag_ref_counts = NULL;
+  tagged_container->tag_count      = 0;
+}
+
+static void
+gimp_tagged_container_constructed (GObject *object)
+{
+  GimpTaggedContainer *tagged_container = GIMP_TAGGED_CONTAINER (object);
+
+  if (G_OBJECT_CLASS (parent_class)->constructed)
+    G_OBJECT_CLASS (parent_class)->constructed (object);
+
+  tagged_container->tag_ref_counts =
+    g_hash_table_new ((GHashFunc) gimp_tag_get_hash,
+                      (GEqualFunc) gimp_tag_equals);
+
+  gimp_container_foreach (tagged_container->src_container,
+                          (GFunc) gimp_tagged_container_tagged_item_added,
+                          tagged_container);
+  gimp_tagged_container_filter (tagged_container);
+}
+
+static void
+gimp_tagged_container_dispose (GObject *object)
+{
+  GimpTaggedContainer *tagged_container = GIMP_TAGGED_CONTAINER (object);
+
+  if (tagged_container->tag_ref_counts)
+    {
+      g_hash_table_unref (tagged_container->tag_ref_counts);
+      tagged_container->tag_ref_counts = NULL;
+    }
+
+  if (tagged_container->src_container)
+    {
+      g_signal_handlers_disconnect_by_func (tagged_container->src_container,
+                                            gimp_tagged_container_src_add,
+                                            tagged_container);
+      g_signal_handlers_disconnect_by_func (tagged_container->src_container,
+                                            gimp_tagged_container_src_remove,
+                                            tagged_container);
+      g_signal_handlers_disconnect_by_func (tagged_container->src_container,
+                                            gimp_tagged_container_src_freeze,
+                                            tagged_container);
+      g_signal_handlers_disconnect_by_func (tagged_container->src_container,
+                                            gimp_tagged_container_src_thaw,
+                                            tagged_container);
+
+      g_object_unref (tagged_container->src_container);
+      tagged_container->src_container = NULL;
+    }
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gimp_tagged_container_set_property (GObject      *object,
+                                    guint         property_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+  GimpTaggedContainer *tagged_container = GIMP_TAGGED_CONTAINER (object);
+
+  switch (property_id)
+    {
+    case PROP_SRC_CONTAINER:
+      tagged_container->src_container = g_value_dup_object (value);
+
+      g_signal_connect (tagged_container->src_container, "add",
+                        G_CALLBACK (gimp_tagged_container_src_add),
+                        tagged_container);
+      g_signal_connect (tagged_container->src_container, "remove",
+                        G_CALLBACK (gimp_tagged_container_src_remove),
+                        tagged_container);
+      g_signal_connect (tagged_container->src_container, "freeze",
+                        G_CALLBACK (gimp_tagged_container_src_freeze),
+                        tagged_container);
+      g_signal_connect (tagged_container->src_container, "thaw",
+                        G_CALLBACK (gimp_tagged_container_src_thaw),
+                        tagged_container);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_tagged_container_get_property (GObject    *object,
+                                    guint       property_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+  GimpTaggedContainer *tagged_container = GIMP_TAGGED_CONTAINER (object);
+
+  switch (property_id)
+    {
+    case PROP_SRC_CONTAINER:
+      g_value_set_object (value, tagged_container->src_container);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static gint64
+gimp_tagged_container_get_memsize (GimpObject *object,
+                                   gint64     *gui_size)
+{
+  gint64 memsize = 0;
+
+  /* FIXME take members into account */
+
+  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
+                                                                  gui_size);
+}
+
+/**
+ * gimp_tagged_container_new:
+ * @src_container: container to be filtered.
+ *
+ * Creates a new #GimpTaggedContainer object which creates filtered
+ * data view of #GimpTagged objects. It filters @src_container for objects
+ * containing all of the filtering tags. Syncronization with @src_container
+ * data is performed automatically.
+ *
+ * Return value: a new #GimpTaggedContainer object.
+ **/
+GimpContainer *
+gimp_tagged_container_new (GimpContainer *src_container,
+                           GCompareFunc   sort_func)
+{
+  GimpTaggedContainer *tagged_container;
+  GType                  children_type;
+
+  g_return_val_if_fail (GIMP_IS_CONTAINER (src_container), NULL);
+
+  children_type = gimp_container_get_children_type (src_container);
+
+  tagged_container = g_object_new (GIMP_TYPE_TAGGED_CONTAINER,
+                                   "sort-func",     sort_func,
+                                   "children-type", children_type,
+                                   "policy",        GIMP_CONTAINER_POLICY_WEAK,
+                                   "unique-names",  FALSE,
+                                   "src-container", src_container,
+                                   NULL);
+
+  return GIMP_CONTAINER (tagged_container);
+}
+
+/**
+ * gimp_tagged_container_set_filter:
+ * @tagged_container: a #GimpTaggedContainer object.
+ * @tags:               list of #GimpTag objects.
+ *
+ * Sets list of tags to be used for filtering. Only objects which have all of
+ * the tags assigned match filtering criteria.
+ **/
+void
+gimp_tagged_container_set_filter (GimpTaggedContainer *tagged_container,
+                                  GList               *tags)
+{
+  g_return_if_fail (GIMP_IS_TAGGED_CONTAINER (tagged_container));
+
+  tagged_container->filter = tags;
+
+  gimp_container_freeze (GIMP_CONTAINER (tagged_container));
+  gimp_tagged_container_filter (tagged_container);
+  gimp_container_thaw (GIMP_CONTAINER (tagged_container));
+}
+
+/**
+ * gimp_tagged_container_get_filter:
+ * @tagged_container: a #GimpTaggedContainer object.
+ *
+ * Returns current tag filter. Tag filter is a list of GimpTag objects, which
+ * must be contained by each object matching filter criteria.
+ *
+ * Return value: a list of GimpTag objects used as filter. This value should
+ * not be modified or freed.
+ **/
+const GList *
+gimp_tagged_container_get_filter (GimpTaggedContainer *tagged_container)
+{
+  g_return_val_if_fail (GIMP_IS_TAGGED_CONTAINER (tagged_container), NULL);
+
+  return tagged_container->filter;
+}
+
+static gboolean
+gimp_tagged_container_object_matches (GimpTaggedContainer *tagged_container,
+                                      GimpObject          *object)
+{
+  GList *filter_tag;
+  GList *object_tag;
+
+  filter_tag = tagged_container->filter;
+  while (filter_tag)
+    {
+      if (! filter_tag->data)
+        {
+          /* invalid tag - does not match */
+          return FALSE;
+        }
+
+      object_tag = gimp_tagged_get_tags (GIMP_TAGGED (object));
+      while (object_tag)
+        {
+          if (gimp_tag_equals (GIMP_TAG (object_tag->data),
+                               GIMP_TAG (filter_tag->data)))
+            {
+              /* found match for the tag */
+              break;
+            }
+          object_tag = g_list_next (object_tag);
+        }
+
+      if (! object_tag)
+        {
+          /* match for the tag was not found.
+           * since query is of type AND, it whole fails. */
+          return FALSE;
+        }
+
+      filter_tag = g_list_next (filter_tag);
+    }
+
+  return TRUE;
+}
+
+static void
+gimp_tagged_container_check_needs_remove (GimpObject  *object,
+                                          MatchParams *match_params)
+{
+  if (! gimp_tagged_container_object_matches (match_params->tagged_container,
+                                              object))
+    {
+      match_params->items_to_remove = g_list_prepend (match_params->items_to_remove,
+                                                      object);
+    }
+}
+
+static void
+gimp_tagged_container_check_needs_add (GimpObject  *object,
+                                         MatchParams *match_params)
+{
+  if (gimp_tagged_container_object_matches (match_params->tagged_container,
+                                            object) &&
+      ! gimp_container_have (GIMP_CONTAINER (match_params->tagged_container),
+                             object))
+    {
+      match_params->items_to_add = g_list_prepend (match_params->items_to_add,
+                                                   object);
+    }
+}
+
+static void
+gimp_tagged_container_filter (GimpTaggedContainer *tagged_container)
+{
+  MatchParams  match_params;
+  GList       *list;
+
+  match_params.tagged_container = tagged_container;
+  match_params.items_to_add       = NULL;
+  match_params.items_to_remove    = NULL;
+
+  gimp_container_foreach (GIMP_CONTAINER (tagged_container),
+                          (GFunc) gimp_tagged_container_check_needs_remove,
+                          &match_params);
+  gimp_container_foreach (GIMP_CONTAINER (tagged_container->src_container),
+                          (GFunc) gimp_tagged_container_check_needs_add,
+                          &match_params);
+
+  for (list = match_params.items_to_remove; list; list = g_list_next (list))
+    {
+      gimp_container_remove (GIMP_CONTAINER (tagged_container),
+                             GIMP_OBJECT (list->data));
+    }
+
+  for (list = match_params.items_to_add; list; list = g_list_next (list))
+    {
+      gimp_container_add (GIMP_CONTAINER (tagged_container),
+                          GIMP_OBJECT (list->data));
+    }
+
+  g_list_free (match_params.items_to_add);
+  g_list_free (match_params.items_to_remove);
+}
+
+static void
+gimp_tagged_container_src_add (GimpContainer       *src_container,
+                               GimpObject          *obj,
+                               GimpTaggedContainer *tagged_container)
+{
+  gimp_tagged_container_tagged_item_added (GIMP_TAGGED (obj),
+                                           tagged_container);
+
+  if (! gimp_container_frozen (src_container))
+    {
+      gimp_container_add (GIMP_CONTAINER (tagged_container), obj);
+    }
+}
+
+static void
+gimp_tagged_container_src_remove (GimpContainer       *src_container,
+                                  GimpObject          *obj,
+                                  GimpTaggedContainer *tagged_container)
+{
+  gimp_tagged_container_tagged_item_removed (GIMP_TAGGED (obj),
+                                             tagged_container);
+
+  if (! gimp_container_frozen (src_container) &&
+      gimp_container_have (GIMP_CONTAINER (tagged_container), obj))
+    {
+      gimp_container_remove (GIMP_CONTAINER (tagged_container), obj);
+    }
+}
+
+static void
+gimp_tagged_container_src_freeze (GimpContainer       *src_container,
+                                  GimpTaggedContainer *tagged_container)
+{
+  gimp_container_freeze (GIMP_CONTAINER (tagged_container));
+  gimp_container_clear (GIMP_CONTAINER (tagged_container));
+}
+
+static void
+gimp_tagged_container_src_thaw (GimpContainer       *src_container,
+                                GimpTaggedContainer *tagged_container)
+{
+  gimp_tagged_container_filter (tagged_container);
+  gimp_container_thaw (GIMP_CONTAINER (tagged_container));
+}
+
+static void
+gimp_tagged_container_tagged_item_added (GimpTagged          *tagged,
+                                         GimpTaggedContainer *tagged_container)
+{
+  GList *list;
+
+  for (list = gimp_tagged_get_tags (tagged); list; list = g_list_next (list))
+    {
+      gimp_tagged_container_tag_added (tagged,
+                                       list->data,
+                                       tagged_container);
+    }
+
+  g_signal_connect (tagged, "tag-added",
+                    G_CALLBACK (gimp_tagged_container_tag_added),
+                    tagged_container);
+  g_signal_connect (tagged, "tag-removed",
+                    G_CALLBACK (gimp_tagged_container_tag_removed),
+                    tagged_container);
+}
+
+static void
+gimp_tagged_container_tagged_item_removed (GimpTagged          *tagged,
+                                           GimpTaggedContainer *tagged_container)
+{
+  GList *list;
+
+  g_signal_handlers_disconnect_by_func (tagged,
+                                        gimp_tagged_container_tag_added,
+                                        tagged_container);
+  g_signal_handlers_disconnect_by_func (tagged,
+                                        gimp_tagged_container_tag_removed,
+                                        tagged_container);
+
+  for (list = gimp_tagged_get_tags (tagged); list; list = g_list_next (list))
+    {
+      gimp_tagged_container_tag_removed (tagged,
+                                         GIMP_TAG (list->data),
+                                         tagged_container);
+    }
+
+}
+
+static void
+gimp_tagged_container_tag_added (GimpTagged          *tagged,
+                                 GimpTag             *tag,
+                                 GimpTaggedContainer *tagged_container)
+{
+  gint ref_count;
+
+  ref_count = GPOINTER_TO_INT (g_hash_table_lookup (tagged_container->tag_ref_counts,
+                                                    tag));
+  ref_count++;
+  g_hash_table_insert (tagged_container->tag_ref_counts,
+                       tag, GINT_TO_POINTER (ref_count));
+  if (ref_count == 1)
+    {
+      tagged_container->tag_count++;
+      g_signal_emit (tagged_container,
+                     gimp_tagged_container_signals[TAG_COUNT_CHANGED], 0,
+                     tagged_container->tag_count);
+    }
+}
+
+static void
+gimp_tagged_container_tag_removed (GimpTagged          *tagged,
+                                   GimpTag             *tag,
+                                   GimpTaggedContainer *tagged_container)
+{
+  gint ref_count;
+
+  ref_count = GPOINTER_TO_INT (g_hash_table_lookup (tagged_container->tag_ref_counts,
+                                                    tag));
+  ref_count--;
+
+  if (ref_count > 0)
+    {
+      g_hash_table_insert (tagged_container->tag_ref_counts,
+                           tag, GINT_TO_POINTER (ref_count));
+    }
+  else
+    {
+      if (g_hash_table_remove (tagged_container->tag_ref_counts, tag))
+        {
+          tagged_container->tag_count--;
+          g_signal_emit (tagged_container,
+                         gimp_tagged_container_signals[TAG_COUNT_CHANGED], 0,
+                         tagged_container->tag_count);
+        }
+    }
+}
+
+static void
+gimp_tagged_container_tag_count_changed (GimpTaggedContainer *container,
+                                         gint                 tag_count)
+{
+}
+
+/**
+ * gimp_tagged_container_get_tag_count:
+ * @container:  a #GimpTaggedContainer object.
+ *
+ * Get number of distinct tags that are currently assigned to all
+ * objects in the container. The count is independent of currently
+ * used filter, it is provided for all available objects (ie. empty
+ * filter).
+ *
+ * Return value: number of distinct tags assigned to all objects in the
+ *               container.
+ **/
+gint
+gimp_tagged_container_get_tag_count (GimpTaggedContainer *container)
+{
+  g_return_val_if_fail (GIMP_IS_TAGGED_CONTAINER (container), 0);
+
+  return container->tag_count;
+}
diff --git a/app/core/gimptaggedcontainer.h b/app/core/gimptaggedcontainer.h
new file mode 100644
index 0000000..86bc2b3
--- /dev/null
+++ b/app/core/gimptaggedcontainer.h
@@ -0,0 +1,69 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * gimptaggedcontainer.h
+ * Copyright (C) 2008 Aurimas Juška <aurisj svn gnome org>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_TAGGED_CONTAINER_H__
+#define __GIMP_TAGGED_CONTAINER_H__
+
+
+#include "gimplist.h"
+
+
+#define GIMP_TYPE_TAGGED_CONTAINER            (gimp_tagged_container_get_type ())
+#define GIMP_TAGGED_CONTAINER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_TAGGED_CONTAINER, GimpTaggedContainer))
+#define GIMP_TAGGED_CONTAINER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_TAGGED_CONTAINER, GimpTaggedContainerClass))
+#define GIMP_IS_TAGGED_CONTAINER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_TAGGED_CONTAINER))
+#define GIMP_IS_TAGGED_CONTAINER_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GIMP_TYPE_TAGGED_CONTAINER))
+#define GIMP_TAGGED_CONTAINER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_TAGGED_CONTAINER, GimpTaggedContainerClass))
+
+
+typedef struct _GimpTaggedContainerClass GimpTaggedContainerClass;
+
+struct _GimpTaggedContainer
+{
+  GimpList       parent_instance;
+
+  GimpContainer *src_container;
+  GList         *filter;
+  GHashTable    *tag_ref_counts;
+  gint           tag_count;
+};
+
+struct _GimpTaggedContainerClass
+{
+  GimpContainerClass  parent_class;
+
+  void (* tag_count_changed) (GimpTaggedContainer *container,
+                              gint                   count);
+};
+
+
+GType           gimp_tagged_container_get_type      (void) G_GNUC_CONST;
+
+GimpContainer * gimp_tagged_container_new           (GimpContainer       *src_container,
+                                                     GCompareFunc         sort_func);
+
+void            gimp_tagged_container_set_filter    (GimpTaggedContainer *tagged_container,
+                                                     GList               *tags);
+const GList   * gimp_tagged_container_get_filter    (GimpTaggedContainer *tagged_container);
+
+gint            gimp_tagged_container_get_tag_count (GimpTaggedContainer *container);
+
+
+#endif  /* __GIMP_TAGGED_CONTAINER_H__ */
diff --git a/app/widgets/gimpcombotagentry.c b/app/widgets/gimpcombotagentry.c
index ac06bc0..11b5a0d 100644
--- a/app/widgets/gimpcombotagentry.c
+++ b/app/widgets/gimpcombotagentry.c
@@ -27,36 +27,36 @@
 #include "widgets-types.h"
 
 #include "core/gimpcontainer.h"
-#include "core/gimpfilteredcontainer.h"
 #include "core/gimpcontext.h"
-#include "core/gimpviewable.h"
 #include "core/gimptag.h"
 #include "core/gimptagged.h"
+#include "core/gimptaggedcontainer.h"
+#include "core/gimpviewable.h"
 
 #include "gimptagentry.h"
 #include "gimptagpopup.h"
 #include "gimpcombotagentry.h"
 
 
-static void     gimp_combo_tag_entry_constructed       (GObject                *object);
-static void     gimp_combo_tag_entry_dispose           (GObject                *object);
+static void     gimp_combo_tag_entry_constructed       (GObject              *object);
+static void     gimp_combo_tag_entry_dispose           (GObject              *object);
 
-static gboolean gimp_combo_tag_entry_expose            (GtkWidget              *widget,
-                                                        GdkEventExpose         *event);
-static void     gimp_combo_tag_entry_style_set         (GtkWidget              *widget,
-                                                        GtkStyle               *previous_style);
+static gboolean gimp_combo_tag_entry_expose            (GtkWidget            *widget,
+                                                        GdkEventExpose       *event);
+static void     gimp_combo_tag_entry_style_set         (GtkWidget            *widget,
+                                                        GtkStyle             *previous_style);
 
-static void     gimp_combo_tag_entry_icon_press        (GtkWidget              *widget,
-                                                        GtkEntryIconPosition    icon_pos,
-                                                        GdkEvent               *event,
-                                                        gpointer                user_data);
+static void     gimp_combo_tag_entry_icon_press        (GtkWidget            *widget,
+                                                        GtkEntryIconPosition  icon_pos,
+                                                        GdkEvent             *event,
+                                                        gpointer              user_data);
 
-static void     gimp_combo_tag_entry_popup_destroy     (GtkObject              *object,
-                                                        GimpComboTagEntry      *entry);
+static void     gimp_combo_tag_entry_popup_destroy     (GtkObject            *object,
+                                                        GimpComboTagEntry    *entry);
 
-static void     gimp_combo_tag_entry_tag_count_changed (GimpFilteredContainer  *container,
-                                                        gint                    tag_count,
-                                                        GimpComboTagEntry      *entry);
+static void     gimp_combo_tag_entry_tag_count_changed (GimpTaggedContainer  *container,
+                                                        gint                  tag_count,
+                                                        GimpComboTagEntry    *entry);
 
 
 G_DEFINE_TYPE (GimpComboTagEntry, gimp_combo_tag_entry, GIMP_TYPE_TAG_ENTRY);
@@ -240,7 +240,7 @@ gimp_combo_tag_entry_style_set (GtkWidget *widget,
 
 /**
  * gimp_combo_tag_entry_new:
- * @container: a filtered container to be used.
+ * @container: a tagged container to be used.
  * @mode:      tag entry mode to work in.
  *
  * Creates a new #GimpComboTagEntry widget which extends #GimpTagEntry by
@@ -249,10 +249,10 @@ gimp_combo_tag_entry_style_set (GtkWidget *widget,
  * Return value: a new #GimpComboTagEntry widget.
  **/
 GtkWidget *
-gimp_combo_tag_entry_new (GimpFilteredContainer *container,
-                          GimpTagEntryMode       mode)
+gimp_combo_tag_entry_new (GimpTaggedContainer *container,
+                          GimpTagEntryMode     mode)
 {
-  g_return_val_if_fail (GIMP_IS_FILTERED_CONTAINER (container), NULL);
+  g_return_val_if_fail (GIMP_IS_TAGGED_CONTAINER (container), NULL);
 
   return g_object_new (GIMP_TYPE_COMBO_TAG_ENTRY,
                        "container", container,
@@ -270,10 +270,10 @@ gimp_combo_tag_entry_icon_press (GtkWidget            *widget,
 
   if (! entry->popup)
     {
-      GimpFilteredContainer *container = GIMP_TAG_ENTRY (entry)->container;
-      gint                   tag_count;
+      GimpTaggedContainer *container = GIMP_TAG_ENTRY (entry)->container;
+      gint                 tag_count;
 
-      tag_count = gimp_filtered_container_get_tag_count (container);
+      tag_count = gimp_tagged_container_get_tag_count (container);
 
       if (tag_count > 0 && ! GIMP_TAG_ENTRY (entry)->has_invalid_tags)
         {
@@ -299,9 +299,9 @@ gimp_combo_tag_entry_popup_destroy (GtkObject         *object,
 }
 
 static void
-gimp_combo_tag_entry_tag_count_changed (GimpFilteredContainer *container,
-                                        gint                   tag_count,
-                                        GimpComboTagEntry     *entry)
+gimp_combo_tag_entry_tag_count_changed (GimpTaggedContainer *container,
+                                        gint                 tag_count,
+                                        GimpComboTagEntry   *entry)
 {
   gboolean sensitive;
 
diff --git a/app/widgets/gimpcombotagentry.h b/app/widgets/gimpcombotagentry.h
index 96d099f..1dcbcb4 100644
--- a/app/widgets/gimpcombotagentry.h
+++ b/app/widgets/gimpcombotagentry.h
@@ -54,8 +54,8 @@ struct _GimpComboTagEntryClass
 
 GType       gimp_combo_tag_entry_get_type (void) G_GNUC_CONST;
 
-GtkWidget * gimp_combo_tag_entry_new      (GimpFilteredContainer *container,
-                                           GimpTagEntryMode       mode);
+GtkWidget * gimp_combo_tag_entry_new      (GimpTaggedContainer *container,
+                                           GimpTagEntryMode     mode);
 
 
 #endif  /*  __GIMP_COMBO_TAG_ENTRY_H__  */
diff --git a/app/widgets/gimpdatafactoryview.c b/app/widgets/gimpdatafactoryview.c
index 2fb8a6b..61603f9 100644
--- a/app/widgets/gimpdatafactoryview.c
+++ b/app/widgets/gimpdatafactoryview.c
@@ -35,9 +35,9 @@
 #include "core/gimpcontext.h"
 #include "core/gimpdata.h"
 #include "core/gimpdatafactory.h"
-#include "core/gimpfilteredcontainer.h"
 #include "core/gimplist.h"
 #include "core/gimpmarshal.h"
+#include "core/gimptaggedcontainer.h"
 
 #include "gimpcombotagentry.h"
 #include "gimpcontainertreestore.h"
@@ -57,7 +57,7 @@ struct _GimpDataFactoryViewPriv
 {
   GimpDataFactory *factory;
 
-  GimpContainer   *tag_filtered_container;
+  GimpContainer   *tagged_container;
   GtkWidget       *query_tag_entry;
   GtkWidget       *assign_tag_entry;
   GList           *selected_items;
@@ -108,15 +108,15 @@ gimp_data_factory_view_init (GimpDataFactoryView *view)
                                             GIMP_TYPE_DATA_FACTORY_VIEW,
                                             GimpDataFactoryViewPriv);
 
-  view->priv->tag_filtered_container = NULL;
-  view->priv->query_tag_entry        = NULL;
-  view->priv->assign_tag_entry       = NULL;
-  view->priv->selected_items         = NULL;
-  view->priv->edit_button            = NULL;
-  view->priv->new_button             = NULL;
-  view->priv->duplicate_button       = NULL;
-  view->priv->delete_button          = NULL;
-  view->priv->refresh_button         = NULL;
+  view->priv->tagged_container = NULL;
+  view->priv->query_tag_entry  = NULL;
+  view->priv->assign_tag_entry = NULL;
+  view->priv->selected_items   = NULL;
+  view->priv->edit_button      = NULL;
+  view->priv->new_button       = NULL;
+  view->priv->duplicate_button = NULL;
+  view->priv->delete_button    = NULL;
+  view->priv->refresh_button   = NULL;
 }
 
 static void
@@ -124,10 +124,10 @@ gimp_data_factory_view_dispose (GObject *object)
 {
   GimpDataFactoryView *factory_view = GIMP_DATA_FACTORY_VIEW (object);
 
-  if (factory_view->priv->tag_filtered_container)
+  if (factory_view->priv->tagged_container)
     {
-      g_object_unref (factory_view->priv->tag_filtered_container);
-      factory_view->priv->tag_filtered_container = NULL;
+      g_object_unref (factory_view->priv->tagged_container);
+      factory_view->priv->tagged_container = NULL;
     }
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
@@ -241,13 +241,14 @@ gimp_data_factory_view_construct (GimpDataFactoryView *factory_view,
 
   factory_view->priv->factory = factory;
 
-  factory_view->priv->tag_filtered_container =
-    gimp_filtered_container_new (gimp_data_factory_get_container (factory),
-                                 (GCompareFunc) gimp_data_compare);
+  factory_view->priv->tagged_container =
+    gimp_tagged_container_new (gimp_data_factory_get_container (factory),
+                               (GCompareFunc) gimp_data_compare);
 
   if (! gimp_container_editor_construct (GIMP_CONTAINER_EDITOR (factory_view),
                                          view_type,
-                                         factory_view->priv->tag_filtered_container, context,
+                                         factory_view->priv->tagged_container,
+                                         context,
                                          view_size, view_border_width,
                                          menu_factory, menu_identifier,
                                          ui_identifier))
@@ -305,7 +306,7 @@ gimp_data_factory_view_construct (GimpDataFactoryView *factory_view,
 
   /* Query tag entry */
   factory_view->priv->query_tag_entry =
-    gimp_combo_tag_entry_new (GIMP_FILTERED_CONTAINER (factory_view->priv->tag_filtered_container),
+    gimp_combo_tag_entry_new (GIMP_TAGGED_CONTAINER (factory_view->priv->tagged_container),
                               GIMP_TAG_ENTRY_MODE_QUERY);
   gtk_box_pack_start (GTK_BOX (editor->view),
                       factory_view->priv->query_tag_entry,
@@ -316,7 +317,7 @@ gimp_data_factory_view_construct (GimpDataFactoryView *factory_view,
 
   /* Assign tag entry */
   factory_view->priv->assign_tag_entry =
-    gimp_combo_tag_entry_new (GIMP_FILTERED_CONTAINER (factory_view->priv->tag_filtered_container),
+    gimp_combo_tag_entry_new (GIMP_TAGGED_CONTAINER (factory_view->priv->tagged_container),
                               GIMP_TAG_ENTRY_MODE_ASSIGN);
   gimp_tag_entry_set_selected_items (GIMP_TAG_ENTRY (factory_view->priv->assign_tag_entry),
                                      factory_view->priv->selected_items);
diff --git a/app/widgets/gimptagentry.c b/app/widgets/gimptagentry.c
index 31f5143..7b88bd1 100644
--- a/app/widgets/gimptagentry.c
+++ b/app/widgets/gimptagentry.c
@@ -30,9 +30,9 @@
 #include "core/gimp-utils.h"
 #include "core/gimpcontainer.h"
 #include "core/gimpcontext.h"
-#include "core/gimpfilteredcontainer.h"
 #include "core/gimptag.h"
 #include "core/gimptagged.h"
+#include "core/gimptaggedcontainer.h"
 #include "core/gimpviewable.h"
 
 #include "gimptagentry.h"
@@ -157,9 +157,9 @@ gimp_tag_entry_class_init (GimpTagEntryClass *klass)
   g_object_class_install_property (object_class,
                                    PROP_CONTAINER,
                                    g_param_spec_object ("container",
-                                                        "Filtered container",
-                                                        "The Filtered container",
-                                                        GIMP_TYPE_FILTERED_CONTAINER,
+                                                        "Tagged container",
+                                                        "The Tagged container",
+                                                        GIMP_TYPE_TAGGED_CONTAINER,
                                                         G_PARAM_CONSTRUCT_ONLY |
                                                         G_PARAM_READWRITE));
 
@@ -310,7 +310,7 @@ gimp_tag_entry_get_property (GObject    *object,
 
 /**
  * gimp_tag_entry_new:
- * @container: a #GimpFilteredContainer object
+ * @container: a #GimpTaggedContainer object
  * @mode:      #GimpTagEntryMode to work in.
  *
  * #GimpTagEntry is a widget which can query and assign tags to tagged objects.
@@ -321,10 +321,10 @@ gimp_tag_entry_get_property (GObject    *object,
  * Return value: a new GimpTagEntry widget.
  **/
 GtkWidget *
-gimp_tag_entry_new (GimpFilteredContainer *container,
-                    GimpTagEntryMode       mode)
+gimp_tag_entry_new (GimpTaggedContainer *container,
+                    GimpTagEntryMode     mode)
 {
-  g_return_val_if_fail (GIMP_IS_FILTERED_CONTAINER (container), NULL);
+  g_return_val_if_fail (GIMP_IS_TAGGED_CONTAINER (container), NULL);
 
   return g_object_new (GIMP_TYPE_TAG_ENTRY,
                        "container", container,
@@ -616,8 +616,8 @@ gimp_tag_entry_query_tag (GimpTagEntry *entry)
     }
   g_strfreev (parsed_tags);
 
-  gimp_filtered_container_set_filter (GIMP_FILTERED_CONTAINER (entry->container),
-                                      query_list);
+  gimp_tagged_container_set_filter (GIMP_TAGGED_CONTAINER (entry->container),
+                                    query_list);
 
   if (has_invalid_tags != entry->has_invalid_tags)
     {
diff --git a/app/widgets/gimptagentry.h b/app/widgets/gimptagentry.h
index a16e5bd..86e18af 100644
--- a/app/widgets/gimptagentry.h
+++ b/app/widgets/gimptagentry.h
@@ -34,9 +34,9 @@ typedef struct _GimpTagEntryClass  GimpTagEntryClass;
 
 struct _GimpTagEntry
 {
-  GtkEntry                parent_instance;
+  GtkEntry             parent_instance;
 
-  GimpFilteredContainer  *container;
+  GimpTaggedContainer *container;
 
   /* mask describes the meaning of each char in GimpTagEntry.
    * It is maintained automatically on insert-text and delete-text
@@ -49,18 +49,18 @@ struct _GimpTagEntry
    * s - separator
    * w - whitespace.
    */
-  GString                *mask;
-  GList                  *selected_items;
-  GList                  *common_tags;
-  GList                  *recent_list;
-  gint                    tab_completion_index;
-  gint                    internal_operation;
-  gint                    suppress_mask_update;
-  gint                    suppress_tag_query;
-  GimpTagEntryMode        mode;
-  gboolean                description_shown;
-  gboolean                has_invalid_tags;
-  gboolean                tag_query_pending;
+  GString             *mask;
+  GList               *selected_items;
+  GList               *common_tags;
+  GList               *recent_list;
+  gint                 tab_completion_index;
+  gint                 internal_operation;
+  gint                 suppress_mask_update;
+  gint                 suppress_tag_query;
+  GimpTagEntryMode     mode;
+  gboolean             description_shown;
+  gboolean             has_invalid_tags;
+  gboolean             tag_query_pending;
 };
 
 struct _GimpTagEntryClass
@@ -71,15 +71,16 @@ struct _GimpTagEntryClass
 
 GType          gimp_tag_entry_get_type           (void) G_GNUC_CONST;
 
-GtkWidget    * gimp_tag_entry_new                (GimpFilteredContainer *container,
-                                                  GimpTagEntryMode       mode);
+GtkWidget    * gimp_tag_entry_new                (GimpTaggedContainer *container,
+                                                  GimpTagEntryMode     mode);
 
-void           gimp_tag_entry_set_selected_items (GimpTagEntry          *entry,
-                                                  GList                 *items);
-gchar       ** gimp_tag_entry_parse_tags         (GimpTagEntry          *entry);
-void           gimp_tag_entry_set_tag_string     (GimpTagEntry          *entry,
-                                                  const gchar           *tag_string);
+void           gimp_tag_entry_set_selected_items (GimpTagEntry        *entry,
+                                                  GList               *items);
+gchar       ** gimp_tag_entry_parse_tags         (GimpTagEntry        *entry);
+void           gimp_tag_entry_set_tag_string     (GimpTagEntry        *entry,
+                                                  const gchar         *tag_string);
 
 const gchar  * gimp_tag_entry_get_separator      (void);
 
+
 #endif  /*  __GIMP_TAG_ENTRY_H__  */
diff --git a/app/widgets/gimptagpopup.c b/app/widgets/gimptagpopup.c
index 888e876..c4db0bb 100644
--- a/app/widgets/gimptagpopup.c
+++ b/app/widgets/gimptagpopup.c
@@ -29,9 +29,9 @@
 
 #include "core/gimpcontainer.h"
 #include "core/gimpcontext.h"
-#include "core/gimpfilteredcontainer.h"
 #include "core/gimptag.h"
 #include "core/gimptagged.h"
+#include "core/gimptaggedcontainer.h"
 #include "core/gimpviewable.h"
 
 #include "gimpcombotagentry.h"
@@ -195,28 +195,28 @@ gimp_tag_popup_init (GimpTagPopup *popup)
 static void
 gimp_tag_popup_constructed (GObject *object)
 {
-  GimpTagPopup          *popup = GIMP_TAG_POPUP (object);
-  GimpFilteredContainer *container;
-  GtkWidget             *entry;
-  GtkAllocation          entry_allocation;
-  GtkStyle              *frame_style;
-  gint                   x;
-  gint                   y;
-  gint                   width;
-  gint                   height;
-  gint                   popup_height;
-  GHashTable            *tag_hash;
-  GList                 *tag_list;
-  GList                 *tag_iterator;
-  gint                   i;
-  gint                   j;
-  gint                   max_height;
-  gint                   screen_height;
-  gchar                **current_tags;
-  gint                   current_count;
-  const gchar           *list_tag;
-  GdkRectangle           popup_rects[2]; /* variants of popup placement */
-  GdkRectangle           popup_rect; /* best popup rect in screen coordinates */
+  GimpTagPopup        *popup = GIMP_TAG_POPUP (object);
+  GimpTaggedContainer *container;
+  GtkWidget           *entry;
+  GtkAllocation        entry_allocation;
+  GtkStyle            *frame_style;
+  gint                 x;
+  gint                 y;
+  gint                 width;
+  gint                 height;
+  gint                 popup_height;
+  GHashTable          *tag_hash;
+  GList               *tag_list;
+  GList               *tag_iterator;
+  gint                 i;
+  gint                 j;
+  gint                 max_height;
+  gint                 screen_height;
+  gchar              **current_tags;
+  gint                 current_count;
+  const gchar         *list_tag;
+  GdkRectangle         popup_rects[2]; /* variants of popup placement */
+  GdkRectangle         popup_rect; /* best popup rect in screen coordinates */
 
   if (G_OBJECT_CLASS (parent_class)->constructed)
     G_OBJECT_CLASS (parent_class)->constructed (object);
@@ -1028,7 +1028,7 @@ gimp_tag_popup_toggle_tag (GimpTagPopup *popup,
 
   if (GIMP_TAG_ENTRY (popup->combo_entry)->mode == GIMP_TAG_ENTRY_MODE_QUERY)
     {
-      GimpFilteredContainer *container;
+      GimpTaggedContainer *container;
 
       container = GIMP_TAG_ENTRY (popup->combo_entry)->container;
 



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