summaryrefslogtreecommitdiff
path: root/gtk/tests/treemodel.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/tests/treemodel.c')
-rw-r--r--gtk/tests/treemodel.c347
1 files changed, 347 insertions, 0 deletions
diff --git a/gtk/tests/treemodel.c b/gtk/tests/treemodel.c
new file mode 100644
index 0000000000..97bbc14b27
--- /dev/null
+++ b/gtk/tests/treemodel.c
@@ -0,0 +1,347 @@
+/* Main wrapper for TreeModel test suite.
+ * 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 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>
+
+#include "treemodel.h"
+
+int
+main (int argc,
+ char **argv)
+{
+ gtk_test_init (&argc, &argv, NULL);
+
+ g_test_bug_base ("http://bugzilla.gnome.org/");
+
+ register_list_store_tests ();
+ register_tree_store_tests ();
+ register_model_ref_count_tests ();
+ register_sort_model_tests ();
+ register_filter_model_tests ();
+
+ return g_test_run ();
+}
+
+/*
+ * Signal monitor
+ */
+
+static const char *
+signal_name_to_string (SignalName signal)
+{
+ switch (signal)
+ {
+ case ROW_INSERTED:
+ return "row-inserted";
+
+ case ROW_DELETED:
+ return "row-deleted";
+
+ case ROW_CHANGED:
+ return "row-changed";
+
+ case ROW_HAS_CHILD_TOGGLED:
+ return "row-has-child-toggled";
+
+ case ROWS_REORDERED:
+ return "rows-reordered";
+
+ default:
+ /* Fall through */
+ break;
+ }
+
+ return "(unknown)";
+}
+
+typedef struct
+{
+ SignalName signal;
+ GtkTreePath *path;
+
+ /* For rows-reordered */
+ int *new_order;
+ int len;
+}
+Signal;
+
+
+static Signal *
+signal_new (SignalName signal, GtkTreePath *path)
+{
+ Signal *s;
+
+ s = g_new0 (Signal, 1);
+ s->signal = signal;
+ s->path = gtk_tree_path_copy (path);
+ s->new_order = NULL;
+
+ return s;
+}
+
+static Signal *
+signal_new_with_order (SignalName signal, GtkTreePath *path,
+ int *new_order, int len)
+{
+ Signal *s = signal_new (signal, path);
+
+ s->new_order = new_order;
+ s->len = len;
+
+ return s;
+}
+
+static void
+signal_free (Signal *s)
+{
+ if (s->path)
+ gtk_tree_path_free (s->path);
+
+ g_free (s);
+}
+
+
+struct _SignalMonitor
+{
+ GQueue *queue;
+ GtkTreeModel *client;
+ gulong signal_ids[LAST_SIGNAL];
+};
+
+
+static void
+signal_monitor_generic_handler (SignalMonitor *m,
+ SignalName signal,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkTreePath *path,
+ int *new_order)
+{
+ Signal *s;
+
+ if (g_queue_is_empty (m->queue))
+ {
+ gchar *path_str;
+
+ path_str = gtk_tree_path_to_string (path);
+ g_error ("Signal queue empty, got signal %s path %s\n",
+ signal_name_to_string (signal), path_str);
+ g_free (path_str);
+
+ g_assert_not_reached ();
+ }
+
+ if (m->client != model)
+ {
+ g_error ("Model mismatch; expected %p, got %p\n",
+ m->client, model);
+ g_assert_not_reached ();
+ }
+
+ s = g_queue_peek_tail (m->queue);
+
+#if 0
+ /* For debugging: output signals that are coming in. Leaks memory. */
+ g_print ("signal=%s path=%s\n", signal_name_to_string (signal),
+ gtk_tree_path_to_string (path));
+#endif
+
+ if (s->signal != signal ||
+ (gtk_tree_path_get_depth (s->path) == 0 &&
+ gtk_tree_path_get_depth (path) != 0) ||
+ (gtk_tree_path_get_depth (s->path) != 0 &&
+ gtk_tree_path_compare (s->path, path) != 0))
+ {
+ gchar *path_str, *s_path_str;
+
+ s_path_str = gtk_tree_path_to_string (s->path);
+ path_str = gtk_tree_path_to_string (path);
+
+ g_error ("Signals don't match; expected signal %s path %s, got signal %s path %s\n",
+ signal_name_to_string (s->signal), s_path_str,
+ signal_name_to_string (signal), path_str);
+
+ g_free (s_path_str);
+ g_free (path_str);
+
+ g_assert_not_reached ();
+ }
+
+ if (signal == ROWS_REORDERED && s->new_order != NULL)
+ {
+ int i, len;
+
+ g_assert (new_order != NULL);
+
+ len = gtk_tree_model_iter_n_children (model, iter);
+ g_assert (s->len == len);
+
+ for (i = 0; i < len; i++)
+ g_assert (s->new_order[i] == new_order[i]);
+ }
+
+ s = g_queue_pop_tail (m->queue);
+
+ signal_free (s);
+}
+
+static void
+signal_monitor_row_inserted (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ signal_monitor_generic_handler (data, ROW_INSERTED,
+ model, iter, path, NULL);
+}
+
+static void
+signal_monitor_row_deleted (GtkTreeModel *model,
+ GtkTreePath *path,
+ gpointer data)
+{
+ signal_monitor_generic_handler (data, ROW_DELETED,
+ model, NULL, path, NULL);
+}
+
+static void
+signal_monitor_row_changed (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ signal_monitor_generic_handler (data, ROW_CHANGED,
+ model, iter, path, NULL);
+}
+
+static void
+signal_monitor_row_has_child_toggled (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ signal_monitor_generic_handler (data, ROW_HAS_CHILD_TOGGLED,
+ model, iter, path, NULL);
+}
+
+static void
+signal_monitor_rows_reordered (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gint *new_order,
+ gpointer data)
+{
+ signal_monitor_generic_handler (data, ROWS_REORDERED,
+ model, iter, path, new_order);
+}
+
+SignalMonitor *
+signal_monitor_new (GtkTreeModel *client)
+{
+ SignalMonitor *m;
+
+ m = g_new0 (SignalMonitor, 1);
+ m->client = g_object_ref (client);
+ m->queue = g_queue_new ();
+
+ m->signal_ids[ROW_INSERTED] = g_signal_connect (client,
+ "row-inserted",
+ G_CALLBACK (signal_monitor_row_inserted),
+ m);
+ m->signal_ids[ROW_DELETED] = g_signal_connect (client,
+ "row-deleted",
+ G_CALLBACK (signal_monitor_row_deleted),
+ m);
+ m->signal_ids[ROW_CHANGED] = g_signal_connect (client,
+ "row-changed",
+ G_CALLBACK (signal_monitor_row_changed),
+ m);
+ m->signal_ids[ROW_HAS_CHILD_TOGGLED] = g_signal_connect (client,
+ "row-has-child-toggled",
+ G_CALLBACK (signal_monitor_row_has_child_toggled),
+ m);
+ m->signal_ids[ROWS_REORDERED] = g_signal_connect (client,
+ "rows-reordered",
+ G_CALLBACK (signal_monitor_rows_reordered),
+ m);
+
+ return m;
+}
+
+void
+signal_monitor_free (SignalMonitor *m)
+{
+ int i;
+
+ for (i = 0; i < LAST_SIGNAL; i++)
+ g_signal_handler_disconnect (m->client, m->signal_ids[i]);
+
+ g_object_unref (m->client);
+
+ if (m->queue)
+ g_queue_free (m->queue);
+
+ g_free (m);
+}
+
+void
+signal_monitor_assert_is_empty (SignalMonitor *m)
+{
+ g_assert (g_queue_is_empty (m->queue));
+}
+
+void
+signal_monitor_append_signal_path (SignalMonitor *m,
+ SignalName signal,
+ GtkTreePath *path)
+{
+ Signal *s;
+
+ s = signal_new (signal, path);
+ g_queue_push_head (m->queue, s);
+}
+
+void
+signal_monitor_append_signal_reordered (SignalMonitor *m,
+ SignalName signal,
+ GtkTreePath *path,
+ int *new_order,
+ int len)
+{
+ Signal *s;
+
+ s = signal_new_with_order (signal, path, new_order, len);
+ g_queue_push_head (m->queue, s);
+}
+
+void
+signal_monitor_append_signal (SignalMonitor *m,
+ SignalName signal,
+ const gchar *path_string)
+{
+ Signal *s;
+ GtkTreePath *path;
+
+ path = gtk_tree_path_new_from_string (path_string);
+
+ s = signal_new (signal, path);
+ g_queue_push_head (m->queue, s);
+
+ gtk_tree_path_free (path);
+}