gtktreestore.c 32.4 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
28

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

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


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
static gboolean gtk_tree_store_drag_data_delete   (GtkTreeDragSource *drag_source,
                                                   GtkTreePath       *path);
static gboolean gtk_tree_store_drag_data_get      (GtkTreeDragSource *drag_source,
                                                   GtkTreePath       *path,
                                                   GtkSelectionData  *selection_data);
static gboolean gtk_tree_store_drag_data_received (GtkTreeDragDest   *drag_dest,
                                                   GtkTreePath       *dest,
                                                   GtkSelectionData  *selection_data);
static gboolean gtk_tree_store_row_drop_possible  (GtkTreeDragDest   *drag_dest,
                                                   GtkTreeModel      *src_model,
                                                   GtkTreePath       *src_path,
                                                   GtkTreePath       *dest_path);

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);
      
      validate_gnode (G_NODE (tree_store->root));
    }
}

88
89
90
GtkType
gtk_tree_store_get_type (void)
{
91
  static GType tree_store_type = 0;
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

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

108
109
110
111
112
113
114
      static const GInterfaceInfo tree_model_info =
      {
	(GInterfaceInitFunc) gtk_tree_store_tree_model_init,
	NULL,
	NULL
      };

115
116
117
118
119
120
121
122
123
124
125
126
127
128
      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
      };
      
129
      tree_store_type = g_type_register_static (G_TYPE_OBJECT, "GtkTreeStore", &tree_store_info, 0);
130

131
132
133
      g_type_add_interface_static (tree_store_type,
				   GTK_TYPE_TREE_MODEL,
				   &tree_model_info);
134
135
136
137
138
139
140
141
142

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

      
143
144
145
146
147
148
    }

  return tree_store_type;
}

static void
149
gtk_tree_store_class_init (GtkTreeStoreClass *tree_store_class)
150
{
151
152
153
154
  GObjectClass *object_class;

  object_class = (GObjectClass *) tree_store_class;

155
156
157
158
159
}

static void
gtk_tree_store_tree_model_init (GtkTreeModelIface *iface)
{
160
  iface->get_flags = gtk_tree_store_get_flags;
161
  iface->get_n_columns = gtk_tree_store_get_n_columns;
162
  iface->get_column_type = gtk_tree_store_get_column_type;
163
  iface->get_path = gtk_tree_store_get_path;
164
  iface->get_value = gtk_tree_store_get_value;
165
166
167
168
169
170
  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;
171
172
}

173
174
175
176
177
178
179
180
181
182
183
184
185
186
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
gtk_tree_store_drag_dest_init   (GtkTreeDragDestIface   *iface)
{
  iface->drag_data_received = gtk_tree_store_drag_data_received;
  iface->row_drop_possible = gtk_tree_store_row_drop_possible;
}

187
188
189
static void
gtk_tree_store_init (GtkTreeStore *tree_store)
{
190
  tree_store->root = g_node_new (NULL);
191
  tree_store->stamp = g_random_int ();
192
193
}

194
GtkTreeStore *
195
196
gtk_tree_store_new (void)
{
197
  return GTK_TREE_STORE (g_object_new (gtk_tree_store_get_type (), NULL));
198
199
}

200
GtkTreeStore *
201
202
gtk_tree_store_new_with_types (gint n_columns,
			       ...)
203
{
204
  GtkTreeStore *retval;
205
206
207
208
209
210
  va_list args;
  gint i;

  g_return_val_if_fail (n_columns > 0, NULL);

  retval = gtk_tree_store_new ();
211
  gtk_tree_store_set_n_columns (retval, n_columns);
212
213

  va_start (args, n_columns);
214

215
  for (i = 0; i < n_columns; i++)
216
    gtk_tree_store_set_column_type (retval, i, va_arg (args, GType));
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

  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,
265
 * it is not visible to the tree or to the user., and the path "0" refers to the
266
267
 * first child of GtkTreeStore::root.
 */
268
269
270
271
272
273
274
275
276
277


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

278
279
280
281
282
283
284
285
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;
}

286
287
288
289
290
291
292
293
294
295
296
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];
}

297
298
static GtkTreePath *
gtk_tree_store_get_path (GtkTreeModel *tree_model,
299
			 GtkTreeIter  *iter)
300
301
302
303
{
  GtkTreePath *retval;
  GNode *tmp_node;
  gint i = 0;
304
  
305
  g_return_val_if_fail (tree_model != NULL, NULL);
306
307
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), NULL);
  g_return_val_if_fail (iter != NULL, NULL);
308
  g_return_val_if_fail (iter->user_data != NULL, NULL);
309

310
  validate_tree ((GtkTreeStore*)tree_model);
311

312
313
  g_assert (G_NODE (iter->user_data)->parent != NULL);
  
Havoc Pennington's avatar
Havoc Pennington committed
314
  if (G_NODE (iter->user_data)->parent == G_NODE (GTK_TREE_STORE (tree_model)->root))
315
316
317
318
319
320
    {
      retval = gtk_tree_path_new ();
      tmp_node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
    }
  else
    {
321
      GtkTreeIter tmp_iter = *iter;
322
323
      
      tmp_iter.user_data = G_NODE (iter->user_data)->parent;
324

325
      retval = gtk_tree_store_get_path (tree_model,
326
					&tmp_iter);
Havoc Pennington's avatar
Havoc Pennington committed
327
      tmp_node = G_NODE (iter->user_data)->parent->children;
328
329
330
331
    }

  if (retval == NULL)
    return NULL;
332

333
334
335
336
337
338
339
340
  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
341
      if (tmp_node == G_NODE (iter->user_data))
342
343
344
	break;
      i++;
    }
345

346
347
348
  if (tmp_node == NULL)
    {
      /* We couldn't find node, meaning it's prolly not ours */
349
      /* Perhaps I should do a g_return_if_fail here. */
350
351
352
353
354
355
356
357
358
359
360
      gtk_tree_path_free (retval);
      return NULL;
    }

  gtk_tree_path_append_index (retval, i);

  return retval;
}


static void
361
362
363
364
gtk_tree_store_get_value (GtkTreeModel *tree_model,
			  GtkTreeIter  *iter,
			  gint          column,
			  GValue       *value)
365
366
367
368
369
370
{
  GtkTreeDataList *list;
  gint tmp_column = column;

  g_return_if_fail (tree_model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (tree_model));
371
  g_return_if_fail (iter != NULL);
372
373
  g_return_if_fail (column < GTK_TREE_STORE (tree_model)->n_columns);

Havoc Pennington's avatar
Havoc Pennington committed
374
  list = G_NODE (iter->user_data)->data;
375
376
377
378

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

379
380
  if (list)
    {
381
382
383
      _gtk_tree_data_list_node_to_value (list,
					 GTK_TREE_STORE (tree_model)->column_headers[column],
					 value);
384
385
386
387
388
389
    }
  else
    {
      /* We want to return an initialized but empty (default) value */
      g_value_init (value, GTK_TREE_STORE (tree_model)->column_headers[column]);
    }
390
391
392
}

static gboolean
393
394
gtk_tree_store_iter_next (GtkTreeModel  *tree_model,
			  GtkTreeIter   *iter)
395
{
396
397
398
399
400
401
402
403
  g_return_val_if_fail (iter->user_data != NULL, FALSE);
  
  if (G_NODE (iter->user_data)->next)
    {
      iter->user_data = G_NODE (iter->user_data)->next;
      return TRUE;
    }
  else
404
405
406
    return FALSE;
}

407
408
409
410
static gboolean
gtk_tree_store_iter_children (GtkTreeModel *tree_model,
			      GtkTreeIter  *iter,
			      GtkTreeIter  *parent)
411
{
412
413
414
415
  GNode *children;

  g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
  
416
  if (parent)
417
    children = G_NODE (parent->user_data)->children;
418
  else
419
    children = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
420

421
422
423
424
425
426
427
428
  if (children)
    {
      iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
      iter->user_data = children;
      return TRUE;
    }
  else
    return FALSE;
429
430
431
}

static gboolean
432
433
gtk_tree_store_iter_has_child (GtkTreeModel *tree_model,
			       GtkTreeIter  *iter)
434
{
435
436
437
  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);
438
  g_return_val_if_fail (iter->user_data != NULL, FALSE);
439

Havoc Pennington's avatar
Havoc Pennington committed
440
  return G_NODE (iter->user_data)->children != NULL;
441
442
443
}

static gint
444
445
gtk_tree_store_iter_n_children (GtkTreeModel *tree_model,
				GtkTreeIter  *iter)
446
{
447
  GNode *node;
448
449
  gint i = 0;

450
451
  g_return_val_if_fail (tree_model != NULL, 0);
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);
452
453
454
  g_return_val_if_fail (iter != NULL, FALSE);
  g_return_val_if_fail (iter->user_data != NULL, FALSE);
  
455
456
457
  if (iter == NULL)
    node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
  else
Havoc Pennington's avatar
Havoc Pennington committed
458
    node = G_NODE (iter->user_data)->children;
459

460
  while (node)
461
462
    {
      i++;
463
      node = node->next;
464
465
466
467
468
    }

  return i;
}

469
470
471
472
static gboolean
gtk_tree_store_iter_nth_child (GtkTreeModel *tree_model,
			       GtkTreeIter  *iter,
			       GtkTreeIter  *parent,
473
474
			       gint          n)
{
475
  GNode *parent_node;
476
  GNode *child;
477

478
479
  g_return_val_if_fail (tree_model != NULL, FALSE);
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), FALSE);
480
  g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
481

482
483
484
  if (parent == NULL)
    parent_node = GTK_TREE_STORE (tree_model)->root;
  else
Havoc Pennington's avatar
Havoc Pennington committed
485
    parent_node = parent->user_data;
486

487
  child = g_node_nth_child (parent_node, n);
488

489
490
491
492
493
494
  if (child)
    {
      iter->user_data = child;
      iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
      return TRUE;
    }
495
  else
496
    return FALSE;
497
498
}

499
500
501
502
static gboolean
gtk_tree_store_iter_parent (GtkTreeModel *tree_model,
			    GtkTreeIter  *iter,
			    GtkTreeIter  *child)
503
{
504
  GNode *parent;
505
  
506
507
508
509
510
511
  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;

  g_assert (parent != NULL);  
512

513
  if (parent != GTK_TREE_STORE (tree_model)->root)
514
    {
515
516
517
      iter->user_data = parent;
      iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
      return TRUE;
518
    }
519
520
  else
    return FALSE;
521
522
523
524
525
526
527
}

/*
 * This is a somewhat inelegant function that does a lot of list
 * manipulations on it's own.
 */
void
528
529
530
531
gtk_tree_store_set_cell (GtkTreeStore *tree_store,
			 GtkTreeIter  *iter,
			 gint          column,
			 GValue       *value)
532
533
534
{
  GtkTreeDataList *list;
  GtkTreeDataList *prev;
535
  GtkTreePath *path = NULL;
536
537
538
539
540

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

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

543
544
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);

545
546
547
548
  while (list != NULL)
    {
      if (column == 0)
	{
549
	  _gtk_tree_data_list_value_to_node (list, value);
550
551
	  gtk_tree_model_changed (GTK_TREE_MODEL (tree_store), path, iter);
	  gtk_tree_path_free (path);
552
553
554
555
556
557
558
559
	  return;
	}

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

Havoc Pennington's avatar
Havoc Pennington committed
560
  if (G_NODE (iter->user_data)->data == NULL)
561
    {
Havoc Pennington's avatar
Havoc Pennington committed
562
      G_NODE (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
563
564
565
566
      list->next = NULL;
    }
  else
    {
567
      list = prev->next = _gtk_tree_data_list_alloc ();
568
569
570
571
572
      list->next = NULL;
    }

  while (column != 0)
    {
573
      list->next = _gtk_tree_data_list_alloc ();
574
575
576
577
      list = list->next;
      list->next = NULL;
      column --;
    }
578
  _gtk_tree_data_list_value_to_node (list, value);
579
580
  gtk_tree_model_changed (GTK_TREE_MODEL (tree_store), path, iter);
  gtk_tree_path_free (path);
581
582
}

583
584
585
586
587
588
589
590
591
592
/**
 * 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.
 * 
 **/
593
void
Havoc Pennington's avatar
Havoc Pennington committed
594
595
596
gtk_tree_store_set_valist (GtkTreeStore *tree_store,
                           GtkTreeIter  *iter,
                           va_list	var_args)
597
598
599
600
601
602
603
{
  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
604
  while (column != -1)
605
606
607
608
609
610
    {
      GValue value = { 0, };
      gchar *error = NULL;

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

616
      G_VALUE_COLLECT (&value, var_args, 0, &error);
617
618
619
620
621
622
623
624
625
626
627
      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;
	}

628
629
630
631
      gtk_tree_store_set_cell (tree_store,
			       iter,
			       column,
			       &value);
632
633
634
635
636
637
638

      g_value_unset (&value);

      column = va_arg (var_args, gint);
    }
}

Havoc Pennington's avatar
Havoc Pennington committed
639
640
641
642
643
644
645
646
647
648
649
650
651
/**
 * gtk_tree_store_set:
 * @tree_store: a #GtkTreeStore
 * @iter: row iterator
 * @Varargs: pairs of column number and value, terminated with -1
 * 
 * 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).
 **/
652
void
653
654
655
gtk_tree_store_set (GtkTreeStore *tree_store,
		    GtkTreeIter  *iter,
		    ...)
656
657
658
659
660
661
{
  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
662
  gtk_tree_store_set_valist (tree_store, iter, var_args);
663
664
665
666
  va_end (var_args);
}

void
667
668
gtk_tree_store_remove (GtkTreeStore *model,
		       GtkTreeIter  *iter)
669
670
{
  GtkTreePath *path;
671
  GtkTreeIter new_iter = {0,};
672
673
674
675
676
  GNode *parent;

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

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

679
680
  g_assert (parent != NULL);
  
Havoc Pennington's avatar
Havoc Pennington committed
681
682
  if (G_NODE (iter->user_data)->data)
    _gtk_tree_data_list_free ((GtkTreeDataList *) G_NODE (iter->user_data)->data,
683
684
			      model->column_headers);

685
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
Havoc Pennington's avatar
Havoc Pennington committed
686
  g_node_destroy (G_NODE (iter->user_data));
687
688

  model->stamp++;
689
690
  gtk_tree_model_deleted (GTK_TREE_MODEL (model), path);

691
692
693
  if (parent != G_NODE (model->root) && parent->children == NULL)
    {
      gtk_tree_path_up (path);
694
695
696

      new_iter.stamp = model->stamp;
      new_iter.user_data = parent;
697
      gtk_tree_model_has_child_toggled (GTK_TREE_MODEL (model), path, &new_iter);
698
699
700
701
    }
  gtk_tree_path_free (path);
}

702
void
703
704
705
706
gtk_tree_store_insert (GtkTreeStore *model,
		       GtkTreeIter  *iter,
		       GtkTreeIter  *parent,
		       gint          position)
707
708
{
  GtkTreePath *path;
709
  GNode *parent_node;
710
  
711
712
  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
713

714
715
716
717
  if (parent)
    parent_node = parent->user_data;
  else
    parent_node = model->root;
718

719
  iter->stamp = model->stamp;
Havoc Pennington's avatar
Havoc Pennington committed
720
  iter->user_data = g_node_new (NULL);
721
  g_node_insert (parent_node, position, G_NODE (iter->user_data));
722
723
  
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
724
725
  gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);

726
  gtk_tree_path_free (path);
727
728

  validate_tree ((GtkTreeStore*)model);
729
730
}

731
void
732
733
734
735
gtk_tree_store_insert_before (GtkTreeStore *model,
			      GtkTreeIter  *iter,
			      GtkTreeIter  *parent,
			      GtkTreeIter  *sibling)
736
737
{
  GtkTreePath *path;
738
  GNode *parent_node = NULL;
739
740
  GNode *new_node;
  
741
742
743
  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
  g_return_if_fail (iter != NULL);
744

745
  new_node = g_node_new (NULL);  
746

747
748
749
  if (parent == NULL && sibling == NULL)
    parent_node = model->root;
  else if (parent == NULL)
Havoc Pennington's avatar
Havoc Pennington committed
750
    parent_node = G_NODE (sibling->user_data)->parent;
751
  else if (sibling == NULL)
Havoc Pennington's avatar
Havoc Pennington committed
752
    parent_node = G_NODE (parent->user_data);
753
754
755
756
757
758
  else
    {
      g_return_if_fail (G_NODE (sibling->user_data)->parent ==
                        G_NODE (parent->user_data));
      parent_node = G_NODE (parent->user_data);
    }
759

760
  g_node_insert_before (parent_node,
Havoc Pennington's avatar
Havoc Pennington committed
761
			sibling ? G_NODE (sibling->user_data) : NULL,
762
                        new_node);
763

764
765
766
  iter->stamp = model->stamp;
  iter->user_data = new_node;
  
767
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
768
769
  gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);

770
  gtk_tree_path_free (path);
771
772

  validate_tree ((GtkTreeStore*)model);
773
774
}

775
void
776
777
778
779
gtk_tree_store_insert_after (GtkTreeStore *model,
			     GtkTreeIter  *iter,
			     GtkTreeIter  *parent,
			     GtkTreeIter  *sibling)
780
781
{
  GtkTreePath *path;
782
  GNode *parent_node;
783
784
  GNode *new_node;
  
785
786
787
  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
  g_return_if_fail (iter != NULL);
788

789
  new_node = g_node_new (NULL);
790

791
792
793
  if (parent == NULL && sibling == NULL)
    parent_node = model->root;
  else if (parent == NULL)
Havoc Pennington's avatar
Havoc Pennington committed
794
    parent_node = G_NODE (sibling->user_data)->parent;
795
  else if (sibling == NULL)
Havoc Pennington's avatar
Havoc Pennington committed
796
    parent_node = G_NODE (parent->user_data);
797
798
799
800
801
802
  else
    {
      g_return_if_fail (G_NODE (sibling->user_data)->parent ==
                        G_NODE (parent->user_data));
      parent_node = G_NODE (parent->user_data);
    }
803

804
  
805
  g_node_insert_after (parent_node,
Havoc Pennington's avatar
Havoc Pennington committed
806
		       sibling ? G_NODE (sibling->user_data) : NULL,
807
808
809
810
811
                       new_node);
  
  iter->stamp = model->stamp;
  iter->user_data = new_node;
  
812
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
813
814
  gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);

815
  gtk_tree_path_free (path);
816
817

  validate_tree ((GtkTreeStore*)model);
818
819
}

820
void
821
822
823
gtk_tree_store_prepend (GtkTreeStore *model,
			GtkTreeIter  *iter,
			GtkTreeIter  *parent)
824
{
825
  GNode *parent_node;
826
  
827
828
829
  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
  g_return_if_fail (iter != NULL);
830
831

  if (parent == NULL)
832
833
    parent_node = model->root;
  else
Havoc Pennington's avatar
Havoc Pennington committed
834
    parent_node = parent->user_data;
835
  
836
  if (parent_node->children == NULL)
837
838
    {
      GtkTreePath *path;
839
840
841
842
843
844
      
      iter->stamp = model->stamp;
      iter->user_data = g_node_new (NULL);
      
      g_node_prepend (parent_node, iter->user_data);
      
845
      if (parent_node != model->root)
846
847
	{
	  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
848
	  gtk_tree_model_has_child_toggled (GTK_TREE_MODEL (model), path, parent);
849
	  gtk_tree_path_append_index (path, 0);
850
851
852
	}
      else
	{
853
	  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
854
	}
855
      gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);
856
857
858
859
      gtk_tree_path_free (path);
    }
  else
    {
860
      gtk_tree_store_insert_after (model, iter, parent, NULL);
861
    }
862
863

  validate_tree ((GtkTreeStore*)model);
864
865
}

866
void
867
868
869
gtk_tree_store_append (GtkTreeStore *model,
		       GtkTreeIter  *iter,
		       GtkTreeIter  *parent)
870
{
871
872
873
874
875
  GNode *parent_node;

  g_return_if_fail (model != NULL);
  g_return_if_fail (GTK_IS_TREE_STORE (model));
  g_return_if_fail (iter != NULL);
876
  
877
  if (parent == NULL)
878
879
    parent_node = model->root;
  else
Havoc Pennington's avatar
Havoc Pennington committed
880
    parent_node = parent->user_data;
881

882
  if (parent_node->children == NULL)
883
884
    {
      GtkTreePath *path;
885

886
887
888
      iter->stamp = model->stamp;
      iter->user_data = g_node_new (NULL);
      
Havoc Pennington's avatar
Havoc Pennington committed
889
      g_node_append (parent_node, G_NODE (iter->user_data));
890
891

      if (parent_node != model->root)
892
893
	{
	  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
894
	  gtk_tree_model_has_child_toggled (GTK_TREE_MODEL (model), path, parent);
895
	  gtk_tree_path_append_index (path, 0);
896
897
898
	}
      else
	{
899
	  path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter);
900
	}
901
      
902
      gtk_tree_model_inserted (GTK_TREE_MODEL (model), path, iter);
903
904
905
906
      gtk_tree_path_free (path);
    }
  else
    {
907
      gtk_tree_store_insert_before (model, iter, parent, NULL);
908
    }
909
910

  validate_tree ((GtkTreeStore*)model);
911
912
913
}

gboolean
914
915
916
gtk_tree_store_is_ancestor (GtkTreeStore *model,
			    GtkTreeIter  *iter,
			    GtkTreeIter  *descendant)
917
918
919
{
  g_return_val_if_fail (model != NULL, FALSE);
  g_return_val_if_fail (GTK_IS_TREE_STORE (model), FALSE);
920
  g_return_val_if_fail (iter != NULL, FALSE);
921
922
  g_return_val_if_fail (descendant != NULL, FALSE);

Havoc Pennington's avatar
Havoc Pennington committed
923
924
  return g_node_is_ancestor (G_NODE (iter->user_data),
			     G_NODE (descendant->user_data));
925
926
927
928
}


gint
929
930
gtk_tree_store_iter_depth (GtkTreeStore *model,
			   GtkTreeIter  *iter)
931
932
933
{
  g_return_val_if_fail (model != NULL, 0);
  g_return_val_if_fail (GTK_IS_TREE_STORE (model), 0);
934
  g_return_val_if_fail (iter != NULL, 0);
935

Havoc Pennington's avatar
Havoc Pennington committed
936
  return g_node_depth (G_NODE (iter->user_data)) - 1;
937
}
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000

/* 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);
  
  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 = NULL;
  GtkTreeDataList *copy_prev = NULL;
  GtkTreeDataList *copy_iter = NULL;
1001
  GtkTreePath *path;
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
  gint col;
  
  col = 0;
  while (dl)
    {
      copy_iter = _gtk_tree_data_list_node_copy (dl,
                                                 tree_store->column_headers[col]);

      if (copy_head == NULL)
        copy_head = copy_iter;

      if (copy_prev)
        copy_prev->next = copy_iter;

      copy_prev = copy_iter;

      dl = dl->next;
      ++col;
    }
          
  G_NODE (dest_iter->user_data)->data = copy_head;

1024
1025
1026
  path = gtk_tree_store_get_path (tree_store, dest_iter);
  gtk_tree_model_changed (GTK_TREE_MODEL (tree_store), path, dest_iter);
  gtk_tree_path_free (path);
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
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
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
}

static void
recursive_node_copy (GtkTreeStore *tree_store,
                     GtkTreeIter  *src_iter,
                     GtkTreeIter  *dest_iter)
{
  GtkTreeIter child;
  GtkTreeModel *model;

  model = GTK_TREE_MODEL (tree_store);
  
  copy_node_data (tree_store, src_iter, dest_iter);

  if (gtk_tree_model_iter_children (model,
                                    &child,
                                    src_iter))
    {
      /* Need to create children and recurse. Note our
       * dependence on persistent iterators here.
       */
      do
        {
          GtkTreeIter copy;

          /* Gee, a really slow algorithm... ;-) FIXME */
          gtk_tree_store_append (tree_store,
                                 &copy,
                                 dest_iter);
          
          recursive_node_copy (tree_store, &child, &copy);
        }
      while (gtk_tree_model_iter_next (model, &child));
    }
}

static gboolean
gtk_tree_store_drag_data_received (GtkTreeDragDest   *drag_dest,
                                   GtkTreePath       *dest,
                                   GtkSelectionData  *selection_data)
{
  GtkTreeModel *tree_model;
  GtkTreeStore *tree_store;
  GtkTreeModel *src_model = NULL;
  GtkTreePath *src_path = NULL;
  gboolean retval = FALSE;
  
  g_return_val_if_fail (GTK_IS_TREE_STORE (drag_dest), FALSE);

  tree_model = GTK_TREE_MODEL (drag_dest);
  tree_store = GTK_TREE_STORE (drag_dest);

  validate_tree (tree_store);
  
  if (gtk_selection_data_get_tree_row (selection_data,
                                       &src_model,
                                       &src_path) &&
      src_model == tree_model)
    {
      /* Copy the given row to a new position */
      GtkTreeIter src_iter;
      GtkTreeIter dest_iter;
      GtkTreePath *prev;
      
      if (!gtk_tree_model_get_iter (src_model,
                                    &src_iter,
                                    src_path))
        {
          goto out;
        }

      /* Get the path to insert _after_ (dest is the path to insert _before_) */
      prev = gtk_tree_path_copy (dest);
      
      if (!gtk_tree_path_prev (prev))
        {
          GtkTreeIter dest_parent;
          GtkTreePath *parent;
          GtkTreeIter *dest_parent_p;
          
          /* dest was the first spot at the current depth; which means
           * we are supposed to prepend.
           */
          
          /* Get the parent, NULL if parent is the root */
          dest_parent_p = NULL;
          parent = gtk_tree_path_copy (dest);
          if (gtk_tree_path_up (parent))
            {
              gtk_tree_model_get_iter (tree_model,
                                       &dest_parent,
                                       parent);
              dest_parent_p = &dest_parent;
            }
          gtk_tree_path_free (parent);
          parent = NULL;
          
          gtk_tree_store_prepend (GTK_TREE_STORE (tree_model),
                                  &dest_iter,
                                  dest_parent_p);
          
          retval = TRUE;
        }
      else
        {
          if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model),
                                       &dest_iter,
                                       prev))
            {
              GtkTreeIter tmp_iter = dest_iter;
              gtk_tree_store_insert_after (GTK_TREE_STORE (tree_model),
                                           &dest_iter,
                                           NULL,
                                           &tmp_iter);
              retval = TRUE;

            }
        }

      gtk_tree_path_free (prev);
      
      /* If we succeeded in creating dest_iter, walk src_iter tree branch,
       * duplicating it below dest_iter.
       */
      
      if (retval)
        {
          recursive_node_copy (tree_store,
                               &src_iter,
                               &dest_iter);
        }
    }
  else
    {
      /* FIXME maybe add some data targets eventually, or handle text
       * targets in the simple case.
       */
Havoc Pennington's avatar
Havoc Pennington committed
1164

1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
    }

 out:
  
  if (src_path)
    gtk_tree_path_free (src_path);
  
  return retval;  
}

static gboolean
gtk_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest,
                                  GtkTreeModel    *src_model,
                                  GtkTreePath     *src_path,
                                  GtkTreePath     *dest_path)
{
  /* can only drag to ourselves */
  if (src_model != GTK_TREE_MODEL (drag_dest))
    return FALSE;
  
  /* Can't drop into ourself. */
  if (gtk_tree_path_is_ancestor (src_path,
                                 dest_path))
    return FALSE;

  /* Can't drop if dest_path's parent doesn't exist */
  {
    GtkTreeIter iter;
    GtkTreePath *tmp = gtk_tree_path_copy (dest_path);

    /* if we can't go up, we know the parent exists, the root
     * always exists.
     */
    if (gtk_tree_path_up (tmp))
      {
        if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_dest),
                                      &iter, tmp))
          {
            if (tmp)
              gtk_tree_path_free (tmp);
            return FALSE;
          }
      }
    
    if (tmp)
      gtk_tree_path_free (tmp);
  }
  
  /* Can otherwise drop anywhere. */
  return TRUE;
}
     
static void
validate_gnode (GNode* node)
{
  GNode *iter;
  
  iter = node->children;
  while (iter != NULL)
    {
      g_assert (iter->parent == node);
      if (iter->prev)
        g_assert (iter->prev->next == iter);
      validate_gnode (iter);
      iter = iter->next;
    }
}