Deduplicate games found from multiple sources

When a game appears as both a Steam manifest and an XDG
desktop entry, drop the desktop duplicate. Steam entries are
preferred because they carry cover artwork and route through
the Steam launcher for Proton compatibility.
This commit is contained in:
Marco Allegretti 2026-04-20 11:24:03 +02:00
parent d58f691c7a
commit 764a8708f6
2 changed files with 24 additions and 0 deletions

View file

@ -92,6 +92,10 @@ void GameLauncherProvider::refresh()
loadFlatpakGames();
loadRecentTimestamps();
// Deduplicate: when the same game appears from multiple sources,
// prefer Steam (has artwork + Proton handling) over desktop.
deduplicateGames();
// Sort alphabetically, case-insensitive
std::sort(m_allGames.begin(), m_allGames.end(), [](const GameEntry &a, const GameEntry &b) {
return a.name.compare(b.name, Qt::CaseInsensitive) < 0;
@ -182,6 +186,25 @@ void GameLauncherProvider::launchByStorageId(const QString &storageId)
}
}
void GameLauncherProvider::deduplicateGames()
{
// Build a set of names from Steam entries (case-insensitive).
QSet<QString> steamNames;
for (const auto &g : std::as_const(m_allGames)) {
if (g.source == QLatin1String("steam")) {
steamNames.insert(g.name.toLower());
}
}
// Remove desktop entries whose name matches a Steam entry.
m_allGames.erase(std::remove_if(m_allGames.begin(),
m_allGames.end(),
[&steamNames](const GameEntry &g) {
return g.source == QLatin1String("desktop") && steamNames.contains(g.name.toLower());
}),
m_allGames.end());
}
// --- XDG .desktop games ---
void GameLauncherProvider::loadDesktopGames()

View file

@ -74,6 +74,7 @@ private:
void loadDesktopGames();
void loadSteamGames();
void loadFlatpakGames();
void deduplicateGames();
void loadRecentTimestamps();
void saveRecentTimestamp(const QString &storageId, const QDateTime &when);
void applyFilter();