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)
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,
39 static gboolean gtk_list_store_get_iter (GtkTreeModel *tree_model,
42 static GtkTreePath *gtk_list_store_get_path (GtkTreeModel *tree_model,
44 static void gtk_list_store_get_value (GtkTreeModel *tree_model,
48 static gboolean gtk_list_store_iter_next (GtkTreeModel *tree_model,
50 static gboolean gtk_list_store_iter_children (GtkTreeModel *tree_model,
53 static gboolean gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
55 static gint gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
57 static gboolean gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
61 static gboolean gtk_list_store_iter_parent (GtkTreeModel *tree_model,
65 static gboolean gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
67 static gboolean gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
69 GtkSelectionData *selection_data);
70 static gboolean gtk_list_store_drag_data_received (GtkTreeDragDest *drag_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);
78 validate_list_store (GtkListStore *list_store)
80 if (gtk_debug_flags & GTK_DEBUG_TREE)
82 g_assert (g_slist_length (list_store->root) == list_store->length);
84 g_assert (g_slist_last (list_store->root) == list_store->tail);
89 gtk_list_store_get_type (void)
91 static GType list_store_type = 0;
95 static const GTypeInfo list_store_info =
97 sizeof (GtkListStoreClass),
99 NULL, /* base_finalize */
100 (GClassInitFunc) gtk_list_store_class_init,
101 NULL, /* class_finalize */
102 NULL, /* class_data */
103 sizeof (GtkListStore),
105 (GInstanceInitFunc) gtk_list_store_init,
108 static const GInterfaceInfo tree_model_info =
110 (GInterfaceInitFunc) gtk_list_store_tree_model_init,
115 static const GInterfaceInfo drag_source_info =
117 (GInterfaceInitFunc) gtk_list_store_drag_source_init,
122 static const GInterfaceInfo drag_dest_info =
124 (GInterfaceInitFunc) gtk_list_store_drag_dest_init,
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,
133 g_type_add_interface_static (list_store_type,
134 GTK_TYPE_TREE_DRAG_SOURCE,
136 g_type_add_interface_static (list_store_type,
137 GTK_TYPE_TREE_DRAG_DEST,
141 return list_store_type;
145 gtk_list_store_class_init (GtkListStoreClass *class)
147 GObjectClass *object_class;
149 object_class = (GObjectClass*) class;
153 gtk_list_store_tree_model_init (GtkTreeModelIface *iface)
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;
170 gtk_list_store_drag_source_init (GtkTreeDragSourceIface *iface)
172 iface->drag_data_delete = gtk_list_store_drag_data_delete;
173 iface->drag_data_get = gtk_list_store_drag_data_get;
177 gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface)
179 iface->drag_data_received = gtk_list_store_drag_data_received;
180 iface->row_drop_possible = gtk_list_store_row_drop_possible;
184 gtk_list_store_init (GtkListStore *list_store)
186 list_store->root = NULL;
187 list_store->tail = NULL;
188 list_store->stamp = g_random_int ();
189 list_store->length = 0;
193 * gtk_list_store_new:
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
202 * Return value: a new #GtkListStore
205 gtk_list_store_new (void)
207 return GTK_LIST_STORE (g_object_new (gtk_list_store_get_type (), NULL));
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
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().
221 * Return value: a new #GtkListStore
224 gtk_list_store_new_with_types (gint n_columns,
227 GtkListStore *retval;
231 g_return_val_if_fail (n_columns > 0, NULL);
233 retval = gtk_list_store_new ();
234 gtk_list_store_set_n_columns (retval, n_columns);
236 va_start (args, n_columns);
238 for (i = 0; i < n_columns; i++)
239 gtk_list_store_set_column_type (retval, i, va_arg (args, GType));
247 * gtk_list_store_set_n_columns:
248 * @store: a #GtkListStore
249 * @n_columns: number of columns
251 * Sets the number of columns in the #GtkListStore.
255 gtk_list_store_set_n_columns (GtkListStore *list_store,
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);
264 if (list_store->n_columns == n_columns)
267 new_columns = g_new0 (GType, n_columns);
268 if (list_store->column_headers)
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 *));
274 memcpy (new_columns, list_store->column_headers, n_columns * sizeof (GType));
276 g_free (list_store->column_headers);
279 list_store->column_headers = new_columns;
280 list_store->n_columns = n_columns;
284 * gtk_list_store_set_column_type:
285 * @store: a #GtkListStore
286 * @column: column number
287 * @type: type of the data stored in @column
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.
296 gtk_list_store_set_column_type (GtkListStore *list_store,
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);
304 list_store->column_headers[column] = type;
307 /* Fulfill the GtkTreeModel requirements */
309 gtk_list_store_get_flags (GtkTreeModel *tree_model)
311 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
313 return GTK_TREE_MODEL_ITERS_PERSIST;
317 gtk_list_store_get_n_columns (GtkTreeModel *tree_model)
319 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
321 return GTK_LIST_STORE (tree_model)->n_columns;
325 gtk_list_store_get_column_type (GtkTreeModel *tree_model,
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);
332 return GTK_LIST_STORE (tree_model)->column_headers[index];
336 gtk_list_store_get_iter (GtkTreeModel *tree_model,
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);
346 i = gtk_tree_path_get_indices (path)[0];
348 if (i >= GTK_LIST_STORE (tree_model)->length)
351 list = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root),
354 /* If this fails, list_store->length has gotten mangled. */
357 iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
358 iter->user_data = list;
363 gtk_list_store_get_path (GtkTreeModel *tree_model,
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);
373 for (list = G_SLIST (GTK_LIST_STORE (tree_model)->root); list; list = list->next)
375 if (list == G_SLIST (iter->user_data))
382 retval = gtk_tree_path_new ();
383 gtk_tree_path_append_index (retval, i);
388 gtk_list_store_get_value (GtkTreeModel *tree_model,
393 GtkTreeDataList *list;
394 gint tmp_column = column;
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);
400 list = G_SLIST (iter->user_data)->data;
402 while (tmp_column-- > 0 && list)
406 g_value_init (value, GTK_LIST_STORE (tree_model)->column_headers[column]);
408 _gtk_tree_data_list_node_to_value (list,
409 GTK_LIST_STORE (tree_model)->column_headers[column],
414 gtk_list_store_iter_next (GtkTreeModel *tree_model,
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);
420 if (G_SLIST (iter->user_data)->next)
422 iter->user_data = G_SLIST (iter->user_data)->next;
430 gtk_list_store_iter_children (GtkTreeModel *tree_model,
434 /* this is a list, nodes have no children */
438 /* but if parent == NULL we return the list itself as children of the
442 if (GTK_LIST_STORE (tree_model)->root)
444 iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
445 iter->user_data = GTK_LIST_STORE (tree_model)->root;
453 gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
460 gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
464 return GTK_LIST_STORE (tree_model)->length;
470 gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
477 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
482 child = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root), n);
486 iter->user_data = child;
487 iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
495 gtk_list_store_iter_parent (GtkTreeModel *tree_model,
502 /* Public accessors */
503 /* This is a somewhat inelegant function that does a lot of list
504 * manipulations on it's own.
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
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
520 gtk_list_store_set_cell (GtkListStore *list_store,
525 GtkTreeDataList *list;
526 GtkTreeDataList *prev;
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);
534 prev = list = G_SLIST (iter->user_data)->data;
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);
552 if (G_SLIST (iter->user_data)->data == NULL)
554 G_SLIST (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
559 list = prev->next = _gtk_tree_data_list_alloc ();
565 list->next = _gtk_tree_data_list_alloc ();
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);
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
583 * See gtk_list_store_set(); this version takes a va_list for
584 * use by language bindings.
588 gtk_list_store_set_valist (GtkListStore *list_store,
594 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
596 column = va_arg (var_args, gint);
600 GValue value = { 0, };
603 if (column >= list_store->n_columns)
605 g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
608 g_value_init (&value, list_store->column_headers[column]);
610 G_VALUE_COLLECT (&value, var_args, 0, &error);
613 g_warning ("%s: %s", G_STRLOC, error);
616 /* we purposely leak the value here, it might not be
617 * in a sane state if an error condition occoured
622 gtk_list_store_set_cell (list_store,
627 g_value_unset (&value);
629 column = va_arg (var_args, gint);
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
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,
647 gtk_list_store_set (GtkListStore *list_store,
653 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
655 va_start (var_args, iter);
656 gtk_list_store_set_valist (list_store, iter, var_args);
661 remove_link_saving_prev (GSList *list,
676 prev->next = link->next;
695 gtk_list_store_remove_silently (GtkListStore *list_store,
699 if (G_SLIST (iter->user_data)->data)
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;
709 list_store->root = remove_link_saving_prev (G_SLIST (list_store->root),
710 G_SLIST (iter->user_data),
713 list_store->length -= 1;
715 if (iter->user_data == list_store->tail)
716 list_store->tail = prev;
719 list_store->stamp ++;
723 * gtk_list_store_remove:
724 * @store: a #GtkListStore
725 * @iter: a row in @list_store
727 * Removes the given row from the list store, emitting the
728 * "deleted" signal on #GtkTreeModel.
732 gtk_list_store_remove (GtkListStore *list_store,
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);
741 path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
743 validate_list_store (list_store);
745 gtk_list_store_remove_silently (list_store, iter, path);
747 validate_list_store (list_store);
749 gtk_tree_model_deleted (GTK_TREE_MODEL (list_store), path);
751 gtk_tree_path_free (path);
755 insert_after (GtkListStore *list_store,
759 g_return_if_fail (sibling != NULL);
760 g_return_if_fail (new_list != NULL);
762 /* insert new node after list */
763 new_list->next = sibling->next;
764 sibling->next = new_list;
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;
770 list_store->length += 1;
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
779 * Creates a new row at @position, initializing @iter to point to the
780 * new row, and emitting the "inserted" signal from the #GtkTreeModel
785 gtk_list_store_insert (GtkListStore *list_store,
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);
800 gtk_list_store_prepend (list_store, iter);
804 new_list = g_slist_alloc ();
806 list = g_slist_nth (G_SLIST (list_store->root), position - 1);
810 g_warning ("%s: position %d is off the end of the list\n", G_STRLOC, position);
814 insert_after (list_store, list, new_list);
816 iter->stamp = list_store->stamp;
817 iter->user_data = new_list;
819 validate_list_store (list_store);
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);
828 * gtk_list_store_insert_before:
829 * @store: a #GtkListStore
830 * @iter: iterator to initialize with the new row
831 * @sibling: an existing row
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.
839 gtk_list_store_insert_before (GtkListStore *list_store,
841 GtkTreeIter *sibling)
844 GSList *list, *prev, *new_list;
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);
853 gtk_list_store_append (list_store, iter);
857 new_list = g_slist_alloc ();
860 list = list_store->root;
861 while (list && list != sibling->user_data)
868 if (list != sibling->user_data)
870 g_warning ("%s: sibling iterator invalid? not found in the list", G_STRLOC);
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
879 if (list_store->root == NULL)
880 list_store->tail = new_list;
884 new_list->next = prev->next;
885 prev->next = new_list;
889 new_list->next = list_store->root;
890 list_store->root = new_list;
893 iter->stamp = list_store->stamp;
894 iter->user_data = new_list;
896 list_store->length += 1;
898 validate_list_store (list_store);
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);
907 * gtk_list_store_insert_after:
908 * @store: a #GtkListStore
909 * @iter: iterator to initialize with the new row
910 * @sibling: an existing row
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.
918 gtk_list_store_insert_after (GtkListStore *list_store,
920 GtkTreeIter *sibling)
923 GSList *list, *new_list;
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);
930 g_return_if_fail (sibling->stamp == list_store->stamp);
934 gtk_list_store_prepend (list_store, iter);
938 for (list = list_store->root; list && list != sibling->user_data; list = list->next)
941 g_return_if_fail (list == sibling->user_data);
943 new_list = g_slist_alloc ();
945 insert_after (list_store, list, new_list);
947 iter->stamp = list_store->stamp;
948 iter->user_data = new_list;
950 validate_list_store (list_store);
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);
959 * gtk_list_store_prepend:
960 * @store: a #GtkListStore
961 * @iter: iterator to initialize with new row
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.
969 gtk_list_store_prepend (GtkListStore *list_store,
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);
978 iter->stamp = list_store->stamp;
979 iter->user_data = g_slist_alloc ();
981 if (list_store->root == NULL)
982 list_store->tail = iter->user_data;
984 G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
985 list_store->root = iter->user_data;
987 list_store->length += 1;
989 validate_list_store (list_store);
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);
998 * gtk_list_store_append:
999 * @store: a #GtkListStore
1000 * @iter: iterator to initialize with the new row
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.
1008 gtk_list_store_append (GtkListStore *list_store,
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);
1017 iter->stamp = list_store->stamp;
1018 iter->user_data = g_slist_alloc ();
1020 if (list_store->tail)
1021 list_store->tail->next = iter->user_data;
1023 list_store->root = iter->user_data;
1025 list_store->tail = iter->user_data;
1027 list_store->length += 1;
1029 validate_list_store (list_store);
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);
1038 gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
1042 g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1044 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source),
1048 gtk_list_store_remove (GTK_LIST_STORE (drag_source),
1059 gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
1061 GtkSelectionData *selection_data)
1063 g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
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
1071 if (gtk_selection_data_set_tree_row (selection_data,
1072 GTK_TREE_MODEL (drag_source),
1079 /* FIXME handle text targets at least. */
1086 gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest,
1088 GtkSelectionData *selection_data)
1090 GtkTreeModel *tree_model;
1091 GtkListStore *list_store;
1092 GtkTreeModel *src_model = NULL;
1093 GtkTreePath *src_path = NULL;
1094 gboolean retval = FALSE;
1096 g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1098 tree_model = GTK_TREE_MODEL (drag_dest);
1099 list_store = GTK_LIST_STORE (drag_dest);
1101 if (gtk_selection_data_get_tree_row (selection_data,
1104 src_model == tree_model)
1106 /* Copy the given row to a new position */
1107 GtkTreeIter src_iter;
1108 GtkTreeIter dest_iter;
1111 if (!gtk_tree_model_get_iter (src_model,
1118 /* Get the path to insert _after_ (dest is the path to insert _before_) */
1119 prev = gtk_tree_path_copy (dest);
1121 if (!gtk_tree_path_prev (prev))
1123 /* dest was the first spot in the list; which means we are supposed
1126 gtk_list_store_prepend (GTK_LIST_STORE (tree_model),
1133 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model),
1137 GtkTreeIter tmp_iter = dest_iter;
1138 gtk_list_store_insert_after (GTK_LIST_STORE (tree_model),
1145 gtk_tree_path_free (prev);
1147 /* If we succeeded in creating dest_iter, copy data from src
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;
1161 copy_iter = _gtk_tree_data_list_node_copy (dl,
1162 list_store->column_headers[col]);
1164 if (copy_head == NULL)
1165 copy_head = copy_iter;
1168 copy_prev->next = copy_iter;
1170 copy_prev = copy_iter;
1176 G_SLIST (dest_iter.user_data)->data = copy_head;
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);
1185 /* FIXME maybe add some data targets eventually, or handle text
1186 * targets in the simple case.
1193 gtk_tree_path_free (src_path);
1199 gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest,
1200 GtkTreeModel *src_model,
1201 GtkTreePath *src_path,
1202 GtkTreePath *dest_path)
1206 g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1208 if (src_model != GTK_TREE_MODEL (drag_dest))
1211 if (gtk_tree_path_get_depth (dest_path) != 1)
1214 /* can drop before any existing node, or before one past any existing. */
1216 indices = gtk_tree_path_get_indices (dest_path);
1218 if (indices[0] <= GTK_LIST_STORE (drag_dest)->length)