gtkliststore.c 75.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/* gtkliststore.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
Javier Jardón's avatar
Javier Jardón committed
15
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 17
 */

18
#include "config.h"
19 20
#include <errno.h>
#include <stdlib.h>
21
#include <string.h>
Manish Singh's avatar
Manish Singh committed
22
#include <gobject/gvaluecollector.h>
23 24 25
#include "gtktreemodel.h"
#include "gtkliststore.h"
#include "gtktreedatalist.h"
26
#include "gtktreednd.h"
27
#include "gtkintl.h"
28
#include "gtkbuildable.h"
29
#include "gtkbuilderprivate.h"
30

31

32 33 34 35 36 37 38 39 40 41
/**
 * SECTION:gtkliststore
 * @Short_description: A list-like data structure that can be used with the GtkTreeView
 * @Title: GtkListStore
 * @See_also:#GtkTreeModel, #GtkTreeStore
 *
 * The #GtkListStore object is a list model for use with a #GtkTreeView
 * widget.  It implements the #GtkTreeModel interface, and consequentialy,
 * can use all of the methods available there.  It also implements the
 * #GtkTreeSortable interface so it can be sorted by the view.
42
 * Finally, it also implements the tree
43
 * [drag and drop][gtk3-GtkTreeView-drag-and-drop]
44
 * interfaces.
45 46
 *
 * The #GtkListStore can accept most GObject types as a column type, though
47
 * it can’t accept all custom types.  Internally, it will keep a copy of
48
 * data passed in (such as a string or a boxed pointer).  Columns that
49
 * accept #GObjects are handled a little differently.  The
50 51 52 53
 * #GtkListStore will keep a reference to the object instead of copying the
 * value.  As a result, if the object is modified, it is up to the
 * application writer to call gtk_tree_model_row_changed() to emit the
 * #GtkTreeModel::row_changed signal.  This most commonly affects lists with
54
 * #GdkPixbufs stored.
Benjamin Otte's avatar
Benjamin Otte committed
55
 *
56
 * An example for creating a simple list store:
57
 * |[<!-- language="C" -->
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
 * enum {
 *   COLUMN_STRING,
 *   COLUMN_INT,
 *   COLUMN_BOOLEAN,
 *   N_COLUMNS
 * };
 *
 * {
 *   GtkListStore *list_store;
 *   GtkTreePath *path;
 *   GtkTreeIter iter;
 *   gint i;
 *
 *   list_store = gtk_list_store_new (N_COLUMNS,
 *                                    G_TYPE_STRING,
 *                                    G_TYPE_INT,
 *                                    G_TYPE_BOOLEAN);
 *
 *   for (i = 0; i < 10; i++)
 *     {
 *       gchar *some_data;
 *
 *       some_data = get_some_data (i);
 *
82
 *       // Add a new row to the model
83 84 85 86 87 88 89
 *       gtk_list_store_append (list_store, &iter);
 *       gtk_list_store_set (list_store, &iter,
 *                           COLUMN_STRING, some_data,
 *                           COLUMN_INT, i,
 *                           COLUMN_BOOLEAN,  FALSE,
 *                           -1);
 *
90 91
 *       // As the store will keep a copy of the string internally,
 *       // we free some_data.
92 93 94
 *       g_free (some_data);
 *     }
 *
95
 *   // Modify a particular row
96 97 98 99 100 101 102 103 104
 *   path = gtk_tree_path_new_from_string ("4");
 *   gtk_tree_model_get_iter (GTK_TREE_MODEL (list_store),
 *                            &iter,
 *                            path);
 *   gtk_tree_path_free (path);
 *   gtk_list_store_set (list_store, &iter,
 *                       COLUMN_BOOLEAN, TRUE,
 *                       -1);
 * }
105
 * ]|
Benjamin Otte's avatar
Benjamin Otte committed
106
 *
107
 * # Performance Considerations
108 109 110
 *
 * Internally, the #GtkListStore was implemented with a linked list with
 * a tail pointer prior to GTK+ 2.6.  As a result, it was fast at data
111 112
 * insertion and deletion, and not fast at random data access.  The
 * #GtkListStore sets the #GTK_TREE_MODEL_ITERS_PERSIST flag, which means
113
 * that #GtkTreeIters can be cached while the row exists.  Thus, if
114 115
 * access to a particular row is needed often and your code is expected to
 * run on older versions of GTK+, it is worth keeping the iter around.
116
 *
117
 * # Atomic Operations
118
 *
119 120 121 122 123 124 125 126 127 128 129 130 131 132
 * It is important to note that only the methods
 * gtk_list_store_insert_with_values() and gtk_list_store_insert_with_valuesv()
 * are atomic, in the sense that the row is being appended to the store and the
 * values filled in in a single operation with regard to #GtkTreeModel signaling.
 * In contrast, using e.g. gtk_list_store_append() and then gtk_list_store_set()
 * will first create a row, which triggers the #GtkTreeModel::row-inserted signal
 * on #GtkListStore. The row, however, is still empty, and any signal handler
 * connecting to #GtkTreeModel::row-inserted on this particular store should be prepared
 * for the situation that the row might be empty. This is especially important
 * if you are wrapping the #GtkListStore inside a #GtkTreeModelFilter and are
 * using a #GtkTreeModelFilterVisibleFunc. Using any of the non-atomic operations
 * to append rows to the #GtkListStore will cause the
 * #GtkTreeModelFilterVisibleFunc to be visited with an empty row first; the
 * function must be prepared for that.
133
 *
134
 * # GtkListStore as GtkBuildable
135
 *
136
 * The GtkListStore implementation of the GtkBuildable interface allows
137 138 139
 * to specify the model columns with a <columns> element that may contain
 * multiple <column> elements, each specifying one model column. The “type”
 * attribute specifies the data type for the column.
140 141
 *
 * Additionally, it is possible to specify content for the list store
142 143 144 145 146 147 148 149
 * in the UI definition, with the <data> element. It can contain multiple
 * <row> elements, each specifying to content for one row of the list model.
 * Inside a <row>, the <col> elements specify the content for individual cells.
 *
 * Note that it is probably more common to define your models in the code,
 * and one might consider it a layering violation to specify the content of
 * a list store in a UI definition, data, not presentation, and common wisdom
 * is to separate the two, as far as possible.
150
 *
151
 * An example of a UI Definition fragment for a list store:
152
 * |[<!-- language="C" -->
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
 * <object class="GtkListStore">
 *   <columns>
 *     <column type="gchararray"/>
 *     <column type="gchararray"/>
 *     <column type="gint"/>
 *   </columns>
 *   <data>
 *     <row>
 *       <col id="0">John</col>
 *       <col id="1">Doe</col>
 *       <col id="2">25</col>
 *     </row>
 *     <row>
 *       <col id="0">Johan</col>
 *       <col id="1">Dahlin</col>
 *       <col id="2">50</col>
 *     </row>
 *   </data>
 * </object>
172
 * ]|
173 174 175
 */


176
struct _GtkListStorePrivate
177 178 179 180 181 182 183 184 185 186 187 188
{
  GtkTreeIterCompareFunc default_sort_func;

  GDestroyNotify default_sort_destroy;
  GList *sort_list;
  GType *column_headers;

  gint stamp;
  gint n_columns;
  gint sort_column_id;
  gint length;

189 190
  GtkSortType order;

191 192 193 194 195 196 197
  guint columns_dirty : 1;

  gpointer default_sort_data;
  gpointer seq;         /* head of the list */
};

#define GTK_LIST_STORE_IS_SORTED(list) (((GtkListStore*)(list))->priv->sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
198
static void         gtk_list_store_tree_model_init (GtkTreeModelIface *iface);
199 200
static void         gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface);
static void         gtk_list_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
201
static void         gtk_list_store_sortable_init   (GtkTreeSortableIface   *iface);
202
static void         gtk_list_store_buildable_init  (GtkBuildableIface      *iface);
203
static void         gtk_list_store_finalize        (GObject           *object);
204
static GtkTreeModelFlags gtk_list_store_get_flags  (GtkTreeModel      *tree_model);
205
static gint         gtk_list_store_get_n_columns   (GtkTreeModel      *tree_model);
206 207
static GType        gtk_list_store_get_column_type (GtkTreeModel      *tree_model,
						    gint               index);
208 209 210 211 212 213 214 215 216 217 218
static gboolean     gtk_list_store_get_iter        (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter,
						    GtkTreePath       *path);
static GtkTreePath *gtk_list_store_get_path        (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter);
static void         gtk_list_store_get_value       (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter,
						    gint               column,
						    GValue            *value);
static gboolean     gtk_list_store_iter_next       (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter);
219 220
static gboolean     gtk_list_store_iter_previous   (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter);
221 222 223 224 225 226 227 228 229 230 231 232 233 234
static gboolean     gtk_list_store_iter_children   (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter,
						    GtkTreeIter       *parent);
static gboolean     gtk_list_store_iter_has_child  (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter);
static gint         gtk_list_store_iter_n_children (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter);
static gboolean     gtk_list_store_iter_nth_child  (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter,
						    GtkTreeIter       *parent,
						    gint               n);
static gboolean     gtk_list_store_iter_parent     (GtkTreeModel      *tree_model,
						    GtkTreeIter       *iter,
						    GtkTreeIter       *child);
235

236

237 238 239 240 241 242
static void gtk_list_store_set_n_columns   (GtkListStore *list_store,
					    gint          n_columns);
static void gtk_list_store_set_column_type (GtkListStore *list_store,
					    gint          column,
					    GType         type);

243 244
static void gtk_list_store_increment_stamp (GtkListStore *list_store);

245

246
/* Drag and Drop */
Murray Cumming's avatar
Murray Cumming committed
247 248
static gboolean real_gtk_list_store_row_draggable (GtkTreeDragSource *drag_source,
                                                   GtkTreePath       *path);
249 250 251 252 253 254 255 256
static gboolean gtk_list_store_drag_data_delete   (GtkTreeDragSource *drag_source,
                                                   GtkTreePath       *path);
static gboolean gtk_list_store_drag_data_get      (GtkTreeDragSource *drag_source,
                                                   GtkTreePath       *path,
                                                   GtkSelectionData  *selection_data);
static gboolean gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
                                                   GtkTreePath       *dest,
                                                   GtkSelectionData  *selection_data);
257
static gboolean gtk_list_store_row_drop_possible  (GtkTreeDragDest   *drag_dest,
258 259
                                                   GtkTreePath       *dest_path,
						   GtkSelectionData  *selection_data);
260

261

262
/* sortable */
263 264 265 266 267 268 269 270 271 272 273 274 275 276
static void     gtk_list_store_sort                  (GtkListStore           *list_store);
static void     gtk_list_store_sort_iter_changed     (GtkListStore           *list_store,
						      GtkTreeIter            *iter,
						      gint                    column);
static gboolean gtk_list_store_get_sort_column_id    (GtkTreeSortable        *sortable,
						      gint                   *sort_column_id,
						      GtkSortType            *order);
static void     gtk_list_store_set_sort_column_id    (GtkTreeSortable        *sortable,
						      gint                    sort_column_id,
						      GtkSortType             order);
static void     gtk_list_store_set_sort_func         (GtkTreeSortable        *sortable,
						      gint                    sort_column_id,
						      GtkTreeIterCompareFunc  func,
						      gpointer                data,
277
						      GDestroyNotify          destroy);
278 279 280
static void     gtk_list_store_set_default_sort_func (GtkTreeSortable        *sortable,
						      GtkTreeIterCompareFunc  func,
						      gpointer                data,
281
						      GDestroyNotify          destroy);
282 283
static gboolean gtk_list_store_has_default_sort_func (GtkTreeSortable        *sortable);

284

285 286 287 288 289 290 291 292 293 294 295 296 297
/* buildable */
static gboolean gtk_list_store_buildable_custom_tag_start (GtkBuildable  *buildable,
							   GtkBuilder    *builder,
							   GObject       *child,
							   const gchar   *tagname,
							   GMarkupParser *parser,
							   gpointer      *data);
static void     gtk_list_store_buildable_custom_tag_end (GtkBuildable *buildable,
							 GtkBuilder   *builder,
							 GObject      *child,
							 const gchar  *tagname,
							 gpointer     *data);

Matthias Clasen's avatar
Matthias Clasen committed
298
G_DEFINE_TYPE_WITH_CODE (GtkListStore, gtk_list_store, G_TYPE_OBJECT,
299
                         G_ADD_PRIVATE (GtkListStore)
Matthias Clasen's avatar
Matthias Clasen committed
300 301 302 303 304 305 306
			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
						gtk_list_store_tree_model_init)
			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
						gtk_list_store_drag_source_init)
			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
						gtk_list_store_drag_dest_init)
			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
307 308 309 310
						gtk_list_store_sortable_init)
			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
						gtk_list_store_buildable_init))

311 312 313 314

static void
gtk_list_store_class_init (GtkListStoreClass *class)
{
315 316 317
  GObjectClass *object_class;

  object_class = (GObjectClass*) class;
318 319

  object_class->finalize = gtk_list_store_finalize;
320 321 322 323 324
}

static void
gtk_list_store_tree_model_init (GtkTreeModelIface *iface)
{
325
  iface->get_flags = gtk_list_store_get_flags;
326
  iface->get_n_columns = gtk_list_store_get_n_columns;
327
  iface->get_column_type = gtk_list_store_get_column_type;
328
  iface->get_iter = gtk_list_store_get_iter;
329
  iface->get_path = gtk_list_store_get_path;
330
  iface->get_value = gtk_list_store_get_value;
331
  iface->iter_next = gtk_list_store_iter_next;
332
  iface->iter_previous = gtk_list_store_iter_previous;
333 334 335 336 337
  iface->iter_children = gtk_list_store_iter_children;
  iface->iter_has_child = gtk_list_store_iter_has_child;
  iface->iter_n_children = gtk_list_store_iter_n_children;
  iface->iter_nth_child = gtk_list_store_iter_nth_child;
  iface->iter_parent = gtk_list_store_iter_parent;
338 339
}

340 341 342
static void
gtk_list_store_drag_source_init (GtkTreeDragSourceIface *iface)
{
Murray Cumming's avatar
Murray Cumming committed
343
  iface->row_draggable = real_gtk_list_store_row_draggable;
344 345 346 347 348
  iface->drag_data_delete = gtk_list_store_drag_data_delete;
  iface->drag_data_get = gtk_list_store_drag_data_get;
}

static void
349
gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface)
350 351
{
  iface->drag_data_received = gtk_list_store_drag_data_received;
352
  iface->row_drop_possible = gtk_list_store_row_drop_possible;
353 354
}

355 356 357 358 359
static void
gtk_list_store_sortable_init (GtkTreeSortableIface *iface)
{
  iface->get_sort_column_id = gtk_list_store_get_sort_column_id;
  iface->set_sort_column_id = gtk_list_store_set_sort_column_id;
360
  iface->set_sort_func = gtk_list_store_set_sort_func;
361 362
  iface->set_default_sort_func = gtk_list_store_set_default_sort_func;
  iface->has_default_sort_func = gtk_list_store_has_default_sort_func;
363 364
}

365 366 367 368 369 370 371
void
gtk_list_store_buildable_init (GtkBuildableIface *iface)
{
  iface->custom_tag_start = gtk_list_store_buildable_custom_tag_start;
  iface->custom_tag_end = gtk_list_store_buildable_custom_tag_end;
}

372 373 374
static void
gtk_list_store_init (GtkListStore *list_store)
{
375
  GtkListStorePrivate *priv;
376

377
  list_store->priv = gtk_list_store_get_instance_private (list_store);
378 379 380 381 382 383 384 385
  priv = list_store->priv;

  priv->seq = g_sequence_new (NULL);
  priv->sort_list = NULL;
  priv->stamp = g_random_int ();
  priv->sort_column_id = GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID;
  priv->columns_dirty = FALSE;
  priv->length = 0;
386 387
}

388 389 390 391 392 393 394 395 396 397 398
static gboolean
iter_is_valid (GtkTreeIter  *iter,
               GtkListStore *list_store)
{
  return iter != NULL && 
         iter->user_data != NULL &&
         list_store->priv->stamp == iter->stamp &&
         !g_sequence_iter_is_end (iter->user_data) &&
         g_sequence_iter_get_sequence (iter->user_data) == list_store->priv->seq;
}

399 400 401
/**
 * gtk_list_store_new:
 * @n_columns: number of columns in the list store
Matthias Clasen's avatar
Matthias Clasen committed
402
 * @...: all #GType types for the columns, from first to last
403
 *
404
 * Creates a new list store as with @n_columns columns each of the types passed
Matthias Clasen's avatar
Matthias Clasen committed
405 406
 * in.  Note that only types derived from standard GObject fundamental types
 * are supported.
407
 *
408 409
 * As an example, `gtk_list_store_new (3, G_TYPE_INT, G_TYPE_STRING,
 * GDK_TYPE_PIXBUF);` will create a new #GtkListStore with three columns, of type
Matthias Clasen's avatar
Matthias Clasen committed
410
 * int, string and #GdkPixbuf respectively.
411
 *
412
 * Returns: a new #GtkListStore
Matthias Clasen's avatar
Matthias Clasen committed
413
 */
414
GtkListStore *
415
gtk_list_store_new (gint n_columns,
Soeren Sandmann's avatar
Soeren Sandmann committed
416
		    ...)
417
{
418
  GtkListStore *retval;
419 420 421 422 423
  va_list args;
  gint i;

  g_return_val_if_fail (n_columns > 0, NULL);

Manish Singh's avatar
Manish Singh committed
424
  retval = g_object_new (GTK_TYPE_LIST_STORE, NULL);
425
  gtk_list_store_set_n_columns (retval, n_columns);
426 427

  va_start (args, n_columns);
428

429
  for (i = 0; i < n_columns; i++)
430 431 432
    {
      GType type = va_arg (args, GType);
      if (! _gtk_tree_data_list_check_type (type))
433
        {
434
          g_warning ("%s: Invalid type %s", G_STRLOC, g_type_name (type));
435 436 437 438 439
          g_object_unref (retval);
          va_end (args);

          return NULL;
        }
440 441 442

      gtk_list_store_set_column_type (retval, i, type);
    }
443 444 445 446 447 448

  va_end (args);

  return retval;
}

449 450

/**
Jasper St. Pierre's avatar
Jasper St. Pierre committed
451
 * gtk_list_store_newv: (rename-to gtk_list_store_new)
452
 * @n_columns: number of columns in the list store
453
 * @types: (array length=n_columns): an array of #GType types for the columns, from first to last
454
 *
Matthias Clasen's avatar
Matthias Clasen committed
455
 * Non-vararg creation function.  Used primarily by language bindings.
456
 *
457
 * Returns: (transfer full): a new #GtkListStore
458 459 460 461 462 463 464 465 466 467
 **/
GtkListStore *
gtk_list_store_newv (gint   n_columns,
		     GType *types)
{
  GtkListStore *retval;
  gint i;

  g_return_val_if_fail (n_columns > 0, NULL);

Manish Singh's avatar
Manish Singh committed
468
  retval = g_object_new (GTK_TYPE_LIST_STORE, NULL);
469 470 471 472 473 474
  gtk_list_store_set_n_columns (retval, n_columns);

  for (i = 0; i < n_columns; i++)
    {
      if (! _gtk_tree_data_list_check_type (types[i]))
	{
475
	  g_warning ("%s: Invalid type %s", G_STRLOC, g_type_name (types[i]));
Manish Singh's avatar
Manish Singh committed
476
	  g_object_unref (retval);
477 478 479 480 481 482 483 484 485
	  return NULL;
	}

      gtk_list_store_set_column_type (retval, i, types[i]);
    }

  return retval;
}

486 487 488 489
/**
 * gtk_list_store_set_column_types:
 * @list_store: A #GtkListStore
 * @n_columns: Number of columns for the list store
490 491
 * @types: (array length=n_columns): An array length n of #GTypes
 *
Matthias Clasen's avatar
Matthias Clasen committed
492 493 494
 * This function is meant primarily for #GObjects that inherit from #GtkListStore,
 * and should only be used when constructing a new #GtkListStore.  It will not
 * function after a row has been added, or a method on the #GtkTreeModel
495 496 497 498 499 500 501
 * interface is called.
 **/
void
gtk_list_store_set_column_types (GtkListStore *list_store,
				 gint          n_columns,
				 GType        *types)
{
502
  GtkListStorePrivate *priv;
503 504 505
  gint i;

  g_return_if_fail (GTK_IS_LIST_STORE (list_store));
506 507 508 509

  priv = list_store->priv;

  g_return_if_fail (priv->columns_dirty == 0);
510 511

  gtk_list_store_set_n_columns (list_store, n_columns);
512
  for (i = 0; i < n_columns; i++)
513 514 515
    {
      if (! _gtk_tree_data_list_check_type (types[i]))
	{
516
	  g_warning ("%s: Invalid type %s", G_STRLOC, g_type_name (types[i]));
517 518 519 520 521 522
	  continue;
	}
      gtk_list_store_set_column_type (list_store, i, types[i]);
    }
}

523
static void
524 525 526
gtk_list_store_set_n_columns (GtkListStore *list_store,
			      gint          n_columns)
{
527
  GtkListStorePrivate *priv = list_store->priv;
528
  int i;
529

530
  if (priv->n_columns == n_columns)
531 532
    return;

533 534 535 536
  priv->column_headers = g_renew (GType, priv->column_headers, n_columns);
  for (i = priv->n_columns; i < n_columns; i++)
    priv->column_headers[i] = G_TYPE_INVALID;
  priv->n_columns = n_columns;
537

538 539 540
  if (priv->sort_list)
    _gtk_tree_data_list_header_free (priv->sort_list);
  priv->sort_list = _gtk_tree_data_list_header_new (n_columns, priv->column_headers);
541 542
}

543
static void
544 545 546 547
gtk_list_store_set_column_type (GtkListStore *list_store,
				gint          column,
				GType         type)
{
548
  GtkListStorePrivate *priv = list_store->priv;
549

550 551
  if (!_gtk_tree_data_list_check_type (type))
    {
552
      g_warning ("%s: Invalid type %s", G_STRLOC, g_type_name (type));
553 554
      return;
    }
555

556
  priv->column_headers[column] = type;
557 558
}

559 560 561 562
static void
gtk_list_store_finalize (GObject *object)
{
  GtkListStore *list_store = GTK_LIST_STORE (object);
563
  GtkListStorePrivate *priv = list_store->priv;
564

565 566
  g_sequence_foreach (priv->seq,
		      (GFunc) _gtk_tree_data_list_free, priv->column_headers);
Soeren Sandmann's avatar
Soeren Sandmann committed
567

568
  g_sequence_free (priv->seq);
569

570 571 572 573
  _gtk_tree_data_list_header_free (priv->sort_list);
  g_free (priv->column_headers);

  if (priv->default_sort_destroy)
574
    {
575
      GDestroyNotify d = priv->default_sort_destroy;
576

577 578 579
      priv->default_sort_destroy = NULL;
      d (priv->default_sort_data);
      priv->default_sort_data = NULL;
580
    }
581

582
  G_OBJECT_CLASS (gtk_list_store_parent_class)->finalize (object);
583 584
}

585
/* Fulfill the GtkTreeModel requirements */
586
static GtkTreeModelFlags
587 588
gtk_list_store_get_flags (GtkTreeModel *tree_model)
{
589
  return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
590 591
}

592 593 594
static gint
gtk_list_store_get_n_columns (GtkTreeModel *tree_model)
{
595
  GtkListStore *list_store = GTK_LIST_STORE (tree_model);
596
  GtkListStorePrivate *priv = list_store->priv;
597

598
  priv->columns_dirty = TRUE;
599

600
  return priv->n_columns;
601 602
}

603 604 605 606
static GType
gtk_list_store_get_column_type (GtkTreeModel *tree_model,
				gint          index)
{
607
  GtkListStore *list_store = GTK_LIST_STORE (tree_model);
608
  GtkListStorePrivate *priv = list_store->priv;
609

610
  g_return_val_if_fail (index < priv->n_columns, G_TYPE_INVALID);
611

612
  priv->columns_dirty = TRUE;
613

614
  return priv->column_headers[index];
615 616
}

617
static gboolean
618
gtk_list_store_get_iter (GtkTreeModel *tree_model,
619
			 GtkTreeIter  *iter,
620 621
			 GtkTreePath  *path)
{
622
  GtkListStore *list_store = GTK_LIST_STORE (tree_model);
623
  GtkListStorePrivate *priv = list_store->priv;
624
  GSequence *seq;
625
  gint i;
626

627 628 629
  priv->columns_dirty = TRUE;

  seq = priv->seq;
630

631
  i = gtk_tree_path_get_indices (path)[0];
632

633
  if (i >= g_sequence_get_length (seq))
634 635 636 637
    {
      iter->stamp = 0;
      return FALSE;
    }
638

639
  iter->stamp = priv->stamp;
640
  iter->user_data = g_sequence_get_iter_at_pos (seq, i);
641

642
  return TRUE;
643 644 645 646
}

static GtkTreePath *
gtk_list_store_get_path (GtkTreeModel *tree_model,
647
			 GtkTreeIter  *iter)
648
{
649
  GtkListStore *list_store = GTK_LIST_STORE (tree_model);
650
  GtkListStorePrivate *priv = list_store->priv;
Soeren Sandmann's avatar
Soeren Sandmann committed
651
  GtkTreePath *path;
652

653
  g_return_val_if_fail (iter->stamp == priv->stamp, NULL);
654

655
  if (g_sequence_iter_is_end (iter->user_data))
656
    return NULL;
Soeren Sandmann's avatar
Soeren Sandmann committed
657 658
	
  path = gtk_tree_path_new ();
659
  gtk_tree_path_append_index (path, g_sequence_iter_get_position (iter->user_data));
Soeren Sandmann's avatar
Soeren Sandmann committed
660 661
  
  return path;
662 663 664
}

static void
665 666 667 668
gtk_list_store_get_value (GtkTreeModel *tree_model,
			  GtkTreeIter  *iter,
			  gint          column,
			  GValue       *value)
669
{
670
  GtkListStore *list_store = GTK_LIST_STORE (tree_model);
671
  GtkListStorePrivate *priv = list_store->priv;
672 673 674
  GtkTreeDataList *list;
  gint tmp_column = column;

675
  g_return_if_fail (column < priv->n_columns);
676
  g_return_if_fail (iter_is_valid (iter, list_store));
Soeren Sandmann's avatar
Soeren Sandmann committed
677
		    
678
  list = g_sequence_get (iter->user_data);
679 680 681 682

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

683
  if (list == NULL)
684
    g_value_init (value, priv->column_headers[column]);
685 686
  else
    _gtk_tree_data_list_node_to_value (list,
687
				       priv->column_headers[column],
688
				       value);
689 690 691
}

static gboolean
692 693
gtk_list_store_iter_next (GtkTreeModel  *tree_model,
			  GtkTreeIter   *iter)
694
{
695
  GtkListStore *list_store = GTK_LIST_STORE (tree_model);
696
  GtkListStorePrivate *priv = list_store->priv;
697 698
  gboolean retval;

699
  g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);
700
  iter->user_data = g_sequence_iter_next (iter->user_data);
701

702 703 704 705 706
  retval = g_sequence_iter_is_end (iter->user_data);
  if (retval)
    iter->stamp = 0;

  return !retval;
707 708
}

709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
static gboolean
gtk_list_store_iter_previous (GtkTreeModel *tree_model,
                              GtkTreeIter  *iter)
{
  GtkListStore *list_store = GTK_LIST_STORE (tree_model);
  GtkListStorePrivate *priv = list_store->priv;

  g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);

  if (g_sequence_iter_is_begin (iter->user_data))
    {
      iter->stamp = 0;
      return FALSE;
    }

  iter->user_data = g_sequence_iter_prev (iter->user_data);

  return TRUE;
}

729
static gboolean
730
gtk_list_store_iter_children (GtkTreeModel *tree_model,
731 732
			      GtkTreeIter  *iter,
			      GtkTreeIter  *parent)
733
{
734
  GtkListStore *list_store = (GtkListStore *) tree_model;
735
  GtkListStorePrivate *priv = list_store->priv;
736

737
  /* this is a list, nodes have no children */
738
  if (parent)
739 740 741 742
    {
      iter->stamp = 0;
      return FALSE;
    }
743

744
  if (g_sequence_get_length (priv->seq) > 0)
745
    {
746 747
      iter->stamp = priv->stamp;
      iter->user_data = g_sequence_get_begin_iter (priv->seq);
748 749
      return TRUE;
    }
750
  else
751 752 753 754
    {
      iter->stamp = 0;
      return FALSE;
    }
755 756 757
}

static gboolean
758
gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
759
			       GtkTreeIter  *iter)
760 761 762 763 764
{
  return FALSE;
}

static gint
765
gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
766
				GtkTreeIter  *iter)
767
{
768
  GtkListStore *list_store = GTK_LIST_STORE (tree_model);
769
  GtkListStorePrivate *priv = list_store->priv;
Soeren Sandmann's avatar
Soeren Sandmann committed
770

771
  if (iter == NULL)
772
    return g_sequence_get_length (priv->seq);
773

774
  g_return_val_if_fail (priv->stamp == iter->stamp, -1);
775 776

  return 0;
777 778
}

779
static gboolean
780
gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
781 782
			       GtkTreeIter  *iter,
			       GtkTreeIter  *parent,
783
			       gint          n)
784
{
785
  GtkListStore *list_store = GTK_LIST_STORE (tree_model);
786
  GtkListStorePrivate *priv = list_store->priv;
787
  GSequenceIter *child;
788

789 790
  iter->stamp = 0;

791
  if (parent)
792
    return FALSE;
793

794
  child = g_sequence_get_iter_at_pos (priv->seq, n);
795

796
  if (g_sequence_iter_is_end (child))
797
    return FALSE;
Soeren Sandmann's avatar
Soeren Sandmann committed
798

799
  iter->stamp = priv->stamp;
Soeren Sandmann's avatar
Soeren Sandmann committed
800
  iter->user_data = child;
801

Soeren Sandmann's avatar
Soeren Sandmann committed
802
  return TRUE;
803 804
}

805 806 807 808
static gboolean
gtk_list_store_iter_parent (GtkTreeModel *tree_model,
			    GtkTreeIter  *iter,
			    GtkTreeIter  *child)
809
{
810
  iter->stamp = 0;
811
  return FALSE;
812 813
}

814
static gboolean
815 816 817
gtk_list_store_real_set_value (GtkListStore *list_store,
			       GtkTreeIter  *iter,
			       gint          column,
818 819
			       GValue       *value,
			       gboolean      sort)
820
{
821
  GtkListStorePrivate *priv = list_store->priv;
822 823
  GtkTreeDataList *list;
  GtkTreeDataList *prev;
824
  gint old_column = column;
Javier Jardón's avatar
Javier Jardón committed
825
  GValue real_value = G_VALUE_INIT;
826
  gboolean converted = FALSE;
827
  gboolean retval = FALSE;
828

829
  if (! g_type_is_a (G_VALUE_TYPE (value), priv->column_headers[column]))
830
    {
831
      if (! (g_value_type_transformable (G_VALUE_TYPE (value), priv->column_headers[column])))
832
	{
833
	  g_warning ("%s: Unable to convert from %s to %s",
834 835
		     G_STRLOC,
		     g_type_name (G_VALUE_TYPE (value)),
836
		     g_type_name (priv->column_headers[column]));
837
	  return retval;
838
	}
839 840

      g_value_init (&real_value, priv->column_headers[column]);
841 842
      if (!g_value_transform (value, &real_value))
	{
843
	  g_warning ("%s: Unable to make conversion from %s to %s",
844 845
		     G_STRLOC,
		     g_type_name (G_VALUE_TYPE (value)),
846
		     g_type_name (priv->column_headers[column]));
847
	  g_value_unset (&real_value);
848
	  return retval;
849 850 851
	}
      converted = TRUE;
    }
852

853
  prev = list = g_sequence_get (iter->user_data);
854 855 856 857 858

  while (list != NULL)
    {
      if (column == 0)
	{
859 860 861 862
	  if (converted)
	    _gtk_tree_data_list_value_to_node (list, &real_value);
	  else
	    _gtk_tree_data_list_value_to_node (list, value);
863
	  retval = TRUE;
864 865
	  if (converted)
	    g_value_unset (&real_value);
866 867
         if (sort && GTK_LIST_STORE_IS_SORTED (list_store))
            gtk_list_store_sort_iter_changed (list_store, iter, old_column);
868
	  return retval;
869 870 871 872 873 874 875
	}

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

876
  if (g_sequence_get (iter->user_data) == NULL)
877
    {
Soeren Sandmann's avatar
Soeren Sandmann committed
878
      list = _gtk_tree_data_list_alloc();
879
      g_sequence_set (iter->user_data, list);
880 881 882 883
      list->next = NULL;
    }
  else
    {
884
      list = prev->next = _gtk_tree_data_list_alloc ();
885 886 887 888 889
      list->next = NULL;
    }

  while (column != 0)
    {
890
      list->next = _gtk_tree_data_list_alloc ();
891 892 893 894
      list = list->next;
      list->next = NULL;
      column --;
    }
895

896
  if (converted)
897
    _gtk_tree_data_list_value_to_node (list, &real_value);
898 899
  else
    _gtk_tree_data_list_value_to_node (list, value);
900

901
  retval = TRUE;
902 903
  if (converted)
    g_value_unset (&real_value);
904

905
  if (sort && GTK_LIST_STORE_IS_SORTED (list_store))
906
    gtk_list_store_sort_iter_changed (list_store, iter, old_column);
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929

  return retval;
}


/**
 * gtk_list_store_set_value:
 * @list_store: A #GtkListStore
 * @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_list_store_set_value (GtkListStore *list_store,
			  GtkTreeIter  *iter,
			  gint          column,
			  GValue       *value)
{
930
  GtkListStorePrivate *priv;
931

932
  g_return_if_fail (GTK_IS_LIST_STORE (list_store));
933
  g_return_if_fail (iter_is_valid (iter, list_store));
934
  g_return_if_fail (G_IS_VALUE (value));
935 936
  priv = list_store->priv;
  g_return_if_fail (column >= 0 && column < priv->n_columns);
937

938
  if (gtk_list_store_real_set_value (list_store, iter, column, value, TRUE))
939 940 941
    {
      GtkTreePath *path;

942
      path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
943 944 945
      gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
      gtk_tree_path_free (path);
    }
946 947
}

948 949
static GtkTreeIterCompareFunc
gtk_list_store_get_compare_func (GtkListStore *list_store)
Havoc Pennington's avatar
Havoc Pennington committed
950
{
951
  GtkListStorePrivate *priv = list_store->priv;
952
  GtkTreeIterCompareFunc func = NULL;
Havoc Pennington's avatar
Havoc Pennington committed
953

954
  if (GTK_LIST_STORE_IS_SORTED (list_store))
955
    {
956
      if (priv->sort_column_id != -1)
957 958
	{
	  GtkTreeDataSortHeader *header;
959 960
	  header = _gtk_tree_data_list_get_header (priv->sort_list,
						   priv->sort_column_id);
961 962
	  g_return_val_if_fail (header != NULL, NULL);
	  g_return_val_if_fail (header->func != NULL, NULL);
963 964 965 966
	  func = header->func;
	}
      else
	{
967
	  func = priv->default_sort_func;
968
	}
969 970
    }

971 972 973
  return func;
}

974 975 976 977 978 979 980 981 982
static void
gtk_list_store_set_vector_internal (GtkListStore *list_store,
				    GtkTreeIter  *iter,
				    gboolean     *emit_signal,
				    gboolean     *maybe_need_sort,
				    gint         *columns,
				    GValue       *values,
				    gint          n_values)
{
983
  GtkListStorePrivate *priv = list_store->priv;
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
  gint i;
  GtkTreeIterCompareFunc func = NULL;

  func = gtk_list_store_get_compare_func (list_store);
  if (func != _gtk_tree_data_list_compare_func)
    *maybe_need_sort = TRUE;

  for (i = 0; i < n_values; i++)
    {
      *emit_signal = gtk_list_store_real_set_value (list_store, 
					       iter, 
					       columns[i],
					       &values[i],
					       FALSE) || *emit_signal;

      if (func == _gtk_tree_data_list_compare_func &&
1000
	  columns[i] == priv->sort_column_id)
1001 1002 1003 1004
	*maybe_need_sort = TRUE;
    }
}

1005 1006 1007 1008 1009 1010 1011
static void
gtk_list_store_set_valist_internal (GtkListStore *list_store,
				    GtkTreeIter  *iter,
				    gboolean     *emit_signal,
				    gboolean     *maybe_need_sort,
				    va_list	  var_args)
{
1012
  GtkListStorePrivate *priv = list_store->priv;
1013 1014 1015 1016 1017 1018
  gint column;
  GtkTreeIterCompareFunc func = NULL;

  column = va_arg (var_args, gint);

  func = gtk_list_store_get_compare_func (list_store);
1019
  if (func != _gtk_tree_data_list_compare_func)
1020
    *maybe_need_sort = TRUE;
1021

Havoc Pennington's avatar
Havoc Pennington committed
1022 1023
  while (column != -1)
    {
Javier Jardón's avatar
Javier Jardón committed
1024
      GValue value = G_VALUE_INIT;
Havoc Pennington's avatar
Havoc Pennington committed
1025 1026
      gchar *error = NULL;

1027
      if (column < 0 || column >= priv->n_columns)
Havoc Pennington's avatar
Havoc Pennington committed
1028 1029 1030 1031 1032
	{
	  g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
	  break;
	}

1033 1034
      G_VALUE_COLLECT_INIT (&value, priv->column_headers[column],
                            var_args, 0, &error);
Havoc Pennington's avatar
Havoc Pennington committed
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
      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
1046
      /* FIXME: instead of calling this n times, refactor with above */
1047 1048 1049 1050 1051 1052
      *emit_signal = gtk_list_store_real_set_value (list_store,
						    iter,
						    column,
						    &value,
						    FALSE) || *emit_signal;
      
1053
      if (func == _gtk_tree_data_list_compare_func &&
1054
	  column == priv->sort_column_id)
1055
	*maybe_need_sort = TRUE;
Havoc Pennington's avatar
Havoc Pennington committed
1056 1057 1058 1059 1060

      g_value_unset (&value);

      column = va_arg (var_args, gint);
    }
1061 1062
}

1063
/**
Jasper St. Pierre's avatar
Jasper St. Pierre committed
1064
 * gtk_list_store_set_valuesv: (rename-to gtk_list_store_set)
1065 1066
 * @list_store: A #GtkListStore
 * @iter: A valid #GtkTreeIter for the row being modified
1067 1068
 * @columns: (array length=n_values): an array of column numbers
 * @values: (array length=n_values): an array of GValues
1069
 * @n_values: the length of the @columns and @values arrays
1070
 *
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
 * A variant of gtk_list_store_set_valist() which
 * takes the columns and values as two arrays, instead of
 * varargs. This function is mainly intended for 
 * language-bindings and in case the number of columns to
 * change is not known until run-time.
 *
 * Since: 2.12
 */
void
gtk_list_store_set_valuesv (GtkListStore *list_store,
			    GtkTreeIter  *iter,
			    gint         *columns,
			    GValue       *values,
			    gint          n_values)
{
1086
  GtkListStorePrivate *priv;
1087 1088 1089 1090
  gboolean emit_signal = FALSE;
  gboolean maybe_need_sort = FALSE;

  g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1091
  g_return_if_fail (iter_is_valid (iter, list_store));
1092

1093 1094
  priv = list_store->priv;

1095 1096 1097 1098 1099 1100
  gtk_list_store_set_vector_internal (list_store, iter,
				      &emit_signal,
				      &maybe_need_sort,
				      columns, values, n_values);

  if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
1101
    gtk_list_store_sort_iter_changed (list_store, iter, priv->sort_column_id);
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112

  if (emit_signal)
    {
      GtkTreePath *path;

      path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
      gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
      gtk_tree_path_free (path);
    }
}

1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
/**
 * gtk_list_store_set_valist:
 * @list_store: A #GtkListStore
 * @iter: A valid #GtkTreeIter for the row being modified
 * @var_args: va_list of column/value pairs
 *
 * See gtk_list_store_set(); this version takes a va_list for use by language
 * bindings.
 *
 **/
void
gtk_list_store_set_valist (GtkListStore *list_store,
                           GtkTreeIter  *iter,
                           va_list	 var_args)
{
1128
  GtkListStorePrivate *priv;
1129 1130 1131 1132
  gboolean emit_signal = FALSE;
  gboolean maybe_need_sort = FALSE;

  g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1133
  g_return_if_fail (iter_is_valid (iter, list_store));
1134

1135 1136
  priv = list_store->priv;

1137 1138 1139 1140
  gtk_list_store_set_valist_internal (list_store, iter, 
				      &emit_signal, 
				      &maybe_need_sort,
				      var_args);
1141

1142
  if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
1143
    gtk_list_store_sort_iter_changed (list_store, iter, priv->sort_column_id);
1144

1145 1146 1147 1148
  if (emit_signal)
    {
      GtkTreePath *path;

1149
      path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
1150 1151 1152
      gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
      gtk_tree_path_free (path);
    }
Havoc Pennington's avatar
Havoc Pennington committed
1153 1154 1155 1156 1157 1158
}

/**
 * gtk_list_store_set:
 * @list_store: a #GtkListStore
 * @iter: row iterator
Matthias Clasen's avatar
Matthias Clasen committed
1159
 * @...: pairs of column number and value, terminated with -1
1160
 *
Havoc Pennington's avatar
Havoc Pennington committed
1161 1162
 * Sets the value of one or more cells in the row referenced by @iter.
 * The variable argument list should contain integer column numbers,
1163
 * each column number followed by the value to be set.
Havoc Pennington's avatar
Havoc Pennington committed
1164
 * The list is terminated by a -1. For example, to set column 0 with type
1165
 * %G_TYPE_STRING to “Foo”, you would write `gtk_list_store_set (store, iter,
1166
 * 0, "Foo", -1)`.
1167 1168 1169
 *
 * The value will be referenced by the store if it is a %G_TYPE_OBJECT, and it
 * will be copied if it is a %G_TYPE_STRING or %G_TYPE_BOXED.
Matthias Clasen's avatar
Matthias Clasen committed
1170
 */
Havoc Pennington's avatar
Havoc Pennington committed
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
void
gtk_list_store_set (GtkListStore *list_store,
		    GtkTreeIter  *iter,
		    ...)
{
  va_list var_args;

  va_start (var_args, iter);
  gtk_list_store_set_valist (list_store, iter, var_args);
  va_end (var_args);
}

1183 1184
/**
 * gtk_list_store_remove:
1185 1186
 * @list_store: A #GtkListStore
 * @iter: A valid #GtkTreeIter
1187
 *
Matthias Clasen's avatar
Matthias Clasen committed
1188 1189 1190
 * Removes the given row from the list store.  After being removed, 
 * @iter is set to be the next valid row, or invalidated if it pointed 
 * to the last row in @list_store.
1191
 *
1192
 * Returns: %TRUE if @iter is valid, %FALSE if not.
1193
 **/
Kristian Rietveld's avatar
Kristian Rietveld committed
1194
gboolean
1195 1196 1197
gtk_list_store_remove (GtkListStore *list_store,
		       GtkTreeIter  *iter)
{
1198
  GtkListStorePrivate *priv;
1199
  GtkTreePath *path;
1200
  GSequenceIter *ptr, *next;
1201

Kristian Rietveld's avatar
Kristian Rietveld committed
1202
  g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
1203
  g_return_val_if_fail (iter_is_valid (iter, list_store), FALSE);
1204

1205 1206
  priv = list_store->priv;

1207 1208
  path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);

Soeren Sandmann's avatar
Soeren Sandmann committed
1209
  ptr = iter->user_data;
1210
  next = g_sequence_iter_next (ptr);
Soeren Sandmann's avatar
Soeren Sandmann committed
1211
  
1212
  _gtk_tree_data_list_free (g_sequence_get (ptr), priv->column_headers);
1213
  g_sequence_remove (iter->user_data);
1214

1215
  priv->length--;
Soeren Sandmann's avatar
Soeren Sandmann committed
1216
  
1217
  gtk_tree_model_row_deleted (GTK_TREE_MODEL (list_store), path);
1218
  gtk_tree_path_free (path);
1219

1220
  if (g_sequence_iter_is_end (next))
1221
    {
Soeren Sandmann's avatar
Soeren Sandmann committed
1222 1223
      iter->stamp = 0;
      return FALSE;
1224 1225 1226
    }
  else
    {
1227
      iter->stamp = priv->stamp;
Soeren Sandmann's avatar
Soeren Sandmann committed
1228 1229
      iter->user_data = next;
      return TRUE;
1230
    }
1231 1232
}

1233 1234
/**
 * gtk_list_store_insert:
1235
 * @list_store: A #GtkListStore
1236
 * @iter: (out): An unset #GtkTreeIter to set to the new row
1237
 * @position: position to insert the new row, or -1 for last
1238
 *
1239
 * Creates a new row at @position.  @iter will be changed to point to this new
1240 1241 1242
 * row.  If @position is -1 or is larger than the number of rows on the list,
 * then the new row will be appended to the list. The row will be empty after
 * this function is called.  To fill in values, you need to call
1243
 * gtk_list_store_set() or gtk_list_store_set_value().
1244
 *
1245
 **/
Jonathan Blandford's avatar