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