[gtk/wip/otte/bitset: 5/22] selectionmodel: Add gtk_selection_model_set_selection()



commit fa0295629bd155eaa82f6b25d2c3f97e2b0f9bb3
Author: Benjamin Otte <otte redhat com>
Date:   Sun Jun 14 06:41:05 2020 +0200

    selectionmodel: Add gtk_selection_model_set_selection()
    
    Also port the testsuite.

 docs/reference/gtk/gtk4-sections.txt |   1 +
 gtk/gtkmultiselection.c              |  86 ++++++------------
 gtk/gtkpropertyselection.c           |  85 ++++-------------
 gtk/gtkselectionmodel.c              | 171 +++++++++++++++++++++++++++++++++--
 gtk/gtkselectionmodel.h              |  14 +++
 testsuite/gtk/multiselection.c       |  68 ++++----------
 6 files changed, 240 insertions(+), 185 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 3af8dbedeb..85f2ef371a 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -397,6 +397,7 @@ gtk_selection_model_select_range
 gtk_selection_model_unselect_range
 gtk_selection_model_select_all
 gtk_selection_model_unselect_all
+gtk_selection_model_set_selection
 GtkSelectionCallback
 gtk_selection_model_select_callback
 gtk_selection_model_unselect_callback
diff --git a/gtk/gtkmultiselection.c b/gtk/gtkmultiselection.c
index 40fc3402a9..048be34cd4 100644
--- a/gtk/gtkmultiselection.c
+++ b/gtk/gtkmultiselection.c
@@ -107,72 +107,43 @@ gtk_multi_selection_is_selected (GtkSelectionModel *model,
 }
 
 static gboolean
-gtk_multi_selection_select_range (GtkSelectionModel *model,
-                                  guint              position,
-                                  guint              n_items,
-                                  gboolean           exclusive)
+gtk_multi_selection_set_selection (GtkSelectionModel *model,
+                                   GtkBitset         *selected,
+                                   GtkBitset         *mask)
 {
   GtkMultiSelection *self = GTK_MULTI_SELECTION (model);
-  guint min = G_MAXUINT;
-  guint max = 0;
+  GtkBitset *changes;
+  guint min, max, n_items;
 
-  if (exclusive)
-    {
-      min = gtk_bitset_get_minimum (self->selected);
-      max = gtk_bitset_get_maximum (self->selected);
-      gtk_bitset_remove_all (self->selected);
-    }
-
-  gtk_bitset_add_range (self->selected, position, n_items);
+  /* changes = (self->selected XOR selected) AND mask
+   * But doing it this way avoids looking at all values outside the mask
+   */
+  changes = gtk_bitset_copy (selected);
+  gtk_bitset_difference (changes, self->selected);
+  gtk_bitset_intersect (changes, mask);
 
-  min = MIN (position, min);
-  max = MAX (max, position + n_items - 1);
+  min = gtk_bitset_get_minimum (changes);
+  max = gtk_bitset_get_maximum (changes);
 
-  gtk_selection_model_selection_changed (model, min, max - min + 1);
+  /* sanity check */
+  n_items = g_list_model_get_n_items (self->model);
+  if (max >= n_items)
+    {
+      gtk_bitset_remove_range_closed (changes, n_items, max);
+      max = gtk_bitset_get_maximum (changes);
+    }
 
-  return TRUE;
-}
+  /* actually do the change */
+  gtk_bitset_difference (self->selected, changes);
 
-static gboolean
-gtk_multi_selection_unselect_range (GtkSelectionModel *model,
-                                    guint              position,
-                                    guint              n_items)
-{
-  GtkMultiSelection *self = GTK_MULTI_SELECTION (model);
+  gtk_bitset_unref (changes);
 
-  gtk_bitset_remove_range (self->selected, position, n_items);
-  gtk_selection_model_selection_changed (model, position, n_items);
+  if (min <= max)
+    gtk_selection_model_selection_changed (model, min, max - min + 1);
 
   return TRUE;
 }
 
-static gboolean
-gtk_multi_selection_select_item (GtkSelectionModel *model,
-                                 guint              position,
-                                 gboolean           exclusive)
-{
-  return gtk_multi_selection_select_range (model, position, 1, exclusive);
-}
-
-static gboolean
-gtk_multi_selection_unselect_item (GtkSelectionModel *model,
-                                   guint              position)
-{
-  return gtk_multi_selection_unselect_range (model, position, 1);
-}
-
-static gboolean
-gtk_multi_selection_select_all (GtkSelectionModel *model)
-{
-  return gtk_multi_selection_select_range (model, 0, g_list_model_get_n_items (G_LIST_MODEL (model)), FALSE);
-}
-
-static gboolean
-gtk_multi_selection_unselect_all (GtkSelectionModel *model)
-{
-  return gtk_multi_selection_unselect_range (model, 0, g_list_model_get_n_items (G_LIST_MODEL (model)));
-}
-
 static gboolean
 gtk_multi_selection_add_or_remove (GtkSelectionModel    *model,
                                    gboolean              unselect_rest,
@@ -250,12 +221,7 @@ static void
 gtk_multi_selection_selection_model_init (GtkSelectionModelInterface *iface)
 {
   iface->is_selected = gtk_multi_selection_is_selected;
-  iface->select_item = gtk_multi_selection_select_item;
-  iface->unselect_item = gtk_multi_selection_unselect_item;
-  iface->select_range = gtk_multi_selection_select_range;
-  iface->unselect_range = gtk_multi_selection_unselect_range;
-  iface->select_all = gtk_multi_selection_select_all;
-  iface->unselect_all = gtk_multi_selection_unselect_all;
+  iface->set_selection = gtk_multi_selection_set_selection;
   iface->select_callback = gtk_multi_selection_select_callback;
   iface->unselect_callback = gtk_multi_selection_unselect_callback;
 }
diff --git a/gtk/gtkpropertyselection.c b/gtk/gtkpropertyselection.c
index 2fa311091e..0430d0ed04 100644
--- a/gtk/gtkpropertyselection.c
+++ b/gtk/gtkpropertyselection.c
@@ -138,77 +138,35 @@ gtk_property_selection_is_selected (GtkSelectionModel *model,
 }
 
 static gboolean
-gtk_property_selection_select_range (GtkSelectionModel *model,
-                                     guint              position,
-                                     guint              n_items,
-                                     gboolean           exclusive)
+gtk_property_selection_set_selection (GtkSelectionModel *model,
+                                      GtkBitset         *selected,
+                                      GtkBitset         *mask)
 {
   GtkPropertySelection *self = GTK_PROPERTY_SELECTION (model);
-  guint i;
-  guint n;
+  GtkBitsetIter iter;
+  guint i, n, min, max;
+  gboolean has_value;
 
   n = g_list_model_get_n_items (G_LIST_MODEL (self));
-  if (exclusive)
+  min = G_MAXUINT;
+  max = 0;
+
+  for (has_value = gtk_bitset_iter_init_first (&iter, mask, &i);
+       has_value && i < n;
+       has_value = gtk_bitset_iter_next (&iter, &i))
     {
-      for (i = 0; i < n; i++)
-        set_selected (self, i, FALSE);
+      set_selected (self, i, gtk_bitset_contains (selected, i));
+      /* XXX: Check if something changed? */
+      min = MIN (min, i);
+      max = MAX (max, i);
     }
 
-  for (i = position; i < position + n_items; i++)
-    set_selected (self, i, TRUE);
-
-  /* FIXME: do better here */
-  if (exclusive)
-    gtk_selection_model_selection_changed (model, 0, n);
-  else
-    gtk_selection_model_selection_changed (model, position, n_items);
-
-  return TRUE;
-}
-
-static gboolean
-gtk_property_selection_unselect_range (GtkSelectionModel *model,
-                                       guint              position,
-                                       guint              n_items)
-{
-  GtkPropertySelection *self = GTK_PROPERTY_SELECTION (model);
-  guint i;
-
-  for (i = position; i < position + n_items; i++)
-    set_selected (self, i, FALSE);
-
-  gtk_selection_model_selection_changed (model, position, n_items);
+  if (min <= max)
+    gtk_selection_model_selection_changed (model, min, max - min + 1);
 
   return TRUE;
 }
 
-static gboolean
-gtk_property_selection_select_item (GtkSelectionModel *model,
-                                    guint              position,
-                                    gboolean           exclusive)
-{
-  return gtk_property_selection_select_range (model, position, 1, exclusive);
-}
-
-static gboolean
-gtk_property_selection_unselect_item (GtkSelectionModel *model,
-                                      guint              position)
-{
-  return gtk_property_selection_unselect_range (model, position, 1);
-}
-
-static gboolean
-gtk_property_selection_select_all (GtkSelectionModel *model)
-{
-  return gtk_property_selection_select_range (model, 0, g_list_model_get_n_items (G_LIST_MODEL (model)), 
FALSE);
-}
-
-static gboolean
-gtk_property_selection_unselect_all (GtkSelectionModel *model)
-{
-  return gtk_property_selection_unselect_range (model, 0, g_list_model_get_n_items (G_LIST_MODEL (model)));
-}
-
 static gboolean
 gtk_property_selection_add_or_remove (GtkSelectionModel    *model,
                                       gboolean              unselect_rest,
@@ -280,12 +238,7 @@ static void
 gtk_property_selection_selection_model_init (GtkSelectionModelInterface *iface)
 {
   iface->is_selected = gtk_property_selection_is_selected;
-  iface->select_item = gtk_property_selection_select_item;
-  iface->unselect_item = gtk_property_selection_unselect_item;
-  iface->select_range = gtk_property_selection_select_range;
-  iface->unselect_range = gtk_property_selection_unselect_range;
-  iface->select_all = gtk_property_selection_select_all;
-  iface->unselect_all = gtk_property_selection_unselect_all;
+  iface->set_selection = gtk_property_selection_set_selection;
   iface->select_callback = gtk_property_selection_select_callback;
   iface->unselect_callback = gtk_property_selection_unselect_callback;
 }
diff --git a/gtk/gtkselectionmodel.c b/gtk/gtkselectionmodel.c
index 24db61f739..c62efbb538 100644
--- a/gtk/gtkselectionmodel.c
+++ b/gtk/gtkselectionmodel.c
@@ -114,13 +114,48 @@ gtk_selection_model_default_select_item (GtkSelectionModel *model,
                                          guint              position,
                                          gboolean           unselect_rest)
 {
-  return FALSE;
+  GtkBitset *selected;
+  GtkBitset *mask;
+  gboolean result;
+
+  selected = gtk_bitset_new_empty ();
+  gtk_bitset_add (selected, position);
+  if (unselect_rest)
+    {
+      mask = gtk_bitset_new_empty ();
+      gtk_bitset_add_range (mask, 0, g_list_model_get_n_items (G_LIST_MODEL (model)));
+    }
+  else
+    {
+      mask = gtk_bitset_ref (selected);
+    }
+
+  result = gtk_selection_model_set_selection (model, selected, mask);
+
+  gtk_bitset_unref (selected);
+  gtk_bitset_unref (mask);
+
+  return result;
 }
+
 static gboolean
 gtk_selection_model_default_unselect_item (GtkSelectionModel *model,
                                            guint              position)
 {
-  return FALSE;
+  GtkBitset *selected;
+  GtkBitset *mask;
+  gboolean result;
+
+  selected = gtk_bitset_new_empty ();
+  mask = gtk_bitset_new_empty ();
+  gtk_bitset_add (mask, position);
+
+  result = gtk_selection_model_set_selection (model, selected, mask);
+
+  gtk_bitset_unref (selected);
+  gtk_bitset_unref (mask);
+
+  return result;
 }
 
 static gboolean
@@ -129,7 +164,28 @@ gtk_selection_model_default_select_range (GtkSelectionModel *model,
                                           guint              n_items,
                                           gboolean           unselect_rest)
 {
-  return FALSE;
+  GtkBitset *selected;
+  GtkBitset *mask;
+  gboolean result;
+
+  selected = gtk_bitset_new_empty ();
+  gtk_bitset_add_range (selected, position, n_items);
+  if (unselect_rest)
+    {
+      mask = gtk_bitset_new_empty ();
+      gtk_bitset_add_range (mask, 0, g_list_model_get_n_items (G_LIST_MODEL (model)));
+    }
+  else
+    {
+      mask = gtk_bitset_ref (selected);
+    }
+
+  result = gtk_selection_model_set_selection (model, selected, mask);
+
+  gtk_bitset_unref (selected);
+  gtk_bitset_unref (mask);
+
+  return result;
 }
 
 static gboolean
@@ -137,7 +193,20 @@ gtk_selection_model_default_unselect_range (GtkSelectionModel *model,
                                             guint              position,
                                             guint              n_items)
 {
-  return FALSE;
+  GtkBitset *selected;
+  GtkBitset *mask;
+  gboolean result;
+
+  selected = gtk_bitset_new_empty ();
+  mask = gtk_bitset_new_empty ();
+  gtk_bitset_add_range (mask, position, n_items);
+
+  result = gtk_selection_model_set_selection (model, selected, mask);
+
+  gtk_bitset_unref (selected);
+  gtk_bitset_unref (mask);
+
+  return result;
 }
 
 static gboolean
@@ -169,6 +238,14 @@ gtk_selection_model_default_unselect_all (GtkSelectionModel *model)
   return gtk_selection_model_unselect_range (model, 0, g_list_model_get_n_items (G_LIST_MODEL (model)));
 }
 
+static gboolean
+gtk_selection_model_default_set_selection (GtkSelectionModel *model,
+                                           GtkBitset         *selected,
+                                           GtkBitset         *mask)
+{
+  return FALSE;
+}
+
 static void
 gtk_selection_model_default_init (GtkSelectionModelInterface *iface)
 {
@@ -180,6 +257,7 @@ gtk_selection_model_default_init (GtkSelectionModelInterface *iface)
   iface->unselect_range = gtk_selection_model_default_unselect_range;
   iface->select_all = gtk_selection_model_default_select_all;
   iface->unselect_all = gtk_selection_model_default_unselect_all;
+  iface->set_selection = gtk_selection_model_default_set_selection;
   iface->select_callback = gtk_selection_model_default_select_callback;
   iface->unselect_callback = gtk_selection_model_default_unselect_callback;
 
@@ -294,6 +372,9 @@ gtk_selection_model_get_selection_in_range (GtkSelectionModel *model,
  * @unselect_rest: whether previously selected items should be unselected
  *
  * Requests to select an item in the model.
+ *
+ * Returns: %TRUE if this action was supported and no fallback should be
+ *     tried. This does not mean the item was selected.
  */
 gboolean
 gtk_selection_model_select_item (GtkSelectionModel *model,
@@ -302,7 +383,7 @@ gtk_selection_model_select_item (GtkSelectionModel *model,
 {
   GtkSelectionModelInterface *iface;
 
-  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), 0);
+  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), FALSE);
 
   iface = GTK_SELECTION_MODEL_GET_IFACE (model);
   return iface->select_item (model, position, unselect_rest);
@@ -314,6 +395,9 @@ gtk_selection_model_select_item (GtkSelectionModel *model,
  * @position: the position of the item to unselect
  *
  * Requests to unselect an item in the model.
+ *
+ * Returns: %TRUE if this action was supported and no fallback should be
+ *     tried. This does not mean the item was unselected.
  */
 gboolean
 gtk_selection_model_unselect_item (GtkSelectionModel *model,
@@ -321,7 +405,7 @@ gtk_selection_model_unselect_item (GtkSelectionModel *model,
 {
   GtkSelectionModelInterface *iface;
 
-  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), 0);
+  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), FALSE);
 
   iface = GTK_SELECTION_MODEL_GET_IFACE (model);
   return iface->unselect_item (model, position);
@@ -335,6 +419,9 @@ gtk_selection_model_unselect_item (GtkSelectionModel *model,
  * @unselect_rest: whether previously selected items should be unselected
  *
  * Requests to select a range of items in the model.
+ *
+ * Returns: %TRUE if this action was supported and no fallback should be
+ *     tried. This does not mean the range was selected.
  */
 gboolean
 gtk_selection_model_select_range (GtkSelectionModel *model,
@@ -344,7 +431,7 @@ gtk_selection_model_select_range (GtkSelectionModel *model,
 {
   GtkSelectionModelInterface *iface;
 
-  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), 0);
+  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), FALSE);
 
   iface = GTK_SELECTION_MODEL_GET_IFACE (model);
   return iface->select_range (model, position, n_items, unselect_rest);
@@ -357,6 +444,9 @@ gtk_selection_model_select_range (GtkSelectionModel *model,
  * @n_items: the number of items to unselect
  *
  * Requests to unselect a range of items in the model.
+ *
+ * Returns: %TRUE if this action was supported and no fallback should be
+ *     tried. This does not mean the range was unselected.
  */
 gboolean
 gtk_selection_model_unselect_range (GtkSelectionModel *model,
@@ -365,7 +455,7 @@ gtk_selection_model_unselect_range (GtkSelectionModel *model,
 {
   GtkSelectionModelInterface *iface;
 
-  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), 0);
+  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), FALSE);
 
   iface = GTK_SELECTION_MODEL_GET_IFACE (model);
   return iface->unselect_range (model, position, n_items);
@@ -376,13 +466,16 @@ gtk_selection_model_unselect_range (GtkSelectionModel *model,
  * @model: a #GtkSelectionModel
  *
  * Requests to select all items in the model.
+ *
+ * Returns: %TRUE if this action was supported and no fallback should be
+ *     tried. This does not mean that all items are now selected.
  */
 gboolean
 gtk_selection_model_select_all (GtkSelectionModel *model)
 {
   GtkSelectionModelInterface *iface;
 
-  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), 0);
+  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), FALSE);
 
   iface = GTK_SELECTION_MODEL_GET_IFACE (model);
   return iface->select_all (model);
@@ -393,18 +486,76 @@ gtk_selection_model_select_all (GtkSelectionModel *model)
  * @model: a #GtkSelectionModel
  *
  * Requests to unselect all items in the model.
+ *
+ * Returns: %TRUE if this action was supported and no fallback should be
+ *     tried. This does not mean that all items are now unselected.
  */
 gboolean
 gtk_selection_model_unselect_all (GtkSelectionModel *model)
 {
   GtkSelectionModelInterface *iface;
 
-  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), 0);
+  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), FALSE);
 
   iface = GTK_SELECTION_MODEL_GET_IFACE (model);
   return iface->unselect_all (model);
 }
 
+/**
+ * gtk_selection_model_set_selection:
+ * @model: a #GtkSelectionModel
+ * @selected: bitmask specifying if items should be selected or
+ *     unselected
+ * @mask: bitmask specifying which items should be updated
+ *
+ * This is the most advanced selection updating method that allows
+ * the most fine-grained control over selection changes.
+ * If you can, you should try the simpler versions, as implementations
+ * are more likely to implement support for those.
+ *
+ * Requests that the selection state of all positions set in @mask be
+ * updated to the respecitve value in the @selected bitmask.  
+ *
+ * In pseudocode, it would look something like this:
+ *
+ * |[<!-- language="C" -->
+ * for (i = 0; i < n_items; i++)
+ *   {
+ *     // don't change values not in the mask
+ *     if (!gtk_bitset_contains (mask, i))
+ *       continue;
+ *
+ *     if (gtk_bitset_contains (selected, i))
+ *       select_item (i);
+ *     else
+ *       unselect_item (i);
+ *   }
+ *
+ * gtk_selection_model_selection_changed (model, first_changed_item, n_changed_items);
+ * ]|
+ *
+ * @mask and @selected must not be modified. They may refer to the same bitset,
+ * which would mean that every item in the set should be selected.
+ *
+ * Returns: %TRUE if this action was supported and no fallback should be
+ *     tried. This does not mean that all items were updated according
+ *     to the inputs.
+ **/
+gboolean
+gtk_selection_model_set_selection (GtkSelectionModel *model,
+                                   GtkBitset         *selected,
+                                   GtkBitset         *mask)
+{
+  GtkSelectionModelInterface *iface;
+
+  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), FALSE);
+  g_return_val_if_fail (selected != NULL, FALSE);
+  g_return_val_if_fail (mask != NULL, FALSE);
+
+  iface = GTK_SELECTION_MODEL_GET_IFACE (model);
+  return iface->set_selection (model, selected, mask);
+}
+
 /**
  * gtk_selection_model_select_callback:
  * @model: a #GtkSelectionModel
diff --git a/gtk/gtkselectionmodel.h b/gtk/gtkselectionmodel.h
index e48ce20fee..8b90fc6793 100644
--- a/gtk/gtkselectionmodel.h
+++ b/gtk/gtkselectionmodel.h
@@ -82,6 +82,9 @@ typedef void     (* GtkSelectionCallback) (guint     position,
  *     unsupported or known to fail for all items, return %FALSE.
  * @unselect_all: Unselect all items in the model. If the operation is
  *     unsupported or known to fail for all items, return %FALSE.
+ * @set_selection: Set selection state of all items in mask to selected.
+ *     See gtk_selection_model_set_selection() for a detailed explanation
+ *     of this function.
  *
  * The list of virtual functions for the #GtkSelectionModel interface.
  * No function must be implemented, but unless #GtkSelectionModel::is_selected()
@@ -91,6 +94,10 @@ typedef void     (* GtkSelectionCallback) (guint     position,
  * selecting or unselecting items. Of course, if the model does not do that,
  * it means that users cannot select or unselect items in a list widget
  * using the model.
+ *
+ * All selection functions fall back to #GtkSelectionModel::set_selection()
+ * so it is sufficient to implement just that function for full selection
+ * support.
  */
 struct _GtkSelectionModelInterface
 {
@@ -118,6 +125,9 @@ struct _GtkSelectionModelInterface
                                                                  guint                   n_items);
   gboolean              (* select_all)                          (GtkSelectionModel      *model);
   gboolean              (* unselect_all)                        (GtkSelectionModel      *model);
+  gboolean              (* set_selection)                       (GtkSelectionModel      *model,
+                                                                 GtkBitset              *selected,
+                                                                 GtkBitset              *mask);
   gboolean              (* select_callback)                     (GtkSelectionModel      *model,
                                                                  gboolean                unselect_rest,
                                                                  GtkSelectionCallback    callback,
@@ -158,6 +168,10 @@ GDK_AVAILABLE_IN_ALL
 gboolean                gtk_selection_model_select_all          (GtkSelectionModel      *model);
 GDK_AVAILABLE_IN_ALL
 gboolean                gtk_selection_model_unselect_all        (GtkSelectionModel      *model);
+GDK_AVAILABLE_IN_ALL
+gboolean                gtk_selection_model_set_selection       (GtkSelectionModel      *model,
+                                                                 GtkBitset              *selected,
+                                                                 GtkBitset              *mask);
 
 GDK_AVAILABLE_IN_ALL
 gboolean                gtk_selection_model_select_callback     (GtkSelectionModel      *model,
diff --git a/testsuite/gtk/multiselection.c b/testsuite/gtk/multiselection.c
index 3c59d307f3..c9ec1b3bc6 100644
--- a/testsuite/gtk/multiselection.c
+++ b/testsuite/gtk/multiselection.c
@@ -396,7 +396,7 @@ test_select_range (void)
   ret = gtk_selection_model_select_range (selection, 3, 2, FALSE);
   g_assert_true (ret);
   assert_selection (selection, "3 4 5");
-  assert_selection_changes (selection, "3:2");
+  assert_selection_changes (selection, "4:1");
 
   ret = gtk_selection_model_select_range (selection, 0, 1, TRUE);
   g_assert_true (ret);
@@ -438,56 +438,13 @@ test_readd (void)
   g_object_unref (selection);
 }
 
-typedef struct {
-  guint start;
-  guint n;
-  gboolean in;
-} SelectionData;
-
-static void
-select_some (guint position,
-             guint *start,
-             guint *n,
-             gboolean *selected,
-             gpointer data)
-{
-  SelectionData *sdata = data;
-  guint i;
-
-  for (i = 0; sdata[i].n != 0; i++)
-    {
-      if (sdata[i].start <= position &&
-          position < sdata[i].start + sdata[i].n)
-        break;
-    }
-
-  *start = sdata[i].start;
-  *n = sdata[i].n;
-  *selected = sdata[i].in;
-}
-
 static void
-test_callback (void)
+test_set_selection (void)
 {
   GtkSelectionModel *selection;
   gboolean ret;
   GListStore *store;
-  SelectionData data[] = {
-    { 0, 2, FALSE },
-    { 2, 3, TRUE },
-    { 5, 2, FALSE },
-    { 6, 3, TRUE },
-    { 9, 1, FALSE },
-    { 0, 0, FALSE }
-  };
-
-  SelectionData more_data[] = {
-    { 0, 3, FALSE },
-    { 3, 1, TRUE },
-    { 4, 3, FALSE },
-    { 7, 1, TRUE },
-    { 0, 0, FALSE }
-  };
+  GtkBitset *selected, *mask;
 
   store = new_store (1, 10, 1);
 
@@ -496,13 +453,26 @@ test_callback (void)
   assert_selection (selection, "");
   assert_selection_changes (selection, "");
 
-  ret = gtk_selection_model_select_callback (selection, FALSE, select_some, data);
+  selected = gtk_bitset_new_empty ();
+  gtk_bitset_add_range (selected, 2, 3);
+  gtk_bitset_add_range (selected, 6, 3);
+  mask = gtk_bitset_new_empty ();
+  gtk_bitset_add_range (mask, 0, 100); /* too big on purpose */
+  ret = gtk_selection_model_set_selection (selection, selected, mask);
   g_assert_true (ret);
+  gtk_bitset_unref (selected);
+  gtk_bitset_unref (mask);
   assert_selection (selection, "3 4 5 7 8 9");
   assert_selection_changes (selection, "2:7");
 
-  ret = gtk_selection_model_unselect_callback (selection, select_some, more_data);
+  selected = gtk_bitset_new_empty ();
+  mask = gtk_bitset_new_empty ();
+  gtk_bitset_add (mask, 3);
+  gtk_bitset_add (mask, 7);
+  ret = gtk_selection_model_set_selection (selection, selected, mask);
   g_assert_true (ret);
+  gtk_bitset_unref (selected);
+  gtk_bitset_unref (mask);
   assert_selection (selection, "3 5 7 9");
   assert_selection_changes (selection, "3:5");
 
@@ -528,7 +498,7 @@ main (int argc, char *argv[])
   g_test_add_func ("/multiselection/selection", test_selection);
   g_test_add_func ("/multiselection/select-range", test_select_range);
   g_test_add_func ("/multiselection/readd", test_readd);
-  g_test_add_func ("/multiselection/callback", test_callback);
+  g_test_add_func ("/multiselection/set_selection", test_set_selection);
 
   return g_test_run ();
 }


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