gtktreestore.c 61 KB
Newer Older
1
/* gtktreestore.c
Manish Singh's avatar
Manish Singh committed
2
 * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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 != -2)
29
#define VALID_ITER(iter, tree_store) (iter!= NULL && iter->user_data != NULL && tree_store->stamp == iter->stamp)
30

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


69 70 71 72 73 74 75
static void gtk_tree_store_set_n_columns   (GtkTreeStore *tree_store,
					    gint          n_columns);
static void gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
					    gint          column,
					    GType         type);


76
/* DND interfaces */
77
static gboolean gtk_tree_store_drag_data_delete   (GtkTreeDragSource *drag_source,
78
						   GtkTreePath       *path);
79
static gboolean gtk_tree_store_drag_data_get      (GtkTreeDragSource *drag_source,
80 81
						   GtkTreePath       *path,
						   GtkSelectionData  *selection_data);
82
static gboolean gtk_tree_store_drag_data_received (GtkTreeDragDest   *drag_dest,
83 84
						   GtkTreePath       *dest,
						   GtkSelectionData  *selection_data);
85
static gboolean gtk_tree_store_row_drop_possible  (GtkTreeDragDest   *drag_dest,
86 87
						   GtkTreePath       *dest_path,
						   GtkSelectionData  *selection_data);
88 89 90

/* Sortable Interfaces */

91 92 93 94 95 96
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,
97
							GtkSortType            *order);
98 99
static void     gtk_tree_store_set_sort_column_id      (GtkTreeSortable        *sortable,
							gint                    sort_column_id,
100
							GtkSortType             order);
101
static void     gtk_tree_store_set_sort_func           (GtkTreeSortable        *sortable,
102 103 104 105
							gint                    sort_column_id,
							GtkTreeIterCompareFunc  func,
							gpointer                data,
							GtkDestroyNotify        destroy);
106 107 108 109 110
static void     gtk_tree_store_set_default_sort_func   (GtkTreeSortable        *sortable,
							GtkTreeIterCompareFunc  func,
							gpointer                data,
							GtkDestroyNotify        destroy);
static gboolean gtk_tree_store_has_default_sort_func   (GtkTreeSortable        *sortable);
111

112 113 114 115 116
static void     validate_gnode                         (GNode *node);


static GObjectClass *parent_class = NULL;

117 118 119 120 121 122 123

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

125 126 127 128
      validate_gnode (G_NODE (tree_store->root));
    }
}

129 130 131
GtkType
gtk_tree_store_get_type (void)
{
132
  static GType tree_store_type = 0;
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148

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

149 150 151 152 153 154 155
      static const GInterfaceInfo tree_model_info =
      {
	(GInterfaceInitFunc) gtk_tree_store_tree_model_init,
	NULL,
	NULL
      };

156 157 158 159 160 161 162 163 164 165 166 167 168
      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
      };
169 170 171 172 173 174 175 176

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

177
      tree_store_type = g_type_register_static (G_TYPE_OBJECT, "GtkTreeStore", &tree_store_info, 0);
178

179 180 181
      g_type_add_interface_static (tree_store_type,
				   GTK_TYPE_TREE_MODEL,
				   &tree_model_info);
182 183 184 185 186 187
      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);
188 189 190
      g_type_add_interface_static (tree_store_type,
				   GTK_TYPE_TREE_SORTABLE,
				   &sortable_info);
191

192 193 194 195 196 197
    }

  return tree_store_type;
}

static void
198
gtk_tree_store_class_init (GtkTreeStoreClass *class)
199
{
200 201
  GObjectClass *object_class;

202 203
  parent_class = g_type_class_peek_parent (class);
  object_class = (GObjectClass *) class;
204

205
  object_class->finalize = gtk_tree_store_finalize;
206 207 208 209 210
}

static void
gtk_tree_store_tree_model_init (GtkTreeModelIface *iface)
{
211
  iface->get_flags = gtk_tree_store_get_flags;
212
  iface->get_n_columns = gtk_tree_store_get_n_columns;
213
  iface->get_column_type = gtk_tree_store_get_column_type;
214
  iface->get_iter = gtk_tree_store_get_iter;
215
  iface->get_path = gtk_tree_store_get_path;
216
  iface->get_value = gtk_tree_store_get_value;
217 218 219 220 221 222
  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;
223 224
}

225 226 227 228 229 230 231 232
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
233
gtk_tree_store_drag_dest_init (GtkTreeDragDestIface *iface)
234 235 236 237 238
{
  iface->drag_data_received = gtk_tree_store_drag_data_received;
  iface->row_drop_possible = gtk_tree_store_row_drop_possible;
}

239 240 241
static void
gtk_tree_store_sortable_init (GtkTreeSortableIface *iface)
{
242 243
  iface->get_sort_column_id = gtk_tree_store_get_sort_column_id;
  iface->set_sort_column_id = gtk_tree_store_set_sort_column_id;
244
  iface->set_sort_func = gtk_tree_store_set_sort_func;
245 246
  iface->set_default_sort_func = gtk_tree_store_set_default_sort_func;
  iface->has_default_sort_func = gtk_tree_store_has_default_sort_func;
247 248
}

249 250 251
static void
gtk_tree_store_init (GtkTreeStore *tree_store)
{
252
  tree_store->root = g_node_new (NULL);
253 254
  /* While the odds are against us getting 0...
   */
255 256 257 258
  do
    {
      tree_store->stamp = g_random_int ();
    }
259
  while (tree_store->stamp == 0);
260

261
  tree_store->sort_list = NULL;
262
  tree_store->sort_column_id = -2;
263
  tree_store->columns_dirty = FALSE;
264 265
}

266 267 268 269 270 271
/**
 * gtk_tree_store_new:
 * @n_columns: number of columns in the tree store
 * @Varargs: all #GType types for the columns, from first to last
 *
 * Creates a new tree store as with @n_columns columns each of the types passed
272 273 274
 * in.  As an example, <literal>gtk_tree_store_new (3, G_TYPE_INT, G_TYPE_STRING,
 * GDK_TYPE_PIXBUF);</literal> will create a new #GtkTreeStore with three columns, of type
 * <type>int</type>, <type>string</type> and #GdkPixbuf respectively.
275 276 277
 *
 * Return value: a new #GtkTreeStore
 **/
278
GtkTreeStore *
279
gtk_tree_store_new (gint n_columns,
280
			       ...)
281
{
282
  GtkTreeStore *retval;
283 284 285 286 287
  va_list args;
  gint i;

  g_return_val_if_fail (n_columns > 0, NULL);

288
  retval = GTK_TREE_STORE (g_object_new (GTK_TYPE_TREE_STORE, NULL));
289
  gtk_tree_store_set_n_columns (retval, n_columns);
290 291

  va_start (args, n_columns);
292

293
  for (i = 0; i < n_columns; i++)
294 295 296 297 298 299 300 301 302 303
    {
      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);
    }
304 305 306 307
  va_end (args);

  return retval;
}
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
/**
 * gtk_tree_store_newv:
 * @n_columns: number of columns in the tree store
 * @types: an array of #GType types for the columns, from first to last
 *
 * Non vararg creation function.  Used primarily by language bindings.
 *
 * Return value: a new #GtkTreeStore
 **/
GtkTreeStore *
gtk_tree_store_newv (gint   n_columns,
		     GType *types)
{
  GtkTreeStore *retval;
  gint i;

  g_return_val_if_fail (n_columns > 0, NULL);

  retval = GTK_TREE_STORE (g_object_new (GTK_TYPE_TREE_STORE, NULL));
  gtk_tree_store_set_n_columns (retval, n_columns);

   for (i = 0; i < n_columns; i++)
    {
      if (! _gtk_tree_data_list_check_type (types[i]))
	{
	  g_warning ("%s: Invalid type %s passed to gtk_tree_store_new_with_types\n", G_STRLOC, g_type_name (types[i]));
	  g_object_unref (G_OBJECT (retval));
	  return NULL;
	}
      gtk_tree_store_set_column_type (retval, i, types[i]);
    }

  return retval;
}
342

343 344 345 346 347

/**
 * gtk_tree_store_set_column_types:
 * @tree_store: A #GtkTreeStore
 * @n_columns: Number of columns for the tree store
Matthias Clasen's avatar
Matthias Clasen committed
348
 * @types: An array of #GType types, one for each column
349
 * 
Matthias Clasen's avatar
Matthias Clasen committed
350 351 352 353
 * This function is meant primarily for #GObjects that inherit from 
 * #GtkTreeStore, and should only be used when constructing a new 
 * #GtkTreeStore.  It will not function after a row has been added, 
 * or a method on the #GtkTreeModel interface is called.
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
 **/
void
gtk_tree_store_set_column_types (GtkTreeStore *tree_store,
				 gint          n_columns,
				 GType        *types)
{
  gint i;

  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
  g_return_if_fail (tree_store->columns_dirty == 0);

  gtk_tree_store_set_n_columns (tree_store, n_columns);
   for (i = 0; i < n_columns; i++)
    {
      if (! _gtk_tree_data_list_check_type (types[i]))
	{
	  g_warning ("%s: Invalid type %s passed to gtk_tree_store_set_column_types\n", G_STRLOC, g_type_name (types[i]));
	  continue;
	}
      gtk_tree_store_set_column_type (tree_store, i, types[i]);
    }
}

377
static void
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
gtk_tree_store_set_n_columns (GtkTreeStore *tree_store,
			      gint          n_columns)
{
  GType *new_columns;

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

400 401 402 403 404
  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);

405 406 407 408
  tree_store->column_headers = new_columns;
  tree_store->n_columns = n_columns;
}

409 410 411 412 413
/**
 * gtk_tree_store_set_column_type:
 * @tree_store: a #GtkTreeStore
 * @column: column number
 * @type: type of the data to be stored in @column
414
 *
415 416 417 418
 * 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.
419
 *
420
 **/
421
static void
422 423 424 425 426 427
gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
				gint          column,
				GType         type)
{
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
  g_return_if_fail (column >=0 && column < tree_store->n_columns);
428 429 430 431 432
  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;
    }
433 434 435
  tree_store->column_headers[column] = type;
}

436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
static void
node_free (GNode *node, gpointer data)
{
  _gtk_tree_data_list_free (node->data, (GType*)data);
}

static void
gtk_tree_store_finalize (GObject *object)
{
  GtkTreeStore *tree_store = GTK_TREE_STORE (object);

  g_node_children_foreach (tree_store->root, G_TRAVERSE_LEAFS, node_free, tree_store->column_headers);
  _gtk_tree_data_list_header_free (tree_store->sort_list);
  g_free (tree_store->column_headers);

  if (tree_store->default_sort_destroy)
    {
453 454
      GtkDestroyNotify d = tree_store->default_sort_destroy;

455
      tree_store->default_sort_destroy = NULL;
456
      d (tree_store->default_sort_data);
457 458
      tree_store->default_sort_data = NULL;
    }
459 460

  (* parent_class->finalize) (object);
461 462
}

463 464
/* fulfill the GtkTreeModel requirements */
/* NOTE: GtkTreeStore::root is a GNode, that acts as the parent node.  However,
465
 * it is not visible to the tree or to the user., and the path "0" refers to the
466 467
 * first child of GtkTreeStore::root.
 */
468 469 470 471 472 473 474 475 476 477


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

478 479 480
static gint
gtk_tree_store_get_n_columns (GtkTreeModel *tree_model)
{
481 482
  GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;

483 484
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);

485 486 487
  tree_store->columns_dirty = TRUE;

  return tree_store->n_columns;
488 489
}

490 491 492 493
static GType
gtk_tree_store_get_column_type (GtkTreeModel *tree_model,
				gint          index)
{
494 495
  GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;

496 497 498 499
  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);

500 501 502
  tree_store->columns_dirty = TRUE;

  return tree_store->column_headers[index];
503 504
}

505 506 507 508 509 510 511 512 513 514 515
static gboolean
gtk_tree_store_get_iter (GtkTreeModel *tree_model,
			 GtkTreeIter  *iter,
			 GtkTreePath  *path)
{
  GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
  GtkTreeIter parent;
  gint *indices;
  gint depth, i;

  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), FALSE);
516 517 518

  tree_store->columns_dirty = TRUE;

519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
  indices = gtk_tree_path_get_indices (path);
  depth = gtk_tree_path_get_depth (path);

  g_return_val_if_fail (depth > 0, FALSE);

  parent.stamp = tree_store->stamp;
  parent.user_data = tree_store->root;

  if (! gtk_tree_model_iter_nth_child (tree_model, iter, &parent, indices[0]))
    return FALSE;

  for (i = 1; i < depth; i++)
    {
      parent = *iter;
      if (! gtk_tree_model_iter_nth_child (tree_model, iter, &parent, indices[i]))
	return FALSE;
    }

  return TRUE;
}

540 541
static GtkTreePath *
gtk_tree_store_get_path (GtkTreeModel *tree_model,
542
			 GtkTreeIter  *iter)
543 544 545 546
{
  GtkTreePath *retval;
  GNode *tmp_node;
  gint i = 0;
547

548 549
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), NULL);
  g_return_val_if_fail (iter != NULL, NULL);
550
  g_return_val_if_fail (iter->user_data != NULL, NULL);
551
  g_return_val_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->stamp, NULL);
552

553
  validate_tree ((GtkTreeStore*)tree_model);
554

555 556 557
  if (G_NODE (iter->user_data)->parent == NULL &&
      G_NODE (iter->user_data) == GTK_TREE_STORE (tree_model)->root)
    return gtk_tree_path_new ();
558
  g_assert (G_NODE (iter->user_data)->parent != NULL);
559

Havoc Pennington's avatar
Havoc Pennington committed
560
  if (G_NODE (iter->user_data)->parent == G_NODE (GTK_TREE_STORE (tree_model)->root))
561 562 563 564 565 566
    {
      retval = gtk_tree_path_new ();
      tmp_node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
    }
  else
    {
567
      GtkTreeIter tmp_iter = *iter;
568

569
      tmp_iter.user_data = G_NODE (iter->user_data)->parent;
570

571
      retval = gtk_tree_store_get_path (tree_model,
572
					&tmp_iter);
Havoc Pennington's avatar
Havoc Pennington committed
573
      tmp_node = G_NODE (iter->user_data)->parent->children;
574 575 576 577
    }

  if (retval == NULL)
    return NULL;
578

579 580 581 582 583 584 585 586
  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
587
      if (tmp_node == G_NODE (iter->user_data))
588 589 590
	break;
      i++;
    }
591

592 593 594
  if (tmp_node == NULL)
    {
      /* We couldn't find node, meaning it's prolly not ours */
595
      /* Perhaps I should do a g_return_if_fail here. */
596 597 598 599 600 601 602 603 604 605 606
      gtk_tree_path_free (retval);
      return NULL;
    }

  gtk_tree_path_append_index (retval, i);

  return retval;
}


static void
607 608 609 610
gtk_tree_store_get_value (GtkTreeModel *tree_model,
			  GtkTreeIter  *iter,
			  gint          column,
			  GValue       *value)
611 612 613 614 615
{
  GtkTreeDataList *list;
  gint tmp_column = column;

  g_return_if_fail (GTK_IS_TREE_STORE (tree_model));
616
  g_return_if_fail (iter != NULL);
617
  g_return_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->stamp);
618 619
  g_return_if_fail (column < GTK_TREE_STORE (tree_model)->n_columns);

Havoc Pennington's avatar
Havoc Pennington committed
620
  list = G_NODE (iter->user_data)->data;
621 622 623 624

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

625 626
  if (list)
    {
627 628 629
      _gtk_tree_data_list_node_to_value (list,
					 GTK_TREE_STORE (tree_model)->column_headers[column],
					 value);
630 631 632 633 634 635
    }
  else
    {
      /* We want to return an initialized but empty (default) value */
      g_value_init (value, GTK_TREE_STORE (tree_model)->column_headers[column]);
    }
636 637 638
}

static gboolean
639 640
gtk_tree_store_iter_next (GtkTreeModel  *tree_model,
			  GtkTreeIter   *iter)
641
{
642
  g_return_val_if_fail (iter != NULL, FALSE);
643
  g_return_val_if_fail (iter->user_data != NULL, FALSE);
644
  g_return_val_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->stamp, FALSE);
645

646 647 648 649 650 651
  if (G_NODE (iter->user_data)->next)
    {
      iter->user_data = G_NODE (iter->user_data)->next;
      return TRUE;
    }
  else
652 653 654
    return FALSE;
}

655 656 657 658
static gboolean
gtk_tree_store_iter_children (GtkTreeModel *tree_model,
			      GtkTreeIter  *iter,
			      GtkTreeIter  *parent)
659
{
660 661 662
  GNode *children;

  g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
663
  g_return_val_if_fail (parent == NULL || parent->stamp == GTK_TREE_STORE (tree_model)->stamp, FALSE);
664

665
  if (parent)
666
    children = G_NODE (parent->user_data)->children;
667
  else
668
    children = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
669

670 671 672 673 674 675 676 677
  if (children)
    {
      iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
      iter->user_data = children;
      return TRUE;
    }
  else
    return FALSE;
678 679 680
}

static gboolean
681 682
gtk_tree_store_iter_has_child (GtkTreeModel *tree_model,
			       GtkTreeIter  *iter)
683
{
684
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), FALSE);
Jonathan Blandford's avatar
Jonathan Blandford committed
685
  g_return_val_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->stamp, FALSE);
686
  g_return_val_if_fail (iter->user_data != NULL, FALSE);
687

Havoc Pennington's avatar
Havoc Pennington committed
688
  return G_NODE (iter->user_data)->children != NULL;
689 690 691
}

static gint
692 693
gtk_tree_store_iter_n_children (GtkTreeModel *tree_model,
				GtkTreeIter  *iter)
694
{
695
  GNode *node;
696 697
  gint i = 0;

698
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);
699
  g_return_val_if_fail (iter == NULL || iter->user_data != NULL, FALSE);
700

701 702 703
  if (iter == NULL)
    node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
  else
Havoc Pennington's avatar
Havoc Pennington committed
704
    node = G_NODE (iter->user_data)->children;
705

706
  while (node)
707 708
    {
      i++;
709
      node = node->next;
710 711 712 713 714
    }

  return i;
}

715 716 717 718
static gboolean
gtk_tree_store_iter_nth_child (GtkTreeModel *tree_model,
			       GtkTreeIter  *iter,
			       GtkTreeIter  *parent,
719 720
			       gint          n)
{
721
  GNode *parent_node;
722
  GNode *child;
723

724
  g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), FALSE);
725
  g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
726

727 728 729
  if (parent == NULL)
    parent_node = GTK_TREE_STORE (tree_model)->root;
  else
Havoc Pennington's avatar
Havoc Pennington committed
730
    parent_node = parent->user_data;
731

732
  child = g_node_nth_child (parent_node, n);
733

734 735 736 737 738 739
  if (child)
    {
      iter->user_data = child;
      iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
      return TRUE;
    }
740
  else
741
    return FALSE;
742 743
}

744 745 746 747
static gboolean
gtk_tree_store_iter_parent (GtkTreeModel *tree_model,
			    GtkTreeIter  *iter,
			    GtkTreeIter  *child)
748
{
749
  GNode *parent;
750

751
  g_return_val_if_fail (iter != NULL, FALSE);
752 753 754
  g_return_val_if_fail (child != NULL, FALSE);
  g_return_val_if_fail (child->user_data != NULL, FALSE);
  g_return_val_if_fail (child->stamp == GTK_TREE_STORE (tree_model)->stamp, FALSE);
755 756 757

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

758
  g_assert (parent != NULL);
759

760
  if (parent != GTK_TREE_STORE (tree_model)->root)
761
    {
762 763 764
      iter->user_data = parent;
      iter->stamp = GTK_TREE_STORE (tree_model)->stamp;
      return TRUE;
765
    }
766 767
  else
    return FALSE;
768 769
}

770 771

/* Does not emit a signal */
772
static gboolean
773 774 775
gtk_tree_store_real_set_value (GtkTreeStore *tree_store,
			       GtkTreeIter  *iter,
			       gint          column,
776 777
			       GValue       *value,
			       gboolean      sort)
778 779 780
{
  GtkTreeDataList *list;
  GtkTreeDataList *prev;
781
  GtkTreePath *path = NULL;
782 783
  GValue real_value = {0, };
  gboolean converted = FALSE;
784
  gboolean retval = FALSE;
785

786
  if (! g_type_is_a (G_VALUE_TYPE (value), tree_store->column_headers[column]))
787
    {
788 789
      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))))
790 791 792 793
	{
	  g_warning ("%s: Unable to convert from %s to %s\n",
		     G_STRLOC,
		     g_type_name (G_VALUE_TYPE (value)),
794
		     g_type_name (tree_store->column_headers[column]));
795
	  return retval;
796 797 798 799 800 801
	}
      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)),
802
		     g_type_name (tree_store->column_headers[column]));
803
	  g_value_unset (&real_value);
804
	  return retval;
805 806 807
	}
      converted = TRUE;
    }
808

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

811 812
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);

813 814 815 816
  while (list != NULL)
    {
      if (column == 0)
	{
817 818 819 820
	  if (converted)
	    _gtk_tree_data_list_value_to_node (list, &real_value);
	  else
	    _gtk_tree_data_list_value_to_node (list, value);
821
	  retval = TRUE;
822
	  gtk_tree_path_free (path);
823 824
	  if (converted)
	    g_value_unset (&real_value);
825
	  return retval;
826 827 828 829 830 831 832
	}

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

Havoc Pennington's avatar
Havoc Pennington committed
833
  if (G_NODE (iter->user_data)->data == NULL)
834
    {
Havoc Pennington's avatar
Havoc Pennington committed
835
      G_NODE (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
836 837 838 839
      list->next = NULL;
    }
  else
    {
840
      list = prev->next = _gtk_tree_data_list_alloc ();
841 842 843 844 845
      list->next = NULL;
    }

  while (column != 0)
    {
846
      list->next = _gtk_tree_data_list_alloc ();
847 848 849 850
      list = list->next;
      list->next = NULL;
      column --;
    }
851
  if (converted)
852
    _gtk_tree_data_list_value_to_node (list, &real_value);
853 854
  else
    _gtk_tree_data_list_value_to_node (list, value);
855 856
  
  retval = TRUE;
857
  gtk_tree_path_free (path);
858 859
  if (converted)
    g_value_unset (&real_value);
860

861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886
  return retval;
}

/**
 * gtk_tree_store_set_value:
 * @tree_store: a #GtkTreeStore
 * @iter: A valid #GtkTreeIter for the row being modified
 * @column: column number to modify
 * @value: new value for the cell
 *
 * Sets the data in the cell specified by @iter and @column.
 * The type of @value must be convertible to the type of the
 * column.
 *
 **/
void
gtk_tree_store_set_value (GtkTreeStore *tree_store,
			  GtkTreeIter  *iter,
			  gint          column,
			  GValue       *value)
{
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
  g_return_if_fail (VALID_ITER (iter, tree_store));
  g_return_if_fail (column >= 0 && column < tree_store->n_columns);
  g_return_if_fail (G_IS_VALUE (value));

887
  if (gtk_tree_store_real_set_value (tree_store, iter, column, value, TRUE))
888 889 890 891 892 893 894
    {
      GtkTreePath *path;

      path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_store), iter);
      gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter);
      gtk_tree_path_free (path);
    }
895 896
}

897 898
/**
 * gtk_tree_store_set_valist:
899 900
 * @tree_store: A #GtkTreeStore
 * @iter: A valid #GtkTreeIter for the row being modified
Matthias Clasen's avatar
Matthias Clasen committed
901
 * @var_args: <type>va_list</type> of column/value pairs
902
 *
Matthias Clasen's avatar
Matthias Clasen committed
903
 * See gtk_tree_store_set(); this version takes a <type>va_list</type> for
904
 * use by language bindings.
905
 *
906
 **/
907
void
Havoc Pennington's avatar
Havoc Pennington committed
908 909 910
gtk_tree_store_set_valist (GtkTreeStore *tree_store,
                           GtkTreeIter  *iter,
                           va_list	var_args)
911 912
{
  gint column;
913
  gboolean emit_signal = FALSE;
914
  gboolean maybe_need_sort = FALSE;
915
  GtkTreeIterCompareFunc func = NULL;
916 917

  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
918
  g_return_if_fail (VALID_ITER (iter, tree_store));
919 920 921

  column = va_arg (var_args, gint);

922
  if (GTK_TREE_STORE_IS_SORTED (tree_store))
923
    {
924 925 926 927 928 929 930 931 932 933 934 935 936
      if (tree_store->sort_column_id != -1)
	{
	  GtkTreeDataSortHeader *header;
	  header = _gtk_tree_data_list_get_header (tree_store->sort_list,
						   tree_store->sort_column_id);
	  g_return_if_fail (header != NULL);
	  g_return_if_fail (header->func != NULL);
	  func = header->func;
	}
      else
	{
	  func = tree_store->default_sort_func;
	}
937 938 939 940 941
    }

  if (func != gtk_tree_data_list_compare_func)
    maybe_need_sort = TRUE;

Havoc Pennington's avatar
Havoc Pennington committed
942
  while (column != -1)
943 944 945 946 947 948
    {
      GValue value = { 0, };
      gchar *error = NULL;

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

954
      G_VALUE_COLLECT (&value, var_args, 0, &error);
955 956 957 958 959 960 961 962 963 964 965
      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;
	}

966 967 968
      emit_signal = gtk_tree_store_real_set_value (tree_store,
						   iter,
						   column,
969 970 971 972 973 974
						   &value,
						   FALSE) || emit_signal;

      if (func == gtk_tree_data_list_compare_func &&
	  column == tree_store->sort_column_id)
	maybe_need_sort = TRUE;
975 976 977 978 979

      g_value_unset (&value);

      column = va_arg (var_args, gint);
    }
980 981 982 983

  if (maybe_need_sort && GTK_TREE_STORE_IS_SORTED (tree_store))
    gtk_tree_store_sort_iter_changed (tree_store, iter, tree_store->sort_column_id);

984 985 986 987 988 989 990 991
  if (emit_signal)
    {
      GtkTreePath *path;

      path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_store), iter);
      gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter);
      gtk_tree_path_free (path);
    }
992 993
}

Havoc Pennington's avatar
Havoc Pennington committed
994 995
/**
 * gtk_tree_store_set:
996 997
 * @tree_store: A #GtkTreeStore
 * @iter: A valid #GtkTreeIter for the row being modified
Havoc Pennington's avatar
Havoc Pennington committed
998
 * @Varargs: pairs of column number and value, terminated with -1
999
 *
Havoc Pennington's avatar
Havoc Pennington committed
1000 1001
 * Sets the value of one or more cells in the row referenced by @iter.
 * The variable argument list should contain integer column numbers,
1002
 * each column number followed by the value to be set. 
Havoc Pennington's avatar
Havoc Pennington committed
1003
 * The list is terminated by a -1. For example, to set column 0 with type
Matthias Clasen's avatar
Matthias Clasen committed
1004 1005
 * %G_TYPE_STRING to "Foo", you would write 
 * <literal>gtk_tree_store_set (store, iter, 0, "Foo", -1)</literal>.
Havoc Pennington's avatar
Havoc Pennington committed
1006
 **/
1007
void
1008 1009 1010
gtk_tree_store_set (GtkTreeStore *tree_store,
		    GtkTreeIter  *iter,
		    ...)
1011 1012 1013 1014
{
  va_list var_args;

  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1015
  g_return_if_fail (VALID_ITER (iter, tree_store));
1016 1017

  va_start (var_args, iter);
Havoc Pennington's avatar
Havoc Pennington committed
1018
  gtk_tree_store_set_valist (tree_store, iter, var_args);
1019 1020 1021
  va_end (var_args);
}

1022 1023 1024 1025 1026 1027
/**
 * gtk_tree_store_remove:
 * @tree_store: A #GtkTreeStore
 * @iter: A valid #GtkTreeIter
 * 
 * Removes @iter from @tree_store.  After being removed, @iter is set to the
1028
 * next valid row at that level, or invalidated if it previously pointed to the
1029
 * last one.
1030
 **/
1031
void
1032
gtk_tree_store_remove (GtkTreeStore *tree_store,
1033
		       GtkTreeIter  *iter)
1034 1035
{
  GtkTreePath *path;
1036
  GtkTreeIter new_iter = {0,};
1037
  GNode *parent;
1038
  GNode *next_node;
1039

1040 1041
  g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
  g_return_if_fail (VALID_ITER (iter, tree_store));
1042

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

1045
  g_assert (parent != NULL);
1046
  next_node = G_NODE (iter->user_data)->next;
1047

Havoc Pennington's avatar
Havoc Pennington committed
1048 1049
  if (G_NODE (iter->user_data)->data)
    _gtk_tree_data_list_free ((GtkTreeDataList *) G_NODE (iter->user_data)->data,
1050
			      tree_store->column_headers);
1051

1052
  path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
Havoc Pennington's avatar
Havoc Pennington committed
1053
  g_node_destroy (G_NODE (iter->user_data));
1054

1055
  gtk_tree_model_row_deleted (GTK_TREE_MODEL (tree_store), path);