Merge pull request #32 from flowln/modpack_update_page

Closes https://github.com/PrismLauncher/PrismLauncher/issues/180
Closes https://github.com/PrismLauncher/PrismLauncher/issues/170
This commit is contained in:
flow
2022-12-10 06:34:18 -08:00
committed by GitHub
25 changed files with 983 additions and 106 deletions

View File

@ -132,6 +132,12 @@ InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent)
{
connect(m_instance.get(), &BaseInstance::statusChanged, this, &InstanceWindow::on_instanceStatusChanged);
}
// add ourself as the modpack page's instance window
{
static_cast<ManagedPackPage*>(m_container->getPage("managed_pack"))->setInstanceWindow(this);
}
show();
}

View File

@ -1,10 +1,13 @@
#pragma once
class BasePage;
class BasePageContainer
{
public:
virtual ~BasePageContainer(){};
virtual bool selectPage(QString pageId) = 0;
virtual BasePage* getPage(QString pageId) { return nullptr; };
virtual void refreshContainer() = 0;
virtual bool requestClose() = 0;
};

View File

@ -0,0 +1,432 @@
// SPDX-FileCopyrightText: 2022 flow <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#include "ManagedPackPage.h"
#include "ui_ManagedPackPage.h"
#include <QListView>
#include <QProxyStyle>
#include <HoeDown.h>
#include "Application.h"
#include "BuildConfig.h"
#include "InstanceImportTask.h"
#include "InstanceList.h"
#include "InstanceTask.h"
#include "Json.h"
#include "modplatform/modrinth/ModrinthPackManifest.h"
#include "ui/InstanceWindow.h"
#include "ui/dialogs/CustomMessageBox.h"
#include "ui/dialogs/ProgressDialog.h"
/** 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")
return new ModrinthManagedPackPage(inst, nullptr, parent);
if (type == "flame" && (APPLICATION->capabilities() & Application::SupportsFlame))
return new FlameManagedPackPage(inst, nullptr, parent);
return new GenericManagedPackPage(inst, nullptr, parent);
}
ManagedPackPage::ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent)
: QWidget(parent), m_instance_window(instance_window), ui(new Ui::ManagedPackPage), m_inst(inst)
{
Q_ASSERT(inst);
ui->setupUi(this);
ui->versionsComboBox->setStyle(new NoBigComboBoxStyle(ui->versionsComboBox->style()));
ui->reloadButton->setVisible(false);
connect(ui->reloadButton, &QPushButton::clicked, this, [this](bool){
ui->reloadButton->setVisible(false);
m_loaded = false;
// Pretend we're opening the page again
openedImpl();
});
}
ManagedPackPage::~ManagedPackPage()
{
delete ui;
}
void ManagedPackPage::openedImpl()
{
ui->packName->setText(m_inst->getManagedPackName());
ui->packVersion->setText(m_inst->getManagedPackVersionName());
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()));
parseManagedPack();
}
QString ManagedPackPage::displayName() const
{
auto type = m_inst->getManagedPackType();
if (type.isEmpty())
return {};
if (type == "flame")
type = "CurseForge";
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();
}
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();
}
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);
ui->reloadButton->setVisible(true);
}
ModrinthManagedPackPage::ModrinthManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent)
: ManagedPackPage(inst, instance_window, parent)
{
Q_ASSERT(inst->isManagedPack());
connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion()));
connect(ui->updateButton, &QPushButton::pressed, this, &ModrinthManagedPackPage::update);
}
// MODRINTH
void ModrinthManagedPackPage::parseManagedPack()
{
qDebug() << "Parsing Modrinth pack";
// No need for the extra work because we already have everything we need.
if (m_loaded)
return;
if (m_fetch_job && m_fetch_job->isRunning())
m_fetch_job->abort();
m_fetch_job.reset(new NetJob(QString("Modrinth::PackVersions(%1)").arg(m_inst->getManagedPackName()), APPLICATION->network()));
auto response = std::make_shared<QByteArray>();
QString id = m_inst->getManagedPackID();
m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response.get()));
QObject::connect(m_fetch_job.get(), &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;
setFailState();
return;
}
try {
Modrinth::loadIndexedVersions(m_pack, doc);
} catch (const JSONValidationError& e) {
qDebug() << *response;
qWarning() << "Error while reading modrinth modpack version: " << e.cause();
setFailState();
return;
}
// We block signals here so that suggestVersion() doesn't get called, causing an assertion fail.
ui->versionsComboBox->blockSignals(true);
ui->versionsComboBox->clear();
ui->versionsComboBox->blockSignals(false);
for (auto version : m_pack.versions) {
QString name;
if (!version.name.contains(version.version))
name = QString("%1 — %2").arg(version.name, version.version);
else
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));
}
suggestVersion();
m_loaded = true;
});
QObject::connect(m_fetch_job.get(), &NetJob::failed, this, &ModrinthManagedPackPage::setFailState);
QObject::connect(m_fetch_job.get(), &NetJob::aborted, this, &ModrinthManagedPackPage::setFailState);
ui->changelogTextBrowser->setText(tr("Fetching changelogs..."));
m_fetch_job->start();
}
QString ModrinthManagedPackPage::url() const
{
return "https://modrinth.com/mod/" + m_inst->getManagedPackID();
}
void ModrinthManagedPackPage::suggestVersion()
{
auto index = ui->versionsComboBox->currentIndex();
auto version = m_pack.versions.at(index);
HoeDown md_parser;
ui->changelogTextBrowser->setHtml(md_parser.process(version.changelog.toUtf8()));
ManagedPackPage::suggestVersion();
}
void ModrinthManagedPackPage::update()
{
auto index = ui->versionsComboBox->currentIndex();
auto version = m_pack.versions.at(index);
QMap<QString, QString> extra_info;
// NOTE: Don't use 'm_pack.id' here, since we didn't completely parse all the metadata for the pack, including this field.
extra_info.insert("pack_id", m_inst->getManagedPackID());
extra_info.insert("pack_version_id", version.id);
extra_info.insert("original_instance_id", m_inst->id());
auto extracted = new InstanceImportTask(version.download_url, this, std::move(extra_info));
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();
}
// FLAME
FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent)
: ManagedPackPage(inst, instance_window, parent)
{
Q_ASSERT(inst->isManagedPack());
connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion()));
connect(ui->updateButton, &QPushButton::pressed, this, &FlameManagedPackPage::update);
}
void FlameManagedPackPage::parseManagedPack()
{
qDebug() << "Parsing Flame pack";
// We need to tell the user to redownload the pack, since we didn't save the required info previously
if (m_inst->getManagedPackID().isEmpty()) {
setFailState();
QString message =
tr("<h1>Hey there!</h1>"
"<h4>"
"It seems like your Pack ID is null. This is because of a bug in older versions of the launcher.<br/>"
"Unfortunately, we can't do the proper API requests without this information.<br/>"
"<br/>"
"So, in order for this feature to work, you will need to re-download the modpack from the built-in downloader.<br/>"
"<br/>"
"Don't worry though, it will ask you to update this instance instead, so you'll not lose this instance!"
"</h4>");
ui->changelogTextBrowser->setHtml(message);
return;
}
// No need for the extra work because we already have everything we need.
if (m_loaded)
return;
if (m_fetch_job && m_fetch_job->isRunning())
m_fetch_job->abort();
m_fetch_job.reset(new NetJob(QString("Flame::PackVersions(%1)").arg(m_inst->getManagedPackName()), APPLICATION->network()));
auto response = std::make_shared<QByteArray>();
QString id = m_inst->getManagedPackID();
m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response.get()));
QObject::connect(m_fetch_job.get(), &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 Flame at " << parse_error.offset
<< " reason: " << parse_error.errorString();
qWarning() << *response;
setFailState();
return;
}
try {
auto obj = doc.object();
auto data = Json::ensureArray(obj, "data");
Flame::loadIndexedPackVersions(m_pack, data);
} catch (const JSONValidationError& e) {
qDebug() << *response;
qWarning() << "Error while reading flame modpack version: " << e.cause();
setFailState();
return;
}
// We block signals here so that suggestVersion() doesn't get called, causing an assertion fail.
ui->versionsComboBox->blockSignals(true);
ui->versionsComboBox->clear();
ui->versionsComboBox->blockSignals(false);
for (auto version : m_pack.versions) {
QString name;
name = version.version;
if (version.fileId == m_inst->getManagedPackVersionID().toInt())
name.append(tr(" (Current)"));
ui->versionsComboBox->addItem(name, QVariant(version.fileId));
}
suggestVersion();
m_loaded = true;
});
QObject::connect(m_fetch_job.get(), &NetJob::failed, this, &FlameManagedPackPage::setFailState);
QObject::connect(m_fetch_job.get(), &NetJob::aborted, this, &FlameManagedPackPage::setFailState);
m_fetch_job->start();
}
QString FlameManagedPackPage::url() const
{
// FIXME: We should display the websiteUrl field, but this requires doing the API request first :(
return {};
}
void FlameManagedPackPage::suggestVersion()
{
auto index = ui->versionsComboBox->currentIndex();
auto version = m_pack.versions.at(index);
ui->changelogTextBrowser->setHtml(m_api.getModFileChangelog(m_inst->getManagedPackID().toInt(), version.fileId));
ManagedPackPage::suggestVersion();
}
void FlameManagedPackPage::update()
{
auto index = ui->versionsComboBox->currentIndex();
auto version = m_pack.versions.at(index);
QMap<QString, QString> extra_info;
extra_info.insert("pack_id", m_inst->getManagedPackID());
extra_info.insert("pack_version_id", QString::number(version.fileId));
extra_info.insert("original_instance_id", m_inst->id());
auto extracted = new InstanceImportTask(version.downloadUrl, this, std::move(extra_info));
extracted->setName(m_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();
}
#include "ManagedPackPage.moc"

View File

@ -0,0 +1,152 @@
// SPDX-FileCopyrightText: 2022 flow <flowlnlnln@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include "BaseInstance.h"
#include "modplatform/modrinth/ModrinthAPI.h"
#include "modplatform/modrinth/ModrinthPackManifest.h"
#include "modplatform/flame/FlameAPI.h"
#include "modplatform/flame/FlamePackIndex.h"
#include "ui/pages/BasePage.h"
#include <QWidget>
namespace Ui {
class ManagedPackPage;
}
class InstanceTask;
class InstanceWindow;
class ManagedPackPage : public QWidget, public BasePage {
Q_OBJECT
public:
inline static ManagedPackPage* createPage(BaseInstance* inst, QWidget* parent = nullptr)
{
return ManagedPackPage::createPage(inst, inst->getManagedPackType(), parent);
}
static ManagedPackPage* createPage(BaseInstance* inst, QString type, QWidget* parent = nullptr);
~ManagedPackPage() override;
[[nodiscard]] QString displayName() const override;
[[nodiscard]] QIcon icon() const override;
[[nodiscard]] QString helpPage() const override;
[[nodiscard]] QString id() const override { return "managed_pack"; }
[[nodiscard]] bool shouldDisplay() const override;
void openedImpl() override;
bool apply() override { return true; }
void retranslate() override;
/** Gets the necessary information about the managed pack, such as
* available versions*/
virtual void parseManagedPack(){};
/** URL of the managed pack.
* Not the version-specific one.
*/
[[nodiscard]] virtual QString url() const { return {}; };
void setInstanceWindow(InstanceWindow* window) { m_instance_window = window; }
public slots:
/** Gets the current version selection and update the UI, including the update button and the changelog.
*/
virtual void suggestVersion();
virtual void update(){};
protected slots:
/** Does the necessary UI changes for when something failed.
*
* This includes:
* - Setting an appropriate text on the version selector to indicate a fail;
* - Setting an appropriate text on the changelog text browser to indicate a fail;
* - Disable the update button.
*/
void setFailState();
protected:
ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent = nullptr);
/** Run the InstanceTask, with a progress dialog and all.
* Similar to MainWindow::instanceFromInstanceTask
*
* Returns whether the task was successful.
*/
bool runUpdateTask(InstanceTask*);
protected:
InstanceWindow* m_instance_window = nullptr;
Ui::ManagedPackPage* ui;
BaseInstance* m_inst;
bool m_loaded = false;
};
/** Simple page for when we aren't a managed pack. */
class GenericManagedPackPage final : public ManagedPackPage {
Q_OBJECT
public:
GenericManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent = nullptr)
: ManagedPackPage(inst, instance_window, parent)
{}
~GenericManagedPackPage() override = default;
// TODO: We may want to show this page with some useful info at some point.
[[nodiscard]] bool shouldDisplay() const override { return false; };
};
class ModrinthManagedPackPage final : public ManagedPackPage {
Q_OBJECT
public:
ModrinthManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent = nullptr);
~ModrinthManagedPackPage() override = default;
void parseManagedPack() override;
[[nodiscard]] QString url() const override;
public slots:
void suggestVersion() override;
void update() override;
private:
NetJob::Ptr m_fetch_job = nullptr;
Modrinth::Modpack m_pack;
ModrinthAPI m_api;
};
class FlameManagedPackPage final : public ManagedPackPage {
Q_OBJECT
public:
FlameManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent = nullptr);
~FlameManagedPackPage() override = default;
void parseManagedPack() override;
[[nodiscard]] QString url() const override;
public slots:
void suggestVersion() override;
void update() override;
private:
NetJob::Ptr m_fetch_job = nullptr;
Flame::IndexedPack m_pack;
FlameAPI m_api;
};

View File

@ -0,0 +1,193 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ManagedPackPage</class>
<widget class="QWidget" name="ManagedPackPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>731</width>
<height>538</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="packInformationBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Pack information</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<layout class="QHBoxLayout" name="packNameLayout">
<item>
<widget class="QLabel" name="packNameLabel">
<property name="text">
<string>Pack name:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="packName">
<property name="text">
<string notr="true">placeholder</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="packVersionLayout">
<item>
<widget class="QLabel" name="packVersionLabel">
<property name="text">
<string>Current version:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="packVersion">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string notr="true">placeholder</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="packOriginLayout">
<item>
<widget class="QLabel" name="packOriginLabel">
<property name="text">
<string>Provider information:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="packOrigin">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string notr="true">placeholder</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="updateToVersionLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Update to version:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="versionsComboBox"/>
</item>
<item>
<widget class="QPushButton" name="updateButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Fetching versions...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="changelogBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Changelog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QTextBrowser" name="changelogTextBrowser">
<property name="placeholderText">
<string>No changelog available for this version!</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="reloadButton">
<property name="text">
<string>Reload page</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -197,12 +197,18 @@ void FlamePage::suggestCurrent()
return;
}
if (selectedVersion.isEmpty() || selectedVersion == "-1") {
if (m_selected_version_index == -1) {
dialog->setSuggestedPack();
return;
}
dialog->setSuggestedPack(current.name, new InstanceImportTask(selectedVersion,this));
auto version = current.versions.at(m_selected_version_index);
QMap<QString, QString> extra_info;
extra_info.insert("pack_id", QString::number(current.addonId));
extra_info.insert("pack_version_id", QString::number(version.fileId));
dialog->setSuggestedPack(current.name, new InstanceImportTask(version.downloadUrl, this, std::move(extra_info)));
QString editedLogoName;
editedLogoName = "curseforge_" + current.logoName.section(".", 0, 0);
listModel->getLogo(current.logoName, current.logoUrl,
@ -211,11 +217,18 @@ void FlamePage::suggestCurrent()
void FlamePage::onVersionSelectionChanged(QString data)
{
if (data.isNull() || data.isEmpty()) {
selectedVersion = "";
bool is_blocked = false;
ui->versionSelectionBox->currentData().toInt(&is_blocked);
if (data.isNull() || data.isEmpty() || is_blocked) {
m_selected_version_index = -1;
return;
}
selectedVersion = ui->versionSelectionBox->currentData().toString();
m_selected_version_index = ui->versionSelectionBox->currentIndex();
Q_ASSERT(current.versions.at(m_selected_version_index).downloadUrl == ui->versionSelectionBox->currentData().toString());
suggestCurrent();
}

View File

@ -99,5 +99,5 @@ private:
Flame::ListModel* listModel = nullptr;
Flame::IndexedPack current;
QString selectedVersion;
int m_selected_version_index = -1;
};

View File

@ -300,7 +300,11 @@ void ModrinthPage::suggestCurrent()
for (auto& ver : current.versions) {
if (ver.id == selectedVersion) {
dialog->setSuggestedPack(current.name, ver.version, new InstanceImportTask(ver.download_url, this));
QMap<QString, QString> extra_info;
extra_info.insert("pack_id", current.id);
extra_info.insert("pack_version_id", ver.id);
dialog->setSuggestedPack(current.name, ver.version, new InstanceImportTask(ver.download_url, this, std::move(extra_info)));
auto iconName = current.iconName;
m_model->getLogo(iconName, current.iconUrl.toString(),
[this, iconName](QString logo) { dialog->setSuggestedIconFromFile(logo, iconName); });

View File

@ -130,6 +130,11 @@ bool PageContainer::selectPage(QString pageId)
return false;
}
BasePage* PageContainer::getPage(QString pageId)
{
return m_model->findPageEntryById(pageId);
}
void PageContainer::refreshContainer()
{
m_proxyModel->invalidate();

View File

@ -79,6 +79,7 @@ public:
}
virtual bool selectPage(QString pageId) override;
BasePage* getPage(QString pageId) override;
void refreshContainer() override;
virtual void setParentContainer(BasePageContainer * container)