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