Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/data/org.gnome.nautilus.gschema.xml b/data/org.gnome.nautilus.gschema.xml
- index e162ebb42..b64e526a0 100644
- --- a/data/org.gnome.nautilus.gschema.xml
- +++ b/data/org.gnome.nautilus.gschema.xml
- @@ -207,6 +207,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 7e52f6c77..b5b761da1 100644
- --- a/src/nautilus-global-preferences.h
- +++ b/src/nautilus-global-preferences.h
- @@ -164,6 +164,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 0d2f54fb5..9f9a1692f 100644
- --- a/src/nautilus-list-view.c
- +++ b/src/nautilus-list-view.c
- @@ -2706,6 +2706,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);
- @@ -2722,10 +2723,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);
- }
- @@ -3600,3 +3613,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 f77543100..bbcb565d7 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 8c4f981c0..b545fc3ec 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 \
- @@ -492,6 +494,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 c5c94e103..67a6fd0a9 100644
- --- a/src/nautilus-window-slot.c
- +++ b/src/nautilus-window-slot.c
- @@ -122,6 +122,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);
- @@ -153,6 +164,98 @@ static void trash_state_changed_cb (NautilusTrashMonitor *monitor,
- gboolean is_empty,
- gpointer user_data);
- +
- +/* 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)
- @@ -569,21 +672,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)
- {
- @@ -612,10 +780,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);
- }
- @@ -908,9 +1085,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"
- @@ -2687,6 +2885,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);
- @@ -2777,6 +2976,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;
- @@ -3198,3 +3398,792 @@ 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);
- + 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);
- +
- + 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 96a2be860..b1cb7c3d0 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>
- --
- 2.12.2
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement