aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--launcher/InstanceCreationTask.h2
-rw-r--r--launcher/InstanceImportTask.cpp28
-rw-r--r--launcher/minecraft/MinecraftInstance.cpp30
-rw-r--r--launcher/minecraft/MinecraftInstance.h16
-rw-r--r--launcher/minecraft/WorldList.cpp2
-rw-r--r--launcher/minecraft/WorldList.h4
-rw-r--r--launcher/minecraft/mod/ModFolderModel.cpp2
-rw-r--r--launcher/minecraft/mod/ModFolderModel.h2
-rw-r--r--launcher/minecraft/mod/ResourceFolderModel.cpp2
-rw-r--r--launcher/minecraft/mod/ResourceFolderModel.h4
-rw-r--r--launcher/minecraft/mod/ResourcePackFolderModel.cpp2
-rw-r--r--launcher/minecraft/mod/ResourcePackFolderModel.h2
-rw-r--r--launcher/minecraft/mod/ShaderPackFolderModel.h2
-rw-r--r--launcher/minecraft/mod/TexturePackFolderModel.cpp2
-rw-r--r--launcher/minecraft/mod/TexturePackFolderModel.h2
-rw-r--r--launcher/modplatform/ModIndex.h3
-rw-r--r--launcher/modplatform/flame/FileResolvingTask.cpp111
-rw-r--r--launcher/modplatform/flame/FileResolvingTask.h36
-rw-r--r--launcher/modplatform/flame/FlameAPI.cpp41
-rw-r--r--launcher/modplatform/flame/FlameInstanceCreationTask.cpp1
-rw-r--r--launcher/modplatform/helpers/NetworkResourceAPI.cpp12
-rw-r--r--launcher/net/Download.cpp5
-rw-r--r--launcher/tasks/ConcurrentTask.cpp27
-rw-r--r--launcher/tasks/Task.cpp2
-rw-r--r--launcher/tasks/Task.h14
-rw-r--r--launcher/ui/dialogs/NewInstanceDialog.cpp2
-rw-r--r--launcher/ui/dialogs/ResourceDownloadDialog.cpp2
-rw-r--r--launcher/ui/pages/instance/ManagedPackPage.cpp39
-rw-r--r--launcher/ui/pages/instance/VersionPage.cpp2
-rw-r--r--launcher/ui/pages/modplatform/ModModel.cpp4
-rw-r--r--launcher/ui/pages/modplatform/ModPage.h2
-rw-r--r--launcher/ui/pages/modplatform/ResourceModel.cpp31
-rw-r--r--launcher/ui/pages/modplatform/ResourceModel.h2
-rw-r--r--launcher/ui/pages/modplatform/ResourcePackModel.cpp4
-rw-r--r--launcher/ui/pages/modplatform/ResourcePackPage.h2
-rw-r--r--launcher/ui/pages/modplatform/ResourcePage.cpp2
-rw-r--r--launcher/ui/pages/modplatform/ShaderPackModel.cpp4
-rw-r--r--launcher/ui/pages/modplatform/ShaderPackPage.h2
-rw-r--r--launcher/ui/widgets/PageContainer.cpp4
-rw-r--r--libraries/katabasis/src/Reply.cpp2
-rw-r--r--tests/ResourceFolderModel_test.cpp17
-rw-r--r--tests/ResourceModel_test.cpp6
42 files changed, 283 insertions, 198 deletions
diff --git a/launcher/InstanceCreationTask.h b/launcher/InstanceCreationTask.h
index 03ee1a7a..380fdf8a 100644
--- a/launcher/InstanceCreationTask.h
+++ b/launcher/InstanceCreationTask.h
@@ -34,7 +34,7 @@ class InstanceCreationTask : public InstanceTask {
QString getError() const { return m_error_message; }
protected:
- void setError(QString message) { m_error_message = message; };
+ void setError(const QString& message) { m_error_message = message; };
protected:
bool m_abort = false;
diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp
index 8a48873e..352848f0 100644
--- a/launcher/InstanceImportTask.cpp
+++ b/launcher/InstanceImportTask.cpp
@@ -41,6 +41,7 @@
#include "MMCZip.h"
#include "NullInstance.h"
+#include "QObjectPtr.h"
#include "icons/IconList.h"
#include "icons/IconUtils.h"
@@ -260,7 +261,7 @@ void InstanceImportTask::extractFinished()
void InstanceImportTask::processFlame()
{
- FlameCreationTask* inst_creation_task = nullptr;
+ shared_qobject_ptr<FlameCreationTask> inst_creation_task = nullptr;
if (!m_extra_info.isEmpty()) {
auto pack_id_it = m_extra_info.constFind("pack_id");
Q_ASSERT(pack_id_it != m_extra_info.constEnd());
@@ -275,10 +276,10 @@ void InstanceImportTask::processFlame()
if (original_instance_id_it != m_extra_info.constEnd())
original_instance_id = original_instance_id_it.value();
- inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id);
+ inst_creation_task = makeShared<FlameCreationTask>(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id);
} else {
// FIXME: Find a way to get IDs in directly imported ZIPs
- inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent, {}, {});
+ inst_creation_task = makeShared<FlameCreationTask>(m_stagingPath, m_globalSettings, m_parent, QString(), QString());
}
inst_creation_task->setName(*this);
@@ -286,20 +287,19 @@ void InstanceImportTask::processFlame()
inst_creation_task->setGroup(m_instGroup);
inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
- connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] {
+ connect(inst_creation_task.get(), &Task::succeeded, this, [this, inst_creation_task] {
setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID());
emitSucceeded();
});
- connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
- connect(inst_creation_task, &Task::progress, this, &InstanceImportTask::setProgress);
- connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress);
- connect(inst_creation_task, &Task::status, this, &InstanceImportTask::setStatus);
- connect(inst_creation_task, &Task::details, this, &InstanceImportTask::setDetails);
- connect(inst_creation_task, &Task::finished, inst_creation_task, &InstanceCreationTask::deleteLater);
-
- connect(this, &Task::aborted, inst_creation_task, &InstanceCreationTask::abort);
- connect(inst_creation_task, &Task::aborted, this, &Task::abort);
- connect(inst_creation_task, &Task::abortStatusChanged, this, &Task::setAbortable);
+ connect(inst_creation_task.get(), &Task::failed, this, &InstanceImportTask::emitFailed);
+ connect(inst_creation_task.get(), &Task::progress, this, &InstanceImportTask::setProgress);
+ connect(inst_creation_task.get(), &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress);
+ connect(inst_creation_task.get(), &Task::status, this, &InstanceImportTask::setStatus);
+ connect(inst_creation_task.get(), &Task::details, this, &InstanceImportTask::setDetails);
+
+ connect(this, &Task::aborted, inst_creation_task.get(), &InstanceCreationTask::abort);
+ connect(inst_creation_task.get(), &Task::aborted, this, &Task::abort);
+ connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable);
inst_creation_task->start();
}
diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp
index 35bef05e..2c624a36 100644
--- a/launcher/minecraft/MinecraftInstance.cpp
+++ b/launcher/minecraft/MinecraftInstance.cpp
@@ -1109,79 +1109,79 @@ JavaVersion MinecraftInstance::getJavaVersion()
return JavaVersion(settings()->get("JavaVersion").toString());
}
-std::shared_ptr<ModFolderModel> MinecraftInstance::loaderModList() const
+std::shared_ptr<ModFolderModel> MinecraftInstance::loaderModList()
{
if (!m_loader_mod_list)
{
bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
- m_loader_mod_list.reset(new ModFolderModel(modsRoot(), shared_from_this(), is_indexed));
+ m_loader_mod_list.reset(new ModFolderModel(modsRoot(), this, is_indexed));
m_loader_mod_list->disableInteraction(isRunning());
connect(this, &BaseInstance::runningStatusChanged, m_loader_mod_list.get(), &ModFolderModel::disableInteraction);
}
return m_loader_mod_list;
}
-std::shared_ptr<ModFolderModel> MinecraftInstance::coreModList() const
+std::shared_ptr<ModFolderModel> MinecraftInstance::coreModList()
{
if (!m_core_mod_list)
{
bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
- m_core_mod_list.reset(new ModFolderModel(coreModsDir(), shared_from_this(), is_indexed));
+ m_core_mod_list.reset(new ModFolderModel(coreModsDir(), this, is_indexed));
m_core_mod_list->disableInteraction(isRunning());
connect(this, &BaseInstance::runningStatusChanged, m_core_mod_list.get(), &ModFolderModel::disableInteraction);
}
return m_core_mod_list;
}
-std::shared_ptr<ModFolderModel> MinecraftInstance::nilModList() const
+std::shared_ptr<ModFolderModel> MinecraftInstance::nilModList()
{
if (!m_nil_mod_list)
{
bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
- m_nil_mod_list.reset(new ModFolderModel(nilModsDir(), shared_from_this(), is_indexed, false));
+ m_nil_mod_list.reset(new ModFolderModel(nilModsDir(), this, is_indexed, false));
m_nil_mod_list->disableInteraction(isRunning());
connect(this, &BaseInstance::runningStatusChanged, m_nil_mod_list.get(), &ModFolderModel::disableInteraction);
}
return m_nil_mod_list;
}
-std::shared_ptr<ResourcePackFolderModel> MinecraftInstance::resourcePackList() const
+std::shared_ptr<ResourcePackFolderModel> MinecraftInstance::resourcePackList()
{
if (!m_resource_pack_list)
{
- m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir(), shared_from_this()));
+ m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir(), this));
}
return m_resource_pack_list;
}
-std::shared_ptr<TexturePackFolderModel> MinecraftInstance::texturePackList() const
+std::shared_ptr<TexturePackFolderModel> MinecraftInstance::texturePackList()
{
if (!m_texture_pack_list)
{
- m_texture_pack_list.reset(new TexturePackFolderModel(texturePacksDir(), shared_from_this()));
+ m_texture_pack_list.reset(new TexturePackFolderModel(texturePacksDir(), this));
}
return m_texture_pack_list;
}
-std::shared_ptr<ShaderPackFolderModel> MinecraftInstance::shaderPackList() const
+std::shared_ptr<ShaderPackFolderModel> MinecraftInstance::shaderPackList()
{
if (!m_shader_pack_list)
{
- m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir(), shared_from_this()));
+ m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir(), this));
}
return m_shader_pack_list;
}
-std::shared_ptr<WorldList> MinecraftInstance::worldList() const
+std::shared_ptr<WorldList> MinecraftInstance::worldList()
{
if (!m_world_list)
{
- m_world_list.reset(new WorldList(worldDir(), shared_from_this()));
+ m_world_list.reset(new WorldList(worldDir(), this));
}
return m_world_list;
}
-std::shared_ptr<GameOptions> MinecraftInstance::gameOptionsModel() const
+std::shared_ptr<GameOptions> MinecraftInstance::gameOptionsModel()
{
if (!m_game_options)
{
diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h
index a75fa481..068b3008 100644
--- a/launcher/minecraft/MinecraftInstance.h
+++ b/launcher/minecraft/MinecraftInstance.h
@@ -115,14 +115,14 @@ public:
std::shared_ptr<PackProfile> getPackProfile() const;
////// Mod Lists //////
- std::shared_ptr<ModFolderModel> loaderModList() const;
- std::shared_ptr<ModFolderModel> coreModList() const;
- std::shared_ptr<ModFolderModel> nilModList() const;
- std::shared_ptr<ResourcePackFolderModel> resourcePackList() const;
- std::shared_ptr<TexturePackFolderModel> texturePackList() const;
- std::shared_ptr<ShaderPackFolderModel> shaderPackList() const;
- std::shared_ptr<WorldList> worldList() const;
- std::shared_ptr<GameOptions> gameOptionsModel() const;
+ std::shared_ptr<ModFolderModel> loaderModList();
+ std::shared_ptr<ModFolderModel> coreModList();
+ std::shared_ptr<ModFolderModel> nilModList();
+ std::shared_ptr<ResourcePackFolderModel> resourcePackList();
+ std::shared_ptr<TexturePackFolderModel> texturePackList();
+ std::shared_ptr<ShaderPackFolderModel> shaderPackList();
+ std::shared_ptr<WorldList> worldList();
+ std::shared_ptr<GameOptions> gameOptionsModel();
////// Launch stuff //////
Task::Ptr createUpdateTask(Net::Mode mode) override;
diff --git a/launcher/minecraft/WorldList.cpp b/launcher/minecraft/WorldList.cpp
index df6b4ecc..0feee299 100644
--- a/launcher/minecraft/WorldList.cpp
+++ b/launcher/minecraft/WorldList.cpp
@@ -45,7 +45,7 @@
#include <QFileSystemWatcher>
#include <QDebug>
-WorldList::WorldList(const QString &dir, std::shared_ptr<const BaseInstance> instance)
+WorldList::WorldList(const QString &dir, BaseInstance* instance)
: QAbstractListModel(), m_instance(instance), m_dir(dir)
{
FS::ensureFolderPathExists(m_dir.absolutePath());
diff --git a/launcher/minecraft/WorldList.h b/launcher/minecraft/WorldList.h
index 10fb4e3c..96b64193 100644
--- a/launcher/minecraft/WorldList.h
+++ b/launcher/minecraft/WorldList.h
@@ -50,7 +50,7 @@ public:
IconFileRole
};
- WorldList(const QString &dir, std::shared_ptr<const BaseInstance> instance);
+ WorldList(const QString &dir, BaseInstance* instance);
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
@@ -128,7 +128,7 @@ signals:
void changed();
protected:
- std::shared_ptr<const BaseInstance> m_instance;
+ BaseInstance* m_instance;
QFileSystemWatcher *m_watcher;
bool is_watching;
QDir m_dir;
diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp
index 6ae25d33..5e3b31e0 100644
--- a/launcher/minecraft/mod/ModFolderModel.cpp
+++ b/launcher/minecraft/mod/ModFolderModel.cpp
@@ -54,7 +54,7 @@
#include "minecraft/mod/tasks/ModFolderLoadTask.h"
#include "modplatform/ModIndex.h"
-ModFolderModel::ModFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance, bool is_indexed, bool create_dir)
+ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool is_indexed, bool create_dir)
: ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed)
{
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER };
diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h
index 46f5087f..d337fe29 100644
--- a/launcher/minecraft/mod/ModFolderModel.h
+++ b/launcher/minecraft/mod/ModFolderModel.h
@@ -75,7 +75,7 @@ public:
Enable,
Toggle
};
- ModFolderModel(const QString &dir, std::shared_ptr<const BaseInstance> instance, bool is_indexed = false, bool create_dir = true);
+ ModFolderModel(const QString &dir, BaseInstance* instance, bool is_indexed = false, bool create_dir = true);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp
index e1973468..d2d875e4 100644
--- a/launcher/minecraft/mod/ResourceFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourceFolderModel.cpp
@@ -16,7 +16,7 @@
#include "tasks/Task.h"
-ResourceFolderModel::ResourceFolderModel(QDir dir, std::shared_ptr<const BaseInstance> instance, QObject* parent, bool create_dir)
+ResourceFolderModel::ResourceFolderModel(QDir dir, BaseInstance* instance, QObject* parent, bool create_dir)
: QAbstractListModel(parent), m_dir(dir), m_instance(instance), m_watcher(this)
{
if (create_dir) {
diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h
index fdf5f331..0a35e1bc 100644
--- a/launcher/minecraft/mod/ResourceFolderModel.h
+++ b/launcher/minecraft/mod/ResourceFolderModel.h
@@ -26,7 +26,7 @@ class QSortFilterProxyModel;
class ResourceFolderModel : public QAbstractListModel {
Q_OBJECT
public:
- ResourceFolderModel(QDir, std::shared_ptr<const BaseInstance>, QObject* parent = nullptr, bool create_dir = true);
+ ResourceFolderModel(QDir, BaseInstance* instance, QObject* parent = nullptr, bool create_dir = true);
~ResourceFolderModel() override;
/** Starts watching the paths for changes.
@@ -191,7 +191,7 @@ class ResourceFolderModel : public QAbstractListModel {
bool m_can_interact = true;
QDir m_dir;
- std::shared_ptr<const BaseInstance> m_instance;
+ BaseInstance* m_instance;
QFileSystemWatcher m_watcher;
bool m_is_watching = false;
diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
index 6eba4e2e..c12d1f23 100644
--- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
@@ -45,7 +45,7 @@
#include "minecraft/mod/tasks/BasicFolderLoadTask.h"
#include "minecraft/mod/tasks/LocalResourcePackParseTask.h"
-ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
+ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstance* instance)
: ResourceFolderModel(QDir(dir), instance)
{
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE };
diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.h b/launcher/minecraft/mod/ResourcePackFolderModel.h
index 66d5a074..db4b14fb 100644
--- a/launcher/minecraft/mod/ResourcePackFolderModel.h
+++ b/launcher/minecraft/mod/ResourcePackFolderModel.h
@@ -17,7 +17,7 @@ public:
NUM_COLUMNS
};
- explicit ResourcePackFolderModel(const QString &dir, std::shared_ptr<const BaseInstance> instance);
+ explicit ResourcePackFolderModel(const QString &dir, BaseInstance* instance);
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
diff --git a/launcher/minecraft/mod/ShaderPackFolderModel.h b/launcher/minecraft/mod/ShaderPackFolderModel.h
index 6f3f2811..dc5acf80 100644
--- a/launcher/minecraft/mod/ShaderPackFolderModel.h
+++ b/launcher/minecraft/mod/ShaderPackFolderModel.h
@@ -6,7 +6,7 @@ class ShaderPackFolderModel : public ResourceFolderModel {
Q_OBJECT
public:
- explicit ShaderPackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
+ explicit ShaderPackFolderModel(const QString& dir, BaseInstance* instance)
: ResourceFolderModel(QDir(dir), instance)
{}
};
diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp
index 1e218537..c6609ed1 100644
--- a/launcher/minecraft/mod/TexturePackFolderModel.cpp
+++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp
@@ -39,7 +39,7 @@
#include "minecraft/mod/tasks/BasicFolderLoadTask.h"
#include "minecraft/mod/tasks/LocalTexturePackParseTask.h"
-TexturePackFolderModel::TexturePackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
+TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance* instance)
: ResourceFolderModel(QDir(dir), instance)
{}
diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h
index 246997bd..425a71e4 100644
--- a/launcher/minecraft/mod/TexturePackFolderModel.h
+++ b/launcher/minecraft/mod/TexturePackFolderModel.h
@@ -43,7 +43,7 @@ class TexturePackFolderModel : public ResourceFolderModel
Q_OBJECT
public:
- explicit TexturePackFolderModel(const QString &dir, std::shared_ptr<const BaseInstance> instance);
+ explicit TexturePackFolderModel(const QString &dir, BaseInstance* instance);
[[nodiscard]] Task* createUpdateTask() override;
[[nodiscard]] Task* createParseTask(Resource&) override;
};
diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h
index 40f1efc4..8d0223f9 100644
--- a/launcher/modplatform/ModIndex.h
+++ b/launcher/modplatform/ModIndex.h
@@ -23,6 +23,7 @@
#include <QString>
#include <QVariant>
#include <QVector>
+#include <memory>
class QIODevice;
@@ -83,6 +84,8 @@ struct ExtraPackData {
};
struct IndexedPack {
+ using Ptr = std::shared_ptr<IndexedPack>;
+
QVariant addonId;
ResourceProvider provider;
QString name;
diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp
index d3a737bb..83db642e 100644
--- a/launcher/modplatform/flame/FileResolvingTask.cpp
+++ b/launcher/modplatform/flame/FileResolvingTask.cpp
@@ -35,7 +35,29 @@ void Flame::FileResolvingTask::executeTask()
QByteArray data = Json::toText(object);
auto dl = Net::Upload::makeByteArray(QUrl("https://api.curseforge.com/v1/mods/files"), result.get(), data);
m_dljob->addNetAction(dl);
- connect(m_dljob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::netJobFinished);
+
+ auto step_progress = std::make_shared<TaskStepProgress>();
+ connect(m_dljob.get(), &NetJob::finished, this, [this, step_progress]() {
+ step_progress->state = TaskStepState::Succeeded;
+ stepProgress(*step_progress);
+ netJobFinished();
+ });
+ connect(m_dljob.get(), &NetJob::failed, this, [this, step_progress](QString reason) {
+ step_progress->state = TaskStepState::Failed;
+ stepProgress(*step_progress);
+ emitFailed(reason);
+ });
+ connect(m_dljob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress);
+ connect(m_dljob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) {
+ qDebug() << "Resolve slug progress" << current << total;
+ step_progress->update(current, total);
+ stepProgress(*step_progress);
+ });
+ connect(m_dljob.get(), &NetJob::status, this, [this, step_progress](QString status) {
+ step_progress->status = status;
+ stepProgress(*step_progress);
+ });
+
m_dljob->start();
}
@@ -44,7 +66,7 @@ void Flame::FileResolvingTask::netJobFinished()
setProgress(1, 3);
// job to check modrinth for blocked projects
m_checkJob.reset(new NetJob("Modrinth check", m_network));
- blockedProjects = QMap<File *,QByteArray *>();
+ blockedProjects = QMap<File*, std::shared_ptr<QByteArray>>();
QJsonDocument doc;
QJsonArray array;
@@ -71,8 +93,8 @@ void Flame::FileResolvingTask::netJobFinished()
auto hash = out.hash;
if(!hash.isEmpty()) {
auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash);
- auto output = new QByteArray();
- auto dl = Net::Download::makeByteArray(QUrl(url), output);
+ auto output = std::make_shared<QByteArray>();
+ auto dl = Net::Download::makeByteArray(QUrl(url), output.get());
QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() {
out.resolved = true;
});
@@ -82,7 +104,27 @@ void Flame::FileResolvingTask::netJobFinished()
}
}
}
- connect(m_checkJob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::modrinthCheckFinished);
+ auto step_progress = std::make_shared<TaskStepProgress>();
+ connect(m_checkJob.get(), &NetJob::finished, this, [this, step_progress]() {
+ step_progress->state = TaskStepState::Succeeded;
+ stepProgress(*step_progress);
+ modrinthCheckFinished();
+ });
+ connect(m_checkJob.get(), &NetJob::failed, this, [this, step_progress](QString reason) {
+ step_progress->state = TaskStepState::Failed;
+ stepProgress(*step_progress);
+ emitFailed(reason);
+ });
+ connect(m_checkJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress);
+ connect(m_checkJob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) {
+ qDebug() << "Resolve slug progress" << current << total;
+ step_progress->update(current, total);
+ stepProgress(*step_progress);
+ });
+ connect(m_checkJob.get(), &NetJob::status, this, [this, step_progress](QString status) {
+ step_progress->status = status;
+ stepProgress(*step_progress);
+ });
m_checkJob->start();
}
@@ -95,7 +137,6 @@ void Flame::FileResolvingTask::modrinthCheckFinished() {
auto &out = *it;
auto bytes = blockedProjects[out];
if (!out->resolved) {
- delete bytes;
continue;
}
@@ -112,11 +153,9 @@ void Flame::FileResolvingTask::modrinthCheckFinished() {
} else {
out->resolved = false;
}
-
- delete bytes;
}
//copy to an output list and filter out projects found on modrinth
- auto block = new QList<File *>();
+ auto block = std::make_shared<QList<File*>>();
auto it = blockedProjects.keys();
std::copy_if(it.begin(), it.end(), std::back_inserter(*block), [](File *f) {
return !f->resolved;
@@ -124,32 +163,48 @@ void Flame::FileResolvingTask::modrinthCheckFinished() {
//Display not found mods early
if (!block->empty()) {
//blocked mods found, we need the slug for displaying.... we need another job :D !
- auto slugJob = new NetJob("Slug Job", m_network);
- auto slugs = QVector<QByteArray>(block->size());
- auto index = 0;
- for (auto fileInfo: *block) {
- auto projectId = fileInfo->projectId;
- slugs[index] = QByteArray();
+ m_slugJob.reset(new NetJob("Slug Job", m_network));
+ int index = 0;
+ for (auto mod : *block) {
+ auto projectId = mod->projectId;
+ auto output = std::make_shared<QByteArray>();
auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(projectId);
- auto dl = Net::Download::makeByteArray(url, &slugs[index]);
- slugJob->addNetAction(dl);
- index++;
- }
- connect(slugJob, &NetJob::succeeded, this, [slugs, this, slugJob, block]() {
- slugJob->deleteLater();
- auto index = 0;
- for (const auto &slugResult: slugs) {
- auto json = QJsonDocument::fromJson(slugResult);
+ auto dl = Net::Download::makeByteArray(url, output.get());
+ qDebug() << "Fetching url slug for file:" << mod->fileName;
+ 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 json = QJsonDocument::fromJson(*output);
auto base = Json::requireString(Json::requireObject(Json::requireObject(Json::requireObject(json),"data"),"links"),
"websiteUrl");
- auto mod = block->at(index);
auto link = QString("%1/download/%2").arg(base, QString::number(mod->fileId));
mod->websiteUrl = link;
- index++;
- }
+ });
+ m_slugJob->addNetAction(dl);
+ index++;
+ }
+ auto step_progress = std::make_shared<TaskStepProgress>();
+ connect(m_slugJob.get(), &NetJob::succeeded, this, [this, step_progress]() {
+ step_progress->state = TaskStepState::Succeeded;
+ stepProgress(*step_progress);
emitSucceeded();
});
- slugJob->start();
+ connect(m_slugJob.get(), &NetJob::failed, this, [this, step_progress](QString reason) {
+ step_progress->state = TaskStepState::Failed;
+ stepProgress(*step_progress);
+ emitFailed(reason);
+ });
+ connect(m_slugJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress);
+ connect(m_slugJob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) {
+ qDebug() << "Resolve slug progress" << current << total;
+ step_progress->update(current, total);
+ stepProgress(*step_progress);
+ });
+ connect(m_slugJob.get(), &NetJob::status, this, [this, step_progress](QString status) {
+ step_progress->status = status;
+ stepProgress(*step_progress);
+ });
+
+ m_slugJob->start();
} else {
emitSucceeded();
}
diff --git a/launcher/modplatform/flame/FileResolvingTask.h b/launcher/modplatform/flame/FileResolvingTask.h
index 8fc17ea9..c280827a 100644
--- a/launcher/modplatform/flame/FileResolvingTask.h
+++ b/launcher/modplatform/flame/FileResolvingTask.h
@@ -1,41 +1,37 @@
#pragma once
-#include "tasks/Task.h"
-#include "net/NetJob.h"
#include "PackManifest.h"
+#include "net/NetJob.h"
+#include "tasks/Task.h"
-namespace Flame
-{
-class FileResolvingTask : public Task
-{
+namespace Flame {
+class FileResolvingTask : public Task {
Q_OBJECT
-public:
- explicit FileResolvingTask(const shared_qobject_ptr<QNetworkAccessManager>& network, Flame::Manifest &toProcess);
- virtual ~FileResolvingTask() {};
+ public:
+ explicit FileResolvingTask(const shared_qobject_ptr<QNetworkAccessManager>& network, Flame::Manifest& toProcess);
+ virtual ~FileResolvingTask(){};
bool canAbort() const override { return true; }
bool abort() override;
- const Flame::Manifest &getResults() const
- {
- return m_toProcess;
- }
+ const Flame::Manifest& getResults() const { return m_toProcess; }
-protected:
+ protected:
virtual void executeTask() override;
-protected slots:
+ protected slots:
void netJobFinished();
-private: /* data */
+ private: /* data */
shared_qobject_ptr<QNetworkAccessManager> m_network;
Flame::Manifest m_toProcess;
- std::shared_ptr<QByteArray> result;
+ std::shared_ptr<QByteArray> result;
NetJob::Ptr m_dljob;
- NetJob::Ptr m_checkJob;
+ NetJob::Ptr m_checkJob;
+ NetJob::Ptr m_slugJob;
void modrinthCheckFinished();
- QMap<File *, QByteArray *> blockedProjects;
+ QMap<File*, std::shared_ptr<QByteArray>> blockedProjects;
};
-}
+} // namespace Flame
diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp
index 5ef9a409..92590a08 100644
--- a/launcher/modplatform/flame/FlameAPI.cpp
+++ b/launcher/modplatform/flame/FlameAPI.cpp
@@ -38,14 +38,14 @@ auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString
QEventLoop lock;
QString changelog;
- auto* netJob = new NetJob(QString("Flame::FileChangelog"), APPLICATION->network());
- auto* response = new QByteArray();
+ auto netJob = makeShared<NetJob>(QString("Flame::FileChangelog"), APPLICATION->network());
+ auto response = std::make_shared<QByteArray>();
netJob->addNetAction(Net::Download::makeByteArray(
QString("https://api.curseforge.com/v1/mods/%1/files/%2/changelog")
.arg(QString::fromStdString(std::to_string(modId)), QString::fromStdString(std::to_string(fileId))),
- response));
+ response.get()));
- QObject::connect(netJob, &NetJob::succeeded, [netJob, response, &changelog] {
+ QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &changelog] {
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
@@ -60,10 +60,7 @@ auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString
changelog = Json::ensureString(doc.object(), "data");
});
- QObject::connect(netJob, &NetJob::finished, [response, &lock] {
- delete response;
- lock.quit();
- });
+ QObject::connect(netJob.get(), &NetJob::finished, [&lock] { lock.quit(); });
netJob->start();
lock.exec();
@@ -76,13 +73,12 @@ auto FlameAPI::getModDescription(int modId) -> QString
QEventLoop lock;
QString description;
- auto* netJob = new NetJob(QString("Flame::ModDescription"), APPLICATION->network());
- auto* response = new QByteArray();
+ auto netJob = makeShared<NetJob>(QString("Flame::ModDescription"), APPLICATION->network());
+ auto response = std::make_shared<QByteArray>();
netJob->addNetAction(Net::Download::makeByteArray(
- QString("https://api.curseforge.com/v1/mods/%1/description")
- .arg(QString::number(modId)), response));
+ QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response.get()));
- QObject::connect(netJob, &NetJob::succeeded, [netJob, response, &description] {
+ QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] {
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
@@ -97,10 +93,7 @@ auto FlameAPI::getModDescription(int modId) -> QString
description = Json::ensureString(doc.object(), "data");
});
- QObject::connect(netJob, &NetJob::finished, [response, &lock] {
- delete response;
- lock.quit();
- });
+ QObject::connect(netJob.get(), &NetJob::finished, [&lock] { lock.quit(); });
netJob->start();
lock.exec();
@@ -118,13 +111,13 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe
QEventLoop loop;
- auto netJob = new NetJob(QString("Flame::GetLatestVersion(%1)").arg(args.pack.name), APPLICATION->network());
- auto response = new QByteArray();
+ auto netJob = makeShared<NetJob>(QString("Flame::GetLatestVersion(%1)").arg(args.pack.name), APPLICATION->network());
+ auto response = std::make_shared<QByteArray>();
ModPlatform::IndexedVersion ver;
- netJob->addNetAction(Net::Download::makeByteArray(versions_url, response));
+ netJob->addNetAction(Net::Download::makeByteArray(versions_url, response.get()));
- QObject::connect(netJob, &NetJob::succeeded, [response, args, &ver] {
+ QObject::connect(netJob.get(), &NetJob::succeeded, [response, args, &ver] {
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
@@ -158,11 +151,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe
}
});
- QObject::connect(netJob, &NetJob::finished, [response, netJob, &loop] {
- netJob->deleteLater();
- delete response;
- loop.quit();
- });
+ QObject::connect(netJob.get(), &NetJob::finished, [&loop] { loop.quit(); });
netJob->start();
diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
index 86fd2ab4..dae93d1c 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
@@ -384,6 +384,7 @@ bool FlameCreationTask::createInstance()
connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::progress, this, &FlameCreationTask::setProgress);
connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::status, this, &FlameCreationTask::setStatus);
connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::stepProgress, this, &FlameCreationTask::propogateStepProgress);
+ connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::details, this, &FlameCreationTask::setDetails);
m_mod_id_resolver->start();
loop.exec();
diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp
index 010ac15e..a3c592fd 100644
--- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp
+++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp
@@ -24,7 +24,7 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&
netJob->addNetAction(Net::Download::makeByteArray(QUrl(search_url), response));
- QObject::connect(netJob.get(), &NetJob::succeeded, [=]{
+ QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks]{
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
@@ -40,16 +40,20 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&
callbacks.on_succeed(doc);
});
- QObject::connect(netJob.get(), &NetJob::failed, [=](QString reason){
+ QObject::connect(netJob.get(), &NetJob::failed, [&netJob, callbacks](QString reason){
int network_error_code = -1;
if (auto* failed_action = netJob->getFailedActions().at(0); failed_action && failed_action->m_reply)
network_error_code = failed_action->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
callbacks.on_fail(reason, network_error_code);
});
- QObject::connect(netJob.get(), &NetJob::aborted, [=]{
+ QObject::connect(netJob.get(), &NetJob::aborted, [callbacks]{
callbacks.on_abort();
});
+ QObject::connect(netJob.get(), &NetJob::finished, [response] {
+ delete response;
+ });
+
return netJob;
}
@@ -88,7 +92,7 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi
netJob->addNetAction(Net::Download::makeByteArray(versions_url, response));
- QObject::connect(netJob.get(), &NetJob::succeeded, [=] {
+ QObject::connect(netJob.get(), &NetJob::succeeded, [response, callbacks, args] {
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp
index cd3fcc85..7f8d3a06 100644
--- a/launcher/net/Download.cpp
+++ b/launcher/net/Download.cpp
@@ -134,11 +134,14 @@ void Download::executeTask()
request.setRawHeader("Authorization", token.toUtf8());
}
+#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
+ request.setTransferTimeout();
+#endif
+
m_last_progress_time = m_clock.now();
m_last_progress_bytes = 0;
QNetworkReply* rep = m_network->get(request);
-
m_reply.reset(rep);
connect(rep, &QNetworkReply::downloadProgress, this, &Download::downloadProgress);
connect(rep, &QNetworkReply::finished, this, &Download::downloadFinished);
diff --git a/launcher/tasks/ConcurrentTask.cpp b/launcher/tasks/ConcurrentTask.cpp
index fae2f3dc..5ee14505 100644
--- a/launcher/tasks/ConcurrentTask.cpp
+++ b/launcher/tasks/ConcurrentTask.cpp
@@ -138,7 +138,7 @@ void ConcurrentTask::startNext()
connect(next.get(), &Task::progress, this, [this, next](qint64 current, qint64 total) { subTaskProgress(next, current, total); });
m_doing.insert(next.get(), next);
- auto task_progress = std::make_shared<TaskStepProgress>(TaskStepProgress({ next->getUid() }));
+ auto task_progress = std::make_shared<TaskStepProgress>(next->getUid());
m_task_progress.insert(next->getUid(), task_progress);
updateState();
@@ -166,9 +166,9 @@ void ConcurrentTask::subTaskSucceeded(Task::Ptr task)
disconnect(task.get(), 0, this, 0);
- emit stepProgress(*task_progress.get());
+ emit stepProgress(*task_progress);
updateState();
- updateStepProgress(*task_progress.get(), Operation::REMOVED);
+ updateStepProgress(*task_progress, Operation::REMOVED);
startNext();
}
@@ -184,9 +184,9 @@ void ConcurrentTask::subTaskFailed(Task::Ptr task, const QString& msg)
disconnect(task.get(), 0, this, 0);
- emit stepProgress(*task_progress.get());
+ emit stepProgress(*task_progress);
updateState();
- updateStepProgress(*task_progress.get(), Operation::REMOVED);
+ updateStepProgress(*task_progress, Operation::REMOVED);
startNext();
}
@@ -196,7 +196,7 @@ void ConcurrentTask::subTaskStatus(Task::Ptr task, const QString& msg)
task_progress->status = msg;
task_progress->state = TaskStepState::Running;
- emit stepProgress(*task_progress.get());
+ emit stepProgress(*task_progress);
if (totalSize() == 1) {
setStatus(msg);
@@ -209,7 +209,7 @@ void ConcurrentTask::subTaskDetails(Task::Ptr task, const QString& msg)
task_progress->details = msg;
task_progress->state = TaskStepState::Running;
- emit stepProgress(*task_progress.get());
+ emit stepProgress(*task_progress);
if (totalSize() == 1) {
setDetails(msg);
@@ -220,15 +220,10 @@ void ConcurrentTask::subTaskProgress(Task::Ptr task, qint64 current, qint64 tota
{
auto task_progress = m_task_progress.value(task->getUid());
- task_progress->old_current = task_progress->current;
- task_progress->old_total = task_progress->old_total;
-
- task_progress->current = current;
- task_progress->total = total;
- task_progress->state = TaskStepState::Running;
-
- emit stepProgress(*task_progress.get());
- updateStepProgress(*task_progress.get(), Operation::CHANGED);
+ task_progress->update(current, total);
+
+ emit stepProgress(*task_progress);
+ updateStepProgress(*task_progress, Operation::CHANGED);
updateState();
if (totalSize() == 1) {
diff --git a/launcher/tasks/Task.cpp b/launcher/tasks/Task.cpp
index b0addd46..29c55cd4 100644
--- a/launcher/tasks/Task.cpp
+++ b/launcher/tasks/Task.cpp
@@ -109,7 +109,7 @@ void Task::start()
return;
}
}
- // NOTE: only fall thorugh to here in end states
+ // NOTE: only fall through to here in end states
m_state = State::Running;
emit started();
executeTask();
diff --git a/launcher/tasks/Task.h b/launcher/tasks/Task.h
index 799ed945..6d8bbbb4 100644
--- a/launcher/tasks/Task.h
+++ b/launcher/tasks/Task.h
@@ -64,7 +64,21 @@ struct TaskStepProgress {
QString status = "";
QString details = "";
TaskStepState state = TaskStepState::Waiting;
+ TaskStepProgress() {
+ this->uid = QUuid::createUuid();
+ }
+ TaskStepProgress(QUuid uid) {
+ this->uid = uid;
+ }
bool isDone() const { return (state == TaskStepState::Failed) || (state == TaskStepState::Succeeded); }
+ void update(qint64 current, qint64 total) {
+ this->old_current = this->current;
+ this->old_total = this->total;
+
+ this->current = current;
+ this->total = total;
+ this->state = TaskStepState::Running;
+ }
};
Q_DECLARE_METATYPE(TaskStepProgress)
diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp
index 64ed7673..aafaf220 100644
--- a/launcher/ui/dialogs/NewInstanceDialog.cpp
+++ b/launcher/ui/dialogs/NewInstanceDialog.cpp
@@ -99,7 +99,7 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString
// NOTE: m_buttons must be initialized before PageContainer, because it indirectly accesses m_buttons through setSuggestedPack! Do not move this below.
m_buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
- m_container = new PageContainer(this);
+ m_container = new PageContainer(this, {}, this);
m_container->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding);
m_container->layout()->setContentsMargins(0, 0, 0, 0);
ui->verticalLayout->insertWidget(2, m_container);
diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
index edb7d063..d2a8d33e 100644
--- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp
+++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp
@@ -89,7 +89,7 @@ void ResourceDownloadDialog::reject()
// won't work with subclasses if we put it in this ctor.
void ResourceDownloadDialog::initializeContainer()
{
- m_container = new PageContainer(this);
+ m_container = new PageContainer(this, {}, this);
m_container->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding);
m_container->layout()->setContentsMargins(0, 0, 0, 0);
m_vertical_layout.addWidget(m_container);
diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp
index dc983d9a..d0701a7a 100644
--- a/launcher/ui/pages/instance/ManagedPackPage.cpp
+++ b/launcher/ui/pages/instance/ManagedPackPage.cpp
@@ -30,8 +30,6 @@ class NoBigComboBoxStyle : public QProxyStyle {
Q_OBJECT
public:
- NoBigComboBoxStyle(QStyle* style) : QProxyStyle(style) {}
-
// clang-format off
int styleHint(QStyle::StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override
{
@@ -41,6 +39,37 @@ class NoBigComboBoxStyle : public QProxyStyle {
return QProxyStyle::styleHint(hint, option, widget, returnData);
}
// clang-format on
+
+ /**
+ * Something about QProxyStyle and QStyle objects means they can't be free'd just
+ * because all the widgets using them are gone.
+ * They seems to be tied to the QApplicaiton lifecycle.
+ * So make singletons tied to the lifetime of the application to clean them up and ensure they aren't
+ * being remade over and over again, thus leaking memory.
+ */
+ public:
+ static NoBigComboBoxStyle* getInstance(QStyle* style)
+ {
+ static QHash<QStyle*, NoBigComboBoxStyle*> s_singleton_instances_ = {};
+ static std::mutex s_singleton_instances_mutex_;
+
+ std::lock_guard<std::mutex> lock(s_singleton_instances_mutex_);
+ auto inst_iter = s_singleton_instances_.constFind(style);
+ NoBigComboBoxStyle* inst = nullptr;
+ if (inst_iter == s_singleton_instances_.constEnd() || *inst_iter == nullptr) {
+ inst = new NoBigComboBoxStyle(style);
+ inst->setParent(APPLICATION);
+ s_singleton_instances_.insert(style, inst);
+ qDebug() << "QProxyStyle NoBigComboBox created for" << style->objectName() << style;
+ } else {
+ inst = *inst_iter;
+ }
+ return inst;
+ }
+
+ private:
+ NoBigComboBoxStyle(QStyle* style) : QProxyStyle(style) {}
+
};
ManagedPackPage* ManagedPackPage::createPage(BaseInstance* inst, QString type, QWidget* parent)
@@ -62,8 +91,10 @@ ManagedPackPage::ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_wi
// NOTE: GTK2 themes crash with the proxy style.
// This seems like an upstream bug, so there's not much else that can be done.
- if (!QStyleFactory::keys().contains("gtk2"))
- ui->versionsComboBox->setStyle(new NoBigComboBoxStyle(ui->versionsComboBox->style()));
+ if (!QStyleFactory::keys().contains("gtk2")){
+ auto comboStyle = NoBigComboBoxStyle::getInstance(ui->versionsComboBox->style());
+ ui->versionsComboBox->setStyle(comboStyle);
+ }
ui->reloadButton->setVisible(false);
connect(ui->reloadButton, &QPushButton::clicked, this, [this](bool){
diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp
index fffb96f2..74b7ec7c 100644
--- a/launcher/ui/pages/instance/VersionPage.cpp
+++ b/launcher/ui/pages/instance/VersionPage.cpp
@@ -165,7 +165,7 @@ VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent)
auto proxy = new IconProxy(ui->packageView);
proxy->setSourceModel(m_profile.get());
- m_filterModel = new QSortFilterProxyModel();
+ m_filterModel = new QSortFilterProxyModel(this);
m_filterModel->setDynamicSortFilter(true);
m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp
index 3ffe6cb0..afd8b292 100644
--- a/launcher/ui/pages/modplatform/ModModel.cpp
+++ b/launcher/ui/pages/modplatform/ModModel.cpp
@@ -36,7 +36,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& entry)
{
- auto& pack = m_packs[entry.row()];
+ auto& pack = *m_packs[entry.row()];
auto profile = static_cast<MinecraftInstance const&>(m_base_instance).getPackProfile();
Q_ASSERT(profile);
@@ -51,7 +51,7 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en
ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry)
{
- auto& pack = m_packs[entry.row()];
+ auto& pack = *m_packs[entry.row()];
return { pack };
}
diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h
index c3b58cd6..4ea55efa 100644
--- a/launcher/ui/pages/modplatform/ModPage.h
+++ b/launcher/ui/pages/modplatform/ModPage.h
@@ -41,8 +41,6 @@ class ModPage : public ResourcePage {
return page;
}
- ~ModPage() override = default;
-
//: The plural version of 'mod'
[[nodiscard]] inline QString resourcesString() const override { return tr("mods"); }
//: The singular version of 'mods'
diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp
index db7d26f8..472aa851 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourceModel.cpp
@@ -9,6 +9,7 @@
#include <QMessageBox>
#include <QPixmapCache>
#include <QUrl>
+#include <memory>
#include "Application.h"
#include "BuildConfig.h"
@@ -45,16 +46,16 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant
auto pack = m_packs.at(pos);
switch (role) {
case Qt::ToolTipRole: {
- if (pack.description.length() > 100) {
+ 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("...");
return edit;
}
- return pack.description;
+ return pack->description;
}
case Qt::DecorationRole: {
- if (auto icon_or_none = const_cast<ResourceModel*>(this)->getIcon(const_cast<QModelIndex&>(index), pack.logoUrl);
+ if (auto icon_or_none = const_cast<ResourceModel*>(this)->getIcon(const_cast<QModelIndex&>(index), pack->logoUrl);
icon_or_none.has_value())
return icon_or_none.value();
@@ -64,16 +65,16 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant
return QSize(0, 58);
case Qt::UserRole: {
QVariant v;
- v.setValue(pack);
+ v.setValue(*pack);
return v;
}
// Custom data
case UserDataTypes::TITLE:
- return pack.name;
+ return pack->name;
case UserDataTypes::DESCRIPTION:
- return pack.description;
+ return pack->description;
case UserDataTypes::SELECTED:
- return pack.isAnyVersionSelected();
+ return pack->isAnyVersionSelected();
default:
break;
}
@@ -102,7 +103,7 @@ bool ResourceModel::setData(const QModelIndex& index, const QVariant& value, int
if (pos >= m_packs.size() || pos < 0 || !index.isValid())
return false;
- m_packs[pos] = value.value<ModPlatform::IndexedPack>();
+ m_packs[pos] = std::make_shared<ModPlatform::IndexedPack>(value.value<ModPlatform::IndexedPack>());
emit dataChanged(index, index);
return true;
@@ -161,7 +162,7 @@ void ResourceModel::loadEntry(QModelIndex& entry)
if (!hasActiveInfoJob())
m_current_info_job.clear();
- if (!pack.versionsLoaded) {
+ if (!pack->versionsLoaded) {
auto args{ createVersionsArguments(entry) };
auto callbacks{ createVersionsCallbacks(entry) };
@@ -177,7 +178,7 @@ void ResourceModel::loadEntry(QModelIndex& entry)
runInfoJob(job);
}
- if (!pack.extraDataLoaded) {
+ if (!pack->extraDataLoaded) {
auto args{ createInfoArguments(entry) };
auto callbacks{ createInfoCallbacks(entry) };
@@ -229,7 +230,7 @@ void ResourceModel::clearData()
void ResourceModel::runSearchJob(Task::Ptr ptr)
{
- m_current_search_job = ptr;
+ m_current_search_job.reset(ptr); // clean up first
m_current_search_job->start();
}
void ResourceModel::runInfoJob(Task::Ptr ptr)
@@ -326,15 +327,15 @@ void ResourceModel::loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArra
void ResourceModel::searchRequestSucceeded(QJsonDocument& doc)
{
- QList<ModPlatform::IndexedPack> newList;
+ QList<ModPlatform::IndexedPack::Ptr> newList;
auto packs = documentToArray(doc);
for (auto packRaw : packs) {
auto packObj = packRaw.toObject();
- ModPlatform::IndexedPack pack;
+ ModPlatform::IndexedPack::Ptr pack = std::make_shared<ModPlatform::IndexedPack>();
try {
- loadIndexedPack(pack, packObj);
+ loadIndexedPack(*pack, packObj);
newList.append(pack);
} catch (const JSONValidationError& e) {
qWarning() << "Error while loading resource from " << debugName() << ": " << e.cause();
diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h
index 46a02d6e..1ec42cda 100644
--- a/launcher/ui/pages/modplatform/ResourceModel.h
+++ b/launcher/ui/pages/modplatform/ResourceModel.h
@@ -123,7 +123,7 @@ class ResourceModel : public QAbstractListModel {
QSet<QUrl> m_currently_running_icon_actions;
QSet<QUrl> m_failed_icon_actions;
- QList<ModPlatform::IndexedPack> m_packs;
+ QList<ModPlatform::IndexedPack::Ptr> m_packs;
// HACK: We need this to prevent callbacks from calling the model after it has already been deleted.
// This leaks a tiny bit of memory per time the user has opened a resource dialog. How to make this better?
diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.cpp b/launcher/ui/pages/modplatform/ResourcePackModel.cpp
index 3df9a787..18c14bf8 100644
--- a/launcher/ui/pages/modplatform/ResourcePackModel.cpp
+++ b/launcher/ui/pages/modplatform/ResourcePackModel.cpp
@@ -22,13 +22,13 @@ ResourceAPI::SearchArgs ResourcePackResourceModel::createSearchArguments()
ResourceAPI::VersionSearchArgs ResourcePackResourceModel::createVersionsArguments(QModelIndex& entry)
{
auto& pack = m_packs[entry.row()];
- return { pack };
+ return { *pack };
}
ResourceAPI::ProjectInfoArgs ResourcePackResourceModel::createInfoArguments(QModelIndex& entry)
{
auto& pack = m_packs[entry.row()];
- return { pack };
+ return { *pack };
}
void ResourcePackResourceModel::searchWithTerm(const QString& term, unsigned int sort)
diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.h b/launcher/ui/pages/modplatform/ResourcePackPage.h
index c01c89c4..8c5cf08b 100644
--- a/launcher/ui/pages/modplatform/ResourcePackPage.h
+++ b/launcher/ui/pages/modplatform/ResourcePackPage.h
@@ -31,8 +31,6 @@ class ResourcePackResourcePage : public ResourcePage {
return page;
}
- ~ResourcePackResourcePage() override = default;
-
//: The plural version of 'resource pack'
[[nodiscard]] inline QString resourcesString() const override { return tr("resource packs"); }
//: The singular version of 'resource packs'
diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp
index bbd465bc..f75bb886 100644
--- a/launcher/ui/pages/modplatform/ResourcePage.cpp
+++ b/launcher/ui/pages/modplatform/ResourcePage.cpp
@@ -83,6 +83,8 @@ ResourcePage::ResourcePage(ResourceDownloadDialog* parent, BaseInstance& base_in
ResourcePage::~ResourcePage()
{
delete m_ui;
+ if (m_model)
+ delete m_model;
}
void ResourcePage::retranslate()
diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.cpp b/launcher/ui/pages/modplatform/ShaderPackModel.cpp
index 2101b394..aabd3be6 100644
--- a/launcher/ui/pages/modplatform/ShaderPackModel.cpp
+++ b/launcher/ui/pages/modplatform/ShaderPackModel.cpp
@@ -22,13 +22,13 @@ ResourceAPI::SearchArgs ShaderPackResourceModel::createSearchArguments()
ResourceAPI::VersionSearchArgs ShaderPackResourceModel::createVersionsArguments(QModelIndex& entry)
{
auto& pack = m_packs[entry.row()];
- return { pack };
+ return { *pack };
}
ResourceAPI::ProjectInfoArgs ShaderPackResourceModel::createInfoArguments(QModelIndex& entry)
{
auto& pack = m_packs[entry.row()];
- return { pack };
+ return { *pack };
}
void ShaderPackResourceModel::searchWithTerm(const QString& term, unsigned int sort)
diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.h b/launcher/ui/pages/modplatform/ShaderPackPage.h
index 972419a8..9039c4d9 100644
--- a/launcher/ui/pages/modplatform/ShaderPackPage.h
+++ b/launcher/ui/pages/modplatform/ShaderPackPage.h
@@ -31,8 +31,6 @@ class ShaderPackResourcePage : public ResourcePage {
return page;
}
- ~ShaderPackResourcePage() override = default;
-
//: The plural version of 'shader pack'
[[nodiscard]] inline QString resourcesString() const override { return tr("shader packs"); }
//: The singular version of 'shader packs'
diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp
index 0a06a351..b9b17b42 100644
--- a/launcher/ui/widgets/PageContainer.cpp
+++ b/launcher/ui/widgets/PageContainer.cpp
@@ -87,7 +87,9 @@ PageContainer::PageContainer(BasePageProvider *pageProvider, QString defaultId,
auto pages = pageProvider->getPages();
for (auto page : pages)
{
- page->stackIndex = m_pageStack->addWidget(dynamic_cast<QWidget *>(page));
+ auto widget = dynamic_cast<QWidget *>(page);
+ widget->setParent(this);
+ page->stackIndex = m_pageStack->addWidget(widget);
page->listIndex = counter;
page->setParentContainer(this);
counter++;
diff --git a/libraries/katabasis/src/Reply.cpp b/libraries/katabasis/src/Reply.cpp
index 3e27a7e6..c2607900 100644
--- a/libraries/katabasis/src/Reply.cpp
+++ b/libraries/katabasis/src/Reply.cpp
@@ -40,6 +40,8 @@ void ReplyList::remove(QNetworkReply *reply) {
if (o2Reply) {
o2Reply->stop();
(void)replies_.removeOne(o2Reply);
+ // we took ownership, we must free
+ delete o2Reply;
}
}
diff --git a/tests/ResourceFolderModel_test.cpp b/tests/ResourceFolderModel_test.cpp
index 054d81c4..962d89f1 100644
--- a/tests/ResourceFolderModel_test.cpp
+++ b/tests/ResourceFolderModel_test.cpp
@@ -90,9 +90,7 @@ slots:
QEventLoop loop;
- InstancePtr instance;
-
- ModFolderModel m(tempDir.path(), instance, true);
+ ModFolderModel m(tempDir.path(), nullptr, true);
connect(&m, &ModFolderModel::updateFinished, &loop, &QEventLoop::quit);
@@ -116,8 +114,7 @@ slots:
QString folder = source + '/';
QTemporaryDir tempDir;
QEventLoop loop;
- InstancePtr instance;
- ModFolderModel m(tempDir.path(), instance, true);
+ ModFolderModel m(tempDir.path(), nullptr, true);
connect(&m, &ModFolderModel::updateFinished, &loop, &QEventLoop::quit);
@@ -140,8 +137,7 @@ slots:
void test_addFromWatch()
{
QString source = QFINDTESTDATA("testdata/ResourceFolderModel");
- InstancePtr instance;
- ModFolderModel model(source, instance);
+ ModFolderModel model(source, nullptr);
QCOMPARE(model.size(), 0);
@@ -161,9 +157,7 @@ slots:
QString file_mod = QFINDTESTDATA("testdata/ResourceFolderModel/supercoolmod.jar");
QTemporaryDir tmp;
- InstancePtr instance;
-
- ResourceFolderModel model(QDir(tmp.path()), instance);
+ ResourceFolderModel model(QDir(tmp.path()), nullptr);
QCOMPARE(model.size(), 0);
@@ -214,8 +208,7 @@ slots:
QString file_mod = QFINDTESTDATA("testdata/ResourceFolderModel/supercoolmod.jar");
QTemporaryDir tmp;
- InstancePtr instance;
- ResourceFolderModel model(tmp.path(), instance);
+ ResourceFolderModel model(tmp.path(), nullptr);
QCOMPARE(model.size(), 0);
diff --git a/tests/ResourceModel_test.cpp b/tests/ResourceModel_test.cpp
index 716bf853..c0d9cd95 100644
--- a/tests/ResourceModel_test.cpp
+++ b/tests/ResourceModel_test.cpp
@@ -75,9 +75,9 @@ class ResourceModelTest : public QObject {
auto search_json = DummyResourceAPI::searchRequestResult();
auto processed_response = model->documentToArray(search_json).first().toObject();
- QVERIFY(processed_pack.addonId.toString() == Json::requireString(processed_response, "project_id"));
- QVERIFY(processed_pack.description == Json::requireString(processed_response, "description"));
- QVERIFY(processed_pack.authors.first().name == Json::requireString(processed_response, "author"));
+ QVERIFY(processed_pack->addonId.toString() == Json::requireString(processed_response, "project_id"));
+ QVERIFY(processed_pack->description == Json::requireString(processed_response, "description"));
+ QVERIFY(processed_pack->authors.first().name == Json::requireString(processed_response, "author"));
}
};