4 * An OpenGL based 'interactive canvas' library.
6 * Authored By Matthew Allum <mallum@openedhand.com>
7 * Neil Jagdish Patel <njp@o-hand.com>
8 * Emmanuele Bassi <ebassi@openedhand.com>
10 * Copyright (C) 2006 OpenedHand
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
27 * NB: Inspiration for column storage taken from GtkListStore
31 * SECTION:clutter-model
32 * @short_description: A generic model implementation
34 * #ClutterModel is a generic list model API which can be used to implement
35 * the model-view-controller architectural pattern in Clutter.
37 * The #ClutterModel class is a list model which can accept most GObject
38 * types as a column type.
40 * Creating a simple clutter model:
41 * <informalexample><programlisting>
51 * ClutterModel *model;
54 * model = clutter_model_default_new (N_COLUMNS,
55 * /<!-- -->* column type, column title *<!-- -->/
56 * G_TYPE_INT, "my integers",
57 * G_TYPE_STRING, "my strings");
58 * for (i = 0; i < 10; i++)
60 * gchar *string = g_strdup_printf ("String %d", i);
61 * clutter_model_append (model,
63 * COLUMN_STRING, string,
70 * </programlisting></informalexample>
72 * Iterating through the model consists of retrieving a new #ClutterModelIter
73 * pointing to the starting row, and calling clutter_model_iter_next() or
74 * clutter_model_iter_prev() to move forward or backwards, repectively.
76 * A valid #ClutterModelIter represents the position between two rows in the
77 * model. For example, the "first" iterator represents the gap immediately
78 * before the first row, and the "last" iterator represents the gap immediately
79 * after the last row. In an empty sequence, the first and last iterators are
82 * Iterating a #ClutterModel:
83 * <informalexample><programlisting>
93 * ClutterModel *model;
94 * ClutterModelIter *iter = NULL;
96 * /<!-- -->* Fill the model *<!-- -->/
97 * model = populate_model ();
99 * /<!-- -->* Get the first iter *<!-- -->/
100 * iter = clutter_model_get_first_iter (model);
101 * while (!clutter_model_iter_is_last (iter))
105 * iter = clutter_model_iter_next (iter);
108 * /<!-- -->* Make sure to unref the iter *<!-- -->/
109 * g_object_unref (iter);
111 * </programlisting></informalexample>
113 * #ClutterModel is an abstract class. Clutter provides a list model
114 * implementation called #ClutterListModel which has been optimised
115 * for insertion and look up in sorted lists.
117 * <refsect2 id="ClutterModel-script">
118 * <title>ClutterModel custom properties for #ClutterScript</title>
119 * <para>#ClutterModel defines a custom property "columns" for #ClutterScript
120 * which allows defining the column names and types. It also defines a custom
121 * "rows" property which allows filling the #ClutterModel with some
123 * <example id="ClutterModel-script-example">
124 * <title>Example of the "columns" and "rows" custom properties</title>
125 * <para>The definition below will create a #ClutterListModel with three
126 * columns: the first one with name "Name" and containing strings; the
127 * second one with name "Score" and containing integers; the third one with
128 * name "Icon" and containing #ClutterTexture<!-- -->s. The model is filled
129 * with three rows. A row can be defined either with an array that holds
130 * all columns of a row, or an object that holds "column-name" :
131 * "column-value" pairs.
135 * "type" : "ClutterListModel",
136 * "id" : "teams-model",
138 * [ "Name", "gchararray" ],
139 * [ "Score", "gint" ],
140 * [ "Icon", "ClutterTexture" ]
143 * [ "Team 1", 42, { "type" : "ClutterTexture", "filename" : "team1.png" } ],
144 * [ "Team 2", 23, "team2-icon-script-id" ],
145 * { "Name" : "Team 3", "Icon" : "team3-icon-script-id" }
152 * #ClutterModel is available since Clutter 0.6
161 #include <glib-object.h>
162 #include <gobject/gvaluecollector.h>
164 #include "clutter-model.h"
165 #include "clutter-model-private.h"
167 #include "clutter-marshal.h"
168 #include "clutter-private.h"
169 #include "clutter-debug.h"
170 #include "clutter-scriptable.h"
171 #include "clutter-script-private.h"
173 static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
175 G_DEFINE_ABSTRACT_TYPE_WITH_CODE
176 (ClutterModel, clutter_model, G_TYPE_OBJECT,
177 G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE,
178 clutter_scriptable_iface_init));
199 static guint model_signals[LAST_SIGNAL] = { 0, };
201 #define CLUTTER_MODEL_GET_PRIVATE(obj) \
202 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_MODEL, ClutterModelPrivate))
204 struct _ClutterModelPrivate
207 gchar **column_names;
209 /* we use an integer here because we want to be able to use -1 as a
210 * guard value, to allow calling set_names() and set_types() from
211 * sub-classes of ClutterModel. see bug:
213 * http://bugzilla.openedhand.com/show_bug.cgi?id=2032
219 ClutterModelFilterFunc filter_func;
220 gpointer filter_data;
221 GDestroyNotify filter_notify;
224 ClutterModelSortFunc sort_func;
226 GDestroyNotify sort_notify;
230 clutter_model_real_get_column_type (ClutterModel *model,
233 ClutterModelPrivate *priv = model->priv;
235 if (column >= clutter_model_get_n_columns (model))
236 return G_TYPE_INVALID;
238 return priv->column_types[column];
242 clutter_model_real_get_column_name (ClutterModel *model,
245 ClutterModelPrivate *priv = model->priv;
247 if (column >= clutter_model_get_n_columns (model))
250 if (priv->column_names && priv->column_names[column])
251 return priv->column_names[column];
253 return g_type_name (priv->column_types[column]);
257 clutter_model_real_get_n_columns (ClutterModel *model)
259 ClutterModelPrivate *priv = model->priv;
261 if (priv->n_columns < 0)
264 return priv->n_columns;
268 clutter_model_real_get_n_rows (ClutterModel *model)
270 ClutterModelIter *iter;
273 g_return_val_if_fail (CLUTTER_IS_MODEL (model), 0);
275 iter = clutter_model_get_first_iter (model);
280 while (!clutter_model_iter_is_last (iter))
282 if (clutter_model_filter_iter (model, iter))
285 iter = clutter_model_iter_next (iter);
288 g_object_unref (iter);
294 clutter_model_finalize (GObject *object)
296 ClutterModelPrivate *priv = CLUTTER_MODEL (object)->priv;
299 if (priv->sort_notify)
300 priv->sort_notify (priv->sort_data);
302 if (priv->filter_notify)
303 priv->filter_notify (priv->filter_data);
305 g_free (priv->column_types);
307 if (priv->column_names != NULL)
309 /* the column_names vector might have holes in it, so we need
310 * to use the columns number to clear up everything
312 for (i = 0; i < priv->n_columns; i++)
313 g_free (priv->column_names[i]);
315 g_free (priv->column_names);
318 G_OBJECT_CLASS (clutter_model_parent_class)->finalize (object);
322 clutter_model_get_property (GObject *gobject,
327 ClutterModelPrivate *priv = CLUTTER_MODEL (gobject)->priv;
331 case PROP_FILTER_SET:
332 g_value_set_boolean (value, priv->filter_func != NULL);
336 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
342 clutter_model_class_init (ClutterModelClass *klass)
344 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
347 gobject_class->get_property = clutter_model_get_property;
348 gobject_class->finalize = clutter_model_finalize;
350 g_type_class_add_private (gobject_class, sizeof (ClutterModelPrivate));
352 klass->get_column_name = clutter_model_real_get_column_name;
353 klass->get_column_type = clutter_model_real_get_column_type;
354 klass->get_n_columns = clutter_model_real_get_n_columns;
355 klass->get_n_rows = clutter_model_real_get_n_rows;
358 * ClutterModel:filter-set:
360 * Whether the #ClutterModel has a filter set
362 * This property is set to %TRUE if a filter function has been
363 * set using clutter_model_set_filter()
367 pspec = g_param_spec_boolean ("filter-set",
369 "Whether the model has a filter",
371 CLUTTER_PARAM_READABLE);
372 g_object_class_install_property (gobject_class, PROP_FILTER_SET, pspec);
375 * ClutterModel::row-added:
376 * @model: the #ClutterModel on which the signal is emitted
377 * @iter: a #ClutterModelIter pointing to the new row
379 * The ::row-added signal is emitted when a new row has been added.
380 * The data on the row has already been set when the ::row-added signal
385 model_signals[ROW_ADDED] =
386 g_signal_new ("row-added",
387 G_TYPE_FROM_CLASS (gobject_class),
389 G_STRUCT_OFFSET (ClutterModelClass, row_added),
391 _clutter_marshal_VOID__OBJECT,
393 CLUTTER_TYPE_MODEL_ITER);
395 * ClutterModel::row-removed:
396 * @model: the #ClutterModel on which the signal is emitted
397 * @iter: a #ClutterModelIter pointing to the removed row
399 * The ::row-removed signal is emitted when a row has been removed.
400 * The data on the row pointed by the passed iterator is still valid
401 * when the ::row-removed signal has been emitted.
405 model_signals[ROW_REMOVED] =
406 g_signal_new ("row-removed",
407 G_TYPE_FROM_CLASS (gobject_class),
409 G_STRUCT_OFFSET (ClutterModelClass, row_removed),
411 _clutter_marshal_VOID__OBJECT,
413 CLUTTER_TYPE_MODEL_ITER);
415 * ClutterModel::row-changed:
416 * @model: the #ClutterModel on which the signal is emitted
417 * @iter: a #ClutterModelIter pointing to the changed row
419 * The ::row-removed signal is emitted when a row has been changed.
420 * The data on the row has already been updated when the ::row-changed
421 * signal has been emitted.
425 model_signals[ROW_CHANGED] =
426 g_signal_new ("row-changed",
427 G_TYPE_FROM_CLASS (gobject_class),
429 G_STRUCT_OFFSET (ClutterModelClass, row_changed),
431 _clutter_marshal_VOID__OBJECT,
433 CLUTTER_TYPE_MODEL_ITER);
435 * ClutterModel::sort-changed:
436 * @model: the #ClutterModel on which the signal is emitted
438 * The ::sort-changed signal is emitted after the model has been sorted
442 model_signals[SORT_CHANGED] =
443 g_signal_new ("sort-changed",
444 G_TYPE_FROM_CLASS (gobject_class),
446 G_STRUCT_OFFSET (ClutterModelClass, sort_changed),
448 _clutter_marshal_VOID__VOID,
451 * ClutterModel::filter-changed:
452 * @model: the #ClutterModel on which the signal is emitted
454 * The ::filter-changed signal is emitted when a new filter has been applied
458 model_signals[FILTER_CHANGED] =
459 g_signal_new ("filter-changed",
460 G_TYPE_FROM_CLASS (gobject_class),
462 G_STRUCT_OFFSET (ClutterModelClass, filter_changed),
464 _clutter_marshal_VOID__VOID,
469 clutter_model_init (ClutterModel *self)
471 ClutterModelPrivate *priv;
473 self->priv = priv = CLUTTER_MODEL_GET_PRIVATE (self);
475 priv->n_columns = -1;
476 priv->column_types = NULL;
477 priv->column_names = NULL;
479 priv->filter_func = NULL;
480 priv->filter_data = NULL;
481 priv->filter_notify = NULL;
483 priv->sort_column = -1;
484 priv->sort_func = NULL;
485 priv->sort_data = NULL;
486 priv->sort_notify = NULL;
489 /* XXX - is this whitelist really necessary? we accept every fundamental
493 _clutter_model_check_type (GType gtype)
496 static const GType type_list[] =
518 if (! G_TYPE_IS_VALUE_TYPE (gtype))
521 while (type_list[i] != G_TYPE_INVALID)
523 if (g_type_is_a (gtype, type_list[i]))
537 clutter_model_parse_custom_node (ClutterScriptable *scriptable,
538 ClutterScript *script,
543 if (strcmp (name, "columns") == 0)
545 GSList *columns = NULL;
548 if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY)
551 elements = json_array_get_elements (json_node_get_array (node));
553 for (l = elements; l != NULL; l = l->next)
555 JsonNode *child_node = l->data;
556 JsonArray *array = json_node_get_array (child_node);
558 const gchar *column_name;
559 const gchar *type_name;
561 if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY ||
562 json_array_get_length (array) != 2)
564 g_warning ("A column must be an array of "
565 "[\"column-name\", \"GType-name\"] pairs");
569 column_name = json_array_get_string_element (array, 0);
570 type_name = json_array_get_string_element (array, 1);
572 cinfo = g_slice_new0 (ColumnInfo);
573 cinfo->name = g_strdup (column_name);
574 cinfo->type = clutter_script_get_type_from_name (script, type_name);
576 columns = g_slist_prepend (columns, cinfo);
579 g_list_free (elements);
581 g_value_init (value, G_TYPE_POINTER);
582 g_value_set_pointer (value, g_slist_reverse (columns));
586 else if (strcmp (name, "rows") == 0)
591 if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY)
595 * at this point we have no information about the column types, so
596 * we just copy the json elements and resolve them in the
597 * set_custom_property method
599 elements = json_array_get_elements (json_node_get_array (node));
600 for (l = elements; l != NULL; l = l->next)
601 rows = g_slist_prepend (rows, json_node_copy (l->data));
602 g_list_free (elements);
604 g_value_init (value, G_TYPE_POINTER);
605 g_value_set_pointer (value, g_slist_reverse (rows));
613 clutter_model_set_custom_property (ClutterScriptable *scriptable,
614 ClutterScript *script,
618 if (strcmp (name, "columns") == 0)
620 ClutterModel *model = CLUTTER_MODEL (scriptable);
625 columns = g_value_get_pointer (value);
626 n_columns = g_slist_length (columns);
628 _clutter_model_set_n_columns (model, n_columns, TRUE, TRUE);
630 for (i = 0, l = columns; l != NULL; l = l->next, i++)
632 ColumnInfo *cinfo = l->data;
634 _clutter_model_set_column_name (model, i, cinfo->name);
635 _clutter_model_set_column_type (model, i, cinfo->type);
637 g_free (cinfo->name);
638 g_slice_free (ColumnInfo, cinfo);
641 g_slist_free (columns);
643 else if (strcmp (name, "rows") == 0)
645 ClutterModel *model = CLUTTER_MODEL (scriptable);
647 guint n_columns, row = 0;
649 rows = g_value_get_pointer (value);
650 n_columns = clutter_model_get_n_columns (model);
652 for (l = rows; l; l = l->next)
654 JsonNode *node = l->data;
655 guint *columns = NULL, i, n_values = 0;
656 GValue *values = NULL;
658 if (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY)
660 JsonArray *array = json_node_get_array (node);
662 if (json_array_get_length (array) != n_columns)
664 g_warning ("Row %d contains the wrong count of columns",
665 g_slist_position (rows, l) + 1);
670 /* array more requires all columns */
671 n_values = n_columns;
673 columns = g_new (guint, n_values);
674 values = g_new0 (GValue, n_values);
676 for (i = 0; i < n_values; i++)
679 const gchar *column_name;
681 column_type = clutter_model_get_column_type (model, i);
682 column_name = clutter_model_get_column_name (model, i);
685 g_value_init (&values[i], column_type);
687 _clutter_script_parse_node (script, &values[i], column_name,
688 json_array_get_element (array, i),
692 else if (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT)
694 JsonObject *object = json_node_get_object (node);
698 /* object mode does not require all columns */
699 n_values = json_object_get_size (object);
701 columns = g_new (guint, n_values);
702 values = g_new0 (GValue, n_values);
704 members = json_object_get_members (object);
705 for (m = members; m; m = m->next)
707 const gchar *mname = m->data;
709 for (i = 0; i < clutter_model_get_n_columns (model); i++)
713 cname = clutter_model_get_column_name (model, i);
714 if (strcmp (mname, cname) == 0)
718 const gchar *col_name;
720 member = json_object_get_member (object, mname);
722 col_type = clutter_model_get_column_type (model, i);
723 col_name = clutter_model_get_column_name (model, i);
726 g_value_init (&values[column], col_type);
728 _clutter_script_parse_node (script, &values[column],
744 clutter_model_insertv (model, row, n_values, columns, values);
748 json_node_free (node);
758 clutter_scriptable_iface_init (ClutterScriptableIface *iface)
760 iface->parse_custom_node = clutter_model_parse_custom_node;
761 iface->set_custom_property = clutter_model_set_custom_property;
765 * clutter_model_resort:
766 * @model: a #ClutterModel
768 * Force a resort on the @model. This function should only be
769 * used by subclasses of #ClutterModel.
774 clutter_model_resort (ClutterModel *model)
776 ClutterModelPrivate *priv;
777 ClutterModelClass *klass;
779 g_return_if_fail (CLUTTER_IS_MODEL (model));
782 klass = CLUTTER_MODEL_GET_CLASS (model);
785 klass->resort (model, priv->sort_func, priv->sort_data);
789 * clutter_model_filter_row:
790 * @model: a #ClutterModel
791 * @row: the row to filter
793 * Checks whether @row should be filtered or not using the
794 * filtering function set on @model.
796 * This function should be used only by subclasses of #ClutterModel.
798 * Return value: %TRUE if the row should be displayed,
804 clutter_model_filter_row (ClutterModel *model,
807 ClutterModelPrivate *priv;
808 ClutterModelIter *iter;
811 g_return_val_if_fail (CLUTTER_IS_MODEL (model), TRUE);
815 if (!priv->filter_func)
818 iter = clutter_model_get_iter_at_row (model, row);
822 res = priv->filter_func (model, iter, priv->filter_data);
824 g_object_unref (iter);
830 * clutter_model_filter_iter:
831 * @model: a #ClutterModel
832 * @iter: the row to filter
834 * Checks whether the row pointer by @iter should be filtered or not using
835 * the filtering function set on @model.
837 * This function should be used only by subclasses of #ClutterModel.
839 * Return value: %TRUE if the row should be displayed,
845 clutter_model_filter_iter (ClutterModel *model,
846 ClutterModelIter *iter)
848 ClutterModelPrivate *priv;
850 g_return_val_if_fail (CLUTTER_IS_MODEL (model), TRUE);
851 g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), TRUE);
855 if (!priv->filter_func)
858 return priv->filter_func (model, iter, priv->filter_data);
862 * clutter_model_set_n_columns:
863 * @model: a #ClutterModel
864 * @n_columns: number of columns
865 * @set_types: set the columns type
866 * @set_names: set the columns name
868 * Sets the number of columns in @model to @n_columns. If @set_types
869 * or @set_names are %TRUE, initialises the columns type and name
872 * This function can only be called once.
875 _clutter_model_set_n_columns (ClutterModel *model,
880 ClutterModelPrivate *priv = model->priv;
882 if (priv->n_columns > 0 && priv->n_columns != n_columns)
885 priv->n_columns = n_columns;
887 if (set_types && !priv->column_types)
888 priv->column_types = g_new0 (GType, n_columns);
890 if (set_names && !priv->column_names)
891 priv->column_names = g_new0 (gchar*, n_columns);
895 * _clutter_model_set_column_type:
896 * @model: a #ClutterModel
897 * @column: column index
898 * @gtype: type of the column
900 * Sets the type of @column inside @model
903 _clutter_model_set_column_type (ClutterModel *model,
907 ClutterModelPrivate *priv = model->priv;
909 priv->column_types[column] = gtype;
913 * _clutter_model_set_column_name:
914 * @model: a #ClutterModel
915 * @column: column index
916 * @name: name of the column, or %NULL
918 * Sets the name of @column inside @model
921 _clutter_model_set_column_name (ClutterModel *model,
925 ClutterModelPrivate *priv = model->priv;
927 priv->column_names[column] = g_strdup (name);
931 * clutter_model_set_types:
932 * @model: a #ClutterModel
933 * @n_columns: number of columns for the model
934 * @types: (array length=n_columns): an array of #GType types
936 * Sets the types of the columns inside a #ClutterModel.
938 * This function is meant primarily for #GObjects that inherit from
939 * #ClutterModel, and should only be used when contructing a #ClutterModel.
940 * It will not work after the initial creation of the #ClutterModel.
945 clutter_model_set_types (ClutterModel *model,
949 ClutterModelPrivate *priv;
952 g_return_if_fail (CLUTTER_IS_MODEL (model));
953 g_return_if_fail (n_columns > 0);
957 g_return_if_fail (priv->n_columns < 0 || priv->n_columns == n_columns);
958 g_return_if_fail (priv->column_types == NULL);
960 _clutter_model_set_n_columns (model, n_columns, TRUE, FALSE);
962 for (i = 0; i < n_columns; i++)
964 if (!_clutter_model_check_type (types[i]))
966 g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i]));
970 _clutter_model_set_column_type (model, i, types[i]);
975 * clutter_model_set_names:
976 * @model: a #ClutterModel
977 * @n_columns: the number of column names
978 * @names: (array length=n_columns): an array of strings
980 * Assigns a name to the columns of a #ClutterModel.
982 * This function is meant primarily for #GObjects that inherit from
983 * #ClutterModel, and should only be used when contructing a #ClutterModel.
984 * It will not work after the initial creation of the #ClutterModel.
989 clutter_model_set_names (ClutterModel *model,
991 const gchar * const names[])
993 ClutterModelPrivate *priv;
996 g_return_if_fail (CLUTTER_IS_MODEL (model));
997 g_return_if_fail (n_columns > 0);
1001 g_return_if_fail (priv->n_columns < 0 || priv->n_columns == n_columns);
1002 g_return_if_fail (priv->column_names == NULL);
1004 _clutter_model_set_n_columns (model, n_columns, FALSE, TRUE);
1006 for (i = 0; i < n_columns; i++)
1007 _clutter_model_set_column_name (model, i, names[i]);
1011 * clutter_model_get_n_columns:
1012 * @model: a #ClutterModel
1014 * Retrieves the number of columns inside @model.
1016 * Return value: the number of columns
1021 clutter_model_get_n_columns (ClutterModel *model)
1023 g_return_val_if_fail (CLUTTER_IS_MODEL (model), 0);
1025 return CLUTTER_MODEL_GET_CLASS (model)->get_n_columns (model);
1029 * clutter_model_appendv:
1030 * @model: a #ClutterModel
1031 * @n_columns: the number of columns and values
1032 * @columns: (array length=n_columns): a vector with the columns to set
1033 * @values: (array length=n_columns): a vector with the values
1035 * Creates and appends a new row to the #ClutterModel, setting the row
1036 * values for the given @columns upon creation.
1041 clutter_model_appendv (ClutterModel *model,
1046 ClutterModelPrivate *priv;
1047 ClutterModelIter *iter;
1049 gboolean resort = FALSE;
1051 g_return_if_fail (CLUTTER_IS_MODEL (model));
1052 g_return_if_fail (n_columns <= clutter_model_get_n_columns (model));
1053 g_return_if_fail (columns != NULL);
1054 g_return_if_fail (values != NULL);
1058 iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, -1);
1059 g_assert (CLUTTER_IS_MODEL_ITER (iter));
1061 for (i = 0; i < n_columns; i++)
1063 if (priv->sort_column == columns[i])
1066 clutter_model_iter_set_value (iter, columns[i], &values[i]);
1069 g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
1072 clutter_model_resort (model);
1074 g_object_unref (iter);
1077 /* forward declaration */
1078 static void clutter_model_iter_set_internal_valist (ClutterModelIter *iter,
1082 * clutter_model_append:
1083 * @model: a #ClutterModel
1084 * @...: pairs of column number and value, terminated with -1
1086 * Creates and appends a new row to the #ClutterModel, setting the
1087 * row values upon creation. For example, to append a new row where
1088 * column 0 is type %G_TYPE_INT and column 1 is of type %G_TYPE_STRING:
1090 * <informalexample><programlisting>
1091 * ClutterModel *model;
1092 * model = clutter_model_default_new (2,
1093 * G_TYPE_INT, "Score",
1094 * G_TYPE_STRING, "Team");
1095 * clutter_model_append (model, 0, 42, 1, "Team #1", -1);
1096 * </programlisting></informalexample>
1101 clutter_model_append (ClutterModel *model,
1104 ClutterModelIter *iter;
1107 g_return_if_fail (CLUTTER_IS_MODEL (model));
1109 iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, -1);
1110 g_assert (CLUTTER_IS_MODEL_ITER (iter));
1112 /* do not emit the ::row-changed signal */
1113 va_start (args, model);
1114 clutter_model_iter_set_internal_valist (iter, args);
1117 g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
1119 g_object_unref (iter);
1123 * clutter_model_prependv:
1124 * @model: a #ClutterModel
1125 * @n_columns: the number of columns and values to set
1126 * @columns: (array length=n_columns): a vector containing the columns to set
1127 * @values: (array length=n_columns): a vector containing the values for the cells
1129 * Creates and prepends a new row to the #ClutterModel, setting the row
1130 * values for the given @columns upon creation.
1135 clutter_model_prependv (ClutterModel *model,
1140 ClutterModelPrivate *priv;
1141 ClutterModelIter *iter;
1143 gboolean resort = FALSE;
1145 g_return_if_fail (CLUTTER_IS_MODEL (model));
1146 g_return_if_fail (n_columns <= clutter_model_get_n_columns (model));
1147 g_return_if_fail (columns != NULL);
1148 g_return_if_fail (values != NULL);
1152 iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, 0);
1153 g_assert (CLUTTER_IS_MODEL_ITER (iter));
1155 for (i = 0; i < n_columns; i++)
1157 if (priv->sort_column == columns[i])
1160 clutter_model_iter_set_value (iter, columns[i], &values[i]);
1163 g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
1166 clutter_model_resort (model);
1168 g_object_unref (iter);
1172 * clutter_model_prepend:
1173 * @model: a #ClutterModel
1174 * @...: pairs of column number and value, terminated with -1
1176 * Creates and prepends a new row to the #ClutterModel, setting the row
1177 * values upon creation. For example, to prepend a new row where column 0
1178 * is type %G_TYPE_INT and column 1 is of type %G_TYPE_STRING:
1180 * <informalexample><programlisting>
1181 * ClutterModel *model;
1182 * model = clutter_model_default_new (2,
1183 * G_TYPE_INT, "Score",
1184 * G_TYPE_STRING, "Team");
1185 * clutter_model_prepend (model, 0, 42, 1, "Team #1", -1);
1186 * </programlisting></informalexample>
1191 clutter_model_prepend (ClutterModel *model,
1194 ClutterModelIter *iter;
1197 g_return_if_fail (CLUTTER_IS_MODEL (model));
1199 iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, 0);
1200 g_assert (CLUTTER_IS_MODEL_ITER (iter));
1202 va_start (args, model);
1203 clutter_model_iter_set_internal_valist (iter, args);
1206 g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
1208 g_object_unref (iter);
1213 * clutter_model_insert:
1214 * @model: a #ClutterModel
1215 * @row: the position to insert the new row
1216 * @...: pairs of column number and value, terminated with -1
1218 * Inserts a new row to the #ClutterModel at @row, setting the row
1219 * values upon creation. For example, to insert a new row at index 100,
1220 * where column 0 is type %G_TYPE_INT and column 1 is of type
1223 * <informalexample><programlisting>
1224 * ClutterModel *model;
1225 * model = clutter_model_default_new (2,
1226 * G_TYPE_INT, "Score",
1227 * G_TYPE_STRING, "Team");
1228 * clutter_model_insert (model, 3, 0, 42, 1, "Team #1", -1);
1229 * </programlisting></informalexample>
1234 clutter_model_insert (ClutterModel *model,
1238 ClutterModelIter *iter;
1241 g_return_if_fail (CLUTTER_IS_MODEL (model));
1243 iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, row);
1244 g_assert (CLUTTER_IS_MODEL_ITER (iter));
1246 /* set_valist() will call clutter_model_resort() if one of the
1247 * passed columns matches the model sorting column index
1249 va_start (args, row);
1250 clutter_model_iter_set_internal_valist (iter, args);
1253 g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
1255 g_object_unref (iter);
1259 * clutter_model_insertv:
1260 * @model: a #ClutterModel
1262 * @n_columns: the number of columns and values to set
1263 * @columns: (array length=n_columns): a vector containing the columns to set
1264 * @values: (array length=n_columns): a vector containing the values for the cells
1266 * Inserts data at @row into the #ClutterModel, setting the row
1267 * values for the given @columns upon creation.
1272 clutter_model_insertv (ClutterModel *model,
1278 ClutterModelPrivate *priv;
1279 ClutterModelIter *iter;
1281 gboolean resort = FALSE;
1283 g_return_if_fail (CLUTTER_IS_MODEL (model));
1284 g_return_if_fail (n_columns <= clutter_model_get_n_columns (model));
1285 g_return_if_fail (columns != NULL);
1286 g_return_if_fail (values != NULL);
1290 iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, row);
1291 g_assert (CLUTTER_IS_MODEL_ITER (iter));
1293 for (i = 0; i < n_columns; i++)
1295 if (priv->sort_column == columns[i])
1298 clutter_model_iter_set_value (iter, columns[i], &values[i]);
1301 g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
1304 clutter_model_resort (model);
1306 g_object_unref (iter);
1310 * clutter_model_insert_value:
1311 * @model: a #ClutterModel
1312 * @row: position of the row to modify
1313 * @column: column to modify
1314 * @value: new value for the cell
1316 * Sets the data in the cell specified by @iter and @column. The type of
1317 * @value must be convertable to the type of the column. If the row does
1318 * not exist then it is created.
1323 clutter_model_insert_value (ClutterModel *model,
1326 const GValue *value)
1328 ClutterModelPrivate *priv;
1329 ClutterModelClass *klass;
1330 ClutterModelIter *iter;
1331 gboolean added = FALSE;
1333 g_return_if_fail (CLUTTER_IS_MODEL (model));
1336 klass = CLUTTER_MODEL_GET_CLASS (model);
1338 iter = klass->get_iter_at_row (model, row);
1341 iter = klass->insert_row (model, row);
1345 g_assert (CLUTTER_IS_MODEL_ITER (iter));
1347 clutter_model_iter_set_value (iter, column, value);
1350 g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
1352 if (priv->sort_column == column)
1353 clutter_model_resort (model);
1355 g_object_unref (iter);
1359 * clutter_model_remove:
1360 * @model: a #ClutterModel
1361 * @row: position of row to remove
1363 * Removes the row at the given position from the model.
1368 clutter_model_remove (ClutterModel *model,
1371 ClutterModelClass *klass;
1373 g_return_if_fail (CLUTTER_IS_MODEL (model));
1375 klass = CLUTTER_MODEL_GET_CLASS (model);
1376 if (klass->remove_row)
1377 klass->remove_row (model, row);
1381 * clutter_model_get_column_name:
1382 * @model: #ClutterModel
1383 * @column: the column number
1385 * Retrieves the name of the @column
1387 * Return value: the name of the column. The model holds the returned
1388 * string, and it should not be modified or freed
1393 clutter_model_get_column_name (ClutterModel *model,
1396 ClutterModelClass *klass;
1398 g_return_val_if_fail (CLUTTER_IS_MODEL (model), NULL);
1400 if (column >= clutter_model_get_n_columns (model))
1402 g_warning ("%s: Invalid column id value %d\n", G_STRLOC, column);
1406 klass = CLUTTER_MODEL_GET_CLASS (model);
1407 if (klass->get_column_name)
1408 return klass->get_column_name (model, column);
1414 * clutter_model_get_column_type:
1415 * @model: #ClutterModel
1416 * @column: the column number
1418 * Retrieves the type of the @column.
1420 * Return value: the type of the column.
1425 clutter_model_get_column_type (ClutterModel *model,
1428 ClutterModelClass *klass;
1430 g_return_val_if_fail (CLUTTER_IS_MODEL (model), G_TYPE_INVALID);
1432 if (column >= clutter_model_get_n_columns (model))
1434 g_warning ("%s: Invalid column id value %d\n", G_STRLOC, column);
1435 return G_TYPE_INVALID;
1438 klass = CLUTTER_MODEL_GET_CLASS (model);
1439 if (klass->get_column_type)
1440 return klass->get_column_type (model, column);
1442 return G_TYPE_INVALID;
1446 * clutter_model_get_iter_at_row:
1447 * @model: a #ClutterModel
1448 * @row: position of the row to retrieve
1450 * Retrieves a #ClutterModelIter representing the row at the given index.
1452 * If a filter function has been set using clutter_model_set_filter()
1453 * then the @model implementation will return the first non filtered
1456 * Return value: (transfer full): A new #ClutterModelIter, or %NULL if @row was
1457 * out of bounds. When done using the iterator object, call g_object_unref()
1458 * to deallocate its resources
1463 clutter_model_get_iter_at_row (ClutterModel *model,
1466 ClutterModelClass *klass;
1468 g_return_val_if_fail (CLUTTER_IS_MODEL (model), NULL);
1470 klass = CLUTTER_MODEL_GET_CLASS (model);
1471 if (klass->get_iter_at_row)
1472 return klass->get_iter_at_row (model, row);
1479 * clutter_model_get_first_iter:
1480 * @model: a #ClutterModel
1482 * Retrieves a #ClutterModelIter representing the first non-filtered
1485 * Return value: (transfer full): A new #ClutterModelIter.
1486 * Call g_object_unref() when done using it
1491 clutter_model_get_first_iter (ClutterModel *model)
1493 ClutterModelIter *retval;
1495 g_return_val_if_fail (CLUTTER_IS_MODEL (model), NULL);
1497 retval = clutter_model_get_iter_at_row (model, 0);
1500 g_assert (clutter_model_filter_iter (model, retval) != FALSE);
1501 g_assert (clutter_model_iter_get_row (retval) == 0);
1508 * clutter_model_get_last_iter:
1509 * @model: a #ClutterModel
1511 * Retrieves a #ClutterModelIter representing the last non-filtered
1514 * Return value: (transfer full): A new #ClutterModelIter.
1515 * Call g_object_unref() when done using it
1520 clutter_model_get_last_iter (ClutterModel *model)
1522 ClutterModelIter *retval;
1525 g_return_val_if_fail (CLUTTER_IS_MODEL (model), NULL);
1527 length = clutter_model_get_n_rows (model);
1528 retval = clutter_model_get_iter_at_row (model, length - 1);
1530 g_assert (clutter_model_filter_iter (model, retval) != FALSE);
1536 * clutter_model_get_n_rows:
1537 * @model: a #ClutterModel
1539 * Retrieves the number of rows inside @model, eventually taking
1540 * into account any filtering function set using clutter_model_set_filter().
1542 * Return value: The length of the @model. If there is a filter set, then
1543 * the length of the filtered @model is returned.
1548 clutter_model_get_n_rows (ClutterModel *model)
1550 g_return_val_if_fail (CLUTTER_IS_MODEL (model), 0);
1552 return CLUTTER_MODEL_GET_CLASS (model)->get_n_rows (model);
1556 * clutter_model_set_sorting_column:
1557 * @model: a #ClutterModel
1558 * @column: the column of the @model to sort, or -1
1560 * Sets the model to sort by @column. If @column is a negative value
1561 * the sorting column will be unset.
1566 clutter_model_set_sorting_column (ClutterModel *model,
1569 ClutterModelPrivate *priv;
1571 g_return_if_fail (CLUTTER_IS_MODEL (model));
1574 /* The extra comparison for >= 0 is because column gets promoted to
1575 unsigned in the second comparison */
1576 if (column >= 0 && column >= clutter_model_get_n_columns (model))
1578 g_warning ("%s: Invalid column id value %d\n", G_STRLOC, column);
1582 priv->sort_column = column;
1584 if (priv->sort_column >= 0)
1585 clutter_model_resort (model);
1587 g_signal_emit (model, model_signals[SORT_CHANGED], 0);
1591 * clutter_model_get_sorting_column:
1592 * @model: a #ClutterModel
1594 * Retrieves the number of column used for sorting the @model.
1596 * Return value: a column number, or -1 if the model is not sorted
1601 clutter_model_get_sorting_column (ClutterModel *model)
1603 g_return_val_if_fail (CLUTTER_IS_MODEL (model), -1);
1605 return model->priv->sort_column;
1609 * clutter_model_foreach:
1610 * @model: a #ClutterModel
1611 * @func: (scope call): a #ClutterModelForeachFunc
1612 * @user_data: user data to pass to @func
1614 * Calls @func for each row in the model.
1619 clutter_model_foreach (ClutterModel *model,
1620 ClutterModelForeachFunc func,
1623 ClutterModelIter *iter;
1625 g_return_if_fail (CLUTTER_IS_MODEL (model));
1627 iter = clutter_model_get_first_iter (model);
1631 while (!clutter_model_iter_is_last (iter))
1633 if (clutter_model_filter_iter (model, iter))
1635 if (!func (model, iter, user_data))
1639 iter = clutter_model_iter_next (iter);
1642 g_object_unref (iter);
1646 * clutter_model_set_sort:
1647 * @model: a #ClutterModel
1648 * @column: the column to sort on
1649 * @func: (allow-none): a #ClutterModelSortFunc, or #NULL
1650 * @user_data: user data to pass to @func, or #NULL
1651 * @notify: destroy notifier of @user_data, or #NULL
1653 * Sorts @model using the given sorting function.
1658 clutter_model_set_sort (ClutterModel *model,
1660 ClutterModelSortFunc func,
1662 GDestroyNotify notify)
1664 ClutterModelPrivate *priv;
1666 g_return_if_fail (CLUTTER_IS_MODEL (model));
1667 g_return_if_fail ((func != NULL && column >= 0) ||
1668 (func == NULL && column == -1));
1672 if (priv->sort_notify)
1673 priv->sort_notify (priv->sort_data);
1675 priv->sort_func = func;
1676 priv->sort_data = user_data;
1677 priv->sort_notify = notify;
1679 /* This takes care of calling _model_sort & emitting the signal*/
1680 clutter_model_set_sorting_column (model, column);
1684 * clutter_model_set_filter:
1685 * @model: a #ClutterModel
1686 * @func: (allow-none): a #ClutterModelFilterFunc, or #NULL
1687 * @user_data: user data to pass to @func, or #NULL
1688 * @notify: destroy notifier of @user_data, or #NULL
1690 * Filters the @model using the given filtering function.
1695 clutter_model_set_filter (ClutterModel *model,
1696 ClutterModelFilterFunc func,
1698 GDestroyNotify notify)
1700 ClutterModelPrivate *priv;
1702 g_return_if_fail (CLUTTER_IS_MODEL (model));
1705 if (priv->filter_notify)
1706 priv->filter_notify (priv->filter_data);
1708 priv->filter_func = func;
1709 priv->filter_data = user_data;
1710 priv->filter_notify = notify;
1712 g_signal_emit (model, model_signals[FILTER_CHANGED], 0);
1713 g_object_notify (G_OBJECT (model), "filter-set");
1717 * clutter_model_get_filter_set:
1718 * @model: a #ClutterModel
1720 * Returns whether the @model has a filter in place, set
1721 * using clutter_model_set_filter()
1723 * Return value: %TRUE if a filter is set
1728 clutter_model_get_filter_set (ClutterModel *model)
1730 g_return_val_if_fail (CLUTTER_IS_MODEL (model), FALSE);
1732 return model->priv->filter_func != NULL;
1736 * ClutterModelIter Object
1740 * SECTION:clutter-model-iter
1741 * @short_description: Iterates through a model
1743 * #ClutterModelIter is an object used for iterating through all the rows
1744 * of a #ClutterModel. It allows setting and getting values on the row
1745 * which is currently pointing at.
1747 * A #ClutterModelIter represents a position between two elements
1748 * of the sequence. For example, the iterator returned by
1749 * clutter_model_get_first_iter() represents the gap immediately before
1750 * the first row of the #ClutterModel, and the iterator returned by
1751 * clutter_model_get_last_iter() represents the gap immediately after the
1754 * A #ClutterModelIter can only be created by a #ClutterModel implementation
1755 * and it is valid as long as the model does not change.
1757 * #ClutterModelIter is available since Clutter 0.6
1760 G_DEFINE_ABSTRACT_TYPE (ClutterModelIter, clutter_model_iter, G_TYPE_OBJECT);
1762 #define CLUTTER_MODEL_ITER_GET_PRIVATE(obj) \
1763 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
1764 CLUTTER_TYPE_MODEL_ITER, ClutterModelIterPrivate))
1766 struct _ClutterModelIterPrivate
1768 ClutterModel *model;
1781 static ClutterModel *
1782 clutter_model_iter_real_get_model (ClutterModelIter *iter)
1784 return iter->priv->model;
1788 clutter_model_iter_real_get_row (ClutterModelIter *iter)
1790 return iter->priv->row;
1793 /* private function */
1795 _clutter_model_iter_set_row (ClutterModelIter *iter,
1798 iter->priv->row = row;
1802 clutter_model_iter_get_value_unimplemented (ClutterModelIter *iter,
1806 g_warning ("%s: Iterator of type '%s' does not implement the "
1807 "ClutterModelIter::get_value() virtual function",
1809 g_type_name (G_OBJECT_TYPE (iter)));
1813 clutter_model_iter_set_value_unimplemented (ClutterModelIter *iter,
1815 const GValue *value)
1817 g_warning ("%s: Iterator of type '%s' does not implement the "
1818 "ClutterModelIter::set_value() virtual function",
1820 g_type_name (G_OBJECT_TYPE (iter)));
1824 clutter_model_iter_is_first_unimplemented (ClutterModelIter *iter)
1826 g_warning ("%s: Iterator of type '%s' does not implement the "
1827 "ClutterModelIter::is_first() virtual function",
1829 g_type_name (G_OBJECT_TYPE (iter)));
1834 clutter_model_iter_is_last_unimplemented (ClutterModelIter *iter)
1836 g_warning ("%s: Iterator of type '%s' does not implement the "
1837 "ClutterModelIter::is_last() virtual function",
1839 g_type_name (G_OBJECT_TYPE (iter)));
1843 static ClutterModelIter *
1844 clutter_model_iter_next_unimplemented (ClutterModelIter *iter)
1846 g_warning ("%s: Iterator of type '%s' does not implement the "
1847 "ClutterModelIter::next() virtual function",
1849 g_type_name (G_OBJECT_TYPE (iter)));
1853 static ClutterModelIter *
1854 clutter_model_iter_prev_unimplemented (ClutterModelIter *iter)
1856 g_warning ("%s: Iterator of type '%s' does not implement the "
1857 "ClutterModelIter::prev() virtual function",
1859 g_type_name (G_OBJECT_TYPE (iter)));
1863 static ClutterModelIter *
1864 clutter_model_iter_copy_unimplemented (ClutterModelIter *iter)
1866 g_warning ("%s: Iterator of type '%s' does not implement the "
1867 "ClutterModelIter::copy() virtual function",
1869 g_type_name (G_OBJECT_TYPE (iter)));
1874 clutter_model_iter_get_property (GObject *object,
1879 ClutterModelIter *iter = CLUTTER_MODEL_ITER (object);
1880 ClutterModelIterPrivate *priv = iter->priv;
1884 case ITER_PROP_MODEL:
1885 g_value_set_object (value, priv->model);
1888 g_value_set_uint (value, priv->row);
1891 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1897 clutter_model_iter_set_property (GObject *object,
1899 const GValue *value,
1902 ClutterModelIter *iter = CLUTTER_MODEL_ITER (object);
1903 ClutterModelIterPrivate *priv = iter->priv;
1907 case ITER_PROP_MODEL:
1908 priv->model = g_value_get_object (value);
1911 priv->row = g_value_get_uint (value);
1914 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1920 clutter_model_iter_class_init (ClutterModelIterClass *klass)
1922 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1925 gobject_class->get_property = clutter_model_iter_get_property;
1926 gobject_class->set_property = clutter_model_iter_set_property;
1928 klass->get_model = clutter_model_iter_real_get_model;
1929 klass->get_row = clutter_model_iter_real_get_row;
1930 klass->is_first = clutter_model_iter_is_first_unimplemented;
1931 klass->is_last = clutter_model_iter_is_last_unimplemented;
1932 klass->next = clutter_model_iter_next_unimplemented;
1933 klass->prev = clutter_model_iter_prev_unimplemented;
1934 klass->get_value = clutter_model_iter_get_value_unimplemented;
1935 klass->set_value = clutter_model_iter_set_value_unimplemented;
1936 klass->copy = clutter_model_iter_copy_unimplemented;
1941 * ClutterModelIter:model:
1943 * A reference to the #ClutterModel that this iter belongs to.
1947 pspec = g_param_spec_object ("model",
1949 "The model to which the iterator belongs to",
1951 CLUTTER_PARAM_READWRITE);
1952 g_object_class_install_property (gobject_class, ITER_PROP_MODEL, pspec);
1955 * ClutterModelIter:row:
1957 * The row number to which this iter points to.
1961 pspec = g_param_spec_uint ("row",
1963 "The row to which the iterator points to",
1965 CLUTTER_PARAM_READWRITE);
1966 g_object_class_install_property (gobject_class, ITER_PROP_ROW, pspec);
1968 g_type_class_add_private (gobject_class, sizeof (ClutterModelIterPrivate));
1972 clutter_model_iter_init (ClutterModelIter *self)
1974 ClutterModelIterPrivate *priv;
1976 self->priv = priv = CLUTTER_MODEL_ITER_GET_PRIVATE (self);
1987 clutter_model_iter_set_value_internal (ClutterModelIter *iter,
1989 const GValue *value)
1991 CLUTTER_MODEL_ITER_GET_CLASS (iter)->set_value (iter, column, value);
1995 clutter_model_iter_set_internal_valist (ClutterModelIter *iter,
1998 ClutterModelIterPrivate *priv = iter->priv;
1999 ClutterModel *model = priv->model;
2001 gboolean sort = FALSE;
2003 g_assert (CLUTTER_IS_MODEL (model));
2005 column = va_arg (args, gint);
2007 while (column != -1)
2009 GValue value = G_VALUE_INIT;
2010 gchar *error = NULL;
2013 if (column >= clutter_model_get_n_columns (model))
2015 g_warning ("%s: Invalid column number %d added to iter "
2016 "(remember to end you list of columns with a -1)",
2021 col_type = clutter_model_get_column_type (model, column);
2023 G_VALUE_COLLECT_INIT (&value, col_type, args, 0, &error);
2026 g_warning ("%s: %s", G_STRLOC, error);
2029 /* Leak value as it might not be in a sane state */
2033 clutter_model_iter_set_value_internal (iter, column, &value);
2035 g_value_unset (&value);
2037 if (column == clutter_model_get_sorting_column (model))
2040 column = va_arg (args, gint);
2044 clutter_model_resort (model);
2048 clutter_model_iter_emit_row_changed (ClutterModelIter *iter)
2050 ClutterModelIterPrivate *priv = iter->priv;
2051 ClutterModel *model = priv->model;
2053 g_assert (CLUTTER_IS_MODEL (model));
2055 g_signal_emit (model, model_signals[ROW_CHANGED], 0, iter);
2059 * clutter_model_iter_set_valist:
2060 * @iter: a #ClutterModelIter
2061 * @args: va_list of column/value pairs, terminiated by -1
2063 * See clutter_model_iter_set(); this version takes a va_list for language
2069 clutter_model_iter_set_valist (ClutterModelIter *iter,
2072 g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter));
2074 clutter_model_iter_set_internal_valist (iter, args);
2075 clutter_model_iter_emit_row_changed (iter);
2079 * clutter_model_iter_get:
2080 * @iter: a #ClutterModelIter
2081 * @...: a list of column/return location pairs, terminated by -1
2083 * Gets the value of one or more cells in the row referenced by @iter. The
2084 * variable argument list should contain integer column numbers, each column
2085 * column number followed by a place to store the value being retrieved. The
2086 * list is terminated by a -1.
2088 * For example, to get a value from column 0 with type %G_TYPE_STRING use:
2089 * <informalexample><programlisting>
2090 * clutter_model_iter_get (iter, 0, &place_string_here, -1);
2091 * </programlisting></informalexample>
2093 * where place_string_here is a gchar* to be filled with the string. If
2094 * appropriate, the returned values have to be freed or unreferenced.
2099 clutter_model_iter_get (ClutterModelIter *iter,
2104 g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter));
2106 va_start (args, iter);
2107 clutter_model_iter_get_valist (iter, args);
2112 clutter_model_iter_get_value_internal (ClutterModelIter *iter,
2116 CLUTTER_MODEL_ITER_GET_CLASS (iter)->get_value (iter, column, value);
2120 * clutter_model_iter_get_value:
2121 * @iter: a #ClutterModelIter
2122 * @column: column number to retrieve the value from
2123 * @value: (out): an empty #GValue to set
2125 * Sets an initializes @value to that at @column. When done with @value,
2126 * g_value_unset() needs to be called to free any allocated memory.
2131 clutter_model_iter_get_value (ClutterModelIter *iter,
2135 ClutterModel *model;
2137 g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter));
2139 model = iter->priv->model;
2141 if (G_VALUE_TYPE (value) == G_TYPE_INVALID)
2142 g_value_init (value, clutter_model_get_column_type (model, column));
2144 CLUTTER_MODEL_ITER_GET_CLASS (iter)->get_value (iter, column, value);
2148 * clutter_model_iter_get_valist:
2149 * @iter: a #ClutterModelIter
2150 * @args: a list of column/return location pairs, terminated by -1
2152 * See clutter_model_iter_get(). This version takes a va_list for language
2158 clutter_model_iter_get_valist (ClutterModelIter *iter,
2161 ClutterModelIterPrivate *priv;
2162 ClutterModel *model;
2165 g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter));
2168 model = priv->model;
2169 g_assert (CLUTTER_IS_MODEL (model));
2171 column = va_arg (args, gint);
2173 while (column != -1)
2175 GValue value = G_VALUE_INIT;
2176 gchar *error = NULL;
2179 if (column >= clutter_model_get_n_columns (model))
2181 g_warning ("%s: Invalid column number %d added to iter "
2182 "(remember to end you list of columns with a -1)",
2187 col_type = clutter_model_get_column_type (model, column);
2188 g_value_init (&value, col_type);
2190 clutter_model_iter_get_value_internal (iter, column, &value);
2192 G_VALUE_LCOPY (&value, args, 0, &error);
2195 g_warning ("%s: %s", G_STRLOC, error);
2198 /* Leak value as it might not be in a sane state */
2202 g_value_unset (&value);
2204 column = va_arg (args, gint);
2209 * clutter_model_iter_set:
2210 * @iter: a #ClutterModelIter
2211 * @...: a list of column/return location pairs, terminated by -1
2213 * Sets the value of one or more cells in the row referenced by @iter. The
2214 * variable argument list should contain integer column numbers, each column
2215 * column number followed by the value to be set. The list is terminated by a
2218 * For example, to set column 0 with type %G_TYPE_STRING, use:
2219 * <informalexample><programlisting>
2220 * clutter_model_iter_set (iter, 0, "foo", -1);
2221 * </programlisting></informalexample>
2226 clutter_model_iter_set (ClutterModelIter *iter,
2231 g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter));
2233 va_start (args, iter);
2234 clutter_model_iter_set_internal_valist (iter, args);
2235 clutter_model_iter_emit_row_changed (iter);
2240 * clutter_model_iter_set_value:
2241 * @iter: a #ClutterModelIter
2242 * @column: column number to retrieve the value from
2243 * @value: new value for the cell
2245 * Sets the data in the cell specified by @iter and @column. The type of
2246 * @value must be convertable to the type of the column.
2251 clutter_model_iter_set_value (ClutterModelIter *iter,
2253 const GValue *value)
2255 g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter));
2257 clutter_model_iter_set_value_internal (iter, column, value);
2258 clutter_model_iter_emit_row_changed (iter);
2262 * clutter_model_iter_is_first:
2263 * @iter: a #ClutterModelIter
2265 * Gets whether the current iterator is at the beginning of the model
2266 * to which it belongs.
2268 * Return value: #TRUE if @iter is the first iter in the filtered model
2273 clutter_model_iter_is_first (ClutterModelIter *iter)
2275 g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), FALSE);
2277 return CLUTTER_MODEL_ITER_GET_CLASS (iter)->is_first (iter);
2281 * clutter_model_iter_is_last:
2282 * @iter: a #ClutterModelIter
2284 * Gets whether the iterator is at the end of the model to which it
2287 * Return value: #TRUE if @iter is the last iter in the filtered model.
2292 clutter_model_iter_is_last (ClutterModelIter *iter)
2294 g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), FALSE);
2296 return CLUTTER_MODEL_ITER_GET_CLASS (iter)->is_last (iter);
2300 * clutter_model_iter_next:
2301 * @iter: a #ClutterModelIter
2303 * Updates the @iter to point at the next position in the model.
2304 * The model implementation should take into account the presence of
2305 * a filter function.
2307 * Return value: (transfer none): The passed iterator, updated to point at the next
2313 clutter_model_iter_next (ClutterModelIter *iter)
2315 g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), NULL);
2317 return CLUTTER_MODEL_ITER_GET_CLASS (iter)->next (iter);
2321 * clutter_model_iter_prev:
2322 * @iter: a #ClutterModelIter
2324 * Sets the @iter to point at the previous position in the model.
2325 * The model implementation should take into account the presence of
2326 * a filter function.
2328 * Return value: (transfer none): The passed iterator, updated to point at the previous
2334 clutter_model_iter_prev (ClutterModelIter *iter)
2336 g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), NULL);
2338 return CLUTTER_MODEL_ITER_GET_CLASS (iter)->prev (iter);
2342 * clutter_model_iter_get_model:
2343 * @iter: a #ClutterModelIter
2345 * Retrieves a pointer to the #ClutterModel that this iter is part of.
2347 * Return value: (transfer none): a pointer to a #ClutterModel.
2352 clutter_model_iter_get_model (ClutterModelIter *iter)
2354 g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), NULL);
2356 return CLUTTER_MODEL_ITER_GET_CLASS (iter)->get_model (iter);
2360 * clutter_model_iter_get_row:
2361 * @iter: a #ClutterModelIter
2363 * Retrieves the position of the row that the @iter points to.
2365 * Return value: the position of the @iter in the model
2370 clutter_model_iter_get_row (ClutterModelIter *iter)
2372 g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), 0);
2374 return CLUTTER_MODEL_ITER_GET_CLASS (iter)->get_row (iter);
2378 * clutter_model_iter_copy:
2379 * @iter: a #ClutterModelIter
2381 * Copies the passed iterator.
2383 * Return value: (transfer full): a copy of the iterator, or %NULL
2388 clutter_model_iter_copy (ClutterModelIter *iter)
2390 g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), NULL);
2392 return CLUTTER_MODEL_ITER_GET_CLASS (iter)->copy (iter);