gtktreestore.c 45.8 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
/* 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"
23
#include "gtktreednd.h"
24
#include <string.h>
25
#include <gobject/gvaluecollector.h>
26
27

#define G_NODE(node) ((GNode *)node)
28
#define GTK_TREE_STORE_IS_SORTED(tree) (GTK_TREE_STORE (tree)->sort_column_id != -1)
29

30
31
32
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);
33
34
static void         gtk_tree_store_drag_source_init(GtkTreeDragSourceIface *iface);
static void         gtk_tree_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
35
static void         gtk_tree_store_sortable_init   (GtkTreeSortableIface   *iface);
36
static guint        gtk_tree_store_get_flags       (GtkTreeModel      *tree_model);
37
static gint         gtk_tree_store_get_n_columns   (GtkTreeModel      *tree_model);
38
39
static GType        gtk_tree_store_get_column_type (GtkTreeModel      *tree_model,
						    gint               index);
40
41
static GtkTreePath *gtk_tree_store_get_path        (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter);
42
static void         gtk_tree_store_get_value       (GtkTreeModel      *tree_model,
43
44
45
46
47
48
49
50
51
52
53
54
55
56
						    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,
57
						    GtkTreeIter       *parent,
58
59
60
						    gint               n);
static gboolean     gtk_tree_store_iter_parent     (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter,
61
						    GtkTreeIter       *child);
62
63


64
/* DND interfaces */
65
static gboolean gtk_tree_store_drag_data_delete   (GtkTreeDragSource *drag_source,
66
						   GtkTreePath       *path);
67
static gboolean gtk_tree_store_drag_data_get      (GtkTreeDragSource *drag_source,
68
69
						   GtkTreePath       *path,
						   GtkSelectionData  *selection_data);
70
static gboolean gtk_tree_store_drag_data_received (GtkTreeDragDest   *drag_dest,
71
72
						   GtkTreePath       *dest,
						   GtkSelectionData  *selection_data);
73
static gboolean gtk_tree_store_row_drop_possible  (GtkTreeDragDest   *drag_dest,
74
75
76
77
78
79
						   GtkTreeModel      *src_model,
						   GtkTreePath       *src_path,
						   GtkTreePath       *dest_path);

/* Sortable Interfaces */

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
static void     gtk_tree_store_sort                    (GtkTreeStore           *tree_store);
static void     gtk_tree_store_sort_iter_changed       (GtkTreeStore           *tree_store,
							GtkTreeIter            *iter,
							gint                    column);
static gboolean gtk_tree_store_get_sort_column_id      (GtkTreeSortable        *sortable,
							gint                   *sort_column_id,
							GtkTreeSortOrder       *order);
static void     gtk_tree_store_set_sort_column_id      (GtkTreeSortable        *sortable,
							gint                    sort_column_id,
							GtkTreeSortOrder        order);
static void     gtk_tree_store_sort_column_id_set_func (GtkTreeSortable        *sortable,
							gint                    sort_column_id,
							GtkTreeIterCompareFunc  func,
							gpointer                data,
							GtkDestroyNotify        destroy);
95

96
97
98
99
100
101
102
103
104

static void     validate_gnode                    (GNode *node);

static inline void
validate_tree (GtkTreeStore *tree_store)
{
  if (gtk_debug_flags & GTK_DEBUG_TREE)
    {
      g_assert (G_NODE (tree_store->root)->parent == NULL);
105

106
107
108
109
      validate_gnode (G_NODE (tree_store->root));
    }
}

110
111
112
GtkType
gtk_tree_store_get_type (void)
{
113
  static GType tree_store_type = 0;
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

  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
      };

130
131
132
133
134
135
136
      static const GInterfaceInfo tree_model_info =
      {
	(GInterfaceInitFunc) gtk_tree_store_tree_model_init,
	NULL,
	NULL
      };

137
138
139
140
141
142
143
144
145
146
147
148
149
      static const GInterfaceInfo drag_source_info =
      {
	(GInterfaceInitFunc) gtk_tree_store_drag_source_init,
	NULL,
	NULL
      };

      static const GInterfaceInfo drag_dest_info =
      {
	(GInterfaceInitFunc) gtk_tree_store_drag_dest_init,
	NULL,
	NULL
      };
150
151
152
153
154
155
156
157

      static const GInterfaceInfo sortable_info =
      {
	(GInterfaceInitFunc) gtk_tree_store_sortable_init,
	NULL,
	NULL
      };

158
      tree_store_type = g_type_register_static (G_TYPE_OBJECT, "GtkTreeStore", &tree_store_info, 0);
159

160
161
162
      g_type_add_interface_static (tree_store_type,
				   GTK_TYPE_TREE_MODEL,
				   &tree_model_info);
163
164
165
166
167
168
      g_type_add_interface_static (tree_store_type,
				   GTK_TYPE_TREE_DRAG_SOURCE,
				   &drag_source_info);
      g_type_add_interface_static (tree_store_type,
				   GTK_TYPE_TREE_DRAG_DEST,
				   &drag_dest_info);
169
170
171
      g_type_add_interface_static (tree_store_type,
				   GTK_TYPE_TREE_SORTABLE,
				   &sortable_info);
172

173
174
175
176
177
178
    }

  return tree_store_type;
}

static void
179
gtk_tree_store_class_init (GtkTreeStoreClass *tree_store_class)
180
{
181
182
183
184
  GObjectClass *object_class;

  object_class = (GObjectClass *) tree_store_class;

185
186
187
188
189
}

static void
gtk_tree_store_tree_model_init (GtkTreeModelIface *iface)
{
190
  iface->get_flags = gtk_tree_store_get_flags;
191
  iface->get_n_columns = gtk_tree_store_get_n_columns;
192
  iface->get_column_type = gtk_tree_store_get_column_type;
193
  iface->get_path = gtk_tree_store_get_path;
194
  iface->get_value = gtk_tree_store_get_value;
195
196
197
198
199
200
  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;
201
202
}

203
204
205
206
207
208
209
210
static void
gtk_tree_store_drag_source_init (GtkTreeDragSourceIface *iface)
{
  iface->drag_data_delete = gtk_tree_store_drag_data_delete;
  iface->drag_data_get = gtk_tree_store_drag_data_get;
}

static void
211
gtk_tree_store_drag_dest_init (GtkTreeDragDestIface *iface)
212
213
214
215
216
{
  iface->drag_data_received = gtk_tree_store_drag_data_received;
  iface->row_drop_possible = gtk_tree_store_row_drop_possible;
}

217
218
219
static void
gtk_tree_store_sortable_init (GtkTreeSortableIface *iface)
{
220
221
222
  iface->get_sort_column_id = gtk_tree_store_get_sort_column_id;
  iface->set_sort_column_id = gtk_tree_store_set_sort_column_id;
  iface->sort_column_id_set_func = gtk_tree_store_sort_column_id_set_func;
223
224
}

225
226
227
static void
gtk_tree_store_init (GtkTreeStore *tree_store)
{
228
  tree_store->root = g_node_new (NULL);
229
  tree_store->stamp = g_random_int ();
230
  tree_store->sort_list = NULL;
231
  tree_store->sort_column_id = -1;
232
233
}

234
GtkTreeStore *
235
236
gtk_tree_store_new (void)
{
237
  return GTK_TREE_STORE (g_object_new (GTK_TYPE_TREE_STORE, NULL));
238
239
}

240
GtkTreeStore *
241
242
gtk_tree_store_new_with_types (gint n_columns,
			       ...)
243
{
244
  GtkTreeStore *retval;
245
246
247
248
249
250
  va_list args;
  gint i;

  g_return_val_if_fail (n_columns > 0, NULL);

  retval = gtk_tree_store_new ();
251
  gtk_tree_store_set_n_columns (retval, n_columns);
252
253

  va_start (args, n_columns);
254

255
  for (i = 0; i < n_columns; i++)
256
257
258
259
260
261
262
263
264
265
    {
      GType type = va_arg (args, GType);
      if (! _gtk_tree_data_list_check_type (type))
	{
	  g_warning ("%s: Invalid type %s passed to gtk_tree_store_new_with_types\n", G_STRLOC, g_type_name (type));
	  g_object_unref (G_OBJECT (retval));
	  return NULL;
	}
      gtk_tree_store_set_column_type (retval, i, type);
    }
266
267
268
269
270
  va_end (args);

  return retval;
}

271
272
273
274
275
276
277
278
/**
 * gtk_tree_store_set_n_columns:
 * @tree_store: 
 * @n_columns: 
 * 
 * As a side effect of calling this function, all sort columns that overlap with
 * the current number of columns will be removed.
 **/
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
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);
    }

303
304
305
306
307
  if (tree_store->sort_list)
    _gtk_tree_data_list_header_free (tree_store->sort_list);

  tree_store->sort_list = _gtk_tree_data_list_header_new (n_columns, tree_store->column_headers);

308
309
310
311
  tree_store->column_headers = new_columns;
  tree_store->n_columns = n_columns;
}

312
313
314
315
316
/**
 * gtk_tree_store_set_column_type:
 * @tree_store: a #GtkTreeStore
 * @column: column number
 * @type: type of the data to be stored in @column
317
 *
318
319
320
321
 * Supported types include: %G_TYPE_UINT, %G_TYPE_INT, %G_TYPE_UCHAR,
 * %G_TYPE_CHAR, %G_TYPE_BOOLEAN, %G_TYPE_POINTER, %G_TYPE_FLOAT,
 * %G_TYPE_DOUBLE, %G_TYPE_STRING, %G_TYPE_OBJECT, and %G_TYPE_BOXED, along with
 * subclasses of those types such as %GDK_TYPE_PIXBUF.
322
 *
323
 **/
324
325
326
327
328
329
330
331
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);
332
333
334
335
336
  if (!_gtk_tree_data_list_check_type (type))
    {
      g_warning ("%s: Invalid type %s passed to gtk_tree_store_new_with_types\n", G_STRLOC, g_type_name (type));
      return;
    }
337
338
339
340
341
  tree_store->column_headers[column] = type;
}

/* fulfill the GtkTreeModel requirements */
/* NOTE: GtkTreeStore::root is a GNode, that acts as the parent node.  However,
342
 * it is not visible to the tree or to the user., and the path "0" refers to the
343
344
 * first child of GtkTreeStore::root.
 */
345
346
347
348
349
350
351
352
353
354


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;
}

355
356
357
358
359
360
361
362
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;
}

363
364
365
366
367
368
369
370
371
372
373
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];
}

374
375
static GtkTreePath *
gtk_tree_store_get_path (GtkTreeModel *tree_model,
376
			 GtkTreeIter  *iter)
377
378
379
380
{
  GtkTreePath *retval;
  GNode *tmp_node;
  gint i = 0;
381

382
  g_return_val_if_fail (tree_model != NULL, NULL);
383
384
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), NULL);
  g_return_val_if_fail (iter != NULL, NULL);
385
  g_return_val_if_fail (iter->user_data != NULL, NULL);
386

387
  validate_tree ((GtkTreeStore*)tree_model);
388

389
  g_assert (G_NODE (iter->user_data)->parent != NULL);
390

Havoc Pennington's avatar
Havoc Pennington committed
391
  if (G_NODE (iter->user_data)->parent == G_NODE (GTK_TREE_STORE (tree_model)->root))
392
393
394
395
396
397
    {
      retval = gtk_tree_path_new ();
      tmp_node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
    }
  else
    {
398
      GtkTreeIter tmp_iter = *iter;
399

400
      tmp_iter.user_data = G_NODE (iter->user_data)->parent;
401

402
      retval = gtk_tree_store_get_path (tree_model,
403
					&tmp_iter);
Havoc Pennington's avatar
Havoc Pennington committed
404
      tmp_node = G_NODE (iter->user_data)->parent->children;
405
406
407
408
    }

  if (retval == NULL)
    return NULL;
409

410
411
412
413
414
415
416
417
  if (tmp_node == NULL)
    {
      gtk_tree_path_free (retval);
      return NULL;
    }

  for (; tmp_node; tmp_node = tmp_node->next)
    {
Havoc Pennington's avatar
Havoc Pennington committed
418
      if (tmp_node == G_NODE (iter->user_data))
419
420
421
	break;
      i++;
    }
422

423
424
425
  if (tmp_node == NULL)
    {
      /* We couldn't find node, meaning it's prolly not ours */
426
      /* Perhaps I should do a g_return_if_fail here. */
427
428
429
430
431
432
433
434
435
436
437
      gtk_tree_path_free (retval);
      return NULL;
    }

  gtk_tree_path_append_index (retval, i);

  return retval;
}


static void
438
439
440
441
gtk_tree_store_get_value (GtkTreeModel *tree_model,
			  GtkTreeIter  *iter,
			  gint          column,
			  GValue       *value)
442
443
444
445
446
447
{
  GtkTreeDataList *list;
  gint tmp_column = column;

  g_return_if_fail (tree_model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (tree_model));
448
  g_return_if_fail (iter != NULL);
449
450
  g_return_if_fail (column < GTK_TREE_STORE (tree_model)->n_columns);

Havoc Pennington's avatar
Havoc Pennington committed
451
  list = G_NODE (iter->user_data)->data;
452
453
454
455

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

456
457
  if (list)
    {
458
459
460
      _gtk_tree_data_list_node_to_value (list,
					 GTK_TREE_STORE (tree_model)->column_headers[column],
					 value);
461
462
463
464
465
466
    }
  else
    {
      /* We want to return an initialized but empty (default) value */
      g_value_init (value, GTK_TREE_STORE (tree_model)->column_headers[column]);
    }
467
468
469
}

static gboolean
470
471
gtk_tree_store_iter_next (GtkTreeModel  *tree_model,
			  GtkTreeIter   *iter)
472
{
473
  g_return_val_if_fail (iter->user_data != NULL, FALSE);
474

475
476
477
478
479
480
  if (G_NODE (iter->user_data)->next)
    {
      iter->user_data = G_NODE (iter->user_data)->next;
      return TRUE;
    }
  else
481
482
483
    return FALSE;
}

484
485
486
487
static gboolean
gtk_tree_store_iter_children (GtkTreeModel *tree_model,
			      GtkTreeIter  *iter,
			      GtkTreeIter  *parent)
488
{
489
490
491
  GNode *children;

  g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
492

493
  if (parent)
494
    children = G_NODE (parent->user_data)->children;
495
  else
496
    children = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
497

498
499
500
501
502
503
504
505
  if (children)
    {
      iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
      iter->user_data = children;
      return TRUE;
    }
  else
    return FALSE;
506
507
508
}

static gboolean
509
510
gtk_tree_store_iter_has_child (GtkTreeModel *tree_model,
			       GtkTreeIter  *iter)
511
{
512
513
514
  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);
515
  g_return_val_if_fail (iter->user_data != NULL, FALSE);
516

Havoc Pennington's avatar
Havoc Pennington committed
517
  return G_NODE (iter->user_data)->children != NULL;
518
519
520
}

static gint
521
522
gtk_tree_store_iter_n_children (GtkTreeModel *tree_model,
				GtkTreeIter  *iter)
523
{
524
  GNode *node;
525
526
  gint i = 0;

527
528
  g_return_val_if_fail (tree_model != NULL, 0);
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);
529
530
  g_return_val_if_fail (iter != NULL, FALSE);
  g_return_val_if_fail (iter->user_data != NULL, FALSE);
531

532
533
534
  if (iter == NULL)
    node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
  else
Havoc Pennington's avatar
Havoc Pennington committed
535
    node = G_NODE (iter->user_data)->children;
536

537
  while (node)
538
539
    {
      i++;
540
      node = node->next;
541
542
543
544
545
    }

  return i;
}

546
547
548
549
static gboolean
gtk_tree_store_iter_nth_child (GtkTreeModel *tree_model,
			       GtkTreeIter  *iter,
			       GtkTreeIter  *parent,
550
551
			       gint          n)
{
552
  GNode *parent_node;
553
  GNode *child;
554

555
556
  g_return_val_if_fail (tree_model != NULL, FALSE);
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), FALSE);
557
  g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
558

559
560
561
  if (parent == NULL)
    parent_node = GTK_TREE_STORE (tree_model)->root;
  else
Havoc Pennington's avatar
Havoc Pennington committed
562
    parent_node = parent->user_data;
563

564
  child = g_node_nth_child (parent_node, n);
565

566
567
568
569
570
571
  if (child)
    {
      iter->user_data = child;
      iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
      return TRUE;
    }
572
  else
573
    return FALSE;
574
575
}

576
577
578
579
static gboolean
gtk_tree_store_iter_parent (GtkTreeModel *tree_model,
			    GtkTreeIter  *iter,
			    GtkTreeIter  *child)
580
{
581
  GNode *parent;
582

583
584
585
586
587
  g_return_val_if_fail (iter != NULL, FALSE);
  g_return_val_if_fail (iter->user_data != NULL, FALSE);

  parent = G_NODE (child->user_data)->parent;

588
  g_assert (parent != NULL);
589

590
  if (parent != GTK_TREE_STORE (tree_model)->root)
591
    {
592
593
594
      iter->user_data = parent;
      iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
      return TRUE;
595
    }
596
597
  else
    return FALSE;
598
599
600
601
602
603
604
}

/*
 * This is a somewhat inelegant function that does a lot of list
 * manipulations on it's own.
 */
void
Jonathan Blandford's avatar
Jonathan Blandford committed
605
606
607
608
gtk_tree_store_set_value (GtkTreeStore *tree_store,
			  GtkTreeIter  *iter,
			  gint          column,
			  GValue       *value)
609
610
611
{
  GtkTreeDataList *list;
  GtkTreeDataList *prev;
612
  GtkTreePath *path = NULL;
613
614
  GValue real_value = {0, };
  gboolean converted = FALSE;
615
616
617
618

  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);
Jonathan Blandford's avatar
Jonathan Blandford committed
619
  g_return_if_fail (G_IS_VALUE (value));
620

621
  if (! g_type_is_a (G_VALUE_TYPE (value), tree_store->column_headers[column]))
622
    {
623
624
      if (! (g_value_type_compatible (G_VALUE_TYPE (value), tree_store->column_headers[column]) &&
	     g_value_type_compatible (tree_store->column_headers[column], G_VALUE_TYPE (value))))
625
626
627
628
	{
	  g_warning ("%s: Unable to convert from %s to %s\n",
		     G_STRLOC,
		     g_type_name (G_VALUE_TYPE (value)),
629
		     g_type_name (tree_store->column_headers[column]));
630
631
632
633
634
635
636
	  return;
	}
      if (!g_value_transform (value, &real_value))
	{
	  g_warning ("%s: Unable to make conversion from %s to %s\n",
		     G_STRLOC,
		     g_type_name (G_VALUE_TYPE (value)),
637
		     g_type_name (tree_store->column_headers[column]));
638
639
640
641
642
	  g_value_unset (&real_value);
	  return;
	}
      converted = TRUE;
    }
643

Havoc Pennington's avatar
Havoc Pennington committed
644
  prev = list = G_NODE (iter->user_data)->data;
645

646
647
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);

648
649
650
651
  while (list != NULL)
    {
      if (column == 0)
	{
652
653
654
655
	  if (converted)
	    _gtk_tree_data_list_value_to_node (list, &real_value);
	  else
	    _gtk_tree_data_list_value_to_node (list, value);
656
	  gtk_tree_model_range_changed (GTK_TREE_MODEL (tree_store), path, iter, path, iter);
657
	  gtk_tree_path_free (path);
658
659
	  if (converted)
	    g_value_unset (&real_value);
660
661
662
663
664
665
666
667
	  return;
	}

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

Havoc Pennington's avatar
Havoc Pennington committed
668
  if (G_NODE (iter->user_data)->data == NULL)
669
    {
Havoc Pennington's avatar
Havoc Pennington committed
670
      G_NODE (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
671
672
673
674
      list->next = NULL;
    }
  else
    {
675
      list = prev->next = _gtk_tree_data_list_alloc ();
676
677
678
679
680
      list->next = NULL;
    }

  while (column != 0)
    {
681
      list->next = _gtk_tree_data_list_alloc ();
682
683
684
685
      list = list->next;
      list->next = NULL;
      column --;
    }
686
  if (converted)
687
    _gtk_tree_data_list_value_to_node (list, &real_value);
688
689
  else
    _gtk_tree_data_list_value_to_node (list, value);
690
  gtk_tree_model_range_changed (GTK_TREE_MODEL (tree_store), path, iter, path, iter);
691
  gtk_tree_path_free (path);
692
693
  if (converted)
    g_value_unset (&real_value);
694
695

  if (GTK_TREE_STORE_IS_SORTED (tree_store))
696
    gtk_tree_store_sort_iter_changed (tree_store, iter, column);
697
698
}

699
700
701
702
703
704
705
706
/**
 * gtk_tree_store_set_valist:
 * @tree_store: a #GtkTreeStore
 * @iter: row to set data for
 * @var_args: va_list of column/value pairs
 *
 * See gtk_tree_store_set(); this version takes a va_list for
 * use by language bindings.
707
 *
708
 **/
709
void
Havoc Pennington's avatar
Havoc Pennington committed
710
711
712
gtk_tree_store_set_valist (GtkTreeStore *tree_store,
                           GtkTreeIter  *iter,
                           va_list	var_args)
713
714
715
716
717
718
719
{
  gint column;

  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));

  column = va_arg (var_args, gint);

Havoc Pennington's avatar
Havoc Pennington committed
720
  while (column != -1)
721
722
723
724
725
726
    {
      GValue value = { 0, };
      gchar *error = NULL;

      if (column >= tree_store->n_columns)
	{
Havoc Pennington's avatar
Havoc Pennington committed
727
	  g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
728
729
730
731
	  break;
	}
      g_value_init (&value, tree_store->column_headers[column]);

732
      G_VALUE_COLLECT (&value, var_args, 0, &error);
733
734
735
736
737
738
739
740
741
742
743
      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;
	}

Jonathan Blandford's avatar
Jonathan Blandford committed
744
      /* FIXME: instead of calling this n times, refactor with above */
Jonathan Blandford's avatar
Jonathan Blandford committed
745
746
747
748
      gtk_tree_store_set_value (tree_store,
				iter,
				column,
				&value);
749
750
751
752
753
754
755

      g_value_unset (&value);

      column = va_arg (var_args, gint);
    }
}

Havoc Pennington's avatar
Havoc Pennington committed
756
757
758
759
760
/**
 * gtk_tree_store_set:
 * @tree_store: a #GtkTreeStore
 * @iter: row iterator
 * @Varargs: pairs of column number and value, terminated with -1
761
 *
Havoc Pennington's avatar
Havoc Pennington committed
762
763
764
765
766
767
768
 * Sets the value of one or more cells in the row referenced by @iter.
 * The variable argument list should contain integer column numbers,
 * each column number followed by the value to be set. For example,
 * The list is terminated by a -1. For example, to set column 0 with type
 * %G_TYPE_STRING to "Foo", you would write gtk_tree_store_set (store, iter,
 * 0, "Foo", -1).
 **/
769
void
770
771
772
gtk_tree_store_set (GtkTreeStore *tree_store,
		    GtkTreeIter  *iter,
		    ...)
773
774
775
776
777
778
{
  va_list var_args;

  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));

  va_start (var_args, iter);
Havoc Pennington's avatar
Havoc Pennington committed
779
  gtk_tree_store_set_valist (tree_store, iter, var_args);
780
781
782
783
  va_end (var_args);
}

void
784
785
gtk_tree_store_remove (GtkTreeStore *model,
		       GtkTreeIter  *iter)
786
787
{
  GtkTreePath *path;
788
  GtkTreeIter new_iter = {0,};
789
790
791
792
793
  GNode *parent;

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

Havoc Pennington's avatar
Havoc Pennington committed
794
  parent = G_NODE (iter->user_data)->parent;
795

796
  g_assert (parent != NULL);
797

Havoc Pennington's avatar
Havoc Pennington committed
798
799
  if (G_NODE (iter->user_data)->data)
    _gtk_tree_data_list_free ((GtkTreeDataList *) G_NODE (iter->user_data)->data,
800
801
			      model->column_headers);

802
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
Havoc Pennington's avatar
Havoc Pennington committed
803
  g_node_destroy (G_NODE (iter->user_data));
804
805

  model->stamp++;
806
807
  gtk_tree_model_deleted (GTK_TREE_MODEL (model), path);

808
809
810
  if (parent != G_NODE (model->root) && parent->children == NULL)
    {
      gtk_tree_path_up (path);
811
812
813

      new_iter.stamp = model->stamp;
      new_iter.user_data = parent;
814
      gtk_tree_model_has_child_toggled (GTK_TREE_MODEL (model), path, &new_iter);
815
816
817
818
    }
  gtk_tree_path_free (path);
}

819
void
820
821
822
823
gtk_tree_store_insert (GtkTreeStore *model,
		       GtkTreeIter  *iter,
		       GtkTreeIter  *parent,
		       gint          position)
824
825
{
  GtkTreePath *path;
826
  GNode *parent_node;
827

828
829
  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
830

831
832
833
834
  if (parent)
    parent_node = parent->user_data;
  else
    parent_node = model->root;
835

836
  iter->stamp = model->stamp;
Havoc Pennington's avatar
Havoc Pennington committed
837
  iter->user_data = g_node_new (NULL);
838
  g_node_insert (parent_node, position, G_NODE (iter->user_data));
839

840
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
841
842
  gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);

843
  gtk_tree_path_free (path);
844
845

  validate_tree ((GtkTreeStore*)model);
846
847
}

848
void
849
850
851
852
gtk_tree_store_insert_before (GtkTreeStore *model,
			      GtkTreeIter  *iter,
			      GtkTreeIter  *parent,
			      GtkTreeIter  *sibling)
853
854
{
  GtkTreePath *path;
855
  GNode *parent_node = NULL;
856
  GNode *new_node;
857

858
859
860
  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
  g_return_if_fail (iter != NULL);
861

862
  new_node = g_node_new (NULL);
863

864
865
866
  if (parent == NULL && sibling == NULL)
    parent_node = model->root;
  else if (parent == NULL)
Havoc Pennington's avatar
Havoc Pennington committed
867
    parent_node = G_NODE (sibling->user_data)->parent;
868
  else if (sibling == NULL)
Havoc Pennington's avatar
Havoc Pennington committed
869
    parent_node = G_NODE (parent->user_data);
870
871
872
873
874
875
  else
    {
      g_return_if_fail (G_NODE (sibling->user_data)->parent ==
                        G_NODE (parent->user_data));
      parent_node = G_NODE (parent->user_data);
    }
876

877
  g_node_insert_before (parent_node,
Havoc Pennington's avatar
Havoc Pennington committed
878
			sibling ? G_NODE (sibling->user_data) : NULL,
879
                        new_node);
880

881
882
  iter->stamp = model->stamp;
  iter->user_data = new_node;
883

884
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
885
886
  gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);

887
  gtk_tree_path_free (path);
888
889

  validate_tree ((GtkTreeStore*)model);
890
891
}

892
void
893
894
895
896
gtk_tree_store_insert_after (GtkTreeStore *model,
			     GtkTreeIter  *iter,
			     GtkTreeIter  *parent,
			     GtkTreeIter  *sibling)
897
898
{
  GtkTreePath *path;
899
  GNode *parent_node;
900
  GNode *new_node;
901

902
903
904
  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
  g_return_if_fail (iter != NULL);
905

906
  new_node = g_node_new (NULL);
907

908
909
910
  if (parent == NULL && sibling == NULL)
    parent_node = model->root;
  else if (parent == NULL)
Havoc Pennington's avatar
Havoc Pennington committed
911
    parent_node = G_NODE (sibling->user_data)->parent;
912
  else if (sibling == NULL)
Havoc Pennington's avatar
Havoc Pennington committed
913
    parent_node = G_NODE (parent->user_data);
914
915
916
917
918
919
  else
    {
      g_return_if_fail (G_NODE (sibling->user_data)->parent ==
                        G_NODE (parent->user_data));
      parent_node = G_NODE (parent->user_data);
    }
920

921

922
  g_node_insert_after (parent_node,
Havoc Pennington's avatar
Havoc Pennington committed
923
		       sibling ? G_NODE (sibling->user_data) : NULL,
924
                       new_node);
925

926
927
  iter->stamp = model->stamp;
  iter->user_data = new_node;
928

929
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
930
931
  gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);

932
  gtk_tree_path_free (path);
933
934

  validate_tree ((GtkTreeStore*)model);
935
936
}

937
void
938
939
940
gtk_tree_store_prepend (GtkTreeStore *model,
			GtkTreeIter  *iter,
			GtkTreeIter  *parent)
941
{
942
  GNode *parent_node;
943

944
945
946
  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
  g_return_if_fail (iter != NULL);
947
948

  if (parent == NULL)
949
950
    parent_node = model->root;
  else
Havoc Pennington's avatar
Havoc Pennington committed
951
    parent_node = parent->user_data;
952

953
  if (parent_node->children == NULL)
954
955
    {
      GtkTreePath *path;
956

957
958
      iter->stamp = model->stamp;
      iter->user_data = g_node_new (NULL);
959

960
      g_node_prepend (parent_node, iter->user_data);
961

962
      if (parent_node != model->root)
963
964
	{
	  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
965
	  gtk_tree_model_has_child_toggled (GTK_TREE_MODEL (model), path, parent);
966
	  gtk_tree_path_append_index (path, 0);
967
968
969
	}
      else
	{
970
	  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
971
	}
972
      gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);
973
974
975
976
      gtk_tree_path_free (path);
    }
  else
    {
977
      gtk_tree_store_insert_after (model, iter, parent, NULL);
978
    }
979
980

  validate_tree ((GtkTreeStore*)model);
981
982
}

983
void
984
985
986
gtk_tree_store_append (GtkTreeStore *model,
		       GtkTreeIter  *iter,
		       GtkTreeIter  *parent)
987
{
988
989
990
991
992
  GNode *parent_node;

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

994
  if (parent == NULL)
995
996
    parent_node = model->root;
  else
Havoc Pennington's avatar
Havoc Pennington committed
997
    parent_node = parent->user_data;
998

999
  if (parent_node->children == NULL)
1000
1001
    {
      GtkTreePath *path;
1002

1003
1004
      iter->stamp = model->stamp;
      iter->user_data = g_node_new (NULL);
1005

Havoc Pennington's avatar
Havoc Pennington committed
1006
      g_node_append (parent_node, G_NODE (iter->user_data));
1007
1008

      if (parent_node != model->root)
1009
1010
	{
	  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
1011
	  gtk_tree_model_has_child_toggled (GTK_TREE_MODEL (model), path, parent);
1012
	  gtk_tree_path_append_index (path, 0);
1013
1014
1015
	}
      else
	{
1016
	  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
1017
	}
1018

1019
      gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);
1020
1021
1022
1023
      gtk_tree_path_free (path);
    }
  else
    {
1024
      gtk_tree_store_insert_before (model, iter, parent, NULL);
1025
    }
1026
1027

  validate_tree ((GtkTreeStore*)model);
1028
1029
1030
}

gboolean
1031
1032
1033
gtk_tree_store_is_ancestor (GtkTreeStore *model,
			    GtkTreeIter  *iter,
			    GtkTreeIter  *descendant)
1034
1035
1036
{
  g_return_val_if_fail (model != NULL, FALSE);
  g_return_val_if_fail (GTK_IS_TREE_STORE (model), FALSE);
1037
  g_return_val_if_fail (iter != NULL, FALSE);
1038
1039
  g_return_val_if_fail (descendant != NULL, FALSE);

Havoc Pennington's avatar
Havoc Pennington committed
1040
1041
  return g_node_is_ancestor (G_NODE (iter->user_data),
			     G_NODE (descendant->user_data));
1042
1043
1044
1045
}


gint
1046
1047
gtk_tree_store_iter_depth (GtkTreeStore *model,
			   GtkTreeIter  *iter)
1048
1049
1050
{
  g_return_val_if_fail (model != NULL, 0);
  g_return_val_if_fail (GTK_IS_TREE_STORE (model), 0);
1051
  g_return_val_if_fail (iter != NULL, 0);
1052

Havoc Pennington's avatar
Havoc Pennington committed
1053
  return g_node_depth (G_NODE (iter->user_data)) - 1;
1054
}
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066

/* DND */



static gboolean
gtk_tree_store_drag_data_delete (GtkTreeDragSource *drag_source,
                                 GtkTreePath       *path)
{
  GtkTreeIter iter;

  g_return_val_if_fail (GTK_IS_TREE_STORE (drag_source), FALSE);
1067

1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
  if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source),
                               &iter,
                               path))
    {
      gtk_tree_store_remove (GTK_TREE_STORE (drag_source),
                             &iter);
      return TRUE;
    }
  else
    {
      return FALSE;
    }
}

static gboolean
gtk_tree_store_drag_data_get (GtkTreeDragSource *drag_source,
                              GtkTreePath       *path,
                              GtkSelectionData  *selection_data)
{
  g_return_val_if_fail (GTK_IS_TREE_STORE (drag_source), FALSE);

  /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
   * target, because the default handler does it for us, but
   * we do anyway for the convenience of someone maybe overriding the
   * default handler.
   */

  if (gtk_selection_data_set_tree_row (selection_data,
                                       GTK_TREE_MODEL (drag_source),
                                       path))
    {
      return TRUE;
    }
  else
    {
      /* FIXME handle text targets at least. */
    }

  return FALSE;
}

static void
copy_node_data (GtkTreeStore *tree_store,
                GtkTreeIter  *src_iter,
                GtkTreeIter  *dest_iter)
{
  GtkTreeDataList *dl = G_NODE (src_iter->user_data)->data;
  GtkTreeDataList *copy_head =