#include "gtktreemodelfilter.h"
#include "gtkintl.h"
#include "gtktreednd.h"
-#include "gtkalias.h"
#include "gtkprivate.h"
+#include "gtkalias.h"
#include <string.h>
/* ITER FORMAT:
GType *modify_types;
GtkTreeModelFilterModifyFunc modify_func;
gpointer modify_data;
- gpointer modify_destroy;
+ GtkDestroyNotify modify_destroy;
gint visible_column;
gboolean modify_func_set;
gboolean in_row_deleted;
+ gboolean virtual_root_deleted;
/* signal ids */
guint changed_id;
filter->priv->visible_method_set = FALSE;
filter->priv->modify_func_set = FALSE;
filter->priv->in_row_deleted = FALSE;
+ filter->priv->virtual_root_deleted = FALSE;
}
static void
{
GtkTreeModelFilter *filter = (GtkTreeModelFilter *) object;
- if (filter->priv->virtual_root)
- gtk_tree_model_filter_unref_path (filter, filter->priv->virtual_root);
+ if (filter->priv->virtual_root && !filter->priv->virtual_root_deleted)
+ {
+ gtk_tree_model_filter_unref_path (filter, filter->priv->virtual_root);
+ filter->priv->virtual_root_deleted = TRUE;
+ }
gtk_tree_model_filter_set_model (filter, NULL);
if (filter->priv->root)
gtk_tree_model_filter_free_level (filter, filter->priv->root);
- if (filter->priv->modify_types)
- g_free (filter->priv->modify_types);
+ g_free (filter->priv->modify_types);
+
+ if (filter->priv->modify_destroy)
+ filter->priv->modify_destroy (filter->priv->modify_data);
+
+ if (filter->priv->visible_destroy)
+ filter->priv->visible_destroy (filter->priv->visible_data);
/* must chain up */
G_OBJECT_CLASS (gtk_tree_model_filter_parent_class)->finalize (object);
FilterLevel *parent_level = filter_level->parent_level;
FilterElt *parent_elt = filter_level->parent_elt;
- do
+ while (parent_level)
{
- if (parent_elt)
- parent_elt->zero_ref_count--;
+ parent_elt->zero_ref_count--;
- if (parent_level)
- {
- parent_elt = parent_level->parent_elt;
- parent_level = parent_level->parent_level;
- }
+ parent_elt = parent_level->parent_elt;
+ parent_level = parent_level->parent_level;
}
- while (parent_level);
+
if (filter_level != filter->priv->root)
filter->priv->zero_ref_count--;
}
g_array_insert_val (level->array, i, elt);
*index = i;
- if (i > 0)
- i--;
-
- for ( ; i < level->array->len; i++)
+ for (i = 0; i < level->array->len; i++)
{
FilterElt *e = &(g_array_index (level->array, FilterElt, i));
if (e->children)
{
FilterElt *elt, *parent;
FilterLevel *level, *parent_level;
- gint offset, i, length;
+ gint i, length;
gboolean emit_child_toggled = FALSE;
parent_level = level->parent_level;
length = level->array->len;
- offset = elt->offset;
/* we distinguish a couple of cases:
* - root level, length > 1: emit row-deleted and remove.
GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
GtkTreePath *path;
GtkTreeIter iter;
- FilterElt *elt, *parent;
- FilterLevel *level, *parent_level;
+ FilterElt *elt, *parent = NULL;
+ FilterLevel *level, *parent_level = NULL;
gboolean emit_child_toggled = FALSE;
gint offset;
gint i;
GtkTreePath *path;
FilterLevel *level = FILTER_LEVEL (filter->priv->root);
+ gtk_tree_model_filter_unref_path (filter, filter->priv->virtual_root);
+ filter->priv->virtual_root_deleted = TRUE;
+
if (!level)
return;
FilterElt *parent_elt = level->parent_elt;
/* we were at zero -- time to decrease the zero_ref_count val */
- do
+ while (parent_level)
{
- if (parent_elt)
- parent_elt->zero_ref_count--;
+ parent_elt->zero_ref_count--;
- if (parent_level)
- {
- parent_elt = parent_level->parent_elt;
- parent_level = parent_level->parent_level;
- }
+ parent_elt = parent_level->parent_elt;
+ parent_level = parent_level->parent_level;
}
- while (parent_level);
- filter->priv->zero_ref_count--;
+
+ if (filter->priv->root != level)
+ filter->priv->zero_ref_count--;
}
}
parent_elt = parent_level->parent_elt;
parent_level = parent_level->parent_level;
}
- filter->priv->zero_ref_count++;
+
+ if (filter->priv->root != level)
+ filter->priv->zero_ref_count++;
}
}
filter = GTK_TREE_MODEL_FILTER (retval);
if (filter->priv->virtual_root)
- gtk_tree_model_filter_ref_path (filter, filter->priv->virtual_root);
+ {
+ gtk_tree_model_filter_ref_path (filter, filter->priv->virtual_root);
+ filter->priv->virtual_root_deleted = FALSE;
+ }
return retval;
}
* @child_iter: A valid #GtkTreeIter pointing to a row on the child model.
*
* Sets @filter_iter to point to the row in @filter that corresponds to the
- * row pointed at by @child_iter.
+ * row pointed at by @child_iter. If @filter_iter was not set, %FALSE is
+ * returned.
+ *
+ * Return value: %TRUE, if @filter_iter was set, i.e. if @child_iter is a
+ * valid iterator pointing to a visible row in child model.
*
* Since: 2.4
*/
-void
+gboolean
gtk_tree_model_filter_convert_child_iter_to_iter (GtkTreeModelFilter *filter,
GtkTreeIter *filter_iter,
GtkTreeIter *child_iter)
{
+ gboolean ret;
GtkTreePath *child_path, *path;
- g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
- g_return_if_fail (filter->priv->child_model != NULL);
- g_return_if_fail (filter_iter != NULL);
- g_return_if_fail (child_iter != NULL);
+ g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), FALSE);
+ g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
+ g_return_val_if_fail (filter_iter != NULL, FALSE);
+ g_return_val_if_fail (child_iter != NULL, FALSE);
filter_iter->stamp = 0;
child_path = gtk_tree_model_get_path (filter->priv->child_model, child_iter);
- g_return_if_fail (child_path != NULL);
+ g_return_val_if_fail (child_path != NULL, FALSE);
path = gtk_tree_model_filter_convert_child_path_to_path (filter,
child_path);
gtk_tree_path_free (child_path);
- g_return_if_fail (path != NULL);
- gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), filter_iter, path);
+ if (!path)
+ return FALSE;
+
+ ret = gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), filter_iter, path);
gtk_tree_path_free (path);
+
+ return ret;
}
/**
* Converts @child_path to a path relative to @filter. That is, @child_path
* points to a path in the child model. The rerturned path will point to the
* same row in the filtered model. If @child_path isn't a valid path on the
- * child model, then %NULL is returned.
+ * child model or points to a row which is not visible in @filter, then %NULL
+ * is returned.
*
* Return value: A newly allocated #GtkTreePath, or %NULL.
*
TRUE,
TRUE);
+ if (!path)
+ return NULL;
+
/* get a new path which only takes visible nodes into account.
* -- if this gives any performance issues, we can write a special
* version of convert_child_path_to_path immediately returning
* a visible-nodes-only path.
*/
- gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
+ gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (filter), &iter, path);
gtk_tree_path_free (path);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);