Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
cmake_minimum_required(VERSION 3.25)
project(Umbra VERSION 0.2.0 LANGUAGES CXX)

# build options used for distributors
option(BUILD_FLATPAK "Build for Flatpak." OFF)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

Expand Down Expand Up @@ -40,14 +37,14 @@ find_package(Qt6 ${QT_MIN_VERSION} REQUIRED COMPONENTS
Concurrent
Test
QmlPrivate) # QmlPrivate is here to work around a QCoro issue with 6.10, remove later
if (LINUX)
find_package(Qt6 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS DBus)
endif ()

find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS Kirigami I18n Config CoreAddons Archive IconThemes)
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS Kirigami I18n Config CoreAddons Archive IconThemes GuiAddons)
find_package(KF6KirigamiAddons 1.7.0 REQUIRED)
find_package(QCoro6 REQUIRED COMPONENTS Core Network Qml)
qcoro_enable_coroutines()
if (LINUX)
find_package(KF6FileMetaData ${KF_MIN_VERSION} REQUIRED)
endif ()

qt_policy(SET QTP0001 NEW)
qt_policy(SET QTP0004 NEW)
Expand Down
16 changes: 5 additions & 11 deletions launcher/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ target_link_libraries(umbra_static PUBLIC
QCoro::Core
QCoro::Network
QCoro::Qml
physis)
physis
KF6::GuiAddons)
if (LINUX)
target_link_libraries(umbra_static PUBLIC KF6::FileMetaData)
endif()
kconfig_target_kcfg_file(umbra_static FILE config.kcfg CLASS_NAME Config MUTATORS GENERATE_PROPERTIES GENERATE_MOC DEFAULT_VALUE_GETTERS PARENT_IN_CONSTRUCTOR QML_REGISTRATION QML_UNCREATABLE USE_ENUM_TYPES)
kconfig_target_kcfg_file(umbra_static FILE accountconfig.kcfg CLASS_NAME AccountConfig MUTATORS GENERATE_PROPERTIES GENERATE_MOC DEFAULT_VALUE_GETTERS PARENT_IN_CONSTRUCTOR QML_REGISTRATION QML_UNCREATABLE USE_ENUM_TYPES)
kconfig_target_kcfg_file(umbra_static FILE profileconfig.kcfg CLASS_NAME ProfileConfig MUTATORS GENERATE_PROPERTIES GENERATE_MOC DEFAULT_VALUE_GETTERS PARENT_IN_CONSTRUCTOR QML_REGISTRATION QML_UNCREATABLE USE_ENUM_TYPES)
Expand All @@ -88,16 +92,6 @@ if (NOT MSVC)
target_compile_options(umbra_static PUBLIC -fexceptions)
endif ()

if (BUILD_FLATPAK)
target_compile_definitions(umbra_static PUBLIC FLATPAK)
endif ()

# For screensaver inhibition on Linux
if (TARGET Qt6::DBus)
target_link_libraries(umbra_static PRIVATE Qt6::DBus)
target_compile_definitions(umbra_static PRIVATE -DHAS_DBUS)
endif ()

add_executable(umbra)

target_sources(umbra PRIVATE
Expand Down
12 changes: 9 additions & 3 deletions launcher/include/launchercore.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
class SquareEnixLogin;
class AssetUpdater;
class GameRunner;
class KSystemInhibitor;

class LoginInformation : public QObject
{
Expand Down Expand Up @@ -48,7 +49,6 @@ class LauncherCore : public QObject
QML_SINGLETON

Q_PROPERTY(bool loadingFinished READ isLoadingFinished NOTIFY loadingFinished)
Q_PROPERTY(bool isWindows READ isWindows CONSTANT)
Q_PROPERTY(Config *config READ config CONSTANT)
Q_PROPERTY(ProfileManager *profileManager READ profileManager CONSTANT)
Q_PROPERTY(AccountManager *accountManager READ accountManager CONSTANT)
Expand Down Expand Up @@ -85,7 +85,6 @@ class LauncherCore : public QObject
void setupIgnoreSSL(QNetworkReply *reply);

[[nodiscard]] bool isLoadingFinished() const;
[[nodiscard]] static bool isWindows();
[[nodiscard]] static bool needsCompatibilityTool();
[[nodiscard]] Q_INVOKABLE bool isPatching() const;

Expand All @@ -108,6 +107,13 @@ class LauncherCore : public QObject

Q_INVOKABLE void resetServerConfiguration(Account *account);

/**
* @brief Translates this path from its sandbox form (if applicable) to the host path.
*
* @note This should be used to display any and all paths, if users are exposed to the Documents API they are (rightfully) confused!
*/
Q_INVOKABLE QString readHostPath(const QString &path);

Q_SIGNALS:
void loadingFinished();
void successfulLaunch();
Expand Down Expand Up @@ -158,5 +164,5 @@ class LauncherCore : public QObject

int m_currentProfileIndex = 0;

unsigned int screenSaverDbusCookie = 0;
KSystemInhibitor *m_inhibitor = nullptr;
};
8 changes: 0 additions & 8 deletions launcher/src/account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,7 @@ void Account::setKeychainValue(const QString &key, const QString &value)
{
auto job = new QKeychain::WritePasswordJob(QStringLiteral("Umbra"), this);
job->setTextData(value);
#ifdef FLATPAK
job->setKey(QStringLiteral("flatpak-") + m_key + QStringLiteral("-") + key);
#else
job->setKey(m_key + QStringLiteral("-") + key);
#endif
job->start();

connect(job, &QKeychain::WritePasswordJob::finished, this, [job] {
Expand All @@ -73,11 +69,7 @@ void Account::setKeychainValue(const QString &key, const QString &value)
QCoro::Task<QString> Account::getKeychainValue(const QString &key)
{
auto job = new QKeychain::ReadPasswordJob(QStringLiteral("Umbra"), this);
#ifdef FLATPAK
job->setKey(QStringLiteral("flatpak-") + m_key + QStringLiteral("-") + key);
#else
job->setKey(m_key + QStringLiteral("-") + key);
#endif
job->start();

co_await qCoro(job, &QKeychain::ReadPasswordJob::finished);
Expand Down
66 changes: 23 additions & 43 deletions launcher/src/launchercore.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
// SPDX-FileCopyrightText: 2023 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-3.0-or-later

#ifdef Q_OS_LINUX
#include <KFileMetaData/UserMetaData>
#endif
#include <KLocalizedString>
#include <KSystemInhibitor>
#include <QDir>
#include <QImage>
#include <QNetworkAccessManager>
Expand All @@ -19,12 +23,6 @@
#include "squareenixlogin.h"
#include "utility.h"

#ifdef HAS_DBUS
#include <QDBusConnection>
#include <QDBusReply>
#include <QGuiApplication>
#endif

using namespace Qt::StringLiterals;

LauncherCore::LauncherCore()
Expand Down Expand Up @@ -188,18 +186,12 @@ bool LauncherCore::isLoadingFinished() const
return m_loadingFinished;
}

bool LauncherCore::isWindows()
bool LauncherCore::needsCompatibilityTool()
{
#if defined(Q_OS_WIN)
return true;
#else
#ifdef Q_OS_WINDOWS
return false;
#endif
}

bool LauncherCore::needsCompatibilityTool()
{
return !isWindows();
return true;
}

bool LauncherCore::isPatching() const
Expand Down Expand Up @@ -290,38 +282,14 @@ QCoro::Task<> LauncherCore::beginAutoConfiguration(Account *account, QString url

void LauncherCore::inhibitSleep()
{
#ifdef HAS_DBUS
if (screenSaverDbusCookie != 0)
return;

QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.ScreenSaver"),
QStringLiteral("/ScreenSaver"),
QStringLiteral("org.freedesktop.ScreenSaver"),
QStringLiteral("Inhibit"));
message << QGuiApplication::desktopFileName();
message << i18n("Playing FFXIV");

const QDBusReply<uint> reply = QDBusConnection::sessionBus().call(message);
if (reply.isValid()) {
screenSaverDbusCookie = reply.value();
}
#endif
uninhibitSleep(); // clean up the previous one (if any)
m_inhibitor = new KSystemInhibitor(i18n("Playing a game"), KSystemInhibitor::Type::Suspend, nullptr, this);
}

void LauncherCore::uninhibitSleep()
{
#ifdef HAS_DBUS
if (screenSaverDbusCookie == 0)
return;

QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.ScreenSaver"),
QStringLiteral("/ScreenSaver"),
QStringLiteral("org.freedesktop.ScreenSaver"),
QStringLiteral("UnInhibit"));
message << static_cast<uint>(screenSaverDbusCookie);
screenSaverDbusCookie = 0;
QDBusConnection::sessionBus().send(message);
#endif
delete m_inhibitor;
m_inhibitor = nullptr;
}

QString LauncherCore::currentProfileId() const
Expand Down Expand Up @@ -356,4 +324,16 @@ void LauncherCore::resetServerConfiguration(Account *account)
Q_EMIT account->resetConfiguration();
}

QString LauncherCore::readHostPath(const QString &path)
{
#ifdef Q_OS_LINUX
KFileMetaData::UserMetaData metadata(path);
if (metadata.hasAttribute(QStringLiteral("document-portal.host-path"))) {
return metadata.attribute(QStringLiteral("document-portal.host-path"));
}
#endif

return path;
}

#include "moc_launchercore.cpp"
6 changes: 1 addition & 5 deletions launcher/ui/Main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,7 @@ Kirigami.ApplicationWindow {
}

function pushDialogLayer(url: string): void {
if (LauncherCore.isSteamDeck) {
pageStack.layers.push(url)
} else {
pageStack.pushDialogLayer(url)
}
pageStack.pushDialogLayer(url);
}

function openUrl(url: string): void {
Expand Down
2 changes: 1 addition & 1 deletion launcher/ui/Settings/AccountSettings.qml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ FormCard.FormCardPage {

text: i18n("Wine Prefix Folder")
folder: page.account.config.winePrefixPath
displayText: page.account.isWinePrefixDefault ? i18n("Default Location") : folder
displayText: page.account.isWinePrefixDefault ? i18n("Default Location") : LauncherCore.readHostPath(folder)
visible: LauncherCore.config.showDevTools

onAccepted: (path) => {
Expand Down
6 changes: 3 additions & 3 deletions launcher/ui/Settings/ProfileSettings.qml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ FormCard.FormCardPage {
Kirigami.Action {
id: wineAction
text: i18n("Wine")
visible: !LauncherCore.isWindows
visible: Qt.platform.os !== "windows"
icon.name: "wine-symbolic"
},
Kirigami.Action {
Expand Down Expand Up @@ -84,7 +84,7 @@ FormCard.FormCardPage {

text: i18n("Game Folder")
folder: page.profile.config.gamePath
displayText: page.profile.isGamePathDefault ? i18n("Default Location") : folder
displayText: page.profile.isGamePathDefault ? i18n("Default Location") : LauncherCore.readHostPath(folder)

onAccepted: (folder) => {
page.profile.config.gamePath = folder;
Expand Down Expand Up @@ -147,7 +147,7 @@ FormCard.FormCardPage {
id: winePathDelegate

text: i18n("Wine Executable")
file: page.profile.winePath
file: LauncherCore.readHostPath(page.profile.winePath)
visible: page.profile.config.wineType !== Profile.BuiltIn

onAccepted: (path) => {
Expand Down
1 change: 0 additions & 1 deletion zone.xiv.umbra.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ modules:
buildsystem: cmake-ninja
config-opts:
- -DRust_COMPILER=/usr/lib/sdk/rust-stable/bin/rustc
- -DBUILD_FLATPAK=ON
- -DCMAKE_INSTALL_LIBDIR=/app/lib
- -DLIB_INSTALL_DIR=/app/lib
- -DBUILD_TESTING=OFF
Expand Down
Loading