Skip to content

Conversation

@Dankirk
Copy link

@Dankirk Dankirk commented Sep 3, 2025

Description

Applies natural, locale aware sorting when drag&dropping many sources at once and to profile and scene names in menus. For slideshow (mk2) and VLC the files in added directories are cycled using this sorting method instead of an arbitrary order. The order of items in the slideshow listbox is otherwise preserved.

For background: Natural sort means sorting by numerical value. Alphabetical sort arranges numbers like this: 1 < 10 < 11 < 2 < 3.
Natural sort does it this way: 1 < 2 < 3 < 10 < 11.
The natural sort is what Windows explorer uses under the hood when you sort by name or use ls -v on unix.

For general use, qt-wrappers has couple new methods for natural sorting:

template<typename T, typename Callback> void NaturalSort(QList<T> &list, Callback extractor, bool reverse = false)
template<typename T> void NaturalSort(QList<T> &list, bool reverse = false)

The list parameter is sorted using locale and number value aware algorithm with QCollator. It works with QString and QStringView. System locale is used to achieve the locale-aware sorting.

For lower level stuff in C, like slideshow plugin, there's new comparison functions for char* and wchar_t* in dstr library.

EXPORT int astrnatcmp(const char *str1, const char *str2);
EXPORT int wstrnatcmp(const wchar_t *str1, const wchar_t *str2);

The return value is <0, 0 or >0 as expected for return value of qsort()'s callback function. This sorting uses strcoll() and wcscoll() respectively for locale aware sorting, but does natural number sorting using a custom implementation. The locale aware sorting, however, is currently with limited use on Windows, as the program is using the process wide 'C' locale. Changing this behavior is out of this PR scope, so I made another here #12624.

OBSBasic_Dropfiles.cpp has somewhat sizable changes, due to how late the names for listed sources were acquired. This changes it so names are gathered first for sorting and only later added to the UI.

Motivation and Context

Fixes #10382
Couple requests on forums here and here. Most recently I saw a Youtuber mention this during a live stream.

The issue is with filenames and other listings that contain incremental numbers which are not sorted intuitively when sorted alphabetically. In fact the alphabetical sorting is also coincidental, since the methods for iterating over files give no guarantee about the order.

How Has This Been Tested?

I tested the features with files in directories with the following file names to see if they are sorted correctly:
testnames.txt
The files should appear in the order listed for en_FI locale. The files with 'ä' or 'ö' could be in another place for different locales. The important part is the numerical comparison works, so 5.jpg is before 10.jpg while the opposite is true for basic alphabetical sorting.

I'm on Windows 11 English US version, but with Finnish region/locale settings.

Types of changes

  • New feature (non-breaking change which adds functionality)

Checklist:

  • My code has been run through clang-format.
  • I have read the contributing document.
  • My code is not on the master branch.
  • The code has been tested.
  • All commit messages are properly formatted and commits squashed where appropriate.
  • I have included updates to all appropriate documentation.

@Dankirk Dankirk changed the title frontend: Natural sorting for files, profle and scene names frontend: Natural sorting for files, profile and scene names Sep 3, 2025
@gxalpha gxalpha added the UI/UX Anything to do with changes or additions to UI/UX elements. label Sep 3, 2025
@Dankirk Dankirk changed the title frontend: Natural sorting for files, profile and scene names frontend, libobs, plugins: Natural sorting for files, profile and scene names Sep 5, 2025
@Dankirk
Copy link
Author

Dankirk commented Sep 5, 2025

Updated the list of filenames I tested the sorting with and I'm happy with the results.

One issue remains:
For image slideshow directories, the sorting is not locale aware (natural sort works), because the app uses the default 'C' locale. The app does call QLocale::setDefault() for Qt based things during app start, but does not call setlocale() for lower level functions. For sorting purposes setting LC_COLLATE with setlocale() would suffice, but it is uncertain how much that affects other things. Parts that can use qt-wrapper, use QCollator instead with system locale. For plain C I can't seem to find any multithreading safe ways to use different locale temporarily.

There is also a question if the default locale set with QLocale should actually be the system locale instead of the app language/translations locale? If so, could we then also do so with setlocale() to match?
This is a bit out of this PR scope though.

@Dankirk Dankirk force-pushed the natsort branch 2 times, most recently from b12ac87 to 35c77a8 Compare September 6, 2025 21:29
@gxalpha gxalpha requested a review from Warchamp7 September 7, 2025 11:09
@Dankirk Dankirk requested a review from gxalpha September 7, 2025 18:04
Copy link
Member

@Warchamp7 Warchamp7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving on a conceptual/UX level, but others will need to speak to the technical implications

@Dankirk Dankirk force-pushed the natsort branch 2 times, most recently from 28140c8 to 1c78f24 Compare December 18, 2025 00:05
Sort drag&dropped sources using locale-aware natural sorting with QCollator and system locale.
Change locale-aware sorting of profiles and scene collections in menus to locale-aware natural sorting, so number sequences in names are treated by value rather than their alphabetical order.
New comparison methods astrnatcmpi() and wstrnatcmpi() for sorting strings and documentation for them. Uses locale aware strcol() / wcscoll() and a custom implementation of natural comparison for number sequences. Supports multibyte and whcar surrogate characters.

This is intended to be used for parts that do not have direct access to higher level methods like Qt QCollator.
Applies locale-aware natural sorting to the cycled files when adding directory to image slideshow. Previously files in directories were cycled in arbitrary order by os_readdir().

Locale-awareness is limited on Windows currently, because we are using minimal 'C' locale for it. This is to be addressed separately.
Applies the same natural, alphabetical sort to vlc playlist directories that was added for slideshow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

UI/UX Anything to do with changes or additions to UI/UX elements.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Images in slideshow are not ordered if added by folder (random setting is disabled)

4 participants