]> Pileus Git - ~andy/gtk/blob - gtk/gtkliststore.c
stylecontext: Do invalidation on first resize container
[~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_list_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_transformable (G_VALUE_TYPE (value), priv->column_headers[column])))
846         {
847           g_warning ("%s: Unable to convert from %s to %s\n",
848                      G_STRLOC,
849                      g_type_name (G_VALUE_TYPE (value)),
850                      g_type_name (priv->column_headers[column]));
851           return retval;
852         }
853
854       g_value_init (&real_value, priv->column_headers[column]);
855       if (!g_value_transform (value, &real_value))
856         {
857           g_warning ("%s: Unable to make conversion from %s to %s\n",
858                      G_STRLOC,
859                      g_type_name (G_VALUE_TYPE (value)),
860                      g_type_name (priv->column_headers[column]));
861           g_value_unset (&real_value);
862           return retval;
863         }
864       converted = TRUE;
865     }
866
867   prev = list = g_sequence_get (iter->user_data);
868
869   while (list != NULL)
870     {
871       if (column == 0)
872         {
873           if (converted)
874             _gtk_tree_data_list_value_to_node (list, &real_value);
875           else
876             _gtk_tree_data_list_value_to_node (list, value);
877           retval = TRUE;
878           if (converted)
879             g_value_unset (&real_value);
880          if (sort && GTK_LIST_STORE_IS_SORTED (list_store))
881             gtk_list_store_sort_iter_changed (list_store, iter, old_column);
882           return retval;
883         }
884
885       column--;
886       prev = list;
887       list = list->next;
888     }
889
890   if (g_sequence_get (iter->user_data) == NULL)
891     {
892       list = _gtk_tree_data_list_alloc();
893       g_sequence_set (iter->user_data, list);
894       list->next = NULL;
895     }
896   else
897     {
898       list = prev->next = _gtk_tree_data_list_alloc ();
899       list->next = NULL;
900     }
901
902   while (column != 0)
903     {
904       list->next = _gtk_tree_data_list_alloc ();
905       list = list->next;
906       list->next = NULL;
907       column --;
908     }
909
910   if (converted)
911     _gtk_tree_data_list_value_to_node (list, &real_value);
912   else
913     _gtk_tree_data_list_value_to_node (list, value);
914
915   retval = TRUE;
916   if (converted)
917     g_value_unset (&real_value);
918
919   if (sort && GTK_LIST_STORE_IS_SORTED (list_store))
920     gtk_list_store_sort_iter_changed (list_store, iter, old_column);
921
922   return retval;
923 }
924
925
926 /**
927  * gtk_list_store_set_value:
928  * @list_store: A #GtkListStore
929  * @iter: A valid #GtkTreeIter for the row being modified
930  * @column: column number to modify
931  * @value: new value for the cell
932  *
933  * Sets the data in the cell specified by @iter and @column.
934  * The type of @value must be convertible to the type of the
935  * column.
936  *
937  **/
938 void
939 gtk_list_store_set_value (GtkListStore *list_store,
940                           GtkTreeIter  *iter,
941                           gint          column,
942                           GValue       *value)
943 {
944   GtkListStorePrivate *priv;
945
946   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
947   g_return_if_fail (iter_is_valid (iter, list_store));
948   g_return_if_fail (G_IS_VALUE (value));
949   priv = list_store->priv;
950   g_return_if_fail (column >= 0 && column < priv->n_columns);
951
952   if (gtk_list_store_real_set_value (list_store, iter, column, value, TRUE))
953     {
954       GtkTreePath *path;
955
956       path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
957       gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
958       gtk_tree_path_free (path);
959     }
960 }
961
962 static GtkTreeIterCompareFunc
963 gtk_list_store_get_compare_func (GtkListStore *list_store)
964 {
965   GtkListStorePrivate *priv = list_store->priv;
966   GtkTreeIterCompareFunc func = NULL;
967
968   if (GTK_LIST_STORE_IS_SORTED (list_store))
969     {
970       if (priv->sort_column_id != -1)
971         {
972           GtkTreeDataSortHeader *header;
973           header = _gtk_tree_data_list_get_header (priv->sort_list,
974                                                    priv->sort_column_id);
975           g_return_val_if_fail (header != NULL, NULL);
976           g_return_val_if_fail (header->func != NULL, NULL);
977           func = header->func;
978         }
979       else
980         {
981           func = priv->default_sort_func;
982         }
983     }
984
985   return func;
986 }
987
988 static void
989 gtk_list_store_set_vector_internal (GtkListStore *list_store,
990                                     GtkTreeIter  *iter,
991                                     gboolean     *emit_signal,
992                                     gboolean     *maybe_need_sort,
993                                     gint         *columns,
994                                     GValue       *values,
995                                     gint          n_values)
996 {
997   GtkListStorePrivate *priv = list_store->priv;
998   gint i;
999   GtkTreeIterCompareFunc func = NULL;
1000
1001   func = gtk_list_store_get_compare_func (list_store);
1002   if (func != _gtk_tree_data_list_compare_func)
1003     *maybe_need_sort = TRUE;
1004
1005   for (i = 0; i < n_values; i++)
1006     {
1007       *emit_signal = gtk_list_store_real_set_value (list_store, 
1008                                                iter, 
1009                                                columns[i],
1010                                                &values[i],
1011                                                FALSE) || *emit_signal;
1012
1013       if (func == _gtk_tree_data_list_compare_func &&
1014           columns[i] == priv->sort_column_id)
1015         *maybe_need_sort = TRUE;
1016     }
1017 }
1018
1019 static void
1020 gtk_list_store_set_valist_internal (GtkListStore *list_store,
1021                                     GtkTreeIter  *iter,
1022                                     gboolean     *emit_signal,
1023                                     gboolean     *maybe_need_sort,
1024                                     va_list       var_args)
1025 {
1026   GtkListStorePrivate *priv = list_store->priv;
1027   gint column;
1028   GtkTreeIterCompareFunc func = NULL;
1029
1030   column = va_arg (var_args, gint);
1031
1032   func = gtk_list_store_get_compare_func (list_store);
1033   if (func != _gtk_tree_data_list_compare_func)
1034     *maybe_need_sort = TRUE;
1035
1036   while (column != -1)
1037     {
1038       GValue value = G_VALUE_INIT;
1039       gchar *error = NULL;
1040
1041       if (column < 0 || column >= priv->n_columns)
1042         {
1043           g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
1044           break;
1045         }
1046
1047       G_VALUE_COLLECT_INIT (&value, priv->column_headers[column],
1048                             var_args, 0, &error);
1049       if (error)
1050         {
1051           g_warning ("%s: %s", G_STRLOC, error);
1052           g_free (error);
1053
1054           /* we purposely leak the value here, it might not be
1055            * in a sane state if an error condition occoured
1056            */
1057           break;
1058         }
1059
1060       /* FIXME: instead of calling this n times, refactor with above */
1061       *emit_signal = gtk_list_store_real_set_value (list_store,
1062                                                     iter,
1063                                                     column,
1064                                                     &value,
1065                                                     FALSE) || *emit_signal;
1066       
1067       if (func == _gtk_tree_data_list_compare_func &&
1068           column == priv->sort_column_id)
1069         *maybe_need_sort = TRUE;
1070
1071       g_value_unset (&value);
1072
1073       column = va_arg (var_args, gint);
1074     }
1075 }
1076
1077 /**
1078  * gtk_list_store_set_valuesv:
1079  * @list_store: A #GtkListStore
1080  * @iter: A valid #GtkTreeIter for the row being modified
1081  * @columns: (array length=n_values): an array of column numbers
1082  * @values: (array length=n_values): an array of GValues
1083  * @n_values: the length of the @columns and @values arrays
1084  *
1085  * A variant of gtk_list_store_set_valist() which
1086  * takes the columns and values as two arrays, instead of
1087  * varargs. This function is mainly intended for 
1088  * language-bindings and in case the number of columns to
1089  * change is not known until run-time.
1090  *
1091  * Since: 2.12
1092  * Rename to: gtk_list_store_set
1093  */
1094 void
1095 gtk_list_store_set_valuesv (GtkListStore *list_store,
1096                             GtkTreeIter  *iter,
1097                             gint         *columns,
1098                             GValue       *values,
1099                             gint          n_values)
1100 {
1101   GtkListStorePrivate *priv;
1102   gboolean emit_signal = FALSE;
1103   gboolean maybe_need_sort = FALSE;
1104
1105   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1106   g_return_if_fail (iter_is_valid (iter, list_store));
1107
1108   priv = list_store->priv;
1109
1110   gtk_list_store_set_vector_internal (list_store, iter,
1111                                       &emit_signal,
1112                                       &maybe_need_sort,
1113                                       columns, values, n_values);
1114
1115   if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
1116     gtk_list_store_sort_iter_changed (list_store, iter, priv->sort_column_id);
1117
1118   if (emit_signal)
1119     {
1120       GtkTreePath *path;
1121
1122       path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
1123       gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
1124       gtk_tree_path_free (path);
1125     }
1126 }
1127
1128 /**
1129  * gtk_list_store_set_valist:
1130  * @list_store: A #GtkListStore
1131  * @iter: A valid #GtkTreeIter for the row being modified
1132  * @var_args: va_list of column/value pairs
1133  *
1134  * See gtk_list_store_set(); this version takes a va_list for use by language
1135  * bindings.
1136  *
1137  **/
1138 void
1139 gtk_list_store_set_valist (GtkListStore *list_store,
1140                            GtkTreeIter  *iter,
1141                            va_list       var_args)
1142 {
1143   GtkListStorePrivate *priv;
1144   gboolean emit_signal = FALSE;
1145   gboolean maybe_need_sort = FALSE;
1146
1147   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1148   g_return_if_fail (iter_is_valid (iter, list_store));
1149
1150   priv = list_store->priv;
1151
1152   gtk_list_store_set_valist_internal (list_store, iter, 
1153                                       &emit_signal, 
1154                                       &maybe_need_sort,
1155                                       var_args);
1156
1157   if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
1158     gtk_list_store_sort_iter_changed (list_store, iter, priv->sort_column_id);
1159
1160   if (emit_signal)
1161     {
1162       GtkTreePath *path;
1163
1164       path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
1165       gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
1166       gtk_tree_path_free (path);
1167     }
1168 }
1169
1170 /**
1171  * gtk_list_store_set:
1172  * @list_store: a #GtkListStore
1173  * @iter: row iterator
1174  * @...: pairs of column number and value, terminated with -1
1175  *
1176  * Sets the value of one or more cells in the row referenced by @iter.
1177  * The variable argument list should contain integer column numbers,
1178  * each column number followed by the value to be set.
1179  * The list is terminated by a -1. For example, to set column 0 with type
1180  * %G_TYPE_STRING to "Foo", you would write <literal>gtk_list_store_set (store, iter,
1181  * 0, "Foo", -1)</literal>.
1182  *
1183  * The value will be referenced by the store if it is a %G_TYPE_OBJECT, and it
1184  * will be copied if it is a %G_TYPE_STRING or %G_TYPE_BOXED.
1185  */
1186 void
1187 gtk_list_store_set (GtkListStore *list_store,
1188                     GtkTreeIter  *iter,
1189                     ...)
1190 {
1191   va_list var_args;
1192
1193   va_start (var_args, iter);
1194   gtk_list_store_set_valist (list_store, iter, var_args);
1195   va_end (var_args);
1196 }
1197
1198 /**
1199  * gtk_list_store_remove:
1200  * @list_store: A #GtkListStore
1201  * @iter: A valid #GtkTreeIter
1202  *
1203  * Removes the given row from the list store.  After being removed, 
1204  * @iter is set to be the next valid row, or invalidated if it pointed 
1205  * to the last row in @list_store.
1206  *
1207  * Return value: %TRUE if @iter is valid, %FALSE if not.
1208  **/
1209 gboolean
1210 gtk_list_store_remove (GtkListStore *list_store,
1211                        GtkTreeIter  *iter)
1212 {
1213   GtkListStorePrivate *priv;
1214   GtkTreePath *path;
1215   GSequenceIter *ptr, *next;
1216
1217   g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
1218   g_return_val_if_fail (iter_is_valid (iter, list_store), FALSE);
1219
1220   priv = list_store->priv;
1221
1222   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
1223
1224   ptr = iter->user_data;
1225   next = g_sequence_iter_next (ptr);
1226   
1227   _gtk_tree_data_list_free (g_sequence_get (ptr), priv->column_headers);
1228   g_sequence_remove (iter->user_data);
1229
1230   priv->length--;
1231   
1232   gtk_tree_model_row_deleted (GTK_TREE_MODEL (list_store), path);
1233   gtk_tree_path_free (path);
1234
1235   if (g_sequence_iter_is_end (next))
1236     {
1237       iter->stamp = 0;
1238       return FALSE;
1239     }
1240   else
1241     {
1242       iter->stamp = priv->stamp;
1243       iter->user_data = next;
1244       return TRUE;
1245     }
1246 }
1247
1248 /**
1249  * gtk_list_store_insert:
1250  * @list_store: A #GtkListStore
1251  * @iter: (out): An unset #GtkTreeIter to set to the new row
1252  * @position: position to insert the new row, or -1 for last
1253  *
1254  * Creates a new row at @position.  @iter will be changed to point to this new
1255  * row.  If @position is -1 or is larger than the number of rows on the list,
1256  * then the new row will be appended to the list. The row will be empty after
1257  * this function is called.  To fill in values, you need to call
1258  * gtk_list_store_set() or gtk_list_store_set_value().
1259  *
1260  **/
1261 void
1262 gtk_list_store_insert (GtkListStore *list_store,
1263                        GtkTreeIter  *iter,
1264                        gint          position)
1265 {
1266   GtkListStorePrivate *priv;
1267   GtkTreePath *path;
1268   GSequence *seq;
1269   GSequenceIter *ptr;
1270   gint length;
1271
1272   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1273   g_return_if_fail (iter != NULL);
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 || position < 0)
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   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1408   g_return_if_fail (iter != NULL);
1409
1410   gtk_list_store_insert (list_store, iter, -1);
1411 }
1412
1413 static void
1414 gtk_list_store_increment_stamp (GtkListStore *list_store)
1415 {
1416   GtkListStorePrivate *priv = list_store->priv;
1417
1418   do
1419     {
1420       priv->stamp++;
1421     }
1422   while (priv->stamp == 0);
1423 }
1424
1425 /**
1426  * gtk_list_store_clear:
1427  * @list_store: a #GtkListStore.
1428  *
1429  * Removes all rows from the list store.  
1430  *
1431  **/
1432 void
1433 gtk_list_store_clear (GtkListStore *list_store)
1434 {
1435   GtkListStorePrivate *priv;
1436   GtkTreeIter iter;
1437
1438   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1439
1440   priv = list_store->priv;
1441
1442   while (g_sequence_get_length (priv->seq) > 0)
1443     {
1444       iter.stamp = priv->stamp;
1445       iter.user_data = g_sequence_get_begin_iter (priv->seq);
1446       gtk_list_store_remove (list_store, &iter);
1447     }
1448
1449   gtk_list_store_increment_stamp (list_store);
1450 }
1451
1452 /**
1453  * gtk_list_store_iter_is_valid:
1454  * @list_store: A #GtkListStore.
1455  * @iter: A #GtkTreeIter.
1456  *
1457  * <warning>This function is slow. Only use it for debugging and/or testing
1458  * purposes.</warning>
1459  *
1460  * Checks if the given iter is a valid iter for this #GtkListStore.
1461  *
1462  * Return value: %TRUE if the iter is valid, %FALSE if the iter is invalid.
1463  *
1464  * Since: 2.2
1465  **/
1466 gboolean
1467 gtk_list_store_iter_is_valid (GtkListStore *list_store,
1468                               GtkTreeIter  *iter)
1469 {
1470   g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
1471   g_return_val_if_fail (iter != NULL, FALSE);
1472
1473   return iter_is_valid (iter, list_store);
1474 }
1475
1476 static gboolean real_gtk_list_store_row_draggable (GtkTreeDragSource *drag_source,
1477                                                    GtkTreePath       *path)
1478 {
1479   return TRUE;
1480 }
1481   
1482 static gboolean
1483 gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
1484                                  GtkTreePath       *path)
1485 {
1486   GtkTreeIter iter;
1487
1488   if (gtk_list_store_get_iter (GTK_TREE_MODEL (drag_source),
1489                                &iter,
1490                                path))
1491     {
1492       gtk_list_store_remove (GTK_LIST_STORE (drag_source), &iter);
1493       return TRUE;
1494     }
1495   return FALSE;
1496 }
1497
1498 static gboolean
1499 gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
1500                               GtkTreePath       *path,
1501                               GtkSelectionData  *selection_data)
1502 {
1503   /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1504    * target, because the default handler does it for us, but
1505    * we do anyway for the convenience of someone maybe overriding the
1506    * default handler.
1507    */
1508
1509   if (gtk_tree_set_row_drag_data (selection_data,
1510                                   GTK_TREE_MODEL (drag_source),
1511                                   path))
1512     {
1513       return TRUE;
1514     }
1515   else
1516     {
1517       /* FIXME handle text targets at least. */
1518     }
1519
1520   return FALSE;
1521 }
1522
1523 static gboolean
1524 gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
1525                                    GtkTreePath       *dest,
1526                                    GtkSelectionData  *selection_data)
1527 {
1528   GtkTreeModel *tree_model = GTK_TREE_MODEL (drag_dest);
1529   GtkListStore *list_store = GTK_LIST_STORE (tree_model);
1530   GtkListStorePrivate *priv = list_store->priv;
1531   GtkTreeModel *src_model = NULL;
1532   GtkTreePath *src_path = NULL;
1533   gboolean retval = FALSE;
1534
1535   if (gtk_tree_get_row_drag_data (selection_data,
1536                                   &src_model,
1537                                   &src_path) &&
1538       src_model == tree_model)
1539     {
1540       /* Copy the given row to a new position */
1541       GtkTreeIter src_iter;
1542       GtkTreeIter dest_iter;
1543       GtkTreePath *prev;
1544
1545       if (!gtk_list_store_get_iter (src_model,
1546                                     &src_iter,
1547                                     src_path))
1548         {
1549           goto out;
1550         }
1551
1552       /* Get the path to insert _after_ (dest is the path to insert _before_) */
1553       prev = gtk_tree_path_copy (dest);
1554
1555       if (!gtk_tree_path_prev (prev))
1556         {
1557           /* dest was the first spot in the list; which means we are supposed
1558            * to prepend.
1559            */
1560           gtk_list_store_prepend (list_store, &dest_iter);
1561
1562           retval = TRUE;
1563         }
1564       else
1565         {
1566           if (gtk_list_store_get_iter (tree_model, &dest_iter, prev))
1567             {
1568               GtkTreeIter tmp_iter = dest_iter;
1569
1570               gtk_list_store_insert_after (list_store, &dest_iter, &tmp_iter);
1571
1572               retval = TRUE;
1573             }
1574         }
1575
1576       gtk_tree_path_free (prev);
1577
1578       /* If we succeeded in creating dest_iter, copy data from src
1579        */
1580       if (retval)
1581         {
1582           GtkTreeDataList *dl = g_sequence_get (src_iter.user_data);
1583           GtkTreeDataList *copy_head = NULL;
1584           GtkTreeDataList *copy_prev = NULL;
1585           GtkTreeDataList *copy_iter = NULL;
1586           GtkTreePath *path;
1587           gint col;
1588
1589           col = 0;
1590           while (dl)
1591             {
1592               copy_iter = _gtk_tree_data_list_node_copy (dl,
1593                                                          priv->column_headers[col]);
1594
1595               if (copy_head == NULL)
1596                 copy_head = copy_iter;
1597
1598               if (copy_prev)
1599                 copy_prev->next = copy_iter;
1600
1601               copy_prev = copy_iter;
1602
1603               dl = dl->next;
1604               ++col;
1605             }
1606
1607           dest_iter.stamp = priv->stamp;
1608           g_sequence_set (dest_iter.user_data, copy_head);
1609
1610           path = gtk_list_store_get_path (tree_model, &dest_iter);
1611           gtk_tree_model_row_changed (tree_model, path, &dest_iter);
1612           gtk_tree_path_free (path);
1613         }
1614     }
1615   else
1616     {
1617       /* FIXME maybe add some data targets eventually, or handle text
1618        * targets in the simple case.
1619        */
1620     }
1621
1622  out:
1623
1624   if (src_path)
1625     gtk_tree_path_free (src_path);
1626
1627   return retval;
1628 }
1629
1630 static gboolean
1631 gtk_list_store_row_drop_possible (GtkTreeDragDest  *drag_dest,
1632                                   GtkTreePath      *dest_path,
1633                                   GtkSelectionData *selection_data)
1634 {
1635   gint *indices;
1636   GtkTreeModel *src_model = NULL;
1637   GtkTreePath *src_path = NULL;
1638   gboolean retval = FALSE;
1639
1640   /* don't accept drops if the list has been sorted */
1641   if (GTK_LIST_STORE_IS_SORTED (drag_dest))
1642     return FALSE;
1643
1644   if (!gtk_tree_get_row_drag_data (selection_data,
1645                                    &src_model,
1646                                    &src_path))
1647     goto out;
1648
1649   if (src_model != GTK_TREE_MODEL (drag_dest))
1650     goto out;
1651
1652   if (gtk_tree_path_get_depth (dest_path) != 1)
1653     goto out;
1654
1655   /* can drop before any existing node, or before one past any existing. */
1656
1657   indices = gtk_tree_path_get_indices (dest_path);
1658
1659   if (indices[0] <= g_sequence_get_length (GTK_LIST_STORE (drag_dest)->priv->seq))
1660     retval = TRUE;
1661
1662  out:
1663   if (src_path)
1664     gtk_tree_path_free (src_path);
1665   
1666   return retval;
1667 }
1668
1669 /* Sorting and reordering */
1670
1671 /* Reordering */
1672 static gint
1673 gtk_list_store_reorder_func (GSequenceIter *a,
1674                              GSequenceIter *b,
1675                              gpointer       user_data)
1676 {
1677   GHashTable *new_positions = user_data;
1678   gint apos = GPOINTER_TO_INT (g_hash_table_lookup (new_positions, a));
1679   gint bpos = GPOINTER_TO_INT (g_hash_table_lookup (new_positions, b));
1680
1681   if (apos < bpos)
1682     return -1;
1683   if (apos > bpos)
1684     return 1;
1685   return 0;
1686 }
1687   
1688 /**
1689  * gtk_list_store_reorder:
1690  * @store: A #GtkListStore.
1691  * @new_order: (array zero-terminated=1): an array of integers mapping the new
1692  *      position of each child to its old position before the re-ordering,
1693  *      i.e. @new_order<literal>[newpos] = oldpos</literal>. It must have
1694  *      exactly as many items as the list store's length.
1695  *
1696  * Reorders @store to follow the order indicated by @new_order. Note that
1697  * this function only works with unsorted stores.
1698  *
1699  * Since: 2.2
1700  **/
1701 void
1702 gtk_list_store_reorder (GtkListStore *store,
1703                         gint         *new_order)
1704 {
1705   GtkListStorePrivate *priv;
1706   gint i;
1707   GtkTreePath *path;
1708   GHashTable *new_positions;
1709   GSequenceIter *ptr;
1710   gint *order;
1711   
1712   g_return_if_fail (GTK_IS_LIST_STORE (store));
1713   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1714   g_return_if_fail (new_order != NULL);
1715
1716   priv = store->priv;
1717
1718   order = g_new (gint, g_sequence_get_length (priv->seq));
1719   for (i = 0; i < g_sequence_get_length (priv->seq); i++)
1720     order[new_order[i]] = i;
1721   
1722   new_positions = g_hash_table_new (g_direct_hash, g_direct_equal);
1723
1724   ptr = g_sequence_get_begin_iter (priv->seq);
1725   i = 0;
1726   while (!g_sequence_iter_is_end (ptr))
1727     {
1728       g_hash_table_insert (new_positions, ptr, GINT_TO_POINTER (order[i++]));
1729
1730       ptr = g_sequence_iter_next (ptr);
1731     }
1732   g_free (order);
1733   
1734   g_sequence_sort_iter (priv->seq, gtk_list_store_reorder_func, new_positions);
1735
1736   g_hash_table_destroy (new_positions);
1737   
1738   /* emit signal */
1739   path = gtk_tree_path_new ();
1740   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1741                                  path, NULL, new_order);
1742   gtk_tree_path_free (path);
1743 }
1744
1745 static GHashTable *
1746 save_positions (GSequence *seq)
1747 {
1748   GHashTable *positions = g_hash_table_new (g_direct_hash, g_direct_equal);
1749   GSequenceIter *ptr;
1750
1751   ptr = g_sequence_get_begin_iter (seq);
1752   while (!g_sequence_iter_is_end (ptr))
1753     {
1754       g_hash_table_insert (positions, ptr,
1755                            GINT_TO_POINTER (g_sequence_iter_get_position (ptr)));
1756       ptr = g_sequence_iter_next (ptr);
1757     }
1758
1759   return positions;
1760 }
1761
1762 static int *
1763 generate_order (GSequence *seq,
1764                 GHashTable *old_positions)
1765 {
1766   GSequenceIter *ptr;
1767   int *order = g_new (int, g_sequence_get_length (seq));
1768   int i;
1769
1770   i = 0;
1771   ptr = g_sequence_get_begin_iter (seq);
1772   while (!g_sequence_iter_is_end (ptr))
1773     {
1774       int old_pos = GPOINTER_TO_INT (g_hash_table_lookup (old_positions, ptr));
1775       order[i++] = old_pos;
1776       ptr = g_sequence_iter_next (ptr);
1777     }
1778
1779   g_hash_table_destroy (old_positions);
1780
1781   return order;
1782 }
1783
1784 /**
1785  * gtk_list_store_swap:
1786  * @store: A #GtkListStore.
1787  * @a: A #GtkTreeIter.
1788  * @b: Another #GtkTreeIter.
1789  *
1790  * Swaps @a and @b in @store. Note that this function only works with
1791  * unsorted stores.
1792  *
1793  * Since: 2.2
1794  **/
1795 void
1796 gtk_list_store_swap (GtkListStore *store,
1797                      GtkTreeIter  *a,
1798                      GtkTreeIter  *b)
1799 {
1800   GtkListStorePrivate *priv;
1801   GHashTable *old_positions;
1802   gint *order;
1803   GtkTreePath *path;
1804
1805   g_return_if_fail (GTK_IS_LIST_STORE (store));
1806   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1807   g_return_if_fail (iter_is_valid (a, store));
1808   g_return_if_fail (iter_is_valid (b, store));
1809
1810   priv = store->priv;
1811
1812   if (a->user_data == b->user_data)
1813     return;
1814
1815   old_positions = save_positions (priv->seq);
1816   
1817   g_sequence_swap (a->user_data, b->user_data);
1818
1819   order = generate_order (priv->seq, old_positions);
1820   path = gtk_tree_path_new ();
1821   
1822   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1823                                  path, NULL, order);
1824
1825   gtk_tree_path_free (path);
1826   g_free (order);
1827 }
1828
1829 static void
1830 gtk_list_store_move_to (GtkListStore *store,
1831                         GtkTreeIter  *iter,
1832                         gint          new_pos)
1833 {
1834   GtkListStorePrivate *priv = store->priv;
1835   GHashTable *old_positions;
1836   GtkTreePath *path;
1837   gint *order;
1838
1839   old_positions = save_positions (priv->seq);
1840
1841   g_sequence_move (iter->user_data, g_sequence_get_iter_at_pos (priv->seq, new_pos));
1842
1843   order = generate_order (priv->seq, old_positions);
1844
1845   path = gtk_tree_path_new ();
1846   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1847                                  path, NULL, order);
1848   gtk_tree_path_free (path);
1849   g_free (order);
1850 }
1851
1852 /**
1853  * gtk_list_store_move_before:
1854  * @store: A #GtkListStore.
1855  * @iter: A #GtkTreeIter.
1856  * @position: (allow-none): A #GtkTreeIter, or %NULL.
1857  *
1858  * Moves @iter in @store to the position before @position. Note that this
1859  * function only works with unsorted stores. If @position is %NULL, @iter
1860  * will be moved to the end of the list.
1861  *
1862  * Since: 2.2
1863  **/
1864 void
1865 gtk_list_store_move_before (GtkListStore *store,
1866                             GtkTreeIter  *iter,
1867                             GtkTreeIter  *position)
1868 {
1869   gint pos;
1870   
1871   g_return_if_fail (GTK_IS_LIST_STORE (store));
1872   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1873   g_return_if_fail (iter_is_valid (iter, store));
1874   if (position)
1875     g_return_if_fail (iter_is_valid (position, store));
1876
1877   if (position)
1878     pos = g_sequence_iter_get_position (position->user_data);
1879   else
1880     pos = -1;
1881   
1882   gtk_list_store_move_to (store, iter, pos);
1883 }
1884
1885 /**
1886  * gtk_list_store_move_after:
1887  * @store: A #GtkListStore.
1888  * @iter: A #GtkTreeIter.
1889  * @position: (allow-none): A #GtkTreeIter or %NULL.
1890  *
1891  * Moves @iter in @store to the position after @position. Note that this
1892  * function only works with unsorted stores. If @position is %NULL, @iter
1893  * will be moved to the start of the list.
1894  *
1895  * Since: 2.2
1896  **/
1897 void
1898 gtk_list_store_move_after (GtkListStore *store,
1899                            GtkTreeIter  *iter,
1900                            GtkTreeIter  *position)
1901 {
1902   gint pos;
1903   
1904   g_return_if_fail (GTK_IS_LIST_STORE (store));
1905   g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1906   g_return_if_fail (iter_is_valid (iter, store));
1907   if (position)
1908     g_return_if_fail (iter_is_valid (position, store));
1909
1910   if (position)
1911     pos = g_sequence_iter_get_position (position->user_data) + 1;
1912   else
1913     pos = 0;
1914   
1915   gtk_list_store_move_to (store, iter, pos);
1916 }
1917     
1918 /* Sorting */
1919 static gint
1920 gtk_list_store_compare_func (GSequenceIter *a,
1921                              GSequenceIter *b,
1922                              gpointer      user_data)
1923 {
1924   GtkListStore *list_store = user_data;
1925   GtkListStorePrivate *priv = list_store->priv;
1926   GtkTreeIter iter_a;
1927   GtkTreeIter iter_b;
1928   gint retval;
1929   GtkTreeIterCompareFunc func;
1930   gpointer data;
1931
1932   if (priv->sort_column_id != -1)
1933     {
1934       GtkTreeDataSortHeader *header;
1935
1936       header = _gtk_tree_data_list_get_header (priv->sort_list,
1937                                                priv->sort_column_id);
1938       g_return_val_if_fail (header != NULL, 0);
1939       g_return_val_if_fail (header->func != NULL, 0);
1940
1941       func = header->func;
1942       data = header->data;
1943     }
1944   else
1945     {
1946       g_return_val_if_fail (priv->default_sort_func != NULL, 0);
1947       func = priv->default_sort_func;
1948       data = priv->default_sort_data;
1949     }
1950
1951   iter_a.stamp = priv->stamp;
1952   iter_a.user_data = (gpointer)a;
1953   iter_b.stamp = priv->stamp;
1954   iter_b.user_data = (gpointer)b;
1955
1956   g_assert (iter_is_valid (&iter_a, list_store));
1957   g_assert (iter_is_valid (&iter_b, list_store));
1958
1959   retval = (* func) (GTK_TREE_MODEL (list_store), &iter_a, &iter_b, data);
1960
1961   if (priv->order == GTK_SORT_DESCENDING)
1962     {
1963       if (retval > 0)
1964         retval = -1;
1965       else if (retval < 0)
1966         retval = 1;
1967     }
1968
1969   return retval;
1970 }
1971
1972 static void
1973 gtk_list_store_sort (GtkListStore *list_store)
1974 {
1975   GtkListStorePrivate *priv = list_store->priv;
1976   gint *new_order;
1977   GtkTreePath *path;
1978   GHashTable *old_positions;
1979
1980   if (!GTK_LIST_STORE_IS_SORTED (list_store) ||
1981       g_sequence_get_length (priv->seq) <= 1)
1982     return;
1983
1984   old_positions = save_positions (priv->seq);
1985
1986   g_sequence_sort_iter (priv->seq, gtk_list_store_compare_func, list_store);
1987
1988   /* Let the world know about our new order */
1989   new_order = generate_order (priv->seq, old_positions);
1990
1991   path = gtk_tree_path_new ();
1992   gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
1993                                  path, NULL, new_order);
1994   gtk_tree_path_free (path);
1995   g_free (new_order);
1996 }
1997
1998 static gboolean
1999 iter_is_sorted (GtkListStore *list_store,
2000                 GtkTreeIter  *iter)
2001 {
2002   GSequenceIter *cmp;
2003
2004   if (!g_sequence_iter_is_begin (iter->user_data))
2005     {
2006       cmp = g_sequence_iter_prev (iter->user_data);
2007       if (gtk_list_store_compare_func (cmp, iter->user_data, list_store) > 0)
2008         return FALSE;
2009     }
2010
2011   cmp = g_sequence_iter_next (iter->user_data);
2012   if (!g_sequence_iter_is_end (cmp))
2013     {
2014       if (gtk_list_store_compare_func (iter->user_data, cmp, list_store) > 0)
2015         return FALSE;
2016     }
2017   
2018   return TRUE;
2019 }
2020
2021 static void
2022 gtk_list_store_sort_iter_changed (GtkListStore *list_store,
2023                                   GtkTreeIter  *iter,
2024                                   gint          column)
2025
2026 {
2027   GtkListStorePrivate *priv = list_store->priv;
2028   GtkTreePath *path;
2029
2030   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
2031   gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
2032   gtk_tree_path_free (path);
2033
2034   if (!iter_is_sorted (list_store, iter))
2035     {
2036       GHashTable *old_positions;
2037       gint *order;
2038
2039       old_positions = save_positions (priv->seq);
2040       g_sequence_sort_changed_iter (iter->user_data,
2041                                     gtk_list_store_compare_func,
2042                                     list_store);
2043       order = generate_order (priv->seq, old_positions);
2044       path = gtk_tree_path_new ();
2045       gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
2046                                      path, NULL, order);
2047       gtk_tree_path_free (path);
2048       g_free (order);
2049     }
2050 }
2051
2052 static gboolean
2053 gtk_list_store_get_sort_column_id (GtkTreeSortable  *sortable,
2054                                    gint             *sort_column_id,
2055                                    GtkSortType      *order)
2056 {
2057   GtkListStore *list_store = GTK_LIST_STORE (sortable);
2058   GtkListStorePrivate *priv = list_store->priv;
2059
2060   if (sort_column_id)
2061     * sort_column_id = priv->sort_column_id;
2062   if (order)
2063     * order = priv->order;
2064
2065   if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID ||
2066       priv->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
2067     return FALSE;
2068
2069   return TRUE;
2070 }
2071
2072 static void
2073 gtk_list_store_set_sort_column_id (GtkTreeSortable  *sortable,
2074                                    gint              sort_column_id,
2075                                    GtkSortType       order)
2076 {
2077   GtkListStore *list_store = GTK_LIST_STORE (sortable);
2078   GtkListStorePrivate *priv = list_store->priv;
2079
2080   if ((priv->sort_column_id == sort_column_id) &&
2081       (priv->order == order))
2082     return;
2083
2084   if (sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
2085     {
2086       if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
2087         {
2088           GtkTreeDataSortHeader *header = NULL;
2089
2090           header = _gtk_tree_data_list_get_header (priv->sort_list, 
2091                                                    sort_column_id);
2092
2093           /* We want to make sure that we have a function */
2094           g_return_if_fail (header != NULL);
2095           g_return_if_fail (header->func != NULL);
2096         }
2097       else
2098         {
2099           g_return_if_fail (priv->default_sort_func != NULL);
2100         }
2101     }
2102
2103
2104   priv->sort_column_id = sort_column_id;
2105   priv->order = order;
2106
2107   gtk_tree_sortable_sort_column_changed (sortable);
2108
2109   gtk_list_store_sort (list_store);
2110 }
2111
2112 static void
2113 gtk_list_store_set_sort_func (GtkTreeSortable        *sortable,
2114                               gint                    sort_column_id,
2115                               GtkTreeIterCompareFunc  func,
2116                               gpointer                data,
2117                               GDestroyNotify          destroy)
2118 {
2119   GtkListStore *list_store = GTK_LIST_STORE (sortable);
2120   GtkListStorePrivate *priv = list_store->priv;
2121
2122   priv->sort_list = _gtk_tree_data_list_set_header (priv->sort_list, 
2123                                                           sort_column_id, 
2124                                                           func, data, destroy);
2125
2126   if (priv->sort_column_id == sort_column_id)
2127     gtk_list_store_sort (list_store);
2128 }
2129
2130 static void
2131 gtk_list_store_set_default_sort_func (GtkTreeSortable        *sortable,
2132                                       GtkTreeIterCompareFunc  func,
2133                                       gpointer                data,
2134                                       GDestroyNotify          destroy)
2135 {
2136   GtkListStore *list_store = GTK_LIST_STORE (sortable);
2137   GtkListStorePrivate *priv = list_store->priv;
2138
2139   if (priv->default_sort_destroy)
2140     {
2141       GDestroyNotify d = priv->default_sort_destroy;
2142
2143       priv->default_sort_destroy = NULL;
2144       d (priv->default_sort_data);
2145     }
2146
2147   priv->default_sort_func = func;
2148   priv->default_sort_data = data;
2149   priv->default_sort_destroy = destroy;
2150
2151   if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
2152     gtk_list_store_sort (list_store);
2153 }
2154
2155 static gboolean
2156 gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable)
2157 {
2158   GtkListStore *list_store = GTK_LIST_STORE (sortable);
2159   GtkListStorePrivate *priv = list_store->priv;
2160
2161   return (priv->default_sort_func != NULL);
2162 }
2163
2164
2165 /**
2166  * gtk_list_store_insert_with_values:
2167  * @list_store: A #GtkListStore
2168  * @iter: (out) (allow-none): An unset #GtkTreeIter to set to the new row, or %NULL
2169  * @position: position to insert the new row, or -1 to append after existing
2170  *     rows
2171  * @...: pairs of column number and value, terminated with -1
2172  *
2173  * Creates a new row at @position. @iter will be changed to point to this new
2174  * row. If @position is -1, or larger than the number of rows in the list, then
2175  * the new row will be appended to the list. The row will be filled with the
2176  * values given to this function.
2177  *
2178  * Calling
2179  * <literal>gtk_list_store_insert_with_values (list_store, iter, position...)</literal>
2180  * has the same effect as calling
2181  * |[
2182  * gtk_list_store_insert (list_store, iter, position);
2183  * gtk_list_store_set (list_store, iter, ...);
2184  * ]|
2185  * with the difference that the former will only emit a row_inserted signal,
2186  * while the latter will emit row_inserted, row_changed and, if the list store
2187  * is sorted, rows_reordered. Since emitting the rows_reordered signal
2188  * repeatedly can affect the performance of the program,
2189  * gtk_list_store_insert_with_values() should generally be preferred when
2190  * inserting rows in a sorted list store.
2191  *
2192  * Since: 2.6
2193  */
2194 void
2195 gtk_list_store_insert_with_values (GtkListStore *list_store,
2196                                    GtkTreeIter  *iter,
2197                                    gint          position,
2198                                    ...)
2199 {
2200   GtkListStorePrivate *priv;
2201   GtkTreePath *path;
2202   GSequence *seq;
2203   GSequenceIter *ptr;
2204   GtkTreeIter tmp_iter;
2205   gint length;
2206   gboolean changed = FALSE;
2207   gboolean maybe_need_sort = FALSE;
2208   va_list var_args;
2209
2210   /* FIXME: refactor to reduce overlap with gtk_list_store_set() */
2211   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
2212
2213   priv = list_store->priv;
2214
2215   if (!iter)
2216     iter = &tmp_iter;
2217
2218   priv->columns_dirty = TRUE;
2219
2220   seq = priv->seq;
2221
2222   length = g_sequence_get_length (seq);
2223   if (position > length || position < 0)
2224     position = length;
2225
2226   ptr = g_sequence_get_iter_at_pos (seq, position);
2227   ptr = g_sequence_insert_before (ptr, NULL);
2228
2229   iter->stamp = priv->stamp;
2230   iter->user_data = ptr;
2231
2232   g_assert (iter_is_valid (iter, list_store));
2233
2234   priv->length++;
2235
2236   va_start (var_args, position);
2237   gtk_list_store_set_valist_internal (list_store, iter, 
2238                                       &changed, &maybe_need_sort,
2239                                       var_args);
2240   va_end (var_args);
2241
2242   /* Don't emit rows_reordered here */
2243   if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
2244     g_sequence_sort_changed_iter (iter->user_data,
2245                                   gtk_list_store_compare_func,
2246                                   list_store);
2247
2248   /* Just emit row_inserted */
2249   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
2250   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
2251   gtk_tree_path_free (path);
2252 }
2253
2254
2255 /**
2256  * gtk_list_store_insert_with_valuesv:
2257  * @list_store: A #GtkListStore
2258  * @iter: (out) (allow-none): An unset #GtkTreeIter to set to the new row, or %NULL.
2259  * @position: position to insert the new row, or -1 for last
2260  * @columns: (array length=n_values): an array of column numbers
2261  * @values: (array length=n_values): an array of GValues 
2262  * @n_values: the length of the @columns and @values arrays
2263  * 
2264  * A variant of gtk_list_store_insert_with_values() which
2265  * takes the columns and values as two arrays, instead of
2266  * varargs. This function is mainly intended for 
2267  * language-bindings.
2268  *
2269  * Since: 2.6
2270  */
2271 void
2272 gtk_list_store_insert_with_valuesv (GtkListStore *list_store,
2273                                     GtkTreeIter  *iter,
2274                                     gint          position,
2275                                     gint         *columns, 
2276                                     GValue       *values,
2277                                     gint          n_values)
2278 {
2279   GtkListStorePrivate *priv;
2280   GtkTreePath *path;
2281   GSequence *seq;
2282   GSequenceIter *ptr;
2283   GtkTreeIter tmp_iter;
2284   gint length;
2285   gboolean changed = FALSE;
2286   gboolean maybe_need_sort = FALSE;
2287
2288   /* FIXME refactor to reduce overlap with 
2289    * gtk_list_store_insert_with_values() 
2290    */
2291   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
2292
2293   priv = list_store->priv;
2294
2295   if (!iter)
2296     iter = &tmp_iter;
2297
2298   priv->columns_dirty = TRUE;
2299
2300   seq = priv->seq;
2301
2302   length = g_sequence_get_length (seq);
2303   if (position > length || position < 0)
2304     position = length;
2305
2306   ptr = g_sequence_get_iter_at_pos (seq, position);
2307   ptr = g_sequence_insert_before (ptr, NULL);
2308
2309   iter->stamp = priv->stamp;
2310   iter->user_data = ptr;
2311
2312   g_assert (iter_is_valid (iter, list_store));
2313
2314   priv->length++;  
2315
2316   gtk_list_store_set_vector_internal (list_store, iter,
2317                                       &changed, &maybe_need_sort,
2318                                       columns, values, n_values);
2319
2320   /* Don't emit rows_reordered here */
2321   if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
2322     g_sequence_sort_changed_iter (iter->user_data,
2323                                   gtk_list_store_compare_func,
2324                                   list_store);
2325
2326   /* Just emit row_inserted */
2327   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
2328   gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
2329   gtk_tree_path_free (path);
2330 }
2331
2332 /* GtkBuildable custom tag implementation
2333  *
2334  * <columns>
2335  *   <column type="..."/>
2336  *   <column type="..."/>
2337  * </columns>
2338  */
2339 typedef struct {
2340   gboolean translatable;
2341   gchar *context;
2342   int id;
2343 } ColInfo;
2344
2345 typedef struct {
2346   GtkBuilder *builder;
2347   GObject *object;
2348   GSList *column_type_names;
2349   GType *column_types;
2350   GValue *values;
2351   gint *colids;
2352   ColInfo **columns;
2353   gint last_row;
2354   gint n_columns;
2355   gint row_column;
2356   GQuark error_quark;
2357   gboolean is_data;
2358   const gchar *domain;
2359 } SubParserData;
2360
2361 static void
2362 list_store_start_element (GMarkupParseContext *context,
2363                           const gchar         *element_name,
2364                           const gchar        **names,
2365                           const gchar        **values,
2366                           gpointer             user_data,
2367                           GError             **error)
2368 {
2369   guint i;
2370   SubParserData *data = (SubParserData*)user_data;
2371
2372   if (strcmp (element_name, "col") == 0)
2373     {
2374       int i, id = -1;
2375       gchar *context = NULL;
2376       gboolean translatable = FALSE;
2377       ColInfo *info;
2378
2379       if (data->row_column >= data->n_columns)
2380         {
2381           g_set_error (error, data->error_quark, 0,
2382                        "Too many columns, maximum is %d\n", data->n_columns - 1);
2383           return;
2384         }
2385
2386       for (i = 0; names[i]; i++)
2387         if (strcmp (names[i], "id") == 0)
2388           {
2389             errno = 0;
2390             id = atoi (values[i]);
2391             if (errno)
2392               {
2393                 g_set_error (error, data->error_quark, 0,
2394                              "the id tag %s could not be converted to an integer",
2395                              values[i]);
2396                 return;
2397               }
2398             if (id < 0 || id >= data->n_columns)
2399               {
2400                 g_set_error (error, data->error_quark, 0,
2401                              "id value %d out of range", id);
2402                 return;
2403               }
2404           }
2405         else if (strcmp (names[i], "translatable") == 0)
2406           {
2407             if (!_gtk_builder_boolean_from_string (values[i], &translatable,
2408                                                    error))
2409               return;
2410           }
2411         else if (strcmp (names[i], "comments") == 0)
2412           {
2413             /* do nothing, comments are for translators */
2414           }
2415         else if (strcmp (names[i], "context") == 0) 
2416           {
2417             context = g_strdup (values[i]);
2418           }
2419
2420       if (id == -1)
2421         {
2422           g_set_error (error, data->error_quark, 0,
2423                        "<col> needs an id attribute");
2424           return;
2425         }
2426       
2427       info = g_slice_new0 (ColInfo);
2428       info->translatable = translatable;
2429       info->context = context;
2430       info->id = id;
2431
2432       data->colids[data->row_column] = id;
2433       data->columns[data->row_column] = info;
2434       data->row_column++;
2435       data->is_data = TRUE;
2436     }
2437   else if (strcmp (element_name, "row") == 0)
2438     ;
2439   else if (strcmp (element_name, "column") == 0)
2440     {
2441       for (i = 0; names[i]; i++)
2442         if (strcmp (names[i], "type") == 0)
2443           data->column_type_names = g_slist_prepend (data->column_type_names,
2444                                                      g_strdup (values[i]));
2445     }
2446   else if (strcmp (element_name, "columns") == 0)
2447     ;
2448   else if (strcmp (element_name, "data") == 0)
2449     ;
2450   else
2451     g_set_error (error, data->error_quark, 0,
2452                  "Unknown start tag: %s", element_name);
2453 }
2454
2455 static void
2456 list_store_end_element (GMarkupParseContext *context,
2457                         const gchar         *element_name,
2458                         gpointer             user_data,
2459                         GError             **error)
2460 {
2461   SubParserData *data = (SubParserData*)user_data;
2462
2463   g_assert (data->builder);
2464   
2465   if (strcmp (element_name, "row") == 0)
2466     {
2467       GtkTreeIter iter;
2468       int i;
2469
2470       gtk_list_store_insert_with_valuesv (GTK_LIST_STORE (data->object),
2471                                           &iter,
2472                                           data->last_row,
2473                                           data->colids,
2474                                           data->values,
2475                                           data->row_column);
2476       for (i = 0; i < data->row_column; i++)
2477         {
2478           ColInfo *info = data->columns[i];
2479           g_free (info->context);
2480           g_slice_free (ColInfo, info);
2481           data->columns[i] = NULL;
2482           g_value_unset (&data->values[i]);
2483         }
2484       g_free (data->values);
2485       data->values = g_new0 (GValue, data->n_columns);
2486       data->last_row++;
2487       data->row_column = 0;
2488     }
2489   else if (strcmp (element_name, "columns") == 0)
2490     {
2491       GType *column_types;
2492       GSList *l;
2493       int i;
2494       GType type;
2495
2496       data->column_type_names = g_slist_reverse (data->column_type_names);
2497       column_types = g_new0 (GType, g_slist_length (data->column_type_names));
2498
2499       for (l = data->column_type_names, i = 0; l; l = l->next, i++)
2500         {
2501           type = gtk_builder_get_type_from_name (data->builder, l->data);
2502           if (type == G_TYPE_INVALID)
2503             {
2504               g_warning ("Unknown type %s specified in treemodel %s",
2505                          (const gchar*)l->data,
2506                          gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
2507               continue;
2508             }
2509           column_types[i] = type;
2510
2511           g_free (l->data);
2512         }
2513
2514       gtk_list_store_set_column_types (GTK_LIST_STORE (data->object), i,
2515                                        column_types);
2516
2517       g_free (column_types);
2518     }
2519   else if (strcmp (element_name, "col") == 0)
2520     data->is_data = FALSE;
2521   else if (strcmp (element_name, "data") == 0)
2522     ;
2523   else if (strcmp (element_name, "column") == 0)
2524     ;
2525   else
2526     g_set_error (error, data->error_quark, 0,
2527                  "Unknown end tag: %s", element_name);
2528 }
2529
2530 static void
2531 list_store_text (GMarkupParseContext *context,
2532                  const gchar         *text,
2533                  gsize                text_len,
2534                  gpointer             user_data,
2535                  GError             **error)
2536 {
2537   SubParserData *data = (SubParserData*)user_data;
2538   gint i;
2539   GError *tmp_error = NULL;
2540   gchar *string;
2541   ColInfo *info;
2542   
2543   if (!data->is_data)
2544     return;
2545
2546   i = data->row_column - 1;
2547   info = data->columns[i];
2548
2549   string = g_strndup (text, text_len);
2550   if (info->translatable && text_len)
2551     {
2552       gchar *translated;
2553
2554       /* FIXME: This will not use the domain set in the .ui file,
2555        * since the parser is not telling the builder about the domain.
2556        * However, it will work for gtk_builder_set_translation_domain() calls.
2557        */
2558       translated = _gtk_builder_parser_translate (data->domain,
2559                                                   info->context,
2560                                                   string);
2561       g_free (string);
2562       string = translated;
2563     }
2564
2565   if (!gtk_builder_value_from_string_type (data->builder,
2566                                            data->column_types[info->id],
2567                                            string,
2568                                            &data->values[i],
2569                                            &tmp_error))
2570     {
2571       g_set_error (error,
2572                    tmp_error->domain,
2573                    tmp_error->code,
2574                    "Could not convert '%s' to type %s: %s\n",
2575                    text, g_type_name (data->column_types[info->id]),
2576                    tmp_error->message);
2577       g_error_free (tmp_error);
2578     }
2579   g_free (string);
2580 }
2581
2582 static const GMarkupParser list_store_parser =
2583   {
2584     list_store_start_element,
2585     list_store_end_element,
2586     list_store_text
2587   };
2588
2589 static gboolean
2590 gtk_list_store_buildable_custom_tag_start (GtkBuildable  *buildable,
2591                                            GtkBuilder    *builder,
2592                                            GObject       *child,
2593                                            const gchar   *tagname,
2594                                            GMarkupParser *parser,
2595                                            gpointer      *data)
2596 {
2597   SubParserData *parser_data;
2598
2599   if (child)
2600     return FALSE;
2601
2602   if (strcmp (tagname, "columns") == 0)
2603     {
2604
2605       parser_data = g_slice_new0 (SubParserData);
2606       parser_data->builder = builder;
2607       parser_data->object = G_OBJECT (buildable);
2608       parser_data->column_type_names = NULL;
2609
2610       *parser = list_store_parser;
2611       *data = parser_data;
2612       return TRUE;
2613     }
2614   else if (strcmp (tagname, "data") == 0)
2615     {
2616       gint n_columns = gtk_list_store_get_n_columns (GTK_TREE_MODEL (buildable));
2617       if (n_columns == 0)
2618         g_error ("Cannot append data to an empty model");
2619
2620       parser_data = g_slice_new0 (SubParserData);
2621       parser_data->builder = builder;
2622       parser_data->object = G_OBJECT (buildable);
2623       parser_data->values = g_new0 (GValue, n_columns);
2624       parser_data->colids = g_new0 (gint, n_columns);
2625       parser_data->columns = g_new0 (ColInfo*, n_columns);
2626       parser_data->column_types = GTK_LIST_STORE (buildable)->priv->column_headers;
2627       parser_data->n_columns = n_columns;
2628       parser_data->last_row = 0;
2629       parser_data->error_quark = g_quark_from_static_string ("GtkListStore");
2630       parser_data->domain = gtk_builder_get_translation_domain (builder);
2631       
2632       *parser = list_store_parser;
2633       *data = parser_data;
2634       return TRUE;
2635     }
2636   else
2637     g_warning ("Unknown custom list store tag: %s", tagname);
2638   
2639   return FALSE;
2640 }
2641
2642 static void
2643 gtk_list_store_buildable_custom_tag_end (GtkBuildable *buildable,
2644                                          GtkBuilder   *builder,
2645                                          GObject      *child,
2646                                          const gchar  *tagname,
2647                                          gpointer     *data)
2648 {
2649   SubParserData *sub = (SubParserData*)data;
2650   
2651   if (strcmp (tagname, "columns") == 0)
2652     {
2653       g_slist_free (sub->column_type_names);
2654       g_slice_free (SubParserData, sub);
2655     }
2656   else if (strcmp (tagname, "data") == 0)
2657     {
2658       int i;
2659       for (i = 0; i < sub->n_columns; i++)
2660         {
2661           ColInfo *info = sub->columns[i];
2662           if (info)
2663             {
2664               g_free (info->context);
2665               g_slice_free (ColInfo, info);
2666             }
2667         }
2668       g_free (sub->colids);
2669       g_free (sub->columns);
2670       g_free (sub->values);
2671       g_slice_free (SubParserData, sub);
2672     }
2673   else
2674     g_warning ("Unknown custom list store tag: %s", tagname);
2675 }