2009-02-14 06:45:27 -05:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <clutter/clutter.h>
|
|
|
|
|
|
|
|
typedef struct _ModelData
|
|
|
|
{
|
|
|
|
ClutterModel *model;
|
|
|
|
|
|
|
|
guint n_row;
|
|
|
|
} ModelData;
|
|
|
|
|
model: Make sure to emit ::row-changed
Currently, only clutter_model_iter_set_valist() is in charge of emitting
the ClutterModel::row-changed signal. Both the set() and the
set_valist() functions can be called with multiple columns, so we
coalesce the signal emission at the end of the set_valist(), to have a
single ::row-changed emission per change.
The clutter_model_iter_set_value() function is just a thin wrapper
around the set_value() virtual function, but since it's called
internally we cannot add the signal emission there as well, as we'd
break the signal coalescing.
For this reason, we need some code refactoring inside the various set()
variants of ClutterModelIter:
- we only use the internal va_arg variant for both the set() and
set_valist() public functions, to avoid multiple type checks;
- the internal set_valist() calls an internal set_value() method
which calls the virtual function from the iterator vtable;
- a new internal emit_row_changed() method is needed to retrieve
the ClutterModel from the iterator, and emit the signal;
Now, all three variants of the value setter will call an internal
ClutterModelIter::set_value() wrapper, and emit the ::row-changed
signal.
To check that the intended behaviour has been implemented, and it's not
going to be broken, the test suite has grown a new unit which populates
a model and changes a random row.
2011-07-28 10:00:18 -04:00
|
|
|
typedef struct _ChangedData
|
|
|
|
{
|
|
|
|
ClutterModel *model;
|
|
|
|
|
|
|
|
ClutterModelIter *iter;
|
|
|
|
|
|
|
|
guint row;
|
|
|
|
guint n_emissions;
|
|
|
|
|
|
|
|
gint value_check;
|
|
|
|
} ChangedData;
|
|
|
|
|
2009-02-14 06:45:27 -05:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
COLUMN_FOO, /* G_TYPE_STRING */
|
|
|
|
COLUMN_BAR, /* G_TYPE_INT */
|
|
|
|
|
|
|
|
N_COLUMNS
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
const gchar *expected_foo;
|
|
|
|
gint expected_bar;
|
|
|
|
} base_model[] = {
|
|
|
|
{ "String 1", 1 },
|
|
|
|
{ "String 2", 2 },
|
|
|
|
{ "String 3", 3 },
|
|
|
|
{ "String 4", 4 },
|
|
|
|
{ "String 5", 5 },
|
|
|
|
{ "String 6", 6 },
|
|
|
|
{ "String 7", 7 },
|
|
|
|
{ "String 8", 8 },
|
|
|
|
{ "String 9", 9 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
const gchar *expected_foo;
|
|
|
|
gint expected_bar;
|
|
|
|
} forward_base[] = {
|
|
|
|
{ "String 1", 1 },
|
|
|
|
{ "String 2", 2 },
|
|
|
|
{ "String 3", 3 },
|
|
|
|
{ "String 4", 4 },
|
|
|
|
{ "String 5", 5 },
|
|
|
|
{ "String 6", 6 },
|
|
|
|
{ "String 7", 7 },
|
|
|
|
{ "String 8", 8 },
|
|
|
|
{ "String 9", 9 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
const gchar *expected_foo;
|
|
|
|
gint expected_bar;
|
|
|
|
} backward_base[] = {
|
|
|
|
{ "String 9", 9 },
|
|
|
|
{ "String 8", 8 },
|
|
|
|
{ "String 7", 7 },
|
|
|
|
{ "String 6", 6 },
|
|
|
|
{ "String 5", 5 },
|
|
|
|
{ "String 4", 4 },
|
|
|
|
{ "String 3", 3 },
|
|
|
|
{ "String 2", 2 },
|
|
|
|
{ "String 1", 1 },
|
|
|
|
};
|
|
|
|
|
2009-04-29 10:39:23 -04:00
|
|
|
static const struct {
|
|
|
|
const gchar *expected_foo;
|
|
|
|
gint expected_bar;
|
|
|
|
} filter_odd[] = {
|
|
|
|
{ "String 1", 1 },
|
|
|
|
{ "String 3", 3 },
|
|
|
|
{ "String 5", 5 },
|
|
|
|
{ "String 7", 7 },
|
|
|
|
{ "String 9", 9 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
const gchar *expected_foo;
|
|
|
|
gint expected_bar;
|
|
|
|
} filter_even[] = {
|
|
|
|
{ "String 8", 8 },
|
|
|
|
{ "String 6", 6 },
|
|
|
|
{ "String 4", 4 },
|
|
|
|
{ "String 2", 2 },
|
|
|
|
};
|
|
|
|
|
2009-02-14 06:45:27 -05:00
|
|
|
static inline void
|
|
|
|
compare_iter (ClutterModelIter *iter,
|
2009-04-29 10:39:23 -04:00
|
|
|
const gint expected_row,
|
2009-02-14 06:45:27 -05:00
|
|
|
const gchar *expected_foo,
|
|
|
|
const gint expected_bar)
|
|
|
|
{
|
|
|
|
gchar *foo = NULL;
|
|
|
|
gint bar = 0;
|
2009-04-29 10:39:23 -04:00
|
|
|
gint row = 0;
|
2009-02-14 06:45:27 -05:00
|
|
|
|
2009-04-29 10:39:23 -04:00
|
|
|
row = clutter_model_iter_get_row (iter);
|
2009-02-14 06:45:27 -05:00
|
|
|
clutter_model_iter_get (iter,
|
|
|
|
COLUMN_FOO, &foo,
|
|
|
|
COLUMN_BAR, &bar,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
if (g_test_verbose ())
|
2009-04-29 10:39:23 -04:00
|
|
|
g_print ("Row %d => %d: Got [ '%s', '%d' ], expected [ '%s', '%d' ]\n",
|
|
|
|
row, expected_row,
|
2009-02-14 06:45:27 -05:00
|
|
|
foo, bar,
|
|
|
|
expected_foo, expected_bar);
|
|
|
|
|
2009-04-29 10:39:23 -04:00
|
|
|
g_assert_cmpint (row, ==, expected_row);
|
2009-02-14 06:45:27 -05:00
|
|
|
g_assert_cmpstr (foo, ==, expected_foo);
|
|
|
|
g_assert_cmpint (bar, ==, expected_bar);
|
|
|
|
|
|
|
|
g_free (foo);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_row_added (ClutterModel *model,
|
|
|
|
ClutterModelIter *iter,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
ModelData *model_data = data;
|
|
|
|
|
|
|
|
compare_iter (iter,
|
2009-04-29 10:39:23 -04:00
|
|
|
model_data->n_row,
|
2009-02-14 06:45:27 -05:00
|
|
|
base_model[model_data->n_row].expected_foo,
|
|
|
|
base_model[model_data->n_row].expected_bar);
|
|
|
|
|
|
|
|
model_data->n_row += 1;
|
|
|
|
}
|
|
|
|
|
2009-04-29 10:39:23 -04:00
|
|
|
static gboolean
|
|
|
|
filter_even_rows (ClutterModel *model,
|
|
|
|
ClutterModelIter *iter,
|
|
|
|
gpointer dummy G_GNUC_UNUSED)
|
|
|
|
{
|
|
|
|
gint bar_value;
|
|
|
|
|
|
|
|
clutter_model_iter_get (iter, COLUMN_BAR, &bar_value, -1);
|
|
|
|
|
|
|
|
if (bar_value % 2 == 0)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
filter_odd_rows (ClutterModel *model,
|
|
|
|
ClutterModelIter *iter,
|
|
|
|
gpointer dummy G_GNUC_UNUSED)
|
|
|
|
{
|
|
|
|
gint bar_value;
|
|
|
|
|
|
|
|
clutter_model_iter_get (iter, COLUMN_BAR, &bar_value, -1);
|
|
|
|
|
|
|
|
if (bar_value % 2 != 0)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2013-12-12 10:05:16 -05:00
|
|
|
static void
|
|
|
|
list_model_filter (void)
|
2009-04-29 10:39:23 -04:00
|
|
|
{
|
|
|
|
ModelData test_data = { NULL, 0 };
|
|
|
|
ClutterModelIter *iter;
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
test_data.model = clutter_list_model_new (N_COLUMNS,
|
|
|
|
G_TYPE_STRING, "Foo",
|
|
|
|
G_TYPE_INT, "Bar");
|
|
|
|
test_data.n_row = 0;
|
|
|
|
|
|
|
|
for (i = 1; i < 10; i++)
|
|
|
|
{
|
|
|
|
gchar *foo = g_strdup_printf ("String %d", i);
|
|
|
|
|
|
|
|
clutter_model_append (test_data.model,
|
|
|
|
COLUMN_FOO, foo,
|
|
|
|
COLUMN_BAR, i,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
g_free (foo);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_test_verbose ())
|
|
|
|
g_print ("Forward iteration (filter odd)...\n");
|
|
|
|
|
|
|
|
clutter_model_set_filter (test_data.model, filter_odd_rows, NULL, NULL);
|
|
|
|
|
|
|
|
iter = clutter_model_get_first_iter (test_data.model);
|
|
|
|
g_assert (iter != NULL);
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
while (!clutter_model_iter_is_last (iter))
|
|
|
|
{
|
|
|
|
compare_iter (iter, i,
|
|
|
|
filter_odd[i].expected_foo,
|
|
|
|
filter_odd[i].expected_bar);
|
|
|
|
|
|
|
|
iter = clutter_model_iter_next (iter);
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_object_unref (iter);
|
|
|
|
|
|
|
|
if (g_test_verbose ())
|
|
|
|
g_print ("Backward iteration (filter even)...\n");
|
|
|
|
|
|
|
|
clutter_model_set_filter (test_data.model, filter_even_rows, NULL, NULL);
|
|
|
|
|
|
|
|
iter = clutter_model_get_last_iter (test_data.model);
|
|
|
|
g_assert (iter != NULL);
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
compare_iter (iter, G_N_ELEMENTS (filter_even) - i - 1,
|
|
|
|
filter_even[i].expected_foo,
|
|
|
|
filter_even[i].expected_bar);
|
|
|
|
|
|
|
|
iter = clutter_model_iter_prev (iter);
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
while (!clutter_model_iter_is_first (iter));
|
|
|
|
|
|
|
|
g_object_unref (iter);
|
|
|
|
|
2010-12-02 09:08:10 -05:00
|
|
|
if (g_test_verbose ())
|
|
|
|
g_print ("get_iter_at_row...\n");
|
|
|
|
|
|
|
|
clutter_model_set_filter (test_data.model, filter_odd_rows, NULL, NULL);
|
|
|
|
|
|
|
|
for (i = 0; i < 5; i++)
|
|
|
|
{
|
|
|
|
iter = clutter_model_get_iter_at_row (test_data.model, i);
|
|
|
|
compare_iter (iter, i ,
|
|
|
|
filter_odd[i].expected_foo,
|
|
|
|
filter_odd[i].expected_bar);
|
|
|
|
g_object_unref (iter);
|
|
|
|
}
|
|
|
|
|
|
|
|
iter = clutter_model_get_iter_at_row (test_data.model, 5);
|
|
|
|
g_assert (iter == NULL);
|
|
|
|
|
2009-04-29 10:39:23 -04:00
|
|
|
g_object_unref (test_data.model);
|
|
|
|
}
|
|
|
|
|
2013-12-12 10:05:16 -05:00
|
|
|
static void
|
|
|
|
list_model_iterate (void)
|
2009-02-14 06:45:27 -05:00
|
|
|
{
|
|
|
|
ModelData test_data = { NULL, 0 };
|
|
|
|
ClutterModelIter *iter;
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
test_data.model = clutter_list_model_new (N_COLUMNS,
|
|
|
|
G_TYPE_STRING, "Foo",
|
|
|
|
G_TYPE_INT, "Bar");
|
|
|
|
test_data.n_row = 0;
|
|
|
|
|
|
|
|
g_signal_connect (test_data.model, "row-added",
|
|
|
|
G_CALLBACK (on_row_added),
|
|
|
|
&test_data);
|
|
|
|
|
|
|
|
for (i = 1; i < 10; i++)
|
|
|
|
{
|
|
|
|
gchar *foo = g_strdup_printf ("String %d", i);
|
|
|
|
|
|
|
|
clutter_model_append (test_data.model,
|
|
|
|
COLUMN_FOO, foo,
|
|
|
|
COLUMN_BAR, i,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
g_free (foo);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_test_verbose ())
|
|
|
|
g_print ("Forward iteration...\n");
|
|
|
|
|
|
|
|
iter = clutter_model_get_first_iter (test_data.model);
|
|
|
|
g_assert (iter != NULL);
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
while (!clutter_model_iter_is_last (iter))
|
|
|
|
{
|
2009-04-29 10:39:23 -04:00
|
|
|
compare_iter (iter, i,
|
2009-02-14 06:45:27 -05:00
|
|
|
forward_base[i].expected_foo,
|
|
|
|
forward_base[i].expected_bar);
|
|
|
|
|
|
|
|
iter = clutter_model_iter_next (iter);
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_object_unref (iter);
|
|
|
|
|
|
|
|
if (g_test_verbose ())
|
|
|
|
g_print ("Backward iteration...\n");
|
|
|
|
|
|
|
|
iter = clutter_model_get_last_iter (test_data.model);
|
|
|
|
g_assert (iter != NULL);
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
do
|
|
|
|
{
|
2009-04-29 10:39:23 -04:00
|
|
|
compare_iter (iter, G_N_ELEMENTS (backward_base) - i - 1,
|
2009-02-14 06:45:27 -05:00
|
|
|
backward_base[i].expected_foo,
|
|
|
|
backward_base[i].expected_bar);
|
|
|
|
|
|
|
|
iter = clutter_model_iter_prev (iter);
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
while (!clutter_model_iter_is_first (iter));
|
|
|
|
|
2009-04-29 10:39:23 -04:00
|
|
|
compare_iter (iter, G_N_ELEMENTS (backward_base) - i - 1,
|
2009-02-14 06:45:27 -05:00
|
|
|
backward_base[i].expected_foo,
|
|
|
|
backward_base[i].expected_bar);
|
|
|
|
|
|
|
|
g_object_unref (iter);
|
|
|
|
|
|
|
|
g_object_unref (test_data.model);
|
|
|
|
}
|
|
|
|
|
2013-12-12 10:05:16 -05:00
|
|
|
static void
|
|
|
|
list_model_populate (void)
|
2009-02-14 06:45:27 -05:00
|
|
|
{
|
|
|
|
ModelData test_data = { NULL, 0 };
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
test_data.model = clutter_list_model_new (N_COLUMNS,
|
|
|
|
G_TYPE_STRING, "Foo",
|
|
|
|
G_TYPE_INT, "Bar");
|
|
|
|
test_data.n_row = 0;
|
|
|
|
|
|
|
|
g_signal_connect (test_data.model, "row-added",
|
|
|
|
G_CALLBACK (on_row_added),
|
|
|
|
&test_data);
|
|
|
|
|
|
|
|
for (i = 1; i < 10; i++)
|
|
|
|
{
|
|
|
|
gchar *foo = g_strdup_printf ("String %d", i);
|
|
|
|
|
|
|
|
clutter_model_append (test_data.model,
|
|
|
|
COLUMN_FOO, foo,
|
|
|
|
COLUMN_BAR, i,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
g_free (foo);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_object_unref (test_data.model);
|
|
|
|
}
|
2010-02-25 17:47:49 -05:00
|
|
|
|
2013-12-12 10:05:16 -05:00
|
|
|
static void
|
|
|
|
list_model_from_script (void)
|
2010-02-25 17:47:49 -05:00
|
|
|
{
|
|
|
|
ClutterScript *script = clutter_script_new ();
|
|
|
|
GObject *model;
|
|
|
|
GError *error = NULL;
|
|
|
|
gchar *test_file;
|
|
|
|
const gchar *name;
|
|
|
|
GType type;
|
2011-01-21 08:50:44 -05:00
|
|
|
ClutterModelIter *iter;
|
|
|
|
GValue value = { 0, };
|
2010-02-25 17:47:49 -05:00
|
|
|
|
2013-12-12 10:05:16 -05:00
|
|
|
test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-model.json", NULL);
|
2010-02-25 17:47:49 -05:00
|
|
|
clutter_script_load_from_file (script, test_file, &error);
|
|
|
|
if (g_test_verbose () && error)
|
|
|
|
g_print ("Error: %s", error->message);
|
2010-03-02 14:09:20 -05:00
|
|
|
|
|
|
|
g_assert_no_error (error);
|
2010-02-25 17:47:49 -05:00
|
|
|
|
|
|
|
model = clutter_script_get_object (script, "test-model");
|
|
|
|
|
|
|
|
g_assert (CLUTTER_IS_MODEL (model));
|
|
|
|
g_assert (clutter_model_get_n_columns (CLUTTER_MODEL (model)) == 3);
|
|
|
|
|
|
|
|
name = clutter_model_get_column_name (CLUTTER_MODEL (model), 0);
|
|
|
|
type = clutter_model_get_column_type (CLUTTER_MODEL (model), 0);
|
2010-02-25 18:15:59 -05:00
|
|
|
|
|
|
|
if (g_test_verbose ())
|
|
|
|
g_print ("column[0]: %s, type: %s\n", name, g_type_name (type));
|
|
|
|
|
2010-02-25 17:47:49 -05:00
|
|
|
g_assert (strcmp (name, "text-column") == 0);
|
|
|
|
g_assert (type == G_TYPE_STRING);
|
|
|
|
|
|
|
|
name = clutter_model_get_column_name (CLUTTER_MODEL (model), 2);
|
|
|
|
type = clutter_model_get_column_type (CLUTTER_MODEL (model), 2);
|
2010-02-25 18:15:59 -05:00
|
|
|
|
|
|
|
if (g_test_verbose ())
|
|
|
|
g_print ("column[2]: %s, type: %s\n", name, g_type_name (type));
|
|
|
|
|
2010-02-25 17:47:49 -05:00
|
|
|
g_assert (strcmp (name, "actor-column") == 0);
|
2013-12-12 10:05:16 -05:00
|
|
|
g_assert (g_type_is_a (type, CLUTTER_TYPE_ACTOR));
|
2011-01-21 08:50:44 -05:00
|
|
|
|
|
|
|
g_assert (clutter_model_get_n_rows (CLUTTER_MODEL (model)) == 3);
|
|
|
|
|
|
|
|
iter = clutter_model_get_iter_at_row (CLUTTER_MODEL (model), 0);
|
|
|
|
clutter_model_iter_get_value (iter, 0, &value);
|
|
|
|
g_assert (G_VALUE_HOLDS_STRING (&value));
|
|
|
|
g_assert (strcmp (g_value_get_string (&value), "text-row-1") == 0);
|
|
|
|
g_value_unset (&value);
|
|
|
|
|
|
|
|
clutter_model_iter_get_value (iter, 1, &value);
|
|
|
|
g_assert (G_VALUE_HOLDS_INT (&value));
|
|
|
|
g_assert (g_value_get_int (&value) == 1);
|
|
|
|
g_value_unset (&value);
|
|
|
|
|
|
|
|
clutter_model_iter_get_value (iter, 2, &value);
|
|
|
|
g_assert (G_VALUE_HOLDS_OBJECT (&value));
|
|
|
|
g_assert (g_value_get_object (&value) == NULL);
|
|
|
|
g_value_unset (&value);
|
|
|
|
|
|
|
|
iter = clutter_model_iter_next (iter);
|
|
|
|
clutter_model_iter_get_value (iter, 2, &value);
|
|
|
|
g_assert (G_VALUE_HOLDS_OBJECT (&value));
|
2013-12-12 10:05:16 -05:00
|
|
|
g_assert (CLUTTER_IS_ACTOR (g_value_get_object (&value)));
|
2011-01-21 08:50:44 -05:00
|
|
|
g_value_unset (&value);
|
|
|
|
|
|
|
|
iter = clutter_model_iter_next (iter);
|
|
|
|
clutter_model_iter_get_value (iter, 2, &value);
|
|
|
|
g_assert (G_VALUE_HOLDS_OBJECT (&value));
|
2013-12-12 10:05:16 -05:00
|
|
|
g_assert (CLUTTER_IS_ACTOR (g_value_get_object (&value)));
|
2011-01-21 08:50:44 -05:00
|
|
|
g_assert (strcmp (clutter_actor_get_name (g_value_get_object (&value)),
|
|
|
|
"actor-row-3") == 0);
|
|
|
|
g_value_unset (&value);
|
|
|
|
g_object_unref (iter);
|
2010-02-25 17:47:49 -05:00
|
|
|
}
|
model: Make sure to emit ::row-changed
Currently, only clutter_model_iter_set_valist() is in charge of emitting
the ClutterModel::row-changed signal. Both the set() and the
set_valist() functions can be called with multiple columns, so we
coalesce the signal emission at the end of the set_valist(), to have a
single ::row-changed emission per change.
The clutter_model_iter_set_value() function is just a thin wrapper
around the set_value() virtual function, but since it's called
internally we cannot add the signal emission there as well, as we'd
break the signal coalescing.
For this reason, we need some code refactoring inside the various set()
variants of ClutterModelIter:
- we only use the internal va_arg variant for both the set() and
set_valist() public functions, to avoid multiple type checks;
- the internal set_valist() calls an internal set_value() method
which calls the virtual function from the iterator vtable;
- a new internal emit_row_changed() method is needed to retrieve
the ClutterModel from the iterator, and emit the signal;
Now, all three variants of the value setter will call an internal
ClutterModelIter::set_value() wrapper, and emit the ::row-changed
signal.
To check that the intended behaviour has been implemented, and it's not
going to be broken, the test suite has grown a new unit which populates
a model and changes a random row.
2011-07-28 10:00:18 -04:00
|
|
|
|
|
|
|
static void
|
|
|
|
on_row_changed (ClutterModel *model,
|
|
|
|
ClutterModelIter *iter,
|
|
|
|
ChangedData *data)
|
|
|
|
{
|
|
|
|
gint value = -1;
|
|
|
|
|
|
|
|
clutter_model_iter_get (iter, COLUMN_BAR, &value, -1);
|
|
|
|
|
|
|
|
if (g_test_verbose ())
|
|
|
|
g_print ("row-changed value-check: %d, expected: %d\n",
|
|
|
|
value, data->value_check);
|
|
|
|
|
|
|
|
g_assert_cmpint (value, ==, data->value_check);
|
|
|
|
|
|
|
|
data->n_emissions += 1;
|
|
|
|
}
|
|
|
|
|
2013-12-12 10:05:16 -05:00
|
|
|
static void
|
|
|
|
list_model_row_changed (void)
|
model: Make sure to emit ::row-changed
Currently, only clutter_model_iter_set_valist() is in charge of emitting
the ClutterModel::row-changed signal. Both the set() and the
set_valist() functions can be called with multiple columns, so we
coalesce the signal emission at the end of the set_valist(), to have a
single ::row-changed emission per change.
The clutter_model_iter_set_value() function is just a thin wrapper
around the set_value() virtual function, but since it's called
internally we cannot add the signal emission there as well, as we'd
break the signal coalescing.
For this reason, we need some code refactoring inside the various set()
variants of ClutterModelIter:
- we only use the internal va_arg variant for both the set() and
set_valist() public functions, to avoid multiple type checks;
- the internal set_valist() calls an internal set_value() method
which calls the virtual function from the iterator vtable;
- a new internal emit_row_changed() method is needed to retrieve
the ClutterModel from the iterator, and emit the signal;
Now, all three variants of the value setter will call an internal
ClutterModelIter::set_value() wrapper, and emit the ::row-changed
signal.
To check that the intended behaviour has been implemented, and it's not
going to be broken, the test suite has grown a new unit which populates
a model and changes a random row.
2011-07-28 10:00:18 -04:00
|
|
|
{
|
|
|
|
ChangedData test_data = { NULL, NULL, 0, 0 };
|
|
|
|
GValue value = { 0, };
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
test_data.model = clutter_list_model_new (N_COLUMNS,
|
|
|
|
G_TYPE_STRING, "Foo",
|
|
|
|
G_TYPE_INT, "Bar");
|
|
|
|
for (i = 1; i < 10; i++)
|
|
|
|
{
|
|
|
|
gchar *foo = g_strdup_printf ("String %d", i);
|
|
|
|
|
|
|
|
clutter_model_append (test_data.model,
|
|
|
|
COLUMN_FOO, foo,
|
|
|
|
COLUMN_BAR, i,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
g_free (foo);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_signal_connect (test_data.model, "row-changed",
|
|
|
|
G_CALLBACK (on_row_changed),
|
|
|
|
&test_data);
|
|
|
|
|
|
|
|
test_data.row = g_random_int_range (0, 9);
|
|
|
|
test_data.iter = clutter_model_get_iter_at_row (test_data.model,
|
|
|
|
test_data.row);
|
|
|
|
g_assert (CLUTTER_IS_MODEL_ITER (test_data.iter));
|
|
|
|
|
|
|
|
test_data.value_check = 47;
|
|
|
|
|
|
|
|
g_value_init (&value, G_TYPE_INT);
|
|
|
|
g_value_set_int (&value, test_data.value_check);
|
|
|
|
|
|
|
|
clutter_model_iter_set_value (test_data.iter, COLUMN_BAR, &value);
|
|
|
|
|
|
|
|
g_value_unset (&value);
|
|
|
|
|
|
|
|
if (g_test_verbose ())
|
|
|
|
g_print ("iter.set_value() emissions: %d, expected: 1\n",
|
|
|
|
test_data.n_emissions);
|
|
|
|
|
|
|
|
g_assert_cmpint (test_data.n_emissions, ==, 1);
|
|
|
|
|
|
|
|
test_data.n_emissions = 0;
|
|
|
|
test_data.value_check = 42;
|
|
|
|
|
|
|
|
clutter_model_iter_set (test_data.iter,
|
|
|
|
COLUMN_FOO, "changed",
|
|
|
|
COLUMN_BAR, test_data.value_check,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
if (g_test_verbose ())
|
|
|
|
g_print ("iter.set() emissions: %d, expected: 1\n",
|
|
|
|
test_data.n_emissions);
|
|
|
|
|
|
|
|
g_assert_cmpint (test_data.n_emissions, ==, 1);
|
|
|
|
|
|
|
|
g_object_unref (test_data.iter);
|
|
|
|
g_object_unref (test_data.model);
|
|
|
|
}
|
2013-12-12 10:05:16 -05:00
|
|
|
|
|
|
|
CLUTTER_TEST_SUITE (
|
|
|
|
CLUTTER_TEST_UNIT ("/list-model/populate", list_model_populate)
|
|
|
|
CLUTTER_TEST_UNIT ("/list-model/iterate", list_model_iterate)
|
|
|
|
CLUTTER_TEST_UNIT ("/list-model/filter", list_model_filter)
|
|
|
|
CLUTTER_TEST_UNIT ("/list-model/row-changed", list_model_row_changed)
|
|
|
|
CLUTTER_TEST_UNIT ("/list-model/from-script", list_model_from_script)
|
|
|
|
)
|