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