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"
32 * SECTION:gtktreestore
33 * @Short_description: A tree-like data structure that can be used with the GtkTreeView
34 * @Title: GtkTreeStore
35 * @See_also: #GtkTreeModel
37 * The #GtkTreeStore object is a list model for use with a #GtkTreeView
38 * widget. It implements the #GtkTreeModel interface, and consequentialy,
39 * can use all of the methods available there. It also implements the
40 * #GtkTreeSortable interface so it can be sorted by the view. Finally,
41 * it also implements the tree <link linkend="gtktreednd">drag and
42 * drop</link> interfaces.
44 * <refsect2 id="GtkTreeStore-BUILDER-UI">
45 * <title>GtkTreeStore as GtkBuildable</title>
46 * The GtkTreeStore implementation of the #GtkBuildable interface allows
47 * to specify the model columns with a <columns> element that may
48 * contain multiple <column> elements, each specifying one model
49 * column. The "type" attribute specifies the data type for the column.
51 * <title>A UI Definition fragment for a tree store</title>
52 * <programlisting><![CDATA[
53 * <object class="GtkTreeStore">
55 * <column type="gchararray"/>
56 * <column type="gchararray"/>
57 * <column type="gint"/>
60 * ]]></programlisting>
65 struct _GtkTreeStorePrivate
74 GType *column_headers;
75 GtkTreeIterCompareFunc default_sort_func;
76 gpointer default_sort_data;
77 GDestroyNotify default_sort_destroy;
78 guint columns_dirty : 1;
82 #define G_NODE(node) ((GNode *)node)
83 #define GTK_TREE_STORE_IS_SORTED(tree) (((GtkTreeStore*)(tree))->priv->sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
84 #define VALID_ITER(iter, tree_store) ((iter)!= NULL && (iter)->user_data != NULL && ((GtkTreeStore*)(tree_store))->priv->stamp == (iter)->stamp)
86 static void gtk_tree_store_tree_model_init (GtkTreeModelIface *iface);
87 static void gtk_tree_store_drag_source_init(GtkTreeDragSourceIface *iface);
88 static void gtk_tree_store_drag_dest_init (GtkTreeDragDestIface *iface);
89 static void gtk_tree_store_sortable_init (GtkTreeSortableIface *iface);
90 static void gtk_tree_store_buildable_init (GtkBuildableIface *iface);
91 static void gtk_tree_store_finalize (GObject *object);
92 static GtkTreeModelFlags gtk_tree_store_get_flags (GtkTreeModel *tree_model);
93 static gint gtk_tree_store_get_n_columns (GtkTreeModel *tree_model);
94 static GType gtk_tree_store_get_column_type (GtkTreeModel *tree_model,
96 static gboolean gtk_tree_store_get_iter (GtkTreeModel *tree_model,
99 static GtkTreePath *gtk_tree_store_get_path (GtkTreeModel *tree_model,
101 static void gtk_tree_store_get_value (GtkTreeModel *tree_model,
105 static gboolean gtk_tree_store_iter_next (GtkTreeModel *tree_model,
107 static gboolean gtk_tree_store_iter_previous (GtkTreeModel *tree_model,
109 static gboolean gtk_tree_store_iter_children (GtkTreeModel *tree_model,
111 GtkTreeIter *parent);
112 static gboolean gtk_tree_store_iter_has_child (GtkTreeModel *tree_model,
114 static gint gtk_tree_store_iter_n_children (GtkTreeModel *tree_model,
116 static gboolean gtk_tree_store_iter_nth_child (GtkTreeModel *tree_model,
120 static gboolean gtk_tree_store_iter_parent (GtkTreeModel *tree_model,
125 static void gtk_tree_store_set_n_columns (GtkTreeStore *tree_store,
127 static void gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
131 static void gtk_tree_store_increment_stamp (GtkTreeStore *tree_store);
135 static gboolean real_gtk_tree_store_row_draggable (GtkTreeDragSource *drag_source,
137 static gboolean gtk_tree_store_drag_data_delete (GtkTreeDragSource *drag_source,
139 static gboolean gtk_tree_store_drag_data_get (GtkTreeDragSource *drag_source,
141 GtkSelectionData *selection_data);
142 static gboolean gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest,
144 GtkSelectionData *selection_data);
145 static gboolean gtk_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest,
146 GtkTreePath *dest_path,
147 GtkSelectionData *selection_data);
149 /* Sortable Interfaces */
151 static void gtk_tree_store_sort (GtkTreeStore *tree_store);
152 static void gtk_tree_store_sort_iter_changed (GtkTreeStore *tree_store,
155 gboolean emit_signal);
156 static gboolean gtk_tree_store_get_sort_column_id (GtkTreeSortable *sortable,
157 gint *sort_column_id,
159 static void gtk_tree_store_set_sort_column_id (GtkTreeSortable *sortable,
162 static void gtk_tree_store_set_sort_func (GtkTreeSortable *sortable,
164 GtkTreeIterCompareFunc func,
166 GDestroyNotify destroy);
167 static void gtk_tree_store_set_default_sort_func (GtkTreeSortable *sortable,
168 GtkTreeIterCompareFunc func,
170 GDestroyNotify destroy);
171 static gboolean gtk_tree_store_has_default_sort_func (GtkTreeSortable *sortable);
176 static gboolean gtk_tree_store_buildable_custom_tag_start (GtkBuildable *buildable,
179 const gchar *tagname,
180 GMarkupParser *parser,
182 static void gtk_tree_store_buildable_custom_finished (GtkBuildable *buildable,
185 const gchar *tagname,
188 static void validate_gnode (GNode *node);
190 static void gtk_tree_store_move (GtkTreeStore *tree_store,
192 GtkTreeIter *position,
197 validate_tree (GtkTreeStore *tree_store)
199 if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
201 g_assert (G_NODE (tree_store->priv->root)->parent == NULL);
203 validate_gnode (G_NODE (tree_store->priv->root));
207 G_DEFINE_TYPE_WITH_CODE (GtkTreeStore, gtk_tree_store, G_TYPE_OBJECT,
208 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
209 gtk_tree_store_tree_model_init)
210 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
211 gtk_tree_store_drag_source_init)
212 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
213 gtk_tree_store_drag_dest_init)
214 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
215 gtk_tree_store_sortable_init)
216 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
217 gtk_tree_store_buildable_init))
220 gtk_tree_store_class_init (GtkTreeStoreClass *class)
222 GObjectClass *object_class;
224 object_class = (GObjectClass *) class;
226 object_class->finalize = gtk_tree_store_finalize;
228 g_type_class_add_private (class, sizeof (GtkTreeStorePrivate));
232 gtk_tree_store_tree_model_init (GtkTreeModelIface *iface)
234 iface->get_flags = gtk_tree_store_get_flags;
235 iface->get_n_columns = gtk_tree_store_get_n_columns;
236 iface->get_column_type = gtk_tree_store_get_column_type;
237 iface->get_iter = gtk_tree_store_get_iter;
238 iface->get_path = gtk_tree_store_get_path;
239 iface->get_value = gtk_tree_store_get_value;
240 iface->iter_next = gtk_tree_store_iter_next;
241 iface->iter_previous = gtk_tree_store_iter_previous;
242 iface->iter_children = gtk_tree_store_iter_children;
243 iface->iter_has_child = gtk_tree_store_iter_has_child;
244 iface->iter_n_children = gtk_tree_store_iter_n_children;
245 iface->iter_nth_child = gtk_tree_store_iter_nth_child;
246 iface->iter_parent = gtk_tree_store_iter_parent;
250 gtk_tree_store_drag_source_init (GtkTreeDragSourceIface *iface)
252 iface->row_draggable = real_gtk_tree_store_row_draggable;
253 iface->drag_data_delete = gtk_tree_store_drag_data_delete;
254 iface->drag_data_get = gtk_tree_store_drag_data_get;
258 gtk_tree_store_drag_dest_init (GtkTreeDragDestIface *iface)
260 iface->drag_data_received = gtk_tree_store_drag_data_received;
261 iface->row_drop_possible = gtk_tree_store_row_drop_possible;
265 gtk_tree_store_sortable_init (GtkTreeSortableIface *iface)
267 iface->get_sort_column_id = gtk_tree_store_get_sort_column_id;
268 iface->set_sort_column_id = gtk_tree_store_set_sort_column_id;
269 iface->set_sort_func = gtk_tree_store_set_sort_func;
270 iface->set_default_sort_func = gtk_tree_store_set_default_sort_func;
271 iface->has_default_sort_func = gtk_tree_store_has_default_sort_func;
275 gtk_tree_store_buildable_init (GtkBuildableIface *iface)
277 iface->custom_tag_start = gtk_tree_store_buildable_custom_tag_start;
278 iface->custom_finished = gtk_tree_store_buildable_custom_finished;
282 gtk_tree_store_init (GtkTreeStore *tree_store)
284 GtkTreeStorePrivate *priv;
286 priv = G_TYPE_INSTANCE_GET_PRIVATE (tree_store,
288 GtkTreeStorePrivate);
289 tree_store->priv = priv;
290 priv->root = g_node_new (NULL);
291 /* While the odds are against us getting 0... */
294 priv->stamp = g_random_int ();
296 while (priv->stamp == 0);
298 priv->sort_list = NULL;
299 priv->sort_column_id = GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID;
300 priv->columns_dirty = FALSE;
304 * gtk_tree_store_new:
305 * @n_columns: number of columns in the tree store
306 * @Varargs: all #GType types for the columns, from first to last
308 * Creates a new tree store as with @n_columns columns each of the types passed
309 * in. Note that only types derived from standard GObject fundamental types
312 * As an example, <literal>gtk_tree_store_new (3, G_TYPE_INT, G_TYPE_STRING,
313 * GDK_TYPE_PIXBUF);</literal> will create a new #GtkTreeStore with three columns, of type
314 * <type>int</type>, <type>string</type> and #GdkPixbuf respectively.
316 * Return value: a new #GtkTreeStore
319 gtk_tree_store_new (gint n_columns,
322 GtkTreeStore *retval;
326 g_return_val_if_fail (n_columns > 0, NULL);
328 retval = g_object_new (GTK_TYPE_TREE_STORE, NULL);
329 gtk_tree_store_set_n_columns (retval, n_columns);
331 va_start (args, n_columns);
333 for (i = 0; i < n_columns; i++)
335 GType type = va_arg (args, GType);
336 if (! _gtk_tree_data_list_check_type (type))
338 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
339 g_object_unref (retval);
343 gtk_tree_store_set_column_type (retval, i, type);
350 * gtk_tree_store_newv:
351 * @n_columns: number of columns in the tree store
352 * @types: (array length=n_columns): an array of #GType types for the columns, from first to last
354 * Non vararg creation function. Used primarily by language bindings.
356 * Return value: (transfer full): a new #GtkTreeStore
359 gtk_tree_store_newv (gint n_columns,
362 GtkTreeStore *retval;
365 g_return_val_if_fail (n_columns > 0, NULL);
367 retval = g_object_new (GTK_TYPE_TREE_STORE, NULL);
368 gtk_tree_store_set_n_columns (retval, n_columns);
370 for (i = 0; i < n_columns; i++)
372 if (! _gtk_tree_data_list_check_type (types[i]))
374 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i]));
375 g_object_unref (retval);
378 gtk_tree_store_set_column_type (retval, i, types[i]);
386 * gtk_tree_store_set_column_types:
387 * @tree_store: A #GtkTreeStore
388 * @n_columns: Number of columns for the tree store
389 * @types: (array length=n_columns): An array of #GType types, one for each column
391 * This function is meant primarily for #GObjects that inherit from
392 * #GtkTreeStore, and should only be used when constructing a new
393 * #GtkTreeStore. It will not function after a row has been added,
394 * or a method on the #GtkTreeModel interface is called.
397 gtk_tree_store_set_column_types (GtkTreeStore *tree_store,
403 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
404 g_return_if_fail (tree_store->priv->columns_dirty == 0);
406 gtk_tree_store_set_n_columns (tree_store, n_columns);
407 for (i = 0; i < n_columns; i++)
409 if (! _gtk_tree_data_list_check_type (types[i]))
411 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i]));
414 gtk_tree_store_set_column_type (tree_store, i, types[i]);
419 gtk_tree_store_set_n_columns (GtkTreeStore *tree_store,
422 GtkTreeStorePrivate *priv = tree_store->priv;
425 if (priv->n_columns == n_columns)
428 priv->column_headers = g_renew (GType, priv->column_headers, n_columns);
429 for (i = priv->n_columns; i < n_columns; i++)
430 priv->column_headers[i] = G_TYPE_INVALID;
431 priv->n_columns = n_columns;
434 _gtk_tree_data_list_header_free (priv->sort_list);
436 priv->sort_list = _gtk_tree_data_list_header_new (n_columns, priv->column_headers);
440 * gtk_tree_store_set_column_type:
441 * @tree_store: a #GtkTreeStore
442 * @column: column number
443 * @type: type of the data to be stored in @column
445 * Supported types include: %G_TYPE_UINT, %G_TYPE_INT, %G_TYPE_UCHAR,
446 * %G_TYPE_CHAR, %G_TYPE_BOOLEAN, %G_TYPE_POINTER, %G_TYPE_FLOAT,
447 * %G_TYPE_DOUBLE, %G_TYPE_STRING, %G_TYPE_OBJECT, and %G_TYPE_BOXED, along with
448 * subclasses of those types such as %GDK_TYPE_PIXBUF.
452 gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
456 GtkTreeStorePrivate *priv = tree_store->priv;
458 if (!_gtk_tree_data_list_check_type (type))
460 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
463 priv->column_headers[column] = type;
467 node_free (GNode *node, gpointer data)
470 _gtk_tree_data_list_free (node->data, (GType*)data);
477 gtk_tree_store_finalize (GObject *object)
479 GtkTreeStore *tree_store = GTK_TREE_STORE (object);
480 GtkTreeStorePrivate *priv = tree_store->priv;
482 g_node_traverse (priv->root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
483 node_free, priv->column_headers);
484 g_node_destroy (priv->root);
485 _gtk_tree_data_list_header_free (priv->sort_list);
486 g_free (priv->column_headers);
488 if (priv->default_sort_destroy)
490 GDestroyNotify d = priv->default_sort_destroy;
492 priv->default_sort_destroy = NULL;
493 d (priv->default_sort_data);
494 priv->default_sort_data = NULL;
498 G_OBJECT_CLASS (gtk_tree_store_parent_class)->finalize (object);
501 /* fulfill the GtkTreeModel requirements */
502 /* NOTE: GtkTreeStore::root is a GNode, that acts as the parent node. However,
503 * it is not visible to the tree or to the user., and the path "0" refers to the
504 * first child of GtkTreeStore::root.
508 static GtkTreeModelFlags
509 gtk_tree_store_get_flags (GtkTreeModel *tree_model)
511 return GTK_TREE_MODEL_ITERS_PERSIST;
515 gtk_tree_store_get_n_columns (GtkTreeModel *tree_model)
517 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
518 GtkTreeStorePrivate *priv = tree_store->priv;
520 priv->columns_dirty = TRUE;
522 return priv->n_columns;
526 gtk_tree_store_get_column_type (GtkTreeModel *tree_model,
529 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
530 GtkTreeStorePrivate *priv = tree_store->priv;
532 g_return_val_if_fail (index < priv->n_columns, G_TYPE_INVALID);
534 priv->columns_dirty = TRUE;
536 return priv->column_headers[index];
540 gtk_tree_store_get_iter (GtkTreeModel *tree_model,
544 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
545 GtkTreeStorePrivate *priv = tree_store->priv;
550 priv->columns_dirty = TRUE;
552 indices = gtk_tree_path_get_indices (path);
553 depth = gtk_tree_path_get_depth (path);
555 g_return_val_if_fail (depth > 0, FALSE);
557 parent.stamp = priv->stamp;
558 parent.user_data = priv->root;
560 if (!gtk_tree_store_iter_nth_child (tree_model, iter, &parent, indices[0]))
563 for (i = 1; i < depth; i++)
566 if (!gtk_tree_store_iter_nth_child (tree_model, iter, &parent, indices[i]))
574 gtk_tree_store_get_path (GtkTreeModel *tree_model,
577 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
578 GtkTreeStorePrivate *priv = tree_store->priv;
583 g_return_val_if_fail (iter->user_data != NULL, NULL);
584 g_return_val_if_fail (iter->stamp == priv->stamp, NULL);
586 validate_tree (tree_store);
588 if (G_NODE (iter->user_data)->parent == NULL &&
589 G_NODE (iter->user_data) == priv->root)
590 return gtk_tree_path_new ();
591 g_assert (G_NODE (iter->user_data)->parent != NULL);
593 if (G_NODE (iter->user_data)->parent == G_NODE (priv->root))
595 retval = gtk_tree_path_new ();
596 tmp_node = G_NODE (priv->root)->children;
600 GtkTreeIter tmp_iter = *iter;
602 tmp_iter.user_data = G_NODE (iter->user_data)->parent;
604 retval = gtk_tree_store_get_path (tree_model, &tmp_iter);
605 tmp_node = G_NODE (iter->user_data)->parent->children;
611 if (tmp_node == NULL)
613 gtk_tree_path_free (retval);
617 for (; tmp_node; tmp_node = tmp_node->next)
619 if (tmp_node == G_NODE (iter->user_data))
624 if (tmp_node == NULL)
626 /* We couldn't find node, meaning it's prolly not ours */
627 /* Perhaps I should do a g_return_if_fail here. */
628 gtk_tree_path_free (retval);
632 gtk_tree_path_append_index (retval, i);
639 gtk_tree_store_get_value (GtkTreeModel *tree_model,
644 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
645 GtkTreeStorePrivate *priv = tree_store->priv;
646 GtkTreeDataList *list;
647 gint tmp_column = column;
649 g_return_if_fail (column < priv->n_columns);
650 g_return_if_fail (VALID_ITER (iter, tree_store));
652 list = G_NODE (iter->user_data)->data;
654 while (tmp_column-- > 0 && list)
659 _gtk_tree_data_list_node_to_value (list,
660 priv->column_headers[column],
665 /* We want to return an initialized but empty (default) value */
666 g_value_init (value, priv->column_headers[column]);
671 gtk_tree_store_iter_next (GtkTreeModel *tree_model,
674 g_return_val_if_fail (iter->user_data != NULL, FALSE);
675 g_return_val_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->priv->stamp, FALSE);
677 if (G_NODE (iter->user_data)->next == NULL)
683 iter->user_data = G_NODE (iter->user_data)->next;
689 gtk_tree_store_iter_previous (GtkTreeModel *tree_model,
692 g_return_val_if_fail (iter->user_data != NULL, FALSE);
693 g_return_val_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->priv->stamp, FALSE);
695 if (G_NODE (iter->user_data)->prev == NULL)
701 iter->user_data = G_NODE (iter->user_data)->prev;
707 gtk_tree_store_iter_children (GtkTreeModel *tree_model,
711 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
712 GtkTreeStorePrivate *priv = tree_store->priv;
716 g_return_val_if_fail (VALID_ITER (parent, tree_store), FALSE);
719 children = G_NODE (parent->user_data)->children;
721 children = G_NODE (priv->root)->children;
725 iter->stamp = priv->stamp;
726 iter->user_data = children;
737 gtk_tree_store_iter_has_child (GtkTreeModel *tree_model,
740 g_return_val_if_fail (iter->user_data != NULL, FALSE);
741 g_return_val_if_fail (VALID_ITER (iter, tree_model), FALSE);
743 return G_NODE (iter->user_data)->children != NULL;
747 gtk_tree_store_iter_n_children (GtkTreeModel *tree_model,
753 g_return_val_if_fail (iter == NULL || iter->user_data != NULL, 0);
756 node = G_NODE (GTK_TREE_STORE (tree_model)->priv->root)->children;
758 node = G_NODE (iter->user_data)->children;
770 gtk_tree_store_iter_nth_child (GtkTreeModel *tree_model,
775 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
776 GtkTreeStorePrivate *priv = tree_store->priv;
780 g_return_val_if_fail (parent == NULL || parent->user_data != NULL, FALSE);
783 parent_node = priv->root;
785 parent_node = parent->user_data;
787 child = g_node_nth_child (parent_node, n);
791 iter->user_data = child;
792 iter->stamp = priv->stamp;
803 gtk_tree_store_iter_parent (GtkTreeModel *tree_model,
807 GtkTreeStore *tree_store = (GtkTreeStore *) tree_model;
808 GtkTreeStorePrivate *priv = tree_store->priv;
811 g_return_val_if_fail (iter != NULL, FALSE);
812 g_return_val_if_fail (VALID_ITER (child, tree_store), FALSE);
814 parent = G_NODE (child->user_data)->parent;
816 g_assert (parent != NULL);
818 if (parent != priv->root)
820 iter->user_data = parent;
821 iter->stamp = priv->stamp;
832 /* Does not emit a signal */
834 gtk_tree_store_real_set_value (GtkTreeStore *tree_store,
840 GtkTreeStorePrivate *priv = tree_store->priv;
841 GtkTreeDataList *list;
842 GtkTreeDataList *prev;
843 gint old_column = column;
844 GValue real_value = { 0, };
845 gboolean converted = FALSE;
846 gboolean retval = FALSE;
848 if (! g_type_is_a (G_VALUE_TYPE (value), priv->column_headers[column]))
850 if (! (g_value_type_compatible (G_VALUE_TYPE (value), priv->column_headers[column]) &&
851 g_value_type_compatible (priv->column_headers[column], G_VALUE_TYPE (value))))
853 g_warning ("%s: Unable to convert from %s to %s\n",
855 g_type_name (G_VALUE_TYPE (value)),
856 g_type_name (priv->column_headers[column]));
859 if (!g_value_transform (value, &real_value))
861 g_warning ("%s: Unable to make conversion from %s to %s\n",
863 g_type_name (G_VALUE_TYPE (value)),
864 g_type_name (priv->column_headers[column]));
865 g_value_unset (&real_value);
871 prev = list = G_NODE (iter->user_data)->data;
878 _gtk_tree_data_list_value_to_node (list, &real_value);
880 _gtk_tree_data_list_value_to_node (list, value);
883 g_value_unset (&real_value);
884 if (sort && GTK_TREE_STORE_IS_SORTED (tree_store))
885 gtk_tree_store_sort_iter_changed (tree_store, iter, old_column, TRUE);
894 if (G_NODE (iter->user_data)->data == NULL)
896 G_NODE (iter->user_data)->data = list = _gtk_tree_data_list_alloc ();
901 list = prev->next = _gtk_tree_data_list_alloc ();
907 list->next = _gtk_tree_data_list_alloc ();
914 _gtk_tree_data_list_value_to_node (list, &real_value);
916 _gtk_tree_data_list_value_to_node (list, value);
920 g_value_unset (&real_value);
922 if (sort && GTK_TREE_STORE_IS_SORTED (tree_store))
923 gtk_tree_store_sort_iter_changed (tree_store, iter, old_column, TRUE);
929 * gtk_tree_store_set_value:
930 * @tree_store: a #GtkTreeStore
931 * @iter: A valid #GtkTreeIter for the row being modified
932 * @column: column number to modify
933 * @value: new value for the cell
935 * Sets the data in the cell specified by @iter and @column.
936 * The type of @value must be convertible to the type of the
941 gtk_tree_store_set_value (GtkTreeStore *tree_store,
946 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
947 g_return_if_fail (VALID_ITER (iter, tree_store));
948 g_return_if_fail (column >= 0 && column < tree_store->priv->n_columns);
949 g_return_if_fail (G_IS_VALUE (value));
951 if (gtk_tree_store_real_set_value (tree_store, iter, column, value, TRUE))
955 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
956 gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter);
957 gtk_tree_path_free (path);
961 static GtkTreeIterCompareFunc
962 gtk_tree_store_get_compare_func (GtkTreeStore *tree_store)
964 GtkTreeStorePrivate *priv = tree_store->priv;
965 GtkTreeIterCompareFunc func = NULL;
967 if (GTK_TREE_STORE_IS_SORTED (tree_store))
969 if (priv->sort_column_id != -1)
971 GtkTreeDataSortHeader *header;
972 header = _gtk_tree_data_list_get_header (priv->sort_list,
973 priv->sort_column_id);
974 g_return_val_if_fail (header != NULL, NULL);
975 g_return_val_if_fail (header->func != NULL, NULL);
980 func = priv->default_sort_func;
988 gtk_tree_store_set_vector_internal (GtkTreeStore *tree_store,
990 gboolean *emit_signal,
991 gboolean *maybe_need_sort,
996 GtkTreeStorePrivate *priv = tree_store->priv;
998 GtkTreeIterCompareFunc func = NULL;
1000 func = gtk_tree_store_get_compare_func (tree_store);
1001 if (func != _gtk_tree_data_list_compare_func)
1002 *maybe_need_sort = TRUE;
1004 for (i = 0; i < n_values; i++)
1006 *emit_signal = gtk_tree_store_real_set_value (tree_store, iter,
1007 columns[i], &values[i],
1008 FALSE) || *emit_signal;
1010 if (func == _gtk_tree_data_list_compare_func &&
1011 columns[i] == priv->sort_column_id)
1012 *maybe_need_sort = TRUE;
1017 gtk_tree_store_set_valist_internal (GtkTreeStore *tree_store,
1019 gboolean *emit_signal,
1020 gboolean *maybe_need_sort,
1023 GtkTreeStorePrivate *priv = tree_store->priv;
1025 GtkTreeIterCompareFunc func = NULL;
1027 column = va_arg (var_args, gint);
1029 func = gtk_tree_store_get_compare_func (tree_store);
1030 if (func != _gtk_tree_data_list_compare_func)
1031 *maybe_need_sort = TRUE;
1033 while (column != -1)
1035 GValue value = { 0, };
1036 gchar *error = NULL;
1038 if (column < 0 || column >= priv->n_columns)
1040 g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
1043 g_value_init (&value, priv->column_headers[column]);
1045 G_VALUE_COLLECT (&value, var_args, 0, &error);
1048 g_warning ("%s: %s", G_STRLOC, error);
1051 /* we purposely leak the value here, it might not be
1052 * in a sane state if an error condition occoured
1057 *emit_signal = gtk_tree_store_real_set_value (tree_store,
1061 FALSE) || *emit_signal;
1063 if (func == _gtk_tree_data_list_compare_func &&
1064 column == priv->sort_column_id)
1065 *maybe_need_sort = TRUE;
1067 g_value_unset (&value);
1069 column = va_arg (var_args, gint);
1074 * gtk_tree_store_set_valuesv:
1075 * @tree_store: A #GtkTreeStore
1076 * @iter: A valid #GtkTreeIter for the row being modified
1077 * @columns: (array length=n_values): an array of column numbers
1078 * @values: (array length=n_values): an array of GValues
1079 * @n_values: the length of the @columns and @values arrays
1081 * A variant of gtk_tree_store_set_valist() which takes
1082 * the columns and values as two arrays, instead of varargs. This
1083 * function is mainly intended for language bindings or in case
1084 * the number of columns to change is not known until run-time.
1089 gtk_tree_store_set_valuesv (GtkTreeStore *tree_store,
1095 GtkTreeStorePrivate *priv = tree_store->priv;
1096 gboolean emit_signal = FALSE;
1097 gboolean maybe_need_sort = FALSE;
1099 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1100 g_return_if_fail (VALID_ITER (iter, tree_store));
1102 gtk_tree_store_set_vector_internal (tree_store, iter,
1105 columns, values, n_values);
1107 if (maybe_need_sort && GTK_TREE_STORE_IS_SORTED (tree_store))
1108 gtk_tree_store_sort_iter_changed (tree_store, iter, priv->sort_column_id, TRUE);
1114 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1115 gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter);
1116 gtk_tree_path_free (path);
1121 * gtk_tree_store_set_valist:
1122 * @tree_store: A #GtkTreeStore
1123 * @iter: A valid #GtkTreeIter for the row being modified
1124 * @var_args: <type>va_list</type> of column/value pairs
1126 * See gtk_tree_store_set(); this version takes a <type>va_list</type> for
1127 * use by language bindings.
1131 gtk_tree_store_set_valist (GtkTreeStore *tree_store,
1135 GtkTreeStorePrivate *priv = tree_store->priv;
1136 gboolean emit_signal = FALSE;
1137 gboolean maybe_need_sort = FALSE;
1139 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1140 g_return_if_fail (VALID_ITER (iter, tree_store));
1142 gtk_tree_store_set_valist_internal (tree_store, iter,
1147 if (maybe_need_sort && GTK_TREE_STORE_IS_SORTED (tree_store))
1148 gtk_tree_store_sort_iter_changed (tree_store, iter, priv->sort_column_id, TRUE);
1154 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1155 gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, iter);
1156 gtk_tree_path_free (path);
1161 * gtk_tree_store_set:
1162 * @tree_store: A #GtkTreeStore
1163 * @iter: A valid #GtkTreeIter for the row being modified
1164 * @Varargs: pairs of column number and value, terminated with -1
1166 * Sets the value of one or more cells in the row referenced by @iter.
1167 * The variable argument list should contain integer column numbers,
1168 * each column number followed by the value to be set.
1169 * The list is terminated by a -1. For example, to set column 0 with type
1170 * %G_TYPE_STRING to "Foo", you would write
1171 * <literal>gtk_tree_store_set (store, iter, 0, "Foo", -1)</literal>.
1173 * The value will be referenced by the store if it is a %G_TYPE_OBJECT, and it
1174 * will be copied if it is a %G_TYPE_STRING or %G_TYPE_BOXED.
1177 gtk_tree_store_set (GtkTreeStore *tree_store,
1183 va_start (var_args, iter);
1184 gtk_tree_store_set_valist (tree_store, iter, var_args);
1189 * gtk_tree_store_remove:
1190 * @tree_store: A #GtkTreeStore
1191 * @iter: A valid #GtkTreeIter
1193 * Removes @iter from @tree_store. After being removed, @iter is set to the
1194 * next valid row at that level, or invalidated if it previously pointed to the
1197 * Return value: %TRUE if @iter is still valid, %FALSE if not.
1200 gtk_tree_store_remove (GtkTreeStore *tree_store,
1203 GtkTreeStorePrivate *priv = tree_store->priv;
1205 GtkTreeIter new_iter = {0,};
1209 g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), FALSE);
1210 g_return_val_if_fail (VALID_ITER (iter, tree_store), FALSE);
1212 parent = G_NODE (iter->user_data)->parent;
1214 g_assert (parent != NULL);
1215 next_node = G_NODE (iter->user_data)->next;
1217 if (G_NODE (iter->user_data)->data)
1218 g_node_traverse (G_NODE (iter->user_data), G_POST_ORDER, G_TRAVERSE_ALL,
1219 -1, node_free, priv->column_headers);
1221 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1222 g_node_destroy (G_NODE (iter->user_data));
1224 gtk_tree_model_row_deleted (GTK_TREE_MODEL (tree_store), path);
1226 if (parent != G_NODE (priv->root))
1229 if (parent->children == NULL)
1231 gtk_tree_path_up (path);
1233 new_iter.stamp = priv->stamp;
1234 new_iter.user_data = parent;
1235 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, &new_iter);
1238 gtk_tree_path_free (path);
1240 /* revalidate iter */
1241 if (next_node != NULL)
1243 iter->stamp = priv->stamp;
1244 iter->user_data = next_node;
1250 iter->user_data = NULL;
1257 * gtk_tree_store_insert:
1258 * @tree_store: A #GtkTreeStore
1259 * @iter: (out): An unset #GtkTreeIter to set to the new row
1260 * @parent: (allow-none): A valid #GtkTreeIter, or %NULL
1261 * @position: position to insert the new row
1263 * Creates a new row at @position. If parent is non-%NULL, then the row will be
1264 * made a child of @parent. Otherwise, the row will be created at the toplevel.
1265 * If @position is larger than the number of rows at that level, then the new
1266 * row will be inserted to the end of the list. @iter will be changed to point
1267 * to this new row. The row will be empty after this function is called. To
1268 * fill in values, you need to call gtk_tree_store_set() or
1269 * gtk_tree_store_set_value().
1273 gtk_tree_store_insert (GtkTreeStore *tree_store,
1275 GtkTreeIter *parent,
1278 GtkTreeStorePrivate *priv = tree_store->priv;
1283 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1284 g_return_if_fail (iter != NULL);
1286 g_return_if_fail (VALID_ITER (parent, tree_store));
1289 parent_node = parent->user_data;
1291 parent_node = priv->root;
1293 priv->columns_dirty = TRUE;
1295 new_node = g_node_new (NULL);
1297 iter->stamp = priv->stamp;
1298 iter->user_data = new_node;
1299 g_node_insert (parent_node, position, new_node);
1301 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1302 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1304 if (parent_node != priv->root)
1306 if (new_node->prev == NULL && new_node->next == NULL)
1308 gtk_tree_path_up (path);
1309 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
1313 gtk_tree_path_free (path);
1315 validate_tree ((GtkTreeStore*)tree_store);
1319 * gtk_tree_store_insert_before:
1320 * @tree_store: A #GtkTreeStore
1321 * @iter: (out): An unset #GtkTreeIter to set to the new row
1322 * @parent: (allow-none): A valid #GtkTreeIter, or %NULL
1323 * @sibling: (allow-none): A valid #GtkTreeIter, or %NULL
1325 * Inserts a new row before @sibling. If @sibling is %NULL, then the row will
1326 * be appended to @parent 's children. If @parent and @sibling are %NULL, then
1327 * the row will be appended to the toplevel. If both @sibling and @parent are
1328 * set, then @parent must be the parent of @sibling. When @sibling is set,
1329 * @parent is optional.
1331 * @iter will be changed to point to this new row. The row will be empty after
1332 * this function is called. To fill in values, you need to call
1333 * gtk_tree_store_set() or gtk_tree_store_set_value().
1337 gtk_tree_store_insert_before (GtkTreeStore *tree_store,
1339 GtkTreeIter *parent,
1340 GtkTreeIter *sibling)
1342 GtkTreeStorePrivate *priv = tree_store->priv;
1344 GNode *parent_node = NULL;
1347 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1348 g_return_if_fail (iter != NULL);
1350 g_return_if_fail (VALID_ITER (parent, tree_store));
1351 if (sibling != NULL)
1352 g_return_if_fail (VALID_ITER (sibling, tree_store));
1354 if (parent == NULL && sibling == NULL)
1355 parent_node = priv->root;
1356 else if (parent == NULL)
1357 parent_node = G_NODE (sibling->user_data)->parent;
1358 else if (sibling == NULL)
1359 parent_node = G_NODE (parent->user_data);
1362 g_return_if_fail (G_NODE (sibling->user_data)->parent == G_NODE (parent->user_data));
1363 parent_node = G_NODE (parent->user_data);
1366 priv->columns_dirty = TRUE;
1368 new_node = g_node_new (NULL);
1370 g_node_insert_before (parent_node,
1371 sibling ? G_NODE (sibling->user_data) : NULL,
1374 iter->stamp = priv->stamp;
1375 iter->user_data = new_node;
1377 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1378 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1380 if (parent_node != priv->root)
1382 if (new_node->prev == NULL && new_node->next == NULL)
1384 GtkTreeIter parent_iter;
1386 parent_iter.stamp = priv->stamp;
1387 parent_iter.user_data = parent_node;
1389 gtk_tree_path_up (path);
1390 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, &parent_iter);
1394 gtk_tree_path_free (path);
1396 validate_tree (tree_store);
1400 * gtk_tree_store_insert_after:
1401 * @tree_store: A #GtkTreeStore
1402 * @iter: (out): An unset #GtkTreeIter to set to the new row
1403 * @parent: (allow-none): A valid #GtkTreeIter, or %NULL
1404 * @sibling: (allow-none): A valid #GtkTreeIter, or %NULL
1406 * Inserts a new row after @sibling. If @sibling is %NULL, then the row will be
1407 * prepended to @parent 's children. If @parent and @sibling are %NULL, then
1408 * the row will be prepended to the toplevel. If both @sibling and @parent are
1409 * set, then @parent must be the parent of @sibling. When @sibling is set,
1410 * @parent is optional.
1412 * @iter will be changed to point to this new row. The row will be empty after
1413 * this function is called. To fill in values, you need to call
1414 * gtk_tree_store_set() or gtk_tree_store_set_value().
1418 gtk_tree_store_insert_after (GtkTreeStore *tree_store,
1420 GtkTreeIter *parent,
1421 GtkTreeIter *sibling)
1423 GtkTreeStorePrivate *priv = tree_store->priv;
1428 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1429 g_return_if_fail (iter != NULL);
1431 g_return_if_fail (VALID_ITER (parent, tree_store));
1432 if (sibling != NULL)
1433 g_return_if_fail (VALID_ITER (sibling, tree_store));
1435 if (parent == NULL && sibling == NULL)
1436 parent_node = priv->root;
1437 else if (parent == NULL)
1438 parent_node = G_NODE (sibling->user_data)->parent;
1439 else if (sibling == NULL)
1440 parent_node = G_NODE (parent->user_data);
1443 g_return_if_fail (G_NODE (sibling->user_data)->parent ==
1444 G_NODE (parent->user_data));
1445 parent_node = G_NODE (parent->user_data);
1448 priv->columns_dirty = TRUE;
1450 new_node = g_node_new (NULL);
1452 g_node_insert_after (parent_node,
1453 sibling ? G_NODE (sibling->user_data) : NULL,
1456 iter->stamp = priv->stamp;
1457 iter->user_data = new_node;
1459 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1460 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1462 if (parent_node != priv->root)
1464 if (new_node->prev == NULL && new_node->next == NULL)
1466 GtkTreeIter parent_iter;
1468 parent_iter.stamp = priv->stamp;
1469 parent_iter.user_data = parent_node;
1471 gtk_tree_path_up (path);
1472 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, &parent_iter);
1476 gtk_tree_path_free (path);
1478 validate_tree (tree_store);
1482 * gtk_tree_store_insert_with_values:
1483 * @tree_store: A #GtkTreeStore
1484 * @iter: (out) (allow-none): An unset #GtkTreeIter to set the new row, or %NULL.
1485 * @parent: (allow-none): A valid #GtkTreeIter, or %NULL
1486 * @position: position to insert the new row
1487 * @Varargs: pairs of column number and value, terminated with -1
1489 * Creates a new row at @position. @iter will be changed to point to this
1490 * new row. If @position is larger than the number of rows on the list, then
1491 * the new row will be appended to the list. The row will be filled with
1492 * the values given to this function.
1495 * <literal>gtk_tree_store_insert_with_values (tree_store, iter, position, ...)</literal>
1496 * has the same effect as calling
1498 * gtk_tree_store_insert (tree_store, iter, position);
1499 * gtk_tree_store_set (tree_store, iter, ...);
1501 * with the different that the former will only emit a row_inserted signal,
1502 * while the latter will emit row_inserted, row_changed and if the tree store
1503 * is sorted, rows_reordered. Since emitting the rows_reordered signal
1504 * repeatedly can affect the performance of the program,
1505 * gtk_tree_store_insert_with_values() should generally be preferred when
1506 * inserting rows in a sorted tree store.
1511 gtk_tree_store_insert_with_values (GtkTreeStore *tree_store,
1513 GtkTreeIter *parent,
1517 GtkTreeStorePrivate *priv = tree_store->priv;
1521 GtkTreeIter tmp_iter;
1523 gboolean changed = FALSE;
1524 gboolean maybe_need_sort = FALSE;
1526 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1532 g_return_if_fail (VALID_ITER (parent, tree_store));
1535 parent_node = parent->user_data;
1537 parent_node = priv->root;
1539 priv->columns_dirty = TRUE;
1541 new_node = g_node_new (NULL);
1543 iter->stamp = priv->stamp;
1544 iter->user_data = new_node;
1545 g_node_insert (parent_node, position, new_node);
1547 va_start (var_args, position);
1548 gtk_tree_store_set_valist_internal (tree_store, iter,
1549 &changed, &maybe_need_sort,
1553 if (maybe_need_sort && GTK_TREE_STORE_IS_SORTED (tree_store))
1554 gtk_tree_store_sort_iter_changed (tree_store, iter, priv->sort_column_id, FALSE);
1556 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1557 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1559 if (parent_node != priv->root)
1561 if (new_node->prev == NULL && new_node->next == NULL)
1563 gtk_tree_path_up (path);
1564 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
1568 gtk_tree_path_free (path);
1570 validate_tree ((GtkTreeStore *)tree_store);
1574 * gtk_tree_store_insert_with_valuesv:
1575 * @tree_store: A #GtkTreeStore
1576 * @iter: (out) (allow-none): An unset #GtkTreeIter to set the new row, or %NULL.
1577 * @parent: (allow-none): A valid #GtkTreeIter, or %NULL
1578 * @position: position to insert the new row
1579 * @columns: (array length=n_values): an array of column numbers
1580 * @values: (array length=n_values): an array of GValues
1581 * @n_values: the length of the @columns and @values arrays
1583 * A variant of gtk_tree_store_insert_with_values() which takes
1584 * the columns and values as two arrays, instead of varargs. This
1585 * function is mainly intended for language bindings.
1590 gtk_tree_store_insert_with_valuesv (GtkTreeStore *tree_store,
1592 GtkTreeIter *parent,
1598 GtkTreeStorePrivate *priv = tree_store->priv;
1602 GtkTreeIter tmp_iter;
1603 gboolean changed = FALSE;
1604 gboolean maybe_need_sort = FALSE;
1606 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1612 g_return_if_fail (VALID_ITER (parent, tree_store));
1615 parent_node = parent->user_data;
1617 parent_node = priv->root;
1619 priv->columns_dirty = TRUE;
1621 new_node = g_node_new (NULL);
1623 iter->stamp = priv->stamp;
1624 iter->user_data = new_node;
1625 g_node_insert (parent_node, position, new_node);
1627 gtk_tree_store_set_vector_internal (tree_store, iter,
1628 &changed, &maybe_need_sort,
1629 columns, values, n_values);
1631 if (maybe_need_sort && GTK_TREE_STORE_IS_SORTED (tree_store))
1632 gtk_tree_store_sort_iter_changed (tree_store, iter, priv->sort_column_id, FALSE);
1634 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1635 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1637 if (parent_node != priv->root)
1639 if (new_node->prev == NULL && new_node->next == NULL)
1641 gtk_tree_path_up (path);
1642 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
1646 gtk_tree_path_free (path);
1648 validate_tree ((GtkTreeStore *)tree_store);
1652 * gtk_tree_store_prepend:
1653 * @tree_store: A #GtkTreeStore
1654 * @iter: (out): An unset #GtkTreeIter to set to the prepended row
1655 * @parent: (allow-none): A valid #GtkTreeIter, or %NULL
1657 * Prepends a new row to @tree_store. If @parent is non-%NULL, then it will prepend
1658 * the new row before the first child of @parent, otherwise it will prepend a row
1659 * to the top level. @iter will be changed to point to this new row. The row
1660 * will be empty after this function is called. To fill in values, you need to
1661 * call gtk_tree_store_set() or gtk_tree_store_set_value().
1664 gtk_tree_store_prepend (GtkTreeStore *tree_store,
1666 GtkTreeIter *parent)
1668 GtkTreeStorePrivate *priv = tree_store->priv;
1671 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1672 g_return_if_fail (iter != NULL);
1674 g_return_if_fail (VALID_ITER (parent, tree_store));
1676 priv->columns_dirty = TRUE;
1679 parent_node = priv->root;
1681 parent_node = parent->user_data;
1683 if (parent_node->children == NULL)
1687 iter->stamp = priv->stamp;
1688 iter->user_data = g_node_new (NULL);
1690 g_node_prepend (parent_node, G_NODE (iter->user_data));
1692 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1693 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1695 if (parent_node != priv->root)
1697 gtk_tree_path_up (path);
1698 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
1700 gtk_tree_path_free (path);
1704 gtk_tree_store_insert_after (tree_store, iter, parent, NULL);
1707 validate_tree (tree_store);
1711 * gtk_tree_store_append:
1712 * @tree_store: A #GtkTreeStore
1713 * @iter: (out): An unset #GtkTreeIter to set to the appended row
1714 * @parent: (allow-none): A valid #GtkTreeIter, or %NULL
1716 * Appends a new row to @tree_store. If @parent is non-%NULL, then it will append the
1717 * new row after the last child of @parent, otherwise it will append a row to
1718 * the top level. @iter will be changed to point to this new row. The row will
1719 * be empty after this function is called. To fill in values, you need to call
1720 * gtk_tree_store_set() or gtk_tree_store_set_value().
1723 gtk_tree_store_append (GtkTreeStore *tree_store,
1725 GtkTreeIter *parent)
1727 GtkTreeStorePrivate *priv = tree_store->priv;
1730 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1731 g_return_if_fail (iter != NULL);
1733 g_return_if_fail (VALID_ITER (parent, tree_store));
1736 parent_node = priv->root;
1738 parent_node = parent->user_data;
1740 priv->columns_dirty = TRUE;
1742 if (parent_node->children == NULL)
1746 iter->stamp = priv->stamp;
1747 iter->user_data = g_node_new (NULL);
1749 g_node_append (parent_node, G_NODE (iter->user_data));
1751 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
1752 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_store), path, iter);
1754 if (parent_node != priv->root)
1756 gtk_tree_path_up (path);
1757 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (tree_store), path, parent);
1759 gtk_tree_path_free (path);
1763 gtk_tree_store_insert_before (tree_store, iter, parent, NULL);
1766 validate_tree (tree_store);
1770 * gtk_tree_store_is_ancestor:
1771 * @tree_store: A #GtkTreeStore
1772 * @iter: A valid #GtkTreeIter
1773 * @descendant: A valid #GtkTreeIter
1775 * Returns %TRUE if @iter is an ancestor of @descendant. That is, @iter is the
1776 * parent (or grandparent or great-grandparent) of @descendant.
1778 * Return value: %TRUE, if @iter is an ancestor of @descendant
1781 gtk_tree_store_is_ancestor (GtkTreeStore *tree_store,
1783 GtkTreeIter *descendant)
1785 g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), FALSE);
1786 g_return_val_if_fail (VALID_ITER (iter, tree_store), FALSE);
1787 g_return_val_if_fail (VALID_ITER (descendant, tree_store), FALSE);
1789 return g_node_is_ancestor (G_NODE (iter->user_data),
1790 G_NODE (descendant->user_data));
1795 * gtk_tree_store_iter_depth:
1796 * @tree_store: A #GtkTreeStore
1797 * @iter: A valid #GtkTreeIter
1799 * Returns the depth of @iter. This will be 0 for anything on the root level, 1
1800 * for anything down a level, etc.
1802 * Return value: The depth of @iter
1805 gtk_tree_store_iter_depth (GtkTreeStore *tree_store,
1808 g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), 0);
1809 g_return_val_if_fail (VALID_ITER (iter, tree_store), 0);
1811 return g_node_depth (G_NODE (iter->user_data)) - 2;
1814 /* simple ripoff from g_node_traverse_post_order */
1816 gtk_tree_store_clear_traverse (GNode *node,
1817 GtkTreeStore *store)
1825 child = node->children;
1828 register GNode *current;
1831 child = current->next;
1832 if (gtk_tree_store_clear_traverse (current, store))
1838 iter.stamp = store->priv->stamp;
1839 iter.user_data = node;
1841 gtk_tree_store_remove (store, &iter);
1844 else if (node->parent)
1846 iter.stamp = store->priv->stamp;
1847 iter.user_data = node;
1849 gtk_tree_store_remove (store, &iter);
1856 gtk_tree_store_increment_stamp (GtkTreeStore *tree_store)
1858 GtkTreeStorePrivate *priv = tree_store->priv;
1863 while (priv->stamp == 0);
1867 * gtk_tree_store_clear:
1868 * @tree_store: a #GtkTreeStore
1870 * Removes all rows from @tree_store
1873 gtk_tree_store_clear (GtkTreeStore *tree_store)
1875 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
1877 gtk_tree_store_clear_traverse (tree_store->priv->root, tree_store);
1878 gtk_tree_store_increment_stamp (tree_store);
1882 gtk_tree_store_iter_is_valid_helper (GtkTreeIter *iter,
1891 if (node == iter->user_data)
1895 if (gtk_tree_store_iter_is_valid_helper (iter, node->children))
1906 * gtk_tree_store_iter_is_valid:
1907 * @tree_store: A #GtkTreeStore.
1908 * @iter: A #GtkTreeIter.
1910 * WARNING: This function is slow. Only use it for debugging and/or testing
1913 * Checks if the given iter is a valid iter for this #GtkTreeStore.
1915 * Return value: %TRUE if the iter is valid, %FALSE if the iter is invalid.
1920 gtk_tree_store_iter_is_valid (GtkTreeStore *tree_store,
1923 g_return_val_if_fail (GTK_IS_TREE_STORE (tree_store), FALSE);
1924 g_return_val_if_fail (iter != NULL, FALSE);
1926 if (!VALID_ITER (iter, tree_store))
1929 return gtk_tree_store_iter_is_valid_helper (iter, tree_store->priv->root);
1935 static gboolean real_gtk_tree_store_row_draggable (GtkTreeDragSource *drag_source,
1942 gtk_tree_store_drag_data_delete (GtkTreeDragSource *drag_source,
1947 if (gtk_tree_store_get_iter (GTK_TREE_MODEL (drag_source),
1951 gtk_tree_store_remove (GTK_TREE_STORE (drag_source),
1962 gtk_tree_store_drag_data_get (GtkTreeDragSource *drag_source,
1964 GtkSelectionData *selection_data)
1966 /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1967 * target, because the default handler does it for us, but
1968 * we do anyway for the convenience of someone maybe overriding the
1972 if (gtk_tree_set_row_drag_data (selection_data,
1973 GTK_TREE_MODEL (drag_source),
1980 /* FIXME handle text targets at least. */
1987 copy_node_data (GtkTreeStore *tree_store,
1988 GtkTreeIter *src_iter,
1989 GtkTreeIter *dest_iter)
1991 GtkTreeDataList *dl = G_NODE (src_iter->user_data)->data;
1992 GtkTreeDataList *copy_head = NULL;
1993 GtkTreeDataList *copy_prev = NULL;
1994 GtkTreeDataList *copy_iter = NULL;
2001 copy_iter = _gtk_tree_data_list_node_copy (dl, tree_store->priv->column_headers[col]);
2003 if (copy_head == NULL)
2004 copy_head = copy_iter;
2007 copy_prev->next = copy_iter;
2009 copy_prev = copy_iter;
2015 G_NODE (dest_iter->user_data)->data = copy_head;
2017 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), dest_iter);
2018 gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_store), path, dest_iter);
2019 gtk_tree_path_free (path);
2023 recursive_node_copy (GtkTreeStore *tree_store,
2024 GtkTreeIter *src_iter,
2025 GtkTreeIter *dest_iter)
2028 GtkTreeModel *model;
2030 model = GTK_TREE_MODEL (tree_store);
2032 copy_node_data (tree_store, src_iter, dest_iter);
2034 if (gtk_tree_store_iter_children (model,
2038 /* Need to create children and recurse. Note our
2039 * dependence on persistent iterators here.
2045 /* Gee, a really slow algorithm... ;-) FIXME */
2046 gtk_tree_store_append (tree_store,
2050 recursive_node_copy (tree_store, &child, ©);
2052 while (gtk_tree_store_iter_next (model, &child));
2057 gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest,
2059 GtkSelectionData *selection_data)
2061 GtkTreeModel *tree_model;
2062 GtkTreeStore *tree_store;
2063 GtkTreeModel *src_model = NULL;
2064 GtkTreePath *src_path = NULL;
2065 gboolean retval = FALSE;
2067 tree_model = GTK_TREE_MODEL (drag_dest);
2068 tree_store = GTK_TREE_STORE (drag_dest);
2070 validate_tree (tree_store);
2072 if (gtk_tree_get_row_drag_data (selection_data,
2075 src_model == tree_model)
2077 /* Copy the given row to a new position */
2078 GtkTreeIter src_iter;
2079 GtkTreeIter dest_iter;
2082 if (!gtk_tree_store_get_iter (src_model,
2089 /* Get the path to insert _after_ (dest is the path to insert _before_) */
2090 prev = gtk_tree_path_copy (dest);
2092 if (!gtk_tree_path_prev (prev))
2094 GtkTreeIter dest_parent;
2095 GtkTreePath *parent;
2096 GtkTreeIter *dest_parent_p;
2098 /* dest was the first spot at the current depth; which means
2099 * we are supposed to prepend.
2102 /* Get the parent, NULL if parent is the root */
2103 dest_parent_p = NULL;
2104 parent = gtk_tree_path_copy (dest);
2105 if (gtk_tree_path_up (parent) &&
2106 gtk_tree_path_get_depth (parent) > 0)
2108 gtk_tree_store_get_iter (tree_model,
2111 dest_parent_p = &dest_parent;
2113 gtk_tree_path_free (parent);
2116 gtk_tree_store_prepend (tree_store,
2124 if (gtk_tree_store_get_iter (tree_model, &dest_iter, prev))
2126 GtkTreeIter tmp_iter = dest_iter;
2128 gtk_tree_store_insert_after (tree_store, &dest_iter, NULL,
2135 gtk_tree_path_free (prev);
2137 /* If we succeeded in creating dest_iter, walk src_iter tree branch,
2138 * duplicating it below dest_iter.
2143 recursive_node_copy (tree_store,
2150 /* FIXME maybe add some data targets eventually, or handle text
2151 * targets in the simple case.
2159 gtk_tree_path_free (src_path);
2165 gtk_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest,
2166 GtkTreePath *dest_path,
2167 GtkSelectionData *selection_data)
2169 GtkTreeModel *src_model = NULL;
2170 GtkTreePath *src_path = NULL;
2171 GtkTreePath *tmp = NULL;
2172 gboolean retval = FALSE;
2174 /* don't accept drops if the tree has been sorted */
2175 if (GTK_TREE_STORE_IS_SORTED (drag_dest))
2178 if (!gtk_tree_get_row_drag_data (selection_data,
2183 /* can only drag to ourselves */
2184 if (src_model != GTK_TREE_MODEL (drag_dest))
2187 /* Can't drop into ourself. */
2188 if (gtk_tree_path_is_ancestor (src_path,
2192 /* Can't drop if dest_path's parent doesn't exist */
2196 if (gtk_tree_path_get_depth (dest_path) > 1)
2198 tmp = gtk_tree_path_copy (dest_path);
2199 gtk_tree_path_up (tmp);
2201 if (!gtk_tree_store_get_iter (GTK_TREE_MODEL (drag_dest),
2207 /* Can otherwise drop anywhere. */
2213 gtk_tree_path_free (src_path);
2215 gtk_tree_path_free (tmp);
2220 /* Sorting and reordering */
2221 typedef struct _SortTuple
2229 gtk_tree_store_reorder_func (gconstpointer a,
2233 SortTuple *a_reorder;
2234 SortTuple *b_reorder;
2236 a_reorder = (SortTuple *)a;
2237 b_reorder = (SortTuple *)b;
2239 if (a_reorder->offset < b_reorder->offset)
2241 if (a_reorder->offset > b_reorder->offset)
2248 * gtk_tree_store_reorder:
2249 * @tree_store: A #GtkTreeStore.
2250 * @parent: A #GtkTreeIter.
2251 * @new_order: (array): an array of integers mapping the new position of each child
2252 * to its old position before the re-ordering,
2253 * i.e. @new_order<literal>[newpos] = oldpos</literal>.
2255 * Reorders the children of @parent in @tree_store to follow the order
2256 * indicated by @new_order. Note that this function only works with
2262 gtk_tree_store_reorder (GtkTreeStore *tree_store,
2263 GtkTreeIter *parent,
2267 GNode *level, *node;
2269 SortTuple *sort_array;
2271 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
2272 g_return_if_fail (!GTK_TREE_STORE_IS_SORTED (tree_store));
2273 g_return_if_fail (parent == NULL || VALID_ITER (parent, tree_store));
2274 g_return_if_fail (new_order != NULL);
2277 level = G_NODE (tree_store->priv->root)->children;
2279 level = G_NODE (parent->user_data)->children;
2289 /* set up sortarray */
2290 sort_array = g_new (SortTuple, length);
2293 for (i = 0; i < length; i++)
2295 sort_array[new_order[i]].offset = i;
2296 sort_array[i].node = node;
2301 g_qsort_with_data (sort_array,
2304 gtk_tree_store_reorder_func,
2308 for (i = 0; i < length - 1; i++)
2310 sort_array[i].node->next = sort_array[i+1].node;
2311 sort_array[i+1].node->prev = sort_array[i].node;
2314 sort_array[length-1].node->next = NULL;
2315 sort_array[0].node->prev = NULL;
2317 G_NODE (parent->user_data)->children = sort_array[0].node;
2319 G_NODE (tree_store->priv->root)->children = sort_array[0].node;
2323 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), parent);
2325 path = gtk_tree_path_new ();
2326 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), path,
2328 gtk_tree_path_free (path);
2329 g_free (sort_array);
2333 * gtk_tree_store_swap:
2334 * @tree_store: A #GtkTreeStore.
2335 * @a: A #GtkTreeIter.
2336 * @b: Another #GtkTreeIter.
2338 * Swaps @a and @b in the same level of @tree_store. Note that this function
2339 * only works with unsorted stores.
2344 gtk_tree_store_swap (GtkTreeStore *tree_store,
2348 GNode *tmp, *node_a, *node_b, *parent_node;
2349 GNode *a_prev, *a_next, *b_prev, *b_next;
2350 gint i, a_count, b_count, length, *order;
2351 GtkTreePath *path_a, *path_b;
2354 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
2355 g_return_if_fail (VALID_ITER (a, tree_store));
2356 g_return_if_fail (VALID_ITER (b, tree_store));
2358 node_a = G_NODE (a->user_data);
2359 node_b = G_NODE (b->user_data);
2361 /* basic sanity checking */
2362 if (node_a == node_b)
2365 path_a = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), a);
2366 path_b = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), b);
2368 g_return_if_fail (path_a && path_b);
2370 gtk_tree_path_up (path_a);
2371 gtk_tree_path_up (path_b);
2373 if (gtk_tree_path_get_depth (path_a) == 0
2374 || gtk_tree_path_get_depth (path_b) == 0)
2376 if (gtk_tree_path_get_depth (path_a) != gtk_tree_path_get_depth (path_b))
2378 gtk_tree_path_free (path_a);
2379 gtk_tree_path_free (path_b);
2381 g_warning ("Given children are not in the same level\n");
2384 parent_node = G_NODE (tree_store->priv->root);
2388 if (gtk_tree_path_compare (path_a, path_b))
2390 gtk_tree_path_free (path_a);
2391 gtk_tree_path_free (path_b);
2393 g_warning ("Given children don't have a common parent\n");
2396 gtk_tree_store_get_iter (GTK_TREE_MODEL (tree_store), &parent,
2398 parent_node = G_NODE (parent.user_data);
2400 gtk_tree_path_free (path_b);
2402 /* old links which we have to keep around */
2403 a_prev = node_a->prev;
2404 a_next = node_a->next;
2406 b_prev = node_b->prev;
2407 b_next = node_b->next;
2409 /* fix up links if the nodes are next to eachother */
2410 if (a_prev == node_b)
2412 if (a_next == node_b)
2415 if (b_prev == node_a)
2417 if (b_next == node_a)
2420 /* counting nodes */
2421 tmp = parent_node->children;
2422 i = a_count = b_count = 0;
2435 /* hacking the tree */
2437 parent_node->children = node_b;
2439 a_prev->next = node_b;
2442 a_next->prev = node_b;
2445 parent_node->children = node_a;
2447 b_prev->next = node_a;
2450 b_next->prev = node_a;
2452 node_a->prev = b_prev;
2453 node_a->next = b_next;
2455 node_b->prev = a_prev;
2456 node_b->next = a_next;
2459 order = g_new (gint, length);
2460 for (i = 0; i < length; i++)
2463 else if (i == b_count)
2468 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), path_a,
2469 parent_node == tree_store->priv->root
2470 ? NULL : &parent, order);
2471 gtk_tree_path_free (path_a);
2475 /* WARNING: this function is *incredibly* fragile. Please smashtest after
2476 * making changes here.
2480 gtk_tree_store_move (GtkTreeStore *tree_store,
2482 GtkTreeIter *position,
2485 GNode *parent, *node, *a, *b, *tmp, *tmp_a, *tmp_b;
2486 gint old_pos, new_pos, length, i, *order;
2487 GtkTreePath *path = NULL, *tmppath, *pos_path = NULL;
2488 GtkTreeIter parent_iter, dst_a, dst_b;
2490 gboolean handle_b = TRUE;
2492 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
2493 g_return_if_fail (!GTK_TREE_STORE_IS_SORTED (tree_store));
2494 g_return_if_fail (VALID_ITER (iter, tree_store));
2496 g_return_if_fail (VALID_ITER (position, tree_store));
2503 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
2504 pos_path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store),
2508 * moving the iter before path or "path + 1" doesn't make sense
2510 * moving the iter before path or "path - 1" doesn't make sense
2512 if (!gtk_tree_path_compare (path, pos_path))
2513 goto free_paths_and_out;
2516 gtk_tree_path_next (path);
2518 gtk_tree_path_prev (path);
2520 if (!gtk_tree_path_compare (path, pos_path))
2521 goto free_paths_and_out;
2524 gtk_tree_path_prev (path);
2526 gtk_tree_path_next (path);
2528 if (gtk_tree_path_get_depth (path) != gtk_tree_path_get_depth (pos_path))
2530 g_warning ("Given children are not in the same level\n");
2532 goto free_paths_and_out;
2535 tmppath = gtk_tree_path_copy (pos_path);
2536 gtk_tree_path_up (path);
2537 gtk_tree_path_up (tmppath);
2539 if (gtk_tree_path_get_depth (path) > 0 &&
2540 gtk_tree_path_compare (path, tmppath))
2542 g_warning ("Given children are not in the same level\n");
2544 gtk_tree_path_free (tmppath);
2545 goto free_paths_and_out;
2548 gtk_tree_path_free (tmppath);
2553 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), iter);
2554 gtk_tree_path_up (path);
2557 depth = gtk_tree_path_get_depth (path);
2561 gtk_tree_store_get_iter (GTK_TREE_MODEL (tree_store),
2562 &parent_iter, path);
2564 parent = G_NODE (parent_iter.user_data);
2567 parent = G_NODE (tree_store->priv->root);
2569 /* yes, I know that this can be done shorter, but I'm doing it this way
2570 * so the code is also maintainable
2573 if (before && position)
2575 b = G_NODE (position->user_data);
2577 if (gtk_tree_path_get_indices (pos_path)[gtk_tree_path_get_depth (pos_path) - 1] > 0)
2579 gtk_tree_path_prev (pos_path);
2580 if (gtk_tree_store_get_iter (GTK_TREE_MODEL (tree_store),
2582 a = G_NODE (dst_a.user_data);
2585 gtk_tree_path_next (pos_path);
2588 /* if b is NULL, a is NULL too -- we are at the beginning of the list
2589 * yes and we leak memory here ...
2591 g_return_if_fail (b);
2593 else if (before && !position)
2595 /* move before without position is appending */
2602 a = G_NODE (position->user_data);
2608 gtk_tree_path_next (pos_path);
2609 if (gtk_tree_store_get_iter (GTK_TREE_MODEL (tree_store), &dst_b, pos_path))
2610 b = G_NODE (dst_b.user_data);
2613 gtk_tree_path_prev (pos_path);
2617 /* move after without position is prepending */
2619 gtk_tree_store_iter_children (GTK_TREE_MODEL (tree_store), &dst_b,
2622 gtk_tree_store_iter_children (GTK_TREE_MODEL (tree_store), &dst_b,
2625 b = G_NODE (dst_b.user_data);
2628 /* if a is NULL, b is NULL too -- we are at the end of the list
2629 * yes and we leak memory here ...
2632 g_return_if_fail (a);
2635 /* counting nodes */
2636 tmp = parent->children;
2638 length = old_pos = 0;
2641 if (tmp == iter->user_data)
2648 /* remove node from list */
2649 node = G_NODE (iter->user_data);
2654 tmp_a->next = tmp_b;
2656 parent->children = tmp_b;
2659 tmp_b->prev = tmp_a;
2661 /* and reinsert the node */
2670 else if (!a && !before)
2672 tmp = parent->children;
2675 parent->children = node;
2683 else if (!a && before)
2687 node->parent = NULL;
2688 node->next = node->prev = NULL;
2690 /* before with sibling = NULL appends */
2691 g_node_insert_before (parent, NULL, node);
2695 node->parent = NULL;
2696 node->next = node->prev = NULL;
2698 /* after with sibling = NULL prepends */
2699 g_node_insert_after (parent, NULL, node);
2715 else if (!(!a && before)) /* !a && before is completely handled above */
2721 new_pos = gtk_tree_path_get_indices (pos_path)[gtk_tree_path_get_depth (pos_path)-1];
2725 new_pos = gtk_tree_store_iter_n_children (GTK_TREE_MODEL (tree_store),
2728 new_pos = gtk_tree_store_iter_n_children (GTK_TREE_MODEL (tree_store),
2734 if (new_pos > old_pos)
2736 if (before && position)
2741 if (!before && position)
2745 order = g_new (gint, length);
2746 if (new_pos > old_pos)
2748 for (i = 0; i < length; i++)
2751 else if (i >= old_pos && i < new_pos)
2753 else if (i == new_pos)
2760 for (i = 0; i < length; i++)
2763 else if (i > new_pos && i <= old_pos)
2771 tmppath = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store),
2773 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store),
2774 tmppath, &parent_iter, order);
2778 tmppath = gtk_tree_path_new ();
2779 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store),
2780 tmppath, NULL, order);
2783 gtk_tree_path_free (tmppath);
2784 gtk_tree_path_free (path);
2786 gtk_tree_path_free (pos_path);
2792 gtk_tree_path_free (path);
2793 gtk_tree_path_free (pos_path);
2797 * gtk_tree_store_move_before:
2798 * @tree_store: A #GtkTreeStore.
2799 * @iter: A #GtkTreeIter.
2800 * @position: (allow-none): A #GtkTreeIter or %NULL.
2802 * Moves @iter in @tree_store to the position before @position. @iter and
2803 * @position should be in the same level. Note that this function only
2804 * works with unsorted stores. If @position is %NULL, @iter will be
2805 * moved to the end of the level.
2810 gtk_tree_store_move_before (GtkTreeStore *tree_store,
2812 GtkTreeIter *position)
2814 gtk_tree_store_move (tree_store, iter, position, TRUE);
2818 * gtk_tree_store_move_after:
2819 * @tree_store: A #GtkTreeStore.
2820 * @iter: A #GtkTreeIter.
2821 * @position: (allow-none): A #GtkTreeIter.
2823 * Moves @iter in @tree_store to the position after @position. @iter and
2824 * @position should be in the same level. Note that this function only
2825 * works with unsorted stores. If @position is %NULL, @iter will be moved
2826 * to the start of the level.
2831 gtk_tree_store_move_after (GtkTreeStore *tree_store,
2833 GtkTreeIter *position)
2835 gtk_tree_store_move (tree_store, iter, position, FALSE);
2840 gtk_tree_store_compare_func (gconstpointer a,
2844 GtkTreeStore *tree_store = user_data;
2845 GtkTreeStorePrivate *priv = tree_store->priv;
2848 GtkTreeIterCompareFunc func;
2855 if (priv->sort_column_id != -1)
2857 GtkTreeDataSortHeader *header;
2859 header = _gtk_tree_data_list_get_header (priv->sort_list,
2860 priv->sort_column_id);
2861 g_return_val_if_fail (header != NULL, 0);
2862 g_return_val_if_fail (header->func != NULL, 0);
2864 func = header->func;
2865 data = header->data;
2869 g_return_val_if_fail (priv->default_sort_func != NULL, 0);
2870 func = priv->default_sort_func;
2871 data = priv->default_sort_data;
2874 node_a = ((SortTuple *) a)->node;
2875 node_b = ((SortTuple *) b)->node;
2877 iter_a.stamp = priv->stamp;
2878 iter_a.user_data = node_a;
2879 iter_b.stamp = priv->stamp;
2880 iter_b.user_data = node_b;
2882 retval = (* func) (GTK_TREE_MODEL (user_data), &iter_a, &iter_b, data);
2884 if (priv->order == GTK_SORT_DESCENDING)
2888 else if (retval < 0)
2895 gtk_tree_store_sort_helper (GtkTreeStore *tree_store,
2908 node = parent->children;
2909 if (node == NULL || node->next == NULL)
2911 if (recurse && node && node->children)
2912 gtk_tree_store_sort_helper (tree_store, node, TRUE);
2918 for (tmp_node = node; tmp_node; tmp_node = tmp_node->next)
2921 sort_array = g_array_sized_new (FALSE, FALSE, sizeof (SortTuple), list_length);
2924 for (tmp_node = node; tmp_node; tmp_node = tmp_node->next)
2929 tuple.node = tmp_node;
2930 g_array_append_val (sort_array, tuple);
2934 /* Sort the array */
2935 g_array_sort_with_data (sort_array, gtk_tree_store_compare_func, tree_store);
2937 for (i = 0; i < list_length - 1; i++)
2939 g_array_index (sort_array, SortTuple, i).node->next =
2940 g_array_index (sort_array, SortTuple, i + 1).node;
2941 g_array_index (sort_array, SortTuple, i + 1).node->prev =
2942 g_array_index (sort_array, SortTuple, i).node;
2944 g_array_index (sort_array, SortTuple, list_length - 1).node->next = NULL;
2945 g_array_index (sort_array, SortTuple, 0).node->prev = NULL;
2946 parent->children = g_array_index (sort_array, SortTuple, 0).node;
2948 /* Let the world know about our new order */
2949 new_order = g_new (gint, list_length);
2950 for (i = 0; i < list_length; i++)
2951 new_order[i] = g_array_index (sort_array, SortTuple, i).offset;
2953 iter.stamp = tree_store->priv->stamp;
2954 iter.user_data = parent;
2955 path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), &iter);
2956 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store),
2957 path, &iter, new_order);
2958 gtk_tree_path_free (path);
2960 g_array_free (sort_array, TRUE);
2964 for (tmp_node = parent->children; tmp_node; tmp_node = tmp_node->next)
2966 if (tmp_node->children)
2967 gtk_tree_store_sort_helper (tree_store, tmp_node, TRUE);
2973 gtk_tree_store_sort (GtkTreeStore *tree_store)
2975 GtkTreeStorePrivate *priv = tree_store->priv;
2977 if (!GTK_TREE_STORE_IS_SORTED (tree_store))
2980 if (priv->sort_column_id != -1)
2982 GtkTreeDataSortHeader *header = NULL;
2984 header = _gtk_tree_data_list_get_header (priv->sort_list,
2985 priv->sort_column_id);
2987 /* We want to make sure that we have a function */
2988 g_return_if_fail (header != NULL);
2989 g_return_if_fail (header->func != NULL);
2993 g_return_if_fail (priv->default_sort_func != NULL);
2996 gtk_tree_store_sort_helper (tree_store, G_NODE (priv->root), TRUE);
3000 gtk_tree_store_sort_iter_changed (GtkTreeStore *tree_store,
3003 gboolean emit_signal)
3005 GtkTreeStorePrivate *priv = tree_store->priv;
3009 GtkTreePath *tmp_path;
3010 GtkTreeIter tmp_iter;
3018 GtkTreeIterCompareFunc func;
3021 g_return_if_fail (G_NODE (iter->user_data)->parent != NULL);
3023 tmp_iter.stamp = priv->stamp;
3024 if (priv->sort_column_id != -1)
3026 GtkTreeDataSortHeader *header;
3027 header = _gtk_tree_data_list_get_header (priv->sort_list,
3028 priv->sort_column_id);
3029 g_return_if_fail (header != NULL);
3030 g_return_if_fail (header->func != NULL);
3031 func = header->func;
3032 data = header->data;
3036 g_return_if_fail (priv->default_sort_func != NULL);
3037 func = priv->default_sort_func;
3038 data = priv->default_sort_data;
3041 /* If it's the built in function, we don't sort. */
3042 if (func == _gtk_tree_data_list_compare_func &&
3043 priv->sort_column_id != column)
3047 node = G_NODE (iter->user_data)->parent->children;
3048 /* First we find the iter, its prev, and its next */
3051 if (node == G_NODE (iter->user_data))
3056 g_assert (node != NULL);
3061 /* Check the common case, where we don't need to sort it moved. */
3064 tmp_iter.user_data = prev;
3065 cmp_a = (* func) (GTK_TREE_MODEL (tree_store), &tmp_iter, iter, data);
3070 tmp_iter.user_data = next;
3071 cmp_b = (* func) (GTK_TREE_MODEL (tree_store), iter, &tmp_iter, data);
3074 if (priv->order == GTK_SORT_DESCENDING)
3087 if (prev == NULL && cmp_b <= 0)
3089 else if (next == NULL && cmp_a <= 0)
3091 else if (prev != NULL && next != NULL &&
3092 cmp_a <= 0 && cmp_b <= 0)
3095 /* We actually need to sort it */
3096 /* First, remove the old link. */
3101 node->parent->children = next;
3109 /* FIXME: as an optimization, we can potentially start at next */
3111 node = node->parent->children;
3113 tmp_iter.user_data = node;
3114 if (priv->order == GTK_SORT_DESCENDING)
3115 cmp_a = (* func) (GTK_TREE_MODEL (tree_store), &tmp_iter, iter, data);
3117 cmp_a = (* func) (GTK_TREE_MODEL (tree_store), iter, &tmp_iter, data);
3119 while ((node->next) && (cmp_a > 0))
3124 tmp_iter.user_data = node;
3125 if (priv->order == GTK_SORT_DESCENDING)
3126 cmp_a = (* func) (GTK_TREE_MODEL (tree_store), &tmp_iter, iter, data);
3128 cmp_a = (* func) (GTK_TREE_MODEL (tree_store), iter, &tmp_iter, data);
3131 if ((!node->next) && (cmp_a > 0))
3134 node->next = G_NODE (iter->user_data);
3135 node->next->prev = node;
3139 prev->next = G_NODE (iter->user_data);
3140 prev->next->prev = prev;
3141 G_NODE (iter->user_data)->next = node;
3142 G_NODE (iter->user_data)->next->prev = G_NODE (iter->user_data);
3146 G_NODE (iter->user_data)->next = G_NODE (iter->user_data)->parent->children;
3147 G_NODE (iter->user_data)->next->prev = G_NODE (iter->user_data);
3148 G_NODE (iter->user_data)->parent->children = G_NODE (iter->user_data);
3154 /* Emit the reordered signal. */
3155 length = g_node_n_children (node->parent);
3156 new_order = g_new (int, length);
3157 if (old_location < new_location)
3158 for (i = 0; i < length; i++)
3160 if (i < old_location ||
3163 else if (i >= old_location &&
3165 new_order[i] = i + 1;
3166 else if (i == new_location)
3167 new_order[i] = old_location;
3170 for (i = 0; i < length; i++)
3172 if (i < new_location ||
3175 else if (i > new_location &&
3177 new_order[i] = i - 1;
3178 else if (i == new_location)
3179 new_order[i] = old_location;
3182 tmp_iter.user_data = node->parent;
3183 tmp_path = gtk_tree_store_get_path (GTK_TREE_MODEL (tree_store), &tmp_iter);
3185 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store),
3186 tmp_path, &tmp_iter,
3189 gtk_tree_path_free (tmp_path);
3195 gtk_tree_store_get_sort_column_id (GtkTreeSortable *sortable,
3196 gint *sort_column_id,
3199 GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
3200 GtkTreeStorePrivate *priv = tree_store->priv;
3203 * sort_column_id = priv->sort_column_id;
3205 * order = priv->order;
3207 if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID ||
3208 priv->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
3215 gtk_tree_store_set_sort_column_id (GtkTreeSortable *sortable,
3216 gint sort_column_id,
3219 GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
3220 GtkTreeStorePrivate *priv = tree_store->priv;
3222 if ((priv->sort_column_id == sort_column_id) &&
3223 (priv->order == order))
3226 if (sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
3228 if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
3230 GtkTreeDataSortHeader *header = NULL;
3232 header = _gtk_tree_data_list_get_header (priv->sort_list,
3235 /* We want to make sure that we have a function */
3236 g_return_if_fail (header != NULL);
3237 g_return_if_fail (header->func != NULL);
3241 g_return_if_fail (priv->default_sort_func != NULL);
3245 priv->sort_column_id = sort_column_id;
3246 priv->order = order;
3248 gtk_tree_sortable_sort_column_changed (sortable);
3250 gtk_tree_store_sort (tree_store);
3254 gtk_tree_store_set_sort_func (GtkTreeSortable *sortable,
3255 gint sort_column_id,
3256 GtkTreeIterCompareFunc func,
3258 GDestroyNotify destroy)
3260 GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
3261 GtkTreeStorePrivate *priv = tree_store->priv;
3263 priv->sort_list = _gtk_tree_data_list_set_header (priv->sort_list,
3265 func, data, destroy);
3267 if (priv->sort_column_id == sort_column_id)
3268 gtk_tree_store_sort (tree_store);
3272 gtk_tree_store_set_default_sort_func (GtkTreeSortable *sortable,
3273 GtkTreeIterCompareFunc func,
3275 GDestroyNotify destroy)
3277 GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
3278 GtkTreeStorePrivate *priv = tree_store->priv;
3280 if (priv->default_sort_destroy)
3282 GDestroyNotify d = priv->default_sort_destroy;
3284 priv->default_sort_destroy = NULL;
3285 d (priv->default_sort_data);
3288 priv->default_sort_func = func;
3289 priv->default_sort_data = data;
3290 priv->default_sort_destroy = destroy;
3292 if (priv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
3293 gtk_tree_store_sort (tree_store);
3297 gtk_tree_store_has_default_sort_func (GtkTreeSortable *sortable)
3299 GtkTreeStore *tree_store = (GtkTreeStore *) sortable;
3301 return (tree_store->priv->default_sort_func != NULL);
3305 validate_gnode (GNode* node)
3309 iter = node->children;
3310 while (iter != NULL)
3312 g_assert (iter->parent == node);
3314 g_assert (iter->prev->next == iter);
3315 validate_gnode (iter);
3320 /* GtkBuildable custom tag implementation
3323 * <column type="..."/>
3324 * <column type="..."/>
3328 GtkBuilder *builder;
3331 } GSListSubParserData;
3334 tree_model_start_element (GMarkupParseContext *context,
3335 const gchar *element_name,
3336 const gchar **names,
3337 const gchar **values,
3342 GSListSubParserData *data = (GSListSubParserData*)user_data;
3344 for (i = 0; names[i]; i++)
3346 if (strcmp (names[i], "type") == 0)
3347 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
3352 tree_model_end_element (GMarkupParseContext *context,
3353 const gchar *element_name,
3357 GSListSubParserData *data = (GSListSubParserData*)user_data;
3359 g_assert(data->builder);
3361 if (strcmp (element_name, "columns") == 0)
3368 data = (GSListSubParserData*)user_data;
3369 data->items = g_slist_reverse (data->items);
3370 types = g_new0 (GType, g_slist_length (data->items));
3372 for (l = data->items, i = 0; l; l = l->next, i++)
3374 type = gtk_builder_get_type_from_name (data->builder, l->data);
3375 if (type == G_TYPE_INVALID)
3377 g_warning ("Unknown type %s specified in treemodel %s",
3378 (const gchar*)l->data,
3379 gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
3387 gtk_tree_store_set_column_types (GTK_TREE_STORE (data->object), i, types);
3393 static const GMarkupParser tree_model_parser =
3395 tree_model_start_element,
3396 tree_model_end_element
3401 gtk_tree_store_buildable_custom_tag_start (GtkBuildable *buildable,
3402 GtkBuilder *builder,
3404 const gchar *tagname,
3405 GMarkupParser *parser,
3408 GSListSubParserData *parser_data;
3413 if (strcmp (tagname, "columns") == 0)
3415 parser_data = g_slice_new0 (GSListSubParserData);
3416 parser_data->builder = builder;
3417 parser_data->items = NULL;
3418 parser_data->object = G_OBJECT (buildable);
3420 *parser = tree_model_parser;
3421 *data = parser_data;
3429 gtk_tree_store_buildable_custom_finished (GtkBuildable *buildable,
3430 GtkBuilder *builder,
3432 const gchar *tagname,
3435 GSListSubParserData *data;
3437 if (strcmp (tagname, "columns"))
3440 data = (GSListSubParserData*)user_data;
3442 g_slist_free (data->items);
3443 g_slice_free (GSListSubParserData, data);