]> Pileus Git - ~andy/gtk/blob - gtk/gtktreemodel.c
Proxy out to _gtk_tree_row_reference_deleted. (inserted_callback): Proxy
[~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
520 /*
521  * row_reference 
522  */
523 void
524 _gtk_tree_row_reference_inserted (GtkTreeRowReference *reference,
525                                   GtkTreePath         *path)
526 {
527   if (reference->path)
528     {
529       gint depth = gtk_tree_path_get_depth (path);
530       gint ref_depth = gtk_tree_path_get_depth (reference->path);
531           
532       if (ref_depth >= depth)
533         {
534           gint *indices = gtk_tree_path_get_indices (path);
535           gint *ref_indices = gtk_tree_path_get_indices (reference->path);
536           gint i;
537
538           /* This is the depth that might affect us. */
539           i = depth - 1;
540               
541           if (indices[i] <= ref_indices[i])
542             ref_indices[i] += 1;
543         }
544     }
545 }
546
547 /* Returns TRUE if the reference path was deleted; FALSE otherwise */
548 gboolean
549 _gtk_tree_row_reference_deleted (GtkTreeRowReference *reference,
550                                  GtkTreePath         *path)
551 {
552   if (reference->path)
553     {
554       gint depth = gtk_tree_path_get_depth (path);
555       gint ref_depth = gtk_tree_path_get_depth (reference->path);
556
557       if (ref_depth >= depth)
558         {
559           /* Need to adjust path upward */
560           gint *indices = gtk_tree_path_get_indices (path);
561           gint *ref_indices = gtk_tree_path_get_indices (reference->path);
562           gint i;
563               
564           i = depth - 1;
565           if (indices[i] < ref_indices[i])
566             ref_indices[i] -= 1;
567           else if (indices[i] == ref_indices[i])
568             {
569               /* the referenced node itself, or its parent, was
570                * deleted, mark invalid
571                */
572
573               gtk_tree_path_free (reference->path);
574               reference->path = NULL;
575               return TRUE;
576             }
577         }
578     }
579   return FALSE;
580 }
581
582 static void
583 release_row_references (gpointer data)
584 {
585   RowRefList *refs = data;
586   GSList *tmp_list = NULL;
587   
588   tmp_list = refs->list;
589   while (tmp_list != NULL)
590     {
591       GtkTreeRowReference *reference = tmp_list->data;
592
593       reference->model = NULL;
594
595       /* we don't free the reference, users are responsible for that. */
596
597       tmp_list = g_slist_next (tmp_list);
598     }
599
600   g_slist_free (refs->list);
601   g_free (refs);
602 }
603
604 static void
605 inserted_callback (GtkTreeModel *tree_model,
606                    GtkTreePath  *path,
607                    GtkTreeIter  *iter,
608                    gpointer      data)
609 {
610   RowRefList *refs = data;
611   GSList *tmp_list;
612
613   /* This function corrects the path stored in the reference to
614    * account for an insertion. Note that it's called _after_ the insertion
615    * with the path to the newly-inserted row. Which means that
616    * the inserted path is in a different "coordinate system" than
617    * the old path (e.g. if the inserted path was just before the old path,
618    * then inserted path and old path will be the same, and old path must be
619    * moved down one).
620    */
621   
622   tmp_list = refs->list;
623
624   while (tmp_list != NULL)
625     {
626       GtkTreeRowReference *reference = tmp_list->data;
627
628       _gtk_tree_row_reference_inserted (reference, path);
629
630       tmp_list = g_slist_next (tmp_list);
631     }
632 }
633
634 static void
635 deleted_callback (GtkTreeModel *tree_model,
636                   GtkTreePath  *path,
637                   gpointer      data)
638 {
639   RowRefList *refs = data;
640   GSList *tmp_list;
641
642   /* This function corrects the path stored in the reference to
643    * account for an deletion. Note that it's called _after_ the
644    * deletion with the old path of the just-deleted row. Which means
645    * that the deleted path is the same now-defunct "coordinate system"
646    * as the path saved in the reference, which is what we want to fix.
647    *
648    * Note that this is different from the situation in "inserted," so
649    * while you might think you can cut-and-paste between these
650    * functions, it's not going to work. ;-)
651    */
652   
653   tmp_list = refs->list;
654
655   while (tmp_list != NULL)
656     {
657       GtkTreeRowReference *reference = tmp_list->data;
658
659       _gtk_tree_row_reference_deleted (reference, path);
660
661       tmp_list = g_slist_next (tmp_list);
662     }
663 }
664
665 static void
666 connect_ref_callbacks (GtkTreeModel *model,
667                        RowRefList   *refs)
668 {
669   g_signal_connect_data (G_OBJECT (model),
670                          "inserted",
671                          (GCallback) inserted_callback,
672                          refs,
673                          NULL,
674                          FALSE,
675                          FALSE);
676
677   g_signal_connect_data (G_OBJECT (model),
678                          "deleted",
679                          (GCallback) deleted_callback,
680                          refs,
681                          NULL,
682                          FALSE,
683                          FALSE);
684
685 #if 0
686   /* FIXME */
687   g_signal_connect_data (G_OBJECT (model),
688                          "reordered",
689                          (GCallback) reordered_callback,
690                          refs,
691                          NULL,
692                          FALSE,
693                          FALSE);
694 #endif
695 }
696
697 static void
698 disconnect_ref_callbacks (GtkTreeModel *model,
699                           RowRefList   *refs)
700 {
701   g_signal_handlers_disconnect_matched (G_OBJECT (model),
702                                         G_SIGNAL_MATCH_DATA,
703                                         0,
704                                         0,
705                                         NULL,
706                                         NULL,
707                                         refs);
708 }
709
710 GtkTreeRowReference*
711 gtk_tree_row_reference_new (GtkTreeModel *model,
712                             GtkTreePath  *path)
713 {
714   GtkTreeRowReference *reference;
715   RowRefList *refs;
716   
717   reference = g_new (GtkTreeRowReference, 1);
718
719   reference->model = model;
720   reference->path = gtk_tree_path_copy (path);
721
722   refs = g_object_get_data (G_OBJECT (model),
723                             "gtk-tree-row-refs");
724
725   if (refs == NULL)
726     {
727       refs = g_new (RowRefList, 1);
728       refs->list = NULL;
729       connect_ref_callbacks (model, refs);
730       g_object_set_data_full (G_OBJECT (model),
731                               "gtk-tree-row-refs",
732                               refs,
733                               release_row_references);  
734     }
735   
736   refs->list = g_slist_prepend (refs->list, reference);
737
738   return reference;
739 }
740
741 GtkTreeRowReference *
742 _gtk_tree_row_reference_new_from_view (GtkTreePath *path)
743 {
744   GtkTreeRowReference *reference;
745   
746   reference = g_new (GtkTreeRowReference, 1);
747
748   reference->model = NULL;
749   reference->path = gtk_tree_path_copy (path);
750
751   return reference;
752 }
753
754 GtkTreePath*
755 gtk_tree_row_reference_get_path (GtkTreeRowReference *reference)
756 {
757   g_return_val_if_fail (reference != NULL, NULL);
758
759   if (reference->model == NULL)
760     return NULL;
761
762   if (reference->path == NULL)
763     return NULL;
764
765   return gtk_tree_path_copy (reference->path);
766 }
767
768 void
769 gtk_tree_row_reference_free (GtkTreeRowReference *reference)
770 {
771   RowRefList *refs;
772
773   g_return_if_fail (reference != NULL);
774   
775   if (reference->model)
776     {
777       refs = g_object_get_data (G_OBJECT (reference->model),
778                                 "gtk-tree-row-refs");
779
780       if (refs == NULL)
781         {
782           g_warning (G_STRLOC": bad row reference, model has no outstanding row references");
783           return;
784         }
785           
786       refs->list = g_slist_remove (refs->list, reference);
787
788       if (refs->list == NULL)
789         {
790           disconnect_ref_callbacks (reference->model, refs);
791           g_object_set_data (G_OBJECT (reference->model),
792                              "gtk-tree-row-refs",
793                              NULL);
794         }
795     }
796   
797   if (reference->path)
798     gtk_tree_path_free (reference->path);
799
800   g_free (reference);
801 }
802
803 /**
804  * gtk_tree_iter_copy:
805  * @iter: A #GtkTreeIter.
806  * 
807  * Creates a dynamically allocated tree iterator as a copy of @iter.  This
808  * function is not intended for use in applications, because you can just copy
809  * the structs by value (GtkTreeIter new_iter = iter;).  You
810  * must free this iter with gtk_tree_iter_free ().
811  * 
812  * Return value: a newly allocated copy of @iter.
813  **/
814 GtkTreeIter *
815 gtk_tree_iter_copy (GtkTreeIter *iter)
816 {
817   GtkTreeIter *retval;
818
819   g_return_val_if_fail (iter != NULL, NULL);
820
821   retval = g_new (GtkTreeIter, 1);
822   *retval = *iter;
823
824   return retval;
825 }
826
827 /**
828  * gtk_tree_iter_free:
829  * @iter: A dynamically allocated tree iterator.
830  * 
831  * Free an iterator that has been allocated on the heap.  This function is
832  * mainly used for language bindings.
833  **/
834 void
835 gtk_tree_iter_free (GtkTreeIter *iter)
836 {
837   g_return_if_fail (iter != NULL);
838
839   g_free (iter);
840 }
841
842 /**
843  * gtk_tree_model_get_flags:
844  * @tree_model: A #GtkTreeModel.
845  * 
846  * Returns a set of flags supported by this interface.  The flags are a bitwise
847  * combination of #GtkTreeModelFlags.  It is expected that the flags supported
848  * do not change for an interface.
849  * 
850  * Return value: The flags supported by this interface.
851  **/
852 GtkTreeModelFlags
853 gtk_tree_model_get_flags (GtkTreeModel *tree_model)
854 {
855   g_return_val_if_fail (tree_model != NULL, 0);
856   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
857
858   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_flags)
859     return (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_flags) (tree_model);
860
861   return 0;
862 }
863
864 /**
865  * gtk_tree_model_get_n_columns:
866  * @tree_model: A #GtkTreeModel.
867  * 
868  * Returns the number of columns supported by the #tree_model
869  * 
870  * Return value: The number of columns.
871  **/
872 gint
873 gtk_tree_model_get_n_columns (GtkTreeModel *tree_model)
874 {
875   g_return_val_if_fail (tree_model != NULL, 0);
876   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
877   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_n_columns != NULL, 0);
878
879   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_n_columns) (tree_model);
880 }
881
882 /**
883  * gtk_tree_model_get_column_type:
884  * @tree_model: A #GtkTreeModel.
885  * @index: The column index.
886  * 
887  * Returns the type of the column.
888  * 
889  * Return value: The type of the column.
890  **/
891 GType
892 gtk_tree_model_get_column_type (GtkTreeModel *tree_model,
893                                 gint          index)
894 {
895   g_return_val_if_fail (tree_model != NULL, G_TYPE_INVALID);
896   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), G_TYPE_INVALID);
897   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_column_type != NULL, G_TYPE_INVALID);
898   g_return_val_if_fail (index >= 0, G_TYPE_INVALID);
899
900   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_column_type) (tree_model, index);
901 }
902
903 /**
904  * gtk_tree_model_get_iter:
905  * @tree_model: A #GtkTreeModel.
906  * @iter: The uninitialized #GtkTreeIter.
907  * @path: The #GtkTreePath.
908  * 
909  * Sets @iter to a valid iterator pointing to @path.  If the model does not
910  * provide an implementation of this function, it is implemented in terms of
911  * @gtk_tree_model_iter_nth_child.
912  * 
913  * Return value: TRUE, if @iter was set.
914  **/
915 gboolean
916 gtk_tree_model_get_iter (GtkTreeModel *tree_model,
917                          GtkTreeIter  *iter,
918                          GtkTreePath  *path)
919 {
920   GtkTreeIter parent;
921   gint *indices;
922   gint depth, i;
923
924   g_return_val_if_fail (tree_model != NULL, FALSE);
925   g_return_val_if_fail (iter != NULL, FALSE);
926   g_return_val_if_fail (path != NULL, FALSE);
927   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
928
929   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_iter != NULL)
930     return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_iter) (tree_model, iter, path);
931
932   indices = gtk_tree_path_get_indices (path);
933   depth = gtk_tree_path_get_depth (path);
934
935   g_return_val_if_fail (depth > 0, FALSE);
936
937   if (! gtk_tree_model_iter_nth_child (tree_model, iter, NULL, indices[0]))
938     return FALSE;
939
940   for (i = 1; i < depth; i++)
941     {
942       parent = *iter;
943       if (! gtk_tree_model_iter_nth_child (tree_model, iter, &parent, indices[i]))
944         return FALSE;
945     }
946
947   return TRUE;
948 }
949
950 /**
951  * gtk_tree_model_get_first:
952  * @tree_model: a #GtkTreeModel
953  * @iter: iterator to initialize
954  * 
955  * Initialized @iter with the first iterator in the tree (the one at the
956  * root path) and returns %TRUE, or returns %FALSE if there are no
957  * iterable locations in the model (i.e. the tree is empty).
958  * 
959  * Return value: %TRUE if @iter was initialized
960  **/
961 gboolean
962 gtk_tree_model_get_first (GtkTreeModel *tree_model,
963                           GtkTreeIter  *iter)
964 {
965   gboolean retval;
966   GtkTreePath *path;
967   
968   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
969   g_return_val_if_fail (iter != NULL, FALSE);
970
971   path = gtk_tree_path_new_root ();
972
973   retval = gtk_tree_model_get_iter (tree_model, iter, path);
974
975   gtk_tree_path_free (path);
976
977   return retval;
978 }
979
980 /**
981  * gtk_tree_model_get_path:
982  * @tree_model: A #GtkTreeModel.
983  * @iter: The #GtkTreeIter.
984  * 
985  * Returns a newly created #GtkTreePath referenced by @iter.  This path should
986  * be freed with #gtk_tree_path_free.
987  * 
988  * Return value: a newly created #GtkTreePath.
989  **/
990 GtkTreePath *
991 gtk_tree_model_get_path (GtkTreeModel *tree_model,
992                          GtkTreeIter  *iter)
993 {
994   g_return_val_if_fail (tree_model != NULL, NULL);
995   g_return_val_if_fail (iter != NULL, NULL);
996   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), NULL);
997   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_path != NULL, NULL);
998
999   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_path) (tree_model, iter);
1000 }
1001
1002 /**
1003  * gtk_tree_model_get_value:
1004  * @tree_model: A #GtkTreeModel.
1005  * @iter: The #GtkTreeIter.
1006  * @column: The column to lookup the value at.
1007  * @value: An empty #GValue to set.
1008  * 
1009  * Sets initializes and sets @value to that at @column.  When done with value,
1010  * #g_value_unset needs to be called on it.
1011  **/
1012 void
1013 gtk_tree_model_get_value (GtkTreeModel *tree_model,
1014                           GtkTreeIter  *iter,
1015                           gint          column,
1016                           GValue       *value)
1017 {
1018   g_return_if_fail (tree_model != NULL);
1019   g_return_if_fail (iter != NULL);
1020   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1021   g_return_if_fail (value != NULL);
1022   g_return_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_value != NULL);
1023
1024   (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_value) (tree_model, iter, column, value);
1025 }
1026
1027 /**
1028  * gtk_tree_model_iter_next:
1029  * @tree_model: A #GtkTreeModel.
1030  * @iter: The #GtkTreeIter.
1031  * 
1032  * Sets @iter to point to the node following it at the current level.  If there
1033  * is no next @iter, FALSE is returned and @iter is set to be invalid.
1034  * 
1035  * Return value: TRUE if @iter has been changed to the next node.
1036  **/
1037 gboolean
1038 gtk_tree_model_iter_next (GtkTreeModel  *tree_model,
1039                           GtkTreeIter   *iter)
1040 {
1041   g_return_val_if_fail (tree_model != NULL, FALSE);
1042   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1043   g_return_val_if_fail (iter != NULL, FALSE);
1044   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_next != NULL, FALSE);
1045
1046   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_next) (tree_model, iter);
1047 }
1048
1049 /**
1050  * gtk_tree_model_iter_children:
1051  * @tree_model: A #GtkTreeModel.
1052  * @iter: The new #GtkTreeIter to be set to the child.
1053  * @parent: The #GtkTreeIter.
1054  * 
1055  * Sets @iter to point to the first child of @parent.  If @parent has no children,
1056  * FALSE is returned and @iter is set to be invalid.  @parent will remain a valid
1057  * node after this function has been called.
1058  * 
1059  * Return value: TRUE, if @child has been set to the first child.
1060  **/
1061 gboolean
1062 gtk_tree_model_iter_children (GtkTreeModel *tree_model,
1063                               GtkTreeIter  *iter,
1064                               GtkTreeIter  *parent)
1065 {
1066   g_return_val_if_fail (tree_model != NULL, FALSE);
1067   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1068   g_return_val_if_fail (iter != NULL, FALSE);
1069   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_children != NULL, FALSE);
1070
1071   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_children) (tree_model, iter, parent);
1072 }
1073
1074 /**
1075  * gtk_tree_model_iter_has_child:
1076  * @tree_model: A #GtkTreeModel.
1077  * @iter: The #GtkTreeIter to test for children.
1078  * 
1079  * Returns TRUE if @iter has children, FALSE otherwise.
1080  * 
1081  * Return value: TRUE if @iter has children.
1082  **/
1083 gboolean
1084 gtk_tree_model_iter_has_child (GtkTreeModel *tree_model,
1085                                GtkTreeIter  *iter)
1086 {
1087   g_return_val_if_fail (tree_model != NULL, FALSE);
1088   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1089   g_return_val_if_fail (iter != NULL, FALSE);
1090   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_has_child != NULL, FALSE);
1091
1092   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_has_child) (tree_model, iter);
1093 }
1094
1095 /**
1096  * gtk_tree_model_iter_n_children:
1097  * @tree_model: A #GtkTreeModel.
1098  * @iter: The #GtkTreeIter, or NULL.
1099  * 
1100  * Returns the number of children that @iter has.  If @iter is NULL, then the
1101  * number of toplevel nodes is returned.
1102  * 
1103  * Return value: The number of children of @iter.
1104  **/
1105 gint
1106 gtk_tree_model_iter_n_children (GtkTreeModel *tree_model,
1107                                 GtkTreeIter  *iter)
1108 {
1109   g_return_val_if_fail (tree_model != NULL, 0);
1110   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
1111   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_n_children != NULL, 0);
1112
1113   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_n_children) (tree_model, iter);
1114 }
1115
1116 /**
1117  * gtk_tree_model_iter_nth_child:
1118  * @tree_model: A #GtkTreeModel.
1119  * @iter: The #GtkTreeIter to set to the nth child.
1120  * @parent: The #GtkTreeIter to get the child from, or NULL.
1121  * @n: Then index of the desired child.
1122  * 
1123  * Sets @iter to be the child of @parent, using the given index.  The first
1124  * index is 0.  If the index is too big, or @parent has no children, @iter is
1125  * set to an invalid iterator and FALSE is returned.  @parent will remain a
1126  * valid node after this function has been called.  If @parent is NULL, then the
1127  * root node is assumed.
1128  * 
1129  * Return value: TRUE, if @parent has an nth child.
1130  **/
1131 gboolean
1132 gtk_tree_model_iter_nth_child (GtkTreeModel *tree_model,
1133                                GtkTreeIter  *iter,
1134                                GtkTreeIter  *parent,
1135                                gint          n)
1136 {
1137   g_return_val_if_fail (tree_model != NULL, FALSE);
1138   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1139   g_return_val_if_fail (iter != NULL, FALSE);
1140   g_return_val_if_fail (n >= 0, FALSE);
1141   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_nth_child != NULL, FALSE);
1142
1143   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_nth_child) (tree_model, iter, parent, n);
1144 }
1145
1146 /**
1147  * gtk_tree_model_iter_parent:
1148  * @tree_model: A #GtkTreeModel
1149  * @iter: The new #GtkTreeIter to set to the parent.
1150  * @child: The #GtkTreeIter.
1151  * 
1152  * Sets @iter to be the parent of @child.  If @child is at the toplevel, and
1153  * doesn't have a parent, then @iter is set to an invalid iterator and FALSE
1154  * is returned.  @child will remain a valid node after this function has been
1155  * called.
1156  * 
1157  * Return value: TRUE, if @iter is set to the parent of @child.
1158  **/
1159 gboolean
1160 gtk_tree_model_iter_parent (GtkTreeModel *tree_model,
1161                             GtkTreeIter  *iter,
1162                             GtkTreeIter  *child)
1163 {
1164   g_return_val_if_fail (tree_model != NULL, FALSE);
1165   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1166   g_return_val_if_fail (iter != NULL, FALSE);
1167   g_return_val_if_fail (child != NULL, FALSE);
1168   g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_parent != NULL, FALSE);
1169
1170   return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_parent) (tree_model, iter, child);
1171 }
1172
1173 /* FIXME explain what the method is supposed to do! */
1174 /**
1175  * gtk_tree_model_ref_iter:
1176  * @tree_model: A #GtkTreeModel.
1177  * @iter: The #GtkTreeIter.
1178  * 
1179  * Ref's the iter.  This is an optional method for models to implement.  To be
1180  * more specific, models may ignore this call as it exists primarily for
1181  * performance reasons.
1182  **/
1183 void
1184 gtk_tree_model_ref_iter (GtkTreeModel *tree_model,
1185                          GtkTreeIter  *iter)
1186 {
1187   g_return_if_fail (tree_model != NULL);
1188   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1189
1190   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->ref_iter)
1191     (* GTK_TREE_MODEL_GET_IFACE (tree_model)->ref_iter) (tree_model, iter);
1192 }
1193
1194 /* FIXME explain what the method is supposed to do! */
1195 /**
1196  * gtk_tree_model_unref_iter:
1197  * @tree_model: A #GtkTreeModel.
1198  * @iter: The #GtkTreeIter.
1199  * 
1200  * Unref's the iter.  This is an optional method for models to implement.  To be
1201  * more specific, models may ignore this call as it exists primarily for
1202  * performance reasons.
1203  **/
1204 void
1205 gtk_tree_model_unref_iter (GtkTreeModel *tree_model,
1206                            GtkTreeIter  *iter)
1207 {
1208   g_return_if_fail (tree_model != NULL);
1209   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1210
1211   if (GTK_TREE_MODEL_GET_IFACE (tree_model)->unref_iter)
1212     (* GTK_TREE_MODEL_GET_IFACE (tree_model)->unref_iter) (tree_model, iter);
1213 }
1214
1215 /**
1216  * gtk_tree_model_get:
1217  * @tree_model: a #GtkTreeModel
1218  * @iter: a row in @tree_model
1219  * @Varargs: pairs of column number and value return locations, terminated by -1
1220  *
1221  * Gets the value of one or more cells in the row referenced by @iter.
1222  * The variable argument list should contain integer column numbers,
1223  * each column number followed by a place to store the value being
1224  * retrieved.  The list is terminated by a -1. For example, to get a
1225  * value from column 0 with type %G_TYPE_STRING, you would
1226  * write: gtk_tree_model_set (model, iter, 0, &place_string_here, -1),
1227  * where place_string_here is a gchar* to be filled with the string.
1228  * If appropriate, the returned values have to be freed or unreferenced.
1229  * 
1230  **/
1231 void
1232 gtk_tree_model_get (GtkTreeModel *tree_model,
1233                     GtkTreeIter  *iter,
1234                     ...)
1235 {
1236   va_list var_args;
1237
1238   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1239
1240   va_start (var_args, iter);
1241   gtk_tree_model_get_valist (tree_model, iter, var_args);
1242   va_end (var_args);
1243 }
1244
1245 /**
1246  * gtk_tree_model_get_valist:
1247  * @tree_model: a #GtkTreeModel
1248  * @iter: a row in @tree_model
1249  * @var_args: va_list of column/return location pairs
1250  *
1251  * See gtk_tree_model_get(), this version takes a va_list for
1252  * language bindings to use.
1253  * 
1254  **/
1255 void
1256 gtk_tree_model_get_valist (GtkTreeModel *tree_model,
1257                            GtkTreeIter  *iter,
1258                            va_list      var_args)
1259 {
1260   gint column;
1261
1262   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1263
1264   column = va_arg (var_args, gint);
1265
1266   while (column != -1)
1267     {
1268       GValue value = { 0, };
1269       gchar *error = NULL;
1270
1271       if (column >= gtk_tree_model_get_n_columns (tree_model))
1272         {
1273           g_warning ("%s: Invalid column number %d accessed (remember to end your list of columns with a -1)", G_STRLOC, column);
1274           break;
1275         }
1276
1277       gtk_tree_model_get_value (GTK_TREE_MODEL (tree_model), iter, column, &value);
1278
1279       G_VALUE_LCOPY (&value, var_args, 0, &error);
1280       if (error)
1281         {
1282           g_warning ("%s: %s", G_STRLOC, error);
1283           g_free (error);
1284
1285           /* we purposely leak the value here, it might not be
1286            * in a sane state if an error condition occoured
1287            */
1288           break;
1289         }
1290
1291       g_value_unset (&value);
1292
1293       column = va_arg (var_args, gint);
1294     }
1295 }
1296
1297 void
1298 gtk_tree_model_changed (GtkTreeModel *tree_model,
1299                         GtkTreePath  *path,
1300                         GtkTreeIter  *iter)
1301 {
1302   g_return_if_fail (tree_model != NULL);
1303   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1304   g_return_if_fail (path != NULL);
1305   g_return_if_fail (iter != NULL);
1306
1307   g_signal_emit_by_name (tree_model, "changed", path, iter);
1308 }
1309
1310 void
1311 gtk_tree_model_inserted (GtkTreeModel *tree_model,
1312                          GtkTreePath  *path,
1313                          GtkTreeIter  *iter)
1314 {
1315   g_return_if_fail (tree_model != NULL);
1316   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1317   g_return_if_fail (path != NULL);
1318   g_return_if_fail (iter != NULL);
1319
1320   g_signal_emit_by_name (tree_model, "inserted", path, iter);
1321 }
1322
1323 void
1324 gtk_tree_model_child_toggled (GtkTreeModel *tree_model,
1325                               GtkTreePath  *path,
1326                               GtkTreeIter  *iter)
1327 {
1328   g_return_if_fail (tree_model != NULL);
1329   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1330   g_return_if_fail (path != NULL);
1331   g_return_if_fail (iter != NULL);
1332
1333   g_signal_emit_by_name (tree_model, "child_toggled", path, iter);
1334 }
1335
1336 void
1337 gtk_tree_model_deleted (GtkTreeModel *tree_model,
1338                         GtkTreePath  *path)
1339 {
1340   g_return_if_fail (tree_model != NULL);
1341   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1342   g_return_if_fail (path != NULL);
1343
1344   g_signal_emit_by_name (tree_model, "deleted", path);
1345 }