From 07722582eff98afd3e901bcabd62f2c4497e4a9f Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 11 Feb 2019 06:01:19 +0100 Subject: [PATCH] simpleselection: Improve items-changed Make items-changed never emit 2 signals, instead, always emit only one, potentially by extending the range reported in items-changed. And be a lot more exhaustive about autoselect tests. --- gtk/gtksingleselection.c | 24 ++++++--- testsuite/gtk/singleselection.c | 86 +++++++++++++++++++++++++++++---- 2 files changed, 93 insertions(+), 17 deletions(-) diff --git a/gtk/gtksingleselection.c b/gtk/gtksingleselection.c index 642c79847a..ce25eb91d1 100644 --- a/gtk/gtksingleselection.c +++ b/gtk/gtksingleselection.c @@ -199,8 +199,6 @@ gtk_single_selection_items_changed_cb (GListModel *model, guint added, GtkSingleSelection *self) { - gboolean emit_selection_changed = FALSE; - g_object_freeze_notify (G_OBJECT (self)); if (self->selected_item == NULL) @@ -260,12 +258,27 @@ gtk_single_selection_items_changed_cb (GListModel *model, self->selected = position - 1; self->selected_item = g_list_model_get_item (self->model, self->selected); g_assert (self->selected_item); + /* We pretend the newly selected item was part of the original model change. + * This way we get around inconsistent state (no item selected) during + * the items-changed emission. */ + position--; + removed++; + added++; } else self->selected = GTK_INVALID_LIST_POSITION; } - - emit_selection_changed = TRUE; + else + { + if (self->selected == position + added) + { + /* We pretend the newly selected item was part of the original model change. + * This way we get around inconsistent state (no item selected) during + * the items-changed emission. */ + removed++; + added++; + } + } } else { @@ -279,9 +292,6 @@ gtk_single_selection_items_changed_cb (GListModel *model, g_list_model_items_changed (G_LIST_MODEL (self), position, removed, added); - if (emit_selection_changed && self->selected != GTK_INVALID_LIST_POSITION) - gtk_selection_model_selection_changed (GTK_SELECTION_MODEL (self), self->selected, 1); - g_object_thaw_notify (G_OBJECT (self)); } diff --git a/testsuite/gtk/singleselection.c b/testsuite/gtk/singleselection.c index 3ce754bbe9..26e973af78 100644 --- a/testsuite/gtk/singleselection.c +++ b/testsuite/gtk/singleselection.c @@ -390,31 +390,96 @@ test_autoselect (void) GtkSelectionModel *selection; GListStore *store; - store = new_store (2, 1, 1); + store = new_empty_store (); selection = new_model (store, TRUE, FALSE); + assert_model (selection, ""); + assert_changes (selection, ""); assert_selection (selection, ""); assert_selection_changes (selection, ""); add (store, 1); + assert_model (selection, "1"); + assert_changes (selection, "+0"); assert_selection (selection, "1"); assert_selection_changes (selection, ""); - splice (store, 0, 1, (guint[]) { 97 }, 1); - assert_selection (selection, "97"); - assert_selection_changes (selection, "0:1"); + splice (store, 0, 1, (guint[]) { 7, 8, 9 }, 3); + assert_model (selection, "7 8 9"); + assert_changes (selection, "0-1+3"); + assert_selection (selection, "7"); + assert_selection_changes (selection, ""); + + splice (store, 0, 0, (guint[]) { 5, 6 }, 2); + assert_model (selection, "5 6 7 8 9"); + assert_changes (selection, "0+2"); + assert_selection (selection, "7"); + assert_selection_changes (selection, ""); + + g_list_store_remove (store, 2); + assert_model (selection, "5 6 8 9"); + assert_changes (selection, "2-2+1"); + assert_selection (selection, "8"); + assert_selection_changes (selection, ""); + + splice (store, 2, 2, NULL, 0); + assert_model (selection, "5 6"); + assert_changes (selection, "1-3+1"); + assert_selection (selection, "6"); + assert_selection_changes (selection, ""); + + splice (store, 0, 2, (guint[]) { 1, 2 }, 2); + assert_model (selection, "1 2"); + assert_changes (selection, "0-2+2"); + assert_selection (selection, "2"); + assert_selection_changes (selection, ""); + + g_list_store_remove (store, 0); + assert_model (selection, "2"); + assert_changes (selection, "-0"); + assert_selection (selection, "2"); + assert_selection_changes (selection, ""); + + g_list_store_remove (store, 0); + assert_model (selection, ""); + assert_changes (selection, "-0"); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + g_object_unref (store); + g_object_unref (selection); +} + +static void +test_autoselect_toggle (void) +{ + GtkSelectionModel *selection; + GListStore *store; + + store = new_store (1, 1, 1); + selection = new_model (store, TRUE, TRUE); + assert_model (selection, "1"); + assert_changes (selection, ""); + assert_selection (selection, "1"); + assert_selection_changes (selection, ""); gtk_single_selection_set_autoselect (GTK_SINGLE_SELECTION (selection), FALSE); - gtk_single_selection_set_can_unselect (GTK_SINGLE_SELECTION (selection), TRUE); + assert_model (selection, "1"); + assert_changes (selection, ""); + assert_selection (selection, "1"); + assert_selection_changes (selection, ""); + gtk_selection_model_unselect_item (selection, 0); + assert_model (selection, "1"); + assert_changes (selection, ""); assert_selection (selection, ""); assert_selection_changes (selection, "0:1"); gtk_single_selection_set_autoselect (GTK_SINGLE_SELECTION (selection), TRUE); - assert_selection (selection, "97"); + assert_model (selection, "1"); + assert_changes (selection, ""); + assert_selection (selection, "1"); assert_selection_changes (selection, "0:1"); - ignore_changes (selection); - g_object_unref (store); g_object_unref (selection); } @@ -546,16 +611,17 @@ main (int argc, char *argv[]) changes_quark = g_quark_from_static_string ("What did I see? Can I believe what I saw?"); selection_quark = g_quark_from_static_string ("Mana mana, badibidibi"); - g_test_add_func ("/singleselection/create", test_create); #if GLIB_CHECK_VERSION (2, 59, 0) /* g_list_store_get_item() has overflow issues before */ + g_test_add_func ("/singleselection/create", test_create); g_test_add_func ("/singleselection/autoselect", test_autoselect); + g_test_add_func ("/singleselection/autoselect-toggle", test_autoselect_toggle); g_test_add_func ("/singleselection/selection", test_selection); g_test_add_func ("/singleselection/can-unselect", test_can_unselect); g_test_add_func ("/singleselection/persistence", test_persistence); -#endif g_test_add_func ("/singleselection/query-range", test_query_range); #if GLIB_CHECK_VERSION (2, 58, 0) /* g_list_store_splice() is broken before 2.58 */ g_test_add_func ("/singleselection/changes", test_changes); +#endif #endif return g_test_run ();