From dec7a340471c019411d3555254c3219f1208cb3a Mon Sep 17 00:00:00 2001 From: Kristian Rietveld Date: Thu, 2 Jun 2011 22:01:45 +0200 Subject: [PATCH] Avoid unreferencing deleted nodes Now that we call unref_node in free_level, we have to take care that free_level may only unref (parent) nodes when these still exist in the child model. After row-deleted has been received for a node, its children may no longer unref this node. --- gtk/gtktreemodelsort.c | 48 +++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/gtk/gtktreemodelsort.c b/gtk/gtktreemodelsort.c index 90c387c54..e64f37054 100644 --- a/gtk/gtktreemodelsort.c +++ b/gtk/gtktreemodelsort.c @@ -355,7 +355,8 @@ static void gtk_tree_model_sort_build_level (GtkTreeModelSort *tre SortLevel *parent_level, gint parent_elt_index); static void gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort, - SortLevel *sort_level); + SortLevel *sort_level, + gboolean unref); static void gtk_tree_model_sort_increment_stamp (GtkTreeModelSort *tree_model_sort); static void gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort, SortLevel *level, @@ -497,7 +498,7 @@ gtk_tree_model_sort_finalize (GObject *object) gtk_tree_model_sort_set_model (tree_model_sort, NULL); if (priv->root) - gtk_tree_model_sort_free_level (tree_model_sort, priv->root); + gtk_tree_model_sort_free_level (tree_model_sort, priv->root, TRUE); if (priv->sort_list) { @@ -817,7 +818,7 @@ gtk_tree_model_sort_row_inserted (GtkTreeModel *s_model, if (level->ref_count == 0 && level != priv->root) { - gtk_tree_model_sort_free_level (tree_model_sort, level); + gtk_tree_model_sort_free_level (tree_model_sort, level, TRUE); goto done; } @@ -900,20 +901,25 @@ gtk_tree_model_sort_row_deleted (GtkTreeModel *s_model, while (elt->ref_count > 0) gtk_tree_model_sort_real_unref_node (GTK_TREE_MODEL (data), &iter, FALSE); + /* If this node has children, we free the level (recursively) here + * and specify that unref may not be used, because parent and its + * children have been removed by now. + */ + if (elt->children) + gtk_tree_model_sort_free_level (tree_model_sort, + elt->children, FALSE); + if (level->ref_count == 0) { - /* This will prune the level, so I can just emit the signal and - * not worry about cleaning this level up. - * Careful, root level is not cleaned up in increment stamp. - */ gtk_tree_model_sort_increment_stamp (tree_model_sort); gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path); gtk_tree_path_free (path); if (level == tree_model_sort->priv->root) { - gtk_tree_model_sort_free_level (tree_model_sort, - tree_model_sort->priv->root); + gtk_tree_model_sort_free_level (tree_model_sort, + tree_model_sort->priv->root, + TRUE); tree_model_sort->priv->root = NULL; } return; @@ -2096,7 +2102,7 @@ gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort, /* reset our state */ if (priv->root) - gtk_tree_model_sort_free_level (tree_model_sort, priv->root); + gtk_tree_model_sort_free_level (tree_model_sort, priv->root, TRUE); priv->root = NULL; _gtk_tree_data_list_header_free (priv->sort_list); priv->sort_list = NULL; @@ -2521,7 +2527,8 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort, static void gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort, - SortLevel *sort_level) + SortLevel *sort_level, + gboolean unref) { GtkTreeModelSortPrivate *priv = tree_model_sort->priv; gint i; @@ -2532,7 +2539,7 @@ gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort, { if (g_array_index (sort_level->array, SortElt, i).children) gtk_tree_model_sort_free_level (tree_model_sort, - SORT_LEVEL (g_array_index (sort_level->array, SortElt, i).children)); + SORT_LEVEL (g_array_index (sort_level->array, SortElt, i).children), unref); } if (sort_level->ref_count == 0) @@ -2554,14 +2561,17 @@ gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort, if (sort_level->parent_elt_index >= 0) { - GtkTreeIter parent_iter; + if (unref) + { + GtkTreeIter parent_iter; - parent_iter.stamp = tree_model_sort->priv->stamp; - parent_iter.user_data = sort_level->parent_level; - parent_iter.user_data2 = SORT_LEVEL_PARENT_ELT (sort_level); + parent_iter.stamp = tree_model_sort->priv->stamp; + parent_iter.user_data = sort_level->parent_level; + parent_iter.user_data2 = SORT_LEVEL_PARENT_ELT (sort_level); - gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (tree_model_sort), - &parent_iter); + gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (tree_model_sort), + &parent_iter); + } SORT_LEVEL_PARENT_ELT (sort_level)->children = NULL; } @@ -2604,7 +2614,7 @@ gtk_tree_model_sort_clear_cache_helper (GtkTreeModelSort *tree_model_sort, } if (level->ref_count == 0 && level != tree_model_sort->priv->root) - gtk_tree_model_sort_free_level (tree_model_sort, level); + gtk_tree_model_sort_free_level (tree_model_sort, level, TRUE); } /** -- 2.43.2