Skip to content

frontend, libobs, plugins: Natural sorting for files, profile and scene names - #12577

Open
Dankirk wants to merge 6 commits into
obsproject:masterfrom
Dankirk:natsort
Open

frontend, libobs, plugins: Natural sorting for files, profile and scene names#12577
Dankirk wants to merge 6 commits into
obsproject:masterfrom
Dankirk:natsort

Conversation

@Dankirk

@Dankirk Dankirk commented Sep 3, 2025

Copy link
Copy Markdown

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, os_locale_t locale);
EXPORT int wstrnatcmp(const wchar_t *str1, const wchar_t *str2, os_locale_t locale);

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.

OBS doesn't currently use process wide system locale for C/C++ on Windows (issue disussed here #12624), so new locale apis are added to libobs platform library and documentation added. These can be used to do locale aware comparison / sorting in C directly and are used as basis for the main things astrnatcmp and wstrnatcmp.

EXPORT int os_strcoll_l(const char *a, const char *b, os_locale_t locale);
EXPORT int os_wcscoll_l(const wchar_t *a, const wchar_t *b, os_locale_t locale);
EXPORT os_locale_t os_get_locale(const char *locale);
EXPORT void os_free_locale(os_locale_t locale);
EXPORT void os_locale_aware_sort(void *base, size_t elements, size_t element_size, os_locale_aware_cmp cmp,
				 os_locale_t locale);

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
@sebastian-s-beckmann sebastian-s-beckmann added the area/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

Dankirk commented Sep 5, 2025

Copy link
Copy Markdown
Author

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
Comment thread libobs/util/dstr.h Outdated
Comment thread frontend/widgets/OBSBasic.hpp Outdated
Comment thread docs/sphinx/reference-libobs-util-dstr.rst Outdated
Comment thread libobs/util/dstr.c Outdated

@Warchamp7 Warchamp7 left a comment

Copy link
Copy Markdown
Member

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
@Dankirk

Dankirk commented Feb 16, 2026

Copy link
Copy Markdown
Author

I addressed the lack of locale-awareness on Windows by adding some new apis to libsobs/util/platform. They provide the generic locale aware comparison and sorting, but also a convenience function for sorted directory file listing with the existing dir apis. The apis like os_locale_aware_sort can be used with standard *_l comparison functions that take locale as a third parameter like wcscoll_l or rather it's platform agnostic version os_wcscoll_l, or a custom one like the added wstrnatcmp.

Updated the pr description and documentation updates are included.

Dankirk added 6 commits June 10, 2026 19:48
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.
Adds locale aware functions for libobs and makes slideshow and vlc plugins use them for natural, locale aware file sorting.

Adds documentation for the new locale apis.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/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