Re: [Patch] Interactive search (aka typeahead) enhancement patch
- From: Nelson Benítez <gnel cenobioracing com>
- To: Luis Villa <luis villa gmail com>
- Cc: nautilus-list gnome org, Alexander Larsson <alexl redhat com>, "release-team gnome org" <release-team gnome org>
- Subject: Re: [Patch] Interactive search (aka typeahead) enhancement patch
- Date: Tue, 07 Feb 2006 00:06:53 +0000
Luis Villa wrote:
> On 2/6/06, Federico Mena Quintero <federico ximian com> wrote:
>
>>On Mon, 2006-02-06 at 19:06 +0100, Alexander Larsson wrote:
>>
>>>>FYI, we got a lot of complaints for GtkFileChooser when typeahead
>>>>matched strings in the middle of filenames, not just in the beginning.
>>>>You may want to reconsider this :)
>>>
>>>What exactly was the complaints?
>>>Apart from the standard "you changed something, gnome sucks!".
>>
>>People assumed that typing the first few characters of a filename would
>>make the file chooser jump to the first filename in the list that
>>started with those characters. Instead, they would jump to a filename
>>they didn't expect: type "re" and it jumps to "andrea.txt", instead of
>>"resume.txt", which is what they expected.
>
>
> Isn't the obviously correct behavior that it only jumps to andrea.txt
> if re*.* does not exist?
Good point, that is a more complete behaviour imho, that is, to search
firstly at beginning of word and fallback to middle of the word if the
former didn't find anything. So in the example it'll first match
"resume.txt" and then you type one more char "rea" and will match
"andrea.txt".
I attach alex's patch with the said modification to the icon view
typeahead (changes are only in nautilus-icon-container.c), also I could
implement it within the existent loop so no performance penalty added.
Unfortunately we can't change the list view to get this behaviour as we
use the built-in gtktreeview typeahead, but I think that gtktreeview
itself should get this behaviour by default as it's just the current one
plus a fallback to search in middle-of-word if beginning-of-word didn't
find anything...
Index: libnautilus-private/nautilus-icon-container.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-icon-container.c,v
retrieving revision 1.407
diff -u -p -r1.407 nautilus-icon-container.c
--- libnautilus-private/nautilus-icon-container.c 29 Jan 2006 21:48:57 -0000 1.407
+++ libnautilus-private/nautilus-icon-container.c 6 Feb 2006 14:37:10 -0000
@@ -3819,8 +3822,11 @@ nautilus_icon_container_search_iter (Nau
{
GList *p;
NautilusIcon *icon;
+ NautilusIcon *icon_strstr;
+ gboolean strstr_matched;
const char *name;
int count;
+ int count2;
char *normalized_key, *case_normalized_key;
char *normalized_name, *case_normalized_name;
@@ -3838,7 +3844,10 @@ nautilus_icon_container_search_iter (Nau
}
icon = NULL;
+ icon_strstr = NULL;
+ strstr_matched = FALSE;
count = 0;
+ count2 = 0;
for (p = container->details->icons; p != NULL && count != n; p = p->next) {
icon = p->data;
name = nautilus_icon_canvas_item_get_editable_text (icon->item);
@@ -3866,6 +3875,16 @@ nautilus_icon_container_search_iter (Nau
count++;
}
+ if (! strstr_matched) {
+ if (strstr (case_normalized_name, case_normalized_key)) {
+ count2++;
+ if (count2 == n) {
+ icon_strstr = p->data;
+ strstr_matched = TRUE;
+ }
+ }
+ }
+
g_free (case_normalized_name);
}
@@ -3876,6 +3895,14 @@ nautilus_icon_container_search_iter (Nau
g_signal_emit (container, signals[SELECTION_CHANGED], 0);
}
schedule_keyboard_icon_reveal (container, icon);
+
+ return TRUE;
+ }
+ else if (strstr_matched) {
+ if (select_one_unselect_others (container, icon_strstr)) {
+ g_signal_emit (container, signals[SELECTION_CHANGED], 0);
+ }
+ schedule_keyboard_icon_reveal (container, icon_strstr);
return TRUE;
}
Index: libnautilus-private/nautilus-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-view.c,v
retrieving revision 1.4
diff -u -p -r1.4 nautilus-view.c
--- libnautilus-private/nautilus-view.c 31 Jan 2006 00:23:54 -0000 1.4
+++ libnautilus-private/nautilus-view.c 6 Feb 2006 14:37:11 -0000
@@ -270,3 +270,13 @@ nautilus_view_pop_up_location_context_me
(* NAUTILUS_VIEW_GET_IFACE (view)->pop_up_location_context_menu) (view, event);
}
}
+
+void
+nautilus_view_start_interactive_search (NautilusView *view)
+{
+ g_return_if_fail (NAUTILUS_IS_VIEW (view));
+
+ if (NAUTILUS_VIEW_GET_IFACE (view)->start_interactive_search != NULL) {
+ (* NAUTILUS_VIEW_GET_IFACE (view)->start_interactive_search) (view);
+ }
+}
Index: libnautilus-private/nautilus-view.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-view.h,v
retrieving revision 1.4
diff -u -p -r1.4 nautilus-view.h
--- libnautilus-private/nautilus-view.h 31 Jan 2006 00:23:54 -0000 1.4
+++ libnautilus-private/nautilus-view.h 6 Feb 2006 14:37:11 -0000
@@ -117,6 +117,9 @@ struct _NautilusViewIface
void (* pop_up_location_context_menu) (NautilusView *view,
GdkEventButton *event);
+ /* Request popup the interactive search dialog (aka typeahead) */
+ void (* start_interactive_search) (NautilusView *view);
+
/* Padding for future expansion */
void (*_reserved1) (void);
void (*_reserved2) (void);
@@ -124,7 +127,6 @@ struct _NautilusViewIface
void (*_reserved4) (void);
void (*_reserved5) (void);
void (*_reserved6) (void);
- void (*_reserved7) (void);
};
GType nautilus_view_get_type (void);
@@ -154,6 +156,8 @@ NautilusZoomLevel nautilus_view_get_zoom
void nautilus_view_pop_up_location_context_menu (NautilusView *view,
GdkEventButton *event);
void nautilus_view_grab_focus (NautilusView *view);
+void nautilus_view_start_interactive_search (NautilusView *view);
+
G_END_DECLS
Index: src/nautilus-navigation-window-ui.xml
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-navigation-window-ui.xml,v
retrieving revision 1.14
diff -u -p -r1.14 nautilus-navigation-window-ui.xml
--- src/nautilus-navigation-window-ui.xml 15 Dec 2005 14:25:58 -0000 1.14
+++ src/nautilus-navigation-window-ui.xml 6 Feb 2006 14:37:11 -0000
@@ -17,6 +17,11 @@
<menuitem name="Show Hide Statusbar" action="Show Hide Statusbar"/>
</placeholder>
</menu>
+ <menu action="Edit">
+ <placeholder name="Select Items">
+ <menuitem name="Find" action="Interactive Search"/>
+ </placeholder>
+ </menu>
<placeholder name="Other Menus">
<menu action="Go">
<placeholder name="Navigation Items">
Index: src/nautilus-window-menus.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-window-menus.c,v
retrieving revision 1.293
diff -u -p -r1.293 nautilus-window-menus.c
--- src/nautilus-window-menus.c 15 Dec 2005 14:25:58 -0000 1.293
+++ src/nautilus-window-menus.c 6 Feb 2006 14:37:11 -0000
@@ -346,6 +346,16 @@ action_zoom_normal_callback (GtkAction *
}
static void
+action_interactive_search_spatial_callback (GtkAction *action,
+ gpointer user_data)
+{
+ NautilusWindow *window;
+ window = NAUTILUS_WINDOW (user_data);
+
+ nautilus_view_start_interactive_search (window->content_view);
+}
+
+static void
preferences_respond_callback (GtkDialog *dialog,
gint response_id)
{
@@ -702,6 +712,9 @@ static const GtkActionEntry main_entries
N_("CD/_DVD Creator"), NULL, /* label, accelerator */
N_("Go to the CD/DVD Creator"), /* tooltip */
G_CALLBACK (action_go_to_burn_cd_callback) },
+ { "Interactive Search", GTK_STOCK_FIND, N_("_Find in this folder"),
+ "<control>J", N_("Find files in this folder"),
+ G_CALLBACK (action_interactive_search_spatial_callback) },
};
/**
Index: src/file-manager/fm-icon-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-icon-view.c,v
retrieving revision 1.318
diff -u -p -r1.318 fm-icon-view.c
--- src/file-manager/fm-icon-view.c 12 Dec 2005 16:59:11 -0000 1.318
+++ src/file-manager/fm-icon-view.c 6 Feb 2006 14:37:11 -0000
@@ -183,6 +183,7 @@ static void fm_icon_view
static void fm_icon_view_set_directory_tighter_layout (FMIconView *icon_view,
NautilusFile *file,
gboolean tighter_layout);
+static void fm_icon_view_start_interactive_search (NautilusView *view);
static const SortCriterion *get_sort_criterion_by_sort_type (NautilusFileSortType sort_type);
static void set_sort_criterion_by_sort_type (FMIconView *icon_view,
NautilusFileSortType sort_type);
@@ -2584,6 +2585,21 @@ icon_view_scroll_to_file (NautilusView *
}
}
+static void
+fm_icon_view_start_interactive_search (NautilusView *view)
+{
+ NautilusIconContainer *icon_container;
+ gboolean ret;
+
+ icon_container = NAUTILUS_ICON_CONTAINER (GTK_BIN (FM_ICON_VIEW (view))->child);
+ if (!GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (icon_container))) {
+ gtk_widget_grab_focus (GTK_WIDGET (icon_container));
+ }
+
+ ret = EEL_CALL_METHOD_WITH_RETURN_VALUE
+ (NAUTILUS_ICON_CONTAINER_CLASS, icon_container,
+ start_interactive_search, (icon_container));
+}
static void
fm_icon_view_class_init (FMIconViewClass *klass)
@@ -2666,6 +2682,7 @@ fm_icon_view_iface_init (NautilusViewIfa
iface->get_first_visible_file = icon_view_get_first_visible_file;
iface->scroll_to_file = icon_view_scroll_to_file;
iface->get_title = NULL;
+ iface->start_interactive_search = fm_icon_view_start_interactive_search;
}
static void
Index: src/file-manager/fm-list-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-list-view.c,v
retrieving revision 1.265
diff -u -p -r1.265 fm-list-view.c
--- src/file-manager/fm-list-view.c 31 Jan 2006 00:23:55 -0000 1.265
+++ src/file-manager/fm-list-view.c 6 Feb 2006 14:37:11 -0000
@@ -135,6 +135,12 @@ static NautilusZoomLevel default_
static GList * default_visible_columns_auto_value;
static GList * default_column_order_auto_value;
+static gboolean interactive_search_equal_func (GtkTreeModel *model,
+ gint column,
+ const gchar *key,
+ GtkTreeIter *iter,
+ gpointer search_data);
+static void fm_list_view_start_interactive_search (NautilusView *view);
static GList *fm_list_view_get_selection (FMDirectoryView *view);
static GList *fm_list_view_get_selection_for_file_transfer (FMDirectoryView *view);
static void fm_list_view_set_zoom_level (FMListView *view,
@@ -236,6 +242,82 @@ button_event_modifies_selection (GdkEven
return (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) != 0;
}
+static gboolean
+interactive_search_equal_func (GtkTreeModel *model,
+ gint column,
+ const gchar *key,
+ GtkTreeIter *iter,
+ gpointer search_data)
+{
+ gboolean retval;
+ const gchar *str;
+ gchar *normalized_string;
+ gchar *normalized_key;
+ gchar *case_normalized_string;
+ gchar *case_normalized_key;
+ GValue value = {0,};
+ GValue transformed = {0,};
+
+ gtk_tree_model_get_value (model, iter, column, &value);
+
+ g_value_init (&transformed, G_TYPE_STRING);
+
+ if (!g_value_transform (&value, &transformed)) {
+ g_value_unset (&value);
+ return TRUE;
+ }
+
+ g_value_unset (&value);
+
+ str = g_value_get_string (&transformed);
+ if (str == NULL) {
+ g_value_unset (&transformed);
+ return TRUE;
+ }
+
+ normalized_string = g_utf8_normalize (str, -1, G_NORMALIZE_ALL);
+ normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
+
+ case_normalized_string = NULL;
+ case_normalized_key = NULL;
+ retval = TRUE;
+ if (normalized_string && normalized_key) {
+ case_normalized_string = g_utf8_casefold (normalized_string, -1);
+ case_normalized_key = g_utf8_casefold (normalized_key, -1);
+
+ if (strstr (case_normalized_string, case_normalized_key) != NULL) {
+ retval = FALSE;
+ }
+ }
+
+ g_value_unset (&transformed);
+ g_free (normalized_key);
+ g_free (normalized_string);
+ g_free (case_normalized_key);
+ g_free (case_normalized_string);
+
+ return retval;
+}
+
+static void
+fm_list_view_start_interactive_search (NautilusView *view)
+{
+ GtkTreeView *tv;
+ gboolean ret;
+ FMListView *listview;
+
+ listview = FM_LIST_VIEW (view);
+ tv = listview->details->tree_view;
+
+ if (!GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (tv))) {
+ gtk_widget_grab_focus (GTK_WIDGET (tv));
+ }
+
+ ret = EEL_CALL_METHOD_WITH_RETURN_VALUE
+ (GTK_TREE_VIEW_CLASS, tv,
+ start_interactive_search, (tv));
+}
+
static void
fm_list_view_did_not_drag (FMListView *view,
GdkEventButton *event)
@@ -2543,6 +2625,7 @@ fm_list_view_iface_init (NautilusViewIfa
iface->scroll_to_file = list_view_scroll_to_file;
iface->get_title = NULL;
iface->grab_focus = fm_list_view_grab_focus;
+ iface->start_interactive_search = fm_list_view_start_interactive_search;
}
@@ -2552,6 +2635,10 @@ fm_list_view_init (FMListView *list_view
list_view->details = g_new0 (FMListViewDetails, 1);
create_and_set_up_tree_view (list_view);
+
+ gtk_tree_view_set_search_equal_func (list_view->details->tree_view,
+ interactive_search_equal_func,
+ NULL, NULL);
eel_preferences_add_callback_while_alive (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_SORT_ORDER,
default_sort_order_changed_callback,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]