]> Pileus Git - ~andy/gtk/blob - gtk/gtkliststore.c
Updated Russian translation
[~andy/gtk] / gtk / gtkliststore.c
1 /* gtkliststore.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19 #include <errno.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <gobject/gvaluecollector.h>
23 #include "gtktreemodel.h"
24 #include "gtkliststore.h"
25 #include "gtktreedatalist.h"
26 #include "gtktreednd.h"
27 #include "gtkintl.h"
28 #include "gtkbuildable.h"
29 #include "gtkbuilderprivate.h"
30
31
32 /**
33  * SECTION:gtkliststore
34  * @Short_description: A list-like data structure that can be used with the GtkTreeView
35  * @Title: GtkListStore
36  * @See_also:#GtkTreeModel, #GtkTreeStore
37  *
38  * The #GtkListStore object is a list model for use with a #GtkTreeView
39  * widget.  It implements the #GtkTreeModel interface, and consequentialy,
40  * can use all of the methods available there.  It also implements the
41  * #GtkTreeSortable interface so it can be sorted by the view.
42  * Finally, it also implements the tree <link linkend="gtktreednd">drag and
43  * drop</link> interfaces.
44  *
45  * The #GtkListStore can accept most GObject types as a column type, though
46  * it can't accept all custom types.  Internally, it will keep a copy of
47  * data passed in (such as a string or a boxed pointer).  Columns that
48  * accept #GObject<!-- -->s are handled a little differently.  The
49  * #GtkListStore will keep a reference to the object instead of copying the
50  * value.  As a result, if the object is modified, it is up to the
51  * application writer to call gtk_tree_model_row_changed() to emit the
52  * #GtkTreeModel::row_changed signal.  This most commonly affects lists with
53  * #GdkPixbuf<!-- -->s stored.
54  *
55  * <example>
56  * <title>Creating a simple list store.</title>
57  * <programlisting>
58  * enum {
59  *   COLUMN_STRING,
60  *   COLUMN_INT,
61  *   COLUMN_BOOLEAN,
62  *   N_COLUMNS
63  * };
64  *
65  * {
66  *   GtkListStore *list_store;
67  *   GtkTreePath *path;
68  *   GtkTreeIter iter;
69  *   gint i;
70  *
71  *   list_store = gtk_list_store_new (N_COLUMNS,
72  *                                    G_TYPE_STRING,
73  *                                    G_TYPE_INT,
74  *                                    G_TYPE_BOOLEAN);
75  *
76  *   for (i = 0; i < 10; i++)
77  *     {
78  *       gchar *some_data;
79  *
80  *       some_data = get_some_data (i);
81  *
82  *       // Add a new row to the model
83  *       gtk_list_store_append (list_store, &iter);
84  *       gtk_list_store_set (list_store, &iter,
85  *                           COLUMN_STRING, some_data,
86  *                           COLUMN_INT, i,
87  *                           COLUMN_BOOLEAN,  FALSE,
88  *                           -1);
89  *
90  *       /<!---->* As the store will keep a copy of the string internally, we
91  *        * free some_data.
92  *        *<!---->/
93  *       g_free (some_data);
94  *     }
95  *
96  *   // Modify a particular row
97  *   path = gtk_tree_path_new_from_string ("4");
98  *   gtk_tree_model_get_iter (GTK_TREE_MODEL (list_store),
99  *                            &iter,
100  *                            path);
101  *   gtk_tree_path_free (path);
102  *   gtk_list_store_set (list_store, &iter,
103  *                       COLUMN_BOOLEAN, TRUE,
104  *                       -1);
105  * }
106  * </programlisting>
107  * </example>
108  *
109  * <refsect2>
110  * <title>Performance Considerations</title>
111  * Internally, the #GtkListStore was implemented with a linked list with a
112  * tail pointer prior to GTK+ 2.6.  As a result, it was fast at data
113  * insertion and deletion, and not fast at random data access.  The
114  * #GtkListStore sets the #GTK_TREE_MODEL_ITERS_PERSIST flag, which means
115  * that #GtkTreeIter<!-- -->s can be cached while the row exists.  Thus, if
116  * access to a particular row is needed often and your code is expected to
117  * run on older versions of GTK+, it is worth keeping the iter around.
118  * </refsect2>
119  * <refsect2>
120  * <title>Atomic Operations</title>
121  * It is important to note that only the methods
122  * gtk_list_store_insert_with_values() and gtk_list_store_insert_with_valuesv()
123  * are atomic, in the sense that the row is being appended to the store and the
124  * values filled in in a single operation with regard to #GtkTreeModel signaling.
125  * In contrast, using e.g. gtk_list_store_append() and then gtk_list_store_set()
126  * will first create a row, which triggers the #GtkTreeModel::row-inserted signal
127  * on #GtkListStore. The row, however, is still empty, and any signal handler
128  * connecting to #GtkTreeModel::row-inserted on this particular store should be prepared
129  * for the situation that the row might be empty. This is especially important
130  * if you are wrapping the #GtkListStore inside a #GtkTreeModelFilter and are
131  * using a #GtkTreeModelFilterVisibleFunc. Using any of the non-atomic operations
132  * to append rows to the #GtkListStore will cause the
133  * #GtkTreeModelFilterVisibleFunc to be visited with an empty row first; the
134  * function must be prepared for that.
135  * </refsect2>
136  * <refsect2 id="GtkListStore-BUILDER-UI">
137  * <title>GtkListStore as GtkBuildable</title>
138  * <para>
139  * The GtkListStore implementation of the GtkBuildable interface allows
140  * to specify the model columns with a &lt;columns&gt; element that may
141  * contain multiple &lt;column&gt; elements, each specifying one model
142  * column. The "type" attribute specifies the data type for the column.
143  *
144  * Additionally, it is possible to specify content for the list store
145  * in the UI definition, with the &lt;data&gt; element. It can contain
146  * multiple &lt;row&gt; elements, each specifying to content for one
147  * row of the list model. Inside a &lt;row&gt;, the &lt;col&gt; elements
148  * specify the content for individual cells.
149  *
150  * Note that it is probably more common to define your models
151  * in the code, and one might consider it a layering violation
152  * to specify the content of a list store in a UI definition,
153  * <emphasis>data</emphasis>, not <emphasis>presentation</emphasis>,
154  * and common wisdom is to separate the two, as far as possible.
155  * <!-- FIXME a bit inconclusive -->
156  *
157  * <example>
158  * <title>A UI Definition fragment for a list store</title>
159  * <programlisting><![CDATA[
160  * <object class="GtkListStore">
161  *   <columns>
162  *     <column type="gchararray"/>
163  *     <column type="gchararray"/>
164  *     <column type="gint"/>
165  *   </columns>
166  *   <data>
167  *     <row>
168  *       <col id="0">John</col>
169  *       <col id="1">Doe</col>
170  *       <col id="2">25</col>
171  *     </row>
172  *     <row>
173  *       <col id="0">Johan</col>
174  *       <col id="1">Dahlin</col>
175  *       <col id="2">50</col>
176  *     </row>
177  *   </data>
178  * </object>
179  * ]]></programlisting>
180  * </example>
181  * </para>
182  * </refsect2>
183  */
184
185
186 struct _GtkListStorePrivate
187 {
188   GtkTreeIterCompareFunc default_sort_func;
189
190   GDestroyNotify default_sort_destroy;
191   GList *sort_list;
192   GType *column_headers;
193
194   gint stamp;
195   gint n_columns;
196   gint sort_column_id;
197   gint length;
198
199   GtkSortType order;
200
201   guint columns_dirty : 1;
202
203   gpointer default_sort_data;
204   gpointer seq;         /* head of the list */
205 };
206
207 #define GTK_LIST_STORE_IS_SORTED(list) (((GtkListStore*)(list))->priv->sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
208 static void         gtk_list_store_tree_model_init (GtkTreeModelIface *iface);
209 static void         gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface);
210 static void         gtk_list_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
211 static void         gtk_list_store_sortable_init   (GtkTreeSortableIface   *iface);
212 static void         gtk_list_store_buildable_init  (GtkBuildableIface      *iface);
213 static void         gtk_list_store_finalize        (GObject           *object);
214 static GtkTreeModelFlags gtk_list_store_get_flags  (GtkTreeModel      *tree_model);
215 static gint         gtk_list_store_get_n_columns   (GtkTreeModel      *tree_model);
216 static GType        gtk_list_store_get_column_type (GtkTreeModel      *tree_model,
217                                                     gint               index);
218 static gboolean     gtk_list_store_get_iter        (GtkTreeModel      *tree_model,
219                                                     GtkTreeIter       *iter,
220                                                     GtkTreePath       *path);
221 static GtkTreePath *gtk_list_store_get_path        (GtkTreeModel      *tree_model,
222                                                     GtkTreeIter       *iter);
223 static void         gtk_list_store_get_value       (GtkTreeModel      *tree_model,
224                                                     GtkTreeIter       *iter,
225                                                     gint               column,
226                                                     GValue            *value);
227 static gboolean     gtk_list_store_iter_next       (GtkTreeModel      *tree_model,
228                                                     GtkTreeIter       *iter);
229 static gboolean     gtk_list_store_iter_previous   (GtkTreeModel      *tree_model,
230                                                     GtkTreeIter       *iter);
231 static gboolean     gtk_list_store_iter_children   (GtkTreeModel      *tree_model,
232                                                     GtkTreeIter       *iter,
233                                                     GtkTreeIter       *parent);
234 static gboolean     gtk_list_store_iter_has_child  (GtkTreeModel      *tree_model,
235                                                     GtkTreeIter       *iter);
236 static gint         gtk_list_store_iter_n_children (GtkTreeModel      *tree_model,
237                                                     GtkTreeIter       *iter);
238 static gboolean     gtk_list_store_iter_nth_child  (GtkTreeModel      *tree_model,
239                                                     GtkTreeIter       *iter,
240                                                     GtkTreeIter       *parent,
241                                                     gint               n);
242 static gboolean     gtk_list_store_iter_parent     (GtkTreeModel      *tree_model,
243                                                     GtkTreeIter       *iter,
244                                                     GtkTreeIter       *child);
245
246
247 static void gtk_list_store_set_n_columns   (GtkListStore *list_store,
248                                             gint          n_columns);
249 static void gtk_list_store_set_column_type (GtkListStore *list_store,
250                                             gint          column,
251                                             GType         type);
252
253 static void gtk_list_store_increment_stamp (GtkListStore *list_store);
254
255
256 /* Drag and Drop */
257 static gboolean real_gtk_list_store_row_draggable (GtkTreeDragSource *drag_source,
258                                                    GtkTreePath       *path);
259 static gboolean gtk_list_store_drag_data_delete   (GtkTreeDragSource *drag_source,
260                                                    GtkTreePath       *path);
261 static gboolean gtk_list_store_drag_data_get      (GtkTreeDragSource *drag_source,
262                                                    GtkTreePath       *path,
263                                                    GtkSelectionData  *selection_data);
264 static gboolean gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
265                                                    GtkTreePath       *dest,
266                                                    GtkSelectionData  *selection_data);
267 static gboolean gtk_list_store_row_drop_possible  (GtkTreeDragDest   *drag_dest,
268                                                    GtkTreePath       *dest_path,
269                                                    GtkSelectionData  *selection_data);
270
271
272 /* sortable */
273 static void     gtk_list_store_sort                  (GtkListStore           *list_store);
274 static void     gtk_list_store_sort_iter_changed     (GtkListStore           *list_store,
275                                                       GtkTreeIter            *iter,
276                                                       gint                    column);
277 static gboolean gtk_list_store_get_sort_column_id    (GtkTreeSortable        *sortable,
278                                                       gint                   *sort_column_id,
279                                                       GtkSortType            *order);
280 static void     gtk_list_store_set_sort_column_id    (GtkTreeSortable        *sortable,
281                                                       gint                    sort_column_id,
282                                                       GtkSortType             order);
283 static void     gtk_list_store_set_sort_func         (GtkTreeSortable        *sortable,
284                                                       gint                    sort_column_id,
285                                                       GtkTreeIterCompareFunc  func,
286                                                       gpointer                data,
287                                                       GDestroyNotify          destroy);
288 static void     gtk_list_store_set_default_sort_func (GtkTreeSortable        *sortable,
289                                                       GtkTreeIterCompareFunc  func,
290                                                       gpointer                data,
291                                                       GDestroyNotify          destroy);
292 static gboolean gtk_list_store_has_default_sort_func (GtkTreeSortable        *sortable);
293
294
295 /* buildable */
296 static gboolean gtk_list_store_buildable_custom_tag_start (GtkBuildable  *buildable,
297                                                            GtkBuilder    *builder,
298                                                            GObject       *child,
299                                                            const gchar   *tagname,
300                                                            GMarkupParser *parser,
301                                                            gpointer      *data);
302 static void     gtk_list_store_buildable_custom_tag_end (GtkBuildable *buildable,
303                                                          GtkBuilder   *builder,
304                                                          GObject      *child,
305                                                          const gchar  *tagname,
306                                                          gpointer     *data);
307
308 G_DEFINE_TYPE_WITH_CODE (GtkListStore, gtk_list_store, G_TYPE_OBJECT,
309                          G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
310                                                 gtk_list_store_tree_model_init)
311                          G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
312                                                 gtk_list_store_drag_source_init)
313                          G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
314                                                 gtk_list_store_drag_dest_init)
315                          G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
316                                                 gtk_list_store_sortable_init)
317                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
318                                                 gtk_list_store_buildable_init))
319
320
321 static void
322 gtk_list_store_class_init (GtkListStoreClass *class)
323 {
324   GObjectClass *object_class;
325
326   object_class = (GObjectClass*) class;
327
328   object_class->finalize = gtk_list_store_finalize;
329
330   g_type_class_add_private (class, sizeof (GtkListStorePrivate));
331 }
332
333 static void
334 gtk_list_store_tree_model_init (GtkTreeModelIface *iface)
335 {
336   iface->get_flags = gtk_list_store_get_flags;
337   iface->get_n_columns = gtk_list_store_get_n_columns;
338   iface->get_column_type = gtk_list_store_get_column_type;
339   iface->get_iter = gtk_list_store_get_iter;
340   iface->get_path = gtk_list_store_get_path;
341   iface->get_value = gtk_list_store_get_value;
342   iface->iter_next = gtk_list_store_iter_next;
343   iface->iter_previous = gtk_list_store_iter_previous;
344   iface->iter_children = gtk_list_store_iter_children;
345   iface->iter_has_child = gtk_list_store_iter_has_child;
346   iface->iter_n_children = gtk_list_store_iter_n_children;
347   iface->iter_nth_child = gtk_list_store_iter_nth_child;
348   iface->iter_parent = gtk_list_store_iter_parent;
349 }
350
351 static void
352 gtk_list_store_drag_source_init (GtkTreeDragSourceIface *iface)
353 {
354   iface->row_draggable = real_gtk_list_store_row_draggable;
355   iface->drag_data_delete = gtk_list_store_drag_data_delete;
356   iface->drag_data_get = gtk_list_store_drag_data_get;
357 }
358
359 static void
360 gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface)
361 {
362   iface->drag_data_received = gtk_list_store_drag_data_received;
363   iface->row_drop_possible = gtk_list_store_row_drop_possible;
364 }
365
366 static void
367 gtk_list_store_sortable_init (GtkTreeSortableIface *iface)
368 {
369   iface->get_sort_column_id = gtk_list_store_get_sort_column_id;
370   iface->set_sort_column_id = gtk_list_store_set_sort_column_id;
371   iface->set_sort_func = gtk_list_store_set_sort_func;
372   iface->set_default_sort_func = gtk_list_store_set_default_sort_func;
373   iface->has_default_sort_func = gtk_list_store_has_default_sort_func;
374 }
375
376 void
377 gtk_list_store_buildable_init (GtkBuildableIface *iface)
378 {
379   iface->custom_tag_start = gtk_list_store_buildable_custom_tag_start;
380   iface->custom_tag_end = gtk_list_store_buildable_custom_tag_end;
381 }
382
383 static void
384 gtk_list_store_init (GtkListStore *list_store)
385 {
386   GtkListStorePrivate *priv;
387
388   list_store->priv = G_TYPE_INSTANCE_GET_PRIVATE (list_store,
389                                                   GTK_TYPE_LIST_STORE,
390                                                   GtkListStorePrivate);
391   priv = list_store->priv;
392
393   priv->seq = g_sequence_new (NULL);
394   priv->sort_list = NULL;
395   priv->stamp = g_random_int ();
396   priv->sort_column_id = GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID;
397   priv->columns_dirty = FALSE;
398   priv->length = 0;
399 }
400
401 static gboolean
402 iter_is_valid (GtkTreeIter  *iter,
403                GtkListStore *list_store)
404 {
405   return iter != NULL && 
406          iter->user_data != NULL &&
407          list_store->priv->stamp == iter->stamp &&
408          !g_sequence_iter_is_end (iter->user_data) &&
409          g_sequence_iter_get_sequence (iter->user_data) == list_store->priv->seq;
410 }
411
412 /**
413  * gtk_list_store_new:
414  * @n_columns: number of columns in the list store
415  * @...: all #GType types for the columns, from first to last
416  *
417  * Creates a new list store as with @n_columns columns each of the types passed
418  * in.  Note that only types derived from standard GObject fundamental types
419  * are supported.
420  *
421  * As an example, <literal>gtk_tree_store_new (3, G_TYPE_INT, G_TYPE_STRING,
422  * GDK_TYPE_PIXBUF);</literal> will create a new #GtkListStore with three columns, of type
423  * int, string and #GdkPixbuf respectively.
424  *
425  * Return value: a new #GtkListStore
426  */
427 GtkListStore *
428 gtk_list_store_new (gint n_columns,
429                     ...)
430 {
431   GtkListStore *retval;
432   va_list args;
433   gint i;
434
435   g_return_val_if_fail (n_columns > 0, NULL);
436
437   retval = g_object_new (GTK_TYPE_LIST_STORE, NULL);
438   gtk_list_store_set_n_columns (retval, n_columns);
439
440   va_start (args, n_columns);
441
442   for (i = 0; i < n_columns; i++)
443     {
444       GType type = va_arg (args, GType);
445       if (! _gtk_tree_data_list_check_type (type))
446         {
447           g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
448           g_object_unref (retval);
449           va_end (args);
450
451           return NULL;
452         }
453
454       gtk_list_store_set_column_type (retval, i, type);
455     }
456
457   va_end (args);
458
459   return retval;
460 }
461
462
463 /**
464  * gtk_list_store_newv:
465  * @n_columns: number of columns in the list store
466  * @types: (array length=n_columns): an array of #GType types for the columns, from first to last
467  *
468  * Non-vararg creation function.  Used primarily by language bindings.
469  *
470  * Return value: (transfer full): a new #GtkListStore
471  * Rename to: gtk_list_store_new
472  **/
473 GtkListStore *
474 gtk_list_store_newv (gint   n_columns,
475                      GType *types)
476 {
477   GtkListStore *retval;
478   gint i;
479
480   g_return_val_if_fail (n_columns > 0, NULL);
481
482   retval = g_object_new (GTK_TYPE_LIST_STORE, NULL);
483   gtk_list_store_set_n_columns (retval, n_columns);
484
485   for (i = 0; i < n_columns; i++)
486     {
487       if (! _gtk_tree_data_list_check_type (types[i]))
488         {
489           g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i]));
490           g_object_unref (retval);
491           return NULL;
492         }
493
494       gtk_list_store_set_column_type (retval, i, types[i]);
495     }
496
497   return retval;
498 }
499
500 /**
501  * gtk_list_store_set_column_types:
502  * @list_store: A #GtkListStore
503  * @n_columns: Number of columns for the list store
504  * @types: (array length=n_columns): An array length n of #GTypes
505  *
506  * This function is meant primarily for #GObjects that inherit from #GtkListStore,
507  * and should only be used when constructing a new #GtkListStore.  It will not
508  * function after a row has been added, or a method on the #GtkTreeModel
509  * interface is called.
510  **/
511 void
512 gtk_list_store_set_column_types (GtkListStore *list_store,
513                                  gint          n_columns,
514                                  GType        *types)
515 {
516   GtkListStorePrivate *priv;
517   gint i;
518
519   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
520
521   priv = list_store->priv;
522
523   g_return_if_fail (priv->columns_dirty == 0);
524
525   gtk_list_store_set_n_columns (list_store, n_columns);
526   for (i = 0; i < n_columns; i++)
527     {
528       if (! _gtk_tree_data_list_check_type (types[i]))
529         {
530           g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i]));
531           continue;
532         }
533       gtk_list_store_set_column_type (list_store, i, types[i]);
534     }
535 }
536
537 static void
538 gtk_list_store_set_n_columns (GtkListStore *list_store,
539                               gint          n_columns)
540 {
541   GtkListStorePrivate *priv = list_store->priv;
542   int i;
543
544   if (priv->n_columns == n_columns)
545     return;
546
547   priv->column_headers = g_renew (GType, priv->column_headers, n_columns);
548   for (i = priv->n_columns; i < n_columns; i++)
549     priv->column_headers[i] = G_TYPE_INVALID;
550   priv->n_columns = n_columns;
551
552   if (priv->sort_list)
553     _gtk_tree_data_list_header_free (priv->sort_list);
554   priv->sort_list = _gtk_tree_data_list_header_new (n_columns, priv->column_headers);
555 }
556
557 static void
558 gtk_list_store_set_column_type (GtkListStore *list_store,
559                                 gint          column,
560                                 GType         type)
561 {
562   GtkListStorePrivate *priv = list_store->priv;
563
564   if (!_gtk_tree_data_list_check_type (type))
565     {
566       g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
567       return;
568     }
569
570   priv->column_headers[column] = type;
571 }
572
573 static void
574 gtk_list_store_finalize (GObject *object)
575 {
576   GtkListStore *list_store = GTK_LIST_STORE (object);
577   GtkListStorePrivate *priv = list_store->priv;
578
579   g_sequence_foreach (priv->seq,
580                       (GFunc) _gtk_tree_data_list_free, priv->column_headers);
581
582   g_sequence_free (priv->seq);
583
584   _gtk_tree_data_list_header_free (priv->sort_list);
585   g_free (priv->column_headers);
586
587   if (priv->default_sort_destroy)
588     {
589       GDestroyNotify d = priv->default_sort_destroy;
590
591       priv->default_sort_destroy = NULL;
592       d (priv->default_sort_data);
593       priv->default_sort_data = NULL;
594     }
595
596   G_OBJECT_CLASS (gtk_list_store_parent_class)->finalize (object);
597 }
598
599 /* Fulfill the GtkTreeModel requirements */
600 static GtkTreeModelFlags
601 gtk_list_store_get_flags (GtkTreeModel *tree_model)
602 {
603   return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
604 }
605
606 static gint
607 gtk_list_store_get_n_columns (GtkTreeModel *tree_model)
608 {
609   GtkListStore *list_store = GTK_LIST_STORE (tree_model);
610   GtkListStorePrivate *priv = list_store->priv;
611
612   priv->columns_dirty = TRUE;
613
614   return priv->n_columns;
615 }
616
617 static GType
618 gtk_list_store_get_column_type (GtkTreeModel *tree_model,
619                                 gint          index)
620 {
621   GtkListStore *list_store = GTK_LIST_STORE (tree_model);
622   GtkListStorePrivate *priv = list_store->priv;
623
624   g_return_val_if_fail (index < priv->n_columns, G_TYPE_INVALID);
625
626   priv->columns_dirty = TRUE;
627
628   return priv->column_headers[index];
629 }
630
631 static gboolean
632 gtk_list_store_get_iter (GtkTreeModel *tree_model,
633                          GtkTreeIter  *iter,
634                          GtkTreePath  *path)
635 {
636   GtkListStore *list_store = GTK_LIST_STORE (tree_model);
637   GtkListStorePrivate *priv = list_store->priv;
638   GSequence *seq;
639   gint i;
640
641   priv->columns_dirty = TRUE;
642
643   seq = priv->seq;
644
645   i = gtk_tree_path_get_indices (path)[0];
646
647   if (i >= g_sequence_get_length (seq))
648     {
649       iter->stamp = 0;
650       return FALSE;
651     }
652
653   iter->stamp = priv->stamp;
654   iter->user_data = g_sequence_get_iter_at_pos (seq, i);
655
656   return TRUE;
657 }
658
659 static GtkTreePath *
660 gtk_list_store_get_path (GtkTreeModel *tree_model,
661                          GtkTreeIter  *iter)
662 {
663   GtkListStore *list_store = GTK_LIST_STORE (tree_model);
664   GtkListStorePrivate *priv = list_store->priv;
665   GtkTreePath *path;
666
667   g_return_val_if_fail (iter->stamp == priv->stamp, NULL);
668
669   if (g_sequence_iter_is_end (iter->user_data))
670     return NULL;
671         
672   path = gtk_tree_path_new ();
673   gtk_tree_path_append_index (path, g_sequence_iter_get_position (iter->user_data));
674   
675   return path;
676 }
677
678 static void
679 gtk_list_store_get_value (GtkTreeModel *tree_model,
680                           GtkTreeIter  *iter,
681                           gint          column,
682                           GValue       *value)
683 {
684   GtkListStore *list_store = GTK_LIST_STORE (tree_model);
685   GtkListStorePrivate *priv = list_store->priv;
686   GtkTreeDataList *list;
687   gint tmp_column = column;
688
689   g_return_if_fail (column < priv->n_columns);
690   g_return_if_fail (iter_is_valid (iter, list_store));
691                     
692   list = g_sequence_get (iter->user_data);
693
694   while (tmp_column-- > 0 && list)
695     list = list->next;
696
697   if (list == NULL)
698     g_value_init (value, priv->column_headers[column]);
699   else
700     _gtk_tree_data_list_node_to_value (list,
701                                        priv->column_headers[column],
702                                        value);
703 }
704
705 static gboolean
706 gtk_list_store_iter_next (GtkTreeModel  *tree_model,
707                           GtkTreeIter   *iter)
708 {
709   GtkListStore *list_store = GTK_LIST_STORE (tree_model);
710   GtkListStorePrivate *priv = list_store->priv;
711   gboolean retval;
712
713   g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);
714   iter->user_data = g_sequence_iter_next (iter->user_data);
715
716   retval = g_sequence_iter_is_end (iter->user_data);
717   if (retval)
718     iter->stamp = 0;
719
720   return !retval;
721 }
722
723 static gboolean
724 gtk_list_store_iter_previous (GtkTreeModel *tree_model,
725                               GtkTreeIter  *iter)
726 {
727   GtkListStore *list_store = GTK_LIST_STORE (tree_model);
728   GtkListStorePrivate *priv = list_store->priv;
729
730   g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);
731
732   if (g_sequence_iter_is_begin (iter->user_data))
733     {
734       iter->stamp = 0;
735       return FALSE;
736     }
737
738   iter->user_data = g_sequence_iter_prev (iter->user_data);
739
740   return TRUE;
741 }
742
743 static gboolean
744 gtk_list_store_iter_children (GtkTreeModel *tree_model,
745                               GtkTreeIter  *iter,
746                               GtkTreeIter  *parent)
747 {
748   GtkListStore *list_store = (GtkListStore *) tree_model;
749   GtkListStorePrivate *priv = list_store->priv;
750
751   /* this is a list, nodes have no children */
752   if (parent)
753     {
754       iter->stamp = 0;
755       return FALSE;
756     }
757
758   if (g_sequence_get_length (priv->seq) > 0)
759     {
760       iter->stamp = priv->stamp;
761       iter->user_data = g_sequence_get_begin_iter (priv->seq);
762       return TRUE;
763     }
764   else
765     {
766       iter->stamp = 0;
767       return FALSE;
768     }
769 }
770
771 static gboolean
772 gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
773                                GtkTreeIter  *iter)
774 {
775   return FALSE;
776 }
777
778 static gint
779 gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
780                                 GtkTreeIter  *iter)
781 {
782   GtkListStore *list_store = GTK_LIST_STORE (tree_model);
783   GtkListStorePrivate *priv = list_store->priv;
784
785   if (iter == NULL)
786     return g_sequence_get_length (priv->seq);
787
788   g_return_val_if_fail (priv->stamp == iter->stamp, -1);
789
790   return 0;
791 }
792
793 static gboolean
794 gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
795                                GtkTreeIter  *iter,
796                                GtkTreeIter  *parent,
797                                gint          n)
798 {
799   GtkListStore *list_store = GTK_LIST_STORE (tree_model);
800   GtkListStorePrivate *priv = list_store->priv;
801   GSequenceIter *child;
802
803   iter->stamp = 0;
804
805   if (parent)
806     return FALSE;
807
808   child = g_sequence_get_iter_at_pos (priv->seq, n);
809
810   if (g_sequence_iter_is_end (child))
811     return FALSE;
812
813   iter->stamp = priv->stamp;
814   iter->user_data = child;
815
816   return TRUE;
817 }
818
819 static gboolean
820 gtk_list_store_iter_parent (GtkTreeModel *tree_model,
821                             GtkTreeIter  *iter,
822                             GtkTreeIter  *child)
823 {
824   iter->stamp = 0;
825   return FALSE;
826 }
827
828 static gboolean
829 gtk_list_store_real_set_value (GtkListStore *list_store,
830                                GtkTreeIter  *iter,
831                                gint          column,
832                                GValue       *value,
833                                gboolean      sort)
834 {
835   GtkListStorePrivate *priv = list_store->priv;
836   GtkTreeDataList *list;
837   GtkTreeDataList *prev;
838   gint old_column = column;
839   GValue real_value = G_VALUE_INIT;
840   gboolean converted = FALSE;
841   gboolean retval = FALSE;
842
843   if (! g_type_is_a (G_VALUE_TYPE (value), priv->column_headers[column]))
844     {
845       if (! (g_value_type_compatible (G_VALUE_TYPE (value), priv->column_headers[column]) &&
846              g_value_type_compatible (priv->column_headers[column], G_VALUE_TYPE (value))))
847         {
848           g_warning ("%s: Unable to convert from %s to %s\n",
849                      G_STRLOC,
850                      g_type_name (G_VALUE_TYPE (value)),
851                      g_type_name (priv->column_headers[column]));
852           return retval;
853         }
854       if (!g_value_transform (value, &real_value))
855         {
856           g_warning ("%s: Unable to make conversion from %s to %s\n",
857                      G_STRLOC,
858                      g_type_name (G_VALUE_TYPE (value)),
859                      g_type_name (priv->column_headers[column]));
860           g_value_unset (&real_value);
861           return retval;
862         }
863       converted = TRUE;
864     }
865
866   prev = list = g_sequence_get (iter->user_data);
867
868   while (list != NULL)
869     {
870       if (column == 0)
871         {
872           if (converted)
873             _gtk_tree_data_list_value_to_node (list, &real_value);
874           else
875             _gtk_tree_data_list_value_to_node (list, value);
876           retval = TRUE;
877           if (converted)
878             g_value_unset (&real_value);
879          if (sort && GTK_LIST_STORE_IS_SORTED (list_store))
880             gtk_list_store_sort_iter_changed (list_store, iter, old_column);
881           return retval;
882         }
883
884       column--;
885       prev = list;
886       list = list->next;
887     }
888
889   if (g_sequence_get (iter->user_data) == NULL)
890     {
891       list = _gtk_tree_data_list_alloc();
892       g_sequence_set (iter->user_data, list);
893       list->next = NULL;
894     }
895   else
896     {
897       list = prev->next = _gtk_tree_data_list_alloc ();
898       list->next = NULL;
899     }
900
901   while (column != 0)
902     {
903       list->next = _gtk_tree_data_list_alloc ();
904       list = list->next;
905       list->next = NULL;
906       column --;
907     }
908
909   if (converted)
910     _gtk_tree_data_list_value_to_node (list, &real_value);
911   else
912     _gtk_tree_data_list_value_to_node (list, value);
913
914   retval = TRUE;
915   if (converted)
916     g_value_unset (&real_value);
917
918   if (sort && GTK_LIST_STORE_IS_SORTED (list_store))
919     gtk_list_store_sort_iter_changed (list_store, iter, old_column);
920
921   return retval;
922 }
923
924
925 /**
926  * gtk_list_store_set_value:
927  * @list_store: A #GtkListStore
928  * @iter: A valid #GtkTreeIter for the row being modified
929  * @column: column number to modify
930  * @value: new value for the cell
931  *
932  * Sets the data in the cell specified by @iter and @column.
933  * The type of @value must be convertible to the type of the
934  * column.
935  *
936  **/
937 void
938 gtk_list_store_set_value (GtkListStore *list_store,
939                           GtkTreeIter  *iter,
940                           gint          column,
941                           GValue       *value)
942 {
943   GtkListStorePrivate *priv;
944
945   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
946   g_return_if_fail (iter_is_valid (iter, list_store));
947   g_return_if_fail (G_IS_VALUE (value));
948   priv = list_store->priv;
949   g_return_if_fail (column >= 0 && column < priv->n_columns);
950
951   if (gtk_list_store_real_set_value (list_store, iter, column, value, TRUE))
952     {
953       GtkTreePath *path;
954
955       path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
956       gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
957       gtk_tree_path_free (path);
958     }
959 }
960
961 static GtkTreeIterCompareFunc
962 gtk_list_store_get_compare_func (GtkListStore *list_store)
963 {
964   GtkListStorePrivate *priv = list_store->priv;
965   GtkTreeIterCompareFunc func = NULL;
966
967   if (GTK_LIST_STORE_IS_SORTED (list_store))
968     {
969       if (priv->sort_column_id != -1)
970         {
971           GtkTreeDataSortHeader *header;
972           header = _gtk_tree_data_list_get_header (priv->sort_list,
973                                                    priv->sort_column_id);
974           g_return_val_if_fail (header != NULL, NULL);
975           g_return_val_if_fail (header->func != NULL, NULL);
976           func = header->func;
977         }
978       else
979         {
980           func = priv->default_sort_func;
981         }
982     }
983
984   return func;
985 }
986
987 static void
988 gtk_list_store_set_vector_internal (GtkListStore *list_store,
989                                     GtkTreeIter  *iter,
990                                     gboolean     *emit_signal,
991                                     gboolean     *maybe_need_sort,
992                                     gint         *columns,
993                                     GValue       *values,
994                                     gint          n_values)
995 {
996   GtkListStorePrivate *priv = list_store->priv;
997   gint i;
998   GtkTreeIterCompareFunc func = NULL;
999
1000   func = gtk_list_store_get_compare_func (list_store);
1001   if (func != _gtk_tree_data_list_compare_func)
1002     *maybe_need_sort = TRUE;
1003
1004   for (i = 0; i < n_values; i++)
1005     {
1006       *emit_signal = gtk_list_store_real_set_value (list_store, 
1007                                                iter, 
1008                                                columns[i],
1009                                                &values[i],
1010                                                FALSE) || *emit_signal;
1011
1012       if (func == _gtk_tree_data_list_compare_func &&
1013           columns[i] == priv->sort_column_id)
1014         *maybe_need_sort = TRUE;
1015     }
1016 }
1017
1018 static void
1019 gtk_list_store_set_valist_internal (GtkListStore *list_store,
1020                                     GtkTreeIter  *iter,
1021                                     gboolean     *emit_signal,
1022                                     gboolean     *maybe_need_sort,
1023                                     va_list       var_args)
1024 {
1025   GtkListStorePrivate *priv = list_store->priv;
1026   gint column;
1027   GtkTreeIterCompareFunc func = NULL;
1028
1029   column = va_arg (var_args, gint);
1030
1031   func = gtk_list_store_get_compare_func (list_store);
1032   if (func != _gtk_tree_data_list_compare_func)
1033     *maybe_need_sort = TRUE;
1034
1035   while (column != -1)
1036     {
1037       GValue value = G_VALUE_INIT;
1038       gchar *error = NULL;
1039
1040       if (column < 0 || column >= priv->n_columns)
1041         {
1042           g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
1043           break;
1044         }
1045
1046       G_VALUE_COLLECT_INIT (&value, priv->column_headers[column],
1047                             var_args, 0, &error);
1048       if (error)
1049         {
1050           g_warning ("%s: %s", G_STRLOC, error);
1051           g_free (error);
1052
1053           /* we purposely leak the value here, it might not be
1054            * in a sane state if an error condition occoured
1055            */
1056           break;
1057         }
1058
1059       /* FIXME: instead of calling this n times, refactor with above */
1060       *emit_signal = gtk_list_store_real_set_value (list_store,
1061                                                     iter,
1062                                                     column,
1063                                                     &value,
1064                                                     FALSE) || *emit_signal;
1065       
1066       if (func == _gtk_tree_data_list_compare_func &&
1067           column == priv->sort_column_id)
1068         *maybe_need_sort = TRUE;
1069
1070       g_value_unset (&value);
1071
1072       column = va_arg (var_args, gint);
1073     }
1074 }
1075
1076 /**
1077  * gtk_list_store_set_valuesv:
1078  * @list_store: A #GtkListStore
1079  * @iter: A valid #GtkTreeIter for the row being modified
1080  * @columns: (array length=n_values): an array of column numbers
1081  * @values: (array length=n_values): an array of GValues
1082  * @n_values: the length of the @columns and @values arrays
1083  *
1084  * A variant of gtk_list_store_set_valist() which
1085  * takes the columns and values as two arrays, instead of
1086  * varargs. This function is mainly intended for 
1087  * language-bindings and in case the number of columns to
1088  * change is not known until run-time.
1089  *
1090  * Since: 2.12
1091  * Rename to: gtk_list_store_set
1092  */
1093 void
1094 gtk_list_store_set_valuesv (GtkListStore *list_store,
1095                             GtkTreeIter  *iter,
1096                             gint         *columns,
1097                             GValue       *values,
1098                             gint          n_values)
1099 {
1100   GtkListStorePrivate *priv;
1101   gboolean emit_signal = FALSE;
1102   gboolean maybe_need_sort = FALSE;
1103
1104   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1105   g_return_if_fail (iter_is_valid (iter, list_store));
1106
1107   priv = list_store->priv;
1108
1109   gtk_list_store_set_vector_internal (list_store, iter,
1110                                       &emit_signal,
1111                                       &maybe_need_sort,
1112                                       columns, values, n_values);
1113
1114   if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
1115     gtk_list_store_sort_iter_changed (list_store, iter, priv->sort_column_id);
1116
1117   if (emit_signal)
1118     {
1119       GtkTreePath *path;
1120
1121       path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
1122       gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
1123       gtk_tree_path_free (path);
1124     }
1125 }
1126
1127 /**
1128  * gtk_list_store_set_valist:
1129  * @list_store: A #GtkListStore
1130  * @iter: A valid #GtkTreeIter for the row being modified
1131  * @var_args: va_list of column/value pairs
1132  *
1133  * See gtk_list_store_set(); this version takes a va_list for use by language
1134  * bindings.
1135  *
1136  **/
1137 void
1138 gtk_list_store_set_valist (GtkListStore *list_store,
1139                            GtkTreeIter  *iter,
1140                            va_list       var_args)
1141 {
1142   GtkListStorePrivate *priv;
1143   gboolean emit_signal = FALSE;
1144   gboolean maybe_need_sort = FALSE;
1145
1146   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1147   g_return_if_fail (iter_is_valid (iter, list_store));
1148
1149   priv = list_store->priv;
1150
1151   gtk_list_store_set_valist_internal (list_store, iter, 
1152                                       &emit_signal, 
1153                                       &maybe_need_sort,
1154                                       var_args);
1155
1156   if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
1157     gtk_list_store_sort_iter_changed (list_store, iter, priv->sort_column_id);
1158
1159   if (emit_signal)
1160     {
1161       GtkTreePath *path;
1162
1163       path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
1164       gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
1165       gtk_tree_path_free (path);
1166     }
1167 }
1168
1169 /**
1170  * gtk_list_store_set:
1171  * @list_store: a #GtkListStore
1172  * @iter: row iterator
1173  * @...: pairs of column number and value, terminated with -1
1174  *
1175  * Sets the value of one or more cells in the row referenced by @iter.
1176  * The variable argument list should contain integer column numbers,
1177  * each column number followed by the value to be set.
1178  * The list is terminated by a -1. For example, to set column 0 with type
1179  * %G_TYPE_STRING to "Foo", you would write <literal>gtk_list_store_set (store, iter,
1180  * 0, "Foo", -1)</literal>.
1181  *
1182  * The value will be referenced by the store if it is a %G_TYPE_OBJECT, and it
1183  * will be copied if it is a %G_TYPE_STRING or %G_TYPE_BOXED.
1184  */
1185 void
1186 gtk_list_store_set (GtkListStore *list_store,
1187                     GtkTreeIter  *iter,
1188                     ...)
1189 {
1190   va_list var_args;
1191
1192   va_start (var_args, iter);
1193   gtk_list_store_set_valist (list_store, iter, var_args);
1194   va_end (var_args);
1195 }
1196
1197 /**
1198  * gtk_list_store_remove:
1199  * @list_store: A #GtkListStore
1200  * @iter: A valid #GtkTreeIter
1201  *
1202  * Removes the given row from the list store.  After being removed, 
1203  * @iter is set to be the next valid row, or invalidated if it pointed 
1204  * to the last row in @list_store.
1205  *
1206  * Return value: %TRUE if @iter is valid, %FALSE if not.
1207  **/
1208 gboolean
1209 gtk_list_store_remove (GtkListStore *list_store,
1210                        GtkTreeIter  *iter)
1211 {
1212   GtkListStorePrivate *priv;
1213   GtkTreePath *path;
1214   GSequenceIter *ptr, *next;
1215
1216   g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
1217   g_return_val_if_fail (iter_is_valid (iter, list_store), FALSE);
1218
1219   priv = list_store->priv;
1220
1221   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
1222
1223   ptr = iter->user_data;
1224   next = g_sequence_iter_next (ptr);
1225   
1226   _gtk_tree_data_list_free (g_sequence_get (ptr), priv->column_headers);
1227   g_sequence_remove (iter->user_data);
1228
1229   priv->length--;
1230   
1231   gtk_tree_model_row_deleted (GTK_TREE_MODEL (list_store), path);
1232   gtk_tree_path_free (path);
1233
1234   if (g_sequence_iter_is_end (next))
1235     {
1236       iter->stamp = 0;
1237       return FALSE;
1238     }
1239   else
1240     {
1241       iter->stamp = priv->stamp;
1242       iter->user_data = next;
1243       return TRUE;
1244     }
1245 }
1246
1247 /**
1248  * gtk_list_store_insert:
1249  * @list_store: A #GtkListStore
1250  * @iter: (out): An unset #GtkTreeIter to set to the new row
1251  * @position: position to insert the new row
1252  *
1253  * Creates a new row at @position.  @iter will be changed to point to this new
1254  * row.  If @position is larger than the number of rows on the list, then the
1255  * new row will be appended to the list. The row will be empty after this
1256  * function is called.  To fill in values, you need to call 
1257  * gtk_list_store_set() or gtk_list_store_set_value().
1258  *
1259  **/
1260 void
1261 gtk_list_store_insert (GtkListStore *list_store,
1262                        GtkTreeIter  *iter,
1263                        gint          position)
1264 {
1265   GtkListStorePrivate *priv;
1266   GtkTreePath *path;
1267   GSequence *seq;
1268   GSequenceIter *ptr;
1269   gint length;
1270
1271   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1272   g_return_if_fail (iter != NULL);
1273   g_return_if_fail (position >= 0);
1274
1275   priv = list_store->priv;
1276
1277   priv->columns_dirty = TRUE;
1278
1279   seq = priv->seq;
1280
1281   length = g_sequence_get_length (seq);
1282   if (position > length)
1283     position = length;
1284
1285   ptr = g_sequence_get_iter_at_pos (seq, position);
1286   ptr = g_sequence_insert_before (ptr, NULL);
1287
1288   iter->stamp = priv->stamp;
1289   iter->user_data = ptr;
1290
1291   g_assert (iter_is_valid (iter, list_store));
1292
1293   priv->length++;
1294   
1295   path = gtk_tree_path_new ();
1296   gtk_tree_path_append_index (path, position);
1297   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1298   gtk_tree_path_free (path);
1299 }
1300
1301 /**
1302  * gtk_list_store_insert_before:
1303  * @list_store: A #GtkListStore
1304  * @iter: (out): An unset #GtkTreeIter to set to the new row
1305  * @sibling: (allow-none): A valid #GtkTreeIter, or %NULL
1306  *
1307  * Inserts a new row before @sibling. If @sibling is %NULL, then the row will 
1308  * be appended to the end of the list. @iter will be changed to point to this 
1309  * new row. The row will be empty after this function is called. To fill in 
1310  * values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
1311  *
1312  **/
1313 void
1314 gtk_list_store_insert_before (GtkListStore *list_store,
1315                               GtkTreeIter  *iter,
1316                               GtkTreeIter  *sibling)
1317 {
1318   GtkListStorePrivate *priv;
1319   GSequenceIter *after;
1320   
1321   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1322   g_return_if_fail (iter != NULL);
1323
1324   priv = list_store->priv;
1325
1326   if (sibling)
1327     g_return_if_fail (iter_is_valid (sibling, list_store));
1328
1329   if (!sibling)
1330     after = g_sequence_get_end_iter (priv->seq);
1331   else
1332     after = sibling->user_data;
1333
1334   gtk_list_store_insert (list_store, iter, g_sequence_iter_get_position (after));
1335 }
1336
1337 /**
1338  * gtk_list_store_insert_after:
1339  * @list_store: A #GtkListStore
1340  * @iter: (out): An unset #GtkTreeIter to set to the new row
1341  * @sibling: (allow-none): A valid #GtkTreeIter, or %NULL
1342  *
1343  * Inserts a new row after @sibling. If @sibling is %NULL, then the row will be
1344  * prepended to the beginning of the list. @iter will be changed to point to
1345  * this new row. The row will be empty after this function is called. To fill
1346  * in values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
1347  *
1348  **/
1349 void
1350 gtk_list_store_insert_after (GtkListStore *list_store,
1351                              GtkTreeIter  *iter,
1352                              GtkTreeIter  *sibling)
1353 {
1354   GtkListStorePrivate *priv;
1355   GSequenceIter *after;
1356
1357   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1358   g_return_if_fail (iter != NULL);
1359
1360   priv = list_store->priv;
1361
1362   if (sibling)
1363     g_return_if_fail (iter_is_valid (sibling, list_store));
1364
1365   if (!sibling)
1366     after = g_sequence_get_begin_iter (priv->seq);
1367   else
1368     after = g_sequence_iter_next (sibling->user_data);
1369
1370   gtk_list_store_insert (list_store, iter, g_sequence_iter_get_position (after));
1371 }
1372
1373 /**
1374  * gtk_list_store_prepend:
1375  * @list_store: A #GtkListStore
1376  * @iter: (out): An unset #GtkTreeIter to set to the prepend row
1377  *
1378  * Prepends a new row to @list_store. @iter will be changed to point to this new
1379  * row. The row will be empty after this function is called. To fill in
1380  * values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
1381  *
1382  **/
1383 void
1384 gtk_list_store_prepend (GtkListStore *list_store,
1385                         GtkTreeIter  *iter)
1386 {
1387   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1388   g_return_if_fail (iter != NULL);
1389
1390   gtk_list_store_insert (list_store, iter, 0);
1391 }
1392
1393 /**
1394  * gtk_list_store_append:
1395  * @list_store: A #GtkListStore
1396  * @iter: (out): An unset #GtkTreeIter to set to the appended row
1397  *
1398  * Appends a new row to @list_store.  @iter will be changed to point to this new
1399  * row.  The row will be empty after this function is called.  To fill in
1400  * values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
1401  *
1402  **/
1403 void
1404 gtk_list_store_append (GtkListStore *list_store,
1405                        GtkTreeIter  *iter)
1406 {
1407   GtkListStorePrivate *priv;
1408
1409   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1410   g_return_if_fail (iter != NULL);
1411
1412   priv = list_store->priv;
1413
1414   gtk_list_store_insert (list_store, iter, g_sequence_get_length (priv->seq));
1415 }
1416
1417 static void
1418 gtk_list_store_increment_stamp (GtkListStore *list_store)
1419 {
1420   GtkListStorePrivate *priv = list_store->priv;
1421
1422   do
1423     {
1424       priv->stamp++;
1425     }
1426   while (priv->stamp == 0);
1427 }
1428
1429 /**
1430  * gtk_list_store_clear:
1431  * @list_store: a #GtkListStore.
1432  *
1433  * Removes all rows from the list store.  
1434  *
1435  **/
1436 void
1437 gtk_list_store_clear (GtkListStore *list_store)
1438 {
1439   GtkListStorePrivate *priv;
1440   GtkTreeIter iter;
1441
1442   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1443
1444   priv = list_store->priv;
1445
1446   while (g_sequence_get_length (priv->seq) > 0)
1447     {
1448       iter.stamp = priv->stamp;
1449       iter.user_data = g_sequence_get_begin_iter (priv->seq);
1450       gtk_list_store_remove (list_store, &iter);
1451     }
1452
1453   gtk_list_store_increment_stamp (list_store);
1454 }
1455
1456 /**
1457  * gtk_list_store_iter_is_valid:
1458  * @list_store: A #GtkListStore.
1459  * @iter: A #GtkTreeIter.
1460  *
1461  * <warning>This function is slow. Only use it for debugging and/or testing
1462  * purposes.</warning>
1463  *
1464  * Checks if the given iter is a valid iter for this #GtkListStore.
1465  *
1466  * Return value: %TRUE if the iter is valid, %FALSE if the iter is invalid.
1467  *
1468  * Since: 2.2
1469  **/
1470 gboolean
1471 gtk_list_store_iter_is_valid (GtkListStore *list_store,
1472                               GtkTreeIter  *iter)
1473 {
1474   g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
1475   g_return_val_if_fail (iter != NULL, FALSE);
1476
1477   return iter_is_valid (iter, list_store);
1478 }
1479
1480 static gboolean real_gtk_list_store_row_draggable (GtkTreeDragSource *drag_source,
1481                                                    GtkTreePath       *path)
1482 {
1483   return TRUE;
1484 }
1485   
1486 static gboolean
1487 gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
1488                                  GtkTreePath       *path)
1489 {
1490   GtkTreeIter iter;
1491
1492   if (gtk_list_store_get_iter (GTK_TREE_MODEL (drag_source),
1493                                &iter,
1494                                path))
1495     {
1496       gtk_list_store_remove (GTK_LIST_STORE (drag_source), &iter);
1497       return TRUE;
1498     }
1499   return FALSE;
1500 }
1501
1502 static gboolean
1503 gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
1504                               GtkTreePath       *path,
1505                               GtkSelectionData  *selection_data)
1506 {
1507   /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1508    * target, because the default handler does it for us, but
1509    * we do anyway for the convenience of someone maybe overriding the
1510    * default handler.
1511    */
1512
1513   if (gtk_tree_set_row_drag_data (selection_data,
1514                                   GTK_TREE_MODEL (drag_source),
1515                                   path))
1516     {
1517       return TRUE;
1518     }
1519   else
1520     {
1521       /* FIXME handle text targets at least. */
1522     }
1523
1524   return FALSE;
1525 }
1526
1527 static gboolean
1528 gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
1529                                    GtkTreePath       *dest,
1530                                    GtkSelectionData  *selection_data)
1531 {
1532   GtkTreeModel *tree_model = GTK_TREE_MODEL (drag_dest);
1533   GtkListStore *list_store = GTK_LIST_STORE (tree_model);
1534   GtkListStorePrivate *priv = list_store->priv;
1535   GtkTreeModel *src_model = NULL;
1536   GtkTreePath *src_path = NULL;
1537   gboolean retval = FALSE;
1538
1539   if (gtk_tree_get_row_drag_data (selection_data,
1540                                   &src_model,
1541                                   &src_path) &&
1542       src_model == tree_model)
1543     {
1544       /* Copy the given row to a new position */
1545       GtkTreeIter src_iter;
1546       GtkTreeIter dest_iter;
1547       GtkTreePath *prev;
1548
1549       if (!gtk_list_store_get_iter (src_model,
1550                                     &src_iter,
1551                                     src_path))
1552         {
1553           goto out;
1554         }
1555
1556       /* Get the path to insert _after_ (dest is the path to insert _before_) */
1557       prev = gtk_tree_path_copy (dest);
1558
1559       if (!gtk_tree_path_prev (prev))
1560         {
1561           /* dest was the first spot in the list; which means we are supposed
1562            * to prepend.
1563            */
1564           gtk_list_store_prepend (list_store, &dest_iter);
1565
1566           retval = TRUE;
1567         }
1568       else
1569         {
1570           if (gtk_list_store_get_iter (tree_model, &dest_iter, prev))
1571             {
1572               GtkTreeIter tmp_iter = dest_iter;
1573
1574               gtk_list_store_insert_after (list_store, &dest_iter, &tmp_iter);
1575
1576               retval = TRUE;
1577             }
1578         }
1579
1580       gtk_tree_path_free (prev);
1581
1582       /* If we succeeded in creating dest_iter, copy data from src
1583        */
1584       if (retval)
1585         {
1586           GtkTreeDataList *dl = g_sequence_get (src_iter.user_data);
1587           GtkTreeDataList *copy_head = NULL;
1588           GtkTreeDataList *copy_prev = NULL;
1589           GtkTreeDataList *copy_iter = NULL;
1590           GtkTreePath *path;
1591           gint col;
1592
1593           col = 0;
1594           while (dl)
1595             {
1596               copy_iter = _gtk_tree_data_list_node_copy (dl,
1597                                                          priv->column_headers[col]);
1598
1599               if (copy_head == NULL)
1600                 copy_head = copy_iter;
1601
1602               if (copy_prev)
1603                 copy_prev->next = copy_iter;
1604
1605               copy_prev = copy_iter;
1606
1607               dl = dl->next;
1608               ++col;
1609             }
1610
1611           dest_iter.stamp = priv->stamp;
1612           g_sequence_set (dest_iter.user_data, copy_head);
1613
1614           path = gtk_list_store_get_path (tree_model, &dest_iter);
1615           gtk_tree_model_row_changed (tree_model, path, &dest_iter);
1616           gtk_tree_path_free (path);
1617         }
1618     }
1619   else
1620     {
1621       /* FIXME maybe add some data targets eventually, or handle text
1622        * targets in the simple case.
1623        */
1624     }
1625
1626  out:
1627
1628   if (src_path)
1629     gtk_tree_path_free (src_path);
1630
1631   return retval;
1632 }
1633
1634 static gboolean
1635 gtk_list_store_row_drop_possible (GtkTreeDragDest  *drag_dest,
1636                                   GtkTreePath      *dest_path,
1637                                   GtkSelectionData *selection_data)
1638 {
1639   gint *indices;
1640   GtkTreeModel *src_model = NULL;
1641   GtkTreePath *src_path = NULL;
1642   gboolean retval = FALSE;
1643
1644   /* don't accept drops if the list has been sorted */
1645   if (GTK_LIST_STORE_IS_SORTED (drag_dest))
1646     return FALSE;
1647
1648   if (!gtk_tree_get_row_drag_data (selection_data,
1649                                    &src_model,
1650                                    &src_path))
1651     goto out;
1652
1653   if (src_model != GTK_TREE_MODEL (drag_dest))
1654     goto out;
1655
1656   if (gtk_tree_path_get_depth (dest_path) != 1)
1657     goto out;
1658
1659   /* can drop before any existing node, or before one past any existing. */
1660
1661   indices = gtk_tree_path_get_indices (dest_path);
1662
1663   if (indices[0] <= g_sequence_get_length (GTK_LIST_STORE (drag_dest)->priv->seq))
1664     retval = TRUE;
1665
1666  out:
1667   if (src_path)
1668     gtk_tree_path_free (src_path);
1669   
1670   return retval;
1671 }
1672
1673 /* Sorting and reordering */
1674
1675 /* Reordering */
1676 static gint
1677 gtk_list_store_reorder_func (GSequenceIter *a,
1678                              GSequenceIter *b,
1679                              gpointer       user_data)
1680 {
1681   GHashTable *new_positions = user_data;
1682   gint apos = GPOINTER_TO_INT (g_hash_table_lookup (new_positions, a));
1683   gint bpos = GPOINTER_TO_INT (g_hash_table_lookup (new_positions, b));
1684
1685   if (apos < bpos)
1686     return -1;
1687   if (apos > bpos)
1688     return 1;
1689   return 0;
1690 }
1691   
1692 /**
1693  * gtk_list_store_reorder: (skip)
1694  * @store: A #GtkListStore.
1695  * @new_order: (array): an array of integers mapping the new position of each child
1696  *      to its old position before the re-ordering,
1697  *      i.e. @new_order<literal>[newpos] = oldpos</literal>.
1698  *
1699  * Reorders @store to follow the order indicated by @new_order. Note that
1700  * this function only works with unsorted stores.
1701  *
1702  * Since: 2.2
1703  **/
1704 void
1705 gtk_list_store_reorder (GtkListStore *store,
1706                         gint         *new_order)
1707 {
1708   GtkListStorePrivate *priv;
1709   gint i;
1710   GtkTreePath *path;
1711   GHashTable *new_positions;
1712   GSequenceIter *ptr;
1713   gint *order;
1714   
1715   g_return_if_fail (GTK_IS_LIST_STORE (store));
1716   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1717   g_return_if_fail (new_order != NULL);
1718
1719   priv = store->priv;
1720
1721   order = g_new (gint, g_sequence_get_length (priv->seq));
1722   for (i = 0; i < g_sequence_get_length (priv->seq); i++)
1723     order[new_order[i]] = i;
1724   
1725   new_positions = g_hash_table_new (g_direct_hash, g_direct_equal);
1726
1727   ptr = g_sequence_get_begin_iter (priv->seq);
1728   i = 0;
1729   while (!g_sequence_iter_is_end (ptr))
1730     {
1731       g_hash_table_insert (new_positions, ptr, GINT_TO_POINTER (order[i++]));
1732
1733       ptr = g_sequence_iter_next (ptr);
1734     }
1735   g_free (order);
1736   
1737   g_sequence_sort_iter (priv->seq, gtk_list_store_reorder_func, new_positions);
1738
1739   g_hash_table_destroy (new_positions);
1740   
1741   /* emit signal */
1742   path = gtk_tree_path_new ();
1743   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1744                                  path, NULL, new_order);
1745   gtk_tree_path_free (path);
1746 }
1747
1748 static GHashTable *
1749 save_positions (GSequence *seq)
1750 {
1751   GHashTable *positions = g_hash_table_new (g_direct_hash, g_direct_equal);
1752   GSequenceIter *ptr;
1753
1754   ptr = g_sequence_get_begin_iter (seq);
1755   while (!g_sequence_iter_is_end (ptr))
1756     {
1757       g_hash_table_insert (positions, ptr,
1758                            GINT_TO_POINTER (g_sequence_iter_get_position (ptr)));
1759       ptr = g_sequence_iter_next (ptr);
1760     }
1761
1762   return positions;
1763 }
1764
1765 static int *
1766 generate_order (GSequence *seq,
1767                 GHashTable *old_positions)
1768 {
1769   GSequenceIter *ptr;
1770   int *order = g_new (int, g_sequence_get_length (seq));
1771   int i;
1772
1773   i = 0;
1774   ptr = g_sequence_get_begin_iter (seq);
1775   while (!g_sequence_iter_is_end (ptr))
1776     {
1777       int old_pos = GPOINTER_TO_INT (g_hash_table_lookup (old_positions, ptr));
1778       order[i++] = old_pos;
1779       ptr = g_sequence_iter_next (ptr);
1780     }
1781
1782   g_hash_table_destroy (old_positions);
1783
1784   return order;
1785 }
1786
1787 /**
1788  * gtk_list_store_swap:
1789  * @store: A #GtkListStore.
1790  * @a: A #GtkTreeIter.
1791  * @b: Another #GtkTreeIter.
1792  *
1793  * Swaps @a and @b in @store. Note that this function only works with
1794  * unsorted stores.
1795  *
1796  * Since: 2.2
1797  **/
1798 void
1799 gtk_list_store_swap (GtkListStore *store,
1800                      GtkTreeIter  *a,
1801                      GtkTreeIter  *b)
1802 {
1803   GtkListStorePrivate *priv;
1804   GHashTable *old_positions;
1805   gint *order;
1806   GtkTreePath *path;
1807
1808   g_return_if_fail (GTK_IS_LIST_STORE (store));
1809   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1810   g_return_if_fail (iter_is_valid (a, store));
1811   g_return_if_fail (iter_is_valid (b, store));
1812
1813   priv = store->priv;
1814
1815   if (a->user_data == b->user_data)
1816     return;
1817
1818   old_positions = save_positions (priv->seq);
1819   
1820   g_sequence_swap (a->user_data, b->user_data);
1821
1822   order = generate_order (priv->seq, old_positions);
1823   path = gtk_tree_path_new ();
1824   
1825   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1826                                  path, NULL, order);
1827
1828   gtk_tree_path_free (path);
1829   g_free (order);
1830 }
1831
1832 static void
1833 gtk_list_store_move_to (GtkListStore *store,
1834                         GtkTreeIter  *iter,
1835                         gint          new_pos)
1836 {
1837   GtkListStorePrivate *priv = store->priv;
1838   GHashTable *old_positions;
1839   GtkTreePath *path;
1840   gint *order;
1841
1842   old_positions = save_positions (priv->seq);
1843
1844   g_sequence_move (iter->user_data, g_sequence_get_iter_at_pos (priv->seq, new_pos));
1845
1846   order = generate_order (priv->seq, old_positions);
1847
1848   path = gtk_tree_path_new ();
1849   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1850                                  path, NULL, order);
1851   gtk_tree_path_free (path);
1852   g_free (order);
1853 }
1854
1855 /**
1856  * gtk_list_store_move_before:
1857  * @store: A #GtkListStore.
1858  * @iter: A #GtkTreeIter.
1859  * @position: (allow-none): A #GtkTreeIter, or %NULL.
1860  *
1861  * Moves @iter in @store to the position before @position. Note that this
1862  * function only works with unsorted stores. If @position is %NULL, @iter
1863  * will be moved to the end of the list.
1864  *
1865  * Since: 2.2
1866  **/
1867 void
1868 gtk_list_store_move_before (GtkListStore *store,
1869                             GtkTreeIter  *iter,
1870                             GtkTreeIter  *position)
1871 {
1872   gint pos;
1873   
1874   g_return_if_fail (GTK_IS_LIST_STORE (store));
1875   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1876   g_return_if_fail (iter_is_valid (iter, store));
1877   if (position)
1878     g_return_if_fail (iter_is_valid (position, store));
1879
1880   if (position)
1881     pos = g_sequence_iter_get_position (position->user_data);
1882   else
1883     pos = -1;
1884   
1885   gtk_list_store_move_to (store, iter, pos);
1886 }
1887
1888 /**
1889  * gtk_list_store_move_after:
1890  * @store: A #GtkListStore.
1891  * @iter: A #GtkTreeIter.
1892  * @position: (allow-none): A #GtkTreeIter or %NULL.
1893  *
1894  * Moves @iter in @store to the position after @position. Note that this
1895  * function only works with unsorted stores. If @position is %NULL, @iter
1896  * will be moved to the start of the list.
1897  *
1898  * Since: 2.2
1899  **/
1900 void
1901 gtk_list_store_move_after (GtkListStore *store,
1902                            GtkTreeIter  *iter,
1903                            GtkTreeIter  *position)
1904 {
1905   gint pos;
1906   
1907   g_return_if_fail (GTK_IS_LIST_STORE (store));
1908   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1909   g_return_if_fail (iter_is_valid (iter, store));
1910   if (position)
1911     g_return_if_fail (iter_is_valid (position, store));
1912
1913   if (position)
1914     pos = g_sequence_iter_get_position (position->user_data) + 1;
1915   else
1916     pos = 0;
1917   
1918   gtk_list_store_move_to (store, iter, pos);
1919 }
1920     
1921 /* Sorting */
1922 static gint
1923 gtk_list_store_compare_func (GSequenceIter *a,
1924                              GSequenceIter *b,
1925                              gpointer      user_data)
1926 {
1927   GtkListStore *list_store = user_data;
1928   GtkListStorePrivate *priv = list_store->priv;
1929   GtkTreeIter iter_a;
1930   GtkTreeIter iter_b;
1931   gint retval;
1932   GtkTreeIterCompareFunc func;
1933   gpointer data;
1934
1935   if (priv->sort_column_id != -1)
1936     {
1937       GtkTreeDataSortHeader *header;
1938
1939       header = _gtk_tree_data_list_get_header (priv->sort_list,
1940                                                priv->sort_column_id);
1941       g_return_val_if_fail (header != NULL, 0);
1942       g_return_val_if_fail (header->func != NULL, 0);
1943
1944       func = header->func;
1945       data = header->data;
1946     }
1947   else
1948     {
1949       g_return_val_if_fail (priv->default_sort_func != NULL, 0);
1950       func = priv->default_sort_func;
1951       data = priv->default_sort_data;
1952     }
1953
1954   iter_a.stamp = priv->stamp;
1955   iter_a.user_data = (gpointer)a;
1956   iter_b.stamp = priv->stamp;
1957   iter_b.user_data = (gpointer)b;
1958
1959   g_assert (iter_is_valid (&iter_a, list_store));
1960   g_assert (iter_is_valid (&iter_b, list_store));
1961
1962   retval = (* func) (GTK_TREE_MODEL (list_store), &iter_a, &iter_b, data);
1963
1964   if (priv->order == GTK_SORT_DESCENDING)
1965     {
1966       if (retval > 0)
1967         retval = -1;
1968       else if (retval < 0)
1969         retval = 1;
1970     }
1971
1972   return retval;
1973 }
1974
1975 static void
1976 gtk_list_store_sort (GtkListStore *list_store)
1977 {
1978   GtkListStorePrivate *priv = list_store->priv;
1979   gint *new_order;
1980   GtkTreePath *path;
1981   GHashTable *old_positions;
1982
1983   if (!GTK_LIST_STORE_IS_SORTED (list_store) ||
1984       g_sequence_get_length (priv->seq) <= 1)
1985     return;
1986
1987   old_positions = save_positions (priv->seq);
1988
1989   g_sequence_sort_iter (priv->seq, gtk_list_store_compare_func, list_store);
1990
1991   /* Let the world know about our new order */
1992   new_order = generate_order (priv->seq, old_positions);
1993
1994   path = gtk_tree_path_new ();
1995   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
1996                                  path, NULL, new_order);
1997   gtk_tree_path_free (path);
1998   g_free (new_order);
1999 }
2000
2001 static gboolean
2002 iter_is_sorted (GtkListStore *list_store,
2003                 GtkTreeIter  *iter)
2004 {
2005   GSequenceIter *cmp;
2006
2007   if (!g_sequence_iter_is_begin (iter->user_data))
2008     {
2009       cmp = g_sequence_iter_prev (iter->user_data);
2010       if (gtk_list_store_compare_func (cmp, iter->user_data, list_store) > 0)
2011         return FALSE;
2012     }
2013
2014   cmp = g_sequence_iter_next (iter->user_data);
2015   if (!g_sequence_iter_is_end (cmp))
2016     {
2017       if (gtk_list_store_compare_func (iter->user_data, cmp, list_store) > 0)
2018         return FALSE;
2019     }
2020   
2021   return TRUE;
2022 }
2023
2024 static void
2025 gtk_list_store_sort_iter_changed (GtkListStore *list_store,
2026                                   GtkTreeIter  *iter,
2027                                   gint          column)
2028
2029 {
2030   GtkListStorePrivate *priv = list_store->priv;
2031   GtkTreePath *path;
2032
2033   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
2034   gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
2035   gtk_tree_path_free (path);
2036
2037   if (!iter_is_sorted (list_store, iter))
2038     {
2039       GHashTable *old_positions;
2040       gint *order;
2041
2042       old_positions = save_positions (priv->seq);
2043       g_sequence_sort_changed_iter (iter->user_data,
2044                                     gtk_list_store_compare_func,
2045                                     list_store);
2046       order = generate_order (priv->seq, old_positions);
2047       path = gtk_tree_path_new ();
2048       gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
2049                                      path, NULL, order);
2050       gtk_tree_path_free (path);
2051       g_free (order);
2052     }
2053 }
2054
2055 static gboolean
2056 gtk_list_store_get_sort_column_id (GtkTreeSortable  *sortable,
2057                                    gint             *sort_column_id,
2058                                    GtkSortType      *order)
2059 {
2060   GtkListStore *list_store = GTK_LIST_STORE (sortable);
2061   GtkListStorePrivate *priv = list_store->priv;
2062
2063   if (sort_column_id)
2064     * sort_column_id = priv->sort_column_id;
2065   if (order)
2066     * order = priv->order;
2067
2068   if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID ||
2069       priv->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
2070     return FALSE;
2071
2072   return TRUE;
2073 }
2074
2075 static void
2076 gtk_list_store_set_sort_column_id (GtkTreeSortable  *sortable,
2077                                    gint              sort_column_id,
2078                                    GtkSortType       order)
2079 {
2080   GtkListStore *list_store = GTK_LIST_STORE (sortable);
2081   GtkListStorePrivate *priv = list_store->priv;
2082
2083   if ((priv->sort_column_id == sort_column_id) &&
2084       (priv->order == order))
2085     return;
2086
2087   if (sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
2088     {
2089       if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
2090         {
2091           GtkTreeDataSortHeader *header = NULL;
2092
2093           header = _gtk_tree_data_list_get_header (priv->sort_list, 
2094                                                    sort_column_id);
2095
2096           /* We want to make sure that we have a function */
2097           g_return_if_fail (header != NULL);
2098           g_return_if_fail (header->func != NULL);
2099         }
2100       else
2101         {
2102           g_return_if_fail (priv->default_sort_func != NULL);
2103         }
2104     }
2105
2106
2107   priv->sort_column_id = sort_column_id;
2108   priv->order = order;
2109
2110   gtk_tree_sortable_sort_column_changed (sortable);
2111
2112   gtk_list_store_sort (list_store);
2113 }
2114
2115 static void
2116 gtk_list_store_set_sort_func (GtkTreeSortable        *sortable,
2117                               gint                    sort_column_id,
2118                               GtkTreeIterCompareFunc  func,
2119                               gpointer                data,
2120                               GDestroyNotify          destroy)
2121 {
2122   GtkListStore *list_store = GTK_LIST_STORE (sortable);
2123   GtkListStorePrivate *priv = list_store->priv;
2124
2125   priv->sort_list = _gtk_tree_data_list_set_header (priv->sort_list, 
2126                                                           sort_column_id, 
2127                                                           func, data, destroy);
2128
2129   if (priv->sort_column_id == sort_column_id)
2130     gtk_list_store_sort (list_store);
2131 }
2132
2133 static void
2134 gtk_list_store_set_default_sort_func (GtkTreeSortable        *sortable,
2135                                       GtkTreeIterCompareFunc  func,
2136                                       gpointer                data,
2137                                       GDestroyNotify          destroy)
2138 {
2139   GtkListStore *list_store = GTK_LIST_STORE (sortable);
2140   GtkListStorePrivate *priv = list_store->priv;
2141
2142   if (priv->default_sort_destroy)
2143     {
2144       GDestroyNotify d = priv->default_sort_destroy;
2145
2146       priv->default_sort_destroy = NULL;
2147       d (priv->default_sort_data);
2148     }
2149
2150   priv->default_sort_func = func;
2151   priv->default_sort_data = data;
2152   priv->default_sort_destroy = destroy;
2153
2154   if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
2155     gtk_list_store_sort (list_store);
2156 }
2157
2158 static gboolean
2159 gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable)
2160 {
2161   GtkListStore *list_store = GTK_LIST_STORE (sortable);
2162   GtkListStorePrivate *priv = list_store->priv;
2163
2164   return (priv->default_sort_func != NULL);
2165 }
2166
2167
2168 /**
2169  * gtk_list_store_insert_with_values:
2170  * @list_store: A #GtkListStore
2171  * @iter: (out) (allow-none): An unset #GtkTreeIter to set to the new row, or %NULL
2172  * @position: position to insert the new row, or -1 to append after existing
2173  *     rows
2174  * @...: pairs of column number and value, terminated with -1
2175  *
2176  * Creates a new row at @position. @iter will be changed to point to this new
2177  * row. If @position is -1, or larger than the number of rows in the list, then
2178  * the new row will be appended to the list. The row will be filled with the
2179  * values given to this function.
2180  *
2181  * Calling
2182  * <literal>gtk_list_store_insert_with_values (list_store, iter, position...)</literal>
2183  * has the same effect as calling
2184  * |[
2185  * gtk_list_store_insert (list_store, iter, position);
2186  * gtk_list_store_set (list_store, iter, ...);
2187  * ]|
2188  * with the difference that the former will only emit a row_inserted signal,
2189  * while the latter will emit row_inserted, row_changed and, if the list store
2190  * is sorted, rows_reordered. Since emitting the rows_reordered signal
2191  * repeatedly can affect the performance of the program,
2192  * gtk_list_store_insert_with_values() should generally be preferred when
2193  * inserting rows in a sorted list store.
2194  *
2195  * Since: 2.6
2196  */
2197 void
2198 gtk_list_store_insert_with_values (GtkListStore *list_store,
2199                                    GtkTreeIter  *iter,
2200                                    gint          position,
2201                                    ...)
2202 {
2203   GtkListStorePrivate *priv;
2204   GtkTreePath *path;
2205   GSequence *seq;
2206   GSequenceIter *ptr;
2207   GtkTreeIter tmp_iter;
2208   gint length;
2209   gboolean changed = FALSE;
2210   gboolean maybe_need_sort = FALSE;
2211   va_list var_args;
2212
2213   /* FIXME: refactor to reduce overlap with gtk_list_store_set() */
2214   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
2215
2216   priv = list_store->priv;
2217
2218   if (!iter)
2219     iter = &tmp_iter;
2220
2221   priv->columns_dirty = TRUE;
2222
2223   seq = priv->seq;
2224
2225   length = g_sequence_get_length (seq);
2226   if (position > length)
2227     position = length;
2228
2229   ptr = g_sequence_get_iter_at_pos (seq, position);
2230   ptr = g_sequence_insert_before (ptr, NULL);
2231
2232   iter->stamp = priv->stamp;
2233   iter->user_data = ptr;
2234
2235   g_assert (iter_is_valid (iter, list_store));
2236
2237   priv->length++;
2238
2239   va_start (var_args, position);
2240   gtk_list_store_set_valist_internal (list_store, iter, 
2241                                       &changed, &maybe_need_sort,
2242                                       var_args);
2243   va_end (var_args);
2244
2245   /* Don't emit rows_reordered here */
2246   if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
2247     g_sequence_sort_changed_iter (iter->user_data,
2248                                   gtk_list_store_compare_func,
2249                                   list_store);
2250
2251   /* Just emit row_inserted */
2252   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
2253   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
2254   gtk_tree_path_free (path);
2255 }
2256
2257
2258 /**
2259  * gtk_list_store_insert_with_valuesv:
2260  * @list_store: A #GtkListStore
2261  * @iter: (out) (allow-none): An unset #GtkTreeIter to set to the new row, or %NULL.
2262  * @position: position to insert the new row
2263  * @columns: (array length=n_values): an array of column numbers
2264  * @values: (array length=n_values): an array of GValues 
2265  * @n_values: the length of the @columns and @values arrays
2266  * 
2267  * A variant of gtk_list_store_insert_with_values() which
2268  * takes the columns and values as two arrays, instead of
2269  * varargs. This function is mainly intended for 
2270  * language-bindings.
2271  *
2272  * Since: 2.6
2273  */
2274 void
2275 gtk_list_store_insert_with_valuesv (GtkListStore *list_store,
2276                                     GtkTreeIter  *iter,
2277                                     gint          position,
2278                                     gint         *columns, 
2279                                     GValue       *values,
2280                                     gint          n_values)
2281 {
2282   GtkListStorePrivate *priv;
2283   GtkTreePath *path;
2284   GSequence *seq;
2285   GSequenceIter *ptr;
2286   GtkTreeIter tmp_iter;
2287   gint length;
2288   gboolean changed = FALSE;
2289   gboolean maybe_need_sort = FALSE;
2290
2291   /* FIXME refactor to reduce overlap with 
2292    * gtk_list_store_insert_with_values() 
2293    */
2294   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
2295
2296   priv = list_store->priv;
2297
2298   if (!iter)
2299     iter = &tmp_iter;
2300
2301   priv->columns_dirty = TRUE;
2302
2303   seq = priv->seq;
2304
2305   length = g_sequence_get_length (seq);
2306   if (position > length)
2307     position = length;
2308
2309   ptr = g_sequence_get_iter_at_pos (seq, position);
2310   ptr = g_sequence_insert_before (ptr, NULL);
2311
2312   iter->stamp = priv->stamp;
2313   iter->user_data = ptr;
2314
2315   g_assert (iter_is_valid (iter, list_store));
2316
2317   priv->length++;  
2318
2319   gtk_list_store_set_vector_internal (list_store, iter,
2320                                       &changed, &maybe_need_sort,
2321                                       columns, values, n_values);
2322
2323   /* Don't emit rows_reordered here */
2324   if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
2325     g_sequence_sort_changed_iter (iter->user_data,
2326                                   gtk_list_store_compare_func,
2327                                   list_store);
2328
2329   /* Just emit row_inserted */
2330   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
2331   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
2332   gtk_tree_path_free (path);
2333 }
2334
2335 /* GtkBuildable custom tag implementation
2336  *
2337  * <columns>
2338  *   <column type="..."/>
2339  *   <column type="..."/>
2340  * </columns>
2341  */
2342 typedef struct {
2343   gboolean translatable;
2344   gchar *context;
2345   int id;
2346 } ColInfo;
2347
2348 typedef struct {
2349   GtkBuilder *builder;
2350   GObject *object;
2351   GSList *column_type_names;
2352   GType *column_types;
2353   GValue *values;
2354   gint *colids;
2355   ColInfo **columns;
2356   gint last_row;
2357   gint n_columns;
2358   gint row_column;
2359   GQuark error_quark;
2360   gboolean is_data;
2361   const gchar *domain;
2362 } SubParserData;
2363
2364 static void
2365 list_store_start_element (GMarkupParseContext *context,
2366                           const gchar         *element_name,
2367                           const gchar        **names,
2368                           const gchar        **values,
2369                           gpointer             user_data,
2370                           GError             **error)
2371 {
2372   guint i;
2373   SubParserData *data = (SubParserData*)user_data;
2374
2375   if (strcmp (element_name, "col") == 0)
2376     {
2377       int i, id = -1;
2378       gchar *context = NULL;
2379       gboolean translatable = FALSE;
2380       ColInfo *info;
2381
2382       if (data->row_column >= data->n_columns)
2383         {
2384           g_set_error (error, data->error_quark, 0,
2385                        "Too many columns, maximum is %d\n", data->n_columns - 1);
2386           return;
2387         }
2388
2389       for (i = 0; names[i]; i++)
2390         if (strcmp (names[i], "id") == 0)
2391           {
2392             errno = 0;
2393             id = atoi (values[i]);
2394             if (errno)
2395               {
2396                 g_set_error (error, data->error_quark, 0,
2397                              "the id tag %s could not be converted to an integer",
2398                              values[i]);
2399                 return;
2400               }
2401             if (id < 0 || id >= data->n_columns)
2402               {
2403                 g_set_error (error, data->error_quark, 0,
2404                              "id value %d out of range", id);
2405                 return;
2406               }
2407           }
2408         else if (strcmp (names[i], "translatable") == 0)
2409           {
2410             if (!_gtk_builder_boolean_from_string (values[i], &translatable,
2411                                                    error))
2412               return;
2413           }
2414         else if (strcmp (names[i], "comments") == 0)
2415           {
2416             /* do nothing, comments are for translators */
2417           }
2418         else if (strcmp (names[i], "context") == 0) 
2419           {
2420             context = g_strdup (values[i]);
2421           }
2422
2423       if (id == -1)
2424         {
2425           g_set_error (error, data->error_quark, 0,
2426                        "<col> needs an id attribute");
2427           return;
2428         }
2429       
2430       info = g_slice_new0 (ColInfo);
2431       info->translatable = translatable;
2432       info->context = context;
2433       info->id = id;
2434
2435       data->colids[data->row_column] = id;
2436       data->columns[data->row_column] = info;
2437       data->row_column++;
2438       data->is_data = TRUE;
2439     }
2440   else if (strcmp (element_name, "row") == 0)
2441     ;
2442   else if (strcmp (element_name, "column") == 0)
2443     for (i = 0; names[i]; i++)
2444       if (strcmp (names[i], "type") == 0)
2445         data->column_type_names = g_slist_prepend (data->column_type_names,
2446                                                    g_strdup (values[i]));
2447   else if (strcmp (element_name, "columns") == 0)
2448     ;
2449   else if (strcmp (element_name, "data") == 0)
2450     ;
2451   else
2452     g_set_error (error, data->error_quark, 0,
2453                  "Unknown start tag: %s", element_name);
2454 }
2455
2456 static void
2457 list_store_end_element (GMarkupParseContext *context,
2458                         const gchar         *element_name,
2459                         gpointer             user_data,
2460                         GError             **error)
2461 {
2462   SubParserData *data = (SubParserData*)user_data;
2463
2464   g_assert (data->builder);
2465   
2466   if (strcmp (element_name, "row") == 0)
2467     {
2468       GtkTreeIter iter;
2469       int i;
2470
2471       gtk_list_store_insert_with_valuesv (GTK_LIST_STORE (data->object),
2472                                           &iter,
2473                                           data->last_row,
2474                                           data->colids,
2475                                           data->values,
2476                                           data->row_column);
2477       for (i = 0; i < data->row_column; i++)
2478         {
2479           ColInfo *info = data->columns[i];
2480           g_free (info->context);
2481           g_slice_free (ColInfo, info);
2482           data->columns[i] = NULL;
2483           g_value_unset (&data->values[i]);
2484         }
2485       g_free (data->values);
2486       data->values = g_new0 (GValue, data->n_columns);
2487       data->last_row++;
2488       data->row_column = 0;
2489     }
2490   else if (strcmp (element_name, "columns") == 0)
2491     {
2492       GType *column_types;
2493       GSList *l;
2494       int i;
2495       GType type;
2496
2497       data->column_type_names = g_slist_reverse (data->column_type_names);
2498       column_types = g_new0 (GType, g_slist_length (data->column_type_names));
2499
2500       for (l = data->column_type_names, i = 0; l; l = l->next, i++)
2501         {
2502           type = gtk_builder_get_type_from_name (data->builder, l->data);
2503           if (type == G_TYPE_INVALID)
2504             {
2505               g_warning ("Unknown type %s specified in treemodel %s",
2506                          (const gchar*)l->data,
2507                          gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
2508               continue;
2509             }
2510           column_types[i] = type;
2511
2512           g_free (l->data);
2513         }
2514
2515       gtk_list_store_set_column_types (GTK_LIST_STORE (data->object), i,
2516                                        column_types);
2517
2518       g_free (column_types);
2519     }
2520   else if (strcmp (element_name, "col") == 0)
2521     data->is_data = FALSE;
2522   else if (strcmp (element_name, "data") == 0)
2523     ;
2524   else if (strcmp (element_name, "column") == 0)
2525     ;
2526   else
2527     g_set_error (error, data->error_quark, 0,
2528                  "Unknown end tag: %s", element_name);
2529 }
2530
2531 static void
2532 list_store_text (GMarkupParseContext *context,
2533                  const gchar         *text,
2534                  gsize                text_len,
2535                  gpointer             user_data,
2536                  GError             **error)
2537 {
2538   SubParserData *data = (SubParserData*)user_data;
2539   gint i;
2540   GError *tmp_error = NULL;
2541   gchar *string;
2542   ColInfo *info;
2543   
2544   if (!data->is_data)
2545     return;
2546
2547   i = data->row_column - 1;
2548   info = data->columns[i];
2549
2550   string = g_strndup (text, text_len);
2551   if (info->translatable && text_len)
2552     {
2553       gchar *translated;
2554
2555       /* FIXME: This will not use the domain set in the .ui file,
2556        * since the parser is not telling the builder about the domain.
2557        * However, it will work for gtk_builder_set_translation_domain() calls.
2558        */
2559       translated = _gtk_builder_parser_translate (data->domain,
2560                                                   info->context,
2561                                                   string);
2562       g_free (string);
2563       string = translated;
2564     }
2565
2566   if (!gtk_builder_value_from_string_type (data->builder,
2567                                            data->column_types[info->id],
2568                                            string,
2569                                            &data->values[i],
2570                                            &tmp_error))
2571     {
2572       g_set_error (error,
2573                    tmp_error->domain,
2574                    tmp_error->code,
2575                    "Could not convert '%s' to type %s: %s\n",
2576                    text, g_type_name (data->column_types[info->id]),
2577                    tmp_error->message);
2578       g_error_free (tmp_error);
2579     }
2580   g_free (string);
2581 }
2582
2583 static const GMarkupParser list_store_parser =
2584   {
2585     list_store_start_element,
2586     list_store_end_element,
2587     list_store_text
2588   };
2589
2590 static gboolean
2591 gtk_list_store_buildable_custom_tag_start (GtkBuildable  *buildable,
2592                                            GtkBuilder    *builder,
2593                                            GObject       *child,
2594                                            const gchar   *tagname,
2595                                            GMarkupParser *parser,
2596                                            gpointer      *data)
2597 {
2598   SubParserData *parser_data;
2599
2600   if (child)
2601     return FALSE;
2602
2603   if (strcmp (tagname, "columns") == 0)
2604     {
2605
2606       parser_data = g_slice_new0 (SubParserData);
2607       parser_data->builder = builder;
2608       parser_data->object = G_OBJECT (buildable);
2609       parser_data->column_type_names = NULL;
2610
2611       *parser = list_store_parser;
2612       *data = parser_data;
2613       return TRUE;
2614     }
2615   else if (strcmp (tagname, "data") == 0)
2616     {
2617       gint n_columns = gtk_list_store_get_n_columns (GTK_TREE_MODEL (buildable));
2618       if (n_columns == 0)
2619         g_error ("Cannot append data to an empty model");
2620
2621       parser_data = g_slice_new0 (SubParserData);
2622       parser_data->builder = builder;
2623       parser_data->object = G_OBJECT (buildable);
2624       parser_data->values = g_new0 (GValue, n_columns);
2625       parser_data->colids = g_new0 (gint, n_columns);
2626       parser_data->columns = g_new0 (ColInfo*, n_columns);
2627       parser_data->column_types = GTK_LIST_STORE (buildable)->priv->column_headers;
2628       parser_data->n_columns = n_columns;
2629       parser_data->last_row = 0;
2630       parser_data->error_quark = g_quark_from_static_string ("GtkListStore");
2631       parser_data->domain = gtk_builder_get_translation_domain (builder);
2632       
2633       *parser = list_store_parser;
2634       *data = parser_data;
2635       return TRUE;
2636     }
2637   else
2638     g_warning ("Unknown custom list store tag: %s", tagname);
2639   
2640   return FALSE;
2641 }
2642
2643 static void
2644 gtk_list_store_buildable_custom_tag_end (GtkBuildable *buildable,
2645                                          GtkBuilder   *builder,
2646                                          GObject      *child,
2647                                          const gchar  *tagname,
2648                                          gpointer     *data)
2649 {
2650   SubParserData *sub = (SubParserData*)data;
2651   
2652   if (strcmp (tagname, "columns") == 0)
2653     {
2654       g_slist_free (sub->column_type_names);
2655       g_slice_free (SubParserData, sub);
2656     }
2657   else if (strcmp (tagname, "data") == 0)
2658     {
2659       int i;
2660       for (i = 0; i < sub->n_columns; i++)
2661         {
2662           ColInfo *info = sub->columns[i];
2663           if (info)
2664             {
2665               g_free (info->context);
2666               g_slice_free (ColInfo, info);
2667             }
2668         }
2669       g_free (sub->colids);
2670       g_free (sub->columns);
2671       g_free (sub->values);
2672       g_slice_free (SubParserData, sub);
2673     }
2674   else
2675     g_warning ("Unknown custom list store tag: %s", tagname);
2676 }