mirror of
https://invent.kde.org/marcoa/a-la-karte.git
synced 2026-02-09 21:13:08 +00:00
Fix desktop and Flatpak game detection
Use KDesktopFile/KConfigGroup to parse .desktop files reliably. This avoids Categories parsing pitfalls and improves detection of KDE stock games. Centralize game-category matching and use stable IDs based on the full desktop-file basename.
This commit is contained in:
parent
747b02035a
commit
e468f53c91
4 changed files with 64 additions and 71 deletions
|
|
@ -3,10 +3,11 @@
|
||||||
|
|
||||||
#include "desktopimporter.h"
|
#include "desktopimporter.h"
|
||||||
|
|
||||||
|
#include <KConfigGroup>
|
||||||
|
#include <KDesktopFile>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QSettings>
|
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
DesktopImporter::DesktopImporter(QObject *parent)
|
DesktopImporter::DesktopImporter(QObject *parent)
|
||||||
|
|
@ -63,58 +64,38 @@ QStringList DesktopImporter::getDesktopFilePaths() const
|
||||||
|
|
||||||
bool DesktopImporter::isGameDesktopFile(const QString &filePath) const
|
bool DesktopImporter::isGameDesktopFile(const QString &filePath) const
|
||||||
{
|
{
|
||||||
QSettings desktop(filePath, QSettings::IniFormat);
|
KDesktopFile desktopFile(filePath);
|
||||||
desktop.beginGroup(QStringLiteral("Desktop Entry"));
|
KConfigGroup desktop = desktopFile.desktopGroup();
|
||||||
|
|
||||||
QString type = desktop.value(QStringLiteral("Type")).toString();
|
const QString type = desktop.readEntry(QStringLiteral("Type"));
|
||||||
if (type != QStringLiteral("Application")) {
|
if (type != QStringLiteral("Application")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if hidden or not shown
|
// Check if hidden or not shown
|
||||||
if (desktop.value(QStringLiteral("Hidden"), false).toBool()) {
|
if (desktop.readEntry(QStringLiteral("Hidden"), false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (desktop.value(QStringLiteral("NoDisplay"), false).toBool()) {
|
if (desktop.readEntry(QStringLiteral("NoDisplay"), false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check categories for game-related entries
|
// Check categories for game-related entries
|
||||||
QString categories = desktop.value(QStringLiteral("Categories")).toString();
|
const QStringList categories = desktop.readEntry(QStringLiteral("Categories")).split(QLatin1Char(';'), Qt::SkipEmptyParts);
|
||||||
QStringList gameCategories = {QStringLiteral("Game"),
|
|
||||||
QStringLiteral("ArcadeGame"),
|
|
||||||
QStringLiteral("ActionGame"),
|
|
||||||
QStringLiteral("AdventureGame"),
|
|
||||||
QStringLiteral("BlocksGame"),
|
|
||||||
QStringLiteral("BoardGame"),
|
|
||||||
QStringLiteral("CardGame"),
|
|
||||||
QStringLiteral("KidsGame"),
|
|
||||||
QStringLiteral("LogicGame"),
|
|
||||||
QStringLiteral("RolePlaying"),
|
|
||||||
QStringLiteral("Shooter"),
|
|
||||||
QStringLiteral("Simulation"),
|
|
||||||
QStringLiteral("SportsGame"),
|
|
||||||
QStringLiteral("StrategyGame")};
|
|
||||||
|
|
||||||
for (const QString &cat : gameCategories) {
|
return hasGameCategory(categories);
|
||||||
if (categories.contains(cat, Qt::CaseInsensitive)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Game *DesktopImporter::parseDesktopFile(const QString &filePath) const
|
Game *DesktopImporter::parseDesktopFile(const QString &filePath) const
|
||||||
{
|
{
|
||||||
QSettings desktop(filePath, QSettings::IniFormat);
|
KDesktopFile desktopFile(filePath);
|
||||||
desktop.beginGroup(QStringLiteral("Desktop Entry"));
|
KConfigGroup desktop = desktopFile.desktopGroup();
|
||||||
|
|
||||||
QString name = desktop.value(QStringLiteral("Name")).toString();
|
const QString name = desktop.readEntry(QStringLiteral("Name"));
|
||||||
QString exec = desktop.value(QStringLiteral("Exec")).toString();
|
QString exec = desktop.readEntry(QStringLiteral("Exec"));
|
||||||
QString icon = desktop.value(QStringLiteral("Icon")).toString();
|
const QString icon = desktop.readEntry(QStringLiteral("Icon"));
|
||||||
QString comment = desktop.value(QStringLiteral("Comment")).toString();
|
const QString comment = desktop.readEntry(QStringLiteral("Comment"));
|
||||||
QString genericName = desktop.value(QStringLiteral("GenericName")).toString();
|
const QString genericName = desktop.readEntry(QStringLiteral("GenericName"));
|
||||||
|
|
||||||
if (name.isEmpty() || exec.isEmpty()) {
|
if (name.isEmpty() || exec.isEmpty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -126,12 +107,13 @@ Game *DesktopImporter::parseDesktopFile(const QString &filePath) const
|
||||||
|
|
||||||
// Create unique ID from the desktop file name
|
// Create unique ID from the desktop file name
|
||||||
QFileInfo fileInfo(filePath);
|
QFileInfo fileInfo(filePath);
|
||||||
QString gameId = QStringLiteral("desktop_") + fileInfo.baseName();
|
const QString desktopId = fileInfo.completeBaseName();
|
||||||
|
QString gameId = QStringLiteral("desktop_") + desktopId;
|
||||||
|
|
||||||
Game *game = new Game(gameId, name);
|
Game *game = new Game(gameId, name);
|
||||||
game->setLaunchCommand(exec);
|
game->setLaunchCommand(exec);
|
||||||
game->setPlatform(platformName());
|
game->setPlatform(platformName());
|
||||||
game->setPlatformId(platformId());
|
game->setPlatformId(desktopId);
|
||||||
|
|
||||||
if (!comment.isEmpty()) {
|
if (!comment.isEmpty()) {
|
||||||
game->setDescription(comment);
|
game->setDescription(comment);
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,12 @@
|
||||||
|
|
||||||
#include "flatpakimporter.h"
|
#include "flatpakimporter.h"
|
||||||
|
|
||||||
|
#include <KConfigGroup>
|
||||||
|
#include <KDesktopFile>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QSettings>
|
|
||||||
|
|
||||||
FlatpakImporter::FlatpakImporter(QObject *parent)
|
FlatpakImporter::FlatpakImporter(QObject *parent)
|
||||||
: PlatformImporter(parent)
|
: PlatformImporter(parent)
|
||||||
|
|
@ -43,54 +44,34 @@ bool FlatpakImporter::isAvailable() const
|
||||||
|
|
||||||
bool FlatpakImporter::isGameApp(const QString &desktopFilePath) const
|
bool FlatpakImporter::isGameApp(const QString &desktopFilePath) const
|
||||||
{
|
{
|
||||||
QSettings desktop(desktopFilePath, QSettings::IniFormat);
|
KDesktopFile desktopFile(desktopFilePath);
|
||||||
desktop.beginGroup(QStringLiteral("Desktop Entry"));
|
KConfigGroup desktop = desktopFile.desktopGroup();
|
||||||
|
|
||||||
QString type = desktop.value(QStringLiteral("Type")).toString();
|
const QString type = desktop.readEntry(QStringLiteral("Type"));
|
||||||
if (type != QStringLiteral("Application")) {
|
if (type != QStringLiteral("Application")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desktop.value(QStringLiteral("Hidden"), false).toBool()) {
|
if (desktop.readEntry(QStringLiteral("Hidden"), false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (desktop.value(QStringLiteral("NoDisplay"), false).toBool()) {
|
if (desktop.readEntry(QStringLiteral("NoDisplay"), false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString categories = desktop.value(QStringLiteral("Categories")).toString();
|
const QStringList categories = desktop.readEntry(QStringLiteral("Categories")).split(QLatin1Char(';'), Qt::SkipEmptyParts);
|
||||||
QStringList gameCategories = {QStringLiteral("Game"),
|
|
||||||
QStringLiteral("ArcadeGame"),
|
|
||||||
QStringLiteral("ActionGame"),
|
|
||||||
QStringLiteral("AdventureGame"),
|
|
||||||
QStringLiteral("BlocksGame"),
|
|
||||||
QStringLiteral("BoardGame"),
|
|
||||||
QStringLiteral("CardGame"),
|
|
||||||
QStringLiteral("KidsGame"),
|
|
||||||
QStringLiteral("LogicGame"),
|
|
||||||
QStringLiteral("RolePlaying"),
|
|
||||||
QStringLiteral("Shooter"),
|
|
||||||
QStringLiteral("Simulation"),
|
|
||||||
QStringLiteral("SportsGame"),
|
|
||||||
QStringLiteral("StrategyGame")};
|
|
||||||
|
|
||||||
for (const QString &cat : gameCategories) {
|
return hasGameCategory(categories);
|
||||||
if (categories.contains(cat, Qt::CaseInsensitive)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Game *FlatpakImporter::parseDesktopFile(const QString &filePath, const QString &appId) const
|
Game *FlatpakImporter::parseDesktopFile(const QString &filePath, const QString &appId) const
|
||||||
{
|
{
|
||||||
QSettings desktop(filePath, QSettings::IniFormat);
|
KDesktopFile desktopFile(filePath);
|
||||||
desktop.beginGroup(QStringLiteral("Desktop Entry"));
|
KConfigGroup desktop = desktopFile.desktopGroup();
|
||||||
|
|
||||||
QString name = desktop.value(QStringLiteral("Name")).toString();
|
const QString name = desktop.readEntry(QStringLiteral("Name"));
|
||||||
QString icon = desktop.value(QStringLiteral("Icon")).toString();
|
const QString icon = desktop.readEntry(QStringLiteral("Icon"));
|
||||||
QString comment = desktop.value(QStringLiteral("Comment")).toString();
|
const QString comment = desktop.readEntry(QStringLiteral("Comment"));
|
||||||
|
|
||||||
if (name.isEmpty()) {
|
if (name.isEmpty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -100,7 +81,7 @@ Game *FlatpakImporter::parseDesktopFile(const QString &filePath, const QString &
|
||||||
|
|
||||||
Game *game = new Game(gameId, name);
|
Game *game = new Game(gameId, name);
|
||||||
game->setPlatform(platformName());
|
game->setPlatform(platformName());
|
||||||
game->setPlatformId(platformId());
|
game->setPlatformId(appId);
|
||||||
game->setLaunchCommand(QStringLiteral("flatpak run %1").arg(appId));
|
game->setLaunchCommand(QStringLiteral("flatpak run %1").arg(appId));
|
||||||
|
|
||||||
if (!comment.isEmpty()) {
|
if (!comment.isEmpty()) {
|
||||||
|
|
|
||||||
|
|
@ -44,3 +44,31 @@ QString PlatformImporter::expandPath(const QString &path) const
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PlatformImporter::hasGameCategory(const QStringList &categories)
|
||||||
|
{
|
||||||
|
static const QStringList gameCategories = {QStringLiteral("Game"),
|
||||||
|
QStringLiteral("ArcadeGame"),
|
||||||
|
QStringLiteral("ActionGame"),
|
||||||
|
QStringLiteral("AdventureGame"),
|
||||||
|
QStringLiteral("BlocksGame"),
|
||||||
|
QStringLiteral("BoardGame"),
|
||||||
|
QStringLiteral("CardGame"),
|
||||||
|
QStringLiteral("KidsGame"),
|
||||||
|
QStringLiteral("LogicGame"),
|
||||||
|
QStringLiteral("RolePlaying"),
|
||||||
|
QStringLiteral("Shooter"),
|
||||||
|
QStringLiteral("Simulation"),
|
||||||
|
QStringLiteral("SportsGame"),
|
||||||
|
QStringLiteral("StrategyGame")};
|
||||||
|
|
||||||
|
for (const QString &category : categories) {
|
||||||
|
for (const QString &cat : gameCategories) {
|
||||||
|
if (category.compare(cat, Qt::CaseInsensitive) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
|
||||||
|
|
@ -29,4 +30,5 @@ protected:
|
||||||
QString findExecutable(const QString &name) const;
|
QString findExecutable(const QString &name) const;
|
||||||
bool directoryExists(const QString &path) const;
|
bool directoryExists(const QString &path) const;
|
||||||
QString expandPath(const QString &path) const;
|
QString expandPath(const QString &path) const;
|
||||||
|
static bool hasGameCategory(const QStringList &categories);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue