* 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 <http://www.gnu.org/licenses/>.
*/
#include "config.h"
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,
gtk_tree_path_free (filter->priv->virtual_root);
if (filter->priv->root)
- gtk_tree_model_filter_free_level (filter, filter->priv->root, TRUE, FALSE);
+ gtk_tree_model_filter_free_level (filter, filter->priv->root, TRUE, TRUE, FALSE);
g_free (filter->priv->modify_types);
if (empty &&
(parent_level && parent_level->ext_ref_count == 0))
{
- gtk_tree_model_filter_free_level (filter, new_level, FALSE, FALSE);
+ gtk_tree_model_filter_free_level (filter, new_level, FALSE, TRUE, FALSE);
return;
}
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;
FilterElt *elt = g_sequence_get (siter);
if (elt->children)
- gtk_tree_model_filter_free_level (filter,
- FILTER_LEVEL (elt->children),
- unref, unref_external);
+ {
+ /* 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)
{
while (elt->ext_ref_count > 0)
gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
&f_iter,
- TRUE, unref);
+ TRUE, unref_self);
}
}
/* Release the reference on the first item.
*/
- if (unref)
+ if (unref_self)
{
GtkTreeIter f_iter;
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;
}
if (elt->children)
gtk_tree_model_filter_free_level (filter,
- FILTER_LEVEL (elt->children), TRUE,
- TRUE);
+ FILTER_LEVEL (elt->children),
+ TRUE, TRUE, TRUE);
}
/* For the first item, only drop the external references */
}
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);
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, FALSE);
+ gtk_tree_model_filter_free_level (filter, level, TRUE, TRUE, FALSE);
return;
}
}
iter.user_data = level;
iter.user_data2 = elt;
- if (orig_level_ext_ref_count > 0)
+ parent = level->parent_elt;
+ parent_level = level->parent_level;
+
+ 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
*/
path = NULL;
- parent = level->parent_elt;
- parent_level = level->parent_level;
-
length = g_sequence_get_length (level->seq);
/* first register the node to be invisible */
* the case length == 1.
*/
if (elt->children)
- gtk_tree_model_filter_free_level (filter, elt->children, TRUE, 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)))
level->parent_level->ext_ref_count > 0))
{
/* Otherwise, the level can be removed */
- gtk_tree_model_filter_free_level (filter, level, TRUE, TRUE);
+ gtk_tree_model_filter_free_level (filter, level, TRUE, TRUE, TRUE);
}
else
{
#endif
if (elt->children)
gtk_tree_model_filter_free_level (filter, elt->children,
- TRUE, TRUE);
+ TRUE, TRUE, TRUE);
}
else
{
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);
* 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, FALSE);
+ gtk_tree_model_filter_free_level (filter, filter->priv->root, FALSE, TRUE, FALSE);
gtk_tree_model_filter_increment_stamp (filter);
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, FALSE);
+ gtk_tree_model_filter_free_level (filter, level, FALSE, TRUE, FALSE);
}
else
{
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),
gtk_tree_model_filter_iter_next (GtkTreeModel *model,
GtkTreeIter *iter)
{
- FilterLevel *level;
FilterElt *elt;
GSequenceIter *siter;
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);
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);
#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 (filter->priv->zero_ref_count >= 0);
+ if (filter->priv->zero_ref_count > 0)
+ g_assert (filter->priv->root != NULL);
#endif
}
}
/* reset our state */
if (filter->priv->root)
gtk_tree_model_filter_free_level (filter, filter->priv->root,
- TRUE, FALSE);
+ TRUE, TRUE, FALSE);
filter->priv->root = NULL;
g_object_unref (filter->priv->child_model);
{
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 */
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);
}
/**