Compare commits

..

No commits in common. "cca49615d68bd8b07c554e4cc791b9e9aab81a1d" and "b0d09be497a694b51ab5172f8d67da25c1e22454" have entirely different histories.

11 changed files with 465 additions and 937 deletions

File diff suppressed because it is too large Load diff

View file

@ -3,8 +3,6 @@
#pragma once #pragma once
#include <atomic>
#include <QHash> #include <QHash>
#include <QJsonObject> #include <QJsonObject>
#include <QObject> #include <QObject>
@ -38,8 +36,6 @@ public:
static App *instance(); static App *instance();
static App *create(QQmlEngine *engine, QJSEngine *scriptEngine); static App *create(QQmlEngine *engine, QJSEngine *scriptEngine);
~App() override;
GameModel *gameModel() const; GameModel *gameModel() const;
GameLauncher *launcher() const; GameLauncher *launcher() const;
RunnerManagerClient *runnerManager() const; RunnerManagerClient *runnerManager() const;
@ -94,8 +90,6 @@ private:
QString m_importStatus; QString m_importStatus;
QHash<QString, QJsonObject> m_removedGames; QHash<QString, QJsonObject> m_removedGames;
std::atomic_bool m_shuttingDown{false};
void setImporting(bool importing); void setImporting(bool importing);
void setImportStatus(const QString &status); void setImportStatus(const QString &status);
}; };

View file

@ -3,7 +3,6 @@
#include "gamecenterdaemon.h" #include "gamecenterdaemon.h"
#include <QCoreApplication>
#include <QDBusArgument> #include <QDBusArgument>
#include <QDBusConnection> #include <QDBusConnection>
#include <QDBusConnectionInterface> #include <QDBusConnectionInterface>
@ -879,48 +878,6 @@ GameCenterDaemon::GameCenterDaemon(QObject *parent)
{ {
} }
GameCenterDaemon::~GameCenterDaemon()
{
prepareForShutdown();
}
void GameCenterDaemon::prepareForShutdown()
{
for (auto it = m_sessions.begin(); it != m_sessions.end(); ++it) {
if (it.value().scanner) {
it.value().scanner->cancel();
}
QPointer<QProcess> proc = it.value().process;
it.value().process = nullptr;
if (proc) {
proc->disconnect(this);
connect(proc, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), proc, &QObject::deleteLater);
if (proc->state() != QProcess::NotRunning) {
proc->setParent(nullptr);
} else {
proc->deleteLater();
}
}
if (it.value().scanner) {
it.value().scanner->disconnect(this);
it.value().scanner->deleteLater();
it.value().scanner = nullptr;
}
}
for (auto it = m_unitPathWatchers.begin(); it != m_unitPathWatchers.end(); ++it) {
if (QObject *watcher = it.value()) {
watcher->deleteLater();
}
}
m_unitPathWatchers.clear();
m_unitPathToSessionId.clear();
m_unitNameToSessionId.clear();
}
bool GameCenterDaemon::init() bool GameCenterDaemon::init()
{ {
QDBusConnection bus = QDBusConnection::sessionBus(); QDBusConnection bus = QDBusConnection::sessionBus();
@ -940,10 +897,6 @@ bool GameCenterDaemon::init()
recoverExistingSessions(); recoverExistingSessions();
if (QCoreApplication::instance()) {
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &GameCenterDaemon::prepareForShutdown);
}
return true; return true;
} }
@ -1279,7 +1232,7 @@ QString GameCenterDaemon::launchDirect(const QVariantMap &launchSpec)
} }
process->start(program, args); process->start(program, args);
if (!process->waitForStarted(5000)) { if (!process->waitForStarted()) {
const QVariantMap ctx = { const QVariantMap ctx = {
{QStringLiteral("command"), command}, {QStringLiteral("command"), command},
{QStringLiteral("program"), program}, {QStringLiteral("program"), program},

View file

@ -23,7 +23,6 @@ class GameCenterDaemon : public QObject
public: public:
explicit GameCenterDaemon(QObject *parent = nullptr); explicit GameCenterDaemon(QObject *parent = nullptr);
~GameCenterDaemon() override;
bool init(); bool init();
@ -77,8 +76,6 @@ private:
void handleSystemdUnitPropertiesChanged(const QDBusObjectPath &unitPath, const QVariantMap &changedProperties); void handleSystemdUnitPropertiesChanged(const QDBusObjectPath &unitPath, const QVariantMap &changedProperties);
void removeSessionInternal(const QString &sessionId, const QString &finalState); void removeSessionInternal(const QString &sessionId, const QString &finalState);
void prepareForShutdown();
private Q_SLOTS: private Q_SLOTS:
void handleSystemdUnitNew(const QString &unitName, const QDBusObjectPath &unitPath); void handleSystemdUnitNew(const QString &unitName, const QDBusObjectPath &unitPath);
void handleSystemdUnitRemoved(const QString &unitName, const QDBusObjectPath &unitPath); void handleSystemdUnitRemoved(const QString &unitName, const QDBusObjectPath &unitPath);

View file

@ -15,7 +15,6 @@
#include <QJsonArray> #include <QJsonArray>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <QSaveFile>
#include <QStandardPaths> #include <QStandardPaths>
#include <memory> #include <memory>
@ -88,6 +87,14 @@ static QString gamepadTypeToString(SDL_GamepadType t)
return QStringLiteral("unknown"); return QStringLiteral("unknown");
} }
} }
static QVariantMap unwrapVariantMap(QVariant v)
{
if (v.canConvert<QVariantMap>()) {
return v.toMap();
}
return {};
}
} }
QVariantMap InputDaemon::Profile::toVariantMap() const QVariantMap InputDaemon::Profile::toVariantMap() const
@ -266,10 +273,7 @@ void InputDaemon::loadProfiles()
bool InputDaemon::saveProfiles() const bool InputDaemon::saveProfiles() const
{ {
const QString path = profilesPath(); const QString path = profilesPath();
const QString dirPath = QFileInfo(path).absolutePath(); QDir().mkpath(QFileInfo(path).absolutePath());
if (!QDir().mkpath(dirPath)) {
return false;
}
QJsonArray profiles; QJsonArray profiles;
for (const Profile &p : m_profiles) { for (const Profile &p : m_profiles) {
@ -285,17 +289,13 @@ bool InputDaemon::saveProfiles() const
root.insert(QStringLiteral("profiles"), profiles); root.insert(QStringLiteral("profiles"), profiles);
root.insert(QStringLiteral("assignments"), assignments); root.insert(QStringLiteral("assignments"), assignments);
QSaveFile f(path); QFile f(path);
if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
return false; return false;
} }
const QByteArray payload = QJsonDocument(root).toJson(); f.write(QJsonDocument(root).toJson());
if (f.write(payload) != payload.size()) { return true;
return false;
}
return f.commit();
} }
InputDaemon::Profile InputDaemon::profileById(const QString &profileId) const InputDaemon::Profile InputDaemon::profileById(const QString &profileId) const

View file

@ -98,7 +98,7 @@ QList<Game *> LutrisImporter::importGames()
QProcess process; QProcess process;
process.start(lutrisPath, {QStringLiteral("-lo"), QStringLiteral("--json")}); process.start(lutrisPath, {QStringLiteral("-lo"), QStringLiteral("--json")});
if (process.waitForStarted(5000) && process.waitForFinished(30000)) { if (process.waitForFinished(30000)) {
QByteArray output = process.readAllStandardOutput(); QByteArray output = process.readAllStandardOutput();
QJsonDocument doc = QJsonDocument::fromJson(output); QJsonDocument doc = QJsonDocument::fromJson(output);
@ -139,14 +139,6 @@ QList<Game *> LutrisImporter::importGames()
Q_EMIT importProgress(current, total); Q_EMIT importProgress(current, total);
} }
} }
} else {
if (process.state() != QProcess::NotRunning) {
process.terminate();
if (!process.waitForFinished(3000)) {
process.kill();
process.waitForFinished(3000);
}
}
} }
} }

View file

@ -115,10 +115,7 @@ Kirigami.Dialog {
readonly property bool anyConfirmOpen: !!(deletePrefixConfirmDialog && deletePrefixConfirmDialog.opened) readonly property bool anyConfirmOpen: !!(deletePrefixConfirmDialog && deletePrefixConfirmDialog.opened)
readonly property bool anyMenuOpen: { readonly property bool anyMenuOpen: !!(runnerCombo && runnerCombo.popup && runnerCombo.popup.visible)
if (!runnerCombo || !runnerCombo.popup) return false
return runnerCombo.popup.visible === true
}
function currentConfirmDialog() { function currentConfirmDialog() {
if (deletePrefixConfirmDialog && deletePrefixConfirmDialog.opened) return deletePrefixConfirmDialog if (deletePrefixConfirmDialog && deletePrefixConfirmDialog.opened) return deletePrefixConfirmDialog
@ -136,7 +133,7 @@ Kirigami.Dialog {
} }
function closeCurrentMenu() { function closeCurrentMenu() {
if (runnerCombo && runnerCombo.popup && runnerCombo.popup.visible === true) { if (runnerCombo && runnerCombo.popup && runnerCombo.popup.visible) {
runnerCombo.popup.close() runnerCombo.popup.close()
} }
} }

View file

@ -328,6 +328,8 @@ Kirigami.ApplicationWindow {
footer: Item { footer: Item {
implicitWidth: root.width implicitWidth: root.width
anchors.left: parent ? parent.left : undefined
anchors.right: parent ? parent.right : undefined
implicitHeight: footerBar.implicitHeight implicitHeight: footerBar.implicitHeight
height: implicitHeight height: implicitHeight

View file

@ -22,7 +22,6 @@
#include <QNetworkReply> #include <QNetworkReply>
#include <QNetworkRequest> #include <QNetworkRequest>
#include <QProcess> #include <QProcess>
#include <QSaveFile>
#include <QSet> #include <QSet>
#include <QStandardPaths> #include <QStandardPaths>
#include <QTimer> #include <QTimer>
@ -202,10 +201,7 @@ void RunnerManagerDaemon::loadRegistry()
bool RunnerManagerDaemon::saveRegistry() const bool RunnerManagerDaemon::saveRegistry() const
{ {
const QString path = registryPath(); const QString path = registryPath();
const QString dirPath = QFileInfo(path).absolutePath(); QDir().mkpath(QFileInfo(path).absolutePath());
if (!QDir().mkpath(dirPath)) {
return false;
}
QJsonArray arr; QJsonArray arr;
@ -225,17 +221,13 @@ bool RunnerManagerDaemon::saveRegistry() const
QJsonObject root; QJsonObject root;
root.insert(QStringLiteral("runners"), arr); root.insert(QStringLiteral("runners"), arr);
QSaveFile f(path); QFile f(path);
if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
return false; return false;
} }
const QByteArray payload = QJsonDocument(root).toJson(QJsonDocument::Indented); f.write(QJsonDocument(root).toJson(QJsonDocument::Indented));
if (f.write(payload) != payload.size()) { return true;
return false;
}
return f.commit();
} }
QString RunnerManagerDaemon::gameProfilesPath() const QString RunnerManagerDaemon::gameProfilesPath() const
@ -275,10 +267,7 @@ void RunnerManagerDaemon::loadGameProfiles()
bool RunnerManagerDaemon::saveGameProfiles() const bool RunnerManagerDaemon::saveGameProfiles() const
{ {
const QString path = gameProfilesPath(); const QString path = gameProfilesPath();
const QString dirPath = QFileInfo(path).absolutePath(); QDir().mkpath(QFileInfo(path).absolutePath());
if (!QDir().mkpath(dirPath)) {
return false;
}
QJsonArray arr; QJsonArray arr;
for (auto it = m_gameProfiles.constBegin(); it != m_gameProfiles.constEnd(); ++it) { for (auto it = m_gameProfiles.constBegin(); it != m_gameProfiles.constEnd(); ++it) {
@ -292,17 +281,13 @@ bool RunnerManagerDaemon::saveGameProfiles() const
QJsonObject root; QJsonObject root;
root.insert(QStringLiteral("profiles"), arr); root.insert(QStringLiteral("profiles"), arr);
QSaveFile f(path); QFile f(path);
if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
return false; return false;
} }
const QByteArray payload = QJsonDocument(root).toJson(QJsonDocument::Indented); f.write(QJsonDocument(root).toJson(QJsonDocument::Indented));
if (f.write(payload) != payload.size()) { return true;
return false;
}
return f.commit();
} }
QVariantMap RunnerManagerDaemon::gameProfileForGameId(const QString &gameId) const QVariantMap RunnerManagerDaemon::gameProfileForGameId(const QString &gameId) const

View file

@ -152,23 +152,15 @@ void RunnerManagerClient::shutdownSpawnedRunnerDaemon()
return; return;
} }
QProcess *p = m_runnerdProcess; if (m_runnerdProcess->state() == QProcess::NotRunning) {
const auto state = p->state();
if (state == QProcess::NotRunning) {
return; return;
} }
// Avoid our finished() handler nulling the pointer while we're shutting down. m_runnerdProcess->terminate();
p->disconnect(this); if (!m_runnerdProcess->waitForFinished(1000)) {
m_runnerdProcess->kill();
p->terminate(); m_runnerdProcess->waitForFinished(1000);
if (!p->waitForFinished(3000)) {
p->kill();
p->waitForFinished(3000);
} }
p->deleteLater();
m_runnerdProcess = nullptr;
} }
void RunnerManagerClient::ensureRunnerDaemon() void RunnerManagerClient::ensureRunnerDaemon()

View file

@ -8,11 +8,11 @@
#include <KConfigGroup> #include <KConfigGroup>
#include <KSharedConfig> #include <KSharedConfig>
#include <QDir> #include <QDir>
#include <QFile>
#include <QJsonArray> #include <QJsonArray>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <QNetworkReply> #include <QNetworkReply>
#include <QSaveFile>
#include <QStandardPaths> #include <QStandardPaths>
#include <QUrlQuery> #include <QUrlQuery>
@ -297,28 +297,16 @@ void SteamGridDB::onImageDownloaded()
QString coversPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/covers"); QString coversPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/covers");
QDir dir(coversPath); QDir dir(coversPath);
if (!dir.exists()) { if (!dir.exists()) {
if (!dir.mkpath(coversPath)) { dir.mkpath(coversPath);
Q_EMIT fetchError(game, QStringLiteral("Failed to create covers directory"));
m_processedGames++;
Q_EMIT fetchProgress(m_processedGames, m_totalGames);
processNextGame();
return;
}
} }
QString fileName = game->id() + QStringLiteral(".jpg"); QString fileName = game->id() + QStringLiteral(".jpg");
QString filePath = coversPath + QStringLiteral("/") + fileName; QString filePath = coversPath + QStringLiteral("/") + fileName;
const QByteArray payload = reply->readAll(); QFile file(filePath);
QSaveFile file(filePath); if (file.open(QIODevice::WriteOnly)) {
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { file.write(reply->readAll());
if (file.write(payload) != payload.size() || !file.commit()) { file.close();
Q_EMIT fetchError(game, QStringLiteral("Failed to save cover image"));
m_processedGames++;
Q_EMIT fetchProgress(m_processedGames, m_totalGames);
processNextGame();
return;
}
QUrl localUrl = QUrl::fromLocalFile(filePath); QUrl localUrl = QUrl::fromLocalFile(filePath);
game->setCoverUrl(localUrl); game->setCoverUrl(localUrl);