2 * Copyright (C) 2000,2001 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
3 * Copyright (C) 2001,2002 Kristian Rietveld <kris@gtk.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
24 #include "gtktreemodelsort.h"
25 #include "gtktreesortable.h"
26 #include "gtktreestore.h"
27 #include "gtktreedatalist.h"
29 #include "gtkprivate.h"
30 #include "gtktreednd.h"
34 * SECTION:gtktreemodelsort
35 * @Short_description: A GtkTreeModel which makes an underlying tree model sortable
36 * @Title: GtkTreeModelSort
37 * @See_also: #GtkTreeModel, #GtkListStore, #GtkTreeStore, #GtkTreeSortable, #GtkTreeModelFilter
39 * The #GtkTreeModelSort is a model which implements the #GtkTreeSortable
40 * interface. It does not hold any data itself, but rather is created with
41 * a child model and proxies its data. It has identical column types to
42 * this child model, and the changes in the child are propagated. The
43 * primary purpose of this model is to provide a way to sort a different
44 * model without modifying it. Note that the sort function used by
45 * #GtkTreeModelSort is not guaranteed to be stable.
47 * The use of this is best demonstrated through an example. In the
48 * following sample code we create two #GtkTreeView widgets each with a
49 * view of the same data. As the model is wrapped here by a
50 * #GtkTreeModelSort, the two #GtkTreeView<!-- -->s can each sort their
51 * view of the data without affecting the other. By contrast, if we
52 * simply put the same model in each widget, then sorting the first would
56 * <title>Using a <structname>GtkTreeModelSort</structname></title>
59 * GtkTreeView *tree_view1;
60 * GtkTreeView *tree_view2;
61 * GtkTreeModel *sort_model1;
62 * GtkTreeModel *sort_model2;
63 * GtkTreeModel *child_model;
65 * // get the child model
66 * child_model = get_my_model ();
68 * // Create the first tree
69 * sort_model1 = gtk_tree_model_sort_new_with_model (child_model);
70 * tree_view1 = gtk_tree_view_new_with_model (sort_model1);
72 * // Create the second tree
73 * sort_model2 = gtk_tree_model_sort_new_with_model (child_model);
74 * tree_view2 = gtk_tree_view_new_with_model (sort_model2);
76 * // Now we can sort the two models independently
77 * gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model1),
78 * COLUMN_1, GTK_SORT_ASCENDING);
79 * gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model2),
80 * COLUMN_1, GTK_SORT_DESCENDING);
85 * To demonstrate how to access the underlying child model from the sort
86 * model, the next example will be a callback for the #GtkTreeSelection
87 * #GtkTreeSelection::changed signal. In this callback, we get a string
88 * from COLUMN_1 of the model. We then modify the string, find the same
89 * selected row on the child model, and change the row there.
92 * <title>Accessing the child model of in a selection changed callback</title>
95 * selection_changed (GtkTreeSelection *selection, gpointer data)
97 * GtkTreeModel *sort_model = NULL;
98 * GtkTreeModel *child_model;
99 * GtkTreeIter sort_iter;
100 * GtkTreeIter child_iter;
101 * char *some_data = NULL;
102 * char *modified_data;
104 * // Get the current selected row and the model.
105 * if (! gtk_tree_selection_get_selected (selection,
110 * /<!---->* Look up the current value on the selected row and get a new value
113 * gtk_tree_model_get (GTK_TREE_MODEL (sort_model), &sort_iter,
114 * COLUMN_1, &some_data,
117 * modified_data = change_the_data (some_data);
118 * g_free (some_data);
120 * // Get an iterator on the child model, instead of the sort model.
121 * gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (sort_model),
125 * /<!---->* Get the child model and change the value of the row. In this
126 * * example, the child model is a GtkListStore. It could be any other
127 * * type of model, though.
129 * child_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (sort_model));
130 * gtk_list_store_set (GTK_LIST_STORE (child_model), &child_iter,
131 * COLUMN_1, &modified_data,
133 * g_free (modified_data);
140 /* Notes on this implementation of GtkTreeModelSort
141 * ================================================
146 * In this code there is a potential for confusion as to whether an iter,
147 * path or value refers to the GtkTreeModelSort model, or to the child model
148 * that has been set. As a convention, variables referencing the child model
149 * will have an s_ prefix before them (ie. s_iter, s_value, s_path);
150 * Conversion of iterators and paths between GtkTreeModelSort and the child
151 * model is done through the various gtk_tree_model_sort_convert_* functions.
156 * The iterator format of iterators handed out by GtkTreeModelSort is as
159 * iter->stamp = tree_model_sort->stamp
160 * iter->user_data = SortLevel
161 * iter->user_data2 = SortElt
163 * Internal data structure
164 * -----------------------
166 * Using SortLevel and SortElt, GtkTreeModelSort maintains a "cache" of
167 * the mapping from GtkTreeModelSort nodes to nodes in the child model.
168 * This is to avoid sorting a level each time an operation is requested
169 * on GtkTreeModelSort, such as get iter, get path, get value.
171 * A SortElt corresponds to a single node. A node and its siblings are
172 * stored in a SortLevel. The SortLevel keeps a reference to the parent
173 * SortElt and its SortLevel (if any). The SortElt can have a "children"
174 * pointer set, which points at a child level (a sub level).
176 * In a SortLevel, nodes are stored in a GSequence. The GSequence
177 * allows for fast additions and removals, and supports sorting
178 * the level of SortElt nodes.
180 * It is important to recognize the two different mappings that play
181 * a part in this code:
182 * I. The mapping from the client to this model. The order in which
183 * nodes are stored in the GSequence is the order in which the
184 * nodes are exposed to clients of the GtkTreeModelSort.
185 * II. The mapping from this model to its child model. Each SortElt
186 * contains an "offset" field which is the offset of the
187 * corresponding node in the child model.
192 * GtkTreeModelSort forwards all reference and unreference operations
193 * to the corresponding node in the child model. The reference count
194 * of each node is also maintained internally, in the "ref_count"
195 * fields in SortElt and SortLevel. For each ref and unref operation on
196 * a SortElt, the "ref_count" of the SortLevel is updated accordingly.
197 * In addition, if a SortLevel has a parent, a reference is taken on
198 * this parent. This happens in gtk_tree_model_sort_build_level() and
199 * the reference is released again in gtk_tree_model_sort_free_level().
200 * This ensures that when GtkTreeModelSort takes a reference on a node
201 * (for example during sorting), all parent nodes are referenced
202 * according to reference counting rule 1, see the GtkTreeModel
205 * When a level has a reference count of zero, which means that
206 * none of the nodes in the level is referenced, the level has
207 * a "zero ref count" on all its parents. As soon as the level
208 * reaches a reference count of zero, the zero ref count value is
209 * incremented by one on all parents of this level. Similarly, as
210 * soon as the reference count of a level changes from zero, the
211 * zero ref count value is decremented by one on all parents.
213 * The zero ref count value is used to clear unused portions of
214 * the cache. If a SortElt has a zero ref count of one, then
215 * its child level is unused and can be removed from the cache.
216 * If the zero ref count value is higher than one, then the
217 * child level contains sublevels which are unused as well.
218 * gtk_tree_model_sort_clear_cache() uses this to not recurse
219 * into levels which have a zero ref count of zero.
222 typedef struct _SortElt SortElt;
223 typedef struct _SortLevel SortLevel;
224 typedef struct _SortData SortData;
233 GSequenceIter *siter; /* iter into seq */
234 gint old_index; /* used while sorting */
242 SortLevel *parent_level;
247 GtkTreeModelSort *tree_model_sort;
248 GtkTreeIterCompareFunc sort_func;
251 GtkTreePath *parent_path;
252 gint parent_path_depth;
253 gint *parent_path_indices;
264 struct _GtkTreeModelSortPrivate
269 GtkTreeModel *child_model;
272 /* sort information */
278 GtkTreeIterCompareFunc default_sort_func;
279 gpointer default_sort_data;
280 GDestroyNotify default_sort_destroy;
285 gulong has_child_toggled_id;
290 /* Set this to 0 to disable caching of child iterators. This
291 * allows for more stringent testing. It is recommended to set this
292 * to one when refactoring this code and running the unit tests to
296 # define GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS(tree_model_sort) \
297 (((GtkTreeModelSort *)tree_model_sort)->priv->child_flags>K_TREE_MODEL_ITERS_PERSIST)
299 # define GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS(tree_model_sort) (FALSE)
302 #define SORT_ELT(sort_elt) ((SortElt *)sort_elt)
303 #define SORT_LEVEL(sort_level) ((SortLevel *)sort_level)
304 #define GET_ELT(siter) ((SortElt *) (siter ? g_sequence_get (siter) : NULL))
307 #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));
309 #define NO_SORT_FUNC ((GtkTreeIterCompareFunc) 0x1)
311 #define VALID_ITER(iter, tree_model_sort) ((iter) != NULL && (iter)->user_data != NULL && (iter)->user_data2 != NULL && (tree_model_sort)->priv->stamp == (iter)->stamp)
313 /* general (object/interface init, etc) */
314 static void gtk_tree_model_sort_tree_model_init (GtkTreeModelIface *iface);
315 static void gtk_tree_model_sort_tree_sortable_init (GtkTreeSortableIface *iface);
316 static void gtk_tree_model_sort_drag_source_init (GtkTreeDragSourceIface*iface);
317 static void gtk_tree_model_sort_finalize (GObject *object);
318 static void gtk_tree_model_sort_set_property (GObject *object,
322 static void gtk_tree_model_sort_get_property (GObject *object,
327 /* our signal handlers */
328 static void gtk_tree_model_sort_row_changed (GtkTreeModel *model,
329 GtkTreePath *start_path,
330 GtkTreeIter *start_iter,
332 static void gtk_tree_model_sort_row_inserted (GtkTreeModel *model,
336 static void gtk_tree_model_sort_row_has_child_toggled (GtkTreeModel *model,
340 static void gtk_tree_model_sort_row_deleted (GtkTreeModel *model,
343 static void gtk_tree_model_sort_rows_reordered (GtkTreeModel *s_model,
349 /* TreeModel interface */
350 static GtkTreeModelFlags gtk_tree_model_sort_get_flags (GtkTreeModel *tree_model);
351 static gint gtk_tree_model_sort_get_n_columns (GtkTreeModel *tree_model);
352 static GType gtk_tree_model_sort_get_column_type (GtkTreeModel *tree_model,
354 static gboolean gtk_tree_model_sort_get_iter (GtkTreeModel *tree_model,
357 static GtkTreePath *gtk_tree_model_sort_get_path (GtkTreeModel *tree_model,
359 static void gtk_tree_model_sort_get_value (GtkTreeModel *tree_model,
363 static gboolean gtk_tree_model_sort_iter_next (GtkTreeModel *tree_model,
365 static gboolean gtk_tree_model_sort_iter_previous (GtkTreeModel *tree_model,
367 static gboolean gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
369 GtkTreeIter *parent);
370 static gboolean gtk_tree_model_sort_iter_has_child (GtkTreeModel *tree_model,
372 static gint gtk_tree_model_sort_iter_n_children (GtkTreeModel *tree_model,
374 static gboolean gtk_tree_model_sort_iter_nth_child (GtkTreeModel *tree_model,
378 static gboolean gtk_tree_model_sort_iter_parent (GtkTreeModel *tree_model,
381 static void gtk_tree_model_sort_ref_node (GtkTreeModel *tree_model,
383 static void gtk_tree_model_sort_real_unref_node (GtkTreeModel *tree_model,
385 gboolean propagate_unref);
386 static void gtk_tree_model_sort_unref_node (GtkTreeModel *tree_model,
389 /* TreeDragSource interface */
390 static gboolean gtk_tree_model_sort_row_draggable (GtkTreeDragSource *drag_source,
392 static gboolean gtk_tree_model_sort_drag_data_get (GtkTreeDragSource *drag_source,
394 GtkSelectionData *selection_data);
395 static gboolean gtk_tree_model_sort_drag_data_delete (GtkTreeDragSource *drag_source,
398 /* TreeSortable interface */
399 static gboolean gtk_tree_model_sort_get_sort_column_id (GtkTreeSortable *sortable,
400 gint *sort_column_id,
402 static void gtk_tree_model_sort_set_sort_column_id (GtkTreeSortable *sortable,
405 static void gtk_tree_model_sort_set_sort_func (GtkTreeSortable *sortable,
407 GtkTreeIterCompareFunc func,
409 GDestroyNotify destroy);
410 static void gtk_tree_model_sort_set_default_sort_func (GtkTreeSortable *sortable,
411 GtkTreeIterCompareFunc func,
413 GDestroyNotify destroy);
414 static gboolean gtk_tree_model_sort_has_default_sort_func (GtkTreeSortable *sortable);
416 /* Private functions (sort funcs, level handling and other utils) */
417 static void gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
418 SortLevel *parent_level,
419 SortElt *parent_elt);
420 static void gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
421 SortLevel *sort_level,
423 static void gtk_tree_model_sort_increment_stamp (GtkTreeModelSort *tree_model_sort);
424 static void gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
427 gboolean emit_reordered);
428 static void gtk_tree_model_sort_sort (GtkTreeModelSort *tree_model_sort);
429 static gboolean gtk_tree_model_sort_insert_value (GtkTreeModelSort *tree_model_sort,
432 GtkTreeIter *s_iter);
433 static GtkTreePath *gtk_tree_model_sort_elt_get_path (SortLevel *level,
435 static void gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
436 GtkTreeModel *child_model);
437 static GtkTreePath *gtk_real_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_model_sort,
438 GtkTreePath *child_path,
439 gboolean build_levels);
441 static gint gtk_tree_model_sort_compare_func (gconstpointer a,
444 static gint gtk_tree_model_sort_offset_compare_func (gconstpointer a,
447 static void gtk_tree_model_sort_clear_cache_helper (GtkTreeModelSort *tree_model_sort,
451 G_DEFINE_TYPE_WITH_CODE (GtkTreeModelSort, gtk_tree_model_sort, G_TYPE_OBJECT,
452 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
453 gtk_tree_model_sort_tree_model_init)
454 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
455 gtk_tree_model_sort_tree_sortable_init)
456 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
457 gtk_tree_model_sort_drag_source_init))
460 gtk_tree_model_sort_init (GtkTreeModelSort *tree_model_sort)
462 GtkTreeModelSortPrivate *priv;
464 priv = G_TYPE_INSTANCE_GET_PRIVATE (tree_model_sort,
465 GTK_TYPE_TREE_MODEL_SORT,
466 GtkTreeModelSortPrivate);
467 tree_model_sort->priv = priv;
468 priv->sort_column_id = GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID;
470 priv->zero_ref_count = 0;
472 priv->sort_list = NULL;
476 gtk_tree_model_sort_class_init (GtkTreeModelSortClass *class)
478 GObjectClass *object_class;
480 object_class = (GObjectClass *) class;
482 object_class->set_property = gtk_tree_model_sort_set_property;
483 object_class->get_property = gtk_tree_model_sort_get_property;
485 object_class->finalize = gtk_tree_model_sort_finalize;
488 g_object_class_install_property (object_class,
490 g_param_spec_object ("model",
491 P_("TreeModelSort Model"),
492 P_("The model for the TreeModelSort to sort"),
494 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
496 g_type_class_add_private (class, sizeof (GtkTreeModelSortPrivate));
500 gtk_tree_model_sort_tree_model_init (GtkTreeModelIface *iface)
502 iface->get_flags = gtk_tree_model_sort_get_flags;
503 iface->get_n_columns = gtk_tree_model_sort_get_n_columns;
504 iface->get_column_type = gtk_tree_model_sort_get_column_type;
505 iface->get_iter = gtk_tree_model_sort_get_iter;
506 iface->get_path = gtk_tree_model_sort_get_path;
507 iface->get_value = gtk_tree_model_sort_get_value;
508 iface->iter_next = gtk_tree_model_sort_iter_next;
509 iface->iter_previous = gtk_tree_model_sort_iter_previous;
510 iface->iter_children = gtk_tree_model_sort_iter_children;
511 iface->iter_has_child = gtk_tree_model_sort_iter_has_child;
512 iface->iter_n_children = gtk_tree_model_sort_iter_n_children;
513 iface->iter_nth_child = gtk_tree_model_sort_iter_nth_child;
514 iface->iter_parent = gtk_tree_model_sort_iter_parent;
515 iface->ref_node = gtk_tree_model_sort_ref_node;
516 iface->unref_node = gtk_tree_model_sort_unref_node;
520 gtk_tree_model_sort_tree_sortable_init (GtkTreeSortableIface *iface)
522 iface->get_sort_column_id = gtk_tree_model_sort_get_sort_column_id;
523 iface->set_sort_column_id = gtk_tree_model_sort_set_sort_column_id;
524 iface->set_sort_func = gtk_tree_model_sort_set_sort_func;
525 iface->set_default_sort_func = gtk_tree_model_sort_set_default_sort_func;
526 iface->has_default_sort_func = gtk_tree_model_sort_has_default_sort_func;
530 gtk_tree_model_sort_drag_source_init (GtkTreeDragSourceIface *iface)
532 iface->row_draggable = gtk_tree_model_sort_row_draggable;
533 iface->drag_data_delete = gtk_tree_model_sort_drag_data_delete;
534 iface->drag_data_get = gtk_tree_model_sort_drag_data_get;
538 * gtk_tree_model_sort_new_with_model:
539 * @child_model: A #GtkTreeModel
541 * Creates a new #GtkTreeModel, with @child_model as the child model.
543 * Return value: (transfer full): A new #GtkTreeModel.
546 gtk_tree_model_sort_new_with_model (GtkTreeModel *child_model)
548 GtkTreeModel *retval;
550 g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
552 retval = g_object_new (gtk_tree_model_sort_get_type (), NULL);
554 gtk_tree_model_sort_set_model (GTK_TREE_MODEL_SORT (retval), child_model);
559 /* GObject callbacks */
561 gtk_tree_model_sort_finalize (GObject *object)
563 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) object;
564 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
566 gtk_tree_model_sort_set_model (tree_model_sort, NULL);
569 gtk_tree_model_sort_free_level (tree_model_sort, priv->root, TRUE);
573 _gtk_tree_data_list_header_free (priv->sort_list);
574 priv->sort_list = NULL;
577 if (priv->default_sort_destroy)
579 priv->default_sort_destroy (priv->default_sort_data);
580 priv->default_sort_destroy = NULL;
581 priv->default_sort_data = NULL;
586 G_OBJECT_CLASS (gtk_tree_model_sort_parent_class)->finalize (object);
590 gtk_tree_model_sort_set_property (GObject *object,
595 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (object);
600 gtk_tree_model_sort_set_model (tree_model_sort, g_value_get_object (value));
603 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
609 gtk_tree_model_sort_get_property (GObject *object,
614 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (object);
619 g_value_set_object (value, gtk_tree_model_sort_get_model (tree_model_sort));
622 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
631 return g_slice_new (SortElt);
635 sort_elt_free (gpointer elt)
637 g_slice_free (SortElt, elt);
641 increase_offset_iter (gpointer data,
645 gint offset = GPOINTER_TO_INT (user_data);
647 if (elt->offset >= offset)
652 decrease_offset_iter (gpointer data,
656 gint offset = GPOINTER_TO_INT (user_data);
658 if (elt->offset > offset)
663 fill_sort_data (SortData *data,
664 GtkTreeModelSort *tree_model_sort,
667 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
669 data->tree_model_sort = tree_model_sort;
671 if (priv->sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
673 GtkTreeDataSortHeader *header;
675 header = _gtk_tree_data_list_get_header (priv->sort_list,
676 priv->sort_column_id);
678 g_return_if_fail (header != NULL);
679 g_return_if_fail (header->func != NULL);
681 data->sort_func = header->func;
682 data->sort_data = header->data;
686 /* absolutely SHOULD NOT happen: */
687 g_return_if_fail (priv->default_sort_func != NULL);
689 data->sort_func = priv->default_sort_func;
690 data->sort_data = priv->default_sort_data;
693 if (level->parent_elt)
695 data->parent_path = gtk_tree_model_sort_elt_get_path (level->parent_level,
697 gtk_tree_path_append_index (data->parent_path, 0);
701 data->parent_path = gtk_tree_path_new_first ();
703 data->parent_path_depth = gtk_tree_path_get_depth (data->parent_path);
704 data->parent_path_indices = gtk_tree_path_get_indices (data->parent_path);
708 free_sort_data (SortData *data)
710 gtk_tree_path_free (data->parent_path);
714 lookup_elt_with_offset (GtkTreeModelSort *tree_model_sort,
717 GSequenceIter **ret_siter)
719 GSequenceIter *siter, *end_siter;
721 /* FIXME: We have to do a search like this, because the sequence is not
722 * (always) sorted on offset order. Perhaps we should introduce a
723 * second sequence which is sorted on offset order.
725 end_siter = g_sequence_get_end_iter (level->seq);
726 for (siter = g_sequence_get_begin_iter (level->seq);
728 siter = g_sequence_iter_next (siter))
730 SortElt *elt = g_sequence_get (siter);
732 if (elt->offset == offset)
739 return GET_ELT (siter);
744 gtk_tree_model_sort_row_changed (GtkTreeModel *s_model,
745 GtkTreePath *start_s_path,
746 GtkTreeIter *start_s_iter,
749 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
750 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
751 GtkTreePath *path = NULL;
759 gboolean free_s_path = FALSE;
761 gint index = 0, old_index;
763 g_return_if_fail (start_s_path != NULL || start_s_iter != NULL);
768 start_s_path = gtk_tree_model_get_path (s_model, start_s_iter);
771 path = gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort,
777 gtk_tree_path_free (start_s_path);
781 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
782 gtk_tree_model_sort_ref_node (GTK_TREE_MODEL (data), &iter);
784 level = iter.user_data;
785 elt = iter.user_data2;
787 if (g_sequence_get_length (level->seq) < 2 ||
788 (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID &&
789 priv->default_sort_func == NO_SORT_FUNC))
792 gtk_tree_path_free (start_s_path);
794 gtk_tree_model_row_changed (GTK_TREE_MODEL (data), path, &iter);
795 gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (data), &iter);
797 gtk_tree_path_free (path);
802 if (GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
805 gtk_tree_model_get_iter (priv->child_model,
806 &tmpiter, start_s_path);
808 old_index = g_sequence_iter_get_position (elt->siter);
810 fill_sort_data (&sort_data, tree_model_sort, level);
811 g_sequence_sort_changed (elt->siter,
812 gtk_tree_model_sort_compare_func,
814 free_sort_data (&sort_data);
816 index = g_sequence_iter_get_position (elt->siter);
818 /* Prepare the path for signal emission */
819 gtk_tree_path_up (path);
820 gtk_tree_path_append_index (path, index);
822 gtk_tree_model_sort_increment_stamp (tree_model_sort);
824 /* if the item moved, then emit rows_reordered */
825 if (old_index != index)
830 GtkTreePath *tmppath;
832 new_order = g_new (gint, g_sequence_get_length (level->seq));
834 for (j = 0; j < g_sequence_get_length (level->seq); j++)
836 if (index > old_index)
839 new_order[j] = old_index;
840 else if (j >= old_index && j < index)
841 new_order[j] = j + 1;
845 else if (index < old_index)
848 new_order[j] = old_index;
849 else if (j > index && j <= old_index)
850 new_order[j] = j - 1;
854 /* else? shouldn't really happen */
857 if (level->parent_elt)
859 iter.stamp = priv->stamp;
860 iter.user_data = level->parent_level;
861 iter.user_data2 = level->parent_elt;
863 tmppath = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model_sort), &iter);
865 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_model_sort),
866 tmppath, &iter, new_order);
871 tmppath = gtk_tree_path_new ();
873 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_model_sort), tmppath,
877 gtk_tree_path_free (tmppath);
881 /* emit row_changed signal (at new location) */
882 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
883 gtk_tree_model_row_changed (GTK_TREE_MODEL (data), path, &iter);
884 gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (data), &iter);
886 gtk_tree_path_free (path);
888 gtk_tree_path_free (start_s_path);
892 gtk_tree_model_sort_row_inserted (GtkTreeModel *s_model,
897 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
898 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
901 GtkTreeIter real_s_iter;
905 gboolean free_s_path = FALSE;
909 SortLevel *parent_level = NULL;
911 parent_level = level = SORT_LEVEL (priv->root);
913 g_return_if_fail (s_path != NULL || s_iter != NULL);
917 s_path = gtk_tree_model_get_path (s_model, s_iter);
922 gtk_tree_model_get_iter (s_model, &real_s_iter, s_path);
924 real_s_iter = *s_iter;
928 gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
930 /* the build level already put the inserted iter in the level,
931 so no need to handle this signal anymore */
933 goto done_and_submit;
936 /* find the parent level */
937 while (i < gtk_tree_path_get_depth (s_path) - 1)
941 /* level not yet build, we won't cover this signal */
945 if (g_sequence_get_length (level->seq) < gtk_tree_path_get_indices (s_path)[i])
947 g_warning ("%s: A node was inserted with a parent that's not in the tree.\n"
948 "This possibly means that a GtkTreeModel inserted a child node\n"
949 "before the parent was inserted.",
954 elt = lookup_elt_with_offset (tree_model_sort, level,
955 gtk_tree_path_get_indices (s_path)[i],
958 g_return_if_fail (elt != NULL);
962 /* not covering this signal */
966 level = elt->children;
967 parent_level = level;
974 if (level->ref_count == 0 && level != priv->root)
976 gtk_tree_model_sort_free_level (tree_model_sort, level, TRUE);
980 if (!gtk_tree_model_sort_insert_value (tree_model_sort,
987 path = gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort,
994 gtk_tree_model_sort_increment_stamp (tree_model_sort);
996 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
997 gtk_tree_model_row_inserted (GTK_TREE_MODEL (data), path, &iter);
998 gtk_tree_path_free (path);
1002 gtk_tree_path_free (s_path);
1008 gtk_tree_model_sort_row_has_child_toggled (GtkTreeModel *s_model,
1009 GtkTreePath *s_path,
1010 GtkTreeIter *s_iter,
1013 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
1017 g_return_if_fail (s_path != NULL && s_iter != NULL);
1019 path = gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort, s_path, FALSE);
1023 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1024 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data), path, &iter);
1026 gtk_tree_path_free (path);
1030 gtk_tree_model_sort_row_deleted (GtkTreeModel *s_model,
1031 GtkTreePath *s_path,
1034 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
1035 GtkTreePath *path = NULL;
1041 g_return_if_fail (s_path != NULL);
1043 path = gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort, s_path, FALSE);
1047 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1049 level = SORT_LEVEL (iter.user_data);
1050 elt = SORT_ELT (iter.user_data2);
1051 offset = elt->offset;
1053 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1055 while (elt->ref_count > 0)
1056 gtk_tree_model_sort_real_unref_node (GTK_TREE_MODEL (data), &iter, FALSE);
1058 /* If this node has children, we free the level (recursively) here
1059 * and specify that unref may not be used, because parent and its
1060 * children have been removed by now.
1063 gtk_tree_model_sort_free_level (tree_model_sort,
1064 elt->children, FALSE);
1066 if (level->ref_count == 0)
1068 gtk_tree_model_sort_increment_stamp (tree_model_sort);
1069 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1070 gtk_tree_path_free (path);
1072 if (level == tree_model_sort->priv->root)
1074 gtk_tree_model_sort_free_level (tree_model_sort,
1075 tree_model_sort->priv->root,
1077 tree_model_sort->priv->root = NULL;
1082 g_sequence_remove (elt->siter);
1085 /* The sequence is not ordered on offset, so we traverse the entire
1088 g_sequence_foreach (level->seq, decrease_offset_iter,
1089 GINT_TO_POINTER (offset));
1091 gtk_tree_model_sort_increment_stamp (tree_model_sort);
1092 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1094 gtk_tree_path_free (path);
1098 gtk_tree_model_sort_rows_reordered (GtkTreeModel *s_model,
1099 GtkTreePath *s_path,
1100 GtkTreeIter *s_iter,
1110 GSequenceIter *siter, *end_siter;
1111 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
1112 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1114 g_return_if_fail (new_order != NULL);
1116 if (s_path == NULL || gtk_tree_path_get_depth (s_path) == 0)
1118 if (priv->root == NULL)
1120 path = gtk_tree_path_new ();
1121 level = SORT_LEVEL (priv->root);
1125 path = gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort, s_path, FALSE);
1128 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1130 level = SORT_LEVEL (iter.user_data);
1131 elt = SORT_ELT (iter.user_data2);
1135 gtk_tree_path_free (path);
1139 level = elt->children;
1142 length = g_sequence_get_length (level->seq);
1145 gtk_tree_path_free (path);
1149 tmp_array = g_new (int, length);
1151 /* FIXME: I need to think about whether this can be done in a more
1155 end_siter = g_sequence_get_end_iter (level->seq);
1156 for (siter = g_sequence_get_begin_iter (level->seq);
1158 siter = g_sequence_iter_next (siter))
1161 SortElt *elt = g_sequence_get (siter);
1163 for (j = 0; j < length; j++)
1165 if (elt->offset == new_order[j])
1172 /* This loop cannot be merged with the above loop nest, because that
1173 * would introduce duplicate offsets.
1176 end_siter = g_sequence_get_end_iter (level->seq);
1177 for (siter = g_sequence_get_begin_iter (level->seq);
1179 siter = g_sequence_iter_next (siter))
1181 SortElt *elt = g_sequence_get (siter);
1183 elt->offset = tmp_array[i];
1188 if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID &&
1189 priv->default_sort_func == NO_SORT_FUNC)
1191 gtk_tree_model_sort_sort_level (tree_model_sort, level,
1193 gtk_tree_model_sort_increment_stamp (tree_model_sort);
1195 if (gtk_tree_path_get_depth (path))
1197 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_sort),
1200 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_model_sort),
1201 path, &iter, new_order);
1205 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_model_sort),
1206 path, NULL, new_order);
1210 gtk_tree_path_free (path);
1213 /* Fulfill our model requirements */
1214 static GtkTreeModelFlags
1215 gtk_tree_model_sort_get_flags (GtkTreeModel *tree_model)
1217 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1218 GtkTreeModelFlags flags;
1220 g_return_val_if_fail (tree_model_sort->priv->child_model != NULL, 0);
1222 flags = gtk_tree_model_get_flags (tree_model_sort->priv->child_model);
1224 if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
1225 return GTK_TREE_MODEL_LIST_ONLY;
1231 gtk_tree_model_sort_get_n_columns (GtkTreeModel *tree_model)
1233 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1235 if (tree_model_sort->priv->child_model == 0)
1238 return gtk_tree_model_get_n_columns (tree_model_sort->priv->child_model);
1242 gtk_tree_model_sort_get_column_type (GtkTreeModel *tree_model,
1245 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1247 g_return_val_if_fail (tree_model_sort->priv->child_model != NULL, G_TYPE_INVALID);
1249 return gtk_tree_model_get_column_type (tree_model_sort->priv->child_model, index);
1253 gtk_tree_model_sort_get_iter (GtkTreeModel *tree_model,
1257 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1258 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1263 GSequenceIter *siter;
1265 g_return_val_if_fail (priv->child_model != NULL, FALSE);
1267 indices = gtk_tree_path_get_indices (path);
1269 if (priv->root == NULL)
1270 gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
1271 level = SORT_LEVEL (priv->root);
1273 depth = gtk_tree_path_get_depth (path);
1280 for (i = 0; i < depth - 1; i++)
1282 if ((level == NULL) ||
1283 (indices[i] >= g_sequence_get_length (level->seq)))
1289 siter = g_sequence_get_iter_at_pos (level->seq, indices[i]);
1290 if (g_sequence_iter_is_end (siter))
1296 elt = GET_ELT (siter);
1297 if (elt->children == NULL)
1298 gtk_tree_model_sort_build_level (tree_model_sort, level, elt);
1300 level = elt->children;
1303 if (!level || indices[i] >= g_sequence_get_length (level->seq))
1309 iter->stamp = priv->stamp;
1310 iter->user_data = level;
1312 siter = g_sequence_get_iter_at_pos (level->seq, indices[depth - 1]);
1313 if (g_sequence_iter_is_end (siter))
1318 iter->user_data2 = GET_ELT (siter);
1323 static GtkTreePath *
1324 gtk_tree_model_sort_get_path (GtkTreeModel *tree_model,
1327 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1328 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1329 GtkTreePath *retval;
1333 g_return_val_if_fail (priv->child_model != NULL, NULL);
1334 g_return_val_if_fail (priv->stamp == iter->stamp, NULL);
1336 retval = gtk_tree_path_new ();
1338 level = SORT_LEVEL (iter->user_data);
1339 elt = SORT_ELT (iter->user_data2);
1345 index = g_sequence_iter_get_position (elt->siter);
1346 gtk_tree_path_prepend_index (retval, index);
1348 elt = level->parent_elt;
1349 level = level->parent_level;
1356 gtk_tree_model_sort_get_value (GtkTreeModel *tree_model,
1361 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1362 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1363 GtkTreeIter child_iter;
1365 g_return_if_fail (priv->child_model != NULL);
1366 g_return_if_fail (VALID_ITER (iter, tree_model_sort));
1368 GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
1369 gtk_tree_model_get_value (priv->child_model,
1370 &child_iter, column, value);
1374 gtk_tree_model_sort_iter_next (GtkTreeModel *tree_model,
1377 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1378 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1381 GSequenceIter *siter;
1383 g_return_val_if_fail (priv->child_model != NULL, FALSE);
1384 g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);
1386 level = iter->user_data;
1387 elt = iter->user_data2;
1389 siter = g_sequence_iter_next (elt->siter);
1390 if (g_sequence_iter_is_end (siter))
1395 iter->user_data2 = GET_ELT (siter);
1401 gtk_tree_model_sort_iter_previous (GtkTreeModel *tree_model,
1404 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1405 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1408 GSequenceIter *siter;
1410 g_return_val_if_fail (priv->child_model != NULL, FALSE);
1411 g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);
1413 level = iter->user_data;
1414 elt = iter->user_data2;
1416 siter = g_sequence_iter_prev (elt->siter);
1417 if (g_sequence_iter_is_begin (siter))
1422 iter->user_data2 = GET_ELT (siter);
1428 gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
1430 GtkTreeIter *parent)
1432 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1433 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1437 g_return_val_if_fail (priv->child_model != NULL, FALSE);
1439 g_return_val_if_fail (VALID_ITER (parent, tree_model_sort), FALSE);
1443 if (priv->root == NULL)
1444 gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
1445 if (priv->root == NULL)
1449 iter->stamp = priv->stamp;
1450 iter->user_data = level;
1451 iter->user_data2 = g_sequence_get (g_sequence_get_begin_iter (level->seq));
1457 level = SORT_LEVEL (parent->user_data);
1458 elt = SORT_ELT (parent->user_data2);
1460 if (elt->children == NULL)
1461 gtk_tree_model_sort_build_level (tree_model_sort, level, elt);
1463 if (elt->children == NULL)
1466 iter->stamp = priv->stamp;
1467 iter->user_data = elt->children;
1468 iter->user_data2 = g_sequence_get (g_sequence_get_begin_iter (elt->children->seq));
1475 gtk_tree_model_sort_iter_has_child (GtkTreeModel *tree_model,
1478 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1479 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1480 GtkTreeIter child_iter;
1482 g_return_val_if_fail (priv->child_model != NULL, FALSE);
1483 g_return_val_if_fail (VALID_ITER (iter, tree_model_sort), FALSE);
1485 GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
1487 return gtk_tree_model_iter_has_child (priv->child_model, &child_iter);
1491 gtk_tree_model_sort_iter_n_children (GtkTreeModel *tree_model,
1494 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1495 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1496 GtkTreeIter child_iter;
1498 g_return_val_if_fail (priv->child_model != NULL, 0);
1500 g_return_val_if_fail (VALID_ITER (iter, tree_model_sort), 0);
1503 return gtk_tree_model_iter_n_children (priv->child_model, NULL);
1505 GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
1507 return gtk_tree_model_iter_n_children (priv->child_model, &child_iter);
1511 gtk_tree_model_sort_iter_nth_child (GtkTreeModel *tree_model,
1513 GtkTreeIter *parent,
1516 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1518 /* We have this for the iter == parent case */
1519 GtkTreeIter children;
1522 g_return_val_if_fail (VALID_ITER (parent, tree_model_sort), FALSE);
1524 /* Use this instead of has_child to force us to build the level, if needed */
1525 if (gtk_tree_model_sort_iter_children (tree_model, &children, parent) == FALSE)
1531 level = children.user_data;
1532 if (n >= g_sequence_get_length (level->seq))
1538 iter->stamp = tree_model_sort->priv->stamp;
1539 iter->user_data = level;
1540 iter->user_data2 = g_sequence_get (g_sequence_get_iter_at_pos (level->seq, n));
1546 gtk_tree_model_sort_iter_parent (GtkTreeModel *tree_model,
1550 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1551 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1555 g_return_val_if_fail (priv->child_model != NULL, FALSE);
1556 g_return_val_if_fail (VALID_ITER (child, tree_model_sort), FALSE);
1558 level = child->user_data;
1560 if (level->parent_level)
1562 iter->stamp = priv->stamp;
1563 iter->user_data = level->parent_level;
1564 iter->user_data2 = level->parent_elt;
1572 gtk_tree_model_sort_ref_node (GtkTreeModel *tree_model,
1575 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1576 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1577 GtkTreeIter child_iter;
1581 g_return_if_fail (priv->child_model != NULL);
1582 g_return_if_fail (VALID_ITER (iter, tree_model_sort));
1584 GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
1586 /* Reference the node in the child model */
1587 gtk_tree_model_ref_node (priv->child_model, &child_iter);
1589 /* Increase the reference count of this element and its level */
1590 level = iter->user_data;
1591 elt = iter->user_data2;
1596 if (level->ref_count == 1)
1598 SortLevel *parent_level = level->parent_level;
1599 SortElt *parent_elt = level->parent_elt;
1601 /* We were at zero -- time to decrement the zero_ref_count val */
1602 while (parent_level)
1604 parent_elt->zero_ref_count--;
1606 parent_elt = parent_level->parent_elt;
1607 parent_level = parent_level->parent_level;
1610 if (priv->root != level)
1611 priv->zero_ref_count--;
1616 gtk_tree_model_sort_real_unref_node (GtkTreeModel *tree_model,
1618 gboolean propagate_unref)
1620 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1621 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1625 g_return_if_fail (priv->child_model != NULL);
1626 g_return_if_fail (VALID_ITER (iter, tree_model_sort));
1628 if (propagate_unref)
1630 GtkTreeIter child_iter;
1632 GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
1633 gtk_tree_model_unref_node (priv->child_model, &child_iter);
1636 level = iter->user_data;
1637 elt = iter->user_data2;
1639 g_return_if_fail (elt->ref_count > 0);
1644 if (level->ref_count == 0)
1646 SortLevel *parent_level = level->parent_level;
1647 SortElt *parent_elt = level->parent_elt;
1649 /* We are at zero -- time to increment the zero_ref_count val */
1650 while (parent_level)
1652 parent_elt->zero_ref_count++;
1654 parent_elt = parent_level->parent_elt;
1655 parent_level = parent_level->parent_level;
1658 if (priv->root != level)
1659 priv->zero_ref_count++;
1664 gtk_tree_model_sort_unref_node (GtkTreeModel *tree_model,
1667 gtk_tree_model_sort_real_unref_node (tree_model, iter, TRUE);
1670 /* Sortable interface */
1672 gtk_tree_model_sort_get_sort_column_id (GtkTreeSortable *sortable,
1673 gint *sort_column_id,
1676 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
1677 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1680 *sort_column_id = priv->sort_column_id;
1682 *order = priv->order;
1684 if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID ||
1685 priv->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
1692 gtk_tree_model_sort_set_sort_column_id (GtkTreeSortable *sortable,
1693 gint sort_column_id,
1696 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
1697 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1699 if (sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
1701 if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
1703 GtkTreeDataSortHeader *header = NULL;
1705 header = _gtk_tree_data_list_get_header (priv->sort_list,
1708 /* we want to make sure that we have a function */
1709 g_return_if_fail (header != NULL);
1710 g_return_if_fail (header->func != NULL);
1713 g_return_if_fail (priv->default_sort_func != NULL);
1715 if (priv->sort_column_id == sort_column_id)
1717 if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
1719 if (priv->order == order)
1727 priv->sort_column_id = sort_column_id;
1728 priv->order = order;
1730 gtk_tree_sortable_sort_column_changed (sortable);
1732 gtk_tree_model_sort_sort (tree_model_sort);
1736 gtk_tree_model_sort_set_sort_func (GtkTreeSortable *sortable,
1737 gint sort_column_id,
1738 GtkTreeIterCompareFunc func,
1740 GDestroyNotify destroy)
1742 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) sortable;
1743 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1745 priv->sort_list = _gtk_tree_data_list_set_header (priv->sort_list,
1747 func, data, destroy);
1749 if (priv->sort_column_id == sort_column_id)
1750 gtk_tree_model_sort_sort (tree_model_sort);
1754 gtk_tree_model_sort_set_default_sort_func (GtkTreeSortable *sortable,
1755 GtkTreeIterCompareFunc func,
1757 GDestroyNotify destroy)
1759 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
1760 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1762 if (priv->default_sort_destroy)
1764 GDestroyNotify d = priv->default_sort_destroy;
1766 priv->default_sort_destroy = NULL;
1767 d (priv->default_sort_data);
1770 priv->default_sort_func = func;
1771 priv->default_sort_data = data;
1772 priv->default_sort_destroy = destroy;
1774 if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
1775 gtk_tree_model_sort_sort (tree_model_sort);
1779 gtk_tree_model_sort_has_default_sort_func (GtkTreeSortable *sortable)
1781 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
1783 return (tree_model_sort->priv->default_sort_func != NULL);
1786 /* DragSource interface */
1788 gtk_tree_model_sort_row_draggable (GtkTreeDragSource *drag_source,
1791 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)drag_source;
1792 GtkTreePath *child_path;
1795 child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort,
1797 draggable = gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (tree_model_sort->priv->child_model), child_path);
1798 gtk_tree_path_free (child_path);
1804 gtk_tree_model_sort_drag_data_get (GtkTreeDragSource *drag_source,
1806 GtkSelectionData *selection_data)
1808 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)drag_source;
1809 GtkTreePath *child_path;
1812 child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort, path);
1813 gotten = gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (tree_model_sort->priv->child_model), child_path, selection_data);
1814 gtk_tree_path_free (child_path);
1820 gtk_tree_model_sort_drag_data_delete (GtkTreeDragSource *drag_source,
1823 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)drag_source;
1824 GtkTreePath *child_path;
1827 child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort, path);
1828 deleted = gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (tree_model_sort->priv->child_model), child_path);
1829 gtk_tree_path_free (child_path);
1834 /* sorting code - private */
1836 gtk_tree_model_sort_compare_func (gconstpointer a,
1840 SortData *data = (SortData *)user_data;
1841 GtkTreeModelSort *tree_model_sort = data->tree_model_sort;
1842 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1843 const SortElt *sa = a;
1844 const SortElt *sb = b;
1846 GtkTreeIter iter_a, iter_b;
1849 if (GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
1856 data->parent_path_indices [data->parent_path_depth-1] = sa->offset;
1857 gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->child_model), &iter_a, data->parent_path);
1858 data->parent_path_indices [data->parent_path_depth-1] = sb->offset;
1859 gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->child_model), &iter_b, data->parent_path);
1862 retval = (* data->sort_func) (GTK_TREE_MODEL (priv->child_model),
1866 if (priv->order == GTK_SORT_DESCENDING)
1870 else if (retval < 0)
1878 gtk_tree_model_sort_offset_compare_func (gconstpointer a,
1884 const SortElt *sa = (SortElt *)a;
1885 const SortElt *sb = (SortElt *)b;
1887 SortData *data = (SortData *)user_data;
1889 if (sa->offset < sb->offset)
1891 else if (sa->offset > sb->offset)
1896 if (data->tree_model_sort->priv->order == GTK_SORT_DESCENDING)
1900 else if (retval < 0)
1908 gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
1911 gboolean emit_reordered)
1913 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1915 GSequenceIter *begin_siter, *end_siter, *siter;
1924 g_return_if_fail (level != NULL);
1926 begin_siter = g_sequence_get_begin_iter (level->seq);
1927 begin_elt = g_sequence_get (begin_siter);
1929 if (g_sequence_get_length (level->seq) < 1 && !begin_elt->children)
1932 iter.stamp = priv->stamp;
1933 iter.user_data = level;
1934 iter.user_data2 = begin_elt;
1936 gtk_tree_model_sort_ref_node (GTK_TREE_MODEL (tree_model_sort), &iter);
1939 end_siter = g_sequence_get_end_iter (level->seq);
1940 for (siter = g_sequence_get_begin_iter (level->seq);
1942 siter = g_sequence_iter_next (siter))
1944 SortElt *elt = g_sequence_get (siter);
1950 fill_sort_data (&data, tree_model_sort, level);
1952 if (data.sort_func == NO_SORT_FUNC)
1953 g_sequence_sort (level->seq, gtk_tree_model_sort_offset_compare_func,
1956 g_sequence_sort (level->seq, gtk_tree_model_sort_compare_func, &data);
1958 free_sort_data (&data);
1960 new_order = g_new (gint, g_sequence_get_length (level->seq));
1963 end_siter = g_sequence_get_end_iter (level->seq);
1964 for (siter = g_sequence_get_begin_iter (level->seq);
1966 siter = g_sequence_iter_next (siter))
1968 SortElt *elt = g_sequence_get (siter);
1970 new_order[i++] = elt->old_index;
1975 gtk_tree_model_sort_increment_stamp (tree_model_sort);
1976 if (level->parent_elt)
1978 iter.stamp = priv->stamp;
1979 iter.user_data = level->parent_level;
1980 iter.user_data2 = level->parent_elt;
1982 path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model_sort),
1985 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_model_sort), path,
1991 path = gtk_tree_path_new ();
1992 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_model_sort), path,
1996 gtk_tree_path_free (path);
1999 /* recurse, if possible */
2002 end_siter = g_sequence_get_end_iter (level->seq);
2003 for (siter = g_sequence_get_begin_iter (level->seq);
2005 siter = g_sequence_iter_next (siter))
2007 SortElt *elt = g_sequence_get (siter);
2010 gtk_tree_model_sort_sort_level (tree_model_sort,
2012 TRUE, emit_reordered);
2018 /* get the iter we referenced at the beginning of this function and
2021 iter.stamp = priv->stamp;
2022 iter.user_data = level;
2023 iter.user_data2 = begin_elt;
2025 gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (tree_model_sort), &iter);
2029 gtk_tree_model_sort_sort (GtkTreeModelSort *tree_model_sort)
2031 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2033 if (priv->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
2039 if (priv->sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
2041 GtkTreeDataSortHeader *header = NULL;
2043 header = _gtk_tree_data_list_get_header (priv->sort_list,
2044 priv->sort_column_id);
2046 /* we want to make sure that we have a function */
2047 g_return_if_fail (header != NULL);
2048 g_return_if_fail (header->func != NULL);
2051 g_return_if_fail (priv->default_sort_func != NULL);
2053 gtk_tree_model_sort_sort_level (tree_model_sort, priv->root,
2057 /* signal helpers */
2059 gtk_tree_model_sort_insert_value (GtkTreeModelSort *tree_model_sort,
2061 GtkTreePath *s_path,
2062 GtkTreeIter *s_iter)
2064 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2069 elt = sort_elt_new ();
2071 offset = gtk_tree_path_get_indices (s_path)[gtk_tree_path_get_depth (s_path) - 1];
2073 if (GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
2074 elt->iter = *s_iter;
2075 elt->offset = offset;
2076 elt->zero_ref_count = 0;
2078 elt->children = NULL;
2080 /* update all larger offsets */
2081 g_sequence_foreach (level->seq, increase_offset_iter, GINT_TO_POINTER (offset));
2083 fill_sort_data (&data, tree_model_sort, level);
2085 if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID &&
2086 priv->default_sort_func == NO_SORT_FUNC)
2088 elt->siter = g_sequence_insert_sorted (level->seq, elt,
2089 gtk_tree_model_sort_offset_compare_func,
2094 elt->siter = g_sequence_insert_sorted (level->seq, elt,
2095 gtk_tree_model_sort_compare_func,
2099 free_sort_data (&data);
2104 /* sort elt stuff */
2105 static GtkTreePath *
2106 gtk_tree_model_sort_elt_get_path (SortLevel *level,
2109 SortLevel *walker = level;
2110 SortElt *walker2 = elt;
2113 g_return_val_if_fail (level != NULL, NULL);
2114 g_return_val_if_fail (elt != NULL, NULL);
2116 path = gtk_tree_path_new ();
2120 gtk_tree_path_prepend_index (path, walker2->offset);
2122 if (!walker->parent_level)
2125 walker2 = walker->parent_elt;
2126 walker = walker->parent_level;
2133 * gtk_tree_model_sort_set_model:
2134 * @tree_model_sort: The #GtkTreeModelSort.
2135 * @child_model: (allow-none): A #GtkTreeModel, or %NULL.
2137 * Sets the model of @tree_model_sort to be @model. If @model is %NULL,
2138 * then the old model is unset. The sort function is unset as a result
2139 * of this call. The model will be in an unsorted state until a sort
2143 gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
2144 GtkTreeModel *child_model)
2146 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2149 g_object_ref (child_model);
2151 if (priv->child_model)
2153 g_signal_handler_disconnect (priv->child_model,
2155 g_signal_handler_disconnect (priv->child_model,
2157 g_signal_handler_disconnect (priv->child_model,
2158 priv->has_child_toggled_id);
2159 g_signal_handler_disconnect (priv->child_model,
2161 g_signal_handler_disconnect (priv->child_model,
2162 priv->reordered_id);
2164 /* reset our state */
2166 gtk_tree_model_sort_free_level (tree_model_sort, priv->root, TRUE);
2168 _gtk_tree_data_list_header_free (priv->sort_list);
2169 priv->sort_list = NULL;
2170 g_object_unref (priv->child_model);
2173 priv->child_model = child_model;
2181 g_signal_connect (child_model, "row-changed",
2182 G_CALLBACK (gtk_tree_model_sort_row_changed),
2185 g_signal_connect (child_model, "row-inserted",
2186 G_CALLBACK (gtk_tree_model_sort_row_inserted),
2188 priv->has_child_toggled_id =
2189 g_signal_connect (child_model, "row-has-child-toggled",
2190 G_CALLBACK (gtk_tree_model_sort_row_has_child_toggled),
2193 g_signal_connect (child_model, "row-deleted",
2194 G_CALLBACK (gtk_tree_model_sort_row_deleted),
2196 priv->reordered_id =
2197 g_signal_connect (child_model, "rows-reordered",
2198 G_CALLBACK (gtk_tree_model_sort_rows_reordered),
2201 priv->child_flags = gtk_tree_model_get_flags (child_model);
2202 n_columns = gtk_tree_model_get_n_columns (child_model);
2204 types = g_new (GType, n_columns);
2205 for (i = 0; i < n_columns; i++)
2206 types[i] = gtk_tree_model_get_column_type (child_model, i);
2208 priv->sort_list = _gtk_tree_data_list_header_new (n_columns, types);
2211 priv->default_sort_func = NO_SORT_FUNC;
2212 priv->stamp = g_random_int ();
2217 * gtk_tree_model_sort_get_model:
2218 * @tree_model: a #GtkTreeModelSort
2220 * Returns the model the #GtkTreeModelSort is sorting.
2222 * Return value: (transfer none): the "child model" being sorted
2225 gtk_tree_model_sort_get_model (GtkTreeModelSort *tree_model)
2227 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), NULL);
2229 return tree_model->priv->child_model;
2233 static GtkTreePath *
2234 gtk_real_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_model_sort,
2235 GtkTreePath *child_path,
2236 gboolean build_levels)
2238 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2239 gint *child_indices;
2240 GtkTreePath *retval;
2244 g_return_val_if_fail (priv->child_model != NULL, NULL);
2245 g_return_val_if_fail (child_path != NULL, NULL);
2247 retval = gtk_tree_path_new ();
2248 child_indices = gtk_tree_path_get_indices (child_path);
2250 if (priv->root == NULL && build_levels)
2251 gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
2252 level = SORT_LEVEL (priv->root);
2254 for (i = 0; i < gtk_tree_path_get_depth (child_path); i++)
2257 GSequenceIter *siter;
2258 gboolean found_child = FALSE;
2262 gtk_tree_path_free (retval);
2266 if (child_indices[i] >= g_sequence_get_length (level->seq))
2268 gtk_tree_path_free (retval);
2271 tmp = lookup_elt_with_offset (tree_model_sort, level,
2272 child_indices[i], &siter);
2275 gtk_tree_path_append_index (retval, g_sequence_iter_get_position (siter));
2276 if (tmp->children == NULL && build_levels)
2277 gtk_tree_model_sort_build_level (tree_model_sort, level, tmp);
2279 level = tmp->children;
2285 gtk_tree_path_free (retval);
2295 * gtk_tree_model_sort_convert_child_path_to_path:
2296 * @tree_model_sort: A #GtkTreeModelSort
2297 * @child_path: A #GtkTreePath to convert
2299 * Converts @child_path to a path relative to @tree_model_sort. That is,
2300 * @child_path points to a path in the child model. The returned path will
2301 * point to the same row in the sorted model. If @child_path isn't a valid
2302 * path on the child model, then %NULL is returned.
2304 * Return value: A newly allocated #GtkTreePath, or %NULL
2307 gtk_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_model_sort,
2308 GtkTreePath *child_path)
2310 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), NULL);
2311 g_return_val_if_fail (tree_model_sort->priv->child_model != NULL, NULL);
2312 g_return_val_if_fail (child_path != NULL, NULL);
2314 return gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort, child_path, TRUE);
2318 * gtk_tree_model_sort_convert_child_iter_to_iter:
2319 * @tree_model_sort: A #GtkTreeModelSort
2320 * @sort_iter: (out): An uninitialized #GtkTreeIter.
2321 * @child_iter: A valid #GtkTreeIter pointing to a row on the child model
2323 * Sets @sort_iter to point to the row in @tree_model_sort that corresponds to
2324 * the row pointed at by @child_iter. If @sort_iter was not set, %FALSE
2325 * is returned. Note: a boolean is only returned since 2.14.
2327 * Return value: %TRUE, if @sort_iter was set, i.e. if @sort_iter is a
2328 * valid iterator pointer to a visible row in the child model.
2331 gtk_tree_model_sort_convert_child_iter_to_iter (GtkTreeModelSort *tree_model_sort,
2332 GtkTreeIter *sort_iter,
2333 GtkTreeIter *child_iter)
2336 GtkTreePath *child_path, *path;
2337 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2339 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), FALSE);
2340 g_return_val_if_fail (priv->child_model != NULL, FALSE);
2341 g_return_val_if_fail (sort_iter != NULL, FALSE);
2342 g_return_val_if_fail (child_iter != NULL, FALSE);
2343 g_return_val_if_fail (sort_iter != child_iter, FALSE);
2345 sort_iter->stamp = 0;
2347 child_path = gtk_tree_model_get_path (priv->child_model, child_iter);
2348 g_return_val_if_fail (child_path != NULL, FALSE);
2350 path = gtk_tree_model_sort_convert_child_path_to_path (tree_model_sort, child_path);
2351 gtk_tree_path_free (child_path);
2355 g_warning ("%s: The conversion of the child path to a GtkTreeModel sort path failed", G_STRLOC);
2359 ret = gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_sort),
2361 gtk_tree_path_free (path);
2367 * gtk_tree_model_sort_convert_path_to_child_path:
2368 * @tree_model_sort: A #GtkTreeModelSort
2369 * @sorted_path: A #GtkTreePath to convert
2371 * Converts @sorted_path to a path on the child model of @tree_model_sort.
2372 * That is, @sorted_path points to a location in @tree_model_sort. The
2373 * returned path will point to the same location in the model not being
2374 * sorted. If @sorted_path does not point to a location in the child model,
2375 * %NULL is returned.
2377 * Return value: A newly allocated #GtkTreePath, or %NULL
2380 gtk_tree_model_sort_convert_path_to_child_path (GtkTreeModelSort *tree_model_sort,
2381 GtkTreePath *sorted_path)
2383 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2384 gint *sorted_indices;
2385 GtkTreePath *retval;
2389 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), NULL);
2390 g_return_val_if_fail (priv->child_model != NULL, NULL);
2391 g_return_val_if_fail (sorted_path != NULL, NULL);
2393 retval = gtk_tree_path_new ();
2394 sorted_indices = gtk_tree_path_get_indices (sorted_path);
2395 if (priv->root == NULL)
2396 gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
2397 level = SORT_LEVEL (priv->root);
2399 for (i = 0; i < gtk_tree_path_get_depth (sorted_path); i++)
2401 SortElt *elt = NULL;
2402 GSequenceIter *siter;
2404 if ((level == NULL) ||
2405 (g_sequence_get_length (level->seq) <= sorted_indices[i]))
2407 gtk_tree_path_free (retval);
2411 siter = g_sequence_get_iter_at_pos (level->seq, sorted_indices[i]);
2412 if (g_sequence_iter_is_end (siter))
2414 gtk_tree_path_free (retval);
2418 elt = GET_ELT (siter);
2419 if (elt->children == NULL)
2420 gtk_tree_model_sort_build_level (tree_model_sort, level, elt);
2424 gtk_tree_path_free (retval);
2428 gtk_tree_path_append_index (retval, elt->offset);
2429 level = elt->children;
2436 * gtk_tree_model_sort_convert_iter_to_child_iter:
2437 * @tree_model_sort: A #GtkTreeModelSort
2438 * @child_iter: (out): An uninitialized #GtkTreeIter
2439 * @sorted_iter: A valid #GtkTreeIter pointing to a row on @tree_model_sort.
2441 * Sets @child_iter to point to the row pointed to by @sorted_iter.
2444 gtk_tree_model_sort_convert_iter_to_child_iter (GtkTreeModelSort *tree_model_sort,
2445 GtkTreeIter *child_iter,
2446 GtkTreeIter *sorted_iter)
2448 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2449 g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
2450 g_return_if_fail (priv->child_model != NULL);
2451 g_return_if_fail (child_iter != NULL);
2452 g_return_if_fail (VALID_ITER (sorted_iter, tree_model_sort));
2453 g_return_if_fail (sorted_iter != child_iter);
2455 if (GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
2457 *child_iter = SORT_ELT (sorted_iter->user_data2)->iter;
2462 gboolean valid = FALSE;
2464 path = gtk_tree_model_sort_elt_get_path (sorted_iter->user_data,
2465 sorted_iter->user_data2);
2466 valid = gtk_tree_model_get_iter (priv->child_model, child_iter, path);
2467 gtk_tree_path_free (path);
2469 g_return_if_fail (valid == TRUE);
2474 gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
2475 SortLevel *parent_level,
2476 SortElt *parent_elt)
2478 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2480 SortLevel *new_level;
2484 g_assert (priv->child_model != NULL);
2486 if (parent_level == NULL)
2488 if (gtk_tree_model_get_iter_first (priv->child_model, &iter) == FALSE)
2490 length = gtk_tree_model_iter_n_children (priv->child_model, NULL);
2494 GtkTreeIter parent_iter;
2495 GtkTreeIter child_parent_iter;
2497 parent_iter.stamp = priv->stamp;
2498 parent_iter.user_data = parent_level;
2499 parent_iter.user_data2 = parent_elt;
2501 gtk_tree_model_sort_convert_iter_to_child_iter (tree_model_sort,
2504 if (gtk_tree_model_iter_children (priv->child_model,
2506 &child_parent_iter) == FALSE)
2509 /* stamp may have changed */
2510 gtk_tree_model_sort_convert_iter_to_child_iter (tree_model_sort,
2514 length = gtk_tree_model_iter_n_children (priv->child_model, &child_parent_iter);
2516 gtk_tree_model_sort_ref_node (GTK_TREE_MODEL (tree_model_sort),
2520 g_return_if_fail (length > 0);
2522 new_level = g_new (SortLevel, 1);
2523 new_level->seq = g_sequence_new (sort_elt_free);
2524 new_level->ref_count = 0;
2525 new_level->parent_level = parent_level;
2526 new_level->parent_elt = parent_elt;
2529 parent_elt->children = new_level;
2531 priv->root = new_level;
2533 /* increase the count of zero ref_counts.*/
2534 while (parent_level)
2536 parent_elt->zero_ref_count++;
2538 parent_elt = parent_level->parent_elt;
2539 parent_level = parent_level->parent_level;
2542 if (new_level != priv->root)
2543 priv->zero_ref_count++;
2545 for (i = 0; i < length; i++)
2549 sort_elt = sort_elt_new ();
2550 sort_elt->offset = i;
2551 sort_elt->zero_ref_count = 0;
2552 sort_elt->ref_count = 0;
2553 sort_elt->children = NULL;
2555 if (GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
2557 sort_elt->iter = iter;
2558 if (gtk_tree_model_iter_next (priv->child_model, &iter) == FALSE &&
2566 level = gtk_tree_model_sort_elt_get_path (parent_level,
2568 str = gtk_tree_path_to_string (level);
2569 gtk_tree_path_free (level);
2571 g_warning ("%s: There is a discrepancy between the sort model "
2572 "and the child model. The child model is "
2573 "advertising a wrong length for level %s:.",
2579 g_warning ("%s: There is a discrepancy between the sort model "
2580 "and the child model. The child model is "
2581 "advertising a wrong length for the root level.",
2589 sort_elt->siter = g_sequence_append (new_level->seq, sort_elt);
2593 gtk_tree_model_sort_sort_level (tree_model_sort, new_level,
2598 gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
2599 SortLevel *sort_level,
2602 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2603 GSequenceIter *siter;
2604 GSequenceIter *end_siter;
2606 g_assert (sort_level);
2608 end_siter = g_sequence_get_end_iter (sort_level->seq);
2609 for (siter = g_sequence_get_begin_iter (sort_level->seq);
2611 siter = g_sequence_iter_next (siter))
2613 SortElt *elt = g_sequence_get (siter);
2616 gtk_tree_model_sort_free_level (tree_model_sort,
2617 elt->children, unref);
2620 if (sort_level->ref_count == 0)
2622 SortLevel *parent_level = sort_level->parent_level;
2623 SortElt *parent_elt = sort_level->parent_elt;
2625 while (parent_level)
2627 parent_elt->zero_ref_count--;
2629 parent_elt = parent_level->parent_elt;
2630 parent_level = parent_level->parent_level;
2633 if (sort_level != priv->root)
2634 priv->zero_ref_count--;
2637 if (sort_level->parent_elt)
2641 GtkTreeIter parent_iter;
2643 parent_iter.stamp = tree_model_sort->priv->stamp;
2644 parent_iter.user_data = sort_level->parent_level;
2645 parent_iter.user_data2 = sort_level->parent_elt;
2647 gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (tree_model_sort),
2651 sort_level->parent_elt->children = NULL;
2656 g_sequence_free (sort_level->seq);
2657 sort_level->seq = NULL;
2659 g_free (sort_level);
2664 gtk_tree_model_sort_increment_stamp (GtkTreeModelSort *tree_model_sort)
2666 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2672 while (priv->stamp == 0);
2674 gtk_tree_model_sort_clear_cache (tree_model_sort);
2678 gtk_tree_model_sort_clear_cache_helper_iter (gpointer data,
2681 GtkTreeModelSort *tree_model_sort = user_data;
2682 SortElt *elt = data;
2684 if (elt->zero_ref_count > 0)
2685 gtk_tree_model_sort_clear_cache_helper (tree_model_sort, elt->children);
2689 gtk_tree_model_sort_clear_cache_helper (GtkTreeModelSort *tree_model_sort,
2692 g_assert (level != NULL);
2694 g_sequence_foreach (level->seq, gtk_tree_model_sort_clear_cache_helper_iter,
2697 if (level->ref_count == 0 && level != tree_model_sort->priv->root)
2698 gtk_tree_model_sort_free_level (tree_model_sort, level, TRUE);
2702 * gtk_tree_model_sort_reset_default_sort_func:
2703 * @tree_model_sort: A #GtkTreeModelSort
2705 * This resets the default sort function to be in the 'unsorted' state. That
2706 * is, it is in the same order as the child model. It will re-sort the model
2707 * to be in the same order as the child model only if the #GtkTreeModelSort
2708 * is in 'unsorted' state.
2711 gtk_tree_model_sort_reset_default_sort_func (GtkTreeModelSort *tree_model_sort)
2713 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2715 g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
2717 if (priv->default_sort_destroy)
2719 GDestroyNotify d = priv->default_sort_destroy;
2721 priv->default_sort_destroy = NULL;
2722 d (priv->default_sort_data);
2725 priv->default_sort_func = NO_SORT_FUNC;
2726 priv->default_sort_data = NULL;
2727 priv->default_sort_destroy = NULL;
2729 if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
2730 gtk_tree_model_sort_sort (tree_model_sort);
2731 priv->sort_column_id = GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID;
2735 * gtk_tree_model_sort_clear_cache:
2736 * @tree_model_sort: A #GtkTreeModelSort
2738 * This function should almost never be called. It clears the @tree_model_sort
2739 * of any cached iterators that haven't been reffed with
2740 * gtk_tree_model_ref_node(). This might be useful if the child model being
2741 * sorted is static (and doesn't change often) and there has been a lot of
2742 * unreffed access to nodes. As a side effect of this function, all unreffed
2743 * iters will be invalid.
2746 gtk_tree_model_sort_clear_cache (GtkTreeModelSort *tree_model_sort)
2748 g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
2750 if (tree_model_sort->priv->zero_ref_count > 0)
2751 gtk_tree_model_sort_clear_cache_helper (tree_model_sort, (SortLevel *)tree_model_sort->priv->root);
2755 gtk_tree_model_sort_iter_is_valid_helper (GtkTreeIter *iter,
2758 GSequenceIter *siter;
2759 GSequenceIter *end_siter;
2761 end_siter = g_sequence_get_end_iter (level->seq);
2762 for (siter = g_sequence_get_begin_iter (level->seq);
2763 siter != end_siter; siter = g_sequence_iter_next (siter))
2765 SortElt *elt = g_sequence_get (siter);
2767 if (iter->user_data == level && iter->user_data2 == elt)
2771 if (gtk_tree_model_sort_iter_is_valid_helper (iter, elt->children))
2779 * gtk_tree_model_sort_iter_is_valid:
2780 * @tree_model_sort: A #GtkTreeModelSort.
2781 * @iter: A #GtkTreeIter.
2784 * This function is slow. Only use it for debugging and/or testing purposes.
2787 * Checks if the given iter is a valid iter for this #GtkTreeModelSort.
2789 * Return value: %TRUE if the iter is valid, %FALSE if the iter is invalid.
2794 gtk_tree_model_sort_iter_is_valid (GtkTreeModelSort *tree_model_sort,
2797 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), FALSE);
2798 g_return_val_if_fail (iter != NULL, FALSE);
2800 if (!VALID_ITER (iter, tree_model_sort))
2803 return gtk_tree_model_sort_iter_is_valid_helper (iter,
2804 tree_model_sort->priv->root);