[gtk] simpleselection: Improve items-changed



commit 07722582eff98afd3e901bcabd62f2c4497e4a9f
Author: Benjamin Otte <otte redhat com>
Date:   Mon Feb 11 06:01:19 2019 +0100

    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 ();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]