(Re)-implement natural and case sorting
authorColin Clark <colin.clark@cclark.uk>
Fri, 4 Aug 2023 13:55:58 +0000 (14:55 +0100)
committerColin Clark <colin.clark@cclark.uk>
Fri, 4 Aug 2023 13:55:58 +0000 (14:55 +0100)
The directory and file panes now have natural (numeric) and case
sorting.

Other windows sorting is unchanged.

32 files changed:
doc/docbook/GuideOptionsFiltering.xml
src/filedata.cc
src/filedata.h
src/img-view.cc
src/layout.cc
src/layout.h
src/menu.cc
src/options.cc
src/options.h
src/pan-view/pan-calendar.cc
src/pan-view/pan-folder.cc
src/pan-view/pan-grid.cc
src/pan-view/pan-timeline.cc
src/pan-view/pan-util.cc
src/pan-view/pan-util.h
src/pan-view/pan-view.cc
src/pan-view/pan-view.h
src/preferences.cc
src/rcfile.cc
src/remote.cc
src/search.cc
src/trash.cc
src/typedefs.h
src/view-dir-list.cc
src/view-dir-tree.cc
src/view-dir.cc
src/view-file.h
src/view-file/view-file-icon.cc
src/view-file/view-file-icon.h
src/view-file/view-file-list.cc
src/view-file/view-file-list.h
src/view-file/view-file.cc

index 6c5e82c..3e3931b 100644 (file)
@@ -24,7 +24,7 @@
       </varlistentry>
       <varlistentry>
         <term>
-          <guilabel>Case sensitive sort</guilabel>
+          <guilabel>Case sensitive sort (Collection and Search windows, and tab completion)</guilabel>
         </term>
         <listitem>
           <para>Files and folders are sorted such that upper case letters occur before lower case letters.</para>
           </para>
         </listitem>
       </varlistentry>
-      <varlistentry>
-        <term>
-          <guilabel>Natural sort order</guilabel>
-        </term>
-        <listitem>
-          <para>Files and folders are sorted with the dot '.' treated as a special case, so the order is e.g. "event.c" "event.h" "eventgenerator.c". Also, files containing numbers are sorted as "file1" "file5" "file10".</para>
-          <note>If this option is selected and a standard numerical sort is required and the files are in a single folder, a workaround is to put the files in a temporary collection and select Sort By Path</note>
-        </listitem>
-      </varlistentry>
       <varlistentry>
         <term>
           <guilabel>Disable file extension checks</guilabel>
index 5f1ee24..902e87b 100644 (file)
@@ -50,6 +50,7 @@ static void file_data_disconnect_sidecar_file(FileData *target, FileData *sfd);
 
 static SortType filelist_sort_method = SORT_NONE;
 static gboolean filelist_sort_ascend = TRUE;
+static gboolean filelist_sort_case = TRUE;
 
 /*
  *-----------------------------------------------------------------------------
@@ -281,16 +282,10 @@ static void file_data_set_collate_keys(FileData *fd)
        g_free(fd->collate_key_name);
        g_free(fd->collate_key_name_nocase);
 
-       if (options->file_sort.natural)
-               {
-               fd->collate_key_name = g_utf8_collate_key_for_filename(fd->name, -1);
-               fd->collate_key_name_nocase = g_utf8_collate_key_for_filename(caseless_name, -1);
-               }
-       else
-               {
-               fd->collate_key_name = g_utf8_collate_key(valid_name, -1);
-               fd->collate_key_name_nocase = g_utf8_collate_key(caseless_name, -1);
-               }
+       fd->collate_key_name_natural = g_utf8_collate_key_for_filename(fd->name, -1);
+       fd->collate_key_name_nocase_natural = g_utf8_collate_key_for_filename(caseless_name, -1);
+       fd->collate_key_name = g_utf8_collate_key(valid_name, -1);
+       fd->collate_key_name_nocase = g_utf8_collate_key(caseless_name, -1);
 
        g_free(valid_name);
        g_free(caseless_name);
@@ -1187,11 +1182,16 @@ gint filelist_sort_compare_filedata(FileData *fa, FileData *fb)
                        if (fa->format_class > fb->format_class) return 1;
                        /* fall back to name */
                        break;
+               case SORT_NUMBER:
+                       ret = strcmp(fa->collate_key_name_natural, fb->collate_key_name_natural);
+                       if (ret != 0) return ret;
+                       /* fall back to name */
+                       break;
                default:
                        break;
                }
 
-       if (options->file_sort.case_sensitive)
+       if (filelist_sort_case)
                ret = strcmp(fa->collate_key_name, fb->collate_key_name);
        else
                ret = strcmp(fa->collate_key_name_nocase, fb->collate_key_name_nocase);
@@ -1216,30 +1216,32 @@ static gint filelist_sort_file_cb(gpointer a, gpointer b)
        return filelist_sort_compare_filedata(static_cast<FileData *>(a), static_cast<FileData *>(b));
 }
 
-GList *filelist_sort_full(GList *list, SortType method, gboolean ascend, GCompareFunc cb)
+GList *filelist_sort_full(GList *list, SortType method, gboolean ascend, gboolean case_sensitive, GCompareFunc cb)
 {
        filelist_sort_method = method;
        filelist_sort_ascend = ascend;
+       filelist_sort_case = case_sensitive;
        return g_list_sort(list, cb);
 }
 
-GList *filelist_insert_sort_full(GList *list, gpointer data, SortType method, gboolean ascend, GCompareFunc cb)
+GList *filelist_insert_sort_full(GList *list, gpointer data, SortType method, gboolean ascend, gboolean case_sensitive, GCompareFunc cb)
 {
        filelist_sort_method = method;
        filelist_sort_ascend = ascend;
+       filelist_sort_case = case_sensitive;
        return g_list_insert_sorted(list, data, cb);
 }
 
-GList *filelist_sort(GList *list, SortType method, gboolean ascend)
+GList *filelist_sort(GList *list, SortType method, gboolean ascend, gboolean case_sensitive)
 {
-       return filelist_sort_full(list, method, ascend, reinterpret_cast<GCompareFunc>(filelist_sort_file_cb));
+       return filelist_sort_full(list, method, ascend, case_sensitive, reinterpret_cast<GCompareFunc>(filelist_sort_file_cb));
 }
 
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wunused-function"
 GList *filelist_insert_sort_unused(GList *list, FileData *fd, SortType method, gboolean ascend)
 {
-       return filelist_insert_sort_full(list, fd, method, ascend, (GCompareFunc) filelist_sort_file_cb);
+       return filelist_insert_sort_full(list, fd, method, ascend, ascend, (GCompareFunc) filelist_sort_file_cb);
 }
 #pragma GCC diagnostic pop
 
@@ -1664,7 +1666,7 @@ static void filelist_recursive_append(GList **list, GList *dirs)
                }
 }
 
-static void filelist_recursive_append_full(GList **list, GList *dirs, SortType method, gboolean ascend)
+static void filelist_recursive_append_full(GList **list, GList *dirs, SortType method, gboolean ascend, gboolean case_sensitive)
 {
        GList *work;
 
@@ -1678,12 +1680,12 @@ static void filelist_recursive_append_full(GList **list, GList *dirs, SortType m
                if (filelist_read(fd, &f, &d))
                        {
                        f = filelist_filter(f, FALSE);
-                       f = filelist_sort_full(f, method, ascend, reinterpret_cast<GCompareFunc>(filelist_sort_file_cb));
+                       f = filelist_sort_full(f, method, ascend, case_sensitive, reinterpret_cast<GCompareFunc>(filelist_sort_file_cb));
                        *list = g_list_concat(*list, f);
 
                        d = filelist_filter(d, TRUE);
                        d = filelist_sort_path(d);
-                       filelist_recursive_append_full(list, d, method, ascend);
+                       filelist_recursive_append_full(list, d, method, ascend, case_sensitive);
                        filelist_free(d);
                        }
 
@@ -1708,18 +1710,18 @@ GList *filelist_recursive(FileData *dir_fd)
        return list;
 }
 
-GList *filelist_recursive_full(FileData *dir_fd, SortType method, gboolean ascend)
+GList *filelist_recursive_full(FileData *dir_fd, SortType method, gboolean ascend, gboolean case_sensitive)
 {
        GList *list;
        GList *d;
 
        if (!filelist_read(dir_fd, &list, &d)) return nullptr;
        list = filelist_filter(list, FALSE);
-       list = filelist_sort_full(list, method, ascend, reinterpret_cast<GCompareFunc>(filelist_sort_file_cb));
+       list = filelist_sort_full(list, method, ascend, case_sensitive, reinterpret_cast<GCompareFunc>(filelist_sort_file_cb));
 
        d = filelist_filter(d, TRUE);
        d = filelist_sort_path(d);
-       filelist_recursive_append_full(&list, d, method, ascend);
+       filelist_recursive_append_full(&list, d, method, ascend, case_sensitive);
        filelist_free(d);
 
        return list;
index 08712f3..e1bc7fa 100644 (file)
@@ -79,9 +79,9 @@ void file_data_disable_grouping_list(GList *fd_list, gboolean disable);
 
 gint filelist_sort_compare_filedata(FileData *fa, FileData *fb);
 gint filelist_sort_compare_filedata_full(FileData *fa, FileData *fb, SortType method, gboolean ascend);
-GList *filelist_sort(GList *list, SortType method, gboolean ascend);
-GList *filelist_sort_full(GList *list, SortType method, gboolean ascend, GCompareFunc cb);
-GList *filelist_insert_sort_full(GList *list, gpointer data, SortType method, gboolean ascend, GCompareFunc cb);
+GList *filelist_sort(GList *list, SortType method, gboolean ascend, gboolean case_sensitive);
+GList *filelist_sort_full(GList *list, SortType method, gboolean ascend, gboolean case_sensitive, GCompareFunc cb);
+GList *filelist_insert_sort_full(GList *list, gpointer data, SortType method, gboolean ascend, gboolean case_sensitive, GCompareFunc cb);
 
 gboolean filelist_read(FileData *dir_fd, GList **files, GList **dirs);
 gboolean filelist_read_lstat(FileData *dir_fd, GList **files, GList **dirs);
@@ -94,7 +94,7 @@ GList *filelist_filter(GList *list, gboolean is_dir_list);
 
 GList *filelist_sort_path(GList *list);
 GList *filelist_recursive(FileData *dir_fd);
-GList *filelist_recursive_full(FileData *dir_fd, SortType method, gboolean ascend);
+GList *filelist_recursive_full(FileData *dir_fd, SortType method, gboolean ascend, gboolean case_sensitive);
 
 using FileDataGetMarkFunc = gboolean (*)(FileData *, gint, gpointer);
 using FileDataSetMarkFunc = gboolean (*)(FileData *, gint, gboolean, gpointer);
index 663926f..9f50773 100644 (file)
@@ -1320,7 +1320,7 @@ static LayoutWindow *view_new_layout_with_fd(FileData *fd)
        LayoutWindow *nw;
 
        nw = layout_new(nullptr, nullptr);
-       layout_sort_set(nw, options->file_sort.method, options->file_sort.ascending);
+       layout_sort_set_files(nw, nw->options.file_view_list_sort.method, nw->options.file_view_list_sort.ascend, nw->options.file_view_list_sort.case_sensitive);
        layout_set_fd(nw, fd);
        return nw;
 }
index 70a958b..1291303 100644 (file)
@@ -417,14 +417,21 @@ static void layout_sort_menu_cb(GtkWidget *widget, gpointer data)
                {
                vf_read_metadata_in_idle(lw->vf);
                }
-       layout_sort_set(lw, type, lw->sort_ascend);
+       layout_sort_set_files(lw, type, lw->options.file_view_list_sort.ascend, lw->options.file_view_list_sort.case_sensitive);
 }
 
 static void layout_sort_menu_ascend_cb(GtkWidget *, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       layout_sort_set(lw, lw->sort_method, !lw->sort_ascend);
+       layout_sort_set_files(lw, lw->options.file_view_list_sort.method, !lw->options.file_view_list_sort.ascend, lw->options.file_view_list_sort.case_sensitive);
+}
+
+static void layout_sort_menu_case_cb(GtkWidget *, gpointer data)
+{
+       auto lw = static_cast<LayoutWindow *>(data);
+
+       layout_sort_set_files(lw, lw->options.file_view_list_sort.method, lw->options.file_view_list_sort.ascend, !lw->options.file_view_list_sort.case_sensitive);
 }
 
 static void layout_sort_menu_hide_cb(GtkWidget *widget, gpointer)
@@ -438,7 +445,7 @@ static void layout_sort_button_press_cb(GtkWidget *, gpointer data)
        auto lw = static_cast<LayoutWindow *>(data);
        GtkWidget *menu;
 
-       menu = submenu_add_sort(nullptr, G_CALLBACK(layout_sort_menu_cb), lw, FALSE, FALSE, TRUE, lw->sort_method);
+       menu = submenu_add_sort(nullptr, G_CALLBACK(layout_sort_menu_cb), lw, FALSE, FALSE, TRUE, lw->options.file_view_list_sort.method);
 
        /* take ownership of menu */
 #ifdef GTK_OBJECT_FLOATING
@@ -452,7 +459,8 @@ static void layout_sort_button_press_cb(GtkWidget *, gpointer data)
 
        /* ascending option */
        menu_item_add_divider(menu);
-       menu_item_add_check(menu, _("Ascending"), lw->sort_ascend, G_CALLBACK(layout_sort_menu_ascend_cb), lw);
+       menu_item_add_check(menu, _("Ascending"), lw->options.file_view_list_sort.ascend, G_CALLBACK(layout_sort_menu_ascend_cb), lw);
+       menu_item_add_check(menu, _("Case"), lw->options.file_view_list_sort.case_sensitive, G_CALLBACK(layout_sort_menu_case_cb), lw);
 
        g_signal_connect(G_OBJECT(menu), "selection_done",
                         G_CALLBACK(layout_sort_menu_hide_cb), NULL);
@@ -473,7 +481,7 @@ static GtkWidget *layout_sort_button(LayoutWindow *lw, GtkWidget *box)
        gtk_widget_show(frame);
 
        image = gtk_image_new_from_icon_name(GQ_ICON_PAN_DOWN, GTK_ICON_SIZE_BUTTON);
-       button = gtk_button_new_with_label(sort_type_get_text(lw->sort_method));
+       button = gtk_button_new_with_label(sort_type_get_text(lw->options.file_view_list_sort.method));
        gtk_button_set_image(GTK_BUTTON(button), image);
        g_signal_connect(G_OBJECT(button), "clicked",
                         G_CALLBACK(layout_sort_button_press_cb), lw);
@@ -1011,7 +1019,7 @@ static void layout_list_sync_sort(LayoutWindow *lw)
 {
        if (!layout_valid(&lw)) return;
 
-       if (lw->vf) vf_sort_set(lw->vf, lw->sort_method, lw->sort_ascend);
+       if (lw->vf) vf_sort_set(lw->vf, lw->options.file_view_list_sort.method, lw->options.file_view_list_sort.ascend, lw->options.file_view_list_sort.case_sensitive);
 }
 
 GList *layout_selection_list(LayoutWindow *lw)
@@ -1234,7 +1242,7 @@ gboolean layout_set_fd(LayoutWindow *lw, FileData *fd)
        if (options->metadata.confirm_on_dir_change && dir_changed)
                metadata_write_queue_confirm(FALSE, nullptr, nullptr);
 
-       if (lw->vf && (options->read_metadata_in_idle || (lw->sort_method == SORT_EXIFTIME || lw->sort_method == SORT_EXIFTIMEDIGITIZED || lw->sort_method == SORT_RATING)))
+       if (lw->vf && (options->read_metadata_in_idle || (lw->options.file_view_list_sort.method == SORT_EXIFTIME || lw->options.file_view_list_sort.method == SORT_EXIFTIMEDIGITIZED || lw->options.file_view_list_sort.method == SORT_RATING)))
                {
                vf_read_metadata_in_idle(lw->vf);
                }
@@ -1317,24 +1325,26 @@ gboolean layout_marks_get_unused(LayoutWindow *lw)
 }
 #pragma GCC diagnostic pop
 
-void layout_sort_set(LayoutWindow *lw, SortType type, gboolean ascend)
+void layout_sort_set_files(LayoutWindow *lw, SortType type, gboolean ascend, gboolean case_sensitive)
 {
        if (!layout_valid(&lw)) return;
-       if (lw->sort_method == type && lw->sort_ascend == ascend) return;
+       if (lw->options.file_view_list_sort.method == type && lw->options.file_view_list_sort.ascend == ascend && lw->options.file_view_list_sort.case_sensitive == case_sensitive) return;
 
-       lw->sort_method = type;
-       lw->sort_ascend = ascend;
+       lw->options.file_view_list_sort.method = type; //??
+       lw->options.file_view_list_sort.ascend = ascend;
+       lw->options.file_view_list_sort.case_sensitive = case_sensitive;
 
        if (lw->info_sort) gtk_button_set_label(GTK_BUTTON(lw->info_sort), sort_type_get_text(type));
        layout_list_sync_sort(lw);
 }
 
-gboolean layout_sort_get(LayoutWindow *lw, SortType *type, gboolean *ascend)
+gboolean layout_sort_get(LayoutWindow *lw, SortType *type, gboolean *ascend, gboolean *case_sensitive)
 {
        if (!layout_valid(&lw)) return FALSE;
 
-       if (type) *type = lw->sort_method;
-       if (ascend) *ascend = lw->sort_ascend;
+       if (type) *type = lw->options.file_view_list_sort.method;
+       if (ascend) *ascend = lw->options.file_view_list_sort.ascend;
+       if (case_sensitive) *case_sensitive = lw->options.file_view_list_sort.case_sensitive;
 
        return TRUE;
 }
@@ -1404,14 +1414,15 @@ void layout_views_set(LayoutWindow *lw, DirViewType dir_view_type, FileViewType
        layout_style_set(lw, -1, nullptr);
 }
 
-void layout_views_set_sort(LayoutWindow *lw, SortType method, gboolean ascend)
+void layout_views_set_sort_dir(LayoutWindow *lw, SortType method, gboolean ascend, gboolean case_sensitive)
 {
        if (!layout_valid(&lw)) return;
 
-       if (lw->options.dir_view_list_sort.method == method && lw->options.dir_view_list_sort.ascend == ascend) return;
+       if (lw->options.dir_view_list_sort.method == method && lw->options.dir_view_list_sort.ascend == ascend && lw->options.dir_view_list_sort.case_sensitive == case_sensitive) return;
 
        lw->options.dir_view_list_sort.method = method;
        lw->options.dir_view_list_sort.ascend = ascend;
+       lw->options.dir_view_list_sort.case_sensitive = case_sensitive;
 
        layout_style_set(lw, -1, nullptr);
 }
@@ -2553,8 +2564,9 @@ LayoutWindow *layout_new_with_geometry(FileData *dir_fd, LayoutOptions *lop,
        else
                init_layout_options(&lw->options);
 
-       lw->sort_method = SORT_NAME;
-       lw->sort_ascend = TRUE;
+       lw->options.file_view_list_sort.method = SORT_NAME;
+       lw->options.file_view_list_sort.ascend = TRUE;
+       lw->options.file_view_list_sort.case_sensitive = TRUE;
 
        layout_set_unique_id(lw);
 
@@ -2686,8 +2698,14 @@ void layout_write_attributes(LayoutOptions *layout, GString *outstr, gint indent
        WRITE_NL(); WRITE_CHAR(*layout, order);
        WRITE_NL(); WRITE_UINT(*layout, dir_view_type);
        WRITE_NL(); WRITE_UINT(*layout, file_view_type);
+
+       WRITE_NL(); WRITE_UINT(*layout, file_view_list_sort.method);
+       WRITE_NL(); WRITE_BOOL(*layout, file_view_list_sort.ascend);
+       WRITE_NL(); WRITE_BOOL(*layout, file_view_list_sort.case_sensitive);
+
        WRITE_NL(); WRITE_UINT(*layout, dir_view_list_sort.method);
        WRITE_NL(); WRITE_BOOL(*layout, dir_view_list_sort.ascend);
+       WRITE_NL(); WRITE_BOOL(*layout, dir_view_list_sort.case_sensitive);
        WRITE_NL(); WRITE_BOOL(*layout, show_marks);
        WRITE_NL(); WRITE_BOOL(*layout, show_file_filter);
        WRITE_NL(); WRITE_BOOL(*layout, show_thumbnails);
@@ -2808,8 +2826,12 @@ void layout_load_attributes(LayoutOptions *layout, const gchar **attribute_names
 
                if (READ_UINT_ENUM(*layout, dir_view_type)) continue;
                if (READ_UINT_ENUM(*layout, file_view_type)) continue;
+               if (READ_UINT_ENUM(*layout, file_view_list_sort.method)) continue;
+               if (READ_BOOL(*layout, file_view_list_sort.ascend)) continue;
+               if (READ_BOOL(*layout, file_view_list_sort.case_sensitive)) continue;
                if (READ_UINT_ENUM(*layout, dir_view_list_sort.method)) continue;
                if (READ_BOOL(*layout, dir_view_list_sort.ascend)) continue;
+               if (READ_BOOL(*layout, dir_view_list_sort.case_sensitive)) continue;
                if (READ_BOOL(*layout, show_marks)) continue;
                if (READ_BOOL(*layout, show_file_filter)) continue;
                if (READ_BOOL(*layout, show_thumbnails)) continue;
@@ -2978,7 +3000,9 @@ LayoutWindow *layout_new_from_config(const gchar **attribute_names, const gchar
                }
 
        lw = layout_new_with_geometry(nullptr, &lop, use_commandline ? command_line->geometry : nullptr);
-       layout_sort_set(lw, options->file_sort.method, options->file_sort.ascending);
+       layout_sort_set_files(lw, lw->options.file_view_list_sort.method, lw->options.file_view_list_sort.ascend, lw->options.file_view_list_sort.case_sensitive);
+
+
        layout_set_path(lw, path);
 
        if (use_commandline && command_line->startup_full_screen) layout_image_full_screen_start(lw);
index 16840f3..3229b6a 100644 (file)
@@ -91,15 +91,15 @@ void layout_marks_set(LayoutWindow *lw, gboolean enable);
 
 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);
+void layout_sort_set_files(LayoutWindow *lw, SortType type, gboolean ascend, gboolean case_sensitive);
+gboolean layout_sort_get(LayoutWindow *lw, SortType *type, gboolean *ascend, gboolean *case_sensitive);
 
 gboolean layout_geometry_get(LayoutWindow *lw, gint *x, gint *y, gint *w, gint *h);
 gboolean layout_geometry_get_dividers(LayoutWindow *lw, gint *h, gint *v);
 
 void layout_views_set(LayoutWindow *lw, DirViewType dir_view_type, FileViewType file_view_type);
 
-void layout_views_set_sort(LayoutWindow *lw, SortType method, gboolean ascend);
+void layout_views_set_sort_dir(LayoutWindow *lw, SortType method, gboolean ascend, gboolean case_sensitive);
 
 void layout_status_update(LayoutWindow *lw, const gchar *text);
 
index 428f955..642495e 100644 (file)
@@ -155,6 +155,9 @@ gchar *sort_type_get_text(SortType method)
                case SORT_PATH:
                        return _("Sort by path");
                        break;
+               case SORT_NUMBER:
+                       return _("Sort by number");
+                       break;
                case SORT_RATING:
                        return _("Sort by rating");
                        break;
@@ -201,6 +204,7 @@ GtkWidget *submenu_add_sort(GtkWidget *menu, GCallback func, gpointer data,
        g_object_set_data(G_OBJECT(submenu), "submenu_data", data);
 
        submenu_add_sort_item(submenu, func, SORT_NAME, show_current, type);
+       submenu_add_sort_item(submenu, func, SORT_NUMBER, show_current, type);
        submenu_add_sort_item(submenu, func, SORT_TIME, show_current, type);
        submenu_add_sort_item(submenu, func, SORT_CTIME, show_current, type);
        submenu_add_sort_item(submenu, func, SORT_EXIFTIME, show_current, type);
@@ -233,6 +237,7 @@ GtkWidget *submenu_add_dir_sort(GtkWidget *menu, GCallback func, gpointer data,
        g_object_set_data(G_OBJECT(submenu), "submenu_data", data);
 
        submenu_add_sort_item(submenu, func, SORT_NAME, show_current, type);
+       submenu_add_sort_item(submenu, func, SORT_NUMBER, show_current, type);
        submenu_add_sort_item(submenu, func, SORT_TIME, show_current, type);
        if (include_path) submenu_add_sort_item(submenu, func, SORT_PATH, show_current, type);
        if (include_none) submenu_add_sort_item(submenu, func, SORT_NONE, show_current, type);
index b1027a5..43ce45b 100644 (file)
@@ -75,10 +75,7 @@ ConfOptions *init_options(ConfOptions *options)
        options->file_ops.safe_delete_path = nullptr;
        options->file_ops.no_trash = FALSE;
 
-       options->file_sort.ascending = TRUE;
        options->file_sort.case_sensitive = FALSE;
-       options->file_sort.method = SORT_NAME;
-       options->file_sort.natural = FALSE;
 
        options->fullscreen.above = FALSE;
        options->fullscreen.clean_flip = FALSE;
@@ -292,7 +289,11 @@ LayoutOptions *init_layout_options(LayoutOptions *options)
 
        options->dir_view_type = DIRVIEW_LIST;
        options->dir_view_list_sort.ascend = TRUE;
+       options->dir_view_list_sort.case_sensitive = TRUE;
        options->dir_view_list_sort.method = SORT_NAME;
+       options->file_view_list_sort.ascend = TRUE;
+       options->file_view_list_sort.case_sensitive = TRUE;
+       options->file_view_list_sort.method = SORT_NAME;
        options->file_view_type = FILEVIEW_LIST;
        options->float_window.h = 450;
        options->float_window.vdivider_pos = -1;
@@ -352,7 +353,6 @@ static void sync_options_with_current_state(ConfOptions *options)
        if (layout_valid(&lw))
                {
                layout_sync_options_with_current_state(lw);
-               layout_sort_get(lw, &options->file_sort.method, &options->file_sort.ascending);
 
                options->color_profile.enabled = layout_image_color_profile_get_use(lw);
                layout_image_color_profile_get(lw,
index 5dec24d..062280e 100644 (file)
@@ -207,10 +207,7 @@ struct ConfOptions
 
        /* file sorting */
        struct {
-               SortType method;
-               gboolean ascending;
                gboolean case_sensitive; /**< file sorting method (case) */
-               gboolean natural;
        } file_sort;
 
        /* slideshow */
index cc038ba..54e70d0 100644 (file)
@@ -202,18 +202,18 @@ void pan_calendar_compute(PanWindow *pw, FileData *dir_fd, gint *width, gint *he
        gint end_month = 0;
        gint day_of_week;
 
-       list = pan_list_tree(dir_fd, SORT_NONE, TRUE, pw->ignore_symlinks);
+       list = pan_list_tree(dir_fd, SORT_NONE, TRUE, TRUE, pw->ignore_symlinks);
        pan_filter_fd_list(&list, pw->filter_ui->filter_elements, pw->filter_ui->filter_classes);
 
        if (pw->cache_list && pw->exif_date_enable)
                {
-               pw->cache_list = pan_cache_sort(pw->cache_list, SORT_NAME, TRUE);
-               list = filelist_sort(list, SORT_NAME, TRUE);
+               pw->cache_list = pan_cache_sort(pw->cache_list, SORT_NAME, TRUE, TRUE);
+               list = filelist_sort(list, SORT_NAME, TRUE, TRUE);
                pan_cache_sync_date(pw, list);
                }
 
-       pw->cache_list = pan_cache_sort(pw->cache_list, SORT_TIME, TRUE);
-       list = filelist_sort(list, SORT_TIME, TRUE);
+       pw->cache_list = pan_cache_sort(pw->cache_list, SORT_TIME, TRUE, TRUE);
+       list = filelist_sort(list, SORT_TIME, TRUE, TRUE);
 
        day_max = 0;
        count = 0;
index 5911d3a..4e0b00b 100644 (file)
@@ -239,8 +239,8 @@ static FlowerGroup *pan_flower_group(PanWindow *pw, FileData *dir_fd, gint x, gi
        if (!filelist_read(dir_fd, &f, &d)) return nullptr;
        if (!f && !d) return nullptr;
 
-       f = filelist_sort(f, SORT_NAME, TRUE);
-       d = filelist_sort(d, SORT_NAME, TRUE);
+       f = filelist_sort(f, SORT_NAME, TRUE, TRUE);
+       d = filelist_sort(d, SORT_NAME, TRUE, TRUE);
 
        pan_filter_fd_list(&f, pw->filter_ui->filter_elements, pw->filter_ui->filter_classes);
 
@@ -374,8 +374,8 @@ static void pan_folder_tree_path(PanWindow *pw, FileData *dir_fd,
        if (!filelist_read(dir_fd, &f, &d)) return;
        if (!f && !d) return;
 
-       f = filelist_sort(f, SORT_NAME, TRUE);
-       d = filelist_sort(d, SORT_NAME, TRUE);
+       f = filelist_sort(f, SORT_NAME, TRUE, TRUE);
+       d = filelist_sort(d, SORT_NAME, TRUE, TRUE);
 
        pan_filter_fd_list(&f, pw->filter_ui->filter_elements, pw->filter_ui->filter_classes);
 
index 8f08670..2b27fd6 100644 (file)
@@ -35,7 +35,7 @@ void pan_grid_compute(PanWindow *pw, FileData *dir_fd, gint *width, gint *height
        gint grid_size;
        gint next_y;
 
-       list = pan_list_tree(dir_fd, SORT_NAME, TRUE, pw->ignore_symlinks);
+       list = pan_list_tree(dir_fd, SORT_NAME, TRUE, TRUE, pw->ignore_symlinks);
        pan_filter_fd_list(&list, pw->filter_ui->filter_elements, pw->filter_ui->filter_classes);
 
        grid_size = static_cast<gint>(sqrt(static_cast<gdouble>(g_list_length(list))));
index ef48e64..29f04c0 100644 (file)
@@ -41,18 +41,18 @@ void pan_timeline_compute(PanWindow *pw, FileData *dir_fd, gint *width, gint *he
        gint x_width;
        gint y_height;
 
-       list = pan_list_tree(dir_fd, SORT_NONE, TRUE, pw->ignore_symlinks);
+       list = pan_list_tree(dir_fd, SORT_NONE, TRUE, TRUE, pw->ignore_symlinks);
        pan_filter_fd_list(&list, pw->filter_ui->filter_elements, pw->filter_ui->filter_classes);
 
        if (pw->cache_list && pw->exif_date_enable)
                {
-               pw->cache_list = pan_cache_sort(pw->cache_list, SORT_NAME, TRUE);
-               list = filelist_sort(list, SORT_NAME, TRUE);
+               pw->cache_list = pan_cache_sort(pw->cache_list, SORT_NAME, TRUE, TRUE);
+               list = filelist_sort(list, SORT_NAME, TRUE, TRUE);
                pan_cache_sync_date(pw, list);
                }
 
-       pw->cache_list = pan_cache_sort(pw->cache_list, SORT_TIME, TRUE);
-       list = filelist_sort(list, SORT_TIME, TRUE);
+       pw->cache_list = pan_cache_sort(pw->cache_list, SORT_TIME, TRUE, TRUE);
+       list = filelist_sort(list, SORT_TIME, TRUE, TRUE);
 
        *width = PAN_BOX_BORDER * 2;
        *height = PAN_BOX_BORDER * 2;
index 4cf593b..fbb0bb2 100644 (file)
@@ -226,7 +226,7 @@ gboolean pan_is_ignored(const gchar *s, gboolean ignore_symlinks)
        return FALSE;
 }
 
-GList *pan_list_tree(FileData *dir_fd, SortType sort, gboolean ascend,
+GList *pan_list_tree(FileData *dir_fd, SortType sort, gboolean ascend, gboolean case_sensitive,
                     gboolean ignore_symlinks)
 {
        GList *flist;
@@ -237,8 +237,8 @@ GList *pan_list_tree(FileData *dir_fd, SortType sort, gboolean ascend,
        filelist_read(dir_fd, &flist, &dlist);
        if (sort != SORT_NONE)
                {
-               flist = filelist_sort(flist, sort, ascend);
-               dlist = filelist_sort(dlist, sort, ascend);
+               flist = filelist_sort(flist, sort, ascend, case_sensitive);
+               dlist = filelist_sort(dlist, sort, ascend, case_sensitive);
                }
 
        result = flist;
@@ -255,8 +255,8 @@ GList *pan_list_tree(FileData *dir_fd, SortType sort, gboolean ascend,
                        {
                        if (sort != SORT_NONE)
                                {
-                               flist = filelist_sort(flist, sort, ascend);
-                               dlist = filelist_sort(dlist, sort, ascend);
+                               flist = filelist_sort(flist, sort, ascend, case_sensitive);
+                               dlist = filelist_sort(dlist, sort, ascend, case_sensitive);
                                }
 
                        result = g_list_concat(result, flist);
index 969df95..7f1d4a2 100644 (file)
@@ -41,7 +41,7 @@ time_t pan_date_to_time(gint year, gint month, gint day);
 
 gboolean pan_is_link_loop(const gchar *s);
 gboolean pan_is_ignored(const gchar *s, gboolean ignore_symlinks);
-GList *pan_list_tree(FileData *dir_fd, SortType sort, gboolean ascend,
+GList *pan_list_tree(FileData *dir_fd, SortType sort, gboolean ascend, gboolean case_sensitive,
                     gboolean ignore_symlinks);
 
 #endif
index 15d7237..756ba53 100644 (file)
@@ -561,9 +561,9 @@ static gint pan_cache_sort_file_cb(gpointer a, gpointer b)
        auto pcb = static_cast<PanCacheData *>(b);
        return filelist_sort_compare_filedata(pca->fd, pcb->fd);
 }
-GList *pan_cache_sort(GList *list, SortType method, gboolean ascend)
+GList *pan_cache_sort(GList *list, SortType method, gboolean ascend, gboolean case_sensitive)
 {
-       return filelist_sort_full(list, method, ascend, reinterpret_cast<GCompareFunc>(pan_cache_sort_file_cb));
+       return filelist_sort_full(list, method, ascend, case_sensitive, reinterpret_cast<GCompareFunc>(pan_cache_sort_file_cb));
 }
 
 
@@ -595,7 +595,7 @@ static void pan_cache_fill(PanWindow *pw, FileData *dir_fd)
 
        pan_cache_free(pw);
 
-       list = pan_list_tree(dir_fd, SORT_NAME, TRUE, pw->ignore_symlinks);
+       list = pan_list_tree(dir_fd, SORT_NAME, TRUE, TRUE, pw->ignore_symlinks);
        pw->cache_todo = g_list_reverse(list);
 
        pw->cache_total = g_list_length(pw->cache_todo);
index a17c6ab..8ad3521 100644 (file)
@@ -31,7 +31,7 @@ void pan_layout_resize(PanWindow *pw);
 
 void pan_cache_sync_date(PanWindow *pw, GList *list);
 
-GList *pan_cache_sort(GList *list, SortType method, gboolean ascend);
+GList *pan_cache_sort(GList *list, SortType method, gboolean ascend, gboolean case_sensitive);
 
 void pan_info_update(PanWindow *pw, PanItem *pi);
 
index e93a665..de5dc59 100644 (file)
@@ -268,7 +268,6 @@ static void config_window_apply()
        if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
        if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
        if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
-       if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
        if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
        if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
 
@@ -321,7 +320,6 @@ static void config_window_apply()
        options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
 
        options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
-       options->file_sort.natural = c_options->file_sort.natural;
        options->file_filter.disable = c_options->file_filter.disable;
 
        config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, nullptr);
@@ -2658,10 +2656,7 @@ static void config_tab_files(GtkWidget *notebook)
                              options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
        pref_checkbox_new_int(group, _("Show parent folder (..)"),
                              options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
-       pref_checkbox_new_int(group, _("Case sensitive sort"),
-                             options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
-       pref_checkbox_new_int(group, _("Natural sort order - Requires restart"),
-                                         options->file_sort.natural, &c_options->file_sort.natural);
+       pref_checkbox_new_int(group, _("Case sensitive sort (Search and Collection windows, and tab completion)"), options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
        pref_checkbox_new_int(group, _("Disable file extension checks"),
                              options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
 
index 5dcc5a9..72a3530 100644 (file)
@@ -418,10 +418,7 @@ static void write_global_attributes(GString *outstr, gint indent)
        WRITE_NL(); WRITE_INT(*options, thumbnails.collection_preview);
 
        /* File sorting Options */
-       WRITE_NL(); WRITE_INT(*options, file_sort.method);
-       WRITE_NL(); WRITE_BOOL(*options, file_sort.ascending);
        WRITE_NL(); WRITE_BOOL(*options, file_sort.case_sensitive);
-       WRITE_NL(); WRITE_BOOL(*options, file_sort.natural);
 
        /* Fullscreen Options */
        WRITE_NL(); WRITE_INT(*options, fullscreen.screen);
@@ -907,10 +904,7 @@ static gboolean load_global_params(const gchar **attribute_names, const gchar **
                if (READ_BOOL(*options, thumbnails.use_ft_metadata)) continue;
 
                /* File sorting options */
-               if (READ_UINT_ENUM(*options, file_sort.method)) continue;
-               if (READ_BOOL(*options, file_sort.ascending)) continue;
                if (READ_BOOL(*options, file_sort.case_sensitive)) continue;
-               if (READ_BOOL(*options, file_sort.natural)) continue;
 
                /* File operations *options */
                if (READ_BOOL(*options, file_ops.enable_in_place_rename)) continue;
index 27f5477..fdf0341 100644 (file)
@@ -526,7 +526,7 @@ static void gr_slideshow_start_rec(const gchar *text, GIOChannel *, gpointer)
        g_free(tilde_filename);
 
        layout_valid(&lw_id);
-       list = filelist_recursive_full(dir_fd, lw_id->sort_method, lw_id->sort_ascend);
+       list = filelist_recursive_full(dir_fd, lw_id->options.file_view_list_sort.method, lw_id->options.file_view_list_sort.ascend, lw_id->options.file_view_list_sort.case_sensitive);
        file_data_unref(dir_fd);
        if (!list) return;
 
index 4d6544a..314a2a9 100644 (file)
@@ -2517,12 +2517,12 @@ static gboolean search_step_cb(gpointer data)
 
                if (success)
                        {
-                       list = filelist_sort(list, SORT_NAME, TRUE);
+                       list = filelist_sort(list, SORT_NAME, TRUE, TRUE);
                        sd->search_file_list = list;
 
                        if (sd->search_path_recurse)
                                {
-                               dlist = filelist_sort(dlist, SORT_NAME, TRUE);
+                               dlist = filelist_sort(dlist, SORT_NAME, TRUE, TRUE);
                                sd->search_folder_list = g_list_concat(dlist, sd->search_folder_list);
                                }
                        else
@@ -2874,7 +2874,7 @@ static gint search_result_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIt
                        return sort_matchdata_dimensions(fda, fdb);
                        break;
                case SEARCH_COLUMN_PATH:
-                       return utf8_compare(fda->fd->path, fdb->fd->path, options->file_sort.case_sensitive);
+                       return utf8_compare(fda->fd->path, fdb->fd->path, TRUE);
                        break;
                default:
                        break;
index 23466fb..31440fb 100644 (file)
@@ -74,7 +74,7 @@ static gint file_util_safe_number(gint64 free_space)
 
                if (!sorted)
                        {
-                       list = filelist_sort(list, SORT_NAME, TRUE);
+                       list = filelist_sort(list, SORT_NAME, TRUE, TRUE);
                        sorted = TRUE;
                        }
 
index 53dadae..8fae7db 100644 (file)
@@ -83,6 +83,7 @@ enum SortType {
        SORT_TIME,
        SORT_CTIME,
        SORT_PATH,
+       SORT_NUMBER,
        SORT_EXIFTIME,
        SORT_EXIFTIMEDIGITIZED,
        SORT_RATING,
@@ -613,6 +614,8 @@ struct FileData {
        gchar *format_name; /**< set by the image loader */
        gchar *collate_key_name;
        gchar *collate_key_name_nocase;
+       gchar *collate_key_name_natural;
+       gchar *collate_key_name_nocase_natural;
        gint64 size;
        time_t date;
        time_t cdate;
@@ -672,8 +675,15 @@ struct LayoutOptions
        struct {
                SortType method;
                gboolean ascend;
+               gboolean case_sensitive;
        } dir_view_list_sort;
 
+       struct {
+               SortType method;
+               gboolean ascend;
+               gboolean case_sensitive;
+       } file_view_list_sort;
+
        gboolean show_thumbnails;
        gboolean show_marks;
        gboolean show_file_filter;
@@ -845,9 +855,6 @@ struct LayoutWindow
 
        GtkWidget *file_view;
 
-       SortType sort_method;
-       gboolean sort_ascend;
-
        GtkWidget *info_box; /**< status bar */
        GtkWidget *info_progress_bar; /**< status bar */
        GtkWidget *info_sort; /**< status bar */
@@ -948,6 +955,7 @@ struct ViewFile
 
        SortType sort_method;
        gboolean sort_ascend;
+       gboolean sort_case;
 
        /* func list */
        void (*func_thumb_status)(ViewFile *vf, gdouble val, const gchar *text, gpointer data);
index e267fc9..61ebab0 100644 (file)
@@ -139,18 +139,20 @@ static gboolean vdlist_populate(ViewDir *vd, gboolean clear)
        FileData *fd;
        SortType sort_type = SORT_NAME;
        gboolean sort_ascend = TRUE;
+       gboolean sort_case = TRUE;
        gchar *link = nullptr;
 
        if (vd->layout)
                {
                sort_type = vd->layout->options.dir_view_list_sort.method;
                sort_ascend = vd->layout->options.dir_view_list_sort.ascend;
+               sort_case = vd->layout->options.dir_view_list_sort.case_sensitive;
                }
 
        old_list = VDLIST(vd)->list;
 
        ret = filelist_read(vd->dir_fd, nullptr, &VDLIST(vd)->list);
-       VDLIST(vd)->list = filelist_sort(VDLIST(vd)->list, sort_type, sort_ascend);
+       VDLIST(vd)->list = filelist_sort(VDLIST(vd)->list, sort_type, sort_ascend, sort_case);
 
        /* add . and .. */
 
index d7e161a..a7b58e8 100644 (file)
@@ -971,10 +971,11 @@ static void vdtree_row_collapsed(GtkTreeView *treeview, GtkTreeIter *iter, GtkTr
                }
 }
 
-static gint vdtree_sort_cb(GtkTreeModel *store, GtkTreeIter *a, GtkTreeIter *b, gpointer)
+static gint vdtree_sort_cb(GtkTreeModel *store, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
 {
        NodeData *nda;
        NodeData *ndb;
+       auto vd = static_cast<ViewDir *>(data);
 
        gtk_tree_model_get(store, a, DIR_COLUMN_POINTER, &nda, -1);
        gtk_tree_model_get(store, b, DIR_COLUMN_POINTER, &ndb, -1);
@@ -983,10 +984,34 @@ static gint vdtree_sort_cb(GtkTreeModel *store, GtkTreeIter *a, GtkTreeIter *b,
        if (!nda->fd) return 1;
        if (!ndb->fd) return -1;
 
-       if (options->file_sort.case_sensitive)
-               return strcmp(nda->fd->collate_key_name, ndb->fd->collate_key_name);
+       if (vd->layout->options.dir_view_list_sort.method == SORT_NUMBER)
+               {
+               if (vd->layout->options.dir_view_list_sort.case_sensitive == TRUE)
+                       {
+                       return strcmp(nda->fd->collate_key_name_natural, ndb->fd->collate_key_name_natural);
+                       }
+               else
+                       {
+                       return strcmp(nda->fd->collate_key_name_nocase_natural, ndb->fd->collate_key_name_nocase_natural);
+                       }
+               }
+       else if (vd->layout->options.dir_view_list_sort.method == SORT_TIME)
+               {
+               if (nda->fd->date < ndb->fd->date) return -1;
+               if (nda->fd->date > ndb->fd->date) return 1;
+               return 0;
+               }
        else
-               return strcmp(nda->fd->collate_key_name_nocase, ndb->fd->collate_key_name_nocase);
+               {
+               if (vd->layout->options.dir_view_list_sort.case_sensitive == TRUE)
+                       {
+                       return strcmp(nda->fd->collate_key_name, ndb->fd->collate_key_name);
+                       }
+               else
+                       {
+                       return strcmp(nda->fd->collate_key_name_nocase, ndb->fd->collate_key_name_nocase);
+                       }
+               }
 }
 
 /*
index b320546..85644c2 100644 (file)
@@ -556,7 +556,7 @@ static void vd_pop_menu_slide_rec_cb(GtkWidget *, gpointer data)
        if (!vd->layout) return;
        if (!vd->click_fd) return;
 
-       list = filelist_recursive_full(vd->click_fd, vd->layout->sort_method, vd->layout->sort_ascend);
+       list = filelist_recursive_full(vd->click_fd, vd->layout->options.file_view_list_sort.method, vd->layout->options.file_view_list_sort.ascend, vd->layout->options.file_view_list_sort.case_sensitive);
 
        layout_image_slideshow_stop(vd->layout);
        layout_image_slideshow_start_from_list(vd->layout, list);
@@ -722,7 +722,22 @@ static void vd_pop_menu_sort_ascend_cb(GtkWidget *widget, gpointer data)
        if (!vd->layout) return;
 
        ascend = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
-       layout_views_set_sort(vd->layout, vd->layout->options.dir_view_list_sort.method, ascend);
+       layout_views_set_sort_dir(vd->layout, vd->layout->options.dir_view_list_sort.method, ascend, vd->layout->options.dir_view_list_sort.case_sensitive);
+
+       if (vd->layout) layout_refresh(vd->layout);
+}
+
+static void vd_pop_menu_sort_case_cb(GtkWidget *widget, gpointer data)
+{
+       auto vd = static_cast<ViewDir *>(data);
+       gboolean case_sensitive;
+
+       if (!vd) return;
+
+       if (!vd->layout) return;
+
+       case_sensitive = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
+       layout_views_set_sort_dir(vd->layout, vd->layout->options.dir_view_list_sort.method, vd->layout->options.dir_view_list_sort.ascend, case_sensitive);
 
        if (vd->layout) layout_refresh(vd->layout);
 }
@@ -739,9 +754,9 @@ static void vd_pop_menu_sort_cb(GtkWidget *widget, gpointer data)
 
        type = static_cast<SortType>GPOINTER_TO_INT(data);
 
-       if (type == SORT_NAME || type == SORT_TIME)
+       if (type == SORT_NAME || type == SORT_NUMBER || type == SORT_TIME)
                {
-               layout_views_set_sort(vd->layout, type, vd->layout->options.dir_view_list_sort.ascend);
+               layout_views_set_sort_dir(vd->layout, type, vd->layout->options.dir_view_list_sort.ascend, vd->layout->options.dir_view_list_sort.case_sensitive);
 
                if (vd->layout) layout_refresh(vd->layout);
                }
@@ -834,6 +849,14 @@ GtkWidget *vd_pop_menu(ViewDir *vd, FileData *fd)
                {
                submenu = submenu_add_dir_sort(nullptr, G_CALLBACK(vd_pop_menu_sort_cb), vd, FALSE, FALSE, TRUE, vd->layout->options.dir_view_list_sort.method);
                menu_item_add_check(submenu, _("Ascending"), vd->layout->options.dir_view_list_sort.ascend, G_CALLBACK(vd_pop_menu_sort_ascend_cb), (vd));
+               menu_item_add_check(submenu, _("Case"), vd->layout->options.dir_view_list_sort.case_sensitive, G_CALLBACK(vd_pop_menu_sort_case_cb), (vd));
+               item = menu_item_add(menu, _("_Sort"), nullptr, nullptr);
+               gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
+               }
+
+       if (vd->type == DIRVIEW_TREE)
+               {
+               submenu = submenu_add_dir_sort(nullptr, G_CALLBACK(vd_pop_menu_sort_cb), vd, FALSE, FALSE, TRUE, vd->layout->options.dir_view_list_sort.method);
                item = menu_item_add(menu, _("_Sort"), nullptr, nullptr);
                gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
                }
index 16297da..39bd0c8 100644 (file)
@@ -40,7 +40,7 @@ void vf_refresh_idle(ViewFile *vf);
 void vf_thumb_set(ViewFile *vf, gboolean enable);
 void vf_marks_set(ViewFile *vf, gboolean enable);
 void vf_star_rating_set(ViewFile *vf, gboolean enable);
-void vf_sort_set(ViewFile *vf, SortType type, gboolean ascend);
+void vf_sort_set(ViewFile *vf, SortType type, gboolean ascend, gboolean case_sensitive);
 
 guint vf_marks_get_filter(ViewFile *vf);
 void vf_mark_filter_toggle(ViewFile *vf, gint mark);
index a9a5c8b..b2a97cb 100644 (file)
@@ -1675,12 +1675,13 @@ static void vficon_sized_cb(GtkWidget *, GtkAllocation *allocation, gpointer dat
  *-----------------------------------------------------------------------------
  */
 
-void vficon_sort_set(ViewFile *vf, SortType type, gboolean ascend)
+void vficon_sort_set(ViewFile *vf, SortType type, gboolean ascend, gboolean case_sensitive)
 {
-       if (vf->sort_method == type && vf->sort_ascend == ascend) return;
+       if (vf->sort_method == type && vf->sort_ascend == ascend && vf->sort_case == case_sensitive) return;
 
        vf->sort_method = type;
        vf->sort_ascend = ascend;
+       vf->sort_case = case_sensitive;
 
        if (!vf->list) return;
 
@@ -1917,8 +1918,8 @@ static gboolean vficon_refresh_real(ViewFile *vf, gboolean keep_position)
 
                }
 
-       vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend); /* the list might not be sorted if there were renames */
-       new_filelist = filelist_sort(new_filelist, vf->sort_method, vf->sort_ascend);
+       vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend, vf->sort_case); /* the list might not be sorted if there were renames */
+       new_filelist = filelist_sort(new_filelist, vf->sort_method, vf->sort_ascend, vf->sort_case);
 
        if (VFICON(vf)->selection)
                {
index a8d2c71..2eea08f 100644 (file)
@@ -36,7 +36,7 @@ ViewFile *vficon_new(ViewFile *vf, FileData *dir_fd);
 gboolean vficon_set_fd(ViewFile *vf, FileData *dir_fd);
 gboolean vficon_refresh(ViewFile *vf);
 
-void vficon_sort_set(ViewFile *vf, SortType type, gboolean ascend);
+void vficon_sort_set(ViewFile *vf, SortType type, gboolean ascend, gboolean case_sensitive);
 
 void vficon_marks_set(ViewFile *vf, gboolean enable);
 void vficon_star_rating_set(ViewFile *vf, gboolean enable);
index 0e2c7b5..e70f993 100644 (file)
@@ -1083,14 +1083,14 @@ static void vflist_setup_iter_recursive(ViewFile *vf, GtkTreeStore *store, GtkTr
                }
 }
 
-void vflist_sort_set(ViewFile *vf, SortType type, gboolean ascend)
+void vflist_sort_set(ViewFile *vf, SortType type, gboolean ascend, gboolean case_sensitive)
 {
        gint i;
        GHashTable *fd_idx_hash = g_hash_table_new(nullptr, nullptr);
        GtkTreeStore *store;
        GList *work;
 
-       if (vf->sort_method == type && vf->sort_ascend == ascend) return;
+       if (vf->sort_method == type && vf->sort_ascend == ascend && vf->sort_case == case_sensitive) return;
        if (!vf->list) return;
 
        work = vf->list;
@@ -1105,8 +1105,9 @@ void vflist_sort_set(ViewFile *vf, SortType type, gboolean ascend)
 
        vf->sort_method = type;
        vf->sort_ascend = ascend;
+       vf->sort_case = case_sensitive;
 
-       vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
+       vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend, vf->sort_case);
 
        std::vector<gint> new_order;
        new_order.reserve(i);
@@ -1933,7 +1934,7 @@ gboolean vflist_refresh(ViewFile *vf)
                file_data_register_notify_func(vf_notify_cb, vf, NOTIFY_PRIORITY_MEDIUM);
 
                DEBUG_1("%s vflist_refresh: sort", get_exec_time());
-               vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
+               vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend, vf->sort_case);
                }
 
        DEBUG_1("%s vflist_refresh: populate view", get_exec_time());
index f8139f1..394fab8 100644 (file)
@@ -39,7 +39,7 @@ gboolean vflist_refresh(ViewFile *vf);
 void vflist_thumb_set(ViewFile *vf, gboolean enable);
 void vflist_marks_set(ViewFile *vf, gboolean enable);
 void vflist_star_rating_set(ViewFile *vf, gboolean enable);
-void vflist_sort_set(ViewFile *vf, SortType type, gboolean ascend);
+void vflist_sort_set(ViewFile *vf, SortType type, gboolean ascend, gboolean case_sensitive);
 
 GList *vflist_selection_get_one(ViewFile *vf, FileData *fd);
 GList *vflist_pop_menu_file_list(ViewFile *vf);
index ea1b8f9..878c328 100644 (file)
@@ -53,12 +53,12 @@ void vf_send_update(ViewFile *vf)
  *-----------------------------------------------------------------------------
  */
 
-void vf_sort_set(ViewFile *vf, SortType type, gboolean ascend)
+void vf_sort_set(ViewFile *vf, SortType type, gboolean ascend, gboolean case_sensitive)
 {
        switch (vf->type)
        {
-       case FILEVIEW_LIST: vflist_sort_set(vf, type, ascend); break;
-       case FILEVIEW_ICON: vficon_sort_set(vf, type, ascend); break;
+       case FILEVIEW_LIST: vflist_sort_set(vf, type, ascend, case_sensitive); break;
+       case FILEVIEW_ICON: vficon_sort_set(vf, type, ascend, case_sensitive); break;
        }
 }
 
@@ -491,11 +491,11 @@ static void vf_pop_menu_sort_cb(GtkWidget *widget, gpointer data)
 
        if (vf->layout)
                {
-               layout_sort_set(vf->layout, type, vf->sort_ascend);
+               layout_sort_set_files(vf->layout, type, vf->sort_ascend, vf->sort_case);
                }
        else
                {
-               vf_sort_set(vf, type, vf->sort_ascend);
+               vf_sort_set(vf, type, vf->sort_ascend, vf->sort_case);
                }
 }
 
@@ -505,11 +505,25 @@ static void vf_pop_menu_sort_ascend_cb(GtkWidget *, gpointer data)
 
        if (vf->layout)
                {
-               layout_sort_set(vf->layout, vf->sort_method, !vf->sort_ascend);
+               layout_sort_set_files(vf->layout, vf->sort_method, !vf->sort_ascend, vf->sort_case);
                }
        else
                {
-               vf_sort_set(vf, vf->sort_method, !vf->sort_ascend);
+               vf_sort_set(vf, vf->sort_method, !vf->sort_ascend, vf->sort_case);
+               }
+}
+
+static void vf_pop_menu_sort_case_cb(GtkWidget *, gpointer data)
+{
+       auto vf = static_cast<ViewFile *>(data);
+
+       if (vf->layout)
+               {
+               layout_sort_set_files(vf->layout, vf->sort_method, vf->sort_ascend, !vf->sort_case);
+               }
+       else
+               {
+               vf_sort_set(vf, vf->sort_method, vf->sort_ascend, !vf->sort_case);
                }
 }
 
@@ -739,6 +753,8 @@ GtkWidget *vf_pop_menu(ViewFile *vf)
        menu_item_add_divider(submenu);
        menu_item_add_check(submenu, _("Ascending"), vf->sort_ascend,
                            G_CALLBACK(vf_pop_menu_sort_ascend_cb), vf);
+       menu_item_add_check(submenu, _("Case"), vf->sort_ascend,
+                           G_CALLBACK(vf_pop_menu_sort_case_cb), vf);
 
        item = menu_item_add(menu, _("_Sort"), nullptr, nullptr);
        gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);