GitLab repository storage has been migrated to hashed layout. Please contact Infrastructure team if you notice any issues with repositories or hooks.

Commit a59c39f3 authored by Kristian Rietveld's avatar Kristian Rietveld

Bug 346800 - Rework sort/filter models to use indices to parents...

Rework the sort and filter models to store their reference to the parent
element as an array index instead of a pointer to an array element.
These pointers could become invalid with any array modification, whereas
indices do not.
parent 143b06c9
This diff is collapsed.
......@@ -67,7 +67,7 @@ struct _SortLevel
{
GArray *array;
gint ref_count;
SortElt *parent_elt;
gint parent_elt_index;
SortLevel *parent_level;
};
......@@ -101,6 +101,10 @@ enum {
#define SORT_ELT(sort_elt) ((SortElt *)sort_elt)
#define SORT_LEVEL(sort_level) ((SortLevel *)sort_level)
#define SORT_LEVEL_PARENT_ELT(level) (&g_array_index (SORT_LEVEL ((level))->parent_level->array, SortElt, SORT_LEVEL ((level))->parent_elt_index))
#define SORT_LEVEL_ELT_INDEX(level, elt) (SORT_ELT ((elt)) - SORT_ELT (SORT_LEVEL ((level))->array->data))
#define GET_CHILD_ITER(tree_model_sort,ch_iter,so_iter) gtk_tree_model_sort_convert_iter_to_child_iter((GtkTreeModelSort*)(tree_model_sort), (ch_iter), (so_iter));
#define NO_SORT_FUNC ((GtkTreeIterCompareFunc) 0x1)
......@@ -211,7 +215,7 @@ static gboolean gtk_tree_model_sort_has_default_sort_func (GtkTreeSortable
/* Private functions (sort funcs, level handling and other utils) */
static void gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
SortLevel *parent_level,
SortElt *parent_elt);
gint parent_elt_index);
static void gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
SortLevel *sort_level);
static void gtk_tree_model_sort_increment_stamp (GtkTreeModelSort *tree_model_sort);
......@@ -499,7 +503,7 @@ gtk_tree_model_sort_row_changed (GtkTreeModel *s_model,
for (i = 0; i < level->array->len; i++)
if (g_array_index (level->array, SortElt, i).children)
g_array_index (level->array, SortElt, i).children->parent_elt = &g_array_index (level->array, SortElt, i);
g_array_index (level->array, SortElt, i).children->parent_elt_index = i;
gtk_tree_path_up (path);
gtk_tree_path_append_index (path, index);
......@@ -539,11 +543,11 @@ gtk_tree_model_sort_row_changed (GtkTreeModel *s_model,
/* else? shouldn't really happen */
}
if (level->parent_elt)
if (level->parent_elt_index >= 0)
{
iter.stamp = tree_model_sort->stamp;
iter.user_data = level->parent_level;
iter.user_data2 = level->parent_elt;
iter.user_data2 = SORT_LEVEL_PARENT_ELT (level);
tmppath = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model_sort), &iter);
......@@ -609,7 +613,7 @@ gtk_tree_model_sort_row_inserted (GtkTreeModel *s_model,
if (!tree_model_sort->root)
{
gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
gtk_tree_model_sort_build_level (tree_model_sort, NULL, -1);
/* the build level already put the inserted iter in the level,
so no need to handle this signal anymore */
......@@ -785,7 +789,7 @@ gtk_tree_model_sort_row_deleted (GtkTreeModel *s_model,
if (elt->offset > offset)
elt->offset--;
if (elt->children)
elt->children->parent_elt = elt;
elt->children->parent_elt_index = i;
}
gtk_tree_path_free (path);
......@@ -934,7 +938,7 @@ gtk_tree_model_sort_get_iter (GtkTreeModel *tree_model,
indices = gtk_tree_path_get_indices (path);
if (tree_model_sort->root == NULL)
gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
gtk_tree_model_sort_build_level (tree_model_sort, NULL, -1);
level = SORT_LEVEL (tree_model_sort->root);
depth = gtk_tree_path_get_depth (path);
......@@ -948,7 +952,7 @@ gtk_tree_model_sort_get_iter (GtkTreeModel *tree_model,
return FALSE;
if (g_array_index (level->array, SortElt, indices[i]).children == NULL)
gtk_tree_model_sort_build_level (tree_model_sort, level, &g_array_index (level->array, SortElt, indices[i]));
gtk_tree_model_sort_build_level (tree_model_sort, level, indices[i]);
level = g_array_index (level->array, SortElt, indices[i]).children;
}
......@@ -972,19 +976,21 @@ gtk_tree_model_sort_get_path (GtkTreeModel *tree_model,
GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
GtkTreePath *retval;
SortLevel *level;
SortElt *elt;
gint elt_index;
g_return_val_if_fail (tree_model_sort->child_model != NULL, NULL);
g_return_val_if_fail (tree_model_sort->stamp == iter->stamp, NULL);
retval = gtk_tree_path_new ();
level = iter->user_data;
elt = iter->user_data2;
while (level != NULL)
level = SORT_LEVEL (iter->user_data);
elt_index = SORT_LEVEL_ELT_INDEX (level, iter->user_data2);
while (level)
{
gtk_tree_path_prepend_index (retval, elt - (SortElt *)level->array->data);
gtk_tree_path_prepend_index (retval, elt_index);
elt = level->parent_elt;
elt_index = level->parent_elt_index;
level = level->parent_level;
}
......@@ -1048,7 +1054,7 @@ gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
if (parent == NULL)
{
if (tree_model_sort->root == NULL)
gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
gtk_tree_model_sort_build_level (tree_model_sort, NULL, -1);
if (tree_model_sort->root == NULL)
return FALSE;
......@@ -1059,15 +1065,21 @@ gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
}
else
{
if (((SortElt *)parent->user_data2)->children == NULL)
gtk_tree_model_sort_build_level (tree_model_sort,
(SortLevel *)parent->user_data,
(SortElt *)parent->user_data2);
if (((SortElt *)parent->user_data2)->children == NULL)
SortElt *elt;
level = SORT_LEVEL (parent->user_data);
elt = SORT_ELT (parent->user_data2);
if (elt->children == NULL)
gtk_tree_model_sort_build_level (tree_model_sort, level,
SORT_LEVEL_ELT_INDEX (level, elt));
if (elt->children == NULL)
return FALSE;
iter->stamp = tree_model_sort->stamp;
iter->user_data = ((SortElt *)parent->user_data2)->children;
iter->user_data2 = ((SortLevel *)iter->user_data)->array->data;
iter->user_data = elt->children;
iter->user_data2 = elt->children->array->data;
}
return TRUE;
......@@ -1160,7 +1172,7 @@ gtk_tree_model_sort_iter_parent (GtkTreeModel *tree_model,
{
iter->stamp = tree_model_sort->stamp;
iter->user_data = level->parent_level;
iter->user_data2 = level->parent_elt;
iter->user_data2 = SORT_LEVEL_PARENT_ELT (level);
return TRUE;
}
......@@ -1173,9 +1185,9 @@ gtk_tree_model_sort_ref_node (GtkTreeModel *tree_model,
{
GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
GtkTreeIter child_iter;
GtkTreeIter tmp_iter;
SortLevel *level;
SortLevel *level, *parent_level;
SortElt *elt;
gint parent_elt_index;
g_return_if_fail (tree_model_sort->child_model != NULL);
g_return_if_fail (VALID_ITER (iter, tree_model_sort));
......@@ -1193,28 +1205,34 @@ gtk_tree_model_sort_ref_node (GtkTreeModel *tree_model,
level->ref_count++;
/* Increase the reference count of all parent elements */
tmp_iter.stamp = tree_model_sort->stamp;
tmp_iter.user_data = level->parent_level;
tmp_iter.user_data2 = level->parent_elt;;
parent_level = level->parent_level;
parent_elt_index = level->parent_elt_index;
while (tmp_iter.user_data2)
while (parent_level)
{
GtkTreeIter tmp_iter;
tmp_iter.stamp = tree_model_sort->stamp;
tmp_iter.user_data = parent_level;
tmp_iter.user_data2 = &g_array_index (parent_level->array, SortElt, parent_elt_index);
gtk_tree_model_sort_ref_node (tree_model, &tmp_iter);
tmp_iter.user_data2 = SORT_LEVEL (tmp_iter.user_data)->parent_elt;
tmp_iter.user_data = SORT_LEVEL (tmp_iter.user_data)->parent_level;
parent_elt_index = parent_level->parent_elt_index;
parent_level = parent_level->parent_level;
}
if (level->ref_count == 1)
{
SortLevel *parent_level = level->parent_level;
SortElt *parent_elt = level->parent_elt;
gint parent_elt_index = level->parent_elt_index;
/* We were at zero -- time to decrement the zero_ref_count val */
while (parent_level)
{
parent_elt->zero_ref_count--;
{
g_array_index (parent_level->array, SortElt, parent_elt_index).zero_ref_count--;
parent_elt = parent_level->parent_elt;
parent_elt_index = parent_level->parent_elt_index;
parent_level = parent_level->parent_level;
}
......@@ -1229,9 +1247,9 @@ gtk_tree_model_sort_real_unref_node (GtkTreeModel *tree_model,
gboolean propagate_unref)
{
GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
GtkTreeIter tmp_iter;
SortLevel *level;
SortLevel *level, *parent_level;
SortElt *elt;
gint parent_elt_index;
g_return_if_fail (tree_model_sort->child_model != NULL);
g_return_if_fail (VALID_ITER (iter, tree_model_sort));
......@@ -1253,29 +1271,34 @@ gtk_tree_model_sort_real_unref_node (GtkTreeModel *tree_model,
level->ref_count--;
/* Decrease the reference count of all parent elements */
tmp_iter.stamp = tree_model_sort->stamp;
tmp_iter.user_data = level->parent_level;
tmp_iter.user_data2 = level->parent_elt;;
parent_level = level->parent_level;
parent_elt_index = level->parent_elt_index;
while (tmp_iter.user_data2)
while (parent_level)
{
GtkTreeIter tmp_iter;
tmp_iter.stamp = tree_model_sort->stamp;
tmp_iter.user_data = parent_level;
tmp_iter.user_data2 = &g_array_index (parent_level->array, SortElt, parent_elt_index);
gtk_tree_model_sort_real_unref_node (tree_model, &tmp_iter, FALSE);
tmp_iter.user_data2 = SORT_LEVEL (tmp_iter.user_data)->parent_elt;
tmp_iter.user_data = SORT_LEVEL (tmp_iter.user_data)->parent_level;
parent_elt_index = parent_level->parent_elt_index;
parent_level = parent_level->parent_level;
}
if (level->ref_count == 0)
{
SortLevel *parent_level = level->parent_level;
SortElt *parent_elt = level->parent_elt;
gint parent_elt_index = level->parent_elt_index;
/* We are at zero -- time to increment the zero_ref_count val */
while (parent_level)
{
parent_elt->zero_ref_count++;
g_array_index (parent_level->array, SortElt, parent_elt_index).zero_ref_count++;
parent_elt = parent_level->parent_elt;
parent_elt_index = parent_level->parent_elt_index;
parent_level = parent_level->parent_level;
}
......@@ -1558,10 +1581,10 @@ gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
/* Set up data */
data.tree_model_sort = tree_model_sort;
if (level->parent_elt)
if (level->parent_elt_index >= 0)
{
data.parent_path = gtk_tree_model_sort_elt_get_path (level->parent_level,
level->parent_elt);
SORT_LEVEL_PARENT_ELT (level));
gtk_tree_path_append_index (data.parent_path, 0);
}
else
......@@ -1627,9 +1650,8 @@ gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
new_order[i] = g_array_index (sort_array, SortTuple, i).offset;
g_array_append_val (new_array, *elt);
elt = &g_array_index (new_array, SortElt, i);
if (elt->children)
elt->children->parent_elt = elt;
elt->children->parent_elt_index = i;
}
g_array_free (level->array, TRUE);
......@@ -1639,11 +1661,11 @@ gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
if (emit_reordered)
{
gtk_tree_model_sort_increment_stamp (tree_model_sort);
if (level->parent_elt)
if (level->parent_elt_index >= 0)
{
iter.stamp = tree_model_sort->stamp;
iter.user_data = level->parent_level;
iter.user_data2 = level->parent_elt;
iter.user_data2 = SORT_LEVEL_PARENT_ELT (level);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model_sort),
&iter);
......@@ -1846,7 +1868,7 @@ gtk_tree_model_sort_insert_value (GtkTreeModelSort *tree_model_sort,
tmp_elt = SORT_ELT (level->array->data);
for (i = 0; i < level->array->len; i++, tmp_elt++)
if (tmp_elt->children)
tmp_elt->children->parent_elt = tmp_elt;
tmp_elt->children->parent_elt_index = i;
return TRUE;
}
......@@ -1869,7 +1891,10 @@ gtk_tree_model_sort_elt_get_path (SortLevel *level,
{
gtk_tree_path_prepend_index (path, walker2->offset);
walker2 = walker->parent_elt;
if (!walker->parent_level)
break;
walker2 = SORT_LEVEL_PARENT_ELT (walker);
walker = walker->parent_level;
}
......@@ -1992,7 +2017,7 @@ gtk_real_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_mode
child_indices = gtk_tree_path_get_indices (child_path);
if (tree_model_sort->root == NULL && build_levels)
gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
gtk_tree_model_sort_build_level (tree_model_sort, NULL, -1);
level = SORT_LEVEL (tree_model_sort->root);
for (i = 0; i < gtk_tree_path_get_depth (child_path); i++)
......@@ -2018,7 +2043,7 @@ gtk_real_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_mode
gtk_tree_path_append_index (retval, j);
if (g_array_index (level->array, SortElt, j).children == NULL && build_levels)
{
gtk_tree_model_sort_build_level (tree_model_sort, level, &g_array_index (level->array, SortElt, j));
gtk_tree_model_sort_build_level (tree_model_sort, level, j);
}
level = g_array_index (level->array, SortElt, j).children;
found_child = TRUE;
......@@ -2136,7 +2161,7 @@ gtk_tree_model_sort_convert_path_to_child_path (GtkTreeModelSort *tree_model_sor
retval = gtk_tree_path_new ();
sorted_indices = gtk_tree_path_get_indices (sorted_path);
if (tree_model_sort->root == NULL)
gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
gtk_tree_model_sort_build_level (tree_model_sort, NULL, -1);
level = SORT_LEVEL (tree_model_sort->root);
for (i = 0; i < gtk_tree_path_get_depth (sorted_path); i++)
......@@ -2151,7 +2176,7 @@ gtk_tree_model_sort_convert_path_to_child_path (GtkTreeModelSort *tree_model_sor
}
if (g_array_index (level->array, SortElt, count).children == NULL)
gtk_tree_model_sort_build_level (tree_model_sort, level, &g_array_index (level->array, SortElt, count));
gtk_tree_model_sort_build_level (tree_model_sort, level, count);
if (level == NULL)
{
......@@ -2203,9 +2228,10 @@ gtk_tree_model_sort_convert_iter_to_child_iter (GtkTreeModelSort *tree_model_sor
static void
gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
SortLevel *parent_level,
SortElt *parent_elt)
gint parent_elt_index)
{
GtkTreeIter iter;
SortElt *parent_elt = NULL;
SortLevel *new_level;
gint length = 0;
gint i;
......@@ -2223,6 +2249,8 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
GtkTreeIter parent_iter;
GtkTreeIter child_parent_iter;
parent_elt = &g_array_index (parent_level->array, SortElt, parent_elt_index);
parent_iter.stamp = tree_model_sort->stamp;
parent_iter.user_data = parent_level;
parent_iter.user_data2 = parent_elt;
......@@ -2248,10 +2276,10 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
new_level = g_new (SortLevel, 1);
new_level->array = g_array_sized_new (FALSE, FALSE, sizeof (SortElt), length);
new_level->ref_count = 0;
new_level->parent_elt = parent_elt;
new_level->parent_level = parent_level;
new_level->parent_elt_index = parent_elt_index;
if (parent_elt)
if (parent_elt_index >= 0)
parent_elt->children = new_level;
else
tree_model_sort->root = new_level;
......@@ -2259,11 +2287,12 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
/* increase the count of zero ref_counts.*/
while (parent_level)
{
parent_elt->zero_ref_count++;
g_array_index (parent_level->array, SortElt, parent_elt_index).zero_ref_count++;
parent_elt = parent_level->parent_elt;
parent_elt_index = parent_level->parent_elt_index;
parent_level = parent_level->parent_level;
}
if (new_level != tree_model_sort->root)
tree_model_sort->zero_ref_count++;
......@@ -2334,13 +2363,13 @@ gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
if (sort_level->ref_count == 0)
{
SortLevel *parent_level = sort_level->parent_level;
SortElt *parent_elt = sort_level->parent_elt;
gint parent_elt_index = sort_level->parent_elt_index;
while (parent_level)
{
parent_elt->zero_ref_count--;
{
g_array_index (parent_level->array, SortElt, parent_elt_index).zero_ref_count--;
parent_elt = parent_level->parent_elt;
parent_elt_index = parent_level->parent_elt_index;
parent_level = parent_level->parent_level;
}
......@@ -2348,8 +2377,8 @@ gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
tree_model_sort->zero_ref_count--;
}
if (sort_level->parent_elt)
sort_level->parent_elt->children = NULL;
if (sort_level->parent_elt_index >= 0)
SORT_LEVEL_PARENT_ELT (sort_level)->children = NULL;
else
tree_model_sort->root = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment