[gtk/ci-file-filters: 5477/5477] GtkFileFilter: Allow case-insensitive patterns
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/ci-file-filters: 5477/5477] GtkFileFilter: Allow case-insensitive patterns
- Date: Fri, 4 Jun 2021 04:04:03 +0000 (UTC)
commit d13d308959f516a715d9e4e2471aacec03c58c04
Author: Matthias Clasen <mclasen redhat com>
Date: Thu Jun 3 23:55:48 2021 -0400
GtkFileFilter: Allow case-insensitive patterns
In the past, we've hardcoded case-insensitive matching
on Windows, and case-sensitive matching everywhere else.
With this change, we now have a way to explicitly add
case-insensitive patterns to a filter. We still interpret
all patterns case-insensitively on Windows.
demos/gtk-demo/video_player.c | 2 +-
gtk/gtkfilechooserentry.c | 2 +-
gtk/gtkfilefilter.c | 79 +++++++++++++++++++++++++++++++++++++------
gtk/gtkfilefilter.h | 8 ++++-
tests/testfilechooser.c | 4 +--
tests/testgtk.c | 8 ++---
6 files changed, 83 insertions(+), 20 deletions(-)
---
diff --git a/demos/gtk-demo/video_player.c b/demos/gtk-demo/video_player.c
index 8b467a25d9..ffd5eaba73 100644
--- a/demos/gtk-demo/video_player.c
+++ b/demos/gtk-demo/video_player.c
@@ -42,7 +42,7 @@ open_clicked_cb (GtkWidget *button,
"_Cancel");
filter = gtk_file_filter_new ();
- gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_filter_add_pattern_full (filter, "*", FALSE);
gtk_file_filter_set_name (filter, "All Files");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
g_object_unref (filter);
diff --git a/gtk/gtkfilechooserentry.c b/gtk/gtkfilechooserentry.c
index 2bf47a067e..f3a77da9b7 100644
--- a/gtk/gtkfilechooserentry.c
+++ b/gtk/gtkfilechooserentry.c
@@ -716,7 +716,7 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry)
filter = gtk_file_filter_new ();
pattern = g_strconcat (chooser_entry->file_part, "*", NULL);
- gtk_file_filter_add_pattern (filter, pattern);
+ gtk_file_filter_add_pattern_full (filter, pattern, FALSE);
_gtk_file_system_model_set_filter (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
filter);
diff --git a/gtk/gtkfilefilter.c b/gtk/gtkfilefilter.c
index 99a82d6845..ee0dec6b1e 100644
--- a/gtk/gtkfilefilter.c
+++ b/gtk/gtkfilefilter.c
@@ -23,7 +23,7 @@
*
* `GtkFileFilter` can be used to restrict the files being shown in a
* `GtkFileChooser`. Files can be filtered based on their name (with
- * [method@Gtk.FileFilter.add_pattern]) or on their mime type (with
+ * [method@Gtk.FileFilter.add_pattern_full]) or on their mime type (with
* [method@Gtk.FileFilter.add_mime_type]).
*
* Filtering by mime types handles aliasing and subclassing of mime
@@ -44,7 +44,7 @@
* elements and listing the rules within. Specifying a <mime-type>
* or <pattern> has the same effect as as calling
* [method@Gtk.FileFilter.add_mime_type] or
- * [method@Gtk.FileFilter.add_pattern].
+ * [method@Gtk.FileFilter.add_pattern_full].
*
* An example of a UI definition fragment specifying `GtkFileFilter`
* rules:
@@ -84,6 +84,7 @@ typedef struct _FilterRule FilterRule;
typedef enum {
FILTER_RULE_PATTERN,
+ FILTER_RULE_PATTERN_CI,
FILTER_RULE_MIME_TYPE,
FILTER_RULE_PIXBUF_FORMATS
} FilterRuleType;
@@ -182,6 +183,7 @@ filter_rule_free (FilterRule *rule)
switch (rule->type)
{
case FILTER_RULE_PATTERN:
+ case FILTER_RULE_PATTERN_CI:
g_free (rule->u.pattern);
break;
case FILTER_RULE_MIME_TYPE:
@@ -255,6 +257,7 @@ typedef struct
ParserType type;
GString *string;
gboolean parsing;
+ gboolean ignore_case;
} SubParserData;
static void
@@ -267,9 +270,23 @@ parser_start_element (GtkBuildableParseContext *context,
{
SubParserData *data = (SubParserData*)user_data;
- if (!g_markup_collect_attributes (element_name, names, values, error,
- G_MARKUP_COLLECT_INVALID, NULL, NULL,
- G_MARKUP_COLLECT_INVALID))
+ if (strcmp (element_name, "patterns") == 0)
+ {
+ gboolean ignore_case = FALSE;
+
+ if (!g_markup_collect_attributes (element_name, names, values, error,
+ G_MARKUP_COLLECT_BOOLEAN|G_MARKUP_COLLECT_OPTIONAL, "ignore-case",
&ignore_case,
+ G_MARKUP_COLLECT_INVALID))
+ {
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+
+ data->ignore_case = ignore_case;
+ }
+ else if (!g_markup_collect_attributes (element_name, names, values, error,
+ G_MARKUP_COLLECT_INVALID, NULL, NULL,
+ G_MARKUP_COLLECT_INVALID))
{
_gtk_builder_prefix_error (data->builder, context, error);
return;
@@ -332,7 +349,7 @@ parser_end_element (GtkBuildableParseContext *context,
gtk_file_filter_add_mime_type (data->filter, data->string->str);
break;
case PARSE_PATTERNS:
- gtk_file_filter_add_pattern (data->filter, data->string->str);
+ gtk_file_filter_add_pattern_full (data->filter, data->string->str, data->ignore_case);
break;
default:
break;
@@ -422,13 +439,13 @@ gtk_file_filter_buildable_init (GtkBuildableIface *iface)
* Such a filter doesn’t accept any files, so is not
* particularly useful until you add rules with
* [method@Gtk.FileFilter.add_mime_type],
- * [method@Gtk.FileFilter.add_pattern], or
+ * [method@Gtk.FileFilter.add_pattern_full], or
* [method@Gtk.FileFilter.add_pixbuf_formats].
*
* To create a filter that accepts any file, use:
* ```c
* GtkFileFilter *filter = gtk_file_filter_new ();
- * gtk_file_filter_add_pattern (filter, "*");
+ * gtk_file_filter_add_pattern_full (filter, "*", FALSE);
* ```
*
* Returns: a new `GtkFileFilter`
@@ -543,10 +560,30 @@ gtk_file_filter_add_mime_type (GtkFileFilter *filter,
* @pattern: a shell style glob
*
* Adds a rule allowing a shell style glob to a filter.
+ *
+ * Deprecated: 4.4: Use gtk_file_filter_add_pattern_full()
*/
void
gtk_file_filter_add_pattern (GtkFileFilter *filter,
const char *pattern)
+{
+ gtk_file_filter_add_pattern_full (filter, pattern, FALSE);
+}
+
+/**
+ * gtk_file_filter_add_pattern_full:
+ * @filter: a `GtkFileFilter`
+ * @pattern: a shell style glob
+ * @ignore_case: whether to ignore case differences
+ *
+ * Adds a rule allowing a shell style glob to a filter.
+ *
+ * Since: 4.4
+ */
+void
+gtk_file_filter_add_pattern_full (GtkFileFilter *filter,
+ const char *pattern,
+ gboolean ignore_case)
{
FilterRule *rule;
@@ -554,7 +591,7 @@ gtk_file_filter_add_pattern (GtkFileFilter *filter,
g_return_if_fail (pattern != NULL);
rule = g_slice_new (FilterRule);
- rule->type = FILTER_RULE_PATTERN;
+ rule->type = ignore_case ? FILTER_RULE_PATTERN_CI : FILTER_RULE_PATTERN;
rule->u.pattern = g_strdup (pattern);
file_filter_add_attribute (filter, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
@@ -657,6 +694,7 @@ NSArray * _gtk_file_filter_get_as_pattern_nsstrings (GtkFileFilter *filter)
break;
case FILTER_RULE_PATTERN:
+ case FILTER_RULE_PATTERN_CI:
{
// patterns will need to be stripped of their leading *.
GString *pattern = g_string_new (rule->u.pattern);
@@ -725,6 +763,7 @@ _gtk_file_filter_get_as_patterns (GtkFileFilter *filter)
break;
case FILTER_RULE_PATTERN:
+ case FILTER_RULE_PATTERN_CI:
g_ptr_array_add (array, g_strdup (rule->u.pattern));
break;
@@ -794,9 +833,13 @@ gtk_file_filter_match (GtkFilter *filter,
for (tmp_list = file_filter->rules; tmp_list; tmp_list = tmp_list->next)
{
FilterRule *rule = tmp_list->data;
+ gboolean casefold = FALSE;
switch (rule->type)
{
+ case FILTER_RULE_PATTERN_CI:
+ casefold = TRUE;
+ G_GNUC_FALLTHROUGH;
case FILTER_RULE_PATTERN:
{
const char *display_name;
@@ -804,7 +847,7 @@ gtk_file_filter_match (GtkFilter *filter,
display_name = g_file_info_get_display_name (info);
if (display_name)
{
- if (_gtk_fnmatch (rule->u.pattern, display_name, FALSE, FALSE))
+ if (_gtk_fnmatch (rule->u.pattern, display_name, FALSE, casefold))
return TRUE;
}
}
@@ -863,6 +906,17 @@ gtk_file_filter_to_gvariant (GtkFileFilter *filter)
g_variant_builder_add (&builder, "(us)", 0, rule->u.pattern);
break;
+ case FILTER_RULE_PATTERN_CI:
+ {
+ /* Tweak the glob, since the filechooser portal has no api
+ * for case-insensitive globs
+ */
+ char *pattern = _gtk_make_ci_glob_pattern (rule->u.pattern);
+ g_variant_builder_add (&builder, "(us)", 0, pattern);
+ g_free (pattern);
+ }
+ break;
+
case FILTER_RULE_MIME_TYPE:
case FILTER_RULE_PIXBUF_FORMATS:
for (i = 0; rule->u.content_types[i]; i++)
@@ -908,7 +962,10 @@ gtk_file_filter_new_from_gvariant (GVariant *variant)
switch (type)
{
case 0:
- gtk_file_filter_add_pattern (filter, tmp);
+ gtk_file_filter_add_pattern_full (filter, tmp, FALSE);
+ break;
+ case 2:
+ gtk_file_filter_add_pattern_full (filter, tmp, TRUE);
break;
case 1:
gtk_file_filter_add_mime_type (filter, tmp);
diff --git a/gtk/gtkfilefilter.h b/gtk/gtkfilefilter.h
index 5232dfb0ae..485c725833 100644
--- a/gtk/gtkfilefilter.h
+++ b/gtk/gtkfilefilter.h
@@ -48,9 +48,15 @@ const char * gtk_file_filter_get_name (GtkFileFilter *filter);
GDK_AVAILABLE_IN_ALL
void gtk_file_filter_add_mime_type (GtkFileFilter *filter,
const char *mime_type);
-GDK_AVAILABLE_IN_ALL
+
+GDK_DEPRECATED_IN_4_4_FOR(gtk_file_filter_add_pattern_full)
void gtk_file_filter_add_pattern (GtkFileFilter *filter,
const char *pattern);
+
+GDK_AVAILABLE_IN_4_4
+void gtk_file_filter_add_pattern_full (GtkFileFilter *filter,
+ const char *pattern,
+ gboolean ignore_case);
GDK_AVAILABLE_IN_ALL
void gtk_file_filter_add_pixbuf_formats (GtkFileFilter *filter);
diff --git a/tests/testfilechooser.c b/tests/testfilechooser.c
index c06f636884..ac118b7550 100644
--- a/tests/testfilechooser.c
+++ b/tests/testfilechooser.c
@@ -310,7 +310,7 @@ main (int argc, char **argv)
/* Filters */
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, "All Files");
- gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_filter_add_pattern_full (filter, "*", FALSE);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
/* Make this filter the default */
@@ -319,7 +319,7 @@ main (int argc, char **argv)
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, "Starts with D");
- gtk_file_filter_add_pattern (filter, "D*");
+ gtk_file_filter_add_pattern_full (filter, "D*", FALSE);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
g_object_unref (filter);
diff --git a/tests/testgtk.c b/tests/testgtk.c
index 077d16136b..8e325d911a 100644
--- a/tests/testgtk.c
+++ b/tests/testgtk.c
@@ -5576,8 +5576,8 @@ native_filter_changed (GtkWidget *combo,
case 1: /* pattern */
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, "Text");
- gtk_file_filter_add_pattern (filter, "*.doc");
- gtk_file_filter_add_pattern (filter, "*.txt");
+ gtk_file_filter_add_pattern_full (filter, "*.doc", FALSE);
+ gtk_file_filter_add_pattern_full (filter, "*.txt", FALSE);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (native), filter);
g_object_unref (filter);
@@ -5590,7 +5590,7 @@ native_filter_changed (GtkWidget *combo,
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, "All");
- gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_filter_add_pattern_full (filter, "*", FALSE);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (native), filter);
g_object_unref (filter);
break;
@@ -5604,7 +5604,7 @@ native_filter_changed (GtkWidget *combo,
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, "All");
- gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_filter_add_pattern_full (filter, "*", FALSE);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (native), filter);
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (native), filter);
g_object_unref (filter);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]