* we warned you and we're not liable for any head injuries.
*/
-#include <config.h>
+#include "config.h"
#include <string.h>
#include "gtktreemodelsort.h"
#include "gtktreestore.h"
#include "gtktreedatalist.h"
#include "gtkintl.h"
+#include "gtkprivate.h"
#include "gtktreednd.h"
#include "gtkalias.h"
#define SORT_ELT(sort_elt) ((SortElt *)sort_elt)
#define SORT_LEVEL(sort_level) ((SortLevel *)sort_level)
-#define GET_CHILD_ITER(tree_model_sort,ch_iter,so_iter) gtk_tree_model_sort_convert_iter_to_child_iter(GTK_TREE_MODEL_SORT (tree_model_sort), ch_iter, so_iter);
+#define GET_CHILD_ITER(tree_model_sort,ch_iter,so_iter) gtk_tree_model_sort_convert_iter_to_child_iter((GtkTreeModelSort*)(tree_model_sort), (ch_iter), (so_iter));
#define NO_SORT_FUNC ((GtkTreeIterCompareFunc) 0x1)
-#define VALID_ITER(iter, tree_model_sort) (iter != NULL && iter->user_data != NULL && iter->user_data2 != NULL && tree_model_sort->stamp == iter->stamp)
+#define VALID_ITER(iter, tree_model_sort) ((iter) != NULL && (iter)->user_data != NULL && (iter)->user_data2 != NULL && (tree_model_sort)->stamp == (iter)->stamp)
/* general (object/interface init, etc) */
-static void gtk_tree_model_sort_init (GtkTreeModelSort *tree_model_sort);
-static void gtk_tree_model_sort_class_init (GtkTreeModelSortClass *tree_model_sort_class);
static void gtk_tree_model_sort_tree_model_init (GtkTreeModelIface *iface);
static void gtk_tree_model_sort_tree_sortable_init (GtkTreeSortableIface *iface);
static void gtk_tree_model_sort_drag_source_init (GtkTreeDragSourceIface*iface);
gint sort_column_id,
GtkTreeIterCompareFunc func,
gpointer data,
- GtkDestroyNotify destroy);
+ GDestroyNotify destroy);
static void gtk_tree_model_sort_set_default_sort_func (GtkTreeSortable *sortable,
GtkTreeIterCompareFunc func,
gpointer data,
- GtkDestroyNotify destroy);
+ GDestroyNotify destroy);
static gboolean gtk_tree_model_sort_has_default_sort_func (GtkTreeSortable *sortable);
/* Private functions (sort funcs, level handling and other utils) */
GtkTreePath *child_path,
gboolean build_levels);
-static GObjectClass *parent_class = NULL;
-GType
-gtk_tree_model_sort_get_type (void)
-{
- static GType tree_model_sort_type = 0;
-
- if (!tree_model_sort_type)
- {
- static const GTypeInfo tree_model_sort_info =
- {
- sizeof (GtkTreeModelSortClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) gtk_tree_model_sort_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (GtkTreeModelSort),
- 0, /* n_preallocs */
- (GInstanceInitFunc) gtk_tree_model_sort_init
- };
-
- static const GInterfaceInfo tree_model_info =
- {
- (GInterfaceInitFunc) gtk_tree_model_sort_tree_model_init,
- NULL,
- NULL
- };
-
- static const GInterfaceInfo sortable_info =
- {
- (GInterfaceInitFunc) gtk_tree_model_sort_tree_sortable_init,
- NULL,
- NULL
- };
-
- static const GInterfaceInfo drag_source_info =
- {
- (GInterfaceInitFunc) gtk_tree_model_sort_drag_source_init,
- NULL,
- NULL
- };
-
- tree_model_sort_type =
- g_type_register_static (G_TYPE_OBJECT, "GtkTreeModelSort",
- &tree_model_sort_info, 0);
-
- g_type_add_interface_static (tree_model_sort_type,
- GTK_TYPE_TREE_MODEL,
- &tree_model_info);
-
- g_type_add_interface_static (tree_model_sort_type,
- GTK_TYPE_TREE_SORTABLE,
- &sortable_info);
-
- g_type_add_interface_static (tree_model_sort_type,
- GTK_TYPE_TREE_DRAG_SOURCE,
- &drag_source_info);
- }
-
- return tree_model_sort_type;
-}
+G_DEFINE_TYPE_WITH_CODE (GtkTreeModelSort, gtk_tree_model_sort, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
+ gtk_tree_model_sort_tree_model_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
+ gtk_tree_model_sort_tree_sortable_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
+ gtk_tree_model_sort_drag_source_init))
static void
gtk_tree_model_sort_init (GtkTreeModelSort *tree_model_sort)
GObjectClass *object_class;
object_class = (GObjectClass *) class;
- parent_class = g_type_class_peek_parent (class);
object_class->set_property = gtk_tree_model_sort_set_property;
object_class->get_property = gtk_tree_model_sort_get_property;
P_("TreeModelSort Model"),
P_("The model for the TreeModelSort to sort"),
GTK_TYPE_TREE_MODEL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
static void
* gtk_tree_model_sort_new_with_model:
* @child_model: A #GtkTreeModel
*
- * Creates a new #GtkTreeModel, with @child_model as the child_model.
+ * Creates a new #GtkTreeModel, with @child_model as the child model.
*
* Return value: A new #GtkTreeModel.
*/
tree_model_sort->sort_list = NULL;
}
+ if (tree_model_sort->default_sort_destroy)
+ {
+ tree_model_sort->default_sort_destroy (tree_model_sort->default_sort_data);
+ tree_model_sort->default_sort_destroy = NULL;
+ tree_model_sort->default_sort_data = NULL;
+ }
+
+
/* must chain up */
- parent_class->finalize (object);
+ G_OBJECT_CLASS (gtk_tree_model_sort_parent_class)->finalize (object);
}
static void
}
gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
+ gtk_tree_model_sort_ref_node (GTK_TREE_MODEL (data), &iter);
level = iter.user_data;
elt = iter.user_data2;
gtk_tree_path_free (start_s_path);
gtk_tree_model_row_changed (GTK_TREE_MODEL (data), path, &iter);
+ gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (data), &iter);
gtk_tree_path_free (path);
return;
}
-
+
if (!GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
{
gtk_tree_model_get_iter (tree_model_sort->child_model,
/* emit row_changed signal (at new location) */
gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
gtk_tree_model_row_changed (GTK_TREE_MODEL (data), path, &iter);
+ gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (data), &iter);
gtk_tree_path_free (path);
if (free_s_path)
if (level->array->len < gtk_tree_path_get_indices (s_path)[i])
{
- g_warning ("A node was inserted with a parent that's not in the tree.\n"
+ g_warning ("%s: A node was inserted with a parent that's not in the tree.\n"
"This possibly means that a GtkTreeModel inserted a child node\n"
- "before the parent was inserted.");
+ "before the parent was inserted.",
+ G_STRLOC);
goto done;
}
if (!elt->children)
{
- GtkTreePath *tmppath;
- GtkTreeIter tmpiter;
-
- tmpiter.stamp = tree_model_sort->stamp;
- tmpiter.user_data = level;
- tmpiter.user_data2 = elt;
-
- tmppath = gtk_tree_model_get_path (GTK_TREE_MODEL (data), &tmpiter);
- if (tmppath)
- {
- gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data),
- tmppath,
- &tmpiter);
- gtk_tree_path_free (tmppath);
- }
-
/* not covering this signal */
goto done;
}
if (!parent_level)
goto done;
+ if (level->ref_count == 0 && level != tree_model_sort->root)
+ {
+ gtk_tree_model_sort_free_level (tree_model_sort, level);
+ goto done;
+ }
+
if (!gtk_tree_model_sort_insert_value (tree_model_sort,
parent_level,
s_path,
gtk_tree_path_free (path);
}
-/* FIXME: I still have doubts if this works */
static void
gtk_tree_model_sort_row_deleted (GtkTreeModel *s_model,
GtkTreePath *s_path,
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. */
+ /* 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_path_free (path);
if (level == tree_model_sort->root)
- tree_model_sort->root = NULL;
+ {
+ gtk_tree_model_sort_free_level (tree_model_sort,
+ tree_model_sort->root);
+ tree_model_sort->root = NULL;
+ }
return;
}
g_return_if_fail (new_order != NULL);
- if (s_path == NULL || gtk_tree_path_get_indices (s_path) == NULL)
+ if (s_path == NULL || gtk_tree_path_get_depth (s_path) == 0)
{
if (tree_model_sort->root == NULL)
return;
static GtkTreeModelFlags
gtk_tree_model_sort_get_flags (GtkTreeModel *tree_model)
{
+ GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
GtkTreeModelFlags flags;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), 0);
- g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, 0);
+ g_return_val_if_fail (tree_model_sort->child_model != NULL, 0);
- flags = gtk_tree_model_get_flags (GTK_TREE_MODEL_SORT (tree_model)->child_model);
+ flags = gtk_tree_model_get_flags (tree_model_sort->child_model);
if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
return GTK_TREE_MODEL_LIST_ONLY;
{
GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), 0);
-
if (tree_model_sort->child_model == 0)
return 0;
gtk_tree_model_sort_get_column_type (GtkTreeModel *tree_model,
gint index)
{
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), G_TYPE_INVALID);
- g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, G_TYPE_INVALID);
+ GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
- return gtk_tree_model_get_column_type (GTK_TREE_MODEL_SORT (tree_model)->child_model, index);
+ g_return_val_if_fail (tree_model_sort->child_model != NULL, G_TYPE_INVALID);
+
+ return gtk_tree_model_get_column_type (tree_model_sort->child_model, index);
}
static gboolean
GtkTreeIter *iter,
GtkTreePath *path)
{
- GtkTreeModelSort *tree_model_sort;
+ GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
gint *indices;
SortLevel *level;
gint depth, i;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
- g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
+ g_return_val_if_fail (tree_model_sort->child_model != NULL, FALSE);
- tree_model_sort = (GtkTreeModelSort *) tree_model;
indices = gtk_tree_path_get_indices (path);
if (tree_model_sort->root == NULL)
gtk_tree_model_sort_get_path (GtkTreeModel *tree_model,
GtkTreeIter *iter)
{
+ GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
GtkTreePath *retval;
SortLevel *level;
SortElt *elt;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), NULL);
- g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, NULL);
- g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, NULL);
+ g_return_val_if_fail (tree_model_sort->child_model != NULL, NULL);
+ g_return_val_if_fail (tree_model_sort->stamp == iter->stamp, NULL);
retval = gtk_tree_path_new ();
level = iter->user_data;
gint column,
GValue *value)
{
+ GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
GtkTreeIter child_iter;
- g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model));
- g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL);
- g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp);
+ g_return_if_fail (tree_model_sort->child_model != NULL);
+ g_return_if_fail (VALID_ITER (iter, tree_model_sort));
- GET_CHILD_ITER (tree_model, &child_iter, iter);
- gtk_tree_model_get_value (GTK_TREE_MODEL_SORT (tree_model)->child_model,
+ GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
+ gtk_tree_model_get_value (tree_model_sort->child_model,
&child_iter, column, value);
}
gtk_tree_model_sort_iter_next (GtkTreeModel *tree_model,
GtkTreeIter *iter)
{
+ GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
SortLevel *level;
SortElt *elt;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
- g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
- g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, FALSE);
+ g_return_val_if_fail (tree_model_sort->child_model != NULL, FALSE);
+ g_return_val_if_fail (tree_model_sort->stamp == iter->stamp, FALSE);
level = iter->user_data;
elt = iter->user_data2;
SortLevel *level;
iter->stamp = 0;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
g_return_val_if_fail (tree_model_sort->child_model != NULL, FALSE);
- if (parent) g_return_val_if_fail (tree_model_sort->stamp == parent->stamp, FALSE);
+ if (parent)
+ g_return_val_if_fail (VALID_ITER (parent, tree_model_sort), FALSE);
if (parent == NULL)
{
gtk_tree_model_sort_iter_has_child (GtkTreeModel *tree_model,
GtkTreeIter *iter)
{
+ GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
GtkTreeIter child_iter;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
- g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
- g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, FALSE);
+ g_return_val_if_fail (tree_model_sort->child_model != NULL, FALSE);
+ g_return_val_if_fail (VALID_ITER (iter, tree_model_sort), FALSE);
- GET_CHILD_ITER (tree_model, &child_iter, iter);
+ GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
- return gtk_tree_model_iter_has_child (GTK_TREE_MODEL_SORT (tree_model)->child_model, &child_iter);
+ return gtk_tree_model_iter_has_child (tree_model_sort->child_model, &child_iter);
}
static gint
gtk_tree_model_sort_iter_n_children (GtkTreeModel *tree_model,
GtkTreeIter *iter)
{
+ GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
GtkTreeIter child_iter;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), 0);
- g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, 0);
- if (iter) g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, 0);
+ g_return_val_if_fail (tree_model_sort->child_model != NULL, 0);
+ if (iter)
+ g_return_val_if_fail (VALID_ITER (iter, tree_model_sort), 0);
if (iter == NULL)
- return gtk_tree_model_iter_n_children (GTK_TREE_MODEL_SORT (tree_model)->child_model, NULL);
+ return gtk_tree_model_iter_n_children (tree_model_sort->child_model, NULL);
- GET_CHILD_ITER (tree_model, &child_iter, iter);
+ GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
- return gtk_tree_model_iter_n_children (GTK_TREE_MODEL_SORT (tree_model)->child_model, &child_iter);
+ return gtk_tree_model_iter_n_children (tree_model_sort->child_model, &child_iter);
}
static gboolean
GtkTreeIter *parent,
gint n)
{
+ GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
SortLevel *level;
/* We have this for the iter == parent case */
GtkTreeIter children;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
- if (parent) g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == parent->stamp, FALSE);
+ if (parent)
+ g_return_val_if_fail (VALID_ITER (parent, tree_model_sort), FALSE);
/* Use this instead of has_child to force us to build the level, if needed */
if (gtk_tree_model_sort_iter_children (tree_model, &children, parent) == FALSE)
return FALSE;
}
- iter->stamp = GTK_TREE_MODEL_SORT (tree_model)->stamp;
+ iter->stamp = tree_model_sort->stamp;
iter->user_data = level;
iter->user_data2 = &g_array_index (level->array, SortElt, n);
gtk_tree_model_sort_iter_parent (GtkTreeModel *tree_model,
GtkTreeIter *iter,
GtkTreeIter *child)
-{
+{
+ GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
SortLevel *level;
iter->stamp = 0;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
- g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
- g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == child->stamp, FALSE);
+ g_return_val_if_fail (tree_model_sort->child_model != NULL, FALSE);
+ g_return_val_if_fail (VALID_ITER (child, tree_model_sort), FALSE);
level = child->user_data;
if (level->parent_level)
{
- iter->stamp = GTK_TREE_MODEL_SORT (tree_model)->stamp;
+ iter->stamp = tree_model_sort->stamp;
iter->user_data = level->parent_level;
iter->user_data2 = level->parent_elt;
{
GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
GtkTreeIter child_iter;
+ GtkTreeIter tmp_iter;
SortLevel *level;
SortElt *elt;
- g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model));
- g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL);
- g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp);
+ g_return_if_fail (tree_model_sort->child_model != NULL);
+ g_return_if_fail (VALID_ITER (iter, tree_model_sort));
- GET_CHILD_ITER (tree_model, &child_iter, iter);
+ GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
- gtk_tree_model_ref_node (GTK_TREE_MODEL_SORT (tree_model)->child_model, &child_iter);
+ /* Reference the node in the child model */
+ gtk_tree_model_ref_node (tree_model_sort->child_model, &child_iter);
+ /* Increase the reference count of this element and its level */
level = iter->user_data;
elt = iter->user_data2;
elt->ref_count++;
level->ref_count++;
+
+ /* Increase the reference count of all parent elements */
+ tmp_iter.stamp = tree_model_sort->stamp;
+ tmp_iter.user_data = level->parent_level;
+ tmp_iter.user_data2 = level->parent_elt;;
+
+ while (tmp_iter.user_data2)
+ {
+ gtk_tree_model_sort_ref_node (tree_model, &tmp_iter);
+
+ tmp_iter.user_data2 = SORT_LEVEL (tmp_iter.user_data)->parent_elt;
+ tmp_iter.user_data = SORT_LEVEL (tmp_iter.user_data)->parent_level;
+ }
+
if (level->ref_count == 1)
{
SortLevel *parent_level = level->parent_level;
SortElt *parent_elt = level->parent_elt;
/* We were at zero -- time to decrement the zero_ref_count val */
- do
+ while (parent_level)
{
- if (parent_elt)
- parent_elt->zero_ref_count--;
- else
- tree_model_sort->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 (tree_model_sort->root != level)
+ tree_model_sort->zero_ref_count--;
}
}
gboolean propagate_unref)
{
GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
- GtkTreeIter child_iter;
+ GtkTreeIter tmp_iter;
SortLevel *level;
SortElt *elt;
- g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model));
- g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL);
- g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp);
-
- GET_CHILD_ITER (tree_model, &child_iter, iter);
+ g_return_if_fail (tree_model_sort->child_model != NULL);
+ g_return_if_fail (VALID_ITER (iter, tree_model_sort));
if (propagate_unref)
- gtk_tree_model_unref_node (GTK_TREE_MODEL_SORT (tree_model)->child_model, &child_iter);
+ {
+ GtkTreeIter child_iter;
+
+ GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
+ gtk_tree_model_unref_node (tree_model_sort->child_model, &child_iter);
+ }
level = iter->user_data;
elt = iter->user_data2;
elt->ref_count--;
level->ref_count--;
+ /* Decrease the reference count of all parent elements */
+ tmp_iter.stamp = tree_model_sort->stamp;
+ tmp_iter.user_data = level->parent_level;
+ tmp_iter.user_data2 = level->parent_elt;;
+
+ while (tmp_iter.user_data2)
+ {
+ gtk_tree_model_sort_real_unref_node (tree_model, &tmp_iter, FALSE);
+
+ tmp_iter.user_data2 = SORT_LEVEL (tmp_iter.user_data)->parent_elt;
+ tmp_iter.user_data = SORT_LEVEL (tmp_iter.user_data)->parent_level;
+ }
+
if (level->ref_count == 0)
{
SortLevel *parent_level = level->parent_level;
parent_elt = parent_level->parent_elt;
parent_level = parent_level->parent_level;
}
- tree_model_sort->zero_ref_count++;
+
+ if (tree_model_sort->root != level)
+ tree_model_sort->zero_ref_count++;
}
}
{
GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (sortable), FALSE);
-
if (sort_column_id)
*sort_column_id = tree_model_sort->sort_column_id;
if (order)
{
GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
- g_return_if_fail (GTK_IS_TREE_MODEL_SORT (sortable));
-
- if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
+ if (sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
{
- GtkTreeDataSortHeader *header = NULL;
+ if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
+ {
+ GtkTreeDataSortHeader *header = NULL;
- header = _gtk_tree_data_list_get_header (tree_model_sort->sort_list,
- sort_column_id);
+ header = _gtk_tree_data_list_get_header (tree_model_sort->sort_list,
+ sort_column_id);
- /* we want to make sure that we have a function */
- g_return_if_fail (header != NULL);
- g_return_if_fail (header->func != NULL);
- }
- else
- g_return_if_fail (tree_model_sort->default_sort_func != NULL);
+ /* we want to make sure that we have a function */
+ g_return_if_fail (header != NULL);
+ g_return_if_fail (header->func != NULL);
+ }
+ else
+ g_return_if_fail (tree_model_sort->default_sort_func != NULL);
- if (tree_model_sort->sort_column_id == sort_column_id)
- {
- if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
- {
- if (tree_model_sort->order == order)
+ if (tree_model_sort->sort_column_id == sort_column_id)
+ {
+ if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
+ {
+ if (tree_model_sort->order == order)
+ return;
+ }
+ else
return;
- }
- else
- return;
+ }
}
tree_model_sort->sort_column_id = sort_column_id;
gint sort_column_id,
GtkTreeIterCompareFunc func,
gpointer data,
- GtkDestroyNotify destroy)
+ GDestroyNotify destroy)
{
GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) sortable;
- GtkTreeDataSortHeader *header = NULL;
- GList *list;
-
- g_return_if_fail (GTK_IS_TREE_MODEL_SORT (sortable));
- g_return_if_fail (func != NULL);
-
- for (list = tree_model_sort->sort_list; list; list = list->next)
- {
- GtkTreeDataSortHeader *list_header;
-
- list_header = (GtkTreeDataSortHeader*) list->data;
- if (list_header->sort_column_id == sort_column_id)
- {
- header = list_header;
- break;
- }
- }
-
- if (header == NULL)
- {
- header = g_new0 (GtkTreeDataSortHeader, 1);
- header->sort_column_id = sort_column_id;
- tree_model_sort->sort_list = g_list_append (tree_model_sort->sort_list,
- header);
- }
-
- if (header->destroy)
- {
- GtkDestroyNotify d = header->destroy;
-
- header->destroy = NULL;
- d (header->data);
- }
- header->func = func;
- header->data = data;
- header->destroy = destroy;
+ tree_model_sort->sort_list = _gtk_tree_data_list_set_header (tree_model_sort->sort_list,
+ sort_column_id,
+ func, data, destroy);
if (tree_model_sort->sort_column_id == sort_column_id)
gtk_tree_model_sort_sort (tree_model_sort);
gtk_tree_model_sort_set_default_sort_func (GtkTreeSortable *sortable,
GtkTreeIterCompareFunc func,
gpointer data,
- GtkDestroyNotify destroy)
+ GDestroyNotify destroy)
{
GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
- g_return_if_fail (GTK_IS_TREE_MODEL_SORT (sortable));
-
if (tree_model_sort->default_sort_destroy)
{
- GtkDestroyNotify d = tree_model_sort->default_sort_destroy;
+ GDestroyNotify d = tree_model_sort->default_sort_destroy;
tree_model_sort->default_sort_destroy = NULL;
d (tree_model_sort->default_sort_data);
{
GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (sortable), FALSE);
-
return (tree_model_sort->default_sort_func != NULL);
}
GtkTreePath *child_path;
gboolean draggable;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (drag_source), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
-
child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort,
path);
draggable = gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (tree_model_sort->child_model), child_path);
GtkTreePath *child_path;
gboolean gotten;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (drag_source), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
-
- child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort,
- path);
+ child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort, path);
gotten = gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (tree_model_sort->child_model), child_path, selection_data);
gtk_tree_path_free (child_path);
GtkTreePath *child_path;
gboolean deleted;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (drag_source), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
-
- child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort,
- path);
+ child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort, path);
deleted = gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (tree_model_sort->child_model), child_path);
gtk_tree_path_free (child_path);
gboolean emit_reordered)
{
gint i;
+ gint ref_offset;
GArray *sort_array;
GArray *new_array;
gint *new_order;
SortData data;
- g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
g_return_if_fail (level != NULL);
if (level->array->len < 1 && !((SortElt *)level->array->data)->children)
return;
+ iter.stamp = tree_model_sort->stamp;
+ iter.user_data = level;
+ iter.user_data2 = &g_array_index (level->array, SortElt, 0);
+
+ gtk_tree_model_sort_ref_node (GTK_TREE_MODEL (tree_model_sort), &iter);
+ ref_offset = g_array_index (level->array, SortElt, 0).offset;
+
/* Set up data */
data.tree_model_sort = tree_model_sort;
if (level->parent_elt)
}
g_free (new_order);
+
+ /* get the iter we referenced at the beginning of this function and
+ * unref it again
+ */
+ iter.stamp = tree_model_sort->stamp;
+ iter.user_data = level;
+
+ for (i = 0; i < level->array->len; i++)
+ {
+ if (g_array_index (level->array, SortElt, i).offset == ref_offset)
+ {
+ iter.user_data2 = &g_array_index (level->array, SortElt, i);
+ break;
+ }
+ }
+
+ gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (tree_model_sort), &iter);
}
static void
gtk_tree_model_sort_sort (GtkTreeModelSort *tree_model_sort)
{
- g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
+ if (tree_model_sort->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
+ return;
if (!tree_model_sort->root)
return;
/**
* gtk_tree_model_sort_set_model:
* @tree_model_sort: The #GtkTreeModelSort.
- * @child_model: A #GtkTreeModel, or NULL.
+ * @child_model: A #GtkTreeModel, or %NULL.
*
- * Sets the model of @tree_model_sort to be @model. If @model is NULL, then the
- * old model is unset. The sort function is unset as a result of this call.
- * The model will be in an unsorted state until a sort function is set.
+ * Sets the model of @tree_model_sort to be @model. If @model is %NULL,
+ * then the old model is unset. The sort function is unset as a result
+ * of this call. The model will be in an unsorted state until a sort
+ * function is set.
**/
static void
gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
GtkTreeModel *child_model)
{
- g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
-
if (child_model)
g_object_ref (child_model);
gint i, n_columns;
tree_model_sort->changed_id =
- g_signal_connect (child_model, "row_changed",
+ g_signal_connect (child_model, "row-changed",
G_CALLBACK (gtk_tree_model_sort_row_changed),
tree_model_sort);
tree_model_sort->inserted_id =
- g_signal_connect (child_model, "row_inserted",
+ g_signal_connect (child_model, "row-inserted",
G_CALLBACK (gtk_tree_model_sort_row_inserted),
tree_model_sort);
tree_model_sort->has_child_toggled_id =
- g_signal_connect (child_model, "row_has_child_toggled",
+ g_signal_connect (child_model, "row-has-child-toggled",
G_CALLBACK (gtk_tree_model_sort_row_has_child_toggled),
tree_model_sort);
tree_model_sort->deleted_id =
- g_signal_connect (child_model, "row_deleted",
+ g_signal_connect (child_model, "row-deleted",
G_CALLBACK (gtk_tree_model_sort_row_deleted),
tree_model_sort);
tree_model_sort->reordered_id =
- g_signal_connect (child_model, "rows_reordered",
+ g_signal_connect (child_model, "rows-reordered",
G_CALLBACK (gtk_tree_model_sort_rows_reordered),
tree_model_sort);
* Return value: the "child model" being sorted
**/
GtkTreeModel *
-gtk_tree_model_sort_get_model (GtkTreeModelSort *tree_model)
+gtk_tree_model_sort_get_model (GtkTreeModelSort *tree_model)
{
g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), NULL);
SortLevel *level;
gint i;
- g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), NULL);
g_return_val_if_fail (tree_model_sort->child_model != NULL, NULL);
g_return_val_if_fail (child_path != NULL, NULL);
*
* Converts @child_path to a path relative to @tree_model_sort. That is,
* @child_path points to a path in the child model. The returned path will
- * point to the same row in the sorted model. If @child_path isn't a valid path
- * on the child model, then %NULL is returned.
+ * point to the same row in the sorted model. If @child_path isn't a valid
+ * path on the child model, then %NULL is returned.
*
* Return value: A newly allocated #GtkTreePath, or %NULL
**/
* @child_iter: A valid #GtkTreeIter pointing to a row on the child model
*
* Sets @sort_iter to point to the row in @tree_model_sort that corresponds to
- * the row pointed at by @child_iter.
+ * the row pointed at by @child_iter. If @sort_iter was not set, %FALSE
+ * is returned. Note: a boolean is only returned since 2.14.
+ *
+ * Return value: %TRUE, if @sort_iter was set, i.e. if @sort_iter is a
+ * valid iterator pointer to a visible row in the child model.
**/
-void
+gboolean
gtk_tree_model_sort_convert_child_iter_to_iter (GtkTreeModelSort *tree_model_sort,
GtkTreeIter *sort_iter,
GtkTreeIter *child_iter)
{
+ gboolean ret;
GtkTreePath *child_path, *path;
- g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
- g_return_if_fail (tree_model_sort->child_model != NULL);
- g_return_if_fail (sort_iter != NULL);
- g_return_if_fail (child_iter != NULL);
+ g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), FALSE);
+ g_return_val_if_fail (tree_model_sort->child_model != NULL, FALSE);
+ g_return_val_if_fail (sort_iter != NULL, FALSE);
+ g_return_val_if_fail (child_iter != NULL, FALSE);
+ g_return_val_if_fail (sort_iter != child_iter, FALSE);
sort_iter->stamp = 0;
child_path = gtk_tree_model_get_path (tree_model_sort->child_model, child_iter);
- g_return_if_fail (child_path != NULL);
+ g_return_val_if_fail (child_path != NULL, FALSE);
path = gtk_tree_model_sort_convert_child_path_to_path (tree_model_sort, child_path);
gtk_tree_path_free (child_path);
- g_return_if_fail (path != NULL);
- gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_sort), sort_iter, path);
+ if (!path)
+ {
+ g_warning ("%s: The conversion of the child path to a GtkTreeModel sort path failed", G_STRLOC);
+ return FALSE;
+ }
+
+ ret = gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_sort),
+ sort_iter, path);
gtk_tree_path_free (path);
+
+ return ret;
}
/**
* @tree_model_sort: A #GtkTreeModelSort
* @sorted_path: A #GtkTreePath to convert
*
- * Converts @sorted_path to a path on the child model of @tree_model_sort. That
- * is, @sorted_path points to a location in @tree_model_sort. The returned path
- * will point to the same location in the model not being sorted. If @sorted_path
- * does not point to a location in the child model, %NULL is returned.
+ * Converts @sorted_path to a path on the child model of @tree_model_sort.
+ * That is, @sorted_path points to a location in @tree_model_sort. The
+ * returned path will point to the same location in the model not being
+ * sorted. If @sorted_path does not point to a location in the child model,
+ * %NULL is returned.
*
* Return value: A newly allocated #GtkTreePath, or %NULL
**/
g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
g_return_if_fail (tree_model_sort->child_model != NULL);
g_return_if_fail (child_iter != NULL);
- g_return_if_fail (sorted_iter != NULL);
- g_return_if_fail (sorted_iter->stamp == tree_model_sort->stamp);
+ g_return_if_fail (VALID_ITER (sorted_iter, tree_model_sort));
+ g_return_if_fail (sorted_iter != child_iter);
if (GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
{
if (gtk_tree_model_iter_next (tree_model_sort->child_model, &iter) == FALSE &&
i < length - 1)
{
- g_warning ("There is a discrepency between the sort model and the child model.");
+ if (parent_level)
+ {
+ GtkTreePath *level;
+ gchar *str;
+
+ level = gtk_tree_model_sort_elt_get_path (parent_level,
+ parent_elt);
+ str = gtk_tree_path_to_string (level);
+ gtk_tree_path_free (level);
+
+ g_warning ("%s: There is a discrepancy between the sort model "
+ "and the child model. The child model is "
+ "advertising a wrong length for level %s:.",
+ G_STRLOC, str);
+ g_free (str);
+ }
+ else
+ {
+ g_warning ("%s: There is a discrepancy between the sort model "
+ "and the child model. The child model is "
+ "advertising a wrong length for the root level.",
+ G_STRLOC);
+ }
+
return;
}
}
g_assert (sort_level);
+ for (i = 0; i < sort_level->array->len; i++)
+ {
+ 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));
+ }
+
if (sort_level->ref_count == 0)
{
SortLevel *parent_level = sort_level->parent_level;
SortElt *parent_elt = sort_level->parent_elt;
- do
+ while (parent_level)
{
- if (parent_elt)
- parent_elt->zero_ref_count--;
- else
- tree_model_sort->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);
- }
- for (i = 0; i < sort_level->array->len; i++)
- {
- 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));
+ if (sort_level != tree_model_sort->root)
+ tree_model_sort->zero_ref_count--;
}
if (sort_level->parent_elt)
if (tree_model_sort->default_sort_destroy)
{
- GtkDestroyNotify d = tree_model_sort->default_sort_destroy;
+ GDestroyNotify d = tree_model_sort->default_sort_destroy;
tree_model_sort->default_sort_destroy = NULL;
d (tree_model_sort->default_sort_data);
{
g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
- if (tree_model_sort->zero_ref_count)
+ if (tree_model_sort->zero_ref_count > 0)
gtk_tree_model_sort_clear_cache_helper (tree_model_sort, (SortLevel *)tree_model_sort->root);
}
* @tree_model_sort: A #GtkTreeModelSort.
* @iter: A #GtkTreeIter.
*
- * WARNING: This function is slow. Only use it for debugging and/or testing
- * purposes.
+ * <warning><para>
+ * This function is slow. Only use it for debugging and/or testing purposes.
+ * </para></warning>
*
* Checks if the given iter is a valid iter for this #GtkTreeModelSort.
*