changeset 2817:e6f95baec8b5

Fix #624: Filter files by shell or regular expression pattern https://github.com/BestImageViewer/geeqie/issues/624 An option on Select/Show File Filter (or the toolbar) to provide regular expression file-filtering of the currently displayed folder.
author Colin Clark <colin.clark@cclark.uk>
date Wed, 15 Aug 2018 19:43:06 +0100
parents e993f52f08a2
children f1c975235feb
files doc/docbook/GuideMainWindowFilePane.xml src/filedata.c src/filedata.h src/icons/Makefile.am src/icons/icon_file_filter.png src/layout.c src/layout.h src/layout_util.c src/layout_util.h src/options.c src/pixbuf_util.c src/pixbuf_util.h src/toolbar.c src/typedefs.h src/view_file.h src/view_file/view_file.c src/view_file/view_file_icon.c src/view_file/view_file_list.c web/help/GuideMainWindowFilePane.html
diffstat 19 files changed, 276 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/doc/docbook/GuideMainWindowFilePane.xml	Tue Aug 14 21:28:02 2018 +0100
+++ b/doc/docbook/GuideMainWindowFilePane.xml	Wed Aug 15 19:43:06 2018 +0100
@@ -57,6 +57,26 @@
     </para>
     <para />
   </section>
+  <section id="Filefilter">
+    <title id="titleFilefilter">File Filter</title>
+    <para>
+      A filter box can be opened by selecting
+      <emphasis role="bold">Show File Filter</emphasis>
+      from the View menu.
+    </para>
+    <para>
+      Characters you type into this box will be used for pattern matching to select the files displayed.
+      <link linkend="GuideReferencePCRE">Regular expressions</link>
+      are used in this field.
+      <para />
+      For basic pattern matching "JPG" will match any filename containing those characters.
+      <para />
+      To make a case-insensitive search, use "(?i)JPG"
+      <para />
+      If you type a newline, the text will be saved in the dropdown box list. The last 10 items are saved.
+    </para>
+    <para />
+  </section>
   <section id="Multipleselection">
     <title>Multiple selection</title>
     <para>It is possible to select more than one image from the file pane. Multiple files can be selected with several methods:</para>
--- a/src/filedata.c	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/filedata.c	Wed Aug 15 19:43:06 2018 +0100
@@ -1817,6 +1817,33 @@
 	return list;
 }
 
+gboolean file_data_filter_file_filter(FileData *fd, GRegex *filter)
+{
+	return g_regex_match(filter, fd->name, 0, NULL);
+}
+
+GList *file_data_filter_file_filter_list(GList *list, GRegex *filter)
+{
+	GList *work;
+
+	work = list;
+	while (work)
+		{
+		FileData *fd = work->data;
+		GList *link = work;
+		work = work->next;
+
+		if (!file_data_filter_file_filter(fd, filter))
+			{
+			list = g_list_remove_link(list, link);
+			file_data_unref(fd);
+			g_list_free(link);
+			}
+		}
+
+	return list;
+}
+
 static void file_data_notify_mark_func(gpointer key, gpointer value, gpointer user_data)
 {
 	FileData *fd = value;
--- a/src/filedata.h	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/filedata.h	Wed Aug 15 19:43:06 2018 +0100
@@ -99,6 +99,9 @@
 gboolean file_data_filter_marks(FileData *fd, guint filter);
 GList *file_data_filter_marks_list(GList *list, guint filter);
 
+gboolean file_data_filter_file_filter(FileData *fd, GRegex *filter);
+GList *file_data_filter_file_filter_list(GList *list, GRegex *filter);
+
 gint file_data_get_user_orientation(FileData *fd);
 void file_data_set_user_orientation(FileData *fd, gint value);
 
--- a/src/icons/Makefile.am	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/icons/Makefile.am	Wed Aug 15 19:43:06 2018 +0100
@@ -39,7 +39,8 @@
 	icon_select_all.png \
 	icon_select_none.png \
 	icon_select_invert.png \
-	icon_select_rectangle.png
+	icon_select_rectangle.png \
+	icon_file_filter.png
 
 
 ICONS_INLINE_PAIRS = \
@@ -78,7 +79,8 @@
 	icon_select_all	$(srcdir)/icon_select_all.png \
 	icon_select_none	$(srcdir)/icon_select_none.png \
 	icon_select_invert	$(srcdir)/icon_select_invert.png \
-	icon_select_rectangle	$(srcdir)/icon_select_rectangle.png
+	icon_select_rectangle	$(srcdir)/icon_select_rectangle.png \
+	icon_file_filter	$(srcdir)/icon_file_filter.png
 
 icons_inline.h: $(ICONS_INLINE) Makefile.in
 	@sh -ec "echo '/* Auto generated file, do not edit */'; echo; \
Binary file src/icons/icon_file_filter.png has changed
--- a/src/layout.c	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/layout.c	Wed Aug 15 19:43:06 2018 +0100
@@ -862,6 +862,11 @@
 	if (lw->vf) vf_thumb_set(lw->vf, lw->options.show_thumbnails);
 }
 
+static void layout_list_sync_file_filter(LayoutWindow *lw)
+{
+	if (lw->vf) vf_file_filter_set(lw->vf, lw->options.show_file_filter);
+}
+
 static GtkWidget *layout_list_new(LayoutWindow *lw)
 {
 	lw->vf = vf_new(lw->options.file_view_type, NULL);
@@ -873,6 +878,7 @@
 	vf_marks_set(lw->vf, lw->options.show_marks);
 
 	layout_list_sync_thumb(lw);
+	layout_list_sync_file_filter(lw);
 
 	return lw->vf->widget;
 }
@@ -1178,6 +1184,18 @@
 	layout_list_sync_thumb(lw);
 }
 
+void layout_file_filter_set(LayoutWindow *lw, gboolean enable)
+{
+	if (!layout_valid(&lw)) return;
+
+	if (lw->options.show_file_filter == enable) return;
+
+	lw->options.show_file_filter = enable;
+
+	layout_util_sync_file_filter(lw);
+	layout_list_sync_file_filter(lw);
+}
+
 void layout_marks_set(LayoutWindow *lw, gboolean enable)
 {
 	if (!layout_valid(&lw)) return;
@@ -2476,6 +2494,7 @@
 	WRITE_NL(); WRITE_UINT(*layout, dir_view_type);
 	WRITE_NL(); WRITE_UINT(*layout, file_view_type);
 	WRITE_NL(); WRITE_BOOL(*layout, show_marks);
+	WRITE_NL(); WRITE_BOOL(*layout, show_file_filter);
 	WRITE_NL(); WRITE_BOOL(*layout, show_thumbnails);
 	WRITE_NL(); WRITE_BOOL(*layout, show_directory_date);
 	WRITE_NL(); WRITE_CHAR(*layout, home_path);
@@ -2565,6 +2584,7 @@
 		if (READ_UINT(*layout, dir_view_type)) continue;
 		if (READ_UINT(*layout, file_view_type)) continue;
 		if (READ_BOOL(*layout, show_marks)) continue;
+		if (READ_BOOL(*layout, show_file_filter)) continue;
 		if (READ_BOOL(*layout, show_thumbnails)) continue;
 		if (READ_BOOL(*layout, show_directory_date)) continue;
 		if (READ_CHAR(*layout, home_path)) continue;
--- a/src/layout.h	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/layout.h	Wed Aug 15 19:43:06 2018 +0100
@@ -89,6 +89,8 @@
 void layout_marks_set(LayoutWindow *lw, gboolean enable);
 gboolean layout_marks_get(LayoutWindow *lw);
 
+void layout_file_filter_set(LayoutWindow *lw, gboolean enable);
+
 void layout_sort_set(LayoutWindow *lw, SortType type, gboolean ascend);
 gboolean layout_sort_get(LayoutWindow *lw, SortType *type, gboolean *ascend);
 
--- a/src/layout_util.c	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/layout_util.c	Wed Aug 15 19:43:06 2018 +0100
@@ -117,6 +117,15 @@
 			return TRUE;
 			}
 		}
+
+	if (lw->vf->file_filter_combo && gtk_widget_has_focus(gtk_bin_get_child(GTK_BIN(lw->vf->file_filter_combo))))
+		{
+		if (gtk_widget_event(gtk_bin_get_child(GTK_BIN(lw->vf->file_filter_combo)), (GdkEvent *)event))
+			{
+			return TRUE;
+			}
+		}
+
 	if (lw->vd && lw->options.dir_view_type == DIRVIEW_TREE && gtk_widget_has_focus(lw->vd->view) &&
 	    !layout_key_match(event->keyval) &&
 	    gtk_widget_event(lw->vd->view, (GdkEvent *)event))
@@ -1387,6 +1396,13 @@
 	layout_select_invert(lw);
 }
 
+static void layout_menu_file_filter_cb(GtkToggleAction *action, gpointer data)
+{
+	LayoutWindow *lw = data;
+
+	layout_file_filter_set(lw, gtk_toggle_action_get_active(action));
+}
+
 static void layout_menu_marks_cb(GtkToggleAction *action, gpointer data)
 {
 	LayoutWindow *lw = data;
@@ -1940,6 +1956,7 @@
 static GtkToggleActionEntry menu_toggle_entries[] = {
   { "Thumbnails",	PIXBUF_INLINE_ICON_THUMB,N_("Show _Thumbnails"),		"T",			N_("Show Thumbnails"),			CB(layout_menu_thumb_cb),	 FALSE },
   { "ShowMarks",        PIXBUF_INLINE_ICON_MARKS,	N_("Show _Marks"),			"M",			N_("Show Marks"),			CB(layout_menu_marks_cb),	 FALSE  },
+  { "ShowFileFilter", PIXBUF_INLINE_ICON_FILE_FILTER,	N_("Show File Filter"),	NULL,	N_("Show File Filter"),	CB(layout_menu_file_filter_cb),	 FALSE  },
   { "ShowInfoPixel",	GTK_STOCK_COLOR_PICKER,	N_("Pi_xel Info"),			NULL,			N_("Show Pixel Info"),			CB(layout_menu_info_pixel_cb),	 FALSE  },
   { "FloatTools",	PIXBUF_INLINE_ICON_FLOAT,N_("_Float file list"),		"L",			N_("Float file list"),			CB(layout_menu_float_cb),	 FALSE  },
   { "HideToolbar",	NULL,			N_("Hide tool_bar"),			NULL,			N_("Hide toolbar"),			CB(layout_menu_toolbar_cb),	 FALSE  },
@@ -2053,6 +2070,7 @@
 "      <menuitem action='SelectNone'/>"
 "      <menuitem action='SelectInvert'/>"
 "      <menuitem action='RectangularSelection'/>"
+"      <menuitem action='ShowFileFilter'/>"
 "      <placeholder name='SelectSection'/>"
 "      <separator/>"
 "      <menuitem action='CopyPath'/>"
@@ -3004,6 +3022,16 @@
 	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), layout_image_get_desaturate(lw));
 }
 
+void layout_util_sync_file_filter(LayoutWindow *lw)
+{
+	GtkAction *action;
+
+	if (!lw->action_group) return;
+
+	action = gtk_action_group_get_action(lw->action_group, "ShowFileFilter");
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_file_filter);
+}
+
 void layout_util_sync_marks(LayoutWindow *lw)
 {
 	GtkAction *action;
@@ -3078,6 +3106,9 @@
 	action = gtk_action_group_get_action(lw->action_group, "RectangularSelection");
 	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->collections.rectangular_selection);
 
+	action = gtk_action_group_get_action(lw->action_group, "ShowFileFilter");
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_file_filter);
+
 	if (osd_flags & OSD_SHOW_HISTOGRAM)
 		{
 		action = gtk_action_group_get_action(lw->action_group, "HistogramChanR");
--- a/src/layout_util.h	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/layout_util.h	Wed Aug 15 19:43:06 2018 +0100
@@ -29,6 +29,7 @@
 
 void layout_util_sync_thumb(LayoutWindow *lw);
 void layout_util_sync_marks(LayoutWindow *lw);
+void layout_util_sync_file_filter(LayoutWindow *lw);
 void layout_util_sync_color(LayoutWindow *lw);
 void layout_util_sync(LayoutWindow *lw);
 
--- a/src/options.c	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/options.c	Wed Aug 15 19:43:06 2018 +0100
@@ -273,6 +273,7 @@
 	options->order = g_strdup("123");
 	options->show_directory_date = FALSE;
 	options->show_marks = FALSE;
+	options->show_file_filter = FALSE;
 	options->show_thumbnails = FALSE;
 	options->style = 0;
 	options->show_info_pixel = FALSE;
--- a/src/pixbuf_util.c	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/pixbuf_util.c	Wed Aug 15 19:43:06 2018 +0100
@@ -138,6 +138,7 @@
 	{ PIXBUF_INLINE_ICON_SELECT_NONE,	icon_select_none },
 	{ PIXBUF_INLINE_ICON_SELECT_INVERT,	icon_select_invert },
 	{ PIXBUF_INLINE_ICON_SELECT_RECTANGLE,	icon_select_rectangle },
+	{ PIXBUF_INLINE_ICON_FILE_FILTER,	icon_file_filter },
 	{ NULL, NULL }
 };
 
--- a/src/pixbuf_util.h	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/pixbuf_util.h	Wed Aug 15 19:43:06 2018 +0100
@@ -72,6 +72,7 @@
 #define PIXBUF_INLINE_ICON_SELECT_NONE	"icon_select_none"
 #define PIXBUF_INLINE_ICON_SELECT_INVERT	"icon_select_invert"
 #define PIXBUF_INLINE_ICON_SELECT_RECTANGLE	"icon_select_rectangle"
+#define PIXBUF_INLINE_ICON_FILE_FILTER	"icon_file_filter"
 
 GdkPixbuf *pixbuf_copy_rotate_90(GdkPixbuf *src, gboolean counter_clockwise);
 GdkPixbuf *pixbuf_copy_mirror(GdkPixbuf *src, gboolean mirror, gboolean flip);
--- a/src/toolbar.c	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/toolbar.c	Wed Aug 15 19:43:06 2018 +0100
@@ -94,6 +94,7 @@
 	{"SelectAll",	N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
 	{"SelectNone",	N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
 	{"SelectInvert",	N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
+	{"ShowFileFilter",	N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
 	{"RectangularSelection",	N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
 	{"Print",	N_("Print"), GTK_STOCK_PRINT},
 	{"Preferences",	N_("Preferences"), GTK_STOCK_PREFERENCES},
--- a/src/typedefs.h	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/typedefs.h	Wed Aug 15 19:43:06 2018 +0100
@@ -619,6 +619,7 @@
 
 	gboolean show_thumbnails;
 	gboolean show_marks;
+	gboolean show_file_filter;
 	gboolean show_directory_date;
 	gboolean show_info_pixel;
 
@@ -861,6 +862,8 @@
 	GtkWidget *scrolled;
 	GtkWidget *filter;
 	GtkWidget *filter_check[FILEDATA_MARKS_SIZE];
+	GtkWidget *file_filter_combo;
+	GtkWidget *file_filter_frame;
 
 	FileData *dir_fd;
 	GList *list;
--- a/src/view_file.h	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/view_file.h	Wed Aug 15 19:43:06 2018 +0100
@@ -74,5 +74,7 @@
 void vf_thumb_cleanup(ViewFile *vf);
 void vf_thumb_stop(ViewFile *vf);
 void vf_read_metadata_in_idle(ViewFile *vf);
+void vf_file_filter_set(ViewFile *vf, gboolean enable);
+GRegex *vf_file_filter_get_filter(ViewFile *vf);
 #endif /* VIEW_FILE_H */
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
--- a/src/view_file/view_file.c	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/view_file/view_file.c	Wed Aug 15 19:43:06 2018 +0100
@@ -25,6 +25,7 @@
 #include "collect.h"
 #include "collect-table.h"
 #include "editors.h"
+#include "history_list.h"
 #include "layout.h"
 #include "menu.h"
 #include "thumb.h"
@@ -844,6 +845,35 @@
 	return FALSE;
 }
 
+static void vf_file_filter_save_cb(GtkWidget *widget, gpointer data)
+{
+	ViewFile *vf = data;
+	gchar *entry_text;
+
+	entry_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(vf->file_filter_combo)))));
+
+	history_list_add_to_key("file_filter", entry_text, 10);
+
+	vf_refresh(vf);
+
+	g_free(entry_text);
+}
+
+static void vf_file_filter_cb(GtkWidget *widget, gpointer data)
+{
+	ViewFile *vf = data;
+
+	vf_refresh(vf);
+}
+
+static gboolean vf_file_filter_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
+{
+	ViewFile *vf = data;
+
+	gtk_widget_grab_focus(widget);
+
+	return TRUE;
+}
 
 static GtkWidget *vf_marks_filter_init(ViewFile *vf)
 {
@@ -870,6 +900,61 @@
 	return frame;
 }
 
+void vf_file_filter_set(ViewFile *vf, gboolean enable)
+{
+	if (enable)
+		{
+		gtk_widget_show(vf->file_filter_combo);
+		gtk_widget_show(vf->file_filter_frame);
+		}
+	else
+		{
+		gtk_widget_hide(vf->file_filter_combo);
+		gtk_widget_hide(vf->file_filter_frame);
+		}
+
+	vf_refresh(vf);
+}
+
+static GtkWidget *vf_file_filter_init(ViewFile *vf)
+{
+	GtkWidget *frame = gtk_frame_new(NULL);
+	GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
+	GList *work;
+	gint n = 0;
+	GtkWidget *combo_entry;
+
+	vf->file_filter_combo = gtk_combo_box_text_new_with_entry();
+	combo_entry = gtk_bin_get_child(GTK_BIN(vf->file_filter_combo));
+	gtk_widget_show(gtk_bin_get_child(GTK_BIN(vf->file_filter_combo)));
+	gtk_widget_show((GTK_WIDGET(vf->file_filter_combo)));
+
+	work = history_list_get_by_key("file_filter");
+	while (work)
+		{
+		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vf->file_filter_combo), (gchar *)work->data);
+		work = work->next;
+		n++;
+		}
+	gtk_combo_box_set_active(GTK_COMBO_BOX(vf->file_filter_combo), 0);
+
+	g_signal_connect(G_OBJECT(combo_entry), "activate",
+		G_CALLBACK(vf_file_filter_save_cb), vf);
+		
+	g_signal_connect(G_OBJECT(vf->file_filter_combo), "changed",
+		G_CALLBACK(vf_file_filter_cb), vf);
+
+	g_signal_connect(G_OBJECT(combo_entry), "button_press_event",
+			 G_CALLBACK(vf_file_filter_press_cb), vf);
+
+	gtk_box_pack_start(GTK_BOX(hbox), vf->file_filter_combo, FALSE, FALSE, 0);
+	gtk_widget_show(vf->file_filter_combo);
+	gtk_container_add(GTK_CONTAINER(frame), hbox);
+	gtk_widget_show(hbox);
+
+	return frame;
+}
+
 void vf_mark_filter_toggle(ViewFile *vf, gint mark)
 {
 	gint n = mark - 1;
@@ -894,9 +979,11 @@
 				       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
 	vf->filter = vf_marks_filter_init(vf);
+	vf->file_filter_frame = vf_file_filter_init(vf);
 
 	vf->widget = gtk_vbox_new(FALSE, 0);
 	gtk_box_pack_start(GTK_BOX(vf->widget), vf->filter, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vf->widget), vf->file_filter_frame, FALSE, FALSE, 0);
 	gtk_box_pack_start(GTK_BOX(vf->widget), vf->scrolled, TRUE, TRUE, 0);
 	gtk_widget_show(vf->scrolled);
 
@@ -1171,6 +1258,39 @@
 	return ret;
 }
 
+GRegex *vf_file_filter_get_filter(ViewFile *vf)
+{
+	GRegex *ret = NULL;
+	GError *error = NULL;
+	gchar *file_filter_text = NULL;
+
+	if (!gtk_widget_get_visible(vf->file_filter_combo))
+		{
+		return g_regex_new("", 0, 0, NULL);
+		}
+
+	file_filter_text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(vf->file_filter_combo));
+
+	if (file_filter_text[0] != '\0')
+		{
+		ret = g_regex_new(file_filter_text, 0, 0, &error);
+		if (error)
+			{
+			log_printf("Error: could not compile regular expression %s\n%s\n", file_filter_text, error->message);
+			g_error_free(error);
+			error = NULL;
+			ret = g_regex_new("", 0, 0, NULL);
+			}
+		g_free(file_filter_text);
+		}
+	else
+		{
+		ret = g_regex_new("", 0, 0, NULL);
+		}
+
+	return ret;
+}
+
 void vf_set_layout(ViewFile *vf, LayoutWindow *layout)
 {
 	vf->layout = layout;
--- a/src/view_file/view_file_icon.c	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/view_file/view_file_icon.c	Wed Aug 15 19:43:06 2018 +0100
@@ -1842,6 +1842,8 @@
 		{
 		ret = filelist_read(vf->dir_fd, &new_filelist, NULL);
 		new_filelist = file_data_filter_marks_list(new_filelist, vf_marks_get_filter(vf));
+		new_filelist = g_list_first(new_filelist);
+		new_filelist = file_data_filter_file_filter_list(new_filelist, vf_file_filter_get_filter(vf));
 		}
 
 	vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend); /* the list might not be sorted if there were renames */
--- a/src/view_file/view_file_list.c	Tue Aug 14 21:28:02 2018 +0100
+++ b/src/view_file/view_file_list.c	Wed Aug 15 19:43:06 2018 +0100
@@ -1801,6 +1801,8 @@
 			}
 
 		vf->list = file_data_filter_marks_list(vf->list, vf_marks_get_filter(vf));
+		vf->list = g_list_first(vf->list);
+		vf->list = file_data_filter_file_filter_list(vf->list, vf_file_filter_get_filter(vf));
 		file_data_register_notify_func(vf_notify_cb, vf, NOTIFY_PRIORITY_MEDIUM);
 
 		DEBUG_1("%s vflist_refresh: sort", get_exec_time());
--- a/web/help/GuideMainWindowFilePane.html	Tue Aug 14 21:28:02 2018 +0100
+++ b/web/help/GuideMainWindowFilePane.html	Wed Aug 15 19:43:06 2018 +0100
@@ -468,16 +468,19 @@
 <span class="label">2.1.2. </span><a class="xref" href="GuideMainWindowFilePane.html#Iconview" title="Icon view">Icon view</a>
 </li>
 <li>
-<span class="label">2.1.3. </span><a class="xref" href="GuideMainWindowFilePane.html#Multipleselection" title="Multiple selection">Multiple selection</a>
+<span class="label">2.1.3. </span><a class="xref" href="GuideMainWindowFilePane.html#Filefilter" title="File Filter">File Filter</a>
+</li>
+<li>
+<span class="label">2.1.4. </span><a class="xref" href="GuideMainWindowFilePane.html#Multipleselection" title="Multiple selection">Multiple selection</a>
 </li>
 <li>
-<span class="label">2.1.4. </span><a class="xref" href="GuideMainWindowFilePane.html#Sorting" title="Sorting">Sorting</a>
+<span class="label">2.1.5. </span><a class="xref" href="GuideMainWindowFilePane.html#Sorting" title="Sorting">Sorting</a>
 </li>
 <li>
-<span class="label">2.1.5. </span><a class="xref" href="GuideMainWindowFilePane.html#Contextmenu" title="Context menu">Context menu</a>
+<span class="label">2.1.6. </span><a class="xref" href="GuideMainWindowFilePane.html#Contextmenu" title="Context menu">Context menu</a>
 </li>
 <li>
-<span class="label">2.1.6. </span><a class="xref" href="GuideMainWindowFilePane.html#DragandDrop" title="Drag and Drop">Drag and Drop</a>
+<span class="label">2.1.7. </span><a class="xref" href="GuideMainWindowFilePane.html#DragandDrop" title="Drag and Drop">Drag and Drop</a>
 </li>
 </ul></div>
 <div class="division section">
@@ -530,19 +533,39 @@
 <p class="para block"></p>
 </div>
 <div class="division section">
-<a name="Multipleselection"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">2.1.3. </span>Multiple selection</span></h2></div>
+<a name="Filefilter"></a><div class="header"><h2 class="section title"><span class="title"><a name="titleFilefilter"></a><span class="label">2.1.3. </span>File Filter</span></h2></div>
+<p class="para block block-first">
+      A filter box can be opened by selecting
+      <span class="emphasis emphasis-bold">Show File Filter</span>
+      from the View menu.
+    </p>
+<p class="para block">
+      Characters you type into this box will be used for pattern matching to select the files displayed.
+      <a class="link" href="GuideReferencePCRE.html" title="Perl Compatible Regular Expressions">Regular expressions</a>
+      are used in this field.
+      <p class="para block"></p>
+      For basic pattern matching "JPG" will match any filename containing those characters.
+      <p class="para block"></p>
+      To make a case-insensitive search, use "(?i)JPG"
+      <p class="para block"></p>
+      If you type a newline, the text will be saved in the dropdown box list. The last 10 items are saved.
+    </p>
+<p class="para block"></p>
+</div>
+<div class="division section">
+<a name="Multipleselection"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">2.1.4. </span>Multiple selection</span></h2></div>
 <p class="para block block-first">It is possible to select more than one image from the file pane. Multiple files can be selected with several methods:</p>
 <p class="para block"></p>
 <div class="autotoc"><ul>
 <li>
-<span class="label">2.1.3.1. </span><a class="xref" href="GuideMainWindowFilePane.html#Mouse" title="Mouse">Mouse</a>
+<span class="label">2.1.4.1. </span><a class="xref" href="GuideMainWindowFilePane.html#Mouse" title="Mouse">Mouse</a>
 </li>
 <li>
-<span class="label">2.1.3.2. </span><a class="xref" href="GuideMainWindowFilePane.html#Keyboard" title="Keyboard">Keyboard</a>
+<span class="label">2.1.4.2. </span><a class="xref" href="GuideMainWindowFilePane.html#Keyboard" title="Keyboard">Keyboard</a>
 </li>
 </ul></div>
 <div class="division section">
-<a name="Mouse"></a><div class="header"><h3 class="section title"><span class="title"><span class="label">2.1.3.1. </span>Mouse</span></h3></div>
+<a name="Mouse"></a><div class="header"><h3 class="section title"><span class="title"><span class="label">2.1.4.1. </span>Mouse</span></h3></div>
 <div class="block list itemizedlist"><ul class="itemizedlist" compact>
 <li class="li-first">
           <span class="para"><span class="code" dir="ltr">Ctrl</span> + Primary mouse button will add or remove the file from the selection.</span>
@@ -560,7 +583,7 @@
 <p class="para block"></p>
 </div>
 <div class="division section">
-<a name="Keyboard"></a><div class="header"><h3 class="section title"><span class="title"><span class="label">2.1.3.2. </span>Keyboard</span></h3></div>
+<a name="Keyboard"></a><div class="header"><h3 class="section title"><span class="title"><span class="label">2.1.4.2. </span>Keyboard</span></h3></div>
 <div class="block list itemizedlist"><ul class="itemizedlist" compact>
 <li class="li-first">
           <span class="para"><span class="code" dir="ltr">Ctrl + Arrows</span> will move the focus without changing the selection.</span>
@@ -593,13 +616,13 @@
 </div>
 </div>
 <div class="division section">
-<a name="Sorting"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">2.1.4. </span>Sorting</span></h2></div>
+<a name="Sorting"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">2.1.5. </span>Sorting</span></h2></div>
 <p class="para block block-first">The order of the images can be changed by clicking the sort area of the status bar or from the context menu. The sort methods are by file name, number, file date, or file size. The number method will sort file names by their natural order, for example files with names of file_10, file_12, and file_9 will appear in order file_9, file_10, and file_12.</p>
 <p class="para block">Selecting the ascending menu item will toggle between increasing and decreasing sort order.</p>
 <p class="para block"></p>
 </div>
 <div class="division section">
-<a name="Contextmenu"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">2.1.5. </span>Context menu</span></h2></div>
+<a name="Contextmenu"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">2.1.6. </span>Context menu</span></h2></div>
 <p class="para block block-first">
       Right clicking the mouse or pressing the menu key while the file pane has focus will display a menu. The menu functions will perform the same as those that match the window's
       <a class="link" href="GuideMainWindowMenus.html" title="Menus">menu bar</a>
@@ -646,7 +669,7 @@
 <p class="para block"></p>
 </div>
 <div class="division section">
-<a name="DragandDrop"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">2.1.6. </span>Drag and Drop</span></h2></div>
+<a name="DragandDrop"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">2.1.7. </span>Drag and Drop</span></h2></div>
 <p class="para block block-first">Drag and drop can be initialized with the primary or middle mouse buttons in the file pane. Dragging a file that is selected will include all selected files in the drag. Dragging a file that is not selected will first change the selection to the dragged file, and clear the previous selection.</p>
 <p class="para block"></p>
 </div>