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.
22 #include <gobject/gvaluecollector.h>
23 #include "gtktreemodel.h"
24 #include "gtktreestore.h"
25 #include "gtktreedatalist.h"
26 #include "gtktreednd.h"
27 #include "gtkbuildable.h"
31 #define G_NODE(node) ((GNode *)node)
32 #define GTK_TREE_STORE_IS_SORTED(tree) (((GtkTreeStore*)(tree))->sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
33 #define VALID_ITER(iter, tree_store) ((iter)!= NULL && (iter)->user_data != NULL && ((GtkTreeStore*)(tree_store))->stamp == (iter)->stamp)
35 static void gtk_tree_store_tree_model_init (GtkTreeModelIface *iface);
36 static void gtk_tree_store_drag_source_init(GtkTreeDragSourceIface *iface);
37 static void gtk_tree_store_drag_dest_init (GtkTreeDragDestIface *iface);
38 static void gtk_tree_store_sortable_init (GtkTreeSortableIface *iface);
39 static void gtk_tree_store_buildable_init (GtkBuildableIface *iface);
40 static void gtk_tree_store_finalize (GObject *object);
41 static GtkTreeModelFlags gtk_tree_store_get_flags (GtkTreeModel *tree_model);
42 static gint gtk_tree_store_get_n_columns (GtkTreeModel *tree_model);
43 static GType gtk_tree_store_get_column_type (GtkTreeModel *tree_model,
45 static gboolean gtk_tree_store_get_iter (GtkTreeModel *tree_model,
48 static GtkTreePath *gtk_tree_store_get_path (GtkTreeModel *tree_model,
50 static void gtk_tree_store_get_value (GtkTreeModel *tree_model,
54 static gboolean gtk_tree_store_iter_next (GtkTreeModel *tree_model,
56 static gboolean gtk_tree_store_iter_children (GtkTreeModel *tree_model,
59 static gboolean gtk_tree_store_iter_has_child (GtkTreeModel *tree_model,
61 static gint gtk_tree_store_iter_n_children (GtkTreeModel *tree_model,
63 static gboolean gtk_tree_store_iter_nth_child (GtkTreeModel *tree_model,
67 static gboolean gtk_tree_store_iter_parent (GtkTreeModel *tree_model,
72 static void gtk_tree_store_set_n_columns (GtkTreeStore *tree_store,
74 static void gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
78 static void gtk_tree_store_increment_stamp (GtkTreeStore *tree_store);
82 static gboolean real_gtk_tree_store_row_draggable (GtkTreeDragSource *drag_source,
84 static gboolean gtk_tree_store_drag_data_delete (GtkTreeDragSource *drag_source,
86 static gboolean gtk_tree_store_drag_data_get (GtkTreeDragSource *drag_source,
88 GtkSelectionData *selection_data);
89 static gboolean gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest,
91 GtkSelectionData *selection_data);
92 static gboolean gtk_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest,
93 GtkTreePath *dest_path,
94 GtkSelectionData *selection_data);
96 /* Sortable Interfaces */
98 static void gtk_tree_store_sort (GtkTreeStore *tree_store);
99 static void gtk_tree_store_sort_iter_changed (GtkTreeStore *tree_store,
102 gboolean emit_signal);
103 static gboolean gtk_tree_store_get_sort_column_id (GtkTreeSortable *sortable,
104 gint *sort_column_id,
106 static void gtk_tree_store_set_sort_column_id (GtkTreeSortable *sortable,
109 static void gtk_tree_store_set_sort_func (GtkTreeSortable *sortable,
111 GtkTreeIterCompareFunc func,
113 GtkDestroyNotify destroy);
114 static void gtk_tree_store_set_default_sort_func (GtkTreeSortable *sortable,
115 GtkTreeIterCompareFunc func,
117 GtkDestroyNotify destroy);
118 static gboolean gtk_tree_store_has_default_sort_func (GtkTreeSortable *sortable);
123 static gboolean gtk_tree_store_buildable_custom_tag_start (GtkBuildable *buildable,
126 const gchar *tagname,
127 GMarkupParser *parser,
129 static void gtk_tree_store_buildable_custom_finished (GtkBuildable *buildable,
132 const gchar *tagname,
135 static void validate_gnode (GNode *node);
137 static void gtk_tree_store_move (GtkTreeStore *tree_store,
139 GtkTreeIter *position,
144 validate_tree (GtkTreeStore *tree_store)
146 if (gtk_debug_flags & GTK_DEBUG_TREE)
148 g_assert (G_NODE (tree_store->root)->parent == NULL);
150 validate_gnode (G_NODE (tree_store->root));
154 G_DEFINE_TYPE_WITH_CODE (GtkTreeStore, gtk_tree_store, G_TYPE_OBJECT,
155 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
156 gtk_tree_store_tree_model_init)
157 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
158 gtk_tree_store_drag_source_init)
159 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
160 gtk_tree_store_drag_dest_init)
161 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
162 gtk_tree_store_sortable_init)
163 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
164 gtk_tree_store_buildable_init))
167 gtk_tree_store_class_init (GtkTreeStoreClass *class)
169 GObjectClass *object_class;
171 object_class = (GObjectClass *) class;
173 object_class->finalize = gtk_tree_store_finalize;
177 gtk_tree_store_tree_model_init (GtkTreeModelIface *iface)
179 iface->get_flags = gtk_tree_store_get_flags;
180 iface->get_n_columns = gtk_tree_store_get_n_columns;
181 iface->get_column_type = gtk_tree_store_get_column_type;
182 iface->get_iter = gtk_tree_store_get_iter;
183 iface->get_path = gtk_tree_store_get_path;
184 iface->get_value = gtk_tree_store_get_value;
185 iface->iter_next = gtk_tree_store_iter_next;
186 iface->iter_children = gtk_tree_store_iter_children;
187 iface->iter_has_child = gtk_tree_store_iter_has_child;
188 iface->iter_n_children = gtk_tree_store_iter_n_children;
189 iface->iter_nth_child = gtk_tree_store_iter_nth_child;
190 iface->iter_parent = gtk_tree_store_iter_parent;
194 gtk_tree_store_drag_source_init (GtkTreeDragSourceIface *iface)
196 iface->row_draggable = real_gtk_tree_store_row_draggable;
197 iface->drag_data_delete = gtk_tree_store_drag_data_delete;
198 iface->drag_data_get = gtk_tree_store_drag_data_get;
202 gtk_tree_store_drag_dest_init (GtkTreeDragDestIface *iface)
204 iface->drag_data_received = gtk_tree_store_drag_data_received;
205 iface->row_drop_possible = gtk_tree_store_row_drop_possible;
209 gtk_tree_store_sortable_init (GtkTreeSortableIface *iface)
211 iface->get_sort_column_id = gtk_tree_store_get_sort_column_id;
212 iface->set_sort_column_id = gtk_tree_store_set_sort_column_id;
213 iface->set_sort_func = gtk_tree_store_set_sort_func;
214 iface->set_default_sort_func = gtk_tree_store_set_default_sort_func;
215 iface->has_default_sort_func = gtk_tree_store_has_default_sort_func;
219 gtk_tree_store_buildable_init (GtkBuildableIface *iface)
221 iface->custom_tag_start = gtk_tree_store_buildable_custom_tag_start;
222 iface->custom_finished = gtk_tree_store_buildable_custom_finished;
226 gtk_tree_store_init (GtkTreeStore *tree_store)
228 tree_store->root = g_node_new (NULL);
229 /* While the odds are against us getting 0...
233 tree_store->stamp = g_random_int ();
235 while (tree_store->stamp == 0);
237 tree_store->sort_list = NULL;
238 tree_store->sort_column_id = -2;
239 tree_store->columns_dirty = FALSE;
243 * gtk_tree_store_new:
244 * @n_columns: number of columns in the tree store
245 * @Varargs: all #GType types for the columns, from first to last
247 * Creates a new tree store as with @n_columns columns each of the types passed
248 * in. Note that only types derived from standard GObject fundamental types
251 * As an example, <literal>gtk_tree_store_new (3, G_TYPE_INT, G_TYPE_STRING,
252 * GDK_TYPE_PIXBUF);</literal> will create a new #GtkTreeStore with three columns, of type
253 * <type>int</type>, <type>string</type> and #GdkPixbuf respectively.
255 * Return value: a new #GtkTreeStore
258 gtk_tree_store_new (gint n_columns,
261 GtkTreeStore *retval;
265 g_return_val_if_fail (n_columns > 0, NULL);
267 retval = g_object_new (GTK_TYPE_TREE_STORE, NULL);
268 gtk_tree_store_set_n_columns (retval, n_columns);
270 va_start (args, n_columns);
272 for (i = 0; i < n_columns; i++)
274 GType type = va_arg (args, GType);
275 if (! _gtk_tree_data_list_check_type (type))
277 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
278 g_object_unref (retval);
281 gtk_tree_store_set_column_type (retval, i, type);
288 * gtk_tree_store_newv:
289 * @n_columns: number of columns in the tree store
290 * @types: an array of #GType types for the columns, from first to last
292 * Non vararg creation function. Used primarily by language bindings.
294 * Return value: a new #GtkTreeStore
297 gtk_tree_store_newv (gint n_columns,
300 GtkTreeStore *retval;
303 g_return_val_if_fail (n_columns > 0, NULL);
305 retval = g_object_new (GTK_TYPE_TREE_STORE, NULL);
306 gtk_tree_store_set_n_columns (retval, n_columns);
308 for (i = 0; i < n_columns; i++)
310 if (! _gtk_tree_data_list_check_type (types[i]))
312 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i]));
313 g_object_unref (retval);
316 gtk_tree_store_set_column_type (retval, i, types[i]);
324 * gtk_tree_store_set_column_types:
325 * @tree_store: A #GtkTreeStore
326 * @n_columns: Number of columns for the tree store
327 * @types: An array of #GType types, one for each column
329 * This function is meant primarily for #GObjects that inherit from
330 * #GtkTreeStore, and should only be used when constructing a new
331 * #GtkTreeStore. It will not function after a row has been added,
332 * or a method on the #GtkTreeModel interface is called.
335 gtk_tree_store_set_column_types (GtkTreeStore *tree_store,
341 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
342 g_return_if_fail (tree_store->columns_dirty == 0);
344 gtk_tree_store_set_n_columns (tree_store, n_columns);
345 for (i = 0; i < n_columns; i++)
347 if (! _gtk_tree_data_list_check_type (types[i]))
349 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i]));
352 gtk_tree_store_set_column_type (tree_store, i, types[i]);
357 gtk_tree_store_set_n_columns (GtkTreeStore *tree_store,
362 if (tree_store->n_columns == n_columns)
365 new_columns = g_new0 (GType, n_columns);
366 if (tree_store->column_headers)
368 /* copy the old header orders over */
369 if (n_columns >= tree_store->n_columns)
370 memcpy (new_columns, tree_store->column_headers, tree_store->n_columns * sizeof (gchar *));
372 memcpy (new_columns, tree_store->column_headers, n_columns * sizeof (GType));
374 g_free (tree_store->column_headers);
377 if (tree_store->sort_list)
378 _gtk_tree_data_list_header_free (tree_store->sort_list);
380 tree_store->sort_list = _gtk_tree_data_list_header_new (n_columns, tree_store->column_headers);
382 tree_store->column_headers = new_columns;
383 tree_store->n_columns = n_columns;
387 * gtk_tree_store_set_column_type:
388 * @tree_store: a #GtkTreeStore
389 * @column: column number
390 * @type: type of the data to be stored in @column
392 * Supported types include: %G_TYPE_UINT, %G_TYPE_INT, %G_TYPE_UCHAR,
393 * %G_TYPE_CHAR, %G_TYPE_BOOLEAN, %G_TYPE_POINTER, %G_TYPE_FLOAT,
394 * %G_TYPE_DOUBLE, %G_TYPE_STRING, %G_TYPE_OBJECT, and %G_TYPE_BOXED, along with
395 * subclasses of those types such as %GDK_TYPE_PIXBUF.
399 gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
403 if (!_gtk_tree_data_list_check_type (type))
405 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
408 tree_store->column_headers[column] = type;
412 node_free (GNode *node, gpointer data)
415 _gtk_tree_data_list_free (node->data, (GType*)data);
422 gtk_tree_store_finalize (GObject *object)
424 GtkTreeStore *tree_store = GTK_TREE_STORE (object);
426 g_node_traverse (tree_store->root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
427 node_free, tree_store->column_headers);
428 g_node_destroy (tree_store->root);
429 _gtk_tree_data_list_header_free (tree_store->sort_list);
430 g_free (tree_store->column_headers);
432 if (tree_store->default_sort_destroy)
434 GtkDestroyNotify d = tree_store->default_sort_destroy;
436 tree_store->default_sort_destroy = NULL;
437 d (tree_store->default_sort_data);
438 tree_store->default_sort_data = NULL;
442 G_OBJECT_CLASS (gtk_tree_store_parent_class)->finalize (object);
445 /* fulfill the GtkTreeModel requirements */
446 /* NOTE: GtkTreeStore::root is a GNode, that acts as the parent node. However,
447 * it is not visible to the tree or to the user., and the path "0" refers to the
448 * first child of GtkTreeStore::root.
452 static GtkTreeModelFlags
453 gtk_tree_store_get_flags (GtkTreeModel *tree_model)
455 return GTK_TREE_MODEL_ITERS_PERSIST;
459 gtk_tree_store_get_n_columns (GtkTreeModel *tree_model)
461 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
463 tree_store->columns_dirty = TRUE;
465 return tree_store->n_columns;
469 gtk_tree_store_get_column_type (GtkTreeModel *tree_model,
472 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
474 g_return_val_if_fail (index < tree_store->n_columns, G_TYPE_INVALID);
476 tree_store->columns_dirty = TRUE;
478 return tree_store->column_headers[index];
482 gtk_tree_store_get_iter (GtkTreeModel *tree_model,
486 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
491 tree_store->columns_dirty = TRUE;
493 indices = gtk_tree_path_get_indices (path);
494 depth = gtk_tree_path_get_depth (path);
496 g_return_val_if_fail (depth > 0, FALSE);
498 parent.stamp = tree_store->stamp;
499 parent.user_data = tree_store->root;
501 if (!gtk_tree_store_iter_nth_child (tree_model, iter, &parent, indices[0]))
504 for (i = 1; i < depth; i++)
507 if (!gtk_tree_store_iter_nth_child (tree_model, iter, &parent, indices[i]))
515 gtk_tree_store_get_path (GtkTreeModel *tree_model,
518 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
523 g_return_val_if_fail (iter->user_data != NULL, NULL);
524 g_return_val_if_fail (iter->stamp == tree_store->stamp, NULL);
526 validate_tree (tree_store);
528 if (G_NODE (iter->user_data)->parent == NULL &&
529 G_NODE (iter->user_data) == tree_store->root)
530 return gtk_tree_path_new ();
531 g_assert (G_NODE (iter->user_data)->parent != NULL);
533 if (G_NODE (iter->user_data)->parent == G_NODE (tree_store->root))
535 retval = gtk_tree_path_new ();
536 tmp_node = G_NODE (tree_store->root)->children;
540 GtkTreeIter tmp_iter = *iter;
542 tmp_iter.user_data = G_NODE (iter->user_data)->parent;
544 retval = gtk_tree_store_get_path (tree_model, &tmp_iter);
545 tmp_node = G_NODE (iter->user_data)->parent->children;
551 if (tmp_node == NULL)
553 gtk_tree_path_free (retval);
557 for (; tmp_node; tmp_node = tmp_node->next)
559 if (tmp_node == G_NODE (iter->user_data))
564 if (tmp_node == NULL)
566 /* We couldn't find node, meaning it's prolly not ours */
567 /* Perhaps I should do a g_return_if_fail here. */
568 gtk_tree_path_free (retval);
572 gtk_tree_path_append_index (retval, i);
579 gtk_tree_store_get_value (GtkTreeModel *tree_model,
584 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
585 GtkTreeDataList *list;
586 gint tmp_column = column;
588 g_return_if_fail (column < tree_store->n_columns);
589 g_return_if_fail (VALID_ITER (iter, tree_store));
591 list = G_NODE (iter->user_data)->data;
593 while (tmp_column-- > 0 && list)
598 _gtk_tree_data_list_node_to_value (list,
599 tree_store->column_headers[column],
604 /* We want to return an initialized but empty (default) value */
605 g_value_init (value, tree_store->column_headers[column]);
610 gtk_tree_store_iter_next (GtkTreeModel *tree_model,
613 g_return_val_if_fail (iter->user_data != NULL, FALSE);
614 g_return_val_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->stamp, FALSE);
616 if (G_NODE (iter->user_data)->next)
618 iter->user_data = G_NODE (iter->user_data)->next;
626 gtk_tree_store_iter_children (GtkTreeModel *tree_model,
630 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
634 g_return_val_if_fail (VALID_ITER (parent, tree_store), FALSE);
637 children = G_NODE (parent->user_data)->children;
639 children = G_NODE (tree_store->root)->children;
643 iter->stamp = tree_store->stamp;
644 iter->user_data = children;
652 gtk_tree_store_iter_has_child (GtkTreeModel *tree_model,
655 g_return_val_if_fail (iter->user_data != NULL, FALSE);
656 g_return_val_if_fail (VALID_ITER (iter, tree_model), FALSE);
658 return G_NODE (iter->user_data)->children != NULL;
662 gtk_tree_store_iter_n_children (GtkTreeModel *tree_model,
668 g_return_val_if_fail (iter == NULL || iter->user_data != NULL, 0);
671 node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
673 node = G_NODE (iter->user_data)->children;
685 gtk_tree_store_iter_nth_child (GtkTreeModel *tree_model,
690 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
694 g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
697 parent_node = tree_store->root;
699 parent_node = parent->user_data;
701 child = g_node_nth_child (parent_node, n);
705 iter->user_data = child;
706 iter->stamp = tree_store->stamp;
714 gtk_tree_store_iter_parent (GtkTreeModel *tree_model,
718 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
721 g_return_val_if_fail (iter != NULL, FALSE);
722 g_return_val_if_fail (VALID_ITER (child, tree_store), FALSE);
724 parent = G_NODE (child->user_data)->parent;
726 g_assert (parent != NULL);
728 if (parent != tree_store->root)
730 iter->user_data = parent;
731 iter->stamp = tree_store->stamp;
739 /* Does not emit a signal */
741 gtk_tree_store_real_set_value (GtkTreeStore *tree_store,
747 GtkTreeDataList *list;
748 GtkTreeDataList *prev;
749 gint old_column = column;
750 GValue real_value = {0, };
751 gboolean converted = FALSE;
752 gboolean retval = FALSE;
754 if (! g_type_is_a (G_VALUE_TYPE (value), tree_store->column_headers[column]))
756 if (! (g_value_type_compatible (G_VALUE_TYPE (value), tree_store->column_headers[column]) &&
757 g_value_type_compatible (tree_store->column_headers[column], G_VALUE_TYPE (value))))
759 g_warning ("%s: Unable to convert from %s to %s\n",
761 g_type_name (G_VALUE_TYPE (value)),
762 g_type_name (tree_store->column_headers[column]));
765 if (!g_value_transform (value, &real_value))
767 g_warning ("%s: Unable to make conversion from %s to %s\n",
769 g_type_name (G_VALUE_TYPE (value)),
770 g_type_name (tree_store->column_headers[column]));
771 g_value_unset (&real_value);
777 prev = list = G_NODE (iter->user_data)->data;
784 _gtk_tree_data_list_value_to_node (list, &real_value);
786 _gtk_tree_data_list_value_to_node (list, value);
789 g_value_unset (&real_value);
790 if (sort && GTK_TREE_STORE_IS_SORTED (tree_store))
791 gtk_tree_store_sort_iter_changed (tree_store, iter, old_column, TRUE);
800 if (G_NODE (iter->user_data)->data == NULL)
802 G_NODE (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
807 list = prev->next = _gtk_tree_data_list_alloc ();
813 list->next = _gtk_tree_data_list_alloc ();
820 _gtk_tree_data_list_value_to_node (list, &real_value);
822 _gtk_tree_data_list_value_to_node (list, value);
826 g_value_unset (&real_value);
828 if (sort && GTK_TREE_STORE_IS_SORTED (tree_store))
829 gtk_tree_store_sort_iter_changed (tree_store, iter, old_column, TRUE);
835 * gtk_tree_store_set_value:
836 * @tree_store: a #GtkTreeStore
837 * @iter: A valid #GtkTreeIter for the row being modified
838 * @column: column number to modify
839 * @value: new value for the cell
841 * Sets the data in the cell specified by @iter and @column.
842 * The type of @value must be convertible to the type of the
847 gtk_tree_store_set_value (GtkTreeStore *tree_store,
852 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
853 g_return_if_fail (VALID_ITER (iter, tree_store));
854 g_return_if_fail (column >= 0 && column < tree_store->n_columns);
855 g_return_if_fail (G_IS_VALUE (value));
857 if (gtk_tree_store_real_set_value (tree_store, iter, column, value, TRUE))
861 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
862 gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter);
863 gtk_tree_path_free (path);
867 static GtkTreeIterCompareFunc
868 gtk_tree_store_get_compare_func (GtkTreeStore *tree_store)
870 GtkTreeIterCompareFunc func = NULL;
872 if (GTK_TREE_STORE_IS_SORTED (tree_store))
874 if (tree_store->sort_column_id != -1)
876 GtkTreeDataSortHeader *header;
877 header = _gtk_tree_data_list_get_header (tree_store->sort_list,
878 tree_store->sort_column_id);
879 g_return_val_if_fail (header != NULL, NULL);
880 g_return_val_if_fail (header->func != NULL, NULL);
885 func = tree_store->default_sort_func;
893 gtk_tree_store_set_vector_internal (GtkTreeStore *tree_store,
895 gboolean *emit_signal,
896 gboolean *maybe_need_sort,
902 GtkTreeIterCompareFunc func = NULL;
904 func = gtk_tree_store_get_compare_func (tree_store);
905 if (func != _gtk_tree_data_list_compare_func)
906 *maybe_need_sort = TRUE;
908 for (i = 0; i < n_values; i++)
910 *emit_signal = gtk_tree_store_real_set_value (tree_store, iter,
911 columns[i], &values[i],
912 FALSE) || *emit_signal;
914 if (func == _gtk_tree_data_list_compare_func &&
915 columns[i] == tree_store->sort_column_id)
916 *maybe_need_sort = TRUE;
921 gtk_tree_store_set_valist_internal (GtkTreeStore *tree_store,
923 gboolean *emit_signal,
924 gboolean *maybe_need_sort,
928 GtkTreeIterCompareFunc func = NULL;
930 column = va_arg (var_args, gint);
932 func = gtk_tree_store_get_compare_func (tree_store);
933 if (func != _gtk_tree_data_list_compare_func)
934 *maybe_need_sort = TRUE;
938 GValue value = { 0, };
941 if (column < 0 || column >= tree_store->n_columns)
943 g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
946 g_value_init (&value, tree_store->column_headers[column]);
948 G_VALUE_COLLECT (&value, var_args, 0, &error);
951 g_warning ("%s: %s", G_STRLOC, error);
954 /* we purposely leak the value here, it might not be
955 * in a sane state if an error condition occoured
960 *emit_signal = gtk_tree_store_real_set_value (tree_store,
964 FALSE) || *emit_signal;
966 if (func == _gtk_tree_data_list_compare_func &&
967 column == tree_store->sort_column_id)
968 *maybe_need_sort = TRUE;
970 g_value_unset (&value);
972 column = va_arg (var_args, gint);
977 * gtk_tree_store_set_valuesv:
978 * @tree_store: A #GtkTreeStore
979 * @iter: A valid #GtkTreeIter for the row being modified
980 * @columns: an array of column numbers
981 * @values: an array of GValues
982 * @n_values: the length of the @columns and @values arrays
984 * A variant of gtk_tree_store_set_valist() which takes
985 * the columns and values as two arrays, instead of varargs. This
986 * function is mainly intended for language bindings or in case
987 * the number of columns to change is not known until run-time.
992 gtk_tree_store_set_valuesv (GtkTreeStore *tree_store,
998 gboolean emit_signal = FALSE;
999 gboolean maybe_need_sort = FALSE;
1001 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1002 g_return_if_fail (VALID_ITER (iter, tree_store));
1004 gtk_tree_store_set_vector_internal (tree_store, iter,
1007 columns, values, n_values);
1009 if (maybe_need_sort && GTK_TREE_STORE_IS_SORTED (tree_store))
1010 gtk_tree_store_sort_iter_changed (tree_store, iter, tree_store->sort_column_id, TRUE);
1016 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1017 gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter);
1018 gtk_tree_path_free (path);
1023 * gtk_tree_store_set_valist:
1024 * @tree_store: A #GtkTreeStore
1025 * @iter: A valid #GtkTreeIter for the row being modified
1026 * @var_args: <type>va_list</type> of column/value pairs
1028 * See gtk_tree_store_set(); this version takes a <type>va_list</type> for
1029 * use by language bindings.
1033 gtk_tree_store_set_valist (GtkTreeStore *tree_store,
1037 gboolean emit_signal = FALSE;
1038 gboolean maybe_need_sort = FALSE;
1040 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1041 g_return_if_fail (VALID_ITER (iter, tree_store));
1043 gtk_tree_store_set_valist_internal (tree_store, iter,
1048 if (maybe_need_sort && GTK_TREE_STORE_IS_SORTED (tree_store))
1049 gtk_tree_store_sort_iter_changed (tree_store, iter, tree_store->sort_column_id, TRUE);
1055 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1056 gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter);
1057 gtk_tree_path_free (path);
1062 * gtk_tree_store_set:
1063 * @tree_store: A #GtkTreeStore
1064 * @iter: A valid #GtkTreeIter for the row being modified
1065 * @Varargs: pairs of column number and value, terminated with -1
1067 * Sets the value of one or more cells in the row referenced by @iter.
1068 * The variable argument list should contain integer column numbers,
1069 * each column number followed by the value to be set.
1070 * The list is terminated by a -1. For example, to set column 0 with type
1071 * %G_TYPE_STRING to "Foo", you would write
1072 * <literal>gtk_tree_store_set (store, iter, 0, "Foo", -1)</literal>.
1075 gtk_tree_store_set (GtkTreeStore *tree_store,
1081 va_start (var_args, iter);
1082 gtk_tree_store_set_valist (tree_store, iter, var_args);
1087 * gtk_tree_store_remove:
1088 * @tree_store: A #GtkTreeStore
1089 * @iter: A valid #GtkTreeIter
1091 * Removes @iter from @tree_store. After being removed, @iter is set to the
1092 * next valid row at that level, or invalidated if it previously pointed to the
1095 * Return value: %TRUE if @iter is still valid, %FALSE if not.
1098 gtk_tree_store_remove (GtkTreeStore *tree_store,
1102 GtkTreeIter new_iter = {0,};
1106 g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), FALSE);
1107 g_return_val_if_fail (VALID_ITER (iter, tree_store), FALSE);
1109 parent = G_NODE (iter->user_data)->parent;
1111 g_assert (parent != NULL);
1112 next_node = G_NODE (iter->user_data)->next;
1114 if (G_NODE (iter->user_data)->data)
1115 g_node_traverse (G_NODE (iter->user_data), G_POST_ORDER, G_TRAVERSE_ALL,
1116 -1, node_free, tree_store->column_headers);
1118 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1119 g_node_destroy (G_NODE (iter->user_data));
1121 gtk_tree_model_row_deleted (GTK_TREE_MODEL (tree_store), path);
1123 if (parent != G_NODE (tree_store->root))
1126 if (parent->children == NULL)
1128 gtk_tree_path_up (path);
1130 new_iter.stamp = tree_store->stamp;
1131 new_iter.user_data = parent;
1132 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, &new_iter);
1135 gtk_tree_path_free (path);
1137 /* revalidate iter */
1138 if (next_node != NULL)
1140 iter->stamp = tree_store->stamp;
1141 iter->user_data = next_node;
1147 iter->user_data = NULL;
1154 * gtk_tree_store_insert:
1155 * @tree_store: A #GtkTreeStore
1156 * @iter: An unset #GtkTreeIter to set to the new row
1157 * @parent: A valid #GtkTreeIter, or %NULL
1158 * @position: position to insert the new row
1160 * Creates a new row at @position. If parent is non-%NULL, then the row will be
1161 * made a child of @parent. Otherwise, the row will be created at the toplevel.
1162 * If @position is larger than the number of rows at that level, then the new
1163 * row will be inserted to the end of the list. @iter will be changed to point
1164 * to this new row. The row will be empty after this function is called. To
1165 * fill in values, you need to call gtk_tree_store_set() or
1166 * gtk_tree_store_set_value().
1170 gtk_tree_store_insert (GtkTreeStore *tree_store,
1172 GtkTreeIter *parent,
1179 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1180 g_return_if_fail (iter != NULL);
1182 g_return_if_fail (VALID_ITER (parent, tree_store));
1185 parent_node = parent->user_data;
1187 parent_node = tree_store->root;
1189 tree_store->columns_dirty = TRUE;
1191 new_node = g_node_new (NULL);
1193 iter->stamp = tree_store->stamp;
1194 iter->user_data = new_node;
1195 g_node_insert (parent_node, position, new_node);
1197 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1198 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1200 if (parent_node != tree_store->root)
1202 if (new_node->prev == NULL && new_node->next == NULL)
1204 gtk_tree_path_up (path);
1205 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
1209 gtk_tree_path_free (path);
1211 validate_tree ((GtkTreeStore*)tree_store);
1215 * gtk_tree_store_insert_before:
1216 * @tree_store: A #GtkTreeStore
1217 * @iter: An unset #GtkTreeIter to set to the new row
1218 * @parent: A valid #GtkTreeIter, or %NULL
1219 * @sibling: A valid #GtkTreeIter, or %NULL
1221 * Inserts a new row before @sibling. If @sibling is %NULL, then the row will
1222 * be appended to @parent 's children. If @parent and @sibling are %NULL, then
1223 * the row will be appended to the toplevel. If both @sibling and @parent are
1224 * set, then @parent must be the parent of @sibling. When @sibling is set,
1225 * @parent is optional.
1227 * @iter will be changed to point to this new row. The row will be empty after
1228 * this function is called. To fill in values, you need to call
1229 * gtk_tree_store_set() or gtk_tree_store_set_value().
1233 gtk_tree_store_insert_before (GtkTreeStore *tree_store,
1235 GtkTreeIter *parent,
1236 GtkTreeIter *sibling)
1239 GNode *parent_node = NULL;
1242 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1243 g_return_if_fail (iter != NULL);
1245 g_return_if_fail (VALID_ITER (parent, tree_store));
1246 if (sibling != NULL)
1247 g_return_if_fail (VALID_ITER (sibling, tree_store));
1249 if (parent == NULL && sibling == NULL)
1250 parent_node = tree_store->root;
1251 else if (parent == NULL)
1252 parent_node = G_NODE (sibling->user_data)->parent;
1253 else if (sibling == NULL)
1254 parent_node = G_NODE (parent->user_data);
1257 g_return_if_fail (G_NODE (sibling->user_data)->parent == G_NODE (parent->user_data));
1258 parent_node = G_NODE (parent->user_data);
1261 tree_store->columns_dirty = TRUE;
1263 new_node = g_node_new (NULL);
1265 g_node_insert_before (parent_node,
1266 sibling ? G_NODE (sibling->user_data) : NULL,
1269 iter->stamp = tree_store->stamp;
1270 iter->user_data = new_node;
1272 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1273 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1275 if (parent_node != tree_store->root)
1277 if (new_node->prev == NULL && new_node->next == NULL)
1279 GtkTreeIter parent_iter;
1281 parent_iter.stamp = tree_store->stamp;
1282 parent_iter.user_data = parent_node;
1284 gtk_tree_path_up (path);
1285 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, &parent_iter);
1289 gtk_tree_path_free (path);
1291 validate_tree (tree_store);
1295 * gtk_tree_store_insert_after:
1296 * @tree_store: A #GtkTreeStore
1297 * @iter: An unset #GtkTreeIter to set to the new row
1298 * @parent: A valid #GtkTreeIter, or %NULL
1299 * @sibling: A valid #GtkTreeIter, or %NULL
1301 * Inserts a new row after @sibling. If @sibling is %NULL, then the row will be
1302 * prepended to @parent 's children. If @parent and @sibling are %NULL, then
1303 * the row will be prepended to the toplevel. If both @sibling and @parent are
1304 * set, then @parent must be the parent of @sibling. When @sibling is set,
1305 * @parent is optional.
1307 * @iter will be changed to point to this new row. The row will be empty after
1308 * this function is called. To fill in values, you need to call
1309 * gtk_tree_store_set() or gtk_tree_store_set_value().
1313 gtk_tree_store_insert_after (GtkTreeStore *tree_store,
1315 GtkTreeIter *parent,
1316 GtkTreeIter *sibling)
1322 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1323 g_return_if_fail (iter != NULL);
1325 g_return_if_fail (VALID_ITER (parent, tree_store));
1326 if (sibling != NULL)
1327 g_return_if_fail (VALID_ITER (sibling, tree_store));
1329 if (parent == NULL && sibling == NULL)
1330 parent_node = tree_store->root;
1331 else if (parent == NULL)
1332 parent_node = G_NODE (sibling->user_data)->parent;
1333 else if (sibling == NULL)
1334 parent_node = G_NODE (parent->user_data);
1337 g_return_if_fail (G_NODE (sibling->user_data)->parent ==
1338 G_NODE (parent->user_data));
1339 parent_node = G_NODE (parent->user_data);
1342 tree_store->columns_dirty = TRUE;
1344 new_node = g_node_new (NULL);
1346 g_node_insert_after (parent_node,
1347 sibling ? G_NODE (sibling->user_data) : NULL,
1350 iter->stamp = tree_store->stamp;
1351 iter->user_data = new_node;
1353 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1354 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1356 if (parent_node != tree_store->root)
1358 if (new_node->prev == NULL && new_node->next == NULL)
1360 GtkTreeIter parent_iter;
1362 parent_iter.stamp = tree_store->stamp;
1363 parent_iter.user_data = parent_node;
1365 gtk_tree_path_up (path);
1366 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, &parent_iter);
1370 gtk_tree_path_free (path);
1372 validate_tree (tree_store);
1376 * gtk_tree_store_insert_with_values:
1377 * @tree_store: A #GtkTreeStore
1378 * @iter: An unset #GtkTreeIter to set the new row, or %NULL.
1379 * @parent: A valid #GtkTreeIter, or %NULL
1380 * @position: position to insert the new row
1381 * @Varargs: pairs of column number and value, terminated with -1
1383 * Creates a new row at @position. @iter will be changed to point to this
1384 * new row. If @position is larger than the number of rows on the list, then
1385 * the new row will be appended to the list. The row will be filled with
1386 * the values given to this function.
1389 * <literal>gtk_tree_store_insert_with_values (tree_store, iter, position, ...)</literal>
1390 * has the same effect as calling
1392 * gtk_tree_store_insert (tree_store, iter, position);
1393 * gtk_tree_store_set (tree_store, iter, ...);
1395 * with the different that the former will only emit a row_inserted signal,
1396 * while the latter will emit row_inserted, row_changed and if the tree store
1397 * is sorted, rows_reordered. Since emitting the rows_reordered signal
1398 * repeatedly can affect the performance of the program,
1399 * gtk_tree_store_insert_with_values() should generally be preferred when
1400 * inserting rows in a sorted tree store.
1405 gtk_tree_store_insert_with_values (GtkTreeStore *tree_store,
1407 GtkTreeIter *parent,
1414 GtkTreeIter tmp_iter;
1416 gboolean changed = FALSE;
1417 gboolean maybe_need_sort = FALSE;
1419 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1425 g_return_if_fail (VALID_ITER (parent, tree_store));
1428 parent_node = parent->user_data;
1430 parent_node = tree_store->root;
1432 tree_store->columns_dirty = TRUE;
1434 new_node = g_node_new (NULL);
1436 iter->stamp = tree_store->stamp;
1437 iter->user_data = new_node;
1438 g_node_insert (parent_node, position, new_node);
1440 va_start (var_args, position);
1441 gtk_tree_store_set_valist_internal (tree_store, iter,
1442 &changed, &maybe_need_sort,
1446 if (maybe_need_sort && GTK_TREE_STORE_IS_SORTED (tree_store))
1447 gtk_tree_store_sort_iter_changed (tree_store, iter, tree_store->sort_column_id, FALSE);
1449 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1450 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1452 if (parent_node != tree_store->root)
1454 if (new_node->prev == NULL && new_node->next == NULL)
1456 gtk_tree_path_up (path);
1457 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
1461 gtk_tree_path_free (path);
1463 validate_tree ((GtkTreeStore *)tree_store);
1467 * gtk_tree_store_insert_with_valuesv:
1468 * @tree_store: A #GtkTreeStore
1469 * @iter: An unset #GtkTreeIter to set the new row, or %NULL.
1470 * @parent: A valid #GtkTreeIter, or %NULL
1471 * @position: position to insert the new row
1472 * @columns: an array of column numbers
1473 * @values: an array of GValues
1474 * @n_values: the length of the @columns and @values arrays
1476 * A variant of gtk_tree_store_insert_with_values() which takes
1477 * the columns and values as two arrays, instead of varargs. This
1478 * function is mainly intended for language bindings.
1483 gtk_tree_store_insert_with_valuesv (GtkTreeStore *tree_store,
1485 GtkTreeIter *parent,
1494 GtkTreeIter tmp_iter;
1495 gboolean changed = FALSE;
1496 gboolean maybe_need_sort = FALSE;
1498 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1504 g_return_if_fail (VALID_ITER (parent, tree_store));
1507 parent_node = parent->user_data;
1509 parent_node = tree_store->root;
1511 tree_store->columns_dirty = TRUE;
1513 new_node = g_node_new (NULL);
1515 iter->stamp = tree_store->stamp;
1516 iter->user_data = new_node;
1517 g_node_insert (parent_node, position, new_node);
1519 gtk_tree_store_set_vector_internal (tree_store, iter,
1520 &changed, &maybe_need_sort,
1521 columns, values, n_values);
1523 if (maybe_need_sort && GTK_TREE_STORE_IS_SORTED (tree_store))
1524 gtk_tree_store_sort_iter_changed (tree_store, iter, tree_store->sort_column_id, FALSE);
1526 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1527 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1529 if (parent_node != tree_store->root)
1531 if (new_node->prev == NULL && new_node->next == NULL)
1533 gtk_tree_path_up (path);
1534 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
1538 gtk_tree_path_free (path);
1540 validate_tree ((GtkTreeStore *)tree_store);
1544 * gtk_tree_store_prepend:
1545 * @tree_store: A #GtkTreeStore
1546 * @iter: An unset #GtkTreeIter to set to the prepended row
1547 * @parent: A valid #GtkTreeIter, or %NULL
1549 * Prepends a new row to @tree_store. If @parent is non-%NULL, then it will prepend
1550 * the new row before the first child of @parent, otherwise it will prepend a row
1551 * to the top level. @iter will be changed to point to this new row. The row
1552 * will be empty after this function is called. To fill in values, you need to
1553 * call gtk_tree_store_set() or gtk_tree_store_set_value().
1556 gtk_tree_store_prepend (GtkTreeStore *tree_store,
1558 GtkTreeIter *parent)
1562 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1563 g_return_if_fail (iter != NULL);
1565 g_return_if_fail (VALID_ITER (parent, tree_store));
1567 tree_store->columns_dirty = TRUE;
1570 parent_node = tree_store->root;
1572 parent_node = parent->user_data;
1574 if (parent_node->children == NULL)
1578 iter->stamp = tree_store->stamp;
1579 iter->user_data = g_node_new (NULL);
1581 g_node_prepend (parent_node, G_NODE (iter->user_data));
1583 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1584 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1586 if (parent_node != tree_store->root)
1588 gtk_tree_path_up (path);
1589 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
1591 gtk_tree_path_free (path);
1595 gtk_tree_store_insert_after (tree_store, iter, parent, NULL);
1598 validate_tree (tree_store);
1602 * gtk_tree_store_append:
1603 * @tree_store: A #GtkTreeStore
1604 * @iter: An unset #GtkTreeIter to set to the appended row
1605 * @parent: A valid #GtkTreeIter, or %NULL
1607 * Appends a new row to @tree_store. If @parent is non-%NULL, then it will append the
1608 * new row after the last child of @parent, otherwise it will append a row to
1609 * the top level. @iter will be changed to point to this new row. The row will
1610 * be empty after this function is called. To fill in values, you need to call
1611 * gtk_tree_store_set() or gtk_tree_store_set_value().
1614 gtk_tree_store_append (GtkTreeStore *tree_store,
1616 GtkTreeIter *parent)
1620 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1621 g_return_if_fail (iter != NULL);
1623 g_return_if_fail (VALID_ITER (parent, tree_store));
1626 parent_node = tree_store->root;
1628 parent_node = parent->user_data;
1630 tree_store->columns_dirty = TRUE;
1632 if (parent_node->children == NULL)
1636 iter->stamp = tree_store->stamp;
1637 iter->user_data = g_node_new (NULL);
1639 g_node_append (parent_node, G_NODE (iter->user_data));
1641 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1642 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1644 if (parent_node != tree_store->root)
1646 gtk_tree_path_up (path);
1647 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
1649 gtk_tree_path_free (path);
1653 gtk_tree_store_insert_before (tree_store, iter, parent, NULL);
1656 validate_tree (tree_store);
1660 * gtk_tree_store_is_ancestor:
1661 * @tree_store: A #GtkTreeStore
1662 * @iter: A valid #GtkTreeIter
1663 * @descendant: A valid #GtkTreeIter
1665 * Returns %TRUE if @iter is an ancestor of @descendant. That is, @iter is the
1666 * parent (or grandparent or great-grandparent) of @descendant.
1668 * Return value: %TRUE, if @iter is an ancestor of @descendant
1671 gtk_tree_store_is_ancestor (GtkTreeStore *tree_store,
1673 GtkTreeIter *descendant)
1675 g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), FALSE);
1676 g_return_val_if_fail (VALID_ITER (iter, tree_store), FALSE);
1677 g_return_val_if_fail (VALID_ITER (descendant, tree_store), FALSE);
1679 return g_node_is_ancestor (G_NODE (iter->user_data),
1680 G_NODE (descendant->user_data));
1685 * gtk_tree_store_iter_depth:
1686 * @tree_store: A #GtkTreeStore
1687 * @iter: A valid #GtkTreeIter
1689 * Returns the depth of @iter. This will be 0 for anything on the root level, 1
1690 * for anything down a level, etc.
1692 * Return value: The depth of @iter
1695 gtk_tree_store_iter_depth (GtkTreeStore *tree_store,
1698 g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), 0);
1699 g_return_val_if_fail (VALID_ITER (iter, tree_store), 0);
1701 return g_node_depth (G_NODE (iter->user_data)) - 2;
1704 /* simple ripoff from g_node_traverse_post_order */
1706 gtk_tree_store_clear_traverse (GNode *node,
1707 GtkTreeStore *store)
1715 child = node->children;
1718 register GNode *current;
1721 child = current->next;
1722 if (gtk_tree_store_clear_traverse (current, store))
1728 iter.stamp = store->stamp;
1729 iter.user_data = node;
1731 gtk_tree_store_remove (store, &iter);
1734 else if (node->parent)
1736 iter.stamp = store->stamp;
1737 iter.user_data = node;
1739 gtk_tree_store_remove (store, &iter);
1746 gtk_tree_store_increment_stamp (GtkTreeStore *tree_store)
1750 tree_store->stamp++;
1752 while (tree_store->stamp == 0);
1756 * gtk_tree_store_clear:
1757 * @tree_store: a #GtkTreeStore
1759 * Removes all rows from @tree_store
1762 gtk_tree_store_clear (GtkTreeStore *tree_store)
1764 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1766 gtk_tree_store_clear_traverse (tree_store->root, tree_store);
1767 gtk_tree_store_increment_stamp (tree_store);
1771 gtk_tree_store_iter_is_valid_helper (GtkTreeIter *iter,
1780 if (node == iter->user_data)
1784 if (gtk_tree_store_iter_is_valid_helper (iter, node->children))
1795 * gtk_tree_store_iter_is_valid:
1796 * @tree_store: A #GtkTreeStore.
1797 * @iter: A #GtkTreeIter.
1799 * WARNING: This function is slow. Only use it for debugging and/or testing
1802 * Checks if the given iter is a valid iter for this #GtkTreeStore.
1804 * Return value: %TRUE if the iter is valid, %FALSE if the iter is invalid.
1809 gtk_tree_store_iter_is_valid (GtkTreeStore *tree_store,
1812 g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), FALSE);
1813 g_return_val_if_fail (iter != NULL, FALSE);
1815 if (!VALID_ITER (iter, tree_store))
1818 return gtk_tree_store_iter_is_valid_helper (iter, tree_store->root);
1824 static gboolean real_gtk_tree_store_row_draggable (GtkTreeDragSource *drag_source,
1831 gtk_tree_store_drag_data_delete (GtkTreeDragSource *drag_source,
1836 if (gtk_tree_store_get_iter (GTK_TREE_MODEL (drag_source),
1840 gtk_tree_store_remove (GTK_TREE_STORE (drag_source),
1851 gtk_tree_store_drag_data_get (GtkTreeDragSource *drag_source,
1853 GtkSelectionData *selection_data)
1855 /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1856 * target, because the default handler does it for us, but
1857 * we do anyway for the convenience of someone maybe overriding the
1861 if (gtk_tree_set_row_drag_data (selection_data,
1862 GTK_TREE_MODEL (drag_source),
1869 /* FIXME handle text targets at least. */
1876 copy_node_data (GtkTreeStore *tree_store,
1877 GtkTreeIter *src_iter,
1878 GtkTreeIter *dest_iter)
1880 GtkTreeDataList *dl = G_NODE (src_iter->user_data)->data;
1881 GtkTreeDataList *copy_head = NULL;
1882 GtkTreeDataList *copy_prev = NULL;
1883 GtkTreeDataList *copy_iter = NULL;
1890 copy_iter = _gtk_tree_data_list_node_copy (dl, tree_store->column_headers[col]);
1892 if (copy_head == NULL)
1893 copy_head = copy_iter;
1896 copy_prev->next = copy_iter;
1898 copy_prev = copy_iter;
1904 G_NODE (dest_iter->user_data)->data = copy_head;
1906 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), dest_iter);
1907 gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, dest_iter);
1908 gtk_tree_path_free (path);
1912 recursive_node_copy (GtkTreeStore *tree_store,
1913 GtkTreeIter *src_iter,
1914 GtkTreeIter *dest_iter)
1917 GtkTreeModel *model;
1919 model = GTK_TREE_MODEL (tree_store);
1921 copy_node_data (tree_store, src_iter, dest_iter);
1923 if (gtk_tree_store_iter_children (model,
1927 /* Need to create children and recurse. Note our
1928 * dependence on persistent iterators here.
1934 /* Gee, a really slow algorithm... ;-) FIXME */
1935 gtk_tree_store_append (tree_store,
1939 recursive_node_copy (tree_store, &child, ©);
1941 while (gtk_tree_store_iter_next (model, &child));
1946 gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest,
1948 GtkSelectionData *selection_data)
1950 GtkTreeModel *tree_model;
1951 GtkTreeStore *tree_store;
1952 GtkTreeModel *src_model = NULL;
1953 GtkTreePath *src_path = NULL;
1954 gboolean retval = FALSE;
1956 tree_model = GTK_TREE_MODEL (drag_dest);
1957 tree_store = GTK_TREE_STORE (drag_dest);
1959 validate_tree (tree_store);
1961 if (gtk_tree_get_row_drag_data (selection_data,
1964 src_model == tree_model)
1966 /* Copy the given row to a new position */
1967 GtkTreeIter src_iter;
1968 GtkTreeIter dest_iter;
1971 if (!gtk_tree_store_get_iter (src_model,
1978 /* Get the path to insert _after_ (dest is the path to insert _before_) */
1979 prev = gtk_tree_path_copy (dest);
1981 if (!gtk_tree_path_prev (prev))
1983 GtkTreeIter dest_parent;
1984 GtkTreePath *parent;
1985 GtkTreeIter *dest_parent_p;
1987 /* dest was the first spot at the current depth; which means
1988 * we are supposed to prepend.
1991 /* Get the parent, NULL if parent is the root */
1992 dest_parent_p = NULL;
1993 parent = gtk_tree_path_copy (dest);
1994 if (gtk_tree_path_up (parent) &&
1995 gtk_tree_path_get_depth (parent) > 0)
1997 gtk_tree_store_get_iter (tree_model,
2000 dest_parent_p = &dest_parent;
2002 gtk_tree_path_free (parent);
2005 gtk_tree_store_prepend (tree_store,
2013 if (gtk_tree_store_get_iter (tree_model, &dest_iter, prev))
2015 GtkTreeIter tmp_iter = dest_iter;
2017 gtk_tree_store_insert_after (tree_store, &dest_iter, NULL,
2024 gtk_tree_path_free (prev);
2026 /* If we succeeded in creating dest_iter, walk src_iter tree branch,
2027 * duplicating it below dest_iter.
2032 recursive_node_copy (tree_store,
2039 /* FIXME maybe add some data targets eventually, or handle text
2040 * targets in the simple case.
2048 gtk_tree_path_free (src_path);
2054 gtk_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest,
2055 GtkTreePath *dest_path,
2056 GtkSelectionData *selection_data)
2058 GtkTreeModel *src_model = NULL;
2059 GtkTreePath *src_path = NULL;
2060 GtkTreePath *tmp = NULL;
2061 gboolean retval = FALSE;
2063 /* don't accept drops if the tree has been sorted */
2064 if (GTK_TREE_STORE_IS_SORTED (drag_dest))
2067 if (!gtk_tree_get_row_drag_data (selection_data,
2072 /* can only drag to ourselves */
2073 if (src_model != GTK_TREE_MODEL (drag_dest))
2076 /* Can't drop into ourself. */
2077 if (gtk_tree_path_is_ancestor (src_path,
2081 /* Can't drop if dest_path's parent doesn't exist */
2085 if (gtk_tree_path_get_depth (dest_path) > 1)
2087 tmp = gtk_tree_path_copy (dest_path);
2088 gtk_tree_path_up (tmp);
2090 if (!gtk_tree_store_get_iter (GTK_TREE_MODEL (drag_dest),
2096 /* Can otherwise drop anywhere. */
2102 gtk_tree_path_free (src_path);
2104 gtk_tree_path_free (tmp);
2109 /* Sorting and reordering */
2110 typedef struct _SortTuple
2118 gtk_tree_store_reorder_func (gconstpointer a,
2122 SortTuple *a_reorder;
2123 SortTuple *b_reorder;
2125 a_reorder = (SortTuple *)a;
2126 b_reorder = (SortTuple *)b;
2128 if (a_reorder->offset < b_reorder->offset)
2130 if (a_reorder->offset > b_reorder->offset)
2137 * gtk_tree_store_reorder:
2138 * @tree_store: A #GtkTreeStore.
2139 * @parent: A #GtkTreeIter.
2140 * @new_order: an array of integers mapping the new position of each child
2141 * to its old position before the re-ordering,
2142 * i.e. @new_order<literal>[newpos] = oldpos</literal>.
2144 * Reorders the children of @parent in @tree_store to follow the order
2145 * indicated by @new_order. Note that this function only works with
2151 gtk_tree_store_reorder (GtkTreeStore *tree_store,
2152 GtkTreeIter *parent,
2156 GNode *level, *node;
2158 SortTuple *sort_array;
2160 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
2161 g_return_if_fail (!GTK_TREE_STORE_IS_SORTED (tree_store));
2162 g_return_if_fail (parent == NULL || VALID_ITER (parent, tree_store));
2163 g_return_if_fail (new_order != NULL);
2166 level = G_NODE (tree_store->root)->children;
2168 level = G_NODE (parent->user_data)->children;
2178 /* set up sortarray */
2179 sort_array = g_new (SortTuple, length);
2182 for (i = 0; i < length; i++)
2184 sort_array[new_order[i]].offset = i;
2185 sort_array[i].node = node;
2190 g_qsort_with_data (sort_array,
2193 gtk_tree_store_reorder_func,
2197 for (i = 0; i < length - 1; i++)
2199 sort_array[i].node->next = sort_array[i+1].node;
2200 sort_array[i+1].node->prev = sort_array[i].node;
2203 sort_array[length-1].node->next = NULL;
2204 sort_array[0].node->prev = NULL;
2206 G_NODE (parent->user_data)->children = sort_array[0].node;
2208 G_NODE (tree_store->root)->children = sort_array[0].node;
2212 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), parent);
2214 path = gtk_tree_path_new ();
2215 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), path,
2217 gtk_tree_path_free (path);
2218 g_free (sort_array);
2222 * gtk_tree_store_swap:
2223 * @tree_store: A #GtkTreeStore.
2224 * @a: A #GtkTreeIter.
2225 * @b: Another #GtkTreeIter.
2227 * Swaps @a and @b in the same level of @tree_store. Note that this function
2228 * only works with unsorted stores.
2233 gtk_tree_store_swap (GtkTreeStore *tree_store,
2237 GNode *tmp, *node_a, *node_b, *parent_node;
2238 GNode *a_prev, *a_next, *b_prev, *b_next;
2239 gint i, a_count, b_count, length, *order;
2240 GtkTreePath *path_a, *path_b;
2243 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
2244 g_return_if_fail (VALID_ITER (a, tree_store));
2245 g_return_if_fail (VALID_ITER (b, tree_store));
2247 node_a = G_NODE (a->user_data);
2248 node_b = G_NODE (b->user_data);
2250 /* basic sanity checking */
2251 if (node_a == node_b)
2254 path_a = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), a);
2255 path_b = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), b);
2257 g_return_if_fail (path_a && path_b);
2259 gtk_tree_path_up (path_a);
2260 gtk_tree_path_up (path_b);
2262 if (gtk_tree_path_get_depth (path_a) == 0
2263 || gtk_tree_path_get_depth (path_b) == 0)
2265 if (gtk_tree_path_get_depth (path_a) != gtk_tree_path_get_depth (path_b))
2267 gtk_tree_path_free (path_a);
2268 gtk_tree_path_free (path_b);
2270 g_warning ("Given children are not in the same level\n");
2273 parent_node = G_NODE (tree_store->root);
2277 if (gtk_tree_path_compare (path_a, path_b))
2279 gtk_tree_path_free (path_a);
2280 gtk_tree_path_free (path_b);
2282 g_warning ("Given children don't have a common parent\n");
2285 gtk_tree_store_get_iter (GTK_TREE_MODEL (tree_store), &parent,
2287 parent_node = G_NODE (parent.user_data);
2289 gtk_tree_path_free (path_b);
2291 /* old links which we have to keep around */
2292 a_prev = node_a->prev;
2293 a_next = node_a->next;
2295 b_prev = node_b->prev;
2296 b_next = node_b->next;
2298 /* fix up links if the nodes are next to eachother */
2299 if (a_prev == node_b)
2301 if (a_next == node_b)
2304 if (b_prev == node_a)
2306 if (b_next == node_a)
2309 /* counting nodes */
2310 tmp = parent_node->children;
2311 i = a_count = b_count = 0;
2324 /* hacking the tree */
2326 parent_node->children = node_b;
2328 a_prev->next = node_b;
2331 a_next->prev = node_b;
2334 parent_node->children = node_a;
2336 b_prev->next = node_a;
2339 b_next->prev = node_a;
2341 node_a->prev = b_prev;
2342 node_a->next = b_next;
2344 node_b->prev = a_prev;
2345 node_b->next = a_next;
2348 order = g_new (gint, length);
2349 for (i = 0; i < length; i++)
2352 else if (i == b_count)
2357 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), path_a,
2358 parent_node == tree_store->root
2359 ? NULL : &parent, order);
2360 gtk_tree_path_free (path_a);
2364 /* WARNING: this function is *incredibly* fragile. Please smashtest after
2365 * making changes here.
2369 gtk_tree_store_move (GtkTreeStore *tree_store,
2371 GtkTreeIter *position,
2374 GNode *parent, *node, *a, *b, *tmp, *tmp_a, *tmp_b;
2375 gint old_pos, new_pos, length, i, *order;
2376 GtkTreePath *path = NULL, *tmppath, *pos_path = NULL;
2377 GtkTreeIter parent_iter, dst_a, dst_b;
2379 gboolean handle_b = TRUE;
2381 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
2382 g_return_if_fail (!GTK_TREE_STORE_IS_SORTED (tree_store));
2383 g_return_if_fail (VALID_ITER (iter, tree_store));
2385 g_return_if_fail (VALID_ITER (position, tree_store));
2392 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
2393 pos_path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store),
2397 * moving the iter before path or "path + 1" doesn't make sense
2399 * moving the iter before path or "path - 1" doesn't make sense
2401 if (!gtk_tree_path_compare (path, pos_path))
2402 goto free_paths_and_out;
2405 gtk_tree_path_next (path);
2407 gtk_tree_path_prev (path);
2409 if (!gtk_tree_path_compare (path, pos_path))
2410 goto free_paths_and_out;
2413 gtk_tree_path_prev (path);
2415 gtk_tree_path_next (path);
2417 if (gtk_tree_path_get_depth (path) != gtk_tree_path_get_depth (pos_path))
2419 g_warning ("Given children are not in the same level\n");
2421 goto free_paths_and_out;
2424 tmppath = gtk_tree_path_copy (pos_path);
2425 gtk_tree_path_up (path);
2426 gtk_tree_path_up (tmppath);
2428 if (gtk_tree_path_get_depth (path) > 0 &&
2429 gtk_tree_path_compare (path, tmppath))
2431 g_warning ("Given children are not in the same level\n");
2433 gtk_tree_path_free (tmppath);
2434 goto free_paths_and_out;
2437 gtk_tree_path_free (tmppath);
2442 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
2443 gtk_tree_path_up (path);
2446 depth = gtk_tree_path_get_depth (path);
2450 gtk_tree_store_get_iter (GTK_TREE_MODEL (tree_store),
2451 &parent_iter, path);
2453 parent = G_NODE (parent_iter.user_data);
2456 parent = G_NODE (tree_store->root);
2458 /* yes, I know that this can be done shorter, but I'm doing it this way
2459 * so the code is also maintainable
2462 if (before && position)
2464 b = G_NODE (position->user_data);
2466 if (gtk_tree_path_get_indices (pos_path)[gtk_tree_path_get_depth (pos_path) - 1] > 0)
2468 gtk_tree_path_prev (pos_path);
2469 if (gtk_tree_store_get_iter (GTK_TREE_MODEL (tree_store),
2471 a = G_NODE (dst_a.user_data);
2474 gtk_tree_path_next (pos_path);
2477 /* if b is NULL, a is NULL too -- we are at the beginning of the list
2478 * yes and we leak memory here ...
2480 g_return_if_fail (b);
2482 else if (before && !position)
2484 /* move before without position is appending */
2491 a = G_NODE (position->user_data);
2497 gtk_tree_path_next (pos_path);
2498 if (gtk_tree_store_get_iter (GTK_TREE_MODEL (tree_store), &dst_b, pos_path))
2499 b = G_NODE (dst_b.user_data);
2502 gtk_tree_path_prev (pos_path);
2506 /* move after without position is prepending */
2508 gtk_tree_store_iter_children (GTK_TREE_MODEL (tree_store), &dst_b,
2511 gtk_tree_store_iter_children (GTK_TREE_MODEL (tree_store), &dst_b,
2514 b = G_NODE (dst_b.user_data);
2517 /* if a is NULL, b is NULL too -- we are at the end of the list
2518 * yes and we leak memory here ...
2521 g_return_if_fail (a);
2524 /* counting nodes */
2525 tmp = parent->children;
2527 length = old_pos = 0;
2530 if (tmp == iter->user_data)
2537 /* remove node from list */
2538 node = G_NODE (iter->user_data);
2543 tmp_a->next = tmp_b;
2545 parent->children = tmp_b;
2548 tmp_b->prev = tmp_a;
2550 /* and reinsert the node */
2559 else if (!a && !before)
2561 tmp = parent->children;
2564 parent->children = node;
2572 else if (!a && before)
2576 node->parent = NULL;
2577 node->next = node->prev = NULL;
2579 /* before with sibling = NULL appends */
2580 g_node_insert_before (parent, NULL, node);
2584 node->parent = NULL;
2585 node->next = node->prev = NULL;
2587 /* after with sibling = NULL prepends */
2588 g_node_insert_after (parent, NULL, node);
2604 else if (!(!a && before)) /* !a && before is completely handled above */
2610 new_pos = gtk_tree_path_get_indices (pos_path)[gtk_tree_path_get_depth (pos_path)-1];
2614 new_pos = gtk_tree_store_iter_n_children (GTK_TREE_MODEL (tree_store),
2617 new_pos = gtk_tree_store_iter_n_children (GTK_TREE_MODEL (tree_store),
2623 if (new_pos > old_pos)
2625 if (before && position)
2630 if (!before && position)
2634 order = g_new (gint, length);
2635 if (new_pos > old_pos)
2637 for (i = 0; i < length; i++)
2640 else if (i >= old_pos && i < new_pos)
2642 else if (i == new_pos)
2649 for (i = 0; i < length; i++)
2652 else if (i > new_pos && i <= old_pos)
2660 tmppath = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store),
2662 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store),
2663 tmppath, &parent_iter, order);
2667 tmppath = gtk_tree_path_new ();
2668 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store),
2669 tmppath, NULL, order);
2672 gtk_tree_path_free (tmppath);
2673 gtk_tree_path_free (path);
2675 gtk_tree_path_free (pos_path);
2681 gtk_tree_path_free (path);
2682 gtk_tree_path_free (pos_path);
2686 * gtk_tree_store_move_before:
2687 * @tree_store: A #GtkTreeStore.
2688 * @iter: A #GtkTreeIter.
2689 * @position: A #GtkTreeIter or %NULL.
2691 * Moves @iter in @tree_store to the position before @position. @iter and
2692 * @position should be in the same level. Note that this function only
2693 * works with unsorted stores. If @position is %NULL, @iter will be
2694 * moved to the end of the level.
2699 gtk_tree_store_move_before (GtkTreeStore *tree_store,
2701 GtkTreeIter *position)
2703 gtk_tree_store_move (tree_store, iter, position, TRUE);
2707 * gtk_tree_store_move_after:
2708 * @tree_store: A #GtkTreeStore.
2709 * @iter: A #GtkTreeIter.
2710 * @position: A #GtkTreeIter.
2712 * Moves @iter in @tree_store to the position after @position. @iter and
2713 * @position should be in the same level. Note that this function only
2714 * works with unsorted stores. If @position is %NULL, @iter will be moved
2715 * to the start of the level.
2720 gtk_tree_store_move_after (GtkTreeStore *tree_store,
2722 GtkTreeIter *position)
2724 gtk_tree_store_move (tree_store, iter, position, FALSE);
2729 gtk_tree_store_compare_func (gconstpointer a,
2733 GtkTreeStore *tree_store = user_data;
2736 GtkTreeIterCompareFunc func;
2743 if (tree_store->sort_column_id != -1)
2745 GtkTreeDataSortHeader *header;
2747 header = _gtk_tree_data_list_get_header (tree_store->sort_list,
2748 tree_store->sort_column_id);
2749 g_return_val_if_fail (header != NULL, 0);
2750 g_return_val_if_fail (header->func != NULL, 0);
2752 func = header->func;
2753 data = header->data;
2757 g_return_val_if_fail (tree_store->default_sort_func != NULL, 0);
2758 func = tree_store->default_sort_func;
2759 data = tree_store->default_sort_data;
2762 node_a = ((SortTuple *) a)->node;
2763 node_b = ((SortTuple *) b)->node;
2765 iter_a.stamp = tree_store->stamp;
2766 iter_a.user_data = node_a;
2767 iter_b.stamp = tree_store->stamp;
2768 iter_b.user_data = node_b;
2770 retval = (* func) (GTK_TREE_MODEL (user_data), &iter_a, &iter_b, data);
2772 if (tree_store->order == GTK_SORT_DESCENDING)
2776 else if (retval < 0)
2783 gtk_tree_store_sort_helper (GtkTreeStore *tree_store,
2796 node = parent->children;
2797 if (node == NULL || node->next == NULL)
2799 if (recurse && node && node->children)
2800 gtk_tree_store_sort_helper (tree_store, node, TRUE);
2806 for (tmp_node = node; tmp_node; tmp_node = tmp_node->next)
2809 sort_array = g_array_sized_new (FALSE, FALSE, sizeof (SortTuple), list_length);
2812 for (tmp_node = node; tmp_node; tmp_node = tmp_node->next)
2817 tuple.node = tmp_node;
2818 g_array_append_val (sort_array, tuple);
2822 /* Sort the array */
2823 g_array_sort_with_data (sort_array, gtk_tree_store_compare_func, tree_store);
2825 for (i = 0; i < list_length - 1; i++)
2827 g_array_index (sort_array, SortTuple, i).node->next =
2828 g_array_index (sort_array, SortTuple, i + 1).node;
2829 g_array_index (sort_array, SortTuple, i + 1).node->prev =
2830 g_array_index (sort_array, SortTuple, i).node;
2832 g_array_index (sort_array, SortTuple, list_length - 1).node->next = NULL;
2833 g_array_index (sort_array, SortTuple, 0).node->prev = NULL;
2834 parent->children = g_array_index (sort_array, SortTuple, 0).node;
2836 /* Let the world know about our new order */
2837 new_order = g_new (gint, list_length);
2838 for (i = 0; i < list_length; i++)
2839 new_order[i] = g_array_index (sort_array, SortTuple, i).offset;
2841 iter.stamp = tree_store->stamp;
2842 iter.user_data = parent;
2843 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), &iter);
2844 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store),
2845 path, &iter, new_order);
2846 gtk_tree_path_free (path);
2848 g_array_free (sort_array, TRUE);
2852 for (tmp_node = parent->children; tmp_node; tmp_node = tmp_node->next)
2854 if (tmp_node->children)
2855 gtk_tree_store_sort_helper (tree_store, tmp_node, TRUE);
2861 gtk_tree_store_sort (GtkTreeStore *tree_store)
2863 if (!GTK_TREE_STORE_IS_SORTED (tree_store))
2866 if (tree_store->sort_column_id != -1)
2868 GtkTreeDataSortHeader *header = NULL;
2870 header = _gtk_tree_data_list_get_header (tree_store->sort_list,
2871 tree_store->sort_column_id);
2873 /* We want to make sure that we have a function */
2874 g_return_if_fail (header != NULL);
2875 g_return_if_fail (header->func != NULL);
2879 g_return_if_fail (tree_store->default_sort_func != NULL);
2882 gtk_tree_store_sort_helper (tree_store, G_NODE (tree_store->root), TRUE);
2886 gtk_tree_store_sort_iter_changed (GtkTreeStore *tree_store,
2889 gboolean emit_signal)
2894 GtkTreePath *tmp_path;
2895 GtkTreeIter tmp_iter;
2903 GtkTreeIterCompareFunc func;
2906 g_return_if_fail (G_NODE (iter->user_data)->parent != NULL);
2908 tmp_iter.stamp = tree_store->stamp;
2909 if (tree_store->sort_column_id != -1)
2911 GtkTreeDataSortHeader *header;
2912 header = _gtk_tree_data_list_get_header (tree_store->sort_list,
2913 tree_store->sort_column_id);
2914 g_return_if_fail (header != NULL);
2915 g_return_if_fail (header->func != NULL);
2916 func = header->func;
2917 data = header->data;
2921 g_return_if_fail (tree_store->default_sort_func != NULL);
2922 func = tree_store->default_sort_func;
2923 data = tree_store->default_sort_data;
2926 /* If it's the built in function, we don't sort. */
2927 if (func == _gtk_tree_data_list_compare_func &&
2928 tree_store->sort_column_id != column)
2932 node = G_NODE (iter->user_data)->parent->children;
2933 /* First we find the iter, its prev, and its next */
2936 if (node == G_NODE (iter->user_data))
2941 g_assert (node != NULL);
2946 /* Check the common case, where we don't need to sort it moved. */
2949 tmp_iter.user_data = prev;
2950 cmp_a = (* func) (GTK_TREE_MODEL (tree_store), &tmp_iter, iter, data);
2955 tmp_iter.user_data = next;
2956 cmp_b = (* func) (GTK_TREE_MODEL (tree_store), iter, &tmp_iter, data);
2959 if (tree_store->order == GTK_SORT_DESCENDING)
2972 if (prev == NULL && cmp_b <= 0)
2974 else if (next == NULL && cmp_a <= 0)
2976 else if (prev != NULL && next != NULL &&
2977 cmp_a <= 0 && cmp_b <= 0)
2980 /* We actually need to sort it */
2981 /* First, remove the old link. */
2986 node->parent->children = next;
2994 /* FIXME: as an optimization, we can potentially start at next */
2996 node = node->parent->children;
2998 tmp_iter.user_data = node;
2999 if (tree_store->order == GTK_SORT_DESCENDING)
3000 cmp_a = (* func) (GTK_TREE_MODEL (tree_store), &tmp_iter, iter, data);
3002 cmp_a = (* func) (GTK_TREE_MODEL (tree_store), iter, &tmp_iter, data);
3004 while ((node->next) && (cmp_a > 0))
3009 tmp_iter.user_data = node;
3010 if (tree_store->order == GTK_SORT_DESCENDING)
3011 cmp_a = (* func) (GTK_TREE_MODEL (tree_store), &tmp_iter, iter, data);
3013 cmp_a = (* func) (GTK_TREE_MODEL (tree_store), iter, &tmp_iter, data);
3016 if ((!node->next) && (cmp_a > 0))
3019 node->next = G_NODE (iter->user_data);
3020 node->next->prev = node;
3024 prev->next = G_NODE (iter->user_data);
3025 prev->next->prev = prev;
3026 G_NODE (iter->user_data)->next = node;
3027 G_NODE (iter->user_data)->next->prev = G_NODE (iter->user_data);
3031 G_NODE (iter->user_data)->next = G_NODE (iter->user_data)->parent->children;
3032 G_NODE (iter->user_data)->next->prev = G_NODE (iter->user_data);
3033 G_NODE (iter->user_data)->parent->children = G_NODE (iter->user_data);
3039 /* Emit the reordered signal. */
3040 length = g_node_n_children (node->parent);
3041 new_order = g_new (int, length);
3042 if (old_location < new_location)
3043 for (i = 0; i < length; i++)
3045 if (i < old_location ||
3048 else if (i >= old_location &&
3050 new_order[i] = i + 1;
3051 else if (i == new_location)
3052 new_order[i] = old_location;
3055 for (i = 0; i < length; i++)
3057 if (i < new_location ||
3060 else if (i > new_location &&
3062 new_order[i] = i - 1;
3063 else if (i == new_location)
3064 new_order[i] = old_location;
3067 tmp_iter.user_data = node->parent;
3068 tmp_path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), &tmp_iter);
3070 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store),
3071 tmp_path, &tmp_iter,
3074 gtk_tree_path_free (tmp_path);
3080 gtk_tree_store_get_sort_column_id (GtkTreeSortable *sortable,
3081 gint *sort_column_id,
3084 GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
3087 * sort_column_id = tree_store->sort_column_id;
3089 * order = tree_store->order;
3091 if (tree_store->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID ||
3092 tree_store->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
3099 gtk_tree_store_set_sort_column_id (GtkTreeSortable *sortable,
3100 gint sort_column_id,
3103 GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
3106 if ((tree_store->sort_column_id == sort_column_id) &&
3107 (tree_store->order == order))
3110 if (sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
3112 if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
3114 GtkTreeDataSortHeader *header = NULL;
3116 header = _gtk_tree_data_list_get_header (tree_store->sort_list,
3119 /* We want to make sure that we have a function */
3120 g_return_if_fail (header != NULL);
3121 g_return_if_fail (header->func != NULL);
3125 g_return_if_fail (tree_store->default_sort_func != NULL);
3129 tree_store->sort_column_id = sort_column_id;
3130 tree_store->order = order;
3132 gtk_tree_sortable_sort_column_changed (sortable);
3134 gtk_tree_store_sort (tree_store);
3138 gtk_tree_store_set_sort_func (GtkTreeSortable *sortable,
3139 gint sort_column_id,
3140 GtkTreeIterCompareFunc func,
3142 GtkDestroyNotify destroy)
3144 GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
3146 tree_store->sort_list = _gtk_tree_data_list_set_header (tree_store->sort_list,
3148 func, data, destroy);
3150 if (tree_store->sort_column_id == sort_column_id)
3151 gtk_tree_store_sort (tree_store);
3155 gtk_tree_store_set_default_sort_func (GtkTreeSortable *sortable,
3156 GtkTreeIterCompareFunc func,
3158 GtkDestroyNotify destroy)
3160 GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
3162 if (tree_store->default_sort_destroy)
3164 GtkDestroyNotify d = tree_store->default_sort_destroy;
3166 tree_store->default_sort_destroy = NULL;
3167 d (tree_store->default_sort_data);
3170 tree_store->default_sort_func = func;
3171 tree_store->default_sort_data = data;
3172 tree_store->default_sort_destroy = destroy;
3174 if (tree_store->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
3175 gtk_tree_store_sort (tree_store);
3179 gtk_tree_store_has_default_sort_func (GtkTreeSortable *sortable)
3181 GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
3183 return (tree_store->default_sort_func != NULL);
3187 validate_gnode (GNode* node)
3191 iter = node->children;
3192 while (iter != NULL)
3194 g_assert (iter->parent == node);
3196 g_assert (iter->prev->next == iter);
3197 validate_gnode (iter);
3202 /* GtkBuildable custom tag implementation
3205 * <column type="..."/>
3206 * <column type="..."/>
3210 GtkBuilder *builder;
3213 } GSListSubParserData;
3216 tree_model_start_element (GMarkupParseContext *context,
3217 const gchar *element_name,
3218 const gchar **names,
3219 const gchar **values,
3224 GSListSubParserData *data = (GSListSubParserData*)user_data;
3226 for (i = 0; names[i]; i++)
3228 if (strcmp (names[i], "type") == 0)
3229 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
3234 tree_model_end_element (GMarkupParseContext *context,
3235 const gchar *element_name,
3240 GSListSubParserData *data = (GSListSubParserData*)user_data;
3242 g_assert(data->builder);
3244 if (strcmp (element_name, "columns") == 0)
3251 data = (GSListSubParserData*)user_data;
3252 data->items = g_slist_reverse (data->items);
3253 types = g_new0 (GType, g_slist_length (data->items));
3255 for (l = data->items, i = 0; l; l = l->next, i++)
3257 type = gtk_builder_get_type_from_name (data->builder, l->data);
3258 if (type == G_TYPE_INVALID)
3260 g_warning ("Unknown type %s specified in treemodel %s",
3261 (const gchar*)l->data,
3262 gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
3270 gtk_tree_store_set_column_types (GTK_TREE_STORE (data->object), i, types);
3274 else if (strcmp (element_name, "column") == 0)
3278 static const GMarkupParser tree_model_parser =
3280 tree_model_start_element,
3281 tree_model_end_element
3286 gtk_tree_store_buildable_custom_tag_start (GtkBuildable *buildable,
3287 GtkBuilder *builder,
3289 const gchar *tagname,
3290 GMarkupParser *parser,
3293 GSListSubParserData *parser_data;
3298 if (strcmp (tagname, "columns") == 0)
3300 parser_data = g_slice_new0 (GSListSubParserData);
3301 parser_data->builder = builder;
3302 parser_data->items = NULL;
3303 parser_data->object = G_OBJECT (buildable);
3305 *parser = tree_model_parser;
3306 *data = parser_data;
3314 gtk_tree_store_buildable_custom_finished (GtkBuildable *buildable,
3315 GtkBuilder *builder,
3317 const gchar *tagname,
3320 GSListSubParserData *data;
3322 if (strcmp (tagname, "columns"))
3325 data = (GSListSubParserData*)user_data;
3327 g_slist_free (data->items);
3328 g_slice_free (GSListSubParserData, data);
3331 #define __GTK_TREE_STORE_C__
3332 #include "gtkaliasdef.c"