From 41965b149d5e0ed4689eeb78aa9afdf91273a008 Mon Sep 17 00:00:00 2001 From: Nicolas Schneider Date: Mon, 2 Mar 2026 16:13:11 +0100 Subject: [PATCH] file selection: match anywhere in the filename, not just at the start Previously, only the start of the filename was matched. Now, the entire file name is searched (case insensitive), e.g. if you have 3 files named "foobar", "foobaz", "foolol", you can simply start typing "lol" and the last file will be selected automatically. This applies to both, list view and icon view. Closes #2660. --- libnemo-private/nemo-icon-container.c | 3 +- src/nemo-list-view.c | 51 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/libnemo-private/nemo-icon-container.c b/libnemo-private/nemo-icon-container.c index 8652643f2..33389cd6b 100644 --- a/libnemo-private/nemo-icon-container.c +++ b/libnemo-private/nemo-icon-container.c @@ -3853,8 +3853,7 @@ nemo_icon_container_search_iter (NemoIconContainer *container, continue; } - if (strncmp (case_normalized_key, case_normalized_name, - strlen (case_normalized_key)) == 0) { + if (strstr (case_normalized_name, case_normalized_key) != NULL) { count++; } diff --git a/src/nemo-list-view.c b/src/nemo-list-view.c index f89244bfd..233243b0b 100644 --- a/src/nemo-list-view.c +++ b/src/nemo-list-view.c @@ -191,6 +191,53 @@ G_DEFINE_TYPE (NemoListView, nemo_list_view, NEMO_TYPE_VIEW); static gint click_policy = NEMO_CLICK_POLICY_SINGLE; +static gboolean +list_view_search_equal_func (GtkTreeModel *model, + gint search_column, + const gchar *key, + GtkTreeIter *iter, + gpointer user_data) +{ + gchar *name = NULL; + gchar *normalized_key = NULL; + gchar *case_normalized_key = NULL; + gchar *normalized_name = NULL; + gchar *case_normalized_name = NULL; + gboolean is_match = FALSE; + + (void) user_data; + + if (key == NULL || key[0] == '\0') { + return TRUE; + } + + gtk_tree_model_get (model, iter, search_column, &name, -1); + if (name == NULL) { + return TRUE; + } + + normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL); + normalized_name = g_utf8_normalize (name, -1, G_NORMALIZE_ALL); + + if (normalized_key != NULL && normalized_name != NULL) { + case_normalized_key = g_utf8_casefold (normalized_key, -1); + case_normalized_name = g_utf8_casefold (normalized_name, -1); + + if (case_normalized_key != NULL && case_normalized_name != NULL) { + is_match = strstr (case_normalized_name, case_normalized_key) != NULL; + } + } + + g_free (case_normalized_name); + g_free (normalized_name); + g_free (case_normalized_key); + g_free (normalized_key); + g_free (name); + + /* GtkTreeView expects FALSE for a row that matches. */ + return !is_match; +} + static const char * default_trash_visible_columns[] = { "name", "size", "type", "trashed_on", "trash_orig_path", NULL }; @@ -2538,6 +2585,10 @@ create_and_set_up_tree_view (NemoListView *view) NULL); gtk_tree_view_set_enable_search (view->details->tree_view, TRUE); + gtk_tree_view_set_search_equal_func (view->details->tree_view, + list_view_search_equal_func, + view, + NULL); /* Don't handle backspace key. It's used to open the parent folder. */ binding_set = gtk_binding_set_by_class (GTK_WIDGET_GET_CLASS (view->details->tree_view));