This commit is contained in:
Trial97 2023-06-23 19:35:47 +03:00
commit cb2671a02c
No known key found for this signature in database
GPG Key ID: 55EF5DA53DB36318
47 changed files with 659 additions and 793 deletions

View File

@ -10,6 +10,7 @@
#include "modplatform/flame/FlameAPI.h" #include "modplatform/flame/FlameAPI.h"
#include "modplatform/flame/FlameModIndex.h" #include "modplatform/flame/FlameModIndex.h"
#include "modplatform/helpers/HashUtils.h"
#include "modplatform/modrinth/ModrinthAPI.h" #include "modplatform/modrinth/ModrinthAPI.h"
#include "modplatform/modrinth/ModrinthPackIndex.h" #include "modplatform/modrinth/ModrinthPackIndex.h"
@ -24,8 +25,8 @@ EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::Resource
auto hash_task = createNewHash(mod); auto hash_task = createNewHash(mod);
if (!hash_task) if (!hash_task)
return; return;
connect(hash_task.get(), &Task::succeeded, [this, hash_task, mod] { m_mods.insert(hash_task->getResult(), mod); }); connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { m_mods.insert(hash, mod); });
connect(hash_task.get(), &Task::failed, [this, hash_task, mod] { emitFail(mod, "", RemoveFromList::No); }); connect(hash_task.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); });
hash_task->start(); hash_task->start();
} }
@ -37,8 +38,8 @@ EnsureMetadataTask::EnsureMetadataTask(QList<Mod*>& mods, QDir dir, ModPlatform:
auto hash_task = createNewHash(mod); auto hash_task = createNewHash(mod);
if (!hash_task) if (!hash_task)
continue; continue;
connect(hash_task.get(), &Task::succeeded, [this, hash_task, mod] { m_mods.insert(hash_task->getResult(), mod); }); connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { m_mods.insert(hash, mod); });
connect(hash_task.get(), &Task::failed, [this, hash_task, mod] { emitFail(mod, "", RemoveFromList::No); }); connect(hash_task.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); });
m_hashing_task->addTask(hash_task); m_hashing_task->addTask(hash_task);
} }
} }
@ -212,7 +213,7 @@ Task::Ptr EnsureMetadataTask::modrinthVersionsTask()
{ {
auto hash_type = ProviderCaps.hashType(ModPlatform::ResourceProvider::MODRINTH).first(); auto hash_type = ProviderCaps.hashType(ModPlatform::ResourceProvider::MODRINTH).first();
auto* response = new QByteArray(); auto response = std::make_shared<QByteArray>();
auto ver_task = modrinth_api.currentVersions(m_mods.keys(), hash_type, response); auto ver_task = modrinth_api.currentVersions(m_mods.keys(), hash_type, response);
// Prevents unfortunate timings when aborting the task // Prevents unfortunate timings when aborting the task
@ -264,7 +265,7 @@ Task::Ptr EnsureMetadataTask::modrinthProjectsTask()
for (auto const& data : m_temp_versions) for (auto const& data : m_temp_versions)
addonIds.insert(data.addonId.toString(), data.hash); addonIds.insert(data.addonId.toString(), data.hash);
auto response = new QByteArray(); auto response = std::make_shared<QByteArray>();
Task::Ptr proj_task; Task::Ptr proj_task;
if (addonIds.isEmpty()) { if (addonIds.isEmpty()) {
@ -345,7 +346,7 @@ Task::Ptr EnsureMetadataTask::modrinthProjectsTask()
// Flame // Flame
Task::Ptr EnsureMetadataTask::flameVersionsTask() Task::Ptr EnsureMetadataTask::flameVersionsTask()
{ {
auto* response = new QByteArray(); auto response = std::make_shared<QByteArray>();
QList<uint> fingerprints; QList<uint> fingerprints;
for (auto& murmur : m_mods.keys()) { for (auto& murmur : m_mods.keys()) {
@ -413,7 +414,7 @@ Task::Ptr EnsureMetadataTask::flameProjectsTask()
QHash<QString, QString> addonIds; QHash<QString, QString> addonIds;
for (auto const& hash : m_mods.keys()) { for (auto const& hash : m_mods.keys()) {
if (m_temp_versions.contains(hash)) { if (m_temp_versions.contains(hash)) {
auto const& data = m_temp_versions.find(hash).value(); auto data = m_temp_versions.find(hash).value();
auto id_str = data.addonId.toString(); auto id_str = data.addonId.toString();
if (!id_str.isEmpty()) if (!id_str.isEmpty())
@ -421,7 +422,7 @@ Task::Ptr EnsureMetadataTask::flameProjectsTask()
} }
} }
auto response = new QByteArray(); auto response = std::make_shared<QByteArray>();
Task::Ptr proj_task; Task::Ptr proj_task;
if (addonIds.isEmpty()) { if (addonIds.isEmpty()) {

View File

@ -121,12 +121,12 @@ class ResourceAPI {
qWarning() << "TODO"; qWarning() << "TODO";
return nullptr; return nullptr;
} }
[[nodiscard]] virtual Task::Ptr getProject(QString addonId, QByteArray* response) const [[nodiscard]] virtual Task::Ptr getProject(QString addonId, std::shared_ptr<QByteArray> response) const
{ {
qWarning() << "TODO"; qWarning() << "TODO";
return nullptr; return nullptr;
} }
[[nodiscard]] virtual Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const [[nodiscard]] virtual Task::Ptr getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const
{ {
qWarning() << "TODO"; qWarning() << "TODO";
return nullptr; return nullptr;

View File

@ -82,9 +82,9 @@ void PackInstallTask::executeTask()
{ {
qDebug() << "PackInstallTask::executeTask: " << QThread::currentThreadId(); qDebug() << "PackInstallTask::executeTask: " << QThread::currentThreadId();
NetJob::Ptr netJob{ new NetJob("ATLauncher::VersionFetch", APPLICATION->network()) }; NetJob::Ptr netJob{ new NetJob("ATLauncher::VersionFetch", APPLICATION->network()) };
auto searchUrl = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.json") auto searchUrl =
.arg(m_pack_safe_name).arg(m_version_name); QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.json").arg(m_pack_safe_name).arg(m_version_name);
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
QObject::connect(netJob.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded); QObject::connect(netJob.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded);
QObject::connect(netJob.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed); QObject::connect(netJob.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed);
@ -100,10 +100,11 @@ void PackInstallTask::onDownloadSucceeded()
jobPtr.reset(); jobPtr.reset();
QJsonParseError parse_error{}; QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) { if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from ATLauncher at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << "Error while parsing JSON response from ATLauncher at " << parse_error.offset
qWarning() << response; << " reason: " << parse_error.errorString();
qWarning() << *response.get();
return; return;
} }
auto obj = doc.object(); auto obj = doc.object();

View File

@ -40,12 +40,13 @@
#include "ATLPackManifest.h" #include "ATLPackManifest.h"
#include "InstanceTask.h" #include "InstanceTask.h"
#include "net/NetJob.h" #include "meta/Version.h"
#include "settings/INISettingsObject.h"
#include "minecraft/MinecraftInstance.h" #include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h" #include "minecraft/PackProfile.h"
#include "meta/Version.h" #include "net/NetJob.h"
#include "settings/INISettingsObject.h"
#include <memory>
#include <optional> #include <optional>
namespace ATLauncher { namespace ATLauncher {
@ -57,7 +58,6 @@ enum class InstallMode {
}; };
class UserInteractionSupport { class UserInteractionSupport {
public: public:
/** /**
* Requests a user interaction to select which optional mods should be installed. * Requests a user interaction to select which optional mods should be installed.
@ -74,15 +74,19 @@ public:
* Requests a user interaction to display a message. * Requests a user interaction to display a message.
*/ */
virtual void displayMessage(QString message) = 0; virtual void displayMessage(QString message) = 0;
virtual ~UserInteractionSupport() = default;
}; };
class PackInstallTask : public InstanceTask class PackInstallTask : public InstanceTask {
{
Q_OBJECT Q_OBJECT
public: public:
explicit PackInstallTask(UserInteractionSupport *support, QString packName, QString version, InstallMode installMode = InstallMode::Install); explicit PackInstallTask(UserInteractionSupport* support,
virtual ~PackInstallTask(){} QString packName,
QString version,
InstallMode installMode = InstallMode::Install);
virtual ~PackInstallTask() { delete m_support; }
bool canAbort() const override { return true; } bool canAbort() const override { return true; }
bool abort() override; bool abort() override;
@ -110,11 +114,9 @@ private:
void installConfigs(); void installConfigs();
void extractConfigs(); void extractConfigs();
void downloadMods(); void downloadMods();
bool extractMods( bool extractMods(const QMap<QString, VersionMod>& toExtract,
const QMap<QString, VersionMod> &toExtract,
const QMap<QString, VersionMod>& toDecomp, const QMap<QString, VersionMod>& toDecomp,
const QMap<QString, QString> &toCopy const QMap<QString, QString>& toCopy);
);
void install(); void install();
private: private:
@ -123,7 +125,7 @@ private:
bool abortable = false; bool abortable = false;
NetJob::Ptr jobPtr; NetJob::Ptr jobPtr;
QByteArray response; std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
InstallMode m_install_mode; InstallMode m_install_mode;
QString m_pack_name; QString m_pack_name;
@ -145,7 +147,6 @@ private:
QFuture<bool> m_modExtractFuture; QFuture<bool> m_modExtractFuture;
QFutureWatcher<bool> m_modExtractFutureWatcher; QFutureWatcher<bool> m_modExtractFutureWatcher;
}; };
} } // namespace ATLauncher

View File

@ -28,12 +28,13 @@ void Flame::FileResolvingTask::executeTask()
// build json data to send // build json data to send
QJsonObject object; QJsonObject object;
object["fileIds"] = QJsonArray::fromVariantList(std::accumulate(m_toProcess.files.begin(), m_toProcess.files.end(), QVariantList(), [](QVariantList& l, const File& s) { object["fileIds"] = QJsonArray::fromVariantList(
std::accumulate(m_toProcess.files.begin(), m_toProcess.files.end(), QVariantList(), [](QVariantList& l, const File& s) {
l.push_back(s.fileId); l.push_back(s.fileId);
return l; return l;
})); }));
QByteArray data = Json::toText(object); QByteArray data = Json::toText(object);
auto dl = Net::Upload::makeByteArray(QUrl("https://api.curseforge.com/v1/mods/files"), result.get(), data); auto dl = Net::Upload::makeByteArray(QUrl("https://api.curseforge.com/v1/mods/files"), result, data);
m_dljob->addNetAction(dl); m_dljob->addNetAction(dl);
auto step_progress = std::make_shared<TaskStepProgress>(); auto step_progress = std::make_shared<TaskStepProgress>();
@ -94,10 +95,8 @@ void Flame::FileResolvingTask::netJobFinished()
if (!hash.isEmpty()) { if (!hash.isEmpty()) {
auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash); auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash);
auto output = std::make_shared<QByteArray>(); auto output = std::make_shared<QByteArray>();
auto dl = Net::Download::makeByteArray(QUrl(url), output.get()); auto dl = Net::Download::makeByteArray(QUrl(url), output);
QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() { QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() { out.resolved = true; });
out.resolved = true;
});
m_checkJob->addNetAction(dl); m_checkJob->addNetAction(dl);
blockedProjects.insert(&out, output); blockedProjects.insert(&out, output);
@ -169,7 +168,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() {
auto projectId = mod->projectId; auto projectId = mod->projectId;
auto output = std::make_shared<QByteArray>(); auto output = std::make_shared<QByteArray>();
auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(projectId); auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(projectId);
auto dl = Net::Download::makeByteArray(url, output.get()); auto dl = Net::Download::makeByteArray(url, output);
qDebug() << "Fetching url slug for file:" << mod->fileName; qDebug() << "Fetching url slug for file:" << mod->fileName;
QObject::connect(dl.get(), &Net::Download::succeeded, [block, index, output]() { QObject::connect(dl.get(), &Net::Download::succeeded, [block, index, output]() {
auto mod = block->at(index); // use the shared_ptr so it is captured and only freed when we are done auto mod = block->at(index); // use the shared_ptr so it is captured and only freed when we are done

View File

@ -11,7 +11,7 @@
#include "net/NetJob.h" #include "net/NetJob.h"
#include "net/Upload.h" #include "net/Upload.h"
Task::Ptr FlameAPI::matchFingerprints(const QList<uint>& fingerprints, QByteArray* response) Task::Ptr FlameAPI::matchFingerprints(const QList<uint>& fingerprints, std::shared_ptr<QByteArray> response)
{ {
auto netJob = makeShared<NetJob>(QString("Flame::MatchFingerprints"), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("Flame::MatchFingerprints"), APPLICATION->network());
@ -28,8 +28,6 @@ Task::Ptr FlameAPI::matchFingerprints(const QList<uint>& fingerprints, QByteArra
netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/fingerprints"), response, body_raw)); netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/fingerprints"), response, body_raw));
QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
return netJob; return netJob;
} }
@ -43,7 +41,7 @@ auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString
netJob->addNetAction(Net::Download::makeByteArray( netJob->addNetAction(Net::Download::makeByteArray(
QString("https://api.curseforge.com/v1/mods/%1/files/%2/changelog") QString("https://api.curseforge.com/v1/mods/%1/files/%2/changelog")
.arg(QString::fromStdString(std::to_string(modId)), QString::fromStdString(std::to_string(fileId))), .arg(QString::fromStdString(std::to_string(modId)), QString::fromStdString(std::to_string(fileId))),
response.get())); response));
QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &changelog] { QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &changelog] {
QJsonParseError parse_error{}; QJsonParseError parse_error{};
@ -75,8 +73,8 @@ auto FlameAPI::getModDescription(int modId) -> QString
auto netJob = makeShared<NetJob>(QString("Flame::ModDescription"), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("Flame::ModDescription"), APPLICATION->network());
auto response = std::make_shared<QByteArray>(); auto response = std::make_shared<QByteArray>();
netJob->addNetAction(Net::Download::makeByteArray( netJob->addNetAction(
QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response.get())); Net::Download::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response));
QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] { QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] {
QJsonParseError parse_error{}; QJsonParseError parse_error{};
@ -115,7 +113,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe
auto response = std::make_shared<QByteArray>(); auto response = std::make_shared<QByteArray>();
ModPlatform::IndexedVersion ver; ModPlatform::IndexedVersion ver;
netJob->addNetAction(Net::Download::makeByteArray(versions_url, response.get())); netJob->addNetAction(Net::Download::makeByteArray(versions_url, response));
QObject::connect(netJob.get(), &NetJob::succeeded, [response, args, &ver] { QObject::connect(netJob.get(), &NetJob::succeeded, [response, args, &ver] {
QJsonParseError parse_error{}; QJsonParseError parse_error{};
@ -160,7 +158,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe
return ver; return ver;
} }
Task::Ptr FlameAPI::getProjects(QStringList addonIds, QByteArray* response) const Task::Ptr FlameAPI::getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const
{ {
auto netJob = makeShared<NetJob>(QString("Flame::GetProjects"), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("Flame::GetProjects"), APPLICATION->network());
@ -177,13 +175,12 @@ Task::Ptr FlameAPI::getProjects(QStringList addonIds, QByteArray* response) cons
netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/mods"), response, body_raw)); netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/mods"), response, body_raw));
QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; }); QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; });
return netJob; return netJob;
} }
Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, QByteArray* response) const Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, std::shared_ptr<QByteArray> response) const
{ {
auto netJob = makeShared<NetJob>(QString("Flame::GetFiles"), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("Flame::GetFiles"), APPLICATION->network());
@ -200,7 +197,6 @@ Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, QByteArray* response) c
netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/mods/files"), response, body_raw)); netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/mods/files"), response, body_raw));
QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; }); QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; });
return netJob; return netJob;

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <memory>
#include "modplatform/ModIndex.h" #include "modplatform/ModIndex.h"
#include "modplatform/helpers/NetworkResourceAPI.h" #include "modplatform/helpers/NetworkResourceAPI.h"
@ -14,9 +15,9 @@ class FlameAPI : public NetworkResourceAPI {
auto getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::IndexedVersion; auto getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::IndexedVersion;
Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const override; Task::Ptr getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const override;
Task::Ptr matchFingerprints(const QList<uint>& fingerprints, QByteArray* response); Task::Ptr matchFingerprints(const QList<uint>& fingerprints, std::shared_ptr<QByteArray> response);
Task::Ptr getFiles(const QStringList& fileIds, QByteArray* response) const; Task::Ptr getFiles(const QStringList& fileIds, std::shared_ptr<QByteArray> response) const;
[[nodiscard]] auto getSortingMethods() const -> QList<ResourceAPI::SortingMethod> override; [[nodiscard]] auto getSortingMethods() const -> QList<ResourceAPI::SortingMethod> override;
@ -48,7 +49,8 @@ class FlameAPI : public NetworkResourceAPI {
private: private:
[[nodiscard]] std::optional<QString> getSearchURL(SearchArgs const& args) const override [[nodiscard]] std::optional<QString> getSearchURL(SearchArgs const& args) const override
{ {
auto gameVersionStr = args.versions.has_value() ? QString("gameVersion=%1").arg(args.versions.value().front().toString()) : QString(); auto gameVersionStr =
args.versions.has_value() ? QString("gameVersion=%1").arg(args.versions.value().front().toString()) : QString();
QStringList get_arguments; QStringList get_arguments;
get_arguments.append(QString("classId=%1").arg(getClassId(args.type))); get_arguments.append(QString("classId=%1").arg(getClassId(args.type)));

View File

@ -31,7 +31,7 @@ ModPlatform::IndexedPack getProjectInfo(ModPlatform::IndexedVersion& ver_info)
auto get_project_job = new NetJob("Flame::GetProjectJob", APPLICATION->network()); auto get_project_job = new NetJob("Flame::GetProjectJob", APPLICATION->network());
auto response = new QByteArray(); auto response = std::make_shared<QByteArray>();
auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(ver_info.addonId.toString()); auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(ver_info.addonId.toString());
auto dl = Net::Download::makeByteArray(url, response); auto dl = Net::Download::makeByteArray(url, response);
get_project_job->addNetAction(dl); get_project_job->addNetAction(dl);
@ -75,7 +75,7 @@ ModPlatform::IndexedVersion getFileInfo(int addonId, int fileId)
auto get_file_info_job = new NetJob("Flame::GetFileInfoJob", APPLICATION->network()); auto get_file_info_job = new NetJob("Flame::GetFileInfoJob", APPLICATION->network());
auto response = new QByteArray(); auto response = std::make_shared<QByteArray>();
auto url = QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(QString::number(addonId), QString::number(fileId)); auto url = QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(QString::number(addonId), QString::number(fileId));
auto dl = Net::Download::makeByteArray(url, response); auto dl = Net::Download::makeByteArray(url, response);
get_file_info_job->addNetAction(dl); get_file_info_job->addNetAction(dl);

View File

@ -182,7 +182,7 @@ bool FlameCreationTask::updateInstance()
fileIds.append(QString::number(file.fileId)); fileIds.append(QString::number(file.fileId));
} }
auto* raw_response = new QByteArray; auto raw_response = std::make_shared<QByteArray>();
auto job = api.getFiles(fileIds, raw_response); auto job = api.getFiles(fileIds, raw_response);
QEventLoop loop; QEventLoop loop;

View File

@ -71,6 +71,7 @@ void ModrinthHasher::executeTask()
emitFailed("Empty hash!"); emitFailed("Empty hash!");
} else { } else {
emitSucceeded(); emitSucceeded();
emit resultsReady(m_hash);
} }
} }
@ -91,9 +92,8 @@ void FlameHasher::executeTask()
} }
} }
BlockedModHasher::BlockedModHasher(QString file_path, ModPlatform::ResourceProvider provider) : Hasher(file_path), provider(provider)
BlockedModHasher::BlockedModHasher(QString file_path, ModPlatform::ResourceProvider provider) {
: Hasher(file_path), provider(provider) {
setObjectName(QString("BlockedModHasher: %1").arg(file_path)); setObjectName(QString("BlockedModHasher: %1").arg(file_path));
hash_type = ProviderCaps.hashType(provider).first(); hash_type = ProviderCaps.hashType(provider).first();
} }
@ -123,11 +123,13 @@ void BlockedModHasher::executeTask()
} }
} }
QStringList BlockedModHasher::getHashTypes() { QStringList BlockedModHasher::getHashTypes()
{
return ProviderCaps.hashType(provider); return ProviderCaps.hashType(provider);
} }
bool BlockedModHasher::useHashType(QString type) { bool BlockedModHasher::useHashType(QString type)
{
auto types = ProviderCaps.hashType(provider); auto types = ProviderCaps.hashType(provider);
if (types.contains(type)) { if (types.contains(type)) {
hash_type = type; hash_type = type;

View File

@ -8,6 +8,7 @@
namespace Hashing { namespace Hashing {
class Hasher : public Task { class Hasher : public Task {
Q_OBJECT
public: public:
using Ptr = shared_qobject_ptr<Hasher>; using Ptr = shared_qobject_ptr<Hasher>;
@ -21,6 +22,9 @@ class Hasher : public Task {
QString getResult() const { return m_hash; }; QString getResult() const { return m_hash; };
QString getPath() const { return m_path; }; QString getPath() const { return m_path; };
signals:
void resultsReady(QString hash);
protected: protected:
QString m_hash; QString m_hash;
QString m_path; QString m_path;
@ -48,6 +52,7 @@ class BlockedModHasher : public Hasher {
QStringList getHashTypes(); QStringList getHashTypes();
bool useHashType(QString type); bool useHashType(QString type);
private: private:
ModPlatform::ResourceProvider provider; ModPlatform::ResourceProvider provider;
QString hash_type; QString hash_type;

View File

@ -3,6 +3,7 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
#include "NetworkResourceAPI.h" #include "NetworkResourceAPI.h"
#include <memory>
#include "Application.h" #include "Application.h"
#include "net/NetJob.h" #include "net/NetJob.h"
@ -19,7 +20,7 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&
auto search_url = search_url_optional.value(); auto search_url = search_url_optional.value();
auto response = new QByteArray(); auto response = std::make_shared<QByteArray>();
auto netJob = makeShared<NetJob>(QString("%1::Search").arg(debugName()), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("%1::Search").arg(debugName()), APPLICATION->network());
netJob->addNetAction(Net::Download::makeByteArray(QUrl(search_url), response)); netJob->addNetAction(Net::Download::makeByteArray(QUrl(search_url), response));
@ -47,20 +48,14 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&
callbacks.on_fail(reason, network_error_code); callbacks.on_fail(reason, network_error_code);
}); });
QObject::connect(netJob.get(), &NetJob::aborted, [callbacks]{ QObject::connect(netJob.get(), &NetJob::aborted, [callbacks] { callbacks.on_abort(); });
callbacks.on_abort();
});
QObject::connect(netJob.get(), &NetJob::finished, [response] {
delete response;
});
return netJob; return netJob;
} }
Task::Ptr NetworkResourceAPI::getProjectInfo(ProjectInfoArgs&& args, ProjectInfoCallbacks&& callbacks) const Task::Ptr NetworkResourceAPI::getProjectInfo(ProjectInfoArgs&& args, ProjectInfoCallbacks&& callbacks) const
{ {
auto response = new QByteArray(); auto response = std::make_shared<QByteArray>();
auto job = getProject(args.pack.addonId.toString(), response); auto job = getProject(args.pack.addonId.toString(), response);
QObject::connect(job.get(), &NetJob::succeeded, [response, callbacks, args] { QObject::connect(job.get(), &NetJob::succeeded, [response, callbacks, args] {
@ -88,7 +83,7 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi
auto versions_url = versions_url_optional.value(); auto versions_url = versions_url_optional.value();
auto netJob = makeShared<NetJob>(QString("%1::Versions").arg(args.pack.name), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("%1::Versions").arg(args.pack.name), APPLICATION->network());
auto response = new QByteArray(); auto response = std::make_shared<QByteArray>();
netJob->addNetAction(Net::Download::makeByteArray(versions_url, response)); netJob->addNetAction(Net::Download::makeByteArray(versions_url, response));
@ -105,14 +100,10 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi
callbacks.on_succeed(doc, args.pack); callbacks.on_succeed(doc, args.pack);
}); });
QObject::connect(netJob.get(), &NetJob::finished, [response] {
delete response;
});
return netJob; return netJob;
} }
Task::Ptr NetworkResourceAPI::getProject(QString addonId, QByteArray* response) const Task::Ptr NetworkResourceAPI::getProject(QString addonId, std::shared_ptr<QByteArray> response) const
{ {
auto project_url_optional = getInfoURL(addonId); auto project_url_optional = getInfoURL(addonId);
if (!project_url_optional.has_value()) if (!project_url_optional.has_value())
@ -124,9 +115,5 @@ Task::Ptr NetworkResourceAPI::getProject(QString addonId, QByteArray* response)
netJob->addNetAction(Net::Download::makeByteArray(QUrl(project_url), response)); netJob->addNetAction(Net::Download::makeByteArray(QUrl(project_url), response));
QObject::connect(netJob.get(), &NetJob::finished, [response] {
delete response;
});
return netJob; return netJob;
} }

View File

@ -4,13 +4,14 @@
#pragma once #pragma once
#include <memory>
#include "modplatform/ResourceAPI.h" #include "modplatform/ResourceAPI.h"
class NetworkResourceAPI : public ResourceAPI { class NetworkResourceAPI : public ResourceAPI {
public: public:
Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&&) const override; Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&&) const override;
Task::Ptr getProject(QString addonId, QByteArray* response) const override; Task::Ptr getProject(QString addonId, std::shared_ptr<QByteArray> response) const override;
Task::Ptr getProjectInfo(ProjectInfoArgs&&, ProjectInfoCallbacks&&) const override; Task::Ptr getProjectInfo(ProjectInfoArgs&&, ProjectInfoCallbacks&&) const override;
Task::Ptr getProjectVersions(VersionSearchArgs&&, VersionSearchCallbacks&&) const override; Task::Ptr getProjectVersions(VersionSearchArgs&&, VersionSearchCallbacks&&) const override;

View File

@ -51,11 +51,11 @@ void PackFetchTask::fetch()
QUrl publicPacksUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/modpacks.xml"); QUrl publicPacksUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/modpacks.xml");
qDebug() << "Downloading public version info from" << publicPacksUrl.toString(); qDebug() << "Downloading public version info from" << publicPacksUrl.toString();
jobPtr->addNetAction(Net::Download::makeByteArray(publicPacksUrl, &publicModpacksXmlFileData)); jobPtr->addNetAction(Net::Download::makeByteArray(publicPacksUrl, publicModpacksXmlFileData));
QUrl thirdPartyUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/thirdparty.xml"); QUrl thirdPartyUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/thirdparty.xml");
qDebug() << "Downloading thirdparty version info from" << thirdPartyUrl.toString(); qDebug() << "Downloading thirdparty version info from" << thirdPartyUrl.toString();
jobPtr->addNetAction(Net::Download::makeByteArray(thirdPartyUrl, &thirdPartyModpacksXmlFileData)); jobPtr->addNetAction(Net::Download::makeByteArray(thirdPartyUrl, thirdPartyModpacksXmlFileData));
QObject::connect(jobPtr.get(), &NetJob::succeeded, this, &PackFetchTask::fileDownloadFinished); QObject::connect(jobPtr.get(), &NetJob::succeeded, this, &PackFetchTask::fileDownloadFinished);
QObject::connect(jobPtr.get(), &NetJob::failed, this, &PackFetchTask::fileDownloadFailed); QObject::connect(jobPtr.get(), &NetJob::failed, this, &PackFetchTask::fileDownloadFailed);
@ -68,18 +68,15 @@ void PackFetchTask::fetchPrivate(const QStringList & toFetch)
{ {
QString privatePackBaseUrl = BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1.xml"; QString privatePackBaseUrl = BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1.xml";
for (auto &packCode: toFetch) for (auto& packCode : toFetch) {
{ auto data = std::make_shared<QByteArray>();
QByteArray *data = new QByteArray();
NetJob* job = new NetJob("Fetching private pack", m_network); NetJob* job = new NetJob("Fetching private pack", m_network);
job->addNetAction(Net::Download::makeByteArray(privatePackBaseUrl.arg(packCode), data)); job->addNetAction(Net::Download::makeByteArray(privatePackBaseUrl.arg(packCode), data));
QObject::connect(job, &NetJob::succeeded, this, [this, job, data, packCode] QObject::connect(job, &NetJob::succeeded, this, [this, job, data, packCode] {
{
ModpackList packs; ModpackList packs;
parseAndAddPacks(*data, PackType::Private, packs); parseAndAddPacks(*data, PackType::Private, packs);
foreach(Modpack currentPack, packs) foreach (Modpack currentPack, packs) {
{
currentPack.packCode = packCode; currentPack.packCode = packCode;
emit privateFileDownloadFinished(currentPack); emit privateFileDownloadFinished(currentPack);
} }
@ -87,16 +84,13 @@ void PackFetchTask::fetchPrivate(const QStringList & toFetch)
job->deleteLater(); job->deleteLater();
data->clear(); data->clear();
delete data;
}); });
QObject::connect(job, &NetJob::failed, this, [this, job, packCode, data](QString reason) QObject::connect(job, &NetJob::failed, this, [this, job, packCode, data](QString reason) {
{
emit privateFileDownloadFailed(reason, packCode); emit privateFileDownloadFailed(reason, packCode);
job->deleteLater(); job->deleteLater();
data->clear(); data->clear();
delete data;
}); });
QObject::connect(job, &NetJob::aborted, this, [this, job, data] { QObject::connect(job, &NetJob::aborted, this, [this, job, data] {
@ -104,7 +98,6 @@ void PackFetchTask::fetchPrivate(const QStringList & toFetch)
job->deleteLater(); job->deleteLater();
data->clear(); data->clear();
delete data;
}); });
job->start(); job->start();
@ -117,22 +110,17 @@ void PackFetchTask::fileDownloadFinished()
QStringList failedLists; QStringList failedLists;
if(!parseAndAddPacks(publicModpacksXmlFileData, PackType::Public, publicPacks)) if (!parseAndAddPacks(*publicModpacksXmlFileData, PackType::Public, publicPacks)) {
{
failedLists.append(tr("Public Packs")); failedLists.append(tr("Public Packs"));
} }
if(!parseAndAddPacks(thirdPartyModpacksXmlFileData, PackType::ThirdParty, thirdPartyPacks)) if (!parseAndAddPacks(*thirdPartyModpacksXmlFileData, PackType::ThirdParty, thirdPartyPacks)) {
{
failedLists.append(tr("Third Party Packs")); failedLists.append(tr("Third Party Packs"));
} }
if(failedLists.size() > 0) if (failedLists.size() > 0) {
{
emit failed(tr("Failed to download some pack lists: %1").arg(failedLists.join("\n- "))); emit failed(tr("Failed to download some pack lists: %1").arg(failedLists.join("\n- ")));
} } else {
else
{
emit finished(publicPacks, thirdPartyPacks); emit finished(publicPacks, thirdPartyPacks);
} }
} }
@ -145,8 +133,7 @@ bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, Modpac
int errorLine = -1; int errorLine = -1;
int errorCol = -1; int errorCol = -1;
if(!doc.setContent(data, false, &errorMsg, &errorLine, &errorCol)) if (!doc.setContent(data, false, &errorMsg, &errorLine, &errorCol)) {
{
auto fullErrMsg = QString("Failed to fetch modpack data: %1 %2:%3!").arg(errorMsg).arg(errorLine).arg(errorCol); auto fullErrMsg = QString("Failed to fetch modpack data: %1 %2:%3!").arg(errorMsg).arg(errorLine).arg(errorCol);
qWarning() << fullErrMsg; qWarning() << fullErrMsg;
data.clear(); data.clear();
@ -154,8 +141,7 @@ bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, Modpac
} }
QDomNodeList nodes = doc.elementsByTagName("modpack"); QDomNodeList nodes = doc.elementsByTagName("modpack");
for(int i = 0; i < nodes.length(); i++) for (int i = 0; i < nodes.length(); i++) {
{
QDomElement element = nodes.at(i).toElement(); QDomElement element = nodes.at(i).toElement();
Modpack modpack; Modpack modpack;
@ -170,25 +156,19 @@ bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, Modpac
modpack.bugged = false; modpack.bugged = false;
// remove empty if the xml is bugged // remove empty if the xml is bugged
for(QString curr : modpack.oldVersions) for (QString curr : modpack.oldVersions) {
{ if (curr.isNull() || curr.isEmpty()) {
if(curr.isNull() || curr.isEmpty())
{
modpack.oldVersions.removeAll(curr); modpack.oldVersions.removeAll(curr);
modpack.bugged = true; modpack.bugged = true;
qWarning() << "Removed some empty versions from" << modpack.name; qWarning() << "Removed some empty versions from" << modpack.name;
} }
} }
if(modpack.oldVersions.size() < 1) if (modpack.oldVersions.size() < 1) {
{ if (!modpack.currentVersion.isNull() && !modpack.currentVersion.isEmpty()) {
if(!modpack.currentVersion.isNull() && !modpack.currentVersion.isEmpty())
{
modpack.oldVersions.append(modpack.currentVersion); modpack.oldVersions.append(modpack.currentVersion);
qWarning() << "Added current version to oldVersions because oldVersions was empty! (" + modpack.name + ")"; qWarning() << "Added current version to oldVersions because oldVersions was empty! (" + modpack.name + ")";
} } else {
else
{
modpack.broken = true; modpack.broken = true;
qWarning() << "Broken pack:" << modpack.name << " => No valid version!"; qWarning() << "Broken pack:" << modpack.name << " => No valid version!";
} }
@ -218,4 +198,4 @@ void PackFetchTask::fileDownloadAborted()
emit aborted(); emit aborted();
} }
} } // namespace LegacyFTB

View File

@ -1,15 +1,15 @@
#pragma once #pragma once
#include "net/NetJob.h"
#include <QTemporaryDir>
#include <QByteArray> #include <QByteArray>
#include <QObject> #include <QObject>
#include <QTemporaryDir>
#include <memory>
#include "PackHelpers.h" #include "PackHelpers.h"
#include "net/NetJob.h"
namespace LegacyFTB { namespace LegacyFTB {
class PackFetchTask : public QObject { class PackFetchTask : public QObject {
Q_OBJECT Q_OBJECT
public: public:
@ -23,8 +23,8 @@ private:
shared_qobject_ptr<QNetworkAccessManager> m_network; shared_qobject_ptr<QNetworkAccessManager> m_network;
NetJob::Ptr jobPtr; NetJob::Ptr jobPtr;
QByteArray publicModpacksXmlFileData; std::shared_ptr<QByteArray> publicModpacksXmlFileData = std::make_shared<QByteArray>();
QByteArray thirdPartyModpacksXmlFileData; std::shared_ptr<QByteArray> thirdPartyModpacksXmlFileData = std::make_shared<QByteArray>();
bool parseAndAddPacks(QByteArray& data, PackType packType, ModpackList& list); bool parseAndAddPacks(QByteArray& data, PackType packType, ModpackList& list);
ModpackList publicPacks; ModpackList publicPacks;
@ -44,4 +44,4 @@ signals:
void privateFileDownloadFailed(QString reason, QString packCode); void privateFileDownloadFailed(QString reason, QString packCode);
}; };
} } // namespace LegacyFTB

View File

@ -9,19 +9,17 @@
#include "net/NetJob.h" #include "net/NetJob.h"
#include "net/Upload.h" #include "net/Upload.h"
Task::Ptr ModrinthAPI::currentVersion(QString hash, QString hash_format, QByteArray* response) Task::Ptr ModrinthAPI::currentVersion(QString hash, QString hash_format, std::shared_ptr<QByteArray> response)
{ {
auto netJob = makeShared<NetJob>(QString("Modrinth::GetCurrentVersion"), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("Modrinth::GetCurrentVersion"), APPLICATION->network());
netJob->addNetAction(Net::Download::makeByteArray( netJob->addNetAction(Net::Download::makeByteArray(
QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1?algorithm=%2").arg(hash, hash_format), response)); QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1?algorithm=%2").arg(hash, hash_format), response));
QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
return netJob; return netJob;
} }
Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_format, QByteArray* response) Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_format, std::shared_ptr<QByteArray> response)
{ {
auto netJob = makeShared<NetJob>(QString("Modrinth::GetCurrentVersions"), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("Modrinth::GetCurrentVersions"), APPLICATION->network());
@ -35,8 +33,6 @@ Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_f
netJob->addNetAction(Net::Upload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files"), response, body_raw)); netJob->addNetAction(Net::Upload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files"), response, body_raw));
QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
return netJob; return netJob;
} }
@ -44,7 +40,7 @@ Task::Ptr ModrinthAPI::latestVersion(QString hash,
QString hash_format, QString hash_format,
std::optional<std::list<Version>> mcVersions, std::optional<std::list<Version>> mcVersions,
std::optional<ModLoaderTypes> loaders, std::optional<ModLoaderTypes> loaders,
QByteArray* response) std::shared_ptr<QByteArray> response)
{ {
auto netJob = makeShared<NetJob>(QString("Modrinth::GetLatestVersion"), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("Modrinth::GetLatestVersion"), APPLICATION->network());
@ -67,8 +63,6 @@ Task::Ptr ModrinthAPI::latestVersion(QString hash,
netJob->addNetAction(Net::Upload::makeByteArray( netJob->addNetAction(Net::Upload::makeByteArray(
QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1/update?algorithm=%2").arg(hash, hash_format), response, body_raw)); QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1/update?algorithm=%2").arg(hash, hash_format), response, body_raw));
QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
return netJob; return netJob;
} }
@ -76,7 +70,7 @@ Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes,
QString hash_format, QString hash_format,
std::optional<std::list<Version>> mcVersions, std::optional<std::list<Version>> mcVersions,
std::optional<ModLoaderTypes> loaders, std::optional<ModLoaderTypes> loaders,
QByteArray* response) std::shared_ptr<QByteArray> response)
{ {
auto netJob = makeShared<NetJob>(QString("Modrinth::GetLatestVersions"), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("Modrinth::GetLatestVersions"), APPLICATION->network());
@ -101,22 +95,16 @@ Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes,
netJob->addNetAction(Net::Upload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files/update"), response, body_raw)); netJob->addNetAction(Net::Upload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files/update"), response, body_raw));
QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
return netJob; return netJob;
} }
Task::Ptr ModrinthAPI::getProjects(QStringList addonIds, QByteArray* response) const Task::Ptr ModrinthAPI::getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const
{ {
auto netJob = makeShared<NetJob>(QString("Modrinth::GetProjects"), APPLICATION->network()); auto netJob = makeShared<NetJob>(QString("Modrinth::GetProjects"), APPLICATION->network());
auto searchUrl = getMultipleModInfoURL(addonIds); auto searchUrl = getMultipleModInfoURL(addonIds);
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response)); netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response));
QObject::connect(netJob.get(), &NetJob::finished, [response, netJob] {
delete response;
});
return netJob; return netJob;
} }

View File

@ -12,27 +12,23 @@
class ModrinthAPI : public NetworkResourceAPI { class ModrinthAPI : public NetworkResourceAPI {
public: public:
auto currentVersion(QString hash, auto currentVersion(QString hash, QString hash_format, std::shared_ptr<QByteArray> response) -> Task::Ptr;
QString hash_format,
QByteArray* response) -> Task::Ptr;
auto currentVersions(const QStringList& hashes, auto currentVersions(const QStringList& hashes, QString hash_format, std::shared_ptr<QByteArray> response) -> Task::Ptr;
QString hash_format,
QByteArray* response) -> Task::Ptr;
auto latestVersion(QString hash, auto latestVersion(QString hash,
QString hash_format, QString hash_format,
std::optional<std::list<Version>> mcVersions, std::optional<std::list<Version>> mcVersions,
std::optional<ModLoaderTypes> loaders, std::optional<ModLoaderTypes> loaders,
QByteArray* response) -> Task::Ptr; std::shared_ptr<QByteArray> response) -> Task::Ptr;
auto latestVersions(const QStringList& hashes, auto latestVersions(const QStringList& hashes,
QString hash_format, QString hash_format,
std::optional<std::list<Version>> mcVersions, std::optional<std::list<Version>> mcVersions,
std::optional<ModLoaderTypes> loaders, std::optional<ModLoaderTypes> loaders,
QByteArray* response) -> Task::Ptr; std::shared_ptr<QByteArray> response) -> Task::Ptr;
Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const override; Task::Ptr getProjects(QStringList addonIds, std::shared_ptr<QByteArray> response) const override;
public: public:
[[nodiscard]] auto getSortingMethods() const -> QList<ResourceAPI::SortingMethod> override; [[nodiscard]] auto getSortingMethods() const -> QList<ResourceAPI::SortingMethod> override;

View File

@ -53,12 +53,11 @@ void ModrinthCheckUpdate::executeTask()
// (though it will rarely happen, if at all) // (though it will rarely happen, if at all)
if (mod->metadata()->hash_format != best_hash_type) { if (mod->metadata()->hash_format != best_hash_type) {
auto hash_task = Hashing::createModrinthHasher(mod->fileinfo().absoluteFilePath()); auto hash_task = Hashing::createModrinthHasher(mod->fileinfo().absoluteFilePath());
connect(hash_task.get(), &Task::succeeded, [&] { connect(hash_task.get(), &Hashing::Hasher::resultsReady, [&hashes, &mappings, mod](QString hash) {
QString hash(hash_task->getResult());
hashes.append(hash); hashes.append(hash);
mappings.insert(hash, mod); mappings.insert(hash, mod);
}); });
connect(hash_task.get(), &Task::failed, [this, hash_task] { failed("Failed to generate hash"); }); connect(hash_task.get(), &Task::failed, [this] { failed("Failed to generate hash"); });
hashing_task.addTask(hash_task); hashing_task.addTask(hash_task);
} else { } else {
hashes.append(hash); hashes.append(hash);
@ -71,7 +70,7 @@ void ModrinthCheckUpdate::executeTask()
hashing_task.start(); hashing_task.start();
loop.exec(); loop.exec();
auto* response = new QByteArray(); auto response = std::make_shared<QByteArray>();
auto job = api.latestVersions(hashes, best_hash_type, m_game_versions, m_loaders, response); auto job = api.latestVersions(hashes, best_hash_type, m_game_versions, m_loaders, response);
QEventLoop lock; QEventLoop lock;

View File

@ -157,7 +157,7 @@ void ModrinthPackExportTask::makeApiRequest()
if (pendingHashes.isEmpty()) if (pendingHashes.isEmpty())
buildZip(); buildZip();
else { else {
QByteArray* response = new QByteArray; auto response = std::make_shared<QByteArray>();
task = api.currentVersions(pendingHashes.values(), "sha512", response); task = api.currentVersions(pendingHashes.values(), "sha512", response);
connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); });
connect(task.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed); connect(task.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed);
@ -165,7 +165,7 @@ void ModrinthPackExportTask::makeApiRequest()
} }
} }
void ModrinthPackExportTask::parseApiResponse(const QByteArray* response) void ModrinthPackExportTask::parseApiResponse(const std::shared_ptr<QByteArray> response)
{ {
task = nullptr; task = nullptr;

View File

@ -69,7 +69,7 @@ class ModrinthPackExportTask : public Task {
void collectFiles(); void collectFiles();
void collectHashes(); void collectHashes();
void makeApiRequest(); void makeApiRequest();
void parseApiResponse(const QByteArray* response); void parseApiResponse(const std::shared_ptr<QByteArray> response);
void buildZip(); void buildZip();
void finish(); void finish();

View File

@ -37,20 +37,19 @@
#include <FileSystem.h> #include <FileSystem.h>
#include <Json.h> #include <Json.h>
#include <QtConcurrentRun>
#include <MMCZip.h> #include <MMCZip.h>
#include <QtConcurrentRun>
#include "TechnicPackProcessor.h"
#include "SolderPackManifest.h" #include "SolderPackManifest.h"
#include "TechnicPackProcessor.h"
#include "net/ChecksumValidator.h" #include "net/ChecksumValidator.h"
Technic::SolderPackInstallTask::SolderPackInstallTask( Technic::SolderPackInstallTask::SolderPackInstallTask(shared_qobject_ptr<QNetworkAccessManager> network,
shared_qobject_ptr<QNetworkAccessManager> network,
const QUrl& solderUrl, const QUrl& solderUrl,
const QString& pack, const QString& pack,
const QString& version, const QString& version,
const QString &minecraftVersion const QString& minecraftVersion)
) { {
m_solderUrl = solderUrl; m_solderUrl = solderUrl;
m_pack = pack; m_pack = pack;
m_version = version; m_version = version;
@ -58,9 +57,9 @@ Technic::SolderPackInstallTask::SolderPackInstallTask(
m_minecraftVersion = minecraftVersion; m_minecraftVersion = minecraftVersion;
} }
bool Technic::SolderPackInstallTask::abort() { bool Technic::SolderPackInstallTask::abort()
if(m_abortable)
{ {
if (m_abortable) {
return m_filesNetJob->abort(); return m_filesNetJob->abort();
} }
return false; return false;
@ -72,7 +71,7 @@ void Technic::SolderPackInstallTask::executeTask()
m_filesNetJob.reset(new NetJob(tr("Resolving modpack files"), m_network)); m_filesNetJob.reset(new NetJob(tr("Resolving modpack files"), m_network));
auto sourceUrl = QString("%1/modpack/%2/%3").arg(m_solderUrl.toString(), m_pack, m_version); auto sourceUrl = QString("%1/modpack/%2/%3").arg(m_solderUrl.toString(), m_pack, m_version);
m_filesNetJob->addNetAction(Net::Download::makeByteArray(sourceUrl, &m_response)); m_filesNetJob->addNetAction(Net::Download::makeByteArray(sourceUrl, m_response));
auto job = m_filesNetJob.get(); auto job = m_filesNetJob.get();
connect(job, &NetJob::succeeded, this, &Technic::SolderPackInstallTask::fileListSucceeded); connect(job, &NetJob::succeeded, this, &Technic::SolderPackInstallTask::fileListSucceeded);
@ -86,10 +85,10 @@ void Technic::SolderPackInstallTask::fileListSucceeded()
setStatus(tr("Downloading modpack")); setStatus(tr("Downloading modpack"));
QJsonParseError parse_error{}; QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(m_response, &parse_error); QJsonDocument doc = QJsonDocument::fromJson(*m_response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) { if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from Solder at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << "Error while parsing JSON response from Solder at " << parse_error.offset << " reason: " << parse_error.errorString();
qWarning() << m_response; qWarning() << *m_response;
return; return;
} }
auto obj = doc.object(); auto obj = doc.object();

View File

@ -40,14 +40,17 @@
#include <tasks/Task.h> #include <tasks/Task.h>
#include <QUrl> #include <QUrl>
#include <memory>
namespace Technic namespace Technic {
{ class SolderPackInstallTask : public InstanceTask {
class SolderPackInstallTask : public InstanceTask
{
Q_OBJECT Q_OBJECT
public: public:
explicit SolderPackInstallTask(shared_qobject_ptr<QNetworkAccessManager> network, const QUrl &solderUrl, const QString& pack, const QString& version, const QString &minecraftVersion); explicit SolderPackInstallTask(shared_qobject_ptr<QNetworkAccessManager> network,
const QUrl& solderUrl,
const QString& pack,
const QString& version,
const QString& minecraftVersion);
bool canAbort() const override { return true; } bool canAbort() const override { return true; }
bool abort() override; bool abort() override;
@ -75,10 +78,10 @@ namespace Technic
QString m_pack; QString m_pack;
QString m_version; QString m_version;
QString m_minecraftVersion; QString m_minecraftVersion;
QByteArray m_response; std::shared_ptr<QByteArray> m_response = std::make_shared<QByteArray>();
QTemporaryDir m_outputDir; QTemporaryDir m_outputDir;
int m_modCount; int m_modCount;
QFuture<bool> m_extractFuture; QFuture<bool> m_extractFuture;
QFutureWatcher<bool> m_extractFutureWatcher; QFutureWatcher<bool> m_extractFutureWatcher;
}; };
} } // namespace Technic

View File

@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
/* /*
* PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com> * Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
* Copyright (c) 2023 Trial97 <alexandru.tripon97@gmail.com>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -46,7 +47,7 @@ namespace Net {
*/ */
class ByteArraySink : public Sink { class ByteArraySink : public Sink {
public: public:
ByteArraySink(QByteArray* output) : m_output(output){}; ByteArraySink(std::shared_ptr<QByteArray> output) : m_output(output){};
virtual ~ByteArraySink() = default; virtual ~ByteArraySink() = default;
@ -93,6 +94,6 @@ class ByteArraySink : public Sink {
auto hasLocalData() -> bool override { return false; } auto hasLocalData() -> bool override { return false; }
private: private:
QByteArray* m_output; std::shared_ptr<QByteArray> m_output;
}; };
} // namespace Net } // namespace Net

View File

@ -41,6 +41,7 @@
#include <QDateTime> #include <QDateTime>
#include <QFileInfo> #include <QFileInfo>
#include <memory>
#include "ByteArraySink.h" #include "ByteArraySink.h"
#include "ChecksumValidator.h" #include "ChecksumValidator.h"
@ -69,7 +70,7 @@ auto Download::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Down
return dl; return dl;
} }
auto Download::makeByteArray(QUrl url, QByteArray* output, Options options) -> Download::Ptr auto Download::makeByteArray(QUrl url, std::shared_ptr<QByteArray> output, Options options) -> Download::Ptr
{ {
auto dl = makeShared<Download>(); auto dl = makeShared<Download>();
dl->m_url = url; dl->m_url = url;

View File

@ -60,7 +60,7 @@ class Download : public NetAction {
~Download() override = default; ~Download() override = default;
static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr; static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr;
static auto makeByteArray(QUrl url, QByteArray* output, Options options = Option::NoOptions) -> Download::Ptr; static auto makeByteArray(QUrl url, std::shared_ptr<QByteArray> output, Options options = Option::NoOptions) -> Download::Ptr;
static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr;
public: public:

View File

@ -39,9 +39,9 @@
#include "Upload.h" #include "Upload.h"
#include <utility> #include <utility>
#include "ByteArraySink.h"
#include "BuildConfig.h"
#include "Application.h" #include "Application.h"
#include "BuildConfig.h"
#include "ByteArraySink.h"
#include "net/Logging.h" #include "net/Logging.h"
@ -57,11 +57,13 @@ namespace Net {
return true; return true;
} }
void Upload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { void Upload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
setProgress(bytesReceived, bytesTotal); setProgress(bytesReceived, bytesTotal);
} }
void Upload::downloadError(QNetworkReply::NetworkError error) { void Upload::downloadError(QNetworkReply::NetworkError error)
{
if (error == QNetworkReply::OperationCanceledError) { if (error == QNetworkReply::OperationCanceledError) {
qCCritical(taskUploadLogC) << getUid().toString() << "Aborted " << m_url.toString(); qCCritical(taskUploadLogC) << getUid().toString() << "Aborted " << m_url.toString();
m_state = State::AbortedByUser; m_state = State::AbortedByUser;
@ -72,10 +74,12 @@ namespace Net {
} }
} }
void Upload::sslErrors(const QList<QSslError> &errors) { void Upload::sslErrors(const QList<QSslError>& errors)
{
int i = 1; int i = 1;
for (const auto& error : errors) { for (const auto& error : errors) {
qCCritical(taskUploadLogC) << getUid().toString() << "Upload" << m_url.toString() << "SSL Error #" << i << " : " << error.errorString(); qCCritical(taskUploadLogC) << getUid().toString() << "Upload" << m_url.toString() << "SSL Error #" << i << " : "
<< error.errorString();
auto cert = error.certificate(); auto cert = error.certificate();
qCCritical(taskUploadLogC) << getUid().toString() << "Certificate in question:\n" << cert.toText(); qCCritical(taskUploadLogC) << getUid().toString() << "Certificate in question:\n" << cert.toText();
i++; i++;
@ -135,7 +139,8 @@ namespace Net {
return true; return true;
} }
void Upload::downloadFinished() { void Upload::downloadFinished()
{
// handle HTTP redirection first // handle HTTP redirection first
// very unlikely for post requests, still can happen // very unlikely for post requests, still can happen
if (handleRedirect()) { if (handleRedirect()) {
@ -185,14 +190,16 @@ namespace Net {
emit succeeded(); emit succeeded();
} }
void Upload::downloadReadyRead() { void Upload::downloadReadyRead()
{
if (m_state == State::Running) { if (m_state == State::Running) {
auto data = m_reply->readAll(); auto data = m_reply->readAll();
m_state = m_sink->write(data); m_state = m_sink->write(data);
} }
} }
void Upload::executeTask() { void Upload::executeTask()
{
setStatus(tr("Uploading %1").arg(m_url.toString())); setStatus(tr("Uploading %1").arg(m_url.toString()));
if (m_state == State::AbortedByUser) { if (m_state == State::AbortedByUser) {
@ -246,11 +253,12 @@ namespace Net {
connect(rep, &QNetworkReply::readyRead, this, &Upload::downloadReadyRead); connect(rep, &QNetworkReply::readyRead, this, &Upload::downloadReadyRead);
} }
Upload::Ptr Upload::makeByteArray(QUrl url, QByteArray *output, QByteArray m_post_data) { Upload::Ptr Upload::makeByteArray(QUrl url, std::shared_ptr<QByteArray> output, QByteArray m_post_data)
{
auto up = makeShared<Upload>(); auto up = makeShared<Upload>();
up->m_url = std::move(url); up->m_url = std::move(url);
up->m_sink.reset(new ByteArraySink(output)); up->m_sink.reset(new ByteArraySink(output));
up->m_post_data = std::move(m_post_data); up->m_post_data = std::move(m_post_data);
return up; return up;
} }
} // Net } // namespace Net

View File

@ -48,7 +48,7 @@ namespace Net {
public: public:
using Ptr = shared_qobject_ptr<Upload>; using Ptr = shared_qobject_ptr<Upload>;
static Upload::Ptr makeByteArray(QUrl url, QByteArray *output, QByteArray m_post_data); static Upload::Ptr makeByteArray(QUrl url, std::shared_ptr<QByteArray> output, QByteArray m_post_data);
auto abort() -> bool override; auto abort() -> bool override;
auto canAbort() const -> bool override { return true; }; auto canAbort() const -> bool override { return true; };
@ -61,6 +61,7 @@ namespace Net {
public slots: public slots:
void executeTask() override; void executeTask() override;
private: private:
std::unique_ptr<Sink> m_sink; std::unique_ptr<Sink> m_sink;
QByteArray m_post_data; QByteArray m_post_data;
@ -68,5 +69,4 @@ namespace Net {
bool handleRedirect(); bool handleRedirect();
}; };
} // Net } // namespace Net

View File

@ -58,7 +58,7 @@ void NewsChecker::reloadNews()
qDebug() << "Reloading news."; qDebug() << "Reloading news.";
NetJob::Ptr job{ new NetJob("News RSS Feed", m_network) }; NetJob::Ptr job{ new NetJob("News RSS Feed", m_network) };
job->addNetAction(Net::Download::makeByteArray(m_feedUrl, &newsData)); job->addNetAction(Net::Download::makeByteArray(m_feedUrl, newsData));
QObject::connect(job.get(), &NetJob::succeeded, this, &NewsChecker::rssDownloadFinished); QObject::connect(job.get(), &NetJob::succeeded, this, &NewsChecker::rssDownloadFinished);
QObject::connect(job.get(), &NetJob::failed, this, &NewsChecker::rssDownloadFailed); QObject::connect(job.get(), &NetJob::failed, this, &NewsChecker::rssDownloadFailed);
m_newsNetJob.reset(job); m_newsNetJob.reset(job);
@ -79,32 +79,27 @@ void NewsChecker::rssDownloadFinished()
int errorCol = -1; int errorCol = -1;
// Parse the XML. // Parse the XML.
if (!doc.setContent(newsData, false, &errorMsg, &errorLine, &errorCol)) if (!doc.setContent(*newsData, false, &errorMsg, &errorLine, &errorCol)) {
{
QString fullErrorMsg = QString("Error parsing RSS feed XML. %1 at %2:%3.").arg(errorMsg).arg(errorLine).arg(errorCol); QString fullErrorMsg = QString("Error parsing RSS feed XML. %1 at %2:%3.").arg(errorMsg).arg(errorLine).arg(errorCol);
fail(fullErrorMsg); fail(fullErrorMsg);
newsData.clear(); newsData->clear();
return; return;
} }
newsData.clear(); newsData->clear();
} }
// If the parsing succeeded, read it. // If the parsing succeeded, read it.
QDomNodeList items = doc.elementsByTagName("entry"); QDomNodeList items = doc.elementsByTagName("entry");
m_newsEntries.clear(); m_newsEntries.clear();
for (int i = 0; i < items.length(); i++) for (int i = 0; i < items.length(); i++) {
{
QDomElement element = items.at(i).toElement(); QDomElement element = items.at(i).toElement();
NewsEntryPtr entry; NewsEntryPtr entry;
entry.reset(new NewsEntry()); entry.reset(new NewsEntry());
QString errorMsg = "An unknown error occurred."; QString errorMsg = "An unknown error occurred.";
if (NewsEntry::fromXmlElement(element, entry.get(), &errorMsg)) if (NewsEntry::fromXmlElement(element, entry.get(), &errorMsg)) {
{
qDebug() << "Loaded news entry" << entry->title; qDebug() << "Loaded news entry" << entry->title;
m_newsEntries.append(entry); m_newsEntries.append(entry);
} } else {
else
{
qWarning() << "Failed to load news entry at index" << i << ":" << errorMsg; qWarning() << "Failed to load news entry at index" << i << ":" << errorMsg;
} }
} }

View File

@ -85,7 +85,7 @@ protected: /* data */
//! True if news has been loaded. //! True if news has been loaded.
bool m_loadedNews; bool m_loadedNews;
QByteArray newsData; std::shared_ptr<QByteArray> newsData = std::make_shared<QByteArray>();
/*! /*!
* Gets the error message that was given last time the news was loaded. * Gets the error message that was given last time the news was loaded.

View File

@ -32,7 +32,7 @@ NewsDialog::~NewsDialog()
void NewsDialog::selectedArticleChanged(const QString& new_title) void NewsDialog::selectedArticleChanged(const QString& new_title)
{ {
auto const& article_entry = m_entries.constFind(new_title).value(); auto article_entry = m_entries.constFind(new_title).value();
ui->articleTitleLabel->setText(QString("<a href='%1'>%2</a>").arg(article_entry->link, new_title)); ui->articleTitleLabel->setText(QString("<a href='%1'>%2</a>").arg(article_entry->link, new_title));

View File

@ -226,7 +226,7 @@ void ModrinthManagedPackPage::parseManagedPack()
QString id = m_inst->getManagedPackID(); 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] { QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] {
QJsonParseError parse_error{}; QJsonParseError parse_error{};
@ -369,7 +369,7 @@ void FlameManagedPackPage::parseManagedPack()
QString id = m_inst->getManagedPackID(); 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] { QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] {
QJsonParseError parse_error{}; QJsonParseError parse_error{};

View File

@ -16,19 +16,15 @@
#include "AtlListModel.h" #include "AtlListModel.h"
#include <BuildConfig.h>
#include <Application.h> #include <Application.h>
#include <BuildConfig.h>
#include <Json.h> #include <Json.h>
namespace Atl { 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
{ {
@ -43,24 +39,17 @@ int ListModel::columnCount(const QModelIndex &parent) const
QVariant ListModel::data(const QModelIndex& index, int role) const QVariant ListModel::data(const QModelIndex& index, int role) const
{ {
int pos = index.row(); 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); return QString("INVALID INDEX %1").arg(pos);
} }
ATLauncher::IndexedPack pack = modpacks.at(pos); ATLauncher::IndexedPack pack = modpacks.at(pos);
if(role == Qt::DisplayRole) if (role == Qt::DisplayRole) {
{
return pack.name; return pack.name;
} } else if (role == Qt::ToolTipRole) {
else if (role == Qt::ToolTipRole)
{
return pack.name; return pack.name;
} } else if (role == Qt::DecorationRole) {
else if(role == Qt::DecorationRole) if (m_logoMap.contains(pack.safeName)) {
{
if(m_logoMap.contains(pack.safeName))
{
return (m_logoMap.value(pack.safeName)); return (m_logoMap.value(pack.safeName));
} }
auto icon = APPLICATION->getThemedIcon("atlauncher-placeholder"); auto icon = APPLICATION->getThemedIcon("atlauncher-placeholder");
@ -69,9 +58,7 @@ QVariant ListModel::data(const QModelIndex &index, int role) const
((ListModel*)this)->requestLogo(pack.safeName, url); ((ListModel*)this)->requestLogo(pack.safeName, url);
return icon; return icon;
} } else if (role == Qt::UserRole) {
else if(role == Qt::UserRole)
{
QVariant v; QVariant v;
v.setValue(pack); v.setValue(pack);
return v; return v;
@ -88,7 +75,7 @@ void ListModel::request()
auto netJob = makeShared<NetJob>("Atl::Request", APPLICATION->network()); auto netJob = makeShared<NetJob>("Atl::Request", APPLICATION->network());
auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/json/packsnew.json"); 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 = netJob;
jobPtr->start(); jobPtr->start();
@ -101,10 +88,10 @@ void ListModel::requestFinished()
jobPtr.reset(); jobPtr.reset();
QJsonParseError parse_error; QJsonParseError parse_error;
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) { if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString();
qWarning() << response; qWarning() << *response;
return; return;
} }
@ -118,19 +105,21 @@ void ListModel::requestFinished()
try { try {
ATLauncher::loadIndexedPack(pack, packObj); ATLauncher::loadIndexedPack(pack, packObj);
} } catch (const JSONValidationError& e) {
catch (const JSONValidationError &e) { qDebug() << QString::fromUtf8(*response);
qDebug() << QString::fromUtf8(response);
qWarning() << "Error while reading pack manifest from ATLauncher: " << e.cause(); qWarning() << "Error while reading pack manifest from ATLauncher: " << e.cause();
return; return;
} }
// ignore packs without a published version // ignore packs without a published version
if(pack.versions.length() == 0) continue; if (pack.versions.length() == 0)
continue;
// only display public packs (for now) // 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) // ignore "system" packs (Vanilla, Vanilla with Forge, etc)
if(pack.system) continue; if (pack.system)
continue;
newList.append(pack); newList.append(pack);
} }
@ -147,12 +136,10 @@ void ListModel::requestFailed(QString reason)
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)) if (m_logoMap.contains(logo)) {
{ callback(
callback(APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath()); APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
} } else {
else
{
requestLogo(logo, logoUrl); requestLogo(logo, logoUrl);
} }
} }
@ -177,27 +164,25 @@ void ListModel::logoLoaded(QString logo, QIcon out)
void ListModel::requestLogo(QString file, QString url) 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; return;
} }
MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(file.section(".", 0, 0))); 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)); job->addNetAction(Net::Download::makeCached(QUrl(url), entry));
auto fullPath = entry->getFullPath(); 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)); emit logoLoaded(file, QIcon(fullPath));
if(waitingCallbacks.contains(file)) if (waitingCallbacks.contains(file)) {
{
waitingCallbacks.value(file)(fullPath); 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); emit logoFailed(file);
}); });
@ -206,4 +191,4 @@ void ListModel::requestLogo(QString file, QString url)
m_loadingLogos.append(file); m_loadingLogos.append(file);
} }
} } // namespace Atl

View File

@ -18,17 +18,16 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include "net/NetJob.h"
#include <QIcon>
#include <modplatform/atlauncher/ATLPackIndex.h> #include <modplatform/atlauncher/ATLPackIndex.h>
#include <QIcon>
#include "net/NetJob.h"
namespace Atl { namespace Atl {
typedef QMap<QString, QIcon> LogoMap; typedef QMap<QString, QIcon> LogoMap;
typedef std::function<void(QString)> LogoCallback; typedef std::function<void(QString)> LogoCallback;
class ListModel : public QAbstractListModel class ListModel : public QAbstractListModel {
{
Q_OBJECT Q_OBJECT
public: public:
@ -62,7 +61,7 @@ private:
QMap<QString, LogoCallback> waitingCallbacks; QMap<QString, LogoCallback> waitingCallbacks;
NetJob::Ptr jobPtr; 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) { void AtlOptionalModListModel::useShareCode(const QString& code) {
m_jobPtr.reset(new NetJob("Atl::Request", APPLICATION->network())); m_jobPtr.reset(new NetJob("Atl::Request", APPLICATION->network()));
auto url = QString(BuildConfig.ATL_API_BASE_URL + "share-codes/" + code); 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, connect(m_jobPtr.get(), &NetJob::succeeded,
this, &AtlOptionalModListModel::shareCodeSuccess); this, &AtlOptionalModListModel::shareCodeSuccess);
@ -166,10 +166,10 @@ void AtlOptionalModListModel::shareCodeSuccess() {
m_jobPtr.reset(); m_jobPtr.reset();
QJsonParseError parse_error {}; 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) { if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString();
qWarning() << m_response; qWarning() << *m_response;
return; return;
} }
auto obj = doc.object(); auto obj = doc.object();
@ -179,7 +179,7 @@ void AtlOptionalModListModel::shareCodeSuccess() {
ATLauncher::loadShareCodeResponse(response, obj); ATLauncher::loadShareCodeResponse(response, obj);
} }
catch (const JSONValidationError& e) { catch (const JSONValidationError& e) {
qDebug() << QString::fromUtf8(m_response); qDebug() << QString::fromUtf8(*m_response);
qWarning() << "Error while reading response from ATLauncher: " << e.cause(); qWarning() << "Error while reading response from ATLauncher: " << e.cause();
return; return;
} }

View File

@ -84,7 +84,7 @@ private:
private: private:
NetJob::Ptr m_jobPtr; NetJob::Ptr m_jobPtr;
QByteArray m_response; std::shared_ptr<QByteArray> m_response = std::make_shared<QByteArray>();
ATLauncher::PackVersion m_version; ATLauncher::PackVersion m_version;
QVector<ATLauncher::VersionMod> m_mods; QVector<ATLauncher::VersionMod> m_mods;

View File

@ -44,6 +44,7 @@ class AtlUserInteractionSupportImpl : public QObject, public ATLauncher::UserInt
public: public:
AtlUserInteractionSupportImpl(QWidget* parent); AtlUserInteractionSupportImpl(QWidget* parent);
virtual ~AtlUserInteractionSupportImpl() = default;
private: private:
QString chooseVersion(Meta::VersionList::Ptr vlist, QString minecraftVersion) override; QString chooseVersion(Meta::VersionList::Ptr vlist, QString minecraftVersion) override;
@ -52,5 +53,4 @@ private:
private: private:
QWidget* m_parent; QWidget* m_parent;
}; };

View File

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

View File

@ -3,28 +3,26 @@
#include <RWStorage.h> #include <RWStorage.h>
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QSortFilterProxyModel>
#include <QThreadPool>
#include <QIcon> #include <QIcon>
#include <QStyledItemDelegate>
#include <QList> #include <QList>
#include <QMetaType>
#include <QSortFilterProxyModel>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QMetaType> #include <QStyledItemDelegate>
#include <QThreadPool>
#include <functional>
#include <net/NetJob.h> #include <net/NetJob.h>
#include <functional>
#include <modplatform/flame/FlamePackIndex.h> #include <modplatform/flame/FlamePackIndex.h>
namespace Flame { namespace Flame {
typedef QMap<QString, QIcon> LogoMap; typedef QMap<QString, QIcon> LogoMap;
typedef std::function<void(QString)> LogoCallback; typedef std::function<void(QString)> LogoCallback;
class ListModel : public QAbstractListModel class ListModel : public QAbstractListModel {
{
Q_OBJECT Q_OBJECT
public: public:
@ -64,14 +62,9 @@ private:
QString currentSearchTerm; QString currentSearchTerm;
int currentSort = 0; int currentSort = 0;
int nextSearchOffset = 0; int nextSearchOffset = 0;
enum SearchState { enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None;
None,
CanPossiblyFetchMore,
ResetRequested,
Finished
} searchState = None;
NetJob::Ptr jobPtr; 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) { if (current.versionsLoaded == false) {
qDebug() << "Loading flame modpack versions"; qDebug() << "Loading flame modpack versions";
auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network()); 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; int addonId = current.addonId;
netJob->addNetAction(Net::Download::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response)); 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(); suggestCurrent();
}); });
QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); });
netJob->deleteLater();
delete response;
});
netJob->start(); netJob->start();
} else { } else {
for (auto version : current.versions) { for (auto version : current.versions) {

View File

@ -38,11 +38,11 @@
#include "net/HttpMetaCache.h" #include "net/HttpMetaCache.h"
#include "net/NetJob.h" #include "net/NetJob.h"
#include "StringUtils.h"
#include <Version.h> #include <Version.h>
#include "StringUtils.h"
#include <QtMath>
#include <QLabel> #include <QLabel>
#include <QtMath>
#include <RWStorage.h> #include <RWStorage.h>
@ -102,18 +102,13 @@ FilterModel::Sorting FilterModel::getCurrentSorting()
return currentSorting; return currentSorting;
} }
ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) ListModel::ListModel(QObject* parent) : QAbstractListModel(parent) {}
{
}
ListModel::~ListModel() ListModel::~ListModel() {}
{
}
QString ListModel::translatePackType(PackType type) const QString ListModel::translatePackType(PackType type) const
{ {
switch(type) switch (type) {
{
case PackType::Public: case PackType::Public:
return tr("Public Modpack"); return tr("Public Modpack");
case PackType::ThirdParty: case PackType::ThirdParty:
@ -138,54 +133,38 @@ int ListModel::columnCount(const QModelIndex &parent) const
QVariant ListModel::data(const QModelIndex& index, int role) const QVariant ListModel::data(const QModelIndex& index, int role) const
{ {
int pos = index.row(); 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); return QString("INVALID INDEX %1").arg(pos);
} }
Modpack pack = modpacks.at(pos); Modpack pack = modpacks.at(pos);
if(role == Qt::DisplayRole) if (role == Qt::DisplayRole) {
{
return pack.name + "\n" + translatePackType(pack.type); return pack.name + "\n" + translatePackType(pack.type);
} } else if (role == Qt::ToolTipRole) {
else if (role == Qt::ToolTipRole) if (pack.description.length() > 100) {
{
if(pack.description.length() > 100)
{
// some magic to prevent to long tooltips and replace html linebreaks // some magic to prevent to long tooltips and replace html linebreaks
QString edit = pack.description.left(97); QString edit = pack.description.left(97);
edit = edit.left(edit.lastIndexOf("<br>")).left(edit.lastIndexOf(" ")).append("..."); edit = edit.left(edit.lastIndexOf("<br>")).left(edit.lastIndexOf(" ")).append("...");
return edit; return edit;
} }
return pack.description; return pack.description;
} } else if (role == Qt::DecorationRole) {
else if(role == Qt::DecorationRole) if (m_logoMap.contains(pack.logo)) {
{
if(m_logoMap.contains(pack.logo))
{
return (m_logoMap.value(pack.logo)); return (m_logoMap.value(pack.logo));
} }
QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder");
((ListModel*)this)->requestLogo(pack.logo); ((ListModel*)this)->requestLogo(pack.logo);
return icon; return icon;
} } else if (role == Qt::ForegroundRole) {
else if(role == Qt::ForegroundRole) if (pack.broken) {
{
if(pack.broken)
{
// FIXME: Hardcoded color // FIXME: Hardcoded color
return QColor(255, 0, 50); return QColor(255, 0, 50);
} } else if (pack.bugged) {
else if(pack.bugged)
{
// FIXME: Hardcoded color // FIXME: Hardcoded color
// bugged pack, currently only indicates bugged xml // bugged pack, currently only indicates bugged xml
return QColor(244, 229, 66); return QColor(244, 229, 66);
} }
} } else if (role == Qt::UserRole) {
else if(role == Qt::UserRole)
{
QVariant v; QVariant v;
v.setValue(pack); v.setValue(pack);
return v; return v;
@ -222,8 +201,7 @@ Modpack ListModel::at(int row)
void ListModel::remove(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; qWarning() << "Attempt to remove FTB modpacks with invalid row" << row;
return; return;
} }
@ -247,8 +225,7 @@ void ListModel::logoFailed(QString logo)
void ListModel::requestLogo(QString file) void ListModel::requestLogo(QString file)
{ {
if(m_loadingLogos.contains(file) || m_failedLogos.contains(file)) if (m_loadingLogos.contains(file) || m_failedLogos.contains(file)) {
{
return; return;
} }
@ -257,17 +234,16 @@ void ListModel::requestLogo(QString file)
job->addNetAction(Net::Download::makeCached(QUrl(QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry)); job->addNetAction(Net::Download::makeCached(QUrl(QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry));
auto fullPath = entry->getFullPath(); 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)); emit logoLoaded(file, QIcon(fullPath));
if(waitingCallbacks.contains(file)) if (waitingCallbacks.contains(file)) {
{
waitingCallbacks.value(file)(fullPath); 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); emit logoFailed(file);
}); });
@ -278,12 +254,9 @@ void ListModel::requestLogo(QString 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()); callback(APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
} } else {
else
{
requestLogo(logo); requestLogo(logo);
} }
} }
@ -293,4 +266,4 @@ Qt::ItemFlags ListModel::flags(const QModelIndex &index) const
return QAbstractListModel::flags(index); return QAbstractListModel::flags(index);
} }
} } // namespace LegacyFTB

View File

@ -142,16 +142,16 @@ void ModpackListModel::performPaginatedSearch()
.arg(currentSearchTerm) .arg(currentSearchTerm)
.arg(currentSort); .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] { QObject::connect(netJob.get(), &NetJob::succeeded, this, [this] {
QJsonParseError parse_error_all{}; 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) { if (parse_error_all.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from " << debugName() << " at " << parse_error_all.offset qWarning() << "Error while parsing JSON response from " << debugName() << " at " << parse_error_all.offset
<< " reason: " << parse_error_all.errorString(); << " reason: " << parse_error_all.errorString();
qWarning() << m_all_response; qWarning() << *m_all_response;
return; return;
} }

View File

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

View File

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

View File

@ -44,8 +44,7 @@ namespace Technic {
typedef std::function<void(QString)> LogoCallback; typedef std::function<void(QString)> LogoCallback;
class ListModel : public QAbstractListModel class ListModel : public QAbstractListModel {
{
Q_OBJECT Q_OBJECT
public: public:
@ -78,17 +77,13 @@ private:
QMap<QString, LogoCallback> waitingCallbacks; QMap<QString, LogoCallback> waitingCallbacks;
QString currentSearchTerm; QString currentSearchTerm;
enum SearchState { enum SearchState { None, ResetRequested, Finished } searchState = None;
None,
ResetRequested,
Finished
} searchState = None;
enum SearchMode { enum SearchMode {
List, List,
Single, Single,
} searchMode = List; } searchMode = List;
NetJob::Ptr jobPtr; 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()); auto netJob = makeShared<NetJob>(QString("Technic::PackMeta(%1)").arg(current.name), APPLICATION->network());
QString slug = current.slug; 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] QObject::connect(netJob.get(), &NetJob::succeeded, this, [this, slug]
{ {
jobPtr.reset(); jobPtr.reset();
@ -154,7 +154,7 @@ void TechnicPage::suggestCurrent()
} }
QJsonParseError parse_error {}; QJsonParseError parse_error {};
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
QJsonObject obj = doc.object(); QJsonObject obj = doc.object();
if(parse_error.error != QJsonParseError::NoError) 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 netJob = makeShared<NetJob>(QString("Technic::SolderMeta(%1)").arg(current.name), APPLICATION->network());
auto url = QString("%1/modpack/%2").arg(current.url, current.slug); 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); QObject::connect(netJob.get(), &NetJob::succeeded, this, &TechnicPage::onSolderLoaded);
@ -292,10 +292,10 @@ void TechnicPage::onSolderLoaded() {
current.versions.clear(); current.versions.clear();
QJsonParseError parse_error{}; QJsonParseError parse_error{};
auto doc = QJsonDocument::fromJson(response, &parse_error); auto doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) { if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response from Solder at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << "Error while parsing JSON response from Solder at " << parse_error.offset << " reason: " << parse_error.errorString();
qWarning() << response; qWarning() << *response;
fallback(); fallback();
return; return;
} }
@ -304,8 +304,7 @@ void TechnicPage::onSolderLoaded() {
TechnicSolder::Pack pack; TechnicSolder::Pack pack;
try { try {
TechnicSolder::loadPack(pack, obj); TechnicSolder::loadPack(pack, obj);
} } catch (const JSONValidationError& err) {
catch (const JSONValidationError& err) {
qCritical() << "Couldn't parse Solder pack metadata:" << err.cause(); qCritical() << "Couldn't parse Solder pack metadata:" << err.cause();
fallback(); fallback();
return; return;

View File

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