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)
29 #define GTK_LIST_STORE_IS_SORTED(list) (GTK_LIST_STORE (list)->sort_column_id != -2)
30 #define VALID_ITER(iter, list_store) (iter!= NULL && iter->user_data != NULL && list_store->stamp == iter->stamp)
32 static void gtk_list_store_init (GtkListStore *list_store);
33 static void gtk_list_store_class_init (GtkListStoreClass *class);
34 static void gtk_list_store_tree_model_init (GtkTreeModelIface *iface);
35 static void gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface);
36 static void gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface);
37 static void gtk_list_store_sortable_init (GtkTreeSortableIface *iface);
38 static void gtk_list_store_destroy (GtkObject *gobject);
39 static void gtk_list_store_finalize (GObject *object);
40 static guint gtk_list_store_get_flags (GtkTreeModel *tree_model);
41 static gint gtk_list_store_get_n_columns (GtkTreeModel *tree_model);
42 static GType gtk_list_store_get_column_type (GtkTreeModel *tree_model,
44 static gboolean gtk_list_store_get_iter (GtkTreeModel *tree_model,
47 static GtkTreePath *gtk_list_store_get_path (GtkTreeModel *tree_model,
49 static void gtk_list_store_get_value (GtkTreeModel *tree_model,
53 static gboolean gtk_list_store_iter_next (GtkTreeModel *tree_model,
55 static gboolean gtk_list_store_iter_children (GtkTreeModel *tree_model,
58 static gboolean gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
60 static gint gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
62 static gboolean gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
66 static gboolean gtk_list_store_iter_parent (GtkTreeModel *tree_model,
71 static void gtk_list_store_set_n_columns (GtkListStore *list_store,
73 static void gtk_list_store_set_column_type (GtkListStore *list_store,
79 static gboolean gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
81 static gboolean gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
83 GtkSelectionData *selection_data);
84 static gboolean gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest,
86 GtkSelectionData *selection_data);
87 static gboolean gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest,
88 GtkTreeModel *src_model,
89 GtkTreePath *src_path,
90 GtkTreePath *dest_path);
94 static void gtk_list_store_sort (GtkListStore *list_store);
95 static void gtk_list_store_sort_iter_changed (GtkListStore *list_store,
98 static gboolean gtk_list_store_get_sort_column_id (GtkTreeSortable *sortable,
101 static void gtk_list_store_set_sort_column_id (GtkTreeSortable *sortable,
104 static void gtk_list_store_set_sort_func (GtkTreeSortable *sortable,
106 GtkTreeIterCompareFunc func,
108 GtkDestroyNotify destroy);
109 static void gtk_list_store_set_default_sort_func (GtkTreeSortable *sortable,
110 GtkTreeIterCompareFunc func,
112 GtkDestroyNotify destroy);
113 static gboolean gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable);
118 validate_list_store (GtkListStore *list_store)
120 if (gtk_debug_flags & GTK_DEBUG_TREE)
122 g_assert (g_slist_length (list_store->root) == list_store->length);
124 g_assert (g_slist_last (list_store->root) == list_store->tail);
129 gtk_list_store_get_type (void)
131 static GType list_store_type = 0;
133 if (!list_store_type)
135 static const GTypeInfo list_store_info =
137 sizeof (GtkListStoreClass),
138 NULL, /* base_init */
139 NULL, /* base_finalize */
140 (GClassInitFunc) gtk_list_store_class_init,
141 NULL, /* class_finalize */
142 NULL, /* class_data */
143 sizeof (GtkListStore),
145 (GInstanceInitFunc) gtk_list_store_init,
148 static const GInterfaceInfo tree_model_info =
150 (GInterfaceInitFunc) gtk_list_store_tree_model_init,
155 static const GInterfaceInfo drag_source_info =
157 (GInterfaceInitFunc) gtk_list_store_drag_source_init,
162 static const GInterfaceInfo drag_dest_info =
164 (GInterfaceInitFunc) gtk_list_store_drag_dest_init,
169 static const GInterfaceInfo sortable_info =
171 (GInterfaceInitFunc) gtk_list_store_sortable_init,
176 list_store_type = g_type_register_static (G_TYPE_OBJECT, "GtkListStore", &list_store_info, 0);
177 g_type_add_interface_static (list_store_type,
180 g_type_add_interface_static (list_store_type,
181 GTK_TYPE_TREE_DRAG_SOURCE,
183 g_type_add_interface_static (list_store_type,
184 GTK_TYPE_TREE_DRAG_DEST,
186 g_type_add_interface_static (list_store_type,
187 GTK_TYPE_TREE_SORTABLE,
191 return list_store_type;
195 gtk_list_store_class_init (GtkListStoreClass *class)
197 GObjectClass *object_class;
198 GtkObjectClass *gobject_class;
200 object_class = (GObjectClass*) class;
201 gobject_class = (GtkObjectClass*) class;
203 object_class->finalize = gtk_list_store_finalize;
204 gobject_class->destroy = gtk_list_store_destroy;
208 gtk_list_store_tree_model_init (GtkTreeModelIface *iface)
210 iface->get_flags = gtk_list_store_get_flags;
211 iface->get_n_columns = gtk_list_store_get_n_columns;
212 iface->get_column_type = gtk_list_store_get_column_type;
213 iface->get_iter = gtk_list_store_get_iter;
214 iface->get_path = gtk_list_store_get_path;
215 iface->get_value = gtk_list_store_get_value;
216 iface->iter_next = gtk_list_store_iter_next;
217 iface->iter_children = gtk_list_store_iter_children;
218 iface->iter_has_child = gtk_list_store_iter_has_child;
219 iface->iter_n_children = gtk_list_store_iter_n_children;
220 iface->iter_nth_child = gtk_list_store_iter_nth_child;
221 iface->iter_parent = gtk_list_store_iter_parent;
225 gtk_list_store_drag_source_init (GtkTreeDragSourceIface *iface)
227 iface->drag_data_delete = gtk_list_store_drag_data_delete;
228 iface->drag_data_get = gtk_list_store_drag_data_get;
232 gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface)
234 iface->drag_data_received = gtk_list_store_drag_data_received;
235 iface->row_drop_possible = gtk_list_store_row_drop_possible;
239 gtk_list_store_sortable_init (GtkTreeSortableIface *iface)
241 iface->get_sort_column_id = gtk_list_store_get_sort_column_id;
242 iface->set_sort_column_id = gtk_list_store_set_sort_column_id;
243 iface->set_sort_func = gtk_list_store_set_sort_func;
244 iface->set_default_sort_func = gtk_list_store_set_default_sort_func;
245 iface->has_default_sort_func = gtk_list_store_has_default_sort_func;
249 gtk_list_store_init (GtkListStore *list_store)
251 list_store->root = NULL;
252 list_store->tail = NULL;
253 list_store->sort_list = NULL;
254 list_store->stamp = g_random_int ();
255 list_store->length = 0;
256 list_store->sort_column_id = -2;
260 * gtk_list_store_new:
261 * @n_columns: number of columns in the list store
262 * @Varargs: all #GType types for the columns, from first to last
264 * Creates a new list store as with @n_columns columns each of the types passed
265 * in. As an example, gtk_tree_store_new (3, G_TYPE_INT, G_TYPE_STRING,
266 * GDK_TYPE_PIXBUF); will create a new GtkListStore with three columns, of type
267 * int, string and GDkPixbuf respectively.
269 * Return value: a new #GtkListStore
272 gtk_list_store_new (gint n_columns,
275 GtkListStore *retval;
279 g_return_val_if_fail (n_columns > 0, NULL);
281 retval = GTK_LIST_STORE (g_object_new (gtk_list_store_get_type (), NULL));
282 gtk_list_store_set_n_columns (retval, n_columns);
284 va_start (args, n_columns);
286 for (i = 0; i < n_columns; i++)
288 GType type = va_arg (args, GType);
289 if (! _gtk_tree_data_list_check_type (type))
291 g_warning ("%s: Invalid type %s passed to gtk_list_store_new\n", G_STRLOC, g_type_name (type));
292 g_object_unref (G_OBJECT (retval));
296 gtk_list_store_set_column_type (retval, i, type);
306 * gtk_list_store_newv:
307 * @n_columns: number of columns in the list store
308 * @types: an array of #GType types for the columns, from first to last
310 * Non vararg creation function. Used primarily by language bindings.
312 * Return value: a new #GtkListStore
315 gtk_list_store_newv (gint n_columns,
318 GtkListStore *retval;
321 g_return_val_if_fail (n_columns > 0, NULL);
323 retval = GTK_LIST_STORE (g_object_new (gtk_list_store_get_type (), NULL));
324 gtk_list_store_set_n_columns (retval, n_columns);
326 for (i = 0; i < n_columns; i++)
328 if (! _gtk_tree_data_list_check_type (types[i]))
330 g_warning ("%s: Invalid type %s passed to gtk_list_store_newv\n", G_STRLOC, g_type_name (types[i]));
331 g_object_unref (G_OBJECT (retval));
335 gtk_list_store_set_column_type (retval, i, types[i]);
342 gtk_list_store_set_n_columns (GtkListStore *list_store,
347 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
348 g_return_if_fail (n_columns > 0);
350 if (list_store->n_columns == n_columns)
353 new_columns = g_new0 (GType, n_columns);
354 if (list_store->column_headers)
356 /* copy the old header orders over */
357 if (n_columns >= list_store->n_columns)
358 memcpy (new_columns, list_store->column_headers, list_store->n_columns * sizeof (gchar *));
360 memcpy (new_columns, list_store->column_headers, n_columns * sizeof (GType));
362 g_free (list_store->column_headers);
365 if (list_store->sort_list)
366 _gtk_tree_data_list_header_free (list_store->sort_list);
368 list_store->sort_list = _gtk_tree_data_list_header_new (n_columns, list_store->column_headers);
370 list_store->column_headers = new_columns;
371 list_store->n_columns = n_columns;
375 gtk_list_store_set_column_type (GtkListStore *list_store,
379 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
380 g_return_if_fail (column >=0 && column < list_store->n_columns);
381 if (!_gtk_tree_data_list_check_type (type))
383 g_warning ("%s: Invalid type %s passed to gtk_list_store_set_column_type\n", G_STRLOC, g_type_name (type));
387 list_store->column_headers[column] = type;
391 gtk_list_store_finalize (GObject *object)
393 GtkListStore *list_store = GTK_LIST_STORE (object);
395 g_list_foreach (list_store->root, (GFunc) _gtk_tree_data_list_free, list_store->column_headers);
396 _gtk_tree_data_list_header_free (list_store->sort_list);
397 g_free (list_store->column_headers);
402 gtk_list_store_destroy (GtkObject *gobject)
404 GtkListStore *list_store = GTK_LIST_STORE (gobject);
406 if (list_store->default_sort_destroy)
408 (* list_store->default_sort_destroy) (list_store->default_sort_data);
409 list_store->default_sort_destroy = NULL;
410 list_store->default_sort_data = NULL;
414 /* Fulfill the GtkTreeModel requirements */
416 gtk_list_store_get_flags (GtkTreeModel *tree_model)
418 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
420 return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
424 gtk_list_store_get_n_columns (GtkTreeModel *tree_model)
426 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
428 return GTK_LIST_STORE (tree_model)->n_columns;
432 gtk_list_store_get_column_type (GtkTreeModel *tree_model,
435 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), G_TYPE_INVALID);
436 g_return_val_if_fail (index < GTK_LIST_STORE (tree_model)->n_columns &&
437 index >= 0, G_TYPE_INVALID);
439 return GTK_LIST_STORE (tree_model)->column_headers[index];
443 gtk_list_store_get_iter (GtkTreeModel *tree_model,
450 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
451 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
453 i = gtk_tree_path_get_indices (path)[0];
455 if (i >= GTK_LIST_STORE (tree_model)->length)
458 list = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root), i);
460 /* If this fails, list_store->length has gotten mangled. */
463 iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
464 iter->user_data = list;
469 gtk_list_store_get_path (GtkTreeModel *tree_model,
476 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), NULL);
477 g_return_val_if_fail (iter->stamp == GTK_LIST_STORE (tree_model)->stamp, NULL);
479 for (list = G_SLIST (GTK_LIST_STORE (tree_model)->root); list; list = list->next)
481 if (list == G_SLIST (iter->user_data))
488 retval = gtk_tree_path_new ();
489 gtk_tree_path_append_index (retval, i);
494 gtk_list_store_get_value (GtkTreeModel *tree_model,
499 GtkTreeDataList *list;
500 gint tmp_column = column;
502 g_return_if_fail (GTK_IS_LIST_STORE (tree_model));
503 g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns);
504 g_return_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp);
506 list = G_SLIST (iter->user_data)->data;
508 while (tmp_column-- > 0 && list)
512 g_value_init (value, GTK_LIST_STORE (tree_model)->column_headers[column]);
514 _gtk_tree_data_list_node_to_value (list,
515 GTK_LIST_STORE (tree_model)->column_headers[column],
520 gtk_list_store_iter_next (GtkTreeModel *tree_model,
523 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
524 g_return_val_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp, FALSE);
526 iter->user_data = G_SLIST (iter->user_data)->next;
528 return (iter->user_data != NULL);
532 gtk_list_store_iter_children (GtkTreeModel *tree_model,
536 /* this is a list, nodes have no children */
540 /* but if parent == NULL we return the list itself as children of the
544 if (GTK_LIST_STORE (tree_model)->root)
546 iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
547 iter->user_data = GTK_LIST_STORE (tree_model)->root;
555 gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
562 gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
565 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), -1);
567 return GTK_LIST_STORE (tree_model)->length;
569 g_return_val_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp, -1);
574 gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
581 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), FALSE);
586 child = g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root), n);
590 iter->stamp = GTK_LIST_STORE (tree_model)->stamp;
591 iter->user_data = child;
599 gtk_list_store_iter_parent (GtkTreeModel *tree_model,
607 gtk_list_store_real_set_value (GtkListStore *list_store,
612 GtkTreeDataList *list;
613 GtkTreeDataList *prev;
615 GValue real_value = {0, };
616 gboolean converted = FALSE;
617 gint orig_column = column;
618 gboolean retval = FALSE;
620 g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
621 g_return_val_if_fail (VALID_ITER (iter, list_store), FALSE);
622 g_return_val_if_fail (column >= 0 && column < list_store->n_columns, FALSE);
623 g_return_val_if_fail (G_IS_VALUE (value), FALSE);
625 if (! g_type_is_a (G_VALUE_TYPE (value), list_store->column_headers[column]))
627 if (! (g_value_type_compatible (G_VALUE_TYPE (value), list_store->column_headers[column]) &&
628 g_value_type_compatible (list_store->column_headers[column], G_VALUE_TYPE (value))))
630 g_warning ("%s: Unable to convert from %s to %s\n",
632 g_type_name (G_VALUE_TYPE (value)),
633 g_type_name (list_store->column_headers[column]));
636 if (!g_value_transform (value, &real_value))
638 g_warning ("%s: Unable to make conversion from %s to %s\n",
640 g_type_name (G_VALUE_TYPE (value)),
641 g_type_name (list_store->column_headers[column]));
642 g_value_unset (&real_value);
648 prev = list = G_SLIST (iter->user_data)->data;
654 path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
656 _gtk_tree_data_list_value_to_node (list, &real_value);
658 _gtk_tree_data_list_value_to_node (list, value);
660 gtk_tree_path_free (path);
662 g_value_unset (&real_value);
671 if (G_SLIST (iter->user_data)->data == NULL)
673 G_SLIST (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
678 list = prev->next = _gtk_tree_data_list_alloc ();
684 list->next = _gtk_tree_data_list_alloc ();
690 path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
692 _gtk_tree_data_list_value_to_node (list, &real_value);
694 _gtk_tree_data_list_value_to_node (list, value);
696 gtk_tree_path_free (path);
698 g_value_unset (&real_value);
700 if (GTK_LIST_STORE_IS_SORTED (list_store))
701 gtk_list_store_sort_iter_changed (list_store, iter, orig_column);
708 * gtk_list_store_set_value:
709 * @list_store: A #GtkListStore
710 * @iter: A valid #GtkTreeIter for the row being modified
711 * @column: column number to modify
712 * @value: new value for the cell
714 * Sets the data in the cell specified by @iter and @column.
715 * The type of @value must be convertible to the type of the
720 gtk_list_store_set_value (GtkListStore *list_store,
725 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
726 g_return_if_fail (VALID_ITER (iter, list_store));
727 g_return_if_fail (column >= 0 && column < list_store->n_columns);
728 g_return_if_fail (G_IS_VALUE (value));
730 if (gtk_list_store_real_set_value (list_store, iter, column, value))
734 path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), iter);
735 gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
736 gtk_tree_path_free (path);
741 * gtk_list_store_set_valist:
742 * @list_store: A #GtkListStore
743 * @iter: A valid #GtkTreeIter for the row being modified
744 * @var_args: va_list of column/value pairs
746 * See @gtk_list_store_set; this version takes a va_list for use by language
751 gtk_list_store_set_valist (GtkListStore *list_store,
756 gboolean emit_signal = FALSE;
758 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
759 g_return_if_fail (VALID_ITER (iter, list_store));
761 column = va_arg (var_args, gint);
765 GValue value = { 0, };
768 if (column >= list_store->n_columns)
770 g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
773 g_value_init (&value, list_store->column_headers[column]);
775 G_VALUE_COLLECT (&value, var_args, 0, &error);
778 g_warning ("%s: %s", G_STRLOC, error);
781 /* we purposely leak the value here, it might not be
782 * in a sane state if an error condition occoured
787 /* FIXME: instead of calling this n times, refactor with above */
788 emit_signal = gtk_list_store_real_set_value (list_store,
791 &value) || emit_signal;
793 g_value_unset (&value);
795 column = va_arg (var_args, gint);
802 path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), iter);
803 gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
804 gtk_tree_path_free (path);
809 * gtk_list_store_set:
810 * @list_store: a #GtkListStore
811 * @iter: row iterator
812 * @Varargs: pairs of column number and value, terminated with -1
814 * Sets the value of one or more cells in the row referenced by @iter.
815 * The variable argument list should contain integer column numbers,
816 * each column number followed by the value to be set.
817 * The list is terminated by a -1. For example, to set column 0 with type
818 * %G_TYPE_STRING to "Foo", you would write gtk_list_store_set (store, iter,
822 gtk_list_store_set (GtkListStore *list_store,
828 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
829 g_return_if_fail (iter != NULL);
830 g_return_if_fail (iter->stamp == list_store->stamp);
832 va_start (var_args, iter);
833 gtk_list_store_set_valist (list_store, iter, var_args);
838 remove_link_saving_prev (GSList *list,
853 prev->next = link->next;
872 gtk_list_store_remove_silently (GtkListStore *list_store,
876 if (G_SLIST (iter->user_data)->data)
878 _gtk_tree_data_list_free ((GtkTreeDataList *) G_SLIST (iter->user_data)->data,
879 list_store->column_headers);
880 G_SLIST (iter->user_data)->data = NULL;
886 list_store->root = remove_link_saving_prev (G_SLIST (list_store->root),
887 G_SLIST (iter->user_data),
890 list_store->length -= 1;
892 if (iter->user_data == list_store->tail)
893 list_store->tail = prev;
896 list_store->stamp ++;
900 * gtk_list_store_remove:
901 * @list_store: A #GtkListStore
902 * @iter: A valid #GtkTreeIter
904 * Removes the given row from the list store. After being removed, @iter is set to be the next valid row, or invalidated if it pointed to the last row inn @list_store
908 gtk_list_store_remove (GtkListStore *list_store,
914 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
915 g_return_if_fail (VALID_ITER (iter, list_store));
917 next = G_SLIST (iter->user_data)->next;
918 path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
920 validate_list_store (list_store);
922 gtk_list_store_remove_silently (list_store, iter, path);
924 validate_list_store (list_store);
926 list_store->stamp ++;
927 gtk_tree_model_row_deleted (GTK_TREE_MODEL (list_store), path);
928 gtk_tree_path_free (path);
932 iter->stamp = list_store->stamp;
933 iter->user_data = next;
942 insert_after (GtkListStore *list_store,
946 g_return_if_fail (sibling != NULL);
947 g_return_if_fail (new_list != NULL);
949 /* insert new node after list */
950 new_list->next = sibling->next;
951 sibling->next = new_list;
953 /* if list was the tail, the new node is the new tail */
954 if (sibling == ((GSList *) list_store->tail))
955 list_store->tail = new_list;
957 list_store->length += 1;
961 * gtk_list_store_insert:
962 * @list_store: A #GtkListStore
963 * @iter: An unset #GtkTreeIter to set to the new row
964 * @position: position to insert the new row
966 * Creates a new row at @position. @iter will be changed to point to this new
967 * row. If @position is larger than the number of rows on the list, then the
968 * new row will be appended to the list. The row will be empty before this
969 * function is called. To fill in values, you need to call @gtk_list_store_set
970 * or @gtk_list_store_set_value.
974 gtk_list_store_insert (GtkListStore *list_store,
982 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
983 g_return_if_fail (iter != NULL);
984 g_return_if_fail (position >= 0);
987 GTK_LIST_STORE_IS_SORTED (list_store))
989 gtk_list_store_prepend (list_store, iter);
993 new_list = g_slist_alloc ();
995 list = g_slist_nth (G_SLIST (list_store->root), position - 1);
999 g_warning ("%s: position %d is off the end of the list\n", G_STRLOC, position);
1003 insert_after (list_store, list, new_list);
1005 iter->stamp = list_store->stamp;
1006 iter->user_data = new_list;
1008 validate_list_store (list_store);
1010 path = gtk_tree_path_new ();
1011 gtk_tree_path_append_index (path, position);
1012 gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1013 gtk_tree_path_free (path);
1017 * gtk_list_store_insert_before:
1018 * @list_store: A #GtkListStore
1019 * @iter: An unset #GtkTreeIter to set to the new row
1020 * @sibling: A valid #GtkTreeIter, or %NULL
1022 * Inserts a new row before @sibling. If @sibling is %NULL, then the row will be
1023 * appended to the beginning of the list. @iter will be changed to point to
1024 * this new row. The row will be empty before this function is called. To fill
1025 * in values, you need to call @gtk_list_store_set or @gtk_list_store_set_value.
1029 gtk_list_store_insert_before (GtkListStore *list_store,
1031 GtkTreeIter *sibling)
1034 GSList *list, *prev, *new_list;
1037 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1038 g_return_if_fail (iter != NULL);
1040 g_return_if_fail (VALID_ITER (sibling, list_store));
1043 if (GTK_LIST_STORE_IS_SORTED (list_store))
1045 gtk_list_store_prepend (list_store, iter);
1049 if (sibling == NULL)
1051 gtk_list_store_append (list_store, iter);
1055 new_list = g_slist_alloc ();
1058 list = list_store->root;
1059 while (list && list != sibling->user_data)
1066 if (list != sibling->user_data)
1068 g_warning ("%s: sibling iterator invalid? not found in the list", G_STRLOC);
1072 /* if there are no nodes, we become the list tail, otherwise we
1073 * are inserting before any existing nodes so we can't change
1077 if (list_store->root == NULL)
1078 list_store->tail = new_list;
1082 new_list->next = prev->next;
1083 prev->next = new_list;
1087 new_list->next = list_store->root;
1088 list_store->root = new_list;
1091 iter->stamp = list_store->stamp;
1092 iter->user_data = new_list;
1094 list_store->length += 1;
1096 validate_list_store (list_store);
1098 path = gtk_tree_path_new ();
1099 gtk_tree_path_append_index (path, i);
1100 gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1101 gtk_tree_path_free (path);
1105 * gtk_list_store_insert_after:
1106 * @list_store: A #GtkListStore
1107 * @iter: An unset #GtkTreeIter to set to the new row
1108 * @sibling: A valid #GtkTreeIter, or %NULL
1110 * Inserts a new row after @sibling. If @sibling is %NULL, then the row will be
1111 * prepended to the beginning of the list. @iter will be changed to point to
1112 * this new row. The row will be empty after this function is called. To fill
1113 * in values, you need to call @gtk_list_store_set or @gtk_list_store_set_value.
1117 gtk_list_store_insert_after (GtkListStore *list_store,
1119 GtkTreeIter *sibling)
1122 GSList *list, *new_list;
1125 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1126 g_return_if_fail (iter != NULL);
1128 g_return_if_fail (VALID_ITER (sibling, list_store));
1130 if (sibling == NULL ||
1131 GTK_LIST_STORE_IS_SORTED (list_store))
1133 gtk_list_store_prepend (list_store, iter);
1137 for (list = list_store->root; list && list != sibling->user_data; list = list->next)
1140 g_return_if_fail (list == sibling->user_data);
1142 new_list = g_slist_alloc ();
1144 insert_after (list_store, list, new_list);
1146 iter->stamp = list_store->stamp;
1147 iter->user_data = new_list;
1149 validate_list_store (list_store);
1151 path = gtk_tree_path_new ();
1152 gtk_tree_path_append_index (path, i);
1153 gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1154 gtk_tree_path_free (path);
1158 * gtk_list_store_prepend:
1159 * @list_store: A #GtkListStore
1160 * @iter: An unset #GtkTreeIter to set to the prepend row
1162 * Prepend a new row to @list_store. @iter will be changed to point to this new
1163 * row. The row will be empty after this function is called. To fill in
1164 * values, you need to call @gtk_list_store_set or @gtk_list_store_set_value.
1168 gtk_list_store_prepend (GtkListStore *list_store,
1173 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1174 g_return_if_fail (iter != NULL);
1176 iter->stamp = list_store->stamp;
1177 iter->user_data = g_slist_alloc ();
1179 if (list_store->root == NULL)
1180 list_store->tail = iter->user_data;
1182 G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
1183 list_store->root = iter->user_data;
1185 list_store->length += 1;
1187 validate_list_store (list_store);
1189 path = gtk_tree_path_new ();
1190 gtk_tree_path_append_index (path, 0);
1191 gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1192 gtk_tree_path_free (path);
1196 * gtk_list_store_append:
1197 * @list_store: A #GtkListStore
1198 * @iter: An unset #GtkTreeIter to set to the appended row
1200 * Appends a new row to @list_store. @iter will be changed to point to this new
1201 * row. The row will be empty after this function is called. To fill in
1202 * values, you need to call @gtk_list_store_set or @gtk_list_store_set_value.
1206 gtk_list_store_append (GtkListStore *list_store,
1211 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1212 g_return_if_fail (iter != NULL);
1214 if (GTK_LIST_STORE_IS_SORTED (list_store))
1216 gtk_list_store_prepend (list_store, iter);
1220 iter->stamp = list_store->stamp;
1221 iter->user_data = g_slist_alloc ();
1223 if (list_store->tail)
1224 ((GSList *)list_store->tail)->next = iter->user_data;
1226 list_store->root = iter->user_data;
1228 list_store->tail = iter->user_data;
1230 list_store->length += 1;
1232 validate_list_store (list_store);
1234 path = gtk_tree_path_new ();
1235 gtk_tree_path_append_index (path, list_store->length - 1);
1236 gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1237 gtk_tree_path_free (path);
1241 gtk_list_store_clear (GtkListStore *list_store)
1244 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1246 while (list_store->root)
1248 iter.stamp = list_store->stamp;
1249 iter.user_data = list_store->root;
1250 gtk_list_store_remove (list_store, &iter);
1256 gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
1260 g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1262 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source),
1266 gtk_list_store_remove (GTK_LIST_STORE (drag_source), &iter);
1273 gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
1275 GtkSelectionData *selection_data)
1277 g_return_val_if_fail (GTK_IS_LIST_STORE (drag_source), FALSE);
1279 /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1280 * target, because the default handler does it for us, but
1281 * we do anyway for the convenience of someone maybe overriding the
1285 if (gtk_selection_data_set_tree_row (selection_data,
1286 GTK_TREE_MODEL (drag_source),
1293 /* FIXME handle text targets at least. */
1300 gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest,
1302 GtkSelectionData *selection_data)
1304 GtkTreeModel *tree_model;
1305 GtkListStore *list_store;
1306 GtkTreeModel *src_model = NULL;
1307 GtkTreePath *src_path = NULL;
1308 gboolean retval = FALSE;
1310 g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1312 tree_model = GTK_TREE_MODEL (drag_dest);
1313 list_store = GTK_LIST_STORE (drag_dest);
1315 if (gtk_selection_data_get_tree_row (selection_data,
1318 src_model == tree_model)
1320 /* Copy the given row to a new position */
1321 GtkTreeIter src_iter;
1322 GtkTreeIter dest_iter;
1325 if (!gtk_tree_model_get_iter (src_model,
1332 /* Get the path to insert _after_ (dest is the path to insert _before_) */
1333 prev = gtk_tree_path_copy (dest);
1335 if (!gtk_tree_path_prev (prev))
1337 /* dest was the first spot in the list; which means we are supposed
1340 gtk_list_store_prepend (GTK_LIST_STORE (tree_model),
1347 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model),
1351 GtkTreeIter tmp_iter = dest_iter;
1352 gtk_list_store_insert_after (GTK_LIST_STORE (tree_model),
1359 gtk_tree_path_free (prev);
1361 /* If we succeeded in creating dest_iter, copy data from src
1365 GtkTreeDataList *dl = G_SLIST (src_iter.user_data)->data;
1366 GtkTreeDataList *copy_head = NULL;
1367 GtkTreeDataList *copy_prev = NULL;
1368 GtkTreeDataList *copy_iter = NULL;
1375 copy_iter = _gtk_tree_data_list_node_copy (dl,
1376 list_store->column_headers[col]);
1378 if (copy_head == NULL)
1379 copy_head = copy_iter;
1382 copy_prev->next = copy_iter;
1384 copy_prev = copy_iter;
1390 dest_iter.stamp = GTK_LIST_STORE (tree_model)->stamp;
1391 G_SLIST (dest_iter.user_data)->data = copy_head;
1393 path = gtk_list_store_get_path (GTK_TREE_MODEL (tree_model), &dest_iter);
1394 gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_model), path, &dest_iter);
1395 gtk_tree_path_free (path);
1400 /* FIXME maybe add some data targets eventually, or handle text
1401 * targets in the simple case.
1408 gtk_tree_path_free (src_path);
1414 gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest,
1415 GtkTreeModel *src_model,
1416 GtkTreePath *src_path,
1417 GtkTreePath *dest_path)
1421 g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE);
1423 if (src_model != GTK_TREE_MODEL (drag_dest))
1426 if (gtk_tree_path_get_depth (dest_path) != 1)
1429 /* can drop before any existing node, or before one past any existing. */
1431 indices = gtk_tree_path_get_indices (dest_path);
1433 if (indices[0] <= GTK_LIST_STORE (drag_dest)->length)
1441 typedef struct _SortTuple
1448 gtk_list_store_compare_func (gconstpointer a,
1452 GtkListStore *list_store = user_data;
1453 GSList *el_a; /* Los Angeles? */
1458 GtkTreeIterCompareFunc func;
1462 if (list_store->sort_column_id != -1)
1464 GtkTreeDataSortHeader *header;
1466 header = _gtk_tree_data_list_get_header (list_store->sort_list,
1467 list_store->sort_column_id);
1468 g_return_val_if_fail (header != NULL, 0);
1469 g_return_val_if_fail (header->func != NULL, 0);
1471 func = header->func;
1472 data = header->data;
1476 g_return_val_if_fail (list_store->default_sort_func != NULL, 0);
1477 func = list_store->default_sort_func;
1478 data = list_store->default_sort_data;
1481 el_a = ((SortTuple *) a)->el;
1482 el_b = ((SortTuple *) b)->el;
1484 iter_a.stamp = list_store->stamp;
1485 iter_a.user_data = el_a;
1486 iter_b.stamp = list_store->stamp;
1487 iter_b.user_data = el_b;
1489 retval = (* func) (GTK_TREE_MODEL (list_store), &iter_a, &iter_b, data);
1491 if (list_store->order == GTK_SORT_DESCENDING)
1495 else if (retval < 0)
1502 gtk_list_store_sort (GtkListStore *list_store)
1511 if (list_store->length <= 1)
1514 g_assert (GTK_LIST_STORE_IS_SORTED (list_store));
1516 list = G_SLIST (list_store->root);
1518 sort_array = g_array_sized_new (FALSE, FALSE,
1520 list_store->length);
1522 for (i = 0; i < list_store->length; i++)
1526 /* If this fails, we are in an inconsistent state. Bad */
1527 g_return_if_fail (list != NULL);
1531 g_array_append_val (sort_array, tuple);
1536 g_array_sort_with_data (sort_array, gtk_list_store_compare_func, list_store);
1538 for (i = 0; i < list_store->length - 1; i++)
1539 g_array_index (sort_array, SortTuple, i).el->next =
1540 g_array_index (sort_array, SortTuple, i + 1).el;
1541 g_array_index (sort_array, SortTuple, list_store->length - 1).el->next = NULL;
1542 list_store->root = g_array_index (sort_array, SortTuple, 0).el;
1544 /* Let the world know about our new order */
1545 new_order = g_new (gint, list_store->length);
1546 for (i = 0; i < list_store->length; i++)
1547 new_order[i] = g_array_index (sort_array, SortTuple, i).offset;
1548 path = gtk_tree_path_new ();
1549 iter.stamp = list_store->stamp;
1550 iter.user_data = NULL;
1551 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
1552 path, &iter, new_order);
1553 gtk_tree_path_free (path);
1555 g_array_free (sort_array, TRUE);
1559 gtk_list_store_sort_iter_changed (GtkListStore *list_store,
1564 GSList *prev = NULL;
1565 GSList *next = NULL;
1566 GSList *list = G_SLIST (list_store->root);
1567 GtkTreePath *tmp_path;
1568 GtkTreeIter tmp_iter;
1575 GtkTreeIterCompareFunc func;
1578 if (list_store->length < 2)
1581 tmp_iter.stamp = list_store->stamp;
1583 if (list_store->sort_column_id != -1)
1585 GtkTreeDataSortHeader *header;
1586 header = _gtk_tree_data_list_get_header (list_store->sort_list,
1587 list_store->sort_column_id);
1588 g_return_if_fail (header != NULL);
1589 g_return_if_fail (header->func != NULL);
1590 func = header->func;
1591 data = header->data;
1595 g_return_if_fail (list_store->default_sort_func != NULL);
1596 func = list_store->default_sort_func;
1597 data = list_store->default_sort_data;
1600 /* If it's the built in function, we don't sort. */
1601 if (func == gtk_tree_data_list_compare_func &&
1602 list_store->sort_column_id != column)
1606 /* First we find the iter, its prev, and its next */
1609 if (list == G_SLIST (iter->user_data))
1615 g_assert (list != NULL);
1619 /* Check the common case, where we don't need to sort it moved. */
1622 tmp_iter.user_data = prev;
1623 cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
1628 tmp_iter.user_data = next;
1629 cmp_b = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
1633 if (list_store->order == GTK_SORT_DESCENDING)
1646 if (prev == NULL && cmp_b <= 0)
1648 else if (next == NULL && cmp_a <= 0)
1650 else if (prev != NULL && next != NULL &&
1651 cmp_a <= 0 && cmp_b <= 0)
1654 /* We actually need to sort it */
1655 /* First, remove the old link. */
1658 list_store->root = next;
1662 list_store->tail = prev;
1665 /* FIXME: as an optimization, we can potentially start at next */
1667 list = G_SLIST (list_store->root);
1669 tmp_iter.user_data = list;
1670 if (list_store->order == GTK_SORT_DESCENDING)
1671 cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
1673 cmp_a = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
1675 while ((list->next) && (cmp_a > 0))
1680 tmp_iter.user_data = list;
1681 if (list_store->order == GTK_SORT_DESCENDING)
1682 cmp_a = (* func) (GTK_TREE_MODEL (list_store), &tmp_iter, iter, data);
1684 cmp_a = (* func) (GTK_TREE_MODEL (list_store), iter, &tmp_iter, data);
1687 if ((!list->next) && (cmp_a > 0))
1689 list->next = G_SLIST (iter->user_data);
1690 list_store->tail = list->next;
1694 prev->next = G_SLIST (iter->user_data);
1695 G_SLIST (iter->user_data)->next = list;
1699 G_SLIST (iter->user_data)->next = G_SLIST (list_store->root);
1700 list_store->root = G_SLIST (iter->user_data);
1703 /* Emit the reordered signal. */
1704 new_order = g_new (int, list_store->length);
1705 if (old_location < new_location)
1706 for (i = 0; i < list_store->length; i++)
1708 if (i < old_location ||
1711 else if (i >= old_location &&
1713 new_order[i] = i + 1;
1714 else if (i == new_location)
1715 new_order[i] = old_location;
1718 for (i = 0; i < list_store->length; i++)
1720 if (i < new_location ||
1723 else if (i > new_location &&
1725 new_order[i] = i - 1;
1726 else if (i == new_location)
1727 new_order[i] = old_location;
1730 tmp_path = gtk_tree_path_new ();
1731 tmp_iter.user_data = NULL;
1733 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
1734 tmp_path, &tmp_iter,
1737 gtk_tree_path_free (tmp_path);
1742 gtk_list_store_get_sort_column_id (GtkTreeSortable *sortable,
1743 gint *sort_column_id,
1746 GtkListStore *list_store = (GtkListStore *) sortable;
1748 g_return_val_if_fail (GTK_IS_LIST_STORE (sortable), FALSE);
1750 if (list_store->sort_column_id == -1)
1754 * sort_column_id = list_store->sort_column_id;
1756 * order = list_store->order;
1761 gtk_list_store_set_sort_column_id (GtkTreeSortable *sortable,
1762 gint sort_column_id,
1765 GtkListStore *list_store = (GtkListStore *) sortable;
1767 g_return_if_fail (GTK_IS_LIST_STORE (sortable));
1769 if ((list_store->sort_column_id == sort_column_id) &&
1770 (list_store->order == order))
1773 if (sort_column_id != -1)
1775 GtkTreeDataSortHeader *header = NULL;
1777 header = _gtk_tree_data_list_get_header (list_store->sort_list, sort_column_id);
1779 /* We want to make sure that we have a function */
1780 g_return_if_fail (header != NULL);
1781 g_return_if_fail (header->func != NULL);
1785 g_return_if_fail (list_store->default_sort_func != NULL);
1789 list_store->sort_column_id = sort_column_id;
1790 list_store->order = order;
1792 gtk_list_store_sort (list_store);
1794 gtk_tree_sortable_sort_column_changed (sortable);
1798 gtk_list_store_set_sort_func (GtkTreeSortable *sortable,
1799 gint sort_column_id,
1800 GtkTreeIterCompareFunc func,
1802 GtkDestroyNotify destroy)
1804 GtkListStore *list_store = (GtkListStore *) sortable;
1805 GtkTreeDataSortHeader *header = NULL;
1808 g_return_if_fail (GTK_IS_LIST_STORE (sortable));
1809 g_return_if_fail (func != NULL);
1811 for (list = list_store->sort_list; list; list = list->next)
1813 header = (GtkTreeDataSortHeader*) list->data;
1814 if (header->sort_column_id == sort_column_id)
1820 header = g_new0 (GtkTreeDataSortHeader, 1);
1821 header->sort_column_id = sort_column_id;
1822 list_store->sort_list = g_list_append (list_store->sort_list, header);
1825 if (header->destroy)
1826 (* header->destroy) (header->data);
1828 header->func = func;
1829 header->data = data;
1830 header->destroy = destroy;
1835 gtk_list_store_set_default_sort_func (GtkTreeSortable *sortable,
1836 GtkTreeIterCompareFunc func,
1838 GtkDestroyNotify destroy)
1840 GtkListStore *list_store = (GtkListStore *) sortable;
1842 g_return_if_fail (GTK_IS_LIST_STORE (sortable));
1844 if (list_store->default_sort_destroy)
1845 (* list_store->default_sort_destroy) (list_store->default_sort_data);
1847 list_store->default_sort_func = func;
1848 list_store->default_sort_data = data;
1849 list_store->default_sort_destroy = destroy;
1853 gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable)
1855 GtkListStore *list_store = (GtkListStore *) sortable;
1857 g_return_val_if_fail (GTK_IS_LIST_STORE (sortable), FALSE);
1859 return (list_store->default_sort_func != NULL);