Skip to content

Instantly share code, notes, and snippets.

@darthoctopus
Last active October 20, 2016 01:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darthoctopus/9580eb8d68328a607d47 to your computer and use it in GitHub Desktop.
Save darthoctopus/9580eb8d68328a607d47 to your computer and use it in GitHub Desktop.
Typeahead Find for Nautilus 3.22
data/org.gnome.nautilus.gschema.xml | 5 +
src/nautilus-global-preferences.h | 3 +
src/nautilus-list-view.c | 19 +
src/nautilus-list-view.h | 3 +-
src/nautilus-preferences-window.c | 5 +
src/nautilus-window-slot.c | 1011 ++++++++++++++++++++++-
src/resources/ui/nautilus-preferences-window.ui | 50 ++
7 files changed, 1086 insertions(+), 10 deletions(-)
diff --git a/data/org.gnome.nautilus.gschema.xml b/data/org.gnome.nautilus.gschema.xml
index c05faf3..62b5e8c 100644
--- a/data/org.gnome.nautilus.gschema.xml
+++ b/data/org.gnome.nautilus.gschema.xml
@@ -211,6 +211,11 @@
<summary>Bulk rename utility</summary>
<description>If set, Nautilus will append URIs of selected files and treat the result as a command line for bulk renaming. Bulk rename applications can register themselves in this key by setting the key to a space-separated string of their executable name and any command line options. If the executable name is not set to a full path, it will be searched for in the search path.</description>
</key>
+ <key name="enable-interactive-search" type="b">
+ <default>true</default>
+ <summary>Enable interactive (type-ahead) search</summary>
+ <description>If set to true, enables interactive search, similar to Nautilus 3.4.</description>
+ </key>
<key type="b" name="open-folder-on-dnd-hover">
<default>true</default>
<summary>Whether to open the hovered folder after a timeout when drag and drop operation</summary>
diff --git a/src/nautilus-global-preferences.h b/src/nautilus-global-preferences.h
index bf1c896..4eaf370 100644
--- a/src/nautilus-global-preferences.h
+++ b/src/nautilus-global-preferences.h
@@ -161,6 +161,9 @@ typedef enum
/* Recent files */
#define NAUTILUS_PREFERENCES_RECENT_FILES_ENABLED "remember-recent-files"
+/* Interactive search (typeahead) */
+#define NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH "enable-interactive-search"
+
/* Move to trash shorcut changed dialog */
#define NAUTILUS_PREFERENCES_SHOW_MOVE_TO_TRASH_SHORTCUT_CHANGED_DIALOG "show-move-to-trash-shortcut-changed-dialog"
diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c
index f4b1fb0..4162104 100644
--- a/src/nautilus-list-view.c
+++ b/src/nautilus-list-view.c
@@ -2694,6 +2694,7 @@ nautilus_list_view_set_selection (NautilusFilesView *view,
GList *node;
GList *iters, *l;
NautilusFile *file;
+ GtkTreePath *path = NULL;
list_view = NAUTILUS_LIST_VIEW (view);
tree_selection = gtk_tree_view_get_selection (list_view->details->tree_view);
@@ -2710,10 +2711,22 @@ nautilus_list_view_set_selection (NautilusFilesView *view,
{
gtk_tree_selection_select_iter (tree_selection,
(GtkTreeIter *) l->data);
+ if (!path)
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_view->details->model), (GtkTreeIter *) l->data);
}
+
g_list_free_full (iters, g_free);
}
+ if (path) {
+ gtk_tree_view_set_cursor_on_cell (list_view->details->tree_view,
+ path,
+ list_view->details->file_name_column,
+ GTK_CELL_RENDERER (list_view->details->file_name_cell),
+ TRUE);
+ gtk_tree_path_free (path);
+ }
+
g_signal_handlers_unblock_by_func (tree_selection, list_selection_changed_callback, view);
nautilus_files_view_notify_selection_changed (view);
}
@@ -3602,3 +3615,9 @@ nautilus_list_view_new (NautilusWindowSlot *slot)
"window-slot", slot,
NULL);
}
+
+GtkTreeView *
+nautilus_list_view_get_tree_view (NautilusListView *list_view)
+{
+ return list_view->details->tree_view;
+}
diff --git a/src/nautilus-list-view.h b/src/nautilus-list-view.h
index f775431..bbcb565 100644
--- a/src/nautilus-list-view.h
+++ b/src/nautilus-list-view.h
@@ -3,7 +3,7 @@
Copyright (C) 2000 Eazel, Inc.
Copyright (C) 2001 Anders Carlsson <andersca@gnu.org>
-
+
The Gnome Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
@@ -52,5 +52,6 @@ typedef struct {
GType nautilus_list_view_get_type (void);
NautilusFilesView * nautilus_list_view_new (NautilusWindowSlot *slot);
+GtkTreeView * nautilus_list_view_get_tree_view (NautilusListView *list_view);
#endif /* NAUTILUS_LIST_VIEW_H */
diff --git a/src/nautilus-preferences-window.c b/src/nautilus-preferences-window.c
index 2df9e4a..5719bf3 100644
--- a/src/nautilus-preferences-window.c
+++ b/src/nautilus-preferences-window.c
@@ -59,6 +59,8 @@
"trash_confirm_checkbutton"
#define NAUTILUS_PREFERENCES_DIALOG_AUTOMATIC_DECOMPRESSION_WIDGET \
"automatic_decompression_checkbutton"
+#define NAUTILUS_PREFERENCES_DIALOG_ENABLE_INTERACTIVE_SEARCH_WIDGET \
+ "interactive_search_checkbutton"
/* int enums */
#define NAUTILUS_PREFERENCES_DIALOG_THUMBNAIL_LIMIT_WIDGET \
@@ -505,6 +507,9 @@ static void nautilus_preferences_window_setup(GtkBuilder *builder,
bind_builder_bool (builder, nautilus_preferences,
NAUTILUS_PREFERENCES_DIALOG_AUTOMATIC_DECOMPRESSION_WIDGET,
NAUTILUS_PREFERENCES_AUTOMATIC_DECOMPRESSION);
+ bind_builder_bool (builder, nautilus_preferences,
+ NAUTILUS_PREFERENCES_DIALOG_ENABLE_INTERACTIVE_SEARCH_WIDGET,
+ NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH);
bind_builder_bool (builder, nautilus_list_view_preferences,
NAUTILUS_PREFERENCES_DIALOG_LIST_VIEW_USE_TREE_WIDGET,
NAUTILUS_PREFERENCES_LIST_VIEW_USE_TREE);
diff --git a/src/nautilus-window-slot.c b/src/nautilus-window-slot.c
index ba278e7..2e95beb 100644
--- a/src/nautilus-window-slot.c
+++ b/src/nautilus-window-slot.c
@@ -120,6 +120,17 @@ typedef struct
GError *mount_error;
gboolean tried_mount;
gint view_mode_before_search;
+
+ /* Interactive search */
+ gboolean isearch_enable;
+ gboolean isearch_imcontext_changed;
+ gboolean isearch_disable_hide;
+ NautilusFile *isearch_selected_file;
+ GtkWidget *isearch_window;
+ GtkWidget *isearch_entry;
+ gulong isearch_entry_changed_id;
+ guint isearch_timeout_id;
+ gulong isearch_configure_event_id;
} NautilusWindowSlotPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (NautilusWindowSlot, nautilus_window_slot, GTK_TYPE_BOX);
@@ -147,6 +158,97 @@ static void nautilus_window_slot_set_search_visible (NautilusWindowSlot *self,
static gboolean nautilus_window_slot_get_search_visible (NautilusWindowSlot *self);
static void nautilus_window_slot_set_location (NautilusWindowSlot *self,
GFile *location);
+
+/* Interactive search */
+static void isearch_ensure (NautilusWindowSlot *slot);
+
+static gboolean isearch_start (NautilusWindowSlot *slot,
+ GdkDevice *device);
+
+static void isearch_enable_changed (gpointer callback_data);
+
+static void isearch_dispose (NautilusWindowSlot *slot);
+
+static void isearch_hide (NautilusWindowSlot *slot,
+ GdkDevice *device);
+
+static gboolean isearch_timeout (gpointer user_data);
+
+static void isearch_timeout_destroy (gpointer user_data);
+
+static void isearch_timeout_restart (NautilusWindowSlot *slot);
+
+static gboolean isearch_window_delete_event (GtkWidget *widget,
+ GdkEventAny *event,
+ NautilusWindowSlot *slot);
+
+static gboolean isearch_window_button_press_event (GtkWidget *widget,
+ GdkEventButton *event,
+ NautilusWindowSlot *slot);
+
+static gboolean isearch_window_scroll_event (GtkWidget *widget,
+ GdkEventScroll *event,
+ NautilusWindowSlot *slot);
+
+static void isearch_activate_items_alternate (NautilusWindowSlot *slot);
+
+static gboolean isearch_window_key_press_event (GtkWidget *widget,
+ GdkEventKey *event,
+ NautilusWindowSlot *slot);
+
+static void isearch_disable_hide (GtkEntry *entry,
+ GtkMenu *menu,
+ gpointer data);
+
+static void isearch_preedit_changed (GtkEntry *entry,
+ gchar *preedit,
+ NautilusWindowSlot *slot);
+
+static void isearch_activate_event (GtkEntry *entry,
+ NautilusWindowSlot *slot);
+
+static gboolean isearch_enable_hide_real (gpointer data);
+
+static void isearch_enable_hide (GtkWidget *widget,
+ gpointer data);
+
+static void send_focus_change (GtkWidget *widget,
+ GdkDevice *device,
+ gboolean in);
+
+static void isearch_entry_changed (GtkWidget *entry,
+ NautilusWindowSlot *slot);
+
+static void isearch_position (NautilusWindowSlot *slot);
+
+static gboolean isearch_compare_filename (const gchar *f1,
+ const gchar *f2,
+ guint length);
+
+static int compare_files (gconstpointer a,
+ gconstpointer b,
+ gpointer callback_data);
+
+static GList *isearch_get_sorted_files (NautilusWindowSlot *slot);
+
+static NautilusFile *isearch_find (NautilusWindowSlot *slot,
+ const gchar *text);
+
+static NautilusFile *isearch_find_next (NautilusWindowSlot *slot,
+ const gchar *text);
+
+static NautilusFile *isearch_find_prev (NautilusWindowSlot *slot,
+ const gchar *text);
+
+static gboolean isearch_move_next (NautilusWindowSlot *slot);
+
+static gboolean isearch_move_prev (NautilusWindowSlot *slot);
+
+static void isearch_set_selection (NautilusWindowSlot *slot,
+ NautilusFile *file);
+
+#define ISEARCH_TIMEOUT 5000
+
gboolean
nautilus_window_slot_handles_location (NautilusWindowSlot *self,
GFile *location)
@@ -563,21 +665,86 @@ nautilus_window_slot_handle_event (NautilusWindowSlot *self,
action = g_action_map_lookup_action (G_ACTION_MAP (priv->slot_action_group),
"search-visible");
- /* If the action is not enabled, don't try to handle search */
- if (g_action_get_enabled (action))
- {
- retval = gtk_search_bar_handle_event (GTK_SEARCH_BAR (priv->query_editor),
- (GdkEvent *) event);
- }
+ if (priv->isearch_enable) {
+ GdkEvent *new_event;
+ gchar *old_text;
+ const gchar *new_text;
+ GdkScreen *screen;
+ gboolean text_modified;
+ gulong popup_menu_id;
+
+ isearch_ensure (self);
+
+ /* Make a copy of the current text */
+ old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->isearch_entry)));
+ new_event = gdk_event_copy ((GdkEvent *) event);
+ g_object_unref (((GdkEventKey *) new_event)->window);
+
+ ((GdkEventKey *) new_event)->window =
+ g_object_ref (gtk_widget_get_window (priv->isearch_window));
+ gtk_widget_realize (priv->isearch_window);
+
+ popup_menu_id = g_signal_connect (priv->isearch_entry,
+ "popup-menu", G_CALLBACK (gtk_true),
+ NULL);
+
+ /* Move the entry off screen */
+ screen = gtk_widget_get_screen (GTK_WIDGET (self));
+ gtk_window_move (GTK_WINDOW (priv->isearch_window),
+ gdk_screen_get_width (screen) + 1,
+ gdk_screen_get_height (screen) + 1);
+ gtk_widget_show (priv->isearch_window);
+
+ /* Send the event to the window. If the preedit_changed signal is emitted during this
+ * event, we will set priv->imcontext_changed */
+ priv->isearch_imcontext_changed = FALSE;
+ retval = gtk_widget_event (priv->isearch_window, new_event);
+ gdk_event_free (new_event);
+ gtk_widget_hide (priv->isearch_window);
+
+ g_signal_handler_disconnect (priv->isearch_entry, popup_menu_id);
+
+ /* We check to make sure that the entry tried to handle the text, and that the text has
+ * changed. */
+ new_text = gtk_entry_get_text (GTK_ENTRY (priv->isearch_entry));
+ text_modified = strcmp (old_text, new_text) != 0;
+ g_free (old_text);
+
+ if (priv->isearch_imcontext_changed || (retval && text_modified)) {
+ if (isearch_start (self, gdk_event_get_device ((GdkEvent *) event))) {
+ gtk_widget_grab_focus (GTK_WIDGET (self));
+ return TRUE;
+ }
- if (retval)
- {
- nautilus_window_slot_set_search_visible (self, TRUE);
+ gtk_entry_set_text (GTK_ENTRY (priv->isearch_entry), "");
+ return FALSE;
+ }
+ } else {
+ /* If the action is not enabled, don't try to handle search */
+ if (g_action_get_enabled (action))
+ {
+ retval = gtk_search_bar_handle_event (GTK_SEARCH_BAR (priv->query_editor),
+ (GdkEvent *) event);
+ }
+
+ if (retval)
+ {
+ nautilus_window_slot_set_search_visible (self, TRUE);
+ }
}
return retval;
}
+/* static gboolean
+configure_event_cb (GtkWidget *widget,
+ GdkEventConfigure *event,
+ NautilusWindowSlot *slot)
+{
+ isearch_hide (slot, NULL);
+ return FALSE;
+} */
+
static void
real_active (NautilusWindowSlot *self)
{
@@ -606,10 +773,19 @@ static void
real_inactive (NautilusWindowSlot *self)
{
NautilusWindow *window;
+ NautilusWindowSlotPrivate *priv;
+ priv = nautilus_window_slot_get_instance_private (self);
window = nautilus_window_slot_get_window (self);
g_assert (self == nautilus_window_get_active_slot (window));
+ isearch_hide (self, NULL);
+ if (priv->isearch_configure_event_id != 0) {
+ g_signal_handler_disconnect (GTK_WIDGET (priv->window),
+ priv->isearch_configure_event_id);
+ priv->isearch_configure_event_id = 0;
+ }
+
gtk_widget_insert_action_group (GTK_WIDGET (window), "slot", NULL);
}
@@ -898,9 +1074,30 @@ nautilus_window_slot_init (NautilusWindowSlot *self)
nautilus_application_set_accelerator (app, "slot.files-view-mode(uint32 0)", "<control>2");
nautilus_application_set_accelerator (app, "slot.search-visible", "<control>f");
+ priv->isearch_enable = g_settings_get_boolean (nautilus_preferences,
+ NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH);
+
+ g_signal_connect_swapped (nautilus_preferences,
+ "changed::" NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH,
+ G_CALLBACK (isearch_enable_changed),
+ self);
+
priv->view_mode_before_search = NAUTILUS_VIEW_INVALID_ID;
}
+static void
+nautilus_window_slot_finalize (GObject *object)
+{
+ NautilusWindowSlot *slot;
+ slot = NAUTILUS_WINDOW_SLOT (object);
+
+ g_signal_handlers_disconnect_by_func (nautilus_preferences,
+ isearch_enable_changed,
+ slot);
+
+ G_OBJECT_CLASS (nautilus_window_slot_parent_class)->finalize (object);
+}
+
#define DEBUG_FLAG NAUTILUS_DEBUG_WINDOW
#include "nautilus-debug.h"
@@ -2643,6 +2840,7 @@ nautilus_window_slot_dispose (GObject *object)
self = NAUTILUS_WINDOW_SLOT (object);
priv = nautilus_window_slot_get_instance_private (self);
+ isearch_dispose (self);
nautilus_window_slot_clear_forward_list (self);
nautilus_window_slot_clear_back_list (self);
@@ -2731,6 +2929,7 @@ nautilus_window_slot_class_init (NautilusWindowSlotClass *klass)
oclass->constructed = nautilus_window_slot_constructed;
oclass->set_property = nautilus_window_slot_set_property;
oclass->get_property = nautilus_window_slot_get_property;
+ oclass->finalize = nautilus_window_slot_finalize;
widget_class->grab_focus = nautilus_window_slot_grab_focus;
@@ -3122,3 +3321,797 @@ nautilus_window_slot_get_loading (NautilusWindowSlot *self)
return priv->loading;
}
+
+/* Interactive search */
+static void
+isearch_ensure (NautilusWindowSlot *slot)
+{
+ GtkWidget *frame;
+ GtkWidget *vbox;
+ GtkWidget *toplevel;
+ GdkScreen *screen;
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (slot));
+ screen = gtk_widget_get_screen (GTK_WIDGET (slot));
+
+ if (priv->isearch_window != NULL)
+ {
+ if (gtk_window_has_group (GTK_WINDOW (toplevel)))
+ gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
+ GTK_WINDOW (priv->isearch_window));
+ else if (gtk_window_has_group (GTK_WINDOW (priv->isearch_window)))
+ gtk_window_group_remove_window (gtk_window_get_group (
+ GTK_WINDOW (priv->isearch_window)),
+ GTK_WINDOW (priv->isearch_window));
+
+ gtk_window_set_screen (GTK_WINDOW (priv->isearch_window), screen);
+ return;
+ }
+
+ priv->isearch_window = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_window_set_screen (GTK_WINDOW (priv->isearch_window), screen);
+
+ if (gtk_window_has_group (GTK_WINDOW (toplevel)))
+ gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
+ GTK_WINDOW (priv->isearch_window));
+
+ gtk_window_set_type_hint (GTK_WINDOW (priv->isearch_window),
+ GDK_WINDOW_TYPE_HINT_UTILITY);
+ gtk_window_set_modal (GTK_WINDOW (priv->isearch_window), TRUE);
+ g_signal_connect (priv->isearch_window, "delete-event",
+ G_CALLBACK (isearch_window_delete_event), slot);
+ g_signal_connect (priv->isearch_window, "key-press-event",
+ G_CALLBACK (isearch_window_key_press_event), slot);
+ g_signal_connect (priv->isearch_window, "button-press-event",
+ G_CALLBACK (isearch_window_button_press_event), slot);
+ g_signal_connect (priv->isearch_window, "scroll-event",
+ G_CALLBACK (isearch_window_scroll_event), slot);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
+ gtk_widget_show (frame);
+ gtk_container_add (GTK_CONTAINER (priv->isearch_window), frame);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_show (vbox);
+ gtk_container_add (GTK_CONTAINER (frame), vbox);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
+
+ /* add entry */
+ priv->isearch_entry = gtk_entry_new ();
+ gtk_widget_show (priv->isearch_entry);
+ g_signal_connect (priv->isearch_entry, "populate-popup",
+ G_CALLBACK (isearch_disable_hide), slot);
+ g_signal_connect (priv->isearch_entry, "activate",
+ G_CALLBACK (isearch_activate_event), slot);
+
+ g_signal_connect (G_OBJECT (priv->isearch_entry), "preedit-changed",
+ G_CALLBACK (isearch_preedit_changed), slot);
+ gtk_container_add (GTK_CONTAINER (vbox), priv->isearch_entry);
+
+ gtk_widget_realize (priv->isearch_entry);
+}
+
+static gboolean
+isearch_timeout (gpointer user_data)
+{
+ NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (user_data);
+
+ if (!g_source_is_destroyed (g_main_current_source ()))
+ isearch_hide (slot, NULL);
+
+ return FALSE;
+}
+
+static void
+isearch_timeout_destroy (gpointer user_data)
+{
+ NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (user_data);
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+ priv->isearch_timeout_id = 0;
+}
+
+static void
+isearch_timeout_restart (NautilusWindowSlot *slot)
+{
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+ if (priv->isearch_timeout_id != 0)
+ {
+ g_source_remove (priv->isearch_timeout_id);
+
+ priv->isearch_timeout_id =
+ gdk_threads_add_timeout_full (G_PRIORITY_LOW, ISEARCH_TIMEOUT,
+ isearch_timeout, slot,
+ isearch_timeout_destroy);
+ }
+}
+
+static gboolean
+isearch_window_delete_event (GtkWidget *widget,
+ GdkEventAny *event,
+ NautilusWindowSlot *slot)
+{
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ isearch_hide (slot, NULL);
+ return TRUE;
+}
+
+static gboolean
+isearch_window_button_press_event (GtkWidget *widget,
+ GdkEventButton *event,
+ NautilusWindowSlot *slot)
+{
+ GdkDevice *keyb_device;
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ keyb_device = gdk_device_get_associated_device (event->device);
+ isearch_hide (slot, keyb_device);
+
+ /* A bit of hackery here */
+ if (NAUTILUS_IS_CANVAS_VIEW (priv->content_view))
+ {
+ NautilusCanvasContainer *cc = nautilus_canvas_view_get_canvas_container (
+ NAUTILUS_CANVAS_VIEW (priv->content_view));
+ gboolean retval;
+
+ if (event->window == gtk_layout_get_bin_window (GTK_LAYOUT (cc)))
+ g_signal_emit_by_name (GTK_WIDGET (cc), "button-press-event", event,
+ &retval);
+
+ return retval;
+ }
+ else if (NAUTILUS_IS_LIST_VIEW (priv->content_view))
+ {
+ gboolean retval;
+ // NautilusListView *lv = NAUTILUS_LIST_VIEW (priv->content_view);
+ GtkTreeView *tv =
+ nautilus_list_view_get_tree_view (NAUTILUS_LIST_VIEW (priv->content_view));
+
+ if (event->window == gtk_tree_view_get_bin_window (tv))
+ g_signal_emit_by_name (GTK_WIDGET (tv),
+ "button-press-event",
+ event,
+ &retval);
+
+ return retval;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+isearch_window_scroll_event (GtkWidget *widget,
+ GdkEventScroll *event,
+ NautilusWindowSlot *slot)
+{
+ gboolean retval = FALSE;
+
+ if (event->direction == GDK_SCROLL_UP)
+ {
+ isearch_move_prev (slot);
+ retval = TRUE;
+ }
+ else if (event->direction == GDK_SCROLL_DOWN)
+ {
+ isearch_move_next (slot);
+ retval = TRUE;
+ }
+
+ if (retval)
+ isearch_timeout_restart (slot);
+
+ return retval;
+}
+
+static void
+isearch_activate_items_alternate (NautilusWindowSlot *slot)
+{
+ GList *file_list;
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ file_list = nautilus_view_get_selection (priv->content_view);
+ if(file_list != NULL)
+ nautilus_files_view_activate_files (NAUTILUS_FILES_VIEW (priv->content_view),
+ file_list,
+ NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB, TRUE);
+ nautilus_file_list_free (file_list);
+}
+
+static gboolean
+isearch_window_key_press_event (GtkWidget *widget,
+ GdkEventKey *event,
+ NautilusWindowSlot *slot)
+{
+ GdkModifierType default_accel;
+ gboolean retval = FALSE;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+ g_return_val_if_fail (NAUTILUS_IS_WINDOW_SLOT (slot), FALSE);
+
+ /* close window and cancel the search */
+ if (event->keyval == GDK_KEY_Escape || event->keyval == GDK_KEY_Tab ||
+ event->keyval == GDK_KEY_KP_Tab || event->keyval == GDK_KEY_ISO_Left_Tab)
+ {
+
+ isearch_hide (slot, gdk_event_get_device ((GdkEvent *) event));
+ return TRUE;
+ }
+
+ default_accel =
+ gtk_widget_get_modifier_mask (widget,
+ GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR);
+
+ /* select previous matching iter */
+ if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_KP_Up)
+ {
+ if (!isearch_move_prev (slot))
+ gtk_widget_error_bell (widget);
+
+ retval = TRUE;
+ }
+ if (((event->state & (default_accel | GDK_SHIFT_MASK)) ==
+ (default_accel | GDK_SHIFT_MASK)) &&
+ (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G))
+ {
+ if (!isearch_move_prev (slot))
+ gtk_widget_error_bell (widget);
+
+ retval = TRUE;
+ }
+ /* select next matching iter */
+ if (event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down)
+ {
+ if (!isearch_move_next (slot))
+ gtk_widget_error_bell (widget);
+
+ retval = TRUE;
+ }
+ if (((event->state & (default_accel | GDK_SHIFT_MASK)) == default_accel) &&
+ (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G))
+ {
+ if (!isearch_move_next (slot))
+ gtk_widget_error_bell (widget);
+
+ retval = TRUE;
+ }
+
+ /* Alternate activation (ShiftEnter).
+ * Regular activation (Enter) is handled by the entry activate signal.
+ */
+ if ((event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_KP_Enter) &&
+ (event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
+ {
+ isearch_activate_items_alternate (slot);
+ isearch_hide (slot, gdk_event_get_device ((GdkEvent *) event));
+ retval = TRUE;
+ }
+ isearch_timeout_restart (slot);
+ return retval;
+}
+
+static void
+isearch_disable_hide (GtkEntry *entry,
+ GtkMenu *menu,
+ gpointer data)
+{
+ NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (data);
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ priv->isearch_disable_hide = 1;
+ g_signal_connect (menu, "hide", G_CALLBACK (isearch_enable_hide), data);
+}
+
+static void
+isearch_preedit_changed (GtkEntry *entry,
+ gchar *preedit,
+ NautilusWindowSlot *slot)
+{
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+ priv->isearch_imcontext_changed = 1;
+ isearch_timeout_restart (slot);
+}
+
+static void
+isearch_activate_event (GtkEntry *entry,
+ NautilusWindowSlot *slot)
+{
+ // GtkTreePath *path;
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ if(priv->content_view != NULL &&
+ NAUTILUS_IS_FILES_VIEW (priv->content_view) &&
+ nautilus_view_get_selection (NAUTILUS_VIEW (priv->content_view)) != NULL){
+ isearch_hide (slot, gtk_get_current_event_device ());
+ nautilus_files_view_activate_selection (NAUTILUS_FILES_VIEW (priv->content_view));
+ }
+}
+
+static gboolean
+isearch_enable_hide_real (gpointer data)
+{
+ NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (data);
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+ priv->isearch_disable_hide = 0;
+ return FALSE;
+}
+
+static void
+isearch_enable_hide (GtkWidget *widget,
+ gpointer data)
+{
+ gdk_threads_add_timeout_full (G_PRIORITY_HIGH, 200,
+ isearch_enable_hide_real,
+ g_object_ref (data),
+ g_object_unref);
+}
+
+static void
+send_focus_change (GtkWidget *widget,
+ GdkDevice *device,
+ gboolean in)
+{
+ GdkDeviceManager *device_manager;
+ GList *devices;
+ GList *d;
+
+ device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
+ devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
+ devices = g_list_concat (devices,
+ gdk_device_manager_list_devices (device_manager,
+ GDK_DEVICE_TYPE_SLAVE));
+ devices = g_list_concat (devices,
+ gdk_device_manager_list_devices (device_manager,
+ GDK_DEVICE_TYPE_FLOATING));
+
+ for (d = devices; d; d = d->next)
+ {
+ GdkDevice *dev = d->data;
+ GdkEvent *fevent;
+ GdkWindow *window;
+
+ if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
+ continue;
+
+ window = gtk_widget_get_window (widget);
+
+ /* Skip non-master keyboards that haven't
+ * selected for events from this window
+ */
+ if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
+ !gdk_window_get_device_events (window, dev))
+ continue;
+
+ fevent = gdk_event_new (GDK_FOCUS_CHANGE);
+
+ fevent->focus_change.type = GDK_FOCUS_CHANGE;
+ fevent->focus_change.window = g_object_ref (window);
+ fevent->focus_change.in = in;
+ gdk_event_set_device (fevent, device);
+
+ gtk_widget_send_focus_change (widget, fevent);
+
+ gdk_event_free (fevent);
+ }
+
+ g_list_free (devices);
+}
+
+static void
+isearch_hide (NautilusWindowSlot *slot,
+ GdkDevice *device)
+{
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ if (priv->isearch_disable_hide)
+ return;
+
+ if (!priv->isearch_enable)
+ return;
+
+ if (priv->isearch_entry_changed_id)
+ {
+ g_signal_handler_disconnect (priv->isearch_entry,
+ priv->isearch_entry_changed_id);
+ priv->isearch_entry_changed_id = 0;
+ }
+ if (priv->isearch_timeout_id)
+ {
+ g_source_remove (priv->isearch_timeout_id);
+ priv->isearch_timeout_id = 0;
+ }
+ if (priv->isearch_window != NULL &&
+ gtk_widget_get_visible (priv->isearch_window))
+ {
+ /* send focus-in event */
+ send_focus_change (GTK_WIDGET (priv->isearch_entry), device, FALSE);
+ gtk_widget_hide (priv->isearch_window);
+ gtk_entry_set_text (GTK_ENTRY (priv->isearch_entry), "");
+ send_focus_change (GTK_WIDGET (slot), device, TRUE);
+ }
+}
+
+static void
+isearch_entry_changed (GtkWidget *entry,
+ NautilusWindowSlot *slot)
+{
+ // gint ret;
+ const gchar *text;
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+ g_return_if_fail (NAUTILUS_IS_WINDOW_SLOT (slot));
+
+ text = gtk_entry_get_text (GTK_ENTRY (entry));
+
+ /* unselect all */
+ nautilus_view_set_selection (priv->content_view, NULL);
+
+ isearch_timeout_restart (slot);
+
+ if (*text == '\0')
+ return;
+
+ isearch_set_selection (slot, isearch_find (slot, text));
+}
+
+static gboolean
+isearch_start (NautilusWindowSlot *slot,
+ GdkDevice *device)
+{
+ // GList * list;
+ // gboolean found_focus = FALSE;
+ GTypeClass *klass;
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ if (!priv->isearch_enable)
+ return FALSE;
+
+ if (priv->isearch_window != NULL &&
+ gtk_widget_get_visible (priv->isearch_window))
+ return TRUE;
+
+ if (nautilus_files_view_get_loading (NAUTILUS_FILES_VIEW (priv->content_view)))
+ return FALSE;
+
+ isearch_ensure (slot);
+
+ /* done, show it */
+ isearch_position (slot);
+ gtk_widget_show (priv->isearch_window);
+
+ if (priv->isearch_entry_changed_id == 0)
+ {
+ priv->isearch_entry_changed_id =
+ g_signal_connect (priv->isearch_entry, "changed",
+ G_CALLBACK (isearch_entry_changed), slot);
+ }
+
+ priv->isearch_timeout_id =
+ gdk_threads_add_timeout_full (G_PRIORITY_LOW, ISEARCH_TIMEOUT,
+ isearch_timeout, slot,
+ isearch_timeout_destroy);
+
+ /* Grab focus without selecting all the text. */
+ klass = g_type_class_peek_parent (GTK_ENTRY_GET_CLASS (priv->isearch_entry));
+ (*GTK_WIDGET_CLASS (klass)->grab_focus) (priv->isearch_entry);
+
+ /* send focus-in event */
+ send_focus_change (priv->isearch_entry, device, TRUE);
+
+ /* search first matching iter */
+ isearch_entry_changed (priv->isearch_entry, slot);
+ return TRUE;
+}
+
+static void
+isearch_position (NautilusWindowSlot *slot)
+{
+ gint x, y;
+ gint window_x, window_y;
+ gint window_width, window_height;
+ GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (slot));
+ GdkScreen *screen = gdk_window_get_screen (window);
+ GtkRequisition requisition;
+ gint monitor_num;
+ GdkRectangle monitor;
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ monitor_num = gdk_screen_get_monitor_at_window (screen, window);
+ gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);
+
+ gtk_widget_realize (priv->isearch_window);
+
+ gdk_window_get_origin (window, &window_x, &window_y);
+ window_width = gdk_window_get_width (window);
+ window_height = gdk_window_get_height (window);
+ gtk_widget_get_preferred_size (priv->isearch_window, &requisition, NULL);
+
+ if (window_x + window_width > gdk_screen_get_width (screen))
+ x = gdk_screen_get_width (screen) - requisition.width;
+ else if (window_x + window_width - requisition.width < 0)
+ x = 0;
+ else
+ x = window_x + window_width - requisition.width;
+
+ if (window_y + window_height + requisition.height >
+ gdk_screen_get_height (screen))
+ y = gdk_screen_get_height (screen) - requisition.height;
+ else if (window_y + window_height < 0) /* isn't really possible ... */
+ y = 0;
+ else
+ y = window_y + window_height;
+
+ gtk_window_move (GTK_WINDOW (priv->isearch_window), x, y);
+}
+
+static gboolean
+isearch_compare_filename (const gchar *f1,
+ const gchar *f2,
+ guint length)
+{
+ gchar *normalized_f1;
+ gchar *normalized_f2;
+ gchar *case_normalized_f1 = NULL;
+ gchar *case_normalized_f2 = NULL;
+ gboolean retval = FALSE;
+
+ normalized_f1 = g_utf8_normalize (f1, -1, G_NORMALIZE_ALL);
+ normalized_f2 = g_utf8_normalize (f2, -1, G_NORMALIZE_ALL);
+
+ if (G_LIKELY (normalized_f1 != NULL && normalized_f2 != NULL))
+ {
+ case_normalized_f1 = g_utf8_casefold (normalized_f1, -1);
+ case_normalized_f2 = g_utf8_casefold (normalized_f2, -1);
+
+ retval = (strncmp (case_normalized_f1, case_normalized_f2, length) == 0);
+ }
+
+ g_free (normalized_f1);
+ g_free (normalized_f2);
+ g_free (case_normalized_f1);
+ g_free (case_normalized_f2);
+ return retval;
+}
+
+static int
+compare_files (gconstpointer a,
+ gconstpointer b,
+ gpointer callback_data)
+{
+ NautilusFilesView *view = NAUTILUS_FILES_VIEW (callback_data);
+ NautilusFile *f1 = NAUTILUS_FILE (a);
+ NautilusFile *f2 = NAUTILUS_FILE (b);
+
+ return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->compare_files (view, f1, f2);
+}
+
+static GList *
+isearch_get_sorted_files (NautilusWindowSlot *slot)
+{
+ NautilusWindowSlotPrivate *priv = nautilus_window_slot_get_instance_private (slot);
+ NautilusView *view = priv->content_view;
+ NautilusDirectory *dir = nautilus_files_view_get_model (NAUTILUS_FILES_VIEW (view));
+ GList *list = nautilus_directory_get_file_list (dir);
+ GList *sorted_list;
+
+ sorted_list = g_list_sort_with_data (list, compare_files, view);
+ return sorted_list;
+}
+
+static NautilusFile *
+isearch_find (NautilusWindowSlot *slot,
+ const gchar *text)
+{
+ GList *files = isearch_get_sorted_files (slot);
+ GList *l;
+ NautilusFile *found = NULL;
+
+ for (l = files; l; l = g_list_next (l))
+ {
+ NautilusFile *file = NAUTILUS_FILE (l->data);
+ gchar *filename = nautilus_file_get_display_name (file);
+
+ if (isearch_compare_filename (filename, text, strlen (text)))
+ found = file;
+
+ g_free (filename);
+
+ if (found)
+ break;
+ }
+
+ return found;
+}
+
+static NautilusFile *
+isearch_find_next (NautilusWindowSlot *slot,
+ const gchar *text)
+{
+ GList *files = isearch_get_sorted_files (slot);
+ NautilusFile *found = NULL;
+ GList *current;
+ GList *l;
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ current = g_list_find (files, priv->isearch_selected_file);
+ for (l = g_list_next (current); l; l = g_list_next (l))
+ {
+ NautilusFile *file = NAUTILUS_FILE (l->data);
+ gchar *display_name = nautilus_file_get_display_name (file);
+
+ if (isearch_compare_filename (display_name, text, strlen (text)))
+ found = file;
+
+ g_free (display_name);
+
+ if (found)
+ break;
+ }
+
+ return found;
+}
+
+static NautilusFile *
+isearch_find_prev (NautilusWindowSlot *slot,
+ const gchar *text)
+{
+ GList *files = isearch_get_sorted_files (slot);
+ NautilusFile *found = NULL;
+ GList *current;
+ GList *l;
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ current = g_list_find (files, priv->isearch_selected_file);
+ for (l = g_list_previous (current); l; l = g_list_previous (l))
+ {
+ NautilusFile *file = NAUTILUS_FILE (l->data);
+ gchar *display_name = nautilus_file_get_display_name (file);
+
+ if (isearch_compare_filename (display_name, text, strlen (text)))
+ found = file;
+
+ g_free (display_name);
+
+ if (found)
+ break;
+ }
+
+ return found;
+}
+
+static gboolean
+isearch_move_next (NautilusWindowSlot *slot)
+{
+ const gchar *text;
+ NautilusFile *iter;
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ text = gtk_entry_get_text (GTK_ENTRY (priv->isearch_entry));
+ iter = isearch_find_next (slot, text);
+
+ if (iter)
+ isearch_set_selection (slot, iter);
+
+ return iter != NULL;
+}
+
+static gboolean
+isearch_move_prev (NautilusWindowSlot *slot)
+{
+ const gchar *text;
+ NautilusFile *iter;
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ text = gtk_entry_get_text (GTK_ENTRY (priv->isearch_entry));
+ iter = isearch_find_prev (slot, text);
+
+ if (iter)
+ isearch_set_selection (slot, iter);
+
+ return iter != NULL;
+}
+
+static void
+isearch_set_selection (NautilusWindowSlot *slot,
+ NautilusFile *file)
+{
+ GList *list = NULL;
+ NautilusWindowSlotPrivate *priv;
+
+ list = g_list_append (list, file);
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ priv->isearch_selected_file = file;
+ nautilus_view_set_selection (priv->content_view, list);
+ g_list_free (list);
+}
+
+static void
+isearch_enable_changed (gpointer callback_data)
+{
+ NautilusWindowSlot *slot;
+ gboolean enable;
+ NautilusWindowSlotPrivate *priv;
+
+ slot = NAUTILUS_WINDOW_SLOT (callback_data);
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ enable =
+ g_settings_get_boolean (nautilus_preferences,
+ NAUTILUS_PREFERENCES_ENABLE_INTERACTIVE_SEARCH);
+
+ if (enable != priv->isearch_enable)
+ {
+ if (!enable)
+ isearch_dispose (slot);
+
+ priv->isearch_enable = enable;
+ }
+}
+
+static void
+isearch_dispose (NautilusWindowSlot *slot)
+{
+ NautilusWindowSlotPrivate *priv;
+
+ priv = nautilus_window_slot_get_instance_private (slot);
+
+ if (!priv->isearch_enable)
+ return;
+
+ if (priv->isearch_entry_changed_id != 0)
+ {
+ g_signal_handler_disconnect (G_OBJECT (priv->isearch_entry),
+ priv->isearch_entry_changed_id);
+ priv->isearch_entry_changed_id = 0;
+ }
+ if (priv->isearch_timeout_id != 0)
+ {
+ g_source_remove (priv->isearch_timeout_id);
+ priv->isearch_timeout_id = 0;
+ }
+ if (priv->isearch_window != NULL)
+ {
+ gtk_widget_destroy (priv->isearch_window);
+ priv->isearch_window = NULL;
+ priv->isearch_entry = NULL;
+ }
+}
diff --git a/src/resources/ui/nautilus-preferences-window.ui b/src/resources/ui/nautilus-preferences-window.ui
index 96a2be8..b1cb7c3 100644
--- a/src/resources/ui/nautilus-preferences-window.ui
+++ b/src/resources/ui/nautilus-preferences-window.ui
@@ -802,6 +802,56 @@ More information will appear when zooming closer.</property>
<property name="position">4</property>
</packing>
</child>
+
+ <!-- Typeahead checkbutton BEGIN -->
+ <child>
+ <object class="GtkBox" id="vbox100">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label117">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Interactive search (typeahead)</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="interactive_search_checkbutton">
+ <property name="label" translatable="yes">Enable interactive search</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <!-- Typeahead checkbutton END -->
+
</object>
<packing>
<property name="position">1</property>
From cfc221d511b0c9416ff9dbf4bbd7123c7bbdc60c Mon Sep 17 00:00:00 2001
From: Thomas Martitz <kugel@rockbox.org>
Date: Sat, 29 Aug 2015 00:16:27 +0200
Subject: [PATCH] filechooser: restore pre-3.16 type-ahead-find with setting
(off by default)
The previous type-ahead-find was loved by many people, so removing it without
possibility to restore was not nice to them. This commit re-introduces it again
with a default-off seting so that the new default search-as-you-type is
untouched, for those who don't consider the new search a viable replacement.
---
gtk/gtkfilechooserwidget.c | 35 +++++++++++++++++++++++++---
gtk/org.gtk.Settings.FileChooser.gschema.xml | 7 ++++++
2 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c
index 94d051f..8d41775 100644
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -354,6 +354,7 @@ struct _GtkFileChooserWidgetPrivate {
guint show_size_column : 1;
guint create_folders : 1;
guint auto_selecting_first_row : 1;
+ guint use_type_ahead_find : 1;
};
#define MAX_LOADING_TIME 500
@@ -589,6 +590,7 @@ static void clear_model_cache (GtkFileChooserWidget *impl,
static void set_model_filter (GtkFileChooserWidget *impl,
GtkFileFilter *filter);
+static void set_sort_column (GtkFileChooserWidget *impl);
G_DEFINE_TYPE_WITH_CODE (GtkFileChooserWidget, gtk_file_chooser_widget, GTK_TYPE_BOX,
@@ -2437,7 +2439,11 @@ file_list_set_sort_column_ids (GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = impl->priv;
- gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), -1);
+ fprintf(stderr, "file_list_set_sort_column_ids use-type-ahead: %d\n", priv->use_type_ahead_find);
+ if (priv->use_type_ahead_find)
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), MODEL_COL_NAME);
+ else
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), -1);
gtk_tree_view_column_set_sort_column_id (priv->list_name_column, MODEL_COL_NAME);
gtk_tree_view_column_set_sort_column_id (priv->list_time_column, MODEL_COL_TIME);
@@ -3693,6 +3699,16 @@ change_icon_theme (GtkFileChooserWidget *impl)
profile_end ("end", NULL);
}
+static void
+change_type_ahead (GtkFileChooserWidget *impl, gboolean value)
+{
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+ priv->use_type_ahead_find = value;
+
+ file_list_set_sort_column_ids(impl);
+ set_sort_column(impl);
+}
+
/* Callback used when a GtkSettings value changes */
static void
settings_notify_cb (GObject *object,
@@ -3700,6 +3716,7 @@ settings_notify_cb (GObject *object,
GtkFileChooserWidget *impl)
{
const char *name;
+ gboolean value;
profile_start ("start", NULL);
@@ -3707,7 +3724,11 @@ settings_notify_cb (GObject *object,
if (strcmp (name, "gtk-icon-theme-name") == 0)
change_icon_theme (impl);
-
+ if (strcmp (name, "use-type-ahead") == 0)
+ {
+ g_object_get (object, name, &value, NULL);
+ change_type_ahead (impl, value);
+ }
profile_end ("end", NULL);
}
@@ -3806,6 +3827,7 @@ settings_load (GtkFileChooserWidget *impl)
gboolean show_hidden;
gboolean show_size_column;
gboolean sort_directories_first;
+ gboolean use_type_ahead_find;
DateFormat date_format;
gint sort_column;
GtkSortType sort_order;
@@ -3823,10 +3845,12 @@ settings_load (GtkFileChooserWidget *impl)
startup_mode = g_settings_get_enum (settings, SETTINGS_KEY_STARTUP_MODE);
sort_directories_first = g_settings_get_boolean (settings, SETTINGS_KEY_SORT_DIRECTORIES_FIRST);
date_format = g_settings_get_enum (settings, SETTINGS_KEY_DATE_FORMAT);
+ use_type_ahead_find = g_settings_get_boolean (settings, "use-type-ahead");
if (!priv->show_hidden_set)
set_show_hidden (impl, show_hidden);
priv->show_size_column = show_size_column;
+ priv->use_type_ahead_find = use_type_ahead_find;
gtk_tree_view_column_set_visible (priv->list_size_column, show_size_column);
priv->sort_column = sort_column;
@@ -4332,6 +4356,7 @@ load_set_model (GtkFileChooserWidget *impl)
gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view),
GTK_TREE_MODEL (priv->browse_files_model));
update_columns (impl, FALSE, _("Modified"));
+ g_object_set(priv->browse_files_tree_view, "enable-search", priv->use_type_ahead_find, NULL);
file_list_set_sort_column_ids (impl);
set_sort_column (impl);
profile_msg (" gtk_tree_view_set_model end", NULL);
@@ -7412,7 +7437,10 @@ recent_idle_cleanup (gpointer data)
gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view),
GTK_TREE_MODEL (priv->recent_model));
- gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), -1);
+ if (priv->use_type_ahead_find)
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), MODEL_COL_NAME);
+ else
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), -1);
gtk_tree_view_column_set_sort_column_id (priv->list_name_column, -1);
gtk_tree_view_column_set_sort_column_id (priv->list_time_column, -1);
@@ -8556,6 +8584,7 @@ gtk_file_chooser_widget_init (GtkFileChooserWidget *impl)
priv->recent_manager = gtk_recent_manager_get_default ();
priv->create_folders = TRUE;
priv->auto_selecting_first_row = FALSE;
+ priv->use_type_ahead_find = FALSE;
/* Ensure GTK+ private types used by the template
* definition before calling gtk_widget_init_template()
diff --git a/gtk/org.gtk.Settings.FileChooser.gschema.xml b/gtk/org.gtk.Settings.FileChooser.gschema.xml
index c3753f2..bdba1b0 100644
--- a/gtk/org.gtk.Settings.FileChooser.gschema.xml
+++ b/gtk/org.gtk.Settings.FileChooser.gschema.xml
@@ -148,6 +148,13 @@
The amount of detail to show in the Modified column.
</description>
</key>
+ <key name="use-type-ahead" type='b'>
+ <default>false</default>
+ <summary>Enable type-ahead find</summary>
+ <description>
+ Whether to use new search method or previous type-ahead find.
+ </description>
+ </key>
</schema>
</schemalist>
--
2.5.0
@darthoctopus
Copy link
Author

This is based on jthurner's modification of Daniel Wyatt's original patch.

@ElectricPrism
Copy link

Is this patch meant to be applied against 3.18 from git.gnome.org?
https://git.gnome.org/browse/nautilus/snapshot/nautilus-3.18.0.zip

Or is it meant to be applied against nautilus-git on github?

Thanks :)

@darthoctopus
Copy link
Author

as far as I can tell it applies successfully to both (for now)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment