]> Pileus Git - ~andy/gtk/blob - gtk/gtktreemodel.c
Merge branch 'gdk-backend-wayland'
[~andy/gtk] / gtk / gtktreemodel.c
1 /* gtktreemodel.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21 #include <stdlib.h>
22 #include <string.h>
23 #include <glib.h>
24 #include <glib/gprintf.h>
25 #include <gobject/gvaluecollector.h>
26 #include "gtktreemodel.h"
27 #include "gtktreeview.h"
28 #include "gtktreeprivate.h"
29 #include "gtkmarshalers.h"
30 #include "gtkintl.h"
31
32 /**
33  * SECTION:gtktreemodel
34  * @Title: GtkTreeModel
35  * @Short_description: The tree interface used by GtkTreeView
36  * @See_also: #GtkTreeView, #GtkTreeStore, #GtkListStore,
37  *     <link linkend="gtk-GtkTreeView-drag-and-drop">GtkTreeDnd</link>,
38  *     #GtkTreeSortable
39  *
40  * The #GtkTreeModel interface defines a generic tree interface for
41  * use by the #GtkTreeView widget. It is an abstract interface, and
42  * is designed to be usable with any appropriate data structure. The
43  * programmer just has to implement this interface on their own data
44  * type for it to be viewable by a #GtkTreeView widget.
45  *
46  * The model is represented as a hierarchical tree of strongly-typed,
47  * columned data. In other words, the model can be seen as a tree where
48  * every node has different values depending on which column is being
49  * queried. The type of data found in a column is determined by using
50  * the GType system (ie. #G_TYPE_INT, #GTK_TYPE_BUTTON, #G_TYPE_POINTER,
51  * etc). The types are homogeneous per column across all nodes. It is
52  * important to note that this interface only provides a way of examining
53  * a model and observing changes. The implementation of each individual
54  * model decides how and if changes are made.
55  *
56  * In order to make life simpler for programmers who do not need to
57  * write their own specialized model, two generic models are provided
58  * &mdash; the #GtkTreeStore and the #GtkListStore. To use these, the
59  * developer simply pushes data into these models as necessary. These
60  * models provide the data structure as well as all appropriate tree
61  * interfaces. As a result, implementing drag and drop, sorting, and
62  * storing data is trivial. For the vast majority of trees and lists,
63  * these two models are sufficient.
64  *
65  * Models are accessed on a node/column level of granularity. One can
66  * query for the value of a model at a certain node and a certain
67  * column on that node. There are two structures used to reference
68  * a particular node in a model. They are the #GtkTreePath and the
69  * #GtkTreeIter<footnote><para>Here, <abbrev>iter</abbrev> is short
70  * for <quote>iterator</quote></para></footnote>. Most of the interface
71  * consists of operations on a #GtkTreeIter.
72  *
73  * A path is essentially a potential node. It is a location on a model
74  * that may or may not actually correspond to a node on a specific
75  * model. The #GtkTreePath struct can be converted into either an
76  * array of unsigned integers or a string. The string form is a list
77  * of numbers separated by a colon. Each number refers to the offset
78  * at that level. Thus, the path <quote>0</quote> refers to the root
79  * node and the path <quote>2:4</quote> refers to the fifth child of
80  * the third node.
81  *
82  * By contrast, a #GtkTreeIter is a reference to a specific node on
83  * a specific model. It is a generic struct with an integer and three
84  * generic pointers. These are filled in by the model in a model-specific
85  * way. One can convert a path to an iterator by calling
86  * gtk_tree_model_get_iter(). These iterators are the primary way
87  * of accessing a model and are similar to the iterators used by
88  * #GtkTextBuffer. They are generally statically allocated on the
89  * stack and only used for a short time. The model interface defines
90  * a set of operations using them for navigating the model.
91  *
92  * It is expected that models fill in the iterator with private data.
93  * For example, the #GtkListStore model, which is internally a simple
94  * linked list, stores a list node in one of the pointers. The
95  * #GtkTreeModelSort stores an array and an offset in two of the
96  * pointers. Additionally, there is an integer field. This field is
97  * generally filled with a unique stamp per model. This stamp is for
98  * catching errors resulting from using invalid iterators with a model.
99  *
100  * The lifecycle of an iterator can be a little confusing at first.
101  * Iterators are expected to always be valid for as long as the model
102  * is unchanged (and doesn't emit a signal). The model is considered
103  * to own all outstanding iterators and nothing needs to be done to
104  * free them from the user's point of view. Additionally, some models
105  * guarantee that an iterator is valid for as long as the node it refers
106  * to is valid (most notably the #GtkTreeStore and #GtkListStore).
107  * Although generally uninteresting, as one always has to allow for
108  * the case where iterators do not persist beyond a signal, some very
109  * important performance enhancements were made in the sort model.
110  * As a result, the #GTK_TREE_MODEL_ITERS_PERSIST flag was added to
111  * indicate this behavior.
112  *
113  * To help show some common operation of a model, some examples are
114  * provided. The first example shows three ways of getting the iter at
115  * the location <quote>3:2:5</quote>. While the first method shown is
116  * easier, the second is much more common, as you often get paths from
117  * callbacks.
118  *
119  * <example>
120  * <title>Acquiring a <structname>GtkTreeIter</structname></title>
121  * <programlisting>
122  *  /&ast; Three ways of getting the iter pointing to the location &ast;/
123  * GtkTreePath *path;
124  * GtkTreeIter iter;
125  * GtkTreeIter parent_iter;
126  *
127  * /&ast; get the iterator from a string &ast;/
128  * gtk_tree_model_get_iter_from_string (model, &amp;iter, "3:2:5");
129  *
130  * /&ast; get the iterator from a path &ast;/
131  * path = gtk_tree_path_new_from_string ("3:2:5");
132  * gtk_tree_model_get_iter (model, &amp;iter, path);
133  * gtk_tree_path_free (path);
134  *
135  * /&ast; walk the tree to find the iterator &ast;/
136  * gtk_tree_model_iter_nth_child (model, &amp;iter, NULL, 3);
137  * parent_iter = iter;
138  * gtk_tree_model_iter_nth_child (model, &amp;iter, &amp;parent_iter, 2);
139  * parent_iter = iter;
140  * gtk_tree_model_iter_nth_child (model, &amp;iter, &amp;parent_iter, 5);
141  * </programlisting>
142  * </example>
143  *
144  * This second example shows a quick way of iterating through a list
145  * and getting a string and an integer from each row. The
146  * <function>populate_model</function> function used below is not
147  * shown, as it is specific to the #GtkListStore. For information on
148  * how to write such a function, see the #GtkListStore documentation.
149  *
150  * <example>
151  * <title>Reading data from a <structname>GtkTreeModel</structname></title>
152  * <programlisting>
153  * enum
154  * {
155  *   STRING_COLUMN,
156  *   INT_COLUMN,
157  *   N_COLUMNS
158  * };
159  *
160  * ...
161  *
162  * GtkTreeModel *list_store;
163  * GtkTreeIter iter;
164  * gboolean valid;
165  * gint row_count = 0;
166  *
167  * /&ast; make a new list_store &ast;/
168  * list_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
169  *
170  * /&ast; Fill the list store with data &ast;/
171  * populate_model (list_store);
172  *
173  * /&ast; Get the first iter in the list &ast;/
174  * valid = gtk_tree_model_get_iter_first (list_store, &amp;iter);
175  *
176  * while (valid)
177  *  {
178  *    /&ast; Walk through the list, reading each row &ast;/
179  *    gchar *str_data;
180  *    gint   int_data;
181  *
182  *    /&ast; Make sure you terminate calls to gtk_tree_model_get()
183  *     &ast; with a '-1' value
184  *     &ast;/
185  *    gtk_tree_model_get (list_store, &amp;iter,
186  *                        STRING_COLUMN, &amp;str_data,
187  *                        INT_COLUMN, &amp;int_data,
188  *                        -1);
189  *
190  *    /&ast; Do something with the data &ast;/
191  *    g_print ("Row &percnt;d: (&percnt;s,&percnt;d)\n", row_count, str_data, int_data);
192  *    g_free (str_data);
193  *
194  *    row_count++;
195  *    valid = gtk_tree_model_iter_next (list_store, &amp;iter);
196  *  }
197  * </programlisting>
198  * </example>
199  *
200  */
201
202 #define INITIALIZE_TREE_ITER(Iter) \
203     G_STMT_START{ \
204       (Iter)->stamp = 0; \
205       (Iter)->user_data  = NULL; \
206       (Iter)->user_data2 = NULL; \
207       (Iter)->user_data3 = NULL; \
208     }G_STMT_END
209
210 #define ROW_REF_DATA_STRING "gtk-tree-row-refs"
211
212 enum {
213   ROW_CHANGED,
214   ROW_INSERTED,
215   ROW_HAS_CHILD_TOGGLED,
216   ROW_DELETED,
217   ROWS_REORDERED,
218   LAST_SIGNAL
219 };
220
221 static guint tree_model_signals[LAST_SIGNAL] = { 0 };
222
223 struct _GtkTreePath
224 {
225   gint depth;
226   gint *indices;
227 };
228
229 typedef struct
230 {
231   GSList *list;
232 } RowRefList;
233
234 static void      gtk_tree_model_base_init   (gpointer           g_class);
235
236 /* custom closures */
237 static void      row_inserted_marshal       (GClosure          *closure,
238                                              GValue /* out */  *return_value,
239                                              guint              n_param_value,
240                                              const GValue      *param_values,
241                                              gpointer           invocation_hint,
242                                              gpointer           marshal_data);
243 static void      row_deleted_marshal        (GClosure          *closure,
244                                              GValue /* out */  *return_value,
245                                              guint              n_param_value,
246                                              const GValue      *param_values,
247                                              gpointer           invocation_hint,
248                                              gpointer           marshal_data);
249 static void      rows_reordered_marshal     (GClosure          *closure,
250                                              GValue /* out */  *return_value,
251                                              guint              n_param_value,
252                                              const GValue      *param_values,
253                                              gpointer           invocation_hint,
254                                              gpointer           marshal_data);
255
256 static void      gtk_tree_row_ref_inserted  (RowRefList        *refs,
257                                              GtkTreePath       *path,
258                                              GtkTreeIter       *iter);
259 static void      gtk_tree_row_ref_deleted   (RowRefList        *refs,
260                                              GtkTreePath       *path);
261 static void      gtk_tree_row_ref_reordered (RowRefList        *refs,
262                                              GtkTreePath       *path,
263                                              GtkTreeIter       *iter,
264                                              gint              *new_order);
265
266 GType
267 gtk_tree_model_get_type (void)
268 {
269   static GType tree_model_type = 0;
270
271   if (! tree_model_type)
272     {
273       const GTypeInfo tree_model_info =
274       {
275         sizeof (GtkTreeModelIface), /* class_size */
276         gtk_tree_model_base_init,   /* base_init */
277         NULL,           /* base_finalize */
278         NULL,
279         NULL,           /* class_finalize */
280         NULL,           /* class_data */
281         0,
282         0,              /* n_preallocs */
283         NULL
284       };
285
286       tree_model_type =
287         g_type_register_static (G_TYPE_INTERFACE, I_("GtkTreeModel"),
288                                 &tree_model_info, 0);
289
290       g_type_interface_add_prerequisite (tree_model_type, G_TYPE_OBJECT);
291     }
292
293   return tree_model_type;
294 }
295
296 static void
297 gtk_tree_model_base_init (gpointer g_class)
298 {
299   static gboolean initialized = FALSE;
300   GClosure *closure;
301
302   if (! initialized)
303     {
304       GType row_inserted_params[2];
305       GType row_deleted_params[1];
306       GType rows_reordered_params[3];
307
308       row_inserted_params[0] = GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE;
309       row_inserted_params[1] = GTK_TYPE_TREE_ITER;
310
311       row_deleted_params[0] = GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE;
312
313       rows_reordered_params[0] = GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE;
314       rows_reordered_params[1] = GTK_TYPE_TREE_ITER;
315       rows_reordered_params[2] = G_TYPE_POINTER;
316
317       /**
318        * GtkTreeModel::row-changed:
319        * @tree_model: the #GtkTreeModel on which the signal is emitted
320        * @path: a #GtkTreePath identifying the changed row
321        * @iter: a valid #GtkTreeIter pointing to the changed row
322        *
323        * This signal is emitted when a row in the model has changed.
324        */
325       tree_model_signals[ROW_CHANGED] =
326         g_signal_new (I_("row-changed"),
327                       GTK_TYPE_TREE_MODEL,
328                       G_SIGNAL_RUN_LAST, 
329                       G_STRUCT_OFFSET (GtkTreeModelIface, row_changed),
330                       NULL, NULL,
331                       _gtk_marshal_VOID__BOXED_BOXED,
332                       G_TYPE_NONE, 2,
333                       GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE,
334                       GTK_TYPE_TREE_ITER);
335
336       /* We need to get notification about structure changes
337        * to update row references., so instead of using the
338        * standard g_signal_new() with an offset into our interface
339        * structure, we use a customs closures for the class
340        * closures (default handlers) that first update row references
341        * and then calls the function from the interface structure.
342        *
343        * The reason we don't simply update the row references from
344        * the wrapper functions (gtk_tree_model_row_inserted(), etc.)
345        * is to keep proper ordering with respect to signal handlers
346        * connected normally and after.
347        */
348
349       /**
350        * GtkTreeModel::row-inserted:
351        * @tree_model: the #GtkTreeModel on which the signal is emitted
352        * @path: a #GtkTreePath identifying the new row
353        * @iter: a valid #GtkTreeIter pointing to the new row
354        *
355        * This signal is emitted when a new row has been inserted in
356        * the model.
357        *
358        * Note that the row may still be empty at this point, since
359        * it is a common pattern to first insert an empty row, and
360        * then fill it with the desired values.
361        */
362       closure = g_closure_new_simple (sizeof (GClosure), NULL);
363       g_closure_set_marshal (closure, row_inserted_marshal);
364       tree_model_signals[ROW_INSERTED] =
365         g_signal_newv (I_("row-inserted"),
366                        GTK_TYPE_TREE_MODEL,
367                        G_SIGNAL_RUN_FIRST,
368                        closure,
369                        NULL, NULL,
370                        _gtk_marshal_VOID__BOXED_BOXED,
371                        G_TYPE_NONE, 2,
372                        row_inserted_params);
373
374       /**
375        * GtkTreeModel::row-has-child-toggled:
376        * @tree_model: the #GtkTreeModel on which the signal is emitted
377        * @path: a #GtkTreePath identifying the row
378        * @iter: a valid #GtkTreeIter pointing to the row
379        *
380        * This signal is emitted when a row has gotten the first child
381        * row or lost its last child row.
382        */
383       tree_model_signals[ROW_HAS_CHILD_TOGGLED] =
384         g_signal_new (I_("row-has-child-toggled"),
385                       GTK_TYPE_TREE_MODEL,
386                       G_SIGNAL_RUN_LAST,
387                       G_STRUCT_OFFSET (GtkTreeModelIface, row_has_child_toggled),
388                       NULL, NULL,
389                       _gtk_marshal_VOID__BOXED_BOXED,
390                       G_TYPE_NONE, 2,
391                       GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE,
392                       GTK_TYPE_TREE_ITER);
393
394       /**
395        * GtkTreeModel::row-deleted:
396        * @tree_model: the #GtkTreeModel on which the signal is emitted
397        * @path: a #GtkTreePath identifying the row
398        *
399        * This signal is emitted when a row has been deleted.
400        *
401        * Note that no iterator is passed to the signal handler,
402        * since the row is already deleted.
403        *
404        * This should be called by models after a row has been removed.
405        * The location pointed to by @path should be the location that
406        * the row previously was at. It may not be a valid location anymore.
407        */
408       closure = g_closure_new_simple (sizeof (GClosure), NULL);
409       g_closure_set_marshal (closure, row_deleted_marshal);
410       tree_model_signals[ROW_DELETED] =
411         g_signal_newv (I_("row-deleted"),
412                        GTK_TYPE_TREE_MODEL,
413                        G_SIGNAL_RUN_FIRST,
414                        closure,
415                        NULL, NULL,
416                        _gtk_marshal_VOID__BOXED,
417                        G_TYPE_NONE, 1,
418                        row_deleted_params);
419
420       /**
421        * GtkTreeModel::rows-reordered: (skip)
422        * @tree_model: the #GtkTreeModel on which the signal is emitted
423        * @path: a #GtkTreePath identifying the tree node whose children
424        *     have been reordered
425        * @iter: a valid #GtkTreeIter pointing to the node whose
426        * @new_order: an array of integers mapping the current position
427        *     of each child to its old position before the re-ordering,
428        *     i.e. @new_order<literal>[newpos] = oldpos</literal>
429        *
430        * This signal is emitted when the children of a node in the
431        * #GtkTreeModel have been reordered.
432        *
433        * Note that this signal is <emphasis>not</emphasis> emitted
434        * when rows are reordered by DND, since this is implemented
435        * by removing and then reinserting the row.
436        */
437       closure = g_closure_new_simple (sizeof (GClosure), NULL);
438       g_closure_set_marshal (closure, rows_reordered_marshal);
439       tree_model_signals[ROWS_REORDERED] =
440         g_signal_newv (I_("rows-reordered"),
441                        GTK_TYPE_TREE_MODEL,
442                        G_SIGNAL_RUN_FIRST,
443                        closure,
444                        NULL, NULL,
445                        _gtk_marshal_VOID__BOXED_BOXED_POINTER,
446                        G_TYPE_NONE, 3,
447                        rows_reordered_params);
448       initialized = TRUE;
449     }
450 }
451
452 static void
453 row_inserted_marshal (GClosure          *closure,
454                       GValue /* out */  *return_value,
455                       guint              n_param_values,
456                       const GValue      *param_values,
457                       gpointer           invocation_hint,
458                       gpointer           marshal_data)
459 {
460   GtkTreeModelIface *iface;
461
462   void (* row_inserted_callback) (GtkTreeModel *tree_model,
463                                   GtkTreePath *path,
464                                   GtkTreeIter *iter) = NULL;
465
466   GObject *model = g_value_get_object (param_values + 0);
467   GtkTreePath *path = (GtkTreePath *)g_value_get_boxed (param_values + 1);
468   GtkTreeIter *iter = (GtkTreeIter *)g_value_get_boxed (param_values + 2);
469
470   /* first, we need to update internal row references */
471   gtk_tree_row_ref_inserted ((RowRefList *)g_object_get_data (model, ROW_REF_DATA_STRING),
472                              path, iter);
473
474   /* fetch the interface ->row_inserted implementation */
475   iface = GTK_TREE_MODEL_GET_IFACE (model);
476   row_inserted_callback = G_STRUCT_MEMBER (gpointer, iface,
477                               G_STRUCT_OFFSET (GtkTreeModelIface,
478                                                row_inserted));
479
480   /* Call that default signal handler, it if has been set */
481   if (row_inserted_callback)
482     row_inserted_callback (GTK_TREE_MODEL (model), path, iter);
483 }
484
485 static void
486 row_deleted_marshal (GClosure          *closure,
487                      GValue /* out */  *return_value,
488                      guint              n_param_values,
489                      const GValue      *param_values,
490                      gpointer           invocation_hint,
491                      gpointer           marshal_data)
492 {
493   GtkTreeModelIface *iface;
494   void (* row_deleted_callback) (GtkTreeModel *tree_model,
495                                  GtkTreePath  *path) = NULL;
496   GObject *model = g_value_get_object (param_values + 0);
497   GtkTreePath *path = (GtkTreePath *)g_value_get_boxed (param_values + 1);
498
499   /* first, we need to update internal row references */
500   gtk_tree_row_ref_deleted ((RowRefList *)g_object_get_data (model, ROW_REF_DATA_STRING),
501                             path);
502
503   /* fetch the interface ->row_deleted implementation */
504   iface = GTK_TREE_MODEL_GET_IFACE (model);
505   row_deleted_callback = G_STRUCT_MEMBER (gpointer, iface,
506                               G_STRUCT_OFFSET (GtkTreeModelIface,
507                                                row_deleted));
508
509   /* Call that default signal handler, it if has been set */
510   if (row_deleted_callback)
511     row_deleted_callback (GTK_TREE_MODEL (model), path);
512 }
513
514 static void
515 rows_reordered_marshal (GClosure          *closure,
516                         GValue /* out */  *return_value,
517                         guint              n_param_values,
518                         const GValue      *param_values,
519                         gpointer           invocation_hint,
520                         gpointer           marshal_data)
521 {
522   GtkTreeModelIface *iface;
523   void (* rows_reordered_callback) (GtkTreeModel *tree_model,
524                                     GtkTreePath  *path,
525                                     GtkTreeIter  *iter,
526                                     gint         *new_order);
527
528   GObject *model = g_value_get_object (param_values + 0);
529   GtkTreePath *path = (GtkTreePath *)g_value_get_boxed (param_values + 1);
530   GtkTreeIter *iter = (GtkTreeIter *)g_value_get_boxed (param_values + 2);
531   gint *new_order = (gint *)g_value_get_pointer (param_values + 3);
532
533   /* first, we need to update internal row references */
534   gtk_tree_row_ref_reordered ((RowRefList *)g_object_get_data (model, ROW_REF_DATA_STRING),
535                               path, iter, new_order);
536
537   /* fetch the interface ->rows_reordered implementation */
538   iface = GTK_TREE_MODEL_GET_IFACE (model);
539   rows_reordered_callback = G_STRUCT_MEMBER (gpointer, iface,
540                               G_STRUCT_OFFSET (GtkTreeModelIface,
541                                                rows_reordered));
542
543   /* Call that default signal handler, it if has been set */
544   if (rows_reordered_callback)
545     rows_reordered_callback (GTK_TREE_MODEL (model), path, iter, new_order);
546 }
547
548 /**
549  * gtk_tree_path_new:
550  *
551  * Creates a new #GtkTreePath.
552  * This structure refers to a row.
553  *
554  * Return value: A newly created #GtkTreePath.
555  */
556 GtkTreePath *
557 gtk_tree_path_new (void)
558 {
559   GtkTreePath *retval;
560   retval = g_slice_new (GtkTreePath);
561   retval->depth = 0;
562   retval->indices = NULL;
563
564   return retval;
565 }
566
567 /**
568  * gtk_tree_path_new_from_string:
569  * @path: The string representation of a path
570  *
571  * Creates a new #GtkTreePath initialized to @path.
572  *
573  * @path is expected to be a colon separated list of numbers.
574  * For example, the string "10:4:0" would create a path of depth
575  * 3 pointing to the 11th child of the root node, the 5th
576  * child of that 11th child, and the 1st child of that 5th child.
577  * If an invalid path string is passed in, %NULL is returned.
578  *
579  * Return value: A newly-created #GtkTreePath, or %NULL
580  */
581 GtkTreePath *
582 gtk_tree_path_new_from_string (const gchar *path)
583 {
584   GtkTreePath *retval;
585   const gchar *orig_path = path;
586   gchar *ptr;
587   gint i;
588
589   g_return_val_if_fail (path != NULL, NULL);
590   g_return_val_if_fail (*path != '\000', NULL);
591
592   retval = gtk_tree_path_new ();
593
594   while (1)
595     {
596       i = strtol (path, &ptr, 10);
597       if (i < 0)
598         {
599           g_warning (G_STRLOC ": Negative numbers in path %s passed to gtk_tree_path_new_from_string", orig_path);
600           gtk_tree_path_free (retval);
601           return NULL;
602         }
603
604       gtk_tree_path_append_index (retval, i);
605
606       if (*ptr == '\000')
607         break;
608       if (ptr == path || *ptr != ':')
609         {
610           g_warning (G_STRLOC ": Invalid path %s passed to gtk_tree_path_new_from_string", orig_path);
611           gtk_tree_path_free (retval);
612           return NULL;
613         }
614       path = ptr + 1;
615     }
616
617   return retval;
618 }
619
620 /**
621  * gtk_tree_path_new_from_indices:
622  * @first_index: first integer
623  * @varargs: list of integers terminated by -1
624  *
625  * Creates a new path with @first_index and @varargs as indices.
626  *
627  * Return value: A newly created #GtkTreePath
628  *
629  * Since: 2.2
630  */
631 GtkTreePath *
632 gtk_tree_path_new_from_indices (gint first_index,
633                                 ...)
634 {
635   int arg;
636   va_list args;
637   GtkTreePath *path;
638
639   path = gtk_tree_path_new ();
640
641   va_start (args, first_index);
642   arg = first_index;
643
644   while (arg != -1)
645     {
646       gtk_tree_path_append_index (path, arg);
647       arg = va_arg (args, gint);
648     }
649
650   va_end (args);
651
652   return path;
653 }
654
655 /**
656  * gtk_tree_path_to_string:
657  * @path: A #GtkTreePath
658  *
659  * Generates a string representation of the path.
660  *
661  * This string is a ':' separated list of numbers.
662  * For example, "4:10:0:3" would be an acceptable
663  * return value for this string.
664  *
665  * Return value: A newly-allocated string.
666  *     Must be freed with g_free().
667  */
668 gchar *
669 gtk_tree_path_to_string (GtkTreePath *path)
670 {
671   gchar *retval, *ptr, *end;
672   gint i, n;
673
674   g_return_val_if_fail (path != NULL, NULL);
675
676   if (path->depth == 0)
677     return NULL;
678
679   n = path->depth * 12;
680   ptr = retval = g_new0 (gchar, n);
681   end = ptr + n;
682   g_snprintf (retval, end - ptr, "%d", path->indices[0]);
683   while (*ptr != '\000')
684     ptr++;
685
686   for (i = 1; i < path->depth; i++)
687     {
688       g_snprintf (ptr, end - ptr, ":%d", path->indices[i]);
689       while (*ptr != '\000')
690         ptr++;
691     }
692
693   return retval;
694 }
695
696 /**
697  * gtk_tree_path_new_first:
698  *
699  * Creates a new #GtkTreePath.
700  *
701  * The string representation of this path is "0".
702  *
703  * Return value: A new #GtkTreePath
704  */
705 GtkTreePath *
706 gtk_tree_path_new_first (void)
707 {
708   GtkTreePath *retval;
709
710   retval = gtk_tree_path_new ();
711   gtk_tree_path_append_index (retval, 0);
712
713   return retval;
714 }
715
716 /**
717  * gtk_tree_path_append_index:
718  * @path: a #GtkTreePath
719  * @index_: the index
720  *
721  * Appends a new index to a path.
722  *
723  * As a result, the depth of the path is increased.
724  */
725 void
726 gtk_tree_path_append_index (GtkTreePath *path,
727                             gint         index)
728 {
729   g_return_if_fail (path != NULL);
730   g_return_if_fail (index >= 0);
731
732   path->depth += 1;
733   path->indices = g_realloc (path->indices, path->depth * sizeof(gint));
734   path->indices[path->depth - 1] = index;
735 }
736
737 /**
738  * gtk_tree_path_prepend_index:
739  * @path: a #GtkTreePath
740  * @index_: the index
741  *
742  * Prepends a new index to a path.
743  *
744  * As a result, the depth of the path is increased.
745  */
746 void
747 gtk_tree_path_prepend_index (GtkTreePath *path,
748                              gint       index)
749 {
750   gint *new_indices;
751
752   (path->depth)++;
753   new_indices = g_new (gint, path->depth);
754
755   if (path->indices == NULL)
756     {
757       path->indices = new_indices;
758       path->indices[0] = index;
759       return;
760     }
761   memcpy (new_indices + 1, path->indices, (path->depth - 1)*sizeof (gint));
762   g_free (path->indices);
763   path->indices = new_indices;
764   path->indices[0] = index;
765 }
766
767 /**
768  * gtk_tree_path_get_depth:
769  * @path: a #GtkTreePath
770  *
771  * Returns the current depth of @path.
772  *
773  * Return value: The depth of @path
774  */
775 gint
776 gtk_tree_path_get_depth (GtkTreePath *path)
777 {
778   g_return_val_if_fail (path != NULL, 0);
779
780   return path->depth;
781 }
782
783 /**
784  * gtk_tree_path_get_indices: (skip)
785  * @path: a #GtkTreePath
786  *
787  * Returns the current indices of @path.
788  *
789  * This is an array of integers, each representing a node in a tree.
790  * This value should not be freed.
791  *
792  * Return value: The current indices, or %NULL
793  */
794 gint *
795 gtk_tree_path_get_indices (GtkTreePath *path)
796 {
797   g_return_val_if_fail (path != NULL, NULL);
798
799   return path->indices;
800 }
801
802 /**
803  * gtk_tree_path_get_indices_with_depth:
804  * @path: a #GtkTreePath
805  * @depth: (allow-none): return location for number of elements
806  *     returned in the integer array, or %NULL
807  *
808  * Returns the current indices of @path.
809  *
810  * This is an array of integers, each representing a node in a tree.
811  * It also returns the number of elements in the array.
812  * The array should not be freed.
813  *
814  * Return value: (array length=depth) (transfer none): The current
815  *     indices, or %NULL
816  *
817  * Since: 3.0
818  *
819  * Rename to: gtk_tree_path_get_indices
820  */
821 gint *
822 gtk_tree_path_get_indices_with_depth (GtkTreePath *path,
823                                       gint        *depth)
824 {
825   g_return_val_if_fail (path != NULL, NULL);
826
827   if (depth)
828     *depth = path->depth;
829
830   return path->indices;
831 }
832
833 /**
834  * gtk_tree_path_free:
835  * @path: a #GtkTreePath
836  *
837  * Frees @path.
838  */
839 void
840 gtk_tree_path_free (GtkTreePath *path)
841 {
842   if (!path)
843     return;
844
845   g_free (path->indices);
846   g_slice_free (GtkTreePath, path);
847 }
848
849 /**
850  * gtk_tree_path_copy:
851  * @path: a #GtkTreePath
852  *
853  * Creates a new #GtkTreePath as a copy of @path.
854  *
855  * Return value: a new #GtkTreePath
856  */
857 GtkTreePath *
858 gtk_tree_path_copy (const GtkTreePath *path)
859 {
860   GtkTreePath *retval;
861
862   g_return_val_if_fail (path != NULL, NULL);
863
864   retval = g_slice_new (GtkTreePath);
865   retval->depth = path->depth;
866   retval->indices = g_new (gint, path->depth);
867   memcpy (retval->indices, path->indices, path->depth * sizeof (gint));
868   return retval;
869 }
870
871 G_DEFINE_BOXED_TYPE (GtkTreePath, gtk_tree_path,
872                      gtk_tree_path_copy,
873                      gtk_tree_path_free)
874
875 /**
876  * gtk_tree_path_compare:
877  * @a: a #GtkTreePath
878  * @b: a #GtkTreePath to compare with
879  *
880  * Compares two paths.
881  *
882  * If @a appears before @b in a tree, then -1 is returned.
883  * If @b appears before @a, then 1 is returned.
884  * If the two nodes are equal, then 0 is returned.
885  *
886  * Return value: the relative positions of @a and @b
887  */
888 gint
889 gtk_tree_path_compare (const GtkTreePath *a,
890                        const GtkTreePath *b)
891 {
892   gint p = 0, q = 0;
893
894   g_return_val_if_fail (a != NULL, 0);
895   g_return_val_if_fail (b != NULL, 0);
896   g_return_val_if_fail (a->depth > 0, 0);
897   g_return_val_if_fail (b->depth > 0, 0);
898
899   do
900     {
901       if (a->indices[p] == b->indices[q])
902         continue;
903       return (a->indices[p] < b->indices[q]?-1:1);
904     }
905   while (++p < a->depth && ++q < b->depth);
906   if (a->depth == b->depth)
907     return 0;
908   return (a->depth < b->depth?-1:1);
909 }
910
911 /**
912  * gtk_tree_path_is_ancestor:
913  * @path: a #GtkTreePath
914  * @descendant: another #GtkTreePath
915  *
916  * Returns %TRUE if @descendant is a descendant of @path.
917  *
918  * Return value: %TRUE if @descendant is contained inside @path
919  */
920 gboolean
921 gtk_tree_path_is_ancestor (GtkTreePath *path,
922                            GtkTreePath *descendant)
923 {
924   gint i;
925
926   g_return_val_if_fail (path != NULL, FALSE);
927   g_return_val_if_fail (descendant != NULL, FALSE);
928
929   /* can't be an ancestor if we're deeper */
930   if (path->depth >= descendant->depth)
931     return FALSE;
932
933   i = 0;
934   while (i < path->depth)
935     {
936       if (path->indices[i] != descendant->indices[i])
937         return FALSE;
938       ++i;
939     }
940
941   return TRUE;
942 }
943
944 /**
945  * gtk_tree_path_is_descendant:
946  * @path: a #GtkTreePath
947  * @ancestor: another #GtkTreePath
948  *
949  * Returns %TRUE if @path is a descendant of @ancestor.
950  *
951  * Return value: %TRUE if @ancestor contains @path somewhere below it
952  */
953 gboolean
954 gtk_tree_path_is_descendant (GtkTreePath *path,
955                              GtkTreePath *ancestor)
956 {
957   gint i;
958
959   g_return_val_if_fail (path != NULL, FALSE);
960   g_return_val_if_fail (ancestor != NULL, FALSE);
961
962   /* can't be a descendant if we're shallower in the tree */
963   if (path->depth <= ancestor->depth)
964     return FALSE;
965
966   i = 0;
967   while (i < ancestor->depth)
968     {
969       if (path->indices[i] != ancestor->indices[i])
970         return FALSE;
971       ++i;
972     }
973
974   return TRUE;
975 }
976
977
978 /**
979  * gtk_tree_path_next:
980  * @path: a #GtkTreePath
981  *
982  * Moves the @path to point to the next node at the current depth.
983  */
984 void
985 gtk_tree_path_next (GtkTreePath *path)
986 {
987   g_return_if_fail (path != NULL);
988   g_return_if_fail (path->depth > 0);
989
990   path->indices[path->depth - 1] ++;
991 }
992
993 /**
994  * gtk_tree_path_prev:
995  * @path: a #GtkTreePath
996  *
997  * Moves the @path to point to the previous node at the
998  * current depth, if it exists.
999  *
1000  * Return value: %TRUE if @path has a previous node, and
1001  *     the move was made
1002  */
1003 gboolean
1004 gtk_tree_path_prev (GtkTreePath *path)
1005 {
1006   g_return_val_if_fail (path != NULL, FALSE);
1007
1008   if (path->depth == 0)
1009     return FALSE;
1010
1011   if (path->indices[path->depth - 1] == 0)
1012     return FALSE;
1013
1014   path->indices[path->depth - 1] -= 1;
1015
1016   return TRUE;
1017 }
1018
1019 /**
1020  * gtk_tree_path_up:
1021  * @path: a #GtkTreePath
1022  *
1023  * Moves the @path to point to its parent node, if it has a parent.
1024  *
1025  * Return value: %TRUE if @path has a parent, and the move was made
1026  */
1027 gboolean
1028 gtk_tree_path_up (GtkTreePath *path)
1029 {
1030   g_return_val_if_fail (path != NULL, FALSE);
1031
1032   if (path->depth == 0)
1033     return FALSE;
1034
1035   path->depth--;
1036
1037   return TRUE;
1038 }
1039
1040 /**
1041  * gtk_tree_path_down:
1042  * @path: a #GtkTreePath
1043  *
1044  * Moves @path to point to the first child of the current path.
1045  */
1046 void
1047 gtk_tree_path_down (GtkTreePath *path)
1048 {
1049   g_return_if_fail (path != NULL);
1050
1051   gtk_tree_path_append_index (path, 0);
1052 }
1053
1054 /**
1055  * gtk_tree_iter_copy:
1056  * @iter: a #GtkTreeIter
1057  *
1058  * Creates a dynamically allocated tree iterator as a copy of @iter.
1059  *
1060  * This function is not intended for use in applications,
1061  * because you can just copy the structs by value
1062  * (<literal>GtkTreeIter new_iter = iter;</literal>).
1063  * You must free this iter with gtk_tree_iter_free().
1064  *
1065  * Return value: a newly-allocated copy of @iter
1066  */
1067 GtkTreeIter *
1068 gtk_tree_iter_copy (GtkTreeIter *iter)
1069 {
1070   GtkTreeIter *retval;
1071
1072   g_return_val_if_fail (iter != NULL, NULL);
1073
1074   retval = g_slice_new (GtkTreeIter);
1075   *retval = *iter;
1076
1077   return retval;
1078 }
1079
1080 /**
1081  * gtk_tree_iter_free:
1082  * @iter: a dynamically allocated tree iterator
1083  *
1084  * Frees an iterator that has been allocated by gtk_tree_iter_copy().
1085  *
1086  * This function is mainly used for language bindings.
1087  */
1088 void
1089 gtk_tree_iter_free (GtkTreeIter *iter)
1090 {
1091   g_return_if_fail (iter != NULL);
1092
1093   g_slice_free (GtkTreeIter, iter);
1094 }
1095
1096 G_DEFINE_BOXED_TYPE (GtkTreeIter,  gtk_tree_iter,
1097                      gtk_tree_iter_copy,
1098                      gtk_tree_iter_free)
1099
1100 /**
1101  * gtk_tree_model_get_flags:
1102  * @tree_model: a #GtkTreeModel
1103  *
1104  * Returns a set of flags supported by this interface.
1105  *
1106  * The flags are a bitwise combination of #GtkTreeModelFlags.
1107  * The flags supported should not change during the lifetime
1108  * of the @tree_model.
1109  *
1110  * Return value: the flags supported by this interface
1111  */
1112 GtkTreeModelFlags
1113 gtk_tree_model_get_flags (GtkTreeModel *tree_model)
1114 {
1115   GtkTreeModelIface *iface;
1116
1117   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
1118
1119   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1120   if (iface->get_flags)
1121     return (* iface->get_flags) (tree_model);
1122
1123   return 0;
1124 }
1125
1126 /**
1127  * gtk_tree_model_get_n_columns:
1128  * @tree_model: a #GtkTreeModel
1129  *
1130  * Returns the number of columns supported by @tree_model.
1131  *
1132  * Return value: the number of columns
1133  */
1134 gint
1135 gtk_tree_model_get_n_columns (GtkTreeModel *tree_model)
1136 {
1137   GtkTreeModelIface *iface;
1138   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
1139
1140   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1141   g_return_val_if_fail (iface->get_n_columns != NULL, 0);
1142
1143   return (* iface->get_n_columns) (tree_model);
1144 }
1145
1146 /**
1147  * gtk_tree_model_get_column_type:
1148  * @tree_model: a #GtkTreeModel
1149  * @index_: the column index
1150  *
1151  * Returns the type of the column.
1152  *
1153  * Return value: (transfer none): the type of the column
1154  */
1155 GType
1156 gtk_tree_model_get_column_type (GtkTreeModel *tree_model,
1157                                 gint          index)
1158 {
1159   GtkTreeModelIface *iface;
1160
1161   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), G_TYPE_INVALID);
1162
1163   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1164   g_return_val_if_fail (iface->get_column_type != NULL, G_TYPE_INVALID);
1165   g_return_val_if_fail (index >= 0, G_TYPE_INVALID);
1166
1167   return (* iface->get_column_type) (tree_model, index);
1168 }
1169
1170 /**
1171  * gtk_tree_model_get_iter:
1172  * @tree_model: a #GtkTreeModel
1173  * @iter: (out): the uninitialized #GtkTreeIter
1174  * @path: the #GtkTreePath
1175  *
1176  * Sets @iter to a valid iterator pointing to @path.
1177  *
1178  * Return value: %TRUE, if @iter was set
1179  */
1180 gboolean
1181 gtk_tree_model_get_iter (GtkTreeModel *tree_model,
1182                          GtkTreeIter  *iter,
1183                          GtkTreePath  *path)
1184 {
1185   GtkTreeModelIface *iface;
1186
1187   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1188   g_return_val_if_fail (iter != NULL, FALSE);
1189   g_return_val_if_fail (path != NULL, FALSE);
1190
1191   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1192   g_return_val_if_fail (iface->get_iter != NULL, FALSE);
1193   g_return_val_if_fail (path->depth > 0, FALSE);
1194
1195   INITIALIZE_TREE_ITER (iter);
1196
1197   return (* iface->get_iter) (tree_model, iter, path);
1198 }
1199
1200 /**
1201  * gtk_tree_model_get_iter_from_string:
1202  * @tree_model: a #GtkTreeModel
1203  * @iter: (out): an uninitialized #GtkTreeIter
1204  * @path_string: a string representation of a #GtkTreePath
1205  *
1206  * Sets @iter to a valid iterator pointing to @path_string, if it
1207  * exists. Otherwise, @iter is left invalid and %FALSE is returned.
1208  *
1209  * Return value: %TRUE, if @iter was set
1210  */
1211 gboolean
1212 gtk_tree_model_get_iter_from_string (GtkTreeModel *tree_model,
1213                                      GtkTreeIter  *iter,
1214                                      const gchar  *path_string)
1215 {
1216   gboolean retval;
1217   GtkTreePath *path;
1218
1219   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1220   g_return_val_if_fail (iter != NULL, FALSE);
1221   g_return_val_if_fail (path_string != NULL, FALSE);
1222
1223   path = gtk_tree_path_new_from_string (path_string);
1224
1225   g_return_val_if_fail (path != NULL, FALSE);
1226
1227   retval = gtk_tree_model_get_iter (tree_model, iter, path);
1228   gtk_tree_path_free (path);
1229
1230   return retval;
1231 }
1232
1233 /**
1234  * gtk_tree_model_get_string_from_iter:
1235  * @tree_model: a #GtkTreeModel
1236  * @iter: a #GtkTreeIter
1237  *
1238  * Generates a string representation of the iter.
1239  *
1240  * This string is a ':' separated list of numbers.
1241  * For example, "4:10:0:3" would be an acceptable
1242  * return value for this string.
1243  *
1244  * Return value: a newly-allocated string.
1245  *     Must be freed with g_free().
1246  *
1247  * Since: 2.2
1248  */
1249 gchar *
1250 gtk_tree_model_get_string_from_iter (GtkTreeModel *tree_model,
1251                                      GtkTreeIter  *iter)
1252 {
1253   GtkTreePath *path;
1254   gchar *ret;
1255
1256   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), NULL);
1257   g_return_val_if_fail (iter != NULL, NULL);
1258
1259   path = gtk_tree_model_get_path (tree_model, iter);
1260
1261   g_return_val_if_fail (path != NULL, NULL);
1262
1263   ret = gtk_tree_path_to_string (path);
1264   gtk_tree_path_free (path);
1265
1266   return ret;
1267 }
1268
1269 /**
1270  * gtk_tree_model_get_iter_first:
1271  * @tree_model: a #GtkTreeModel
1272  * @iter: (out): the uninitialized #GtkTreeIter
1273  *
1274  * Initializes @iter with the first iterator in the tree
1275  * (the one at the path "0") and returns %TRUE. Returns
1276  * %FALSE if the tree is empty.
1277  *
1278  * Return value: %TRUE, if @iter was set
1279  */
1280 gboolean
1281 gtk_tree_model_get_iter_first (GtkTreeModel *tree_model,
1282                                GtkTreeIter  *iter)
1283 {
1284   GtkTreePath *path;
1285   gboolean retval;
1286
1287   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1288   g_return_val_if_fail (iter != NULL, FALSE);
1289
1290   path = gtk_tree_path_new_first ();
1291   retval = gtk_tree_model_get_iter (tree_model, iter, path);
1292   gtk_tree_path_free (path);
1293
1294   return retval;
1295 }
1296
1297 /**
1298  * gtk_tree_model_get_path:
1299  * @tree_model: a #GtkTreeModel
1300  * @iter: the #GtkTreeIter
1301  *
1302  * Returns a newly-created #GtkTreePath referenced by @iter.
1303  *
1304  * This path should be freed with gtk_tree_path_free().
1305  *
1306  * Return value: a newly-created #GtkTreePath
1307  */
1308 GtkTreePath *
1309 gtk_tree_model_get_path (GtkTreeModel *tree_model,
1310                          GtkTreeIter  *iter)
1311 {
1312   GtkTreeModelIface *iface;
1313
1314   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), NULL);
1315   g_return_val_if_fail (iter != NULL, NULL);
1316
1317   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1318   g_return_val_if_fail (iface->get_path != NULL, NULL);
1319
1320   return (* iface->get_path) (tree_model, iter);
1321 }
1322
1323 /**
1324  * gtk_tree_model_get_value:
1325  * @tree_model: a #GtkTreeModel
1326  * @iter: the #GtkTreeIter
1327  * @column: the column to lookup the value at
1328  * @value: (out) (transfer none): an empty #GValue to set
1329  *
1330  * Initializes and sets @value to that at @column.
1331  *
1332  * When done with @value, g_value_unset() needs to be called
1333  * to free any allocated memory.
1334  */
1335 void
1336 gtk_tree_model_get_value (GtkTreeModel *tree_model,
1337                           GtkTreeIter  *iter,
1338                           gint          column,
1339                           GValue       *value)
1340 {
1341   GtkTreeModelIface *iface;
1342
1343   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1344   g_return_if_fail (iter != NULL);
1345   g_return_if_fail (value != NULL);
1346
1347   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1348   g_return_if_fail (iface->get_value != NULL);
1349
1350   (* iface->get_value) (tree_model, iter, column, value);
1351 }
1352
1353 /**
1354  * gtk_tree_model_iter_next:
1355  * @tree_model: a #GtkTreeModel
1356  * @iter: (in): the #GtkTreeIter
1357  *
1358  * Sets @iter to point to the node following it at the current level.
1359  *
1360  * If there is no next @iter, %FALSE is returned and @iter is set
1361  * to be invalid.
1362  *
1363  * Return value: %TRUE if @iter has been changed to the next node
1364  */
1365 gboolean
1366 gtk_tree_model_iter_next (GtkTreeModel  *tree_model,
1367                           GtkTreeIter   *iter)
1368 {
1369   GtkTreeModelIface *iface;
1370
1371   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1372   g_return_val_if_fail (iter != NULL, FALSE);
1373
1374   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1375   g_return_val_if_fail (iface->iter_next != NULL, FALSE);
1376
1377   return (* iface->iter_next) (tree_model, iter);
1378 }
1379
1380 static gboolean
1381 gtk_tree_model_iter_previous_default (GtkTreeModel *tree_model,
1382                                       GtkTreeIter  *iter)
1383 {
1384   gboolean retval;
1385   GtkTreePath *path;
1386
1387   path = gtk_tree_model_get_path (tree_model, iter);
1388   if (path == NULL)
1389     return FALSE;
1390
1391   retval = gtk_tree_path_prev (path) &&
1392            gtk_tree_model_get_iter (tree_model, iter, path);
1393   if (retval == FALSE)
1394     iter->stamp = 0;
1395
1396   gtk_tree_path_free (path);
1397
1398   return retval;
1399 }
1400
1401 /**
1402  * gtk_tree_model_iter_previous:
1403  * @tree_model: a #GtkTreeModel
1404  * @iter: (in): the #GtkTreeIter
1405  *
1406  * Sets @iter to point to the previous node at the current level.
1407  *
1408  * If there is no previous @iter, %FALSE is returned and @iter is
1409  * set to be invalid.
1410  *
1411  * Return value: %TRUE if @iter has been changed to the previous node
1412  *
1413  * Since: 3.0
1414  */
1415 gboolean
1416 gtk_tree_model_iter_previous (GtkTreeModel *tree_model,
1417                               GtkTreeIter  *iter)
1418 {
1419   gboolean retval;
1420   GtkTreeModelIface *iface;
1421
1422   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1423   g_return_val_if_fail (iter != NULL, FALSE);
1424
1425   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1426
1427   if (iface->iter_previous)
1428     retval = (* iface->iter_previous) (tree_model, iter);
1429   else
1430     retval = gtk_tree_model_iter_previous_default (tree_model, iter);
1431
1432   return retval;
1433 }
1434
1435 /**
1436  * gtk_tree_model_iter_children:
1437  * @tree_model: a #GtkTreeModel
1438  * @iter: (out): the new #GtkTreeIter to be set to the child
1439  * @parent: (allow-none): the #GtkTreeIter, or %NULL
1440  *
1441  * Sets @iter to point to the first child of @parent.
1442  *
1443  * If @parent has no children, %FALSE is returned and @iter is
1444  * set to be invalid. @parent will remain a valid node after this
1445  * function has been called.
1446  *
1447  * If @parent is %NULL returns the first node, equivalent to
1448  * <literal>gtk_tree_model_get_iter_first (tree_model, iter);</literal>
1449  *
1450  * Return value: %TRUE, if @child has been set to the first child
1451  */
1452 gboolean
1453 gtk_tree_model_iter_children (GtkTreeModel *tree_model,
1454                               GtkTreeIter  *iter,
1455                               GtkTreeIter  *parent)
1456 {
1457   GtkTreeModelIface *iface;
1458
1459   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1460   g_return_val_if_fail (iter != NULL, FALSE);
1461
1462   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1463   g_return_val_if_fail (iface->iter_children != NULL, FALSE);
1464
1465   INITIALIZE_TREE_ITER (iter);
1466
1467   return (* iface->iter_children) (tree_model, iter, parent);
1468 }
1469
1470 /**
1471  * gtk_tree_model_iter_has_child:
1472  * @tree_model: a #GtkTreeModel
1473  * @iter: the #GtkTreeIter to test for children
1474  *
1475  * Returns %TRUE if @iter has children, %FALSE otherwise.
1476  *
1477  * Return value: %TRUE if @iter has children
1478  */
1479 gboolean
1480 gtk_tree_model_iter_has_child (GtkTreeModel *tree_model,
1481                                GtkTreeIter  *iter)
1482 {
1483   GtkTreeModelIface *iface;
1484
1485   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1486   g_return_val_if_fail (iter != NULL, FALSE);
1487
1488   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1489   g_return_val_if_fail (iface->iter_has_child != NULL, FALSE);
1490
1491   return (* iface->iter_has_child) (tree_model, iter);
1492 }
1493
1494 /**
1495  * gtk_tree_model_iter_n_children:
1496  * @tree_model: a #GtkTreeModel
1497  * @iter: (allow-none): the #GtkTreeIter, or %NULL
1498  *
1499  * Returns the number of children that @iter has.
1500  *
1501  * As a special case, if @iter is %NULL, then the number
1502  * of toplevel nodes is returned.
1503  *
1504  * Return value: the number of children of @iter
1505  */
1506 gint
1507 gtk_tree_model_iter_n_children (GtkTreeModel *tree_model,
1508                                 GtkTreeIter  *iter)
1509 {
1510   GtkTreeModelIface *iface;
1511
1512   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
1513
1514   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1515   g_return_val_if_fail (iface->iter_n_children != NULL, 0);
1516
1517   return (* iface->iter_n_children) (tree_model, iter);
1518 }
1519
1520 /**
1521  * gtk_tree_model_iter_nth_child:
1522  * @tree_model: a #GtkTreeModel
1523  * @iter: (out): the #GtkTreeIter to set to the nth child
1524  * @parent: (allow-none): the #GtkTreeIter to get the child from, or %NULL.
1525  * @n: the index of the desired child
1526  *
1527  * Sets @iter to be the child of @parent, using the given index.
1528  *
1529  * The first index is 0. If @n is too big, or @parent has no children,
1530  * @iter is set to an invalid iterator and %FALSE is returned. @parent
1531  * will remain a valid node after this function has been called. As a
1532  * special case, if @parent is %NULL, then the @n<!-- -->th root node
1533  * is set.
1534  *
1535  * Return value: %TRUE, if @parent has an @n<!-- -->th child
1536  */
1537 gboolean
1538 gtk_tree_model_iter_nth_child (GtkTreeModel *tree_model,
1539                                GtkTreeIter  *iter,
1540                                GtkTreeIter  *parent,
1541                                gint          n)
1542 {
1543   GtkTreeModelIface *iface;
1544
1545   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1546   g_return_val_if_fail (iter != NULL, FALSE);
1547   g_return_val_if_fail (n >= 0, FALSE);
1548
1549   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1550   g_return_val_if_fail (iface->iter_nth_child != NULL, FALSE);
1551
1552   INITIALIZE_TREE_ITER (iter);
1553
1554   return (* iface->iter_nth_child) (tree_model, iter, parent, n);
1555 }
1556
1557 /**
1558  * gtk_tree_model_iter_parent:
1559  * @tree_model: a #GtkTreeModel
1560  * @iter: (out): the new #GtkTreeIter to set to the parent
1561  * @child: the #GtkTreeIter
1562  *
1563  * Sets @iter to be the parent of @child.
1564  *
1565  * If @child is at the toplevel, and doesn't have a parent, then
1566  * @iter is set to an invalid iterator and %FALSE is returned.
1567  * @child will remain a valid node after this function has been
1568  * called.
1569  *
1570  * Return value: %TRUE, if @iter is set to the parent of @child
1571  */
1572 gboolean
1573 gtk_tree_model_iter_parent (GtkTreeModel *tree_model,
1574                             GtkTreeIter  *iter,
1575                             GtkTreeIter  *child)
1576 {
1577   GtkTreeModelIface *iface;
1578
1579   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1580   g_return_val_if_fail (iter != NULL, FALSE);
1581   g_return_val_if_fail (child != NULL, FALSE);
1582
1583   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1584   g_return_val_if_fail (iface->iter_parent != NULL, FALSE);
1585
1586   INITIALIZE_TREE_ITER (iter);
1587
1588   return (* iface->iter_parent) (tree_model, iter, child);
1589 }
1590
1591 /**
1592  * gtk_tree_model_ref_node:
1593  * @tree_model: a #GtkTreeModel
1594  * @iter: the #GtkTreeIter
1595  *
1596  * Lets the tree ref the node.
1597  *
1598  * This is an optional method for models to implement.
1599  * To be more specific, models may ignore this call as it exists
1600  * primarily for performance reasons.
1601  *
1602  * This function is primarily meant as a way for views to let
1603  * caching models know when nodes are being displayed (and hence,
1604  * whether or not to cache that node). For example, a file-system
1605  * based model would not want to keep the entire file-hierarchy in
1606  * memory, just the sections that are currently being displayed by
1607  * every current view.
1608  *
1609  * A model should be expected to be able to get an iter independent
1610  * of its reffed state.
1611  */
1612 void
1613 gtk_tree_model_ref_node (GtkTreeModel *tree_model,
1614                          GtkTreeIter  *iter)
1615 {
1616   GtkTreeModelIface *iface;
1617
1618   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1619
1620   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1621   if (iface->ref_node)
1622     (* iface->ref_node) (tree_model, iter);
1623 }
1624
1625 /**
1626  * gtk_tree_model_unref_node:
1627  * @tree_model: a #GtkTreeModel
1628  * @iter: the #GtkTreeIter
1629  *
1630  * Lets the tree unref the node.
1631  *
1632  * This is an optional method for models to implement.
1633  * To be more specific, models may ignore this call as it exists
1634  * primarily for performance reasons. For more information on what
1635  * this means, see gtk_tree_model_ref_node().
1636  *
1637  * Please note that nodes that are deleted are not unreffed.
1638  */
1639 void
1640 gtk_tree_model_unref_node (GtkTreeModel *tree_model,
1641                            GtkTreeIter  *iter)
1642 {
1643   GtkTreeModelIface *iface;
1644
1645   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1646   g_return_if_fail (iter != NULL);
1647
1648   iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1649   if (iface->unref_node)
1650     (* iface->unref_node) (tree_model, iter);
1651 }
1652
1653 /**
1654  * gtk_tree_model_get:
1655  * @tree_model: a #GtkTreeModel
1656  * @iter: a row in @tree_model
1657  * @Varargs: pairs of column number and value return locations,
1658  *     terminated by -1
1659  *
1660  * Gets the value of one or more cells in the row referenced by @iter.
1661  * The variable argument list should contain integer column numbers,
1662  * each column number followed by a place to store the value being
1663  * retrieved.  The list is terminated by a -1. For example, to get a
1664  * value from column 0 with type %G_TYPE_STRING, you would
1665  * write: <literal>gtk_tree_model_get (model, iter, 0, &amp;place_string_here, -1)</literal>,
1666  * where <literal>place_string_here</literal> is a <type>gchar*</type>
1667  * to be filled with the string.
1668  *
1669  * Returned values with type %G_TYPE_OBJECT have to be unreferenced,
1670  * values with type %G_TYPE_STRING or %G_TYPE_BOXED have to be freed.
1671  * Other values are passed by value.
1672  */
1673 void
1674 gtk_tree_model_get (GtkTreeModel *tree_model,
1675                     GtkTreeIter  *iter,
1676                     ...)
1677 {
1678   va_list var_args;
1679
1680   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1681   g_return_if_fail (iter != NULL);
1682
1683   va_start (var_args, iter);
1684   gtk_tree_model_get_valist (tree_model, iter, var_args);
1685   va_end (var_args);
1686 }
1687
1688 /**
1689  * gtk_tree_model_get_valist:
1690  * @tree_model: a #GtkTreeModel
1691  * @iter: a row in @tree_model
1692  * @var_args: <type>va_list</type> of column/return location pairs
1693  *
1694  * See gtk_tree_model_get(), this version takes a <type>va_list</type>
1695  * for language bindings to use.
1696  */
1697 void
1698 gtk_tree_model_get_valist (GtkTreeModel *tree_model,
1699                            GtkTreeIter  *iter,
1700                            va_list      var_args)
1701 {
1702   gint column;
1703
1704   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1705   g_return_if_fail (iter != NULL);
1706
1707   column = va_arg (var_args, gint);
1708
1709   while (column != -1)
1710     {
1711       GValue value = { 0, };
1712       gchar *error = NULL;
1713
1714       if (column >= gtk_tree_model_get_n_columns (tree_model))
1715         {
1716           g_warning ("%s: Invalid column number %d accessed (remember to end your list of columns with a -1)", G_STRLOC, column);
1717           break;
1718         }
1719
1720       gtk_tree_model_get_value (GTK_TREE_MODEL (tree_model), iter, column, &value);
1721
1722       G_VALUE_LCOPY (&value, var_args, 0, &error);
1723       if (error)
1724         {
1725           g_warning ("%s: %s", G_STRLOC, error);
1726           g_free (error);
1727
1728           /* we purposely leak the value here, it might not be
1729            * in a sane state if an error condition occurred
1730            */
1731           break;
1732         }
1733
1734       g_value_unset (&value);
1735
1736       column = va_arg (var_args, gint);
1737     }
1738 }
1739
1740 /**
1741  * gtk_tree_model_row_changed:
1742  * @tree_model: a #GtkTreeModel
1743  * @path: a #GtkTreePath pointing to the changed row
1744  * @iter: a valid #GtkTreeIter pointing to the changed row
1745  *
1746  * Emits the #GtkTreeModel::row-changed signal on @tree_model.
1747  */
1748 void
1749 gtk_tree_model_row_changed (GtkTreeModel *tree_model,
1750                             GtkTreePath  *path,
1751                             GtkTreeIter  *iter)
1752 {
1753   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1754   g_return_if_fail (path != NULL);
1755   g_return_if_fail (iter != NULL);
1756
1757   g_signal_emit (tree_model, tree_model_signals[ROW_CHANGED], 0, path, iter);
1758 }
1759
1760 /**
1761  * gtk_tree_model_row_inserted:
1762  * @tree_model: a #GtkTreeModel
1763  * @path: a #GtkTreePath pointing to the inserted row
1764  * @iter: a valid #GtkTreeIter pointing to the inserted row
1765  *
1766  * Emits the #GtkTreeModel::row-inserted signal on @tree_model.
1767  */
1768 void
1769 gtk_tree_model_row_inserted (GtkTreeModel *tree_model,
1770                              GtkTreePath  *path,
1771                              GtkTreeIter  *iter)
1772 {
1773   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1774   g_return_if_fail (path != NULL);
1775   g_return_if_fail (iter != NULL);
1776
1777   g_signal_emit (tree_model, tree_model_signals[ROW_INSERTED], 0, path, iter);
1778 }
1779
1780 /**
1781  * gtk_tree_model_row_has_child_toggled:
1782  * @tree_model: a #GtkTreeModel
1783  * @path: a #GtkTreePath pointing to the changed row
1784  * @iter: a valid #GtkTreeIter pointing to the changed row
1785  *
1786  * Emits the #GtkTreeModel::row-has-child-toggled signal on
1787  * @tree_model. This should be called by models after the child
1788  * state of a node changes.
1789  */
1790 void
1791 gtk_tree_model_row_has_child_toggled (GtkTreeModel *tree_model,
1792                                       GtkTreePath  *path,
1793                                       GtkTreeIter  *iter)
1794 {
1795   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1796   g_return_if_fail (path != NULL);
1797   g_return_if_fail (iter != NULL);
1798
1799   g_signal_emit (tree_model, tree_model_signals[ROW_HAS_CHILD_TOGGLED], 0, path, iter);
1800 }
1801
1802 /**
1803  * gtk_tree_model_row_deleted:
1804  * @tree_model: a #GtkTreeModel
1805  * @path: a #GtkTreePath pointing to the previous location of
1806  *     the deleted row
1807  *
1808  * Emits the #GtkTreeModel::row-deleted signal on @tree_model.
1809  *
1810  * This should be called by models after a row has been removed.
1811  * The location pointed to by @path should be the location that
1812  * the row previously was at. It may not be a valid location anymore.
1813  */
1814 void
1815 gtk_tree_model_row_deleted (GtkTreeModel *tree_model,
1816                             GtkTreePath  *path)
1817 {
1818   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1819   g_return_if_fail (path != NULL);
1820
1821   g_signal_emit (tree_model, tree_model_signals[ROW_DELETED], 0, path);
1822 }
1823
1824 /**
1825  * gtk_tree_model_rows_reordered: (skip)
1826  * @tree_model: a #GtkTreeModel
1827  * @path: a #GtkTreePath pointing to the tree node whose children
1828  *     have been reordered
1829  * @iter: a valid #GtkTreeIter pointing to the node whose children
1830  *     have been reordered, or %NULL if the depth of @path is 0
1831  * @new_order: an array of integers mapping the current position of
1832  *     each child to its old position before the re-ordering,
1833  *     i.e. @new_order<literal>[newpos] = oldpos</literal>
1834  *
1835  * Emits the #GtkTreeModel::rows-reordered signal on @tree_model.
1836  *
1837  * This should be called by models when their rows have been
1838  * reordered.
1839  */
1840 void
1841 gtk_tree_model_rows_reordered (GtkTreeModel *tree_model,
1842                                GtkTreePath  *path,
1843                                GtkTreeIter  *iter,
1844                                gint         *new_order)
1845 {
1846   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1847   g_return_if_fail (new_order != NULL);
1848
1849   g_signal_emit (tree_model, tree_model_signals[ROWS_REORDERED], 0, path, iter, new_order);
1850 }
1851
1852
1853 static gboolean
1854 gtk_tree_model_foreach_helper (GtkTreeModel            *model,
1855                                GtkTreeIter             *iter,
1856                                GtkTreePath             *path,
1857                                GtkTreeModelForeachFunc  func,
1858                                gpointer                 user_data)
1859 {
1860   do
1861     {
1862       GtkTreeIter child;
1863
1864       if ((* func) (model, path, iter, user_data))
1865         return TRUE;
1866
1867       if (gtk_tree_model_iter_children (model, &child, iter))
1868         {
1869           gtk_tree_path_down (path);
1870           if (gtk_tree_model_foreach_helper (model, &child, path, func, user_data))
1871             return TRUE;
1872           gtk_tree_path_up (path);
1873         }
1874
1875       gtk_tree_path_next (path);
1876     }
1877   while (gtk_tree_model_iter_next (model, iter));
1878
1879   return FALSE;
1880 }
1881
1882 /**
1883  * gtk_tree_model_foreach:
1884  * @model: a #GtkTreeModel
1885  * @func: (scope call): a function to be called on each row
1886  * @user_data: user data to passed to @func
1887  *
1888  * Calls func on each node in model in a depth-first fashion.
1889  *
1890  * If @func returns %TRUE, then the tree ceases to be walked,
1891  * and gtk_tree_model_foreach() returns.
1892  */
1893 void
1894 gtk_tree_model_foreach (GtkTreeModel            *model,
1895                         GtkTreeModelForeachFunc  func,
1896                         gpointer                 user_data)
1897 {
1898   GtkTreePath *path;
1899   GtkTreeIter iter;
1900
1901   g_return_if_fail (GTK_IS_TREE_MODEL (model));
1902   g_return_if_fail (func != NULL);
1903
1904   path = gtk_tree_path_new_first ();
1905   if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
1906     {
1907       gtk_tree_path_free (path);
1908       return;
1909     }
1910
1911   gtk_tree_model_foreach_helper (model, &iter, path, func, user_data);
1912   gtk_tree_path_free (path);
1913 }
1914
1915
1916 /*
1917  * GtkTreeRowReference
1918  */
1919
1920 static void gtk_tree_row_reference_unref_path (GtkTreePath  *path,
1921                                                GtkTreeModel *model,
1922                                                gint          depth);
1923
1924
1925 G_DEFINE_BOXED_TYPE (GtkTreeRowReference, gtk_tree_row_reference,
1926                      gtk_tree_row_reference_copy,
1927                      gtk_tree_row_reference_free)
1928
1929 struct _GtkTreeRowReference
1930 {
1931   GObject *proxy;
1932   GtkTreeModel *model;
1933   GtkTreePath *path;
1934 };
1935
1936
1937 static void
1938 release_row_references (gpointer data)
1939 {
1940   RowRefList *refs = data;
1941   GSList *tmp_list = NULL;
1942
1943   tmp_list = refs->list;
1944   while (tmp_list != NULL)
1945     {
1946       GtkTreeRowReference *reference = tmp_list->data;
1947
1948       if (reference->proxy == (GObject *)reference->model)
1949         reference->model = NULL;
1950       reference->proxy = NULL;
1951
1952       /* we don't free the reference, users are responsible for that. */
1953
1954       tmp_list = g_slist_next (tmp_list);
1955     }
1956
1957   g_slist_free (refs->list);
1958   g_free (refs);
1959 }
1960
1961 static void
1962 gtk_tree_row_ref_inserted (RowRefList  *refs,
1963                            GtkTreePath *path,
1964                            GtkTreeIter *iter)
1965 {
1966   GSList *tmp_list;
1967
1968   if (refs == NULL)
1969     return;
1970
1971   /* This function corrects the path stored in the reference to
1972    * account for an insertion. Note that it's called _after_ the
1973    * insertion with the path to the newly-inserted row. Which means
1974    * that the inserted path is in a different "coordinate system" than
1975    * the old path (e.g. if the inserted path was just before the old
1976    * path, then inserted path and old path will be the same, and old
1977    * path must be moved down one).
1978    */
1979
1980   tmp_list = refs->list;
1981
1982   while (tmp_list != NULL)
1983     {
1984       GtkTreeRowReference *reference = tmp_list->data;
1985
1986       if (reference->path == NULL)
1987         goto done;
1988
1989       if (reference->path->depth >= path->depth)
1990         {
1991           gint i;
1992           gboolean ancestor = TRUE;
1993
1994           for (i = 0; i < path->depth - 1; i ++)
1995             {
1996               if (path->indices[i] != reference->path->indices[i])
1997                 {
1998                   ancestor = FALSE;
1999                   break;
2000                 }
2001             }
2002           if (ancestor == FALSE)
2003             goto done;
2004
2005           if (path->indices[path->depth-1] <= reference->path->indices[path->depth-1])
2006             reference->path->indices[path->depth-1] += 1;
2007         }
2008     done:
2009       tmp_list = g_slist_next (tmp_list);
2010     }
2011 }
2012
2013 static void
2014 gtk_tree_row_ref_deleted (RowRefList  *refs,
2015                           GtkTreePath *path)
2016 {
2017   GSList *tmp_list;
2018
2019   if (refs == NULL)
2020     return;
2021
2022   /* This function corrects the path stored in the reference to
2023    * account for an deletion. Note that it's called _after_ the
2024    * deletion with the old path of the just-deleted row. Which means
2025    * that the deleted path is the same now-defunct "coordinate system"
2026    * as the path saved in the reference, which is what we want to fix.
2027    */
2028
2029   tmp_list = refs->list;
2030
2031   while (tmp_list != NULL)
2032     {
2033       GtkTreeRowReference *reference = tmp_list->data;
2034
2035       if (reference->path)
2036         {
2037           gint i;
2038
2039           if (path->depth > reference->path->depth)
2040             goto next;
2041           for (i = 0; i < path->depth - 1; i++)
2042             {
2043               if (path->indices[i] != reference->path->indices[i])
2044                 goto next;
2045             }
2046
2047           /* We know it affects us. */
2048           if (path->indices[i] == reference->path->indices[i])
2049             {
2050               if (reference->path->depth > path->depth)
2051                 /* some parent was deleted, trying to unref any node
2052                  * between the deleted parent and the node the reference
2053                  * is pointing to is bad, as those nodes are already gone.
2054                  */
2055                 gtk_tree_row_reference_unref_path (reference->path, reference->model, path->depth - 1);
2056               else
2057                 gtk_tree_row_reference_unref_path (reference->path, reference->model, reference->path->depth - 1);
2058               gtk_tree_path_free (reference->path);
2059               reference->path = NULL;
2060             }
2061           else if (path->indices[i] < reference->path->indices[i])
2062             {
2063               reference->path->indices[path->depth-1]-=1;
2064             }
2065         }
2066
2067 next:
2068       tmp_list = g_slist_next (tmp_list);
2069     }
2070 }
2071
2072 static void
2073 gtk_tree_row_ref_reordered (RowRefList  *refs,
2074                             GtkTreePath *path,
2075                             GtkTreeIter *iter,
2076                             gint        *new_order)
2077 {
2078   GSList *tmp_list;
2079   gint length;
2080
2081   if (refs == NULL)
2082     return;
2083
2084   tmp_list = refs->list;
2085
2086   while (tmp_list != NULL)
2087     {
2088       GtkTreeRowReference *reference = tmp_list->data;
2089
2090       length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (reference->model), iter);
2091
2092       if (length < 2)
2093         return;
2094
2095       if ((reference->path) &&
2096           (gtk_tree_path_is_ancestor (path, reference->path)))
2097         {
2098           gint ref_depth = gtk_tree_path_get_depth (reference->path);
2099           gint depth = gtk_tree_path_get_depth (path);
2100
2101           if (ref_depth > depth)
2102             {
2103               gint i;
2104               gint *indices = gtk_tree_path_get_indices (reference->path);
2105
2106               for (i = 0; i < length; i++)
2107                 {
2108                   if (new_order[i] == indices[depth])
2109                     {
2110                       indices[depth] = i;
2111                       break;
2112                     }
2113                 }
2114             }
2115         }
2116
2117       tmp_list = g_slist_next (tmp_list);
2118     }
2119 }
2120
2121 /* We do this recursively so that we can unref children nodes
2122  * before their parent
2123  */
2124 static void
2125 gtk_tree_row_reference_unref_path_helper (GtkTreePath  *path,
2126                                           GtkTreeModel *model,
2127                                           GtkTreeIter  *parent_iter,
2128                                           gint          depth,
2129                                           gint          current_depth)
2130 {
2131   GtkTreeIter iter;
2132
2133   if (depth == current_depth)
2134     return;
2135
2136   gtk_tree_model_iter_nth_child (model, &iter, parent_iter, path->indices[current_depth]);
2137   gtk_tree_row_reference_unref_path_helper (path, model, &iter, depth, current_depth + 1);
2138   gtk_tree_model_unref_node (model, &iter);
2139 }
2140
2141 static void
2142 gtk_tree_row_reference_unref_path (GtkTreePath  *path,
2143                                    GtkTreeModel *model,
2144                                    gint          depth)
2145 {
2146   GtkTreeIter iter;
2147
2148   if (depth <= 0)
2149     return;
2150
2151   gtk_tree_model_iter_nth_child (model, &iter, NULL, path->indices[0]);
2152   gtk_tree_row_reference_unref_path_helper (path, model, &iter, depth, 1);
2153   gtk_tree_model_unref_node (model, &iter);
2154 }
2155
2156 /**
2157  * gtk_tree_row_reference_new:
2158  * @model: a #GtkTreeModel
2159  * @path: a valid #GtkTreePath to monitor
2160  *
2161  * Creates a row reference based on @path.
2162  *
2163  * This reference will keep pointing to the node pointed to
2164  * by @path, so long as it exists. It listens to all signals
2165  * emitted by @model, and updates its path appropriately. If
2166  * @path isn't a valid path in @model, then %NULL is returned.
2167  *
2168  * Return value: a newly allocated #GtkTreeRowReference, or %NULL
2169  */
2170 GtkTreeRowReference *
2171 gtk_tree_row_reference_new (GtkTreeModel *model,
2172                             GtkTreePath  *path)
2173 {
2174   g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
2175   g_return_val_if_fail (path != NULL, NULL);
2176
2177   /* We use the model itself as the proxy object; and call
2178    * gtk_tree_row_reference_inserted(), etc, in the
2179    * class closure (default handler) marshalers for the signal.
2180    */
2181   return gtk_tree_row_reference_new_proxy (G_OBJECT (model), model, path);
2182 }
2183
2184 /**
2185  * gtk_tree_row_reference_new_proxy:
2186  * @proxy: a proxy #GObject
2187  * @model: a #GtkTreeModel
2188  * @path: a valid #GtkTreePath to monitor
2189  *
2190  * You do not need to use this function.
2191  *
2192  * Creates a row reference based on @path.
2193  *
2194  * This reference will keep pointing to the node pointed to
2195  * by @path, so long as it exists. If @path isn't a valid
2196  * path in @model, then %NULL is returned. However, unlike
2197  * references created with gtk_tree_row_reference_new(), it
2198  * does not listen to the model for changes. The creator of
2199  * the row reference must do this explicitly using
2200  * gtk_tree_row_reference_inserted(), gtk_tree_row_reference_deleted(),
2201  * gtk_tree_row_reference_reordered().
2202  *
2203  * These functions must be called exactly once per proxy when the
2204  * corresponding signal on the model is emitted. This single call
2205  * updates all row references for that proxy. Since built-in GTK+
2206  * objects like #GtkTreeView already use this mechanism internally,
2207  * using them as the proxy object will produce unpredictable results.
2208  * Further more, passing the same object as @model and @proxy
2209  * doesn't work for reasons of internal implementation.
2210  *
2211  * This type of row reference is primarily meant by structures that
2212  * need to carefully monitor exactly when a row reference updates
2213  * itself, and is not generally needed by most applications.
2214  *
2215  * Return value: a newly allocated #GtkTreeRowReference, or %NULL
2216  */
2217 GtkTreeRowReference *
2218 gtk_tree_row_reference_new_proxy (GObject      *proxy,
2219                                   GtkTreeModel *model,
2220                                   GtkTreePath  *path)
2221 {
2222   GtkTreeRowReference *reference;
2223   RowRefList *refs;
2224   GtkTreeIter parent_iter;
2225   gint i;
2226
2227   g_return_val_if_fail (G_IS_OBJECT (proxy), NULL);
2228   g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
2229   g_return_val_if_fail (path != NULL, NULL);
2230   g_return_val_if_fail (path->depth > 0, NULL);
2231
2232   /* check that the path is valid */
2233   if (gtk_tree_model_get_iter (model, &parent_iter, path) == FALSE)
2234     return NULL;
2235
2236   /* Now we want to ref every node */
2237   gtk_tree_model_iter_nth_child (model, &parent_iter, NULL, path->indices[0]);
2238   gtk_tree_model_ref_node (model, &parent_iter);
2239
2240   for (i = 1; i < path->depth; i++)
2241     {
2242       GtkTreeIter iter;
2243       gtk_tree_model_iter_nth_child (model, &iter, &parent_iter, path->indices[i]);
2244       gtk_tree_model_ref_node (model, &iter);
2245       parent_iter = iter;
2246     }
2247
2248   /* Make the row reference */
2249   reference = g_new (GtkTreeRowReference, 1);
2250
2251   g_object_ref (proxy);
2252   g_object_ref (model);
2253   reference->proxy = proxy;
2254   reference->model = model;
2255   reference->path = gtk_tree_path_copy (path);
2256
2257   refs = g_object_get_data (G_OBJECT (proxy), ROW_REF_DATA_STRING);
2258
2259   if (refs == NULL)
2260     {
2261       refs = g_new (RowRefList, 1);
2262       refs->list = NULL;
2263
2264       g_object_set_data_full (G_OBJECT (proxy),
2265                               I_(ROW_REF_DATA_STRING),
2266                               refs, release_row_references);
2267     }
2268
2269   refs->list = g_slist_prepend (refs->list, reference);
2270
2271   return reference;
2272 }
2273
2274 /**
2275  * gtk_tree_row_reference_get_path:
2276  * @reference: a #GtkTreeRowReference
2277  *
2278  * Returns a path that the row reference currently points to,
2279  * or %NULL if the path pointed to is no longer valid.
2280  *
2281  * Return value: a current path, or %NULL
2282  */
2283 GtkTreePath *
2284 gtk_tree_row_reference_get_path (GtkTreeRowReference *reference)
2285 {
2286   g_return_val_if_fail (reference != NULL, NULL);
2287
2288   if (reference->proxy == NULL)
2289     return NULL;
2290
2291   if (reference->path == NULL)
2292     return NULL;
2293
2294   return gtk_tree_path_copy (reference->path);
2295 }
2296
2297 /**
2298  * gtk_tree_row_reference_get_model:
2299  * @reference: a #GtkTreeRowReference
2300  *
2301  * Returns the model that the row reference is monitoring.
2302  *
2303  * Return value: (transfer none): the model
2304  *
2305  * Since: 2.8
2306  */
2307 GtkTreeModel *
2308 gtk_tree_row_reference_get_model (GtkTreeRowReference *reference)
2309 {
2310   g_return_val_if_fail (reference != NULL, NULL);
2311
2312   return reference->model;
2313 }
2314
2315 /**
2316  * gtk_tree_row_reference_valid:
2317  * @reference: (allow-none): a #GtkTreeRowReference, or %NULL
2318  *
2319  * Returns %TRUE if the @reference is non-%NULL and refers to
2320  * a current valid path.
2321  *
2322  * Return value: %TRUE if @reference points to a valid path
2323  */
2324 gboolean
2325 gtk_tree_row_reference_valid (GtkTreeRowReference *reference)
2326 {
2327   if (reference == NULL || reference->path == NULL)
2328     return FALSE;
2329
2330   return TRUE;
2331 }
2332
2333
2334 /**
2335  * gtk_tree_row_reference_copy:
2336  * @reference: a #GtkTreeRowReference
2337  *
2338  * Copies a #GtkTreeRowReference.
2339  *
2340  * Return value: a copy of @reference
2341  *
2342  * Since: 2.2
2343  */
2344 GtkTreeRowReference *
2345 gtk_tree_row_reference_copy (GtkTreeRowReference *reference)
2346 {
2347   return gtk_tree_row_reference_new_proxy (reference->proxy,
2348                                            reference->model,
2349                                            reference->path);
2350 }
2351
2352 /**
2353  * gtk_tree_row_reference_free:
2354  * @reference: (allow-none): a #GtkTreeRowReference, or %NULL
2355  *
2356  * Free's @reference. @reference may be %NULL
2357  */
2358 void
2359 gtk_tree_row_reference_free (GtkTreeRowReference *reference)
2360 {
2361   RowRefList *refs;
2362
2363   if (reference == NULL)
2364     return;
2365
2366   refs = g_object_get_data (G_OBJECT (reference->proxy), ROW_REF_DATA_STRING);
2367
2368   if (refs == NULL)
2369     {
2370       g_warning (G_STRLOC": bad row reference, proxy has no outstanding row references");
2371       return;
2372     }
2373
2374   refs->list = g_slist_remove (refs->list, reference);
2375
2376   if (refs->list == NULL)
2377     {
2378       g_object_set_data (G_OBJECT (reference->proxy),
2379                          I_(ROW_REF_DATA_STRING),
2380                          NULL);
2381     }
2382
2383   if (reference->path)
2384     {
2385       gtk_tree_row_reference_unref_path (reference->path, reference->model, reference->path->depth);
2386       gtk_tree_path_free (reference->path);
2387     }
2388
2389   g_object_unref (reference->proxy);
2390   g_object_unref (reference->model);
2391   g_free (reference);
2392 }
2393
2394 /**
2395  * gtk_tree_row_reference_inserted:
2396  * @proxy: a #GObject
2397  * @path: the row position that was inserted
2398  *
2399  * Lets a set of row reference created by
2400  * gtk_tree_row_reference_new_proxy() know that the
2401  * model emitted the #GtkTreeModel::row-inserted signal.
2402  */
2403 void
2404 gtk_tree_row_reference_inserted (GObject     *proxy,
2405                                  GtkTreePath *path)
2406 {
2407   g_return_if_fail (G_IS_OBJECT (proxy));
2408
2409   gtk_tree_row_ref_inserted ((RowRefList *)g_object_get_data (proxy, ROW_REF_DATA_STRING), path, NULL);
2410 }
2411
2412 /**
2413  * gtk_tree_row_reference_deleted:
2414  * @proxy: a #GObject
2415  * @path: the path position that was deleted
2416  *
2417  * Lets a set of row reference created by
2418  * gtk_tree_row_reference_new_proxy() know that the
2419  * model emitted the #GtkTreeModel::row-deleted signal.
2420  */
2421 void
2422 gtk_tree_row_reference_deleted (GObject     *proxy,
2423                                 GtkTreePath *path)
2424 {
2425   g_return_if_fail (G_IS_OBJECT (proxy));
2426
2427   gtk_tree_row_ref_deleted ((RowRefList *)g_object_get_data (proxy, ROW_REF_DATA_STRING), path);
2428 }
2429
2430 /**
2431  * gtk_tree_row_reference_reordered: (skip)
2432  * @proxy: a #GObject
2433  * @path: the parent path of the reordered signal
2434  * @iter: the iter pointing to the parent of the reordered
2435  * @new_order: the new order of rows
2436  *
2437  * Lets a set of row reference created by
2438  * gtk_tree_row_reference_new_proxy() know that the
2439  * model emitted the #GtkTreeModel::rows-reordered signal.
2440  */
2441 void
2442 gtk_tree_row_reference_reordered (GObject     *proxy,
2443                                   GtkTreePath *path,
2444                                   GtkTreeIter *iter,
2445                                   gint        *new_order)
2446 {
2447   g_return_if_fail (G_IS_OBJECT (proxy));
2448
2449   gtk_tree_row_ref_reordered ((RowRefList *)g_object_get_data (proxy, ROW_REF_DATA_STRING), path, iter, new_order);
2450 }