Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97
2023-06-23 20:01:17 +03:00
95 changed files with 1872 additions and 936 deletions

View File

@ -35,15 +35,16 @@
#pragma once
#include <QString>
#include <QIcon>
#include <QString>
#include <functional>
#include <memory>
#include "BasePageContainer.h"
class BasePage
{
public:
class BasePage {
public:
using updateExtraInfoFunc = std::function<void(QString)>;
virtual ~BasePage() {}
virtual QString id() const = 0;
virtual QString displayName() const = 0;
@ -63,17 +64,16 @@ public:
}
virtual void openedImpl() {}
virtual void closedImpl() {}
virtual void setParentContainer(BasePageContainer * container)
{
m_container = container;
};
virtual void retranslate() { }
virtual void setParentContainer(BasePageContainer* container) { m_container = container; };
virtual void retranslate() {}
public:
public:
int stackIndex = -1;
int listIndex = -1;
protected:
BasePageContainer * m_container = nullptr;
updateExtraInfoFunc updateExtraInfo;
protected:
BasePageContainer* m_container = nullptr;
bool isOpened = false;
};

View File

@ -172,7 +172,7 @@
<string>Disable using metadata provided by mod providers (like Modrinth or Curseforge) for mods.</string>
</property>
<property name="text">
<string>Disable using metadata for mods?</string>
<string>Disable using metadata for mods</string>
</property>
</widget>
</item>
@ -307,21 +307,21 @@
<item>
<widget class="QCheckBox" name="showConsoleCheck">
<property name="text">
<string>Show console while the game is &amp;running?</string>
<string>Show console while the game is &amp;running</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="autoCloseConsoleCheck">
<property name="text">
<string>&amp;Automatically close console when the game quits?</string>
<string>&amp;Automatically close console when the game quits</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="showConsoleErrorCheck">
<property name="text">
<string>Show console when the game &amp;crashes?</string>
<string>Show console when the game &amp;crashes</string>
</property>
</widget>
</item>

View File

@ -51,7 +51,7 @@
<item>
<widget class="QCheckBox" name="maximizedCheckBox">
<property name="text">
<string>Start Minecraft &amp;maximized?</string>
<string>Start Minecraft &amp;maximized</string>
</property>
</widget>
</item>

View File

@ -1,3 +1,38 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* 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.
*/
#include "ExternalResourcesPage.h"
#include "ui/dialogs/CustomMessageBox.h"
#include "ui_ExternalResourcesPage.h"
@ -9,6 +44,7 @@
#include <QKeyEvent>
#include <QMenu>
#include <algorithm>
ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared_ptr<ResourceFolderModel> model, QWidget* parent)
: QMainWindow(parent), m_instance(instance), ui(new Ui::ExternalResourcesPage), m_model(model)
@ -24,6 +60,8 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared
m_filterModel->setSourceModel(m_model.get());
m_filterModel->setFilterKeyColumn(-1);
ui->treeView->setModel(m_filterModel);
// must come after setModel
ui->treeView->setResizeModes(m_model->columnResizeModes());
ui->treeView->installEventFilter(this);
ui->treeView->sortByColumn(1, Qt::AscendingOrder);
@ -43,7 +81,21 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared
auto selection_model = ui->treeView->selectionModel();
connect(selection_model, &QItemSelectionModel::currentChanged, this, &ExternalResourcesPage::current);
auto updateExtra = [this]() {
if (updateExtraInfo)
updateExtraInfo(extraHeaderInfoString());
};
connect(selection_model, &QItemSelectionModel::selectionChanged, this, updateExtra);
connect(model.get(), &ResourceFolderModel::updateFinished, this, updateExtra);
connect(ui->filterEdit, &QLineEdit::textChanged, this, &ExternalResourcesPage::filterTextChanged);
auto viewHeader = ui->treeView->header();
viewHeader->setContextMenuPolicy(Qt::CustomContextMenu);
connect(viewHeader, &QHeaderView::customContextMenuRequested, this, &ExternalResourcesPage::ShowHeaderContextMenu);
m_model->loadHiddenColumns(ui->treeView);
}
ExternalResourcesPage::~ExternalResourcesPage()
@ -65,6 +117,13 @@ void ExternalResourcesPage::ShowContextMenu(const QPoint& pos)
delete menu;
}
void ExternalResourcesPage::ShowHeaderContextMenu(const QPoint& pos)
{
auto menu = m_model->createHeaderContextMenu(ui->treeView);
menu->exec(ui->treeView->mapToGlobal(pos));
menu->deleteLater();
}
void ExternalResourcesPage::openedImpl()
{
m_model->startWatching();
@ -96,7 +155,6 @@ void ExternalResourcesPage::itemActivated(const QModelIndex&)
return;
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection());
m_model->setResourceEnabled(selection.indexes(), EnableAction::TOGGLE);
}
void ExternalResourcesPage::filterTextChanged(const QString& newContents)
@ -248,6 +306,15 @@ bool ExternalResourcesPage::onSelectionChanged(const QModelIndex& current, const
int row = sourceCurrent.row();
Resource const& resource = m_model->at(row);
ui->frame->updateWithResource(resource);
return true;
}
QString ExternalResourcesPage::extraHeaderInfoString()
{
if (ui && ui->treeView && ui->treeView->selectionModel()) {
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
if (auto count = std::count_if(selection.cbegin(), selection.cend(), [](auto v) { return v.column() == 0; }); count != 0)
return tr(" (%1 installed, %2 selected)").arg(m_model->size()).arg(count);
}
return tr(" (%1 installed)").arg(m_model->size());
}

View File

@ -29,6 +29,7 @@ class ExternalResourcesPage : public QMainWindow, public BasePage {
virtual QString helpPage() const override = 0;
virtual bool shouldDisplay() const override = 0;
QString extraHeaderInfoString();
void openedImpl() override;
void closedImpl() override;
@ -60,6 +61,7 @@ class ExternalResourcesPage : public QMainWindow, public BasePage {
virtual void viewConfigs();
void ShowContextMenu(const QPoint& pos);
void ShowHeaderContextMenu(const QPoint& pos);
protected:
BaseInstance* m_instance = nullptr;

View File

@ -62,6 +62,9 @@
<property name="dragDropMode">
<enum>QAbstractItemView::DropOnly</enum>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
</widget>
</item>
</layout>

View File

@ -269,7 +269,7 @@
<item>
<widget class="QCheckBox" name="maximizedCheckBox">
<property name="text">
<string>Start Minecraft maximized?</string>
<string>Start Minecraft maximized</string>
</property>
</widget>
</item>
@ -341,21 +341,21 @@
<item>
<widget class="QCheckBox" name="showConsoleCheck">
<property name="text">
<string>Show console while the game is running?</string>
<string>Show console while the game is running</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="autoCloseConsoleCheck">
<property name="text">
<string>Automatically close console when the game quits?</string>
<string>Automatically close console when the game quits</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="showConsoleErrorCheck">
<property name="text">
<string>Show console when the game crashes?</string>
<string>Show console when the game crashes</string>
</property>
</widget>
</item>

View File

@ -226,7 +226,7 @@ void ModrinthManagedPackPage::parseManagedPack()
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()));
m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response));
QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] {
QJsonParseError parse_error{};
@ -369,7 +369,7 @@ void FlameManagedPackPage::parseManagedPack()
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()));
m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response));
QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] {
QJsonParseError parse_error{};

View File

@ -4,6 +4,7 @@
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
* Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -86,28 +87,20 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr<ModFolderModel>
connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods);
auto check_allow_update = [this] {
return (!m_instance || !m_instance->isRunning()) &&
(ui->treeView->selectionModel()->hasSelection() || !m_model->empty());
return (!m_instance || !m_instance->isRunning()) && (ui->treeView->selectionModel()->hasSelection() || !m_model->empty());
};
connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this, check_allow_update] {
ui->actionUpdateItem->setEnabled(check_allow_update());
});
connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
[this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); });
connect(mods.get(), &ModFolderModel::rowsInserted, this, [this, check_allow_update] {
ui->actionUpdateItem->setEnabled(check_allow_update());
});
connect(mods.get(), &ModFolderModel::rowsInserted, this,
[this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); });
connect(mods.get(), &ModFolderModel::rowsRemoved, this, [this, check_allow_update] {
ui->actionUpdateItem->setEnabled(check_allow_update());
});
connect(mods.get(), &ModFolderModel::rowsRemoved, this,
[this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); });
connect(mods.get(), &ModFolderModel::updateFinished, this, [this, check_allow_update, mods] {
ui->actionUpdateItem->setEnabled(check_allow_update());
// Prevent a weird crash when trying to open the mods page twice in a session o.O
disconnect(mods.get(), &ModFolderModel::updateFinished, this, 0);
});
connect(mods.get(), &ModFolderModel::updateFinished, this,
[this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); });
connect(m_instance, &BaseInstance::runningStatusChanged, this, &ModFolderPage::runningStateChanged);
ModFolderPage::runningStateChanged(m_instance && m_instance->isRunning());

View File

@ -57,7 +57,7 @@ public:
virtual ~ImportPage();
virtual QString displayName() const override
{
return tr("Import from zip");
return tr("Import");
}
virtual QIcon icon() const override
{

View File

@ -89,17 +89,13 @@ void ModPage::filterMods()
void ModPage::triggerSearch()
{
auto changed = m_filter_widget->changed();
m_filter = m_filter_widget->getFilter();
m_ui->packView->clearSelection();
m_ui->packDescription->clear();
m_ui->versionSelectionBox->clear();
updateSelectionButton();
if (changed) {
m_ui->packView->clearSelection();
m_ui->packDescription->clear();
m_ui->versionSelectionBox->clear();
updateSelectionButton();
}
static_cast<ModModel*>(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt(), changed);
static_cast<ModModel*>(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt(), m_filter_widget->changed());
m_fetch_progress.watch(m_model->activeSearchJob().get());
}
@ -122,6 +118,8 @@ void ModPage::updateVersionList()
QString mcVersion = packProfile->getComponentVersion("net.minecraft");
auto current_pack = getCurrentPack();
if (!current_pack)
return;
for (int i = 0; i < current_pack->versions.size(); i++) {
auto version = current_pack->versions[i];
bool valid = false;

View File

@ -174,7 +174,11 @@ ModPlatform::IndexedPack::Ptr ResourcePage::getCurrentPack() const
void ResourcePage::updateUi()
{
auto current_pack = getCurrentPack();
if (!current_pack) {
m_ui->packDescription->setHtml({});
m_ui->packDescription->flush();
return;
}
QString text = "";
QString name = current_pack->name;
@ -240,8 +244,8 @@ void ResourcePage::updateSelectionButton()
}
m_ui->resourceSelectionButton->setEnabled(true);
if (getCurrentPack()) {
if (!getCurrentPack()->isVersionSelected(m_selected_version_index))
if (auto current_pack = getCurrentPack(); current_pack) {
if (!current_pack->isVersionSelected(m_selected_version_index))
m_ui->resourceSelectionButton->setText(tr("Select %1 for download").arg(resourceString()));
else
m_ui->resourceSelectionButton->setText(tr("Deselect %1 for download").arg(resourceString()));
@ -258,13 +262,14 @@ void ResourcePage::updateVersionList()
m_ui->versionSelectionBox->clear();
m_ui->versionSelectionBox->blockSignals(false);
for (int i = 0; i < current_pack->versions.size(); i++) {
auto& version = current_pack->versions[i];
if (optedOut(version))
continue;
if (current_pack)
for (int i = 0; i < current_pack->versions.size(); i++) {
auto& version = current_pack->versions[i];
if (optedOut(version))
continue;
m_ui->versionSelectionBox->addItem(current_pack->versions[i].version, QVariant(i));
}
m_ui->versionSelectionBox->addItem(current_pack->versions[i].version, QVariant(i));
}
if (m_ui->versionSelectionBox->count() == 0) {
m_ui->versionSelectionBox->addItem(tr("No valid version found."), QVariant(-1));
@ -283,7 +288,7 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
auto current_pack = getCurrentPack();
bool request_load = false;
if (!current_pack->versionsLoaded) {
if (!current_pack || !current_pack->versionsLoaded) {
m_ui->resourceSelectionButton->setText(tr("Loading versions..."));
m_ui->resourceSelectionButton->setEnabled(false);
@ -292,7 +297,7 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
updateVersionList();
}
if (!current_pack->extraDataLoaded)
if (current_pack && !current_pack->extraDataLoaded)
request_load = true;
if (request_load)
@ -340,7 +345,7 @@ void ResourcePage::onResourceSelected()
return;
auto current_pack = getCurrentPack();
if (!current_pack->versionsLoaded)
if (!current_pack || !current_pack->versionsLoaded)
return;
auto& version = current_pack->versions[m_selected_version_index];
@ -386,7 +391,7 @@ void ResourcePage::openUrl(const QUrl& url)
const QString slug = match.captured(1);
// ensure the user isn't opening the same mod
if (slug != getCurrentPack()->slug) {
if (auto current_pack = getCurrentPack(); current_pack && slug != current_pack->slug) {
m_parent_dialog->selectPage(page);
auto newPage = m_parent_dialog->getSelectedPage();

View File

@ -16,62 +16,49 @@
#include "AtlListModel.h"
#include <BuildConfig.h>
#include <Application.h>
#include <BuildConfig.h>
#include <Json.h>
namespace Atl {
ListModel::ListModel(QObject *parent) : QAbstractListModel(parent)
{
}
ListModel::ListModel(QObject* parent) : QAbstractListModel(parent) {}
ListModel::~ListModel()
{
}
ListModel::~ListModel() {}
int ListModel::rowCount(const QModelIndex &parent) const
int ListModel::rowCount(const QModelIndex& parent) const
{
return parent.isValid() ? 0 : modpacks.size();
}
int ListModel::columnCount(const QModelIndex &parent) const
int ListModel::columnCount(const QModelIndex& parent) const
{
return parent.isValid() ? 0 : 1;
}
QVariant ListModel::data(const QModelIndex &index, int role) const
QVariant ListModel::data(const QModelIndex& index, int role) const
{
int pos = index.row();
if(pos >= modpacks.size() || pos < 0 || !index.isValid())
{
if (pos >= modpacks.size() || pos < 0 || !index.isValid()) {
return QString("INVALID INDEX %1").arg(pos);
}
ATLauncher::IndexedPack pack = modpacks.at(pos);
if(role == Qt::DisplayRole)
{
if (role == Qt::DisplayRole) {
return pack.name;
}
else if (role == Qt::ToolTipRole)
{
} else if (role == Qt::ToolTipRole) {
return pack.name;
}
else if(role == Qt::DecorationRole)
{
if(m_logoMap.contains(pack.safeName))
{
} else if (role == Qt::DecorationRole) {
if (m_logoMap.contains(pack.safeName)) {
return (m_logoMap.value(pack.safeName));
}
auto icon = APPLICATION->getThemedIcon("atlauncher-placeholder");
auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1.png").arg(pack.safeName.toLower());
((ListModel *)this)->requestLogo(pack.safeName, url);
((ListModel*)this)->requestLogo(pack.safeName, url);
return icon;
}
else if(role == Qt::UserRole)
{
} else if (role == Qt::UserRole) {
QVariant v;
v.setValue(pack);
return v;
@ -88,7 +75,7 @@ void ListModel::request()
auto netJob = makeShared<NetJob>("Atl::Request", APPLICATION->network());
auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/json/packsnew.json");
netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response));
netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), response));
jobPtr = netJob;
jobPtr->start();
@ -101,36 +88,38 @@ void ListModel::requestFinished()
jobPtr.reset();
QJsonParseError parse_error;
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
if(parse_error.error != QJsonParseError::NoError) {
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString();
qWarning() << response;
qWarning() << *response;
return;
}
QList<ATLauncher::IndexedPack> newList;
auto packs = doc.array();
for(auto packRaw : packs) {
for (auto packRaw : packs) {
auto packObj = packRaw.toObject();
ATLauncher::IndexedPack pack;
try {
ATLauncher::loadIndexedPack(pack, packObj);
}
catch (const JSONValidationError &e) {
qDebug() << QString::fromUtf8(response);
} catch (const JSONValidationError& e) {
qDebug() << QString::fromUtf8(*response);
qWarning() << "Error while reading pack manifest from ATLauncher: " << e.cause();
return;
}
// ignore packs without a published version
if(pack.versions.length() == 0) continue;
if (pack.versions.length() == 0)
continue;
// only display public packs (for now)
if(pack.type != ATLauncher::PackType::Public) continue;
if (pack.type != ATLauncher::PackType::Public)
continue;
// ignore "system" packs (Vanilla, Vanilla with Forge, etc)
if(pack.system) continue;
if (pack.system)
continue;
newList.append(pack);
}
@ -145,14 +134,12 @@ void ListModel::requestFailed(QString reason)
jobPtr.reset();
}
void ListModel::getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback)
void ListModel::getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback)
{
if(m_logoMap.contains(logo))
{
callback(APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
}
else
{
if (m_logoMap.contains(logo)) {
callback(
APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
} else {
requestLogo(logo, logoUrl);
}
}
@ -168,36 +155,34 @@ void ListModel::logoLoaded(QString logo, QIcon out)
m_loadingLogos.removeAll(logo);
m_logoMap.insert(logo, out);
for(int i = 0; i < modpacks.size(); i++) {
if(modpacks[i].safeName == logo) {
emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole});
for (int i = 0; i < modpacks.size(); i++) {
if (modpacks[i].safeName == logo) {
emit dataChanged(createIndex(i, 0), createIndex(i, 0), { Qt::DecorationRole });
}
}
}
void ListModel::requestLogo(QString file, QString url)
{
if(m_loadingLogos.contains(file) || m_failedLogos.contains(file))
{
if (m_loadingLogos.contains(file) || m_failedLogos.contains(file)) {
return;
}
MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(file.section(".", 0, 0)));
NetJob *job = new NetJob(QString("ATLauncher Icon Download %1").arg(file), APPLICATION->network());
auto job = new NetJob(QString("ATLauncher Icon Download %1").arg(file), APPLICATION->network());
job->addNetAction(Net::Download::makeCached(QUrl(url), entry));
auto fullPath = entry->getFullPath();
QObject::connect(job, &NetJob::succeeded, this, [this, file, fullPath]
{
QObject::connect(job, &NetJob::succeeded, this, [this, file, fullPath, job] {
job->deleteLater();
emit logoLoaded(file, QIcon(fullPath));
if(waitingCallbacks.contains(file))
{
if (waitingCallbacks.contains(file)) {
waitingCallbacks.value(file)(fullPath);
}
});
QObject::connect(job, &NetJob::failed, this, [this, file]
{
QObject::connect(job, &NetJob::failed, this, [this, file, job] {
job->deleteLater();
emit logoFailed(file);
});
@ -206,4 +191,4 @@ void ListModel::requestLogo(QString file, QString url)
m_loadingLogos.append(file);
}
}
} // namespace Atl

View File

@ -18,42 +18,41 @@
#include <QAbstractListModel>
#include "net/NetJob.h"
#include <QIcon>
#include <modplatform/atlauncher/ATLPackIndex.h>
#include <QIcon>
#include "net/NetJob.h"
namespace Atl {
typedef QMap<QString, QIcon> LogoMap;
typedef std::function<void(QString)> LogoCallback;
class ListModel : public QAbstractListModel
{
class ListModel : public QAbstractListModel {
Q_OBJECT
public:
ListModel(QObject *parent);
public:
ListModel(QObject* parent);
virtual ~ListModel();
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
int rowCount(const QModelIndex& parent) const override;
int columnCount(const QModelIndex& parent) const override;
QVariant data(const QModelIndex& index, int role) const override;
void request();
void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback);
void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback);
private slots:
private slots:
void requestFinished();
void requestFailed(QString reason);
void logoFailed(QString logo);
void logoLoaded(QString logo, QIcon out);
private:
private:
void requestLogo(QString file, QString url);
private:
private:
QList<ATLauncher::IndexedPack> modpacks;
QStringList m_failedLogos;
@ -62,7 +61,7 @@ private:
QMap<QString, LogoCallback> waitingCallbacks;
NetJob::Ptr jobPtr;
QByteArray response;
std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
};
}
} // namespace Atl

View File

@ -152,7 +152,7 @@ Qt::ItemFlags AtlOptionalModListModel::flags(const QModelIndex &index) const {
void AtlOptionalModListModel::useShareCode(const QString& code) {
m_jobPtr.reset(new NetJob("Atl::Request", APPLICATION->network()));
auto url = QString(BuildConfig.ATL_API_BASE_URL + "share-codes/" + code);
m_jobPtr->addNetAction(Net::Download::makeByteArray(QUrl(url), &m_response));
m_jobPtr->addNetAction(Net::Download::makeByteArray(QUrl(url), m_response));
connect(m_jobPtr.get(), &NetJob::succeeded,
this, &AtlOptionalModListModel::shareCodeSuccess);
@ -166,10 +166,10 @@ void AtlOptionalModListModel::shareCodeSuccess() {
m_jobPtr.reset();
QJsonParseError parse_error {};
auto doc = QJsonDocument::fromJson(m_response, &parse_error);
auto doc = QJsonDocument::fromJson(*m_response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString();
qWarning() << m_response;
qWarning() << *m_response;
return;
}
auto obj = doc.object();
@ -179,7 +179,7 @@ void AtlOptionalModListModel::shareCodeSuccess() {
ATLauncher::loadShareCodeResponse(response, obj);
}
catch (const JSONValidationError& e) {
qDebug() << QString::fromUtf8(m_response);
qDebug() << QString::fromUtf8(*m_response);
qWarning() << "Error while reading response from ATLauncher: " << e.cause();
return;
}

View File

@ -82,9 +82,9 @@ private:
void toggleMod(ATLauncher::VersionMod mod, int index);
void setMod(ATLauncher::VersionMod mod, int index, bool enable, bool shouldEmit = true);
private:
private:
NetJob::Ptr m_jobPtr;
QByteArray m_response;
std::shared_ptr<QByteArray> m_response = std::make_shared<QByteArray>();
ATLauncher::PackVersion m_version;
QVector<ATLauncher::VersionMod> m_mods;

View File

@ -42,15 +42,15 @@
class AtlUserInteractionSupportImpl : public QObject, public ATLauncher::UserInteractionSupport {
Q_OBJECT
public:
public:
AtlUserInteractionSupportImpl(QWidget* parent);
virtual ~AtlUserInteractionSupportImpl() = default;
private:
private:
QString chooseVersion(Meta::VersionList::Ptr vlist, QString minecraftVersion) override;
std::optional<QVector<QString>> chooseOptionalMods(ATLauncher::PackVersion version, QVector<ATLauncher::VersionMod> mods) override;
void displayMessage(QString message) override;
private:
private:
QWidget* m_parent;
};

View File

@ -171,7 +171,7 @@ void ListModel::performPaginatedSearch()
.arg(currentSearchTerm)
.arg(currentSort + 1);
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response));
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
jobPtr = netJob;
jobPtr->start();
QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished);
@ -204,11 +204,11 @@ void Flame::ListModel::searchRequestFinished()
jobPtr.reset();
QJsonParseError parse_error;
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from CurseForge at " << parse_error.offset
<< " reason: " << parse_error.errorString();
qWarning() << response;
qWarning() << *response;
return;
}

View File

@ -3,46 +3,44 @@
#include <RWStorage.h>
#include <QAbstractListModel>
#include <QSortFilterProxyModel>
#include <QThreadPool>
#include <QIcon>
#include <QStyledItemDelegate>
#include <QList>
#include <QMetaType>
#include <QSortFilterProxyModel>
#include <QString>
#include <QStringList>
#include <QMetaType>
#include <QStyledItemDelegate>
#include <QThreadPool>
#include <functional>
#include <net/NetJob.h>
#include <functional>
#include <modplatform/flame/FlamePackIndex.h>
namespace Flame {
typedef QMap<QString, QIcon> LogoMap;
typedef std::function<void(QString)> LogoCallback;
class ListModel : public QAbstractListModel
{
class ListModel : public QAbstractListModel {
Q_OBJECT
public:
ListModel(QObject *parent);
public:
ListModel(QObject* parent);
virtual ~ListModel();
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool canFetchMore(const QModelIndex & parent) const override;
void fetchMore(const QModelIndex & parent) override;
int rowCount(const QModelIndex& parent) const override;
int columnCount(const QModelIndex& parent) const override;
QVariant data(const QModelIndex& index, int role) const override;
bool setData(const QModelIndex& index, const QVariant& value, int role) override;
Qt::ItemFlags flags(const QModelIndex& index) const override;
bool canFetchMore(const QModelIndex& parent) const override;
void fetchMore(const QModelIndex& parent) override;
void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback);
void searchWithTerm(const QString & term, const int sort);
void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback);
void searchWithTerm(const QString& term, const int sort);
private slots:
private slots:
void performPaginatedSearch();
void logoFailed(QString logo);
@ -51,10 +49,10 @@ private slots:
void searchRequestFinished();
void searchRequestFailed(QString reason);
private:
private:
void requestLogo(QString file, QString url);
private:
private:
QList<IndexedPack> modpacks;
QStringList m_failedLogos;
QStringList m_loadingLogos;
@ -64,14 +62,9 @@ private:
QString currentSearchTerm;
int currentSort = 0;
int nextSearchOffset = 0;
enum SearchState {
None,
CanPossiblyFetchMore,
ResetRequested,
Finished
} searchState = None;
enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None;
NetJob::Ptr jobPtr;
QByteArray response;
std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
};
}
} // namespace Flame

View File

@ -130,7 +130,7 @@ void FlamePage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
if (current.versionsLoaded == false) {
qDebug() << "Loading flame modpack versions";
auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network());
auto response = new QByteArray();
auto response = std::make_shared<QByteArray>();
int addonId = current.addonId;
netJob->addNetAction(Net::Download::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response));
@ -170,10 +170,7 @@ void FlamePage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
}
suggestCurrent();
});
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] {
netJob->deleteLater();
delete response;
});
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
netJob->start();
} else {
for (auto version : current.versions) {

View File

@ -38,11 +38,11 @@
#include "net/HttpMetaCache.h"
#include "net/NetJob.h"
#include "StringUtils.h"
#include <Version.h>
#include "StringUtils.h"
#include <QtMath>
#include <QLabel>
#include <QtMath>
#include <RWStorage.h>
@ -50,33 +50,33 @@
namespace LegacyFTB {
FilterModel::FilterModel(QObject *parent) : QSortFilterProxyModel(parent)
FilterModel::FilterModel(QObject* parent) : QSortFilterProxyModel(parent)
{
currentSorting = Sorting::ByGameVersion;
sortings.insert(tr("Sort by Name"), Sorting::ByName);
sortings.insert(tr("Sort by Game Version"), Sorting::ByGameVersion);
}
bool FilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
bool FilterModel::lessThan(const QModelIndex& left, const QModelIndex& right) const
{
Modpack leftPack = sourceModel()->data(left, Qt::UserRole).value<Modpack>();
Modpack rightPack = sourceModel()->data(right, Qt::UserRole).value<Modpack>();
if(currentSorting == Sorting::ByGameVersion) {
if (currentSorting == Sorting::ByGameVersion) {
Version lv(leftPack.mcVersion);
Version rv(rightPack.mcVersion);
return lv < rv;
} else if(currentSorting == Sorting::ByName) {
} else if (currentSorting == Sorting::ByName) {
return StringUtils::naturalCompare(leftPack.name, rightPack.name, Qt::CaseSensitive) >= 0;
}
//UHM, some inavlid value set?!
// UHM, some inavlid value set?!
qWarning() << "Invalid sorting set!";
return true;
}
bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
return true;
}
@ -102,18 +102,13 @@ FilterModel::Sorting FilterModel::getCurrentSorting()
return currentSorting;
}
ListModel::ListModel(QObject *parent) : QAbstractListModel(parent)
{
}
ListModel::ListModel(QObject* parent) : QAbstractListModel(parent) {}
ListModel::~ListModel()
{
}
ListModel::~ListModel() {}
QString ListModel::translatePackType(PackType type) const
{
switch(type)
{
switch (type) {
case PackType::Public:
return tr("Public Modpack");
case PackType::ThirdParty:
@ -125,67 +120,51 @@ QString ListModel::translatePackType(PackType type) const
return QString();
}
int ListModel::rowCount(const QModelIndex &parent) const
int ListModel::rowCount(const QModelIndex& parent) const
{
return parent.isValid() ? 0 : modpacks.size();
}
int ListModel::columnCount(const QModelIndex &parent) const
int ListModel::columnCount(const QModelIndex& parent) const
{
return parent.isValid() ? 0 : 1;
}
QVariant ListModel::data(const QModelIndex &index, int role) const
QVariant ListModel::data(const QModelIndex& index, int role) const
{
int pos = index.row();
if(pos >= modpacks.size() || pos < 0 || !index.isValid())
{
if (pos >= modpacks.size() || pos < 0 || !index.isValid()) {
return QString("INVALID INDEX %1").arg(pos);
}
Modpack pack = modpacks.at(pos);
if(role == Qt::DisplayRole)
{
if (role == Qt::DisplayRole) {
return pack.name + "\n" + translatePackType(pack.type);
}
else if (role == Qt::ToolTipRole)
{
if(pack.description.length() > 100)
{
//some magic to prevent to long tooltips and replace html linebreaks
} else if (role == Qt::ToolTipRole) {
if (pack.description.length() > 100) {
// some magic to prevent to long tooltips and replace html linebreaks
QString edit = pack.description.left(97);
edit = edit.left(edit.lastIndexOf("<br>")).left(edit.lastIndexOf(" ")).append("...");
return edit;
}
return pack.description;
}
else if(role == Qt::DecorationRole)
{
if(m_logoMap.contains(pack.logo))
{
} else if (role == Qt::DecorationRole) {
if (m_logoMap.contains(pack.logo)) {
return (m_logoMap.value(pack.logo));
}
QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder");
((ListModel *)this)->requestLogo(pack.logo);
((ListModel*)this)->requestLogo(pack.logo);
return icon;
}
else if(role == Qt::ForegroundRole)
{
if(pack.broken)
{
//FIXME: Hardcoded color
} else if (role == Qt::ForegroundRole) {
if (pack.broken) {
// FIXME: Hardcoded color
return QColor(255, 0, 50);
}
else if(pack.bugged)
{
//FIXME: Hardcoded color
//bugged pack, currently only indicates bugged xml
} else if (pack.bugged) {
// FIXME: Hardcoded color
// bugged pack, currently only indicates bugged xml
return QColor(244, 229, 66);
}
}
else if(role == Qt::UserRole)
{
} else if (role == Qt::UserRole) {
QVariant v;
v.setValue(pack);
return v;
@ -222,8 +201,7 @@ Modpack ListModel::at(int row)
void ListModel::remove(int row)
{
if(row < 0 || row >= modpacks.size())
{
if (row < 0 || row >= modpacks.size()) {
qWarning() << "Attempt to remove FTB modpacks with invalid row" << row;
return;
}
@ -247,27 +225,25 @@ void ListModel::logoFailed(QString logo)
void ListModel::requestLogo(QString file)
{
if(m_loadingLogos.contains(file) || m_failedLogos.contains(file))
{
if (m_loadingLogos.contains(file) || m_failedLogos.contains(file)) {
return;
}
MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(file.section(".", 0, 0)));
NetJob *job = new NetJob(QString("FTB Icon Download for %1").arg(file), APPLICATION->network());
NetJob* job = new NetJob(QString("FTB Icon Download for %1").arg(file), APPLICATION->network());
job->addNetAction(Net::Download::makeCached(QUrl(QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry));
auto fullPath = entry->getFullPath();
QObject::connect(job, &NetJob::finished, this, [this, file, fullPath]
{
QObject::connect(job, &NetJob::finished, this, [this, file, fullPath, job] {
job->deleteLater();
emit logoLoaded(file, QIcon(fullPath));
if(waitingCallbacks.contains(file))
{
if (waitingCallbacks.contains(file)) {
waitingCallbacks.value(file)(fullPath);
}
});
QObject::connect(job, &NetJob::failed, this, [this, file]
{
QObject::connect(job, &NetJob::failed, this, [this, file, job] {
job->deleteLater();
emit logoFailed(file);
});
@ -276,21 +252,18 @@ void ListModel::requestLogo(QString file)
m_loadingLogos.append(file);
}
void ListModel::getLogo(const QString &logo, LogoCallback callback)
void ListModel::getLogo(const QString& logo, LogoCallback callback)
{
if(m_logoMap.contains(logo))
{
if (m_logoMap.contains(logo)) {
callback(APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
}
else
{
} else {
requestLogo(logo);
}
}
Qt::ItemFlags ListModel::flags(const QModelIndex &index) const
Qt::ItemFlags ListModel::flags(const QModelIndex& index) const
{
return QAbstractListModel::flags(index);
}
}
} // namespace LegacyFTB

View File

@ -131,27 +131,27 @@ void ModpackListModel::performPaginatedSearch()
// TODO: Move to standalone API
auto netJob = makeShared<NetJob>("Modrinth::SearchModpack", APPLICATION->network());
auto searchAllUrl = QString(BuildConfig.MODRINTH_PROD_URL +
"/search?"
"offset=%1&"
"limit=%2&"
"query=%3&"
"index=%4&"
"facets=[[\"project_type:modpack\"]]")
"/search?"
"offset=%1&"
"limit=%2&"
"query=%3&"
"index=%4&"
"facets=[[\"project_type:modpack\"]]")
.arg(nextSearchOffset)
.arg(m_modpacks_per_page)
.arg(currentSearchTerm)
.arg(currentSort);
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchAllUrl), &m_all_response));
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchAllUrl), m_all_response));
QObject::connect(netJob.get(), &NetJob::succeeded, this, [this] {
QJsonParseError parse_error_all{};
QJsonDocument doc_all = QJsonDocument::fromJson(m_all_response, &parse_error_all);
QJsonDocument doc_all = QJsonDocument::fromJson(*m_all_response, &parse_error_all);
if (parse_error_all.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from " << debugName() << " at " << parse_error_all.offset
<< " reason: " << parse_error_all.errorString();
qWarning() << m_all_response;
qWarning() << *m_all_response;
return;
}

View File

@ -110,9 +110,9 @@ class ModpackListModel : public QAbstractListModel {
NetJob::Ptr jobPtr;
QByteArray m_all_response;
std::shared_ptr<QByteArray> m_all_response = std::make_shared<QByteArray>();
QByteArray m_specific_response;
int m_modpacks_per_page = 20;
};
} // namespace ModPlatform
} // namespace Modrinth

View File

@ -123,7 +123,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
qDebug() << "Loading modrinth modpack information";
auto netJob = new NetJob(QString("Modrinth::PackInformation(%1)").arg(current.name), APPLICATION->network());
auto response = new QByteArray();
auto response = std::make_shared<QByteArray>();
QString id = current.id;
@ -162,10 +162,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
suggestCurrent();
});
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] {
netJob->deleteLater();
delete response;
});
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
netJob->start();
} else
updateUI();
@ -174,7 +171,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
qDebug() << "Loading modrinth modpack versions";
auto netJob = new NetJob(QString("Modrinth::PackVersions(%1)").arg(current.name), APPLICATION->network());
auto response = new QByteArray();
auto response = std::make_shared<QByteArray>();
QString id = current.id;
@ -217,10 +214,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
suggestCurrent();
});
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] {
netJob->deleteLater();
delete response;
});
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
netJob->start();
} else {
@ -260,10 +254,8 @@ void ModrinthPage::updateUI()
text += donates.join(", ");
}
if (!current.extra.issuesUrl.isEmpty()
|| !current.extra.sourceUrl.isEmpty()
|| !current.extra.wikiUrl.isEmpty()
|| !current.extra.discordUrl.isEmpty()) {
if (!current.extra.issuesUrl.isEmpty() || !current.extra.sourceUrl.isEmpty() || !current.extra.wikiUrl.isEmpty() ||
!current.extra.discordUrl.isEmpty()) {
text += "<br><br>" + tr("External links:") + "<br>";
}

View File

@ -40,39 +40,28 @@
#include <QIcon>
Technic::ListModel::ListModel(QObject *parent) : QAbstractListModel(parent)
{
}
Technic::ListModel::ListModel(QObject* parent) : QAbstractListModel(parent) {}
Technic::ListModel::~ListModel()
{
}
Technic::ListModel::~ListModel() {}
QVariant Technic::ListModel::data(const QModelIndex& index, int role) const
{
int pos = index.row();
if(pos >= modpacks.size() || pos < 0 || !index.isValid())
{
if (pos >= modpacks.size() || pos < 0 || !index.isValid()) {
return QString("INVALID INDEX %1").arg(pos);
}
Modpack pack = modpacks.at(pos);
if(role == Qt::DisplayRole)
{
if (role == Qt::DisplayRole) {
return pack.name;
}
else if(role == Qt::DecorationRole)
{
if(m_logoMap.contains(pack.logoName))
{
} else if (role == Qt::DecorationRole) {
if (m_logoMap.contains(pack.logoName)) {
return (m_logoMap.value(pack.logoName));
}
QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder");
((ListModel *)this)->requestLogo(pack.logoName, pack.logoUrl);
((ListModel*)this)->requestLogo(pack.logoName, pack.logoUrl);
return icon;
}
else if(role == Qt::UserRole)
{
} else if (role == Qt::UserRole) {
QVariant v;
v.setValue(pack);
return v;
@ -92,16 +81,15 @@ int Technic::ListModel::rowCount(const QModelIndex& parent) const
void Technic::ListModel::searchWithTerm(const QString& term)
{
if(currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull()) {
if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull()) {
return;
}
currentSearchTerm = term;
if(jobPtr) {
if (jobPtr) {
jobPtr->abort();
searchState = ResetRequested;
return;
}
else {
} else {
beginResetModel();
modpacks.clear();
endResetModel();
@ -115,26 +103,20 @@ void Technic::ListModel::performSearch()
auto netJob = makeShared<NetJob>("Technic::Search", APPLICATION->network());
QString searchUrl = "";
if (currentSearchTerm.isEmpty()) {
searchUrl = QString("%1trending?build=%2")
.arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD);
searchUrl = QString("%1trending?build=%2").arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD);
searchMode = List;
}
else if (currentSearchTerm.startsWith("http://api.technicpack.net/modpack/")) {
searchUrl = QString("https://%1?build=%2")
.arg(currentSearchTerm.mid(7), BuildConfig.TECHNIC_API_BUILD);
} else if (currentSearchTerm.startsWith("http://api.technicpack.net/modpack/")) {
searchUrl = QString("https://%1?build=%2").arg(currentSearchTerm.mid(7), BuildConfig.TECHNIC_API_BUILD);
searchMode = Single;
}
else if (currentSearchTerm.startsWith("https://api.technicpack.net/modpack/")) {
} else if (currentSearchTerm.startsWith("https://api.technicpack.net/modpack/")) {
searchUrl = QString("%1?build=%2").arg(currentSearchTerm, BuildConfig.TECHNIC_API_BUILD);
searchMode = Single;
}
else {
searchUrl = QString(
"%1search?build=%2&q=%3"
).arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD, currentSearchTerm);
} else {
searchUrl =
QString("%1search?build=%2&q=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD, currentSearchTerm);
searchMode = List;
}
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response));
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
jobPtr = netJob;
jobPtr->start();
QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished);
@ -146,11 +128,11 @@ void Technic::ListModel::searchRequestFinished()
jobPtr.reset();
QJsonParseError parse_error;
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
if(parse_error.error != QJsonParseError::NoError)
{
qWarning() << "Error while parsing JSON response from Technic at " << parse_error.offset << " reason: " << parse_error.errorString();
qWarning() << response;
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from Technic at " << parse_error.offset
<< " reason: " << parse_error.errorString();
qWarning() << *response;
return;
}
@ -161,7 +143,7 @@ void Technic::ListModel::searchRequestFinished()
switch (searchMode) {
case List: {
auto objs = Json::requireArray(root, "modpacks");
for (auto technicPack: objs) {
for (auto technicPack : objs) {
Modpack pack;
auto technicPackObject = Json::requireObject(technicPack);
pack.name = Json::requireString(technicPackObject, "name");
@ -170,11 +152,10 @@ void Technic::ListModel::searchRequestFinished()
continue;
auto rawURL = Json::ensureString(technicPackObject, "iconUrl", "null");
if(rawURL == "null") {
if (rawURL == "null") {
pack.logoUrl = "null";
pack.logoName = "null";
}
else {
} else {
pack.logoUrl = rawURL;
pack.logoName = rawURL.section(QLatin1Char('/'), -1).section(QLatin1Char('.'), 0, 0);
}
@ -199,8 +180,7 @@ void Technic::ListModel::searchRequestFinished()
pack.logoUrl = iconUrl;
pack.logoName = iconUrl.section(QLatin1Char('/'), -1).section(QLatin1Char('.'), 0, 0);
}
else {
} else {
pack.logoUrl = "null";
pack.logoName = "null";
}
@ -210,10 +190,8 @@ void Technic::ListModel::searchRequestFinished()
break;
}
}
}
catch (const JSONValidationError &err)
{
qCritical() << "Couldn't parse technic search results:" << err.cause() ;
} catch (const JSONValidationError& err) {
qCritical() << "Couldn't parse technic search results:" << err.cause();
return;
}
searchState = Finished;
@ -229,12 +207,9 @@ void Technic::ListModel::searchRequestFinished()
void Technic::ListModel::getLogo(const QString& logo, const QString& logoUrl, Technic::LogoCallback callback)
{
if(m_logoMap.contains(logo))
{
if (m_logoMap.contains(logo)) {
callback(APPLICATION->metacache()->resolveEntry("TechnicPacks", QString("logos/%1").arg(logo))->getFullPath());
}
else
{
} else {
requestLogo(logo, logoUrl);
}
}
@ -243,30 +218,24 @@ void Technic::ListModel::searchRequestFailed()
{
jobPtr.reset();
if(searchState == ResetRequested)
{
if (searchState == ResetRequested) {
beginResetModel();
modpacks.clear();
endResetModel();
performSearch();
}
else
{
} else {
searchState = Finished;
}
}
void Technic::ListModel::logoLoaded(QString logo, QString out)
{
m_loadingLogos.removeAll(logo);
m_logoMap.insert(logo, QIcon(out));
for(int i = 0; i < modpacks.size(); i++)
{
if(modpacks[i].logoName == logo)
{
emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole});
for (int i = 0; i < modpacks.size(); i++) {
if (modpacks[i].logoName == logo) {
emit dataChanged(createIndex(i, 0), createIndex(i, 0), { Qt::DecorationRole });
}
}
}
@ -279,24 +248,23 @@ void Technic::ListModel::logoFailed(QString logo)
void Technic::ListModel::requestLogo(QString logo, QString url)
{
if(m_loadingLogos.contains(logo) || m_failedLogos.contains(logo) || logo == "null")
{
if (m_loadingLogos.contains(logo) || m_failedLogos.contains(logo) || logo == "null") {
return;
}
MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("TechnicPacks", QString("logos/%1").arg(logo));
NetJob *job = new NetJob(QString("Technic Icon Download %1").arg(logo), APPLICATION->network());
auto job = new NetJob(QString("Technic Icon Download %1").arg(logo), APPLICATION->network());
job->addNetAction(Net::Download::makeCached(QUrl(url), entry));
auto fullPath = entry->getFullPath();
QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath]
{
QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath, job] {
job->deleteLater();
logoLoaded(logo, fullPath);
});
QObject::connect(job, &NetJob::failed, this, [this, logo]
{
QObject::connect(job, &NetJob::failed, this, [this, logo, job] {
job->deleteLater();
logoFailed(logo);
});

View File

@ -44,33 +44,32 @@ namespace Technic {
typedef std::function<void(QString)> LogoCallback;
class ListModel : public QAbstractListModel
{
class ListModel : public QAbstractListModel {
Q_OBJECT
public:
ListModel(QObject *parent);
public:
ListModel(QObject* parent);
virtual ~ListModel();
virtual QVariant data(const QModelIndex& index, int role) const;
virtual int columnCount(const QModelIndex& parent) const;
virtual int rowCount(const QModelIndex& parent) const;
void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback);
void searchWithTerm(const QString & term);
void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback);
void searchWithTerm(const QString& term);
private slots:
private slots:
void searchRequestFinished();
void searchRequestFailed();
void logoFailed(QString logo);
void logoLoaded(QString logo, QString out);
private:
private:
void performSearch();
void requestLogo(QString logo, QString url);
private:
private:
QList<Modpack> modpacks;
QStringList m_failedLogos;
QStringList m_loadingLogos;
@ -78,17 +77,13 @@ private:
QMap<QString, LogoCallback> waitingCallbacks;
QString currentSearchTerm;
enum SearchState {
None,
ResetRequested,
Finished
} searchState = None;
enum SearchState { None, ResetRequested, Finished } searchState = None;
enum SearchMode {
List,
Single,
} searchMode = List;
NetJob::Ptr jobPtr;
QByteArray response;
std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
};
}
} // namespace Technic

View File

@ -143,7 +143,7 @@ void TechnicPage::suggestCurrent()
auto netJob = makeShared<NetJob>(QString("Technic::PackMeta(%1)").arg(current.name), APPLICATION->network());
QString slug = current.slug;
netJob->addNetAction(Net::Download::makeByteArray(QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), &response));
netJob->addNetAction(Net::Download::makeByteArray(QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), response));
QObject::connect(netJob.get(), &NetJob::succeeded, this, [this, slug]
{
jobPtr.reset();
@ -154,7 +154,7 @@ void TechnicPage::suggestCurrent()
}
QJsonParseError parse_error {};
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
QJsonObject obj = doc.object();
if(parse_error.error != QJsonParseError::NoError)
{
@ -249,7 +249,7 @@ void TechnicPage::metadataLoaded()
auto netJob = makeShared<NetJob>(QString("Technic::SolderMeta(%1)").arg(current.name), APPLICATION->network());
auto url = QString("%1/modpack/%2").arg(current.url, current.slug);
netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response));
netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), response));
QObject::connect(netJob.get(), &NetJob::succeeded, this, &TechnicPage::onSolderLoaded);
@ -291,11 +291,11 @@ void TechnicPage::onSolderLoaded() {
current.versions.clear();
QJsonParseError parse_error {};
auto doc = QJsonDocument::fromJson(response, &parse_error);
QJsonParseError parse_error{};
auto doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from Solder at " << parse_error.offset << " reason: " << parse_error.errorString();
qWarning() << response;
qWarning() << *response;
fallback();
return;
}
@ -304,8 +304,7 @@ void TechnicPage::onSolderLoaded() {
TechnicSolder::Pack pack;
try {
TechnicSolder::loadPack(pack, obj);
}
catch (const JSONValidationError& err) {
} catch (const JSONValidationError& err) {
qCritical() << "Couldn't parse Solder pack metadata:" << err.cause();
fallback();
return;

View File

@ -104,5 +104,5 @@ private:
QString selectedVersion;
NetJob::Ptr jobPtr;
QByteArray response;
std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
};