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