[gtk+] Add GtkTreeModelRefCount, only to be used in unit tests



commit 1cb14a16b761a8a415b9271233d938ffdbd7ddeb
Author: Kristian Rietveld <kris gtk org>
Date:   Sat May 28 16:41:49 2011 +0200

    Add GtkTreeModelRefCount, only to be used in unit tests

 gtk/tests/gtktreemodelrefcount.c |  273 ++++++++++++++++++++++++++++++++++++++
 gtk/tests/gtktreemodelrefcount.h |   65 +++++++++
 2 files changed, 338 insertions(+), 0 deletions(-)
---
diff --git a/gtk/tests/gtktreemodelrefcount.c b/gtk/tests/gtktreemodelrefcount.c
new file mode 100644
index 0000000..b494540
--- /dev/null
+++ b/gtk/tests/gtktreemodelrefcount.c
@@ -0,0 +1,273 @@
+/* gtktreemodelrefcount.c
+ * Copyright (C) 2011  Kristian Rietveld <kris gtk org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "gtktreemodelrefcount.h"
+
+
+/* The purpose of this GtkTreeModel is to keep record of the reference count
+ * of each node.  The reference count does not effect the functioning of
+ * the model in any way.  Because this model is a subclass of GtkTreeStore,
+ * the GtkTreeStore API should be used to add to and remove nodes from
+ * this model.  We depend on the iter format of GtkTreeStore, which means
+ * that this model needs to be revised in case the iter format of
+ * GtkTreeStore is modified.  Currently, we make use of the fact that
+ * the value stored in the user_data field is unique for each node.
+ */
+
+struct _GtkTreeModelRefCountPrivate
+{
+  GHashTable *node_hash;
+};
+
+typedef struct
+{
+  int ref_count;
+}
+NodeInfo;
+
+
+static void      gtk_tree_model_ref_count_tree_model_init (GtkTreeModelIface *iface);
+static void      gtk_tree_model_ref_count_finalize        (GObject           *object);
+
+static NodeInfo *node_info_new                            (void);
+static void      node_info_free                           (NodeInfo          *info);
+
+/* GtkTreeModel interface */
+static void      gtk_tree_model_ref_count_ref_node        (GtkTreeModel      *model,
+                                                           GtkTreeIter       *iter);
+static void      gtk_tree_model_ref_count_unref_node      (GtkTreeModel      *model,
+                                                           GtkTreeIter       *iter);
+
+
+G_DEFINE_TYPE_WITH_CODE (GtkTreeModelRefCount, gtk_tree_model_ref_count, GTK_TYPE_TREE_STORE,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
+                                                gtk_tree_model_ref_count_tree_model_init))
+
+static void
+gtk_tree_model_ref_count_init (GtkTreeModelRefCount *ref_model)
+{
+  ref_model->priv = G_TYPE_INSTANCE_GET_PRIVATE (ref_model,
+                                                 GTK_TYPE_TREE_MODEL_REF_COUNT,
+                                                 GtkTreeModelRefCountPrivate);
+
+  ref_model->priv->node_hash = g_hash_table_new_full (g_direct_hash,
+                                                      g_direct_equal,
+                                                      NULL,
+                                                      (GDestroyNotify)node_info_free);
+}
+
+static void
+gtk_tree_model_ref_count_class_init (GtkTreeModelRefCountClass *ref_model_class)
+{
+  GObjectClass *object_class;
+
+  object_class = (GObjectClass *) ref_model_class;
+
+  object_class->finalize = gtk_tree_model_ref_count_finalize;
+
+  g_type_class_add_private (object_class, sizeof (GtkTreeModelRefCountPrivate));
+}
+
+static void
+gtk_tree_model_ref_count_tree_model_init (GtkTreeModelIface *iface)
+{
+  iface->ref_node = gtk_tree_model_ref_count_ref_node;
+  iface->unref_node = gtk_tree_model_ref_count_unref_node;
+}
+
+static void
+gtk_tree_model_ref_count_finalize (GObject *object)
+{
+  GtkTreeModelRefCount *ref_model = GTK_TREE_MODEL_REF_COUNT (object);
+
+  if (ref_model->priv->node_hash)
+    {
+      g_hash_table_destroy (ref_model->priv->node_hash);
+      ref_model->priv->node_hash = NULL;
+    }
+
+  G_OBJECT_CLASS (gtk_tree_model_ref_count_parent_class)->finalize (object);
+}
+
+
+static NodeInfo *
+node_info_new (void)
+{
+  NodeInfo *info = g_slice_new (NodeInfo);
+  info->ref_count = 0;
+
+  return info;
+}
+
+static void
+node_info_free (NodeInfo *info)
+{
+  g_slice_free (NodeInfo, info);
+}
+
+static void
+gtk_tree_model_ref_count_ref_node (GtkTreeModel *model,
+                                   GtkTreeIter  *iter)
+{
+  NodeInfo *info;
+  GtkTreeModelRefCount *ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+  info = g_hash_table_lookup (ref_model->priv->node_hash, iter->user_data);
+  if (!info)
+    {
+      info = node_info_new ();
+
+      g_hash_table_insert (ref_model->priv->node_hash, iter->user_data, info);
+    }
+
+  info->ref_count++;
+}
+
+static void
+gtk_tree_model_ref_count_unref_node (GtkTreeModel *model,
+                                     GtkTreeIter  *iter)
+{
+  NodeInfo *info;
+  GtkTreeModelRefCount *ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+  info = g_hash_table_lookup (ref_model->priv->node_hash, iter->user_data);
+  g_assert (info != NULL);
+  g_assert (info->ref_count > 0);
+
+  info->ref_count--;
+}
+
+
+GtkTreeModel *
+gtk_tree_model_ref_count_new (void)
+{
+  GtkTreeModel *retval;
+
+  retval = g_object_new (gtk_tree_model_ref_count_get_type (), NULL);
+
+  return retval;
+}
+
+static void
+dump_iter (GtkTreeModelRefCount *ref_model,
+           GtkTreeIter          *iter)
+{
+  gchar *path_str;
+  NodeInfo *info;
+  GtkTreePath *path;
+
+  path = gtk_tree_model_get_path (GTK_TREE_MODEL (ref_model), iter);
+  path_str = gtk_tree_path_to_string (path);
+  gtk_tree_path_free (path);
+
+  info = g_hash_table_lookup (ref_model->priv->node_hash, iter->user_data);
+  if (!info)
+    g_print ("%-16s ref_count=0\n", path_str);
+  else
+    g_print ("%-16s ref_count=%d\n", path_str, info->ref_count);
+
+  g_free (path_str);
+}
+
+static void
+gtk_tree_model_ref_count_dump_recurse (GtkTreeModelRefCount *ref_model,
+                                       GtkTreeIter          *iter)
+{
+  do
+    {
+      GtkTreeIter child;
+
+      dump_iter (ref_model, iter);
+
+      if (gtk_tree_model_iter_children (GTK_TREE_MODEL (ref_model),
+                                        &child, iter))
+        gtk_tree_model_ref_count_dump_recurse (ref_model, &child);
+    }
+  while (gtk_tree_model_iter_next (GTK_TREE_MODEL (ref_model), iter));
+}
+
+void
+gtk_tree_model_ref_count_dump (GtkTreeModelRefCount *ref_model)
+{
+  GtkTreeIter iter;
+
+  if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ref_model), &iter))
+    return;
+
+  gtk_tree_model_ref_count_dump_recurse (ref_model, &iter);
+}
+
+static gboolean
+check_iter (GtkTreeModelRefCount *ref_model,
+            GtkTreeIter          *iter,
+            gint                  expected_ref_count)
+{
+  NodeInfo *info;
+
+  info = g_hash_table_lookup (ref_model->priv->node_hash, iter->user_data);
+  if (!info)
+    {
+      if (expected_ref_count == 0)
+        return TRUE;
+      else
+        return FALSE;
+    }
+
+  return expected_ref_count == info->ref_count;
+}
+
+gboolean
+gtk_tree_model_ref_count_check_level (GtkTreeModelRefCount *ref_model,
+                                      GtkTreeIter          *parent,
+                                      gint                  expected_ref_count,
+                                      gboolean              recurse)
+{
+  GtkTreeIter iter;
+
+  if (!gtk_tree_model_iter_children (GTK_TREE_MODEL (ref_model),
+                                     &iter, parent))
+    return TRUE;
+
+  do
+    {
+      if (!check_iter (ref_model, &iter, expected_ref_count))
+        return FALSE;
+
+      if (recurse &&
+          gtk_tree_model_iter_has_child (GTK_TREE_MODEL (ref_model), &iter))
+        {
+          if (!gtk_tree_model_ref_count_check_level (ref_model, &iter,
+                                                     expected_ref_count,
+                                                     recurse))
+            return FALSE;
+        }
+    }
+  while (gtk_tree_model_iter_next (GTK_TREE_MODEL (ref_model), &iter));
+
+  return TRUE;
+}
+
+gboolean
+gtk_tree_model_ref_count_check_node (GtkTreeModelRefCount *ref_model,
+                                     GtkTreeIter          *iter,
+                                     gint                  expected_ref_count)
+{
+  return check_iter (ref_model, iter, expected_ref_count);
+}
diff --git a/gtk/tests/gtktreemodelrefcount.h b/gtk/tests/gtktreemodelrefcount.h
new file mode 100644
index 0000000..c8c8e89
--- /dev/null
+++ b/gtk/tests/gtktreemodelrefcount.h
@@ -0,0 +1,65 @@
+/* gtktreemodelrefcount.h
+ * Copyright (C) 2011  Kristian Rietveld <kris gtk org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_TREE_MODEL_REF_COUNT_H__
+#define __GTK_TREE_MODEL_REF_COUNT_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_TREE_MODEL_REF_COUNT              (gtk_tree_model_ref_count_get_type ())
+#define GTK_TREE_MODEL_REF_COUNT(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_TREE_MODEL_REF_COUNT, GtkTreeModelRefCount))
+#define GTK_TREE_MODEL_REF_COUNT_CLASS(vtable)     (G_TYPE_CHECK_CLASS_CAST ((vtable), GTK_TYPE_TREE_MODEL_REF_COUNT, GtkTreeModelRefCountClass))
+#define GTK_IS_TREE_MODEL_REF_COUNT(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_TREE_MODEL_REF_COUNT))
+#define GTK_IS_TREE_MODEL_REF_COUNT_CLASS(vtable)  (G_TYPE_CHECK_CLASS_TYPE ((vtable), GTK_TYPE_TREE_MODEL_REF_COUNT))
+#define GTK_TREE_MODEL_REF_COUNT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TREE_MODEL_REF_COUNT, GtkTreeModelRefCountClass))
+
+
+typedef struct _GtkTreeModelRefCount        GtkTreeModelRefCount;
+typedef struct _GtkTreeModelRefCountClass   GtkTreeModelRefCountClass;
+typedef struct _GtkTreeModelRefCountPrivate GtkTreeModelRefCountPrivate;
+
+struct _GtkTreeModelRefCount
+{
+  GtkTreeStore parent;
+
+  /* < private > */
+  GtkTreeModelRefCountPrivate *priv;
+};
+
+struct _GtkTreeModelRefCountClass
+{
+  GtkTreeStoreClass parent_class;
+};
+
+
+GType         gtk_tree_model_ref_count_get_type    (void) G_GNUC_CONST;
+GtkTreeModel *gtk_tree_model_ref_count_new         (void);
+
+void          gtk_tree_model_ref_count_dump        (GtkTreeModelRefCount *ref_model);
+gboolean      gtk_tree_model_ref_count_check_level (GtkTreeModelRefCount *ref_model,
+                                                    GtkTreeIter          *parent,
+                                                    gint                  expected_ref_count,
+                                                    gboolean              recurse);
+gboolean      gtk_tree_model_ref_count_check_node  (GtkTreeModelRefCount *ref_model,
+                                                    GtkTreeIter          *iter,
+                                                    gint                  expected_ref_count);
+
+#endif /* __GTK_TREE_MODEL_REF_COUNT_H__ */



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