return store;
}
+/*
+ * Signal monitor
+ */
+
+typedef enum
+{
+ ROW_INSERTED,
+ ROW_DELETED,
+ ROW_CHANGED,
+ ROW_HAS_CHILD_TOGGLED,
+ ROWS_REORDERED,
+ LAST_SIGNAL
+}
+SignalName;
+
+typedef struct
+{
+ SignalName signal;
+ GtkTreePath *path;
+}
+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);
+
+ return s;
+}
+
+static void
+signal_free (Signal *s)
+{
+ if (s->path)
+ gtk_tree_path_free (s->path);
+
+ g_free (s);
+}
+
+
+typedef struct
+{
+ GQueue *queue;
+ GtkTreeModel *client;
+ guint signal_ids[LAST_SIGNAL];
+}
+SignalMonitor;
+
+
+static void
+signal_monitor_generic_handler (SignalMonitor *m,
+ SignalName signal,
+ GtkTreeModel *model,
+ GtkTreePath *path)
+{
+ Signal *s;
+
+ g_return_if_fail (m->client == model);
+ g_return_if_fail (!g_queue_is_empty (m->queue));
+
+#if 0
+ /* For debugging: output signals that are coming in. Leaks memory. */
+ g_print ("signal=%d path=%s\n", signal, gtk_tree_path_to_string (path));
+#endif
+
+ s = g_queue_peek_tail (m->queue);
+
+ g_return_if_fail (s->signal == signal);
+
+ s = g_queue_pop_tail (m->queue);
+
+ g_return_if_fail (!gtk_tree_path_compare (path, s->path));
+
+ 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, path);
+}
+
+static void
+signal_monitor_row_deleted (GtkTreeModel *model,
+ GtkTreePath *path,
+ gpointer data)
+{
+ signal_monitor_generic_handler (data, ROW_DELETED,
+ model, path);
+}
+
+static void
+signal_monitor_row_changed (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ signal_monitor_generic_handler (data, ROW_CHANGED,
+ model, path);
+}
+
+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, path);
+}
+
+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, path);
+}
+
+static 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;
+}
+
+static 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);
+}
+
+static void
+signal_monitor_assert_is_empty (SignalMonitor *m)
+{
+ g_assert (g_queue_is_empty (m->queue));
+}
+
+static 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);
+}
+
+static 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);
+}
/*
* Fixture
GtkTreeStore *store;
GtkTreeModelFilter *filter;
+
+ SignalMonitor *monitor;
} FilterTest;
static void
* side.
*/
fixture->tree_view = gtk_tree_view_new_with_model (filter);
+
+ fixture->monitor = signal_monitor_new (filter);
}
static void
filter_test_setup_generic (fixture, test_data, 3, TRUE, TRUE);
}
+static GtkTreePath *
+strip_virtual_root (GtkTreePath *path,
+ GtkTreePath *root_path)
+{
+ GtkTreePath *real_path;
+
+ if (root_path)
+ {
+ int j;
+ int depth = gtk_tree_path_get_depth (path);
+ int root_depth = gtk_tree_path_get_depth (root_path);
+
+ real_path = gtk_tree_path_new ();
+
+ for (j = 0; j < depth - root_depth; j++)
+ gtk_tree_path_append_index (real_path,
+ gtk_tree_path_get_indices (path)[root_depth + j]);
+ }
+ else
+ real_path = gtk_tree_path_copy (path);
+
+ return real_path;
+}
+
+static void
+filter_test_append_refilter_signals_recurse (FilterTest *fixture,
+ GtkTreePath *store_path,
+ GtkTreePath *filter_path,
+ int depth,
+ GtkTreePath *root_path)
+{
+ int i;
+ int rows_deleted = 0;
+ GtkTreeIter iter;
+
+ gtk_tree_path_down (store_path);
+ gtk_tree_path_down (filter_path);
+
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
+ &iter, store_path);
+
+ for (i = 0; i < LEVEL_LENGTH; i++)
+ {
+ gboolean visible;
+ GtkTreePath *real_path;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (fixture->store), &iter,
+ 1, &visible,
+ -1);
+
+ if (root_path &&
+ (!gtk_tree_path_is_descendant (store_path, root_path)
+ || !gtk_tree_path_compare (store_path, root_path)))
+ {
+ if (!gtk_tree_path_compare (store_path, root_path))
+ {
+ if (depth > 1
+ && gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store),
+ &iter))
+ {
+ GtkTreePath *store_copy;
+ GtkTreePath *filter_copy;
+
+ store_copy = gtk_tree_path_copy (store_path);
+ filter_copy = gtk_tree_path_copy (filter_path);
+ filter_test_append_refilter_signals_recurse (fixture,
+ store_copy,
+ filter_copy,
+ depth - 1,
+ root_path);
+ gtk_tree_path_free (store_copy);
+ gtk_tree_path_free (filter_copy);
+ }
+ }
+
+ gtk_tree_path_next (store_path);
+ gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
+
+ if (visible)
+ gtk_tree_path_next (filter_path);
+
+ continue;
+ }
+
+ real_path = strip_virtual_root (filter_path, root_path);
+
+ if (visible)
+ {
+ /* This row will be inserted */
+ signal_monitor_append_signal_path (fixture->monitor, ROW_CHANGED,
+ real_path);
+ signal_monitor_append_signal_path (fixture->monitor,
+ ROW_HAS_CHILD_TOGGLED,
+ real_path);
+
+ if (depth > 1
+ && gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store),
+ &iter))
+ {
+ GtkTreePath *store_copy;
+ GtkTreePath *filter_copy;
+
+ store_copy = gtk_tree_path_copy (store_path);
+ filter_copy = gtk_tree_path_copy (filter_path);
+ filter_test_append_refilter_signals_recurse (fixture,
+ store_copy,
+ filter_copy,
+ depth - 1,
+ root_path);
+ gtk_tree_path_free (store_copy);
+ gtk_tree_path_free (filter_copy);
+ }
+
+ gtk_tree_path_next (filter_path);
+ }
+ else
+ {
+ /* This row will be deleted */
+ rows_deleted++;
+ signal_monitor_append_signal_path (fixture->monitor, ROW_DELETED,
+ real_path);
+ }
+
+ gtk_tree_path_free (real_path);
+
+ gtk_tree_path_next (store_path);
+ gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
+ }
+
+ if (rows_deleted == LEVEL_LENGTH
+ && gtk_tree_path_get_depth (filter_path) > 1)
+ {
+ GtkTreePath *real_path;
+
+ gtk_tree_path_up (store_path);
+ gtk_tree_path_up (filter_path);
+
+ /* A row-has-child-toggled will be emitted on the parent */
+ if (!root_path
+ || (root_path
+ && gtk_tree_path_is_descendant (store_path, root_path)
+ && gtk_tree_path_compare (store_path, root_path)))
+ {
+ real_path = strip_virtual_root (filter_path, root_path);
+ signal_monitor_append_signal_path (fixture->monitor,
+ ROW_HAS_CHILD_TOGGLED,
+ real_path);
+
+ gtk_tree_path_free (real_path);
+ }
+ }
+}
+
+static void
+filter_test_append_refilter_signals (FilterTest *fixture,
+ int depth)
+{
+ /* A special function that walks the tree store like the
+ * model validation functions below.
+ */
+ GtkTreePath *path;
+ GtkTreePath *filter_path;
+
+ path = gtk_tree_path_new ();
+ filter_path = gtk_tree_path_new ();
+ filter_test_append_refilter_signals_recurse (fixture,
+ path,
+ filter_path,
+ depth,
+ NULL);
+ gtk_tree_path_free (path);
+ gtk_tree_path_free (filter_path);
+}
+
+static void
+filter_test_append_refilter_signals_with_vroot (FilterTest *fixture,
+ int depth,
+ GtkTreePath *root_path)
+{
+ /* A special function that walks the tree store like the
+ * model validation functions below.
+ */
+ GtkTreePath *path;
+ GtkTreePath *filter_path;
+
+ path = gtk_tree_path_new ();
+ filter_path = gtk_tree_path_new ();
+ filter_test_append_refilter_signals_recurse (fixture,
+ path,
+ filter_path,
+ depth,
+ root_path);
+ gtk_tree_path_free (path);
+ gtk_tree_path_free (filter_path);
+}
+
static void
filter_test_enable_filter (FilterTest *fixture)
{
filter_test_teardown (FilterTest *fixture,
gconstpointer test_data)
{
+ signal_monitor_free (fixture->monitor);
+
g_object_unref (fixture->filter);
g_object_unref (fixture->store);
}
{
GtkTreePath *path;
+ if (fixture->monitor)
+ signal_monitor_assert_is_empty (fixture->monitor);
+
path = gtk_tree_path_new ();
check_filter_model_recurse (fixture, path, gtk_tree_path_copy (path));
check_filter_model_with_root (FilterTest *fixture,
GtkTreePath *path)
{
+ if (fixture->monitor)
+ signal_monitor_assert_is_empty (fixture->monitor);
+
check_filter_model_recurse (fixture,
gtk_tree_path_copy (path),
gtk_tree_path_new ());
filled_hide_root_level (FilterTest *fixture,
gconstpointer user_data)
{
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
set_path_visibility (fixture, "2", FALSE);
check_filter_model (fixture);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
set_path_visibility (fixture, "0", FALSE);
check_filter_model (fixture);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
set_path_visibility (fixture, "4", FALSE);
check_filter_model (fixture);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
/* Hide remaining */
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
+
set_path_visibility (fixture, "1", FALSE);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
check_filter_model (fixture);
/* Show some */
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
+
set_path_visibility (fixture, "1", TRUE);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
filled_hide_child_levels (FilterTest *fixture,
gconstpointer user_data)
{
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:2");
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);
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:3");
set_path_visibility (fixture, "0:4", FALSE);
check_filter_model (fixture);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
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 */
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:3");
+ /* FIXME: Actually, the filter model should not be emitted the
+ * row-has-child-toggled signal here. *However* an extraneous emission
+ * of this signal does not hurt and is allowed.
+ */
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:3");
+ set_path_visibility (fixture, "0:4", TRUE);
check_filter_model (fixture);
check_level_length (fixture->filter, "0:3", 0);
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:2");
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);
+ /* FIXME: We are missing a row-has-child-toggled signal for path "0:4" */
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:4:0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4:0");
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:4:1");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4:1");
+
set_path_visibility (fixture, "0:4:2", TRUE);
set_path_visibility (fixture, "0:4:4", TRUE);
+ signal_monitor_assert_is_empty (fixture->monitor);
check_level_length (fixture->filter, "0:4", 2);
}
check_filter_model_with_root (fixture, path);
/* Now test changes in the virtual root level */
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
set_path_visibility (fixture, "2:2", FALSE);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "3");
set_path_visibility (fixture, "2:4", FALSE);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "3");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "3");
set_path_visibility (fixture, "2:4", TRUE);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
set_path_visibility (fixture, "2:0", FALSE);
set_path_visibility (fixture, "2:1", FALSE);
set_path_visibility (fixture, "2:2", FALSE);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, 0);
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
set_path_visibility (fixture, "2:4", TRUE);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
set_path_visibility (fixture, "2:4", FALSE);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, 0);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, 0);
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
set_path_visibility (fixture, "2:0", TRUE);
set_path_visibility (fixture, "2:1", TRUE);
set_path_visibility (fixture, "2:2", TRUE);
{
GtkTreePath *path = (GtkTreePath *)user_data;
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:2");
set_path_visibility (fixture, "2:0:2", FALSE);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:3");
set_path_visibility (fixture, "2:0:4", FALSE);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
- set_path_visibility (fixture, "2:0:4", TRUE);
/* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:3");
+ /* FIXME: Actually, the filter model should not be emitted the
+ * row-has-child-toggled signal here. *However* an extraneous emission
+ * of this signal does not hurt and is allowed.
+ */
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:3");
+ set_path_visibility (fixture, "2:0:4", TRUE);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, "0:3", 0);
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:2");
set_path_visibility (fixture, "2:0:2", TRUE);
check_filter_model_with_root (fixture, path);
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);
+ /* FIXME: We are missing a row-has-child-toggled signal for path "0:4" */
+ /* FIXME: Inconsistency! For the non-vroot case we also receive two
+ * row-has-child-toggled signals here.
+ */
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:4:0");
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:4:1");
set_path_visibility (fixture, "2:0:4:2", TRUE);
set_path_visibility (fixture, "2:0:4:4", TRUE);
check_level_length (fixture->filter, "0:4", 2);
check_filter_model (fixture);
check_level_length (fixture->filter, NULL, 0);
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
set_path_visibility (fixture, "3", TRUE);
check_filter_model (fixture);
check_level_length (fixture->filter, NULL, 1);
check_level_length (fixture->filter, NULL, 1);
check_level_length (fixture->filter, "0", 0);
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "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:0", 1);
check_level_length (fixture->filter, "0:0:0", 0);
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
set_path_visibility (fixture, "3", FALSE);
check_filter_model (fixture);
check_level_length (fixture->filter, NULL, 0);
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
set_path_visibility (fixture, "3:2:1", TRUE);
set_path_visibility (fixture, "3", TRUE);
check_filter_model (fixture);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, 0);
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
set_path_visibility (fixture, "2:2", TRUE);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, 1);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, 1);
+ signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
set_path_visibility (fixture, "2:2", FALSE);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, 0);
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
set_path_visibility (fixture, "2:2:1", TRUE);
set_path_visibility (fixture, "2:2", TRUE);
check_filter_model_with_root (fixture, path);
gconstpointer user_data)
{
+ signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
set_path_visibility (fixture, "2", FALSE);
+ signal_monitor_assert_is_empty (fixture->monitor);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+ /* The view only shows the root level, so the filter model only has
+ * the first two levels cached.
+ */
+ filter_test_append_refilter_signals (fixture, 2);
filter_test_enable_filter (fixture);
check_filter_model (fixture);
gconstpointer user_data)
{
+ signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
set_path_visibility (fixture, "2:2", FALSE);
+ signal_monitor_assert_is_empty (fixture->monitor);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
check_level_length (fixture->filter, "2", LEVEL_LENGTH);
+ /* The view only shows the root level, so the filter model only has
+ * the first two levels cached.
+ */
+ filter_test_append_refilter_signals (fixture, 2);
filter_test_enable_filter (fixture);
check_filter_model (fixture);
gconstpointer user_data)
{
+ /* This row is not shown, so its signal is not propagated */
set_path_visibility (fixture, "2:2:2", FALSE);
+
+ signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
set_path_visibility (fixture, "2:2", FALSE);
+ signal_monitor_assert_is_empty (fixture->monitor);
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);
+ /* The view only shows the root level, so the filter model only has
+ * the first two levels cached.
+ */
+ filter_test_append_refilter_signals (fixture, 2);
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);
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2:2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
set_path_visibility (fixture, "2:2", TRUE);
check_filter_model (fixture);
{
GtkTreePath *path = (GtkTreePath *)user_data;
+ signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
set_path_visibility (fixture, "2:2", FALSE);
+ signal_monitor_assert_is_empty (fixture->monitor);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+ /* The view only shows the root level, so the filter model only has
+ * the first two levels cached. (We add an additional level to
+ * take the virtual root into account).
+ */
+ filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
filter_test_enable_filter (fixture);
check_filter_model_with_root (fixture, path);
{
GtkTreePath *path = (GtkTreePath *)user_data;
+ signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
set_path_visibility (fixture, "2:2:2", FALSE);
+ signal_monitor_assert_is_empty (fixture->monitor);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
check_level_length (fixture->filter, "2", LEVEL_LENGTH);
+ /* The view only shows the root level, so the filter model only has
+ * the first two levels cached. (We add an additional level to take
+ * the virtual root into account).
+ */
+ filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
filter_test_enable_filter (fixture);
check_filter_model_with_root (fixture, path);
{
GtkTreePath *path = (GtkTreePath *)user_data;
+ /* This row is not shown, so its signal is not propagated */
set_path_visibility (fixture, "2:2:2:2", FALSE);
+
+ signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
set_path_visibility (fixture, "2:2:2", FALSE);
+ signal_monitor_assert_is_empty (fixture->monitor);
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);
+ /* The view only shows the root level, so the filter model only has
+ * the first two levels cached.
+ */
+ filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
filter_test_enable_filter (fixture);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2:2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
set_path_visibility (fixture, "2:2:2", TRUE);
check_filter_model_with_root (fixture, path);
gconstpointer user_data)
{
+ signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
set_path_visibility (fixture, "2", TRUE);
+ signal_monitor_assert_is_empty (fixture->monitor);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+ /* The view only shows the root level, so the filter model only has
+ * the first two levels cached.
+ */
+ filter_test_append_refilter_signals (fixture, 2);
filter_test_enable_filter (fixture);
check_filter_model (fixture);
gconstpointer user_data)
{
+ signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
set_path_visibility (fixture, "2:2", TRUE);
+ signal_monitor_assert_is_empty (fixture->monitor);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
check_level_length (fixture->filter, "2", LEVEL_LENGTH);
+ /* The view only shows the root level, so the filter model only has
+ * the first two levels cached.
+ */
+ filter_test_append_refilter_signals (fixture, 3);
filter_test_enable_filter (fixture);
check_filter_model (fixture);
/* From here we are filtered, "2" in the real model is "0" in the filter
* model.
*/
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
set_path_visibility (fixture, "2", TRUE);
+ signal_monitor_assert_is_empty (fixture->monitor);
check_level_length (fixture->filter, NULL, 1);
check_level_length (fixture->filter, "0", 1);
}
gconstpointer user_data)
{
+ /* The view is not showing this row (collapsed state), so it is not
+ * referenced. The signal should not go through.
+ */
set_path_visibility (fixture, "2:2:2", TRUE);
+
+ signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
set_path_visibility (fixture, "2:2", TRUE);
+ signal_monitor_assert_is_empty (fixture->monitor);
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);
+ /* The view only shows the root level, so the filter model only has
+ * the first two levels cached.
+ */
+ filter_test_append_refilter_signals (fixture, 3);
filter_test_enable_filter (fixture);
check_filter_model (fixture);
/* From here we are filtered, "2" in the real model is "0" in the filter
* model.
*/
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
set_path_visibility (fixture, "2", TRUE);
check_filter_model (fixture);
check_level_length (fixture->filter, NULL, 1);
{
GtkTreePath *path = (GtkTreePath *)user_data;
+ signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
set_path_visibility (fixture, "2:2", TRUE);
+ signal_monitor_assert_is_empty (fixture->monitor);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
+ /* The view only shows the root level, so the filter model only has
+ * the first two levels cached.
+ */
+ filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
filter_test_enable_filter (fixture);
check_filter_model_with_root (fixture, path);
{
GtkTreePath *path = (GtkTreePath *)user_data;
+ signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
set_path_visibility (fixture, "2:2:2", TRUE);
+ signal_monitor_assert_is_empty (fixture->monitor);
check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
check_level_length (fixture->filter, "2", LEVEL_LENGTH);
+ /* The view only shows the root level, so the filter model only has
+ * the first two levels cached.
+ */
+ filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
filter_test_enable_filter (fixture);
check_filter_model_with_root (fixture, path);
/* From here we are filtered, "2" in the real model is "0" in the filter
* model.
*/
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
set_path_visibility (fixture, "2:2", TRUE);
+ signal_monitor_assert_is_empty (fixture->monitor);
check_level_length (fixture->filter, NULL, 1);
check_level_length (fixture->filter, "0", 1);
}
{
GtkTreePath *path = (GtkTreePath *)user_data;
+ /* The view is not showing this row (collapsed state), so it is not
+ * referenced. The signal should not go through.
+ */
set_path_visibility (fixture, "2:2:2:2", TRUE);
+
+ signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
set_path_visibility (fixture, "2:2:2", TRUE);
+ signal_monitor_assert_is_empty (fixture->monitor);
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);
+ /* The view only shows the root level, so the filter model only has
+ * the first two levels cached.
+ */
+ filter_test_append_refilter_signals_with_vroot (fixture, 4, path);
filter_test_enable_filter (fixture);
check_filter_model_with_root (fixture, path);
/* From here we are filtered, "2" in the real model is "0" in the filter
* model.
*/
+ signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
+ signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
set_path_visibility (fixture, "2:2", TRUE);
check_filter_model_with_root (fixture, path);
check_level_length (fixture->filter, NULL, 1);
filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
fixture.filter = GTK_TREE_MODEL_FILTER (filter);
+ fixture.monitor = NULL;
gtk_tree_model_filter_set_visible_column (fixture.filter, 1);
fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
fixture.filter = GTK_TREE_MODEL_FILTER (filter);
+ fixture.monitor = NULL;
/* We will filter on parent state using a filter function. We will
* manually keep the boolean column in sync, so that we can use
fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
fixture.filter = GTK_TREE_MODEL_FILTER (filter);
+ fixture.monitor = NULL;
/* We will filter on parent state using a filter function. We will
* manually keep the boolean column in sync, so that we can use