]> Pileus Git - ~andy/gtk/blob - gtk/gtkliststore.c
Proxy out to _gtk_tree_row_reference_deleted. (inserted_callback): Proxy
[~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 <string.h>
21 #include "gtktreemodel.h"
22 #include "gtkliststore.h"
23 #include "gtktreedatalist.h"
24 #include "gtksignal.h"
25 #include "gtktreednd.h"
26 #include <gobject/gvaluecollector.h>
27
28 #define G_SLIST(x) ((GSList *) x)
29
30 static void         gtk_list_store_init            (GtkListStore      *list_store);
31 static void         gtk_list_store_class_init      (GtkListStoreClass *class);
32 static void         gtk_list_store_tree_model_init (GtkTreeModelIface *iface);
33 static void         gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface);
34 static void         gtk_list_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
35 static guint        gtk_list_store_get_flags       (GtkTreeModel      *tree_model);
36 static gint         gtk_list_store_get_n_columns   (GtkTreeModel      *tree_model);
37 static GType        gtk_list_store_get_column_type (GtkTreeModel      *tree_model,
38                                                     gint               index);
39 static gboolean     gtk_list_store_get_iter        (GtkTreeModel      *tree_model,
40                                                     GtkTreeIter       *iter,
41                                                     GtkTreePath       *path);
42 static GtkTreePath *gtk_list_store_get_path        (GtkTreeModel      *tree_model,
43                                                     GtkTreeIter       *iter);
44 static void         gtk_list_store_get_value       (GtkTreeModel      *tree_model,
45                                                     GtkTreeIter       *iter,
46                                                     gint               column,
47                                                     GValue            *value);
48 static gboolean     gtk_list_store_iter_next       (GtkTreeModel      *tree_model,
49                                                     GtkTreeIter       *iter);
50 static gboolean     gtk_list_store_iter_children   (GtkTreeModel      *tree_model,
51                                                     GtkTreeIter       *iter,
52                                                     GtkTreeIter       *parent);
53 static gboolean     gtk_list_store_iter_has_child  (GtkTreeModel      *tree_model,
54                                                     GtkTreeIter       *iter);
55 static gint         gtk_list_store_iter_n_children (GtkTreeModel      *tree_model,
56                                                     GtkTreeIter       *iter);
57 static gboolean     gtk_list_store_iter_nth_child  (GtkTreeModel      *tree_model,
58                                                     GtkTreeIter       *iter,
59                                                     GtkTreeIter       *parent,
60                                                     gint               n);
61 static gboolean     gtk_list_store_iter_parent     (GtkTreeModel      *tree_model,
62                                                     GtkTreeIter       *iter,
63                                                     GtkTreeIter       *child);
64
65 static gboolean gtk_list_store_drag_data_delete   (GtkTreeDragSource *drag_source,
66                                                    GtkTreePath       *path);
67 static gboolean gtk_list_store_drag_data_get      (GtkTreeDragSource *drag_source,
68                                                    GtkTreePath       *path,
69                                                    GtkSelectionData  *selection_data);
70 static gboolean gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
71                                                    GtkTreePath       *dest,
72                                                    GtkSelectionData  *selection_data);
73 static gboolean gtk_list_store_row_drop_possible  (GtkTreeDragDest   *drag_dest,
74                                                    GtkTreeModel      *src_model,
75                                                    GtkTreePath       *src_path,
76                                                    GtkTreePath       *dest_path);
77 static void
78 validate_list_store (GtkListStore *list_store)
79 {
80   if (gtk_debug_flags & GTK_DEBUG_TREE)
81     {
82       g_assert (g_slist_length (list_store->root) == list_store->length);
83       
84       g_assert (g_slist_last (list_store->root) == list_store->tail);
85     }
86 }
87
88 GtkType
89 gtk_list_store_get_type (void)
90 {
91   static GType list_store_type = 0;
92
93   if (!list_store_type)
94     {
95       static const GTypeInfo list_store_info =
96       {
97         sizeof (GtkListStoreClass),
98         NULL,           /* base_init */
99         NULL,           /* base_finalize */
100         (GClassInitFunc) gtk_list_store_class_init,
101         NULL,           /* class_finalize */
102         NULL,           /* class_data */
103         sizeof (GtkListStore),
104         0,
105         (GInstanceInitFunc) gtk_list_store_init,
106       };
107
108       static const GInterfaceInfo tree_model_info =
109       {
110         (GInterfaceInitFunc) gtk_list_store_tree_model_init,
111         NULL,
112         NULL
113       };
114
115       static const GInterfaceInfo drag_source_info =
116       {
117         (GInterfaceInitFunc) gtk_list_store_drag_source_init,
118         NULL,
119         NULL
120       };
121
122       static const GInterfaceInfo drag_dest_info =
123       {
124         (GInterfaceInitFunc) gtk_list_store_drag_dest_init,
125         NULL,
126         NULL
127       };
128       
129       list_store_type = g_type_register_static (G_TYPE_OBJECT, "GtkListStore", &list_store_info, 0);
130       g_type_add_interface_static (list_store_type,
131                                    GTK_TYPE_TREE_MODEL,
132                                    &tree_model_info);
133       g_type_add_interface_static (list_store_type,
134                                    GTK_TYPE_TREE_DRAG_SOURCE,
135                                    &drag_source_info);
136       g_type_add_interface_static (list_store_type,
137                                    GTK_TYPE_TREE_DRAG_DEST,
138                                    &drag_dest_info);
139     }
140
141   return list_store_type;
142 }
143
144 static void
145 gtk_list_store_class_init (GtkListStoreClass *class)
146 {
147   GObjectClass *object_class;
148
149   object_class = (GObjectClass*) class;
150 }
151
152 static void
153 gtk_list_store_tree_model_init (GtkTreeModelIface *iface)
154 {
155   iface->get_flags = gtk_list_store_get_flags;
156   iface->get_n_columns = gtk_list_store_get_n_columns;
157   iface->get_column_type = gtk_list_store_get_column_type;
158   iface->get_iter = gtk_list_store_get_iter;
159   iface->get_path = gtk_list_store_get_path;
160   iface->get_value = gtk_list_store_get_value;
161   iface->iter_next = gtk_list_store_iter_next;
162   iface->iter_children = gtk_list_store_iter_children;
163   iface->iter_has_child = gtk_list_store_iter_has_child;
164   iface->iter_n_children = gtk_list_store_iter_n_children;
165   iface->iter_nth_child = gtk_list_store_iter_nth_child;
166   iface->iter_parent = gtk_list_store_iter_parent;
167 }
168
169 static void
170 gtk_list_store_drag_source_init (GtkTreeDragSourceIface *iface)
171 {
172   iface->drag_data_delete = gtk_list_store_drag_data_delete;
173   iface->drag_data_get = gtk_list_store_drag_data_get;
174 }
175
176 static void
177 gtk_list_store_drag_dest_init   (GtkTreeDragDestIface   *iface)
178 {
179   iface->drag_data_received = gtk_list_store_drag_data_received;
180   iface->row_drop_possible = gtk_list_store_row_drop_possible;
181 }
182
183 static void
184 gtk_list_store_init (GtkListStore *list_store)
185 {
186   list_store->root = NULL;
187   list_store->tail = NULL;
188   list_store->stamp = g_random_int ();
189   list_store->length = 0;
190 }
191
192 /**
193  * gtk_list_store_new:
194  *
195  * Creates a new #GtkListStore. A #GtkListStore implements the
196  * #GtkTreeModel interface, and stores a linked list of
197  * rows; each row can have any number of columns. Columns are of uniform type,
198  * i.e. all cells in a column have the same type such as #G_TYPE_STRING or
199  * #GDK_TYPE_PIXBUF. Use #GtkListStore to store data to be displayed in a
200  * #GtkTreeView.
201  * 
202  * Return value: a new #GtkListStore
203  **/
204 GtkListStore *
205 gtk_list_store_new (void)
206 {
207   return GTK_LIST_STORE (g_object_new (gtk_list_store_get_type (), NULL));
208 }
209
210 /**
211  * gtk_list_store_new_with_types:
212  * @n_columns: number of columns in the list store
213  * @Varargs: pairs of column number and #GType
214  *
215  * Creates a new list store as with gtk_list_store_new(),
216  * simultaneously setting up the columns and column types as with
217  * gtk_list_store_set_n_columns() and
218  * gtk_list_store_set_column_type().
219  * 
220  * 
221  * Return value: a new #GtkListStore
222  **/
223 GtkListStore *
224 gtk_list_store_new_with_types (gint n_columns,
225                                ...)
226 {
227   GtkListStore *retval;
228   va_list args;
229   gint i;
230
231   g_return_val_if_fail (n_columns > 0, NULL);
232
233   retval = gtk_list_store_new ();
234   gtk_list_store_set_n_columns (retval, n_columns);
235
236   va_start (args, n_columns);
237
238   for (i = 0; i < n_columns; i++)
239     gtk_list_store_set_column_type (retval, i, va_arg (args, GType));
240
241   va_end (args);
242
243   return retval;
244 }
245
246 /**
247  * gtk_list_store_set_n_columns:
248  * @store: a #GtkListStore
249  * @n_columns: number of columns
250  *
251  * Sets the number of columns in the #GtkListStore.
252  * 
253  **/
254 void
255 gtk_list_store_set_n_columns (GtkListStore *list_store,
256                               gint          n_columns)
257 {
258   GType *new_columns;
259
260   g_return_if_fail (list_store != NULL);
261   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
262   g_return_if_fail (n_columns > 0);
263
264   if (list_store->n_columns == n_columns)
265     return;
266
267   new_columns = g_new0 (GType, n_columns);
268   if (list_store->column_headers)
269     {
270       /* copy the old header orders over */
271       if (n_columns >= list_store->n_columns)
272         memcpy (new_columns, list_store->column_headers, list_store->n_columns * sizeof (gchar *));
273       else
274         memcpy (new_columns, list_store->column_headers, n_columns * sizeof (GType));
275
276       g_free (list_store->column_headers);
277     }
278
279   list_store->column_headers = new_columns;
280   list_store->n_columns = n_columns;
281 }
282
283 /**
284  * gtk_list_store_set_column_type:
285  * @store: a #GtkListStore
286  * @column: column number
287  * @type: type of the data stored in @column
288  *
289  * Supported types include: %G_TYPE_UINT, %G_TYPE_INT, %G_TYPE_UCHAR,
290  * %G_TYPE_CHAR, %G_TYPE_BOOLEAN, %G_TYPE_POINTER, %G_TYPE_FLOAT, %G_TYPE_STRING,
291  * %G_TYPE_OBJECT, and %G_TYPE_BOXED, along with subclasses of those types such
292  * as %GDK_TYPE_PIXBUF.
293  * 
294  **/
295 void
296 gtk_list_store_set_column_type (GtkListStore *list_store,
297                                 gint          column,
298                                 GType         type)
299 {
300   g_return_if_fail (list_store != NULL);
301   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
302   g_return_if_fail (column >=0 && column < list_store->n_columns);
303
304   list_store->column_headers[column] = type;
305 }
306
307 /* Fulfill the GtkTreeModel requirements */
308 static guint
309 gtk_list_store_get_flags (GtkTreeModel *tree_model)
310 {
311   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
312
313   return GTK_TREE_MODEL_ITERS_PERSIST;
314 }
315
316 static gint
317 gtk_list_store_get_n_columns (GtkTreeModel *tree_model)
318 {
319   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
320
321   return GTK_LIST_STORE (tree_model)->n_columns;
322 }
323
324 static GType
325 gtk_list_store_get_column_type (GtkTreeModel *tree_model,
326                                 gint          index)
327 {
328   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), G_TYPE_INVALID);
329   g_return_val_if_fail (index < GTK_LIST_STORE (tree_model)->n_columns &&
330                         index >= 0, G_TYPE_INVALID);
331
332   return GTK_LIST_STORE (tree_model)->column_headers[index];
333 }
334
335 static gboolean
336 gtk_list_store_get_iter (GtkTreeModel *tree_model,
337                          GtkTreeIter  *iter,
338                          GtkTreePath  *path)
339 {
340   GSList *list;
341   gint i;
342   
343   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
344   g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);  
345
346   i = gtk_tree_path_get_indices (path)[0];
347
348   if (i >= GTK_LIST_STORE (tree_model)->length)
349     return FALSE;
350   
351   list = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root),
352                       i);
353
354   /* If this fails, list_store->length has gotten mangled. */
355   g_assert (list);
356   
357   iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
358   iter->user_data = list;
359   return TRUE;
360 }
361
362 static GtkTreePath *
363 gtk_list_store_get_path (GtkTreeModel *tree_model,
364                          GtkTreeIter  *iter)
365 {
366   GtkTreePath *retval;
367   GSList *list;
368   gint i = 0;
369
370   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), NULL);
371   g_return_val_if_fail (iter->stamp == GTK_LIST_STORE (tree_model)->stamp, NULL);
372
373   for (list = G_SLIST (GTK_LIST_STORE (tree_model)->root); list; list = list->next)
374     {
375       if (list == G_SLIST (iter->user_data))
376         break;
377       i++;
378     }
379   if (list == NULL)
380     return NULL;
381
382   retval = gtk_tree_path_new ();
383   gtk_tree_path_append_index (retval, i);
384   return retval;
385 }
386
387 static void
388 gtk_list_store_get_value (GtkTreeModel *tree_model,
389                           GtkTreeIter  *iter,
390                           gint          column,
391                           GValue       *value)
392 {
393   GtkTreeDataList *list;
394   gint tmp_column = column;
395
396   g_return_if_fail (GTK_IS_LIST_STORE (tree_model));
397   g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns);
398   g_return_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp);
399
400   list = G_SLIST (iter->user_data)->data;
401
402   while (tmp_column-- > 0 && list)
403     list = list->next;
404
405   if (list == NULL)
406     g_value_init (value, GTK_LIST_STORE (tree_model)->column_headers[column]);
407   else
408     _gtk_tree_data_list_node_to_value (list,
409                                        GTK_LIST_STORE (tree_model)->column_headers[column],
410                                        value);
411 }
412
413 static gboolean
414 gtk_list_store_iter_next (GtkTreeModel  *tree_model,
415                           GtkTreeIter   *iter)
416 {
417   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
418   g_return_val_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp, FALSE);
419
420   if (G_SLIST (iter->user_data)->next)
421     {
422       iter->user_data = G_SLIST (iter->user_data)->next;
423       return TRUE;
424     }
425   else
426     return FALSE;
427 }
428
429 static gboolean
430 gtk_list_store_iter_children (GtkTreeModel *tree_model,
431                               GtkTreeIter  *iter,
432                               GtkTreeIter  *parent)
433 {
434   /* this is a list, nodes have no children */
435   if (parent)
436     return FALSE;
437
438   /* but if parent == NULL we return the list itself as children of the
439    * "root"
440    */
441   
442   if (GTK_LIST_STORE (tree_model)->root)
443     {
444       iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
445       iter->user_data = GTK_LIST_STORE (tree_model)->root;
446       return TRUE;
447     }
448   else
449     return FALSE;
450 }
451
452 static gboolean
453 gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
454                                GtkTreeIter  *iter)
455 {
456   return FALSE;
457 }
458
459 static gint
460 gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
461                                 GtkTreeIter  *iter)
462 {
463   if (iter == NULL)
464     return GTK_LIST_STORE (tree_model)->length;
465   else
466     return 0;
467 }
468
469 static gboolean
470 gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
471                                GtkTreeIter  *iter,
472                                GtkTreeIter  *parent,
473                                gint          n)
474 {
475   GSList *child;
476   
477   g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
478
479   if (parent)
480     return FALSE;
481
482   child = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root), n);
483
484   if (child)
485     {
486       iter->user_data = child;
487       iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
488       return TRUE;
489     }
490   else
491     return FALSE;
492 }
493
494 static gboolean
495 gtk_list_store_iter_parent (GtkTreeModel *tree_model,
496                             GtkTreeIter  *iter,
497                             GtkTreeIter  *child)
498 {
499   return FALSE;
500 }
501
502 /* Public accessors */
503 /* This is a somewhat inelegant function that does a lot of list
504  * manipulations on it's own.
505  */
506
507 /**
508  * gtk_list_store_set_cell:
509  * @store: a #GtkListStore
510  * @iter: iterator for the row you're modifying
511  * @column: column number to modify
512  * @value: new value for the cell
513  *
514  * Sets the data in the cell specified by @iter and @column.
515  * The type of @value must be convertible to the type of the
516  * column.
517  * 
518  **/
519 void
520 gtk_list_store_set_cell (GtkListStore *list_store,
521                          GtkTreeIter  *iter,
522                          gint          column,
523                          GValue       *value)
524 {
525   GtkTreeDataList *list;
526   GtkTreeDataList *prev;
527   GtkTreePath *path;
528
529   g_return_if_fail (list_store != NULL);
530   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
531   g_return_if_fail (iter != NULL);
532   g_return_if_fail (column >= 0 && column < list_store->n_columns);
533
534   prev = list = G_SLIST (iter->user_data)->data;
535
536   while (list != NULL)
537     {
538       if (column == 0)
539         {
540           path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
541           _gtk_tree_data_list_value_to_node (list, value);
542           gtk_tree_model_changed (GTK_TREE_MODEL (list_store), path, iter);
543           gtk_tree_path_free (path);
544           return;
545         }
546
547       column--;
548       prev = list;
549       list = list->next;
550     }
551
552   if (G_SLIST (iter->user_data)->data == NULL)
553     {
554       G_SLIST (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
555       list->next = NULL;
556     }
557   else
558     {
559       list = prev->next = _gtk_tree_data_list_alloc ();
560       list->next = NULL;
561     }
562
563   while (column != 0)
564     {
565       list->next = _gtk_tree_data_list_alloc ();
566       list = list->next;
567       list->next = NULL;
568       column --;
569     }
570
571   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
572   _gtk_tree_data_list_value_to_node (list, value);
573   gtk_tree_model_changed (GTK_TREE_MODEL (list_store), path, iter);
574   gtk_tree_path_free (path);
575 }
576
577 /**
578  * gtk_list_store_set_valist:
579  * @list_store: a #GtkListStore
580  * @iter: row to set data for
581  * @var_args: va_list of column/value pairs
582  *
583  * See gtk_list_store_set(); this version takes a va_list for
584  * use by language bindings.
585  * 
586  **/
587 void
588 gtk_list_store_set_valist (GtkListStore *list_store,
589                            GtkTreeIter  *iter,
590                            va_list       var_args)
591 {
592   gint column;
593
594   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
595
596   column = va_arg (var_args, gint);
597
598   while (column != -1)
599     {
600       GValue value = { 0, };
601       gchar *error = NULL;
602
603       if (column >= list_store->n_columns)
604         {
605           g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
606           break;
607         }
608       g_value_init (&value, list_store->column_headers[column]);
609
610       G_VALUE_COLLECT (&value, var_args, 0, &error);
611       if (error)
612         {
613           g_warning ("%s: %s", G_STRLOC, error);
614           g_free (error);
615
616           /* we purposely leak the value here, it might not be
617            * in a sane state if an error condition occoured
618            */
619           break;
620         }
621
622       gtk_list_store_set_cell (list_store,
623                                iter,
624                                column,
625                                &value);
626
627       g_value_unset (&value);
628
629       column = va_arg (var_args, gint);
630     }
631 }
632
633 /**
634  * gtk_list_store_set:
635  * @list_store: a #GtkListStore
636  * @iter: row iterator
637  * @Varargs: pairs of column number and value, terminated with -1
638  * 
639  * Sets the value of one or more cells in the row referenced by @iter.
640  * The variable argument list should contain integer column numbers,
641  * each column number followed by the value to be set.
642  * The list is terminated by a -1. For example, to set column 0 with type
643  * %G_TYPE_STRING to "Foo", you would write gtk_list_store_set (store, iter,
644  * 0, "Foo", -1).
645  **/
646 void
647 gtk_list_store_set (GtkListStore *list_store,
648                     GtkTreeIter  *iter,
649                     ...)
650 {
651   va_list var_args;
652
653   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
654
655   va_start (var_args, iter);
656   gtk_list_store_set_valist (list_store, iter, var_args);
657   va_end (var_args);
658 }
659
660 static GSList*
661 remove_link_saving_prev (GSList  *list,
662                          GSList  *link,
663                          GSList **prevp)
664 {
665   GSList *tmp;
666   GSList *prev;
667
668   prev = NULL;
669   tmp = list;
670
671   while (tmp)
672     {
673       if (tmp == link)
674         {
675           if (prev)
676             prev->next = link->next;
677
678           if (list == link)
679             list = list->next;
680
681           link->next = NULL;
682           break;
683         }
684
685       prev = tmp;
686       tmp = tmp->next;
687     }
688
689   *prevp = prev;
690   
691   return list;
692 }
693
694 static void
695 gtk_list_store_remove_silently (GtkListStore *list_store,
696                                 GtkTreeIter  *iter,
697                                 GtkTreePath  *path)
698 {
699   if (G_SLIST (iter->user_data)->data)
700     {
701       _gtk_tree_data_list_free ((GtkTreeDataList *) G_SLIST (iter->user_data)->data,
702                                 list_store->column_headers);
703       G_SLIST (iter->user_data)->data = NULL;
704     }
705
706   {
707     GSList *prev = NULL;
708     
709     list_store->root = remove_link_saving_prev (G_SLIST (list_store->root),
710                                                 G_SLIST (iter->user_data),
711                                                 &prev);
712
713     list_store->length -= 1;
714     
715     if (iter->user_data == list_store->tail)
716       list_store->tail = prev;
717   }
718   
719   list_store->stamp ++;
720 }
721
722 /**
723  * gtk_list_store_remove:
724  * @store: a #GtkListStore
725  * @iter: a row in @list_store
726  *
727  * Removes the given row from the list store, emitting the
728  * "deleted" signal on #GtkTreeModel.
729  * 
730  **/
731 void
732 gtk_list_store_remove (GtkListStore *list_store,
733                        GtkTreeIter  *iter)
734 {
735   GtkTreePath *path;
736
737   g_return_if_fail (list_store != NULL);
738   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
739   g_return_if_fail (iter->user_data != NULL);  
740
741   path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
742
743   validate_list_store (list_store);
744   
745   gtk_list_store_remove_silently (list_store, iter, path);
746
747   validate_list_store (list_store);  
748
749   gtk_tree_model_deleted (GTK_TREE_MODEL (list_store), path);
750
751   gtk_tree_path_free (path);
752 }
753
754 static void
755 insert_after (GtkListStore *list_store,
756               GSList       *sibling,
757               GSList       *new_list)
758 {
759   g_return_if_fail (sibling != NULL);
760   g_return_if_fail (new_list != NULL);
761   
762   /* insert new node after list */
763   new_list->next = sibling->next;
764   sibling->next = new_list;
765
766   /* if list was the tail, the new node is the new tail */
767   if (sibling == list_store->tail)
768     list_store->tail = new_list;
769
770   list_store->length += 1;
771 }
772
773 /**
774  * gtk_list_store_insert:
775  * @store: a #GtkListStore
776  * @iter: iterator to initialize with the new row
777  * @position: position to insert the new row
778  *
779  * Creates a new row at @position, initializing @iter to point to the
780  * new row, and emitting the "inserted" signal from the #GtkTreeModel
781  * interface.
782  * 
783  **/
784 void
785 gtk_list_store_insert (GtkListStore *list_store,
786                        GtkTreeIter  *iter,
787                        gint          position)
788 {
789   GSList *list;
790   GtkTreePath *path;
791   GSList *new_list;
792   
793   g_return_if_fail (list_store != NULL);
794   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
795   g_return_if_fail (iter != NULL);
796   g_return_if_fail (position >= 0);
797
798   if (position == 0)
799     {
800       gtk_list_store_prepend (list_store, iter);
801       return;
802     }
803
804   new_list = g_slist_alloc ();
805
806   list = g_slist_nth (G_SLIST (list_store->root), position - 1);
807
808   if (list == NULL)
809     {
810       g_warning ("%s: position %d is off the end of the list\n", G_STRLOC, position);
811       return;
812     }
813
814   insert_after (list_store, list, new_list);
815   
816   iter->stamp = list_store->stamp;
817   iter->user_data = new_list;
818
819   validate_list_store (list_store);
820   
821   path = gtk_tree_path_new ();
822   gtk_tree_path_append_index (path, position);
823   gtk_tree_model_inserted (GTK_TREE_MODEL (list_store), path, iter);
824   gtk_tree_path_free (path);
825 }
826
827 /**
828  * gtk_list_store_insert_before:
829  * @store: a #GtkListStore
830  * @iter: iterator to initialize with the new row
831  * @sibling: an existing row
832  *
833  * Inserts a new row before @sibling, initializing @iter to point to
834  * the new row, and emitting the "inserted" signal from the
835  * #GtkTreeModel interface.
836  * 
837  **/
838 void
839 gtk_list_store_insert_before (GtkListStore *list_store,
840                               GtkTreeIter  *iter,
841                               GtkTreeIter  *sibling)
842 {
843   GtkTreePath *path;
844   GSList *list, *prev, *new_list;
845   gint i = 0;
846
847   g_return_if_fail (list_store != NULL);
848   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
849   g_return_if_fail (iter != NULL);
850
851   if (sibling == NULL)
852     {
853       gtk_list_store_append (list_store, iter);
854       return;
855     }
856   
857   new_list = g_slist_alloc ();
858
859   prev = NULL;
860   list = list_store->root;
861   while (list && list != sibling->user_data)
862     {
863       prev = list;
864       list = list->next;
865       i++;
866     }
867
868   if (list != sibling->user_data)
869     {
870       g_warning ("%s: sibling iterator invalid? not found in the list", G_STRLOC);
871       return;
872     }
873
874   /* if there are no nodes, we become the list tail, otherwise we
875    * are inserting before any existing nodes so we can't change
876    * the tail
877    */
878
879   if (list_store->root == NULL)
880     list_store->tail = new_list;
881   
882   if (prev)
883     {
884       new_list->next = prev->next;
885       prev->next = new_list;
886     }
887   else
888     {
889       new_list->next = list_store->root;
890       list_store->root = new_list;
891     }
892
893   iter->stamp = list_store->stamp;
894   iter->user_data = new_list;
895
896   list_store->length += 1;
897
898   validate_list_store (list_store);
899   
900   path = gtk_tree_path_new ();
901   gtk_tree_path_append_index (path, i);
902   gtk_tree_model_inserted (GTK_TREE_MODEL (list_store), path, iter);
903   gtk_tree_path_free (path);
904 }
905
906 /**
907  * gtk_list_store_insert_after:
908  * @store: a #GtkListStore
909  * @iter: iterator to initialize with the new row
910  * @sibling: an existing row
911  *
912  * Inserts a new row after @sibling, initializing @iter to point to
913  * the new row, and emitting the "inserted" signal from the
914  * #GtkTreeModel interface.
915  * 
916  **/
917 void
918 gtk_list_store_insert_after (GtkListStore *list_store,
919                              GtkTreeIter  *iter,
920                              GtkTreeIter  *sibling)
921 {
922   GtkTreePath *path;
923   GSList *list, *new_list;
924   gint i = 0;
925
926   g_return_if_fail (list_store != NULL);
927   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
928   g_return_if_fail (iter != NULL);
929   if (sibling)
930     g_return_if_fail (sibling->stamp == list_store->stamp);
931
932   if (sibling == NULL)
933     {
934       gtk_list_store_prepend (list_store, iter);
935       return;
936     }
937
938   for (list = list_store->root; list && list != sibling->user_data; list = list->next)
939     i++;
940
941   g_return_if_fail (list == sibling->user_data);
942
943   new_list = g_slist_alloc ();
944
945   insert_after (list_store, list, new_list);
946   
947   iter->stamp = list_store->stamp;
948   iter->user_data = new_list;
949
950   validate_list_store (list_store);
951   
952   path = gtk_tree_path_new ();
953   gtk_tree_path_append_index (path, i);
954   gtk_tree_model_inserted (GTK_TREE_MODEL (list_store), path, iter);
955   gtk_tree_path_free (path);
956 }
957
958 /**
959  * gtk_list_store_prepend:
960  * @store: a #GtkListStore
961  * @iter: iterator to initialize with new row
962  *
963  * Prepends a row to @store, initializing @iter to point to the
964  * new row, and emitting the "inserted" signal on the #GtkTreeModel
965  * interface for the @store.
966  * 
967  **/
968 void
969 gtk_list_store_prepend (GtkListStore *list_store,
970                         GtkTreeIter  *iter)
971 {
972   GtkTreePath *path;
973
974   g_return_if_fail (list_store != NULL);
975   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
976   g_return_if_fail (iter != NULL);
977
978   iter->stamp = list_store->stamp;
979   iter->user_data = g_slist_alloc ();
980
981   if (list_store->root == NULL)
982     list_store->tail = iter->user_data;
983   
984   G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
985   list_store->root = iter->user_data;
986
987   list_store->length += 1;
988
989   validate_list_store (list_store);
990   
991   path = gtk_tree_path_new ();
992   gtk_tree_path_append_index (path, 0);
993   gtk_tree_model_inserted (GTK_TREE_MODEL (list_store), path, iter);
994   gtk_tree_path_free (path);
995 }
996
997 /**
998  * gtk_list_store_append:
999  * @store: a #GtkListStore
1000  * @iter: iterator to initialize with the new row
1001  *
1002  * Appends a row to @store, initializing @iter to point to the
1003  * new row, and emitting the "inserted" signal on the #GtkTreeModel
1004  * interface for the @store.
1005  * 
1006  **/
1007 void
1008 gtk_list_store_append (GtkListStore *list_store,
1009                        GtkTreeIter  *iter)
1010 {
1011   GtkTreePath *path;
1012
1013   g_return_if_fail (list_store != NULL);
1014   g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1015   g_return_if_fail (iter != NULL);
1016
1017   iter->stamp = list_store->stamp;
1018   iter->user_data = g_slist_alloc ();
1019
1020   if (list_store->tail)
1021     list_store->tail->next = iter->user_data;
1022   else
1023     list_store->root = iter->user_data;
1024
1025   list_store->tail = iter->user_data;
1026
1027   list_store->length += 1;
1028
1029   validate_list_store (list_store);
1030   
1031   path = gtk_tree_path_new ();
1032   gtk_tree_path_append_index (path, list_store->length - 1);
1033   gtk_tree_model_inserted (GTK_TREE_MODEL (list_store), path, iter);
1034   gtk_tree_path_free (path);
1035 }
1036
1037 static gboolean
1038 gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
1039                                  GtkTreePath       *path)
1040 {
1041   GtkTreeIter iter;
1042   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1043   
1044   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source),
1045                                &iter,
1046                                path))
1047     {
1048       gtk_list_store_remove (GTK_LIST_STORE (drag_source),
1049                              &iter);
1050       return TRUE;
1051     }
1052   else
1053     {
1054       return FALSE;
1055     }
1056 }
1057
1058 static gboolean
1059 gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
1060                               GtkTreePath       *path,
1061                               GtkSelectionData  *selection_data)
1062 {
1063   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1064
1065   /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1066    * target, because the default handler does it for us, but
1067    * we do anyway for the convenience of someone maybe overriding the
1068    * default handler.
1069    */
1070
1071   if (gtk_selection_data_set_tree_row (selection_data,
1072                                        GTK_TREE_MODEL (drag_source),
1073                                        path))
1074     {
1075       return TRUE;
1076     }
1077   else
1078     {
1079       /* FIXME handle text targets at least. */
1080     }
1081
1082   return FALSE;
1083 }
1084
1085 static gboolean
1086 gtk_list_store_drag_data_received (GtkTreeDragDest   *drag_dest,
1087                                    GtkTreePath       *dest,
1088                                    GtkSelectionData  *selection_data)
1089 {
1090   GtkTreeModel *tree_model;
1091   GtkListStore *list_store;
1092   GtkTreeModel *src_model = NULL;
1093   GtkTreePath *src_path = NULL;
1094   gboolean retval = FALSE;
1095   
1096   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1097
1098   tree_model = GTK_TREE_MODEL (drag_dest);
1099   list_store = GTK_LIST_STORE (drag_dest);
1100   
1101   if (gtk_selection_data_get_tree_row (selection_data,
1102                                        &src_model,
1103                                        &src_path) &&
1104       src_model == tree_model)
1105     {
1106       /* Copy the given row to a new position */
1107       GtkTreeIter src_iter;
1108       GtkTreeIter dest_iter;
1109       GtkTreePath *prev;
1110       
1111       if (!gtk_tree_model_get_iter (src_model,
1112                                     &src_iter,
1113                                     src_path))
1114         {
1115           goto out;
1116         }
1117
1118       /* Get the path to insert _after_ (dest is the path to insert _before_) */
1119       prev = gtk_tree_path_copy (dest);
1120
1121       if (!gtk_tree_path_prev (prev))
1122         {
1123           /* dest was the first spot in the list; which means we are supposed
1124            * to prepend.
1125            */
1126           gtk_list_store_prepend (GTK_LIST_STORE (tree_model),
1127                                   &dest_iter);
1128           
1129           retval = TRUE;
1130         }
1131       else
1132         {
1133           if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model),
1134                                        &dest_iter,
1135                                        prev))
1136             {
1137               GtkTreeIter tmp_iter = dest_iter;
1138               gtk_list_store_insert_after (GTK_LIST_STORE (tree_model),
1139                                            &dest_iter,
1140                                            &tmp_iter);
1141               retval = TRUE;
1142             }
1143         }
1144
1145       gtk_tree_path_free (prev);
1146       
1147       /* If we succeeded in creating dest_iter, copy data from src
1148        */
1149       if (retval)
1150         {
1151           GtkTreeDataList *dl = G_SLIST (src_iter.user_data)->data;
1152           GtkTreeDataList *copy_head = NULL;
1153           GtkTreeDataList *copy_prev = NULL;
1154           GtkTreeDataList *copy_iter = NULL;
1155           GtkTreePath *path;
1156           gint col;
1157
1158           col = 0;
1159           while (dl)
1160             {
1161               copy_iter = _gtk_tree_data_list_node_copy (dl,
1162                                                          list_store->column_headers[col]);
1163               
1164               if (copy_head == NULL)
1165                 copy_head = copy_iter;
1166
1167               if (copy_prev)
1168                 copy_prev->next = copy_iter;
1169
1170               copy_prev = copy_iter;
1171
1172               dl = dl->next;
1173               ++col;
1174             }
1175           
1176           G_SLIST (dest_iter.user_data)->data = copy_head;
1177
1178           path = gtk_list_store_get_path (GTK_TREE_MODEL (tree_model), &dest_iter);
1179           gtk_tree_model_changed (GTK_TREE_MODEL (tree_model), path, &dest_iter);
1180           gtk_tree_path_free (path);
1181         }
1182     }
1183   else
1184     {
1185       /* FIXME maybe add some data targets eventually, or handle text
1186        * targets in the simple case.
1187        */
1188     }
1189
1190  out:
1191   
1192   if (src_path)
1193     gtk_tree_path_free (src_path);
1194   
1195   return retval;  
1196 }
1197
1198 static gboolean
1199 gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest,
1200                                   GtkTreeModel    *src_model,
1201                                   GtkTreePath     *src_path,
1202                                   GtkTreePath     *dest_path)
1203 {
1204   gint *indices;
1205   
1206   g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1207
1208   if (src_model != GTK_TREE_MODEL (drag_dest))
1209     return FALSE;
1210   
1211   if (gtk_tree_path_get_depth (dest_path) != 1)
1212     return FALSE;
1213
1214   /* can drop before any existing node, or before one past any existing. */
1215
1216   indices = gtk_tree_path_get_indices (dest_path);
1217
1218   if (indices[0] <= GTK_LIST_STORE (drag_dest)->length)
1219     return TRUE;
1220   else
1221     return FALSE;
1222 }