merge upstream and resolve conflicts

This commit is contained in:
flow
2022-02-25 13:43:27 -03:00
26 changed files with 361 additions and 1591 deletions

View File

@ -1,51 +0,0 @@
#include "LegacyUpgradePage.h"
#include "ui_LegacyUpgradePage.h"
#include "InstanceList.h"
#include "minecraft/legacy/LegacyInstance.h"
#include "minecraft/legacy/LegacyUpgradeTask.h"
#include "Application.h"
#include "ui/dialogs/CustomMessageBox.h"
#include "ui/dialogs/ProgressDialog.h"
LegacyUpgradePage::LegacyUpgradePage(InstancePtr inst, QWidget *parent)
: QWidget(parent), ui(new Ui::LegacyUpgradePage), m_inst(inst)
{
ui->setupUi(this);
}
LegacyUpgradePage::~LegacyUpgradePage()
{
delete ui;
}
void LegacyUpgradePage::runModalTask(Task *task)
{
connect(task, &Task::failed, [this](QString reason)
{
CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Warning)->show();
});
ProgressDialog loadDialog(this);
loadDialog.setSkipButton(true, tr("Abort"));
if(loadDialog.execWithTask(task) == QDialog::Accepted)
{
m_container->requestClose();
}
}
void LegacyUpgradePage::on_upgradeButton_clicked()
{
QString newName = tr("%1 (Migrated)").arg(m_inst->name());
auto upgradeTask = new LegacyUpgradeTask(m_inst);
upgradeTask->setName(newName);
upgradeTask->setGroup(APPLICATION->instances()->getInstanceGroup(m_inst->id()));
upgradeTask->setIcon(m_inst->iconKey());
unique_qobject_ptr<Task> task(APPLICATION->instances()->wrapInstanceTask(upgradeTask));
runModalTask(task.get());
}
bool LegacyUpgradePage::shouldDisplay() const
{
return !m_inst->isRunning();
}

View File

@ -1,64 +0,0 @@
/* Copyright 2013-2021 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <QWidget>
#include "minecraft/legacy/LegacyInstance.h"
#include "ui/pages/BasePage.h"
#include <Application.h>
#include "tasks/Task.h"
namespace Ui
{
class LegacyUpgradePage;
}
class LegacyUpgradePage : public QWidget, public BasePage
{
Q_OBJECT
public:
explicit LegacyUpgradePage(InstancePtr inst, QWidget *parent = 0);
virtual ~LegacyUpgradePage();
virtual QString displayName() const override
{
return tr("Upgrade");
}
virtual QIcon icon() const override
{
return APPLICATION->getThemedIcon("checkupdate");
}
virtual QString id() const override
{
return "upgrade";
}
virtual QString helpPage() const override
{
return "Legacy-upgrade";
}
virtual bool shouldDisplay() const override;
private slots:
void on_upgradeButton_clicked();
private:
void runModalTask(Task *task);
private:
Ui::LegacyUpgradePage *ui;
InstancePtr m_inst;
};

View File

@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LegacyUpgradePage</class>
<widget class="QWidget" name="LegacyUpgradePage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>546</width>
<height>405</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTextBrowser" name="textBrowser">
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;h1 style=&quot; margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:xx-large; font-weight:600;&quot;&gt;Upgrade is required&lt;/span&gt;&lt;/h1&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;PolyMC now supports old Minecraft versions and all the required features in the new (OneSix) instance format. As a consequence, the old (Legacy) format has been entirely disabled and old instances need to be upgraded.&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The upgrade will create a new instance with the same contents as the current one, in the new format. The original instance will remain untouched, in case anything goes wrong in the process.&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Please report any issues on our &lt;a href=&quot;https://github.com/PolyMC/PolyMC/issues&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#3584e4;&quot;&gt;github issues page&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCommandLinkButton" name="upgradeButton">
<property name="text">
<string>Upgrade the instance</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -4,209 +4,211 @@
#include <QKeyEvent>
#include "Application.h"
#include "Json.h"
#include "ui/dialogs/ModDownloadDialog.h"
#include "InstanceImportTask.h"
#include "FlameModModel.h"
#include "InstanceImportTask.h"
#include "Json.h"
#include "ModDownloadTask.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "ui/dialogs/ModDownloadDialog.h"
FlameModPage::FlameModPage(ModDownloadDialog *dialog, BaseInstance *instance)
: QWidget(dialog), m_instance(instance), ui(new Ui::FlameModPage), dialog(dialog)
{
ui->setupUi(this);
connect(ui->searchButton, &QPushButton::clicked, this, &FlameModPage::triggerSearch);
ui->searchEdit->installEventFilter(this);
listModel = new FlameMod::ListModel(this);
ui->packView->setModel(listModel);
: QWidget(dialog), m_instance(instance), ui(new Ui::FlameModPage),
dialog(dialog) {
ui->setupUi(this);
connect(ui->searchButton, &QPushButton::clicked, this,
&FlameModPage::triggerSearch);
ui->searchEdit->installEventFilter(this);
listModel = new FlameMod::ListModel(this);
ui->packView->setModel(listModel);
ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(
Qt::ScrollBarAsNeeded);
ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
// index is used to set the sorting with the flame api
ui->sortByBox->addItem(tr("Sort by Featured"));
ui->sortByBox->addItem(tr("Sort by Popularity"));
ui->sortByBox->addItem(tr("Sort by last updated"));
ui->sortByBox->addItem(tr("Sort by Name"));
ui->sortByBox->addItem(tr("Sort by Author"));
ui->sortByBox->addItem(tr("Sort by Downloads"));
// index is used to set the sorting with the flame api
ui->sortByBox->addItem(tr("Sort by Featured"));
ui->sortByBox->addItem(tr("Sort by Popularity"));
ui->sortByBox->addItem(tr("Sort by last updated"));
ui->sortByBox->addItem(tr("Sort by Name"));
ui->sortByBox->addItem(tr("Sort by Author"));
ui->sortByBox->addItem(tr("Sort by Downloads"));
connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch()));
connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FlameModPage::onSelectionChanged);
connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FlameModPage::onVersionSelectionChanged);
connect(ui->modSelectionButton, &QPushButton::clicked, this, &FlameModPage::onModSelected);
connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this,
SLOT(triggerSearch()));
connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &FlameModPage::onSelectionChanged);
connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this,
&FlameModPage::onVersionSelectionChanged);
connect(ui->modSelectionButton, &QPushButton::clicked, this,
&FlameModPage::onModSelected);
}
FlameModPage::~FlameModPage()
{
delete ui;
}
FlameModPage::~FlameModPage() { delete ui; }
bool FlameModPage::eventFilter(QObject* watched, QEvent* event)
{
if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Return) {
triggerSearch();
keyEvent->accept();
return true;
}
bool FlameModPage::eventFilter(QObject *watched, QEvent *event) {
if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Return) {
triggerSearch();
keyEvent->accept();
return true;
}
return QWidget::eventFilter(watched, event);
}
return QWidget::eventFilter(watched, event);
}
bool FlameModPage::shouldDisplay() const
{
return true;
bool FlameModPage::shouldDisplay() const { return true; }
void FlameModPage::openedImpl() {
updateSelectionButton();
triggerSearch();
}
void FlameModPage::openedImpl()
{
updateSelectionButton();
triggerSearch();
void FlameModPage::triggerSearch() {
listModel->searchWithTerm(ui->searchEdit->text(),
ui->sortByBox->currentIndex());
}
void FlameModPage::triggerSearch()
{
listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex());
}
void FlameModPage::onSelectionChanged(QModelIndex first, QModelIndex second) {
ui->versionSelectionBox->clear();
void FlameModPage::onSelectionChanged(QModelIndex first, QModelIndex second)
{
ui->versionSelectionBox->clear();
if (!first.isValid()) {
return;
}
if(!first.isValid())
{
current = listModel->data(first, Qt::UserRole).value<FlameMod::IndexedPack>();
QString text = "";
QString name = current.name;
if (current.websiteUrl.isEmpty())
text = name;
else
text = "<a href=\"" + current.websiteUrl + "\">" + name + "</a>";
if (!current.authors.empty()) {
auto authorToStr = [](FlameMod::ModpackAuthor &author) {
if (author.url.isEmpty()) {
return author.name;
}
return QString("<a href=\"%1\">%2</a>").arg(author.url, author.name);
};
QStringList authorStrs;
for (auto &author : current.authors) {
authorStrs.push_back(authorToStr(author));
}
text += "<br>" + tr(" by ") + authorStrs.join(", ");
}
text += "<br><br>";
ui->packDescription->setHtml(text + current.description);
if (!current.versionsLoaded) {
qDebug() << "Loading flame mod versions";
ui->modSelectionButton->setText(tr("Loading versions..."));
ui->modSelectionButton->setEnabled(false);
auto netJob =
new NetJob(QString("Flame::ModVersions(%1)").arg(current.name),
APPLICATION->network());
auto response = new QByteArray();
int addonId = current.addonId;
netJob->addNetAction(Net::Download::makeByteArray(
QString("https://addons-ecs.forgesvc.net/api/v2/addon/%1/files")
.arg(addonId),
response));
QObject::connect(netJob, &NetJob::succeeded, this, [this, response] {
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;
return;
}
current = listModel->data(first, Qt::UserRole).value<FlameMod::IndexedPack>();
QString text = "";
QString name = current.name;
if (current.websiteUrl.isEmpty())
text = name;
else
text = "<a href=\"" + current.websiteUrl + "\">" + name + "</a>";
if (!current.authors.empty()) {
auto authorToStr = [](FlameMod::ModpackAuthor & author) {
if(author.url.isEmpty()) {
return author.name;
}
return QString("<a href=\"%1\">%2</a>").arg(author.url, author.name);
};
QStringList authorStrs;
for(auto & author: current.authors) {
authorStrs.push_back(authorToStr(author));
}
QJsonArray arr = doc.array();
try {
FlameMod::loadIndexedPackVersions(current, arr, APPLICATION->network(),
m_instance);
} catch (const JSONValidationError &e) {
qDebug() << *response;
qWarning() << "Error while reading Flame mod version: " << e.cause();
}
auto packProfile = ((MinecraftInstance *)m_instance)->getPackProfile();
QString mcVersion = packProfile->getComponentVersion("net.minecraft");
QString loaderString =
(packProfile->getComponentVersion("net.minecraftforge").isEmpty())
? "fabric"
: "forge";
for (int i = 0; i < current.versions.size(); i++) {
auto version = current.versions[i];
if (!version.mcVersion.contains(mcVersion)) {
continue;
}
text += "<br>" + tr(" by ") + authorStrs.join(", ");
ui->versionSelectionBox->addItem(version.version, QVariant(i));
}
if (ui->versionSelectionBox->count() == 0) {
ui->versionSelectionBox->addItem(tr("No Valid Version found!"),
QVariant(-1));
}
ui->modSelectionButton->setText(tr("Cannot select invalid version :("));
updateSelectionButton();
});
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] {
netJob->deleteLater();
delete response;
});
netJob->start();
} else {
for (int i = 0; i < current.versions.size(); i++) {
ui->versionSelectionBox->addItem(current.versions[i].version,
QVariant(i));
}
text += "<br><br>";
ui->packDescription->setHtml(text + current.description);
if (!current.versionsLoaded)
{
qDebug() << "Loading flame mod versions";
ui->modSelectionButton->setText(tr("Loading versions..."));
ui->modSelectionButton->setEnabled(false);
auto netJob = new NetJob(QString("Flame::ModVersions(%1)").arg(current.name), APPLICATION->network());
std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
int addonId = current.addonId;
netJob->addNetAction(Net::Download::makeByteArray(QString("https://addons-ecs.forgesvc.net/api/v2/addon/%1/files").arg(addonId), response.get()));
QObject::connect(netJob, &NetJob::succeeded, this, [this, response, netJob]
{
netJob->deleteLater();
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;
return;
}
QJsonArray arr = doc.array();
try
{
FlameMod::loadIndexedPackVersions(current, arr, APPLICATION->network(), m_instance);
}
catch(const JSONValidationError &e)
{
qDebug() << *response;
qWarning() << "Error while reading Flame mod version: " << e.cause();
}
auto packProfile = ((MinecraftInstance *)m_instance)->getPackProfile();
QString mcVersion = packProfile->getComponentVersion("net.minecraft");
QString loaderString = (packProfile->getComponentVersion("net.minecraftforge").isEmpty()) ? "fabric" : "forge";
for(int i = 0; i < current.versions.size(); i++) {
auto version = current.versions[i];
if(!version.mcVersion.contains(mcVersion)){
continue;
}
ui->versionSelectionBox->addItem(version.version, QVariant(i));
}
if(ui->versionSelectionBox->count() == 0){
ui->versionSelectionBox->addItem(tr("No Valid Version found!"), QVariant(-1));
}
ui->modSelectionButton->setText(tr("Cannot select invalid version :("));
updateSelectionButton();
});
netJob->start();
}
else
{
for(int i = 0; i < current.versions.size(); i++) {
ui->versionSelectionBox->addItem(current.versions[i].version, QVariant(i));
}
if(ui->versionSelectionBox->count() == 0){
ui->versionSelectionBox->addItem(tr("No Valid Version found!"), QVariant(-1));
}
updateSelectionButton();
}
}
void FlameModPage::updateSelectionButton()
{
if(!isOpened || selectedVersion < 0){
ui->modSelectionButton->setEnabled(false);
return;
}
ui->modSelectionButton->setEnabled(true);
auto& version = current.versions[selectedVersion];
if(!dialog->isModSelected(current.name, version.fileName)){
ui->modSelectionButton->setText(tr("Select mod for download"));
}
else{
ui->modSelectionButton->setText(tr("Deselect mod for download"));
}
}
void FlameModPage::onVersionSelectionChanged(QString data)
{
if(data.isNull() || data.isEmpty())
{
selectedVersion = -1;
return;
}
selectedVersion = ui->versionSelectionBox->currentData().toInt();
updateSelectionButton();
}
void FlameModPage::onModSelected()
{
auto& version = current.versions[selectedVersion];
if (dialog->isModSelected(current.name, version.fileName)){
dialog->removeSelectedMod(current.name);
}
else{
dialog->addSelectedMod(current.name, new ModDownloadTask(version.downloadUrl, version.fileName , dialog->mods));
if (ui->versionSelectionBox->count() == 0) {
ui->versionSelectionBox->addItem(tr("No Valid Version found!"),
QVariant(-1));
}
updateSelectionButton();
}
}
void FlameModPage::updateSelectionButton() {
if (!isOpened || selectedVersion < 0) {
ui->modSelectionButton->setEnabled(false);
return;
}
ui->modSelectionButton->setEnabled(true);
auto &version = current.versions[selectedVersion];
if (!dialog->isModSelected(current.name, version.fileName)) {
ui->modSelectionButton->setText(tr("Select mod for download"));
} else {
ui->modSelectionButton->setText(tr("Deselect mod for download"));
}
}
void FlameModPage::onVersionSelectionChanged(QString data) {
if (data.isNull() || data.isEmpty()) {
selectedVersion = -1;
return;
}
selectedVersion = ui->versionSelectionBox->currentData().toInt();
updateSelectionButton();
}
void FlameModPage::onModSelected() {
auto &version = current.versions[selectedVersion];
if (dialog->isModSelected(current.name, version.fileName)) {
dialog->removeSelectedMod(current.name);
} else {
dialog->addSelectedMod(current.name,
new ModDownloadTask(version.downloadUrl,
version.fileName, dialog->mods));
}
updateSelectionButton();
}

View File

@ -4,194 +4,199 @@
#include <QKeyEvent>
#include "Application.h"
#include "Json.h"
#include "ui/dialogs/ModDownloadDialog.h"
#include "InstanceImportTask.h"
#include "ModrinthModel.h"
#include "Json.h"
#include "ModDownloadTask.h"
#include "ModrinthModel.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "ui/dialogs/ModDownloadDialog.h"
ModrinthPage::ModrinthPage(ModDownloadDialog *dialog, BaseInstance *instance)
: QWidget(dialog), m_instance(instance), ui(new Ui::ModrinthPage), dialog(dialog)
{
ui->setupUi(this);
connect(ui->searchButton, &QPushButton::clicked, this, &ModrinthPage::triggerSearch);
ui->searchEdit->installEventFilter(this);
listModel = new Modrinth::ListModel(this);
ui->packView->setModel(listModel);
: QWidget(dialog), m_instance(instance), ui(new Ui::ModrinthPage),
dialog(dialog) {
ui->setupUi(this);
connect(ui->searchButton, &QPushButton::clicked, this,
&ModrinthPage::triggerSearch);
ui->searchEdit->installEventFilter(this);
listModel = new Modrinth::ListModel(this);
ui->packView->setModel(listModel);
ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(
Qt::ScrollBarAsNeeded);
ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
// index is used to set the sorting with the modrinth api
ui->sortByBox->addItem(tr("Sort by Relevence"));
ui->sortByBox->addItem(tr("Sort by Downloads"));
ui->sortByBox->addItem(tr("Sort by Follows"));
ui->sortByBox->addItem(tr("Sort by last updated"));
ui->sortByBox->addItem(tr("Sort by newest"));
// index is used to set the sorting with the modrinth api
ui->sortByBox->addItem(tr("Sort by Relevence"));
ui->sortByBox->addItem(tr("Sort by Downloads"));
ui->sortByBox->addItem(tr("Sort by Follows"));
ui->sortByBox->addItem(tr("Sort by last updated"));
ui->sortByBox->addItem(tr("Sort by newest"));
connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this, SLOT(triggerSearch()));
connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModrinthPage::onSelectionChanged);
connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &ModrinthPage::onVersionSelectionChanged);
connect(ui->modSelectionButton, &QPushButton::clicked, this, &ModrinthPage::onModSelected);
connect(ui->sortByBox, SIGNAL(currentIndexChanged(int)), this,
SLOT(triggerSearch()));
connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &ModrinthPage::onSelectionChanged);
connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this,
&ModrinthPage::onVersionSelectionChanged);
connect(ui->modSelectionButton, &QPushButton::clicked, this,
&ModrinthPage::onModSelected);
}
ModrinthPage::~ModrinthPage()
{
delete ui;
}
ModrinthPage::~ModrinthPage() { delete ui; }
bool ModrinthPage::eventFilter(QObject* watched, QEvent* event)
{
if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Return) {
triggerSearch();
keyEvent->accept();
return true;
}
bool ModrinthPage::eventFilter(QObject *watched, QEvent *event) {
if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Return) {
triggerSearch();
keyEvent->accept();
return true;
}
return QWidget::eventFilter(watched, event);
}
return QWidget::eventFilter(watched, event);
}
bool ModrinthPage::shouldDisplay() const
{
return true;
bool ModrinthPage::shouldDisplay() const { return true; }
void ModrinthPage::openedImpl() {
updateSelectionButton();
triggerSearch();
}
void ModrinthPage::openedImpl()
{
updateSelectionButton();
triggerSearch();
void ModrinthPage::triggerSearch() {
listModel->searchWithTerm(ui->searchEdit->text(),
ui->sortByBox->currentIndex());
}
void ModrinthPage::triggerSearch()
{
listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex());
}
void ModrinthPage::onSelectionChanged(QModelIndex first, QModelIndex second) {
ui->versionSelectionBox->clear();
void ModrinthPage::onSelectionChanged(QModelIndex first, QModelIndex second)
{
ui->versionSelectionBox->clear();
if (!first.isValid()) {
return;
}
if(!first.isValid())
{
current = listModel->data(first, Qt::UserRole).value<Modrinth::IndexedPack>();
QString text = "";
QString name = current.name;
if (current.websiteUrl.isEmpty())
text = name;
else
text = "<a href=\"" + current.websiteUrl + "\">" + name + "</a>";
text += "<br>" + tr(" by ") + "<a href=\"" + current.author.url + "\">" +
current.author.name + "</a><br><br>";
ui->packDescription->setHtml(text + current.description);
if (!current.versionsLoaded) {
qDebug() << "Loading Modrinth mod versions";
ui->modSelectionButton->setText(tr("Loading versions..."));
ui->modSelectionButton->setEnabled(false);
auto netJob =
new NetJob(QString("Modrinth::ModVersions(%1)").arg(current.name),
APPLICATION->network());
auto response = new QByteArray();
QString addonId = current.addonId;
netJob->addNetAction(Net::Download::makeByteArray(
QString("https://api.modrinth.com/v2/project/%1/version").arg(addonId),
response));
QObject::connect(netJob, &NetJob::succeeded, this, [this, response] {
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;
return;
}
current = listModel->data(first, Qt::UserRole).value<Modrinth::IndexedPack>();
QString text = "";
QString name = current.name;
if (current.websiteUrl.isEmpty())
text = name;
else
text = "<a href=\"" + current.websiteUrl + "\">" + name + "</a>";
text += "<br>"+ tr(" by ") + "<a href=\""+current.author.url+"\">"+current.author.name+"</a><br><br>";
ui->packDescription->setHtml(text + current.description);
if (!current.versionsLoaded)
{
qDebug() << "Loading Modrinth mod versions";
ui->modSelectionButton->setText(tr("Loading versions..."));
ui->modSelectionButton->setEnabled(false);
auto netJob = new NetJob(QString("Modrinth::ModVersions(%1)").arg(current.name), APPLICATION->network());
std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
QString addonId = current.addonId;
netJob->addNetAction(Net::Download::makeByteArray(QString("https://api.modrinth.com/v2/project/%1/version").arg(addonId), response.get()));
QObject::connect(netJob, &NetJob::succeeded, this, [this, response, netJob]
{
netJob->deleteLater();
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;
return;
}
QJsonArray arr = doc.array();
try
{
Modrinth::loadIndexedPackVersions(current, arr, APPLICATION->network(), m_instance);
}
catch(const JSONValidationError &e)
{
qDebug() << *response;
qWarning() << "Error while reading Modrinth mod version: " << e.cause();
}
auto packProfile = ((MinecraftInstance *)m_instance)->getPackProfile();
QString mcVersion = packProfile->getComponentVersion("net.minecraft");
QString loaderString = (packProfile->getComponentVersion("net.minecraftforge").isEmpty()) ? "fabric" : "forge";
for(int i = 0; i < current.versions.size(); i++) {
auto version = current.versions[i];
if(!version.mcVersion.contains(mcVersion) || !version.loaders.contains(loaderString)){
continue;
}
ui->versionSelectionBox->addItem(version.version, QVariant(i));
}
if(ui->versionSelectionBox->count() == 0){
ui->versionSelectionBox->addItem(tr("No Valid Version found !"), QVariant(-1));
}
ui->modSelectionButton->setText(tr("Cannot select invalid version :("));
updateSelectionButton();
});
netJob->start();
}
else
{
for(int i = 0; i < current.versions.size(); i++) {
ui->versionSelectionBox->addItem(current.versions[i].version, QVariant(i));
}
if(ui->versionSelectionBox->count() == 0){
ui->versionSelectionBox->addItem(tr("No Valid Version found !"), QVariant(-1));
}
QJsonArray arr = doc.array();
try {
Modrinth::loadIndexedPackVersions(current, arr, APPLICATION->network(),
m_instance);
} catch (const JSONValidationError &e) {
qDebug() << *response;
qWarning() << "Error while reading Modrinth mod version: " << e.cause();
}
auto packProfile = ((MinecraftInstance *)m_instance)->getPackProfile();
QString mcVersion = packProfile->getComponentVersion("net.minecraft");
QString loaderString =
(packProfile->getComponentVersion("net.minecraftforge").isEmpty())
? "fabric"
: "forge";
for (int i = 0; i < current.versions.size(); i++) {
auto version = current.versions[i];
if (!version.mcVersion.contains(mcVersion) ||
!version.loaders.contains(loaderString)) {
continue;
}
ui->versionSelectionBox->addItem(version.version, QVariant(i));
}
if (ui->versionSelectionBox->count() == 0) {
ui->versionSelectionBox->addItem(tr("No Valid Version found !"),
QVariant(-1));
}
updateSelectionButton();
}
}
ui->modSelectionButton->setText(tr("Cannot select invalid version :("));
updateSelectionButton();
});
void ModrinthPage::updateSelectionButton()
{
if(!isOpened || selectedVersion < 0){
ui->modSelectionButton->setEnabled(false);
return;
}
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] {
netJob->deleteLater();
delete response;
});
ui->modSelectionButton->setEnabled(true);
auto& version = current.versions[selectedVersion];
if(!dialog->isModSelected(current.name, version.fileName)){
ui->modSelectionButton->setText(tr("Select mod for download"));
netJob->start();
} else {
for (int i = 0; i < current.versions.size(); i++) {
ui->versionSelectionBox->addItem(current.versions[i].version,
QVariant(i));
}
else{
ui->modSelectionButton->setText(tr("Deselect mod for download"));
}
}
void ModrinthPage::onVersionSelectionChanged(QString data)
{
if (data.isNull() || data.isEmpty()){
selectedVersion = -1;
return;
}
selectedVersion = ui->versionSelectionBox->currentData().toInt();
updateSelectionButton();
}
void ModrinthPage::onModSelected()
{
auto& version = current.versions[selectedVersion];
if (dialog->isModSelected(current.name, version.fileName)){
dialog->removeSelectedMod(current.name);
}
else{
dialog->addSelectedMod(current.name, new ModDownloadTask(version.downloadUrl, version.fileName , dialog->mods));
if (ui->versionSelectionBox->count() == 0) {
ui->versionSelectionBox->addItem(tr("No Valid Version found !"),
QVariant(-1));
}
updateSelectionButton();
}
}
void ModrinthPage::updateSelectionButton() {
if (!isOpened || selectedVersion < 0) {
ui->modSelectionButton->setEnabled(false);
return;
}
ui->modSelectionButton->setEnabled(true);
auto &version = current.versions[selectedVersion];
if (!dialog->isModSelected(current.name, version.fileName)) {
ui->modSelectionButton->setText(tr("Select mod for download"));
} else {
ui->modSelectionButton->setText(tr("Deselect mod for download"));
}
}
void ModrinthPage::onVersionSelectionChanged(QString data) {
if (data.isNull() || data.isEmpty()) {
selectedVersion = -1;
return;
}
selectedVersion = ui->versionSelectionBox->currentData().toInt();
updateSelectionButton();
}
void ModrinthPage::onModSelected() {
auto &version = current.versions[selectedVersion];
if (dialog->isModSelected(current.name, version.fileName)) {
dialog->removeSelectedMod(current.name);
} else {
dialog->addSelectedMod(current.name,
new ModDownloadTask(version.downloadUrl,
version.fileName, dialog->mods));
}
updateSelectionButton();
}