UI: Update order of profiles and scene collections in their menus

The old method to update the profile menu iterated over the directory
entries of the profile directory in the order provided by the operating
system.

The system calls used for this explicitly state that the order of items
is "undefined" but seems to have followed a case-insensitive
alphabetical order on Windows, an order which users have come to expect.

The new code uses a std::map to store discovered profiles and scene
collections, which is ordered by key and with std::string used for keys
this means a lexicographical sorting of keys which is case-sensitive.

To restore the old behavior, profiles and scene collections need to be
added to their respective menus sorted by case-insensitive order, which
has to be done manually before adding the items.
This commit is contained in:
PatTheMav
2024-10-18 14:07:38 +02:00
committed by Ryan Foster
parent 39b91d8875
commit 918fe6171d
2 changed files with 83 additions and 16 deletions

View File

@@ -43,6 +43,30 @@ extern void DuplicateCurrentCookieProfile(ConfigFile &config);
extern void CheckExistingCookieId();
extern void DeleteCookies();
// MARK: - Anonymous Namespace
namespace {
QList<QString> sortedProfiles{};
void updateSortedProfiles(const OBSProfileCache &profiles)
{
const QLocale locale = QLocale::system();
QList<QString> newList{};
for (auto [profileName, _] : profiles) {
QString entry = QString::fromStdString(profileName);
newList.append(entry);
}
std::sort(newList.begin(), newList.end(), [&locale](const QString &lhs, const QString &rhs) -> bool {
int result = QString::localeAwareCompare(locale.toLower(lhs), locale.toLower(rhs));
return (result < 0);
});
sortedProfiles.swap(newList);
}
} // namespace
// MARK: - Main Profile Management Functions
void OBSBasic::SetupNewProfile(const std::string &profileName, bool useWizard)
@@ -277,18 +301,27 @@ void OBSBasic::RefreshProfiles(bool refreshCache)
if (refreshCache) {
RefreshProfileCache();
}
updateSortedProfiles(profiles);
size_t numAddedProfiles = 0;
for (auto &[profileName, profile] : profiles) {
QAction *action = new QAction(QString().fromStdString(profileName), this);
action->setProperty("file_name", QString().fromStdString(profile.directoryName));
connect(action, &QAction::triggered, this, &OBSBasic::ChangeProfile);
action->setCheckable(true);
action->setChecked(profileName == currentProfileName);
for (auto &name : sortedProfiles) {
const std::string profileName = name.toStdString();
try {
OBSProfile &profile = profiles.at(profileName);
ui->profileMenu->addAction(action);
QAction *action = new QAction(QString().fromStdString(profileName), this);
action->setProperty("file_name", QString().fromStdString(profile.directoryName));
connect(action, &QAction::triggered, this, &OBSBasic::ChangeProfile);
action->setCheckable(true);
action->setChecked(profileName == currentProfileName);
numAddedProfiles += 1;
ui->profileMenu->addAction(action);
numAddedProfiles += 1;
} catch (const std::out_of_range &error) {
blog(LOG_ERROR, "No profile with name %s found in profile cache.\n%s", profileName.c_str(),
error.what());
}
}
ui->actionRemoveProfile->setEnabled(numAddedProfiles > 1);