// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2026 A-La-Karte Contributors #pragma once #include #include #include class RunnerManagerClient : public QObject { Q_OBJECT Q_PROPERTY(bool busy READ busy NOTIFY busyChanged) Q_PROPERTY(QString installId READ installId NOTIFY installIdChanged) Q_PROPERTY(qint64 receivedBytes READ receivedBytes NOTIFY progressChanged) Q_PROPERTY(qint64 totalBytes READ totalBytes NOTIFY progressChanged) Q_PROPERTY(QString status READ status NOTIFY statusChanged) Q_PROPERTY(QString lastError READ lastError NOTIFY lastErrorChanged) Q_PROPERTY(QVariantList runners READ runners NOTIFY runnersChanged) Q_PROPERTY(QVariantList gameProfiles READ gameProfiles NOTIFY gameProfilesChanged) public: explicit RunnerManagerClient(QObject *parent = nullptr); ~RunnerManagerClient() override; bool busy() const; QString installId() const; qint64 receivedBytes() const; qint64 totalBytes() const; QString status() const; QString lastError() const; QVariantList runners() const; QVariantList gameProfiles() const; Q_INVOKABLE void installRunnerFromUrl(const QString &url, const QString &sha256 = QString(), const QString &name = QString(), const QString &type = QStringLiteral("proton"), bool overwrite = true); Q_INVOKABLE void cancelCurrentInstall(); Q_INVOKABLE void refreshRunners(); Q_INVOKABLE void uninstallRunner(const QString &runnerId); Q_INVOKABLE void refreshGameProfiles(); Q_INVOKABLE void requestGameProfile(const QString &gameId); Q_INVOKABLE void setGameProfile(const QVariantMap &spec); Q_INVOKABLE void clearGameProfile(const QString &gameId); Q_INVOKABLE void ensurePrefix(const QString &gameId, const QString &runner, const QString &prefixPath = QString()); Q_INVOKABLE void deletePrefix(const QString &gameId, const QString &prefixPath = QString()); Q_SIGNALS: void busyChanged(); void installIdChanged(); void progressChanged(); void statusChanged(); void lastErrorChanged(); void runnersChanged(); void gameProfilesChanged(); void prefixEnsured(const QString &gameId, const QString &prefixPath); void prefixDeleted(const QString &gameId, const QString &prefixPath); void gameProfileFetched(const QString &gameId, const QVariantMap &result); void gameProfileSaved(const QString &gameId, const QVariantMap &result); void gameProfileCleared(const QString &gameId, const QVariantMap &result); private Q_SLOTS: void onInstallStarted(const QString &installId, const QVariantMap &spec); void onInstallProgress(const QString &installId, qlonglong received, qlonglong total); void onInstallFinished(const QString &installId, const QVariantMap &result); void onGameProfilesChanged(); private: void ensureRunnerDaemon(); void shutdownSpawnedRunnerDaemon(); void setBusy(bool busy); void setInstallId(const QString &installId); void setProgress(qint64 received, qint64 total); void setStatus(const QString &status); void setLastError(const QString &error); bool m_busy = false; QString m_installId; qint64 m_receivedBytes = 0; qint64 m_totalBytes = 0; QString m_status; QString m_lastError; QVariantList m_runners; QVariantList m_gameProfiles; bool m_refreshRetryPending = false; bool m_refreshProfilesRetryPending = false; class QProcess *m_runnerdProcess = nullptr; bool m_runnerdSpawnAttempted = false; };