+/* 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
+}
+