[gtk+] Start a testsuite for GtkTreeModelFilter



commit 923a6a808389bb1d7563a791f2bc83bbff1adab9
Author: Kristian Rietveld <kris gtk org>
Date:   Tue Sep 1 09:17:02 2009 +0200

    Start a testsuite for GtkTreeModelFilter

 gtk/tests/Makefile.am   |    4 +
 gtk/tests/filtermodel.c | 1231 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1235 insertions(+), 0 deletions(-)
---
diff --git a/gtk/tests/Makefile.am b/gtk/tests/Makefile.am
index 541cbc2..162db44 100644
--- a/gtk/tests/Makefile.am
+++ b/gtk/tests/Makefile.am
@@ -82,4 +82,8 @@ TEST_PROGS			+= textbuffer
 textbuffer_SOURCES		 = textbuffer.c pixbuf-init.c
 textbuffer_LDADD		 = $(progs_ldadd)
 
+TEST_PROGS			+= filtermodel
+filtermodel_SOURCES		 = filtermodel.c
+filtermodel_LDADD		 = $(progs_ldadd)
+
 -include $(top_srcdir)/git.mk
diff --git a/gtk/tests/filtermodel.c b/gtk/tests/filtermodel.c
new file mode 100644
index 0000000..e0b6a95
--- /dev/null
+++ b/gtk/tests/filtermodel.c
@@ -0,0 +1,1231 @@
+/* Extensive GtkTreeModelFilter tests.
+ * Copyright (C) 2009  Kristian Rietveld  <kris gtk org>
+ *
+ * This library 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 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 <gtk/gtk.h>
+
+
+/*
+ * Model creation
+ */
+
+#define LEVEL_LENGTH 5
+
+static void
+create_tree_store_set_values (GtkTreeStore *store,
+                              GtkTreeIter  *iter,
+                              gboolean      visible)
+{
+  GtkTreePath *path;
+
+  path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter);
+  gtk_tree_store_set (store, iter,
+                      0, gtk_tree_path_to_string (path),
+                      1, visible,
+                      -1);
+  gtk_tree_path_free (path);
+}
+
+static void
+create_tree_store_recurse (int           depth,
+                           GtkTreeStore *store,
+                           GtkTreeIter  *parent,
+                           gboolean      visible)
+{
+  int i;
+
+  for (i = 0; i < LEVEL_LENGTH; i++)
+    {
+      GtkTreeIter iter;
+
+      gtk_tree_store_insert (store, &iter, parent, i);
+      create_tree_store_set_values (store, &iter, visible);
+
+      if (depth > 0)
+        create_tree_store_recurse (depth - 1, store, &iter, visible);
+    }
+}
+
+static GtkTreeStore *
+create_tree_store (int      depth,
+                   gboolean visible)
+{
+  GtkTreeStore *store;
+
+  store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
+
+  create_tree_store_recurse (depth, store, NULL, visible);
+
+  return store;
+}
+
+
+/*
+ * Fixture
+ */
+
+typedef struct
+{
+  GtkWidget *tree_view;
+
+  GtkTreeStore *store;
+  GtkTreeModelFilter *filter;
+} FilterTest;
+
+static void
+filter_test_setup (FilterTest    *fixture,
+                   gconstpointer  test_data)
+{
+  fixture->store = create_tree_store (3, TRUE);
+  fixture->filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture->store), NULL));
+  gtk_tree_model_filter_set_visible_column (fixture->filter, 1);
+
+  /* We need a tree view that's listening to get ref counting from that
+   * side.
+   */
+  fixture->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (fixture->filter));
+}
+
+static void
+filter_test_setup_empty (FilterTest    *fixture,
+                         gconstpointer  test_data)
+{
+  fixture->store = create_tree_store (3, FALSE);
+  fixture->filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture->store), NULL));
+  gtk_tree_model_filter_set_visible_column (fixture->filter, 1);
+
+  /* We need a tree view that's listening to get ref counting from that
+   * side.
+   */
+  fixture->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (fixture->filter));
+}
+
+static void
+filter_test_setup_unfiltered (FilterTest    *fixture,
+                              gconstpointer  test_data)
+{
+  fixture->store = create_tree_store (3, TRUE);
+  fixture->filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture->store), NULL));
+
+  /* We need a tree view that's listening to get ref counting from that
+   * side.
+   */
+  fixture->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (fixture->filter));
+}
+
+static void
+filter_test_setup_empty_unfiltered (FilterTest    *fixture,
+                                    gconstpointer  test_data)
+{
+  fixture->store = create_tree_store (3, FALSE);
+  fixture->filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture->store), NULL));
+
+  /* We need a tree view that's listening to get ref counting from that
+   * side.
+   */
+  fixture->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (fixture->filter));
+}
+
+static void
+filter_test_enable_filter (FilterTest *fixture)
+{
+  gtk_tree_model_filter_set_visible_column (fixture->filter, 1);
+}
+
+static void
+filter_test_teardown (FilterTest    *fixture,
+                      gconstpointer  test_data)
+{
+  g_object_unref (fixture->filter);
+  g_object_unref (fixture->store);
+}
+
+/*
+ * Model structure validation
+ */
+
+static void
+check_filter_model_recurse (FilterTest  *fixture,
+                            GtkTreePath *store_parent_path,
+                            GtkTreePath *filter_parent_path)
+{
+  int i;
+  GtkTreeIter store_iter;
+  GtkTreeIter filter_iter;
+  gboolean store_has_next, filter_has_next;
+
+  gtk_tree_path_down (store_parent_path);
+  gtk_tree_path_down (filter_parent_path);
+
+  store_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
+                                            &store_iter, store_parent_path);
+  filter_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->filter),
+                                             &filter_iter, filter_parent_path);
+
+  for (i = 0; i < LEVEL_LENGTH; i++)
+    {
+      gboolean visible;
+
+      g_return_if_fail (store_has_next == TRUE);
+
+      gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
+                          &store_iter,
+                          1, &visible,
+                          -1);
+
+      if (visible)
+        {
+          GtkTreePath *tmp;
+          gchar *filter_str, *store_str;
+
+          g_return_if_fail (filter_has_next == TRUE);
+
+          /* Verify path */
+          tmp = gtk_tree_model_get_path (GTK_TREE_MODEL (fixture->filter),
+                                         &filter_iter);
+          g_return_if_fail (gtk_tree_path_compare (tmp, filter_parent_path) == 0);
+
+          /* Verify model content */
+          gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
+                              &store_iter,
+                              0, &store_str,
+                              -1);
+          gtk_tree_model_get (GTK_TREE_MODEL (fixture->filter),
+                              &filter_iter,
+                              0, &filter_str,
+                              -1);
+
+          g_return_if_fail (g_strcmp0 (store_str, filter_str) == 0);
+
+          g_free (store_str);
+          g_free (filter_str);
+
+          if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->filter),
+                                             &filter_iter))
+            {
+              g_return_if_fail (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store), &store_iter));
+
+              check_filter_model_recurse (fixture,
+                                          gtk_tree_path_copy (store_parent_path),
+                                          tmp);
+            }
+
+          gtk_tree_path_next (filter_parent_path);
+          filter_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->filter), &filter_iter);
+        }
+
+      gtk_tree_path_next (store_parent_path);
+      store_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &store_iter);
+    }
+
+  /* Both models should have no more content! */
+  g_return_if_fail (store_has_next == FALSE);
+  g_return_if_fail (filter_has_next == FALSE);
+
+  gtk_tree_path_free (store_parent_path);
+  gtk_tree_path_free (filter_parent_path);
+}
+
+static void
+check_filter_model (FilterTest *fixture)
+{
+  GtkTreePath *path;
+
+  path = gtk_tree_path_new ();
+
+  check_filter_model_recurse (fixture, path, gtk_tree_path_copy (path));
+}
+
+/* Helpers */
+
+static void
+check_level_length (GtkTreeModelFilter *filter,
+                    const gchar        *level,
+                    const int           length)
+{
+  if (!level)
+    {
+      int l = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), NULL);
+      g_return_if_fail (l == length);
+    }
+  else
+    {
+      int l;
+      GtkTreeIter iter;
+
+      gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (filter),
+                                           &iter, level);
+      l = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), &iter);
+      g_return_if_fail (l == length);
+    }
+}
+
+static void
+set_path_visibility (FilterTest  *fixture,
+                     const gchar *path,
+                     gboolean     visible)
+{
+  GtkTreeIter store_iter;
+
+  gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
+                                       &store_iter, path);
+  gtk_tree_store_set (fixture->store, &store_iter,
+                      1, visible,
+                      -1);
+}
+
+/*
+ * The actual tests.
+ */
+
+static void
+verify_test_suite (FilterTest    *fixture,
+                   gconstpointer  user_data)
+{
+  check_filter_model (fixture);
+}
+
+
+static void
+filled_hide_root_level (FilterTest    *fixture,
+                        gconstpointer  user_data)
+{
+  set_path_visibility (fixture, "2", FALSE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
+
+  set_path_visibility (fixture, "0", FALSE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
+
+  set_path_visibility (fixture, "4", FALSE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
+
+
+  /* Hide remaining */
+  set_path_visibility (fixture, "1", FALSE);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
+
+  set_path_visibility (fixture, "3", FALSE);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 5);
+
+  check_filter_model (fixture);
+
+  /* Show some */
+  set_path_visibility (fixture, "1", TRUE);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
+
+  set_path_visibility (fixture, "3", TRUE);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
+
+  check_filter_model (fixture);
+}
+
+static void
+filled_hide_child_levels (FilterTest    *fixture,
+                          gconstpointer  user_data)
+{
+  set_path_visibility (fixture, "0:2", FALSE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+  check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
+
+  set_path_visibility (fixture, "0:4", FALSE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+  check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
+
+  set_path_visibility (fixture, "0:4:3", FALSE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+  check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
+
+  set_path_visibility (fixture, "0:4:0", FALSE);
+  set_path_visibility (fixture, "0:4:1", FALSE);
+  set_path_visibility (fixture, "0:4:2", FALSE);
+  set_path_visibility (fixture, "0:4:4", FALSE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+  check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
+
+  set_path_visibility (fixture, "0:4", TRUE);
+  /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, "0:3", 0);
+
+  set_path_visibility (fixture, "0:2", TRUE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
+  check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
+  check_level_length (fixture->filter, "0:4", 0);
+
+  set_path_visibility (fixture, "0:4:2", TRUE);
+  set_path_visibility (fixture, "0:4:4", TRUE);
+  check_level_length (fixture->filter, "0:4", 2);
+}
+
+static void
+empty_show_nodes (FilterTest    *fixture,
+                  gconstpointer  user_data)
+{
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, 0);
+
+  set_path_visibility (fixture, "3", TRUE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, 1);
+  check_level_length (fixture->filter, "0", 0);
+
+  set_path_visibility (fixture, "3:2:2", TRUE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, 1);
+  check_level_length (fixture->filter, "0", 0);
+
+  set_path_visibility (fixture, "3:2", TRUE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, 1);
+  check_level_length (fixture->filter, "0", 1);
+  check_level_length (fixture->filter, "0:0", 1);
+  check_level_length (fixture->filter, "0:0:0", 0);
+
+  set_path_visibility (fixture, "3", FALSE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, 0);
+
+  set_path_visibility (fixture, "3:2:1", TRUE);
+  set_path_visibility (fixture, "3", TRUE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, 1);
+  check_level_length (fixture->filter, "0", 1);
+  check_level_length (fixture->filter, "0:0", 2);
+  check_level_length (fixture->filter, "0:0:0", 0);
+}
+
+
+static void
+unfiltered_hide_single (FilterTest    *fixture,
+                        gconstpointer  user_data)
+
+{
+  set_path_visibility (fixture, "2", FALSE);
+
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+
+  filter_test_enable_filter (fixture);
+
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
+}
+
+static void
+unfiltered_hide_single_child (FilterTest    *fixture,
+                              gconstpointer  user_data)
+
+{
+  set_path_visibility (fixture, "2:2", FALSE);
+
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+  check_level_length (fixture->filter, "2", LEVEL_LENGTH);
+
+  filter_test_enable_filter (fixture);
+
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+  check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
+}
+
+static void
+unfiltered_hide_single_multi_level (FilterTest    *fixture,
+                                    gconstpointer  user_data)
+
+{
+  set_path_visibility (fixture, "2:2:2", FALSE);
+  set_path_visibility (fixture, "2:2", FALSE);
+
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+  check_level_length (fixture->filter, "2", LEVEL_LENGTH);
+  check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
+
+  filter_test_enable_filter (fixture);
+
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+  check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
+
+  set_path_visibility (fixture, "2:2", TRUE);
+
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+  check_level_length (fixture->filter, "2", LEVEL_LENGTH);
+  check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
+}
+
+
+static void
+unfiltered_show_single (FilterTest    *fixture,
+                        gconstpointer  user_data)
+
+{
+  set_path_visibility (fixture, "2", TRUE);
+
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+
+  filter_test_enable_filter (fixture);
+
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, 1);
+}
+
+static void
+unfiltered_show_single_child (FilterTest    *fixture,
+                              gconstpointer  user_data)
+
+{
+  set_path_visibility (fixture, "2:2", TRUE);
+
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+  check_level_length (fixture->filter, "2", LEVEL_LENGTH);
+
+  filter_test_enable_filter (fixture);
+
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, 0);
+
+  set_path_visibility (fixture, "2", TRUE);
+  check_level_length (fixture->filter, NULL, 1);
+  check_level_length (fixture->filter, "2", 1);
+}
+
+static void
+unfiltered_show_single_multi_level (FilterTest    *fixture,
+                                    gconstpointer  user_data)
+
+{
+  set_path_visibility (fixture, "2:2:2", TRUE);
+  set_path_visibility (fixture, "2:2", TRUE);
+
+  check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+  check_level_length (fixture->filter, "2", LEVEL_LENGTH);
+  check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
+
+  filter_test_enable_filter (fixture);
+
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, 0);
+
+  set_path_visibility (fixture, "2", TRUE);
+  check_filter_model (fixture);
+  check_level_length (fixture->filter, NULL, 1);
+  check_level_length (fixture->filter, "2", 1);
+  check_level_length (fixture->filter, "2:2", 1);
+}
+
+
+static gboolean
+specific_path_dependent_filter_func (GtkTreeModel *model,
+                                     GtkTreeIter  *iter,
+                                     gpointer      data)
+{
+  GtkTreePath *path;
+
+  path = gtk_tree_model_get_path (model, iter);
+  if (gtk_tree_path_get_indices (path)[0] < 4)
+    return FALSE;
+
+  return TRUE;
+}
+
+static void
+specific_path_dependent_filter (void)
+{
+  int i;
+  GtkTreeIter iter;
+  GtkListStore *list;
+  GtkTreeModel *sort;
+  GtkTreeModel *filter;
+
+  list = gtk_list_store_new (1, G_TYPE_INT);
+  gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
+  gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
+  gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
+  gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
+  gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
+  gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
+  gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
+  gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
+
+  sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (list));
+  filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (sort), NULL);
+  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
+                                          specific_path_dependent_filter_func,
+                                          NULL, NULL);
+
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort), 0,
+                                        GTK_SORT_DESCENDING);
+
+  for (i = 0; i < 4; i++)
+    {
+      if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
+                                         NULL, 1))
+        gtk_list_store_remove (list, &iter);
+
+      if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
+                                         NULL, 2))
+        gtk_list_store_remove (list, &iter);
+    }
+}
+
+
+static gboolean
+specific_append_after_collapse_visible_func (GtkTreeModel *model,
+                                             GtkTreeIter  *iter,
+                                             gpointer      data)
+{
+  gint number;
+  gboolean hide_negative_numbers;
+
+  gtk_tree_model_get (model, iter, 1, &number, -1);
+  hide_negative_numbers = GPOINTER_TO_INT (g_object_get_data (data, "private-hide-negative-numbers"));
+
+  return (number >= 0 || !hide_negative_numbers);
+}
+
+static void
+specific_append_after_collapse (void)
+{
+  /* This test is based on one of the test cases I found in my
+   * old test cases directory.  I unfortunately do not have a record
+   * from who this test case originated.  -Kris.
+   *
+   * General idea:
+   * - Construct tree.
+   * - Show tree, expand, collapse.
+   * - Add a row.
+   */
+
+  GtkTreeIter iter;
+  GtkTreeIter child_iter;
+  GtkTreeIter child_iter2;
+  GtkTreePath *append_path;
+  GtkTreeStore *store;
+  GtkTreeModel *filter;
+  GtkTreeModel *sort;
+
+  GtkWidget *window;
+  GtkWidget *tree_view;
+
+  store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT);
+
+  filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
+  g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
+                     GINT_TO_POINTER (FALSE));
+  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
+                                          specific_append_after_collapse_visible_func,
+                                          filter, NULL);
+
+  sort = gtk_tree_model_sort_new_with_model (filter);
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  tree_view = gtk_tree_view_new_with_model (sort);
+  gtk_container_add (GTK_CONTAINER (window), tree_view);
+  gtk_widget_realize (tree_view);
+
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+
+  gtk_tree_store_prepend (store, &iter, NULL);
+  gtk_tree_store_set (store, &iter,
+                      0, "hallo", 1, 1, -1);
+
+  gtk_tree_store_append (store, &child_iter, &iter);
+  gtk_tree_store_set (store, &child_iter,
+                      0, "toemaar", 1, 1, -1);
+
+  gtk_tree_store_append (store, &child_iter2, &child_iter);
+  gtk_tree_store_set (store, &child_iter2,
+                      0, "very deep", 1, 1, -1);
+
+  append_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &child_iter2);
+
+  gtk_tree_store_append (store, &child_iter, &iter);
+  gtk_tree_store_set (store, &child_iter,
+                      0, "sja", 1, 1, -1);
+
+  gtk_tree_store_append (store, &child_iter, &iter);
+  gtk_tree_store_set (store, &child_iter,
+                      0, "some word", 1, -1, -1);
+
+  /* Expand and collapse the tree */
+  gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+
+  gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+
+  /* Add another it */
+  g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
+                     GINT_TO_POINTER (TRUE));
+
+  if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, append_path))
+    {
+      gtk_tree_store_append (store, &child_iter, &iter);
+      gtk_tree_store_set (store, &child_iter,
+                          0, "new new new !!", 1, 1, -1);
+    }
+  gtk_tree_path_free (append_path);
+
+  /* Expand */
+  gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+}
+
+
+static gint
+specific_sort_filter_remove_node_compare_func (GtkTreeModel  *model,
+                                               GtkTreeIter   *iter1,
+                                               GtkTreeIter   *iter2,
+                                               gpointer       data)
+{
+  return -1;
+}
+
+static gboolean
+specific_sort_filter_remove_node_visible_func (GtkTreeModel  *model,
+                                               GtkTreeIter   *iter,
+                                               gpointer       data)
+{
+  char *item = NULL;
+
+  /* Do reference the model */
+  gtk_tree_model_get (model, iter, 0, &item, -1);
+  g_free (item);
+
+  return FALSE;
+}
+
+static void
+specific_sort_filter_remove_node (void)
+{
+  /* This test is based on one of the test cases I found in my
+   * old test cases directory.  I unfortunately do not have a record
+   * from who this test case originated.  -Kris.
+   *
+   * General idea:
+   *  - Create tree store, sort, filter models.  The sort model has
+   *    a default sort func that is enabled, filter model a visible func
+   *    that defaults to returning FALSE.
+   *  - Remove a node from the tree store.
+   */
+
+  GtkTreeIter iter;
+  GtkTreeStore *store;
+  GtkTreeModel *filter;
+  GtkTreeModel *sort;
+
+  GtkWidget *window;
+  GtkWidget *tree_view;
+
+  store = gtk_tree_store_new (1, G_TYPE_STRING);
+  gtk_tree_store_append (store, &iter, NULL);
+  gtk_tree_store_set (store, &iter, 0, "Hello1", -1);
+
+  gtk_tree_store_append (store, &iter, NULL);
+  gtk_tree_store_set (store, &iter, 0, "Hello2", -1);
+
+  sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
+  gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
+                                           specific_sort_filter_remove_node_compare_func, NULL, NULL);
+
+  filter = gtk_tree_model_filter_new (sort, NULL);
+  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
+                                          specific_sort_filter_remove_node_visible_func,
+                                          filter, NULL);
+
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  tree_view = gtk_tree_view_new_with_model (filter);
+  gtk_container_add (GTK_CONTAINER (window), tree_view);
+  gtk_widget_realize (tree_view);
+
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+
+  /* Remove a node */
+  gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
+  gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
+  gtk_tree_store_remove (store, &iter);
+
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+}
+
+
+static void
+specific_sort_filter_remove_root (void)
+{
+  /* This test is based on one of the test cases I found in my
+   * old test cases directory.  I unfortunately do not have a record
+   * from who this test case originated.  -Kris.
+   */
+
+  GtkTreeModel *model, *sort, *filter;
+  GtkTreeIter root, mid, leaf;
+  GtkTreePath *path;
+
+  model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_INT));
+  gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
+  gtk_tree_store_append (GTK_TREE_STORE (model), &mid, &root);
+  gtk_tree_store_append (GTK_TREE_STORE (model), &leaf, &mid);
+
+  path = gtk_tree_model_get_path (model, &mid);
+
+  sort = gtk_tree_model_sort_new_with_model (model);
+  filter = gtk_tree_model_filter_new (sort, path);
+
+  gtk_tree_store_remove (GTK_TREE_STORE (model), &root);
+
+  g_object_unref (filter);
+  g_object_unref (sort);
+  g_object_unref (model);
+}
+
+
+static void
+specific_filter_add_child (void)
+{
+  /* This test is based on one of the test cases I found in my
+   * old test cases directory.  I unfortunately do not have a record
+   * from who this test case originated.  -Kris.
+   */
+
+  GtkTreeIter iter;
+  GtkTreeIter iter_first;
+  GtkTreeIter child;
+  GtkTreeStore *store;
+  GtkTreeModel *filter;
+
+  store = gtk_tree_store_new (1, G_TYPE_STRING);
+
+  gtk_tree_store_append (store, &iter_first, NULL);
+  gtk_tree_store_set (store, &iter_first, 0, "Hello", -1);
+
+  gtk_tree_store_append (store, &iter, NULL);
+  gtk_tree_store_set (store, &iter, 0, "Hello", -1);
+
+  gtk_tree_store_append (store, &iter, NULL);
+  gtk_tree_store_set (store, &iter, 0, "Hello", -1);
+
+  gtk_tree_store_append (store, &iter, NULL);
+  gtk_tree_store_set (store, &iter, 0, "Hello", -1);
+
+  filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
+
+  gtk_tree_store_set (store, &iter, 0, "Hello", -1);
+  gtk_tree_store_append (store, &child, &iter_first);
+  gtk_tree_store_set (store, &child, 0, "Hello", -1);
+}
+
+
+static void
+specific_bug_300089 (void)
+{
+  /* Test case for GNOME Bugzilla bug 300089.  Written by
+   * Matthias Clasen.
+   */
+  GtkTreeModel *sort_model, *child_model;
+  GtkTreePath *path;
+  GtkTreeIter iter, iter2, sort_iter;
+
+  child_model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_STRING));
+
+  gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter, NULL);
+  gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "A", -1);
+  gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter, NULL);
+  gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "B", -1);
+
+  gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter2, &iter);
+  gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter2, 0, "D", -1);
+  gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter2, &iter);
+  gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter2, 0, "E", -1);
+
+  gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter, NULL);
+  gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "C", -1);
+
+
+  sort_model = GTK_TREE_MODEL (gtk_tree_model_sort_new_with_model (child_model));
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
+                                        0, GTK_SORT_ASCENDING);
+
+  path = gtk_tree_path_new_from_indices (1, 1, -1);
+
+  /* make sure a level is constructed */ 
+  gtk_tree_model_get_iter (sort_model, &sort_iter, path);
+
+  /* change the "E" row in a way that causes it to change position */ 
+  gtk_tree_model_get_iter (child_model, &iter, path);
+  gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "A", -1);
+}
+
+
+static int
+specific_bug_301558_sort_func (GtkTreeModel *model,
+                               GtkTreeIter  *a,
+                               GtkTreeIter  *b,
+                               gpointer      data)
+{
+  int i, j;
+
+  gtk_tree_model_get (model, a, 0, &i, -1);
+  gtk_tree_model_get (model, b, 0, &j, -1);
+
+  return j - i;
+}
+
+static void
+specific_bug_301558 (void)
+{
+  /* Test case for GNOME Bugzilla bug 301558 provided by
+   * Markku Vire.
+   */
+  GtkTreeStore *tree;
+  GtkTreeModel *filter;
+  GtkTreeModel *sort;
+  GtkTreeIter root, iter, iter2;
+  GtkWidget *view;
+  int i;
+  gboolean add;
+
+  tree = gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_BOOLEAN);
+  gtk_tree_store_append (tree, &iter, NULL);
+  gtk_tree_store_set (tree, &iter, 0, 123, 1, TRUE, -1);
+  gtk_tree_store_append (tree, &iter2, &iter);
+  gtk_tree_store_set (tree, &iter2, 0, 73, 1, TRUE, -1);
+
+  sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
+  gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
+                                           specific_bug_301558_sort_func,
+                                           NULL, NULL);
+
+  filter = gtk_tree_model_filter_new (sort, NULL);
+  gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter), 1);
+
+  view = gtk_tree_view_new_with_model (filter);
+
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+
+  add = TRUE;
+
+  for (i = 0; i < 10; i++)
+    {
+      if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree), &root))
+        g_assert_not_reached ();
+
+      if (add)
+        {
+          gtk_tree_store_append (tree, &iter, &root);
+          gtk_tree_store_set (tree, &iter, 0, 456, 1, TRUE, -1);
+        }
+      else
+        {
+          int n;
+          n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree), &root);
+          gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (tree), &iter,
+                                         &root, n - 1);
+          gtk_tree_store_remove (tree, &iter);
+        }
+
+      add = !add;
+    }
+}
+
+
+static gboolean
+specific_bug_311955_filter_func (GtkTreeModel *model,
+                                 GtkTreeIter  *iter,
+                                 gpointer      data)
+{
+  int value;
+
+  gtk_tree_model_get (model, iter, 0, &value, -1);
+
+  return (value != 0);
+}
+
+static void
+specific_bug_311955 (void)
+{
+  /* This is a test case for GNOME Bugzilla bug 311955.  It was written
+   * by Markku Vire.
+   */
+  GtkTreeIter iter, child, root;
+  GtkTreeStore *store;
+  GtkTreeModel *sort;
+  GtkTreeModel *filter;
+
+  GtkWidget *window;
+  GtkWidget *tree_view;
+  int i;
+  int n;
+
+  store = gtk_tree_store_new (1, G_TYPE_INT);
+
+  gtk_tree_store_append (store, &root, NULL);
+  gtk_tree_store_set (store, &root, 0, 33, -1);
+
+  gtk_tree_store_append (store, &iter, &root);
+  gtk_tree_store_set (store, &iter, 0, 50, -1);
+
+  gtk_tree_store_append (store, &iter, NULL);
+  gtk_tree_store_set (store, &iter, 0, 22, -1);
+
+  sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
+  filter = gtk_tree_model_filter_new (sort, NULL);
+
+  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
+                                          specific_bug_311955_filter_func,
+                                          NULL, NULL);
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  tree_view = gtk_tree_view_new_with_model (filter);
+  g_object_unref (store);
+
+  gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
+
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+
+  /* Fill model */
+  for (i = 0; i < 4; i++)
+    {
+      gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
+
+      gtk_tree_store_append (store, &iter, &root);
+
+      if (i < 3)
+        gtk_tree_store_set (store, &iter, 0, i, -1);
+
+      if (i % 2 == 0)
+        {
+          gtk_tree_store_append (store, &child, &iter);
+          gtk_tree_store_set (store, &child, 0, 10, -1);
+        }
+    }
+
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+
+  /* Remove bottommost child from the tree. */
+  gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
+  n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), &root);
+
+  if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, &root, n - 2))
+    {
+      if (gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &child, &iter))
+        gtk_tree_store_remove (store, &child);
+    }
+  else
+    g_assert_not_reached ();
+}
+
+static void
+specific_bug_346800 (void)
+{
+  /* This is a test case for GNOME Bugzilla bug 346800.  It was written
+   * by Jonathan Matthew.
+   */
+
+  GtkTreeIter node_iters[50];
+  GtkTreeIter child_iters[50];
+  GtkTreeModel *model;
+  GtkTreeModelFilter *filter;
+  GtkTreeStore *store;
+  GType *columns;
+  int i;
+  int items = 50;
+  columns = g_new (GType, 2);
+  columns[0] = G_TYPE_STRING;
+  columns[1] = G_TYPE_BOOLEAN;
+  store = gtk_tree_store_newv (2, columns);
+  model = GTK_TREE_MODEL (store);
+
+  filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
+  gtk_tree_model_filter_set_visible_column (filter, 1);
+
+  for (i=0; i<items; i++)
+    {
+      /* allocate random amounts of junk, otherwise the filter model's arrays can expand without moving */
+
+      g_malloc (138);
+      gtk_tree_store_append (store, &node_iters[i], NULL);
+      gtk_tree_store_set (store, &node_iters[i],
+                          0, "something",
+                          1, ((i%6) == 0) ? FALSE : TRUE,
+                          -1);
+
+      g_malloc (47);
+      gtk_tree_store_append (store, &child_iters[i], &node_iters[i]);
+      gtk_tree_store_set (store, &child_iters[i],
+                          0, "something else",
+                          1, FALSE,
+                          -1);
+      gtk_tree_model_filter_refilter (filter);
+
+      if (i > 6)
+        {
+          gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-1], 1,
+                              (i & 1) ? TRUE : FALSE, -1);
+          gtk_tree_model_filter_refilter (filter);
+
+          gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-2], 1,
+                              (i & 1) ? FALSE: TRUE, -1);
+          gtk_tree_model_filter_refilter (filter);
+        }
+    }
+}
+
+
+static void
+specific_bug_364946 (void)
+{
+  /* This is a test case for GNOME Bugzilla bug 364946.  It was written
+   * by Andreas Koehler.
+   */
+  GtkTreeStore *store;
+  GtkTreeIter a, aa, aaa, aab, iter;
+  GtkTreeModel *s_model;
+
+  store = gtk_tree_store_new (1, G_TYPE_STRING);
+
+  gtk_tree_store_append (store, &a, NULL);
+  gtk_tree_store_set (store, &a, 0, "0", -1);
+
+  gtk_tree_store_append (store, &aa, &a);
+  gtk_tree_store_set (store, &aa, 0, "0:0", -1);
+
+  gtk_tree_store_append (store, &aaa, &aa);
+  gtk_tree_store_set (store, &aaa, 0, "0:0:0", -1);
+
+  gtk_tree_store_append (store, &aab, &aa);
+  gtk_tree_store_set (store, &aab, 0, "0:0:1", -1);
+
+  s_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (s_model), 0,
+                                        GTK_SORT_ASCENDING);
+
+  gtk_tree_model_get_iter_from_string (s_model, &iter, "0:0:0");
+
+  gtk_tree_store_set (store, &aaa, 0, "0:0:0", -1);
+  gtk_tree_store_remove (store, &aaa);
+  gtk_tree_store_remove (store, &aab);
+
+  gtk_tree_model_sort_clear_cache (GTK_TREE_MODEL_SORT (s_model));
+}
+
+/* main */
+
+int
+main (int    argc,
+      char **argv)
+{
+  gtk_test_init (&argc, &argv, NULL);
+
+  g_test_add ("/FilterModel/self/verify-test-suite",
+              FilterTest, NULL,
+              filter_test_setup,
+              verify_test_suite,
+              filter_test_teardown);
+
+  g_test_add ("/FilterModel/filled/hide-root-level",
+              FilterTest, NULL,
+              filter_test_setup,
+              filled_hide_root_level,
+              filter_test_teardown);
+  g_test_add ("/FilterModel/filled/hide-child-levels",
+              FilterTest, NULL,
+              filter_test_setup,
+              filled_hide_child_levels,
+              filter_test_teardown);
+
+  g_test_add ("/FilterModel/empty/show-nodes",
+              FilterTest, NULL,
+              filter_test_setup_empty,
+              empty_show_nodes,
+              filter_test_teardown);
+
+  g_test_add ("/FilterModel/unfiltered/hide-single",
+              FilterTest, NULL,
+              filter_test_setup_unfiltered,
+              unfiltered_hide_single,
+              filter_test_teardown);
+  g_test_add ("/FilterModel/unfiltered/hide-single-child",
+              FilterTest, NULL,
+              filter_test_setup_unfiltered,
+              unfiltered_hide_single_child,
+              filter_test_teardown);
+  g_test_add ("/FilterModel/unfiltered/hide-single-multi-level",
+              FilterTest, NULL,
+              filter_test_setup_unfiltered,
+              unfiltered_hide_single_multi_level,
+              filter_test_teardown);
+
+  g_test_add ("/FilterModel/unfiltered/show-single",
+              FilterTest, NULL,
+              filter_test_setup_empty_unfiltered,
+              unfiltered_show_single,
+              filter_test_teardown);
+  g_test_add ("/FilterModel/unfiltered/show-single-child",
+              FilterTest, NULL,
+              filter_test_setup_empty_unfiltered,
+              unfiltered_show_single_child,
+              filter_test_teardown);
+  g_test_add ("/FilterModel/unfiltered/show-single-multi-level",
+              FilterTest, NULL,
+              filter_test_setup_empty_unfiltered,
+              unfiltered_show_single_multi_level,
+              filter_test_teardown);
+
+
+  g_test_add_func ("/FilterModel/specific/path-dependent-filter",
+                   specific_path_dependent_filter);
+  g_test_add_func ("/FilterModel/specific/append-after-collapse",
+                   specific_append_after_collapse);
+  g_test_add_func ("/FilterModel/specific/sort-filter-remove-node",
+                   specific_sort_filter_remove_node);
+  g_test_add_func ("/FilterModel/specific/sort-filter-remove-root",
+                   specific_sort_filter_remove_root);
+  g_test_add_func ("/FilterModel/specific/filter-add-child",
+                   specific_filter_add_child);
+
+  g_test_add_func ("/FilterModel/specific/bug-300089",
+                   specific_bug_300089);
+  g_test_add_func ("/FilterModel/specific/bug-301558",
+                   specific_bug_301558);
+  g_test_add_func ("/FilterModel/specific/bug-311955",
+                   specific_bug_311955);
+  g_test_add_func ("/FilterModel/specific/bug-346800",
+                   specific_bug_346800);
+  g_test_add_func ("/FilterModel/specific/bug-364946",
+                   specific_bug_364946);
+
+  return g_test_run ();
+}



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