--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Authored By Matthew Allum <mallum@openedhand.com>
+ * Neil Jagdish Patel <njp@o-hand.com>
+ * Emmanuele Bassi <ebassi@openedhand.com>
+ *
+ * Copyright (C) 2006 OpenedHand
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+
+/**
+ * SECTION:clutter-model-default:
+ * @short_description: Default model implementation
+ *
+ * #ClutterModelDefault is a #ClutterModel implementation provided by
+ * Clutter. #ClutterModelDefault uses a #GSequence for storing the
+ * values for each row, so it's optimized for insertion and look up
+ * in sorted lists.
+ *
+ * #ClutterModelDefault is a terminal class: it cannot be subclassed,
+ * only instantiated.
+ *
+ * #ClutterModelDefault is available since Clutter 0.6
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib-object.h>
+
+#include "clutter-model.h"
+#include "clutter-model-default.h"
+#include "clutter-private.h"
+#include "clutter-debug.h"
+
+#define CLUTTER_MODEL_DEFAULT_ITER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ CLUTTER_TYPE_MODEL_DEFAULT_ITER, \
+ ClutterModelDefaultIterClass))
+#define CLUTTER_IS_MODEL_DEFAULT_ITER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ CLUTTER_TYPE_MODEL_DEFAULT_ITER))
+#define CLUTTER_MODEL_DEFAULT_ITER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ CLUTTER_TYPE_MODEL_DEFAULT_ITER, \
+ ClutterModelDefaultIterClass))
+
+#define CLUTTER_MODEL_DEFAULT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ CLUTTER_TYPE_MODEL_DEFAULT, \
+ ClutterModelDefaultClass))
+#define CLUTTER_IS_MODEL_DEFAULT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ CLUTTER_TYPE_MODEL_DEFAULT))
+#define CLUTTER_MODEL_DEFAULT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ CLUTTER_TYPE_MODEL_DEFAULT, \
+ ClutterModelDefaultClass))
+
+typedef struct _ClutterModelIterClass ClutterModelDefaultIterClass;
+typedef struct _ClutterModelClass ClutterModelDefaultClass;
+
+struct _ClutterModelDefault
+{
+ ClutterModel parent_instance;
+
+ GSequence *sequence;
+};
+
+struct _ClutterModelDefaultIter
+{
+ ClutterModelIter parent_instance;
+
+ GSequenceIter *seq_iter;
+};
+
+\f
+
+/*
+ * ClutterModelDefault
+ */
+
+G_DEFINE_TYPE (ClutterModelDefaultIter,
+ clutter_model_default_iter,
+ CLUTTER_TYPE_MODEL_ITER);
+
+static void
+clutter_model_default_iter_get_value (ClutterModelIter *iter,
+ guint column,
+ GValue *value)
+{
+ ClutterModelDefaultIter *iter_default;
+ GValueArray *value_array;
+ GValue *iter_value;
+ GValue real_value = { 0, };
+ gboolean converted = FALSE;
+
+ iter_default = CLUTTER_MODEL_DEFAULT_ITER (iter);
+ g_assert (iter_default->seq_iter != NULL);
+
+ value_array = g_sequence_get (iter_default->seq_iter);
+ iter_value = g_value_array_get_nth (value_array, column);
+ g_assert (iter_value != NULL);
+
+ if (!g_type_is_a (G_VALUE_TYPE (value), G_VALUE_TYPE (iter_value)))
+ {
+ if (!g_value_type_compatible (G_VALUE_TYPE (value),
+ G_VALUE_TYPE (iter_value)) &&
+ !g_value_type_compatible (G_VALUE_TYPE (iter_value),
+ G_VALUE_TYPE (value)))
+ {
+ g_warning ("%s: Unable to convert from %s to %s",
+ G_STRLOC,
+ g_type_name (G_VALUE_TYPE (value)),
+ g_type_name (G_VALUE_TYPE (iter_value)));
+ return;
+ }
+
+ if (!g_value_transform (value, &real_value))
+ {
+ g_warning ("%s: Unable to make conversion from %s to %s",
+ G_STRLOC,
+ g_type_name (G_VALUE_TYPE (value)),
+ g_type_name (G_VALUE_TYPE (iter_value)));
+ g_value_unset (&real_value);
+ }
+
+ converted = TRUE;
+ }
+
+ if (converted)
+ {
+ g_value_copy (&real_value, value);
+ g_value_unset (&real_value);
+ }
+ else
+ g_value_copy (iter_value, value);
+}
+
+static void
+clutter_model_default_iter_set_value (ClutterModelIter *iter,
+ guint column,
+ const GValue *value)
+{
+ ClutterModelDefaultIter *iter_default;
+ GValueArray *value_array;
+ GValue *iter_value;
+ GValue real_value = { 0, };
+ gboolean converted = FALSE;
+
+ iter_default = CLUTTER_MODEL_DEFAULT_ITER (iter);
+ g_assert (iter_default->seq_iter != NULL);
+
+ value_array = g_sequence_get (iter_default->seq_iter);
+ iter_value = g_value_array_get_nth (value_array, column);
+ g_assert (iter_value != NULL);
+
+ if (!g_type_is_a (G_VALUE_TYPE (value), G_VALUE_TYPE (iter_value)))
+ {
+ if (!g_value_type_compatible (G_VALUE_TYPE (value),
+ G_VALUE_TYPE (iter_value)) &&
+ !g_value_type_compatible (G_VALUE_TYPE (iter_value),
+ G_VALUE_TYPE (value)))
+ {
+ g_warning ("%s: Unable to convert from %s to %s\n",
+ G_STRLOC,
+ g_type_name (G_VALUE_TYPE (value)),
+ g_type_name (G_VALUE_TYPE (iter_value)));
+ return;
+ }
+
+ if (!g_value_transform (value, &real_value))
+ {
+ g_warning ("%s: Unable to make conversion from %s to %s\n",
+ G_STRLOC,
+ g_type_name (G_VALUE_TYPE (value)),
+ g_type_name (G_VALUE_TYPE (iter_value)));
+ g_value_unset (&real_value);
+ }
+
+ converted = TRUE;
+ }
+
+ if (converted)
+ {
+ g_value_copy (&real_value, iter_value);
+ g_value_unset (&real_value);
+ }
+ else
+ g_value_copy (value, iter_value);
+}
+
+static gboolean
+clutter_model_default_iter_is_first (ClutterModelIter *iter)
+{
+ ClutterModelDefaultIter *iter_default;
+ ClutterModel *model;
+ ClutterModelIter *temp_iter;
+ GSequenceIter *begin, *end;
+ guint row;
+
+ iter_default = CLUTTER_MODEL_DEFAULT_ITER (iter);
+ g_assert (iter_default->seq_iter != NULL);
+
+ model = clutter_model_iter_get_model (iter);
+ row = clutter_model_iter_get_row (iter);
+
+ begin = g_sequence_get_begin_iter (CLUTTER_MODEL_DEFAULT (model)->sequence);
+ end = iter_default->seq_iter;
+
+ temp_iter = g_object_new (CLUTTER_TYPE_MODEL_DEFAULT_ITER,
+ "model", model,
+ NULL);
+
+ while (!g_sequence_iter_is_begin (begin))
+ {
+ CLUTTER_MODEL_DEFAULT_ITER (temp_iter)->seq_iter = begin;
+ g_object_set (G_OBJECT (temp_iter), "row", row, NULL);
+
+ if (clutter_model_filter_iter (model, temp_iter))
+ {
+ end = begin;
+ break;
+ }
+
+ begin = g_sequence_iter_next (begin);
+ row += 1;
+ }
+
+ g_object_unref (temp_iter);
+
+ /* This is because the 'begin_iter' is always *before* the last valid
+ * iter, otherwise we'd have endless loops
+ */
+ end = g_sequence_iter_prev (end);
+
+ return iter_default->seq_iter == end;
+}
+
+static gboolean
+clutter_model_default_iter_is_last (ClutterModelIter *iter)
+{
+ ClutterModelDefaultIter *iter_default;
+ ClutterModelIter *temp_iter;
+ ClutterModel *model;
+ GSequenceIter *begin, *end;
+ guint row;
+
+ iter_default = CLUTTER_MODEL_DEFAULT_ITER (iter);
+ g_assert (iter_default->seq_iter != NULL);
+
+ if (g_sequence_iter_is_end (iter_default->seq_iter))
+ return TRUE;
+
+ model = clutter_model_iter_get_model (iter);
+ row = clutter_model_iter_get_row (iter);
+
+ begin = g_sequence_get_end_iter (CLUTTER_MODEL_DEFAULT (model)->sequence);
+ begin = g_sequence_iter_prev (begin);
+ end = iter_default->seq_iter;
+
+ temp_iter = g_object_new (CLUTTER_TYPE_MODEL_DEFAULT_ITER,
+ "model", model,
+ NULL);
+
+ while (!g_sequence_iter_is_begin (begin))
+ {
+ CLUTTER_MODEL_DEFAULT_ITER (temp_iter)->seq_iter = begin;
+ g_object_set (G_OBJECT (temp_iter), "row", row, NULL);
+
+ if (clutter_model_filter_iter (model, temp_iter))
+ {
+ end = begin;
+ break;
+ }
+
+ begin = g_sequence_iter_prev (begin);
+ row += 1;
+ }
+
+ g_object_unref (temp_iter);
+
+ /* This is because the 'end_iter' is always *after* the last valid iter.
+ * Otherwise we'd have endless loops
+ */
+ end = g_sequence_iter_next (end);
+
+ return iter_default->seq_iter == end;
+}
+
+static ClutterModelIter *
+clutter_model_default_iter_next (ClutterModelIter *iter)
+{
+ ClutterModelDefaultIter *iter_default;
+ ClutterModelDefaultIter *retval;
+ ClutterModelIter *temp_iter;
+ ClutterModel *model = NULL;
+ GSequenceIter *filter_next;
+ guint row;
+
+ iter_default = CLUTTER_MODEL_DEFAULT_ITER (iter);
+ g_assert (iter_default->seq_iter != NULL);
+
+ model = clutter_model_iter_get_model (iter);
+ row = clutter_model_iter_get_row (iter) + 1;
+
+ filter_next = g_sequence_iter_next (iter_default->seq_iter);
+ g_assert (filter_next != NULL);
+
+ temp_iter = g_object_new (CLUTTER_TYPE_MODEL_DEFAULT_ITER,
+ "model", model,
+ NULL);
+
+ while (!g_sequence_iter_is_end (filter_next))
+ {
+ CLUTTER_MODEL_DEFAULT_ITER (temp_iter)->seq_iter = filter_next;
+ g_object_set (G_OBJECT (temp_iter), "row", row, NULL);
+
+ if (clutter_model_filter_iter (model, temp_iter))
+ break;
+
+ filter_next = g_sequence_iter_next (filter_next);
+ row += 1;
+ }
+
+ g_object_unref (temp_iter);
+
+ /* We do this because the 'end_iter' is always *after* the last valid iter.
+ * Otherwise loops will go on forever
+ */
+ if (filter_next == iter_default->seq_iter)
+ filter_next = g_sequence_iter_next (filter_next);
+
+ retval = g_object_new (CLUTTER_TYPE_MODEL_DEFAULT_ITER,
+ "model", model,
+ "row", row,
+ NULL);
+ retval->seq_iter = filter_next;
+
+ return CLUTTER_MODEL_ITER (retval);
+}
+
+static ClutterModelIter *
+clutter_model_default_iter_prev (ClutterModelIter *iter)
+{
+ ClutterModelDefaultIter *iter_default;
+ ClutterModelDefaultIter *retval;
+ ClutterModelIter *temp_iter;
+ ClutterModel *model;
+ GSequenceIter *filter_prev;
+ guint row;
+
+ iter_default = CLUTTER_MODEL_DEFAULT_ITER (iter);
+ g_assert (iter_default->seq_iter != NULL);
+
+ model = clutter_model_iter_get_model (iter);
+ row = clutter_model_iter_get_row (iter) - 1;
+
+ filter_prev = g_sequence_iter_prev (iter_default->seq_iter);
+ g_assert (filter_prev != NULL);
+
+ temp_iter = g_object_new (CLUTTER_TYPE_MODEL_DEFAULT_ITER,
+ "model", model,
+ NULL);
+
+ while (!g_sequence_iter_is_begin (filter_prev))
+ {
+ CLUTTER_MODEL_DEFAULT_ITER (temp_iter)->seq_iter = filter_prev;
+ g_object_set (G_OBJECT (temp_iter), "row", row, NULL);
+
+ if (clutter_model_filter_iter (model, temp_iter))
+ break;
+
+ filter_prev = g_sequence_iter_prev (filter_prev);
+ row -= 1;
+ }
+
+ g_object_unref (temp_iter);
+
+ /* We do this because the 'end_iter' is always *after* the last valid iter.
+ * Otherwise loops will go on forever
+ */
+ if (filter_prev == iter_default->seq_iter)
+ filter_prev = g_sequence_iter_prev (filter_prev);
+
+ retval = g_object_new (CLUTTER_TYPE_MODEL_DEFAULT_ITER,
+ "model", model,
+ "row", row,
+ NULL);
+ retval->seq_iter = filter_prev;
+
+ return CLUTTER_MODEL_ITER (retval);
+}
+static void
+clutter_model_default_iter_class_init (ClutterModelDefaultIterClass *klass)
+{
+ ClutterModelIterClass *iter_class = CLUTTER_MODEL_ITER_CLASS (klass);
+
+ iter_class->get_value = clutter_model_default_iter_get_value;
+ iter_class->set_value = clutter_model_default_iter_set_value;
+ iter_class->is_first = clutter_model_default_iter_is_first;
+ iter_class->is_last = clutter_model_default_iter_is_last;
+ iter_class->next = clutter_model_default_iter_next;
+ iter_class->prev = clutter_model_default_iter_prev;
+}
+
+static void
+clutter_model_default_iter_init (ClutterModelDefaultIter *iter)
+{
+ iter->seq_iter = NULL;
+}
+
+/*
+ * ClutterModelDefault
+ */
+
+G_DEFINE_TYPE (ClutterModelDefault, clutter_model_default, CLUTTER_TYPE_MODEL);
+
+static ClutterModelIter *
+clutter_model_default_get_iter_at_row (ClutterModel *model,
+ guint row)
+{
+ ClutterModelDefault *model_default = CLUTTER_MODEL_DEFAULT (model);
+ ClutterModelDefaultIter *retval;
+
+ if (row > g_sequence_get_length (model_default->sequence))
+ return NULL;
+
+ retval = g_object_new (CLUTTER_TYPE_MODEL_DEFAULT_ITER,
+ "model", model,
+ "row", row,
+ NULL);
+ retval->seq_iter = g_sequence_get_iter_at_pos (model_default->sequence, row);
+
+ return CLUTTER_MODEL_ITER (retval);
+}
+
+static ClutterModelIter *
+clutter_model_default_insert_row (ClutterModel *model,
+ gint index_)
+{
+ ClutterModelDefault *model_default = CLUTTER_MODEL_DEFAULT (model);
+ ClutterModelDefaultIter *retval;
+ guint n_columns, i, pos;
+ GValueArray *array;
+ GSequenceIter *seq_iter;
+
+ n_columns = clutter_model_get_n_columns (model);
+ array = g_value_array_new (n_columns);
+
+ for (i = 0; i < n_columns; i++)
+ {
+ GValue *value = NULL;
+
+ g_value_array_append (array, NULL);
+
+ value = g_value_array_get_nth (array, i);
+ g_value_init (value, clutter_model_get_column_type (model, i));
+ }
+
+ if (index_ < 0)
+ {
+ seq_iter = g_sequence_append (model_default->sequence, array);
+ pos = g_sequence_get_length (model_default->sequence) - 1;
+ }
+ else if (index_ == 0)
+ {
+ seq_iter = g_sequence_prepend (model_default->sequence, array);
+ pos = 0;
+ }
+ else
+ {
+ seq_iter = g_sequence_get_iter_at_pos (model_default->sequence, index_);
+ seq_iter = g_sequence_insert_before (seq_iter, array);
+ pos = index_;
+ }
+
+ retval = g_object_new (CLUTTER_TYPE_MODEL_DEFAULT_ITER,
+ "model", model,
+ "row", pos,
+ NULL);
+ retval->seq_iter = seq_iter;
+
+ return CLUTTER_MODEL_ITER (retval);
+}
+
+static void
+clutter_model_default_remove_row (ClutterModel *model,
+ guint row)
+{
+ ClutterModelDefault *model_default = CLUTTER_MODEL_DEFAULT (model);
+ GSequenceIter *seq_iter;
+ guint pos = 0;
+
+ seq_iter = g_sequence_get_begin_iter (model_default->sequence);
+ while (!g_sequence_iter_is_end (seq_iter))
+ {
+ if (clutter_model_filter_row (model, pos))
+ {
+ if (pos == row)
+ {
+ ClutterModelIter *iter;
+ GValueArray *array;
+
+ iter = g_object_new (CLUTTER_TYPE_MODEL_DEFAULT_ITER,
+ "model", model,
+ "row", pos,
+ NULL);
+ CLUTTER_MODEL_DEFAULT_ITER (iter)->seq_iter = seq_iter;
+
+ g_signal_emit_by_name (model, "row-removed", iter);
+
+ g_object_unref (iter);
+
+ array = g_sequence_get (seq_iter);
+ g_value_array_free (array);
+
+ g_sequence_remove (seq_iter);
+
+ break;
+ }
+ }
+
+ pos += 1;
+ seq_iter = g_sequence_iter_next (seq_iter);
+ }
+}
+
+static guint
+clutter_model_default_get_n_rows (ClutterModel *model)
+{
+ ClutterModelDefault *model_default = CLUTTER_MODEL_DEFAULT (model);
+
+ return g_sequence_get_length (model_default->sequence);
+}
+
+typedef struct
+{
+ ClutterModel *model;
+ guint column;
+ ClutterModelSortFunc func;
+ gpointer data;
+} SortClosure;
+
+static gint
+sort_model_default (gconstpointer a,
+ gconstpointer b,
+ gpointer data)
+{
+ GValueArray *row_a = (GValueArray *) a;
+ GValueArray *row_b = (GValueArray *) b;
+ SortClosure *clos = data;
+
+ return clos->func (clos->model,
+ g_value_array_get_nth (row_a, clos->column),
+ g_value_array_get_nth (row_b, clos->column),
+ clos->data);
+}
+
+static void
+clutter_model_default_resort (ClutterModel *model,
+ ClutterModelSortFunc func,
+ gpointer data)
+{
+ SortClosure sort_closure = { NULL, 0, NULL, NULL };
+
+ sort_closure.model = model;
+ sort_closure.column = clutter_model_get_sorting_column (model);
+ sort_closure.func = func;
+ sort_closure.data = data;
+
+ g_sequence_sort (CLUTTER_MODEL_DEFAULT (model)->sequence,
+ sort_model_default,
+ &sort_closure);
+}
+
+static void
+clutter_model_default_finalize (GObject *gobject)
+{
+ ClutterModelDefault *model = CLUTTER_MODEL_DEFAULT (gobject);
+ GSequenceIter *iter;
+
+ iter = g_sequence_get_begin_iter (model->sequence);
+ while (!g_sequence_iter_is_end (iter))
+ {
+ GValueArray *value_array = g_sequence_get (iter);
+
+ g_value_array_free (value_array);
+ iter = g_sequence_iter_next (iter);
+ }
+ g_sequence_free (model->sequence);
+
+ G_OBJECT_CLASS (clutter_model_default_parent_class)->finalize (gobject);
+}
+
+static void
+clutter_model_default_class_init (ClutterModelDefaultClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ ClutterModelClass *model_class = CLUTTER_MODEL_CLASS (klass);
+
+ gobject_class->finalize = clutter_model_default_finalize;
+
+ model_class->get_n_rows = clutter_model_default_get_n_rows;
+ model_class->get_iter_at_row = clutter_model_default_get_iter_at_row;
+ model_class->insert_row = clutter_model_default_insert_row;
+ model_class->remove_row = clutter_model_default_remove_row;
+ model_class->resort = clutter_model_default_resort;
+}
+
+static void
+clutter_model_default_init (ClutterModelDefault *model)
+{
+ model->sequence = g_sequence_new (NULL);
+}
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Neil Jagdish Patel <njp@o-hand.com>
+ * Emmanuele Bassi <ebassi@openedhand.com>
*
* Copyright (C) 2006 OpenedHand
*
* SECTION:clutter-model
* @short_description: A generic model implementation
*
- * #ClutterModel is a generic list model which can be used to implement the
- * model-view-controller architectural pattern in Clutter.
+ * #ClutterModel is a generic list model API which can be used to implement
+ * the model-view-controller architectural pattern in Clutter.
*
- * The #ClutterModel object is a list model which can accept most GObject
- * types as a column type. Internally, it will keep a local copy of the data
- * passed in (such as a string or a boxed pointer).
+ * The #ClutterModel class is a list model which can accept most GObject
+ * types as a column type.
*
* Creating a simple clutter model:
- * <programlisting>
- * enum {
+ * <informalexample><programlisting>
+ * enum
+ * {
* COLUMN_INT,
- * COLUMN_STRING.
+ * COLUMN_STRING,
+ *
* N_COLUMNS
* };
*
* ClutterModel *model;
* gint i;
*
- * model = clutter_model_new (N_COLUMNS,
- * G_TYPE_INT, "int",
- * G_TYPE_STRING, "string");
+ * model = clutter_model_default_new (N_COLUMNS,
+ * /<!-- -->* column type, column title *<!-- -->/
+ * G_TYPE_INT, "my integers",
+ * G_TYPE_STRING, "my strings");
* for (i = 0; i < 10; i++)
* {
* gchar *string = g_strdup_printf ("String %d", i);
*
*
* }
- * </programlisting>
+ * </programlisting></informalexample>
*
* Iterating through the model consists of retrieving a new #ClutterModelIter
- * pointing to the starting row, and calling #clutter_model_iter_next or
- * #clutter_model_iter_prev to move forward or backwards, repectively.
+ * pointing to the starting row, and calling clutter_model_iter_next() or
+ * clutter_model_iter_prev() to move forward or backwards, repectively.
*
* A valid #ClutterModelIter represents the position between two rows in the
- * model. For example, the @begin iterator represents the gap immediately
- * before the first row, and the @end iterator represents the gap immediately
- * after the last row. In an empty sequence, the begin and end iterators are
+ * model. For example, the "first" iterator represents the gap immediately
+ * before the first row, and the "last" iterator represents the gap immediately
+ * after the last row. In an empty sequence, the first and last iterators are
* the same.
*
* Iterating a #ClutterModel:
- * <programlisting>
- * enum {
+ * <informalexample><programlisting>
+ * enum
+ * {
* COLUMN_INT,
* COLUMN_STRING.
*
* /<!-- -->* Make sure to unref the iter *<!-- -->/
* g_object_unref (iter);
* }
- * </programlisting>
+ * </programlisting></informalexample>
+ *
+ * #ClutterModel is an abstract class. Clutter provides a default model
+ * implementation called #ClutterModelDefault which has been optimised
+ * for insertion and look up in sorted lists.
*
* #ClutterModel is available since Clutter 0.6
*/
+#ifdef HAVE_CONFIG_H
#include "config.h"
+#endif
#include <string.h>
#include <glib-object.h>
#include <gobject/gvaluecollector.h>
#include "clutter-model.h"
+#include "clutter-model-default.h"
+#include "clutter-marshal.h"
+#include "clutter-private.h"
#include "clutter-debug.h"
-G_DEFINE_TYPE (ClutterModel, clutter_model, G_TYPE_OBJECT);
+G_DEFINE_ABSTRACT_TYPE (ClutterModel, clutter_model, G_TYPE_OBJECT);
enum
{
struct _ClutterModelPrivate
{
- GSequence *sequence;
-
GType *column_types;
gchar **column_names;
gint n_columns;
-
- ClutterModelFilterFunc filter;
+
+ ClutterModelFilterFunc filter_func;
gpointer filter_data;
GDestroyNotify filter_notify;
- ClutterModelSortFunc sort;
gint sort_column;
+ ClutterModelSortFunc sort_func;
gpointer sort_data;
GDestroyNotify sort_notify;
};
-/* Forwards */
-static const gchar * _model_get_column_name (ClutterModel *model,
- guint column);
-static GType _model_get_column_type (ClutterModel *model,
- guint column);
-static ClutterModelIter * _model_get_iter_at_row (ClutterModel *model,
- guint row);
-static void clutter_model_real_remove (ClutterModel *model,
- GSequenceIter *iter);
+static GType
+clutter_model_real_get_column_type (ClutterModel *model,
+ guint column)
+{
+ ClutterModelPrivate *priv = model->priv;
+
+ if (column < 0 || column >= clutter_model_get_n_columns (model))
+ return G_TYPE_INVALID;
+
+ return priv->column_types[column];
+}
+
+static const gchar *
+clutter_model_real_get_column_name (ClutterModel *model,
+ guint column)
+{
+ ClutterModelPrivate *priv = model->priv;
+
+ if (column < 0 || column >= clutter_model_get_n_columns (model))
+ return NULL;
+
+ if (priv->column_names && priv->column_names[column])
+ return priv->column_names[column];
+
+ return g_type_name (priv->column_types[column]);
+}
+
+static guint
+clutter_model_real_get_n_columns (ClutterModel *model)
+{
+ return model->priv->n_columns;
+}
static void
clutter_model_finalize (GObject *object)
{
ClutterModelPrivate *priv = CLUTTER_MODEL (object)->priv;
- GSequenceIter *iter;
-
- iter = g_sequence_get_end_iter (priv->sequence);
- while (!g_sequence_iter_is_end (iter))
- {
- clutter_model_real_remove (CLUTTER_MODEL (object), iter);
- iter = g_sequence_iter_next (iter);
- }
- g_sequence_free (priv->sequence);
+ gint i;
if (priv->sort_notify)
priv->sort_notify (priv->sort_data);
priv->filter_notify (priv->filter_data);
g_free (priv->column_types);
- g_strfreev (priv->column_names);
+
+ /* the column_names vector might have holes in it, so we need to
+ * use the columns number to clear up everything
+ */
+ for (i = 0; i < priv->n_columns; i++)
+ g_free (priv->column_names[i]);
+
+ g_free (priv->column_names);
G_OBJECT_CLASS (clutter_model_parent_class)->finalize (object);
}
gobject_class->finalize = clutter_model_finalize;
- klass->get_iter_at_row = _model_get_iter_at_row;
- klass->get_column_name = _model_get_column_name;
- klass->get_column_type = _model_get_column_type;
+ g_type_class_add_private (gobject_class, sizeof (ClutterModelPrivate));
+
+ klass->get_column_name = clutter_model_real_get_column_name;
+ klass->get_column_type = clutter_model_real_get_column_type;
+ klass->get_n_columns = clutter_model_real_get_n_columns;
/**
* ClutterModel::row-added:
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterModelClass, row_added),
NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
-
+ clutter_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ CLUTTER_TYPE_MODEL_ITER);
/**
* ClutterModel::row-removed:
* @model: the #ClutterModel on which the signal is emitted
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterModelClass, row_removed),
NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
-
+ clutter_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ CLUTTER_TYPE_MODEL_ITER);
/**
* ClutterModel::row-changed:
* @model: the #ClutterModel on which the signal is emitted
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterModelClass, row_changed),
NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
-
+ clutter_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ CLUTTER_TYPE_MODEL_ITER);
/**
* ClutterModel::sort-changed:
* @model: the #ClutterModel on which the signal is emitted
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterModelClass, sort_changed),
NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
+ clutter_marshal_VOID__VOID,
G_TYPE_NONE, 0);
-
/**
* ClutterModel::filter-changed:
* @model: the #ClutterModel on which the signal is emitted
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterModelClass, filter_changed),
NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
+ clutter_marshal_VOID__VOID,
G_TYPE_NONE, 0);
-
- g_type_class_add_private (gobject_class, sizeof (ClutterModelPrivate));
}
static void
self->priv = priv = CLUTTER_MODEL_GET_PRIVATE (self);
- priv->sequence = g_sequence_new (NULL);
-
- priv->column_types = NULL;
priv->n_columns = -1;
+ priv->column_types = NULL;
+ priv->column_names = NULL;
- priv->filter = NULL;
+ priv->filter_func = NULL;
priv->filter_data = NULL;
priv->filter_notify = NULL;
- priv->sort = NULL;
- priv->sort_data = NULL;
+
priv->sort_column = -1;
+ priv->sort_func = NULL;
+ priv->sort_data = NULL;
priv->sort_notify = NULL;
}
-
+/* XXX - is this whitelist really necessary? we accept every fundamental
+ * type.
+ */
static gboolean
clutter_model_check_type (type)
{
if (! G_TYPE_IS_VALUE_TYPE (type))
return FALSE;
-
while (type_list[i] != G_TYPE_INVALID)
{
if (g_type_is_a (type, type_list[i]))
return FALSE;
}
-static gint
-_model_sort_func (GValueArray *val_a,
- GValueArray *val_b,
- ClutterModel *model)
-{
- ClutterModelPrivate *priv;
- const GValue *a;
- const GValue *b;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL (model), 0);
- g_return_val_if_fail (val_a, 0);
- g_return_val_if_fail (val_b, 0);
- priv = model->priv;
-
- a = g_value_array_get_nth (val_a, priv->sort_column);
- b = g_value_array_get_nth (val_b, priv->sort_column);
-
- return priv->sort (model, a, b, priv->sort_data);
-}
-
-static void
-_model_sort (ClutterModel *model)
+/**
+ * clutter_model_resort:
+ * @model: a #ClutterModel
+ *
+ * Force a resort on the @model. This function should only be
+ * used by subclasses of #ClutterModel.
+ *
+ * Since: 0.6
+ */
+void
+clutter_model_resort (ClutterModel *model)
{
ClutterModelPrivate *priv;
+ ClutterModelClass *klass;
g_return_if_fail (CLUTTER_IS_MODEL (model));
priv = model->priv;
- if (!priv->sort)
+ if (!priv->sort_func)
return;
- g_sequence_sort (priv->sequence, (GCompareDataFunc)_model_sort_func, model);
-}
+ klass = CLUTTER_MODEL_GET_CLASS (model);
+ if (klass->resort)
+ klass->resort (model, priv->sort_func, priv->sort_data);
+}
-static gboolean
-_model_filter (ClutterModel *model, ClutterModelIter *iter)
+/**
+ * clutter_model_filter_row:
+ * @model: a #ClutterModel
+ * @row: the row to filter
+ *
+ * Checks whether @row should be filtered or not using the
+ * filtering function set on @model.
+ *
+ * This function should be used only by subclasses of #ClutterModel.
+ *
+ * Return value: %TRUE if the row should be displayed,
+ * %FALSE otherwise
+ *
+ * Since: 0.6
+ */
+gboolean
+clutter_model_filter_row (ClutterModel *model,
+ guint row)
{
ClutterModelPrivate *priv;
+ ClutterModelIter *iter;
gboolean res = TRUE;
g_return_val_if_fail (CLUTTER_IS_MODEL (model), TRUE);
+
priv = model->priv;
- if (!priv->filter)
+ if (!priv->filter_func)
return TRUE;
- res = priv->filter (model, iter, priv->filter_data);
+ iter = clutter_model_get_iter_at_row (model, row);
+ if (!iter)
+ return FALSE;
+
+ res = priv->filter_func (model, iter, priv->filter_data);
+
+ g_object_unref (iter);
return res;
}
+/**
+ * clutter_model_filter_iter:
+ * @model: a #ClutterModel
+ * @iter: the row to filter
+ *
+ * Checks whether the row pointer by @iter should be filtered or not using
+ * the filtering function set on @model.
+ *
+ * This function should be used only by subclasses of #ClutterModel.
+ *
+ * Return value: %TRUE if the row should be displayed,
+ * %FALSE otherwise
+ *
+ * Since: 0.6
+ */
+gboolean
+clutter_model_filter_iter (ClutterModel *model,
+ ClutterModelIter *iter)
+{
+ ClutterModelPrivate *priv;
+
+ g_return_val_if_fail (CLUTTER_IS_MODEL (model), TRUE);
+ g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), TRUE);
+
+ priv = model->priv;
+
+ if (!priv->filter_func)
+ return TRUE;
+
+ return priv->filter_func (model, iter, priv->filter_data);
+}
static void
clutter_model_set_n_columns (ClutterModel *model,
priv->column_names = g_new0 (gchar*, n_columns + 1);
}
-static void
+static inline void
clutter_model_set_column_type (ClutterModel *model,
gint column,
GType type)
priv->column_types[column] = type;
}
-static void
+static inline void
clutter_model_set_column_name (ClutterModel *model,
gint column,
const gchar *name)
priv->column_names[column] = g_strdup (name);
}
+/* we implement the constructors of the default model here because
+ * we need the private accessors to the column names and types
+ * vectors inside ClutterModelPrivate; the ClutterModelDefault ctors
+ * are declared inside clutter-model-default.h
+ */
+
/**
- * clutter_model_new:
+ * clutter_model_default_new:
* @n_columns: number of columns in the model
* @Varargs: @n_columns number of #GType and string pairs
*
- * Creates a new model with @n_columns columns with the types
+ * Creates a new default model with @n_columns columns with the types
* and names passed in.
*
* For example:
*
* <informalexample><programlisting>
- * model = clutter_model_new (3,
- * G_TYPE_INT, "int column",
- * G_TYPE_STRING, "string column",
- * GDK_TYPE_PIXBUF, "pixbuf column");
+ * model = clutter_model_default_new (3,
+ * G_TYPE_INT, "Score",
+ * G_TYPE_STRING, "Team",
+ * GDK_TYPE_PIXBUF, "Logo");
* </programlisting></informalexample>
*
* will create a new #ClutterModel with three columns of type int,
* Since 0.6
*/
ClutterModel *
-clutter_model_new (guint n_columns,
- ...)
+clutter_model_default_new (guint n_columns,
+ ...)
{
ClutterModel *model;
va_list args;
g_return_val_if_fail (n_columns > 0, NULL);
- model = g_object_new (CLUTTER_TYPE_MODEL, NULL);
+ model = g_object_new (CLUTTER_TYPE_MODEL_DEFAULT, NULL);
clutter_model_set_n_columns (model, n_columns, TRUE, TRUE);
va_start (args, n_columns);
{
GType type = va_arg (args, GType);
const gchar *name = va_arg (args, gchar*);
-
+
if (!clutter_model_check_type (type))
{
g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
}
/**
- * clutter_model_newv:
+ * clutter_model_default_newv:
* @n_columns: number of columns in the model
* @types: an array of #GType types for the columns, from first to last
* @names: an array of names for the columns, from first to last
*
- * Non-vararg creation function. Used primarily by language bindings.
+ * Non-vararg creation function. Useful primarily by language bindings.
*
* Return value: a new #ClutterModel
*
* Since 0.6
*/
ClutterModel *
-clutter_model_newv (guint n_columns,
- GType *types,
- const gchar * const names[])
+clutter_model_default_newv (guint n_columns,
+ GType *types,
+ const gchar * const names[])
{
ClutterModel *model;
gint i;
g_return_val_if_fail (n_columns > 0, NULL);
- model = g_object_new (CLUTTER_TYPE_MODEL, NULL);
+ model = g_object_new (CLUTTER_TYPE_MODEL_DEFAULT, NULL);
clutter_model_set_n_columns (model, n_columns, TRUE, TRUE);
for (i = 0; i < n_columns; i++)
{
g_return_val_if_fail (CLUTTER_IS_MODEL (model), 0);
- return model->priv->n_columns;
-}
-
-static GValueArray *
-clutter_model_new_row (ClutterModel *model)
-{
- ClutterModelPrivate *priv;
- GValueArray *row;
- gint i;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL (model), NULL);
- priv = model->priv;
-
- row = g_value_array_new (priv->n_columns);
-
- for (i = 0; i < priv->n_columns; i++)
- {
- GValue value = { 0, };
-
- g_value_init (&value, priv->column_types[i]);
- g_value_array_append (row, &value);
- g_value_unset (&value);
- }
-
- return row;
+ return CLUTTER_MODEL_GET_CLASS (model)->get_n_columns (model);
}
/**
{
ClutterModelPrivate *priv;
ClutterModelIter *iter;
- GSequenceIter *seq_iter;
- GValueArray *row;
g_return_if_fail (CLUTTER_IS_MODEL (model));
priv = model->priv;
- row = clutter_model_new_row (model);
- seq_iter = g_sequence_append (priv->sequence, row);
-
- iter = g_object_new (CLUTTER_TYPE_MODEL_ITER,
- "model", model,
- "iter", seq_iter,
- NULL);
+ iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, -1);
+ g_assert (CLUTTER_IS_MODEL_ITER (iter));
clutter_model_iter_set_value (iter, column, value);
+ g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
+
if (priv->sort_column == column)
- _model_sort (model);
+ clutter_model_resort (model);
- g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
g_object_unref (iter);
}
*
* <informalexample><programlisting>
* ClutterModel *model;
- * model = clutter_model_new (2,
- * G_TYPE_INT, "My integers",
- * G_TYPE_STRING, "My strings");
+ * model = clutter_model_default_new (2,
+ * G_TYPE_INT, "My integers",
+ * G_TYPE_STRING, "My strings");
* clutter_model_append (model, 0, 42, 1, "string", -1);
* </programlisting></informalexample>
*
{
ClutterModelPrivate *priv;
ClutterModelIter *iter;
- GSequenceIter *seq_iter;
- GValueArray *row;
va_list args;
g_return_if_fail (CLUTTER_IS_MODEL (model));
priv = model->priv;
- row = clutter_model_new_row (model);
- seq_iter = g_sequence_append (priv->sequence, row);
-
- iter = g_object_new (CLUTTER_TYPE_MODEL_ITER,
- "model", model,
- "iter", seq_iter,
- NULL);
+ iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, -1);
+ g_assert (CLUTTER_IS_MODEL_ITER (iter));
va_start (args, model);
clutter_model_iter_set_valist (iter, args);
va_end (args);
- /*FIXME: Sort the model if necessary */
g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
+
g_object_unref (iter);
}
{
ClutterModelPrivate *priv;
ClutterModelIter *iter;
- GSequenceIter *seq_iter;
- GValueArray *row;
g_return_if_fail (CLUTTER_IS_MODEL (model));
priv = model->priv;
- row = clutter_model_new_row (model);
- seq_iter = g_sequence_prepend (priv->sequence, row);
-
- iter = g_object_new (CLUTTER_TYPE_MODEL_ITER,
- "model", model,
- "iter", seq_iter,
- NULL);
+ iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, 0);
+ g_assert (CLUTTER_IS_MODEL_ITER (iter));
clutter_model_iter_set_value (iter, column, value);
+ g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
+
if (priv->sort_column == column)
- _model_sort (model);
+ clutter_model_resort (model);
- g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
g_object_unref (iter);
}
*
* <informalexample><programlisting>
* ClutterModel *model;
- * model = clutter_model_new (2,
- * G_TYPE_INT, "My integers",
- * G_TYPE_STRING, "My strings");
+ * model = clutter_model_default_new (2,
+ * G_TYPE_INT, "My integers",
+ * G_TYPE_STRING, "My strings");
* clutter_model_prepend (model, 0, 42, 1, "string", -1);
* </programlisting></informalexample>
*
clutter_model_prepend (ClutterModel *model,
...)
{
- ClutterModelPrivate *priv;
ClutterModelIter *iter;
- GSequenceIter *seq_iter;
- GValueArray *row;
va_list args;
g_return_if_fail (CLUTTER_IS_MODEL (model));
- priv = model->priv;
-
- row = clutter_model_new_row (model);
- seq_iter = g_sequence_prepend (priv->sequence, row);
+ iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, 0);
+ g_assert (CLUTTER_IS_MODEL_ITER (iter));
- iter = g_object_new (CLUTTER_TYPE_MODEL_ITER,
- "model", model,
- "iter", seq_iter,
- NULL);
va_start (args, model);
clutter_model_iter_set_valist (iter, args);
va_end (args);
- /*FIXME: Sort the model if necessary */
- g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
+ g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
+
g_object_unref (iter);
}
*
* <informalexample><programlisting>
* ClutterModel *model;
- * model = clutter_model_new (2,
- * G_TYPE_INT, "My integers",
- * G_TYPE_STRING, "My strings");
+ * model = clutter_model_default_new (2,
+ * G_TYPE_INT, "My integers",
+ * G_TYPE_STRING, "My strings");
* clutter_model_insert (model, 100, 0, 42, 1, "string", -1);
* </programlisting></informalexample>
*
guint row,
...)
{
- ClutterModelPrivate *priv;
ClutterModelIter *iter;
- GValueArray *row_array;
- GSequenceIter *seq_iter;
va_list args;
g_return_if_fail (CLUTTER_IS_MODEL (model));
- priv = model->priv;
-
- row_array = clutter_model_new_row (model);
-
- seq_iter = g_sequence_get_iter_at_pos (priv->sequence, row);
- seq_iter = g_sequence_insert_before (seq_iter, row_array);
-
- iter = g_object_new (CLUTTER_TYPE_MODEL_ITER,
- "model", model,
- "iter", seq_iter,
- NULL);
+ iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, row);
+ g_assert (CLUTTER_IS_MODEL_ITER (iter));
+ /* set_valist() will call clutter_model_resort() if one of the
+ * passed columns matches the model sorting column index
+ */
va_start (args, row);
clutter_model_iter_set_valist (iter, args);
va_end (args);
- /* FIXME: Sort? */
-
g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
+
g_object_unref (iter);
}
* @value: new value for the cell
*
* Sets the data in the cell specified by @iter and @column. The type of
- * @value must be convertable to the type of the column.
+ * @value must be convertable to the type of the column. If the row does
+ * not exist then it is created.
*
* Since 0.6
*/
const GValue *value)
{
ClutterModelPrivate *priv;
+ ClutterModelClass *klass;
ClutterModelIter *iter;
- GSequenceIter *seq_iter;
+ gboolean added = FALSE;
g_return_if_fail (CLUTTER_IS_MODEL (model));
priv = model->priv;
+ klass = CLUTTER_MODEL_GET_CLASS (model);
- seq_iter = g_sequence_get_iter_at_pos (priv->sequence, row);
-
- iter = g_object_new (CLUTTER_TYPE_MODEL_ITER,
- "model", model,
- "iter", seq_iter,
- NULL);
+ iter = klass->get_iter_at_row (model, row);
+ if (!iter)
+ {
+ iter = klass->insert_row (model, row);
+ added = TRUE;
+ }
+
+ g_assert (CLUTTER_IS_MODEL_ITER (iter));
clutter_model_iter_set_value (iter, column, value);
+ if (added)
+ g_signal_emit (model, model_signals[ROW_ADDED], 0, iter);
+
if (priv->sort_column == column)
- _model_sort (model);
+ clutter_model_resort (model);
- g_signal_emit (model, model_signals[ROW_CHANGED], 0, iter);
g_object_unref (iter);
}
-static void
-clutter_model_real_remove (ClutterModel *model,
- GSequenceIter *iter)
-{
- ClutterModelPrivate *priv;
- GValueArray *value_array;
-
- g_return_if_fail (CLUTTER_IS_MODEL (model));
- priv = model->priv;
-
- value_array = g_sequence_get (iter);
- g_value_array_free (value_array);
-}
-
/**
* clutter_model_remove:
* @model: a #ClutterModel
clutter_model_remove (ClutterModel *model,
guint row)
{
- ClutterModelPrivate *priv;
- ClutterModelIter *iter;
- GSequenceIter *seq_iter;
- gint i = 0;
+ ClutterModelClass *klass;
g_return_if_fail (CLUTTER_IS_MODEL (model));
- priv = model->priv;
- seq_iter = g_sequence_get_begin_iter (priv->sequence);
- iter = g_object_new (CLUTTER_TYPE_MODEL_ITER, "model", model, NULL);
-
- while (!g_sequence_iter_is_end (seq_iter))
- {
- g_object_set (iter, "iter", seq_iter, NULL);
- if (_model_filter (model, iter))
- {
- if (i == row)
- {
- g_signal_emit (model, model_signals[ROW_REMOVED], 0, iter);
- clutter_model_real_remove (model, seq_iter);
- g_sequence_remove (seq_iter);
- break;
- }
- i++;
- }
- seq_iter = g_sequence_iter_next (seq_iter);
- }
- g_object_unref (iter);
-}
-
-static const gchar *
-_model_get_column_name (ClutterModel *model,
- guint column)
-{
- ClutterModelPrivate *priv = model->priv;
-
- if (column < 0 || column >= priv->n_columns)
- return NULL;
-
- if (priv->column_names && priv->column_names[column])
- return priv->column_names[column];
-
- return g_type_name (priv->column_types[column]);
+ klass = CLUTTER_MODEL_GET_CLASS (model);
+ if (klass->remove_row)
+ klass->remove_row (model, row);
}
/**
g_return_val_if_fail (CLUTTER_IS_MODEL (model), NULL);
priv = model->priv;
- if (column < 0 || column > priv->n_columns)
+ if (column < 0 || column > clutter_model_get_n_columns (model))
{
g_warning ("%s: Invalid column id value %d\n", G_STRLOC, column);
return NULL;
return NULL;
}
-static GType
-_model_get_column_type (ClutterModel *model,
- guint column)
-{
- ClutterModelPrivate *priv = model->priv;
-
- if (column < 0 || column >= priv->n_columns)
- return G_TYPE_INVALID;
-
- return priv->column_types[column];
-}
-
/**
* clutter_model_get_column_type:
* @model: #ClutterModel
g_return_val_if_fail (CLUTTER_IS_MODEL (model), G_TYPE_INVALID);
priv = model->priv;
- if (column < 0 || column > priv->n_columns)
+ if (column < 0 || column > clutter_model_get_n_columns (model))
{
g_warning ("%s: Invalid column id value %d\n", G_STRLOC, column);
return G_TYPE_INVALID;
return G_TYPE_INVALID;
}
-static ClutterModelIter *
-_model_get_iter_at_row (ClutterModel *model,
- guint row)
-{
- return g_object_new (CLUTTER_TYPE_MODEL_ITER,
- "model", model,
- "row", row,
- NULL);
-}
-
/**
* clutter_model_get_iter_at_row:
* @model: a #ClutterModel
length = clutter_model_get_n_rows (model);
- return clutter_model_get_iter_at_row (model, length-1);
+ return clutter_model_get_iter_at_row (model, length - 1);
}
/**
* Retrieves the number of rows inside @model.
*
* Return value: The length of the @model. If there is a filter set, then
- * thelength of the filtered @model is returned.
+ * the length of the filtered @model is returned.
*
* Since 0.6
*/
{
ClutterModelPrivate *priv;
ClutterModelIter *iter;
- GSequenceIter *seq_iter;
- guint i = 0;
+ guint n_rows;
g_return_val_if_fail (CLUTTER_IS_MODEL (model), 0);
+
priv = model->priv;
- seq_iter = g_sequence_get_begin_iter (priv->sequence);
- iter = g_object_new (CLUTTER_TYPE_MODEL_ITER, "model", model, NULL);
+ /* if there's no filter set, just get the full number of rows */
+ if (!priv->filter_func)
+ return CLUTTER_MODEL_GET_CLASS (model)->get_n_rows (model);
+
+ iter = clutter_model_get_first_iter (model);
+ if (!iter)
+ return 0;
- while (!g_sequence_iter_is_end (seq_iter))
+ n_rows = 0;
+ while (!clutter_model_iter_is_last (iter))
{
- g_object_set (iter, "iter", seq_iter, NULL);
- if (_model_filter (model, iter))
- {
- i++;
- }
- seq_iter = g_sequence_iter_next (seq_iter);
+ if (clutter_model_filter_iter (model, iter))
+ n_rows += 1;
+
+ iter = clutter_model_iter_next (iter);
}
g_object_unref (iter);
-
- return i;
+
+ return n_rows;
}
g_return_if_fail (CLUTTER_IS_MODEL (model));
priv = model->priv;
- if (column > priv->n_columns)
+ if (column > clutter_model_get_n_columns (model))
{
g_warning ("%s: Invalid column id value %d\n", G_STRLOC, column);
return;
priv->sort_column = column;
if (priv->sort_column > 0)
- _model_sort (model);
+ clutter_model_resort (model);
g_signal_emit (model, model_signals[SORT_CHANGED], 0);
}
ClutterModelForeachFunc func,
gpointer user_data)
{
- ClutterModelPrivate *priv;
ClutterModelIter *iter;
- GSequenceIter *seq_iter;
g_return_if_fail (CLUTTER_IS_MODEL (model));
- priv = model->priv;
- seq_iter = g_sequence_get_begin_iter (priv->sequence);
- iter = g_object_new (CLUTTER_TYPE_MODEL_ITER, "model", model, NULL);
+ iter = clutter_model_get_first_iter (model);
+ if (!iter)
+ return;
- while (!g_sequence_iter_is_end (seq_iter))
+ while (!clutter_model_iter_is_last (iter))
{
- g_object_set (iter, "iter", seq_iter, NULL);
- if (_model_filter (model, iter))
+ if (clutter_model_filter_iter (model, iter))
{
if (!func (model, iter, user_data))
break;
}
- seq_iter = g_sequence_iter_next (seq_iter);
+
+ iter = clutter_model_iter_next (iter);
}
g_object_unref (iter);
g_return_if_fail (CLUTTER_IS_MODEL (model));
priv = model->priv;
- if (priv->sort_data && priv->sort_notify)
+ if (priv->sort_notify)
priv->sort_notify (priv->sort_data);
- priv->sort = func;
+ priv->sort_func = func;
priv->sort_data = user_data;
priv->sort_notify = notify;
g_return_if_fail (CLUTTER_IS_MODEL (model));
priv = model->priv;
- if (priv->filter_data && priv->filter_notify)
+ if (priv->filter_notify)
priv->filter_notify (priv->filter_data);
- priv->filter = func;
+ priv->filter_func = func;
priv->filter_data = user_data;
priv->filter_notify = notify;
* clutter_model_get_last_iter() represents the gap immediately after the
* last row.
*
- * A #ClutterModelIter can only be created by a #ClutterModel and it is
- * valid as long as the model does not change.
+ * A #ClutterModelIter can only be created by a #ClutterModel implementation
+ * and it is valid as long as the model does not change.
*
* #ClutterModelIter is available since Clutter 0.6
*/
-G_DEFINE_TYPE (ClutterModelIter, clutter_model_iter, G_TYPE_OBJECT);
+G_DEFINE_ABSTRACT_TYPE (ClutterModelIter, clutter_model_iter, G_TYPE_OBJECT);
#define CLUTTER_MODEL_ITER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
struct _ClutterModelIterPrivate
{
ClutterModel *model;
- GSequenceIter *seq_iter;
- gboolean ignore_sort;
+ gint row;
+
+ guint ignore_sort : 1;
};
enum
ITER_PROP_0,
ITER_PROP_MODEL,
- ITER_PROP_ROW,
- ITER_PROP_ITER,
+ ITER_PROP_ROW
};
-/* Forwards */
-static void _model_iter_get_value (ClutterModelIter *iter,
- guint column,
- GValue *value);
-static void _model_iter_set_value (ClutterModelIter *iter,
- guint column,
- const GValue *value);
-static gboolean _model_iter_is_first (ClutterModelIter *iter);
-static gboolean _model_iter_is_last (ClutterModelIter *iter);
-static ClutterModelIter * _model_iter_next (ClutterModelIter *iter);
-static ClutterModelIter * _model_iter_prev (ClutterModelIter *iter);
-static ClutterModel * _model_iter_get_model (ClutterModelIter *iter);
-static guint _model_iter_get_row (ClutterModelIter *iter);
-static void _model_iter_set_row (ClutterModelIter *iter,
- guint row);
-
-/* GObject stuff */
+static ClutterModel *
+clutter_model_iter_real_get_model (ClutterModelIter *iter)
+{
+ return iter->priv->model;
+}
+
+static guint
+clutter_model_iter_real_get_row (ClutterModelIter *iter)
+{
+ return iter->priv->row;
+}
+
+static void
+clutter_model_iter_get_value_unimplemented (ClutterModelIter *iter,
+ guint column,
+ GValue *value)
+{
+ g_warning ("%s: Iterator of type `%s' does not implement the "
+ "ClutterModelIter::get_value() virtual function",
+ G_STRLOC,
+ g_type_name (G_OBJECT_TYPE (iter)));
+}
+
+static void
+clutter_model_iter_set_value_unimplemented (ClutterModelIter *iter,
+ guint column,
+ const GValue *value)
+{
+ g_warning ("%s: Iterator of type `%s' does not implement the "
+ "ClutterModelIter::set_value() virtual function",
+ G_STRLOC,
+ g_type_name (G_OBJECT_TYPE (iter)));
+}
+
+static gboolean
+clutter_model_iter_is_first_unimplemented (ClutterModelIter *iter)
+{
+ g_warning ("%s: Iterator of type `%s' does not implement the "
+ "ClutterModelIter::is_first() virtual function",
+ G_STRLOC,
+ g_type_name (G_OBJECT_TYPE (iter)));
+ return FALSE;
+}
+
+static gboolean
+clutter_model_iter_is_last_unimplemented (ClutterModelIter *iter)
+{
+ g_warning ("%s: Iterator of type `%s' does not implement the "
+ "ClutterModelIter::is_last() virtual function",
+ G_STRLOC,
+ g_type_name (G_OBJECT_TYPE (iter)));
+ return FALSE;
+}
+
+static ClutterModelIter *
+clutter_model_iter_next_unimplemented (ClutterModelIter *iter)
+{
+ g_warning ("%s: Iterator of type `%s' does not implement the "
+ "ClutterModelIter::next() virtual function",
+ G_STRLOC,
+ g_type_name (G_OBJECT_TYPE (iter)));
+ return NULL;
+}
+
+static ClutterModelIter *
+clutter_model_iter_prev_unimplemented (ClutterModelIter *iter)
+{
+ g_warning ("%s: Iterator of type `%s' does not implement the "
+ "ClutterModelIter::prev() virtual function",
+ G_STRLOC,
+ g_type_name (G_OBJECT_TYPE (iter)));
+ return NULL;
+}
+
static void
clutter_model_iter_get_property (GObject *object,
guint prop_id,
GParamSpec *pspec)
{
ClutterModelIter *iter = CLUTTER_MODEL_ITER (object);
- ClutterModelIterPrivate *priv;
-
- g_return_if_fail (CLUTTER_IS_MODEL_ITER (object));
- priv = iter->priv;
+ ClutterModelIterPrivate *priv = iter->priv;
switch (prop_id)
{
- case ITER_PROP_MODEL:
- g_value_set_object (value, priv->model);
- break;
- case ITER_PROP_ROW:
- g_value_set_uint (value, clutter_model_iter_get_row (iter));
- break;
- case ITER_PROP_ITER:
- g_value_set_pointer (value, priv->seq_iter);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ case ITER_PROP_MODEL:
+ g_value_set_object (value, priv->model);
+ break;
+ case ITER_PROP_ROW:
+ g_value_set_uint (value, priv->row);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
}
}
GParamSpec *pspec)
{
ClutterModelIter *iter = CLUTTER_MODEL_ITER (object);
- ClutterModelIterPrivate *priv;
-
- g_return_if_fail (CLUTTER_IS_MODEL_ITER (object));
- priv = iter->priv;
+ ClutterModelIterPrivate *priv = iter->priv;
switch (prop_id)
{
- case ITER_PROP_MODEL:
- priv->model = g_value_get_object (value);
- break;
- case ITER_PROP_ROW:
- _model_iter_set_row (iter, g_value_get_uint (value));
- break;
- case ITER_PROP_ITER:
- priv->seq_iter = g_value_get_pointer (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ case ITER_PROP_MODEL:
+ priv->model = g_value_get_object (value);
+ break;
+ case ITER_PROP_ROW:
+ priv->row = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
}
}
gobject_class->get_property = clutter_model_iter_get_property;
gobject_class->set_property = clutter_model_iter_set_property;
- klass->get_value = _model_iter_get_value;
- klass->set_value = _model_iter_set_value;
- klass->is_first = _model_iter_is_first;
- klass->is_last = _model_iter_is_last;
- klass->next = _model_iter_next;
- klass->prev = _model_iter_prev;
- klass->get_model = _model_iter_get_model;
- klass->get_row = _model_iter_get_row;
+ klass->get_model = clutter_model_iter_real_get_model;
+ klass->get_row = clutter_model_iter_real_get_row;
+ klass->is_first = clutter_model_iter_is_first_unimplemented;
+ klass->is_last = clutter_model_iter_is_last_unimplemented;
+ klass->next = clutter_model_iter_next_unimplemented;
+ klass->prev = clutter_model_iter_prev_unimplemented;
+ klass->get_value = clutter_model_iter_get_value_unimplemented;
+ klass->set_value = clutter_model_iter_set_value_unimplemented;
/* Properties */
* Since: 0.6
*/
g_object_class_install_property (gobject_class,
- ITER_PROP_MODEL,
- g_param_spec_object ("model",
- "Model",
- "A ClutterModel",
- CLUTTER_TYPE_MODEL,
- G_PARAM_READWRITE));
+ ITER_PROP_MODEL,
+ g_param_spec_object ("model",
+ "Model",
+ "The model to which the iterator belongs to",
+ CLUTTER_TYPE_MODEL,
+ CLUTTER_PARAM_READWRITE));
/**
* ClutterModelIter:row:
*
- * A reference to the row number that this iter represents.
+ * The row number to which this iter points to.
*
* Since: 0.6
*/
g_object_class_install_property (gobject_class,
- ITER_PROP_ROW,
- g_param_spec_uint ("row",
- "Row",
- "The row number",
- 0, 65535, 0,
- G_PARAM_READWRITE));
-
- /**
- * ClutterModelIter:iter:
- *
- * An internal iter reference. This property should only be used when
- * sub-classing #ClutterModelIter.
- *
- * Since: 0.6
- */
- g_object_class_install_property (gobject_class,
- ITER_PROP_ITER,
- g_param_spec_pointer ("iter",
- "Iter",
- "The internal iter reference",
- G_PARAM_READWRITE));
+ ITER_PROP_ROW,
+ g_param_spec_uint ("row",
+ "Row",
+ "The row to which the iterator points to",
+ 0, G_MAXUINT, 0,
+ CLUTTER_PARAM_READWRITE));
g_type_class_add_private (gobject_class, sizeof (ClutterModelIterPrivate));
}
self->priv = priv = CLUTTER_MODEL_ITER_GET_PRIVATE (self);
- priv->seq_iter = NULL;
priv->model = NULL;
- priv->ignore_sort = FALSE;
-}
-
-static void
-_model_iter_get_value (ClutterModelIter *iter,
- guint column,
- GValue *value)
-{
- ClutterModelIterPrivate *priv;
- GValueArray *value_array;
- GValue *iter_value;
- GValue real_value = { 0, };
- gboolean converted = FALSE;
-
- g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter));
- priv = iter->priv;
- g_return_if_fail (CLUTTER_IS_MODEL (priv->model));
- g_return_if_fail (priv->seq_iter);
-
- value_array = g_sequence_get (priv->seq_iter);
- iter_value = g_value_array_get_nth (value_array, column);
-
- if (!g_type_is_a (G_VALUE_TYPE (value), G_VALUE_TYPE (iter_value)))
- {
- if (!g_value_type_compatible (G_VALUE_TYPE (value),
- G_VALUE_TYPE (iter_value)) &&
- !g_value_type_compatible (G_VALUE_TYPE (iter_value),
- G_VALUE_TYPE (value)))
- {
- g_warning ("%s: Unable to convert from %s to %s\n",
- G_STRLOC,
- g_type_name (G_VALUE_TYPE (value)),
- g_type_name (G_VALUE_TYPE (iter_value)));
- return;
- }
- if (!g_value_transform (value, &real_value))
- {
- g_warning ("%s: Unable to make conversion from %s to %s\n",
- G_STRLOC,
- g_type_name (G_VALUE_TYPE (value)),
- g_type_name (G_VALUE_TYPE (iter_value)));
- g_value_unset (&real_value);
- }
- converted = TRUE;
- }
-
- if (converted)
- g_value_copy (&real_value, value);
- else
- g_value_copy (iter_value, value);
-}
-
-static void
-_model_iter_set_value (ClutterModelIter *iter,
- guint column,
- const GValue *value)
-{
- ClutterModelPrivate *model_priv;
- ClutterModelIterPrivate *priv;
- GValueArray *value_array;
- GValue *iter_value;
- GValue real_value = { 0, };
- gboolean converted = FALSE;
-
- g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter));
- priv = iter->priv;
- g_return_if_fail (CLUTTER_IS_MODEL (priv->model));
- g_return_if_fail (priv->seq_iter);
-
- model_priv = priv->model->priv;
-
- value_array = g_sequence_get (priv->seq_iter);
- iter_value = g_value_array_get_nth (value_array, column);
-
- if (!g_type_is_a (G_VALUE_TYPE (value), G_VALUE_TYPE (iter_value)))
- {
- if (!g_value_type_compatible (G_VALUE_TYPE (value),
- G_VALUE_TYPE (iter_value)) &&
- !g_value_type_compatible (G_VALUE_TYPE (iter_value),
- G_VALUE_TYPE (value)))
- {
- g_warning ("%s: Unable to convert from %s to %s\n",
- G_STRLOC,
- g_type_name (G_VALUE_TYPE (value)),
- g_type_name (G_VALUE_TYPE (iter_value)));
- return;
- }
- if (!g_value_transform (value, &real_value))
- {
- g_warning ("%s: Unable to make conversion from %s to %s\n",
- G_STRLOC,
- g_type_name (G_VALUE_TYPE (value)),
- g_type_name (G_VALUE_TYPE (iter_value)));
- g_value_unset (&real_value);
- }
- converted = TRUE;
- }
-
- if (converted)
- {
- g_value_copy (&real_value, iter_value);
- g_value_unset (&real_value);
- }
- else
- g_value_copy (value, iter_value);
-
- /* Check if we need to sort */
- if (!priv->ignore_sort)
- {
- if (model_priv->sort_column == column && model_priv->sort)
- _model_sort (priv->model);
-
- g_signal_emit (priv->model, model_signals[ROW_CHANGED], 0, iter);
- }
-}
-
-static gboolean
-_model_iter_is_first (ClutterModelIter *iter)
-{
- ClutterModel *model = NULL;
- ClutterModelPrivate *model_priv;
- ClutterModelIterPrivate *iter_priv;
- GSequenceIter *begin, *end;
- ClutterModelIter *temp_iter;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), TRUE);
- iter_priv = iter->priv;
- model = iter_priv->model;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL (model), TRUE);
- model_priv = model->priv;
-
- begin = g_sequence_get_begin_iter (model_priv->sequence);
- end = iter_priv->seq_iter;
-
- temp_iter = g_object_new (CLUTTER_TYPE_MODEL_ITER, "model", model, NULL);
-
- while (!g_sequence_iter_is_begin (begin))
- {
- temp_iter->priv->seq_iter = begin;
- if (_model_filter (model, temp_iter))
- {
- end = begin;
- break;
- }
- begin = g_sequence_iter_prev (begin);
- }
- /* This is because the 'begin_iter' is always *before* the last valid iter.
- * Otherwise we'd have endless loops
- */
- end = g_sequence_iter_prev (end);
-
- g_object_unref (temp_iter);
- return iter_priv->seq_iter == end;
-}
-
-static gboolean
-_model_iter_is_last (ClutterModelIter *iter)
-{
- ClutterModel *model = NULL;
- ClutterModelPrivate *model_priv;
- ClutterModelIterPrivate *iter_priv;
- GSequenceIter *begin, *end;
- ClutterModelIter *temp_iter;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), TRUE);
- iter_priv = iter->priv;
- model = iter_priv->model;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL (model), TRUE);
- model_priv = model->priv;
-
- if (g_sequence_iter_is_end (iter_priv->seq_iter))
- return TRUE;
-
- begin = g_sequence_get_end_iter (model_priv->sequence);
- begin = g_sequence_iter_prev (begin);
- end = iter_priv->seq_iter;
-
- temp_iter = g_object_new (CLUTTER_TYPE_MODEL_ITER,
- "model", model,
- "iter", begin,
- NULL);
-
- while (!g_sequence_iter_is_begin (begin))
- {
- temp_iter->priv->seq_iter = begin;
- if (_model_filter (model, temp_iter))
- {
- end = begin;
- break;
- }
-
- begin = g_sequence_iter_prev (begin);
- }
- /* This is because the 'end_iter' is always *after* the last valid iter.
- * Otherwise we'd have endless loops
- */
- end = g_sequence_iter_next (end);
-
- g_object_unref (temp_iter);
- return iter_priv->seq_iter == end;
-}
-
-static ClutterModelIter *
-_model_iter_next (ClutterModelIter *iter)
-{
- ClutterModel *model = NULL;
- ClutterModelPrivate *model_priv;
- ClutterModelIterPrivate *iter_priv;
- GSequenceIter *filter_next;
- ClutterModelIter *temp_iter;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), iter);
- iter_priv = iter->priv;
- model = iter_priv->model;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL (model), iter);
- model_priv = model->priv;
-
- filter_next = g_sequence_iter_next (iter_priv->seq_iter);
- temp_iter = g_object_new (CLUTTER_TYPE_MODEL_ITER, "model", model, NULL);
-
- while (!g_sequence_iter_is_end (filter_next))
- {
- g_object_set (temp_iter, "iter", filter_next, NULL);
- if (_model_filter (model, temp_iter))
- break;
-
- filter_next = g_sequence_iter_next (filter_next);
- }
-
- g_object_unref (temp_iter);
-
- /* We do this because the 'end_iter' is always *after* the last valid iter.
- * Otherwise loops will go on forever
- */
- if (filter_next == iter_priv->seq_iter)
- filter_next = g_sequence_iter_next (filter_next);
-
- g_object_set (iter, "iter", filter_next, NULL);
- return iter;
-}
-
-static ClutterModelIter *
-_model_iter_prev (ClutterModelIter *iter)
-{
- ClutterModel *model = NULL;
- ClutterModelPrivate *model_priv;
- ClutterModelIterPrivate *iter_priv;
- GSequenceIter *filter_prev;
- ClutterModelIter *temp_iter;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), iter);
- iter_priv = iter->priv;
- model = iter_priv->model;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL (model), iter);
- model_priv = model->priv;
-
- filter_prev = g_sequence_iter_prev (iter_priv->seq_iter);
- temp_iter = g_object_new (CLUTTER_TYPE_MODEL_ITER, "model", model, NULL);
-
- while (!g_sequence_iter_is_begin (filter_prev))
- {
- g_object_set (temp_iter, "iter", filter_prev, NULL);
- if (_model_filter (model, temp_iter))
- break;
-
- filter_prev = g_sequence_iter_prev (filter_prev);
- }
-
- /* We do this because the 'end_iter' is always *after* the last valid iter.
- * Otherwise loops will go on forever
- */
- if (filter_prev == iter_priv->seq_iter)
- filter_prev = g_sequence_iter_prev (filter_prev);
-
- g_object_set (iter, "iter", filter_prev, NULL);
-
- g_object_unref (temp_iter);
-
- return iter;
-}
-
-static ClutterModel *
-_model_iter_get_model (ClutterModelIter *iter)
-{
- ClutterModelIterPrivate *priv;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), NULL);
- priv = iter->priv;
- g_return_val_if_fail (CLUTTER_IS_MODEL (priv->model), NULL);
-
- return priv->model;
-}
-
-static guint
-_model_iter_get_row (ClutterModelIter *iter)
-{
- ClutterModel *model = NULL;
- ClutterModelPrivate *model_priv;
- ClutterModelIterPrivate *iter_priv;
- GSequenceIter *filter_next;
- ClutterModelIter *temp_iter;
- guint row = 0;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), row);
- iter_priv = iter->priv;
- model = iter_priv->model;
-
- g_return_val_if_fail (CLUTTER_IS_MODEL (model), row);
- model_priv = model->priv;
-
- filter_next = g_sequence_iter_next (iter_priv->seq_iter);
- temp_iter = g_object_new (CLUTTER_TYPE_MODEL_ITER,
- "model", model, NULL);
-
- while (!g_sequence_iter_is_end (filter_next))
- {
- g_object_set (temp_iter, "iter", filter_next, NULL);
- if (_model_filter (model, temp_iter))
- {
- if (iter_priv->seq_iter == temp_iter->priv->seq_iter)
- break;
-
- row++;
- }
- filter_next = g_sequence_iter_next (filter_next);
- }
-
- g_object_unref (temp_iter);
-
- return row;
-}
-
-static void
-_model_iter_set_row (ClutterModelIter *iter, guint row)
-{
- ClutterModel *model = NULL;
- ClutterModelPrivate *model_priv;
- ClutterModelIterPrivate *iter_priv;
- GSequenceIter *filter_next;
- ClutterModelIter *temp_iter;
- guint i = 0;
-
- g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter));
- iter_priv = iter->priv;
- model = iter_priv->model;
-
- g_return_if_fail (CLUTTER_IS_MODEL (model));
- model_priv = model->priv;
-
- temp_iter = g_object_new (CLUTTER_TYPE_MODEL_ITER,
- "model", model,
- NULL);
-
- filter_next = g_sequence_get_begin_iter (model_priv->sequence);
- while (!g_sequence_iter_is_end (filter_next))
- {
- g_object_set (temp_iter, "iter", filter_next, NULL);
- if (_model_filter (model, temp_iter))
- {
- if (i == row)
- {
- iter_priv->seq_iter = filter_next;
- break;
- }
-
- i++;
- }
-
- filter_next = g_sequence_iter_next (filter_next);
- }
+ priv->row = 0;
- g_object_unref (temp_iter);
+ priv->ignore_sort = FALSE;
}
/*
priv->ignore_sort = FALSE;
if (sort)
- _model_sort (model);
+ clutter_model_resort (model);
g_signal_emit (model, model_signals[ROW_CHANGED], 0, iter);
}
g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter));
- klass = CLUTTER_MODEL_ITER_GET_CLASS (iter);
- g_return_if_fail (klass->get_value != NULL);
-
model = iter->priv->model;
+
g_value_init (value, clutter_model_get_column_type (model, column));
- klass->get_value (iter, column, value);
+
+ klass = CLUTTER_MODEL_ITER_GET_CLASS (iter);
+ if (klass && klass->get_value)
+ klass->get_value (iter, column, value);
}
/**
g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter));
klass = CLUTTER_MODEL_ITER_GET_CLASS (iter);
- g_return_if_fail (klass->set_value != NULL);
-
- klass->set_value (iter, column, value);
+ if (klass && klass->set_value)
+ klass->set_value (iter, column, value);
}
/**
g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), FALSE);
klass = CLUTTER_MODEL_ITER_GET_CLASS (iter);
- g_return_val_if_fail (klass->is_first != NULL, FALSE);
-
- return klass->is_first (iter);
+ if (klass && klass->is_first)
+ return klass->is_first (iter);
+
+ return FALSE;
}
/**
g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), FALSE);
klass = CLUTTER_MODEL_ITER_GET_CLASS (iter);
- g_return_val_if_fail (klass->is_last != NULL, FALSE);
-
- return klass->is_last (iter);
+ if (klass && klass->is_last)
+ return klass->is_last (iter);
+
+ return FALSE;
}
/**
g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), NULL);
klass = CLUTTER_MODEL_ITER_GET_CLASS (iter);
- g_return_val_if_fail (klass->next != NULL, NULL);
-
- return klass->next (iter);
+ if (klass && klass->next)
+ return klass->next (iter);
+
+ return NULL;
}
/**
g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), NULL);
klass = CLUTTER_MODEL_ITER_GET_CLASS (iter);
- g_return_val_if_fail (klass->prev != NULL, NULL);
-
- return klass->prev (iter);
+ if (klass && klass->prev)
+ return klass->prev (iter);
+
+ return NULL;
}
/**
g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), NULL);
klass = CLUTTER_MODEL_ITER_GET_CLASS (iter);
- g_return_val_if_fail (klass->get_model != NULL, NULL);
-
- return klass->get_model (iter);
+ if (klass && klass->get_model)
+ return klass->get_model (iter);
+
+ return NULL;
}
/**
{
ClutterModelIterClass *klass;
- g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), -1);
+ g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), 0);
klass = CLUTTER_MODEL_ITER_GET_CLASS (iter);
- g_return_val_if_fail (klass->get_row != NULL, -1);
-
- return klass->get_row (iter);
+ if (klass && klass->get_row)
+ return klass->get_row (iter);
+
+ return 0;
}