Fixed leaks

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97 2023-06-18 23:27:26 +03:00
parent 147366bc0a
commit 0161520b33
No known key found for this signature in database
GPG Key ID: 55EF5DA53DB36318
10 changed files with 164 additions and 229 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::getResults, [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::getResults, [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);
} }
} }

View File

@ -58,8 +58,7 @@ 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.
*/ */
@ -75,23 +74,27 @@ 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;
protected: protected:
virtual void executeTask() override; virtual void executeTask() override;
private slots: private slots:
void onDownloadSucceeded(); void onDownloadSucceeded();
void onDownloadFailed(QString reason); void onDownloadFailed(QString reason);
void onDownloadAborted(); void onDownloadAborted();
@ -99,7 +102,7 @@ private slots:
void onModsDownloaded(); void onModsDownloaded();
void onModsExtracted(); void onModsExtracted();
private: private:
QString getDirForModType(ModType type, QString raw); QString getDirForModType(ModType type, QString raw);
QString getVersionForLoader(QString uid); QString getVersionForLoader(QString uid);
QString detectLibrary(VersionLibrary library); QString detectLibrary(VersionLibrary library);
@ -111,15 +114,13 @@ 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:
UserInteractionSupport *m_support; UserInteractionSupport* m_support;
bool abortable = false; bool abortable = false;
@ -146,7 +147,6 @@ private:
QFuture<bool> m_modExtractFuture; QFuture<bool> m_modExtractFuture;
QFutureWatcher<bool> m_modExtractFutureWatcher; QFutureWatcher<bool> m_modExtractFutureWatcher;
}; };
} } // namespace ATLauncher

View File

@ -71,6 +71,7 @@ void ModrinthHasher::executeTask()
emitFailed("Empty hash!"); emitFailed("Empty hash!");
} else { } else {
emitSucceeded(); emitSucceeded();
emit getResults(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

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <qtmetamacros.h>
#include <QString> #include <QString>
#include "modplatform/ModIndex.h" #include "modplatform/ModIndex.h"
@ -8,6 +9,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 +23,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 getResults(QString hash);
protected: protected:
QString m_hash; QString m_hash;
QString m_path; QString m_path;
@ -48,6 +53,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

@ -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::getResults, [&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);

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

@ -16,62 +16,49 @@
#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
{ {
return parent.isValid() ? 0 : modpacks.size(); return parent.isValid() ? 0 : modpacks.size();
} }
int ListModel::columnCount(const QModelIndex &parent) const int ListModel::columnCount(const QModelIndex& parent) const
{ {
return parent.isValid() ? 0 : 1; return parent.isValid() ? 0 : 1;
} }
QVariant ListModel::data(const QModelIndex &index, int role) const QVariant ListModel::data(const QModelIndex& index, int role) const
{ {
int pos = index.row(); 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");
auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1.png").arg(pack.safeName.toLower()); auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1.png").arg(pack.safeName.toLower());
((ListModel *)this)->requestLogo(pack.safeName, url); ((ListModel*)this)->requestLogo(pack.safeName, url);
return icon; 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;
@ -102,7 +89,7 @@ void ListModel::requestFinished()
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;
@ -111,26 +98,28 @@ void ListModel::requestFinished()
QList<ATLauncher::IndexedPack> newList; QList<ATLauncher::IndexedPack> newList;
auto packs = doc.array(); auto packs = doc.array();
for(auto packRaw : packs) { for (auto packRaw : packs) {
auto packObj = packRaw.toObject(); auto packObj = packRaw.toObject();
ATLauncher::IndexedPack pack; ATLauncher::IndexedPack pack;
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);
} }
@ -145,14 +134,12 @@ void ListModel::requestFailed(QString reason)
jobPtr.reset(); jobPtr.reset();
} }
void ListModel::getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback) void ListModel::getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback)
{ {
if(m_logoMap.contains(logo)) 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);
} }
} }
@ -168,36 +155,34 @@ void ListModel::logoLoaded(QString logo, QIcon out)
m_loadingLogos.removeAll(logo); m_loadingLogos.removeAll(logo);
m_logoMap.insert(logo, out); m_logoMap.insert(logo, out);
for(int i = 0; i < modpacks.size(); i++) { for (int i = 0; i < modpacks.size(); i++) {
if(modpacks[i].safeName == logo) { if (modpacks[i].safeName == logo) {
emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole}); emit dataChanged(createIndex(i, 0), createIndex(i, 0), { Qt::DecorationRole });
} }
} }
} }
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

@ -42,15 +42,15 @@
class AtlUserInteractionSupportImpl : public QObject, public ATLauncher::UserInteractionSupport { class AtlUserInteractionSupportImpl : public QObject, public ATLauncher::UserInteractionSupport {
Q_OBJECT Q_OBJECT
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;
std::optional<QVector<QString>> chooseOptionalMods(ATLauncher::PackVersion version, QVector<ATLauncher::VersionMod> mods) override; std::optional<QVector<QString>> chooseOptionalMods(ATLauncher::PackVersion version, QVector<ATLauncher::VersionMod> mods) override;
void displayMessage(QString message) override; void displayMessage(QString message) override;
private: private:
QWidget* m_parent; QWidget* m_parent;
}; };

View File

@ -35,14 +35,15 @@
#include "ListModel.h" #include "ListModel.h"
#include "Application.h" #include "Application.h"
#include "QObjectPtr.h"
#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>
@ -50,33 +51,33 @@
namespace LegacyFTB { namespace LegacyFTB {
FilterModel::FilterModel(QObject *parent) : QSortFilterProxyModel(parent) FilterModel::FilterModel(QObject* parent) : QSortFilterProxyModel(parent)
{ {
currentSorting = Sorting::ByGameVersion; currentSorting = Sorting::ByGameVersion;
sortings.insert(tr("Sort by Name"), Sorting::ByName); sortings.insert(tr("Sort by Name"), Sorting::ByName);
sortings.insert(tr("Sort by Game Version"), Sorting::ByGameVersion); sortings.insert(tr("Sort by Game Version"), Sorting::ByGameVersion);
} }
bool FilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const bool FilterModel::lessThan(const QModelIndex& left, const QModelIndex& right) const
{ {
Modpack leftPack = sourceModel()->data(left, Qt::UserRole).value<Modpack>(); Modpack leftPack = sourceModel()->data(left, Qt::UserRole).value<Modpack>();
Modpack rightPack = sourceModel()->data(right, Qt::UserRole).value<Modpack>(); Modpack rightPack = sourceModel()->data(right, Qt::UserRole).value<Modpack>();
if(currentSorting == Sorting::ByGameVersion) { if (currentSorting == Sorting::ByGameVersion) {
Version lv(leftPack.mcVersion); Version lv(leftPack.mcVersion);
Version rv(rightPack.mcVersion); Version rv(rightPack.mcVersion);
return lv < rv; return lv < rv;
} else if(currentSorting == Sorting::ByName) { } else if (currentSorting == Sorting::ByName) {
return StringUtils::naturalCompare(leftPack.name, rightPack.name, Qt::CaseSensitive) >= 0; return StringUtils::naturalCompare(leftPack.name, rightPack.name, Qt::CaseSensitive) >= 0;
} }
//UHM, some inavlid value set?! // UHM, some inavlid value set?!
qWarning() << "Invalid sorting set!"; qWarning() << "Invalid sorting set!";
return true; return true;
} }
bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{ {
return true; return true;
} }
@ -102,18 +103,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:
@ -125,67 +121,51 @@ QString ListModel::translatePackType(PackType type) const
return QString(); return QString();
} }
int ListModel::rowCount(const QModelIndex &parent) const int ListModel::rowCount(const QModelIndex& parent) const
{ {
return parent.isValid() ? 0 : modpacks.size(); return parent.isValid() ? 0 : modpacks.size();
} }
int ListModel::columnCount(const QModelIndex &parent) const int ListModel::columnCount(const QModelIndex& parent) const
{ {
return parent.isValid() ? 0 : 1; return parent.isValid() ? 0 : 1;
} }
QVariant ListModel::data(const QModelIndex &index, int role) const QVariant ListModel::data(const QModelIndex& index, int role) const
{ {
int pos = index.row(); 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) {
{ // some magic to prevent to long tooltips and replace html linebreaks
if(pack.description.length() > 100)
{
//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) {
{ // FIXME: Hardcoded color
if(pack.broken)
{
//FIXME: Hardcoded color
return QColor(255, 0, 50); return QColor(255, 0, 50);
} } else if (pack.bugged) {
else if(pack.bugged) // FIXME: Hardcoded color
{ // bugged pack, currently only indicates bugged xml
//FIXME: Hardcoded color
//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 +202,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,27 +226,25 @@ 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;
} }
MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(file.section(".", 0, 0))); MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(file.section(".", 0, 0)));
NetJob *job = new NetJob(QString("FTB Icon Download for %1").arg(file), APPLICATION->network()); NetJob* job = new NetJob(QString("FTB Icon Download for %1").arg(file), APPLICATION->network());
job->addNetAction(Net::Download::makeCached(QUrl(QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry)); 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);
}); });
@ -276,21 +253,18 @@ void ListModel::requestLogo(QString file)
m_loadingLogos.append(file); m_loadingLogos.append(file);
} }
void ListModel::getLogo(const QString &logo, LogoCallback callback) void ListModel::getLogo(const QString& logo, LogoCallback callback)
{ {
if(m_logoMap.contains(logo)) if (m_logoMap.contains(logo)) {
{
callback(APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath()); callback(APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
} } else {
else
{
requestLogo(logo); requestLogo(logo);
} }
} }
Qt::ItemFlags ListModel::flags(const QModelIndex &index) const Qt::ItemFlags ListModel::flags(const QModelIndex& index) const
{ {
return QAbstractListModel::flags(index); return QAbstractListModel::flags(index);
} }
} } // namespace LegacyFTB

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;
@ -92,16 +81,15 @@ int Technic::ListModel::rowCount(const QModelIndex& parent) const
void Technic::ListModel::searchWithTerm(const QString& term) void Technic::ListModel::searchWithTerm(const QString& term)
{ {
if(currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull()) { if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull()) {
return; return;
} }
currentSearchTerm = term; currentSearchTerm = term;
if(jobPtr) { if (jobPtr) {
jobPtr->abort(); jobPtr->abort();
searchState = ResetRequested; searchState = ResetRequested;
return; return;
} } else {
else {
beginResetModel(); beginResetModel();
modpacks.clear(); modpacks.clear();
endResetModel(); endResetModel();
@ -115,23 +103,17 @@ 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));
@ -161,7 +143,7 @@ void Technic::ListModel::searchRequestFinished()
switch (searchMode) { switch (searchMode) {
case List: { case List: {
auto objs = Json::requireArray(root, "modpacks"); auto objs = Json::requireArray(root, "modpacks");
for (auto technicPack: objs) { for (auto technicPack : objs) {
Modpack pack; Modpack pack;
auto technicPackObject = Json::requireObject(technicPack); auto technicPackObject = Json::requireObject(technicPack);
pack.name = Json::requireString(technicPackObject, "name"); pack.name = Json::requireString(technicPackObject, "name");
@ -170,11 +152,10 @@ void Technic::ListModel::searchRequestFinished()
continue; continue;
auto rawURL = Json::ensureString(technicPackObject, "iconUrl", "null"); auto rawURL = Json::ensureString(technicPackObject, "iconUrl", "null");
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,10 +190,8 @@ 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;
} }
searchState = Finished; searchState = Finished;
@ -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,30 +218,24 @@ 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);
}); });