forked from AuroraMiddleware/gtk
Bug 586374 – code does not follow documentation
Properly invalidate iterators in iter_next, iter_children, iter_nth_child and iter_parent when FALSE is returned. ListStore was actually already mostly in order as the GSequence pointers are very strictly checked, but to be a little stricter we've added stamp = 0 lines. TreeStore did not invalidate its iterators, so stamp = 0 lines were added where appropriate. Unit tests have been added to check this. Fixes bug 586374, reported by Mike Gemunde.
This commit is contained in:
parent
a79ef0866b
commit
d743b2fbea
@ -494,10 +494,16 @@ static gboolean
|
||||
gtk_list_store_iter_next (GtkTreeModel *tree_model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
gboolean retval;
|
||||
|
||||
g_return_val_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp, FALSE);
|
||||
iter->user_data = g_sequence_iter_next (iter->user_data);
|
||||
|
||||
return !g_sequence_iter_is_end (iter->user_data);
|
||||
retval = g_sequence_iter_is_end (iter->user_data);
|
||||
if (retval)
|
||||
iter->stamp = 0;
|
||||
|
||||
return !retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -509,7 +515,10 @@ gtk_list_store_iter_children (GtkTreeModel *tree_model,
|
||||
|
||||
/* this is a list, nodes have no children */
|
||||
if (parent)
|
||||
return FALSE;
|
||||
{
|
||||
iter->stamp = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_sequence_get_length (list_store->seq) > 0)
|
||||
{
|
||||
@ -518,7 +527,10 @@ gtk_list_store_iter_children (GtkTreeModel *tree_model,
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
{
|
||||
iter->stamp = 0;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -551,6 +563,8 @@ gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
|
||||
GtkListStore *list_store = (GtkListStore *) tree_model;
|
||||
GSequenceIter *child;
|
||||
|
||||
iter->stamp = 0;
|
||||
|
||||
if (parent)
|
||||
return FALSE;
|
||||
|
||||
@ -570,6 +584,7 @@ gtk_list_store_iter_parent (GtkTreeModel *tree_model,
|
||||
GtkTreeIter *iter,
|
||||
GtkTreeIter *child)
|
||||
{
|
||||
iter->stamp = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -620,7 +620,10 @@ gtk_tree_store_iter_next (GtkTreeModel *tree_model,
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
{
|
||||
iter->stamp = 0;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -646,7 +649,10 @@ gtk_tree_store_iter_children (GtkTreeModel *tree_model,
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
{
|
||||
iter->stamp = 0;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -708,7 +714,10 @@ gtk_tree_store_iter_nth_child (GtkTreeModel *tree_model,
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
{
|
||||
iter->stamp = 0;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -733,7 +742,10 @@ gtk_tree_store_iter_parent (GtkTreeModel *tree_model,
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
{
|
||||
iter->stamp = 0;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -850,6 +850,72 @@ list_store_test_move_before_single (void)
|
||||
g_object_unref (store);
|
||||
}
|
||||
|
||||
|
||||
/* iter invalidation */
|
||||
|
||||
static void
|
||||
list_store_test_iter_next_invalid (ListStore *fixture,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
|
||||
path = gtk_tree_path_new_from_indices (4, -1);
|
||||
gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store), &iter, path);
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
g_assert (gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store),
|
||||
&iter) == FALSE);
|
||||
g_assert (gtk_list_store_iter_is_valid (fixture->store, &iter) == FALSE);
|
||||
g_assert (iter.stamp == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
list_store_test_iter_children_invalid (ListStore *fixture,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
GtkTreeIter iter, child;
|
||||
|
||||
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (fixture->store), &iter);
|
||||
g_assert (gtk_list_store_iter_is_valid (fixture->store, &iter) == TRUE);
|
||||
|
||||
g_assert (gtk_tree_model_iter_children (GTK_TREE_MODEL (fixture->store),
|
||||
&child, &iter) == FALSE);
|
||||
g_assert (gtk_list_store_iter_is_valid (fixture->store, &child) == FALSE);
|
||||
g_assert (child.stamp == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
list_store_test_iter_nth_child_invalid (ListStore *fixture,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
GtkTreeIter iter, child;
|
||||
|
||||
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (fixture->store), &iter);
|
||||
g_assert (gtk_list_store_iter_is_valid (fixture->store, &iter) == TRUE);
|
||||
|
||||
g_assert (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (fixture->store),
|
||||
&child, &iter, 0) == FALSE);
|
||||
g_assert (gtk_list_store_iter_is_valid (fixture->store, &child) == FALSE);
|
||||
g_assert (child.stamp == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
list_store_test_iter_parent_invalid (ListStore *fixture,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
GtkTreeIter iter, child;
|
||||
|
||||
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (fixture->store), &child);
|
||||
g_assert (gtk_list_store_iter_is_valid (fixture->store, &child) == TRUE);
|
||||
|
||||
g_assert (gtk_tree_model_iter_parent (GTK_TREE_MODEL (fixture->store),
|
||||
&iter, &child) == FALSE);
|
||||
g_assert (gtk_list_store_iter_is_valid (fixture->store, &iter) == FALSE);
|
||||
g_assert (iter.stamp == 0);
|
||||
}
|
||||
|
||||
|
||||
/* main */
|
||||
|
||||
int
|
||||
@ -958,5 +1024,19 @@ main (int argc,
|
||||
g_test_add_func ("/list-store/move-before-single",
|
||||
list_store_test_move_before_single);
|
||||
|
||||
/* iter invalidation */
|
||||
g_test_add ("/list-store/iter-next-invalid", ListStore, NULL,
|
||||
list_store_setup, list_store_test_iter_next_invalid,
|
||||
list_store_teardown);
|
||||
g_test_add ("/list-store/iter-children-invalid", ListStore, NULL,
|
||||
list_store_setup, list_store_test_iter_children_invalid,
|
||||
list_store_teardown);
|
||||
g_test_add ("/list-store/iter-nth-child-invalid", ListStore, NULL,
|
||||
list_store_setup, list_store_test_iter_nth_child_invalid,
|
||||
list_store_teardown);
|
||||
g_test_add ("/list-store/iter-parent-invalid", ListStore, NULL,
|
||||
list_store_setup, list_store_test_iter_parent_invalid,
|
||||
list_store_teardown);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
@ -853,6 +853,72 @@ tree_store_test_move_before_single (void)
|
||||
g_object_unref (store);
|
||||
}
|
||||
|
||||
|
||||
/* iter invalidation */
|
||||
|
||||
static void
|
||||
tree_store_test_iter_next_invalid (TreeStore *fixture,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
|
||||
path = gtk_tree_path_new_from_indices (4, -1);
|
||||
gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store), &iter, path);
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
g_assert (gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store),
|
||||
&iter) == FALSE);
|
||||
g_assert (gtk_tree_store_iter_is_valid (fixture->store, &iter) == FALSE);
|
||||
g_assert (iter.stamp == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
tree_store_test_iter_children_invalid (TreeStore *fixture,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
GtkTreeIter iter, child;
|
||||
|
||||
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (fixture->store), &iter);
|
||||
g_assert (gtk_tree_store_iter_is_valid (fixture->store, &iter) == TRUE);
|
||||
|
||||
g_assert (gtk_tree_model_iter_children (GTK_TREE_MODEL (fixture->store),
|
||||
&child, &iter) == FALSE);
|
||||
g_assert (gtk_tree_store_iter_is_valid (fixture->store, &child) == FALSE);
|
||||
g_assert (child.stamp == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
tree_store_test_iter_nth_child_invalid (TreeStore *fixture,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
GtkTreeIter iter, child;
|
||||
|
||||
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (fixture->store), &iter);
|
||||
g_assert (gtk_tree_store_iter_is_valid (fixture->store, &iter) == TRUE);
|
||||
|
||||
g_assert (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (fixture->store),
|
||||
&child, &iter, 0) == FALSE);
|
||||
g_assert (gtk_tree_store_iter_is_valid (fixture->store, &child) == FALSE);
|
||||
g_assert (child.stamp == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
tree_store_test_iter_parent_invalid (TreeStore *fixture,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
GtkTreeIter iter, child;
|
||||
|
||||
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (fixture->store), &child);
|
||||
g_assert (gtk_tree_store_iter_is_valid (fixture->store, &child) == TRUE);
|
||||
|
||||
g_assert (gtk_tree_model_iter_parent (GTK_TREE_MODEL (fixture->store),
|
||||
&iter, &child) == FALSE);
|
||||
g_assert (gtk_tree_store_iter_is_valid (fixture->store, &iter) == FALSE);
|
||||
g_assert (iter.stamp == 0);
|
||||
}
|
||||
|
||||
|
||||
/* main */
|
||||
|
||||
int
|
||||
@ -961,5 +1027,19 @@ main (int argc,
|
||||
g_test_add_func ("/tree-store/move-before-single",
|
||||
tree_store_test_move_before_single);
|
||||
|
||||
/* iter invalidation */
|
||||
g_test_add ("/tree-store/iter-next-invalid", TreeStore, NULL,
|
||||
tree_store_setup, tree_store_test_iter_next_invalid,
|
||||
tree_store_teardown);
|
||||
g_test_add ("/tree-store/iter-children-invalid", TreeStore, NULL,
|
||||
tree_store_setup, tree_store_test_iter_children_invalid,
|
||||
tree_store_teardown);
|
||||
g_test_add ("/tree-store/iter-nth-child-invalid", TreeStore, NULL,
|
||||
tree_store_setup, tree_store_test_iter_nth_child_invalid,
|
||||
tree_store_teardown);
|
||||
g_test_add ("/tree-store/iter-parent-invalid", TreeStore, NULL,
|
||||
tree_store_setup, tree_store_test_iter_parent_invalid,
|
||||
tree_store_teardown);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user