2 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
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.
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.
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.
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>
28 #define G_SLIST(x) ((GSList *) x)
38 static guint list_store_signals[LAST_SIGNAL] = { 0 };
40 static void gtk_list_store_init (GtkListStore *list_store);
41 static void gtk_list_store_class_init (GtkListStoreClass *class);
42 static void gtk_list_store_tree_model_init (GtkTreeModelIface *iface);
43 static void gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface);
44 static void gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface);
45 static guint gtk_list_store_get_flags (GtkTreeModel *tree_model);
46 static gint gtk_list_store_get_n_columns (GtkTreeModel *tree_model);
47 static GType gtk_list_store_get_column_type (GtkTreeModel *tree_model,
49 static gboolean gtk_list_store_get_iter (GtkTreeModel *tree_model,
52 static GtkTreePath *gtk_list_store_get_path (GtkTreeModel *tree_model,
54 static void gtk_list_store_get_value (GtkTreeModel *tree_model,
58 static gboolean gtk_list_store_iter_next (GtkTreeModel *tree_model,
60 static gboolean gtk_list_store_iter_children (GtkTreeModel *tree_model,
63 static gboolean gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
65 static gint gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
67 static gboolean gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
71 static gboolean gtk_list_store_iter_parent (GtkTreeModel *tree_model,
75 static gboolean gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
77 static gboolean gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
79 GtkSelectionData *selection_data);
80 static gboolean gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest,
82 GtkSelectionData *selection_data);
83 static gboolean gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest,
84 GtkTreeModel *src_model,
85 GtkTreePath *src_path,
86 GtkTreePath *dest_path);
88 validate_list_store (GtkListStore *list_store)
90 if (gtk_debug_flags & GTK_DEBUG_TREE)
92 g_assert (g_slist_length (list_store->root) == list_store->length);
94 g_assert (g_slist_last (list_store->root) == list_store->tail);
99 gtk_list_store_get_type (void)
101 static GtkType list_store_type = 0;
103 if (!list_store_type)
105 static const GTypeInfo list_store_info =
107 sizeof (GtkListStoreClass),
108 NULL, /* base_init */
109 NULL, /* base_finalize */
110 (GClassInitFunc) gtk_list_store_class_init,
111 NULL, /* class_finalize */
112 NULL, /* class_data */
113 sizeof (GtkListStore),
115 (GInstanceInitFunc) gtk_list_store_init,
118 static const GInterfaceInfo tree_model_info =
120 (GInterfaceInitFunc) gtk_list_store_tree_model_init,
125 static const GInterfaceInfo drag_source_info =
127 (GInterfaceInitFunc) gtk_list_store_drag_source_init,
132 static const GInterfaceInfo drag_dest_info =
134 (GInterfaceInitFunc) gtk_list_store_drag_dest_init,
139 list_store_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkListStore", &list_store_info, 0);
140 g_type_add_interface_static (list_store_type,
143 g_type_add_interface_static (list_store_type,
144 GTK_TYPE_TREE_DRAG_SOURCE,
146 g_type_add_interface_static (list_store_type,
147 GTK_TYPE_TREE_DRAG_DEST,
151 return list_store_type;
155 gtk_list_store_class_init (GtkListStoreClass *class)
157 GtkObjectClass *object_class;
159 object_class = (GtkObjectClass*) class;
161 list_store_signals[CHANGED] =
162 gtk_signal_new ("changed",
164 GTK_CLASS_TYPE (object_class),
165 GTK_SIGNAL_OFFSET (GtkListStoreClass, changed),
166 gtk_marshal_VOID__BOXED_BOXED,
170 list_store_signals[INSERTED] =
171 gtk_signal_new ("inserted",
173 GTK_CLASS_TYPE (object_class),
174 GTK_SIGNAL_OFFSET (GtkListStoreClass, inserted),
175 gtk_marshal_VOID__BOXED_BOXED,
179 list_store_signals[CHILD_TOGGLED] =
180 gtk_signal_new ("child_toggled",
182 GTK_CLASS_TYPE (object_class),
183 GTK_SIGNAL_OFFSET (GtkListStoreClass, child_toggled),
184 gtk_marshal_VOID__BOXED_BOXED,
188 list_store_signals[DELETED] =
189 gtk_signal_new ("deleted",
191 GTK_CLASS_TYPE (object_class),
192 GTK_SIGNAL_OFFSET (GtkListStoreClass, deleted),
193 gtk_marshal_VOID__BOXED,
199 gtk_list_store_tree_model_init (GtkTreeModelIface *iface)
201 iface->get_flags = gtk_list_store_get_flags;
202 iface->get_n_columns = gtk_list_store_get_n_columns;
203 iface->get_column_type = gtk_list_store_get_column_type;
204 iface->get_iter = gtk_list_store_get_iter;
205 iface->get_path = gtk_list_store_get_path;
206 iface->get_value = gtk_list_store_get_value;
207 iface->iter_next = gtk_list_store_iter_next;
208 iface->iter_children = gtk_list_store_iter_children;
209 iface->iter_has_child = gtk_list_store_iter_has_child;
210 iface->iter_n_children = gtk_list_store_iter_n_children;
211 iface->iter_nth_child = gtk_list_store_iter_nth_child;
212 iface->iter_parent = gtk_list_store_iter_parent;
216 gtk_list_store_drag_source_init (GtkTreeDragSourceIface *iface)
218 iface->drag_data_delete = gtk_list_store_drag_data_delete;
219 iface->drag_data_get = gtk_list_store_drag_data_get;
223 gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface)
225 iface->drag_data_received = gtk_list_store_drag_data_received;
226 iface->row_drop_possible = gtk_list_store_row_drop_possible;
230 gtk_list_store_init (GtkListStore *list_store)
232 list_store->root = NULL;
233 list_store->tail = NULL;
234 list_store->stamp = g_random_int ();
235 list_store->length = 0;
239 * gtk_list_store_new:
241 * Creates a new #GtkListStore. A #GtkListStore implements the
242 * #GtkTreeModel interface, and stores a linked list of
243 * rows; each row can have any number of columns. Columns are of uniform type,
244 * i.e. all cells in a column have the same type such as #G_TYPE_STRING or
245 * #GDK_TYPE_PIXBUF. Use #GtkListStore to store data to be displayed in a
248 * Return value: a new #GtkListStore
251 gtk_list_store_new (void)
253 return GTK_LIST_STORE (gtk_type_new (gtk_list_store_get_type ()));
257 * gtk_list_store_new_with_types:
258 * @n_columns: number of columns in the list store
259 * @Varargs: pairs of column number and #GType
261 * Creates a new list store as with gtk_list_store_new(),
262 * simultaneously setting up the columns and column types as with
263 * gtk_list_store_set_n_columns() and
264 * gtk_list_store_set_column_type().
267 * Return value: a new #GtkListStore
270 gtk_list_store_new_with_types (gint n_columns,
273 GtkListStore *retval;
277 g_return_val_if_fail (n_columns > 0, NULL);
279 retval = gtk_list_store_new ();
280 gtk_list_store_set_n_columns (retval, n_columns);
282 va_start (args, n_columns);
284 for (i = 0; i < n_columns; i++)
285 gtk_list_store_set_column_type (retval, i, va_arg (args, GType));
293 * gtk_list_store_set_n_columns:
294 * @store: a #GtkListStore
295 * @n_columns: number of columns
297 * Sets the number of columns in the #GtkListStore.
301 gtk_list_store_set_n_columns (GtkListStore *list_store,
306 g_return_if_fail (list_store != NULL);
307 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
308 g_return_if_fail (n_columns > 0);
310 if (list_store->n_columns == n_columns)
313 new_columns = g_new0 (GType, n_columns);
314 if (list_store->column_headers)
316 /* copy the old header orders over */
317 if (n_columns >= list_store->n_columns)
318 memcpy (new_columns, list_store->column_headers, list_store->n_columns * sizeof (gchar *));
320 memcpy (new_columns, list_store->column_headers, n_columns * sizeof (GType));
322 g_free (list_store->column_headers);
325 list_store->column_headers = new_columns;
326 list_store->n_columns = n_columns;
330 * gtk_list_store_set_column_type:
331 * @store: a #GtkListStore
332 * @column: column number
333 * @type: type of the data stored in @column
335 * Supported types include: %G_TYPE_UINT, %G_TYPE_INT, %G_TYPE_UCHAR,
336 * %G_TYPE_CHAR, %G_TYPE_BOOLEAN, %G_TYPE_POINTER, %G_TYPE_FLOAT, %G_TYPE_STRING,
337 * %G_TYPE_OBJECT, and %G_TYPE_BOXED, along with subclasses of those types such
338 * as %GDK_TYPE_PIXBUF.
342 gtk_list_store_set_column_type (GtkListStore *list_store,
346 g_return_if_fail (list_store != NULL);
347 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
348 g_return_if_fail (column >=0 && column < list_store->n_columns);
350 list_store->column_headers[column] = type;
353 /* Fulfill the GtkTreeModel requirements */
355 gtk_list_store_get_flags (GtkTreeModel *tree_model)
357 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
359 return GTK_TREE_MODEL_ITERS_PERSIST;
363 gtk_list_store_get_n_columns (GtkTreeModel *tree_model)
365 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
367 return GTK_LIST_STORE (tree_model)->n_columns;
371 gtk_list_store_get_column_type (GtkTreeModel *tree_model,
374 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), G_TYPE_INVALID);
375 g_return_val_if_fail (index < GTK_LIST_STORE (tree_model)->n_columns &&
376 index >= 0, G_TYPE_INVALID);
378 return GTK_LIST_STORE (tree_model)->column_headers[index];
382 gtk_list_store_get_iter (GtkTreeModel *tree_model,
389 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
390 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
392 i = gtk_tree_path_get_indices (path)[0];
394 if (i >= GTK_LIST_STORE (tree_model)->length)
397 list = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root),
400 /* If this fails, list_store->length has gotten mangled. */
403 iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
404 iter->user_data = list;
409 gtk_list_store_get_path (GtkTreeModel *tree_model,
416 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), NULL);
417 g_return_val_if_fail (iter->stamp == GTK_LIST_STORE (tree_model)->stamp, NULL);
419 for (list = G_SLIST (GTK_LIST_STORE (tree_model)->root); list; list = list->next)
421 if (list == G_SLIST (iter->user_data))
428 retval = gtk_tree_path_new ();
429 gtk_tree_path_append_index (retval, i);
434 gtk_list_store_get_value (GtkTreeModel *tree_model,
439 GtkTreeDataList *list;
440 gint tmp_column = column;
442 g_return_if_fail (GTK_IS_LIST_STORE (tree_model));
443 g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns);
444 g_return_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp);
446 list = G_SLIST (iter->user_data)->data;
448 while (tmp_column-- > 0 && list)
452 g_value_init (value, GTK_LIST_STORE (tree_model)->column_headers[column]);
454 _gtk_tree_data_list_node_to_value (list,
455 GTK_LIST_STORE (tree_model)->column_headers[column],
460 gtk_list_store_iter_next (GtkTreeModel *tree_model,
463 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
464 g_return_val_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp, FALSE);
466 if (G_SLIST (iter->user_data)->next)
468 iter->user_data = G_SLIST (iter->user_data)->next;
476 gtk_list_store_iter_children (GtkTreeModel *tree_model,
480 /* this is a list, nodes have no children */
484 /* but if parent == NULL we return the list itself as children of the
488 if (GTK_LIST_STORE (tree_model)->root)
490 iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
491 iter->user_data = GTK_LIST_STORE (tree_model)->root;
499 gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
506 gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
510 return GTK_LIST_STORE (tree_model)->length;
516 gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
523 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
528 child = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root), n);
532 iter->user_data = child;
533 iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
541 gtk_list_store_iter_parent (GtkTreeModel *tree_model,
548 /* Public accessors */
549 /* This is a somewhat inelegant function that does a lot of list
550 * manipulations on it's own.
554 * gtk_list_store_set_cell:
555 * @store: a #GtkListStore
556 * @iter: iterator for the row you're modifying
557 * @column: column number to modify
558 * @value: new value for the cell
560 * Sets the data in the cell specified by @iter and @column.
561 * The type of @value must be convertible to the type of the
566 gtk_list_store_set_cell (GtkListStore *list_store,
571 GtkTreeDataList *list;
572 GtkTreeDataList *prev;
574 g_return_if_fail (list_store != NULL);
575 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
576 g_return_if_fail (iter != NULL);
577 g_return_if_fail (column >= 0 && column < list_store->n_columns);
579 prev = list = G_SLIST (iter->user_data)->data;
585 _gtk_tree_data_list_value_to_node (list, value);
586 gtk_signal_emit_by_name (GTK_OBJECT (list_store),
597 if (G_SLIST (iter->user_data)->data == NULL)
599 G_SLIST (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
604 list = prev->next = _gtk_tree_data_list_alloc ();
610 list->next = _gtk_tree_data_list_alloc ();
615 _gtk_tree_data_list_value_to_node (list, value);
616 gtk_signal_emit_by_name (GTK_OBJECT (list_store),
622 * gtk_list_store_set_valist:
623 * @list_store: a #GtkListStore
624 * @iter: row to set data for
625 * @var_args: va_list of column/value pairs
627 * See gtk_list_store_set(); this version takes a va_list for
628 * use by language bindings.
632 gtk_list_store_set_valist (GtkListStore *list_store,
638 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
640 column = va_arg (var_args, gint);
644 GValue value = { 0, };
647 if (column >= list_store->n_columns)
649 g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
652 g_value_init (&value, list_store->column_headers[column]);
654 G_VALUE_COLLECT (&value, var_args, &error);
657 g_warning ("%s: %s", G_STRLOC, error);
660 /* we purposely leak the value here, it might not be
661 * in a sane state if an error condition occoured
666 gtk_list_store_set_cell (list_store,
671 g_value_unset (&value);
673 column = va_arg (var_args, gint);
678 * gtk_list_store_set:
679 * @list_store: a #GtkListStore
680 * @iter: row iterator
681 * @Varargs: pairs of column number and value, terminated with -1
683 * Sets the value of one or more cells in the row referenced by @iter.
684 * The variable argument list should contain integer column numbers,
685 * each column number followed by the value to be set.
686 * The list is terminated by a -1. For example, to set column 0 with type
687 * %G_TYPE_STRING to "Foo", you would write gtk_list_store_set (store, iter,
691 gtk_list_store_set (GtkListStore *list_store,
697 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
699 va_start (var_args, iter);
700 gtk_list_store_set_valist (list_store, iter, var_args);
705 * gtk_list_store_get_valist:
706 * @list_store: a #GtkListStore
707 * @iter: a row in @list_store
708 * @var_args: va_list of column/return location pairs
710 * See gtk_list_store_get(), this version takes a va_list for
711 * language bindings to use.
715 gtk_list_store_get_valist (GtkListStore *list_store,
721 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
723 column = va_arg (var_args, gint);
727 GValue value = { 0, };
730 if (column >= list_store->n_columns)
732 g_warning ("%s: Invalid column number %d accessed (remember to end your list of columns with a -1)", G_STRLOC, column);
736 gtk_list_store_get_value (GTK_TREE_MODEL (list_store), iter, column, &value);
738 G_VALUE_LCOPY (&value, var_args, &error);
741 g_warning ("%s: %s", G_STRLOC, error);
744 /* we purposely leak the value here, it might not be
745 * in a sane state if an error condition occoured
750 g_value_unset (&value);
752 column = va_arg (var_args, gint);
757 * gtk_list_store_get:
758 * @list_store: a #GtkListStore
759 * @iter: a row in @list_store
760 * @Varargs: pairs of column number and value return locations, terminated by -1
762 * Gets the value of one or more cells in the row referenced by @iter.
763 * The variable argument list should contain integer column numbers,
764 * each column number followed by a place to store the value being
765 * retrieved. The list is terminated by a -1. For example, to get a
766 * value from column 0 with type %G_TYPE_STRING, you would
767 * write: gtk_list_store_set (store, iter, 0, &place_string_here, -1),
768 * where place_string_here is a gchar* to be filled with the string.
769 * If appropriate, the returned values have to be freed or unreferenced.
773 gtk_list_store_get (GtkListStore *list_store,
779 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
781 va_start (var_args, iter);
782 gtk_list_store_get_valist (list_store, iter, var_args);
787 remove_link_saving_prev (GSList *list,
802 prev->next = link->next;
821 gtk_list_store_remove_silently (GtkListStore *list_store,
825 if (G_SLIST (iter->user_data)->data)
827 _gtk_tree_data_list_free ((GtkTreeDataList *) G_SLIST (iter->user_data)->data,
828 list_store->column_headers);
829 G_SLIST (iter->user_data)->data = NULL;
835 list_store->root = remove_link_saving_prev (G_SLIST (list_store->root),
836 G_SLIST (iter->user_data),
839 list_store->length -= 1;
841 if (iter->user_data == list_store->tail)
842 list_store->tail = prev;
845 list_store->stamp ++;
849 * gtk_list_store_remove:
850 * @store: a #GtkListStore
851 * @iter: a row in @list_store
853 * Removes the given row from the list store, emitting the
854 * "deleted" signal on #GtkTreeModel.
858 gtk_list_store_remove (GtkListStore *list_store,
863 g_return_if_fail (list_store != NULL);
864 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
865 g_return_if_fail (iter->user_data != NULL);
867 path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
869 validate_list_store (list_store);
871 gtk_list_store_remove_silently (list_store, iter, path);
873 validate_list_store (list_store);
875 gtk_signal_emit_by_name (GTK_OBJECT (list_store),
878 gtk_tree_path_free (path);
882 insert_after (GtkListStore *list_store,
886 g_return_if_fail (sibling != NULL);
887 g_return_if_fail (new_list != NULL);
889 /* insert new node after list */
890 new_list->next = sibling->next;
891 sibling->next = new_list;
893 /* if list was the tail, the new node is the new tail */
894 if (sibling == list_store->tail)
895 list_store->tail = new_list;
897 list_store->length += 1;
901 * gtk_list_store_insert:
902 * @store: a #GtkListStore
903 * @iter: iterator to initialize with the new row
904 * @position: position to insert the new row
906 * Creates a new row at @position, initializing @iter to point to the
907 * new row, and emitting the "inserted" signal from the #GtkTreeModel
912 gtk_list_store_insert (GtkListStore *list_store,
920 g_return_if_fail (list_store != NULL);
921 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
922 g_return_if_fail (iter != NULL);
923 g_return_if_fail (position >= 0);
927 gtk_list_store_prepend (list_store, iter);
931 new_list = g_slist_alloc ();
933 list = g_slist_nth (G_SLIST (list_store->root), position - 1);
937 g_warning ("%s: position %d is off the end of the list\n", G_STRLOC, position);
941 insert_after (list_store, list, new_list);
943 iter->stamp = list_store->stamp;
944 iter->user_data = new_list;
946 validate_list_store (list_store);
948 path = gtk_tree_path_new ();
949 gtk_tree_path_append_index (path, position);
950 gtk_signal_emit_by_name (GTK_OBJECT (list_store),
953 gtk_tree_path_free (path);
957 * gtk_list_store_insert_before:
958 * @store: a #GtkListStore
959 * @iter: iterator to initialize with the new row
960 * @sibling: an existing row
962 * Inserts a new row before @sibling, initializing @iter to point to
963 * the new row, and emitting the "inserted" signal from the
964 * #GtkTreeModel interface.
968 gtk_list_store_insert_before (GtkListStore *list_store,
970 GtkTreeIter *sibling)
973 GSList *list, *prev, *new_list;
976 g_return_if_fail (list_store != NULL);
977 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
978 g_return_if_fail (iter != NULL);
982 gtk_list_store_append (list_store, iter);
986 new_list = g_slist_alloc ();
989 list = list_store->root;
990 while (list && list != sibling->user_data)
997 if (list != sibling->user_data)
999 g_warning ("%s: sibling iterator invalid? not found in the list", G_STRLOC);
1003 /* if there are no nodes, we become the list tail, otherwise we
1004 * are inserting before any existing nodes so we can't change
1008 if (list_store->root == NULL)
1009 list_store->tail = new_list;
1013 new_list->next = prev->next;
1014 prev->next = new_list;
1018 new_list->next = list_store->root;
1019 list_store->root = new_list;
1022 iter->stamp = list_store->stamp;
1023 iter->user_data = new_list;
1025 list_store->length += 1;
1027 validate_list_store (list_store);
1029 path = gtk_tree_path_new ();
1030 gtk_tree_path_append_index (path, i);
1031 gtk_signal_emit_by_name (GTK_OBJECT (list_store),
1034 gtk_tree_path_free (path);
1038 * gtk_list_store_insert_after:
1039 * @store: a #GtkListStore
1040 * @iter: iterator to initialize with the new row
1041 * @sibling: an existing row
1043 * Inserts a new row after @sibling, initializing @iter to point to
1044 * the new row, and emitting the "inserted" signal from the
1045 * #GtkTreeModel interface.
1049 gtk_list_store_insert_after (GtkListStore *list_store,
1051 GtkTreeIter *sibling)
1054 GSList *list, *new_list;
1057 g_return_if_fail (list_store != NULL);
1058 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1059 g_return_if_fail (iter != NULL);
1061 g_return_if_fail (sibling->stamp == list_store->stamp);
1063 if (sibling == NULL)
1065 gtk_list_store_prepend (list_store, iter);
1069 for (list = list_store->root; list && list != sibling->user_data; list = list->next)
1072 g_return_if_fail (list == sibling->user_data);
1074 new_list = g_slist_alloc ();
1076 insert_after (list_store, list, new_list);
1078 iter->stamp = list_store->stamp;
1079 iter->user_data = new_list;
1081 validate_list_store (list_store);
1083 path = gtk_tree_path_new ();
1084 gtk_tree_path_append_index (path, i);
1085 gtk_signal_emit_by_name (GTK_OBJECT (list_store),
1088 gtk_tree_path_free (path);
1092 * gtk_list_store_prepend:
1093 * @store: a #GtkListStore
1094 * @iter: iterator to initialize with new row
1096 * Prepends a row to @store, initializing @iter to point to the
1097 * new row, and emitting the "inserted" signal on the #GtkTreeModel
1098 * interface for the @store.
1102 gtk_list_store_prepend (GtkListStore *list_store,
1107 g_return_if_fail (list_store != NULL);
1108 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1109 g_return_if_fail (iter != NULL);
1111 iter->stamp = list_store->stamp;
1112 iter->user_data = g_slist_alloc ();
1114 if (list_store->root == NULL)
1115 list_store->tail = iter->user_data;
1117 G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
1118 list_store->root = iter->user_data;
1120 list_store->length += 1;
1122 validate_list_store (list_store);
1124 path = gtk_tree_path_new ();
1125 gtk_tree_path_append_index (path, 0);
1126 gtk_signal_emit_by_name (GTK_OBJECT (list_store),
1129 gtk_tree_path_free (path);
1133 * gtk_list_store_append:
1134 * @store: a #GtkListStore
1135 * @iter: iterator to initialize with the new row
1137 * Appends a row to @store, initializing @iter to point to the
1138 * new row, and emitting the "inserted" signal on the #GtkTreeModel
1139 * interface for the @store.
1143 gtk_list_store_append (GtkListStore *list_store,
1149 g_return_if_fail (list_store != NULL);
1150 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1151 g_return_if_fail (iter != NULL);
1153 iter->stamp = list_store->stamp;
1154 iter->user_data = g_slist_alloc ();
1156 if (list_store->tail)
1157 list_store->tail->next = iter->user_data;
1159 list_store->root = iter->user_data;
1161 list_store->tail = iter->user_data;
1163 list_store->length += 1;
1165 validate_list_store (list_store);
1167 path = gtk_tree_path_new ();
1168 gtk_tree_path_append_index (path, i);
1169 gtk_signal_emit_by_name (GTK_OBJECT (list_store),
1172 gtk_tree_path_free (path);
1176 gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
1180 g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1182 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source),
1186 gtk_list_store_remove (GTK_LIST_STORE (drag_source),
1197 gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
1199 GtkSelectionData *selection_data)
1201 g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1203 /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1204 * target, because the default handler does it for us, but
1205 * we do anyway for the convenience of someone maybe overriding the
1209 if (gtk_selection_data_set_tree_row (selection_data,
1210 GTK_TREE_MODEL (drag_source),
1217 /* FIXME handle text targets at least. */
1224 gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest,
1226 GtkSelectionData *selection_data)
1228 GtkTreeModel *tree_model;
1229 GtkListStore *list_store;
1230 GtkTreeModel *src_model = NULL;
1231 GtkTreePath *src_path = NULL;
1232 gboolean retval = FALSE;
1234 g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1236 tree_model = GTK_TREE_MODEL (drag_dest);
1237 list_store = GTK_LIST_STORE (drag_dest);
1239 if (gtk_selection_data_get_tree_row (selection_data,
1242 src_model == tree_model)
1244 /* Copy the given row to a new position */
1245 GtkTreeIter src_iter;
1246 GtkTreeIter dest_iter;
1249 if (!gtk_tree_model_get_iter (src_model,
1256 /* Get the path to insert _after_ (dest is the path to insert _before_) */
1257 prev = gtk_tree_path_copy (dest);
1259 if (!gtk_tree_path_prev (prev))
1261 /* dest was the first spot in the list; which means we are supposed
1264 gtk_list_store_prepend (GTK_LIST_STORE (tree_model),
1271 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model),
1275 GtkTreeIter tmp_iter = dest_iter;
1276 gtk_list_store_insert_after (GTK_LIST_STORE (tree_model),
1283 gtk_tree_path_free (prev);
1285 /* If we succeeded in creating dest_iter, copy data from src
1289 GtkTreeDataList *dl = G_SLIST (src_iter.user_data)->data;
1290 GtkTreeDataList *copy_head = NULL;
1291 GtkTreeDataList *copy_prev = NULL;
1292 GtkTreeDataList *copy_iter = NULL;
1298 copy_iter = _gtk_tree_data_list_node_copy (dl,
1299 list_store->column_headers[col]);
1301 if (copy_head == NULL)
1302 copy_head = copy_iter;
1305 copy_prev->next = copy_iter;
1307 copy_prev = copy_iter;
1313 G_SLIST (dest_iter.user_data)->data = copy_head;
1315 gtk_signal_emit_by_name (GTK_OBJECT (tree_model),
1322 /* FIXME maybe add some data targets eventually, or handle text
1323 * targets in the simple case.
1330 gtk_tree_path_free (src_path);
1336 gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest,
1337 GtkTreeModel *src_model,
1338 GtkTreePath *src_path,
1339 GtkTreePath *dest_path)
1343 g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1345 if (src_model != GTK_TREE_MODEL (drag_dest))
1348 if (gtk_tree_path_get_depth (dest_path) != 1)
1351 /* can drop before any existing node, or before one past any existing. */
1353 indices = gtk_tree_path_get_indices (dest_path);
1355 if (indices[0] <= GTK_LIST_STORE (drag_dest)->length)