]> Pileus Git - ~andy/gtk/blob - gtk/gtktreemodel.c
ece4ed2519867a48ac62a773edda50c393892d95
[~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 <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <glib.h>
24 #include <gobject/gvaluecollector.h>
25 #include "gtktreemodel.h"
26 #include "gtktreeview.h"
27 #include "gtktreeprivate.h"
28 #include "gtkmarshalers.h"
29 #include "gtksignal.h"
30
31
32 struct _GtkTreePath
33 {
34   gint depth;
35   gint *indices;
36 };
37
38 static void gtk_tree_model_base_init (gpointer g_class);
39
40
41 GtkType
42 gtk_tree_model_get_type (void)
43 {
44   static GtkType tree_model_type = 0;
45
46   if (! tree_model_type)
47     {
48       static const GTypeInfo tree_model_info =
49       {
50         sizeof (GtkTreeModelIface), /* class_size */
51         gtk_tree_model_base_init,   /* base_init */
52         NULL,           /* base_finalize */
53         NULL,
54         NULL,           /* class_finalize */
55         NULL,           /* class_data */
56         0,
57         0,              /* n_preallocs */
58         NULL
59       };
60
61       tree_model_type = g_type_register_static (G_TYPE_INTERFACE, "GtkTreeModel", &tree_model_info, 0);
62       g_type_interface_add_prerequisite (tree_model_type, G_TYPE_OBJECT);
63     }
64
65   return tree_model_type;
66 }
67
68 static void
69 gtk_tree_model_base_init (gpointer g_class)
70 {
71   static gboolean initialized = FALSE;
72
73   if (! initialized)
74     {
75       g_signal_new ("row_changed",
76                     GTK_TYPE_TREE_MODEL,
77                     G_SIGNAL_RUN_LAST,
78                     G_STRUCT_OFFSET (GtkTreeModelIface, row_changed),
79                     NULL, NULL,
80                     _gtk_marshal_VOID__BOXED_BOXED,
81                     G_TYPE_NONE, 2,
82                     GTK_TYPE_TREE_PATH,
83                     GTK_TYPE_TREE_ITER);
84       g_signal_new ("row_inserted",
85                     GTK_TYPE_TREE_MODEL,
86                     G_SIGNAL_RUN_LAST,
87                     G_STRUCT_OFFSET (GtkTreeModelIface, row_inserted),
88                     NULL, NULL,
89                     _gtk_marshal_VOID__BOXED_BOXED,
90                     G_TYPE_NONE, 2,
91                     GTK_TYPE_TREE_PATH,
92                     GTK_TYPE_TREE_ITER);
93       g_signal_new ("row_has_child_toggled",
94                     GTK_TYPE_TREE_MODEL,
95                     G_SIGNAL_RUN_LAST,
96                     G_STRUCT_OFFSET (GtkTreeModelIface, row_has_child_toggled),
97                     NULL, NULL,
98                     _gtk_marshal_VOID__BOXED_BOXED,
99                     G_TYPE_NONE, 2,
100                     GTK_TYPE_TREE_PATH,
101                     GTK_TYPE_TREE_ITER);
102       g_signal_new ("row_deleted",
103                     GTK_TYPE_TREE_MODEL,
104                     G_SIGNAL_RUN_LAST,
105                     G_STRUCT_OFFSET (GtkTreeModelIface, row_deleted),
106                     NULL, NULL,
107                     _gtk_marshal_VOID__BOXED,
108                     G_TYPE_NONE, 1,
109                     GTK_TYPE_TREE_PATH);
110       g_signal_new ("rows_reordered",
111                     GTK_TYPE_TREE_MODEL,
112                     G_SIGNAL_RUN_LAST,
113                     G_STRUCT_OFFSET (GtkTreeModelIface, rows_reordered),
114                     NULL, NULL,
115                     _gtk_marshal_VOID__BOXED_BOXED_POINTER,
116                     G_TYPE_NONE, 3,
117                     GTK_TYPE_TREE_PATH,
118                     GTK_TYPE_TREE_ITER,
119                     G_TYPE_POINTER);
120       initialized = TRUE;
121     }
122 }
123
124 /**
125  * gtk_tree_path_new:
126  *
127  * Creates a new #GtkTreePath.  This structure refers to a row.
128  *
129  * Return value: A newly created #GtkTreePath.
130  **/
131 /* GtkTreePath Operations */
132 GtkTreePath *
133 gtk_tree_path_new (void)
134 {
135   GtkTreePath *retval;
136   retval = (GtkTreePath *) g_new (GtkTreePath, 1);
137   retval->depth = 0;
138   retval->indices = NULL;
139
140   return retval;
141 }
142
143 /**
144  * gtk_tree_path_new_from_string:
145  * @path: The string representation of a path.
146  *
147  * Creates a new #GtkTreePath initialized to @path.  @path is expected to be a
148  * colon separated list of numbers.  For example, the string "10:4:0" would
149  * create a path of depth 3 pointing to the 11th child of the root node, the 5th
150  * child of that 11th child, and the 1st child of that 5th child.  If an invalid
151  * path string is passed in, %NULL is returned.
152  *
153  * Return value: A newly-created #GtkTreePath, or %NULL
154  **/
155 GtkTreePath *
156 gtk_tree_path_new_from_string (const gchar *path)
157 {
158   GtkTreePath *retval;
159   const gchar *orig_path = path;
160   gchar *ptr;
161   gint i;
162
163   g_return_val_if_fail (path != NULL, NULL);
164   g_return_val_if_fail (*path != '\000', NULL);
165
166   retval = gtk_tree_path_new ();
167
168   while (1)
169     {
170       i = strtol (path, &ptr, 10);
171       gtk_tree_path_append_index (retval, i);
172
173       if (i < 0)
174         {
175           g_warning (G_STRLOC ": Negative numbers in path %s passed to gtk_tree_path_new_from_string", orig_path);
176           gtk_tree_path_free (retval);
177           return NULL;
178         }
179       if (*ptr == '\000')
180         break;
181       if (ptr == path || *ptr != ':')
182         {
183           g_warning (G_STRLOC ": Invalid path %s passed to gtk_tree_path_new_from_string", orig_path);
184           gtk_tree_path_free (retval);
185           return NULL;
186         }
187       path = ptr + 1;
188     }
189
190   return retval;
191 }
192
193 /**
194  * gtk_tree_path_to_string:
195  * @path: A #GtkTreePath
196  *
197  * Generates a string representation of the path.  This string is a ':'
198  * separated list of numbers.  For example, "4:10:0:3" would be an acceptable return value for this string.
199  *
200  * Return value: A newly-allocated string.  Must be freed with g_free().
201  **/
202 gchar *
203 gtk_tree_path_to_string (GtkTreePath *path)
204 {
205   gchar *retval, *ptr;
206   gint i;
207
208   g_return_val_if_fail (path != NULL, NULL);
209
210   if (path->depth == 0)
211     return NULL;
212
213   ptr = retval = (gchar *) g_new0 (char *, path->depth*8);
214   sprintf (retval, "%d", path->indices[0]);
215   while (*ptr != '\000')
216     ptr++;
217
218   for (i = 1; i < path->depth; i++)
219     {
220       sprintf (ptr, ":%d", path->indices[i]);
221       while (*ptr != '\000')
222         ptr++;
223     }
224
225   return retval;
226 }
227
228 /**
229  * gtk_tree_path_new_first:
230  *
231  * Creates a new #GtkTreePath.  The string representation of this path is "0"
232  *
233  * Return value: A new #GtkTreePath.
234  **/
235 GtkTreePath *
236 gtk_tree_path_new_first (void)
237 {
238   GtkTreePath *retval;
239
240   retval = gtk_tree_path_new ();
241   gtk_tree_path_append_index (retval, 0);
242
243   return retval;
244 }
245
246 /**
247  * gtk_tree_path_append_index:
248  * @path: A #GtkTreePath.
249  * @index: The index.
250  *
251  * Appends a new index to a path.  As a result, the depth of the path is
252  * increased.
253  **/
254 void
255 gtk_tree_path_append_index (GtkTreePath *path,
256                             gint         index)
257 {
258   g_return_if_fail (path != NULL);
259   g_return_if_fail (index >= 0);
260
261   path->depth += 1;
262   path->indices = g_realloc (path->indices, path->depth * sizeof(gint));
263   path->indices[path->depth - 1] = index;
264 }
265
266 /**
267  * gtk_tree_path_prepend_index:
268  * @path: A #GtkTreePath.
269  * @index: The index.
270  *
271  * Prepends a new index to a path.  As a result, the depth of the path is
272  * increased.
273  **/
274 void
275 gtk_tree_path_prepend_index (GtkTreePath *path,
276                              gint       index)
277 {
278   gint *new_indices = g_new (gint, ++path->depth);
279   if (path->indices == NULL)
280     {
281       path->indices = new_indices;
282       path->indices[0] = index;
283       return;
284     }
285   memcpy (new_indices + 1, path->indices, (path->depth - 1)*sizeof (gint));
286   g_free (path->indices);
287   path->indices = new_indices;
288   path->indices[0] = index;
289 }
290
291 /**
292  * gtk_tree_path_get_depth:
293  * @path: A #GtkTreePath.
294  *
295  * Returns the current depth of @path.
296  *
297  * Return value: The depth of @path
298  **/
299 gint
300 gtk_tree_path_get_depth (GtkTreePath *path)
301 {
302   g_return_val_if_fail (path != NULL, 0);
303
304   return path->depth;
305 }
306
307 /**
308  * gtk_tree_path_get_indices:
309  * @path: A #GtkTreePath.
310  *
311  * Returns the current indices of @path.  This is an array of integers, each
312  * representing a node in a tree.  This value should not be freed.
313  *
314  * Return value: The current indices, or %NULL.
315  **/
316 gint *
317 gtk_tree_path_get_indices (GtkTreePath *path)
318 {
319   g_return_val_if_fail (path != NULL, NULL);
320
321   return path->indices;
322 }
323
324 /**
325  * gtk_tree_path_free:
326  * @path: A #GtkTreePath.
327  *
328  * Frees @path.
329  **/
330 void
331 gtk_tree_path_free (GtkTreePath *path)
332 {
333   g_return_if_fail (path != NULL);
334
335   g_free (path->indices);
336   g_free (path);
337 }
338
339 /**
340  * gtk_tree_path_copy:
341  * @path: A #GtkTreePath.
342  *
343  * Creates a new #GtkTreePath as a copy of @path.
344  *
345  * Return value: A new #GtkTreePath.
346  **/
347 GtkTreePath *
348 gtk_tree_path_copy (GtkTreePath *path)
349 {
350   GtkTreePath *retval;
351
352   g_return_val_if_fail (path != NULL, NULL);
353
354   retval = g_new (GtkTreePath, 1);
355   retval->depth = path->depth;
356   retval->indices = g_new (gint, path->depth);
357   memcpy (retval->indices, path->indices, path->depth * sizeof (gint));
358   return retval;
359 }
360
361 GType
362 gtk_tree_path_get_type (void)
363 {
364   static GType our_type = 0;
365   
366   if (our_type == 0)
367     our_type = g_boxed_type_register_static ("GtkTypeTreePath",
368                                              (GBoxedCopyFunc) gtk_tree_path_copy,
369                                              (GBoxedFreeFunc) gtk_tree_path_free);
370
371   return our_type;
372 }
373
374 /**
375  * gtk_tree_path_compare:
376  * @a: A #GtkTreePath.
377  * @b: A #GtkTreePath to compare with.
378  *
379  * Compares two paths.  If @a appears before @b in a tree, then -1 is returned.
380  * If @b appears before @a, then 1 is returned.  If the two nodes are equal,
381  * then 0 is returned.
382  *
383  * Return value: The relative positions of @a and @b
384  **/
385 gint
386 gtk_tree_path_compare (const GtkTreePath *a,
387                        const GtkTreePath *b)
388 {
389   gint p = 0, q = 0;
390
391   g_return_val_if_fail (a != NULL, 0);
392   g_return_val_if_fail (b != NULL, 0);
393   g_return_val_if_fail (a->depth > 0, 0);
394   g_return_val_if_fail (b->depth > 0, 0);
395
396   do
397     {
398       if (a->indices[p] == b->indices[q])
399         continue;
400       return (a->indices[p] < b->indices[q]?-1:1);
401     }
402   while (++p < a->depth && ++q < b->depth);
403   if (a->depth == b->depth)
404     return 0;
405   return (a->depth < b->depth?-1:1);
406 }
407
408 /**
409  * gtk_tree_path_is_ancestor:
410  * @path: a #GtkTreePath
411  * @descendant: another #GtkTreePath
412  *
413  * Returns %TRUE if @descendant is a descendant of @path.
414  *
415  * Return value: %TRUE if @descendant is contained inside @path
416  **/
417 gboolean
418 gtk_tree_path_is_ancestor (GtkTreePath *path,
419                            GtkTreePath *descendant)
420 {
421   gint i;
422
423   g_return_val_if_fail (path != NULL, FALSE);
424   g_return_val_if_fail (descendant != NULL, FALSE);
425
426   /* can't be an ancestor if we're deeper */
427   if (path->depth >= descendant->depth)
428     return FALSE;
429
430   i = 0;
431   while (i < path->depth)
432     {
433       if (path->indices[i] != descendant->indices[i])
434         return FALSE;
435       ++i;
436     }
437
438   return TRUE;
439 }
440
441 /**
442  * gtk_tree_path_is_descendant:
443  * @path: a #GtkTreePath
444  * @ancestor: another #GtkTreePath
445  *
446  * Returns %TRUE if @path is a descendant of @ancestor.
447  *
448  * Return value: %TRUE if @ancestor contains @path somewhere below it
449  **/
450 gboolean
451 gtk_tree_path_is_descendant (GtkTreePath *path,
452                              GtkTreePath *ancestor)
453 {
454   gint i;
455
456   g_return_val_if_fail (path != NULL, FALSE);
457   g_return_val_if_fail (ancestor != NULL, FALSE);
458
459   /* can't be a descendant if we're shallower in the tree */
460   if (path->depth <= ancestor->depth)
461     return FALSE;
462
463   i = 0;
464   while (i < ancestor->depth)
465     {
466       if (path->indices[i] != ancestor->indices[i])
467         return FALSE;
468       ++i;
469     }
470
471   return TRUE;
472 }
473
474
475 /**
476  * gtk_tree_path_next:
477  * @path: A #GtkTreePath.
478  *
479  * Moves the @path to point to the next node at the current depth.
480  **/
481 void
482 gtk_tree_path_next (GtkTreePath *path)
483 {
484   g_return_if_fail (path != NULL);
485   g_return_if_fail (path->depth > 0);
486
487   path->indices[path->depth - 1] ++;
488 }
489
490 /**
491  * gtk_tree_path_prev:
492  * @path: A #GtkTreePath.
493  *
494  * Moves the @path to point to the previous node at the current depth, if it exists.
495  *
496  * Return value: %TRUE if @path has a previous node, and the move was made.
497  **/
498 gboolean
499 gtk_tree_path_prev (GtkTreePath *path)
500 {
501   g_return_val_if_fail (path != NULL, FALSE);
502
503   if (path->indices[path->depth - 1] == 0)
504     return FALSE;
505
506   path->indices[path->depth - 1] -= 1;
507
508   return TRUE;
509 }
510
511 /**
512  * gtk_tree_path_up:
513  * @path: A #GtkTreePath.
514  *
515  * Moves the @path to point to it's parent node, if it has a parent.
516  *
517  * Return value: %TRUE if @path has a parent, and the move was made.
518  **/
519 gboolean
520 gtk_tree_path_up (GtkTreePath *path)
521 {
522   g_return_val_if_fail (path != NULL, FALSE);
523
524   if (path->depth == 0)
525     return FALSE;
526
527   path->depth--;
528
529   return TRUE;
530 }
531
532 /**
533  * gtk_tree_path_down:
534  * @path: A #GtkTreePath.
535  *
536  * Moves @path to point to the first child of the current path.
537  **/
538 void
539 gtk_tree_path_down (GtkTreePath *path)
540 {
541   g_return_if_fail (path != NULL);
542
543   gtk_tree_path_append_index (path, 0);
544 }
545
546 /**
547  * gtk_tree_iter_copy:
548  * @iter: A #GtkTreeIter.
549  *
550  * Creates a dynamically allocated tree iterator as a copy of @iter.  This
551  * function is not intended for use in applications, because you can just copy
552  * the structs by value (<literal>GtkTreeIter new_iter = iter;</literal>).  You
553  * must free this iter with gtk_tree_iter_free ().
554  *
555  * Return value: a newly-allocated copy of @iter.
556  **/
557 GtkTreeIter *
558 gtk_tree_iter_copy (GtkTreeIter *iter)
559 {
560   GtkTreeIter *retval;
561
562   g_return_val_if_fail (iter != NULL, NULL);
563
564   retval = g_new (GtkTreeIter, 1);
565   *retval = *iter;
566
567   return retval;
568 }
569
570 /**
571  * gtk_tree_iter_free:
572  * @iter: A dynamically allocated tree iterator.
573  *
574  * Frees an iterator that has been allocated on the heap.  This function is
575  * mainly used for language bindings.
576  **/
577 void
578 gtk_tree_iter_free (GtkTreeIter *iter)
579 {
580   g_return_if_fail (iter != NULL);
581
582   g_free (iter);
583 }
584
585 GType
586 gtk_tree_iter_get_type (void)
587 {
588   static GType our_type = 0;
589   
590   if (our_type == 0)
591     our_type = g_boxed_type_register_static ("GtkTypeTreeIter",
592                                              (GBoxedCopyFunc) gtk_tree_iter_copy,
593                                              (GBoxedFreeFunc) gtk_tree_iter_free);
594
595   return our_type;
596 }
597
598 /**
599  * gtk_tree_model_get_flags:
600  * @tree_model: A #GtkTreeModel.
601  *
602  * Returns a set of flags supported by this interface.  The flags are a bitwise
603  * combination of #GtkTreeModelFlags.  The flags supported should not change
604  * during the lifecycle of the tree_model.
605  *
606  * Return value: The flags supported by this interface.
607  **/
608 GtkTreeModelFlags
609 gtk_tree_model_get_flags (GtkTreeModel *tree_model)
610 {
611   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
612
613   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_flags)
614     return (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_flags) (tree_model);
615
616   return 0;
617 }
618
619 /**
620  * gtk_tree_model_get_n_columns:
621  * @tree_model: A #GtkTreeModel.
622  *
623  * Returns the number of columns supported by @tree_model.
624  *
625  * Return value: The number of columns.
626  **/
627 gint
628 gtk_tree_model_get_n_columns (GtkTreeModel *tree_model)
629 {
630   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
631   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_n_columns != NULL, 0);
632
633   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_n_columns) (tree_model);
634 }
635
636 /**
637  * gtk_tree_model_get_column_type:
638  * @tree_model: A #GtkTreeModel.
639  * @index: The column index.
640  *
641  * Returns the type of the column.
642  *
643  * Return value: The type of the column.
644  **/
645 GType
646 gtk_tree_model_get_column_type (GtkTreeModel *tree_model,
647                                 gint          index)
648 {
649   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), G_TYPE_INVALID);
650   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_column_type != NULL, G_TYPE_INVALID);
651   g_return_val_if_fail (index >= 0, G_TYPE_INVALID);
652
653   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_column_type) (tree_model, index);
654 }
655
656 /**
657  * gtk_tree_model_get_iter:
658  * @tree_model: A #GtkTreeModel.
659  * @iter: The uninitialized #GtkTreeIter.
660  * @path: The #GtkTreePath.
661  *
662  * Sets @iter to a valid iterator pointing to @path.
663  *
664  * Return value: %TRUE, if @iter was set.
665  **/
666 gboolean
667 gtk_tree_model_get_iter (GtkTreeModel *tree_model,
668                          GtkTreeIter  *iter,
669                          GtkTreePath  *path)
670 {
671   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
672   g_return_val_if_fail (iter != NULL, FALSE);
673   g_return_val_if_fail (path != NULL, FALSE);
674   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_iter != NULL, FALSE);
675   g_return_val_if_fail (path->depth > 0, FALSE);
676
677   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_iter) (tree_model, iter, path);
678 }
679
680 /**
681  * gtk_tree_model_get_iter_from_string:
682  * @tree_model: A #GtkTreeModel.
683  * @iter: An uninitialized #GtkTreeIter.
684  * @path_string: A string representation of a #GtkTreePath.
685  *
686  * Sets @iter to a valid iterator pointing to @path_string, if it
687  * exists. Otherwise, @iter is left invalid and %FALSE is returned.
688  *
689  * Return value: %TRUE, if @iter was set.
690  **/
691 gboolean
692 gtk_tree_model_get_iter_from_string (GtkTreeModel *tree_model,
693                                      GtkTreeIter  *iter,
694                                      const gchar  *path_string)
695 {
696   gboolean retval;
697   GtkTreePath *path;
698
699   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
700   g_return_val_if_fail (iter != NULL, FALSE);
701   g_return_val_if_fail (path_string != NULL, FALSE);
702   
703   path = gtk_tree_path_new_from_string (path_string);
704   
705   g_return_val_if_fail (path != NULL, FALSE);
706
707   retval = gtk_tree_model_get_iter (tree_model, iter, path);
708   gtk_tree_path_free (path);
709   
710   return retval;
711 }
712
713
714 /**
715  * gtk_tree_model_get_iter_first:
716  * @tree_model: A #GtkTreeModel.
717  * @iter: The uninitialized #GtkTreeIter.
718  * 
719  * Initializes @iter with the first iterator in the tree (the one at the path
720  * "0") and returns %TRUE.  Returns %FALSE if the tree is empty.
721  * 
722  * Return value: %TRUE, if @iter was set.
723  **/
724 gboolean
725 gtk_tree_model_get_iter_first (GtkTreeModel *tree_model,
726                                GtkTreeIter  *iter)
727 {
728   GtkTreePath *path;
729   gboolean retval;
730
731   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
732   g_return_val_if_fail (iter != NULL, FALSE);
733
734   path = gtk_tree_path_new_first ();
735   retval = gtk_tree_model_get_iter (tree_model, iter, path);
736   gtk_tree_path_free (path);
737
738   return retval;
739 }
740
741 /**
742  * gtk_tree_model_get_path:
743  * @tree_model: A #GtkTreeModel.
744  * @iter: The #GtkTreeIter.
745  *
746  * Returns a newly-created #GtkTreePath referenced by @iter.  This path should
747  * be freed with gtk_tree_path_free().
748  *
749  * Return value: a newly-created #GtkTreePath.
750  **/
751 GtkTreePath *
752 gtk_tree_model_get_path (GtkTreeModel *tree_model,
753                          GtkTreeIter  *iter)
754 {
755   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), NULL);
756   g_return_val_if_fail (iter != NULL, NULL);
757   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_path != NULL, NULL);
758
759   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_path) (tree_model, iter);
760 }
761
762 /**
763  * gtk_tree_model_get_value:
764  * @tree_model: A #GtkTreeModel.
765  * @iter: The #GtkTreeIter.
766  * @column: The column to lookup the value at.
767  * @value: An empty #GValue to set.
768  *
769  * Sets initializes and sets @value to that at @column.  When done with @value,
770  * g_value_unset() needs to be called to free any allocated memory.
771  **/
772 void
773 gtk_tree_model_get_value (GtkTreeModel *tree_model,
774                           GtkTreeIter  *iter,
775                           gint          column,
776                           GValue       *value)
777 {
778   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
779   g_return_if_fail (iter != NULL);
780   g_return_if_fail (value != NULL);
781   g_return_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_value != NULL);
782
783   (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_value) (tree_model, iter, column, value);
784 }
785
786 /**
787  * gtk_tree_model_iter_next:
788  * @tree_model: A #GtkTreeModel.
789  * @iter: The #GtkTreeIter.
790  *
791  * Sets @iter to point to the node following it at the current level.  If there
792  * is no next @iter, %FALSE is returned and @iter is set to be invalid.
793  *
794  * Return value: %TRUE if @iter has been changed to the next node.
795  **/
796 gboolean
797 gtk_tree_model_iter_next (GtkTreeModel  *tree_model,
798                           GtkTreeIter   *iter)
799 {
800   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
801   g_return_val_if_fail (iter != NULL, FALSE);
802   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_next != NULL, FALSE);
803
804   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_next) (tree_model, iter);
805 }
806
807 /**
808  * gtk_tree_model_iter_children:
809  * @tree_model: A #GtkTreeModel.
810  * @iter: The new #GtkTreeIter to be set to the child.
811  * @parent: The #GtkTreeIter.
812  *
813  * Sets @iter to point to the first child of @parent.  If @parent has no children,
814  * %FALSE is returned and @iter is set to be invalid.  @parent will remain a valid
815  * node after this function has been called.
816  *
817  * Return value: %TRUE, if @child has been set to the first child.
818  **/
819 gboolean
820 gtk_tree_model_iter_children (GtkTreeModel *tree_model,
821                               GtkTreeIter  *iter,
822                               GtkTreeIter  *parent)
823 {
824   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
825   g_return_val_if_fail (iter != NULL, FALSE);
826   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_children != NULL, FALSE);
827
828   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_children) (tree_model, iter, parent);
829 }
830
831 /**
832  * gtk_tree_model_iter_has_child:
833  * @tree_model: A #GtkTreeModel.
834  * @iter: The #GtkTreeIter to test for children.
835  *
836  * Returns %TRUE if @iter has children, %FALSE otherwise.
837  *
838  * Return value: %TRUE if @iter has children.
839  **/
840 gboolean
841 gtk_tree_model_iter_has_child (GtkTreeModel *tree_model,
842                                GtkTreeIter  *iter)
843 {
844   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
845   g_return_val_if_fail (iter != NULL, FALSE);
846   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_has_child != NULL, FALSE);
847
848   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_has_child) (tree_model, iter);
849 }
850
851 /**
852  * gtk_tree_model_iter_n_children:
853  * @tree_model: A #GtkTreeModel.
854  * @iter: The #GtkTreeIter, or %NULL.
855  *
856  * Returns the number of children that @iter has.  As a special case, if @iter
857  * is %NULL, then the number of toplevel nodes is returned.
858  *
859  * Return value: The number of children of @iter.
860  **/
861 gint
862 gtk_tree_model_iter_n_children (GtkTreeModel *tree_model,
863                                 GtkTreeIter  *iter)
864 {
865   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
866   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_n_children != NULL, 0);
867
868   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_n_children) (tree_model, iter);
869 }
870
871 /**
872  * gtk_tree_model_iter_nth_child:
873  * @tree_model: A #GtkTreeModel.
874  * @iter: The #GtkTreeIter to set to the nth child.
875  * @parent: The #GtkTreeIter to get the child from, or %NULL.
876  * @n: Then index of the desired child.
877  *
878  * Sets @iter to be the child of @parent, using the given index.  The first
879  * index is 0.  If @index is too big, or @parent has no children, @iter is set
880  * to an invalid iterator and %FALSE is returned.  @parent will remain a valid
881  * node after this function has been called.  As a special case, if @parent is
882  * %NULL, then the @n<!>th root node is set.
883  *
884  * Return value: %TRUE, if @parent has an @n<!>th child.
885  **/
886 gboolean
887 gtk_tree_model_iter_nth_child (GtkTreeModel *tree_model,
888                                GtkTreeIter  *iter,
889                                GtkTreeIter  *parent,
890                                gint          n)
891 {
892   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
893   g_return_val_if_fail (iter != NULL, FALSE);
894   g_return_val_if_fail (n >= 0, FALSE);
895   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_nth_child != NULL, FALSE);
896
897   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_nth_child) (tree_model, iter, parent, n);
898 }
899
900 /**
901  * gtk_tree_model_iter_parent:
902  * @tree_model: A #GtkTreeModel
903  * @iter: The new #GtkTreeIter to set to the parent.
904  * @child: The #GtkTreeIter.
905  *
906  * Sets @iter to be the parent of @child.  If @child is at the toplevel, and
907  * doesn't have a parent, then @iter is set to an invalid iterator and %FALSE
908  * is returned.  @child will remain a valid node after this function has been
909  * called.
910  *
911  * Return value: %TRUE, if @iter is set to the parent of @child.
912  **/
913 gboolean
914 gtk_tree_model_iter_parent (GtkTreeModel *tree_model,
915                             GtkTreeIter  *iter,
916                             GtkTreeIter  *child)
917 {
918   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
919   g_return_val_if_fail (iter != NULL, FALSE);
920   g_return_val_if_fail (child != NULL, FALSE);
921   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_parent != NULL, FALSE);
922
923   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_parent) (tree_model, iter, child);
924 }
925
926 /**
927  * gtk_tree_model_ref_node:
928  * @tree_model: A #GtkTreeModel.
929  * @iter: The #GtkTreeIter.
930  *
931  * Lets the tree ref the node.  This is an optional method for models to
932  * implement.  To be more specific, models may ignore this call as it exists
933  * primarily for performance reasons.
934  * 
935  * This function is primarily meant as a way for views to let caching model know
936  * when nodes are being displayed (and hence, whether or not to cache that
937  * node.)  For example, a file-system based model would not want to keep the
938  * entire file-hierarchy in memory, just the sections that are currently being
939  * displayed by every current view.
940  *
941  * A model should be expected to be able to get an iter independent of it's
942  * reffed state.
943  **/
944 void
945 gtk_tree_model_ref_node (GtkTreeModel *tree_model,
946                          GtkTreeIter  *iter)
947 {
948   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
949
950   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->ref_node)
951     (* GTK_TREE_MODEL_GET_IFACE (tree_model)->ref_node) (tree_model, iter);
952 }
953
954 /**
955  * gtk_tree_model_unref_node:
956  * @tree_model: A #GtkTreeModel.
957  * @iter: The #GtkTreeIter.
958  *
959  * Lets the tree unref the node.  This is an optional method for models to
960  * implement.  To be more specific, models may ignore this call as it exists
961  * primarily for performance reasons.
962  *
963  * For more information on what this means, see gtk_tree_model_ref_node().
964  * Please note that nodes that are deleted are not unreffed.
965  **/
966 void
967 gtk_tree_model_unref_node (GtkTreeModel *tree_model,
968                            GtkTreeIter  *iter)
969 {
970   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
971   g_return_if_fail (iter != NULL);
972
973   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->unref_node)
974     (* GTK_TREE_MODEL_GET_IFACE (tree_model)->unref_node) (tree_model, iter);
975 }
976
977 /**
978  * gtk_tree_model_get:
979  * @tree_model: a #GtkTreeModel
980  * @iter: a row in @tree_model
981  * @Varargs: pairs of column number and value return locations, terminated by -1
982  *
983  * Gets the value of one or more cells in the row referenced by @iter.
984  * The variable argument list should contain integer column numbers,
985  * each column number followed by a place to store the value being
986  * retrieved.  The list is terminated by a -1. For example, to get a
987  * value from column 0 with type %G_TYPE_STRING, you would
988  * write: <literal>gtk_tree_model_get (model, iter, 0, &amp;place_string_here, -1)</literal>,
989  * where <literal>place_string_here</literal> is a <type>gchar*</type> to be 
990  * filled with the string.
991  * If appropriate, the returned values have to be freed or unreferenced.
992  *
993  **/
994 void
995 gtk_tree_model_get (GtkTreeModel *tree_model,
996                     GtkTreeIter  *iter,
997                     ...)
998 {
999   va_list var_args;
1000
1001   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1002   g_return_if_fail (iter != NULL);
1003
1004   va_start (var_args, iter);
1005   gtk_tree_model_get_valist (tree_model, iter, var_args);
1006   va_end (var_args);
1007 }
1008
1009 /**
1010  * gtk_tree_model_get_valist:
1011  * @tree_model: a #GtkTreeModel
1012  * @iter: a row in @tree_model
1013  * @var_args: <type>va_list</type> of column/return location pairs
1014  *
1015  * See gtk_tree_model_get(), this version takes a <type>va_list</type> 
1016  * for language bindings to use.
1017  **/
1018 void
1019 gtk_tree_model_get_valist (GtkTreeModel *tree_model,
1020                            GtkTreeIter  *iter,
1021                            va_list      var_args)
1022 {
1023   gint column;
1024
1025   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1026   g_return_if_fail (iter != NULL);
1027
1028   column = va_arg (var_args, gint);
1029
1030   while (column != -1)
1031     {
1032       GValue value = { 0, };
1033       gchar *error = NULL;
1034
1035       if (column >= gtk_tree_model_get_n_columns (tree_model))
1036         {
1037           g_warning ("%s: Invalid column number %d accessed (remember to end your list of columns with a -1)", G_STRLOC, column);
1038           break;
1039         }
1040
1041       gtk_tree_model_get_value (GTK_TREE_MODEL (tree_model), iter, column, &value);
1042
1043       G_VALUE_LCOPY (&value, var_args, 0, &error);
1044       if (error)
1045         {
1046           g_warning ("%s: %s", G_STRLOC, error);
1047           g_free (error);
1048
1049           /* we purposely leak the value here, it might not be
1050            * in a sane state if an error condition occoured
1051            */
1052           break;
1053         }
1054
1055       g_value_unset (&value);
1056
1057       column = va_arg (var_args, gint);
1058     }
1059 }
1060
1061 /**
1062  * gtk_tree_model_row_changed:
1063  * @tree_model: A #GtkTreeModel
1064  * @path: A #GtkTreePath pointing to the changed row
1065  * @iter: A valid #GtkTreeIter pointing to the changed row
1066  * 
1067  * Emits the "row_changed" signal on @tree_model.
1068  **/
1069 void
1070 gtk_tree_model_row_changed (GtkTreeModel *tree_model,
1071                             GtkTreePath  *path,
1072                             GtkTreeIter  *iter)
1073 {
1074   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1075   g_return_if_fail (path != NULL);
1076   g_return_if_fail (iter != NULL);
1077
1078   g_signal_emit_by_name (tree_model, "row_changed", path, iter);
1079 }
1080
1081 /**
1082  * gtk_tree_model_row_inserted:
1083  * @tree_model: A #GtkTreeModel
1084  * @path: A #GtkTreePath pointing to the inserted row
1085  * @iter: A valid #GtkTreeIter pointing to the inserted row
1086  * 
1087  * Emits the "row_inserted" signal on @tree_model
1088  **/
1089 void
1090 gtk_tree_model_row_inserted (GtkTreeModel *tree_model,
1091                              GtkTreePath  *path,
1092                              GtkTreeIter  *iter)
1093 {
1094   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1095   g_return_if_fail (path != NULL);
1096   g_return_if_fail (iter != NULL);
1097
1098   g_signal_emit_by_name (tree_model, "row_inserted", path, iter);
1099 }
1100
1101 /**
1102  * gtk_tree_model_row_has_child_toggled:
1103  * @tree_model: A #GtkTreeModel
1104  * @path: A #GtkTreePath pointing to the changed row
1105  * @iter: A valid #GtkTreeIter pointing to the changed row
1106  * 
1107  * Emits the "row_has_child_toggled" signal on @tree_model.  This should be
1108  * called by models after the child state of a node changes.
1109  **/
1110 void
1111 gtk_tree_model_row_has_child_toggled (GtkTreeModel *tree_model,
1112                                       GtkTreePath  *path,
1113                                       GtkTreeIter  *iter)
1114 {
1115   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1116   g_return_if_fail (path != NULL);
1117   g_return_if_fail (iter != NULL);
1118
1119   g_signal_emit_by_name (tree_model, "row_has_child_toggled", path, iter);
1120 }
1121
1122 /**
1123  * gtk_tree_model_row_deleted:
1124  * @tree_model: A #GtkTreeModel
1125  * @path: A #GtkTreePath pointing to the previous location of the deleted row.
1126  * 
1127  * Emits the "row_deleted" signal on @tree_model.  This should be called by
1128  * models after a row has been removed.  The location pointed to by @path should
1129  * be the location that the row previously was at.  It may not be a valid
1130  * location anymore.
1131  **/
1132 void
1133 gtk_tree_model_row_deleted (GtkTreeModel *tree_model,
1134                             GtkTreePath  *path)
1135 {
1136   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1137   g_return_if_fail (path != NULL);
1138
1139   g_signal_emit_by_name (tree_model, "row_deleted", path);
1140 }
1141
1142 /**
1143  * gtk_tree_model_rows_reordered:
1144  * @tree_model: A #GtkTreeModel
1145  * @path: A #GtkTreePath pointing to the tree node whose children have been reordered
1146  * @iter: A valid #GtkTreeIter pointing to the node whose children have been reordered
1147  * @new_order: an array of integers containing the new indices of the children,
1148  *      i.e. the former child <literal>n</literal> is now at position
1149  *      @new_order<literal>[n]</literal>. 
1150  * 
1151  * Emits the "rows_reordered" signal on @tree_model.  This should be called by
1152  * models when their rows have been reordered.  
1153  **/
1154 void
1155 gtk_tree_model_rows_reordered (GtkTreeModel *tree_model,
1156                                GtkTreePath  *path,
1157                                GtkTreeIter  *iter,
1158                                gint         *new_order)
1159 {
1160   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1161   g_return_if_fail (new_order != NULL);
1162
1163   g_signal_emit_by_name (tree_model, "rows_reordered", path, iter, new_order);
1164 }
1165
1166
1167 static gboolean
1168 gtk_tree_model_foreach_helper (GtkTreeModel            *model,
1169                                GtkTreeIter             *iter,
1170                                GtkTreePath             *path,
1171                                GtkTreeModelForeachFunc  func,
1172                                gpointer                 user_data)
1173 {
1174   gtk_tree_path_append_index (path, 0);
1175
1176   do
1177     {
1178       GtkTreeIter child;
1179
1180       if (gtk_tree_model_iter_children (model, &child, iter))
1181         {
1182           if (gtk_tree_model_foreach_helper (model, &child, path, func, user_data))
1183             return TRUE;
1184         }
1185
1186       if ((* func) (model, path, iter, user_data))
1187         return TRUE;
1188
1189       gtk_tree_path_next (path);
1190     }
1191   while (gtk_tree_model_iter_next (model, iter));
1192
1193   gtk_tree_path_up (path);
1194   return FALSE;
1195 }
1196
1197 /**
1198  * gtk_tree_model_foreach:
1199  * @model: A #GtkTreeModel
1200  * @func: A function to be called on each row
1201  * @user_data: User data to passed to func.
1202  * 
1203  * Calls func on each node in model in a depth-first fashion.  If func returns
1204  * %TRUE, then the tree ceases to be walked, and gtk_tree_model_foreach() returns.
1205  **/
1206
1207 void
1208 gtk_tree_model_foreach (GtkTreeModel            *model,
1209                         GtkTreeModelForeachFunc  func,
1210                         gpointer                 user_data)
1211 {
1212   GtkTreePath *path;
1213   GtkTreeIter iter;
1214
1215   g_return_if_fail (GTK_IS_TREE_MODEL (model));
1216   g_return_if_fail (func != NULL);
1217
1218   path = gtk_tree_path_new_first ();
1219   if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
1220     {
1221       gtk_tree_path_free (path);
1222       return;
1223     }
1224
1225   gtk_tree_model_foreach_helper (model, &iter, path, func, user_data);
1226   gtk_tree_path_free (path);
1227 }
1228
1229
1230 /*
1231  * GtkTreeRowReference
1232  */
1233
1234 static void gtk_tree_row_reference_unref_path (GtkTreePath  *path,
1235                                                GtkTreeModel *model,
1236                                                gint          depth);
1237
1238
1239 #define ROW_REF_DATA_STRING "gtk-tree-row-refs"
1240
1241 struct _GtkTreeRowReference
1242 {
1243   GObject *proxy;
1244   GtkTreeModel *model;
1245   GtkTreePath *path;
1246 };
1247
1248 typedef struct
1249 {
1250   GSList *list;
1251 } RowRefList;
1252
1253
1254 static void
1255 release_row_references (gpointer data)
1256 {
1257   RowRefList *refs = data;
1258   GSList *tmp_list = NULL;
1259
1260   tmp_list = refs->list;
1261   while (tmp_list != NULL)
1262     {
1263       GtkTreeRowReference *reference = tmp_list->data;
1264
1265       if (reference->proxy == (GObject *)reference->model)
1266         reference->model = NULL;
1267       reference->proxy = NULL;
1268
1269       /* we don't free the reference, users are responsible for that. */
1270
1271       tmp_list = g_slist_next (tmp_list);
1272     }
1273
1274   g_slist_free (refs->list);
1275   g_free (refs);
1276 }
1277
1278 static void
1279 gtk_tree_row_ref_inserted_callback (GObject     *object,
1280                                     GtkTreePath *path,
1281                                     GtkTreeIter *iter,
1282                                     gpointer     data)
1283 {
1284   RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING);
1285
1286   GSList *tmp_list;
1287
1288   if (refs == NULL)
1289     return;
1290
1291   /* This function corrects the path stored in the reference to
1292    * account for an insertion. Note that it's called _after_ the insertion
1293    * with the path to the newly-inserted row. Which means that
1294    * the inserted path is in a different "coordinate system" than
1295    * the old path (e.g. if the inserted path was just before the old path,
1296    * then inserted path and old path will be the same, and old path must be
1297    * moved down one).
1298    */
1299
1300   tmp_list = refs->list;
1301
1302   while (tmp_list != NULL)
1303     {
1304       GtkTreeRowReference *reference = tmp_list->data;
1305
1306       if (reference->path == NULL)
1307         goto done;
1308
1309       if (reference->path->depth >= path->depth)
1310         {
1311           gint i;
1312           gboolean ancestor = TRUE;
1313
1314           for (i = 0; i < path->depth - 1; i ++)
1315             {
1316               if (path->indices[i] != reference->path->indices[i])
1317                 {
1318                   ancestor = FALSE;
1319                   break;
1320                 }
1321             }
1322           if (ancestor == FALSE)
1323             goto done;
1324
1325           if (path->indices[path->depth-1] <= reference->path->indices[path->depth-1])
1326             reference->path->indices[path->depth-1] += 1;
1327         }
1328     done:
1329       tmp_list = g_slist_next (tmp_list);
1330     }
1331 }
1332
1333 static void
1334 gtk_tree_row_ref_deleted_callback (GObject     *object,
1335                                    GtkTreePath *path,
1336                                    gpointer     data)
1337 {
1338   RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING);
1339   GSList *tmp_list;
1340
1341   if (refs == NULL)
1342     return;
1343
1344   /* This function corrects the path stored in the reference to
1345    * account for an deletion. Note that it's called _after_ the
1346    * deletion with the old path of the just-deleted row. Which means
1347    * that the deleted path is the same now-defunct "coordinate system"
1348    * as the path saved in the reference, which is what we want to fix.
1349    */
1350
1351   tmp_list = refs->list;
1352
1353   while (tmp_list != NULL)
1354     {
1355       GtkTreeRowReference *reference = tmp_list->data;
1356
1357       if (reference->path)
1358         {
1359           gint i;
1360
1361           if (path->depth > reference->path->depth)
1362             goto next;
1363           for (i = 0; i < path->depth - 1; i++)
1364             {
1365               if (path->indices[i] != reference->path->indices[i])
1366                 goto next;
1367             }
1368
1369           /* We know it affects us. */
1370           if (path->indices[i] == reference->path->indices[i])
1371             {
1372               gtk_tree_row_reference_unref_path (reference->path, reference->model, reference->path->depth - 1);
1373               gtk_tree_path_free (reference->path);
1374               reference->path = NULL;
1375             }
1376           else if (path->indices[i] < reference->path->indices[i])
1377             {
1378               reference->path->indices[path->depth-1]-=1;
1379             }
1380         }
1381
1382 next:
1383       tmp_list = g_slist_next (tmp_list);
1384     }
1385 }
1386
1387 static void
1388 gtk_tree_row_ref_reordered_callback (GObject     *object,
1389                                      GtkTreePath *path,
1390                                      GtkTreeIter *iter,
1391                                      gint        *new_order,
1392                                      gpointer     data)
1393 {
1394   RowRefList *refs = g_object_get_data (data, ROW_REF_DATA_STRING);
1395   GSList *tmp_list;
1396   gint length;
1397
1398   if (refs == NULL)
1399     return;
1400
1401   tmp_list = refs->list;
1402
1403   while (tmp_list != NULL)
1404     {
1405       GtkTreeRowReference *reference = tmp_list->data;
1406
1407       length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (reference->model), iter);
1408
1409       if (length < 2)
1410         return;
1411
1412       if ((reference->path) &&
1413           (gtk_tree_path_is_ancestor (path, reference->path)))
1414         {
1415           gint ref_depth = gtk_tree_path_get_depth (reference->path);
1416           gint depth = gtk_tree_path_get_depth (path);
1417
1418           if (ref_depth > depth)
1419             {
1420               gint i;
1421               gint *indices = gtk_tree_path_get_indices (reference->path);
1422
1423               for (i = 0; i < length; i++)
1424                 {
1425                   if (new_order[i] == indices[depth])
1426                     {
1427                       indices[depth] = i;
1428                       break;
1429                     }
1430                 }
1431             }
1432         }
1433
1434       tmp_list = g_slist_next (tmp_list);
1435     }
1436   
1437 }
1438      
1439 static void
1440 connect_ref_callbacks (GtkTreeModel *model)
1441 {
1442   g_signal_connect (G_OBJECT (model),
1443                     "row_inserted",
1444                     (GCallback) gtk_tree_row_ref_inserted_callback,
1445                     model);
1446   g_signal_connect (G_OBJECT (model),
1447                     "row_deleted",
1448                     (GCallback) gtk_tree_row_ref_deleted_callback,
1449                     model);
1450   g_signal_connect (G_OBJECT (model),
1451                     "rows_reordered",
1452                     (GCallback) gtk_tree_row_ref_reordered_callback,
1453                     model);
1454 }
1455
1456
1457 /* We do this recursively so that we can unref children nodes before their parent */
1458 static void
1459 gtk_tree_row_reference_unref_path_helper (GtkTreePath  *path,
1460                                           GtkTreeModel *model,
1461                                           GtkTreeIter  *parent_iter,
1462                                           gint          depth,
1463                                           gint          current_depth)
1464 {
1465   GtkTreeIter iter;
1466
1467   if (depth == current_depth)
1468     return;
1469
1470   gtk_tree_model_iter_nth_child (model, &iter, parent_iter, path->indices[current_depth]);
1471   gtk_tree_row_reference_unref_path_helper (path, model, &iter, depth, current_depth + 1);
1472   gtk_tree_model_unref_node (model, &iter);
1473 }
1474
1475 static void
1476 gtk_tree_row_reference_unref_path (GtkTreePath  *path,
1477                                    GtkTreeModel *model,
1478                                    gint          depth)
1479 {
1480   GtkTreeIter iter;
1481
1482   if (depth <= 0)
1483     return;
1484   
1485   gtk_tree_model_iter_nth_child (model, &iter, NULL, path->indices[0]);
1486   gtk_tree_row_reference_unref_path_helper (path, model, &iter, depth, 1);
1487   gtk_tree_model_unref_node (model, &iter);
1488 }
1489
1490 static void
1491 disconnect_ref_callbacks (GtkTreeModel *model)
1492 {
1493   g_signal_handlers_disconnect_matched (G_OBJECT (model),
1494                                         G_SIGNAL_MATCH_FUNC,
1495                                         0, 0, NULL,
1496                                         gtk_tree_row_ref_inserted_callback,
1497                                         NULL);
1498   g_signal_handlers_disconnect_matched (G_OBJECT (model),
1499                                         G_SIGNAL_MATCH_FUNC,
1500                                         0, 0, NULL,
1501                                         gtk_tree_row_ref_deleted_callback,
1502                                         NULL);
1503   g_signal_handlers_disconnect_matched (G_OBJECT (model),
1504                                         G_SIGNAL_MATCH_FUNC,
1505                                         0, 0, NULL,
1506                                         gtk_tree_row_ref_reordered_callback,
1507                                         NULL);
1508 }
1509
1510 /**
1511  * gtk_tree_row_reference_new:
1512  * @model: A #GtkTreeModel
1513  * @path: A valid #GtkTreePath to monitor
1514  * 
1515  * Creates a row reference based on @path.  This reference will keep pointing to
1516  * the node pointed to by @path, so long as it exists.  It listens to all
1517  * signals emitted by @model, and updates it's path appropriately.  If @path
1518  * isn't a valid path in @model, then %NULL is returned.
1519  * 
1520  * Return value: A newly allocated #GtkTreeRowReference, or %NULL
1521  **/
1522 GtkTreeRowReference *
1523 gtk_tree_row_reference_new (GtkTreeModel *model,
1524                             GtkTreePath  *path)
1525 {
1526   g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1527   g_return_val_if_fail (path != NULL, NULL);
1528
1529   return gtk_tree_row_reference_new_proxy (G_OBJECT (model), model, path);
1530 }
1531
1532 /**
1533  * gtk_tree_row_reference_new_proxy:
1534  * @proxy: A proxy #GObject
1535  * @model: A #GtkTreeModel
1536  * @path: A valid #GtkTreePath to monitor
1537  * 
1538  * You do not need to use this function.  Creates a row reference based on
1539  * @path.  This reference will keep pointing to the node pointed to by @path, so
1540  * long as it exists.  If @path isn't a valid path in @model, then %NULL is
1541  * returned.  However, unlike references created with
1542  * gtk_tree_row_reference_new(), it does not listen to the model for changes.
1543  * The creator of the row reference must do this explicitly using
1544  * gtk_tree_row_reference_inserted(), gtk_tree_row_reference_deleted(),
1545  * gtk_tree_row_reference_reordered().  This must be called once per signal per
1546  * proxy.
1547  *
1548  * This type of row reference is primarily meant by structures that need to
1549  * carefully monitor exactly when a row_reference updates itself, and is not
1550  * generally needed by most applications.
1551  *
1552  * Return value: A newly allocated #GtkTreeRowReference, or %NULL
1553  **/
1554 GtkTreeRowReference *
1555 gtk_tree_row_reference_new_proxy (GObject      *proxy,
1556                                   GtkTreeModel *model,
1557                                   GtkTreePath  *path)
1558 {
1559   GtkTreeRowReference *reference;
1560   RowRefList *refs;
1561   GtkTreeIter parent_iter;
1562   gint i;
1563
1564   g_return_val_if_fail (G_IS_OBJECT (proxy), NULL);
1565   g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1566   g_return_val_if_fail (path != NULL, NULL);
1567   g_return_val_if_fail (path->depth > 0, NULL);
1568
1569   /* check that the path is valid */
1570   if (gtk_tree_model_get_iter (model, &parent_iter, path) == FALSE)
1571     return NULL;
1572
1573   /* Now we want to ref every node */
1574   gtk_tree_model_iter_nth_child (model, &parent_iter, NULL, path->indices[0]);
1575   gtk_tree_model_ref_node (model, &parent_iter);
1576
1577   for (i = 1; i < path->depth; i++)
1578     {
1579       GtkTreeIter iter;
1580       gtk_tree_model_iter_nth_child (model, &iter, &parent_iter, path->indices[i]);
1581       gtk_tree_model_ref_node (model, &iter);
1582       parent_iter = iter;
1583     }
1584
1585   /* Make ther row reference */
1586   reference = g_new (GtkTreeRowReference, 1);
1587
1588   g_object_ref (proxy);
1589   g_object_ref (model);
1590   reference->proxy = proxy;
1591   reference->model = model;
1592   reference->path = gtk_tree_path_copy (path);
1593
1594   refs = g_object_get_data (G_OBJECT (proxy), ROW_REF_DATA_STRING);
1595
1596   if (refs == NULL)
1597     {
1598       refs = g_new (RowRefList, 1);
1599       refs->list = NULL;
1600
1601       if (G_OBJECT (model) == proxy)
1602         connect_ref_callbacks (model);
1603
1604       g_object_set_data_full (G_OBJECT (proxy),
1605                               ROW_REF_DATA_STRING,
1606                               refs, release_row_references);
1607     }
1608
1609   refs->list = g_slist_prepend (refs->list, reference);
1610
1611   return reference;
1612 }
1613
1614 /**
1615  * gtk_tree_row_reference_get_path:
1616  * @reference: A #GtkTreeRowReference
1617  * 
1618  * Returns a path that the row reference currently points to, or %NULL if the
1619  * path pointed to is no longer valid.
1620  * 
1621  * Return value: A current path, or %NULL.
1622  **/
1623 GtkTreePath *
1624 gtk_tree_row_reference_get_path (GtkTreeRowReference *reference)
1625 {
1626   g_return_val_if_fail (reference != NULL, NULL);
1627
1628   if (reference->proxy == NULL)
1629     return NULL;
1630
1631   if (reference->path == NULL)
1632     return NULL;
1633
1634   return gtk_tree_path_copy (reference->path);
1635 }
1636
1637 /**
1638  * gtk_tree_row_reference_valid:
1639  * @reference: A #GtkTreeRowReference, or NULL
1640  * 
1641  * Returns TRUE if the %reference is non-NULL and refers to a current valid
1642  * path.
1643  * 
1644  * Return value: TRUE if %reference points to a valid path.
1645  **/
1646 gboolean
1647 gtk_tree_row_reference_valid (GtkTreeRowReference *reference)
1648 {
1649   if (reference == NULL || reference->path == NULL)
1650     return FALSE;
1651
1652   return TRUE;
1653 }
1654
1655 /**
1656  * gtk_tree_row_reference_free:
1657  * @reference: A #GtkTreeRowReference, or NULL
1658  * 
1659  * Free's %reference.  %reference may be NULL.
1660  **/
1661 void
1662 gtk_tree_row_reference_free (GtkTreeRowReference *reference)
1663 {
1664   RowRefList *refs;
1665
1666   if (reference == NULL)
1667     return;
1668
1669   refs = g_object_get_data (G_OBJECT (reference->proxy), ROW_REF_DATA_STRING);
1670
1671   if (refs == NULL)
1672     {
1673       g_warning (G_STRLOC": bad row reference, proxy has no outstanding row references");
1674       return;
1675     }
1676
1677   refs->list = g_slist_remove (refs->list, reference);
1678
1679   if (refs->list == NULL)
1680     {
1681       disconnect_ref_callbacks (reference->model);
1682       g_object_set_data (G_OBJECT (reference->proxy),
1683                          ROW_REF_DATA_STRING,
1684                          NULL);
1685     }
1686
1687   if (reference->path)
1688     {
1689       gtk_tree_row_reference_unref_path (reference->path, reference->model, reference->path->depth);
1690       gtk_tree_path_free (reference->path);
1691     }
1692
1693   g_object_unref (reference->proxy);
1694   g_object_unref (reference->model);
1695   g_free (reference);
1696 }
1697
1698 /**
1699  * gtk_tree_row_reference_inserted:
1700  * @proxy: A #GObject
1701  * @path: The row position that was inserted
1702  * 
1703  * Lets a set of row reference created by gtk_tree_row_reference_new_proxy()
1704  * know that the model emitted the "row_inserted" signal.
1705  **/
1706 void
1707 gtk_tree_row_reference_inserted (GObject     *proxy,
1708                                  GtkTreePath *path)
1709 {
1710   g_return_if_fail (G_IS_OBJECT (proxy));
1711
1712   gtk_tree_row_ref_inserted_callback (NULL, path, NULL, proxy);
1713   
1714 }
1715
1716 /**
1717  * gtk_tree_row_reference_inserted:
1718  * @proxy: A #GObject
1719  * @path: The path position that was deleted
1720  * 
1721  * Lets a set of row reference created by gtk_tree_row_reference_new_proxy()
1722  * know that the model emitted the "row_inserted" signal.
1723  **/
1724 void
1725 gtk_tree_row_reference_deleted (GObject     *proxy,
1726                                 GtkTreePath *path)
1727 {
1728   g_return_if_fail (G_IS_OBJECT (proxy));
1729
1730   gtk_tree_row_ref_deleted_callback (NULL, path, proxy);
1731 }
1732
1733 /**
1734  * gtk_tree_row_reference_reordered:
1735  * @proxy: A #GObject
1736  * @path: The parent path of the reordered signal
1737  * @iter: The iter pointing to the parent of the reordered
1738  * @new_order: The new order of rows
1739  * 
1740  * Lets a set of row reference created by gtk_tree_row_reference_new_proxy()
1741  * know that the model emitted the "rows_reordered" signal.
1742  **/
1743 void
1744 gtk_tree_row_reference_reordered (GObject     *proxy,
1745                                   GtkTreePath *path,
1746                                   GtkTreeIter *iter,
1747                                   gint        *new_order)
1748 {
1749   g_return_if_fail (G_IS_OBJECT (proxy));
1750
1751   gtk_tree_row_ref_reordered_callback (NULL, path, iter, new_order, proxy);
1752 }
1753   
1754