gtktreestore.c 24 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* gtktreestore.c
 * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include "gtktreemodel.h"
#include "gtktreestore.h"
#include "gtktreedatalist.h"
#include "gtksignal.h"
#include <string.h>
25
#include <gobject/gvaluecollector.h>
26
27
28

#define G_NODE(node) ((GNode *)node)

29
enum {
30
31
32
33
  CHANGED,
  INSERTED,
  CHILD_TOGGLED,
  DELETED,
34
35
36
37
38
  LAST_SIGNAL
};

static guint tree_store_signals[LAST_SIGNAL] = { 0 };

39

40
41
42
static void         gtk_tree_store_init            (GtkTreeStore      *tree_store);
static void         gtk_tree_store_class_init      (GtkTreeStoreClass *tree_store_class);
static void         gtk_tree_store_tree_model_init (GtkTreeModelIface *iface);
43
static guint        gtk_tree_store_get_flags       (GtkTreeModel      *tree_model);
44
static gint         gtk_tree_store_get_n_columns   (GtkTreeModel      *tree_model);
45
46
static GType        gtk_tree_store_get_column_type (GtkTreeModel      *tree_model,
						    gint               index);
47
48
static GtkTreePath *gtk_tree_store_get_path        (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter);
49
static void         gtk_tree_store_get_value       (GtkTreeModel      *tree_model,
50
51
52
53
54
55
56
57
58
59
60
61
62
63
						    GtkTreeIter       *iter,
						    gint               column,
						    GValue            *value);
static gboolean     gtk_tree_store_iter_next       (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter);
static gboolean     gtk_tree_store_iter_children   (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter,
						    GtkTreeIter       *parent);
static gboolean     gtk_tree_store_iter_has_child  (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter);
static gint         gtk_tree_store_iter_n_children (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter);
static gboolean     gtk_tree_store_iter_nth_child  (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter,
64
						    GtkTreeIter       *parent,
65
66
67
						    gint               n);
static gboolean     gtk_tree_store_iter_parent     (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter,
68
						    GtkTreeIter       *child);
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90


GtkType
gtk_tree_store_get_type (void)
{
  static GtkType tree_store_type = 0;

  if (!tree_store_type)
    {
      static const GTypeInfo tree_store_info =
      {
        sizeof (GtkTreeStoreClass),
	NULL,		/* base_init */
	NULL,		/* base_finalize */
        (GClassInitFunc) gtk_tree_store_class_init,
	NULL,		/* class_finalize */
	NULL,		/* class_data */
        sizeof (GtkTreeStore),
	0,              /* n_preallocs */
        (GInstanceInitFunc) gtk_tree_store_init
      };

91
92
93
94
95
96
97
      static const GInterfaceInfo tree_model_info =
      {
	(GInterfaceInitFunc) gtk_tree_store_tree_model_init,
	NULL,
	NULL
      };

98
      tree_store_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeStore", &tree_store_info, 0);
99
100
101
      g_type_add_interface_static (tree_store_type,
				   GTK_TYPE_TREE_MODEL,
				   &tree_model_info);
102
103
104
105
106
107
    }

  return tree_store_type;
}

static void
108
gtk_tree_store_class_init (GtkTreeStoreClass *tree_store_class)
109
110
{
  GtkObjectClass *object_class;
111
112
113

  object_class = (GtkObjectClass *) tree_store_class;

114
115
  tree_store_signals[CHANGED] =
    gtk_signal_new ("changed",
116
117
                    GTK_RUN_FIRST,
                    GTK_CLASS_TYPE (object_class),
118
                    GTK_SIGNAL_OFFSET (GtkTreeStoreClass, changed),
119
120
121
122
                    gtk_marshal_VOID__BOXED_BOXED,
                    G_TYPE_NONE, 2,
		    GTK_TYPE_TREE_PATH,
		    GTK_TYPE_TREE_ITER);
123
124
  tree_store_signals[INSERTED] =
    gtk_signal_new ("inserted",
125
126
                    GTK_RUN_FIRST,
                    GTK_CLASS_TYPE (object_class),
127
                    GTK_SIGNAL_OFFSET (GtkTreeStoreClass, inserted),
128
129
130
131
                    gtk_marshal_VOID__BOXED_BOXED,
                    G_TYPE_NONE, 2,
		    GTK_TYPE_TREE_PATH,
		    GTK_TYPE_TREE_ITER);
132
133
  tree_store_signals[CHILD_TOGGLED] =
    gtk_signal_new ("child_toggled",
134
135
                    GTK_RUN_FIRST,
                    GTK_CLASS_TYPE (object_class),
136
                    GTK_SIGNAL_OFFSET (GtkTreeStoreClass, child_toggled),
137
138
139
140
                    gtk_marshal_VOID__BOXED_BOXED,
                    G_TYPE_NONE, 2,
		    GTK_TYPE_TREE_PATH,
		    GTK_TYPE_TREE_ITER);
141
142
  tree_store_signals[DELETED] =
    gtk_signal_new ("deleted",
143
144
                    GTK_RUN_FIRST,
                    GTK_CLASS_TYPE (object_class),
145
                    GTK_SIGNAL_OFFSET (GtkTreeStoreClass, deleted),
146
147
148
                    gtk_marshal_VOID__BOXED,
                    G_TYPE_NONE, 1,
		    GTK_TYPE_TREE_PATH);
149
150
151
152
153
154
155

  gtk_object_class_add_signals (object_class, tree_store_signals, LAST_SIGNAL);
}

static void
gtk_tree_store_tree_model_init (GtkTreeModelIface *iface)
{
156
  iface->get_flags = gtk_tree_store_get_flags;
157
  iface->get_n_columns = gtk_tree_store_get_n_columns;
158
  iface->get_column_type = gtk_tree_store_get_column_type;
159
  iface->get_path = gtk_tree_store_get_path;
160
  iface->get_value = gtk_tree_store_get_value;
161
162
163
164
165
166
  iface->iter_next = gtk_tree_store_iter_next;
  iface->iter_children = gtk_tree_store_iter_children;
  iface->iter_has_child = gtk_tree_store_iter_has_child;
  iface->iter_n_children = gtk_tree_store_iter_n_children;
  iface->iter_nth_child = gtk_tree_store_iter_nth_child;
  iface->iter_parent = gtk_tree_store_iter_parent;
167
168
169
170
171
}

static void
gtk_tree_store_init (GtkTreeStore *tree_store)
{
172
  tree_store->root = g_node_new (NULL);
173
  tree_store->stamp = g_random_int ();
174
175
}

176
GtkTreeStore *
177
178
gtk_tree_store_new (void)
{
179
  return GTK_TREE_STORE (gtk_type_new (gtk_tree_store_get_type ()));
180
181
}

182
GtkTreeStore *
183
184
gtk_tree_store_new_with_types (gint n_columns,
			       ...)
185
{
186
  GtkTreeStore *retval;
187
188
189
190
191
192
  va_list args;
  gint i;

  g_return_val_if_fail (n_columns > 0, NULL);

  retval = gtk_tree_store_new ();
193
  gtk_tree_store_set_n_columns (retval, n_columns);
194
195

  va_start (args, n_columns);
196

197
  for (i = 0; i < n_columns; i++)
198
    gtk_tree_store_set_column_type (retval, i, va_arg (args, GType));
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

  va_end (args);

  return retval;
}

void
gtk_tree_store_set_n_columns (GtkTreeStore *tree_store,
			      gint          n_columns)
{
  GType *new_columns;

  g_return_if_fail (tree_store != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));

  if (tree_store->n_columns == n_columns)
    return;

  new_columns = g_new0 (GType, n_columns);
  if (tree_store->column_headers)
    {
      /* copy the old header orders over */
      if (n_columns >= tree_store->n_columns)
	memcpy (new_columns, tree_store->column_headers, tree_store->n_columns * sizeof (gchar *));
      else
	memcpy (new_columns, tree_store->column_headers, n_columns * sizeof (GType));

      g_free (tree_store->column_headers);
    }

  tree_store->column_headers = new_columns;
  tree_store->n_columns = n_columns;
}

void
gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
				gint          column,
				GType         type)
{
  g_return_if_fail (tree_store != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
  g_return_if_fail (column >=0 && column < tree_store->n_columns);

  tree_store->column_headers[column] = type;
}

/* fulfill the GtkTreeModel requirements */
/* NOTE: GtkTreeStore::root is a GNode, that acts as the parent node.  However,
 * it is not visible to the tree or to the user., and the path "1" refers to the
 * first child of GtkTreeStore::root.
 */
250
251
252
253
254
255
256
257
258
259


static guint
gtk_tree_store_get_flags (GtkTreeModel *tree_model)
{
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);

  return GTK_TREE_MODEL_ITERS_PERSIST;
}

260
261
262
263
264
265
266
267
static gint
gtk_tree_store_get_n_columns (GtkTreeModel *tree_model)
{
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);

  return GTK_TREE_STORE (tree_model)->n_columns;
}

268
269
270
271
272
273
274
275
276
277
278
static GType
gtk_tree_store_get_column_type (GtkTreeModel *tree_model,
				gint          index)
{
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), G_TYPE_INVALID);
  g_return_val_if_fail (index < GTK_TREE_STORE (tree_model)->n_columns &&
			index >= 0, G_TYPE_INVALID);

  return GTK_TREE_STORE (tree_model)->column_headers[index];
}

279
280
static GtkTreePath *
gtk_tree_store_get_path (GtkTreeModel *tree_model,
281
			 GtkTreeIter  *iter)
282
283
284
285
286
287
{
  GtkTreePath *retval;
  GNode *tmp_node;
  gint i = 0;

  g_return_val_if_fail (tree_model != NULL, NULL);
288
289
290
291
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), NULL);
  g_return_val_if_fail (iter != NULL, NULL);
  g_return_val_if_fail (GTK_TREE_STORE (tree_model)->stamp == iter->stamp, NULL);
  if (iter->tree_node == NULL)
292
293
    return NULL;

294
  if (G_NODE (iter->tree_node)->parent == G_NODE (GTK_TREE_STORE (tree_model)->root))
295
296
297
298
299
300
    {
      retval = gtk_tree_path_new ();
      tmp_node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
    }
  else
    {
301
302
303
      GtkTreeIter tmp_iter = *iter;
      tmp_iter.tree_node = G_NODE (tmp_iter.tree_node)->parent;

304
      retval = gtk_tree_store_get_path (tree_model,
305
306
					&tmp_iter);
      tmp_node = G_NODE (iter->tree_node)->parent->children;
307
308
309
310
    }

  if (retval == NULL)
    return NULL;
311

312
313
314
315
316
317
318
319
  if (tmp_node == NULL)
    {
      gtk_tree_path_free (retval);
      return NULL;
    }

  for (; tmp_node; tmp_node = tmp_node->next)
    {
320
      if (tmp_node == G_NODE (iter->tree_node))
321
322
323
	break;
      i++;
    }
324

325
326
327
  if (tmp_node == NULL)
    {
      /* We couldn't find node, meaning it's prolly not ours */
328
      /* Perhaps I should do a g_return_if_fail here. */
329
330
331
332
333
334
335
336
337
338
339
      gtk_tree_path_free (retval);
      return NULL;
    }

  gtk_tree_path_append_index (retval, i);

  return retval;
}


static void
340
341
342
343
gtk_tree_store_get_value (GtkTreeModel *tree_model,
			  GtkTreeIter  *iter,
			  gint          column,
			  GValue       *value)
344
345
346
347
348
349
{
  GtkTreeDataList *list;
  gint tmp_column = column;

  g_return_if_fail (tree_model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (tree_model));
350
351
  g_return_if_fail (iter != NULL);
  g_return_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->stamp);
352
353
  g_return_if_fail (column < GTK_TREE_STORE (tree_model)->n_columns);

354
  list = G_NODE (iter->tree_node)->data;
355
356
357
358

  while (tmp_column-- > 0 && list)
    list = list->next;

359
360
  if (list)
    {
361
362
363
      _gtk_tree_data_list_node_to_value (list,
					 GTK_TREE_STORE (tree_model)->column_headers[column],
					 value);
364
365
366
367
368
369
    }
  else
    {
      /* We want to return an initialized but empty (default) value */
      g_value_init (value, GTK_TREE_STORE (tree_model)->column_headers[column]);
    }
370
371
372
}

static gboolean
373
374
gtk_tree_store_iter_next (GtkTreeModel  *tree_model,
			  GtkTreeIter   *iter)
375
{
376
  if (iter->tree_node == NULL)
377
378
    return FALSE;

379
380
381
  iter->tree_node = G_NODE (iter->tree_node)->next;

  return (iter->tree_node != NULL);
382
383
}

384
385
386
387
static gboolean
gtk_tree_store_iter_children (GtkTreeModel *tree_model,
			      GtkTreeIter  *iter,
			      GtkTreeIter  *parent)
388
{
389
  iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
390
391
392
393
  if (parent)
    iter->tree_node = G_NODE (parent->tree_node)->children;
  else
    iter->tree_node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
394
395

  return iter->tree_node != NULL;
396
397
398
}

static gboolean
399
400
gtk_tree_store_iter_has_child (GtkTreeModel *tree_model,
			       GtkTreeIter  *iter)
401
{
402
403
404
405
406
407
  g_return_val_if_fail (tree_model != NULL, FALSE);
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), FALSE);
  g_return_val_if_fail (iter != NULL, FALSE);
  g_return_val_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->stamp, FALSE);

  return G_NODE (iter->tree_node)->children != NULL;
408
409
410
}

static gint
411
412
gtk_tree_store_iter_n_children (GtkTreeModel *tree_model,
				GtkTreeIter  *iter)
413
{
414
  GNode *node;
415
416
  gint i = 0;

417
418
  g_return_val_if_fail (tree_model != NULL, 0);
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);
419
420
  if (iter)
    g_return_val_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->stamp, 0);
421

422
423
424
425
  if (iter == NULL)
    node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
  else
    node = G_NODE (iter->tree_node)->children;
426
  while (node)
427
428
    {
      i++;
429
      node = node->next;
430
431
432
433
434
    }

  return i;
}

435
436
437
438
static gboolean
gtk_tree_store_iter_nth_child (GtkTreeModel *tree_model,
			       GtkTreeIter  *iter,
			       GtkTreeIter  *parent,
439
440
			       gint          n)
{
441
  GNode *parent_node;
442

443
444
445
446
447
  g_return_val_if_fail (tree_model != NULL, FALSE);
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), FALSE);
  g_return_val_if_fail (iter != NULL, FALSE);
  if (parent)
    g_return_val_if_fail (parent->stamp == GTK_TREE_STORE (tree_model)->stamp, FALSE);
448

449
450
451
452
453
454
455
456
457
458
459
460
461
  if (parent == NULL)
    parent_node = GTK_TREE_STORE (tree_model)->root;
  else
    parent_node = parent->tree_node;

  iter->tree_node = g_node_nth_child (parent_node, n);

  if (iter->tree_node == NULL)
    iter->stamp = 0;
  else
    iter->stamp = GTK_TREE_STORE (tree_model)->stamp;

  return (iter->tree_node != NULL);
462
463
}

464
465
466
467
static gboolean
gtk_tree_store_iter_parent (GtkTreeModel *tree_model,
			    GtkTreeIter  *iter,
			    GtkTreeIter  *child)
468
{
469
470
  iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
  iter->tree_node = G_NODE (child->tree_node)->parent;
471

472
473
474
475
476
477
478
  if (iter->tree_node == GTK_TREE_STORE (tree_model)->root)
    {
      iter->stamp = 0;
      return FALSE;
    }

  return TRUE;
479
480
481
482
483
484
485
}

/*
 * This is a somewhat inelegant function that does a lot of list
 * manipulations on it's own.
 */
void
486
487
488
489
gtk_tree_store_set_cell (GtkTreeStore *tree_store,
			 GtkTreeIter  *iter,
			 gint          column,
			 GValue       *value)
490
491
492
493
494
495
496
497
{
  GtkTreeDataList *list;
  GtkTreeDataList *prev;

  g_return_if_fail (tree_store != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
  g_return_if_fail (column >= 0 && column < tree_store->n_columns);

498
  prev = list = G_NODE (iter->tree_node)->data;
499
500
501
502
503

  while (list != NULL)
    {
      if (column == 0)
	{
504
	  _gtk_tree_data_list_value_to_node (list, value);
505
506
507
508
509
510
511
512
	  return;
	}

      column--;
      prev = list;
      list = list->next;
    }

513
  if (G_NODE (iter->tree_node)->data == NULL)
514
    {
515
      G_NODE (iter->tree_node)->data = list = _gtk_tree_data_list_alloc ();
516
517
518
519
      list->next = NULL;
    }
  else
    {
520
      list = prev->next = _gtk_tree_data_list_alloc ();
521
522
523
524
525
      list->next = NULL;
    }

  while (column != 0)
    {
526
      list->next = _gtk_tree_data_list_alloc ();
527
528
529
530
      list = list->next;
      list->next = NULL;
      column --;
    }
531
532
533
534
  _gtk_tree_data_list_value_to_node (list, value);
  gtk_signal_emit_by_name (GTK_OBJECT (tree_store),
			   "changed",
			   NULL, iter);
535
536
537
}

void
538
539
540
gtk_tree_store_setv (GtkTreeStore *tree_store,
		     GtkTreeIter  *iter,
		     va_list	var_args)
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
{
  gint column;

  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));

  column = va_arg (var_args, gint);

  while (column >= 0)
    {
      GValue value = { 0, };
      gchar *error = NULL;

      if (column >= tree_store->n_columns)
	{
	  g_warning ("Invalid column number %d added to iter", column);
	  break;
	}
      g_value_init (&value, tree_store->column_headers[column]);

      G_VALUE_COLLECT (&value, var_args, &error);
      if (error)
	{
	  g_warning ("%s: %s", G_STRLOC, error);
	  g_free (error);

 	  /* we purposely leak the value here, it might not be
	   * in a sane state if an error condition occoured
	   */
	  break;
	}

572
573
574
575
      gtk_tree_store_set_cell (tree_store,
			       iter,
			       column,
			       &value);
576
577
578
579
580
581
582
583

      g_value_unset (&value);

      column = va_arg (var_args, gint);
    }
}

void
584
585
586
gtk_tree_store_set (GtkTreeStore *tree_store,
		    GtkTreeIter  *iter,
		    ...)
587
588
589
590
591
592
{
  va_list var_args;

  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));

  va_start (var_args, iter);
593
  gtk_tree_store_setv (tree_store, iter, var_args);
594
595
596
597
  va_end (var_args);
}

void
598
599
600
gtk_tree_store_getv (GtkTreeStore *tree_store,
		     GtkTreeIter  *iter,
		     va_list	var_args)
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
{
  gint column;

  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));

  column = va_arg (var_args, gint);

  while (column >= 0)
    {
      GValue value = { 0, };
      gchar *error = NULL;

      if (column >= tree_store->n_columns)
	{
	  g_warning ("Invalid column number %d accessed", column);
	  break;
	}

619
      gtk_tree_store_get_value (GTK_TREE_MODEL (tree_store), iter, column, &value);
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639

      G_VALUE_LCOPY (&value, var_args, &error);
      if (error)
	{
	  g_warning ("%s: %s", G_STRLOC, error);
	  g_free (error);

 	  /* we purposely leak the value here, it might not be
	   * in a sane state if an error condition occoured
	   */
	  break;
	}

      g_value_unset (&value);

      column = va_arg (var_args, gint);
    }
}

void
640
641
642
gtk_tree_store_get (GtkTreeStore *tree_store,
		    GtkTreeIter  *iter,
		    ...)
643
644
645
646
647
648
{
  va_list var_args;

  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));

  va_start (var_args, iter);
649
  gtk_tree_store_getv (tree_store, iter, var_args);
650
651
652
653
  va_end (var_args);
}

void
654
655
gtk_tree_store_remove (GtkTreeStore *model,
		       GtkTreeIter  *iter)
656
657
{
  GtkTreePath *path;
658

659
660
661
662
663
  GNode *parent;

  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));

664
  parent = G_NODE (iter->tree_node)->parent;
665

666
667
668
669
  if (G_NODE (iter->tree_node)->data)
    _gtk_tree_data_list_free ((GtkTreeDataList *) G_NODE (iter->tree_node)->data,
			      model->column_headers);

670
671
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
  g_node_destroy (G_NODE (iter->tree_node));
672
673

  model->stamp++;
674
  gtk_signal_emit_by_name (GTK_OBJECT (model),
675
			   "deleted",
676
677
678
679
680
			   path);
  if (parent != G_NODE (model->root) && parent->children == NULL)
    {
      gtk_tree_path_up (path);
      gtk_signal_emit_by_name (GTK_OBJECT (model),
681
			       "child_toggled",
682
683
684
685
686
687
			       path,
			       parent);
    }
  gtk_tree_path_free (path);
}

688
void
689
690
691
692
gtk_tree_store_insert (GtkTreeStore *model,
		       GtkTreeIter  *iter,
		       GtkTreeIter  *parent,
		       gint          position)
693
694
695
{
  GtkTreePath *path;

696
697
  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
698

699
700
  if (parent->tree_node == NULL)
    parent->tree_node = model->root;
701

702
703
704
705
706
  iter->stamp = model->stamp;
  iter->tree_node = g_node_new (NULL);
  g_node_insert (G_NODE (parent->tree_node), position, G_NODE (iter->tree_node));
  
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
707
  gtk_signal_emit_by_name (GTK_OBJECT (model),
708
709
			   "inserted",
			   path, iter);
710
711
712
  gtk_tree_path_free (path);
}

713
void
714
715
716
717
gtk_tree_store_insert_before (GtkTreeStore *model,
			      GtkTreeIter  *iter,
			      GtkTreeIter  *parent,
			      GtkTreeIter  *sibling)
718
719
{
  GtkTreePath *path;
720
  GNode *parent_node = NULL;
721

722
723
724
725
726
727
728
  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
  g_return_if_fail (iter != NULL);
  if (parent != NULL)
    g_return_if_fail (parent->stamp == model->stamp);
  if (sibling != NULL)
    g_return_if_fail (sibling->stamp == model->stamp);
729

730
731
  iter->stamp = model->stamp;
  iter->tree_node = g_node_new (NULL);
732

733
734
735
736
737
738
  if (parent == NULL && sibling == NULL)
    parent_node = model->root;
  else if (parent == NULL)
    parent_node = G_NODE (sibling->tree_node)->parent;
  else
    parent_node = G_NODE (parent->tree_node);
739

740
741
742
  g_node_insert_before (parent_node,
			sibling ? G_NODE (sibling->tree_node) : NULL,
			G_NODE (iter->tree_node));
743

744
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
745
  gtk_signal_emit_by_name (GTK_OBJECT (model),
746
747
			   "inserted",
			   path, iter);
748
749
750
  gtk_tree_path_free (path);
}

751
void
752
753
754
755
gtk_tree_store_insert_after (GtkTreeStore *model,
			     GtkTreeIter  *iter,
			     GtkTreeIter  *parent,
			     GtkTreeIter  *sibling)
756
757
{
  GtkTreePath *path;
758
  GNode *parent_node;
759

760
761
762
763
764
765
766
  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
  g_return_if_fail (iter != NULL);
  if (parent != NULL)
    g_return_if_fail (parent->stamp == model->stamp);
  if (sibling != NULL)
    g_return_if_fail (sibling->stamp == model->stamp);
767

768
769
  iter->stamp = model->stamp;
  iter->tree_node = g_node_new (NULL);
770

771
772
773
774
775
776
  if (parent == NULL && sibling == NULL)
    parent_node = model->root;
  else if (parent == NULL)
    parent_node = G_NODE (sibling->tree_node)->parent;
  else
    parent_node = G_NODE (parent->tree_node);
777

778
779
780
  g_node_insert_after (parent_node,
		       sibling ? G_NODE (sibling->tree_node) : NULL,
		       G_NODE (iter->tree_node));
781

782
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
783
  gtk_signal_emit_by_name (GTK_OBJECT (model),
784
785
			   "inserted",
			   path, iter);
786
787
788
  gtk_tree_path_free (path);
}

789
void
790
791
792
gtk_tree_store_prepend (GtkTreeStore *model,
			GtkTreeIter  *iter,
			GtkTreeIter  *parent)
793
{
794
795
796
797
798
799
800
  GNode *parent_node;

  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
  g_return_if_fail (iter != NULL);
  if (parent != NULL)
    g_return_if_fail (parent->stamp == model->stamp);
801
802

  if (parent == NULL)
803
804
805
    parent_node = model->root;
  else
    parent_node = parent->tree_node;
806

807
808
809
810
  iter->stamp = model->stamp;
  iter->tree_node = g_node_new (NULL);

  if (parent_node->children == NULL)
811
812
    {
      GtkTreePath *path;
813
814
815
816

      g_node_prepend (parent_node, G_NODE (iter->tree_node));

      if (parent_node != model->root)
817
818
819
	{
	  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
	  gtk_signal_emit_by_name (GTK_OBJECT (model),
820
				   "child_toggled",
821
822
				   path,
				   parent);
823
	  gtk_tree_path_append_index (path, 0);
824
825
826
	}
      else
	{
827
	  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
828
829
	}
      gtk_signal_emit_by_name (GTK_OBJECT (model),
830
			       "inserted",
831
			       path,
832
			       iter);
833
834
835
836
      gtk_tree_path_free (path);
    }
  else
    {
837
      gtk_tree_store_insert_after (model, iter, parent, NULL);
838
839
840
    }
}

841
void
842
843
844
gtk_tree_store_append (GtkTreeStore *model,
		       GtkTreeIter  *iter,
		       GtkTreeIter  *parent)
845
{
846
847
848
849
850
851
852
  GNode *parent_node;

  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
  g_return_if_fail (iter != NULL);
  if (parent != NULL)
    g_return_if_fail (parent->stamp == model->stamp);
853
854

  if (parent == NULL)
855
856
857
    parent_node = model->root;
  else
    parent_node = parent->tree_node;
858

859
860
861
862
  iter->stamp = model->stamp;
  iter->tree_node = g_node_new (NULL);

  if (parent_node->children == NULL)
863
864
    {
      GtkTreePath *path;
865
866
867
868

      g_node_append (parent_node, G_NODE (iter->tree_node));

      if (parent_node != model->root)
869
870
871
	{
	  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
	  gtk_signal_emit_by_name (GTK_OBJECT (model),
872
				   "child_toggled",
873
874
				   path,
				   parent);
875
	  gtk_tree_path_append_index (path, 0);
876
877
878
	}
      else
	{
879
	  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
880
881
	}
      gtk_signal_emit_by_name (GTK_OBJECT (model),
882
			       "inserted",
883
			       path,
884
			       iter);
885
886
887
888
      gtk_tree_path_free (path);
    }
  else
    {
889
      gtk_tree_store_insert_before (model, iter, parent, NULL);
890
891
892
    }
}

893
void
894
895
gtk_tree_store_get_root_iter (GtkTreeStore *model,
			      GtkTreeIter  *iter)
896
{
897
898
899
  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
  g_return_if_fail (iter != NULL);
900

901
902
  iter->stamp = model->stamp;
  iter->tree_node = G_NODE (model->root)->children;
903
904
905
906
}


gboolean
907
908
909
gtk_tree_store_is_ancestor (GtkTreeStore *model,
			    GtkTreeIter  *iter,
			    GtkTreeIter  *descendant)
910
911
912
{
  g_return_val_if_fail (model != NULL, FALSE);
  g_return_val_if_fail (GTK_IS_TREE_STORE (model), FALSE);
913
  g_return_val_if_fail (iter != NULL, FALSE);
914
  g_return_val_if_fail (descendant != NULL, FALSE);
915
916
  g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
  g_return_val_if_fail (descendant->stamp == model->stamp, FALSE);
917

918
919
  return g_node_is_ancestor (G_NODE (iter->tree_node),
			     G_NODE (descendant->tree_node));
920
921
922
923
}


gint
924
925
gtk_tree_store_iter_depth (GtkTreeStore *model,
			   GtkTreeIter  *iter)
926
927
928
{
  g_return_val_if_fail (model != NULL, 0);
  g_return_val_if_fail (GTK_IS_TREE_STORE (model), 0);
929
930
  g_return_val_if_fail (iter != NULL, 0);
  g_return_val_if_fail (iter->stamp == model->stamp, 0);
931

932
  return g_node_depth (G_NODE (iter->tree_node)) - 1;
933
}