X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkliststore.c;h=467bac0f15dc4da7b0a98336a01fe22f63952e7c;hb=ea043cab5718304d9b6170afa2d3f959fc99c718;hp=a42daaa1da4eca0c311f16c165dc76ca95ff3cf3;hpb=5f1b5d24067468fc86b28dccc504c71abdaf68b8;p=~andy%2Fgtk diff --git a/gtk/gtkliststore.c b/gtk/gtkliststore.c index a42daaa1d..467bac0f1 100644 --- a/gtk/gtkliststore.c +++ b/gtk/gtkliststore.c @@ -12,9 +12,7 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include "config.h" @@ -31,9 +29,162 @@ #include "gtkbuilderprivate.h" -struct _GtkListStorePriv +/** + * SECTION:gtkliststore + * @Short_description: A list-like data structure that can be used with the GtkTreeView + * @Title: GtkListStore + * @See_also:#GtkTreeModel, #GtkTreeStore + * + * The #GtkListStore object is a list model for use with a #GtkTreeView + * widget. It implements the #GtkTreeModel interface, and consequentialy, + * can use all of the methods available there. It also implements the + * #GtkTreeSortable interface so it can be sorted by the view. + * Finally, it also implements the tree drag and + * drop interfaces. + * + * The #GtkListStore can accept most GObject types as a column type, though + * it can't accept all custom types. Internally, it will keep a copy of + * data passed in (such as a string or a boxed pointer). Columns that + * accept #GObjects are handled a little differently. The + * #GtkListStore will keep a reference to the object instead of copying the + * value. As a result, if the object is modified, it is up to the + * application writer to call gtk_tree_model_row_changed() to emit the + * #GtkTreeModel::row_changed signal. This most commonly affects lists with + * #GdkPixbufs stored. + * + * + * Creating a simple list store. + * + * enum { + * COLUMN_STRING, + * COLUMN_INT, + * COLUMN_BOOLEAN, + * N_COLUMNS + * }; + * + * { + * GtkListStore *list_store; + * GtkTreePath *path; + * GtkTreeIter iter; + * gint i; + * + * list_store = gtk_list_store_new (N_COLUMNS, + * G_TYPE_STRING, + * G_TYPE_INT, + * G_TYPE_BOOLEAN); + * + * for (i = 0; i < 10; i++) + * { + * gchar *some_data; + * + * some_data = get_some_data (i); + * + * // Add a new row to the model + * gtk_list_store_append (list_store, &iter); + * gtk_list_store_set (list_store, &iter, + * COLUMN_STRING, some_data, + * COLUMN_INT, i, + * COLUMN_BOOLEAN, FALSE, + * -1); + * + * /* As the store will keep a copy of the string internally, we + * * free some_data. + * */ + * g_free (some_data); + * } + * + * // Modify a particular row + * path = gtk_tree_path_new_from_string ("4"); + * gtk_tree_model_get_iter (GTK_TREE_MODEL (list_store), + * &iter, + * path); + * gtk_tree_path_free (path); + * gtk_list_store_set (list_store, &iter, + * COLUMN_BOOLEAN, TRUE, + * -1); + * } + * + * + * + * + * Performance Considerations + * Internally, the #GtkListStore was implemented with a linked list with a + * tail pointer prior to GTK+ 2.6. As a result, it was fast at data + * insertion and deletion, and not fast at random data access. The + * #GtkListStore sets the #GTK_TREE_MODEL_ITERS_PERSIST flag, which means + * that #GtkTreeIters can be cached while the row exists. Thus, if + * access to a particular row is needed often and your code is expected to + * run on older versions of GTK+, it is worth keeping the iter around. + * + * + * Atomic Operations + * It is important to note that only the methods + * gtk_list_store_insert_with_values() and gtk_list_store_insert_with_valuesv() + * are atomic, in the sense that the row is being appended to the store and the + * values filled in in a single operation with regard to #GtkTreeModel signaling. + * In contrast, using e.g. gtk_list_store_append() and then gtk_list_store_set() + * will first create a row, which triggers the #GtkTreeModel::row-inserted signal + * on #GtkListStore. The row, however, is still empty, and any signal handler + * connecting to #GtkTreeModel::row-inserted on this particular store should be prepared + * for the situation that the row might be empty. This is especially important + * if you are wrapping the #GtkListStore inside a #GtkTreeModelFilter and are + * using a #GtkTreeModelFilterVisibleFunc. Using any of the non-atomic operations + * to append rows to the #GtkListStore will cause the + * #GtkTreeModelFilterVisibleFunc to be visited with an empty row first; the + * function must be prepared for that. + * + * + * GtkListStore as GtkBuildable + * + * The GtkListStore implementation of the GtkBuildable interface allows + * to specify the model columns with a <columns> element that may + * contain multiple <column> elements, each specifying one model + * column. The "type" attribute specifies the data type for the column. + * + * Additionally, it is possible to specify content for the list store + * in the UI definition, with the <data> element. It can contain + * multiple <row> elements, each specifying to content for one + * row of the list model. Inside a <row>, the <col> elements + * specify the content for individual cells. + * + * Note that it is probably more common to define your models + * in the code, and one might consider it a layering violation + * to specify the content of a list store in a UI definition, + * data, not presentation, + * and common wisdom is to separate the two, as far as possible. + * + * + * + * A UI Definition fragment for a list store + * + * + * + * + * + * + * + * + * John + * Doe + * 25 + * + * + * Johan + * Dahlin + * 50 + * + * + * + * ]]> + * + * + * + */ + + +struct _GtkListStorePrivate { - GtkSortType order; GtkTreeIterCompareFunc default_sort_func; GDestroyNotify default_sort_destroy; @@ -45,6 +196,8 @@ struct _GtkListStorePriv gint sort_column_id; gint length; + GtkSortType order; + guint columns_dirty : 1; gpointer default_sort_data; @@ -52,8 +205,6 @@ struct _GtkListStorePriv }; #define GTK_LIST_STORE_IS_SORTED(list) (((GtkListStore*)(list))->priv->sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID) -#define VALID_ITER(iter, list_store) ((iter)!= NULL && (iter)->user_data != NULL && list_store->priv->stamp == (iter)->stamp && !g_sequence_iter_is_end ((iter)->user_data) && g_sequence_iter_get_sequence ((iter)->user_data) == list_store->priv->seq) - static void gtk_list_store_tree_model_init (GtkTreeModelIface *iface); static void gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface); static void gtk_list_store_drag_dest_init (GtkTreeDragDestIface *iface); @@ -75,6 +226,8 @@ static void gtk_list_store_get_value (GtkTreeModel *tree_mode GValue *value); static gboolean gtk_list_store_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter); +static gboolean gtk_list_store_iter_previous (GtkTreeModel *tree_model, + GtkTreeIter *iter); static gboolean gtk_list_store_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent); @@ -174,7 +327,7 @@ gtk_list_store_class_init (GtkListStoreClass *class) object_class->finalize = gtk_list_store_finalize; - g_type_class_add_private (class, sizeof (GtkListStorePriv)); + g_type_class_add_private (class, sizeof (GtkListStorePrivate)); } static void @@ -187,6 +340,7 @@ gtk_list_store_tree_model_init (GtkTreeModelIface *iface) iface->get_path = gtk_list_store_get_path; iface->get_value = gtk_list_store_get_value; iface->iter_next = gtk_list_store_iter_next; + iface->iter_previous = gtk_list_store_iter_previous; iface->iter_children = gtk_list_store_iter_children; iface->iter_has_child = gtk_list_store_iter_has_child; iface->iter_n_children = gtk_list_store_iter_n_children; @@ -229,11 +383,11 @@ gtk_list_store_buildable_init (GtkBuildableIface *iface) static void gtk_list_store_init (GtkListStore *list_store) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; list_store->priv = G_TYPE_INSTANCE_GET_PRIVATE (list_store, GTK_TYPE_LIST_STORE, - GtkListStorePriv); + GtkListStorePrivate); priv = list_store->priv; priv->seq = g_sequence_new (NULL); @@ -244,21 +398,32 @@ gtk_list_store_init (GtkListStore *list_store) priv->length = 0; } +static gboolean +iter_is_valid (GtkTreeIter *iter, + GtkListStore *list_store) +{ + return iter != NULL && + iter->user_data != NULL && + list_store->priv->stamp == iter->stamp && + !g_sequence_iter_is_end (iter->user_data) && + g_sequence_iter_get_sequence (iter->user_data) == list_store->priv->seq; +} + /** * gtk_list_store_new: * @n_columns: number of columns in the list store - * @Varargs: all #GType types for the columns, from first to last + * @...: all #GType types for the columns, from first to last * * Creates a new list store as with @n_columns columns each of the types passed - * in. Note that only types derived from standard GObject fundamental types - * are supported. + * in. Note that only types derived from standard GObject fundamental types + * are supported. * - * As an example, gtk_tree_store_new (3, G_TYPE_INT, G_TYPE_STRING, + * As an example, gtk_list_store_new (3, G_TYPE_INT, G_TYPE_STRING, * GDK_TYPE_PIXBUF); will create a new #GtkListStore with three columns, of type * int, string and #GdkPixbuf respectively. * * Return value: a new #GtkListStore - **/ + */ GtkListStore * gtk_list_store_new (gint n_columns, ...) @@ -278,11 +443,13 @@ gtk_list_store_new (gint n_columns, { GType type = va_arg (args, GType); if (! _gtk_tree_data_list_check_type (type)) - { - g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type)); - g_object_unref (retval); - return NULL; - } + { + g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type)); + g_object_unref (retval); + va_end (args); + + return NULL; + } gtk_list_store_set_column_type (retval, i, type); } @@ -300,7 +467,8 @@ gtk_list_store_new (gint n_columns, * * Non-vararg creation function. Used primarily by language bindings. * - * Return value: (transfer none): a new #GtkListStore + * Return value: (transfer full): a new #GtkListStore + * Rename to: gtk_list_store_new **/ GtkListStore * gtk_list_store_newv (gint n_columns, @@ -345,7 +513,7 @@ gtk_list_store_set_column_types (GtkListStore *list_store, gint n_columns, GType *types) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; gint i; g_return_if_fail (GTK_IS_LIST_STORE (list_store)); @@ -370,7 +538,7 @@ static void gtk_list_store_set_n_columns (GtkListStore *list_store, gint n_columns) { - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; int i; if (priv->n_columns == n_columns) @@ -391,7 +559,7 @@ gtk_list_store_set_column_type (GtkListStore *list_store, gint column, GType type) { - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; if (!_gtk_tree_data_list_check_type (type)) { @@ -406,7 +574,7 @@ static void gtk_list_store_finalize (GObject *object) { GtkListStore *list_store = GTK_LIST_STORE (object); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; g_sequence_foreach (priv->seq, (GFunc) _gtk_tree_data_list_free, priv->column_headers); @@ -439,7 +607,7 @@ static gint gtk_list_store_get_n_columns (GtkTreeModel *tree_model) { GtkListStore *list_store = GTK_LIST_STORE (tree_model); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; priv->columns_dirty = TRUE; @@ -451,7 +619,7 @@ gtk_list_store_get_column_type (GtkTreeModel *tree_model, gint index) { GtkListStore *list_store = GTK_LIST_STORE (tree_model); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; g_return_val_if_fail (index < priv->n_columns, G_TYPE_INVALID); @@ -466,7 +634,7 @@ gtk_list_store_get_iter (GtkTreeModel *tree_model, GtkTreePath *path) { GtkListStore *list_store = GTK_LIST_STORE (tree_model); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; GSequence *seq; gint i; @@ -477,7 +645,10 @@ gtk_list_store_get_iter (GtkTreeModel *tree_model, i = gtk_tree_path_get_indices (path)[0]; if (i >= g_sequence_get_length (seq)) - return FALSE; + { + iter->stamp = 0; + return FALSE; + } iter->stamp = priv->stamp; iter->user_data = g_sequence_get_iter_at_pos (seq, i); @@ -490,7 +661,7 @@ gtk_list_store_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter) { GtkListStore *list_store = GTK_LIST_STORE (tree_model); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; GtkTreePath *path; g_return_val_if_fail (iter->stamp == priv->stamp, NULL); @@ -511,12 +682,12 @@ gtk_list_store_get_value (GtkTreeModel *tree_model, GValue *value) { GtkListStore *list_store = GTK_LIST_STORE (tree_model); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; GtkTreeDataList *list; gint tmp_column = column; g_return_if_fail (column < priv->n_columns); - g_return_if_fail (VALID_ITER (iter, list_store)); + g_return_if_fail (iter_is_valid (iter, list_store)); list = g_sequence_get (iter->user_data); @@ -536,7 +707,7 @@ gtk_list_store_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter) { GtkListStore *list_store = GTK_LIST_STORE (tree_model); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; gboolean retval; g_return_val_if_fail (priv->stamp == iter->stamp, FALSE); @@ -549,13 +720,33 @@ gtk_list_store_iter_next (GtkTreeModel *tree_model, return !retval; } +static gboolean +gtk_list_store_iter_previous (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + GtkListStore *list_store = GTK_LIST_STORE (tree_model); + GtkListStorePrivate *priv = list_store->priv; + + g_return_val_if_fail (priv->stamp == iter->stamp, FALSE); + + if (g_sequence_iter_is_begin (iter->user_data)) + { + iter->stamp = 0; + return FALSE; + } + + iter->user_data = g_sequence_iter_prev (iter->user_data); + + return TRUE; +} + static gboolean gtk_list_store_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent) { GtkListStore *list_store = (GtkListStore *) tree_model; - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; /* this is a list, nodes have no children */ if (parent) @@ -589,7 +780,7 @@ gtk_list_store_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter) { GtkListStore *list_store = GTK_LIST_STORE (tree_model); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; if (iter == NULL) return g_sequence_get_length (priv->seq); @@ -606,7 +797,7 @@ gtk_list_store_iter_nth_child (GtkTreeModel *tree_model, gint n) { GtkListStore *list_store = GTK_LIST_STORE (tree_model); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; GSequenceIter *child; iter->stamp = 0; @@ -641,18 +832,17 @@ gtk_list_store_real_set_value (GtkListStore *list_store, GValue *value, gboolean sort) { - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; GtkTreeDataList *list; GtkTreeDataList *prev; gint old_column = column; - GValue real_value = {0, }; + GValue real_value = G_VALUE_INIT; gboolean converted = FALSE; gboolean retval = FALSE; if (! g_type_is_a (G_VALUE_TYPE (value), priv->column_headers[column])) { - if (! (g_value_type_compatible (G_VALUE_TYPE (value), priv->column_headers[column]) && - g_value_type_compatible (priv->column_headers[column], G_VALUE_TYPE (value)))) + if (! (g_value_type_transformable (G_VALUE_TYPE (value), priv->column_headers[column]))) { g_warning ("%s: Unable to convert from %s to %s\n", G_STRLOC, @@ -660,6 +850,8 @@ gtk_list_store_real_set_value (GtkListStore *list_store, g_type_name (priv->column_headers[column])); return retval; } + + g_value_init (&real_value, priv->column_headers[column]); if (!g_value_transform (value, &real_value)) { g_warning ("%s: Unable to make conversion from %s to %s\n", @@ -749,10 +941,10 @@ gtk_list_store_set_value (GtkListStore *list_store, gint column, GValue *value) { - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv; g_return_if_fail (GTK_IS_LIST_STORE (list_store)); - g_return_if_fail (VALID_ITER (iter, list_store)); + g_return_if_fail (iter_is_valid (iter, list_store)); g_return_if_fail (G_IS_VALUE (value)); priv = list_store->priv; g_return_if_fail (column >= 0 && column < priv->n_columns); @@ -770,7 +962,7 @@ gtk_list_store_set_value (GtkListStore *list_store, static GtkTreeIterCompareFunc gtk_list_store_get_compare_func (GtkListStore *list_store) { - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; GtkTreeIterCompareFunc func = NULL; if (GTK_LIST_STORE_IS_SORTED (list_store)) @@ -802,7 +994,7 @@ gtk_list_store_set_vector_internal (GtkListStore *list_store, GValue *values, gint n_values) { - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; gint i; GtkTreeIterCompareFunc func = NULL; @@ -831,7 +1023,7 @@ gtk_list_store_set_valist_internal (GtkListStore *list_store, gboolean *maybe_need_sort, va_list var_args) { - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; gint column; GtkTreeIterCompareFunc func = NULL; @@ -843,7 +1035,7 @@ gtk_list_store_set_valist_internal (GtkListStore *list_store, while (column != -1) { - GValue value = { 0, }; + GValue value = G_VALUE_INIT; gchar *error = NULL; if (column < 0 || column >= priv->n_columns) @@ -851,9 +1043,9 @@ gtk_list_store_set_valist_internal (GtkListStore *list_store, g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column); break; } - g_value_init (&value, priv->column_headers[column]); - G_VALUE_COLLECT (&value, var_args, 0, &error); + G_VALUE_COLLECT_INIT (&value, priv->column_headers[column], + var_args, 0, &error); if (error) { g_warning ("%s: %s", G_STRLOC, error); @@ -897,6 +1089,7 @@ gtk_list_store_set_valist_internal (GtkListStore *list_store, * change is not known until run-time. * * Since: 2.12 + * Rename to: gtk_list_store_set */ void gtk_list_store_set_valuesv (GtkListStore *list_store, @@ -905,12 +1098,12 @@ gtk_list_store_set_valuesv (GtkListStore *list_store, GValue *values, gint n_values) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; gboolean emit_signal = FALSE; gboolean maybe_need_sort = FALSE; g_return_if_fail (GTK_IS_LIST_STORE (list_store)); - g_return_if_fail (VALID_ITER (iter, list_store)); + g_return_if_fail (iter_is_valid (iter, list_store)); priv = list_store->priv; @@ -947,12 +1140,12 @@ gtk_list_store_set_valist (GtkListStore *list_store, GtkTreeIter *iter, va_list var_args) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; gboolean emit_signal = FALSE; gboolean maybe_need_sort = FALSE; g_return_if_fail (GTK_IS_LIST_STORE (list_store)); - g_return_if_fail (VALID_ITER (iter, list_store)); + g_return_if_fail (iter_is_valid (iter, list_store)); priv = list_store->priv; @@ -978,7 +1171,7 @@ gtk_list_store_set_valist (GtkListStore *list_store, * gtk_list_store_set: * @list_store: a #GtkListStore * @iter: row iterator - * @Varargs: pairs of column number and value, terminated with -1 + * @...: pairs of column number and value, terminated with -1 * * Sets the value of one or more cells in the row referenced by @iter. * The variable argument list should contain integer column numbers, @@ -986,8 +1179,10 @@ gtk_list_store_set_valist (GtkListStore *list_store, * The list is terminated by a -1. For example, to set column 0 with type * %G_TYPE_STRING to "Foo", you would write gtk_list_store_set (store, iter, * 0, "Foo", -1). - * The value will be copied or referenced by the store if appropriate. - **/ + * + * The value will be referenced by the store if it is a %G_TYPE_OBJECT, and it + * will be copied if it is a %G_TYPE_STRING or %G_TYPE_BOXED. + */ void gtk_list_store_set (GtkListStore *list_store, GtkTreeIter *iter, @@ -1015,12 +1210,12 @@ gboolean gtk_list_store_remove (GtkListStore *list_store, GtkTreeIter *iter) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; GtkTreePath *path; GSequenceIter *ptr, *next; g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE); - g_return_val_if_fail (VALID_ITER (iter, list_store), FALSE); + g_return_val_if_fail (iter_is_valid (iter, list_store), FALSE); priv = list_store->priv; @@ -1054,12 +1249,12 @@ gtk_list_store_remove (GtkListStore *list_store, * gtk_list_store_insert: * @list_store: A #GtkListStore * @iter: (out): An unset #GtkTreeIter to set to the new row - * @position: position to insert the new row + * @position: position to insert the new row, or -1 for last * * Creates a new row at @position. @iter will be changed to point to this new - * row. If @position is larger than the number of rows on the list, then the - * new row will be appended to the list. The row will be empty after this - * function is called. To fill in values, you need to call + * row. If @position is -1 or is larger than the number of rows on the list, + * then the new row will be appended to the list. The row will be empty after + * this function is called. To fill in values, you need to call * gtk_list_store_set() or gtk_list_store_set_value(). * **/ @@ -1068,7 +1263,7 @@ gtk_list_store_insert (GtkListStore *list_store, GtkTreeIter *iter, gint position) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; GtkTreePath *path; GSequence *seq; GSequenceIter *ptr; @@ -1076,7 +1271,6 @@ gtk_list_store_insert (GtkListStore *list_store, g_return_if_fail (GTK_IS_LIST_STORE (list_store)); g_return_if_fail (iter != NULL); - g_return_if_fail (position >= 0); priv = list_store->priv; @@ -1085,7 +1279,7 @@ gtk_list_store_insert (GtkListStore *list_store, seq = priv->seq; length = g_sequence_get_length (seq); - if (position > length) + if (position > length || position < 0) position = length; ptr = g_sequence_get_iter_at_pos (seq, position); @@ -1094,7 +1288,7 @@ gtk_list_store_insert (GtkListStore *list_store, iter->stamp = priv->stamp; iter->user_data = ptr; - g_assert (VALID_ITER (iter, list_store)); + g_assert (iter_is_valid (iter, list_store)); priv->length++; @@ -1121,7 +1315,7 @@ gtk_list_store_insert_before (GtkListStore *list_store, GtkTreeIter *iter, GtkTreeIter *sibling) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; GSequenceIter *after; g_return_if_fail (GTK_IS_LIST_STORE (list_store)); @@ -1130,7 +1324,7 @@ gtk_list_store_insert_before (GtkListStore *list_store, priv = list_store->priv; if (sibling) - g_return_if_fail (VALID_ITER (sibling, list_store)); + g_return_if_fail (iter_is_valid (sibling, list_store)); if (!sibling) after = g_sequence_get_end_iter (priv->seq); @@ -1157,7 +1351,7 @@ gtk_list_store_insert_after (GtkListStore *list_store, GtkTreeIter *iter, GtkTreeIter *sibling) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; GSequenceIter *after; g_return_if_fail (GTK_IS_LIST_STORE (list_store)); @@ -1166,7 +1360,7 @@ gtk_list_store_insert_after (GtkListStore *list_store, priv = list_store->priv; if (sibling) - g_return_if_fail (VALID_ITER (sibling, list_store)); + g_return_if_fail (iter_is_valid (sibling, list_store)); if (!sibling) after = g_sequence_get_begin_iter (priv->seq); @@ -1210,20 +1404,16 @@ void gtk_list_store_append (GtkListStore *list_store, GtkTreeIter *iter) { - GtkListStorePriv *priv; - g_return_if_fail (GTK_IS_LIST_STORE (list_store)); g_return_if_fail (iter != NULL); - priv = list_store->priv; - - gtk_list_store_insert (list_store, iter, g_sequence_get_length (priv->seq)); + gtk_list_store_insert (list_store, iter, -1); } static void gtk_list_store_increment_stamp (GtkListStore *list_store) { - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; do { @@ -1242,7 +1432,7 @@ gtk_list_store_increment_stamp (GtkListStore *list_store) void gtk_list_store_clear (GtkListStore *list_store) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; GtkTreeIter iter; g_return_if_fail (GTK_IS_LIST_STORE (list_store)); @@ -1277,20 +1467,10 @@ gboolean gtk_list_store_iter_is_valid (GtkListStore *list_store, GtkTreeIter *iter) { - GtkListStorePriv *priv; - g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), FALSE); g_return_val_if_fail (iter != NULL, FALSE); - priv = list_store->priv; - - if (!VALID_ITER (iter, list_store)) - return FALSE; - - if (g_sequence_iter_get_sequence (iter->user_data) != priv->seq) - return FALSE; - - return TRUE; + return iter_is_valid (iter, list_store); } static gboolean real_gtk_list_store_row_draggable (GtkTreeDragSource *drag_source, @@ -1347,7 +1527,7 @@ gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest, { GtkTreeModel *tree_model = GTK_TREE_MODEL (drag_dest); GtkListStore *list_store = GTK_LIST_STORE (tree_model); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; GtkTreeModel *src_model = NULL; GtkTreePath *src_path = NULL; gboolean retval = FALSE; @@ -1508,9 +1688,10 @@ gtk_list_store_reorder_func (GSequenceIter *a, /** * gtk_list_store_reorder: * @store: A #GtkListStore. - * @new_order: an array of integers mapping the new position of each child - * to its old position before the re-ordering, - * i.e. @new_order[newpos] = oldpos. + * @new_order: (array zero-terminated=1): an array of integers mapping the new + * position of each child to its old position before the re-ordering, + * i.e. @new_order[newpos] = oldpos. It must have + * exactly as many items as the list store's length. * * Reorders @store to follow the order indicated by @new_order. Note that * this function only works with unsorted stores. @@ -1521,7 +1702,7 @@ void gtk_list_store_reorder (GtkListStore *store, gint *new_order) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; gint i; GtkTreePath *path; GHashTable *new_positions; @@ -1616,15 +1797,15 @@ gtk_list_store_swap (GtkListStore *store, GtkTreeIter *a, GtkTreeIter *b) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; GHashTable *old_positions; gint *order; GtkTreePath *path; g_return_if_fail (GTK_IS_LIST_STORE (store)); g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store)); - g_return_if_fail (VALID_ITER (a, store)); - g_return_if_fail (VALID_ITER (b, store)); + g_return_if_fail (iter_is_valid (a, store)); + g_return_if_fail (iter_is_valid (b, store)); priv = store->priv; @@ -1650,7 +1831,7 @@ gtk_list_store_move_to (GtkListStore *store, GtkTreeIter *iter, gint new_pos) { - GtkListStorePriv *priv = store->priv; + GtkListStorePrivate *priv = store->priv; GHashTable *old_positions; GtkTreePath *path; gint *order; @@ -1689,9 +1870,9 @@ gtk_list_store_move_before (GtkListStore *store, g_return_if_fail (GTK_IS_LIST_STORE (store)); g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store)); - g_return_if_fail (VALID_ITER (iter, store)); + g_return_if_fail (iter_is_valid (iter, store)); if (position) - g_return_if_fail (VALID_ITER (position, store)); + g_return_if_fail (iter_is_valid (position, store)); if (position) pos = g_sequence_iter_get_position (position->user_data); @@ -1722,9 +1903,9 @@ gtk_list_store_move_after (GtkListStore *store, g_return_if_fail (GTK_IS_LIST_STORE (store)); g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store)); - g_return_if_fail (VALID_ITER (iter, store)); + g_return_if_fail (iter_is_valid (iter, store)); if (position) - g_return_if_fail (VALID_ITER (position, store)); + g_return_if_fail (iter_is_valid (position, store)); if (position) pos = g_sequence_iter_get_position (position->user_data) + 1; @@ -1741,7 +1922,7 @@ gtk_list_store_compare_func (GSequenceIter *a, gpointer user_data) { GtkListStore *list_store = user_data; - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; GtkTreeIter iter_a; GtkTreeIter iter_b; gint retval; @@ -1772,17 +1953,17 @@ gtk_list_store_compare_func (GSequenceIter *a, iter_b.stamp = priv->stamp; iter_b.user_data = (gpointer)b; - g_assert (VALID_ITER (&iter_a, list_store)); - g_assert (VALID_ITER (&iter_b, list_store)); - + g_assert (iter_is_valid (&iter_a, list_store)); + g_assert (iter_is_valid (&iter_b, list_store)); + retval = (* func) (GTK_TREE_MODEL (list_store), &iter_a, &iter_b, data); if (priv->order == GTK_SORT_DESCENDING) { if (retval > 0) - retval = -1; + retval = -1; else if (retval < 0) - retval = 1; + retval = 1; } return retval; @@ -1791,7 +1972,7 @@ gtk_list_store_compare_func (GSequenceIter *a, static void gtk_list_store_sort (GtkListStore *list_store) { - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; gint *new_order; GtkTreePath *path; GHashTable *old_positions; @@ -1843,7 +2024,7 @@ gtk_list_store_sort_iter_changed (GtkListStore *list_store, gint column) { - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; GtkTreePath *path; path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter); @@ -1874,7 +2055,7 @@ gtk_list_store_get_sort_column_id (GtkTreeSortable *sortable, GtkSortType *order) { GtkListStore *list_store = GTK_LIST_STORE (sortable); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; if (sort_column_id) * sort_column_id = priv->sort_column_id; @@ -1894,7 +2075,7 @@ gtk_list_store_set_sort_column_id (GtkTreeSortable *sortable, GtkSortType order) { GtkListStore *list_store = GTK_LIST_STORE (sortable); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; if ((priv->sort_column_id == sort_column_id) && (priv->order == order)) @@ -1936,7 +2117,7 @@ gtk_list_store_set_sort_func (GtkTreeSortable *sortable, GDestroyNotify destroy) { GtkListStore *list_store = GTK_LIST_STORE (sortable); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; priv->sort_list = _gtk_tree_data_list_set_header (priv->sort_list, sort_column_id, @@ -1953,7 +2134,7 @@ gtk_list_store_set_default_sort_func (GtkTreeSortable *sortable, GDestroyNotify destroy) { GtkListStore *list_store = GTK_LIST_STORE (sortable); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; if (priv->default_sort_destroy) { @@ -1975,7 +2156,7 @@ static gboolean gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable) { GtkListStore *list_store = GTK_LIST_STORE (sortable); - GtkListStorePriv *priv = list_store->priv; + GtkListStorePrivate *priv = list_store->priv; return (priv->default_sort_func != NULL); } @@ -1984,18 +2165,19 @@ gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable) /** * gtk_list_store_insert_with_values: * @list_store: A #GtkListStore - * @iter: (out) (allow-none): An unset #GtkTreeIter to set to the new row, or %NULL. - * @position: position to insert the new row - * @Varargs: pairs of column number and value, terminated with -1 + * @iter: (out) (allow-none): An unset #GtkTreeIter to set to the new row, or %NULL + * @position: position to insert the new row, or -1 to append after existing + * rows + * @...: pairs of column number and value, terminated with -1 + * + * Creates a new row at @position. @iter will be changed to point to this new + * row. If @position is -1, or larger than the number of rows in the list, then + * the new row will be appended to the list. The row will be filled with the + * values given to this function. * - * Creates a new row at @position. @iter will be changed to point to this new - * row. If @position is larger than the number of rows on the list, then the - * new row will be appended to the list. The row will be filled with the - * values given to this function. - * * Calling - * gtk_list_store_insert_with_values(list_store, iter, position...) - * has the same effect as calling + * gtk_list_store_insert_with_values (list_store, iter, position...) + * has the same effect as calling * |[ * gtk_list_store_insert (list_store, iter, position); * gtk_list_store_set (list_store, iter, ...); @@ -2003,7 +2185,7 @@ gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable) * with the difference that the former will only emit a row_inserted signal, * while the latter will emit row_inserted, row_changed and, if the list store * is sorted, rows_reordered. Since emitting the rows_reordered signal - * repeatedly can affect the performance of the program, + * repeatedly can affect the performance of the program, * gtk_list_store_insert_with_values() should generally be preferred when * inserting rows in a sorted list store. * @@ -2015,7 +2197,7 @@ gtk_list_store_insert_with_values (GtkListStore *list_store, gint position, ...) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; GtkTreePath *path; GSequence *seq; GSequenceIter *ptr; @@ -2038,7 +2220,7 @@ gtk_list_store_insert_with_values (GtkListStore *list_store, seq = priv->seq; length = g_sequence_get_length (seq); - if (position > length) + if (position > length || position < 0) position = length; ptr = g_sequence_get_iter_at_pos (seq, position); @@ -2047,7 +2229,7 @@ gtk_list_store_insert_with_values (GtkListStore *list_store, iter->stamp = priv->stamp; iter->user_data = ptr; - g_assert (VALID_ITER (iter, list_store)); + g_assert (iter_is_valid (iter, list_store)); priv->length++; @@ -2074,9 +2256,9 @@ gtk_list_store_insert_with_values (GtkListStore *list_store, * gtk_list_store_insert_with_valuesv: * @list_store: A #GtkListStore * @iter: (out) (allow-none): An unset #GtkTreeIter to set to the new row, or %NULL. - * @position: position to insert the new row - * @columns: an array of column numbers - * @values: an array of GValues + * @position: position to insert the new row, or -1 for last + * @columns: (array length=n_values): an array of column numbers + * @values: (array length=n_values): an array of GValues * @n_values: the length of the @columns and @values arrays * * A variant of gtk_list_store_insert_with_values() which @@ -2094,7 +2276,7 @@ gtk_list_store_insert_with_valuesv (GtkListStore *list_store, GValue *values, gint n_values) { - GtkListStorePriv *priv; + GtkListStorePrivate *priv; GtkTreePath *path; GSequence *seq; GSequenceIter *ptr; @@ -2118,7 +2300,7 @@ gtk_list_store_insert_with_valuesv (GtkListStore *list_store, seq = priv->seq; length = g_sequence_get_length (seq); - if (position > length) + if (position > length || position < 0) position = length; ptr = g_sequence_get_iter_at_pos (seq, position); @@ -2127,7 +2309,7 @@ gtk_list_store_insert_with_valuesv (GtkListStore *list_store, iter->stamp = priv->stamp; iter->user_data = ptr; - g_assert (VALID_ITER (iter, list_store)); + g_assert (iter_is_valid (iter, list_store)); priv->length++; @@ -2255,10 +2437,12 @@ list_store_start_element (GMarkupParseContext *context, else if (strcmp (element_name, "row") == 0) ; else if (strcmp (element_name, "column") == 0) - for (i = 0; names[i]; i++) - if (strcmp (names[i], "type") == 0) - data->column_type_names = g_slist_prepend (data->column_type_names, - g_strdup (values[i])); + { + for (i = 0; names[i]; i++) + if (strcmp (names[i], "type") == 0) + data->column_type_names = g_slist_prepend (data->column_type_names, + g_strdup (values[i])); + } else if (strcmp (element_name, "columns") == 0) ; else if (strcmp (element_name, "data") == 0)