Re: [Patch] Interactive search (aka typeahead) enhancement patch



I attach new patch with all commented issues fixed, the patch is also in
bugzilla[1].

[1] http://bugzilla.gnome.org/show_bug.cgi?id=328725

Comments about the patch:

Alexander Larsson wrote:
> Sometimes when i switch from icon to list view the "normal" typeahead
> seems to only match at the start of the name.

 Fixed, now the search_equal_func is set in the listview initialization.

> Comments on the code:
> 
> @@ -3861,8 +3864,7 @@ nautilus_icon_container_search_iter (Nau
>  			continue;
>  		}
>  		
> -		if (strncmp (case_normalized_key, case_normalized_name,
> -			     strlen (case_normalized_key)) == 0) {
> +		if (strcasestr (case_normalized_name, case_normalized_key)) {
>  			count++;
>  		}
> 
> 
> This is already case insensitive due to the case normalization!
> strcasestr is a locale-specific function that is absolutely wrong to use
> here.

Now I use strstr after a g_utf8_normalize and g_utf8_casefold as this is
a sane way to do this, that is what original gtktreeview search_func
does, also pointed by this mail[1], for the listview I copied that
function and only changed it to strstr instead of strncmp.

[1]
http://mail.gnome.org/archives/gtk-app-devel-list/2003-March/msg00416.html

>  void
> +action_interactive_search_spatial_callback (GtkAction *action,
> +					    gpointer   user_data)
> 
> You shouldn't special case views like this in the generic code. If you
> need to, add new view methods.

I reformatted the patch so now we only call
nautilus_view_start_interactive_search() from the spatial callback.

> +  { "Interactive Search", GTK_STOCK_FIND, N_("_Find in this folder"),
> +    "<control>G", N_("Find files in this folder"),
> +    G_CALLBACK (action_interactive_search_spatial_callback) },
> 
> control G is typically "find next". I'm not sure if its the best to use
> in this case.

  Now has CTRL-Z as seems is not used in nautilus.
Index: libnautilus-private/nautilus-icon-container.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-icon-container.c,v
retrieving revision 1.406
diff -p -u -r1.406 nautilus-icon-container.c
--- libnautilus-private/nautilus-icon-container.c	12 Dec 2005 16:59:10 -0000	1.406
+++ libnautilus-private/nautilus-icon-container.c	26 Jan 2006 01:01:33 -0000
@@ -3861,8 +3861,7 @@ nautilus_icon_container_search_iter (Nau
 			continue;
 		}
 		
-		if (strncmp (case_normalized_key, case_normalized_name,
-			     strlen (case_normalized_key)) == 0) {
+		if (strstr (case_normalized_name, case_normalized_key)) {
 			count++;
 		}
 
Index: libnautilus-private/nautilus-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-view.c,v
retrieving revision 1.3
diff -p -u -r1.3 nautilus-view.c
--- libnautilus-private/nautilus-view.c	17 May 2005 13:27:29 -0000	1.3
+++ libnautilus-private/nautilus-view.c	26 Jan 2006 01:01:34 -0000
@@ -260,3 +260,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.3
diff -p -u -r1.3 nautilus-view.h
--- libnautilus-private/nautilus-view.h	17 May 2005 13:27:29 -0000	1.3
+++ libnautilus-private/nautilus-view.h	26 Jan 2006 01:01:34 -0000
@@ -115,6 +115,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);
@@ -151,6 +154,7 @@ gboolean          nautilus_view_can_zoom
 NautilusZoomLevel nautilus_view_get_zoom_level             (NautilusView      *view);
 void              nautilus_view_pop_up_location_context_menu (NautilusView    *view,
 							      GdkEventButton  *event);
+void              nautilus_view_start_interactive_search   (NautilusView      *view);
 
 G_END_DECLS
 
Index: src/nautilus-spatial-window-ui.xml
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-spatial-window-ui.xml,v
retrieving revision 1.17
diff -p -u -r1.17 nautilus-spatial-window-ui.xml
--- src/nautilus-spatial-window-ui.xml	15 Dec 2005 14:25:58 -0000	1.17
+++ src/nautilus-spatial-window-ui.xml	26 Jan 2006 01:01:34 -0000
@@ -10,6 +10,11 @@
 			<menuitem name="Close All Folders" action="Close All Folders"/>
 		</placeholder>
 	</menu>
+	<menu action="Edit">
+		<placeholder name="Select Items">
+			<menuitem name="Find" action="Interactive Search"/>
+		</placeholder>
+	</menu>
         <placeholder name="Other Menus">
 	        <menu action="Places">
 		      <menuitem name="Home" action="Home"/>
Index: src/nautilus-spatial-window.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-spatial-window.c,v
retrieving revision 1.456
diff -p -u -r1.456 nautilus-spatial-window.c
--- src/nautilus-spatial-window.c	16 Jan 2006 23:48:19 -0000	1.456
+++ src/nautilus-spatial-window.c	26 Jan 2006 01:01:35 -0000
@@ -319,6 +319,17 @@ action_close_all_folders_callback (GtkAc
 	nautilus_application_close_all_spatial_windows ();
 }
 
+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
 real_prompt_for_location (NautilusWindow *window,
 			  const char     *initial)
@@ -849,6 +860,9 @@ static const GtkActionEntry spatial_entr
   { "Search", "gtk-find", N_("_Search"), /* name, stock id, label */
     "<control>F", N_("Search for files"),
     G_CALLBACK (action_search_callback) },
+  { "Interactive Search", GTK_STOCK_FIND, N_("_Find in this folder"),
+    "<control>Z", N_("Find files in this folder"),
+    G_CALLBACK (action_interactive_search_spatial_callback) },
 };
 
 static void
Index: src/nautilus-spatial-window.h
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-spatial-window.h,v
retrieving revision 1.113
diff -p -u -r1.113 nautilus-spatial-window.h
--- src/nautilus-spatial-window.h	11 Jul 2005 10:23:57 -0000	1.113
+++ src/nautilus-spatial-window.h	26 Jan 2006 01:01:35 -0000
@@ -63,6 +63,8 @@ void             nautilus_spatial_window
 void             nautilus_spatial_window_save_show_hidden_files_mode	(NautilusSpatialWindow *window);
 void             nautilus_spatial_window_set_location_button		(NautilusSpatialWindow *window,
 									 const char            *location);
+void             action_interactive_search_spatial_callback		(GtkAction *action, 
+									 gpointer  user_data);
 
 
 #endif
Index: src/file-manager/fm-directory-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-directory-view.c,v
retrieving revision 1.733
diff -p -u -r1.733 fm-directory-view.c
--- src/file-manager/fm-directory-view.c	16 Jan 2006 09:14:33 -0000	1.733
+++ src/file-manager/fm-directory-view.c	26 Jan 2006 01:01:44 -0000
@@ -343,6 +343,7 @@ static void     load_directory          
 								NautilusDirectory    *directory);
 static void     fm_directory_view_merge_menus                  (FMDirectoryView      *view);
 static void     fm_directory_view_init_show_hidden_files       (FMDirectoryView      *view);
+static void     fm_directory_view_start_interactive_search     (FMDirectoryView      *view);
 static char *   file_name_from_uri                             (const char           *uri);
 static void     fm_directory_view_load_location                (NautilusView         *nautilus_view,
 								const char           *location);
@@ -444,6 +445,7 @@ EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_d
 EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, set_selection)
 EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, zoom_to_level)
 EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, get_zoom_level)
+EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, start_interactive_search)
 
 typedef struct {
 	GnomeVFSMimeApplication *application;
@@ -1875,6 +1877,7 @@ fm_directory_view_init_view_iface (Nauti
 	iface->get_zoom_level = (gpointer)fm_directory_view_get_zoom_level;
 
 	iface->pop_up_location_context_menu = (gpointer)fm_directory_view_pop_up_location_context_menu;
+	iface->start_interactive_search = (gpointer)fm_directory_view_start_interactive_search;
 }
 
 static void
@@ -7559,6 +7562,23 @@ fm_directory_view_pop_up_location_contex
 				      event);
 }
 
+/**
+ * fm_directory_view_start_interactive_search
+ *
+ * Pop up the interactive search box (aka typeahead).
+ * @view: FMDirectoryView of interest.
+ *
+ **/
+static void 
+fm_directory_view_start_interactive_search (FMDirectoryView *view)
+{
+	g_assert (FM_IS_DIRECTORY_VIEW (view));
+
+	EEL_CALL_METHOD
+	(FM_DIRECTORY_VIEW_CLASS, view,
+	start_interactive_search, (view));
+}
+
 static void
 schedule_update_menus (FMDirectoryView *view) 
 {
@@ -9736,7 +9756,8 @@ fm_directory_view_class_init (FMDirector
 	EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, set_selection);
 	EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, zoom_to_level);
 	EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, get_zoom_level);
-
+	EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, start_interactive_search);
+	
 	copied_files_atom = gdk_atom_intern ("x-special/gnome-copied-files", FALSE);
 	utf8_string_atom = gdk_atom_intern ("UTF8_STRING", FALSE);
 
Index: src/file-manager/fm-directory-view.h
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-directory-view.h,v
retrieving revision 1.143
diff -p -u -r1.143 fm-directory-view.h
--- src/file-manager/fm-directory-view.h	12 Dec 2005 16:59:11 -0000	1.143
+++ src/file-manager/fm-directory-view.h	26 Jan 2006 01:01:44 -0000
@@ -195,6 +195,9 @@ struct FMDirectoryViewClass {
          */
         void     (* reveal_selection)	 	(FMDirectoryView *view);
 
+	/* Pops up the interactive_search_dialog (aka typeahead) */
+        void     (* start_interactive_search)	(FMDirectoryView *view);
+
         /* get_background is a function pointer that subclasses must
          * override to return the EelBackground for this view.
          */
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 -p -u -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	26 Jan 2006 01:01:47 -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     (FMDirectoryView      *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,20 @@ icon_view_scroll_to_file (NautilusView *
 	}
 }
 
+static void
+fm_icon_view_start_interactive_search (FMDirectoryView *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)
@@ -2633,6 +2648,7 @@ fm_icon_view_class_init (FMIconViewClass
         fm_directory_view_class->text_attribute_names_changed = fm_icon_view_text_attribute_names_changed;
         fm_directory_view_class->update_menus = fm_icon_view_update_menus;
 	fm_directory_view_class->using_manual_layout = fm_icon_view_using_manual_layout;
+	fm_directory_view_class->start_interactive_search = fm_icon_view_start_interactive_search;
 
 	klass->clean_up = fm_icon_view_real_clean_up;
 	klass->supports_auto_layout = real_supports_auto_layout;
Index: src/file-manager/fm-list-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-list-view.c,v
retrieving revision 1.263
diff -p -u -r1.263 fm-list-view.c
--- src/file-manager/fm-list-view.c	12 Dec 2005 16:59:11 -0000	1.263
+++ src/file-manager/fm-list-view.c	26 Jan 2006 01:01:49 -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	   (FMDirectoryView   *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,80 @@ 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 = TRUE;
+  const gchar *str;
+  gchar *normalized_string;
+  gchar *normalized_key;
+  gchar *case_normalized_string = NULL;
+  gchar *case_normalized_key = NULL;
+  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)
+    {
+      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);
+
+  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 (FMDirectoryView *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)
@@ -2498,6 +2578,7 @@ fm_list_view_class_init (FMListViewClass
         fm_directory_view_class->emblems_changed = fm_list_view_emblems_changed;
 	fm_directory_view_class->end_file_changes = fm_list_view_end_file_changes;
 	fm_directory_view_class->using_manual_layout = fm_list_view_using_manual_layout;
+	fm_directory_view_class->start_interactive_search = fm_list_view_start_interactive_search;
 
 	eel_preferences_add_auto_enum (NAUTILUS_PREFERENCES_CLICK_POLICY,
 				       &click_policy_auto_value);
@@ -2538,6 +2619,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,
Index: src/file-manager/fm-list-view.h
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-list-view.h,v
retrieving revision 1.12
diff -p -u -r1.12 fm-list-view.h
--- src/file-manager/fm-list-view.h	22 Nov 2004 15:24:38 -0000	1.12
+++ src/file-manager/fm-list-view.h	26 Jan 2006 01:01:49 -0000
@@ -46,6 +46,9 @@ typedef struct {
 
 typedef struct {
 	FMDirectoryViewClass parent_class;
+
+	/* Pops up the interactive search dialog */
+        /* void    (* start_interactive_search)       (FMListView *view); */
 } FMListViewClass;
 
 GType fm_list_view_get_type (void);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]