X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtktreemodelfilter.c;h=45281c298a8532e5805d68de4b2041d59729be86;hb=ee44ed75ca50cb078ba8d5cb62c6a5d9d568f0e6;hp=b1e0e0d0628220946bfc06bcbb885bace93ce114;hpb=f317dd383108d796c4ab98395d846d24dfbd6d53;p=~andy%2Fgtk diff --git a/gtk/gtktreemodelfilter.c b/gtk/gtktreemodelfilter.c index b1e0e0d06..45281c298 100644 --- a/gtk/gtktreemodelfilter.c +++ b/gtk/gtktreemodelfilter.c @@ -13,9 +13,7 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library 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. + * License along with this library. If not, see . */ #include "config.h" @@ -322,6 +320,11 @@ enum # define GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS(filter) (FALSE) #endif +/* Defining this constant enables more assertions, which will be + * helpful when debugging the code. + */ +#undef MODEL_FILTER_DEBUG + #define FILTER_ELT(filter_elt) ((FilterElt *)filter_elt) #define FILTER_LEVEL(filter_level) ((FilterLevel *)filter_level) #define GET_ELT(siter) ((FilterElt*) (siter ? g_sequence_get (siter) : NULL)) @@ -418,7 +421,9 @@ static void gtk_tree_model_filter_build_level (GtkTr static void gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter, FilterLevel *filter_level, - gboolean unref); + gboolean unref_self, + gboolean unref_parent, + gboolean unref_external); static GtkTreePath *gtk_tree_model_filter_elt_get_path (FilterLevel *level, FilterElt *elt, @@ -596,7 +601,7 @@ gtk_tree_model_filter_finalize (GObject *object) gtk_tree_path_free (filter->priv->virtual_root); if (filter->priv->root) - gtk_tree_model_filter_free_level (filter, filter->priv->root, TRUE); + gtk_tree_model_filter_free_level (filter, filter->priv->root, TRUE, TRUE, FALSE); g_free (filter->priv->modify_types); @@ -886,7 +891,7 @@ gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter, if (empty && (parent_level && parent_level->ext_ref_count == 0)) { - gtk_tree_model_filter_free_level (filter, new_level, FALSE); + gtk_tree_model_filter_free_level (filter, new_level, FALSE, TRUE, FALSE); return; } @@ -925,7 +930,9 @@ gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter, static void gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter, FilterLevel *filter_level, - gboolean unref) + gboolean unref_self, + gboolean unref_parent, + gboolean unref_external) { GSequenceIter *siter; GSequenceIter *end_siter; @@ -940,14 +947,36 @@ gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter, FilterElt *elt = g_sequence_get (siter); if (elt->children) - gtk_tree_model_filter_free_level (filter, - FILTER_LEVEL (elt->children), - unref); + { + /* If we recurse and unref_self == FALSE, then unref_parent + * must also be FALSE (otherwise a still unref a node in this + * level). + */ + gtk_tree_model_filter_free_level (filter, + FILTER_LEVEL (elt->children), + unref_self, + unref_self == FALSE ? FALSE : unref_parent, + unref_external); + } + + if (unref_external) + { + GtkTreeIter f_iter; + + f_iter.stamp = filter->priv->stamp; + f_iter.user_data = filter_level; + f_iter.user_data2 = elt; + + while (elt->ext_ref_count > 0) + gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter), + &f_iter, + TRUE, unref_self); + } } /* Release the reference on the first item. */ - if (unref) + if (unref_self) { GtkTreeIter f_iter; @@ -976,20 +1005,22 @@ gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter, filter->priv->zero_ref_count--; } +#ifdef MODEL_FILTER_DEBUG + if (filter_level == filter->priv->root) + g_assert (filter->priv->zero_ref_count == 0); +#endif + if (filter_level->parent_elt) { /* Release reference on parent */ - if (unref) - { - GtkTreeIter parent_iter; + GtkTreeIter parent_iter; - parent_iter.stamp = filter->priv->stamp; - parent_iter.user_data = filter_level->parent_level; - parent_iter.user_data2 = filter_level->parent_elt; + parent_iter.stamp = filter->priv->stamp; + parent_iter.user_data = filter_level->parent_level; + parent_iter.user_data2 = filter_level->parent_elt; - gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter), - &parent_iter, FALSE, TRUE); - } + gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter), + &parent_iter, FALSE, unref_parent); filter_level->parent_elt->children = NULL; } @@ -1001,6 +1032,100 @@ gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter, g_free (filter_level); } +/* prune_level() is like free_level(), however instead of being fully + * freed, the level is pruned to a level with only the first node used + * for monitoring. For now it is only being called from + * gtk_tree_model_filter_remove_elt_from_level(), which is the reason + * this function is lacking a "gboolean unref" argument. + */ +static void +gtk_tree_model_filter_prune_level (GtkTreeModelFilter *filter, + FilterLevel *level) +{ + GSequenceIter *siter; + GSequenceIter *end_siter; + FilterElt *elt; + GtkTreeIter f_iter; + + /* This function is called when the parent of level became invisible. + * All external ref counts of the children need to be dropped. + * All children except the first one can be removed. + */ + + /* Any child levels can be freed */ + end_siter = g_sequence_get_end_iter (level->seq); + for (siter = g_sequence_get_begin_iter (level->seq); + siter != end_siter; + siter = g_sequence_iter_next (siter)) + { + FilterElt *elt = g_sequence_get (siter); + + if (elt->children) + gtk_tree_model_filter_free_level (filter, + FILTER_LEVEL (elt->children), + TRUE, TRUE, TRUE); + } + + /* For the first item, only drop the external references */ + elt = g_sequence_get (g_sequence_get_begin_iter (level->seq)); + + f_iter.stamp = filter->priv->stamp; + f_iter.user_data = level; + f_iter.user_data2 = elt; + + while (elt->ext_ref_count > 0) + gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter), + &f_iter, TRUE, TRUE); + + if (elt->visible_siter) + { + g_sequence_remove (elt->visible_siter); + elt->visible_siter = NULL; + } + + /* Remove the other elts */ + end_siter = g_sequence_get_end_iter (level->seq); + siter = g_sequence_get_begin_iter (level->seq); + siter = g_sequence_iter_next (siter); + for (; siter != end_siter; siter = g_sequence_iter_next (siter)) + { + elt = g_sequence_get (siter); + + f_iter.stamp = filter->priv->stamp; + f_iter.user_data = level; + f_iter.user_data2 = elt; + + while (elt->ext_ref_count > 0) + gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter), + &f_iter, TRUE, TRUE); + /* In this case, we do remove reference counts we've added ourselves, + * since the node will be removed from the data structures. + */ + while (elt->ref_count > 0) + gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter), + &f_iter, FALSE, TRUE); + + if (elt->visible_siter) + { + g_sequence_remove (elt->visible_siter); + elt->visible_siter = NULL; + } + } + + /* Remove [begin + 1, end] */ + siter = g_sequence_get_begin_iter (level->seq); + siter = g_sequence_iter_next (siter); + + g_sequence_remove_range (siter, end_siter); + + /* The level must have reached an ext ref count of zero by now, though + * we only assert on this in debugging mode. + */ +#ifdef MODEL_FILTER_DEBUG + g_assert (level->ext_ref_count == 0); +#endif +} + static void gtk_tree_model_filter_level_transfer_first_ref (GtkTreeModelFilter *filter, FilterLevel *level, @@ -1137,7 +1262,7 @@ gtk_tree_model_filter_real_visible (GtkTreeModelFilter *filter, } else if (filter->priv->visible_column >= 0) { - GValue val = {0, }; + GValue val = G_VALUE_INIT; gtk_tree_model_get_value (child_model, child_iter, filter->priv->visible_column, &val); @@ -1171,6 +1296,10 @@ gtk_tree_model_filter_clear_cache_helper_iter (gpointer data, GtkTreeModelFilter *filter = user_data; FilterElt *elt = data; +#ifdef MODEL_FILTER_DEBUG + g_assert (elt->zero_ref_count >= 0); +#endif + if (elt->zero_ref_count > 0) gtk_tree_model_filter_clear_cache_helper (filter, elt->children); } @@ -1189,11 +1318,15 @@ gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter, * free the level if the parent level also has an external ref * count of zero. In that case, changes concerning our parent are * not requested. + * + * The root level is always visible, so an exception holds for levels + * with the root level as parent level: these have to remain cached. */ if (level->ext_ref_count == 0 && level != filter->priv->root && - level->parent_level && level->parent_level->ext_ref_count == 0) + level->parent_level && level->parent_level != filter->priv->root && + level->parent_level->ext_ref_count == 0) { - gtk_tree_model_filter_free_level (filter, level, TRUE); + gtk_tree_model_filter_free_level (filter, level, TRUE, TRUE, FALSE); return; } } @@ -1511,37 +1644,37 @@ gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter, gboolean emit_child_toggled = FALSE; + /* We need to know about the level's ext ref count before removal + * of this node. + */ + orig_level_ext_ref_count = level->ext_ref_count; + iter.stamp = filter->priv->stamp; iter.user_data = level; iter.user_data2 = elt; - path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter); - parent = level->parent_elt; parent_level = level->parent_level; - length = g_sequence_get_length (level->seq); + if (!parent || orig_level_ext_ref_count > 0) + path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter); + else + /* If the level is not visible, the parent is potentially invisible + * too. Either way, as no signal will be emitted, there is no use + * for a path. + */ + path = NULL; - /* We need to know about the level's ext ref count before removal - * of this node. - */ - orig_level_ext_ref_count = level->ext_ref_count; + length = g_sequence_get_length (level->seq); /* first register the node to be invisible */ g_sequence_remove (elt->visible_siter); elt->visible_siter = NULL; - /* we distinguish a couple of cases: - * - root level, length > 1: emit row-deleted and remove. - * - root level, length == 1: emit row-deleted and keep in cache. - * - level, length == 1: parent->ext_ref_count > 0: emit row-deleted - * and keep. - * - level, length > 1: emit row-deleted and remove. - * - else, remove level. - * - * if level != root level and the number of visible nodes is 0 (ie. this - * is the last node to be removed from the level), emit - * row-has-child-toggled. + /* + * If level != root level and the number of visible nodes is 0 (ie. this + * is the last node to be removed from the level), emit + * row-has-child-toggled. */ if (level != filter->priv->root @@ -1550,6 +1683,12 @@ gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter, && parent->visible_siter) emit_child_toggled = TRUE; + /* Distinguish: + * - length > 1: in this case, the node is removed from the level + * and row-deleted is emitted. + * - length == 1: in this case, we need to decide whether to keep + * the level or to free it. + */ if (length > 1) { GSequenceIter *siter; @@ -1558,8 +1697,13 @@ gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter, * If it has any children, these will be removed here as well. */ + /* FIXME: I am not 100% sure it is always save to fully free the + * level here. Perhaps the state of the parent level, etc. has to + * be checked to make the right decision, like is done below for + * the case length == 1. + */ if (elt->children) - gtk_tree_model_filter_free_level (filter, elt->children, TRUE); + gtk_tree_model_filter_free_level (filter, elt->children, TRUE, TRUE, TRUE); /* If the first node is being removed, transfer, the reference */ if (elt == g_sequence_get (g_sequence_get_begin_iter (level->seq))) @@ -1570,10 +1714,13 @@ gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter, while (elt->ext_ref_count > 0) gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter), - &iter, TRUE, FALSE); + &iter, TRUE, TRUE); + /* In this case, we do remove reference counts we've added ourselves, + * since the node will be removed from the data structures. + */ while (elt->ref_count > 0) gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter), - &iter, FALSE, FALSE); + &iter, FALSE, TRUE); /* remove the node */ lookup_elt_with_offset (level->seq, elt->offset, &siter); @@ -1587,40 +1734,61 @@ gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter, if (!parent || orig_level_ext_ref_count > 0) gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path); } - else if ((length == 1 && parent && parent->ext_ref_count > 0) - || (length == 1 && level == filter->priv->root)) + else { - /* We emit row-deleted, but keep the node in the cache and - * referenced. Its children will be removed. - */ - - if (elt->children) - { - gtk_tree_model_filter_free_level (filter, elt->children, TRUE); - elt->children = NULL; - } - - gtk_tree_model_filter_increment_stamp (filter); + /* There is only one node left in this level */ +#ifdef MODEL_FILTER_DEBUG + g_assert (length == 1); +#endif - /* Only if the node is in the root level (parent == NULL) or - * the level is visible, a row-deleted signal is necessary. + /* The row is signalled as deleted to the client. We have to + * drop the remaining external reference count here, the client + * will not do it. + * + * We keep the reference counts we've obtained ourselves. */ - if (!parent || orig_level_ext_ref_count > 0) - gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path); - } - else - { while (elt->ext_ref_count > 0) gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter), - &iter, TRUE, FALSE); - while (elt->ref_count > 0) - gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter), - &iter, FALSE, FALSE); - - /* Blow level away, including any child levels */ - gtk_tree_model_filter_free_level (filter, level, TRUE); + &iter, TRUE, TRUE); - gtk_tree_model_filter_increment_stamp (filter); + /* This level is still required if: + * - it is the root level + * - its parent level is the root level + * - its parent level has an external ref count > 0 + */ + if (! (level == filter->priv->root || + level->parent_level == filter->priv->root || + level->parent_level->ext_ref_count > 0)) + { + /* Otherwise, the level can be removed */ + gtk_tree_model_filter_free_level (filter, level, TRUE, TRUE, TRUE); + } + else + { + /* Level is kept, but we turn our attention to a child level. + * + * If level is not the root level, it is a child level with + * an ext ref count that is now 0. That means that any child level + * of elt can be removed. + */ + if (level != filter->priv->root) + { +#ifdef MODEL_FILTER_DEBUG + g_assert (level->ext_ref_count == 0); +#endif + if (elt->children) + gtk_tree_model_filter_free_level (filter, elt->children, + TRUE, TRUE, TRUE); + } + else + { + /* In this case, we want to keep the level with the first + * node pulled in to monitor for signals. + */ + if (elt->children) + gtk_tree_model_filter_prune_level (filter, elt->children); + } + } if (!parent || orig_level_ext_ref_count > 0) gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path); @@ -1903,17 +2071,17 @@ gtk_tree_model_filter_row_changed (GtkTreeModel *c_model, if (current_state == TRUE && requested_state == TRUE) { - /* propagate the signal; also get a path taking only visible - * nodes into account. - */ - gtk_tree_path_free (path); - path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter); - level = FILTER_LEVEL (iter.user_data); elt = FILTER_ELT (iter.user_data2); if (gtk_tree_model_filter_elt_is_visible_in_target (level, elt)) { + /* propagate the signal; also get a path taking only visible + * nodes into account. + */ + gtk_tree_path_free (path); + path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter); + if (level->ext_ref_count > 0) gtk_tree_model_row_changed (GTK_TREE_MODEL (filter), path, &iter); @@ -2121,7 +2289,8 @@ gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model, } done: - gtk_tree_model_filter_check_ancestors (filter, real_path); + if (real_path) + gtk_tree_model_filter_check_ancestors (filter, real_path); if (emit_row_inserted) gtk_tree_model_filter_emit_row_inserted_for_path (filter, c_model, @@ -2263,7 +2432,7 @@ gtk_tree_model_filter_virtual_root_deleted (GtkTreeModelFilter *filter, * nodes will fail, since the respective nodes in the child model are * no longer there. */ - gtk_tree_model_filter_free_level (filter, filter->priv->root, FALSE); + gtk_tree_model_filter_free_level (filter, filter->priv->root, FALSE, TRUE, FALSE); gtk_tree_model_filter_increment_stamp (filter); @@ -2442,14 +2611,24 @@ gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model, while (elt->ext_ref_count > 0) gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter, TRUE, FALSE); - while (elt->ref_count > 0) - gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter, - FALSE, FALSE); + + if (elt->children) + /* If this last node has children, then the recursion in free_level + * will release this reference. + */ + while (elt->ref_count > 1) + gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter, + FALSE, FALSE); + else + while (elt->ref_count > 0) + gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter, + FALSE, FALSE); + if (g_sequence_get_length (level->seq) == 1) { /* kill level */ - gtk_tree_model_filter_free_level (filter, level, FALSE); + gtk_tree_model_filter_free_level (filter, level, FALSE, TRUE, FALSE); } else { @@ -2459,8 +2638,13 @@ gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model, lookup_elt_with_offset (level->seq, elt->offset, &siter); is_first = g_sequence_get_begin_iter (level->seq) == siter; + if (elt->children) + gtk_tree_model_filter_free_level (filter, elt->children, + FALSE, FALSE, FALSE); + /* remove the row */ - g_sequence_remove (elt->visible_siter); + if (elt->visible_siter) + g_sequence_remove (elt->visible_siter); tmp = g_sequence_iter_next (siter); g_sequence_remove (siter); g_sequence_foreach_range (tmp, g_sequence_get_end_iter (level->seq), @@ -2546,7 +2730,7 @@ gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model, GSequence *tmp_seq; GSequenceIter *tmp_end_iter; - GSequenceIter *old_first_elt = NULL; + GSequenceIter *old_first_siter = NULL; gint *tmp_array; gint i, elt_count; gint length; @@ -2666,6 +2850,8 @@ gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model, tmp_array = g_new (gint, g_sequence_get_length (level->visible_seq)); elt_count = 0; + old_first_siter = g_sequence_get_iter_at_pos (level->seq, 0); + for (i = 0; i < length; i++) { FilterElt *elt; @@ -2675,10 +2861,6 @@ gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model, if (elt == NULL) continue; - /* Keep a reference if this elt has old_pos == 0 */ - if (new_order[i] == 0) - old_first_elt = siter; - /* Only for visible items an entry should be present in the order array * to be emitted. */ @@ -2696,15 +2878,15 @@ gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model, g_sequence_sort (level->visible_seq, filter_elt_cmp, NULL); /* Transfer the reference from the old item at position 0 to the - * new item at position 0. + * new item at position 0, unless the old item at position 0 is also + * at position 0 in the new sequence. */ - if (old_first_elt && g_sequence_iter_get_position (old_first_elt)) + if (g_sequence_iter_get_position (old_first_siter) != 0) gtk_tree_model_filter_level_transfer_first_ref (filter, level, - old_first_elt, + old_first_siter, g_sequence_get_iter_at_pos (level->seq, 0)); - /* emit rows_reordered */ if (g_sequence_get_length (level->visible_seq) > 0) { @@ -3011,7 +3193,6 @@ static gboolean gtk_tree_model_filter_iter_next (GtkTreeModel *model, GtkTreeIter *iter) { - FilterLevel *level; FilterElt *elt; GSequenceIter *siter; @@ -3019,7 +3200,6 @@ gtk_tree_model_filter_iter_next (GtkTreeModel *model, g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE); g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE); - level = iter->user_data; elt = iter->user_data2; siter = g_sequence_iter_next (elt->visible_siter); @@ -3047,12 +3227,12 @@ gtk_tree_model_filter_iter_previous (GtkTreeModel *model, elt = iter->user_data2; - siter = g_sequence_iter_prev (elt->visible_siter); - if (g_sequence_iter_is_begin (siter)) + if (g_sequence_iter_is_begin (elt->visible_siter)) { iter->stamp = 0; return FALSE; } + siter = g_sequence_iter_prev (elt->visible_siter); iter->user_data2 = GET_ELT (siter); @@ -3312,8 +3492,20 @@ gtk_tree_model_filter_real_ref_node (GtkTreeModel *model, if (filter->priv->root != level) filter->priv->zero_ref_count--; + +#ifdef MODEL_FILTER_DEBUG + g_assert (filter->priv->zero_ref_count >= 0); + if (filter->priv->zero_ref_count > 0) + g_assert (filter->priv->root != NULL); +#endif } } + +#ifdef MODEL_FILTER_DEBUG + g_assert (elt->ref_count >= elt->ext_ref_count); + g_assert (elt->ref_count >= 0); + g_assert (elt->ext_ref_count >= 0); +#endif } static void @@ -3348,6 +3540,11 @@ gtk_tree_model_filter_real_unref_node (GtkTreeModel *model, elt = iter->user_data2; g_return_if_fail (elt->ref_count > 0); +#ifdef MODEL_FILTER_DEBUG + g_assert (elt->ref_count >= elt->ext_ref_count); + g_assert (elt->ref_count >= 0); + g_assert (elt->ext_ref_count >= 0); +#endif elt->ref_count--; level->ref_count--; @@ -3373,8 +3570,20 @@ gtk_tree_model_filter_real_unref_node (GtkTreeModel *model, if (filter->priv->root != level) filter->priv->zero_ref_count++; + +#ifdef MODEL_FILTER_DEBUG + g_assert (filter->priv->zero_ref_count >= 0); + if (filter->priv->zero_ref_count > 0) + g_assert (filter->priv->root != NULL); +#endif } } + +#ifdef MODEL_FILTER_DEBUG + g_assert (elt->ref_count >= elt->ext_ref_count); + g_assert (elt->ref_count >= 0); + g_assert (elt->ext_ref_count >= 0); +#endif } /* TreeDragSource interface implementation */ @@ -3455,7 +3664,8 @@ gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter, /* reset our state */ if (filter->priv->root) - gtk_tree_model_filter_free_level (filter, filter->priv->root, TRUE); + gtk_tree_model_filter_free_level (filter, filter->priv->root, + TRUE, TRUE, FALSE); filter->priv->root = NULL; g_object_unref (filter->priv->child_model); @@ -3548,10 +3758,14 @@ gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter, { g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter)); - if (!root) - filter->priv->virtual_root = NULL; + if (root) + { + filter->priv->virtual_root = gtk_tree_path_copy (root); + gtk_tree_model_filter_ref_path (filter, filter->priv->virtual_root); + filter->priv->virtual_root_deleted = FALSE; + } else - filter->priv->virtual_root = gtk_tree_path_copy (root); + filter->priv->virtual_root = NULL; } /* public API */ @@ -3572,24 +3786,12 @@ GtkTreeModel * gtk_tree_model_filter_new (GtkTreeModel *child_model, GtkTreePath *root) { - GtkTreeModel *retval; - GtkTreeModelFilter *filter; - g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL); - retval = g_object_new (GTK_TYPE_TREE_MODEL_FILTER, - "child-model", child_model, - "virtual-root", root, - NULL); - - filter = GTK_TREE_MODEL_FILTER (retval); - if (filter->priv->virtual_root) - { - gtk_tree_model_filter_ref_path (filter, filter->priv->virtual_root); - filter->priv->virtual_root_deleted = FALSE; - } - - return retval; + return g_object_new (GTK_TYPE_TREE_MODEL_FILTER, + "child-model", child_model, + "virtual-root", root, + NULL); } /**