[gtk/wip/otte/bitset: 213/217] selectionmodel: Replace query_range() with get_selection()
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/bitset: 213/217] selectionmodel: Replace query_range() with get_selection()
- Date: Sun, 21 Jun 2020 13:02:22 +0000 (UTC)
commit 2f22912cfd052cd38f7d953816c2187d002bf10a
Author: Benjamin Otte <otte redhat com>
Date: Sun Jun 14 05:30:06 2020 +0200
selectionmodel: Replace query_range() with get_selection()
docs/reference/gtk/gtk4-sections.txt | 3 +-
gtk/gtkmultiselection.c | 18 -----
gtk/gtknoselection.c | 23 ------
gtk/gtkpropertyselection.c | 38 +--------
gtk/gtkselectionmodel.c | 148 ++++++++++++++++++++---------------
gtk/gtkselectionmodel.h | 38 +++++----
gtk/gtksingleselection.c | 62 ++++-----------
testsuite/gtk/singleselection.c | 46 +++++------
8 files changed, 150 insertions(+), 226 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 59df2f46e8..19bf9d5302 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -344,6 +344,8 @@ gtk_list_box_row_get_type
<TITLE>GtkSelectionModel</TITLE>
GtkSelectionModel
gtk_selection_model_is_selected
+gtk_selection_model_get_selection
+gtk_selection_model_get_selection_in_range
gtk_selection_model_select_item
gtk_selection_model_unselect_item
gtk_selection_model_select_range
@@ -353,7 +355,6 @@ gtk_selection_model_unselect_all
GtkSelectionCallback
gtk_selection_model_select_callback
gtk_selection_model_unselect_callback
-gtk_selection_model_query_range
<SUBSECTION>
gtk_selection_model_selection_changed
<SUBSECTION Standard>
diff --git a/gtk/gtkmultiselection.c b/gtk/gtkmultiselection.c
index 051d45ae33..40fc3402a9 100644
--- a/gtk/gtkmultiselection.c
+++ b/gtk/gtkmultiselection.c
@@ -246,21 +246,6 @@ gtk_multi_selection_unselect_callback (GtkSelectionModel *model,
return gtk_multi_selection_add_or_remove (model, FALSE, FALSE, callback, data);
}
-#if 0
-static void
-gtk_multi_selection_query_range (GtkSelectionModel *model,
- guint position,
- guint *start_range,
- guint *n_items,
- gboolean *selected)
-{
- GtkMultiSelection *self = GTK_MULTI_SELECTION (model);
- guint upper_bound = g_list_model_get_n_items (self->model);
-
- gtk_set_find_range (self->selected, position, upper_bound, start_range, n_items, selected);
-}
-#endif
-
static void
gtk_multi_selection_selection_model_init (GtkSelectionModelInterface *iface)
{
@@ -273,9 +258,6 @@ gtk_multi_selection_selection_model_init (GtkSelectionModelInterface *iface)
iface->unselect_all = gtk_multi_selection_unselect_all;
iface->select_callback = gtk_multi_selection_select_callback;
iface->unselect_callback = gtk_multi_selection_unselect_callback;
-#if 0
- iface->query_range = gtk_multi_selection_query_range;
-#endif
}
G_DEFINE_TYPE_EXTENDED (GtkMultiSelection, gtk_multi_selection, G_TYPE_OBJECT, 0,
diff --git a/gtk/gtknoselection.c b/gtk/gtknoselection.c
index c3706f2e1c..192d3e75b1 100644
--- a/gtk/gtknoselection.c
+++ b/gtk/gtknoselection.c
@@ -89,32 +89,9 @@ gtk_no_selection_list_model_init (GListModelInterface *iface)
iface->get_item = gtk_no_selection_get_item;
}
-static gboolean
-gtk_no_selection_is_selected (GtkSelectionModel *model,
- guint position)
-{
- return FALSE;
-}
-
-static void
-gtk_no_selection_query_range (GtkSelectionModel *model,
- guint position,
- guint *start_range,
- guint *n_range,
- gboolean *selected)
-{
- GtkNoSelection *self = GTK_NO_SELECTION (model);
-
- *start_range = 0;
- *n_range = g_list_model_get_n_items (self->model);
- *selected = FALSE;
-}
-
static void
gtk_no_selection_selection_model_init (GtkSelectionModelInterface *iface)
{
- iface->is_selected = gtk_no_selection_is_selected;
- iface->query_range = gtk_no_selection_query_range;
}
G_DEFINE_TYPE_EXTENDED (GtkNoSelection, gtk_no_selection, G_TYPE_OBJECT, 0,
diff --git a/gtk/gtkpropertyselection.c b/gtk/gtkpropertyselection.c
index 25fb94846d..2fa311091e 100644
--- a/gtk/gtkpropertyselection.c
+++ b/gtk/gtkpropertyselection.c
@@ -21,6 +21,7 @@
#include "gtkpropertyselection.h"
+#include "gtkbitset.h"
#include "gtkintl.h"
#include "gtkselectionmodel.h"
@@ -275,42 +276,6 @@ gtk_property_selection_unselect_callback (GtkSelectionModel *model,
return gtk_property_selection_add_or_remove (model, FALSE, FALSE, callback, data);
}
-static void
-gtk_property_selection_query_range (GtkSelectionModel *model,
- guint position,
- guint *start_range,
- guint *n_items,
- gboolean *selected)
-{
- GtkPropertySelection *self = GTK_PROPERTY_SELECTION (model);
- guint n;
- gboolean sel;
- guint start, end;
-
- n = g_list_model_get_n_items (G_LIST_MODEL (self));
- sel = is_selected (self, position);
-
- start = position;
- while (start > 0)
- {
- if (is_selected (self, start - 1) != sel)
- break;
- start--;
- }
-
- end = position;
- while (end + 1 < n)
- {
- if (is_selected (self, end + 1) != sel)
- break;
- end++;
- }
-
- *start_range = start;
- *n_items = end - start + 1;
- *selected = sel;
-}
-
static void
gtk_property_selection_selection_model_init (GtkSelectionModelInterface *iface)
{
@@ -323,7 +288,6 @@ gtk_property_selection_selection_model_init (GtkSelectionModelInterface *iface)
iface->unselect_all = gtk_property_selection_unselect_all;
iface->select_callback = gtk_property_selection_select_callback;
iface->unselect_callback = gtk_property_selection_unselect_callback;
- iface->query_range = gtk_property_selection_query_range;
}
G_DEFINE_TYPE_EXTENDED (GtkPropertySelection, gtk_property_selection, G_TYPE_OBJECT, 0,
diff --git a/gtk/gtkselectionmodel.c b/gtk/gtkselectionmodel.c
index 1bd62e810d..24db61f739 100644
--- a/gtk/gtkselectionmodel.c
+++ b/gtk/gtkselectionmodel.c
@@ -21,6 +21,7 @@
#include "gtkselectionmodel.h"
+#include "gtkbitset.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
@@ -79,7 +80,33 @@ static gboolean
gtk_selection_model_default_is_selected (GtkSelectionModel *model,
guint position)
{
- return FALSE;
+ GtkBitset *bitset;
+ gboolean selected;
+
+ bitset = gtk_selection_model_get_selection_in_range (model, position, 1);
+ selected = gtk_bitset_contains (bitset, position);
+ gtk_bitset_unref (bitset);
+
+ return selected;
+}
+
+static GtkBitset *
+gtk_selection_model_default_get_selection_in_range (GtkSelectionModel *model,
+ guint position,
+ guint n_items)
+{
+ GtkBitset *bitset;
+ guint i;
+
+ bitset = gtk_bitset_new_empty ();
+
+ for (i = position; i < position + n_items; i++)
+ {
+ if (gtk_selection_model_is_selected (model, i))
+ gtk_bitset_add (bitset, i);
+ }
+
+ return bitset;
}
static gboolean
@@ -142,31 +169,11 @@ 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 void
-gtk_selection_model_default_query_range (GtkSelectionModel *model,
- guint position,
- guint *start_range,
- guint *n_items,
- gboolean *selected)
-{
- *start_range = position;
-
- if (position >= g_list_model_get_n_items (G_LIST_MODEL (model)))
- {
- *n_items = 0;
- *selected = FALSE;
- }
- else
- {
- *n_items = 1;
- *selected = gtk_selection_model_is_selected (model, position);
- }
-}
-
static void
gtk_selection_model_default_init (GtkSelectionModelInterface *iface)
{
iface->is_selected = gtk_selection_model_default_is_selected;
+ iface->get_selection_in_range = gtk_selection_model_default_get_selection_in_range;
iface->select_item = gtk_selection_model_default_select_item;
iface->unselect_item = gtk_selection_model_default_unselect_item;
iface->select_range = gtk_selection_model_default_select_range;
@@ -175,7 +182,6 @@ gtk_selection_model_default_init (GtkSelectionModelInterface *iface)
iface->unselect_all = gtk_selection_model_default_unselect_all;
iface->select_callback = gtk_selection_model_default_select_callback;
iface->unselect_callback = gtk_selection_model_default_unselect_callback;
- iface->query_range = gtk_selection_model_default_query_range;
/**
* GtkSelectionModel::selection-changed
@@ -225,6 +231,62 @@ gtk_selection_model_is_selected (GtkSelectionModel *model,
return iface->is_selected (model, position);
}
+/**
+ * gtk_selection_model_get_selection:
+ * @model: a #GtkSelectionModel
+ *
+ * Gets the set containing all currently selected items in the model.
+ *
+ * This function may be slow, so if you are only interested in single item,
+ * consider using gtk_selection_model_is_selected() or if you are only
+ * interested in a few consider gtk_selection_model_get_selection_in_range().
+ *
+ * Returns: (transfer full): a #GtkBitset containing all the values currently
+ * selected in @model. If no items are selected, the bitset is empty.
+ * The bitset must not be modified.
+ **/
+GtkBitset *
+gtk_selection_model_get_selection (GtkSelectionModel *model)
+{
+ g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), gtk_bitset_new_empty ());
+
+ return gtk_selection_model_get_selection_in_range (model, 0, g_list_model_get_n_items (G_LIST_MODEL
(model)));
+}
+
+/**
+ * gtk_selection_model_get_selection_in_range:
+ * @model: a #GtkSelectionModel
+ * @position: start of the queired range
+ * @n_items: number of items in the queried range
+ *
+ * Gets a set containing a set where the values in the range [position,
+ * position + n_items) match the selected state of the items in that range.
+ * All values outside that range are undefined.
+ *
+ * This function is an optimization for gtk_selection_model_get_selection() when
+ * you are only interested in part of the model's selected state. A common use
+ * case is in response to the :selection-changed signal.
+ *
+ * Returns: A #GtkBitset that matches the selection state for the given state
+ * with all other values being undefined.
+ * The bitset must not be modified.
+ **/
+GtkBitset *
+gtk_selection_model_get_selection_in_range (GtkSelectionModel *model,
+ guint position,
+ guint n_items)
+{
+ GtkSelectionModelInterface *iface;
+
+ g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), gtk_bitset_new_empty ());
+
+ if (n_items == 0)
+ return gtk_bitset_new_empty ();
+
+ iface = GTK_SELECTION_MODEL_GET_IFACE (model);
+ return iface->get_selection_in_range (model, position, n_items);
+}
+
/**
* gtk_selection_model_select_item:
* @model: a #GtkSelectionModel
@@ -383,46 +445,6 @@ gtk_selection_model_unselect_callback (GtkSelectionModel *model,
return GTK_SELECTION_MODEL_GET_IFACE (model)->unselect_callback (model, callback, data);
}
-/**
- * gtk_selection_model_query_range:
- * @model: a #GtkSelectionModel
- * @position: the position inside the range
- * @start_range: (out): returns the position of the first element of the range
- * @n_items: (out): returns the size of the range
- * @selected: (out): returns whether items in @range are selected
- *
- * This function allows to query the selection status of multiple elements at once.
- * It is passed a position and returns a range of elements of uniform selection status.
- *
- * If @position is greater than the number of items in @model, @n_items is set to 0.
- * Otherwise the returned range is guaranteed to include the passed-in position, so
- * @n_items will be >= 1.
- *
- * Positions directly adjacent to the returned range may have the same selection
- * status as the returned range.
- *
- * This is an optimization function to make iterating over a model faster when few
- * items are selected. However, it is valid behavior for implementations to use a
- * naive implementation that only ever returns a single element.
- */
-void
-gtk_selection_model_query_range (GtkSelectionModel *model,
- guint position,
- guint *start_range,
- guint *n_items,
- gboolean *selected)
-{
- GtkSelectionModelInterface *iface;
-
- g_return_if_fail (GTK_IS_SELECTION_MODEL (model));
- g_return_if_fail (start_range != NULL);
- g_return_if_fail (n_items != NULL);
- g_return_if_fail (selected != NULL);
-
- iface = GTK_SELECTION_MODEL_GET_IFACE (model);
- return iface->query_range (model, position, start_range, n_items, selected);
-}
-
/**
* gtk_selection_model_selection_changed:
* @model: a #GtkSelectionModel
diff --git a/gtk/gtkselectionmodel.h b/gtk/gtkselectionmodel.h
index 55a012e3d6..e48ce20fee 100644
--- a/gtk/gtkselectionmodel.h
+++ b/gtk/gtkselectionmodel.h
@@ -24,7 +24,7 @@
#error "Only <gtk/gtk.h> can be included directly."
#endif
-#include <gdk/gdk.h>
+#include <gtk/gtktypes.h>
G_BEGIN_DECLS
@@ -66,6 +66,9 @@ typedef void (* GtkSelectionCallback) (guint position,
/**
* GtkSelectionModelInterface:
* @is_selected: Return if the item at the given position is selected.
+ * @get_selection_in_range: Return a bitset with all currently selected
+ * items in the given range. By default, this function will call
+ * #GtkSelectionModel::is_selected() on all items in the given range.
* @select_item: Select the item in the given position. If the operation
* is known to fail, return %FALSE.
* @unselect_item: Unselect the item in the given position. If the
@@ -81,10 +84,13 @@ typedef void (* GtkSelectionCallback) (guint position,
* unsupported or known to fail for all items, return %FALSE.
*
* The list of virtual functions for the #GtkSelectionModel interface.
- * All getter functions are mandatory to implement, but the model does
- * not need to implement any functions to support 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 widgets using the model.
+ * No function must be implemented, but unless #GtkSelectionModel::is_selected()
+ * is implemented, it will not be possible to select items in the set.
+ *
+ * The model does not need to implement any functions to support either
+ * 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.
*/
struct _GtkSelectionModelInterface
{
@@ -94,6 +100,9 @@ struct _GtkSelectionModelInterface
/*< public >*/
gboolean (* is_selected) (GtkSelectionModel *model,
guint position);
+ GtkBitset * (* get_selection_in_range) (GtkSelectionModel *model,
+ guint position,
+ guint n_items);
gboolean (* select_item) (GtkSelectionModel *model,
guint position,
@@ -116,16 +125,18 @@ struct _GtkSelectionModelInterface
gboolean (* unselect_callback) (GtkSelectionModel *model,
GtkSelectionCallback callback,
gpointer data);
- void (* query_range) (GtkSelectionModel *model,
- guint position,
- guint *start_range,
- guint *n_items,
- gboolean *selected);
};
GDK_AVAILABLE_IN_ALL
gboolean gtk_selection_model_is_selected (GtkSelectionModel *model,
guint position);
+GDK_AVAILABLE_IN_ALL
+GtkBitset * gtk_selection_model_get_selection (GtkSelectionModel *model);
+GDK_AVAILABLE_IN_ALL
+GtkBitset * gtk_selection_model_get_selection_in_range
+ (GtkSelectionModel *model,
+ guint position,
+ guint n_items);
GDK_AVAILABLE_IN_ALL
gboolean gtk_selection_model_select_item (GtkSelectionModel *model,
@@ -158,13 +169,6 @@ gboolean gtk_selection_model_unselect_callback (GtkSelectionMod
GtkSelectionCallback callback,
gpointer data);
-GDK_AVAILABLE_IN_ALL
-void gtk_selection_model_query_range (GtkSelectionModel *model,
- guint position,
- guint *start_range,
- guint *n_items,
- gboolean *selected);
-
/* for implementations only */
GDK_AVAILABLE_IN_ALL
void gtk_selection_model_selection_changed (GtkSelectionModel *model,
diff --git a/gtk/gtksingleselection.c b/gtk/gtksingleselection.c
index 5d0172c7b1..bd35aed782 100644
--- a/gtk/gtksingleselection.c
+++ b/gtk/gtksingleselection.c
@@ -21,6 +21,7 @@
#include "gtksingleselection.h"
+#include "gtkbitset.h"
#include "gtkintl.h"
#include "gtkselectionmodel.h"
@@ -110,6 +111,21 @@ gtk_single_selection_is_selected (GtkSelectionModel *model,
return self->selected == position;
}
+static GtkBitset *
+gtk_single_selection_get_selection_in_range (GtkSelectionModel *model,
+ guint position,
+ guint n_items)
+{
+ GtkSingleSelection *self = GTK_SINGLE_SELECTION (model);
+ GtkBitset *result;
+
+ result = gtk_bitset_new_empty ();
+ if (self->selected != GTK_INVALID_LIST_POSITION)
+ gtk_bitset_add (result, self->selected);
+
+ return result;
+}
+
static gboolean
gtk_single_selection_select_item (GtkSelectionModel *model,
guint position,
@@ -138,57 +154,13 @@ gtk_single_selection_unselect_item (GtkSelectionModel *model,
return TRUE;
}
-static void
-gtk_single_selection_query_range (GtkSelectionModel *model,
- guint position,
- guint *start_range,
- guint *n_range,
- gboolean *selected)
-{
- GtkSingleSelection *self = GTK_SINGLE_SELECTION (model);
- guint n_items;
-
- n_items = g_list_model_get_n_items (self->model);
-
- if (position >= n_items)
- {
- *start_range = position;
- *n_range = 0;
- *selected = FALSE;
- }
- else if (self->selected == GTK_INVALID_LIST_POSITION)
- {
- *start_range = 0;
- *n_range = n_items;
- *selected = FALSE;
- }
- else if (position < self->selected)
- {
- *start_range = 0;
- *n_range = self->selected;
- *selected = FALSE;
- }
- else if (position > self->selected)
- {
- *start_range = self->selected + 1;
- *n_range = n_items - *start_range;
- *selected = FALSE;
- }
- else
- {
- *start_range = self->selected;
- *n_range = 1;
- *selected = TRUE;
- }
-}
-
static void
gtk_single_selection_selection_model_init (GtkSelectionModelInterface *iface)
{
iface->is_selected = gtk_single_selection_is_selected;
+ iface->get_selection_in_range = gtk_single_selection_get_selection_in_range;
iface->select_item = gtk_single_selection_select_item;
iface->unselect_item = gtk_single_selection_unselect_item;
- iface->query_range = gtk_single_selection_query_range;
}
G_DEFINE_TYPE_EXTENDED (GtkSingleSelection, gtk_single_selection, G_TYPE_OBJECT, 0,
diff --git a/testsuite/gtk/singleselection.c b/testsuite/gtk/singleselection.c
index 24de458e1c..81b96e90d0 100644
--- a/testsuite/gtk/singleselection.c
+++ b/testsuite/gtk/singleselection.c
@@ -593,28 +593,30 @@ test_persistence (void)
}
static void
-check_query_range (GtkSelectionModel *selection)
+check_get_selection (GtkSelectionModel *selection)
{
- guint i, j;
- guint position, n_items;
- gboolean selected;
+ GtkBitset *set;
+ guint i, n_items;
- /* check that range always contains position, and has uniform selection */
- for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (selection)); i++)
+ set = gtk_selection_model_get_selection (selection);
+
+ n_items = g_list_model_get_n_items (G_LIST_MODEL (selection));
+ if (n_items == 0)
{
- gtk_selection_model_query_range (selection, i, &position, &n_items, &selected);
- g_assert_cmpint (position, <=, i);
- g_assert_cmpint (i, <, position + n_items);
- for (j = position; j < position + n_items; j++)
- g_assert_true (selected == gtk_selection_model_is_selected (selection, j));
+ g_assert_true (gtk_bitset_is_empty (set));
}
-
- /* check that out-of-range returns the correct invalid values */
- i = MIN (i, g_random_int ());
- gtk_selection_model_query_range (selection, i, &position, &n_items, &selected);
- g_assert_cmpint (position, ==, i);
- g_assert_cmpint (n_items, ==, 0);
- g_assert_true (!selected);
+ else
+ {
+ for (i = 0; i < n_items; i++)
+ {
+ g_assert_cmpint (gtk_bitset_contains (set, i), ==, gtk_selection_model_is_selected (selection, i));
+ }
+
+ /* check that out-of-range has no bits set */
+ g_assert_cmpint (gtk_bitset_get_maximum (set), <, g_list_model_get_n_items (G_LIST_MODEL (selection)));
+ }
+
+ gtk_bitset_unref (set);
}
static void
@@ -625,16 +627,16 @@ test_query_range (void)
store = new_store (1, 5, 1);
selection = new_model (store, TRUE, TRUE);
- check_query_range (selection);
+ check_get_selection (selection);
gtk_selection_model_unselect_item (selection, 0);
- check_query_range (selection);
+ check_get_selection (selection);
gtk_selection_model_select_item (selection, 2, TRUE);
- check_query_range (selection);
+ check_get_selection (selection);
gtk_selection_model_select_item (selection, 4, TRUE);
- check_query_range (selection);
+ check_get_selection (selection);
ignore_selection_changes (selection);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]