From: Colin Clark Date: Wed, 15 Aug 2018 18:43:06 +0000 (+0100) Subject: Fix #624: Filter files by shell or regular expression pattern X-Git-Tag: v1.5~87 X-Git-Url: http://geeqie.org/cgi-bin/gitweb.cgi?p=geeqie.git;a=commitdiff_plain;h=eb348ad698d5ee1d55218442548aae986552d296 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. --- diff --git a/doc/docbook/GuideMainWindowFilePane.xml b/doc/docbook/GuideMainWindowFilePane.xml index fc863038..98b24930 100644 --- a/doc/docbook/GuideMainWindowFilePane.xml +++ b/doc/docbook/GuideMainWindowFilePane.xml @@ -57,6 +57,26 @@ +
+ File Filter + + A filter box can be opened by selecting + Show File Filter + from the View menu. + + + Characters you type into this box will be used for pattern matching to select the files displayed. + Regular expressions + are used in this field. + + For basic pattern matching "JPG" will match any filename containing those characters. + + To make a case-insensitive search, use "(?i)JPG" + + If you type a newline, the text will be saved in the dropdown box list. The last 10 items are saved. + + +
Multiple selection It is possible to select more than one image from the file pane. Multiple files can be selected with several methods: diff --git a/src/filedata.c b/src/filedata.c index 0461755b..af6e59d3 100644 --- a/src/filedata.c +++ b/src/filedata.c @@ -1817,6 +1817,33 @@ GList *file_data_filter_marks_list(GList *list, guint filter) 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; diff --git a/src/filedata.h b/src/filedata.h index 1b4e0975..878bbb97 100644 --- a/src/filedata.h +++ b/src/filedata.h @@ -99,6 +99,9 @@ void file_data_set_mark(FileData *fd, gint n, gboolean value); 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); diff --git a/src/icons/Makefile.am b/src/icons/Makefile.am index dcca29f1..589b2698 100644 --- a/src/icons/Makefile.am +++ b/src/icons/Makefile.am @@ -39,7 +39,8 @@ ICONS_INLINE = \ 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 @@ ICONS_INLINE_PAIRS = \ 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; \ diff --git a/src/icons/icon_file_filter.png b/src/icons/icon_file_filter.png new file mode 100644 index 00000000..321c7cc6 Binary files /dev/null and b/src/icons/icon_file_filter.png differ diff --git a/src/layout.c b/src/layout.c index 14ae251b..50062416 100644 --- a/src/layout.c +++ b/src/layout.c @@ -862,6 +862,11 @@ static void layout_list_sync_thumb(LayoutWindow *lw) 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 @@ static GtkWidget *layout_list_new(LayoutWindow *lw) 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 @@ void layout_thumb_set(LayoutWindow *lw, gboolean enable) 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 @@ void layout_write_attributes(LayoutOptions *layout, GString *outstr, gint indent 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 @@ void layout_load_attributes(LayoutOptions *layout, const gchar **attribute_names 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; diff --git a/src/layout.h b/src/layout.h index 61f68c3f..2b338431 100644 --- a/src/layout.h +++ b/src/layout.h @@ -89,6 +89,8 @@ gboolean layout_thumb_get(LayoutWindow *lw); 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); diff --git a/src/layout_util.c b/src/layout_util.c index ca78abc5..cf1cf46f 100644 --- a/src/layout_util.c +++ b/src/layout_util.c @@ -117,6 +117,15 @@ gboolean layout_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer dat 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 @@ static void layout_menu_invert_selection_cb(GtkAction *action, gpointer data) 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 GtkActionEntry menu_entries[] = { 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 @@ static const gchar *menu_ui_description = " " " " " " +" " " " " " " " @@ -3004,6 +3022,16 @@ void layout_util_sync_color(LayoutWindow *lw) 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 @@ static void layout_util_sync_views(LayoutWindow *lw) 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"); diff --git a/src/layout_util.h b/src/layout_util.h index 49f3642f..c2a4d3a4 100644 --- a/src/layout_util.h +++ b/src/layout_util.h @@ -29,6 +29,7 @@ gboolean layout_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer dat 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); diff --git a/src/options.c b/src/options.c index e7d1f0db..ff98542c 100644 --- a/src/options.c +++ b/src/options.c @@ -273,6 +273,7 @@ LayoutOptions *init_layout_options(LayoutOptions *options) 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; diff --git a/src/pixbuf_util.c b/src/pixbuf_util.c index c6941587..f32e110d 100644 --- a/src/pixbuf_util.c +++ b/src/pixbuf_util.c @@ -138,6 +138,7 @@ static PixbufInline inline_pixbuf_data[] = { { 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 } }; diff --git a/src/pixbuf_util.h b/src/pixbuf_util.h index cfa8ffce..fe124fb8 100644 --- a/src/pixbuf_util.h +++ b/src/pixbuf_util.h @@ -72,6 +72,7 @@ gboolean pixbuf_scale_aspect(gint req_w, gint req_h, gint old_w, gint old_h, gin #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); diff --git a/src/toolbar.c b/src/toolbar.c index 2a6d913c..008fafe9 100644 --- a/src/toolbar.c +++ b/src/toolbar.c @@ -94,6 +94,7 @@ static const UseableToolbarItems useable_toolbar_items[] = { {"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}, diff --git a/src/typedefs.h b/src/typedefs.h index 9d9d985e..1217eac0 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -619,6 +619,7 @@ struct _LayoutOptions gboolean show_thumbnails; gboolean show_marks; + gboolean show_file_filter; gboolean show_directory_date; gboolean show_info_pixel; @@ -861,6 +862,8 @@ struct _ViewFile GtkWidget *scrolled; GtkWidget *filter; GtkWidget *filter_check[FILEDATA_MARKS_SIZE]; + GtkWidget *file_filter_combo; + GtkWidget *file_filter_frame; FileData *dir_fd; GList *list; diff --git a/src/view_file.h b/src/view_file.h index 48025899..ec9dff8e 100644 --- a/src/view_file.h +++ b/src/view_file.h @@ -74,5 +74,7 @@ void vf_thumb_update(ViewFile *vf); 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: */ diff --git a/src/view_file/view_file.c b/src/view_file/view_file.c index c4da36b6..15324506 100644 --- a/src/view_file/view_file.c +++ b/src/view_file/view_file.c @@ -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 @@ static gboolean vf_marks_tooltip_cb(GtkWidget *widget, 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 @@ static GtkWidget *vf_marks_filter_init(ViewFile *vf) 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 @@ ViewFile *vf_new(FileViewType type, FileData *dir_fd) 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 @@ guint vf_marks_get_filter(ViewFile *vf) 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; diff --git a/src/view_file/view_file_icon.c b/src/view_file/view_file_icon.c index 210af6c8..866e3420 100644 --- a/src/view_file/view_file_icon.c +++ b/src/view_file/view_file_icon.c @@ -1842,6 +1842,8 @@ static gboolean vficon_refresh_real(ViewFile *vf, gboolean keep_position) { 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 */ diff --git a/src/view_file/view_file_list.c b/src/view_file/view_file_list.c index 168bf57f..b50abe7d 100644 --- a/src/view_file/view_file_list.c +++ b/src/view_file/view_file_list.c @@ -1801,6 +1801,8 @@ gboolean vflist_refresh(ViewFile *vf) } 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()); diff --git a/web/help/GuideMainWindowFilePane.html b/web/help/GuideMainWindowFilePane.html index 9d29445f..6b062e2f 100644 --- a/web/help/GuideMainWindowFilePane.html +++ b/web/help/GuideMainWindowFilePane.html @@ -468,16 +468,19 @@ dd.answer div.label { float: left; } 2.1.2. Icon view
  • -2.1.3. Multiple selection +2.1.3. File Filter
  • -2.1.4. Sorting +2.1.4. Multiple selection
  • -2.1.5. Context menu +2.1.5. Sorting
  • -2.1.6. Drag and Drop +2.1.6. Context menu +
  • +
  • +2.1.7. Drag and Drop
  • @@ -530,19 +533,39 @@ dd.answer div.label { float: left; }

    -

    2.1.3. Multiple selection

    +

    2.1.3. File Filter

    +

    + A filter box can be opened by selecting + Show File Filter + from the View menu. +

    +

    + Characters you type into this box will be used for pattern matching to select the files displayed. + Regular expressions + are used in this field. +

    + For basic pattern matching "JPG" will match any filename containing those characters. +

    + To make a case-insensitive search, use "(?i)JPG" +

    + If you type a newline, the text will be saved in the dropdown box list. The last 10 items are saved. +

    +

    +
    +
    +

    2.1.4. Multiple selection

    It is possible to select more than one image from the file pane. Multiple files can be selected with several methods:

    -

    2.1.3.1. Mouse

    +

    2.1.4.1. Mouse

    • Ctrl + Primary mouse button will add or remove the file from the selection. @@ -560,7 +583,7 @@ dd.answer div.label { float: left; }

    -

    2.1.3.2. Keyboard

    +

    2.1.4.2. Keyboard

    • Ctrl + Arrows will move the focus without changing the selection. @@ -593,13 +616,13 @@ dd.answer div.label { float: left; }
    -

    2.1.4. Sorting

    +

    2.1.5. Sorting

    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.

    Selecting the ascending menu item will toggle between increasing and decreasing sort order.

    -

    2.1.5. Context menu

    +

    2.1.6. Context menu

    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 menu bar @@ -646,7 +669,7 @@ dd.answer div.label { float: left; }

    -

    2.1.6. Drag and Drop

    +

    2.1.7. Drag and Drop

    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.