1/* gtktreemodelsort.c
2 * Copyright (C) 2000,2001 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
3 * Copyright (C) 2001,2002 Kristian Rietveld <kris@gtk.org>
4 *
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.
9 *
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.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "config.h"
20#include <string.h>
21
22#include "gtktreemodelsort.h"
23#include "gtktreesortable.h"
24#include "gtktreestore.h"
25#include "gtktreedatalist.h"
26#include "gtkintl.h"
27#include "gtkprivate.h"
28#include "gtktreednd.h"
29
30
31/**
32 * GtkTreeModelSort:
33 *
34 * A GtkTreeModel which makes an underlying tree model sortable
35 *
36 * The `GtkTreeModelSort` is a model which implements the `GtkTreeSortable`
37 * interface. It does not hold any data itself, but rather is created with
38 * a child model and proxies its data. It has identical column types to
39 * this child model, and the changes in the child are propagated. The
40 * primary purpose of this model is to provide a way to sort a different
41 * model without modifying it. Note that the sort function used by
42 * `GtkTreeModelSort` is not guaranteed to be stable.
43 *
44 * The use of this is best demonstrated through an example. In the
45 * following sample code we create two `GtkTreeView` widgets each with a
46 * view of the same data. As the model is wrapped here by a
47 * `GtkTreeModelSort`, the two `GtkTreeView`s can each sort their
48 * view of the data without affecting the other. By contrast, if we
49 * simply put the same model in each widget, then sorting the first would
50 * sort the second.
51 *
52 * ## Using a `GtkTreeModelSort`
53 *
54 * |[<!-- language="C" -->
55 * {
56 * GtkTreeView *tree_view1;
57 * GtkTreeView *tree_view2;
58 * GtkTreeModel *sort_model1;
59 * GtkTreeModel *sort_model2;
60 * GtkTreeModel *child_model;
61 *
62 * // get the child model
63 * child_model = get_my_model ();
64 *
65 * // Create the first tree
66 * sort_model1 = gtk_tree_model_sort_new_with_model (child_model);
67 * tree_view1 = gtk_tree_view_new_with_model (sort_model1);
68 *
69 * // Create the second tree
70 * sort_model2 = gtk_tree_model_sort_new_with_model (child_model);
71 * tree_view2 = gtk_tree_view_new_with_model (sort_model2);
72 *
73 * // Now we can sort the two models independently
74 * gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model1),
75 * COLUMN_1, GTK_SORT_ASCENDING);
76 * gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model2),
77 * COLUMN_1, GTK_SORT_DESCENDING);
78 * }
79 * ]|
80 *
81 * To demonstrate how to access the underlying child model from the sort
82 * model, the next example will be a callback for the `GtkTreeSelection`
83 * `GtkTreeSelection::changed` signal. In this callback, we get a string
84 * from COLUMN_1 of the model. We then modify the string, find the same
85 * selected row on the child model, and change the row there.
86 *
87 * ## Accessing the child model of in a selection changed callback
88 *
89 * |[<!-- language="C" -->
90 * void
91 * selection_changed (GtkTreeSelection *selection, gpointer data)
92 * {
93 * GtkTreeModel *sort_model = NULL;
94 * GtkTreeModel *child_model;
95 * GtkTreeIter sort_iter;
96 * GtkTreeIter child_iter;
97 * char *some_data = NULL;
98 * char *modified_data;
99 *
100 * // Get the current selected row and the model.
101 * if (! gtk_tree_selection_get_selected (selection,
102 * &sort_model,
103 * &sort_iter))
104 * return;
105 *
106 * // Look up the current value on the selected row and get
107 * // a new value to change it to.
108 * gtk_tree_model_get (GTK_TREE_MODEL (sort_model), &sort_iter,
109 * COLUMN_1, &some_data,
110 * -1);
111 *
112 * modified_data = change_the_data (some_data);
113 * g_free (some_data);
114 *
115 * // Get an iterator on the child model, instead of the sort model.
116 * gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (sort_model),
117 * &child_iter,
118 * &sort_iter);
119 *
120 * // Get the child model and change the value of the row. In this
121 * // example, the child model is a GtkListStore. It could be any other
122 * // type of model, though.
123 * child_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (sort_model));
124 * gtk_list_store_set (GTK_LIST_STORE (child_model), &child_iter,
125 * COLUMN_1, &modified_data,
126 * -1);
127 * g_free (modified_data);
128 * }
129 * ]|
130 */
131
132
133/* Notes on this implementation of GtkTreeModelSort
134 * ================================================
135 *
136 * Warnings
137 * --------
138 *
139 * In this code there is a potential for confusion as to whether an iter,
140 * path or value refers to the GtkTreeModelSort model, or to the child model
141 * that has been set. As a convention, variables referencing the child model
142 * will have an s_ prefix before them (ie. s_iter, s_value, s_path);
143 * Conversion of iterators and paths between GtkTreeModelSort and the child
144 * model is done through the various gtk_tree_model_sort_convert_* functions.
145 *
146 * Iterator format
147 * ---------------
148 *
149 * The iterator format of iterators handed out by GtkTreeModelSort is as
150 * follows:
151 *
152 * iter->stamp = tree_model_sort->stamp
153 * iter->user_data = SortLevel
154 * iter->user_data2 = SortElt
155 *
156 * Internal data structure
157 * -----------------------
158 *
159 * Using SortLevel and SortElt, GtkTreeModelSort maintains a “cache” of
160 * the mapping from GtkTreeModelSort nodes to nodes in the child model.
161 * This is to avoid sorting a level each time an operation is requested
162 * on GtkTreeModelSort, such as get iter, get path, get value.
163 *
164 * A SortElt corresponds to a single node. A node and its siblings are
165 * stored in a SortLevel. The SortLevel keeps a reference to the parent
166 * SortElt and its SortLevel (if any). The SortElt can have a "children"
167 * pointer set, which points at a child level (a sub level).
168 *
169 * In a SortLevel, nodes are stored in a GSequence. The GSequence
170 * allows for fast additions and removals, and supports sorting
171 * the level of SortElt nodes.
172 *
173 * It is important to recognize the two different mappings that play
174 * a part in this code:
175 * I. The mapping from the client to this model. The order in which
176 * nodes are stored in the GSequence is the order in which the
177 * nodes are exposed to clients of the GtkTreeModelSort.
178 * II. The mapping from this model to its child model. Each SortElt
179 * contains an “offset” field which is the offset of the
180 * corresponding node in the child model.
181 *
182 * Reference counting
183 * ------------------
184 *
185 * GtkTreeModelSort forwards all reference and unreference operations
186 * to the corresponding node in the child model. The reference count
187 * of each node is also maintained internally, in the “ref_count”
188 * fields in SortElt and SortLevel. For each ref and unref operation on
189 * a SortElt, the “ref_count” of the SortLevel is updated accordingly.
190 * In addition, if a SortLevel has a parent, a reference is taken on
191 * this parent. This happens in gtk_tree_model_sort_build_level() and
192 * the reference is released again in gtk_tree_model_sort_free_level().
193 * This ensures that when GtkTreeModelSort takes a reference on a node
194 * (for example during sorting), all parent nodes are referenced
195 * according to reference counting rule 1, see the GtkTreeModel
196 * documentation.
197 *
198 * When a level has a reference count of zero, which means that
199 * none of the nodes in the level is referenced, the level has
200 * a “zero ref count” on all its parents. As soon as the level
201 * reaches a reference count of zero, the zero ref count value is
202 * incremented by one on all parents of this level. Similarly, as
203 * soon as the reference count of a level changes from zero, the
204 * zero ref count value is decremented by one on all parents.
205 *
206 * The zero ref count value is used to clear unused portions of
207 * the cache. If a SortElt has a zero ref count of one, then
208 * its child level is unused and can be removed from the cache.
209 * If the zero ref count value is higher than one, then the
210 * child level contains sublevels which are unused as well.
211 * gtk_tree_model_sort_clear_cache() uses this to not recurse
212 * into levels which have a zero ref count of zero.
213 */
214
215typedef struct _SortElt SortElt;
216typedef struct _SortLevel SortLevel;
217typedef struct _SortData SortData;
218
219struct _SortElt
220{
221 GtkTreeIter iter;
222 SortLevel *children;
223 int offset;
224 int ref_count;
225 int zero_ref_count;
226 int old_index; /* used while sorting */
227 GSequenceIter *siter; /* iter into seq */
228};
229
230struct _SortLevel
231{
232 GSequence *seq;
233 int ref_count;
234 SortElt *parent_elt;
235 SortLevel *parent_level;
236};
237
238struct _SortData
239{
240 GtkTreeModelSort *tree_model_sort;
241 GtkTreeIterCompareFunc sort_func;
242 gpointer sort_data;
243
244 GtkTreePath *parent_path;
245 int *parent_path_indices;
246 int parent_path_depth;
247};
248
249/* Properties */
250enum {
251 PROP_0,
252 /* Construct args */
253 PROP_MODEL
254};
255
256
257struct _GtkTreeModelSortPrivate
258{
259 gpointer root;
260 int stamp;
261 guint child_flags;
262 GtkTreeModel *child_model;
263 int zero_ref_count;
264
265 /* sort information */
266 GList *sort_list;
267 int sort_column_id;
268 GtkSortType order;
269
270 /* default sort */
271 GtkTreeIterCompareFunc default_sort_func;
272 gpointer default_sort_data;
273 GDestroyNotify default_sort_destroy;
274
275 /* signal ids */
276 gulong changed_id;
277 gulong inserted_id;
278 gulong has_child_toggled_id;
279 gulong deleted_id;
280 gulong reordered_id;
281};
282
283/* Set this to 0 to disable caching of child iterators. This
284 * allows for more stringent testing. It is recommended to set this
285 * to one when refactoring this code and running the unit tests to
286 * catch more errors.
287 */
288#if 1
289# define GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS(tree_model_sort) \
290 (((GtkTreeModelSort *)tree_model_sort)->priv->child_flags&GTK_TREE_MODEL_ITERS_PERSIST)
291#else
292# define GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS(tree_model_sort) (FALSE)
293#endif
294
295#define SORT_ELT(sort_elt) ((SortElt *)sort_elt)
296#define SORT_LEVEL(sort_level) ((SortLevel *)sort_level)
297#define GET_ELT(siter) ((SortElt *) (siter ? g_sequence_get (siter) : NULL))
298
299
300#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));
301
302#define NO_SORT_FUNC ((GtkTreeIterCompareFunc) 0x1)
303
304#define VALID_ITER(iter, tree_model_sort) ((iter) != NULL && (iter)->user_data != NULL && (iter)->user_data2 != NULL && (tree_model_sort)->priv->stamp == (iter)->stamp)
305
306/* general (object/interface init, etc) */
307static void gtk_tree_model_sort_tree_model_init (GtkTreeModelIface *iface);
308static void gtk_tree_model_sort_tree_sortable_init (GtkTreeSortableIface *iface);
309static void gtk_tree_model_sort_drag_source_init (GtkTreeDragSourceIface*iface);
310static void gtk_tree_model_sort_finalize (GObject *object);
311static void gtk_tree_model_sort_set_property (GObject *object,
312 guint prop_id,
313 const GValue *value,
314 GParamSpec *pspec);
315static void gtk_tree_model_sort_get_property (GObject *object,
316 guint prop_id,
317 GValue *value,
318 GParamSpec *pspec);
319
320/* our signal handlers */
321static void gtk_tree_model_sort_row_changed (GtkTreeModel *model,
322 GtkTreePath *start_path,
323 GtkTreeIter *start_iter,
324 gpointer data);
325static void gtk_tree_model_sort_row_inserted (GtkTreeModel *model,
326 GtkTreePath *path,
327 GtkTreeIter *iter,
328 gpointer data);
329static void gtk_tree_model_sort_row_has_child_toggled (GtkTreeModel *model,
330 GtkTreePath *path,
331 GtkTreeIter *iter,
332 gpointer data);
333static void gtk_tree_model_sort_row_deleted (GtkTreeModel *model,
334 GtkTreePath *path,
335 gpointer data);
336static void gtk_tree_model_sort_rows_reordered (GtkTreeModel *s_model,
337 GtkTreePath *s_path,
338 GtkTreeIter *s_iter,
339 int *new_order,
340 gpointer data);
341
342/* TreeModel interface */
343static GtkTreeModelFlags gtk_tree_model_sort_get_flags (GtkTreeModel *tree_model);
344static int gtk_tree_model_sort_get_n_columns (GtkTreeModel *tree_model);
345static GType gtk_tree_model_sort_get_column_type (GtkTreeModel *tree_model,
346 int index);
347static gboolean gtk_tree_model_sort_get_iter (GtkTreeModel *tree_model,
348 GtkTreeIter *iter,
349 GtkTreePath *path);
350static GtkTreePath *gtk_tree_model_sort_get_path (GtkTreeModel *tree_model,
351 GtkTreeIter *iter);
352static void gtk_tree_model_sort_get_value (GtkTreeModel *tree_model,
353 GtkTreeIter *iter,
354 int column,
355 GValue *value);
356static gboolean gtk_tree_model_sort_iter_next (GtkTreeModel *tree_model,
357 GtkTreeIter *iter);
358static gboolean gtk_tree_model_sort_iter_previous (GtkTreeModel *tree_model,
359 GtkTreeIter *iter);
360static gboolean gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
361 GtkTreeIter *iter,
362 GtkTreeIter *parent);
363static gboolean gtk_tree_model_sort_iter_has_child (GtkTreeModel *tree_model,
364 GtkTreeIter *iter);
365static int gtk_tree_model_sort_iter_n_children (GtkTreeModel *tree_model,
366 GtkTreeIter *iter);
367static gboolean gtk_tree_model_sort_iter_nth_child (GtkTreeModel *tree_model,
368 GtkTreeIter *iter,
369 GtkTreeIter *parent,
370 int n);
371static gboolean gtk_tree_model_sort_iter_parent (GtkTreeModel *tree_model,
372 GtkTreeIter *iter,
373 GtkTreeIter *child);
374static void gtk_tree_model_sort_ref_node (GtkTreeModel *tree_model,
375 GtkTreeIter *iter);
376static void gtk_tree_model_sort_real_unref_node (GtkTreeModel *tree_model,
377 GtkTreeIter *iter,
378 gboolean propagate_unref);
379static void gtk_tree_model_sort_unref_node (GtkTreeModel *tree_model,
380 GtkTreeIter *iter);
381
382/* TreeDragSource interface */
383static gboolean gtk_tree_model_sort_row_draggable (GtkTreeDragSource *drag_source,
384 GtkTreePath *path);
385static GdkContentProvider *
386 gtk_tree_model_sort_drag_data_get (GtkTreeDragSource *drag_source,
387 GtkTreePath *path);
388static gboolean gtk_tree_model_sort_drag_data_delete (GtkTreeDragSource *drag_source,
389 GtkTreePath *path);
390
391/* TreeSortable interface */
392static gboolean gtk_tree_model_sort_get_sort_column_id (GtkTreeSortable *sortable,
393 int *sort_column_id,
394 GtkSortType *order);
395static void gtk_tree_model_sort_set_sort_column_id (GtkTreeSortable *sortable,
396 int sort_column_id,
397 GtkSortType order);
398static void gtk_tree_model_sort_set_sort_func (GtkTreeSortable *sortable,
399 int sort_column_id,
400 GtkTreeIterCompareFunc func,
401 gpointer data,
402 GDestroyNotify destroy);
403static void gtk_tree_model_sort_set_default_sort_func (GtkTreeSortable *sortable,
404 GtkTreeIterCompareFunc func,
405 gpointer data,
406 GDestroyNotify destroy);
407static gboolean gtk_tree_model_sort_has_default_sort_func (GtkTreeSortable *sortable);
408
409/* Private functions (sort funcs, level handling and other utils) */
410static void gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
411 SortLevel *parent_level,
412 SortElt *parent_elt);
413static void gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
414 SortLevel *sort_level,
415 gboolean unref);
416static void gtk_tree_model_sort_increment_stamp (GtkTreeModelSort *tree_model_sort);
417static void gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
418 SortLevel *level,
419 gboolean recurse,
420 gboolean emit_reordered);
421static void gtk_tree_model_sort_sort (GtkTreeModelSort *tree_model_sort);
422static gboolean gtk_tree_model_sort_insert_value (GtkTreeModelSort *tree_model_sort,
423 SortLevel *level,
424 GtkTreePath *s_path,
425 GtkTreeIter *s_iter);
426static GtkTreePath *gtk_tree_model_sort_elt_get_path (SortLevel *level,
427 SortElt *elt);
428static void gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
429 GtkTreeModel *child_model);
430static GtkTreePath *gtk_real_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_model_sort,
431 GtkTreePath *child_path,
432 gboolean build_levels);
433
434static int gtk_tree_model_sort_compare_func (gconstpointer a,
435 gconstpointer b,
436 gpointer user_data);
437static int gtk_tree_model_sort_offset_compare_func (gconstpointer a,
438 gconstpointer b,
439 gpointer user_data);
440static void gtk_tree_model_sort_clear_cache_helper (GtkTreeModelSort *tree_model_sort,
441 SortLevel *level);
442
443
444G_DEFINE_TYPE_WITH_CODE (GtkTreeModelSort, gtk_tree_model_sort, G_TYPE_OBJECT,
445 G_ADD_PRIVATE (GtkTreeModelSort)
446 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
447 gtk_tree_model_sort_tree_model_init)
448 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
449 gtk_tree_model_sort_tree_sortable_init)
450 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
451 gtk_tree_model_sort_drag_source_init))
452
453static void
454gtk_tree_model_sort_init (GtkTreeModelSort *tree_model_sort)
455{
456 GtkTreeModelSortPrivate *priv;
457
458 tree_model_sort->priv = priv =
459 gtk_tree_model_sort_get_instance_private (self: tree_model_sort);
460 priv->sort_column_id = GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID;
461 priv->stamp = 0;
462 priv->zero_ref_count = 0;
463 priv->root = NULL;
464 priv->sort_list = NULL;
465}
466
467static void
468gtk_tree_model_sort_class_init (GtkTreeModelSortClass *class)
469{
470 GObjectClass *object_class;
471
472 object_class = (GObjectClass *) class;
473
474 object_class->set_property = gtk_tree_model_sort_set_property;
475 object_class->get_property = gtk_tree_model_sort_get_property;
476
477 object_class->finalize = gtk_tree_model_sort_finalize;
478
479 /* Properties */
480 g_object_class_install_property (oclass: object_class,
481 property_id: PROP_MODEL,
482 pspec: g_param_spec_object (name: "model",
483 P_("TreeModelSort Model"),
484 P_("The model for the TreeModelSort to sort"),
485 GTK_TYPE_TREE_MODEL,
486 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
487}
488
489static void
490gtk_tree_model_sort_tree_model_init (GtkTreeModelIface *iface)
491{
492 iface->get_flags = gtk_tree_model_sort_get_flags;
493 iface->get_n_columns = gtk_tree_model_sort_get_n_columns;
494 iface->get_column_type = gtk_tree_model_sort_get_column_type;
495 iface->get_iter = gtk_tree_model_sort_get_iter;
496 iface->get_path = gtk_tree_model_sort_get_path;
497 iface->get_value = gtk_tree_model_sort_get_value;
498 iface->iter_next = gtk_tree_model_sort_iter_next;
499 iface->iter_previous = gtk_tree_model_sort_iter_previous;
500 iface->iter_children = gtk_tree_model_sort_iter_children;
501 iface->iter_has_child = gtk_tree_model_sort_iter_has_child;
502 iface->iter_n_children = gtk_tree_model_sort_iter_n_children;
503 iface->iter_nth_child = gtk_tree_model_sort_iter_nth_child;
504 iface->iter_parent = gtk_tree_model_sort_iter_parent;
505 iface->ref_node = gtk_tree_model_sort_ref_node;
506 iface->unref_node = gtk_tree_model_sort_unref_node;
507}
508
509static void
510gtk_tree_model_sort_tree_sortable_init (GtkTreeSortableIface *iface)
511{
512 iface->get_sort_column_id = gtk_tree_model_sort_get_sort_column_id;
513 iface->set_sort_column_id = gtk_tree_model_sort_set_sort_column_id;
514 iface->set_sort_func = gtk_tree_model_sort_set_sort_func;
515 iface->set_default_sort_func = gtk_tree_model_sort_set_default_sort_func;
516 iface->has_default_sort_func = gtk_tree_model_sort_has_default_sort_func;
517}
518
519static void
520gtk_tree_model_sort_drag_source_init (GtkTreeDragSourceIface *iface)
521{
522 iface->row_draggable = gtk_tree_model_sort_row_draggable;
523 iface->drag_data_delete = gtk_tree_model_sort_drag_data_delete;
524 iface->drag_data_get = gtk_tree_model_sort_drag_data_get;
525}
526
527/**
528 * gtk_tree_model_sort_new_with_model: (constructor)
529 * @child_model: A `GtkTreeModel`
530 *
531 * Creates a new `GtkTreeModelSort`, with @child_model as the child model.
532 *
533 * Returns: (transfer full) (type Gtk.TreeModelSort): A new `GtkTreeModelSort`.
534 */
535GtkTreeModel *
536gtk_tree_model_sort_new_with_model (GtkTreeModel *child_model)
537{
538 GtkTreeModel *retval;
539
540 g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
541
542 retval = g_object_new (object_type: gtk_tree_model_sort_get_type (), NULL);
543
544 gtk_tree_model_sort_set_model (GTK_TREE_MODEL_SORT (retval), child_model);
545
546 return retval;
547}
548
549/* GObject callbacks */
550static void
551gtk_tree_model_sort_finalize (GObject *object)
552{
553 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) object;
554 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
555
556 gtk_tree_model_sort_set_model (tree_model_sort, NULL);
557
558 if (priv->root)
559 gtk_tree_model_sort_free_level (tree_model_sort, sort_level: priv->root, TRUE);
560
561 if (priv->sort_list)
562 {
563 _gtk_tree_data_list_header_free (header_list: priv->sort_list);
564 priv->sort_list = NULL;
565 }
566
567 if (priv->default_sort_destroy)
568 {
569 priv->default_sort_destroy (priv->default_sort_data);
570 priv->default_sort_destroy = NULL;
571 priv->default_sort_data = NULL;
572 }
573
574
575 /* must chain up */
576 G_OBJECT_CLASS (gtk_tree_model_sort_parent_class)->finalize (object);
577}
578
579static void
580gtk_tree_model_sort_set_property (GObject *object,
581 guint prop_id,
582 const GValue *value,
583 GParamSpec *pspec)
584{
585 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (object);
586
587 switch (prop_id)
588 {
589 case PROP_MODEL:
590 gtk_tree_model_sort_set_model (tree_model_sort, child_model: g_value_get_object (value));
591 break;
592 default:
593 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
594 break;
595 }
596}
597
598static void
599gtk_tree_model_sort_get_property (GObject *object,
600 guint prop_id,
601 GValue *value,
602 GParamSpec *pspec)
603{
604 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (object);
605
606 switch (prop_id)
607 {
608 case PROP_MODEL:
609 g_value_set_object (value, v_object: gtk_tree_model_sort_get_model (tree_model: tree_model_sort));
610 break;
611 default:
612 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
613 break;
614 }
615}
616
617/* helpers */
618static SortElt *
619sort_elt_new (void)
620{
621 return g_slice_new (SortElt);
622}
623
624static void
625sort_elt_free (gpointer elt)
626{
627 g_slice_free (SortElt, elt);
628}
629
630static void
631increase_offset_iter (gpointer data,
632 gpointer user_data)
633{
634 SortElt *elt = data;
635 int offset = GPOINTER_TO_INT (user_data);
636
637 if (elt->offset >= offset)
638 elt->offset++;
639}
640
641static void
642decrease_offset_iter (gpointer data,
643 gpointer user_data)
644{
645 SortElt *elt = data;
646 int offset = GPOINTER_TO_INT (user_data);
647
648 if (elt->offset > offset)
649 elt->offset--;
650}
651
652static void
653fill_sort_data (SortData *data,
654 GtkTreeModelSort *tree_model_sort,
655 SortLevel *level)
656{
657 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
658
659 data->tree_model_sort = tree_model_sort;
660
661 if (priv->sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
662 {
663 GtkTreeDataSortHeader *header;
664
665 header = _gtk_tree_data_list_get_header (header_list: priv->sort_list,
666 sort_column_id: priv->sort_column_id);
667
668 g_return_if_fail (header != NULL);
669 g_return_if_fail (header->func != NULL);
670
671 data->sort_func = header->func;
672 data->sort_data = header->data;
673 }
674 else
675 {
676 /* absolutely SHOULD NOT happen: */
677 g_return_if_fail (priv->default_sort_func != NULL);
678
679 data->sort_func = priv->default_sort_func;
680 data->sort_data = priv->default_sort_data;
681 }
682
683 if (level->parent_elt)
684 {
685 data->parent_path = gtk_tree_model_sort_elt_get_path (level: level->parent_level,
686 elt: level->parent_elt);
687 gtk_tree_path_append_index (path: data->parent_path, index_: 0);
688 }
689 else
690 {
691 data->parent_path = gtk_tree_path_new_first ();
692 }
693 data->parent_path_depth = gtk_tree_path_get_depth (path: data->parent_path);
694 data->parent_path_indices = gtk_tree_path_get_indices (path: data->parent_path);
695}
696
697static void
698free_sort_data (SortData *data)
699{
700 gtk_tree_path_free (path: data->parent_path);
701}
702
703static SortElt *
704lookup_elt_with_offset (GtkTreeModelSort *tree_model_sort,
705 SortLevel *level,
706 int offset,
707 GSequenceIter **ret_siter)
708{
709 GSequenceIter *siter, *end_siter;
710
711 /* FIXME: We have to do a search like this, because the sequence is not
712 * (always) sorted on offset order. Perhaps we should introduce a
713 * second sequence which is sorted on offset order.
714 */
715 end_siter = g_sequence_get_end_iter (seq: level->seq);
716 for (siter = g_sequence_get_begin_iter (seq: level->seq);
717 siter != end_siter;
718 siter = g_sequence_iter_next (iter: siter))
719 {
720 SortElt *elt = g_sequence_get (iter: siter);
721
722 if (elt->offset == offset)
723 break;
724 }
725
726 if (ret_siter)
727 *ret_siter = siter;
728
729 return GET_ELT (siter);
730}
731
732
733static void
734gtk_tree_model_sort_row_changed (GtkTreeModel *s_model,
735 GtkTreePath *start_s_path,
736 GtkTreeIter *start_s_iter,
737 gpointer data)
738{
739 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
740 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
741 GtkTreePath *path = NULL;
742 GtkTreeIter iter;
743 GtkTreeIter tmpiter;
744
745 SortElt *elt;
746 SortLevel *level;
747 SortData sort_data;
748
749 gboolean free_s_path = FALSE;
750
751 int index = 0, old_index;
752
753 g_return_if_fail (start_s_path != NULL || start_s_iter != NULL);
754
755 if (!start_s_path)
756 {
757 free_s_path = TRUE;
758 start_s_path = gtk_tree_model_get_path (tree_model: s_model, iter: start_s_iter);
759 }
760
761 path = gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort,
762 child_path: start_s_path,
763 FALSE);
764 if (!path)
765 {
766 if (free_s_path)
767 gtk_tree_path_free (path: start_s_path);
768 return;
769 }
770
771 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), iter: &iter, path);
772 gtk_tree_model_sort_ref_node (GTK_TREE_MODEL (data), iter: &iter);
773
774 level = iter.user_data;
775 elt = iter.user_data2;
776
777 if (g_sequence_get_length (seq: level->seq) < 2 ||
778 (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID &&
779 priv->default_sort_func == NO_SORT_FUNC))
780 {
781 if (free_s_path)
782 gtk_tree_path_free (path: start_s_path);
783
784 gtk_tree_model_row_changed (GTK_TREE_MODEL (data), path, iter: &iter);
785 gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (data), iter: &iter);
786
787 gtk_tree_path_free (path);
788
789 return;
790 }
791
792 if (GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
793 tmpiter = elt->iter;
794 else
795 gtk_tree_model_get_iter (tree_model: priv->child_model,
796 iter: &tmpiter, path: start_s_path);
797
798 old_index = g_sequence_iter_get_position (iter: elt->siter);
799
800 fill_sort_data (data: &sort_data, tree_model_sort, level);
801 g_sequence_sort_changed (iter: elt->siter,
802 cmp_func: gtk_tree_model_sort_compare_func,
803 cmp_data: &sort_data);
804 free_sort_data (data: &sort_data);
805
806 index = g_sequence_iter_get_position (iter: elt->siter);
807
808 /* Prepare the path for signal emission */
809 gtk_tree_path_up (path);
810 gtk_tree_path_append_index (path, index_: index);
811
812 gtk_tree_model_sort_increment_stamp (tree_model_sort);
813
814 /* if the item moved, then emit rows_reordered */
815 if (old_index != index)
816 {
817 int *new_order;
818 int j;
819
820 GtkTreePath *tmppath;
821
822 new_order = g_new (int, g_sequence_get_length (level->seq));
823
824 for (j = 0; j < g_sequence_get_length (seq: level->seq); j++)
825 {
826 if (index > old_index)
827 {
828 if (j == index)
829 new_order[j] = old_index;
830 else if (j >= old_index && j < index)
831 new_order[j] = j + 1;
832 else
833 new_order[j] = j;
834 }
835 else if (index < old_index)
836 {
837 if (j == index)
838 new_order[j] = old_index;
839 else if (j > index && j <= old_index)
840 new_order[j] = j - 1;
841 else
842 new_order[j] = j;
843 }
844 /* else? shouldn't really happen */
845 }
846
847 if (level->parent_elt)
848 {
849 iter.stamp = priv->stamp;
850 iter.user_data = level->parent_level;
851 iter.user_data2 = level->parent_elt;
852
853 tmppath = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model_sort), iter: &iter);
854
855 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_model_sort),
856 path: tmppath, iter: &iter, new_order);
857 }
858 else
859 {
860 /* toplevel */
861 tmppath = gtk_tree_path_new ();
862
863 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_model_sort), path: tmppath,
864 NULL, new_order);
865 }
866
867 gtk_tree_path_free (path: tmppath);
868 g_free (mem: new_order);
869 }
870
871 /* emit row_changed signal (at new location) */
872 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), iter: &iter, path);
873 gtk_tree_model_row_changed (GTK_TREE_MODEL (data), path, iter: &iter);
874 gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (data), iter: &iter);
875
876 gtk_tree_path_free (path);
877 if (free_s_path)
878 gtk_tree_path_free (path: start_s_path);
879}
880
881static void
882gtk_tree_model_sort_row_inserted (GtkTreeModel *s_model,
883 GtkTreePath *s_path,
884 GtkTreeIter *s_iter,
885 gpointer data)
886{
887 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
888 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
889 GtkTreePath *path;
890 GtkTreeIter iter;
891 GtkTreeIter real_s_iter;
892
893 int i = 0;
894
895 gboolean free_s_path = FALSE;
896
897 SortElt *elt;
898 SortLevel *level;
899 SortLevel *parent_level = NULL;
900
901 parent_level = level = SORT_LEVEL (priv->root);
902
903 g_return_if_fail (s_path != NULL || s_iter != NULL);
904
905 if (!s_path)
906 {
907 s_path = gtk_tree_model_get_path (tree_model: s_model, iter: s_iter);
908 free_s_path = TRUE;
909 }
910
911 if (!s_iter)
912 gtk_tree_model_get_iter (tree_model: s_model, iter: &real_s_iter, path: s_path);
913 else
914 real_s_iter = *s_iter;
915
916 if (!priv->root)
917 {
918 gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
919
920 /* the build level already put the inserted iter in the level,
921 so no need to handle this signal anymore */
922
923 goto done_and_submit;
924 }
925
926 /* find the parent level */
927 while (i < gtk_tree_path_get_depth (path: s_path) - 1)
928 {
929 if (!level)
930 {
931 /* level not yet build, we won't cover this signal */
932 goto done;
933 }
934
935 if (g_sequence_get_length (seq: level->seq) < gtk_tree_path_get_indices (path: s_path)[i])
936 {
937 g_warning ("%s: A node was inserted with a parent that's not in the tree.\n"
938 "This possibly means that a GtkTreeModel inserted a child node\n"
939 "before the parent was inserted.",
940 G_STRLOC);
941 goto done;
942 }
943
944 elt = lookup_elt_with_offset (tree_model_sort, level,
945 offset: gtk_tree_path_get_indices (path: s_path)[i],
946 NULL);
947
948 g_return_if_fail (elt != NULL);
949
950 if (!elt->children)
951 {
952 /* not covering this signal */
953 goto done;
954 }
955
956 level = elt->children;
957 parent_level = level;
958 i++;
959 }
960
961 if (!parent_level)
962 goto done;
963
964 if (level->ref_count == 0 && level != priv->root)
965 {
966 gtk_tree_model_sort_free_level (tree_model_sort, sort_level: level, TRUE);
967 goto done;
968 }
969
970 if (!gtk_tree_model_sort_insert_value (tree_model_sort,
971 level: parent_level,
972 s_path,
973 s_iter: &real_s_iter))
974 goto done;
975
976 done_and_submit:
977 path = gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort,
978 child_path: s_path,
979 FALSE);
980
981 if (!path)
982 return;
983
984 gtk_tree_model_sort_increment_stamp (tree_model_sort);
985
986 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), iter: &iter, path);
987 gtk_tree_model_row_inserted (GTK_TREE_MODEL (data), path, iter: &iter);
988 gtk_tree_path_free (path);
989
990 done:
991 if (free_s_path)
992 gtk_tree_path_free (path: s_path);
993
994 return;
995}
996
997static void
998gtk_tree_model_sort_row_has_child_toggled (GtkTreeModel *s_model,
999 GtkTreePath *s_path,
1000 GtkTreeIter *s_iter,
1001 gpointer data)
1002{
1003 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
1004 GtkTreePath *path;
1005 GtkTreeIter iter;
1006
1007 g_return_if_fail (s_path != NULL && s_iter != NULL);
1008
1009 path = gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort, child_path: s_path, FALSE);
1010 if (path == NULL)
1011 return;
1012
1013 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), iter: &iter, path);
1014 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data), path, iter: &iter);
1015
1016 gtk_tree_path_free (path);
1017}
1018
1019static void
1020gtk_tree_model_sort_row_deleted (GtkTreeModel *s_model,
1021 GtkTreePath *s_path,
1022 gpointer data)
1023{
1024 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
1025 GtkTreePath *path = NULL;
1026 SortElt *elt;
1027 SortLevel *level;
1028 GtkTreeIter iter;
1029 int offset;
1030
1031 g_return_if_fail (s_path != NULL);
1032
1033 path = gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort, child_path: s_path, FALSE);
1034 if (path == NULL)
1035 return;
1036
1037 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), iter: &iter, path);
1038
1039 level = SORT_LEVEL (iter.user_data);
1040 elt = SORT_ELT (iter.user_data2);
1041 offset = elt->offset;
1042
1043 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), iter: &iter, path);
1044
1045 while (elt->ref_count > 0)
1046 gtk_tree_model_sort_real_unref_node (GTK_TREE_MODEL (data), iter: &iter, FALSE);
1047
1048 /* If this node has children, we free the level (recursively) here
1049 * and specify that unref may not be used, because parent and its
1050 * children have been removed by now.
1051 */
1052 if (elt->children)
1053 gtk_tree_model_sort_free_level (tree_model_sort,
1054 sort_level: elt->children, FALSE);
1055
1056 if (level->ref_count == 0 && g_sequence_get_length (seq: level->seq) == 1)
1057 {
1058 gtk_tree_model_sort_increment_stamp (tree_model_sort);
1059 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1060 gtk_tree_path_free (path);
1061
1062 if (level == tree_model_sort->priv->root)
1063 {
1064 gtk_tree_model_sort_free_level (tree_model_sort,
1065 sort_level: tree_model_sort->priv->root,
1066 TRUE);
1067 tree_model_sort->priv->root = NULL;
1068 }
1069 return;
1070 }
1071
1072 g_sequence_remove (iter: elt->siter);
1073 elt = NULL;
1074
1075 /* The sequence is not ordered on offset, so we traverse the entire
1076 * sequence.
1077 */
1078 g_sequence_foreach (seq: level->seq, func: decrease_offset_iter,
1079 GINT_TO_POINTER (offset));
1080
1081 gtk_tree_model_sort_increment_stamp (tree_model_sort);
1082 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1083
1084 gtk_tree_path_free (path);
1085}
1086
1087static void
1088gtk_tree_model_sort_rows_reordered (GtkTreeModel *s_model,
1089 GtkTreePath *s_path,
1090 GtkTreeIter *s_iter,
1091 int *new_order,
1092 gpointer data)
1093{
1094 SortLevel *level;
1095 GtkTreeIter iter;
1096 GtkTreePath *path;
1097 int *tmp_array;
1098 int i, length;
1099 GSequenceIter *siter, *end_siter;
1100 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
1101 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1102
1103 g_return_if_fail (new_order != NULL);
1104
1105 if (s_path == NULL || gtk_tree_path_get_depth (path: s_path) == 0)
1106 {
1107 if (priv->root == NULL)
1108 return;
1109 path = gtk_tree_path_new ();
1110 level = SORT_LEVEL (priv->root);
1111 }
1112 else
1113 {
1114 SortElt *elt;
1115
1116 path = gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort, child_path: s_path, FALSE);
1117 if (path == NULL)
1118 return;
1119 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), iter: &iter, path);
1120
1121 elt = SORT_ELT (iter.user_data2);
1122
1123 if (!elt->children)
1124 {
1125 gtk_tree_path_free (path);
1126 return;
1127 }
1128
1129 level = elt->children;
1130 }
1131
1132 length = g_sequence_get_length (seq: level->seq);
1133 if (length < 2)
1134 {
1135 gtk_tree_path_free (path);
1136 return;
1137 }
1138
1139 tmp_array = g_new (int, length);
1140
1141 /* FIXME: I need to think about whether this can be done in a more
1142 * efficient way?
1143 */
1144 i = 0;
1145 end_siter = g_sequence_get_end_iter (seq: level->seq);
1146 for (siter = g_sequence_get_begin_iter (seq: level->seq);
1147 siter != end_siter;
1148 siter = g_sequence_iter_next (iter: siter))
1149 {
1150 int j;
1151 SortElt *elt = g_sequence_get (iter: siter);
1152
1153 for (j = 0; j < length; j++)
1154 {
1155 if (elt->offset == new_order[j])
1156 tmp_array[i] = j;
1157 }
1158
1159 i++;
1160 }
1161
1162 /* This loop cannot be merged with the above loop nest, because that
1163 * would introduce duplicate offsets.
1164 */
1165 i = 0;
1166 end_siter = g_sequence_get_end_iter (seq: level->seq);
1167 for (siter = g_sequence_get_begin_iter (seq: level->seq);
1168 siter != end_siter;
1169 siter = g_sequence_iter_next (iter: siter))
1170 {
1171 SortElt *elt = g_sequence_get (iter: siter);
1172
1173 elt->offset = tmp_array[i];
1174 i++;
1175 }
1176 g_free (mem: tmp_array);
1177
1178 if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID &&
1179 priv->default_sort_func == NO_SORT_FUNC)
1180 {
1181 gtk_tree_model_sort_sort_level (tree_model_sort, level,
1182 FALSE, FALSE);
1183 gtk_tree_model_sort_increment_stamp (tree_model_sort);
1184
1185 if (gtk_tree_path_get_depth (path))
1186 {
1187 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_sort),
1188 iter: &iter,
1189 path);
1190 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_model_sort),
1191 path, iter: &iter, new_order);
1192 }
1193 else
1194 {
1195 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_model_sort),
1196 path, NULL, new_order);
1197 }
1198 }
1199
1200 gtk_tree_path_free (path);
1201}
1202
1203/* Fulfill our model requirements */
1204static GtkTreeModelFlags
1205gtk_tree_model_sort_get_flags (GtkTreeModel *tree_model)
1206{
1207 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1208 GtkTreeModelFlags flags;
1209
1210 g_return_val_if_fail (tree_model_sort->priv->child_model != NULL, 0);
1211
1212 flags = gtk_tree_model_get_flags (tree_model: tree_model_sort->priv->child_model);
1213
1214 if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
1215 return GTK_TREE_MODEL_LIST_ONLY;
1216
1217 return 0;
1218}
1219
1220static int
1221gtk_tree_model_sort_get_n_columns (GtkTreeModel *tree_model)
1222{
1223 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1224
1225 if (tree_model_sort->priv->child_model == 0)
1226 return 0;
1227
1228 return gtk_tree_model_get_n_columns (tree_model: tree_model_sort->priv->child_model);
1229}
1230
1231static GType
1232gtk_tree_model_sort_get_column_type (GtkTreeModel *tree_model,
1233 int index)
1234{
1235 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1236
1237 g_return_val_if_fail (tree_model_sort->priv->child_model != NULL, G_TYPE_INVALID);
1238
1239 return gtk_tree_model_get_column_type (tree_model: tree_model_sort->priv->child_model, index_: index);
1240}
1241
1242static gboolean
1243gtk_tree_model_sort_get_iter (GtkTreeModel *tree_model,
1244 GtkTreeIter *iter,
1245 GtkTreePath *path)
1246{
1247 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1248 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1249 int *indices;
1250 SortElt *elt;
1251 SortLevel *level;
1252 int depth, i;
1253 GSequenceIter *siter;
1254
1255 g_return_val_if_fail (priv->child_model != NULL, FALSE);
1256
1257 indices = gtk_tree_path_get_indices (path);
1258
1259 if (priv->root == NULL)
1260 gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
1261 level = SORT_LEVEL (priv->root);
1262
1263 depth = gtk_tree_path_get_depth (path);
1264 if (depth == 0)
1265 {
1266 iter->stamp = 0;
1267 return FALSE;
1268 }
1269
1270 for (i = 0; i < depth - 1; i++)
1271 {
1272 if ((level == NULL) ||
1273 (indices[i] >= g_sequence_get_length (seq: level->seq)))
1274 {
1275 iter->stamp = 0;
1276 return FALSE;
1277 }
1278
1279 siter = g_sequence_get_iter_at_pos (seq: level->seq, pos: indices[i]);
1280 if (g_sequence_iter_is_end (iter: siter))
1281 {
1282 iter->stamp = 0;
1283 return FALSE;
1284 }
1285
1286 elt = GET_ELT (siter);
1287 g_assert (elt);
1288 if (elt->children == NULL)
1289 gtk_tree_model_sort_build_level (tree_model_sort, parent_level: level, parent_elt: elt);
1290
1291 level = elt->children;
1292 }
1293
1294 if (!level || indices[i] >= g_sequence_get_length (seq: level->seq))
1295 {
1296 iter->stamp = 0;
1297 return FALSE;
1298 }
1299
1300 iter->stamp = priv->stamp;
1301 iter->user_data = level;
1302
1303 siter = g_sequence_get_iter_at_pos (seq: level->seq, pos: indices[depth - 1]);
1304 if (g_sequence_iter_is_end (iter: siter))
1305 {
1306 iter->stamp = 0;
1307 return FALSE;
1308 }
1309 iter->user_data2 = GET_ELT (siter);
1310
1311 return TRUE;
1312}
1313
1314static GtkTreePath *
1315gtk_tree_model_sort_get_path (GtkTreeModel *tree_model,
1316 GtkTreeIter *iter)
1317{
1318 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1319 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1320 GtkTreePath *retval;
1321 SortLevel *level;
1322 SortElt *elt;
1323
1324 g_return_val_if_fail (priv->child_model != NULL, NULL);
1325 g_return_val_if_fail (priv->stamp == iter->stamp, NULL);
1326
1327 retval = gtk_tree_path_new ();
1328
1329 level = SORT_LEVEL (iter->user_data);
1330 elt = SORT_ELT (iter->user_data2);
1331
1332 while (level)
1333 {
1334 int index;
1335
1336 index = g_sequence_iter_get_position (iter: elt->siter);
1337 gtk_tree_path_prepend_index (path: retval, index_: index);
1338
1339 elt = level->parent_elt;
1340 level = level->parent_level;
1341 }
1342
1343 return retval;
1344}
1345
1346static void
1347gtk_tree_model_sort_get_value (GtkTreeModel *tree_model,
1348 GtkTreeIter *iter,
1349 int column,
1350 GValue *value)
1351{
1352 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1353 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1354 GtkTreeIter child_iter;
1355
1356 g_return_if_fail (priv->child_model != NULL);
1357 g_return_if_fail (VALID_ITER (iter, tree_model_sort));
1358
1359 GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
1360 gtk_tree_model_get_value (tree_model: priv->child_model,
1361 iter: &child_iter, column, value);
1362}
1363
1364static gboolean
1365gtk_tree_model_sort_iter_next (GtkTreeModel *tree_model,
1366 GtkTreeIter *iter)
1367{
1368 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1369 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1370 SortElt *elt;
1371 GSequenceIter *siter;
1372
1373 g_return_val_if_fail (priv->child_model != NULL, FALSE);
1374 g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);
1375
1376 elt = iter->user_data2;
1377
1378 siter = g_sequence_iter_next (iter: elt->siter);
1379 if (g_sequence_iter_is_end (iter: siter))
1380 {
1381 iter->stamp = 0;
1382 return FALSE;
1383 }
1384 iter->user_data2 = GET_ELT (siter);
1385
1386 return TRUE;
1387}
1388
1389static gboolean
1390gtk_tree_model_sort_iter_previous (GtkTreeModel *tree_model,
1391 GtkTreeIter *iter)
1392{
1393 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1394 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1395 SortElt *elt;
1396 GSequenceIter *siter;
1397
1398 g_return_val_if_fail (priv->child_model != NULL, FALSE);
1399 g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);
1400
1401 elt = iter->user_data2;
1402
1403 if (g_sequence_iter_is_begin (iter: elt->siter))
1404 {
1405 iter->stamp = 0;
1406 return FALSE;
1407 }
1408
1409 siter = g_sequence_iter_prev (iter: elt->siter);
1410 iter->user_data2 = GET_ELT (siter);
1411
1412 return TRUE;
1413}
1414
1415static gboolean
1416gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
1417 GtkTreeIter *iter,
1418 GtkTreeIter *parent)
1419{
1420 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1421 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1422 SortLevel *level;
1423
1424 iter->stamp = 0;
1425 g_return_val_if_fail (priv->child_model != NULL, FALSE);
1426 if (parent)
1427 g_return_val_if_fail (VALID_ITER (parent, tree_model_sort), FALSE);
1428
1429 if (parent == NULL)
1430 {
1431 if (priv->root == NULL)
1432 gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
1433 if (priv->root == NULL)
1434 return FALSE;
1435
1436 level = priv->root;
1437 iter->stamp = priv->stamp;
1438 iter->user_data = level;
1439 iter->user_data2 = g_sequence_get (iter: g_sequence_get_begin_iter (seq: level->seq));
1440 }
1441 else
1442 {
1443 SortElt *elt;
1444
1445 level = SORT_LEVEL (parent->user_data);
1446 elt = SORT_ELT (parent->user_data2);
1447
1448 if (elt->children == NULL)
1449 gtk_tree_model_sort_build_level (tree_model_sort, parent_level: level, parent_elt: elt);
1450
1451 if (elt->children == NULL)
1452 return FALSE;
1453
1454 iter->stamp = priv->stamp;
1455 iter->user_data = elt->children;
1456 iter->user_data2 = g_sequence_get (iter: g_sequence_get_begin_iter (seq: elt->children->seq));
1457 }
1458
1459 return TRUE;
1460}
1461
1462static gboolean
1463gtk_tree_model_sort_iter_has_child (GtkTreeModel *tree_model,
1464 GtkTreeIter *iter)
1465{
1466 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1467 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1468 GtkTreeIter child_iter;
1469
1470 g_return_val_if_fail (priv->child_model != NULL, FALSE);
1471 g_return_val_if_fail (VALID_ITER (iter, tree_model_sort), FALSE);
1472
1473 GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
1474
1475 return gtk_tree_model_iter_has_child (tree_model: priv->child_model, iter: &child_iter);
1476}
1477
1478static int
1479gtk_tree_model_sort_iter_n_children (GtkTreeModel *tree_model,
1480 GtkTreeIter *iter)
1481{
1482 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1483 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1484 GtkTreeIter child_iter;
1485
1486 g_return_val_if_fail (priv->child_model != NULL, 0);
1487 if (iter)
1488 g_return_val_if_fail (VALID_ITER (iter, tree_model_sort), 0);
1489
1490 if (iter == NULL)
1491 return gtk_tree_model_iter_n_children (tree_model: priv->child_model, NULL);
1492
1493 GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
1494
1495 return gtk_tree_model_iter_n_children (tree_model: priv->child_model, iter: &child_iter);
1496}
1497
1498static gboolean
1499gtk_tree_model_sort_iter_nth_child (GtkTreeModel *tree_model,
1500 GtkTreeIter *iter,
1501 GtkTreeIter *parent,
1502 int n)
1503{
1504 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1505 SortLevel *level;
1506 /* We have this for the iter == parent case */
1507 GtkTreeIter children;
1508
1509 if (parent)
1510 g_return_val_if_fail (VALID_ITER (parent, tree_model_sort), FALSE);
1511
1512 /* Use this instead of has_child to force us to build the level, if needed */
1513 if (gtk_tree_model_sort_iter_children (tree_model, iter: &children, parent) == FALSE)
1514 {
1515 iter->stamp = 0;
1516 return FALSE;
1517 }
1518
1519 level = children.user_data;
1520 if (n >= g_sequence_get_length (seq: level->seq))
1521 {
1522 iter->stamp = 0;
1523 return FALSE;
1524 }
1525
1526 iter->stamp = tree_model_sort->priv->stamp;
1527 iter->user_data = level;
1528 iter->user_data2 = g_sequence_get (iter: g_sequence_get_iter_at_pos (seq: level->seq, pos: n));
1529
1530 return TRUE;
1531}
1532
1533static gboolean
1534gtk_tree_model_sort_iter_parent (GtkTreeModel *tree_model,
1535 GtkTreeIter *iter,
1536 GtkTreeIter *child)
1537{
1538 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1539 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1540 SortLevel *level;
1541
1542 iter->stamp = 0;
1543 g_return_val_if_fail (priv->child_model != NULL, FALSE);
1544 g_return_val_if_fail (VALID_ITER (child, tree_model_sort), FALSE);
1545
1546 level = child->user_data;
1547
1548 if (level->parent_level)
1549 {
1550 iter->stamp = priv->stamp;
1551 iter->user_data = level->parent_level;
1552 iter->user_data2 = level->parent_elt;
1553
1554 return TRUE;
1555 }
1556 return FALSE;
1557}
1558
1559static void
1560gtk_tree_model_sort_ref_node (GtkTreeModel *tree_model,
1561 GtkTreeIter *iter)
1562{
1563 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1564 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1565 GtkTreeIter child_iter;
1566 SortLevel *level;
1567 SortElt *elt;
1568
1569 g_return_if_fail (priv->child_model != NULL);
1570 g_return_if_fail (VALID_ITER (iter, tree_model_sort));
1571
1572 GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
1573
1574 /* Reference the node in the child model */
1575 gtk_tree_model_ref_node (tree_model: priv->child_model, iter: &child_iter);
1576
1577 /* Increase the reference count of this element and its level */
1578 level = iter->user_data;
1579 elt = iter->user_data2;
1580
1581 elt->ref_count++;
1582 level->ref_count++;
1583
1584 if (level->ref_count == 1)
1585 {
1586 SortLevel *parent_level = level->parent_level;
1587 SortElt *parent_elt = level->parent_elt;
1588
1589 /* We were at zero -- time to decrement the zero_ref_count val */
1590 while (parent_level)
1591 {
1592 parent_elt->zero_ref_count--;
1593
1594 parent_elt = parent_level->parent_elt;
1595 parent_level = parent_level->parent_level;
1596 }
1597
1598 if (priv->root != level)
1599 priv->zero_ref_count--;
1600 }
1601}
1602
1603static void
1604gtk_tree_model_sort_real_unref_node (GtkTreeModel *tree_model,
1605 GtkTreeIter *iter,
1606 gboolean propagate_unref)
1607{
1608 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
1609 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1610 SortLevel *level;
1611 SortElt *elt;
1612
1613 g_return_if_fail (priv->child_model != NULL);
1614 g_return_if_fail (VALID_ITER (iter, tree_model_sort));
1615
1616 if (propagate_unref)
1617 {
1618 GtkTreeIter child_iter;
1619
1620 GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
1621 gtk_tree_model_unref_node (tree_model: priv->child_model, iter: &child_iter);
1622 }
1623
1624 level = iter->user_data;
1625 elt = iter->user_data2;
1626
1627 g_return_if_fail (elt->ref_count > 0);
1628
1629 elt->ref_count--;
1630 level->ref_count--;
1631
1632 if (level->ref_count == 0)
1633 {
1634 SortLevel *parent_level = level->parent_level;
1635 SortElt *parent_elt = level->parent_elt;
1636
1637 /* We are at zero -- time to increment the zero_ref_count val */
1638 while (parent_level)
1639 {
1640 parent_elt->zero_ref_count++;
1641
1642 parent_elt = parent_level->parent_elt;
1643 parent_level = parent_level->parent_level;
1644 }
1645
1646 if (priv->root != level)
1647 priv->zero_ref_count++;
1648 }
1649}
1650
1651static void
1652gtk_tree_model_sort_unref_node (GtkTreeModel *tree_model,
1653 GtkTreeIter *iter)
1654{
1655 gtk_tree_model_sort_real_unref_node (tree_model, iter, TRUE);
1656}
1657
1658/* Sortable interface */
1659static gboolean
1660gtk_tree_model_sort_get_sort_column_id (GtkTreeSortable *sortable,
1661 int *sort_column_id,
1662 GtkSortType *order)
1663{
1664 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
1665 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1666
1667 if (sort_column_id)
1668 *sort_column_id = priv->sort_column_id;
1669 if (order)
1670 *order = priv->order;
1671
1672 if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID ||
1673 priv->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
1674 return FALSE;
1675
1676 return TRUE;
1677}
1678
1679static void
1680gtk_tree_model_sort_set_sort_column_id (GtkTreeSortable *sortable,
1681 int sort_column_id,
1682 GtkSortType order)
1683{
1684 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
1685 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1686
1687 if (priv->sort_column_id == sort_column_id && priv->order == order)
1688 return;
1689
1690 if (sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
1691 {
1692 if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
1693 {
1694 GtkTreeDataSortHeader *header = NULL;
1695
1696 header = _gtk_tree_data_list_get_header (header_list: priv->sort_list,
1697 sort_column_id);
1698
1699 /* we want to make sure that we have a function */
1700 g_return_if_fail (header != NULL);
1701 g_return_if_fail (header->func != NULL);
1702 }
1703 else
1704 g_return_if_fail (priv->default_sort_func != NULL);
1705 }
1706
1707 priv->sort_column_id = sort_column_id;
1708 priv->order = order;
1709
1710 gtk_tree_sortable_sort_column_changed (sortable);
1711
1712 gtk_tree_model_sort_sort (tree_model_sort);
1713}
1714
1715static void
1716gtk_tree_model_sort_set_sort_func (GtkTreeSortable *sortable,
1717 int sort_column_id,
1718 GtkTreeIterCompareFunc func,
1719 gpointer data,
1720 GDestroyNotify destroy)
1721{
1722 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) sortable;
1723 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1724
1725 priv->sort_list = _gtk_tree_data_list_set_header (header_list: priv->sort_list,
1726 sort_column_id,
1727 func, data, destroy);
1728
1729 if (priv->sort_column_id == sort_column_id)
1730 gtk_tree_model_sort_sort (tree_model_sort);
1731}
1732
1733static void
1734gtk_tree_model_sort_set_default_sort_func (GtkTreeSortable *sortable,
1735 GtkTreeIterCompareFunc func,
1736 gpointer data,
1737 GDestroyNotify destroy)
1738{
1739 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
1740 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1741
1742 if (priv->default_sort_destroy)
1743 {
1744 GDestroyNotify d = priv->default_sort_destroy;
1745
1746 priv->default_sort_destroy = NULL;
1747 d (priv->default_sort_data);
1748 }
1749
1750 priv->default_sort_func = func;
1751 priv->default_sort_data = data;
1752 priv->default_sort_destroy = destroy;
1753
1754 if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
1755 gtk_tree_model_sort_sort (tree_model_sort);
1756}
1757
1758static gboolean
1759gtk_tree_model_sort_has_default_sort_func (GtkTreeSortable *sortable)
1760{
1761 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
1762
1763 return (tree_model_sort->priv->default_sort_func != NO_SORT_FUNC);
1764}
1765
1766/* DragSource interface */
1767static gboolean
1768gtk_tree_model_sort_row_draggable (GtkTreeDragSource *drag_source,
1769 GtkTreePath *path)
1770{
1771 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)drag_source;
1772 GtkTreePath *child_path;
1773 gboolean draggable;
1774
1775 child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort,
1776 sorted_path: path);
1777 draggable = gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (tree_model_sort->priv->child_model), path: child_path);
1778 gtk_tree_path_free (path: child_path);
1779
1780 return draggable;
1781}
1782
1783static GdkContentProvider *
1784gtk_tree_model_sort_drag_data_get (GtkTreeDragSource *drag_source,
1785 GtkTreePath *path)
1786{
1787 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)drag_source;
1788 GtkTreePath *child_path;
1789 GdkContentProvider *gotten;
1790
1791 child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort, sorted_path: path);
1792 gotten = gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (tree_model_sort->priv->child_model), path: child_path);
1793 gtk_tree_path_free (path: child_path);
1794
1795 return gotten;
1796}
1797
1798static gboolean
1799gtk_tree_model_sort_drag_data_delete (GtkTreeDragSource *drag_source,
1800 GtkTreePath *path)
1801{
1802 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)drag_source;
1803 GtkTreePath *child_path;
1804 gboolean deleted;
1805
1806 child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort, sorted_path: path);
1807 deleted = gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (tree_model_sort->priv->child_model), path: child_path);
1808 gtk_tree_path_free (path: child_path);
1809
1810 return deleted;
1811}
1812
1813/* sorting code - private */
1814static int
1815gtk_tree_model_sort_compare_func (gconstpointer a,
1816 gconstpointer b,
1817 gpointer user_data)
1818{
1819 SortData *data = (SortData *)user_data;
1820 GtkTreeModelSort *tree_model_sort = data->tree_model_sort;
1821 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1822 const SortElt *sa = a;
1823 const SortElt *sb = b;
1824
1825 GtkTreeIter iter_a, iter_b;
1826 int retval;
1827
1828 if (GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
1829 {
1830 iter_a = sa->iter;
1831 iter_b = sb->iter;
1832 }
1833 else
1834 {
1835 data->parent_path_indices [data->parent_path_depth-1] = sa->offset;
1836 gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->child_model), iter: &iter_a, path: data->parent_path);
1837 data->parent_path_indices [data->parent_path_depth-1] = sb->offset;
1838 gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->child_model), iter: &iter_b, path: data->parent_path);
1839 }
1840
1841 retval = (* data->sort_func) (GTK_TREE_MODEL (priv->child_model),
1842 &iter_a, &iter_b,
1843 data->sort_data);
1844
1845 if (priv->order == GTK_SORT_DESCENDING)
1846 {
1847 if (retval > 0)
1848 retval = -1;
1849 else if (retval < 0)
1850 retval = 1;
1851 }
1852
1853 return retval;
1854}
1855
1856static int
1857gtk_tree_model_sort_offset_compare_func (gconstpointer a,
1858 gconstpointer b,
1859 gpointer user_data)
1860{
1861 int retval;
1862
1863 const SortElt *sa = (SortElt *)a;
1864 const SortElt *sb = (SortElt *)b;
1865
1866 SortData *data = (SortData *)user_data;
1867
1868 if (sa->offset < sb->offset)
1869 retval = -1;
1870 else if (sa->offset > sb->offset)
1871 retval = 1;
1872 else
1873 retval = 0;
1874
1875 if (data->tree_model_sort->priv->order == GTK_SORT_DESCENDING)
1876 {
1877 if (retval > 0)
1878 retval = -1;
1879 else if (retval < 0)
1880 retval = 1;
1881 }
1882
1883 return retval;
1884}
1885
1886static void
1887gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
1888 SortLevel *level,
1889 gboolean recurse,
1890 gboolean emit_reordered)
1891{
1892 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
1893 int i;
1894 GSequenceIter *begin_siter, *end_siter, *siter;
1895 SortElt *begin_elt;
1896 int *new_order;
1897
1898 GtkTreeIter iter;
1899 GtkTreePath *path;
1900
1901 SortData data;
1902
1903 g_return_if_fail (level != NULL);
1904
1905 begin_siter = g_sequence_get_begin_iter (seq: level->seq);
1906 begin_elt = g_sequence_get (iter: begin_siter);
1907
1908 if (g_sequence_get_length (seq: level->seq) < 1 && !begin_elt->children)
1909 return;
1910
1911 iter.stamp = priv->stamp;
1912 iter.user_data = level;
1913 iter.user_data2 = begin_elt;
1914
1915 gtk_tree_model_sort_ref_node (GTK_TREE_MODEL (tree_model_sort), iter: &iter);
1916
1917 i = 0;
1918 end_siter = g_sequence_get_end_iter (seq: level->seq);
1919 for (siter = g_sequence_get_begin_iter (seq: level->seq);
1920 siter != end_siter;
1921 siter = g_sequence_iter_next (iter: siter))
1922 {
1923 SortElt *elt = g_sequence_get (iter: siter);
1924
1925 elt->old_index = i;
1926 i++;
1927 }
1928
1929 fill_sort_data (data: &data, tree_model_sort, level);
1930
1931 if (data.sort_func == NO_SORT_FUNC)
1932 g_sequence_sort (seq: level->seq, cmp_func: gtk_tree_model_sort_offset_compare_func,
1933 cmp_data: &data);
1934 else
1935 g_sequence_sort (seq: level->seq, cmp_func: gtk_tree_model_sort_compare_func, cmp_data: &data);
1936
1937 free_sort_data (data: &data);
1938
1939 new_order = g_new (int, g_sequence_get_length (level->seq));
1940
1941 i = 0;
1942 end_siter = g_sequence_get_end_iter (seq: level->seq);
1943 for (siter = g_sequence_get_begin_iter (seq: level->seq);
1944 siter != end_siter;
1945 siter = g_sequence_iter_next (iter: siter))
1946 {
1947 SortElt *elt = g_sequence_get (iter: siter);
1948
1949 new_order[i++] = elt->old_index;
1950 }
1951
1952 if (emit_reordered)
1953 {
1954 gtk_tree_model_sort_increment_stamp (tree_model_sort);
1955 if (level->parent_elt)
1956 {
1957 iter.stamp = priv->stamp;
1958 iter.user_data = level->parent_level;
1959 iter.user_data2 = level->parent_elt;
1960
1961 path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model_sort),
1962 iter: &iter);
1963
1964 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_model_sort), path,
1965 iter: &iter, new_order);
1966 }
1967 else
1968 {
1969 /* toplevel list */
1970 path = gtk_tree_path_new ();
1971 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_model_sort), path,
1972 NULL, new_order);
1973 }
1974
1975 gtk_tree_path_free (path);
1976 }
1977
1978 /* recurse, if possible */
1979 if (recurse)
1980 {
1981 end_siter = g_sequence_get_end_iter (seq: level->seq);
1982 for (siter = g_sequence_get_begin_iter (seq: level->seq);
1983 siter != end_siter;
1984 siter = g_sequence_iter_next (iter: siter))
1985 {
1986 SortElt *elt = g_sequence_get (iter: siter);
1987
1988 if (elt->children)
1989 gtk_tree_model_sort_sort_level (tree_model_sort,
1990 level: elt->children,
1991 TRUE, emit_reordered);
1992 }
1993 }
1994
1995 g_free (mem: new_order);
1996
1997 /* get the iter we referenced at the beginning of this function and
1998 * unref it again
1999 */
2000 iter.stamp = priv->stamp;
2001 iter.user_data = level;
2002 iter.user_data2 = begin_elt;
2003
2004 gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (tree_model_sort), iter: &iter);
2005}
2006
2007static void
2008gtk_tree_model_sort_sort (GtkTreeModelSort *tree_model_sort)
2009{
2010 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2011
2012 if (priv->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
2013 return;
2014
2015 if (!priv->root)
2016 return;
2017
2018 if (priv->sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
2019 {
2020 GtkTreeDataSortHeader *header = NULL;
2021
2022 header = _gtk_tree_data_list_get_header (header_list: priv->sort_list,
2023 sort_column_id: priv->sort_column_id);
2024
2025 /* we want to make sure that we have a function */
2026 g_return_if_fail (header != NULL);
2027 g_return_if_fail (header->func != NULL);
2028 }
2029 else
2030 g_return_if_fail (priv->default_sort_func != NULL);
2031
2032 gtk_tree_model_sort_sort_level (tree_model_sort, level: priv->root,
2033 TRUE, TRUE);
2034}
2035
2036/* signal helpers */
2037static gboolean
2038gtk_tree_model_sort_insert_value (GtkTreeModelSort *tree_model_sort,
2039 SortLevel *level,
2040 GtkTreePath *s_path,
2041 GtkTreeIter *s_iter)
2042{
2043 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2044 SortElt *elt;
2045 SortData data;
2046 int offset;
2047
2048 elt = sort_elt_new ();
2049
2050 offset = gtk_tree_path_get_indices (path: s_path)[gtk_tree_path_get_depth (path: s_path) - 1];
2051
2052 if (GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
2053 elt->iter = *s_iter;
2054 elt->offset = offset;
2055 elt->zero_ref_count = 0;
2056 elt->ref_count = 0;
2057 elt->children = NULL;
2058
2059 /* update all larger offsets */
2060 g_sequence_foreach (seq: level->seq, func: increase_offset_iter, GINT_TO_POINTER (offset));
2061
2062 fill_sort_data (data: &data, tree_model_sort, level);
2063
2064 if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID &&
2065 priv->default_sort_func == NO_SORT_FUNC)
2066 {
2067 elt->siter = g_sequence_insert_sorted (seq: level->seq, data: elt,
2068 cmp_func: gtk_tree_model_sort_offset_compare_func,
2069 cmp_data: &data);
2070 }
2071 else
2072 {
2073 elt->siter = g_sequence_insert_sorted (seq: level->seq, data: elt,
2074 cmp_func: gtk_tree_model_sort_compare_func,
2075 cmp_data: &data);
2076 }
2077
2078 free_sort_data (data: &data);
2079
2080 return TRUE;
2081}
2082
2083/* sort elt stuff */
2084static GtkTreePath *
2085gtk_tree_model_sort_elt_get_path (SortLevel *level,
2086 SortElt *elt)
2087{
2088 SortLevel *walker = level;
2089 SortElt *walker2 = elt;
2090 GtkTreePath *path;
2091
2092 g_return_val_if_fail (level != NULL, NULL);
2093 g_return_val_if_fail (elt != NULL, NULL);
2094
2095 path = gtk_tree_path_new ();
2096
2097 while (walker)
2098 {
2099 gtk_tree_path_prepend_index (path, index_: walker2->offset);
2100
2101 if (!walker->parent_level)
2102 break;
2103
2104 walker2 = walker->parent_elt;
2105 walker = walker->parent_level;
2106 }
2107
2108 return path;
2109}
2110
2111/**
2112 * gtk_tree_model_sort_set_model:
2113 * @tree_model_sort: The `GtkTreeModelSort`.
2114 * @child_model: (nullable): A `GtkTreeModel`
2115 *
2116 * Sets the model of @tree_model_sort to be @model. If @model is %NULL,
2117 * then the old model is unset. The sort function is unset as a result
2118 * of this call. The model will be in an unsorted state until a sort
2119 * function is set.
2120 **/
2121static void
2122gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
2123 GtkTreeModel *child_model)
2124{
2125 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2126
2127 if (child_model)
2128 g_object_ref (child_model);
2129
2130 if (priv->child_model)
2131 {
2132 g_signal_handler_disconnect (instance: priv->child_model,
2133 handler_id: priv->changed_id);
2134 g_signal_handler_disconnect (instance: priv->child_model,
2135 handler_id: priv->inserted_id);
2136 g_signal_handler_disconnect (instance: priv->child_model,
2137 handler_id: priv->has_child_toggled_id);
2138 g_signal_handler_disconnect (instance: priv->child_model,
2139 handler_id: priv->deleted_id);
2140 g_signal_handler_disconnect (instance: priv->child_model,
2141 handler_id: priv->reordered_id);
2142
2143 /* reset our state */
2144 if (priv->root)
2145 gtk_tree_model_sort_free_level (tree_model_sort, sort_level: priv->root, TRUE);
2146 priv->root = NULL;
2147 _gtk_tree_data_list_header_free (header_list: priv->sort_list);
2148 priv->sort_list = NULL;
2149 g_object_unref (object: priv->child_model);
2150 }
2151
2152 priv->child_model = child_model;
2153
2154 if (child_model)
2155 {
2156 GType *types;
2157 int i, n_columns;
2158
2159 priv->changed_id =
2160 g_signal_connect (child_model, "row-changed",
2161 G_CALLBACK (gtk_tree_model_sort_row_changed),
2162 tree_model_sort);
2163 priv->inserted_id =
2164 g_signal_connect (child_model, "row-inserted",
2165 G_CALLBACK (gtk_tree_model_sort_row_inserted),
2166 tree_model_sort);
2167 priv->has_child_toggled_id =
2168 g_signal_connect (child_model, "row-has-child-toggled",
2169 G_CALLBACK (gtk_tree_model_sort_row_has_child_toggled),
2170 tree_model_sort);
2171 priv->deleted_id =
2172 g_signal_connect (child_model, "row-deleted",
2173 G_CALLBACK (gtk_tree_model_sort_row_deleted),
2174 tree_model_sort);
2175 priv->reordered_id =
2176 g_signal_connect (child_model, "rows-reordered",
2177 G_CALLBACK (gtk_tree_model_sort_rows_reordered),
2178 tree_model_sort);
2179
2180 priv->child_flags = gtk_tree_model_get_flags (tree_model: child_model);
2181 n_columns = gtk_tree_model_get_n_columns (tree_model: child_model);
2182
2183 types = g_new (GType, n_columns);
2184 for (i = 0; i < n_columns; i++)
2185 types[i] = gtk_tree_model_get_column_type (tree_model: child_model, index_: i);
2186
2187 priv->sort_list = _gtk_tree_data_list_header_new (n_columns, types);
2188 g_free (mem: types);
2189
2190 priv->default_sort_func = NO_SORT_FUNC;
2191 priv->stamp = g_random_int ();
2192 }
2193}
2194
2195/**
2196 * gtk_tree_model_sort_get_model:
2197 * @tree_model: a `GtkTreeModelSort`
2198 *
2199 * Returns the model the `GtkTreeModelSort` is sorting.
2200 *
2201 * Returns: (transfer none): the "child model" being sorted
2202 **/
2203GtkTreeModel *
2204gtk_tree_model_sort_get_model (GtkTreeModelSort *tree_model)
2205{
2206 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), NULL);
2207
2208 return tree_model->priv->child_model;
2209}
2210
2211
2212static GtkTreePath *
2213gtk_real_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_model_sort,
2214 GtkTreePath *child_path,
2215 gboolean build_levels)
2216{
2217 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2218 int *child_indices;
2219 GtkTreePath *retval;
2220 SortLevel *level;
2221 int i;
2222
2223 g_return_val_if_fail (priv->child_model != NULL, NULL);
2224 g_return_val_if_fail (child_path != NULL, NULL);
2225
2226 retval = gtk_tree_path_new ();
2227 child_indices = gtk_tree_path_get_indices (path: child_path);
2228
2229 if (priv->root == NULL && build_levels)
2230 gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
2231 level = SORT_LEVEL (priv->root);
2232
2233 for (i = 0; i < gtk_tree_path_get_depth (path: child_path); i++)
2234 {
2235 SortElt *tmp;
2236 GSequenceIter *siter;
2237 gboolean found_child = FALSE;
2238
2239 if (!level)
2240 {
2241 gtk_tree_path_free (path: retval);
2242 return NULL;
2243 }
2244
2245 if (child_indices[i] >= g_sequence_get_length (seq: level->seq))
2246 {
2247 gtk_tree_path_free (path: retval);
2248 return NULL;
2249 }
2250 tmp = lookup_elt_with_offset (tree_model_sort, level,
2251 offset: child_indices[i], ret_siter: &siter);
2252 if (tmp)
2253 {
2254 gtk_tree_path_append_index (path: retval, index_: g_sequence_iter_get_position (iter: siter));
2255 if (tmp->children == NULL && build_levels)
2256 gtk_tree_model_sort_build_level (tree_model_sort, parent_level: level, parent_elt: tmp);
2257
2258 level = tmp->children;
2259 found_child = TRUE;
2260 }
2261
2262 if (! found_child)
2263 {
2264 gtk_tree_path_free (path: retval);
2265 return NULL;
2266 }
2267 }
2268
2269 return retval;
2270}
2271
2272
2273/**
2274 * gtk_tree_model_sort_convert_child_path_to_path:
2275 * @tree_model_sort: A `GtkTreeModelSort`
2276 * @child_path: A `GtkTreePath` to convert
2277 *
2278 * Converts @child_path to a path relative to @tree_model_sort. That is,
2279 * @child_path points to a path in the child model. The returned path will
2280 * point to the same row in the sorted model. If @child_path isn’t a valid
2281 * path on the child model, then %NULL is returned.
2282 *
2283 * Returns: (nullable) (transfer full): A newly allocated `GtkTreePath`
2284 **/
2285GtkTreePath *
2286gtk_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_model_sort,
2287 GtkTreePath *child_path)
2288{
2289 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), NULL);
2290 g_return_val_if_fail (tree_model_sort->priv->child_model != NULL, NULL);
2291 g_return_val_if_fail (child_path != NULL, NULL);
2292
2293 return gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort, child_path, TRUE);
2294}
2295
2296/**
2297 * gtk_tree_model_sort_convert_child_iter_to_iter:
2298 * @tree_model_sort: A `GtkTreeModelSort`
2299 * @sort_iter: (out): An uninitialized `GtkTreeIter`
2300 * @child_iter: A valid `GtkTreeIter` pointing to a row on the child model
2301 *
2302 * Sets @sort_iter to point to the row in @tree_model_sort that corresponds to
2303 * the row pointed at by @child_iter. If @sort_iter was not set, %FALSE
2304 * is returned. Note: a boolean is only returned since 2.14.
2305 *
2306 * Returns: %TRUE, if @sort_iter was set, i.e. if @sort_iter is a
2307 * valid iterator pointer to a visible row in the child model.
2308 **/
2309gboolean
2310gtk_tree_model_sort_convert_child_iter_to_iter (GtkTreeModelSort *tree_model_sort,
2311 GtkTreeIter *sort_iter,
2312 GtkTreeIter *child_iter)
2313{
2314 gboolean ret;
2315 GtkTreePath *child_path, *path;
2316 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2317
2318 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), FALSE);
2319 g_return_val_if_fail (priv->child_model != NULL, FALSE);
2320 g_return_val_if_fail (sort_iter != NULL, FALSE);
2321 g_return_val_if_fail (child_iter != NULL, FALSE);
2322 g_return_val_if_fail (sort_iter != child_iter, FALSE);
2323
2324 sort_iter->stamp = 0;
2325
2326 child_path = gtk_tree_model_get_path (tree_model: priv->child_model, iter: child_iter);
2327 g_return_val_if_fail (child_path != NULL, FALSE);
2328
2329 path = gtk_tree_model_sort_convert_child_path_to_path (tree_model_sort, child_path);
2330 gtk_tree_path_free (path: child_path);
2331
2332 if (!path)
2333 {
2334 g_warning ("%s: The conversion of the child path to a GtkTreeModel sort path failed", G_STRLOC);
2335 return FALSE;
2336 }
2337
2338 ret = gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_sort),
2339 iter: sort_iter, path);
2340 gtk_tree_path_free (path);
2341
2342 return ret;
2343}
2344
2345/**
2346 * gtk_tree_model_sort_convert_path_to_child_path:
2347 * @tree_model_sort: A `GtkTreeModelSort`
2348 * @sorted_path: A `GtkTreePath` to convert
2349 *
2350 * Converts @sorted_path to a path on the child model of @tree_model_sort.
2351 * That is, @sorted_path points to a location in @tree_model_sort. The
2352 * returned path will point to the same location in the model not being
2353 * sorted. If @sorted_path does not point to a location in the child model,
2354 * %NULL is returned.
2355 *
2356 * Returns: (nullable) (transfer full): A newly allocated `GtkTreePath`
2357 **/
2358GtkTreePath *
2359gtk_tree_model_sort_convert_path_to_child_path (GtkTreeModelSort *tree_model_sort,
2360 GtkTreePath *sorted_path)
2361{
2362 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2363 int *sorted_indices;
2364 GtkTreePath *retval;
2365 SortLevel *level;
2366 int i;
2367
2368 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), NULL);
2369 g_return_val_if_fail (priv->child_model != NULL, NULL);
2370 g_return_val_if_fail (sorted_path != NULL, NULL);
2371
2372 retval = gtk_tree_path_new ();
2373 sorted_indices = gtk_tree_path_get_indices (path: sorted_path);
2374 if (priv->root == NULL)
2375 gtk_tree_model_sort_build_level (tree_model_sort, NULL, NULL);
2376 level = SORT_LEVEL (priv->root);
2377
2378 for (i = 0; i < gtk_tree_path_get_depth (path: sorted_path); i++)
2379 {
2380 SortElt *elt = NULL;
2381 GSequenceIter *siter;
2382
2383 if ((level == NULL) ||
2384 (g_sequence_get_length (seq: level->seq) <= sorted_indices[i]))
2385 {
2386 gtk_tree_path_free (path: retval);
2387 return NULL;
2388 }
2389
2390 siter = g_sequence_get_iter_at_pos (seq: level->seq, pos: sorted_indices[i]);
2391 if (g_sequence_iter_is_end (iter: siter))
2392 {
2393 gtk_tree_path_free (path: retval);
2394 return NULL;
2395 }
2396
2397 elt = GET_ELT (siter);
2398 g_assert (elt);
2399 if (elt->children == NULL)
2400 gtk_tree_model_sort_build_level (tree_model_sort, parent_level: level, parent_elt: elt);
2401
2402 if (level == NULL)
2403 {
2404 gtk_tree_path_free (path: retval);
2405 break;
2406 }
2407
2408 gtk_tree_path_append_index (path: retval, index_: elt->offset);
2409 level = elt->children;
2410 }
2411
2412 return retval;
2413}
2414
2415/**
2416 * gtk_tree_model_sort_convert_iter_to_child_iter:
2417 * @tree_model_sort: A `GtkTreeModelSort`
2418 * @child_iter: (out): An uninitialized `GtkTreeIter`
2419 * @sorted_iter: A valid `GtkTreeIter` pointing to a row on @tree_model_sort.
2420 *
2421 * Sets @child_iter to point to the row pointed to by @sorted_iter.
2422 **/
2423void
2424gtk_tree_model_sort_convert_iter_to_child_iter (GtkTreeModelSort *tree_model_sort,
2425 GtkTreeIter *child_iter,
2426 GtkTreeIter *sorted_iter)
2427{
2428 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2429 g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
2430 g_return_if_fail (priv->child_model != NULL);
2431 g_return_if_fail (child_iter != NULL);
2432 g_return_if_fail (VALID_ITER (sorted_iter, tree_model_sort));
2433 g_return_if_fail (sorted_iter != child_iter);
2434
2435 if (GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
2436 {
2437 *child_iter = SORT_ELT (sorted_iter->user_data2)->iter;
2438 }
2439 else
2440 {
2441 GtkTreePath *path;
2442 gboolean valid = FALSE;
2443
2444 path = gtk_tree_model_sort_elt_get_path (level: sorted_iter->user_data,
2445 elt: sorted_iter->user_data2);
2446 valid = gtk_tree_model_get_iter (tree_model: priv->child_model, iter: child_iter, path);
2447 gtk_tree_path_free (path);
2448
2449 g_return_if_fail (valid == TRUE);
2450 }
2451}
2452
2453static void
2454gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
2455 SortLevel *parent_level,
2456 SortElt *parent_elt)
2457{
2458 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2459 GtkTreeIter iter;
2460 SortLevel *new_level;
2461 int length = 0;
2462 int i;
2463
2464 g_assert (priv->child_model != NULL);
2465
2466 if (parent_level == NULL)
2467 {
2468 if (gtk_tree_model_get_iter_first (tree_model: priv->child_model, iter: &iter) == FALSE)
2469 return;
2470 length = gtk_tree_model_iter_n_children (tree_model: priv->child_model, NULL);
2471 }
2472 else
2473 {
2474 GtkTreeIter parent_iter;
2475 GtkTreeIter child_parent_iter;
2476
2477 parent_iter.stamp = priv->stamp;
2478 parent_iter.user_data = parent_level;
2479 parent_iter.user_data2 = parent_elt;
2480
2481 gtk_tree_model_sort_convert_iter_to_child_iter (tree_model_sort,
2482 child_iter: &child_parent_iter,
2483 sorted_iter: &parent_iter);
2484 if (gtk_tree_model_iter_children (tree_model: priv->child_model,
2485 iter: &iter,
2486 parent: &child_parent_iter) == FALSE)
2487 return;
2488
2489 /* stamp may have changed */
2490 gtk_tree_model_sort_convert_iter_to_child_iter (tree_model_sort,
2491 child_iter: &child_parent_iter,
2492 sorted_iter: &parent_iter);
2493
2494 length = gtk_tree_model_iter_n_children (tree_model: priv->child_model, iter: &child_parent_iter);
2495
2496 gtk_tree_model_sort_ref_node (GTK_TREE_MODEL (tree_model_sort),
2497 iter: &parent_iter);
2498 }
2499
2500 g_return_if_fail (length > 0);
2501
2502 new_level = g_new (SortLevel, 1);
2503 new_level->seq = g_sequence_new (data_destroy: sort_elt_free);
2504 new_level->ref_count = 0;
2505 new_level->parent_level = parent_level;
2506 new_level->parent_elt = parent_elt;
2507
2508 if (parent_elt)
2509 parent_elt->children = new_level;
2510 else
2511 priv->root = new_level;
2512
2513 /* increase the count of zero ref_counts.*/
2514 while (parent_level)
2515 {
2516 parent_elt->zero_ref_count++;
2517
2518 parent_elt = parent_level->parent_elt;
2519 parent_level = parent_level->parent_level;
2520 }
2521
2522 if (new_level != priv->root)
2523 priv->zero_ref_count++;
2524
2525 for (i = 0; i < length; i++)
2526 {
2527 SortElt *sort_elt;
2528
2529 sort_elt = sort_elt_new ();
2530 sort_elt->offset = i;
2531 sort_elt->zero_ref_count = 0;
2532 sort_elt->ref_count = 0;
2533 sort_elt->children = NULL;
2534
2535 if (GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
2536 {
2537 sort_elt->iter = iter;
2538 if (gtk_tree_model_iter_next (tree_model: priv->child_model, iter: &iter) == FALSE &&
2539 i < length - 1)
2540 {
2541 if (parent_level)
2542 {
2543 GtkTreePath *level;
2544 char *str;
2545
2546 level = gtk_tree_model_sort_elt_get_path (level: parent_level,
2547 elt: parent_elt);
2548 str = gtk_tree_path_to_string (path: level);
2549 gtk_tree_path_free (path: level);
2550
2551 g_warning ("%s: There is a discrepancy between the sort model "
2552 "and the child model. The child model is "
2553 "advertising a wrong length for level %s:.",
2554 G_STRLOC, str);
2555 g_free (mem: str);
2556 }
2557 else
2558 {
2559 g_warning ("%s: There is a discrepancy between the sort model "
2560 "and the child model. The child model is "
2561 "advertising a wrong length for the root level.",
2562 G_STRLOC);
2563 }
2564
2565 return;
2566 }
2567 }
2568
2569 sort_elt->siter = g_sequence_append (seq: new_level->seq, data: sort_elt);
2570 }
2571
2572 /* sort level */
2573 gtk_tree_model_sort_sort_level (tree_model_sort, level: new_level,
2574 FALSE, FALSE);
2575}
2576
2577static void
2578gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
2579 SortLevel *sort_level,
2580 gboolean unref)
2581{
2582 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2583 GSequenceIter *siter;
2584 GSequenceIter *end_siter;
2585
2586 g_assert (sort_level);
2587
2588 end_siter = g_sequence_get_end_iter (seq: sort_level->seq);
2589 for (siter = g_sequence_get_begin_iter (seq: sort_level->seq);
2590 siter != end_siter;
2591 siter = g_sequence_iter_next (iter: siter))
2592 {
2593 SortElt *elt = g_sequence_get (iter: siter);
2594
2595 if (elt->children)
2596 gtk_tree_model_sort_free_level (tree_model_sort,
2597 sort_level: elt->children, unref);
2598 }
2599
2600 if (sort_level->ref_count == 0)
2601 {
2602 SortLevel *parent_level = sort_level->parent_level;
2603 SortElt *parent_elt = sort_level->parent_elt;
2604
2605 while (parent_level)
2606 {
2607 parent_elt->zero_ref_count--;
2608
2609 parent_elt = parent_level->parent_elt;
2610 parent_level = parent_level->parent_level;
2611 }
2612
2613 if (sort_level != priv->root)
2614 priv->zero_ref_count--;
2615 }
2616
2617 if (sort_level->parent_elt)
2618 {
2619 if (unref)
2620 {
2621 GtkTreeIter parent_iter;
2622
2623 parent_iter.stamp = tree_model_sort->priv->stamp;
2624 parent_iter.user_data = sort_level->parent_level;
2625 parent_iter.user_data2 = sort_level->parent_elt;
2626
2627 gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (tree_model_sort),
2628 iter: &parent_iter);
2629 }
2630
2631 sort_level->parent_elt->children = NULL;
2632 }
2633 else
2634 priv->root = NULL;
2635
2636 g_sequence_free (seq: sort_level->seq);
2637 sort_level->seq = NULL;
2638
2639 g_free (mem: sort_level);
2640 sort_level = NULL;
2641}
2642
2643static void
2644gtk_tree_model_sort_increment_stamp (GtkTreeModelSort *tree_model_sort)
2645{
2646 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2647
2648 do
2649 {
2650 priv->stamp++;
2651 }
2652 while (priv->stamp == 0);
2653
2654 gtk_tree_model_sort_clear_cache (tree_model_sort);
2655}
2656
2657static void
2658gtk_tree_model_sort_clear_cache_helper_iter (gpointer data,
2659 gpointer user_data)
2660{
2661 GtkTreeModelSort *tree_model_sort = user_data;
2662 SortElt *elt = data;
2663
2664 if (elt->zero_ref_count > 0)
2665 gtk_tree_model_sort_clear_cache_helper (tree_model_sort, level: elt->children);
2666}
2667
2668static void
2669gtk_tree_model_sort_clear_cache_helper (GtkTreeModelSort *tree_model_sort,
2670 SortLevel *level)
2671{
2672 g_assert (level != NULL);
2673
2674 g_sequence_foreach (seq: level->seq, func: gtk_tree_model_sort_clear_cache_helper_iter,
2675 user_data: tree_model_sort);
2676
2677 if (level->ref_count == 0 && level != tree_model_sort->priv->root)
2678 gtk_tree_model_sort_free_level (tree_model_sort, sort_level: level, TRUE);
2679}
2680
2681/**
2682 * gtk_tree_model_sort_reset_default_sort_func:
2683 * @tree_model_sort: A `GtkTreeModelSort`
2684 *
2685 * This resets the default sort function to be in the “unsorted” state. That
2686 * is, it is in the same order as the child model. It will re-sort the model
2687 * to be in the same order as the child model only if the `GtkTreeModelSort`
2688 * is in “unsorted” state.
2689 **/
2690void
2691gtk_tree_model_sort_reset_default_sort_func (GtkTreeModelSort *tree_model_sort)
2692{
2693 GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
2694
2695 g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
2696
2697 if (priv->default_sort_destroy)
2698 {
2699 GDestroyNotify d = priv->default_sort_destroy;
2700
2701 priv->default_sort_destroy = NULL;
2702 d (priv->default_sort_data);
2703 }
2704
2705 priv->default_sort_func = NO_SORT_FUNC;
2706 priv->default_sort_data = NULL;
2707 priv->default_sort_destroy = NULL;
2708
2709 if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
2710 gtk_tree_model_sort_sort (tree_model_sort);
2711 priv->sort_column_id = GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID;
2712}
2713
2714/**
2715 * gtk_tree_model_sort_clear_cache:
2716 * @tree_model_sort: A `GtkTreeModelSort`
2717 *
2718 * This function should almost never be called. It clears the @tree_model_sort
2719 * of any cached iterators that haven’t been reffed with
2720 * gtk_tree_model_ref_node(). This might be useful if the child model being
2721 * sorted is static (and doesn’t change often) and there has been a lot of
2722 * unreffed access to nodes. As a side effect of this function, all unreffed
2723 * iters will be invalid.
2724 **/
2725void
2726gtk_tree_model_sort_clear_cache (GtkTreeModelSort *tree_model_sort)
2727{
2728 g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
2729
2730 if (tree_model_sort->priv->zero_ref_count > 0)
2731 gtk_tree_model_sort_clear_cache_helper (tree_model_sort, level: (SortLevel *)tree_model_sort->priv->root);
2732}
2733
2734static gboolean
2735gtk_tree_model_sort_iter_is_valid_helper (GtkTreeIter *iter,
2736 SortLevel *level)
2737{
2738 GSequenceIter *siter;
2739 GSequenceIter *end_siter;
2740
2741 end_siter = g_sequence_get_end_iter (seq: level->seq);
2742 for (siter = g_sequence_get_begin_iter (seq: level->seq);
2743 siter != end_siter; siter = g_sequence_iter_next (iter: siter))
2744 {
2745 SortElt *elt = g_sequence_get (iter: siter);
2746
2747 if (iter->user_data == level && iter->user_data2 == elt)
2748 return TRUE;
2749
2750 if (elt->children)
2751 if (gtk_tree_model_sort_iter_is_valid_helper (iter, level: elt->children))
2752 return TRUE;
2753 }
2754
2755 return FALSE;
2756}
2757
2758/**
2759 * gtk_tree_model_sort_iter_is_valid:
2760 * @tree_model_sort: A `GtkTreeModelSort`.
2761 * @iter: A `GtkTreeIter`
2762 *
2763 * > This function is slow. Only use it for debugging and/or testing
2764 * > purposes.
2765 *
2766 * Checks if the given iter is a valid iter for this `GtkTreeModelSort`.
2767 *
2768 * Returns: %TRUE if the iter is valid, %FALSE if the iter is invalid.
2769 **/
2770gboolean
2771gtk_tree_model_sort_iter_is_valid (GtkTreeModelSort *tree_model_sort,
2772 GtkTreeIter *iter)
2773{
2774 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), FALSE);
2775 g_return_val_if_fail (iter != NULL, FALSE);
2776
2777 if (!VALID_ITER (iter, tree_model_sort))
2778 return FALSE;
2779
2780 return gtk_tree_model_sort_iter_is_valid_helper (iter,
2781 level: tree_model_sort->priv->root);
2782}
2783

source code of gtk/gtk/gtktreemodelsort.c