nautilus-typeahead 44.1-1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/data/org.gnome.nautilus.gschema.xml b/data/org.gnome.nautilus.gschema.xml | |
index 253bc67a1..1d216539b 100644 | |
--- a/data/org.gnome.nautilus.gschema.xml | |
+++ b/data/org.gnome.nautilus.gschema.xml | |
@@ -77,6 +77,11 @@ | |
<summary>Always use the location entry, instead of the pathbar</summary> | |
<description>If set to true, then Nautilus browser windows will always use a textual input entry for the location toolbar, instead of the pathbar.</description> | |
</key> | |
+ <key type="b" name="type-ahead-search"> | |
+ <default>false</default> | |
+ <summary>Start searching on type ahead</summary> | |
+ <description>If set to true, typing on the files viewer will start searching. Otherwise it select first matching file.</description> | |
+ </key> | |
<key name="recursive-search" enum="org.gnome.nautilus.SpeedTradeoff"> | |
<default>'local-only'</default> | |
<summary>Where to perform recursive search</summary> | |
diff --git a/src/nautilus-global-preferences.h b/src/nautilus-global-preferences.h | |
index 5a73717b3..31e22aa7b 100644 | |
--- a/src/nautilus-global-preferences.h | |
+++ b/src/nautilus-global-preferences.h | |
@@ -119,6 +119,7 @@ typedef enum | |
/* Search behaviour */ | |
#define NAUTILUS_PREFERENCES_RECURSIVE_SEARCH "recursive-search" | |
+#define NAUTILUS_PREFERENCES_TYPE_AHEAD_SEARCH "type-ahead-search" | |
/* Context menu options */ | |
#define NAUTILUS_PREFERENCES_SHOW_DELETE_PERMANENTLY "show-delete-permanently" | |
diff --git a/src/nautilus-preferences-window.c b/src/nautilus-preferences-window.c | |
index 4a6477d29..6f1542cdf 100644 | |
--- a/src/nautilus-preferences-window.c | |
+++ b/src/nautilus-preferences-window.c | |
@@ -45,6 +45,8 @@ | |
"show_create_link_switch" | |
#define NAUTILUS_PREFERENCES_DIALOG_LIST_VIEW_USE_TREE_WIDGET \ | |
"use_tree_view_switch" | |
+#define NAUTILUS_PREFERENCES_DIALOG_TYPE_AHEAD_WIDGET \ | |
+ "type_ahead_search" | |
/* combo preferences */ | |
#define NAUTILUS_PREFERENCES_DIALOG_OPEN_ACTION_COMBO \ | |
@@ -352,6 +354,9 @@ static void nautilus_preferences_window_setup(GtkBuilder *builder, | |
bind_builder_bool (builder, nautilus_preferences, | |
NAUTILUS_PREFERENCES_DIALOG_DELETE_PERMANENTLY_WIDGET, | |
NAUTILUS_PREFERENCES_SHOW_DELETE_PERMANENTLY); | |
+ bind_builder_bool (builder, nautilus_preferences, | |
+ NAUTILUS_PREFERENCES_DIALOG_TYPE_AHEAD_WIDGET, | |
+ NAUTILUS_PREFERENCES_TYPE_AHEAD_SEARCH); | |
bind_builder_combo_row (builder, nautilus_preferences, | |
NAUTILUS_PREFERENCES_DIALOG_OPEN_ACTION_COMBO, | |
diff --git a/src/nautilus-query-editor.c b/src/nautilus-query-editor.c | |
index 7de9dddd6..dee287660 100644 | |
--- a/src/nautilus-query-editor.c | |
+++ b/src/nautilus-query-editor.c | |
@@ -52,6 +52,9 @@ struct _NautilusQueryEditor | |
guint search_changed_timeout_id; | |
gboolean change_frozen; | |
+ guint clear_type_ahead_timeout_id; | |
+ gboolean searching; | |
+ | |
GFile *location; | |
NautilusQuery *query; | |
@@ -86,6 +89,9 @@ G_DEFINE_TYPE (NautilusQueryEditor, nautilus_query_editor, GTK_TYPE_WIDGET); | |
* so wait 400ms after typing, to improve performance by not spamming search engines: */ | |
#define SEARCH_CHANGED_TIMEOUT 400 | |
+/* In type ahead mode, clear entry if it did not change for a while */ | |
+#define CLEAR_TYPE_AHEAD_TIMEOUT 1000 | |
+ | |
static void | |
update_fts_sensitivity (NautilusQueryEditor *editor) | |
{ | |
@@ -139,6 +145,7 @@ nautilus_query_editor_dispose (GObject *object) | |
editor = NAUTILUS_QUERY_EDITOR (object); | |
g_clear_handle_id (&editor->search_changed_timeout_id, g_source_remove); | |
+ g_clear_handle_id (&editor->clear_type_ahead_timeout_id, g_source_remove); | |
gtk_widget_unparent (gtk_widget_get_first_child (GTK_WIDGET (editor))); | |
g_clear_pointer (&editor->tags_box, gtk_widget_unparent); | |
@@ -403,6 +410,25 @@ entry_changed_internal (NautilusQueryEditor *editor) | |
return G_SOURCE_REMOVE; | |
} | |
+static void | |
+clear_type_ahead (NautilusQueryEditor *editor) | |
+{ | |
+ editor->change_frozen = TRUE; | |
+ gtk_editable_set_text (GTK_EDITABLE (editor->text), ""); | |
+ editor->change_frozen = FALSE; | |
+} | |
+ | |
+static gboolean | |
+clear_type_ahead_timeout_callback (NautilusQueryEditor *editor) | |
+{ | |
+ if (!editor->searching) | |
+ { | |
+ clear_type_ahead (editor); | |
+ } | |
+ editor->clear_type_ahead_timeout_id = 0; | |
+ return G_SOURCE_REMOVE; | |
+} | |
+ | |
static void | |
entry_changed_cb (GtkWidget *entry, | |
NautilusQueryEditor *editor) | |
@@ -412,10 +438,24 @@ entry_changed_cb (GtkWidget *entry, | |
return; | |
} | |
+ g_clear_handle_id (&editor->clear_type_ahead_timeout_id, g_source_remove); | |
g_clear_handle_id (&editor->search_changed_timeout_id, g_source_remove); | |
- editor->search_changed_timeout_id = g_timeout_add (SEARCH_CHANGED_TIMEOUT, | |
- G_SOURCE_FUNC (entry_changed_internal), | |
- editor); | |
+ | |
+ /* In type ahead mode notify immediately that the entry changed, otherwise | |
+ * wait a few ms to not spam search engines. */ | |
+ if (editor->searching) | |
+ { | |
+ editor->search_changed_timeout_id = g_timeout_add (SEARCH_CHANGED_TIMEOUT, | |
+ G_SOURCE_FUNC (entry_changed_internal), | |
+ editor); | |
+ } | |
+ else | |
+ { | |
+ entry_changed_internal (editor); | |
+ editor->clear_type_ahead_timeout_id = g_timeout_add (CLEAR_TYPE_AHEAD_TIMEOUT, | |
+ G_SOURCE_FUNC (clear_type_ahead_timeout_callback), | |
+ editor); | |
+ } | |
} | |
static GtkWidget * | |
@@ -673,6 +713,8 @@ nautilus_query_editor_init (NautilusQueryEditor *editor) | |
G_CALLBACK (search_popover_time_type_changed_cb), editor); | |
g_signal_connect (editor->popover, "notify::fts-enabled", | |
G_CALLBACK (search_popover_fts_changed_cb), editor); | |
+ | |
+ editor->searching = FALSE; | |
} | |
static void | |
@@ -828,3 +870,15 @@ nautilus_query_editor_handle_event (NautilusQueryEditor *self, | |
return gtk_event_controller_key_forward (controller, self->text); | |
} | |
+ | |
+void | |
+nautilus_query_editor_set_searching (NautilusQueryEditor *editor, | |
+ gboolean searching) | |
+{ | |
+ g_return_if_fail (NAUTILUS_IS_QUERY_EDITOR (editor)); | |
+ editor->searching = searching; | |
+ if (!editor->searching) | |
+ { | |
+ clear_type_ahead (editor); | |
+ } | |
+} | |
diff --git a/src/nautilus-query-editor.h b/src/nautilus-query-editor.h | |
index 39b1f5e62..18eb4c9df 100644 | |
--- a/src/nautilus-query-editor.h | |
+++ b/src/nautilus-query-editor.h | |
@@ -69,3 +69,6 @@ nautilus_query_editor_handle_event (NautilusQueryEditor *self, | |
GtkEventControllerKey *controller, | |
guint keyval, | |
GdkModifierType state); | |
+ | |
+void nautilus_query_editor_set_searching (NautilusQueryEditor *editor, | |
+ gboolean searching); | |
diff --git a/src/nautilus-window-slot.c b/src/nautilus-window-slot.c | |
index 785386ea1..d8ffb09cc 100644 | |
--- a/src/nautilus-window-slot.c | |
+++ b/src/nautilus-window-slot.c | |
@@ -105,10 +105,6 @@ struct _NautilusWindowSlot | |
/* Query editor */ | |
NautilusQueryEditor *query_editor; | |
NautilusQuery *pending_search_query; | |
- gulong qe_changed_id; | |
- gulong qe_cancel_id; | |
- gulong qe_activated_id; | |
- gulong qe_focus_view_id; | |
GtkLabel *search_info_label; | |
GtkRevealer *search_info_label_revealer; | |
@@ -179,6 +175,7 @@ static void real_set_templates_menu (NautilusWindowSlot *self, | |
GMenuModel *menu); | |
static GMenuModel *real_get_templates_menu (NautilusWindowSlot *self); | |
static void nautilus_window_slot_setup_extra_location_widgets (NautilusWindowSlot *self); | |
+static GFile *nautilus_window_slot_get_current_location (NautilusWindowSlot *self); | |
void | |
free_navigation_state (gpointer data) | |
@@ -447,6 +444,12 @@ query_editor_focus_view_callback (NautilusQueryEditor *editor, | |
} | |
} | |
+static gboolean | |
+type_ahead_search (void) | |
+{ | |
+ return g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_TYPE_AHEAD_SEARCH); | |
+} | |
+ | |
static void | |
query_editor_changed_callback (NautilusQueryEditor *editor, | |
NautilusQuery *query, | |
@@ -457,8 +460,47 @@ query_editor_changed_callback (NautilusQueryEditor *editor, | |
view = nautilus_window_slot_get_current_view (self); | |
- nautilus_view_set_search_query (view, query); | |
- nautilus_window_slot_open_location_full (self, nautilus_view_get_location (view), 0, NULL); | |
+ if (type_ahead_search () || nautilus_window_slot_get_searching (self)) | |
+ { | |
+ nautilus_view_set_search_query (view, query); | |
+ nautilus_window_slot_open_location_full (self, nautilus_view_get_location (view), 0, NULL); | |
+ } | |
+ else | |
+ { | |
+ /* Find all files with a display name that starts with the query, case insensitive. */ | |
+ GFile *location = nautilus_window_slot_get_current_location (self); | |
+ g_autoptr (NautilusDirectory) directory = nautilus_directory_get (location); | |
+ const gchar *text = nautilus_query_get_text (query); | |
+ g_autofree gchar *text_casefold = g_utf8_casefold (text, -1); | |
+ g_autofree gchar *text_collate = g_utf8_collate_key_for_filename (text_casefold, -1); | |
+ gsize text_len = strlen (text); | |
+ GList *files, *l; | |
+ GList *matches = NULL; | |
+ | |
+ files = nautilus_directory_get_file_list (directory); | |
+ for (l = files; l; l = l->next) | |
+ { | |
+ NautilusFile *file = NAUTILUS_FILE (l->data); | |
+ g_autofree const gchar *name = nautilus_file_get_display_name (file); | |
+ g_autofree const gchar *name_casefold = g_utf8_casefold (name, text_len); | |
+ g_autofree const gchar *name_collate = g_utf8_collate_key_for_filename (name_casefold, -1); | |
+ | |
+ if (g_str_equal (name_collate, text_collate)) | |
+ { | |
+ matches = g_list_prepend (matches, nautilus_file_ref (file)); | |
+ } | |
+ } | |
+ | |
+ /* Select the first match */ | |
+ matches = nautilus_file_list_sort_by_display_name (matches); | |
+ l = matches; | |
+ matches = g_list_remove_link (matches, l); | |
+ nautilus_view_set_selection (self->content_view, l); | |
+ | |
+ nautilus_file_list_free (files); | |
+ nautilus_file_list_free (matches); | |
+ nautilus_file_list_free (l); | |
+ } | |
} | |
static void | |
@@ -468,11 +510,6 @@ hide_query_editor (NautilusWindowSlot *self) | |
view = nautilus_window_slot_get_current_view (self); | |
- g_clear_signal_handler (&self->qe_changed_id, self->query_editor); | |
- g_clear_signal_handler (&self->qe_cancel_id, self->query_editor); | |
- g_clear_signal_handler (&self->qe_activated_id, self->query_editor); | |
- g_clear_signal_handler (&self->qe_focus_view_id, self->query_editor); | |
- | |
nautilus_query_editor_set_query (self->query_editor, NULL); | |
if (nautilus_view_is_searching (view)) | |
@@ -534,31 +571,6 @@ show_query_editor (NautilusWindowSlot *self) | |
} | |
gtk_widget_grab_focus (GTK_WIDGET (self->query_editor)); | |
- | |
- if (self->qe_changed_id == 0) | |
- { | |
- self->qe_changed_id = | |
- g_signal_connect (self->query_editor, "changed", | |
- G_CALLBACK (query_editor_changed_callback), self); | |
- } | |
- if (self->qe_cancel_id == 0) | |
- { | |
- self->qe_cancel_id = | |
- g_signal_connect (self->query_editor, "cancel", | |
- G_CALLBACK (query_editor_cancel_callback), self); | |
- } | |
- if (self->qe_activated_id == 0) | |
- { | |
- self->qe_activated_id = | |
- g_signal_connect (self->query_editor, "activated", | |
- G_CALLBACK (query_editor_activated_callback), self); | |
- } | |
- if (self->qe_focus_view_id == 0) | |
- { | |
- self->qe_focus_view_id = | |
- g_signal_connect (self->query_editor, "focus-view", | |
- G_CALLBACK (query_editor_focus_view_callback), self); | |
- } | |
} | |
static void | |
@@ -653,7 +665,7 @@ nautilus_window_slot_handle_event (NautilusWindowSlot *self, | |
state); | |
} | |
- if (retval) | |
+ if (retval && type_ahead_search ()) | |
{ | |
nautilus_window_slot_set_search_visible (self, TRUE); | |
} | |
@@ -684,6 +696,7 @@ nautilus_window_slot_set_searching (NautilusWindowSlot *self, | |
{ | |
self->searching = searching; | |
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SEARCHING]); | |
+ nautilus_query_editor_set_searching (self->query_editor, searching); | |
} | |
static void | |
@@ -917,6 +930,15 @@ nautilus_window_slot_constructed (GObject *object) | |
gtk_box_append (GTK_BOX (self), extras_vbox); | |
self->query_editor = NAUTILUS_QUERY_EDITOR (nautilus_query_editor_new ()); | |
+ g_signal_connect (self->query_editor, "changed", | |
+ G_CALLBACK (query_editor_changed_callback), self); | |
+ g_signal_connect (self->query_editor, "cancel", | |
+ G_CALLBACK (query_editor_cancel_callback), self); | |
+ g_signal_connect (self->query_editor, "activated", | |
+ G_CALLBACK (query_editor_activated_callback), self); | |
+ g_signal_connect (self->query_editor, "focus-view", | |
+ G_CALLBACK (query_editor_focus_view_callback), self); | |
+ | |
/* We want to keep alive the query editor betwen additions and removals on the | |
* UI, specifically when the toolbar adds or removes it */ | |
g_object_ref_sink (self->query_editor); | |
diff --git a/src/nautilus-window.c b/src/nautilus-window.c | |
index 0033dcf5d..0f1c1004e 100644 | |
--- a/src/nautilus-window.c | |
+++ b/src/nautilus-window.c | |
@@ -1531,6 +1531,7 @@ const GActionEntry win_entries[] = | |
{ "forward", action_forward }, | |
{ "back-n", action_back_n, "u" }, | |
{ "forward-n", action_forward_n, "u" }, | |
+ { "backspaceup", action_up }, | |
{ "up", action_up }, | |
{ "current-location-menu", action_show_current_location_menu }, | |
{ "open-location", action_open_location, "s" }, | |
@@ -1587,6 +1588,7 @@ nautilus_window_initialize_actions (NautilusWindow *window) | |
/* Only accesible by shorcuts */ | |
nautilus_application_set_accelerators (app, "win.bookmark-current-location", ACCELS ("<control>d", "AddFavorite")); | |
nautilus_application_set_accelerator (app, "win.up", "<alt>Up"); | |
+ nautilus_application_set_accelerator (app, "win.backspaceup", "BackSpace"); | |
nautilus_application_set_accelerators (app, "win.go-home", ACCELS ("<alt>Home", "HomePage", "Start")); | |
nautilus_application_set_accelerator (app, "win.go-starred", "Favorites"); | |
nautilus_application_set_accelerator (app, "win.tab-move-left", "<shift><control>Page_Up"); | |
diff --git a/src/resources/ui/nautilus-preferences-window.ui b/src/resources/ui/nautilus-preferences-window.ui | |
index 9b2cd2edc..6ba51aaae 100644 | |
--- a/src/resources/ui/nautilus-preferences-window.ui | |
+++ b/src/resources/ui/nautilus-preferences-window.ui | |
@@ -50,6 +50,21 @@ | |
<property name="visible">True</property> | |
</object> | |
</child> | |
+ <child> | |
+ <object class="AdwActionRow"> | |
+ <property name="activatable_widget">type_ahead_search</property> | |
+ <property name="subtitle_lines">0</property> | |
+ <property name="title" translatable="yes">Search on type ahead</property> | |
+ <property name="title_lines">0</property> | |
+ <property name="use_underline">True</property> | |
+ <property name="visible">True</property> | |
+ <child> | |
+ <object class="GtkSwitch" id="type_ahead_search"> | |
+ <property name="valign">center</property> | |
+ </object> | |
+ </child> | |
+ </object> | |
+ </child> | |
</object> | |
</child> | |
<child> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git i/test/automated/displayless/meson.build w/test/automated/displayless/meson.build | |
index b154cb191..9d77b509d 100644 | |
--- i/test/automated/displayless/meson.build | |
+++ w/test/automated/displayless/meson.build | |
@@ -35,11 +35,7 @@ tests = [ | |
]] | |
] | |
-tracker_tests = [ | |
- ['test-nautilus-search-engine-tracker', [ | |
- 'test-nautilus-search-engine-tracker.c', | |
- ]], | |
-] | |
+tracker_tests = [] | |
foreach t: tests | |
test( |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# $Id: PKGBUILD 278826 2016-10-15 00:15:40Z heftig $ | |
# Contributor (original patch code): Jan de Groot <jgc@archlinux.org> | |
# Contributor (original package maintainer): Ian Hernández <badwolfie@archlinux.info> | |
# Contributor (current main repo package maintainer): Jan Alexander Steffens (heftig) <heftig@archlinux.org> | |
# Contributor (current patch code): Xavier Claessens <xavier.claessens@collabora.com> | |
# Contributor (fix for backspace going to parent folder): Jeremy Bicha <jbicha@debian.org> | |
# Contributor (updated patch for 43.2): Bryan Lai <bryanlais@gmail.com> | |
# Maintainer: Albert Vaca Cintora <albertvaka@gmail.com> | |
pkgbase=nautilus-typeahead | |
pkgname=( | |
nautilus-typeahead | |
libnautilus-extension-typeahead | |
libnautilus-extension-typeahead-docs | |
) | |
packager="Albert Vaca Cintora <albertvaka@gmail.com>" | |
pkgver=44.1 | |
pkgrel=1 | |
pkgdesc="Default file manager for GNOME - Patched to bring back the 'typeahead find' feature" | |
url="https://wiki.gnome.org/Apps/Files" | |
arch=(x86_64) | |
license=(GPL) | |
depends=( | |
dconf | |
gdk-pixbuf2 | |
gnome-autoar | |
gnome-desktop-4 | |
gst-plugins-base-libs | |
gvfs | |
libadwaita | |
libcloudproviders | |
libgexiv2 | |
libportal-gtk4 | |
tracker3 | |
) | |
makedepends=( | |
appstream-glib | |
gi-docgen | |
git | |
gobject-introspection | |
meson | |
tracker3-miners | |
) | |
checkdepends=(python-gobject) | |
_commit=a3fda22858ad6186ace1b22bc466e4087d67ca8e # tags/44.1^0 | |
source=( | |
"git+https://gitlab.gnome.org/GNOME/nautilus.git#commit=$_commit" | |
nautilus-restore-typeahead.patch | |
no-tracker-test.diff | |
) | |
b2sums=('SKIP' | |
'c5c44954bff8f73ddb89f7fa4375c626db532565142f5e95e817a7796f0ace0d6da8839734d633b7daa2b3b619cc03158ec4e3d1969974d74a18e1843271a493' | |
'079cd60e8f408cd145bc71c4c0edb9738719adcaccb24f110464ac9cd87f6b65cc9246563c809aec65f67e050dce6b5f09520e621c61cb83ca4b7f13917d57cf') | |
pkgver() { | |
cd nautilus | |
git describe --tags | sed 's/[^-]*-g/r&/;s/-/+/g' | |
} | |
prepare() { | |
cd nautilus | |
# Apply Typeahead patches | |
patch -p1 -i ../nautilus-restore-typeahead.patch | |
# Tracker test broken in our containers because bubblewrap stopped working, | |
# also see https://bugs.archlinux.org/task/78033 | |
git apply -3 ../no-tracker-test.diff | |
} | |
build() { | |
local meson_options=( | |
-D docs=true | |
-D packagekit=false | |
) | |
arch-meson nautilus build "${meson_options[@]}" | |
meson compile -C build | |
} | |
check() { | |
echo "Skipping checks for Typeahead builds..." | |
#meson test -C build --print-errorlogs | |
} | |
_pick() { | |
local p="$1" f d; shift | |
for f; do | |
d="$srcdir/$p/${f#$pkgdir/}" | |
mkdir -p "$(dirname "$d")" | |
mv "$f" "$d" | |
rmdir -p --ignore-fail-on-non-empty "$(dirname "$f")" | |
done | |
} | |
package_nautilus-typeahead() { | |
depends+=(libnautilus-extension-typeahead) | |
optdepends=( | |
'nautilus-sendto: Send files via mail extension' | |
'tracker3-miners: Full text search and metadata-based renaming' | |
'python-nautilus: to use extensions written in python' | |
) | |
install='post.install' | |
conflicts=(nautilus) | |
provides=(nautilus) | |
groups=(gnome) | |
meson install -C build --destdir "$pkgdir" | |
cd "$pkgdir" | |
_pick libne usr/include | |
_pick libne usr/lib/{girepository-1.0,libnautilus-extension*,pkgconfig} | |
_pick libne usr/share/gir-1.0 | |
_pick ldocs usr/share/doc | |
} | |
package_libnautilus-extension-typeahead() { | |
pkgdesc="Extension interface for Nautilus" | |
depends=( | |
gcc-libs | |
glib2 | |
) | |
conflicts=(libnautilus-extension libnautilus-extension.so) | |
provides=(libnautilus-extension libnautilus-extension.so) | |
mv libne/* "$pkgdir" | |
} | |
package_libnautilus-extension-typeahead-docs() { | |
pkgdesc="Extension interface for Nautilus (documentation)" | |
depends=() | |
mv ldocs/* "$pkgdir" | |
} | |
# vim:set sw=2 sts=-1 et: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment