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