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