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