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