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