1
Fork 0
mirror of https://github.com/redstrate/Astra.git synced 2025-04-22 12:47:44 +00:00

Add a method to use existing game installations from other launchers

This should work for XIVLauncher.Core, XIVQuickLauncher and the official
launcher. More testing is needed of course, but the framework is there
now.
This commit is contained in:
Joshua Goins 2024-05-26 08:02:56 -04:00
parent 42a135e730
commit 4948db82be
5 changed files with 153 additions and 26 deletions

2
external/libphysis vendored

@ -1 +1 @@
Subproject commit 07193fc6e272a41c498112b3eb0e5808a6095e53 Subproject commit 1b8a8dddcafe31799dfb5597ab41cc32ac3ec7a3

View file

@ -47,6 +47,7 @@ target_sources(astra PRIVATE
include/benchmarkinstaller.h include/benchmarkinstaller.h
include/compatibilitytoolinstaller.h include/compatibilitytoolinstaller.h
include/encryptedarg.h include/encryptedarg.h
include/existinginstallmodel.h
include/gamerunner.h include/gamerunner.h
include/gameinstaller.h include/gameinstaller.h
include/headline.h include/headline.h
@ -68,6 +69,7 @@ target_sources(astra PRIVATE
src/benchmarkinstaller.cpp src/benchmarkinstaller.cpp
src/compatibilitytoolinstaller.cpp src/compatibilitytoolinstaller.cpp
src/encryptedarg.cpp src/encryptedarg.cpp
src/existinginstallmodel.cpp
src/gamerunner.cpp src/gamerunner.cpp
src/headline.cpp src/headline.cpp
src/gameinstaller.cpp src/gameinstaller.cpp

View file

@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: 2024 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <QtQml>
#include <physis.hpp>
class ExistingInstallModel : public QAbstractListModel
{
Q_OBJECT
QML_ELEMENT
public:
enum CustomRoles {
TypeRole = Qt::UserRole,
PathRole,
};
explicit ExistingInstallModel(QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role) const override;
int rowCount(const QModelIndex &parent) const override;
QHash<int, QByteArray> roleNames() const override;
private:
void fill();
struct ExistingInstall {
ExistingInstallType type;
QString path;
};
QList<ExistingInstall> m_existingInstalls;
};

View file

@ -0,0 +1,68 @@
// SPDX-FileCopyrightText: 2024 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "existinginstallmodel.h"
#include <KLocalizedString>
ExistingInstallModel::ExistingInstallModel(QObject *parent)
: QAbstractListModel(parent)
{
fill();
}
QVariant ExistingInstallModel::data(const QModelIndex &index, int role) const
{
Q_ASSERT(checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid));
const auto &install = m_existingInstalls[index.row()];
switch (role) {
case TypeRole: {
switch (install.type) {
case ExistingInstallType::OfficialLauncher:
return i18n("Official Launcher");
case ExistingInstallType::XIVLauncherCore:
return QStringLiteral("XIVLauncher.Core");
case ExistingInstallType::XIVOnMac:
return QStringLiteral("XIV on Mac");
case ExistingInstallType::XIVQuickLauncher:
return QStringLiteral("XIVQuickLauncher");
default:
return i18n("Unknown");
}
}
case PathRole:
return install.path;
default:
return {};
}
}
int ExistingInstallModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_existingInstalls.size();
}
QHash<int, QByteArray> ExistingInstallModel::roleNames() const
{
return {
{TypeRole, "type"},
{PathRole, "path"},
};
}
void ExistingInstallModel::fill()
{
auto dirs = physis_find_existing_game_dirs();
for (int i = 0; i < dirs.count; i++) {
// We shouldn't be able to import our own game installs, that's handled elsewhere in the UI
if (dirs.entries[i].install_type != ExistingInstallType::Astra) {
beginInsertRows({}, m_existingInstalls.size(), m_existingInstalls.size());
m_existingInstalls.push_back(ExistingInstall{.type = dirs.entries[i].install_type, .path = QString::fromUtf8(dirs.entries[i].path)});
endInsertRows();
}
}
}
#include "moc_existinginstallmodel.cpp"

View file

@ -19,30 +19,6 @@ FormCard.FormCardPage {
title: i18n("Find Existing Installation") title: i18n("Find Existing Installation")
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
FormCard.FormTextDelegate {
id: helpTextDelegate
text: i18n("Please select the path to your existing installation.")
}
FormCard.FormDelegateSeparator {
above: helpTextDelegate
below: selectDelegate
}
FormCard.FormButtonDelegate {
id: selectDelegate
text: i18n("Select Existing Path")
icon.name: "document-open-folder"
onClicked: dialog.open()
}
}
data: FolderDialog { data: FolderDialog {
id: dialog id: dialog
@ -51,4 +27,50 @@ FormCard.FormCardPage {
applicationWindow().checkSetup(); applicationWindow().checkSetup();
} }
} }
}
FormCard.FormCard {
Layout.fillWidth: true
Layout.topMargin: Kirigami.Units.largeSpacing
Repeater {
model: ExistingInstallModel {}
delegate: FormCard.FormButtonDelegate {
required property var path
required property var type
text: path
description: type
onClicked: {
page.profile.gamePath = path;
applicationWindow().checkSetup();
}
}
}
}
FormCard.FormCard {
Layout.fillWidth: true
Layout.topMargin: Kirigami.Units.largeSpacing
FormCard.FormTextDelegate {
id: helpTextDelegate
text: i18n("If you can't find your existing game installation, manually select the path below.")
}
FormCard.FormDelegateSeparator {
above: helpTextDelegate
below: selectDelegate
}
FormCard.FormButtonDelegate {
id: selectDelegate
icon.name: "document-open-folder"
text: i18n("Select Existing Path")
onClicked: dialog.open()
}
}
}