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 "gtkliststore.h"
25 #include "gtktreedatalist.h"
26 #include "gtktreednd.h"
27 #include "gtksequence.h"
31 #define GTK_LIST_STORE_IS_SORTED(list) (((GtkListStore*)(list))->sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
32 #define VALID_ITER(iter, list_store) ((iter)!= NULL && (iter)->user_data != NULL && list_store->stamp == (iter)->stamp && !_gtk_sequence_ptr_is_end ((iter)->user_data) && _gtk_sequence_ptr_get_sequence ((iter)->user_data) == list_store->seq)
34 static void gtk_list_store_tree_model_init (GtkTreeModelIface *iface);
35 static void gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface);
36 static void gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface);
37 static void gtk_list_store_sortable_init (GtkTreeSortableIface *iface);
38 static void gtk_list_store_finalize (GObject *object);
39 static GtkTreeModelFlags gtk_list_store_get_flags (GtkTreeModel *tree_model);
40 static gint gtk_list_store_get_n_columns (GtkTreeModel *tree_model);
41 static GType gtk_list_store_get_column_type (GtkTreeModel *tree_model,
43 static gboolean gtk_list_store_get_iter (GtkTreeModel *tree_model,
46 static GtkTreePath *gtk_list_store_get_path (GtkTreeModel *tree_model,
48 static void gtk_list_store_get_value (GtkTreeModel *tree_model,
52 static gboolean gtk_list_store_iter_next (GtkTreeModel *tree_model,
54 static gboolean gtk_list_store_iter_children (GtkTreeModel *tree_model,
57 static gboolean gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
59 static gint gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
61 static gboolean gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
65 static gboolean gtk_list_store_iter_parent (GtkTreeModel *tree_model,
70 static void gtk_list_store_set_n_columns (GtkListStore *list_store,
72 static void gtk_list_store_set_column_type (GtkListStore *list_store,
76 static void gtk_list_store_increment_stamp (GtkListStore *list_store);
80 static gboolean real_gtk_list_store_row_draggable (GtkTreeDragSource *drag_source,
82 static gboolean gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
84 static gboolean gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
86 GtkSelectionData *selection_data);
87 static gboolean gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest,
89 GtkSelectionData *selection_data);
90 static gboolean gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest,
91 GtkTreePath *dest_path,
92 GtkSelectionData *selection_data);
96 static void gtk_list_store_sort (GtkListStore *list_store);
97 static void gtk_list_store_sort_iter_changed (GtkListStore *list_store,
100 static gboolean gtk_list_store_get_sort_column_id (GtkTreeSortable *sortable,
101 gint *sort_column_id,
103 static void gtk_list_store_set_sort_column_id (GtkTreeSortable *sortable,
106 static void gtk_list_store_set_sort_func (GtkTreeSortable *sortable,
108 GtkTreeIterCompareFunc func,
110 GtkDestroyNotify destroy);
111 static void gtk_list_store_set_default_sort_func (GtkTreeSortable *sortable,
112 GtkTreeIterCompareFunc func,
114 GtkDestroyNotify destroy);
115 static gboolean gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable);
118 G_DEFINE_TYPE_WITH_CODE (GtkListStore, gtk_list_store, G_TYPE_OBJECT,
119 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
120 gtk_list_store_tree_model_init)
121 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
122 gtk_list_store_drag_source_init)
123 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
124 gtk_list_store_drag_dest_init)
125 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
126 gtk_list_store_sortable_init))
129 gtk_list_store_class_init (GtkListStoreClass *class)
131 GObjectClass *object_class;
133 object_class = (GObjectClass*) class;
135 object_class->finalize = gtk_list_store_finalize;
139 gtk_list_store_tree_model_init (GtkTreeModelIface *iface)
141 iface->get_flags = gtk_list_store_get_flags;
142 iface->get_n_columns = gtk_list_store_get_n_columns;
143 iface->get_column_type = gtk_list_store_get_column_type;
144 iface->get_iter = gtk_list_store_get_iter;
145 iface->get_path = gtk_list_store_get_path;
146 iface->get_value = gtk_list_store_get_value;
147 iface->iter_next = gtk_list_store_iter_next;
148 iface->iter_children = gtk_list_store_iter_children;
149 iface->iter_has_child = gtk_list_store_iter_has_child;
150 iface->iter_n_children = gtk_list_store_iter_n_children;
151 iface->iter_nth_child = gtk_list_store_iter_nth_child;
152 iface->iter_parent = gtk_list_store_iter_parent;
156 gtk_list_store_drag_source_init (GtkTreeDragSourceIface *iface)
158 iface->row_draggable = real_gtk_list_store_row_draggable;
159 iface->drag_data_delete = gtk_list_store_drag_data_delete;
160 iface->drag_data_get = gtk_list_store_drag_data_get;
164 gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface)
166 iface->drag_data_received = gtk_list_store_drag_data_received;
167 iface->row_drop_possible = gtk_list_store_row_drop_possible;
171 gtk_list_store_sortable_init (GtkTreeSortableIface *iface)
173 iface->get_sort_column_id = gtk_list_store_get_sort_column_id;
174 iface->set_sort_column_id = gtk_list_store_set_sort_column_id;
175 iface->set_sort_func = gtk_list_store_set_sort_func;
176 iface->set_default_sort_func = gtk_list_store_set_default_sort_func;
177 iface->has_default_sort_func = gtk_list_store_has_default_sort_func;
181 gtk_list_store_init (GtkListStore *list_store)
183 list_store->seq = _gtk_sequence_new (NULL);
184 list_store->sort_list = NULL;
185 list_store->stamp = g_random_int ();
186 list_store->sort_column_id = -2;
187 list_store->columns_dirty = FALSE;
188 list_store->length = 0;
192 * gtk_list_store_new:
193 * @n_columns: number of columns in the list store
194 * @Varargs: all #GType types for the columns, from first to last
196 * Creates a new list store as with @n_columns columns each of the types passed
197 * in. Note that only types derived from standard GObject fundamental types
200 * As an example, <literal>gtk_tree_store_new (3, G_TYPE_INT, G_TYPE_STRING,
201 * GDK_TYPE_PIXBUF);</literal> will create a new #GtkListStore with three columns, of type
202 * int, string and #GdkPixbuf respectively.
204 * Return value: a new #GtkListStore
207 gtk_list_store_new (gint n_columns,
210 GtkListStore *retval;
214 g_return_val_if_fail (n_columns > 0, NULL);
216 retval = g_object_new (GTK_TYPE_LIST_STORE, NULL);
217 gtk_list_store_set_n_columns (retval, n_columns);
219 va_start (args, n_columns);
221 for (i = 0; i < n_columns; i++)
223 GType type = va_arg (args, GType);
224 if (! _gtk_tree_data_list_check_type (type))
226 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
227 g_object_unref (retval);
231 gtk_list_store_set_column_type (retval, i, type);
241 * gtk_list_store_newv:
242 * @n_columns: number of columns in the list store
243 * @types: an array of #GType types for the columns, from first to last
245 * Non-vararg creation function. Used primarily by language bindings.
247 * Return value: a new #GtkListStore
250 gtk_list_store_newv (gint n_columns,
253 GtkListStore *retval;
256 g_return_val_if_fail (n_columns > 0, NULL);
258 retval = g_object_new (GTK_TYPE_LIST_STORE, NULL);
259 gtk_list_store_set_n_columns (retval, n_columns);
261 for (i = 0; i < n_columns; i++)
263 if (! _gtk_tree_data_list_check_type (types[i]))
265 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i]));
266 g_object_unref (retval);
270 gtk_list_store_set_column_type (retval, i, types[i]);
277 * gtk_list_store_set_column_types:
278 * @list_store: A #GtkListStore
279 * @n_columns: Number of columns for the list store
280 * @types: An array length n of #GTypes
282 * This function is meant primarily for #GObjects that inherit from #GtkListStore,
283 * and should only be used when constructing a new #GtkListStore. It will not
284 * function after a row has been added, or a method on the #GtkTreeModel
285 * interface is called.
288 gtk_list_store_set_column_types (GtkListStore *list_store,
294 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
295 g_return_if_fail (list_store->columns_dirty == 0);
297 gtk_list_store_set_n_columns (list_store, n_columns);
298 for (i = 0; i < n_columns; i++)
300 if (! _gtk_tree_data_list_check_type (types[i]))
302 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i]));
305 gtk_list_store_set_column_type (list_store, i, types[i]);
310 gtk_list_store_set_n_columns (GtkListStore *list_store,
315 if (list_store->n_columns == n_columns)
318 new_columns = g_new0 (GType, n_columns);
319 if (list_store->column_headers)
321 /* copy the old header orders over */
322 if (n_columns >= list_store->n_columns)
323 memcpy (new_columns, list_store->column_headers, list_store->n_columns * sizeof (gchar *));
325 memcpy (new_columns, list_store->column_headers, n_columns * sizeof (GType));
327 g_free (list_store->column_headers);
330 if (list_store->sort_list)
331 _gtk_tree_data_list_header_free (list_store->sort_list);
333 list_store->sort_list = _gtk_tree_data_list_header_new (n_columns, list_store->column_headers);
335 list_store->column_headers = new_columns;
336 list_store->n_columns = n_columns;
340 gtk_list_store_set_column_type (GtkListStore *list_store,
344 if (!_gtk_tree_data_list_check_type (type))
346 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
350 list_store->column_headers[column] = type;
354 gtk_list_store_finalize (GObject *object)
356 GtkListStore *list_store = GTK_LIST_STORE (object);
358 _gtk_sequence_foreach (list_store->seq,
359 (GFunc) _gtk_tree_data_list_free, list_store->column_headers);
361 _gtk_sequence_free (list_store->seq);
363 _gtk_tree_data_list_header_free (list_store->sort_list);
364 g_free (list_store->column_headers);
366 if (list_store->default_sort_destroy)
368 GtkDestroyNotify d = list_store->default_sort_destroy;
370 list_store->default_sort_destroy = NULL;
371 d (list_store->default_sort_data);
372 list_store->default_sort_data = NULL;
376 (* G_OBJECT_CLASS (gtk_list_store_parent_class)->finalize) (object);
379 /* Fulfill the GtkTreeModel requirements */
380 static GtkTreeModelFlags
381 gtk_list_store_get_flags (GtkTreeModel *tree_model)
383 return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
387 gtk_list_store_get_n_columns (GtkTreeModel *tree_model)
389 GtkListStore *list_store = (GtkListStore *) tree_model;
391 list_store->columns_dirty = TRUE;
393 return list_store->n_columns;
397 gtk_list_store_get_column_type (GtkTreeModel *tree_model,
400 GtkListStore *list_store = (GtkListStore *) tree_model;
402 g_return_val_if_fail (index < GTK_LIST_STORE (tree_model)->n_columns,
405 list_store->columns_dirty = TRUE;
407 return list_store->column_headers[index];
411 gtk_list_store_get_iter (GtkTreeModel *tree_model,
415 GtkListStore *list_store = (GtkListStore *) tree_model;
419 list_store->columns_dirty = TRUE;
421 seq = list_store->seq;
423 i = gtk_tree_path_get_indices (path)[0];
425 if (i >= _gtk_sequence_get_length (seq))
428 iter->stamp = list_store->stamp;
429 iter->user_data = _gtk_sequence_get_ptr_at_pos (seq, i);
435 gtk_list_store_get_path (GtkTreeModel *tree_model,
440 g_return_val_if_fail (iter->stamp == GTK_LIST_STORE (tree_model)->stamp, NULL);
442 if (_gtk_sequence_ptr_is_end (iter->user_data))
445 path = gtk_tree_path_new ();
446 gtk_tree_path_append_index (path, _gtk_sequence_ptr_get_position (iter->user_data));
452 gtk_list_store_get_value (GtkTreeModel *tree_model,
457 GtkListStore *list_store = (GtkListStore *) tree_model;
458 GtkTreeDataList *list;
459 gint tmp_column = column;
461 g_return_if_fail (column < list_store->n_columns);
462 g_return_if_fail (VALID_ITER (iter, list_store));
464 list = _gtk_sequence_ptr_get_data (iter->user_data);
466 while (tmp_column-- > 0 && list)
470 g_value_init (value, list_store->column_headers[column]);
472 _gtk_tree_data_list_node_to_value (list,
473 list_store->column_headers[column],
478 gtk_list_store_iter_next (GtkTreeModel *tree_model,
481 g_return_val_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp, FALSE);
482 iter->user_data = _gtk_sequence_ptr_next (iter->user_data);
484 return !_gtk_sequence_ptr_is_end (iter->user_data);
488 gtk_list_store_iter_children (GtkTreeModel *tree_model,
492 GtkListStore *list_store = (GtkListStore *) tree_model;
494 /* this is a list, nodes have no children */
498 if (_gtk_sequence_get_length (list_store->seq) > 0)
500 iter->stamp = list_store->stamp;
501 iter->user_data = _gtk_sequence_get_begin_ptr (list_store->seq);
509 gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
516 gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
519 GtkListStore *list_store = (GtkListStore *) tree_model;
522 return _gtk_sequence_get_length (list_store->seq);
524 g_return_val_if_fail (list_store->stamp == iter->stamp, -1);
530 gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
535 GtkListStore *list_store = (GtkListStore *) tree_model;
536 GtkSequencePtr child;
541 child = _gtk_sequence_get_ptr_at_pos (list_store->seq, n);
543 if (_gtk_sequence_ptr_is_end (child))
546 iter->stamp = list_store->stamp;
547 iter->user_data = child;
553 gtk_list_store_iter_parent (GtkTreeModel *tree_model,
561 gtk_list_store_real_set_value (GtkListStore *list_store,
567 GtkTreeDataList *list;
568 GtkTreeDataList *prev;
569 gint old_column = column;
570 GValue real_value = {0, };
571 gboolean converted = FALSE;
572 gboolean retval = FALSE;
574 if (! g_type_is_a (G_VALUE_TYPE (value), list_store->column_headers[column]))
576 if (! (g_value_type_compatible (G_VALUE_TYPE (value), list_store->column_headers[column]) &&
577 g_value_type_compatible (list_store->column_headers[column], G_VALUE_TYPE (value))))
579 g_warning ("%s: Unable to convert from %s to %s\n",
581 g_type_name (G_VALUE_TYPE (value)),
582 g_type_name (list_store->column_headers[column]));
585 if (!g_value_transform (value, &real_value))
587 g_warning ("%s: Unable to make conversion from %s to %s\n",
589 g_type_name (G_VALUE_TYPE (value)),
590 g_type_name (list_store->column_headers[column]));
591 g_value_unset (&real_value);
597 prev = list = _gtk_sequence_ptr_get_data (iter->user_data);
604 _gtk_tree_data_list_value_to_node (list, &real_value);
606 _gtk_tree_data_list_value_to_node (list, value);
609 g_value_unset (&real_value);
610 if (sort && GTK_LIST_STORE_IS_SORTED (list_store))
611 gtk_list_store_sort_iter_changed (list_store, iter, old_column);
620 if (_gtk_sequence_ptr_get_data (iter->user_data) == NULL)
622 list = _gtk_tree_data_list_alloc();
623 _gtk_sequence_set (iter->user_data, list);
628 list = prev->next = _gtk_tree_data_list_alloc ();
634 list->next = _gtk_tree_data_list_alloc ();
641 _gtk_tree_data_list_value_to_node (list, &real_value);
643 _gtk_tree_data_list_value_to_node (list, value);
647 g_value_unset (&real_value);
649 if (sort && GTK_LIST_STORE_IS_SORTED (list_store))
650 gtk_list_store_sort_iter_changed (list_store, iter, old_column);
657 * gtk_list_store_set_value:
658 * @list_store: A #GtkListStore
659 * @iter: A valid #GtkTreeIter for the row being modified
660 * @column: column number to modify
661 * @value: new value for the cell
663 * Sets the data in the cell specified by @iter and @column.
664 * The type of @value must be convertible to the type of the
669 gtk_list_store_set_value (GtkListStore *list_store,
674 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
675 g_return_if_fail (VALID_ITER (iter, list_store));
676 g_return_if_fail (column >= 0 && column < list_store->n_columns);
677 g_return_if_fail (G_IS_VALUE (value));
679 if (gtk_list_store_real_set_value (list_store, iter, column, value, TRUE))
683 path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
684 gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
685 gtk_tree_path_free (path);
689 static GtkTreeIterCompareFunc
690 gtk_list_store_get_compare_func (GtkListStore *list_store)
692 GtkTreeIterCompareFunc func = NULL;
694 if (GTK_LIST_STORE_IS_SORTED (list_store))
696 if (list_store->sort_column_id != -1)
698 GtkTreeDataSortHeader *header;
699 header = _gtk_tree_data_list_get_header (list_store->sort_list,
700 list_store->sort_column_id);
701 g_return_val_if_fail (header != NULL, NULL);
702 g_return_val_if_fail (header->func != NULL, NULL);
707 func = list_store->default_sort_func;
715 gtk_list_store_set_valist_internal (GtkListStore *list_store,
717 gboolean *emit_signal,
718 gboolean *maybe_need_sort,
722 GtkTreeIterCompareFunc func = NULL;
724 column = va_arg (var_args, gint);
726 func = gtk_list_store_get_compare_func (list_store);
727 if (func != _gtk_tree_data_list_compare_func)
728 *maybe_need_sort = TRUE;
732 GValue value = { 0, };
735 if (column >= list_store->n_columns)
737 g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
740 g_value_init (&value, list_store->column_headers[column]);
742 G_VALUE_COLLECT (&value, var_args, 0, &error);
745 g_warning ("%s: %s", G_STRLOC, error);
748 /* we purposely leak the value here, it might not be
749 * in a sane state if an error condition occoured
754 /* FIXME: instead of calling this n times, refactor with above */
755 *emit_signal = gtk_list_store_real_set_value (list_store,
759 FALSE) || *emit_signal;
761 if (func == _gtk_tree_data_list_compare_func &&
762 column == list_store->sort_column_id)
763 *maybe_need_sort = TRUE;
765 g_value_unset (&value);
767 column = va_arg (var_args, gint);
772 * gtk_list_store_set_valist:
773 * @list_store: A #GtkListStore
774 * @iter: A valid #GtkTreeIter for the row being modified
775 * @var_args: va_list of column/value pairs
777 * See gtk_list_store_set(); this version takes a va_list for use by language
782 gtk_list_store_set_valist (GtkListStore *list_store,
786 gboolean emit_signal = FALSE;
787 gboolean maybe_need_sort = FALSE;
789 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
790 g_return_if_fail (VALID_ITER (iter, list_store));
792 gtk_list_store_set_valist_internal (list_store, iter,
797 if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
798 gtk_list_store_sort_iter_changed (list_store, iter, list_store->sort_column_id);
804 path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
805 gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
806 gtk_tree_path_free (path);
811 * gtk_list_store_set:
812 * @list_store: a #GtkListStore
813 * @iter: row iterator
814 * @Varargs: pairs of column number and value, terminated with -1
816 * Sets the value of one or more cells in the row referenced by @iter.
817 * The variable argument list should contain integer column numbers,
818 * each column number followed by the value to be set.
819 * The list is terminated by a -1. For example, to set column 0 with type
820 * %G_TYPE_STRING to "Foo", you would write <literal>gtk_list_store_set (store, iter,
821 * 0, "Foo", -1)</literal>.
824 gtk_list_store_set (GtkListStore *list_store,
830 va_start (var_args, iter);
831 gtk_list_store_set_valist (list_store, iter, var_args);
836 * gtk_list_store_remove:
837 * @list_store: A #GtkListStore
838 * @iter: A valid #GtkTreeIter
840 * Removes the given row from the list store. After being removed,
841 * @iter is set to be the next valid row, or invalidated if it pointed
842 * to the last row in @list_store.
844 * Return value: %TRUE if @iter is valid, %FALSE if not.
847 gtk_list_store_remove (GtkListStore *list_store,
851 GtkSequencePtr ptr, next;
853 g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
854 g_return_val_if_fail (VALID_ITER (iter, list_store), FALSE);
856 path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
858 ptr = iter->user_data;
859 next = _gtk_sequence_ptr_next (ptr);
861 _gtk_tree_data_list_free (_gtk_sequence_ptr_get_data (ptr), list_store->column_headers);
862 _gtk_sequence_remove (iter->user_data);
864 list_store->length--;
866 gtk_tree_model_row_deleted (GTK_TREE_MODEL (list_store), path);
867 gtk_tree_path_free (path);
869 if (_gtk_sequence_ptr_is_end (next))
876 iter->stamp = list_store->stamp;
877 iter->user_data = next;
883 * gtk_list_store_insert:
884 * @list_store: A #GtkListStore
885 * @iter: An unset #GtkTreeIter to set to the new row
886 * @position: position to insert the new row
888 * Creates a new row at @position. @iter will be changed to point to this new
889 * row. If @position is larger than the number of rows on the list, then the
890 * new row will be appended to the list. The row will be empty after this
891 * function is called. To fill in values, you need to call
892 * gtk_list_store_set() or gtk_list_store_set_value().
896 gtk_list_store_insert (GtkListStore *list_store,
905 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
906 g_return_if_fail (iter != NULL);
907 g_return_if_fail (position >= 0);
909 list_store->columns_dirty = TRUE;
911 seq = list_store->seq;
913 length = _gtk_sequence_get_length (seq);
914 if (position > length)
917 ptr = _gtk_sequence_get_ptr_at_pos (seq, position);
918 ptr = _gtk_sequence_insert (ptr, NULL);
920 iter->stamp = list_store->stamp;
921 iter->user_data = ptr;
923 g_assert (VALID_ITER (iter, list_store));
925 list_store->length++;
927 path = gtk_tree_path_new ();
928 gtk_tree_path_append_index (path, position);
929 gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
930 gtk_tree_path_free (path);
934 * gtk_list_store_insert_before:
935 * @list_store: A #GtkListStore
936 * @iter: An unset #GtkTreeIter to set to the new row
937 * @sibling: A valid #GtkTreeIter, or %NULL
939 * Inserts a new row before @sibling. If @sibling is %NULL, then the row will
940 * be appended to the end of the list. @iter will be changed to point to this
941 * new row. The row will be empty after this function is called. To fill in
942 * values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
946 gtk_list_store_insert_before (GtkListStore *list_store,
948 GtkTreeIter *sibling)
950 GtkSequencePtr after;
952 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
953 g_return_if_fail (iter != NULL);
955 g_return_if_fail (VALID_ITER (sibling, list_store));
958 after = _gtk_sequence_get_end_ptr (list_store->seq);
960 after = sibling->user_data;
962 gtk_list_store_insert (list_store, iter, _gtk_sequence_ptr_get_position (after));
966 * gtk_list_store_insert_after:
967 * @list_store: A #GtkListStore
968 * @iter: An unset #GtkTreeIter to set to the new row
969 * @sibling: A valid #GtkTreeIter, or %NULL
971 * Inserts a new row after @sibling. If @sibling is %NULL, then the row will be
972 * prepended to the beginning of the list. @iter will be changed to point to
973 * this new row. The row will be empty after this function is called. To fill
974 * in values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
978 gtk_list_store_insert_after (GtkListStore *list_store,
980 GtkTreeIter *sibling)
982 GtkSequencePtr after;
984 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
985 g_return_if_fail (iter != NULL);
987 g_return_if_fail (VALID_ITER (sibling, list_store));
990 after = _gtk_sequence_get_begin_ptr (list_store->seq);
992 after = _gtk_sequence_ptr_next (sibling->user_data);
994 gtk_list_store_insert (list_store, iter, _gtk_sequence_ptr_get_position (after));
998 * gtk_list_store_prepend:
999 * @list_store: A #GtkListStore
1000 * @iter: An unset #GtkTreeIter to set to the prepend row
1002 * Prepends a new row to @list_store. @iter will be changed to point to this new
1003 * row. The row will be empty after this function is called. To fill in
1004 * values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
1008 gtk_list_store_prepend (GtkListStore *list_store,
1011 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1012 g_return_if_fail (iter != NULL);
1014 gtk_list_store_insert (list_store, iter, 0);
1018 * gtk_list_store_append:
1019 * @list_store: A #GtkListStore
1020 * @iter: An unset #GtkTreeIter to set to the appended row
1022 * Appends a new row to @list_store. @iter will be changed to point to this new
1023 * row. The row will be empty after this function is called. To fill in
1024 * values, you need to call gtk_list_store_set() or gtk_list_store_set_value().
1028 gtk_list_store_append (GtkListStore *list_store,
1031 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1032 g_return_if_fail (iter != NULL);
1034 gtk_list_store_insert (list_store, iter, _gtk_sequence_get_length (list_store->seq));
1038 gtk_list_store_increment_stamp (GtkListStore *list_store)
1042 list_store->stamp++;
1044 while (list_store->stamp == 0);
1048 * gtk_list_store_clear:
1049 * @list_store: a #GtkListStore.
1051 * Removes all rows from the list store.
1055 gtk_list_store_clear (GtkListStore *list_store)
1058 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1060 while (_gtk_sequence_get_length (list_store->seq) > 0)
1062 iter.stamp = list_store->stamp;
1063 iter.user_data = _gtk_sequence_get_begin_ptr (list_store->seq);
1064 gtk_list_store_remove (list_store, &iter);
1067 gtk_list_store_increment_stamp (list_store);
1071 * gtk_list_store_iter_is_valid:
1072 * @list_store: A #GtkListStore.
1073 * @iter: A #GtkTreeIter.
1075 * <warning>This function is slow. Only use it for debugging and/or testing
1076 * purposes.</warning>
1078 * Checks if the given iter is a valid iter for this #GtkListStore.
1080 * Return value: %TRUE if the iter is valid, %FALSE if the iter is invalid.
1085 gtk_list_store_iter_is_valid (GtkListStore *list_store,
1088 g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE);
1089 g_return_val_if_fail (iter != NULL, FALSE);
1091 if (!VALID_ITER (iter, list_store))
1094 if (_gtk_sequence_ptr_get_sequence (iter->user_data) != list_store->seq)
1100 static gboolean real_gtk_list_store_row_draggable (GtkTreeDragSource *drag_source,
1107 gtk_list_store_drag_data_delete (GtkTreeDragSource *drag_source,
1112 if (gtk_list_store_get_iter (GTK_TREE_MODEL (drag_source),
1116 gtk_list_store_remove (GTK_LIST_STORE (drag_source), &iter);
1123 gtk_list_store_drag_data_get (GtkTreeDragSource *drag_source,
1125 GtkSelectionData *selection_data)
1127 /* Note that we don't need to handle the GTK_TREE_MODEL_ROW
1128 * target, because the default handler does it for us, but
1129 * we do anyway for the convenience of someone maybe overriding the
1133 if (gtk_tree_set_row_drag_data (selection_data,
1134 GTK_TREE_MODEL (drag_source),
1141 /* FIXME handle text targets at least. */
1148 gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest,
1150 GtkSelectionData *selection_data)
1152 GtkTreeModel *tree_model;
1153 GtkListStore *list_store;
1154 GtkTreeModel *src_model = NULL;
1155 GtkTreePath *src_path = NULL;
1156 gboolean retval = FALSE;
1158 tree_model = GTK_TREE_MODEL (drag_dest);
1159 list_store = GTK_LIST_STORE (drag_dest);
1161 if (gtk_tree_get_row_drag_data (selection_data,
1164 src_model == tree_model)
1166 /* Copy the given row to a new position */
1167 GtkTreeIter src_iter;
1168 GtkTreeIter dest_iter;
1171 if (!gtk_list_store_get_iter (src_model,
1178 /* Get the path to insert _after_ (dest is the path to insert _before_) */
1179 prev = gtk_tree_path_copy (dest);
1181 if (!gtk_tree_path_prev (prev))
1183 /* dest was the first spot in the list; which means we are supposed
1186 gtk_list_store_prepend (list_store, &dest_iter);
1192 if (gtk_list_store_get_iter (tree_model, &dest_iter, prev))
1194 GtkTreeIter tmp_iter = dest_iter;
1196 gtk_list_store_insert_after (list_store, &dest_iter, &tmp_iter);
1202 gtk_tree_path_free (prev);
1204 /* If we succeeded in creating dest_iter, copy data from src
1208 GtkTreeDataList *dl = _gtk_sequence_ptr_get_data (src_iter.user_data);
1209 GtkTreeDataList *copy_head = NULL;
1210 GtkTreeDataList *copy_prev = NULL;
1211 GtkTreeDataList *copy_iter = NULL;
1218 copy_iter = _gtk_tree_data_list_node_copy (dl,
1219 list_store->column_headers[col]);
1221 if (copy_head == NULL)
1222 copy_head = copy_iter;
1225 copy_prev->next = copy_iter;
1227 copy_prev = copy_iter;
1233 dest_iter.stamp = list_store->stamp;
1234 _gtk_sequence_set (dest_iter.user_data, copy_head);
1236 path = gtk_list_store_get_path (tree_model, &dest_iter);
1237 gtk_tree_model_row_changed (tree_model, path, &dest_iter);
1238 gtk_tree_path_free (path);
1243 /* FIXME maybe add some data targets eventually, or handle text
1244 * targets in the simple case.
1251 gtk_tree_path_free (src_path);
1257 gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest,
1258 GtkTreePath *dest_path,
1259 GtkSelectionData *selection_data)
1262 GtkTreeModel *src_model = NULL;
1263 GtkTreePath *src_path = NULL;
1264 gboolean retval = FALSE;
1266 /* don't accept drops if the list has been sorted */
1267 if (GTK_LIST_STORE_IS_SORTED (drag_dest))
1270 if (!gtk_tree_get_row_drag_data (selection_data,
1275 if (src_model != GTK_TREE_MODEL (drag_dest))
1278 if (gtk_tree_path_get_depth (dest_path) != 1)
1281 /* can drop before any existing node, or before one past any existing. */
1283 indices = gtk_tree_path_get_indices (dest_path);
1285 if (indices[0] <= _gtk_sequence_get_length (GTK_LIST_STORE (drag_dest)->seq))
1290 gtk_tree_path_free (src_path);
1295 /* Sorting and reordering */
1299 gtk_list_store_reorder_func (gconstpointer a,
1303 GHashTable *new_positions = user_data;
1304 gint apos = GPOINTER_TO_INT (g_hash_table_lookup (new_positions, a));
1305 gint bpos = GPOINTER_TO_INT (g_hash_table_lookup (new_positions, b));
1315 * gtk_list_store_reorder:
1316 * @store: A #GtkListStore.
1317 * @new_order: an array of integers mapping the new position of each child
1318 * to its old position before the re-ordering,
1319 * i.e. @new_order<literal>[newpos] = oldpos</literal>.
1321 * Reorders @store to follow the order indicated by @new_order. Note that
1322 * this function only works with unsorted stores.
1327 gtk_list_store_reorder (GtkListStore *store,
1332 GHashTable *new_positions;
1336 g_return_if_fail (GTK_IS_LIST_STORE (store));
1337 g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1338 g_return_if_fail (new_order != NULL);
1340 order = g_new (gint, _gtk_sequence_get_length (store->seq));
1341 for (i = 0; i < _gtk_sequence_get_length (store->seq); i++)
1342 order[new_order[i]] = i;
1344 new_positions = g_hash_table_new (g_direct_hash, g_direct_equal);
1346 ptr = _gtk_sequence_get_begin_ptr (store->seq);
1348 while (!_gtk_sequence_ptr_is_end (ptr))
1350 g_hash_table_insert (new_positions, ptr, GINT_TO_POINTER (order[i++]));
1352 ptr = _gtk_sequence_ptr_next (ptr);
1356 _gtk_sequence_sort (store->seq, gtk_list_store_reorder_func, new_positions);
1358 g_hash_table_destroy (new_positions);
1361 path = gtk_tree_path_new ();
1362 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1363 path, NULL, new_order);
1364 gtk_tree_path_free (path);
1368 save_positions (GtkSequence *seq)
1370 GHashTable *positions = g_hash_table_new (g_direct_hash, g_direct_equal);
1373 ptr = _gtk_sequence_get_begin_ptr (seq);
1374 while (!_gtk_sequence_ptr_is_end (ptr))
1376 g_hash_table_insert (positions, ptr,
1377 GINT_TO_POINTER (_gtk_sequence_ptr_get_position (ptr)));
1378 ptr = _gtk_sequence_ptr_next (ptr);
1385 generate_order (GtkSequence *seq,
1386 GHashTable *old_positions)
1389 int *order = g_new (int, _gtk_sequence_get_length (seq));
1393 ptr = _gtk_sequence_get_begin_ptr (seq);
1394 while (!_gtk_sequence_ptr_is_end (ptr))
1396 int old_pos = GPOINTER_TO_INT (g_hash_table_lookup (old_positions, ptr));
1397 order[i++] = old_pos;
1398 ptr = _gtk_sequence_ptr_next (ptr);
1401 g_hash_table_destroy (old_positions);
1407 * gtk_list_store_swap:
1408 * @store: A #GtkListStore.
1409 * @a: A #GtkTreeIter.
1410 * @b: Another #GtkTreeIter.
1412 * Swaps @a and @b in @store. Note that this function only works with
1418 gtk_list_store_swap (GtkListStore *store,
1422 GHashTable *old_positions;
1426 g_return_if_fail (GTK_IS_LIST_STORE (store));
1427 g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1428 g_return_if_fail (VALID_ITER (a, store));
1429 g_return_if_fail (VALID_ITER (b, store));
1431 if (a->user_data == b->user_data)
1434 old_positions = save_positions (store->seq);
1436 _gtk_sequence_swap (a->user_data, b->user_data);
1438 order = generate_order (store->seq, old_positions);
1439 path = gtk_tree_path_new ();
1441 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1444 gtk_tree_path_free (path);
1449 gtk_list_store_move_to (GtkListStore *store,
1453 GHashTable *old_positions;
1457 old_positions = save_positions (store->seq);
1459 _gtk_sequence_move (iter->user_data, _gtk_sequence_get_ptr_at_pos (store->seq, new_pos));
1461 order = generate_order (store->seq, old_positions);
1463 path = gtk_tree_path_new ();
1464 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store),
1466 gtk_tree_path_free (path);
1471 * gtk_list_store_move_before:
1472 * @store: A #GtkListStore.
1473 * @iter: A #GtkTreeIter.
1474 * @position: A #GtkTreeIter, or %NULL.
1476 * Moves @iter in @store to the position before @position. Note that this
1477 * function only works with unsorted stores. If @position is %NULL, @iter
1478 * will be moved to the end of the list.
1483 gtk_list_store_move_before (GtkListStore *store,
1485 GtkTreeIter *position)
1489 g_return_if_fail (GTK_IS_LIST_STORE (store));
1490 g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1491 g_return_if_fail (VALID_ITER (iter, store));
1493 g_return_if_fail (VALID_ITER (position, store));
1496 pos = _gtk_sequence_ptr_get_position (position->user_data);
1500 gtk_list_store_move_to (store, iter, pos);
1504 * gtk_list_store_move_after:
1505 * @store: A #GtkListStore.
1506 * @iter: A #GtkTreeIter.
1507 * @position: A #GtkTreeIter or %NULL.
1509 * Moves @iter in @store to the position after @position. Note that this
1510 * function only works with unsorted stores. If @position is %NULL, @iter
1511 * will be moved to the start of the list.
1516 gtk_list_store_move_after (GtkListStore *store,
1518 GtkTreeIter *position)
1522 g_return_if_fail (GTK_IS_LIST_STORE (store));
1523 g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store));
1524 g_return_if_fail (VALID_ITER (iter, store));
1526 g_return_if_fail (VALID_ITER (position, store));
1529 pos = _gtk_sequence_ptr_get_position (position->user_data) + 1;
1533 gtk_list_store_move_to (store, iter, pos);
1538 gtk_list_store_compare_func (gconstpointer a,
1542 GtkListStore *list_store = user_data;
1546 GtkTreeIterCompareFunc func;
1549 if (list_store->sort_column_id != -1)
1551 GtkTreeDataSortHeader *header;
1553 header = _gtk_tree_data_list_get_header (list_store->sort_list,
1554 list_store->sort_column_id);
1555 g_return_val_if_fail (header != NULL, 0);
1556 g_return_val_if_fail (header->func != NULL, 0);
1558 func = header->func;
1559 data = header->data;
1563 g_return_val_if_fail (list_store->default_sort_func != NULL, 0);
1564 func = list_store->default_sort_func;
1565 data = list_store->default_sort_data;
1568 iter_a.stamp = list_store->stamp;
1569 iter_a.user_data = (gpointer)a;
1570 iter_b.stamp = list_store->stamp;
1571 iter_b.user_data = (gpointer)b;
1573 g_assert (VALID_ITER (&iter_a, list_store));
1574 g_assert (VALID_ITER (&iter_b, list_store));
1576 retval = (* func) (GTK_TREE_MODEL (list_store), &iter_a, &iter_b, data);
1578 if (list_store->order == GTK_SORT_DESCENDING)
1582 else if (retval < 0)
1590 gtk_list_store_sort (GtkListStore *list_store)
1594 GHashTable *old_positions;
1596 if (!GTK_LIST_STORE_IS_SORTED (list_store) ||
1597 _gtk_sequence_get_length (list_store->seq) <= 1)
1600 old_positions = save_positions (list_store->seq);
1602 _gtk_sequence_sort (list_store->seq, gtk_list_store_compare_func, list_store);
1604 /* Let the world know about our new order */
1605 new_order = generate_order (list_store->seq, old_positions);
1607 path = gtk_tree_path_new ();
1608 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
1609 path, NULL, new_order);
1610 gtk_tree_path_free (path);
1615 iter_is_sorted (GtkListStore *list_store,
1620 if (!_gtk_sequence_ptr_is_begin (iter->user_data))
1622 cmp = _gtk_sequence_ptr_prev (iter->user_data);
1623 if (gtk_list_store_compare_func (cmp, iter->user_data, list_store) > 0)
1627 cmp = _gtk_sequence_ptr_next (iter->user_data);
1628 if (!_gtk_sequence_ptr_is_end (cmp))
1630 if (gtk_list_store_compare_func (iter->user_data, cmp, list_store) > 0)
1638 gtk_list_store_sort_iter_changed (GtkListStore *list_store,
1645 path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
1646 gtk_tree_model_row_changed (GTK_TREE_MODEL (list_store), path, iter);
1647 gtk_tree_path_free (path);
1649 if (!iter_is_sorted (list_store, iter))
1651 GHashTable *old_positions;
1654 old_positions = save_positions (list_store->seq);
1655 _gtk_sequence_sort_changed (iter->user_data,
1656 gtk_list_store_compare_func,
1658 order = generate_order (list_store->seq, old_positions);
1659 path = gtk_tree_path_new ();
1660 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (list_store),
1662 gtk_tree_path_free (path);
1668 gtk_list_store_get_sort_column_id (GtkTreeSortable *sortable,
1669 gint *sort_column_id,
1672 GtkListStore *list_store = (GtkListStore *) sortable;
1675 * sort_column_id = list_store->sort_column_id;
1677 * order = list_store->order;
1679 if (list_store->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID ||
1680 list_store->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
1687 gtk_list_store_set_sort_column_id (GtkTreeSortable *sortable,
1688 gint sort_column_id,
1691 GtkListStore *list_store = (GtkListStore *) sortable;
1693 if ((list_store->sort_column_id == sort_column_id) &&
1694 (list_store->order == order))
1697 if (sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
1699 if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
1701 GtkTreeDataSortHeader *header = NULL;
1703 header = _gtk_tree_data_list_get_header (list_store->sort_list,
1706 /* We want to make sure that we have a function */
1707 g_return_if_fail (header != NULL);
1708 g_return_if_fail (header->func != NULL);
1712 g_return_if_fail (list_store->default_sort_func != NULL);
1717 list_store->sort_column_id = sort_column_id;
1718 list_store->order = order;
1720 gtk_tree_sortable_sort_column_changed (sortable);
1722 gtk_list_store_sort (list_store);
1726 gtk_list_store_set_sort_func (GtkTreeSortable *sortable,
1727 gint sort_column_id,
1728 GtkTreeIterCompareFunc func,
1730 GtkDestroyNotify destroy)
1732 GtkListStore *list_store = (GtkListStore *) sortable;
1734 list_store->sort_list = _gtk_tree_data_list_set_header (list_store->sort_list,
1736 func, data, destroy);
1738 if (list_store->sort_column_id == sort_column_id)
1739 gtk_list_store_sort (list_store);
1743 gtk_list_store_set_default_sort_func (GtkTreeSortable *sortable,
1744 GtkTreeIterCompareFunc func,
1746 GtkDestroyNotify destroy)
1748 GtkListStore *list_store = (GtkListStore *) sortable;
1750 if (list_store->default_sort_destroy)
1752 GtkDestroyNotify d = list_store->default_sort_destroy;
1754 list_store->default_sort_destroy = NULL;
1755 d (list_store->default_sort_data);
1758 list_store->default_sort_func = func;
1759 list_store->default_sort_data = data;
1760 list_store->default_sort_destroy = destroy;
1762 if (list_store->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
1763 gtk_list_store_sort (list_store);
1767 gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable)
1769 GtkListStore *list_store = (GtkListStore *) sortable;
1771 return (list_store->default_sort_func != NULL);
1776 * gtk_list_store_insert_with_values:
1777 * @list_store: A #GtkListStore
1778 * @iter: An unset #GtkTreeIter to set to the new row, or %NULL.
1779 * @position: position to insert the new row
1780 * @Varargs: pairs of column number and value, terminated with -1
1782 * Creates a new row at @position. @iter will be changed to point to this new
1783 * row. If @position is larger than the number of rows on the list, then the
1784 * new row will be appended to the list. The row will be filled with the
1785 * values given to this function.
1788 * <literal>gtk_list_store_insert_with_values(list_store, iter, position...)</literal>
1789 * has the same effect as calling
1790 * <informalexample><programlisting>
1791 * gtk_list_store_insert (list_store, iter, position);
1792 * gtk_list_store_set (list_store_iter, ...);
1793 * </programlisting></informalexample>
1794 * with the difference that the former will only emit a row_inserted signal,
1795 * while the latter will emit row_inserted, row_changed and, if the list store
1796 * is sorted, rows_reordered. Since emitting the rows_reordered signal
1797 * repeatedly can affect the performance of the program,
1798 * gtk_list_store_insert_with_values() should generally be preferred when
1799 * inserting rows in a sorted list store.
1804 gtk_list_store_insert_with_values (GtkListStore *list_store,
1812 GtkTreeIter tmp_iter;
1814 gboolean changed = FALSE;
1815 gboolean maybe_need_sort = FALSE;
1818 /* FIXME: refactor to reduce overlap with gtk_list_store_set() */
1819 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1824 list_store->columns_dirty = TRUE;
1826 seq = list_store->seq;
1828 length = _gtk_sequence_get_length (seq);
1829 if (position > length)
1832 ptr = _gtk_sequence_get_ptr_at_pos (seq, position);
1833 ptr = _gtk_sequence_insert (ptr, NULL);
1835 iter->stamp = list_store->stamp;
1836 iter->user_data = ptr;
1838 g_assert (VALID_ITER (iter, list_store));
1840 list_store->length++;
1842 va_start (var_args, position);
1843 gtk_list_store_set_valist_internal (list_store, iter,
1844 &changed, &maybe_need_sort,
1848 /* Don't emit rows_reordered here */
1849 if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
1850 _gtk_sequence_sort_changed (iter->user_data,
1851 gtk_list_store_compare_func,
1854 /* Just emit row_inserted */
1855 path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
1856 gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1857 gtk_tree_path_free (path);
1862 * gtk_list_store_insert_with_valuesv:
1863 * @list_store: A #GtkListStore
1864 * @iter: An unset #GtkTreeIter to set to the new row, or %NULL.
1865 * @position: position to insert the new row
1866 * @columns: an array of column numbers
1867 * @values: an array of GValues
1868 * @n_values: the length of the @columns and @values arrays
1870 * A variant of gtk_list_store_insert_with_values() which
1871 * takes the columns and values as two arrays, instead of
1872 * varargs. This function is mainly intended for
1873 * language-bindings.
1878 gtk_list_store_insert_with_valuesv (GtkListStore *list_store,
1888 GtkTreeIter tmp_iter;
1890 gboolean changed = FALSE;
1891 gboolean maybe_need_sort = FALSE;
1892 GtkTreeIterCompareFunc func = NULL;
1895 /* FIXME refactor to reduce overlap with
1896 * gtk_list_store_insert_with_values()
1898 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
1903 list_store->columns_dirty = TRUE;
1905 seq = list_store->seq;
1907 length = _gtk_sequence_get_length (seq);
1908 if (position > length)
1911 ptr = _gtk_sequence_get_ptr_at_pos (seq, position);
1912 ptr = _gtk_sequence_insert (ptr, NULL);
1914 iter->stamp = list_store->stamp;
1915 iter->user_data = ptr;
1917 g_assert (VALID_ITER (iter, list_store));
1919 list_store->length++;
1921 func = gtk_list_store_get_compare_func (list_store);
1922 if (func != _gtk_tree_data_list_compare_func)
1923 maybe_need_sort = TRUE;
1925 for (i = 0; i < n_values; i++)
1927 changed = gtk_list_store_real_set_value (list_store,
1933 if (func == _gtk_tree_data_list_compare_func &&
1934 columns[i] == list_store->sort_column_id)
1935 maybe_need_sort = TRUE;
1938 /* Don't emit rows_reordered here */
1939 if (maybe_need_sort && GTK_LIST_STORE_IS_SORTED (list_store))
1940 _gtk_sequence_sort_changed (iter->user_data,
1941 gtk_list_store_compare_func,
1944 /* Just emit row_inserted */
1945 path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter);
1946 gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter);
1947 gtk_tree_path_free (path);
1950 #define __GTK_LIST_STORE_C__
1951 #include "gtkaliasdef.c"