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