[gtk/wip/otte/listview: 38/169] Redo sort list model with GtkSorter
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/listview: 38/169] Redo sort list model with GtkSorter
- Date: Fri, 13 Dec 2019 01:14:07 +0000 (UTC)
commit 0f7f9a0a781c0ae4007d932b7f7f173ecff4f7cc
Author: Matthias Clasen <mclasen redhat com>
Date: Mon Dec 2 23:44:22 2019 -0500
Redo sort list model with GtkSorter
Reshuffle the api to take full advantage
of GtkSorter. Update all callers.
docs/reference/gtk/gtk4-sections.txt | 5 +-
gtk/gtksortlistmodel.c | 218 ++++++++++++++++++-----------------
gtk/gtksortlistmodel.h | 21 ++--
gtk/inspector/controllers.c | 8 +-
testsuite/gtk/sortlistmodel.c | 23 +++-
5 files changed, 142 insertions(+), 133 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 6fed6829fe..e32cfe1336 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -2865,11 +2865,10 @@ gtk_multi_sorter_get_type
GtkSortListModel
gtk_sort_list_model_new
gtk_sort_list_model_new_for_type
-gtk_sort_list_model_set_sort_func
-gtk_sort_list_model_has_sort
+gtk_sort_list_model_set_sorter
+gtk_sort_list_model_get_sorter
gtk_sort_list_model_set_model
gtk_sort_list_model_get_model
-gtk_sort_list_model_resort
<SUBSECTION Standard>
GTK_SORT_LIST_MODEL
GTK_IS_SORT_LIST_MODEL
diff --git a/gtk/gtksortlistmodel.c b/gtk/gtksortlistmodel.c
index 4a3b09dde3..fc88d6de70 100644
--- a/gtk/gtksortlistmodel.c
+++ b/gtk/gtksortlistmodel.c
@@ -28,10 +28,10 @@
* SECTION:gtksortlistmodel
* @title: GtkSortListModel
* @short_description: A list model that sorts its items
- * @see_also: #GListModel
+ * @see_also: #GListModel, #GtkSorter
*
* #GtkSortListModel is a list model that takes a list model and
- * sorts its elements according to a compare function.
+ * sorts its elements according to a #GtkSorter.
*
* #GtkSortListModel is a generic model and because of that it
* cannot take advantage of any external knowledge when sorting.
@@ -42,9 +42,9 @@
enum {
PROP_0,
- PROP_HAS_SORT,
PROP_ITEM_TYPE,
PROP_MODEL,
+ PROP_SORTER,
NUM_PROPERTIES
};
@@ -54,9 +54,7 @@ struct _GtkSortListModel
GType item_type;
GListModel *model;
- GCompareDataFunc sort_func;
- gpointer user_data;
- GDestroyNotify user_destroy;
+ GtkSorter *sorter;
GSequence *sorted; /* NULL if sort_func == NULL */
GSequence *unsorted; /* NULL if sort_func == NULL */
@@ -157,6 +155,14 @@ gtk_sort_list_model_remove_items (GtkSortListModel *self,
*unmodified_end = end;
}
+static int
+_sort_func (gconstpointer item1,
+ gconstpointer item2,
+ gpointer data)
+{
+ return gtk_sorter_compare (GTK_SORTER (data), (gpointer)item1, (gpointer)item2);
+}
+
static void
gtk_sort_list_model_add_items (GtkSortListModel *self,
guint position,
@@ -173,7 +179,7 @@ gtk_sort_list_model_add_items (GtkSortListModel *self,
for (i = 0; i < n_items; i++)
{
gpointer item = g_list_model_get_item (self->model, position + i);
- sorted_iter = g_sequence_insert_sorted (self->sorted, item, self->sort_func, self->user_data);
+ sorted_iter = g_sequence_insert_sorted (self->sorted, item, _sort_func, self->sorter);
g_sequence_insert_before (unsorted_iter, sorted_iter);
if (unmodified_start != NULL || unmodified_end != NULL)
{
@@ -234,6 +240,10 @@ gtk_sort_list_model_set_property (GObject *object,
gtk_sort_list_model_set_model (self, g_value_get_object (value));
break;
+ case PROP_SORTER:
+ gtk_sort_list_model_set_sorter (self, g_value_get_object (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -250,10 +260,6 @@ gtk_sort_list_model_get_property (GObject *object,
switch (prop_id)
{
- case PROP_HAS_SORT:
- g_value_set_boolean (value, self->sort_func != NULL);
- break;
-
case PROP_ITEM_TYPE:
g_value_set_gtype (value, self->item_type);
break;
@@ -262,12 +268,26 @@ gtk_sort_list_model_get_property (GObject *object,
g_value_set_object (value, self->model);
break;
+ case PROP_SORTER:
+ g_value_set_object (value, self->sorter);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
+static void gtk_sort_list_model_resort (GtkSortListModel *self);
+
+static void
+gtk_sort_list_model_sorter_changed_cb (GtkSorter *sorter,
+ int change,
+ GtkSortListModel *self)
+{
+ gtk_sort_list_model_resort (self);
+}
+
static void
gtk_sort_list_model_clear_model (GtkSortListModel *self)
{
@@ -280,17 +300,23 @@ gtk_sort_list_model_clear_model (GtkSortListModel *self)
g_clear_pointer (&self->unsorted, g_sequence_free);
}
+static void
+gtk_sort_list_model_clear_sorter (GtkSortListModel *self)
+{
+ if (self->sorter == NULL)
+ return;
+
+ g_signal_handlers_disconnect_by_func (self->sorter, gtk_sort_list_model_sorter_changed_cb, self);
+ g_clear_object (&self->sorter);
+}
+
static void
gtk_sort_list_model_dispose (GObject *object)
{
GtkSortListModel *self = GTK_SORT_LIST_MODEL (object);
gtk_sort_list_model_clear_model (self);
- if (self->user_destroy)
- self->user_destroy (self->user_data);
- self->sort_func = NULL;
- self->user_data = NULL;
- self->user_destroy = NULL;
+ gtk_sort_list_model_clear_sorter (self);
G_OBJECT_CLASS (gtk_sort_list_model_parent_class)->dispose (object);
};
@@ -305,16 +331,16 @@ gtk_sort_list_model_class_init (GtkSortListModelClass *class)
gobject_class->dispose = gtk_sort_list_model_dispose;
/**
- * GtkSortListModel:has-sort:
+ * GtkSortListModel:sorter:
*
- * If a sort function is set for this model
+ * The sorter for this model
*/
- properties[PROP_HAS_SORT] =
- g_param_spec_boolean ("has-sort",
- P_("has sort"),
- P_("If a sort function is set for this model"),
- FALSE,
- GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
+ properties[PROP_SORTER] =
+ g_param_spec_object ("sorter",
+ P_("Sorter"),
+ P_("The sorter for this model"),
+ GTK_TYPE_SORTER,
+ GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkSortListModel:item-type:
@@ -348,36 +374,30 @@ gtk_sort_list_model_init (GtkSortListModel *self)
{
}
-
/**
* gtk_sort_list_model_new:
* @model: the model to sort
- * @sort_func: (allow-none): sort function or %NULL to not sort items
- * @user_data: user data passed to @sort_func
- * @user_destroy: destroy notifier for @user_data
+ * @sorter: (allow-none): the #GtkSorter to sort @model with
*
- * Creates a new sort list model that uses the @sort_func to sort @model.
+ * Creates a new sort list model that uses the @sorter to sort @model.
*
* Returns: a new #GtkSortListModel
**/
GtkSortListModel *
-gtk_sort_list_model_new (GListModel *model,
- GCompareDataFunc sort_func,
- gpointer user_data,
- GDestroyNotify user_destroy)
+gtk_sort_list_model_new (GListModel *model,
+ GtkSorter *sorter)
{
GtkSortListModel *result;
g_return_val_if_fail (G_IS_LIST_MODEL (model), NULL);
+ g_return_val_if_fail (sorter == NULL || GTK_IS_SORTER (sorter), NULL);
result = g_object_new (GTK_TYPE_SORT_LIST_MODEL,
"item-type", g_list_model_get_item_type (model),
"model", model,
+ "sorter", sorter,
NULL);
- if (sort_func)
- gtk_sort_list_model_set_sort_func (result, sort_func, user_data, user_destroy);
-
return result;
}
@@ -404,7 +424,7 @@ gtk_sort_list_model_new_for_type (GType item_type)
static void
gtk_sort_list_model_create_sequences (GtkSortListModel *self)
{
- if (!self->sort_func || self->model == NULL)
+ if (self->sorter == NULL || self->model == NULL)
return;
self->sorted = g_sequence_new (g_object_unref);
@@ -413,50 +433,6 @@ gtk_sort_list_model_create_sequences (GtkSortListModel *self)
gtk_sort_list_model_add_items (self, 0, g_list_model_get_n_items (self->model), NULL, NULL);
}
-/**
- * gtk_sort_list_model_set_sort_func:
- * @self: a #GtkSortListModel
- * @sort_func: (allow-none): sort function or %NULL to not sort items
- * @user_data: user data passed to @sort_func
- * @user_destroy: destroy notifier for @user_data
- *
- * Sets the function used to sort items. The function will be called for every
- * item and must return an integer less than, equal to, or greater than zero if
- * for two items from the model if the first item is considered to be respectively
- * less than, equal to, or greater than the second.
- **/
-void
-gtk_sort_list_model_set_sort_func (GtkSortListModel *self,
- GCompareDataFunc sort_func,
- gpointer user_data,
- GDestroyNotify user_destroy)
-{
- guint n_items;
-
- g_return_if_fail (GTK_IS_SORT_LIST_MODEL (self));
- g_return_if_fail (sort_func != NULL || (user_data == NULL && !user_destroy));
-
- if (!sort_func && !self->sort_func)
- return;
-
- if (self->user_destroy)
- self->user_destroy (self->user_data);
-
- g_clear_pointer (&self->unsorted, g_sequence_free);
- g_clear_pointer (&self->sorted, g_sequence_free);
- self->sort_func = sort_func;
- self->user_data = user_data;
- self->user_destroy = user_destroy;
-
- gtk_sort_list_model_create_sequences (self);
-
- n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
- if (n_items > 1)
- g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items, n_items);
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HAS_SORT]);
-}
-
/**
* gtk_sort_list_model_set_model:
* @self: a #GtkSortListModel
@@ -517,32 +493,7 @@ gtk_sort_list_model_get_model (GtkSortListModel *self)
return self->model;
}
-/**
- * gtk_sort_list_model_has_sort:
- * @self: a #GtkSortListModel
- *
- * Checks if a sort function is currently set on @self
- *
- * Returns: %TRUE if a sort function is set
- **/
-gboolean
-gtk_sort_list_model_has_sort (GtkSortListModel *self)
-{
- g_return_val_if_fail (GTK_IS_SORT_LIST_MODEL (self), FALSE);
-
- return self->sort_func != NULL;
-}
-
-/**
- * gtk_sort_list_model_resort:
- * @self: a #GtkSortListModel
- *
- * Causes @self to resort all items in the model.
- *
- * Calling this function is necessary when data used by the sort
- * function has changed.
- **/
-void
+static void
gtk_sort_list_model_resort (GtkSortListModel *self)
{
guint n_items;
@@ -556,8 +507,59 @@ gtk_sort_list_model_resort (GtkSortListModel *self)
if (n_items <= 1)
return;
- g_sequence_sort (self->sorted, self->sort_func, self->user_data);
+ g_sequence_sort (self->sorted, _sort_func, self->sorter);
g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items, n_items);
}
+/**
+ * gtk_sort_list_model_set_sorter:
+ * @self: a #GtkSortListModel
+ * @sorter: (allow-none): the #GtkSorter to sort @model with
+ *
+ * Sets a new sorter on @self.
+ */
+void
+gtk_sort_list_model_set_sorter (GtkSortListModel *self,
+ GtkSorter *sorter)
+{
+ guint n_items;
+
+ g_return_if_fail (GTK_IS_SORT_LIST_MODEL (self));
+ g_return_if_fail (sorter == NULL || GTK_IS_SORTER (sorter));
+
+ gtk_sort_list_model_clear_sorter (self);
+
+ if (sorter)
+ {
+ self->sorter = g_object_ref (sorter);
+ g_signal_connect (sorter, "changed", G_CALLBACK (gtk_sort_list_model_sorter_changed_cb), self);
+ }
+
+ g_clear_pointer (&self->unsorted, g_sequence_free);
+ g_clear_pointer (&self->sorted, g_sequence_free);
+
+ gtk_sort_list_model_create_sequences (self);
+
+ n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
+ if (n_items > 1)
+ g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items, n_items);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SORTER]);
+}
+
+/**
+ * gtk_sort_list_model_get_sorter:
+ * @self: a #GtkSortLisTModel
+ *
+ * Gets the sorter that is used to sort @self.
+ *
+ * Returns: (nullable) (transfer none): the sorter of #self
+ */
+GtkSorter *
+gtk_sort_list_model_get_sorter (GtkSortListModel *self)
+{
+ g_return_val_if_fail (GTK_IS_SORT_LIST_MODEL (self), NULL);
+
+ return self->sorter;
+}
diff --git a/gtk/gtksortlistmodel.h b/gtk/gtksortlistmodel.h
index 2fbc465dcb..3e009502e2 100644
--- a/gtk/gtksortlistmodel.h
+++ b/gtk/gtksortlistmodel.h
@@ -27,6 +27,7 @@
#include <gio/gio.h>
#include <gtk/gtkwidget.h>
+#include <gtk/gtksorter.h>
G_BEGIN_DECLS
@@ -37,29 +38,23 @@ GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkSortListModel, gtk_sort_list_model, GTK, SORT_LIST_MODEL, GObject)
GDK_AVAILABLE_IN_ALL
-GtkSortListModel * gtk_sort_list_model_new (GListModel *model,
- GCompareDataFunc sort_func,
- gpointer user_data,
- GDestroyNotify user_destroy);
+GtkSortListModel * gtk_sort_list_model_new (GListModel *model,
+ GtkSorter *sorter);
GDK_AVAILABLE_IN_ALL
-GtkSortListModel * gtk_sort_list_model_new_for_type (GType item_type);
+GtkSortListModel * gtk_sort_list_model_new_for_type (GType item_type);
GDK_AVAILABLE_IN_ALL
-void gtk_sort_list_model_set_sort_func (GtkSortListModel *self,
- GCompareDataFunc sort_func,
- gpointer user_data,
- GDestroyNotify user_destroy);
+void gtk_sort_list_model_set_sorter (GtkSortListModel *self,
+ GtkSorter *sorter);
GDK_AVAILABLE_IN_ALL
-gboolean gtk_sort_list_model_has_sort (GtkSortListModel *self);
+GtkSorter * gtk_sort_list_model_get_sorter (GtkSortListModel *self);
+
GDK_AVAILABLE_IN_ALL
void gtk_sort_list_model_set_model (GtkSortListModel *self,
GListModel *model);
GDK_AVAILABLE_IN_ALL
GListModel * gtk_sort_list_model_get_model (GtkSortListModel *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_sort_list_model_resort (GtkSortListModel *self);
-
G_END_DECLS
#endif /* __GTK_SORT_LIST_MODEL_H__ */
diff --git a/gtk/inspector/controllers.c b/gtk/inspector/controllers.c
index deea5b866f..353939100c 100644
--- a/gtk/inspector/controllers.c
+++ b/gtk/inspector/controllers.c
@@ -35,6 +35,7 @@
#include "gtkwidgetprivate.h"
#include "gtkstack.h"
#include "gtkstylecontext.h"
+#include "gtkcustomsorter.h"
enum
{
@@ -214,6 +215,7 @@ gtk_inspector_controllers_set_object (GtkInspectorControllers *sl,
GtkMapListModel *map_model;
GtkFlattenListModel *flatten_model;
GtkSortListModel *sort_model;
+ GtkSorter *sorter;
stack = gtk_widget_get_parent (GTK_WIDGET (sl));
page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (sl));
@@ -234,9 +236,9 @@ gtk_inspector_controllers_set_object (GtkInspectorControllers *sl,
flatten_model = gtk_flatten_list_model_new (GTK_TYPE_EVENT_CONTROLLER, G_LIST_MODEL (map_model));
- sort_model = gtk_sort_list_model_new (G_LIST_MODEL (flatten_model),
- compare_controllers,
- NULL, NULL);
+ sorter = gtk_custom_sorter_new (compare_controllers, NULL, NULL);
+ sort_model = gtk_sort_list_model_new (G_LIST_MODEL (flatten_model), sorter);
+ g_object_unref (sorter);
gtk_list_box_bind_model (GTK_LIST_BOX (priv->listbox),
G_LIST_MODEL (sort_model),
diff --git a/testsuite/gtk/sortlistmodel.c b/testsuite/gtk/sortlistmodel.c
index 1fb430aafb..e0ed7e37df 100644
--- a/testsuite/gtk/sortlistmodel.c
+++ b/testsuite/gtk/sortlistmodel.c
@@ -195,7 +195,13 @@ new_model (gpointer model)
g_assert (model == NULL || G_IS_LIST_MODEL (model));
if (model)
- result = gtk_sort_list_model_new (model, compare, NULL, NULL);
+ {
+ GtkSorter *sorter;
+
+ sorter = gtk_custom_sorter_new (compare, NULL, NULL);
+ result = gtk_sort_list_model_new (model, sorter);
+ g_object_unref (sorter);
+ }
else
result = gtk_sort_list_model_new_for_type (G_TYPE_OBJECT);
@@ -275,9 +281,10 @@ test_set_model (void)
}
static void
-test_set_sort_func (void)
+test_set_sorter (void)
{
GtkSortListModel *sort;
+ GtkSorter *sorter;
GListStore *store;
store = new_store ((guint[]) { 4, 8, 2, 6, 10, 0 });
@@ -285,15 +292,19 @@ test_set_sort_func (void)
assert_model (sort, "2 4 6 8 10");
assert_changes (sort, "");
- gtk_sort_list_model_set_sort_func (sort, compare_modulo, GUINT_TO_POINTER (5), NULL);
+ sorter = gtk_custom_sorter_new (compare_modulo, GUINT_TO_POINTER (5), NULL);
+ gtk_sort_list_model_set_sorter (sort, sorter);
+ g_object_unref (sorter);
assert_model (sort, "10 6 2 8 4");
assert_changes (sort, "0-5+5");
- gtk_sort_list_model_set_sort_func (sort, NULL, NULL, NULL);
+ gtk_sort_list_model_set_sorter (sort, NULL);
assert_model (sort, "4 8 2 6 10");
assert_changes (sort, "0-5+5");
- gtk_sort_list_model_set_sort_func (sort, compare, NULL, NULL);
+ sorter = gtk_custom_sorter_new (compare, NULL, NULL);
+ gtk_sort_list_model_set_sorter (sort, sorter);
+ g_object_unref (sorter);
assert_model (sort, "2 4 6 8 10");
/* Technically, this is correct, but we shortcut setting the sort func:
* assert_changes (sort, "0-4+4"); */
@@ -395,7 +406,7 @@ main (int argc, char *argv[])
g_test_add_func ("/sortlistmodel/create_empty", test_create_empty);
g_test_add_func ("/sortlistmodel/create", test_create);
g_test_add_func ("/sortlistmodel/set-model", test_set_model);
- g_test_add_func ("/sortlistmodel/set-sort-func", test_set_sort_func);
+ g_test_add_func ("/sortlistmodel/set-sorter", test_set_sorter);
#if GLIB_CHECK_VERSION (2, 58, 0) /* g_list_store_splice() is broken before 2.58 */
g_test_add_func ("/sortlistmodel/add_items", test_add_items);
g_test_add_func ("/sortlistmodel/remove_items", test_remove_items);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]