2022-10-13 23:55:21 +01:00
|
|
|
#include "ManagedPackPage.h"
|
|
|
|
#include "ui_ManagedPackPage.h"
|
|
|
|
|
|
|
|
#include <QListView>
|
|
|
|
#include <QProxyStyle>
|
|
|
|
|
2022-10-22 20:02:10 +01:00
|
|
|
#include <HoeDown.h>
|
|
|
|
|
2022-10-13 23:55:21 +01:00
|
|
|
#include "Application.h"
|
2022-10-13 23:57:23 +01:00
|
|
|
#include "BuildConfig.h"
|
2022-10-14 18:36:48 +01:00
|
|
|
#include "InstanceImportTask.h"
|
|
|
|
#include "InstanceList.h"
|
|
|
|
#include "InstanceTask.h"
|
2022-10-13 23:57:23 +01:00
|
|
|
#include "Json.h"
|
|
|
|
|
|
|
|
#include "modplatform/modrinth/ModrinthPackManifest.h"
|
2022-10-13 23:55:21 +01:00
|
|
|
|
2022-10-14 18:36:48 +01:00
|
|
|
#include "ui/InstanceWindow.h"
|
|
|
|
#include "ui/dialogs/CustomMessageBox.h"
|
|
|
|
#include "ui/dialogs/ProgressDialog.h"
|
|
|
|
|
2022-10-13 23:55:21 +01:00
|
|
|
/** This is just to override the combo box popup behavior so that the combo box doesn't take the whole screen.
|
|
|
|
* ... thanks Qt.
|
|
|
|
*/
|
|
|
|
class NoBigComboBoxStyle : public QProxyStyle {
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
|
|
|
NoBigComboBoxStyle(QStyle* style) : QProxyStyle(style) {}
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
int styleHint(QStyle::StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override
|
|
|
|
{
|
|
|
|
if (hint == QStyle::SH_ComboBox_Popup)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return QProxyStyle::styleHint(hint, option, widget, returnData);
|
|
|
|
}
|
|
|
|
// clang-format on
|
|
|
|
};
|
|
|
|
|
|
|
|
ManagedPackPage* ManagedPackPage::createPage(BaseInstance* inst, QString type, QWidget* parent)
|
|
|
|
{
|
|
|
|
if (type == "modrinth")
|
2022-10-14 18:36:48 +01:00
|
|
|
return new ModrinthManagedPackPage(inst, nullptr, parent);
|
2022-10-13 23:55:21 +01:00
|
|
|
if (type == "flame")
|
2022-10-14 18:36:48 +01:00
|
|
|
return new FlameManagedPackPage(inst, nullptr, parent);
|
2022-10-13 23:55:21 +01:00
|
|
|
|
2022-10-14 18:36:48 +01:00
|
|
|
return new GenericManagedPackPage(inst, nullptr, parent);
|
2022-10-13 23:55:21 +01:00
|
|
|
}
|
|
|
|
|
2022-10-14 18:36:48 +01:00
|
|
|
ManagedPackPage::ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent)
|
|
|
|
: QWidget(parent), m_instance_window(instance_window), ui(new Ui::ManagedPackPage), m_inst(inst)
|
2022-10-13 23:55:21 +01:00
|
|
|
{
|
|
|
|
Q_ASSERT(inst);
|
|
|
|
|
|
|
|
ui->setupUi(this);
|
|
|
|
|
|
|
|
ui->versionsComboBox->setStyle(new NoBigComboBoxStyle(ui->versionsComboBox->style()));
|
|
|
|
}
|
|
|
|
|
|
|
|
ManagedPackPage::~ManagedPackPage()
|
|
|
|
{
|
|
|
|
delete ui;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ManagedPackPage::openedImpl()
|
|
|
|
{
|
|
|
|
ui->packName->setText(m_inst->getManagedPackName());
|
|
|
|
ui->packVersion->setText(m_inst->getManagedPackVersionName());
|
2022-11-11 21:29:32 +00:00
|
|
|
ui->packOrigin->setText(tr("Website: <a href=%1>%2</a> | Pack ID: %3 | Version ID: %4")
|
|
|
|
.arg(url(), displayName(), m_inst->getManagedPackID(), m_inst->getManagedPackVersionID()));
|
2022-10-13 23:55:21 +01:00
|
|
|
|
|
|
|
parseManagedPack();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ManagedPackPage::displayName() const
|
|
|
|
{
|
|
|
|
auto type = m_inst->getManagedPackType();
|
|
|
|
if (type.isEmpty())
|
|
|
|
return {};
|
|
|
|
return type.replace(0, 1, type[0].toUpper());
|
|
|
|
}
|
|
|
|
|
|
|
|
QIcon ManagedPackPage::icon() const
|
|
|
|
{
|
|
|
|
return APPLICATION->getThemedIcon(m_inst->getManagedPackType());
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ManagedPackPage::helpPage() const
|
|
|
|
{
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
void ManagedPackPage::retranslate()
|
|
|
|
{
|
|
|
|
ui->retranslateUi(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ManagedPackPage::shouldDisplay() const
|
|
|
|
{
|
|
|
|
return m_inst->isManagedPack();
|
|
|
|
}
|
|
|
|
|
2022-10-14 18:36:48 +01:00
|
|
|
bool ManagedPackPage::runUpdateTask(InstanceTask* task)
|
|
|
|
{
|
|
|
|
Q_ASSERT(task);
|
|
|
|
|
|
|
|
unique_qobject_ptr<Task> wrapped_task(APPLICATION->instances()->wrapInstanceTask(task));
|
|
|
|
|
|
|
|
connect(task, &Task::failed,
|
|
|
|
[this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); });
|
|
|
|
connect(task, &Task::succeeded, [this, task]() {
|
|
|
|
QStringList warnings = task->warnings();
|
|
|
|
if (warnings.count())
|
|
|
|
CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show();
|
|
|
|
});
|
|
|
|
connect(task, &Task::aborted, [this] {
|
|
|
|
CustomMessageBox::selectable(this, tr("Task aborted"), tr("The task has been aborted by the user."), QMessageBox::Information)
|
|
|
|
->show();
|
|
|
|
});
|
|
|
|
|
|
|
|
ProgressDialog loadDialog(this);
|
|
|
|
loadDialog.setSkipButton(true, tr("Abort"));
|
|
|
|
loadDialog.execWithTask(task);
|
|
|
|
|
|
|
|
return task->wasSuccessful();
|
|
|
|
}
|
|
|
|
|
2022-11-11 20:44:16 +00:00
|
|
|
void ManagedPackPage::suggestVersion()
|
|
|
|
{
|
|
|
|
ui->updateButton->setText(tr("Update pack"));
|
|
|
|
ui->updateButton->setDisabled(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ManagedPackPage::setFailState()
|
|
|
|
{
|
|
|
|
qDebug() << "Setting fail state!";
|
|
|
|
|
|
|
|
// We block signals here so that suggestVersion() doesn't get called, causing an assertion fail.
|
|
|
|
ui->versionsComboBox->blockSignals(true);
|
|
|
|
ui->versionsComboBox->clear();
|
|
|
|
ui->versionsComboBox->addItem(tr("Failed to search for available versions."), {});
|
|
|
|
ui->versionsComboBox->blockSignals(false);
|
|
|
|
|
|
|
|
ui->changelogTextBrowser->setText(tr("Failed to request changelog data for this modpack."));
|
|
|
|
|
|
|
|
ui->updateButton->setText(tr("Cannot update!"));
|
|
|
|
ui->updateButton->setDisabled(true);
|
|
|
|
|
|
|
|
// TODO: Perhaps start a timer here when m_loaded is false to try and reload.
|
|
|
|
}
|
|
|
|
|
2022-10-14 18:36:48 +01:00
|
|
|
ModrinthManagedPackPage::ModrinthManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent)
|
|
|
|
: ManagedPackPage(inst, instance_window, parent)
|
2022-10-13 23:55:21 +01:00
|
|
|
{
|
|
|
|
Q_ASSERT(inst->isManagedPack());
|
|
|
|
connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion()));
|
2022-10-14 18:36:48 +01:00
|
|
|
connect(ui->updateButton, &QPushButton::pressed, this, &ModrinthManagedPackPage::update);
|
2022-10-13 23:55:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ModrinthManagedPackPage::parseManagedPack()
|
|
|
|
{
|
2022-10-13 23:57:23 +01:00
|
|
|
qDebug() << "Parsing Modrinth pack";
|
|
|
|
|
|
|
|
auto netJob = new NetJob(QString("Modrinth::PackVersions(%1)").arg(m_inst->getManagedPackName()), APPLICATION->network());
|
|
|
|
auto response = new QByteArray();
|
|
|
|
|
|
|
|
QString id = m_inst->getManagedPackID();
|
|
|
|
|
|
|
|
netJob->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response));
|
|
|
|
|
|
|
|
QObject::connect(netJob, &NetJob::succeeded, this, [this, response, id] {
|
|
|
|
QJsonParseError parse_error{};
|
|
|
|
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
|
|
|
|
if (parse_error.error != QJsonParseError::NoError) {
|
|
|
|
qWarning() << "Error while parsing JSON response from Modrinth at " << parse_error.offset
|
|
|
|
<< " reason: " << parse_error.errorString();
|
|
|
|
qWarning() << *response;
|
2022-11-11 20:44:16 +00:00
|
|
|
|
|
|
|
setFailState();
|
|
|
|
|
2022-10-13 23:57:23 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
Modrinth::loadIndexedVersions(m_pack, doc);
|
|
|
|
} catch (const JSONValidationError& e) {
|
|
|
|
qDebug() << *response;
|
|
|
|
qWarning() << "Error while reading modrinth modpack version: " << e.cause();
|
2022-11-11 20:44:16 +00:00
|
|
|
|
|
|
|
setFailState();
|
|
|
|
return;
|
2022-10-13 23:57:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (auto version : m_pack.versions) {
|
2022-10-14 00:32:40 +01:00
|
|
|
QString name;
|
|
|
|
|
2022-10-13 23:57:23 +01:00
|
|
|
if (!version.name.contains(version.version))
|
2022-10-14 00:32:40 +01:00
|
|
|
name = QString("%1 — %2").arg(version.name, version.version);
|
2022-10-13 23:57:23 +01:00
|
|
|
else
|
2022-10-14 00:32:40 +01:00
|
|
|
name = version.name;
|
|
|
|
|
|
|
|
// NOTE: the id from version isn't the same id in the modpack format spec...
|
|
|
|
// e.g. HexMC's 4.4.0 has versionId 4.0.0 in the modpack index..............
|
|
|
|
if (version.version == m_inst->getManagedPackVersionName())
|
|
|
|
name.append(tr(" (Current)"));
|
|
|
|
|
|
|
|
ui->versionsComboBox->addItem(name, QVariant(version.id));
|
2022-10-13 23:57:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
suggestVersion();
|
|
|
|
|
|
|
|
m_loaded = true;
|
|
|
|
});
|
2022-11-11 20:44:16 +00:00
|
|
|
QObject::connect(netJob, &NetJob::failed, this, &ModrinthManagedPackPage::setFailState);
|
|
|
|
QObject::connect(netJob, &NetJob::aborted, this, &ModrinthManagedPackPage::setFailState);
|
2022-10-13 23:57:23 +01:00
|
|
|
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] {
|
|
|
|
netJob->deleteLater();
|
|
|
|
delete response;
|
|
|
|
});
|
2022-11-12 14:49:21 +00:00
|
|
|
|
|
|
|
ui->changelogTextBrowser->setText(tr("Fetching changelogs..."));
|
|
|
|
|
2022-10-13 23:57:23 +01:00
|
|
|
netJob->start();
|
2022-10-13 23:55:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QString ModrinthManagedPackPage::url() const
|
|
|
|
{
|
2022-11-11 21:29:32 +00:00
|
|
|
return "https://modrinth.com/mod/" + m_inst->getManagedPackID();
|
2022-10-13 23:55:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ModrinthManagedPackPage::suggestVersion()
|
|
|
|
{
|
2022-10-13 23:57:23 +01:00
|
|
|
auto index = ui->versionsComboBox->currentIndex();
|
|
|
|
auto version = m_pack.versions.at(index);
|
|
|
|
|
2022-10-22 20:02:10 +01:00
|
|
|
HoeDown md_parser;
|
|
|
|
ui->changelogTextBrowser->setHtml(md_parser.process(version.changelog.toUtf8()));
|
2022-11-11 20:44:16 +00:00
|
|
|
|
|
|
|
ManagedPackPage::suggestVersion();
|
2022-10-13 23:55:21 +01:00
|
|
|
}
|
|
|
|
|
2022-10-14 18:36:48 +01:00
|
|
|
void ModrinthManagedPackPage::update()
|
2022-10-13 23:55:21 +01:00
|
|
|
{
|
2022-10-14 18:36:48 +01:00
|
|
|
auto index = ui->versionsComboBox->currentIndex();
|
|
|
|
auto version = m_pack.versions.at(index);
|
|
|
|
|
|
|
|
auto extracted = new InstanceImportTask(version.download_url, this);
|
|
|
|
|
|
|
|
InstanceName inst_name(m_inst->getManagedPackName(), version.version);
|
|
|
|
inst_name.setName(m_inst->name().replace(m_inst->getManagedPackVersionName(), version.version));
|
|
|
|
extracted->setName(inst_name);
|
|
|
|
|
|
|
|
extracted->setGroup(APPLICATION->instances()->getInstanceGroup(m_inst->id()));
|
|
|
|
extracted->setIcon(m_inst->iconKey());
|
|
|
|
extracted->setConfirmUpdate(false);
|
|
|
|
|
|
|
|
auto did_succeed = runUpdateTask(extracted);
|
|
|
|
|
|
|
|
if (m_instance_window && did_succeed)
|
|
|
|
m_instance_window->close();
|
2022-10-13 23:55:21 +01:00
|
|
|
}
|
|
|
|
|
2022-10-14 18:36:48 +01:00
|
|
|
FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent)
|
|
|
|
: ManagedPackPage(inst, instance_window, parent)
|
2022-10-13 23:55:21 +01:00
|
|
|
{
|
2022-10-14 18:36:48 +01:00
|
|
|
Q_ASSERT(inst->isManagedPack());
|
|
|
|
connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion()));
|
2022-10-13 23:55:21 +01:00
|
|
|
}
|
|
|
|
|
2022-10-14 18:36:48 +01:00
|
|
|
void FlameManagedPackPage::parseManagedPack() {}
|
|
|
|
|
2022-10-13 23:55:21 +01:00
|
|
|
QString FlameManagedPackPage::url() const
|
|
|
|
{
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
void FlameManagedPackPage::suggestVersion()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "ManagedPackPage.moc"
|