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:
parent
42a135e730
commit
4948db82be
5 changed files with 153 additions and 26 deletions
2
external/libphysis
vendored
2
external/libphysis
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 07193fc6e272a41c498112b3eb0e5808a6095e53
|
Subproject commit 1b8a8dddcafe31799dfb5597ab41cc32ac3ec7a3
|
|
@ -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
|
||||||
|
|
35
launcher/include/existinginstallmodel.h
Normal file
35
launcher/include/existinginstallmodel.h
Normal 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;
|
||||||
|
};
|
68
launcher/src/existinginstallmodel.cpp
Normal file
68
launcher/src/existinginstallmodel.cpp
Normal 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"
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue