From 141aac1a60f64bf8891d5531055cc297a91e8cc0 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 11 Oct 2022 12:57:09 -0400 Subject: [PATCH 1/5] stringsorter: Add a collation property The new property lets us choose between Unicode collation, filename collation, and plain strcmp. This will be used in the filechooser. --- gtk/gtkstringsorter.c | 116 ++++++++++++++++++++++++++++++++++++------ gtk/gtkstringsorter.h | 26 ++++++++++ 2 files changed, 127 insertions(+), 15 deletions(-) diff --git a/gtk/gtkstringsorter.c b/gtk/gtkstringsorter.c index 59d2d8737e..87f65da897 100644 --- a/gtk/gtkstringsorter.c +++ b/gtk/gtkstringsorter.c @@ -42,6 +42,7 @@ struct _GtkStringSorter GtkSorter parent_instance; gboolean ignore_case; + GtkCollation collation; GtkExpression *expression; }; @@ -50,6 +51,7 @@ enum { PROP_0, PROP_EXPRESSION, PROP_IGNORE_CASE, + PROP_COLLATION, NUM_PROPERTIES }; @@ -60,10 +62,13 @@ static GParamSpec *properties[NUM_PROPERTIES] = { NULL, }; static char * gtk_string_sorter_get_key (GtkExpression *expression, gboolean ignore_case, + GtkCollation collation, gpointer item1) { GValue value = G_VALUE_INIT; + const char *string; char *s; + char *key; if (expression == NULL) return NULL; @@ -71,23 +76,35 @@ gtk_string_sorter_get_key (GtkExpression *expression, if (!gtk_expression_evaluate (expression, item1, &value)) return NULL; - /* If strings are NULL, order them before "". */ - if (ignore_case) - { - char *t; + string = g_value_get_string (&value); - t = g_utf8_casefold (g_value_get_string (&value), -1); - s = g_utf8_collate_key (t, -1); - g_free (t); - } + if (ignore_case) + s = g_utf8_casefold (string, -1); else + s = (char *) string; + + switch (collation) { - s = g_utf8_collate_key (g_value_get_string (&value), -1); + case GTK_COLLATION_NONE: + key = s; + break; + case GTK_COLLATION_UNICODE: + key = g_utf8_collate_key (s, -1); + break; + case GTK_COLLATION_FILENAME: + key = g_utf8_collate_key_for_filename (s, -1); + break; + default: + g_assert_not_reached (); + break; } + if (s != string) + g_free (s); + g_value_unset (&value); - return s; + return key; } static GtkOrdering @@ -102,8 +119,8 @@ gtk_string_sorter_compare (GtkSorter *sorter, if (self->expression == NULL) return GTK_ORDERING_EQUAL; - s1 = gtk_string_sorter_get_key (self->expression, self->ignore_case, item1); - s2 = gtk_string_sorter_get_key (self->expression, self->ignore_case, item2); + s1 = gtk_string_sorter_get_key (self->expression, self->ignore_case, self->collation, item1); + s2 = gtk_string_sorter_get_key (self->expression, self->ignore_case, self->collation, item2); result = gtk_ordering_from_cmpfunc (g_strcmp0 (s1, s2)); @@ -131,6 +148,7 @@ struct _GtkStringSortKeys GtkExpression *expression; gboolean ignore_case; + GtkCollation collation; }; static void @@ -173,7 +191,7 @@ gtk_string_sort_keys_init_key (GtkSortKeys *keys, GtkStringSortKeys *self = (GtkStringSortKeys *) keys; char **key = (char **) key_memory; - *key = gtk_string_sorter_get_key (self->expression, self->ignore_case, item); + *key = gtk_string_sorter_get_key (self->expression, self->ignore_case, self->collation, item); } static void @@ -209,6 +227,7 @@ gtk_string_sort_keys_new (GtkStringSorter *self) result->expression = gtk_expression_ref (self->expression); result->ignore_case = self->ignore_case; + result->collation = self->collation; return (GtkSortKeys *) result; } @@ -231,13 +250,17 @@ gtk_string_sorter_set_property (GObject *object, gtk_string_sorter_set_ignore_case (self, g_value_get_boolean (value)); break; + case PROP_COLLATION: + gtk_string_sorter_set_collation (self, g_value_get_enum (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } -static void +static void gtk_string_sorter_get_property (GObject *object, guint prop_id, GValue *value, @@ -255,6 +278,10 @@ gtk_string_sorter_get_property (GObject *object, g_value_set_boolean (value, self->ignore_case); break; + case PROP_COLLATION: + g_value_set_enum (value, self->collation); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -296,13 +323,26 @@ gtk_string_sorter_class_init (GtkStringSorterClass *class) /** * GtkStringSorter:ignore-case: (attributes org.gtk.Property.get=gtk_string_sorter_get_ignore_case org.gtk.Property.set=gtk_string_sorter_set_ignore_case) * - * If matching is case sensitive. + * If sorting is case sensitive. */ properties[PROP_IGNORE_CASE] = g_param_spec_boolean ("ignore-case", NULL, NULL, TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + /** + * GtkStringSorter:collation: (attributes org.gtk.Property.get=gtk_string_sorter_get_collation org.gtk.Property.set=gtk_string_sorter_set_collation) + * + * The collation method to use for sorting. + * + * Since: 4.10 + */ + properties[PROP_COLLATION] = + g_param_spec_enum ("collationmode", NULL, NULL, + GTK_TYPE_COLLATION, + GTK_COLLATION_UNICODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + g_object_class_install_properties (object_class, NUM_PROPERTIES, properties); } @@ -311,6 +351,7 @@ static void gtk_string_sorter_init (GtkStringSorter *self) { self->ignore_case = TRUE; + self->collation = GTK_COLLATION_UNICODE; gtk_sorter_changed_with_keys (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT, @@ -429,3 +470,48 @@ gtk_string_sorter_set_ignore_case (GtkStringSorter *self, g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_IGNORE_CASE]); } + +/** + * gtk_string_sorter_get_collation: (attributes org.gtk.Method.get_property=collation) + * @self: a `GtkStringSorter` + * + * Gets which collation method the sorter uses. + * + * Returns: The collation method + * + * Since: 4.10 + */ +GtkCollation +gtk_string_sorter_get_collation (GtkStringSorter *self) +{ + g_return_val_if_fail (GTK_IS_STRING_SORTER (self), GTK_COLLATION_UNICODE); + + return self->collation; +} + +/** + * gtk_string_sorter_set_collation: (attributes org.gtk.Method.set_property=collation) + * @self: a `GtkStringSorter` + * @collation: the collation method + * + * Sets the collation method to use for sorting. + * + * Since: 4.10 + */ +void +gtk_string_sorter_set_collation (GtkStringSorter *self, + GtkCollation collation) +{ + g_return_if_fail (GTK_IS_STRING_SORTER (self)); + + if (self->collation == collation) + return; + + self->collation = collation; + + gtk_sorter_changed_with_keys (GTK_SORTER (self), + GTK_SORTER_CHANGE_DIFFERENT, + gtk_string_sort_keys_new (self)); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COLLATION]); +} diff --git a/gtk/gtkstringsorter.h b/gtk/gtkstringsorter.h index c340c6fa8d..ea61a47061 100644 --- a/gtk/gtkstringsorter.h +++ b/gtk/gtkstringsorter.h @@ -47,6 +47,32 @@ GDK_AVAILABLE_IN_ALL void gtk_string_sorter_set_ignore_case (GtkStringSorter *self, gboolean ignore_case); +/** + * GtkCollation: + * @GTK_COLLATION_NONE: Don't do any collation + * @GTK_COLLATION_UNICODE: Use [func@GLib.g_utf8_collate_key] + * @GTK_COLLATION_FILENAME: Use [func@GLib.g_utf8_collate_key_for_filename] + * + * Describes how a [class@Gtk.StringSorter] turns strings into sort keys to + * compare them. + * + * Note that the result of sorting will in general depend on the current locale + * unless the mode is @GTK_COLLATION_NONE. + */ +typedef enum +{ + GTK_COLLATION_NONE, + GTK_COLLATION_UNICODE, + GTK_COLLATION_FILENAME +} GtkCollation; + +GDK_AVAILABLE_IN_4_10 +void gtk_string_sorter_set_collation (GtkStringSorter *self, + GtkCollation collation); + +GDK_AVAILABLE_IN_4_10 +GtkCollation gtk_string_sorter_get_collation (GtkStringSorter *self); + G_END_DECLS #endif /* __GTK_STRING_SORTER_H__ */ From a06a4ad59ab76e338faea72fbdda22866c7697da Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 11 Oct 2022 13:43:36 -0400 Subject: [PATCH 2/5] ci: Allow macos builds to fail The runner seems busted, so allow builds to fail for now. --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8829a100c0..a1382ce2a3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -192,6 +192,7 @@ macos: only: - branches@GNOME/gtk stage: build + allow_failure: true tags: - macos needs: [] From 2520148ebb174c6c938282a4916efc5597ca9afe Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 11 Oct 2022 17:53:26 +0000 Subject: [PATCH 3/5] Apply 2 suggestion(s) to 2 file(s) --- gtk/gtkstringsorter.c | 2 +- gtk/gtkstringsorter.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gtk/gtkstringsorter.c b/gtk/gtkstringsorter.c index 87f65da897..266fc81e55 100644 --- a/gtk/gtkstringsorter.c +++ b/gtk/gtkstringsorter.c @@ -338,7 +338,7 @@ gtk_string_sorter_class_init (GtkStringSorterClass *class) * Since: 4.10 */ properties[PROP_COLLATION] = - g_param_spec_enum ("collationmode", NULL, NULL, + g_param_spec_enum ("collation", NULL, NULL, GTK_TYPE_COLLATION, GTK_COLLATION_UNICODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); diff --git a/gtk/gtkstringsorter.h b/gtk/gtkstringsorter.h index ea61a47061..7e687e51d1 100644 --- a/gtk/gtkstringsorter.h +++ b/gtk/gtkstringsorter.h @@ -58,6 +58,8 @@ void gtk_string_sorter_set_ignore_case (GtkStringSorter * * Note that the result of sorting will in general depend on the current locale * unless the mode is @GTK_COLLATION_NONE. + * + * Since: 4.10 */ typedef enum { From 05323869d72e466faa286881c959c1de58cfe22b Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 11 Oct 2022 14:03:57 -0400 Subject: [PATCH 4/5] stringsorter: Add more detail to the docs Mention when a collation value of NONE might be useful. --- gtk/gtkstringsorter.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gtk/gtkstringsorter.c b/gtk/gtkstringsorter.c index 266fc81e55..507adca17c 100644 --- a/gtk/gtkstringsorter.c +++ b/gtk/gtkstringsorter.c @@ -335,6 +335,12 @@ gtk_string_sorter_class_init (GtkStringSorterClass *class) * * The collation method to use for sorting. * + * The `GTK_COLLATION_NONE` value is useful when the expression already + * returns collation keys, or strings that need to be compared byte-by-byte. + * + * The default value, `GTK_COLLATION_UNICODE`, compares strings according + * to the [Unicode collation algorithm](https://www.unicode.org/reports/tr10/). + * * Since: 4.10 */ properties[PROP_COLLATION] = From c419b57754994b0e972a87b7b6549f1770171a8a Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 11 Oct 2022 15:32:05 -0400 Subject: [PATCH 5/5] stringsorter: Fix up a doc typo gi-docgen links can be tricky to get right. --- gtk/gtkstringsorter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gtk/gtkstringsorter.h b/gtk/gtkstringsorter.h index 7e687e51d1..2d0924fd2a 100644 --- a/gtk/gtkstringsorter.h +++ b/gtk/gtkstringsorter.h @@ -50,8 +50,8 @@ void gtk_string_sorter_set_ignore_case (GtkStringSorter /** * GtkCollation: * @GTK_COLLATION_NONE: Don't do any collation - * @GTK_COLLATION_UNICODE: Use [func@GLib.g_utf8_collate_key] - * @GTK_COLLATION_FILENAME: Use [func@GLib.g_utf8_collate_key_for_filename] + * @GTK_COLLATION_UNICODE: Use [func@GLib.utf8_collate_key] + * @GTK_COLLATION_FILENAME: Use [func@GLib.utf8_collate_key_for_filename] * * Describes how a [class@Gtk.StringSorter] turns strings into sort keys to * compare them.