Skip to content

Commit b1ba002

Browse files
committed
FSUI: Use locale sensitive sort for game list
1 parent 8ddf9ea commit b1ba002

File tree

4 files changed

+55
-2
lines changed

4 files changed

+55
-2
lines changed

pcsx2-qt/Translations.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ namespace QtHost
7171

7272
static QLocale s_current_locale;
7373
static QCollator s_current_collator;
74+
static std::mutex s_collator_mtx;
7475

7576
static std::vector<QTranslator*> s_translators;
7677
} // namespace QtHost
@@ -122,7 +123,10 @@ void QtHost::InstallTranslator(QWidget* dialog_parent)
122123
QString qlanguage = language;
123124
qlanguage.replace('-', '_');
124125
s_current_locale = QLocale(qlanguage);
125-
s_current_collator = QCollator(s_current_locale);
126+
{
127+
std::lock_guard<std::mutex> guard(s_collator_mtx);
128+
s_current_collator = QCollator(s_current_locale);
129+
}
126130

127131
// Install the base qt translation first.
128132
#if defined(__APPLE__)
@@ -693,3 +697,11 @@ int QtHost::LocaleSensitiveCompare(QStringView lhs, QStringView rhs)
693697
{
694698
return s_current_collator.compare(lhs, rhs);
695699
}
700+
701+
int Host::LocaleSensitiveCompare(std::string_view lhs, std::string_view rhs)
702+
{
703+
QString qlhs = QString::fromUtf8(lhs.data(), lhs.size());
704+
QString qrhs = QString::fromUtf8(rhs.data(), rhs.size());
705+
std::lock_guard<std::mutex> guard(QtHost::s_collator_mtx);
706+
return QtHost::s_current_collator.compare(qlhs, qrhs);
707+
}

pcsx2/Host.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ namespace Host
149149
/// Creates a progress callback that displays in the host.
150150
std::unique_ptr<ProgressCallback> CreateHostProgressCallback();
151151

152+
/// Compare strings in the locale of the current UI language from any thread. Prefer the QtHost version if you can use it.
153+
int LocaleSensitiveCompare(std::string_view lhs, std::string_view rhs);
154+
152155
namespace Internal
153156
{
154157
/// Retrieves the base settings layer. Must call with lock held.

pcsx2/ImGui/FullscreenUI.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7684,11 +7684,41 @@ void FullscreenUI::PopulateGameListEntryList()
76847684
{
76857685
const int sort = Host::GetBaseIntSettingValue("UI", "FullscreenUIGameSort", 0);
76867686
const bool reverse = Host::GetBaseBoolSettingValue("UI", "FullscreenUIGameSortReverse", false);
7687+
static int s_last_sort = -1;
7688+
static bool s_last_reverse = false;
7689+
static bool s_last_prefer_eng = false;
7690+
static std::vector<const GameList::Entry*> s_last_unsorted_entries;
76877691

7692+
// Sort can be expensive, try to avoid when possible
76887693
const u32 count = GameList::GetEntryCount();
7694+
bool needs_update = sort != s_last_sort || reverse != s_last_reverse || s_last_prefer_eng != s_prefer_english_titles;
7695+
needs_update |= count != s_last_unsorted_entries.size();
7696+
if (!needs_update)
7697+
{
7698+
for (u32 i = 0; i < count; i++)
7699+
{
7700+
if (GameList::GetEntryByIndex(i) != s_last_unsorted_entries[i])
7701+
{
7702+
needs_update = true;
7703+
break;
7704+
}
7705+
}
7706+
}
7707+
7708+
if (!needs_update)
7709+
return;
7710+
7711+
s_last_sort = sort;
7712+
s_last_reverse = reverse;
7713+
s_last_prefer_eng = s_prefer_english_titles;
7714+
76897715
s_game_list_sorted_entries.resize(count);
7716+
s_last_unsorted_entries.resize(count);
76907717
for (u32 i = 0; i < count; i++)
7718+
{
76917719
s_game_list_sorted_entries[i] = GameList::GetEntryByIndex(i);
7720+
s_last_unsorted_entries[i] = s_game_list_sorted_entries[i];
7721+
}
76927722

76937723
std::sort(s_game_list_sorted_entries.begin(), s_game_list_sorted_entries.end(),
76947724
[sort, reverse](const GameList::Entry* lhs, const GameList::Entry* rhs) {
@@ -7759,7 +7789,7 @@ void FullscreenUI::PopulateGameListEntryList()
77597789
}
77607790

77617791
// fallback to title when all else is equal
7762-
const int res = StringUtil::Strcasecmp(lhs->GetTitleSort(s_prefer_english_titles).c_str(), rhs->GetTitleSort(s_prefer_english_titles).c_str());
7792+
const int res = Host::LocaleSensitiveCompare(lhs->GetTitleSort(s_prefer_english_titles), rhs->GetTitleSort(s_prefer_english_titles));
77637793
return reverse ? (res > 0) : (res < 0);
77647794
});
77657795
}

tests/ctest/core/StubHost.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,14 @@ void Host::OpenHostFileSelectorAsync(std::string_view title, bool select_directo
271271
callback(std::string());
272272
}
273273

274+
int Host::LocaleSensitiveCompare(std::string_view lhs, std::string_view rhs)
275+
{
276+
int res = std::strncmp(lhs.data(), rhs.data(), std::min(lhs.size(), rhs.size()));
277+
if (res != 0)
278+
return res;
279+
return lhs.size() > rhs.size() ? 1 : lhs.size() < rhs.size() ? -1 : 0;
280+
}
281+
274282
std::optional<u32> InputManager::ConvertHostKeyboardStringToCode(const std::string_view str)
275283
{
276284
return std::nullopt;

0 commit comments

Comments
 (0)