]> Pileus Git - ~andy/gtk/blob - gtk/gtktreemodel.c
fix bug where it always set the foreground, even if we were only using a
[~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 "gtktreemodel.h"
24
25 struct _GtkTreePath
26 {
27   gint depth;
28   gint *indices;
29 };
30
31 GtkType
32 gtk_tree_model_get_type (void)
33 {
34   static GtkType tree_model_type = 0;
35
36   if (!tree_model_type)
37     {
38       static const GTypeInfo tree_model_info =
39       {
40         sizeof (GtkTreeModelIface), /* class_size */
41         NULL,           /* base_init */
42         NULL,           /* base_finalize */
43         NULL,
44         NULL,           /* class_finalize */
45         NULL,           /* class_data */
46         0,
47         0,              /* n_preallocs */
48         NULL
49       };
50
51       tree_model_type = g_type_register_static (G_TYPE_INTERFACE, "GtkTreeModel", &tree_model_info, 0);
52     }
53
54   return tree_model_type;
55 }
56
57 /**
58  * gtk_tree_path_new:
59  * 
60  * Creates a new #GtkTreePath.
61  * 
62  * Return value: A newly created #GtkTreePath.
63  **/
64 /* GtkTreePath Operations */
65 GtkTreePath *
66 gtk_tree_path_new (void)
67 {
68   GtkTreePath *retval;
69   retval = (GtkTreePath *) g_new (GtkTreePath, 1);
70   retval->depth = 0;
71   retval->indices = NULL;
72
73   return retval;
74 }
75
76 /**
77  * gtk_tree_path_new_from_string:
78  * @path: The string representation of a path.
79  * 
80  * Creates a new #GtkTreePath initialized to @path.  @path is expected
81  * to be a colon separated list of numbers.  For example, the string
82  * "10:4:0" would create a path of depth 3 pointing to the 11th child
83  * of the root node, the 5th child of that 11th child, and the 1st
84  * child of that 5th child.
85  * 
86  * Return value: A newly created #GtkTreePath.
87  **/
88 GtkTreePath *
89 gtk_tree_path_new_from_string (gchar *path)
90 {
91   GtkTreePath *retval;
92   gchar *ptr;
93   gint i;
94
95   g_return_val_if_fail (path != NULL, gtk_tree_path_new ());
96
97   retval = gtk_tree_path_new ();
98
99   while (1)
100     {
101       i = strtol (path, &ptr, 10);
102       gtk_tree_path_append_index (retval, i);
103
104       if (*ptr == '\000')
105         break;
106       /* FIXME: should we error out if this is not a ':', or should we be tolerant? */
107       path = ptr + 1;
108     }
109
110   return retval;
111 }
112
113 /**
114  * gtk_tree_path_to_string:
115  * @path: A #GtkTreePath
116  * 
117  * Generates a string representation of the path.  This string is a ':'
118  * separated list of numbers.  For example, "4:10:0:3" would be an acceptable return value for this string.
119  * 
120  * Return value: A newly allocated string.  Must be freed with #g_free.
121  **/
122 gchar *
123 gtk_tree_path_to_string (GtkTreePath *path)
124 {
125   gchar *retval, *ptr;
126   gint i;
127
128   if (path->depth == 0)
129     return NULL;
130
131   ptr = retval = (gchar *) g_new0 (char *, path->depth*8);
132   sprintf (retval, "%d", path->indices[0]);
133   while (*ptr != '\000')
134     ptr++;
135
136   for (i = 1; i < path->depth; i++)
137     {
138       sprintf (ptr, ":%d", path->indices[i]);
139       while (*ptr != '\000')
140         ptr++;
141     }
142
143   return retval;
144 }
145
146 /**
147  * gtk_tree_path_new_root:
148  * 
149  * Creates a new root #GtkTreePath.  The string representation of this path is
150  * "0"
151  * 
152  * Return value: A new #GtkTreePath.
153  **/
154 GtkTreePath *
155 gtk_tree_path_new_root (void)
156 {
157   GtkTreePath *retval;
158
159   retval = gtk_tree_path_new ();
160   gtk_tree_path_append_index (retval, 0);
161
162   return retval;
163 }
164
165 /**
166  * gtk_tree_path_append_index:
167  * @path: A #GtkTreePath.
168  * @index: The index.
169  * 
170  * Appends a new index to a path.  As a result, the depth of the path is
171  * increased.
172  **/
173 void
174 gtk_tree_path_append_index (GtkTreePath *path,
175                             gint         index)
176 {
177   gint *new_indices;
178
179   g_return_if_fail (path != NULL);
180   g_return_if_fail (index >= 0);
181
182   path->depth += 1;
183   path->indices = g_realloc (path->indices, path->depth * sizeof(gint));
184   path->indices[path->depth - 1] = index;
185 }
186
187 /**
188  * gtk_tree_path_prepend_index:
189  * @path: A #GtkTreePath.
190  * @index: The index.
191  * 
192  * Prepends a new index to a path.  As a result, the depth of the path is
193  * increased.
194  **/
195 void
196 gtk_tree_path_prepend_index (GtkTreePath *path,
197                              gint       index)
198 {
199   gint *new_indices = g_new (gint, ++path->depth);
200   if (path->indices == NULL)
201     {
202       path->indices = new_indices;
203       path->indices[0] = index;
204       return;
205     }
206   memcpy (new_indices + 1, path->indices, (path->depth - 1)*sizeof (gint));
207   g_free (path->indices);
208   path->indices = new_indices;
209   path->indices[0] = index;
210 }
211
212 /**
213  * gtk_tree_path_get_depth:
214  * @path: A #GtkTreePath.
215  * 
216  * Returns the current depth of @path.
217  * 
218  * Return value: The depth of @path
219  **/
220 gint
221 gtk_tree_path_get_depth (GtkTreePath *path)
222 {
223   g_return_val_if_fail (path != NULL, 0);
224
225   return path->depth;
226 }
227
228 /**
229  * gtk_tree_path_get_indices:
230  * @path: A #GtkTreePath.
231  * 
232  * Returns the current indices of @path.  This is an array of integers, each
233  * representing a node in a tree.
234  * 
235  * Return value: The current indices, or NULL.
236  **/
237 gint *
238 gtk_tree_path_get_indices (GtkTreePath *path)
239 {
240   g_return_val_if_fail (path != NULL, NULL);
241
242   return path->indices;
243 }
244
245 /**
246  * gtk_tree_path_free:
247  * @path: A #GtkTreePath.
248  * 
249  * Frees @path.
250  **/
251 void
252 gtk_tree_path_free (GtkTreePath *path)
253 {
254   g_return_if_fail (path != NULL);
255
256   g_free (path->indices);
257   g_free (path);
258 }
259
260 /**
261  * gtk_tree_path_copy:
262  * @path: A #GtkTreePath.
263  * 
264  * Creates a new #GtkTreePath as a copy of @path.
265  * 
266  * Return value: A new #GtkTreePath.
267  **/
268 GtkTreePath *
269 gtk_tree_path_copy (GtkTreePath *path)
270 {
271   GtkTreePath *retval;
272
273   g_return_val_if_fail (path != NULL, NULL);
274
275   retval = g_new (GtkTreePath, 1);
276   retval->depth = path->depth;
277   retval->indices = g_new (gint, path->depth);
278   memcpy (retval->indices, path->indices, path->depth * sizeof (gint));
279   return retval;
280 }
281
282 /**
283  * gtk_tree_path_compare:
284  * @a: A #GtkTreePath.
285  * @b: A #GtkTreePath to compare with.
286  * 
287  * Compares two paths.  If @a appears before @b in a tree, then 1, is returned.
288  * If @b appears before @a, then -1 is returned.  If the two nodes are equal,
289  * then 0 is returned.
290  * 
291  * Return value: The relative positions of @a and @b
292  **/
293 gint
294 gtk_tree_path_compare (const GtkTreePath *a,
295                        const GtkTreePath *b)
296 {
297   gint p = 0, q = 0;
298
299   g_return_val_if_fail (a != NULL, 0);
300   g_return_val_if_fail (b != NULL, 0);
301   g_return_val_if_fail (a->depth > 0, 0);
302   g_return_val_if_fail (b->depth > 0, 0);
303
304   do
305     {
306       if (a->indices[p] == b->indices[q])
307         continue;
308       return (a->indices[p] < b->indices[q]?1:-1);
309     }
310   while (++p < a->depth && ++q < b->depth);
311   if (a->depth == b->depth)
312     return 0;
313   return (a->depth < b->depth?1:-1);
314 }
315
316 /**
317  * gtk_tree_path_is_ancestor:
318  * @path: a #GtkTreePath
319  * @descendant: another #GtkTreePath
320  * 
321  * 
322  * 
323  * Return value: %TRUE if @descendant is contained inside @path
324  **/
325 gboolean
326 gtk_tree_path_is_ancestor (GtkTreePath *path,
327                            GtkTreePath *descendant)
328 {
329   gint i;
330   
331   g_return_val_if_fail (path != NULL, FALSE);
332   g_return_val_if_fail (descendant != NULL, FALSE);
333
334   /* can't be an ancestor if we're deeper */
335   if (path->depth >= descendant->depth)
336     return FALSE;
337   
338   i = 0;
339   while (i < path->depth)
340     {
341       if (path->indices[i] != descendant->indices[i])
342         return FALSE;
343       ++i;
344     }
345
346   return TRUE;
347 }
348
349 /**
350  * gtk_tree_path_is_descendant:
351  * @path: a #GtkTreePath
352  * @ancestor: another #GtkTreePath
353  * 
354  * 
355  * 
356  * Return value: %TRUE if @ancestor contains @path somewhere below it
357  **/
358 gboolean
359 gtk_tree_path_is_descendant (GtkTreePath *path,
360                              GtkTreePath *ancestor)
361 {
362   gint i;
363   
364   g_return_val_if_fail (path != NULL, FALSE);
365   g_return_val_if_fail (ancestor != NULL, FALSE);
366   
367   /* can't be a descendant if we're shallower in the tree */
368   if (path->depth <= ancestor->depth)
369     return FALSE;
370   
371   i = 0;
372   while (i < ancestor->depth)
373     {
374       if (path->indices[i] != ancestor->indices[i])
375         return FALSE;
376       ++i;
377     }
378
379   return TRUE;
380 }
381
382
383 /**
384  * gtk_tree_path_next:
385  * @path: A #GtkTreePath.
386  * 
387  * Moves the @path to point to the next node at the current depth.
388  **/
389 void
390 gtk_tree_path_next (GtkTreePath *path)
391 {
392   g_return_if_fail (path != NULL);
393   g_return_if_fail (path->depth > 0);
394
395   path->indices[path->depth - 1] ++;
396 }
397
398 /**
399  * gtk_tree_path_prev:
400  * @path: A #GtkTreePath.
401  * 
402  * Moves the @path to point to the previous node at the current depth, if it exists.
403  * 
404  * Return value: TRUE if @path has a previous node, and the move was made.
405  **/
406 gboolean
407 gtk_tree_path_prev (GtkTreePath *path)
408 {
409   g_return_val_if_fail (path != NULL, FALSE);
410
411   if (path->indices[path->depth - 1] == 0)
412     return FALSE;
413
414   path->indices[path->depth - 1] -= 1;
415
416   return TRUE;
417 }
418
419 /**
420  * gtk_tree_path_up:
421  * @path: A #GtkTreePath.
422  * 
423  * Moves the @path to point to it's parent node, if it has a parent.
424  * 
425  * Return value: TRUE if @path has a parent, and the move was made.
426  **/
427 gboolean
428 gtk_tree_path_up (GtkTreePath *path)
429 {
430   g_return_val_if_fail (path != NULL, FALSE);
431
432   if (path->depth == 1)
433     return FALSE;
434
435   path->depth--;
436
437   return TRUE;
438 }
439
440 /**
441  * gtk_tree_path_down:
442  * @path: A #GtkTreePath.
443  * 
444  * Moves @path to point to the first child of the current path.
445  **/
446 void
447 gtk_tree_path_down (GtkTreePath *path)
448 {
449   g_return_if_fail (path != NULL);
450
451   gtk_tree_path_append_index (path, 0);
452 }
453
454 struct _GtkTreeRowReference
455 {
456   GtkTreeModel *model;
457   GtkTreePath *path;
458 };
459
460 typedef struct _RowRefList RowRefList;
461
462 struct _RowRefList
463 {
464   GSList *list;
465 };
466
467 static void
468 release_row_references (gpointer data)
469 {
470   RowRefList *refs = data;
471   GSList *tmp_list = NULL;
472   
473   tmp_list = refs->list;
474   while (tmp_list != NULL)
475     {
476       GtkTreeRowReference *reference = tmp_list->data;
477
478       reference->model = NULL;
479
480       /* we don't free the reference, users are responsible for that. */
481
482       tmp_list = g_slist_next (tmp_list);
483     }
484
485   g_slist_free (refs->list);
486   g_free (refs);
487 }
488
489 static void
490 inserted_callback (GtkTreeModel *tree_model,
491                    GtkTreePath  *path,
492                    GtkTreeIter  *iter,
493                    gpointer      data)
494 {
495   RowRefList *refs = data;
496   GSList *tmp_list;
497
498   /* This function corrects the path stored in the reference to
499    * account for an insertion. Note that it's called _after_ the insertion
500    * with the path to the newly-inserted row. Which means that
501    * the inserted path is in a different "coordinate system" than
502    * the old path (e.g. if the inserted path was just before the old path,
503    * then inserted path and old path will be the same, and old path must be
504    * moved down one).
505    */
506   
507   tmp_list = refs->list;
508
509   while (tmp_list != NULL)
510     {
511       GtkTreeRowReference *reference = tmp_list->data;
512
513       /* if reference->path == NULL then the reference was already
514        * deleted.
515        */
516       
517       if (reference->path)
518         {
519           gint depth = gtk_tree_path_get_depth (path);
520           gint ref_depth = gtk_tree_path_get_depth (reference->path);
521           
522           if (ref_depth >= depth)
523             {
524               gint *indices = gtk_tree_path_get_indices (path);
525               gint *ref_indices = gtk_tree_path_get_indices (reference->path);
526               gint i;
527
528               /* This is the depth that might affect us. */
529               i = depth - 1;
530               
531               if (indices[i] <= ref_indices[i])
532                 ref_indices[i] += 1;
533             }
534         }
535
536       tmp_list = g_slist_next (tmp_list);
537     }
538 }
539
540 static void
541 deleted_callback (GtkTreeModel *tree_model,
542                   GtkTreePath  *path,
543                   gpointer      data)
544 {
545   RowRefList *refs = data;
546   GSList *tmp_list;
547
548   /* This function corrects the path stored in the reference to
549    * account for an deletion. Note that it's called _after_ the
550    * deletion with the old path of the just-deleted row. Which means
551    * that the deleted path is the same now-defunct "coordinate system"
552    * as the path saved in the reference, which is what we want to fix.
553    *
554    * Note that this is different from the situation in "inserted," so
555    * while you might think you can cut-and-paste between these
556    * functions, it's not going to work. ;-)
557    */
558   
559   tmp_list = refs->list;
560
561   while (tmp_list != NULL)
562     {
563       GtkTreeRowReference *reference = tmp_list->data;
564
565       /* if reference->path == NULL then the reference was already
566        * deleted.
567        */
568       
569       if (reference->path)
570         {
571           gint depth = gtk_tree_path_get_depth (path);
572           gint ref_depth = gtk_tree_path_get_depth (reference->path);
573
574           if (ref_depth >= depth)
575             {
576               /* Need to adjust path upward */
577               gint *indices = gtk_tree_path_get_indices (path);
578               gint *ref_indices = gtk_tree_path_get_indices (reference->path);
579               gint i;
580
581               i = depth - 1;
582               if (indices[i] < ref_indices[i])
583                 ref_indices[i] -= 1;
584               else if (indices[i] == ref_indices[i])
585                 {
586                   /* the referenced node itself, or its parent, was
587                    * deleted, mark invalid
588                    */
589
590                   gtk_tree_path_free (reference->path);
591                   reference->path = NULL;
592                 }
593             }
594         }
595
596       tmp_list = g_slist_next (tmp_list);
597     }
598 }
599
600 static void
601 reordered_callback (GtkTreeModel *tree_model,
602                     GtkTreePath  *path,
603                     gint         *new_order,
604                     gpointer      data)
605 {
606
607   /* FIXME */
608 }
609
610 static void
611 connect_ref_callbacks (GtkTreeModel *model,
612                        RowRefList   *refs)
613 {
614   g_signal_connect_data (G_OBJECT (model),
615                          "inserted",
616                          (GCallback) inserted_callback,
617                          refs,
618                          NULL,
619                          FALSE,
620                          FALSE);
621
622   g_signal_connect_data (G_OBJECT (model),
623                          "deleted",
624                          (GCallback) deleted_callback,
625                          refs,
626                          NULL,
627                          FALSE,
628                          FALSE);
629
630 #if 0
631   /* FIXME */
632   g_signal_connect_data (G_OBJECT (model),
633                          "reordered",
634                          (GCallback) reordered_callback,
635                          refs,
636                          NULL,
637                          FALSE,
638                          FALSE);
639 #endif
640 }
641
642 static void
643 disconnect_ref_callbacks (GtkTreeModel *model,
644                           RowRefList   *refs)
645 {
646   g_signal_handlers_disconnect_matched (G_OBJECT (model),
647                                         G_SIGNAL_MATCH_DATA,
648                                         0,
649                                         0,
650                                         NULL,
651                                         NULL,
652                                         refs);
653 }
654
655 GtkTreeRowReference*
656 gtk_tree_row_reference_new (GtkTreeModel *model,
657                             GtkTreePath  *path)
658 {
659   GtkTreeRowReference *reference;
660   RowRefList *refs;
661   
662   reference = g_new (GtkTreeRowReference, 1);
663
664   reference->model = model;
665   reference->path = gtk_tree_path_copy (path);
666
667   refs = g_object_get_data (G_OBJECT (model),
668                             "gtk-tree-row-refs");
669
670   if (refs == NULL)
671     {
672       refs = g_new (RowRefList, 1);
673       refs->list = NULL;
674       connect_ref_callbacks (model, refs);
675       g_object_set_data_full (G_OBJECT (model),
676                               "gtk-tree-row-refs",
677                               refs,
678                               release_row_references);  
679     }
680   
681   refs->list = g_slist_prepend (refs->list, reference);
682   
683   return reference;
684 }
685
686 GtkTreePath*
687 gtk_tree_row_reference_get_path (GtkTreeRowReference *reference)
688 {
689   g_return_val_if_fail (reference != NULL, NULL);
690
691   if (reference->model == NULL)
692     return NULL;
693
694   if (reference->path == NULL)
695     return NULL;
696
697   return gtk_tree_path_copy (reference->path);
698 }
699
700 void
701 gtk_tree_row_reference_free (GtkTreeRowReference *reference)
702 {
703   RowRefList *refs;
704
705   g_return_if_fail (reference != NULL);
706   
707   if (reference->model)
708     {
709       refs = g_object_get_data (G_OBJECT (reference->model),
710                                 "gtk-tree-row-refs");
711
712       if (refs == NULL)
713         {
714           g_warning (G_STRLOC": bad row reference, model has no outstanding row references");
715           return;
716         }
717           
718       refs->list = g_slist_remove (refs->list, reference);
719
720       if (refs->list == NULL)
721         {
722           disconnect_ref_callbacks (reference->model, refs);
723           g_object_set_data (G_OBJECT (reference->model),
724                              "gtk-tree-row-refs",
725                              NULL);
726         }
727     }
728   
729   if (reference->path)
730     gtk_tree_path_free (reference->path);
731
732   g_free (reference);
733 }
734
735 /**
736  * gtk_tree_iter_copy:
737  * @iter: A #GtkTreeIter.
738  * 
739  * Creates a dynamically allocated tree iterator as a copy of @iter.  This
740  * function is not intended for use in applications, because you can just copy
741  * the structs by value (GtkTreeIter new_iter = iter;).  You
742  * must free this iter with gtk_tree_iter_free ().
743  * 
744  * Return value: a newly allocated copy of @iter.
745  **/
746 GtkTreeIter *
747 gtk_tree_iter_copy (GtkTreeIter *iter)
748 {
749   GtkTreeIter *retval;
750
751   g_return_val_if_fail (iter != NULL, NULL);
752
753   retval = g_new (GtkTreeIter, 1);
754   *retval = *iter;
755
756   return retval;
757 }
758
759 /**
760  * gtk_tree_iter_free:
761  * @iter: A dynamically allocated tree iterator.
762  * 
763  * Free an iterator that has been allocated on the heap.  This function is
764  * mainly used for language bindings.
765  **/
766 void
767 gtk_tree_iter_free (GtkTreeIter *iter)
768 {
769   g_return_if_fail (iter != NULL);
770
771   g_free (iter);
772 }
773
774 /**
775  * gtk_tree_model_get_flags:
776  * @tree_model: A #GtkTreeModel.
777  * 
778  * Returns a set of flags supported by this interface.  The flags are a bitwise
779  * combination of #GtkTreeModelFlags.  It is expected that the flags supported
780  * do not change for an interface.
781  * 
782  * Return value: The flags supported by this interface.
783  **/
784 GtkTreeModelFlags
785 gtk_tree_model_get_flags (GtkTreeModel *tree_model)
786 {
787   g_return_val_if_fail (tree_model != NULL, 0);
788   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
789
790   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_flags)
791     return (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_flags) (tree_model);
792
793   return 0;
794 }
795
796 /**
797  * gtk_tree_model_get_n_columns:
798  * @tree_model: A #GtkTreeModel.
799  * 
800  * Returns the number of columns supported by the #tree_model
801  * 
802  * Return value: The number of columns.
803  **/
804 gint
805 gtk_tree_model_get_n_columns (GtkTreeModel *tree_model)
806 {
807   g_return_val_if_fail (tree_model != NULL, 0);
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)->get_n_columns != NULL, 0);
810
811   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_n_columns) (tree_model);
812 }
813
814 /**
815  * gtk_tree_model_get_column_type:
816  * @tree_model: A #GtkTreeModel.
817  * @index: The column index.
818  * 
819  * Returns the type of the column.
820  * 
821  * Return value: The type of the column.
822  **/
823 GType
824 gtk_tree_model_get_column_type (GtkTreeModel *tree_model,
825                                 gint          index)
826 {
827   g_return_val_if_fail (tree_model != NULL, G_TYPE_INVALID);
828   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), G_TYPE_INVALID);
829   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_column_type != NULL, G_TYPE_INVALID);
830   g_return_val_if_fail (index >= 0, G_TYPE_INVALID);
831
832   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_column_type) (tree_model, index);
833 }
834
835 /**
836  * gtk_tree_model_get_iter:
837  * @tree_model: A #GtkTreeModel.
838  * @iter: The uninitialized #GtkTreeIter.
839  * @path: The #GtkTreePath.
840  * 
841  * Sets @iter to a valid iterator pointing to @path.  If the model does not
842  * provide an implementation of this function, it is implemented in terms of
843  * @gtk_tree_model_iter_nth_child.
844  * 
845  * Return value: TRUE, if @iter was set.
846  **/
847 gboolean
848 gtk_tree_model_get_iter (GtkTreeModel *tree_model,
849                          GtkTreeIter  *iter,
850                          GtkTreePath  *path)
851 {
852   GtkTreeIter parent;
853   gint *indices;
854   gint depth, i;
855
856   g_return_val_if_fail (tree_model != NULL, FALSE);
857   g_return_val_if_fail (iter != NULL, FALSE);
858   g_return_val_if_fail (path != NULL, FALSE);
859   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
860
861   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_iter != NULL)
862     return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_iter) (tree_model, iter, path);
863
864   indices = gtk_tree_path_get_indices (path);
865   depth = gtk_tree_path_get_depth (path);
866
867   g_return_val_if_fail (depth > 0, FALSE);
868
869   if (! gtk_tree_model_iter_nth_child (tree_model, iter, NULL, indices[0]))
870     return FALSE;
871
872   for (i = 1; i < depth; i++)
873     {
874       parent = *iter;
875       if (! gtk_tree_model_iter_nth_child (tree_model, iter, &parent, indices[i]))
876         return FALSE;
877     }
878
879   return TRUE;
880 }
881
882 /**
883  * gtk_tree_model_get_first:
884  * @tree_model: a #GtkTreeModel
885  * @iter: iterator to initialize
886  * 
887  * Initialized @iter with the first iterator in the tree (the one at the
888  * root path) and returns %TRUE, or returns %FALSE if there are no
889  * iterable locations in the model (i.e. the tree is empty).
890  * 
891  * Return value: %TRUE if @iter was initialized
892  **/
893 gboolean
894 gtk_tree_model_get_first (GtkTreeModel *tree_model,
895                           GtkTreeIter  *iter)
896 {
897   gboolean retval;
898   GtkTreePath *path;
899   
900   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
901   g_return_val_if_fail (iter != NULL, FALSE);
902
903   path = gtk_tree_path_new_root ();
904
905   retval = gtk_tree_model_get_iter (tree_model, iter, path);
906
907   gtk_tree_path_free (path);
908
909   return retval;
910 }
911
912 /**
913  * gtk_tree_model_get_path:
914  * @tree_model: A #GtkTreeModel.
915  * @iter: The #GtkTreeIter.
916  * 
917  * Returns a newly created #GtkTreePath referenced by @iter.  This path should
918  * be freed with #gtk_tree_path_free.
919  * 
920  * Return value: a newly created #GtkTreePath.
921  **/
922 GtkTreePath *
923 gtk_tree_model_get_path (GtkTreeModel *tree_model,
924                          GtkTreeIter  *iter)
925 {
926   g_return_val_if_fail (tree_model != NULL, NULL);
927   g_return_val_if_fail (iter != NULL, NULL);
928   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), NULL);
929   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_path != NULL, NULL);
930
931   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_path) (tree_model, iter);
932 }
933
934 /**
935  * gtk_tree_model_get_value:
936  * @tree_model: A #GtkTreeModel.
937  * @iter: The #GtkTreeIter.
938  * @column: The column to lookup the value at.
939  * @value: An empty #GValue to set.
940  * 
941  * Sets initializes and sets @value to that at @column.  When done with value,
942  * #g_value_unset needs to be called on it.
943  **/
944 void
945 gtk_tree_model_get_value (GtkTreeModel *tree_model,
946                           GtkTreeIter  *iter,
947                           gint          column,
948                           GValue       *value)
949 {
950   g_return_if_fail (tree_model != NULL);
951   g_return_if_fail (iter != NULL);
952   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
953   g_return_if_fail (value != NULL);
954   g_return_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_value != NULL);
955
956   (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_value) (tree_model, iter, column, value);
957 }
958
959 /**
960  * gtk_tree_model_iter_next:
961  * @tree_model: A #GtkTreeModel.
962  * @iter: The #GtkTreeIter.
963  * 
964  * Sets @iter to point to the node following it at the current level.  If there
965  * is no next @iter, FALSE is returned and @iter is set to be invalid.
966  * 
967  * Return value: TRUE if @iter has been changed to the next node.
968  **/
969 gboolean
970 gtk_tree_model_iter_next (GtkTreeModel  *tree_model,
971                           GtkTreeIter   *iter)
972 {
973   g_return_val_if_fail (tree_model != NULL, FALSE);
974   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
975   g_return_val_if_fail (iter != NULL, FALSE);
976   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_next != NULL, FALSE);
977
978   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_next) (tree_model, iter);
979 }
980
981 /**
982  * gtk_tree_model_iter_children:
983  * @tree_model: A #GtkTreeModel.
984  * @iter: The new #GtkTreeIter to be set to the child.
985  * @parent: The #GtkTreeIter.
986  * 
987  * Sets @iter to point to the first child of @parent.  If @parent has no children,
988  * FALSE is returned and @iter is set to be invalid.  @parent will remain a valid
989  * node after this function has been called.
990  * 
991  * Return value: TRUE, if @child has been set to the first child.
992  **/
993 gboolean
994 gtk_tree_model_iter_children (GtkTreeModel *tree_model,
995                               GtkTreeIter  *iter,
996                               GtkTreeIter  *parent)
997 {
998   g_return_val_if_fail (tree_model != NULL, FALSE);
999   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1000   g_return_val_if_fail (iter != NULL, FALSE);
1001   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_children != NULL, FALSE);
1002
1003   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_children) (tree_model, iter, parent);
1004 }
1005
1006 /**
1007  * gtk_tree_model_iter_has_child:
1008  * @tree_model: A #GtkTreeModel.
1009  * @iter: The #GtkTreeIter to test for children.
1010  * 
1011  * Returns TRUE if @iter has children, FALSE otherwise.
1012  * 
1013  * Return value: TRUE if @iter has children.
1014  **/
1015 gboolean
1016 gtk_tree_model_iter_has_child (GtkTreeModel *tree_model,
1017                                GtkTreeIter  *iter)
1018 {
1019   g_return_val_if_fail (tree_model != NULL, FALSE);
1020   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1021   g_return_val_if_fail (iter != NULL, FALSE);
1022   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_has_child != NULL, FALSE);
1023
1024   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_has_child) (tree_model, iter);
1025 }
1026
1027 /**
1028  * gtk_tree_model_iter_n_children:
1029  * @tree_model: A #GtkTreeModel.
1030  * @iter: The #GtkTreeIter, or NULL.
1031  * 
1032  * Returns the number of children that @iter has.  If @iter is NULL, then the
1033  * number of toplevel nodes is returned.
1034  * 
1035  * Return value: The number of children of @iter.
1036  **/
1037 gint
1038 gtk_tree_model_iter_n_children (GtkTreeModel *tree_model,
1039                                 GtkTreeIter  *iter)
1040 {
1041   g_return_val_if_fail (tree_model != NULL, 0);
1042   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
1043   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_n_children != NULL, 0);
1044
1045   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_n_children) (tree_model, iter);
1046 }
1047
1048 /**
1049  * gtk_tree_model_iter_nth_child:
1050  * @tree_model: A #GtkTreeModel.
1051  * @iter: The #GtkTreeIter to set to the nth child.
1052  * @parent: The #GtkTreeIter to get the child from, or NULL.
1053  * @n: Then index of the desired child.
1054  * 
1055  * Sets @iter to be the child of @parent, using the given index.  The first
1056  * index is 0.  If the index is too big, or @parent has no children, @iter is
1057  * set to an invalid iterator and FALSE is returned.  @parent will remain a
1058  * valid node after this function has been called.  If @parent is NULL, then the
1059  * root node is assumed.
1060  * 
1061  * Return value: TRUE, if @parent has an nth child.
1062  **/
1063 gboolean
1064 gtk_tree_model_iter_nth_child (GtkTreeModel *tree_model,
1065                                GtkTreeIter  *iter,
1066                                GtkTreeIter  *parent,
1067                                gint          n)
1068 {
1069   g_return_val_if_fail (tree_model != NULL, FALSE);
1070   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1071   g_return_val_if_fail (iter != NULL, FALSE);
1072   g_return_val_if_fail (n >= 0, FALSE);
1073   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_nth_child != NULL, FALSE);
1074
1075   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_nth_child) (tree_model, iter, parent, n);
1076 }
1077
1078 /**
1079  * gtk_tree_model_iter_parent:
1080  * @tree_model: A #GtkTreeModel
1081  * @iter: The new #GtkTreeIter to set to the parent.
1082  * @child: The #GtkTreeIter.
1083  * 
1084  * Sets @iter to be the parent of @child.  If @child is at the toplevel, and
1085  * doesn't have a parent, then @iter is set to an invalid iterator and FALSE
1086  * is returned.  @child will remain a valid node after this function has been
1087  * called.
1088  * 
1089  * Return value: TRUE, if @iter is set to the parent of @child.
1090  **/
1091 gboolean
1092 gtk_tree_model_iter_parent (GtkTreeModel *tree_model,
1093                             GtkTreeIter  *iter,
1094                             GtkTreeIter  *child)
1095 {
1096   g_return_val_if_fail (tree_model != NULL, FALSE);
1097   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1098   g_return_val_if_fail (iter != NULL, FALSE);
1099   g_return_val_if_fail (child != NULL, FALSE);
1100   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_parent != NULL, FALSE);
1101
1102   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_parent) (tree_model, iter, child);
1103 }
1104
1105 /* FIXME explain what the method is supposed to do! */
1106 /**
1107  * gtk_tree_model_ref_iter:
1108  * @tree_model: A #GtkTreeModel.
1109  * @iter: The #GtkTreeIter.
1110  * 
1111  * Ref's the iter.  This is an optional method for models to implement.  To be
1112  * more specific, models may ignore this call as it exists primarily for
1113  * performance reasons.
1114  **/
1115 void
1116 gtk_tree_model_ref_iter (GtkTreeModel *tree_model,
1117                          GtkTreeIter  *iter)
1118 {
1119   g_return_if_fail (tree_model != NULL);
1120   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1121
1122   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->ref_iter)
1123     (* GTK_TREE_MODEL_GET_IFACE (tree_model)->ref_iter) (tree_model, iter);
1124 }
1125
1126 /* FIXME explain what the method is supposed to do! */
1127 /**
1128  * gtk_tree_model_unref_iter:
1129  * @tree_model: A #GtkTreeModel.
1130  * @iter: The #GtkTreeIter.
1131  * 
1132  * Unref's the iter.  This is an optional method for models to implement.  To be
1133  * more specific, models may ignore this call as it exists primarily for
1134  * performance reasons.
1135  **/
1136 void
1137 gtk_tree_model_unref_iter (GtkTreeModel *tree_model,
1138                            GtkTreeIter  *iter)
1139 {
1140   g_return_if_fail (tree_model != NULL);
1141   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1142
1143   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->unref_iter)
1144     (* GTK_TREE_MODEL_GET_IFACE (tree_model)->unref_iter) (tree_model, iter);
1145 }