Merge branch 'Fix_Assert' of github.com:Trial97/PrismLauncher into develop
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
commit
737fc1a2a4
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@ -68,7 +68,7 @@ jobs:
|
|||||||
qt_ver: 6
|
qt_ver: 6
|
||||||
qt_host: windows
|
qt_host: windows
|
||||||
qt_arch: ''
|
qt_arch: ''
|
||||||
qt_version: '6.5.0'
|
qt_version: '6.5.1'
|
||||||
qt_modules: 'qt5compat qtimageformats'
|
qt_modules: 'qt5compat qtimageformats'
|
||||||
qt_tools: ''
|
qt_tools: ''
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ jobs:
|
|||||||
qt_ver: 6
|
qt_ver: 6
|
||||||
qt_host: windows
|
qt_host: windows
|
||||||
qt_arch: 'win64_msvc2019_arm64'
|
qt_arch: 'win64_msvc2019_arm64'
|
||||||
qt_version: '6.5.0'
|
qt_version: '6.5.1'
|
||||||
qt_modules: 'qt5compat qtimageformats'
|
qt_modules: 'qt5compat qtimageformats'
|
||||||
qt_tools: ''
|
qt_tools: ''
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ jobs:
|
|||||||
qt_ver: 6
|
qt_ver: 6
|
||||||
qt_host: mac
|
qt_host: mac
|
||||||
qt_arch: ''
|
qt_arch: ''
|
||||||
qt_version: '6.5.0'
|
qt_version: '6.5.1'
|
||||||
qt_modules: 'qt5compat qtimageformats'
|
qt_modules: 'qt5compat qtimageformats'
|
||||||
qt_tools: ''
|
qt_tools: ''
|
||||||
|
|
||||||
@ -587,7 +587,7 @@ jobs:
|
|||||||
submodules: 'true'
|
submodules: 'true'
|
||||||
- name: Install nix
|
- name: Install nix
|
||||||
if: inputs.build_type == 'Debug'
|
if: inputs.build_type == 'Debug'
|
||||||
uses: cachix/install-nix-action@v20
|
uses: cachix/install-nix-action@v21
|
||||||
with:
|
with:
|
||||||
install_url: https://nixos.org/nix/install
|
install_url: https://nixos.org/nix/install
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
|
@ -34,7 +34,7 @@ class InstanceCreationTask : public InstanceTask {
|
|||||||
QString getError() const { return m_error_message; }
|
QString getError() const { return m_error_message; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setError(QString message) { m_error_message = message; };
|
void setError(const QString& message) { m_error_message = message; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_abort = false;
|
bool m_abort = false;
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "MMCZip.h"
|
#include "MMCZip.h"
|
||||||
#include "NullInstance.h"
|
#include "NullInstance.h"
|
||||||
|
|
||||||
|
#include "QObjectPtr.h"
|
||||||
#include "icons/IconList.h"
|
#include "icons/IconList.h"
|
||||||
#include "icons/IconUtils.h"
|
#include "icons/IconUtils.h"
|
||||||
|
|
||||||
@ -260,7 +261,7 @@ void InstanceImportTask::extractFinished()
|
|||||||
|
|
||||||
void InstanceImportTask::processFlame()
|
void InstanceImportTask::processFlame()
|
||||||
{
|
{
|
||||||
FlameCreationTask* inst_creation_task = nullptr;
|
shared_qobject_ptr<FlameCreationTask> inst_creation_task = nullptr;
|
||||||
if (!m_extra_info.isEmpty()) {
|
if (!m_extra_info.isEmpty()) {
|
||||||
auto pack_id_it = m_extra_info.constFind("pack_id");
|
auto pack_id_it = m_extra_info.constFind("pack_id");
|
||||||
Q_ASSERT(pack_id_it != m_extra_info.constEnd());
|
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())
|
if (original_instance_id_it != m_extra_info.constEnd())
|
||||||
original_instance_id = original_instance_id_it.value();
|
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 {
|
} else {
|
||||||
// FIXME: Find a way to get IDs in directly imported ZIPs
|
// 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);
|
inst_creation_task->setName(*this);
|
||||||
@ -286,20 +287,19 @@ void InstanceImportTask::processFlame()
|
|||||||
inst_creation_task->setGroup(m_instGroup);
|
inst_creation_task->setGroup(m_instGroup);
|
||||||
inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
|
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());
|
setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID());
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
});
|
});
|
||||||
connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
|
connect(inst_creation_task.get(), &Task::failed, this, &InstanceImportTask::emitFailed);
|
||||||
connect(inst_creation_task, &Task::progress, this, &InstanceImportTask::setProgress);
|
connect(inst_creation_task.get(), &Task::progress, this, &InstanceImportTask::setProgress);
|
||||||
connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress);
|
connect(inst_creation_task.get(), &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress);
|
||||||
connect(inst_creation_task, &Task::status, this, &InstanceImportTask::setStatus);
|
connect(inst_creation_task.get(), &Task::status, this, &InstanceImportTask::setStatus);
|
||||||
connect(inst_creation_task, &Task::details, this, &InstanceImportTask::setDetails);
|
connect(inst_creation_task.get(), &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(this, &Task::aborted, inst_creation_task.get(), &InstanceCreationTask::abort);
|
||||||
connect(inst_creation_task, &Task::aborted, this, &Task::abort);
|
connect(inst_creation_task.get(), &Task::aborted, this, &Task::abort);
|
||||||
connect(inst_creation_task, &Task::abortStatusChanged, this, &Task::setAbortable);
|
connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable);
|
||||||
|
|
||||||
inst_creation_task->start();
|
inst_creation_task->start();
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
/*
|
/*
|
||||||
* Prism Launcher - Minecraft Launcher
|
* Prism Launcher - Minecraft Launcher
|
||||||
* Copyright (c) 2022-2023 flowln <flowlnlnln@gmail.com>
|
* Copyright (c) 2022-2023 flowln <flowlnlnln@gmail.com>
|
||||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* the Free Software Foundation, version 3.
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ResourceDownloadTask.h"
|
#include "ResourceDownloadTask.h"
|
||||||
|
|
||||||
@ -24,7 +24,7 @@
|
|||||||
#include "minecraft/mod/ModFolderModel.h"
|
#include "minecraft/mod/ModFolderModel.h"
|
||||||
#include "minecraft/mod/ResourceFolderModel.h"
|
#include "minecraft/mod/ResourceFolderModel.h"
|
||||||
|
|
||||||
ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack pack,
|
ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack,
|
||||||
ModPlatform::IndexedVersion version,
|
ModPlatform::IndexedVersion version,
|
||||||
const std::shared_ptr<ResourceFolderModel> packs,
|
const std::shared_ptr<ResourceFolderModel> packs,
|
||||||
bool is_indexed,
|
bool is_indexed,
|
||||||
@ -32,7 +32,7 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack pack,
|
|||||||
: m_pack(std::move(pack)), m_pack_version(std::move(version)), m_pack_model(packs), m_custom_target_folder(custom_target_folder)
|
: m_pack(std::move(pack)), m_pack_version(std::move(version)), m_pack_model(packs), m_custom_target_folder(custom_target_folder)
|
||||||
{
|
{
|
||||||
if (auto model = dynamic_cast<ModFolderModel*>(m_pack_model.get()); model && is_indexed) {
|
if (auto model = dynamic_cast<ModFolderModel*>(m_pack_model.get()); model && is_indexed) {
|
||||||
m_update_task.reset(new LocalModUpdateTask(model->indexDir(), m_pack, m_pack_version));
|
m_update_task.reset(new LocalModUpdateTask(model->indexDir(), *m_pack, m_pack_version));
|
||||||
connect(m_update_task.get(), &LocalModUpdateTask::hasOldMod, this, &ResourceDownloadTask::hasOldResource);
|
connect(m_update_task.get(), &LocalModUpdateTask::hasOldMod, this, &ResourceDownloadTask::hasOldResource);
|
||||||
|
|
||||||
addTask(m_update_task);
|
addTask(m_update_task);
|
||||||
|
@ -30,7 +30,7 @@ class ResourceFolderModel;
|
|||||||
class ResourceDownloadTask : public SequentialTask {
|
class ResourceDownloadTask : public SequentialTask {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit ResourceDownloadTask(ModPlatform::IndexedPack pack,
|
explicit ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack,
|
||||||
ModPlatform::IndexedVersion version,
|
ModPlatform::IndexedVersion version,
|
||||||
const std::shared_ptr<ResourceFolderModel> packs,
|
const std::shared_ptr<ResourceFolderModel> packs,
|
||||||
bool is_indexed = true,
|
bool is_indexed = true,
|
||||||
@ -39,12 +39,12 @@ class ResourceDownloadTask : public SequentialTask {
|
|||||||
const QString& getCustomPath() const { return m_custom_target_folder; }
|
const QString& getCustomPath() const { return m_custom_target_folder; }
|
||||||
const QVariant& getVersionID() const { return m_pack_version.fileId; }
|
const QVariant& getVersionID() const { return m_pack_version.fileId; }
|
||||||
const ModPlatform::IndexedVersion& getVersion() const { return m_pack_version; }
|
const ModPlatform::IndexedVersion& getVersion() const { return m_pack_version; }
|
||||||
ModPlatform::IndexedPack& getPack() { return m_pack; }
|
const ModPlatform::ResourceProvider& getProvider() const { return m_pack->provider; }
|
||||||
const ModPlatform::ResourceProvider& getProvider() const { return m_pack.provider; }
|
const QString& getName() const { return m_pack->name; }
|
||||||
const QString& getName() const { return m_pack.name; }
|
ModPlatform::IndexedPack::Ptr getPack() { return m_pack; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ModPlatform::IndexedPack m_pack;
|
ModPlatform::IndexedPack::Ptr m_pack;
|
||||||
ModPlatform::IndexedVersion m_pack_version;
|
ModPlatform::IndexedVersion m_pack_version;
|
||||||
const std::shared_ptr<ResourceFolderModel> m_pack_model;
|
const std::shared_ptr<ResourceFolderModel> m_pack_model;
|
||||||
QString m_custom_target_folder;
|
QString m_custom_target_folder;
|
||||||
|
@ -1109,79 +1109,79 @@ JavaVersion MinecraftInstance::getJavaVersion()
|
|||||||
return JavaVersion(settings()->get("JavaVersion").toString());
|
return JavaVersion(settings()->get("JavaVersion").toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModFolderModel> MinecraftInstance::loaderModList() const
|
std::shared_ptr<ModFolderModel> MinecraftInstance::loaderModList()
|
||||||
{
|
{
|
||||||
if (!m_loader_mod_list)
|
if (!m_loader_mod_list)
|
||||||
{
|
{
|
||||||
bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
|
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());
|
m_loader_mod_list->disableInteraction(isRunning());
|
||||||
connect(this, &BaseInstance::runningStatusChanged, m_loader_mod_list.get(), &ModFolderModel::disableInteraction);
|
connect(this, &BaseInstance::runningStatusChanged, m_loader_mod_list.get(), &ModFolderModel::disableInteraction);
|
||||||
}
|
}
|
||||||
return m_loader_mod_list;
|
return m_loader_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModFolderModel> MinecraftInstance::coreModList() const
|
std::shared_ptr<ModFolderModel> MinecraftInstance::coreModList()
|
||||||
{
|
{
|
||||||
if (!m_core_mod_list)
|
if (!m_core_mod_list)
|
||||||
{
|
{
|
||||||
bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
|
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());
|
m_core_mod_list->disableInteraction(isRunning());
|
||||||
connect(this, &BaseInstance::runningStatusChanged, m_core_mod_list.get(), &ModFolderModel::disableInteraction);
|
connect(this, &BaseInstance::runningStatusChanged, m_core_mod_list.get(), &ModFolderModel::disableInteraction);
|
||||||
}
|
}
|
||||||
return m_core_mod_list;
|
return m_core_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ModFolderModel> MinecraftInstance::nilModList() const
|
std::shared_ptr<ModFolderModel> MinecraftInstance::nilModList()
|
||||||
{
|
{
|
||||||
if (!m_nil_mod_list)
|
if (!m_nil_mod_list)
|
||||||
{
|
{
|
||||||
bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
|
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());
|
m_nil_mod_list->disableInteraction(isRunning());
|
||||||
connect(this, &BaseInstance::runningStatusChanged, m_nil_mod_list.get(), &ModFolderModel::disableInteraction);
|
connect(this, &BaseInstance::runningStatusChanged, m_nil_mod_list.get(), &ModFolderModel::disableInteraction);
|
||||||
}
|
}
|
||||||
return m_nil_mod_list;
|
return m_nil_mod_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ResourcePackFolderModel> MinecraftInstance::resourcePackList() const
|
std::shared_ptr<ResourcePackFolderModel> MinecraftInstance::resourcePackList()
|
||||||
{
|
{
|
||||||
if (!m_resource_pack_list)
|
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;
|
return m_resource_pack_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<TexturePackFolderModel> MinecraftInstance::texturePackList() const
|
std::shared_ptr<TexturePackFolderModel> MinecraftInstance::texturePackList()
|
||||||
{
|
{
|
||||||
if (!m_texture_pack_list)
|
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;
|
return m_texture_pack_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ShaderPackFolderModel> MinecraftInstance::shaderPackList() const
|
std::shared_ptr<ShaderPackFolderModel> MinecraftInstance::shaderPackList()
|
||||||
{
|
{
|
||||||
if (!m_shader_pack_list)
|
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;
|
return m_shader_pack_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<WorldList> MinecraftInstance::worldList() const
|
std::shared_ptr<WorldList> MinecraftInstance::worldList()
|
||||||
{
|
{
|
||||||
if (!m_world_list)
|
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;
|
return m_world_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<GameOptions> MinecraftInstance::gameOptionsModel() const
|
std::shared_ptr<GameOptions> MinecraftInstance::gameOptionsModel()
|
||||||
{
|
{
|
||||||
if (!m_game_options)
|
if (!m_game_options)
|
||||||
{
|
{
|
||||||
|
@ -115,14 +115,14 @@ public:
|
|||||||
std::shared_ptr<PackProfile> getPackProfile() const;
|
std::shared_ptr<PackProfile> getPackProfile() const;
|
||||||
|
|
||||||
////// Mod Lists //////
|
////// Mod Lists //////
|
||||||
std::shared_ptr<ModFolderModel> loaderModList() const;
|
std::shared_ptr<ModFolderModel> loaderModList();
|
||||||
std::shared_ptr<ModFolderModel> coreModList() const;
|
std::shared_ptr<ModFolderModel> coreModList();
|
||||||
std::shared_ptr<ModFolderModel> nilModList() const;
|
std::shared_ptr<ModFolderModel> nilModList();
|
||||||
std::shared_ptr<ResourcePackFolderModel> resourcePackList() const;
|
std::shared_ptr<ResourcePackFolderModel> resourcePackList();
|
||||||
std::shared_ptr<TexturePackFolderModel> texturePackList() const;
|
std::shared_ptr<TexturePackFolderModel> texturePackList();
|
||||||
std::shared_ptr<ShaderPackFolderModel> shaderPackList() const;
|
std::shared_ptr<ShaderPackFolderModel> shaderPackList();
|
||||||
std::shared_ptr<WorldList> worldList() const;
|
std::shared_ptr<WorldList> worldList();
|
||||||
std::shared_ptr<GameOptions> gameOptionsModel() const;
|
std::shared_ptr<GameOptions> gameOptionsModel();
|
||||||
|
|
||||||
////// Launch stuff //////
|
////// Launch stuff //////
|
||||||
Task::Ptr createUpdateTask(Net::Mode mode) override;
|
Task::Ptr createUpdateTask(Net::Mode mode) override;
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
#include <QFileSystemWatcher>
|
#include <QFileSystemWatcher>
|
||||||
#include <QDebug>
|
#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)
|
: QAbstractListModel(), m_instance(instance), m_dir(dir)
|
||||||
{
|
{
|
||||||
FS::ensureFolderPathExists(m_dir.absolutePath());
|
FS::ensureFolderPathExists(m_dir.absolutePath());
|
||||||
|
@ -50,7 +50,7 @@ public:
|
|||||||
IconFileRole
|
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;
|
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ signals:
|
|||||||
void changed();
|
void changed();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<const BaseInstance> m_instance;
|
BaseInstance* m_instance;
|
||||||
QFileSystemWatcher *m_watcher;
|
QFileSystemWatcher *m_watcher;
|
||||||
bool is_watching;
|
bool is_watching;
|
||||||
QDir m_dir;
|
QDir m_dir;
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
#include "minecraft/mod/tasks/ModFolderLoadTask.h"
|
#include "minecraft/mod/tasks/ModFolderLoadTask.h"
|
||||||
#include "modplatform/ModIndex.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)
|
: 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 };
|
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER };
|
||||||
|
@ -75,7 +75,7 @@ public:
|
|||||||
Enable,
|
Enable,
|
||||||
Toggle
|
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;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
#include "tasks/Task.h"
|
#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)
|
: QAbstractListModel(parent), m_dir(dir), m_instance(instance), m_watcher(this)
|
||||||
{
|
{
|
||||||
if (create_dir) {
|
if (create_dir) {
|
||||||
|
@ -26,7 +26,7 @@ class QSortFilterProxyModel;
|
|||||||
class ResourceFolderModel : public QAbstractListModel {
|
class ResourceFolderModel : public QAbstractListModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
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;
|
~ResourceFolderModel() override;
|
||||||
|
|
||||||
/** Starts watching the paths for changes.
|
/** Starts watching the paths for changes.
|
||||||
@ -191,7 +191,7 @@ class ResourceFolderModel : public QAbstractListModel {
|
|||||||
bool m_can_interact = true;
|
bool m_can_interact = true;
|
||||||
|
|
||||||
QDir m_dir;
|
QDir m_dir;
|
||||||
std::shared_ptr<const BaseInstance> m_instance;
|
BaseInstance* m_instance;
|
||||||
QFileSystemWatcher m_watcher;
|
QFileSystemWatcher m_watcher;
|
||||||
bool m_is_watching = false;
|
bool m_is_watching = false;
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
#include "minecraft/mod/tasks/BasicFolderLoadTask.h"
|
#include "minecraft/mod/tasks/BasicFolderLoadTask.h"
|
||||||
#include "minecraft/mod/tasks/LocalResourcePackParseTask.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)
|
: ResourceFolderModel(QDir(dir), instance)
|
||||||
{
|
{
|
||||||
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE };
|
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE };
|
||||||
|
@ -17,7 +17,7 @@ public:
|
|||||||
NUM_COLUMNS
|
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;
|
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ class ShaderPackFolderModel : public ResourceFolderModel {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ShaderPackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
|
explicit ShaderPackFolderModel(const QString& dir, BaseInstance* instance)
|
||||||
: ResourceFolderModel(QDir(dir), instance)
|
: ResourceFolderModel(QDir(dir), instance)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#include "minecraft/mod/tasks/BasicFolderLoadTask.h"
|
#include "minecraft/mod/tasks/BasicFolderLoadTask.h"
|
||||||
#include "minecraft/mod/tasks/LocalTexturePackParseTask.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)
|
: ResourceFolderModel(QDir(dir), instance)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ class TexturePackFolderModel : public ResourceFolderModel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
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* createUpdateTask() override;
|
||||||
[[nodiscard]] Task* createParseTask(Resource&) override;
|
[[nodiscard]] Task* createParseTask(Resource&) override;
|
||||||
};
|
};
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class QIODevice;
|
class QIODevice;
|
||||||
|
|
||||||
@ -92,6 +93,8 @@ struct ExtraPackData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct IndexedPack {
|
struct IndexedPack {
|
||||||
|
using Ptr = std::shared_ptr<IndexedPack>;
|
||||||
|
|
||||||
QVariant addonId;
|
QVariant addonId;
|
||||||
ResourceProvider provider;
|
ResourceProvider provider;
|
||||||
QString name;
|
QString name;
|
||||||
|
@ -35,7 +35,29 @@ void Flame::FileResolvingTask::executeTask()
|
|||||||
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.get(), data);
|
||||||
m_dljob->addNetAction(dl);
|
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();
|
m_dljob->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +66,7 @@ void Flame::FileResolvingTask::netJobFinished()
|
|||||||
setProgress(1, 3);
|
setProgress(1, 3);
|
||||||
// job to check modrinth for blocked projects
|
// job to check modrinth for blocked projects
|
||||||
m_checkJob.reset(new NetJob("Modrinth check", m_network));
|
m_checkJob.reset(new NetJob("Modrinth check", m_network));
|
||||||
blockedProjects = QMap<File *,QByteArray *>();
|
blockedProjects = QMap<File*, std::shared_ptr<QByteArray>>();
|
||||||
|
|
||||||
QJsonDocument doc;
|
QJsonDocument doc;
|
||||||
QJsonArray array;
|
QJsonArray array;
|
||||||
@ -71,8 +93,8 @@ void Flame::FileResolvingTask::netJobFinished()
|
|||||||
auto hash = out.hash;
|
auto hash = out.hash;
|
||||||
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 = new QByteArray();
|
auto output = std::make_shared<QByteArray>();
|
||||||
auto dl = Net::Download::makeByteArray(QUrl(url), output);
|
auto dl = Net::Download::makeByteArray(QUrl(url), output.get());
|
||||||
QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() {
|
QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() {
|
||||||
out.resolved = true;
|
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();
|
m_checkJob->start();
|
||||||
}
|
}
|
||||||
@ -95,7 +137,6 @@ void Flame::FileResolvingTask::modrinthCheckFinished() {
|
|||||||
auto &out = *it;
|
auto &out = *it;
|
||||||
auto bytes = blockedProjects[out];
|
auto bytes = blockedProjects[out];
|
||||||
if (!out->resolved) {
|
if (!out->resolved) {
|
||||||
delete bytes;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,11 +153,9 @@ void Flame::FileResolvingTask::modrinthCheckFinished() {
|
|||||||
} else {
|
} else {
|
||||||
out->resolved = false;
|
out->resolved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete bytes;
|
|
||||||
}
|
}
|
||||||
//copy to an output list and filter out projects found on modrinth
|
//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();
|
auto it = blockedProjects.keys();
|
||||||
std::copy_if(it.begin(), it.end(), std::back_inserter(*block), [](File *f) {
|
std::copy_if(it.begin(), it.end(), std::back_inserter(*block), [](File *f) {
|
||||||
return !f->resolved;
|
return !f->resolved;
|
||||||
@ -124,32 +163,48 @@ void Flame::FileResolvingTask::modrinthCheckFinished() {
|
|||||||
//Display not found mods early
|
//Display not found mods early
|
||||||
if (!block->empty()) {
|
if (!block->empty()) {
|
||||||
//blocked mods found, we need the slug for displaying.... we need another job :D !
|
//blocked mods found, we need the slug for displaying.... we need another job :D !
|
||||||
auto slugJob = new NetJob("Slug Job", m_network);
|
m_slugJob.reset(new NetJob("Slug Job", m_network));
|
||||||
auto slugs = QVector<QByteArray>(block->size());
|
int index = 0;
|
||||||
auto index = 0;
|
for (auto mod : *block) {
|
||||||
for (auto fileInfo: *block) {
|
auto projectId = mod->projectId;
|
||||||
auto projectId = fileInfo->projectId;
|
auto output = std::make_shared<QByteArray>();
|
||||||
slugs[index] = 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, &slugs[index]);
|
auto dl = Net::Download::makeByteArray(url, output.get());
|
||||||
slugJob->addNetAction(dl);
|
qDebug() << "Fetching url slug for file:" << mod->fileName;
|
||||||
index++;
|
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
|
||||||
connect(slugJob, &NetJob::succeeded, this, [slugs, this, slugJob, block]() {
|
auto json = QJsonDocument::fromJson(*output);
|
||||||
slugJob->deleteLater();
|
|
||||||
auto index = 0;
|
|
||||||
for (const auto &slugResult: slugs) {
|
|
||||||
auto json = QJsonDocument::fromJson(slugResult);
|
|
||||||
auto base = Json::requireString(Json::requireObject(Json::requireObject(Json::requireObject(json),"data"),"links"),
|
auto base = Json::requireString(Json::requireObject(Json::requireObject(Json::requireObject(json),"data"),"links"),
|
||||||
"websiteUrl");
|
"websiteUrl");
|
||||||
auto mod = block->at(index);
|
|
||||||
auto link = QString("%1/download/%2").arg(base, QString::number(mod->fileId));
|
auto link = QString("%1/download/%2").arg(base, QString::number(mod->fileId));
|
||||||
mod->websiteUrl = link;
|
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();
|
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 {
|
} else {
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
}
|
}
|
||||||
|
@ -1,41 +1,37 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "tasks/Task.h"
|
|
||||||
#include "net/NetJob.h"
|
|
||||||
#include "PackManifest.h"
|
#include "PackManifest.h"
|
||||||
|
#include "net/NetJob.h"
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
|
||||||
namespace Flame
|
namespace Flame {
|
||||||
{
|
class FileResolvingTask : public Task {
|
||||||
class FileResolvingTask : public Task
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit FileResolvingTask(const shared_qobject_ptr<QNetworkAccessManager>& network, Flame::Manifest &toProcess);
|
explicit FileResolvingTask(const shared_qobject_ptr<QNetworkAccessManager>& network, Flame::Manifest& toProcess);
|
||||||
virtual ~FileResolvingTask() {};
|
virtual ~FileResolvingTask(){};
|
||||||
|
|
||||||
bool canAbort() const override { return true; }
|
bool canAbort() const override { return true; }
|
||||||
bool abort() override;
|
bool abort() override;
|
||||||
|
|
||||||
const Flame::Manifest &getResults() const
|
const Flame::Manifest& getResults() const { return m_toProcess; }
|
||||||
{
|
|
||||||
return m_toProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void executeTask() override;
|
virtual void executeTask() override;
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void netJobFinished();
|
void netJobFinished();
|
||||||
|
|
||||||
private: /* data */
|
private: /* data */
|
||||||
shared_qobject_ptr<QNetworkAccessManager> m_network;
|
shared_qobject_ptr<QNetworkAccessManager> m_network;
|
||||||
Flame::Manifest m_toProcess;
|
Flame::Manifest m_toProcess;
|
||||||
std::shared_ptr<QByteArray> result;
|
std::shared_ptr<QByteArray> result;
|
||||||
NetJob::Ptr m_dljob;
|
NetJob::Ptr m_dljob;
|
||||||
NetJob::Ptr m_checkJob;
|
NetJob::Ptr m_checkJob;
|
||||||
|
NetJob::Ptr m_slugJob;
|
||||||
|
|
||||||
void modrinthCheckFinished();
|
void modrinthCheckFinished();
|
||||||
|
|
||||||
QMap<File *, QByteArray *> blockedProjects;
|
QMap<File*, std::shared_ptr<QByteArray>> blockedProjects;
|
||||||
};
|
};
|
||||||
}
|
} // namespace Flame
|
||||||
|
@ -38,14 +38,14 @@ auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString
|
|||||||
QEventLoop lock;
|
QEventLoop lock;
|
||||||
QString changelog;
|
QString changelog;
|
||||||
|
|
||||||
auto* netJob = new NetJob(QString("Flame::FileChangelog"), APPLICATION->network());
|
auto netJob = makeShared<NetJob>(QString("Flame::FileChangelog"), APPLICATION->network());
|
||||||
auto* response = new QByteArray();
|
auto response = std::make_shared<QByteArray>();
|
||||||
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));
|
response.get()));
|
||||||
|
|
||||||
QObject::connect(netJob, &NetJob::succeeded, [netJob, response, &changelog] {
|
QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &changelog] {
|
||||||
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) {
|
||||||
@ -60,10 +60,7 @@ auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString
|
|||||||
changelog = Json::ensureString(doc.object(), "data");
|
changelog = Json::ensureString(doc.object(), "data");
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(netJob, &NetJob::finished, [response, &lock] {
|
QObject::connect(netJob.get(), &NetJob::finished, [&lock] { lock.quit(); });
|
||||||
delete response;
|
|
||||||
lock.quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
netJob->start();
|
netJob->start();
|
||||||
lock.exec();
|
lock.exec();
|
||||||
@ -76,13 +73,12 @@ auto FlameAPI::getModDescription(int modId) -> QString
|
|||||||
QEventLoop lock;
|
QEventLoop lock;
|
||||||
QString description;
|
QString description;
|
||||||
|
|
||||||
auto* netJob = new NetJob(QString("Flame::ModDescription"), APPLICATION->network());
|
auto netJob = makeShared<NetJob>(QString("Flame::ModDescription"), APPLICATION->network());
|
||||||
auto* response = new QByteArray();
|
auto response = std::make_shared<QByteArray>();
|
||||||
netJob->addNetAction(Net::Download::makeByteArray(
|
netJob->addNetAction(Net::Download::makeByteArray(
|
||||||
QString("https://api.curseforge.com/v1/mods/%1/description")
|
QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response.get()));
|
||||||
.arg(QString::number(modId)), response));
|
|
||||||
|
|
||||||
QObject::connect(netJob, &NetJob::succeeded, [netJob, response, &description] {
|
QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] {
|
||||||
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) {
|
||||||
@ -97,10 +93,7 @@ auto FlameAPI::getModDescription(int modId) -> QString
|
|||||||
description = Json::ensureString(doc.object(), "data");
|
description = Json::ensureString(doc.object(), "data");
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(netJob, &NetJob::finished, [response, &lock] {
|
QObject::connect(netJob.get(), &NetJob::finished, [&lock] { lock.quit(); });
|
||||||
delete response;
|
|
||||||
lock.quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
netJob->start();
|
netJob->start();
|
||||||
lock.exec();
|
lock.exec();
|
||||||
@ -118,13 +111,13 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe
|
|||||||
|
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
|
|
||||||
auto netJob = new NetJob(QString("Flame::GetLatestVersion(%1)").arg(args.pack.name), APPLICATION->network());
|
auto netJob = makeShared<NetJob>(QString("Flame::GetLatestVersion(%1)").arg(args.pack.name), APPLICATION->network());
|
||||||
auto response = new QByteArray();
|
auto response = std::make_shared<QByteArray>();
|
||||||
ModPlatform::IndexedVersion ver;
|
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{};
|
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) {
|
||||||
@ -158,11 +151,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(netJob, &NetJob::finished, [response, netJob, &loop] {
|
QObject::connect(netJob.get(), &NetJob::finished, [&loop] { loop.quit(); });
|
||||||
netJob->deleteLater();
|
|
||||||
delete response;
|
|
||||||
loop.quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
netJob->start();
|
netJob->start();
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "FlameModIndex.h"
|
#include "FlameModIndex.h"
|
||||||
|
|
||||||
#include <MurmurHash2.h>
|
#include <MurmurHash2.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
@ -156,15 +157,15 @@ void FlameCheckUpdate::executeTask()
|
|||||||
|
|
||||||
if (!latest_ver.hash.isEmpty() && (mod->metadata()->hash != latest_ver.hash || mod->status() == ModStatus::NotInstalled)) {
|
if (!latest_ver.hash.isEmpty() && (mod->metadata()->hash != latest_ver.hash || mod->status() == ModStatus::NotInstalled)) {
|
||||||
// Fake pack with the necessary info to pass to the download task :)
|
// Fake pack with the necessary info to pass to the download task :)
|
||||||
ModPlatform::IndexedPack pack;
|
auto pack = std::make_shared<ModPlatform::IndexedPack>();
|
||||||
pack.name = mod->name();
|
pack->name = mod->name();
|
||||||
pack.slug = mod->metadata()->slug;
|
pack->slug = mod->metadata()->slug;
|
||||||
pack.addonId = mod->metadata()->project_id;
|
pack->addonId = mod->metadata()->project_id;
|
||||||
pack.websiteUrl = mod->homeurl();
|
pack->websiteUrl = mod->homeurl();
|
||||||
for (auto& author : mod->authors())
|
for (auto& author : mod->authors())
|
||||||
pack.authors.append({ author });
|
pack->authors.append({ author });
|
||||||
pack.description = mod->description();
|
pack->description = mod->description();
|
||||||
pack.provider = ModPlatform::ResourceProvider::FLAME;
|
pack->provider = ModPlatform::ResourceProvider::FLAME;
|
||||||
|
|
||||||
auto old_version = mod->version();
|
auto old_version = mod->version();
|
||||||
if (old_version.isEmpty() && mod->status() != ModStatus::NotInstalled) {
|
if (old_version.isEmpty() && mod->status() != ModStatus::NotInstalled) {
|
||||||
@ -173,7 +174,7 @@ void FlameCheckUpdate::executeTask()
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto download_task = makeShared<ResourceDownloadTask>(pack, latest_ver, m_mods_folder);
|
auto download_task = makeShared<ResourceDownloadTask>(pack, latest_ver, m_mods_folder);
|
||||||
m_updatable.emplace_back(pack.name, mod->metadata()->hash, old_version, latest_ver.version,
|
m_updatable.emplace_back(pack->name, mod->metadata()->hash, old_version, latest_ver.version,
|
||||||
api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()),
|
api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()),
|
||||||
ModPlatform::ResourceProvider::FLAME, download_task);
|
ModPlatform::ResourceProvider::FLAME, download_task);
|
||||||
}
|
}
|
||||||
|
@ -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::progress, this, &FlameCreationTask::setProgress);
|
||||||
connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::status, this, &FlameCreationTask::setStatus);
|
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::stepProgress, this, &FlameCreationTask::propogateStepProgress);
|
||||||
|
connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::details, this, &FlameCreationTask::setDetails);
|
||||||
m_mod_id_resolver->start();
|
m_mod_id_resolver->start();
|
||||||
|
|
||||||
loop.exec();
|
loop.exec();
|
||||||
|
@ -24,7 +24,7 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&
|
|||||||
|
|
||||||
netJob->addNetAction(Net::Download::makeByteArray(QUrl(search_url), response));
|
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{};
|
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) {
|
||||||
@ -40,14 +40,15 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks&
|
|||||||
callbacks.on_succeed(doc);
|
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;
|
int network_error_code = -1;
|
||||||
if (auto* failed_action = netJob->getFailedActions().at(0); failed_action && failed_action->m_reply)
|
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();
|
network_error_code = failed_action->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
|
||||||
callbacks.on_fail(reason, network_error_code);
|
callbacks.on_fail(reason, network_error_code);
|
||||||
});
|
});
|
||||||
QObject::connect(netJob.get(), &NetJob::aborted, [=] { callbacks.on_abort(); });
|
QObject::connect(netJob.get(), &NetJob::aborted, [callbacks] { callbacks.on_abort(); });
|
||||||
|
QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; });
|
||||||
|
|
||||||
return netJob;
|
return netJob;
|
||||||
}
|
}
|
||||||
@ -86,7 +87,7 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi
|
|||||||
|
|
||||||
netJob->addNetAction(Net::Download::makeByteArray(versions_url, response));
|
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{};
|
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) {
|
||||||
|
@ -54,7 +54,7 @@ void ModrinthCheckUpdate::executeTask()
|
|||||||
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(), &Task::succeeded, [&] {
|
||||||
QString hash (hash_task->getResult());
|
QString hash(hash_task->getResult());
|
||||||
hashes.append(hash);
|
hashes.append(hash);
|
||||||
mappings.insert(hash, mod);
|
mappings.insert(hash, mod);
|
||||||
});
|
});
|
||||||
@ -67,7 +67,7 @@ void ModrinthCheckUpdate::executeTask()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
connect(&hashing_task, &Task::finished, [&loop]{ loop.quit(); });
|
connect(&hashing_task, &Task::finished, [&loop] { loop.quit(); });
|
||||||
hashing_task.start();
|
hashing_task.start();
|
||||||
loop.exec();
|
loop.exec();
|
||||||
|
|
||||||
@ -112,7 +112,8 @@ void ModrinthCheckUpdate::executeTask()
|
|||||||
// so we may want to filter it
|
// so we may want to filter it
|
||||||
QString loader_filter;
|
QString loader_filter;
|
||||||
if (m_loaders.has_value()) {
|
if (m_loaders.has_value()) {
|
||||||
static auto flags = { ResourceAPI::ModLoaderType::Forge, ResourceAPI::ModLoaderType::Fabric, ResourceAPI::ModLoaderType::Quilt };
|
static auto flags = { ResourceAPI::ModLoaderType::Forge, ResourceAPI::ModLoaderType::Fabric,
|
||||||
|
ResourceAPI::ModLoaderType::Quilt };
|
||||||
for (auto flag : flags) {
|
for (auto flag : flags) {
|
||||||
if (m_loaders.value().testFlag(flag)) {
|
if (m_loaders.value().testFlag(flag)) {
|
||||||
loader_filter = api.getModLoaderString(flag);
|
loader_filter = api.getModLoaderString(flag);
|
||||||
@ -122,7 +123,8 @@ void ModrinthCheckUpdate::executeTask()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Currently, we rely on a couple heuristics to determine whether an update is actually available or not:
|
// Currently, we rely on a couple heuristics to determine whether an update is actually available or not:
|
||||||
// - The file needs to be preferred: It is either the primary file, or the one found via (explicit) usage of the loader_filter
|
// - The file needs to be preferred: It is either the primary file, or the one found via (explicit) usage of the
|
||||||
|
// loader_filter
|
||||||
// - The version reported by the JAR is different from the version reported by the indexed version (it's usually the case)
|
// - The version reported by the JAR is different from the version reported by the indexed version (it's usually the case)
|
||||||
// Such is the pain of having arbitrary files for a given version .-.
|
// Such is the pain of having arbitrary files for a given version .-.
|
||||||
|
|
||||||
@ -149,19 +151,19 @@ void ModrinthCheckUpdate::executeTask()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Fake pack with the necessary info to pass to the download task :)
|
// Fake pack with the necessary info to pass to the download task :)
|
||||||
ModPlatform::IndexedPack pack;
|
auto pack = std::make_shared<ModPlatform::IndexedPack>();
|
||||||
pack.name = mod->name();
|
pack->name = mod->name();
|
||||||
pack.slug = mod->metadata()->slug;
|
pack->slug = mod->metadata()->slug;
|
||||||
pack.addonId = mod->metadata()->project_id;
|
pack->addonId = mod->metadata()->project_id;
|
||||||
pack.websiteUrl = mod->homeurl();
|
pack->websiteUrl = mod->homeurl();
|
||||||
for (auto& author : mod->authors())
|
for (auto& author : mod->authors())
|
||||||
pack.authors.append({ author });
|
pack->authors.append({ author });
|
||||||
pack.description = mod->description();
|
pack->description = mod->description();
|
||||||
pack.provider = ModPlatform::ResourceProvider::MODRINTH;
|
pack->provider = ModPlatform::ResourceProvider::MODRINTH;
|
||||||
|
|
||||||
auto download_task = makeShared<ResourceDownloadTask>(pack, project_ver, m_mods_folder);
|
auto download_task = makeShared<ResourceDownloadTask>(pack, project_ver, m_mods_folder);
|
||||||
|
|
||||||
m_updatable.emplace_back(pack.name, hash, mod->version(), project_ver.version_number, project_ver.changelog,
|
m_updatable.emplace_back(pack->name, hash, mod->version(), project_ver.version_number, project_ver.changelog,
|
||||||
ModPlatform::ResourceProvider::MODRINTH, download_task);
|
ModPlatform::ResourceProvider::MODRINTH, download_task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,11 +134,14 @@ void Download::executeTask()
|
|||||||
request.setRawHeader("Authorization", token.toUtf8());
|
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_time = m_clock.now();
|
||||||
m_last_progress_bytes = 0;
|
m_last_progress_bytes = 0;
|
||||||
|
|
||||||
QNetworkReply* rep = m_network->get(request);
|
QNetworkReply* rep = m_network->get(request);
|
||||||
|
|
||||||
m_reply.reset(rep);
|
m_reply.reset(rep);
|
||||||
connect(rep, &QNetworkReply::downloadProgress, this, &Download::downloadProgress);
|
connect(rep, &QNetworkReply::downloadProgress, this, &Download::downloadProgress);
|
||||||
connect(rep, &QNetworkReply::finished, this, &Download::downloadFinished);
|
connect(rep, &QNetworkReply::finished, this, &Download::downloadFinished);
|
||||||
|
@ -138,7 +138,7 @@ void ConcurrentTask::startNext()
|
|||||||
connect(next.get(), &Task::progress, this, [this, next](qint64 current, qint64 total) { subTaskProgress(next, current, total); });
|
connect(next.get(), &Task::progress, this, [this, next](qint64 current, qint64 total) { subTaskProgress(next, current, total); });
|
||||||
|
|
||||||
m_doing.insert(next.get(), next);
|
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);
|
m_task_progress.insert(next->getUid(), task_progress);
|
||||||
|
|
||||||
updateState();
|
updateState();
|
||||||
@ -166,9 +166,9 @@ void ConcurrentTask::subTaskSucceeded(Task::Ptr task)
|
|||||||
|
|
||||||
disconnect(task.get(), 0, this, 0);
|
disconnect(task.get(), 0, this, 0);
|
||||||
|
|
||||||
emit stepProgress(*task_progress.get());
|
emit stepProgress(*task_progress);
|
||||||
updateState();
|
updateState();
|
||||||
updateStepProgress(*task_progress.get(), Operation::REMOVED);
|
updateStepProgress(*task_progress, Operation::REMOVED);
|
||||||
startNext();
|
startNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,9 +184,9 @@ void ConcurrentTask::subTaskFailed(Task::Ptr task, const QString& msg)
|
|||||||
|
|
||||||
disconnect(task.get(), 0, this, 0);
|
disconnect(task.get(), 0, this, 0);
|
||||||
|
|
||||||
emit stepProgress(*task_progress.get());
|
emit stepProgress(*task_progress);
|
||||||
updateState();
|
updateState();
|
||||||
updateStepProgress(*task_progress.get(), Operation::REMOVED);
|
updateStepProgress(*task_progress, Operation::REMOVED);
|
||||||
startNext();
|
startNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ void ConcurrentTask::subTaskStatus(Task::Ptr task, const QString& msg)
|
|||||||
task_progress->status = msg;
|
task_progress->status = msg;
|
||||||
task_progress->state = TaskStepState::Running;
|
task_progress->state = TaskStepState::Running;
|
||||||
|
|
||||||
emit stepProgress(*task_progress.get());
|
emit stepProgress(*task_progress);
|
||||||
|
|
||||||
if (totalSize() == 1) {
|
if (totalSize() == 1) {
|
||||||
setStatus(msg);
|
setStatus(msg);
|
||||||
@ -209,7 +209,7 @@ void ConcurrentTask::subTaskDetails(Task::Ptr task, const QString& msg)
|
|||||||
task_progress->details = msg;
|
task_progress->details = msg;
|
||||||
task_progress->state = TaskStepState::Running;
|
task_progress->state = TaskStepState::Running;
|
||||||
|
|
||||||
emit stepProgress(*task_progress.get());
|
emit stepProgress(*task_progress);
|
||||||
|
|
||||||
if (totalSize() == 1) {
|
if (totalSize() == 1) {
|
||||||
setDetails(msg);
|
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());
|
auto task_progress = m_task_progress.value(task->getUid());
|
||||||
|
|
||||||
task_progress->old_current = task_progress->current;
|
task_progress->update(current, total);
|
||||||
task_progress->old_total = task_progress->old_total;
|
|
||||||
|
|
||||||
task_progress->current = current;
|
emit stepProgress(*task_progress);
|
||||||
task_progress->total = total;
|
updateStepProgress(*task_progress, Operation::CHANGED);
|
||||||
task_progress->state = TaskStepState::Running;
|
|
||||||
|
|
||||||
emit stepProgress(*task_progress.get());
|
|
||||||
updateStepProgress(*task_progress.get(), Operation::CHANGED);
|
|
||||||
updateState();
|
updateState();
|
||||||
|
|
||||||
if (totalSize() == 1) {
|
if (totalSize() == 1) {
|
||||||
|
@ -109,7 +109,7 @@ void Task::start()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// NOTE: only fall thorugh to here in end states
|
// NOTE: only fall through to here in end states
|
||||||
m_state = State::Running;
|
m_state = State::Running;
|
||||||
emit started();
|
emit started();
|
||||||
executeTask();
|
executeTask();
|
||||||
|
@ -64,7 +64,21 @@ struct TaskStepProgress {
|
|||||||
QString status = "";
|
QString status = "";
|
||||||
QString details = "";
|
QString details = "";
|
||||||
TaskStepState state = TaskStepState::Waiting;
|
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); }
|
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)
|
Q_DECLARE_METATYPE(TaskStepProgress)
|
||||||
|
@ -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.
|
// 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_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->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding);
|
||||||
m_container->layout()->setContentsMargins(0, 0, 0, 0);
|
m_container->layout()->setContentsMargins(0, 0, 0, 0);
|
||||||
ui->verticalLayout->insertWidget(2, m_container);
|
ui->verticalLayout->insertWidget(2, m_container);
|
||||||
|
@ -99,7 +99,7 @@ void ResourceDownloadDialog::reject()
|
|||||||
// won't work with subclasses if we put it in this ctor.
|
// won't work with subclasses if we put it in this ctor.
|
||||||
void ResourceDownloadDialog::initializeContainer()
|
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->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding);
|
||||||
m_container->layout()->setContentsMargins(0, 0, 0, 0);
|
m_container->layout()->setContentsMargins(0, 0, 0, 0);
|
||||||
m_vertical_layout.addWidget(m_container);
|
m_vertical_layout.addWidget(m_container);
|
||||||
@ -204,9 +204,9 @@ ResourcePage* ResourceDownloadDialog::getSelectedPage()
|
|||||||
return m_selectedPage;
|
return m_selectedPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver)
|
void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& ver)
|
||||||
{
|
{
|
||||||
removeResource(pack.name);
|
removeResource(pack->name);
|
||||||
m_selectedPage->addResourceToPage(pack, ver, getBaseModel());
|
m_selectedPage->addResourceToPage(pack, ver, getBaseModel());
|
||||||
setButtonStatus();
|
setButtonStatus();
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider {
|
|||||||
bool selectPage(QString pageId);
|
bool selectPage(QString pageId);
|
||||||
ResourcePage* getSelectedPage();
|
ResourcePage* getSelectedPage();
|
||||||
|
|
||||||
void addResource(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
|
void addResource(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&);
|
||||||
void removeResource(const QString&);
|
void removeResource(const QString&);
|
||||||
|
|
||||||
const QList<DownloadTaskPtr> getTasks();
|
const QList<DownloadTaskPtr> getTasks();
|
||||||
|
@ -30,8 +30,6 @@ class NoBigComboBoxStyle : public QProxyStyle {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NoBigComboBoxStyle(QStyle* style) : QProxyStyle(style) {}
|
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
int styleHint(QStyle::StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override
|
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);
|
return QProxyStyle::styleHint(hint, option, widget, returnData);
|
||||||
}
|
}
|
||||||
// clang-format on
|
// 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)
|
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.
|
// NOTE: GTK2 themes crash with the proxy style.
|
||||||
// This seems like an upstream bug, so there's not much else that can be done.
|
// This seems like an upstream bug, so there's not much else that can be done.
|
||||||
if (!QStyleFactory::keys().contains("gtk2"))
|
if (!QStyleFactory::keys().contains("gtk2")){
|
||||||
ui->versionsComboBox->setStyle(new NoBigComboBoxStyle(ui->versionsComboBox->style()));
|
auto comboStyle = NoBigComboBoxStyle::getInstance(ui->versionsComboBox->style());
|
||||||
|
ui->versionsComboBox->setStyle(comboStyle);
|
||||||
|
}
|
||||||
|
|
||||||
ui->reloadButton->setVisible(false);
|
ui->reloadButton->setVisible(false);
|
||||||
connect(ui->reloadButton, &QPushButton::clicked, this, [this](bool){
|
connect(ui->reloadButton, &QPushButton::clicked, this, [this](bool){
|
||||||
|
@ -165,7 +165,7 @@ VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent)
|
|||||||
auto proxy = new IconProxy(ui->packageView);
|
auto proxy = new IconProxy(ui->packageView);
|
||||||
proxy->setSourceModel(m_profile.get());
|
proxy->setSourceModel(m_profile.get());
|
||||||
|
|
||||||
m_filterModel = new QSortFilterProxyModel();
|
m_filterModel = new QSortFilterProxyModel(this);
|
||||||
m_filterModel->setDynamicSortFilter(true);
|
m_filterModel->setDynamicSortFilter(true);
|
||||||
m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||||
m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
@ -36,7 +36,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
|
|||||||
|
|
||||||
ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& entry)
|
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();
|
auto profile = static_cast<MinecraftInstance const&>(m_base_instance).getPackProfile();
|
||||||
|
|
||||||
Q_ASSERT(profile);
|
Q_ASSERT(profile);
|
||||||
@ -51,7 +51,7 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en
|
|||||||
|
|
||||||
ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry)
|
ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry)
|
||||||
{
|
{
|
||||||
auto& pack = m_packs[entry.row()];
|
auto& pack = *m_packs[entry.row()];
|
||||||
return { pack };
|
return { pack };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,8 +122,8 @@ void ModPage::updateVersionList()
|
|||||||
QString mcVersion = packProfile->getComponentVersion("net.minecraft");
|
QString mcVersion = packProfile->getComponentVersion("net.minecraft");
|
||||||
|
|
||||||
auto current_pack = getCurrentPack();
|
auto current_pack = getCurrentPack();
|
||||||
for (int i = 0; i < current_pack.versions.size(); i++) {
|
for (int i = 0; i < current_pack->versions.size(); i++) {
|
||||||
auto version = current_pack.versions[i];
|
auto version = current_pack->versions[i];
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
for (auto& mcVer : m_filter->versions) {
|
for (auto& mcVer : m_filter->versions) {
|
||||||
// NOTE: Flame doesn't care about loader, so passing it changes nothing.
|
// NOTE: Flame doesn't care about loader, so passing it changes nothing.
|
||||||
@ -145,7 +145,7 @@ void ModPage::updateVersionList()
|
|||||||
updateSelectionButton();
|
updateSelectionButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModPage::addResourceToPage(ModPlatform::IndexedPack& pack,
|
void ModPage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack,
|
||||||
ModPlatform::IndexedVersion& version,
|
ModPlatform::IndexedVersion& version,
|
||||||
const std::shared_ptr<ResourceFolderModel> base_model)
|
const std::shared_ptr<ResourceFolderModel> base_model)
|
||||||
{
|
{
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
#include "modplatform/ModIndex.h"
|
#include "modplatform/ModIndex.h"
|
||||||
|
|
||||||
#include "ui/pages/modplatform/ResourcePage.h"
|
|
||||||
#include "ui/pages/modplatform/ModModel.h"
|
#include "ui/pages/modplatform/ModModel.h"
|
||||||
|
#include "ui/pages/modplatform/ResourcePage.h"
|
||||||
#include "ui/widgets/ModFilterWidget.h"
|
#include "ui/widgets/ModFilterWidget.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
@ -25,13 +25,14 @@ class ModPage : public ResourcePage {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
template <typename T>
|
||||||
static T* create(ModDownloadDialog* dialog, BaseInstance& instance)
|
static T* create(ModDownloadDialog* dialog, BaseInstance& instance)
|
||||||
{
|
{
|
||||||
auto page = new T(dialog, instance);
|
auto page = new T(dialog, instance);
|
||||||
auto model = static_cast<ModModel*>(page->getModel());
|
auto model = static_cast<ModModel*>(page->getModel());
|
||||||
|
|
||||||
auto filter_widget = ModFilterWidget::create(static_cast<MinecraftInstance&>(instance).getPackProfile()->getComponentVersion("net.minecraft"), page);
|
auto filter_widget =
|
||||||
|
ModFilterWidget::create(static_cast<MinecraftInstance&>(instance).getPackProfile()->getComponentVersion("net.minecraft"), page);
|
||||||
page->setFilterWidget(filter_widget);
|
page->setFilterWidget(filter_widget);
|
||||||
model->setFilter(page->getFilter());
|
model->setFilter(page->getFilter());
|
||||||
|
|
||||||
@ -41,8 +42,6 @@ class ModPage : public ResourcePage {
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ModPage() override = default;
|
|
||||||
|
|
||||||
//: The plural version of 'mod'
|
//: The plural version of 'mod'
|
||||||
[[nodiscard]] inline QString resourcesString() const override { return tr("mods"); }
|
[[nodiscard]] inline QString resourcesString() const override { return tr("mods"); }
|
||||||
//: The singular version of 'mods'
|
//: The singular version of 'mods'
|
||||||
@ -50,9 +49,13 @@ class ModPage : public ResourcePage {
|
|||||||
|
|
||||||
[[nodiscard]] QMap<QString, QString> urlHandlers() const override;
|
[[nodiscard]] QMap<QString, QString> urlHandlers() const override;
|
||||||
|
|
||||||
void addResourceToPage(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, const std::shared_ptr<ResourceFolderModel>) override;
|
void addResourceToPage(ModPlatform::IndexedPack::Ptr,
|
||||||
|
ModPlatform::IndexedVersion&,
|
||||||
|
const std::shared_ptr<ResourceFolderModel>) override;
|
||||||
|
|
||||||
virtual auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional<ResourceAPI::ModLoaderTypes> loaders = {}) const -> bool = 0;
|
virtual auto validateVersion(ModPlatform::IndexedVersion& ver,
|
||||||
|
QString mineVer,
|
||||||
|
std::optional<ResourceAPI::ModLoaderTypes> loaders = {}) const -> bool = 0;
|
||||||
|
|
||||||
[[nodiscard]] bool supportsFiltering() const override { return true; };
|
[[nodiscard]] bool supportsFiltering() const override { return true; };
|
||||||
auto getFilter() const -> const std::shared_ptr<ModFilterWidget::Filter> { return m_filter; }
|
auto getFilter() const -> const std::shared_ptr<ModFilterWidget::Filter> { return m_filter; }
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <QPixmapCache>
|
#include <QPixmapCache>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "BuildConfig.h"
|
#include "BuildConfig.h"
|
||||||
@ -47,16 +48,16 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant
|
|||||||
auto pack = m_packs.at(pos);
|
auto pack = m_packs.at(pos);
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Qt::ToolTipRole: {
|
case 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;
|
||||||
}
|
}
|
||||||
case Qt::DecorationRole: {
|
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())
|
icon_or_none.has_value())
|
||||||
return icon_or_none.value();
|
return icon_or_none.value();
|
||||||
|
|
||||||
@ -71,11 +72,11 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant
|
|||||||
}
|
}
|
||||||
// Custom data
|
// Custom data
|
||||||
case UserDataTypes::TITLE:
|
case UserDataTypes::TITLE:
|
||||||
return pack.name;
|
return pack->name;
|
||||||
case UserDataTypes::DESCRIPTION:
|
case UserDataTypes::DESCRIPTION:
|
||||||
return pack.description;
|
return pack->description;
|
||||||
case UserDataTypes::SELECTED:
|
case UserDataTypes::SELECTED:
|
||||||
return pack.isAnyVersionSelected();
|
return pack->isAnyVersionSelected();
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -104,7 +105,7 @@ bool ResourceModel::setData(const QModelIndex& index, const QVariant& value, int
|
|||||||
if (pos >= m_packs.size() || pos < 0 || !index.isValid())
|
if (pos >= m_packs.size() || pos < 0 || !index.isValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_packs[pos] = value.value<ModPlatform::IndexedPack>();
|
m_packs[pos] = value.value<ModPlatform::IndexedPack::Ptr>();
|
||||||
emit dataChanged(index, index);
|
emit dataChanged(index, index);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -163,7 +164,7 @@ void ResourceModel::loadEntry(QModelIndex& entry)
|
|||||||
if (!hasActiveInfoJob())
|
if (!hasActiveInfoJob())
|
||||||
m_current_info_job.clear();
|
m_current_info_job.clear();
|
||||||
|
|
||||||
if (!pack.versionsLoaded) {
|
if (!pack->versionsLoaded) {
|
||||||
auto args{ createVersionsArguments(entry) };
|
auto args{ createVersionsArguments(entry) };
|
||||||
auto callbacks{ createVersionsCallbacks(entry) };
|
auto callbacks{ createVersionsCallbacks(entry) };
|
||||||
|
|
||||||
@ -179,7 +180,7 @@ void ResourceModel::loadEntry(QModelIndex& entry)
|
|||||||
runInfoJob(job);
|
runInfoJob(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pack.extraDataLoaded) {
|
if (!pack->extraDataLoaded) {
|
||||||
auto args{ createInfoArguments(entry) };
|
auto args{ createInfoArguments(entry) };
|
||||||
auto callbacks{ createInfoCallbacks(entry) };
|
auto callbacks{ createInfoCallbacks(entry) };
|
||||||
|
|
||||||
@ -231,7 +232,7 @@ void ResourceModel::clearData()
|
|||||||
|
|
||||||
void ResourceModel::runSearchJob(Task::Ptr ptr)
|
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();
|
m_current_search_job->start();
|
||||||
}
|
}
|
||||||
void ResourceModel::runInfoJob(Task::Ptr ptr)
|
void ResourceModel::runInfoJob(Task::Ptr ptr)
|
||||||
@ -328,19 +329,19 @@ void ResourceModel::loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArra
|
|||||||
|
|
||||||
void ResourceModel::searchRequestSucceeded(QJsonDocument& doc)
|
void ResourceModel::searchRequestSucceeded(QJsonDocument& doc)
|
||||||
{
|
{
|
||||||
QList<ModPlatform::IndexedPack> newList;
|
QList<ModPlatform::IndexedPack::Ptr> newList;
|
||||||
auto packs = documentToArray(doc);
|
auto packs = documentToArray(doc);
|
||||||
|
|
||||||
for (auto packRaw : packs) {
|
for (auto packRaw : packs) {
|
||||||
auto packObj = packRaw.toObject();
|
auto packObj = packRaw.toObject();
|
||||||
|
|
||||||
ModPlatform::IndexedPack pack;
|
ModPlatform::IndexedPack::Ptr pack = std::make_shared<ModPlatform::IndexedPack>();
|
||||||
try {
|
try {
|
||||||
loadIndexedPack(pack, packObj);
|
loadIndexedPack(*pack, packObj);
|
||||||
if (auto sel = std::find_if(m_selected.begin(), m_selected.end(),
|
if (auto sel = std::find_if(m_selected.begin(), m_selected.end(),
|
||||||
[&pack](const DownloadTaskPtr i) {
|
[&pack](const DownloadTaskPtr i) {
|
||||||
const auto ipack = i->getPack();
|
const auto ipack = i->getPack();
|
||||||
return ipack.provider == pack.provider && ipack.addonId == pack.addonId;
|
return ipack->provider == pack->provider && ipack->addonId == pack->addonId;
|
||||||
});
|
});
|
||||||
sel != m_selected.end()) {
|
sel != m_selected.end()) {
|
||||||
newList.append(sel->get()->getPack());
|
newList.append(sel->get()->getPack());
|
||||||
@ -399,15 +400,15 @@ void ResourceModel::searchRequestAborted()
|
|||||||
|
|
||||||
void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index)
|
void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index)
|
||||||
{
|
{
|
||||||
auto current_pack = data(index, Qt::UserRole).value<ModPlatform::IndexedPack>();
|
auto current_pack = data(index, Qt::UserRole).value<ModPlatform::IndexedPack::Ptr>();
|
||||||
|
|
||||||
// Check if the index is still valid for this resource or not
|
// Check if the index is still valid for this resource or not
|
||||||
if (pack.addonId != current_pack.addonId)
|
if (pack.addonId != current_pack->addonId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
|
auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
|
||||||
loadIndexedPackVersions(current_pack, arr);
|
loadIndexedPackVersions(*current_pack, arr);
|
||||||
} catch (const JSONValidationError& e) {
|
} catch (const JSONValidationError& e) {
|
||||||
qDebug() << doc;
|
qDebug() << doc;
|
||||||
qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause();
|
qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause();
|
||||||
@ -426,15 +427,15 @@ void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::Ind
|
|||||||
|
|
||||||
void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index)
|
void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index)
|
||||||
{
|
{
|
||||||
auto current_pack = data(index, Qt::UserRole).value<ModPlatform::IndexedPack>();
|
auto current_pack = data(index, Qt::UserRole).value<ModPlatform::IndexedPack::Ptr>();
|
||||||
|
|
||||||
// Check if the index is still valid for this resource or not
|
// Check if the index is still valid for this resource or not
|
||||||
if (pack.addonId != current_pack.addonId)
|
if (pack.addonId != current_pack->addonId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto obj = Json::requireObject(doc);
|
auto obj = Json::requireObject(doc);
|
||||||
loadExtraPackInfo(current_pack, obj);
|
loadExtraPackInfo(*current_pack, obj);
|
||||||
} catch (const JSONValidationError& e) {
|
} catch (const JSONValidationError& e) {
|
||||||
qDebug() << doc;
|
qDebug() << doc;
|
||||||
qWarning() << "Error while reading " << debugName() << " resource info: " << e.cause();
|
qWarning() << "Error while reading " << debugName() << " resource info: " << e.cause();
|
||||||
@ -451,7 +452,7 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe
|
|||||||
emit projectInfoUpdated();
|
emit projectInfoUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceModel::addPack(ModPlatform::IndexedPack& pack,
|
void ResourceModel::addPack(ModPlatform::IndexedPack::Ptr pack,
|
||||||
ModPlatform::IndexedVersion& version,
|
ModPlatform::IndexedVersion& version,
|
||||||
const std::shared_ptr<ResourceFolderModel> packs,
|
const std::shared_ptr<ResourceFolderModel> packs,
|
||||||
bool is_indexed,
|
bool is_indexed,
|
||||||
@ -475,14 +476,14 @@ void ResourceModel::removePack(const QString& rem)
|
|||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](const ModPlatform::IndexedPack& i) { return rem == i.name; });
|
auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](const ModPlatform::IndexedPack::Ptr i) { return rem == i->name; });
|
||||||
if (pack == m_packs.end()) { // ignore it if is not in the current search
|
if (pack == m_packs.end()) { // ignore it if is not in the current search
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!pack->versionsLoaded) {
|
if (!pack->get()->versionsLoaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (auto& ver : pack->versions)
|
for (auto& ver : pack->get()->versions)
|
||||||
ver.is_currently_selected = false;
|
ver.is_currently_selected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ class ResourceModel : public QAbstractListModel {
|
|||||||
/** Gets the icon at the URL for the given index. If it's not fetched yet, fetch it and update when fisinhed. */
|
/** Gets the icon at the URL for the given index. If it's not fetched yet, fetch it and update when fisinhed. */
|
||||||
std::optional<QIcon> getIcon(QModelIndex&, const QUrl&);
|
std::optional<QIcon> getIcon(QModelIndex&, const QUrl&);
|
||||||
|
|
||||||
void addPack(ModPlatform::IndexedPack& pack,
|
void addPack(ModPlatform::IndexedPack::Ptr pack,
|
||||||
ModPlatform::IndexedVersion& version,
|
ModPlatform::IndexedVersion& version,
|
||||||
const std::shared_ptr<ResourceFolderModel> packs,
|
const std::shared_ptr<ResourceFolderModel> packs,
|
||||||
bool is_indexed = false,
|
bool is_indexed = false,
|
||||||
@ -134,7 +134,7 @@ class ResourceModel : public QAbstractListModel {
|
|||||||
QSet<QUrl> m_currently_running_icon_actions;
|
QSet<QUrl> m_currently_running_icon_actions;
|
||||||
QSet<QUrl> m_failed_icon_actions;
|
QSet<QUrl> m_failed_icon_actions;
|
||||||
|
|
||||||
QList<ModPlatform::IndexedPack> m_packs;
|
QList<ModPlatform::IndexedPack::Ptr> m_packs;
|
||||||
QList<DownloadTaskPtr> m_selected;
|
QList<DownloadTaskPtr> m_selected;
|
||||||
|
|
||||||
// HACK: We need this to prevent callbacks from calling the model after it has already been deleted.
|
// HACK: We need this to prevent callbacks from calling the model after it has already been deleted.
|
||||||
|
@ -22,13 +22,13 @@ ResourceAPI::SearchArgs ResourcePackResourceModel::createSearchArguments()
|
|||||||
ResourceAPI::VersionSearchArgs ResourcePackResourceModel::createVersionsArguments(QModelIndex& entry)
|
ResourceAPI::VersionSearchArgs ResourcePackResourceModel::createVersionsArguments(QModelIndex& entry)
|
||||||
{
|
{
|
||||||
auto& pack = m_packs[entry.row()];
|
auto& pack = m_packs[entry.row()];
|
||||||
return { pack };
|
return { *pack };
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceAPI::ProjectInfoArgs ResourcePackResourceModel::createInfoArguments(QModelIndex& entry)
|
ResourceAPI::ProjectInfoArgs ResourcePackResourceModel::createInfoArguments(QModelIndex& entry)
|
||||||
{
|
{
|
||||||
auto& pack = m_packs[entry.row()];
|
auto& pack = m_packs[entry.row()];
|
||||||
return { pack };
|
return { *pack };
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourcePackResourceModel::searchWithTerm(const QString& term, unsigned int sort)
|
void ResourcePackResourceModel::searchWithTerm(const QString& term, unsigned int sort)
|
||||||
|
@ -31,8 +31,6 @@ class ResourcePackResourcePage : public ResourcePage {
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ResourcePackResourcePage() override = default;
|
|
||||||
|
|
||||||
//: The plural version of 'resource pack'
|
//: The plural version of 'resource pack'
|
||||||
[[nodiscard]] inline QString resourcesString() const override { return tr("resource packs"); }
|
[[nodiscard]] inline QString resourcesString() const override { return tr("resource packs"); }
|
||||||
//: The singular version of 'resource packs'
|
//: The singular version of 'resource packs'
|
||||||
|
@ -84,6 +84,8 @@ ResourcePage::ResourcePage(ResourceDownloadDialog* parent, BaseInstance& base_in
|
|||||||
ResourcePage::~ResourcePage()
|
ResourcePage::~ResourcePage()
|
||||||
{
|
{
|
||||||
delete m_ui;
|
delete m_ui;
|
||||||
|
if (m_model)
|
||||||
|
delete m_model;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourcePage::retranslate()
|
void ResourcePage::retranslate()
|
||||||
@ -157,16 +159,16 @@ void ResourcePage::addSortings()
|
|||||||
m_ui->sortByBox->addItem(sorting.readable_name, QVariant(sorting.index));
|
m_ui->sortByBox->addItem(sorting.readable_name, QVariant(sorting.index));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourcePage::setCurrentPack(ModPlatform::IndexedPack pack)
|
bool ResourcePage::setCurrentPack(ModPlatform::IndexedPack::Ptr pack)
|
||||||
{
|
{
|
||||||
QVariant v;
|
QVariant v;
|
||||||
v.setValue(pack);
|
v.setValue(pack);
|
||||||
return m_model->setData(m_ui->packView->currentIndex(), v, Qt::UserRole);
|
return m_model->setData(m_ui->packView->currentIndex(), v, Qt::UserRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModPlatform::IndexedPack ResourcePage::getCurrentPack() const
|
ModPlatform::IndexedPack::Ptr ResourcePage::getCurrentPack() const
|
||||||
{
|
{
|
||||||
return m_model->data(m_ui->packView->currentIndex(), Qt::UserRole).value<ModPlatform::IndexedPack>();
|
return m_model->data(m_ui->packView->currentIndex(), Qt::UserRole).value<ModPlatform::IndexedPack::Ptr>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourcePage::updateUi()
|
void ResourcePage::updateUi()
|
||||||
@ -174,14 +176,14 @@ void ResourcePage::updateUi()
|
|||||||
auto current_pack = getCurrentPack();
|
auto current_pack = getCurrentPack();
|
||||||
|
|
||||||
QString text = "";
|
QString text = "";
|
||||||
QString name = current_pack.name;
|
QString name = current_pack->name;
|
||||||
|
|
||||||
if (current_pack.websiteUrl.isEmpty())
|
if (current_pack->websiteUrl.isEmpty())
|
||||||
text = name;
|
text = name;
|
||||||
else
|
else
|
||||||
text = "<a href=\"" + current_pack.websiteUrl + "\">" + name + "</a>";
|
text = "<a href=\"" + current_pack->websiteUrl + "\">" + name + "</a>";
|
||||||
|
|
||||||
if (!current_pack.authors.empty()) {
|
if (!current_pack->authors.empty()) {
|
||||||
auto authorToStr = [](ModPlatform::ModpackAuthor& author) -> QString {
|
auto authorToStr = [](ModPlatform::ModpackAuthor& author) -> QString {
|
||||||
if (author.url.isEmpty()) {
|
if (author.url.isEmpty()) {
|
||||||
return author.name;
|
return author.name;
|
||||||
@ -189,44 +191,44 @@ void ResourcePage::updateUi()
|
|||||||
return QString("<a href=\"%1\">%2</a>").arg(author.url, author.name);
|
return QString("<a href=\"%1\">%2</a>").arg(author.url, author.name);
|
||||||
};
|
};
|
||||||
QStringList authorStrs;
|
QStringList authorStrs;
|
||||||
for (auto& author : current_pack.authors) {
|
for (auto& author : current_pack->authors) {
|
||||||
authorStrs.push_back(authorToStr(author));
|
authorStrs.push_back(authorToStr(author));
|
||||||
}
|
}
|
||||||
text += "<br>" + tr(" by ") + authorStrs.join(", ");
|
text += "<br>" + tr(" by ") + authorStrs.join(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_pack.extraDataLoaded) {
|
if (current_pack->extraDataLoaded) {
|
||||||
if (!current_pack.extraData.donate.isEmpty()) {
|
if (!current_pack->extraData.donate.isEmpty()) {
|
||||||
text += "<br><br>" + tr("Donate information: ");
|
text += "<br><br>" + tr("Donate information: ");
|
||||||
auto donateToStr = [](ModPlatform::DonationData& donate) -> QString {
|
auto donateToStr = [](ModPlatform::DonationData& donate) -> QString {
|
||||||
return QString("<a href=\"%1\">%2</a>").arg(donate.url, donate.platform);
|
return QString("<a href=\"%1\">%2</a>").arg(donate.url, donate.platform);
|
||||||
};
|
};
|
||||||
QStringList donates;
|
QStringList donates;
|
||||||
for (auto& donate : current_pack.extraData.donate) {
|
for (auto& donate : current_pack->extraData.donate) {
|
||||||
donates.append(donateToStr(donate));
|
donates.append(donateToStr(donate));
|
||||||
}
|
}
|
||||||
text += donates.join(", ");
|
text += donates.join(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!current_pack.extraData.issuesUrl.isEmpty() || !current_pack.extraData.sourceUrl.isEmpty() ||
|
if (!current_pack->extraData.issuesUrl.isEmpty() || !current_pack->extraData.sourceUrl.isEmpty() ||
|
||||||
!current_pack.extraData.wikiUrl.isEmpty() || !current_pack.extraData.discordUrl.isEmpty()) {
|
!current_pack->extraData.wikiUrl.isEmpty() || !current_pack->extraData.discordUrl.isEmpty()) {
|
||||||
text += "<br><br>" + tr("External links:") + "<br>";
|
text += "<br><br>" + tr("External links:") + "<br>";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!current_pack.extraData.issuesUrl.isEmpty())
|
if (!current_pack->extraData.issuesUrl.isEmpty())
|
||||||
text += "- " + tr("Issues: <a href=%1>%1</a>").arg(current_pack.extraData.issuesUrl) + "<br>";
|
text += "- " + tr("Issues: <a href=%1>%1</a>").arg(current_pack->extraData.issuesUrl) + "<br>";
|
||||||
if (!current_pack.extraData.wikiUrl.isEmpty())
|
if (!current_pack->extraData.wikiUrl.isEmpty())
|
||||||
text += "- " + tr("Wiki: <a href=%1>%1</a>").arg(current_pack.extraData.wikiUrl) + "<br>";
|
text += "- " + tr("Wiki: <a href=%1>%1</a>").arg(current_pack->extraData.wikiUrl) + "<br>";
|
||||||
if (!current_pack.extraData.sourceUrl.isEmpty())
|
if (!current_pack->extraData.sourceUrl.isEmpty())
|
||||||
text += "- " + tr("Source code: <a href=%1>%1</a>").arg(current_pack.extraData.sourceUrl) + "<br>";
|
text += "- " + tr("Source code: <a href=%1>%1</a>").arg(current_pack->extraData.sourceUrl) + "<br>";
|
||||||
if (!current_pack.extraData.discordUrl.isEmpty())
|
if (!current_pack->extraData.discordUrl.isEmpty())
|
||||||
text += "- " + tr("Discord: <a href=%1>%1</a>").arg(current_pack.extraData.discordUrl) + "<br>";
|
text += "- " + tr("Discord: <a href=%1>%1</a>").arg(current_pack->extraData.discordUrl) + "<br>";
|
||||||
}
|
}
|
||||||
|
|
||||||
text += "<hr>";
|
text += "<hr>";
|
||||||
|
|
||||||
m_ui->packDescription->setHtml(
|
m_ui->packDescription->setHtml(
|
||||||
text + (current_pack.extraData.body.isEmpty() ? current_pack.description : markdownToHTML(current_pack.extraData.body)));
|
text + (current_pack->extraData.body.isEmpty() ? current_pack->description : markdownToHTML(current_pack->extraData.body)));
|
||||||
m_ui->packDescription->flush();
|
m_ui->packDescription->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +240,7 @@ void ResourcePage::updateSelectionButton()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_ui->resourceSelectionButton->setEnabled(true);
|
m_ui->resourceSelectionButton->setEnabled(true);
|
||||||
if (!getCurrentPack().isVersionSelected(m_selected_version_index)) {
|
if (!getCurrentPack()->isVersionSelected(m_selected_version_index)) {
|
||||||
m_ui->resourceSelectionButton->setText(tr("Select %1 for download").arg(resourceString()));
|
m_ui->resourceSelectionButton->setText(tr("Select %1 for download").arg(resourceString()));
|
||||||
} else {
|
} else {
|
||||||
m_ui->resourceSelectionButton->setText(tr("Deselect %1 for download").arg(resourceString()));
|
m_ui->resourceSelectionButton->setText(tr("Deselect %1 for download").arg(resourceString()));
|
||||||
@ -253,12 +255,12 @@ void ResourcePage::updateVersionList()
|
|||||||
m_ui->versionSelectionBox->clear();
|
m_ui->versionSelectionBox->clear();
|
||||||
m_ui->versionSelectionBox->blockSignals(false);
|
m_ui->versionSelectionBox->blockSignals(false);
|
||||||
|
|
||||||
for (int i = 0; i < current_pack.versions.size(); i++) {
|
for (int i = 0; i < current_pack->versions.size(); i++) {
|
||||||
auto& version = current_pack.versions[i];
|
auto& version = current_pack->versions[i];
|
||||||
if (optedOut(version))
|
if (optedOut(version))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
m_ui->versionSelectionBox->addItem(current_pack.versions[i].version, QVariant(i));
|
m_ui->versionSelectionBox->addItem(current_pack->versions[i].version, QVariant(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_ui->versionSelectionBox->count() == 0) {
|
if (m_ui->versionSelectionBox->count() == 0) {
|
||||||
@ -278,7 +280,7 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
|
|||||||
auto current_pack = getCurrentPack();
|
auto current_pack = getCurrentPack();
|
||||||
|
|
||||||
bool request_load = false;
|
bool request_load = false;
|
||||||
if (!current_pack.versionsLoaded) {
|
if (!current_pack->versionsLoaded) {
|
||||||
m_ui->resourceSelectionButton->setText(tr("Loading versions..."));
|
m_ui->resourceSelectionButton->setText(tr("Loading versions..."));
|
||||||
m_ui->resourceSelectionButton->setEnabled(false);
|
m_ui->resourceSelectionButton->setEnabled(false);
|
||||||
|
|
||||||
@ -287,7 +289,7 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, QModelIndex prev)
|
|||||||
updateVersionList();
|
updateVersionList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!current_pack.extraDataLoaded)
|
if (!current_pack->extraDataLoaded)
|
||||||
request_load = true;
|
request_load = true;
|
||||||
|
|
||||||
if (request_load)
|
if (request_load)
|
||||||
@ -307,7 +309,7 @@ void ResourcePage::onVersionSelectionChanged(QString data)
|
|||||||
updateSelectionButton();
|
updateSelectionButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version)
|
void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& version)
|
||||||
{
|
{
|
||||||
m_parent_dialog->addResource(pack, version);
|
m_parent_dialog->addResource(pack, version);
|
||||||
}
|
}
|
||||||
@ -317,7 +319,7 @@ void ResourcePage::removeResourceFromDialog(const QString& pack_name)
|
|||||||
m_parent_dialog->removeResource(pack_name);
|
m_parent_dialog->removeResource(pack_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourcePage::addResourceToPage(ModPlatform::IndexedPack& pack,
|
void ResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack,
|
||||||
ModPlatform::IndexedVersion& ver,
|
ModPlatform::IndexedVersion& ver,
|
||||||
const std::shared_ptr<ResourceFolderModel> base_model)
|
const std::shared_ptr<ResourceFolderModel> base_model)
|
||||||
{
|
{
|
||||||
@ -335,12 +337,12 @@ void ResourcePage::onResourceSelected()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
auto current_pack = getCurrentPack();
|
auto current_pack = getCurrentPack();
|
||||||
if (!current_pack.versionsLoaded)
|
if (!current_pack->versionsLoaded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& version = current_pack.versions[m_selected_version_index];
|
auto& version = current_pack->versions[m_selected_version_index];
|
||||||
if (version.is_currently_selected)
|
if (version.is_currently_selected)
|
||||||
removeResourceFromDialog(current_pack.name);
|
removeResourceFromDialog(current_pack->name);
|
||||||
else
|
else
|
||||||
addResourceToDialog(current_pack, version);
|
addResourceToDialog(current_pack, version);
|
||||||
|
|
||||||
@ -351,7 +353,7 @@ void ResourcePage::onResourceSelected()
|
|||||||
updateSelectionButton();
|
updateSelectionButton();
|
||||||
|
|
||||||
/* Force redraw on the resource list when the selection changes */
|
/* Force redraw on the resource list when the selection changes */
|
||||||
m_ui->packView->adjustSize();
|
m_ui->packView->repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourcePage::openUrl(const QUrl& url)
|
void ResourcePage::openUrl(const QUrl& url)
|
||||||
@ -381,7 +383,7 @@ void ResourcePage::openUrl(const QUrl& url)
|
|||||||
const QString slug = match.captured(1);
|
const QString slug = match.captured(1);
|
||||||
|
|
||||||
// ensure the user isn't opening the same mod
|
// ensure the user isn't opening the same mod
|
||||||
if (slug != getCurrentPack().slug) {
|
if (slug != getCurrentPack()->slug) {
|
||||||
m_parent_dialog->selectPage(page);
|
m_parent_dialog->selectPage(page);
|
||||||
|
|
||||||
auto newPage = m_parent_dialog->getSelectedPage();
|
auto newPage = m_parent_dialog->getSelectedPage();
|
||||||
|
@ -60,8 +60,8 @@ class ResourcePage : public QWidget, public BasePage {
|
|||||||
/** Programatically set the term in the search bar. */
|
/** Programatically set the term in the search bar. */
|
||||||
void setSearchTerm(QString);
|
void setSearchTerm(QString);
|
||||||
|
|
||||||
[[nodiscard]] bool setCurrentPack(ModPlatform::IndexedPack);
|
[[nodiscard]] bool setCurrentPack(ModPlatform::IndexedPack::Ptr);
|
||||||
[[nodiscard]] auto getCurrentPack() const -> ModPlatform::IndexedPack;
|
[[nodiscard]] auto getCurrentPack() const -> ModPlatform::IndexedPack::Ptr;
|
||||||
[[nodiscard]] auto getDialog() const -> const ResourceDownloadDialog* { return m_parent_dialog; }
|
[[nodiscard]] auto getDialog() const -> const ResourceDownloadDialog* { return m_parent_dialog; }
|
||||||
[[nodiscard]] auto getModel() const -> ResourceModel* { return m_model; }
|
[[nodiscard]] auto getModel() const -> ResourceModel* { return m_model; }
|
||||||
|
|
||||||
@ -75,10 +75,10 @@ class ResourcePage : public QWidget, public BasePage {
|
|||||||
virtual void updateSelectionButton();
|
virtual void updateSelectionButton();
|
||||||
virtual void updateVersionList();
|
virtual void updateVersionList();
|
||||||
|
|
||||||
void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&);
|
void addResourceToDialog(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&);
|
||||||
void removeResourceFromDialog(const QString& pack_name);
|
void removeResourceFromDialog(const QString& pack_name);
|
||||||
virtual void removeResourceFromPage(const QString& name);
|
virtual void removeResourceFromPage(const QString& name);
|
||||||
virtual void addResourceToPage(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, const std::shared_ptr<ResourceFolderModel>);
|
virtual void addResourceToPage(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&, const std::shared_ptr<ResourceFolderModel>);
|
||||||
|
|
||||||
QList<DownloadTaskPtr> selectedPacks() { return m_model->selectedPacks(); }
|
QList<DownloadTaskPtr> selectedPacks() { return m_model->selectedPacks(); }
|
||||||
bool hasSelectedPacks() { return !(m_model->selectedPacks().isEmpty()); }
|
bool hasSelectedPacks() { return !(m_model->selectedPacks().isEmpty()); }
|
||||||
|
@ -22,13 +22,13 @@ ResourceAPI::SearchArgs ShaderPackResourceModel::createSearchArguments()
|
|||||||
ResourceAPI::VersionSearchArgs ShaderPackResourceModel::createVersionsArguments(QModelIndex& entry)
|
ResourceAPI::VersionSearchArgs ShaderPackResourceModel::createVersionsArguments(QModelIndex& entry)
|
||||||
{
|
{
|
||||||
auto& pack = m_packs[entry.row()];
|
auto& pack = m_packs[entry.row()];
|
||||||
return { pack };
|
return { *pack };
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceAPI::ProjectInfoArgs ShaderPackResourceModel::createInfoArguments(QModelIndex& entry)
|
ResourceAPI::ProjectInfoArgs ShaderPackResourceModel::createInfoArguments(QModelIndex& entry)
|
||||||
{
|
{
|
||||||
auto& pack = m_packs[entry.row()];
|
auto& pack = m_packs[entry.row()];
|
||||||
return { pack };
|
return { *pack };
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderPackResourceModel::searchWithTerm(const QString& term, unsigned int sort)
|
void ShaderPackResourceModel::searchWithTerm(const QString& term, unsigned int sort)
|
||||||
|
@ -43,7 +43,7 @@ QMap<QString, QString> ShaderPackResourcePage::urlHandlers() const
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderPackResourcePage::addResourceToPage(ModPlatform::IndexedPack& pack,
|
void ShaderPackResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack,
|
||||||
ModPlatform::IndexedVersion& version,
|
ModPlatform::IndexedVersion& version,
|
||||||
const std::shared_ptr<ResourceFolderModel> base_model)
|
const std::shared_ptr<ResourceFolderModel> base_model)
|
||||||
{
|
{
|
||||||
|
@ -31,8 +31,6 @@ class ShaderPackResourcePage : public ResourcePage {
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ShaderPackResourcePage() override = default;
|
|
||||||
|
|
||||||
//: The plural version of 'shader pack'
|
//: The plural version of 'shader pack'
|
||||||
[[nodiscard]] inline QString resourcesString() const override { return tr("shader packs"); }
|
[[nodiscard]] inline QString resourcesString() const override { return tr("shader packs"); }
|
||||||
//: The singular version of 'shader packs'
|
//: The singular version of 'shader packs'
|
||||||
@ -40,7 +38,9 @@ class ShaderPackResourcePage : public ResourcePage {
|
|||||||
|
|
||||||
[[nodiscard]] bool supportsFiltering() const override { return false; };
|
[[nodiscard]] bool supportsFiltering() const override { return false; };
|
||||||
|
|
||||||
void addResourceToPage(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, const std::shared_ptr<ResourceFolderModel>) override;
|
void addResourceToPage(ModPlatform::IndexedPack::Ptr,
|
||||||
|
ModPlatform::IndexedVersion&,
|
||||||
|
const std::shared_ptr<ResourceFolderModel>) override;
|
||||||
|
|
||||||
[[nodiscard]] QMap<QString, QString> urlHandlers() const override;
|
[[nodiscard]] QMap<QString, QString> urlHandlers() const override;
|
||||||
|
|
||||||
|
@ -87,7 +87,9 @@ PageContainer::PageContainer(BasePageProvider *pageProvider, QString defaultId,
|
|||||||
auto pages = pageProvider->getPages();
|
auto pages = pageProvider->getPages();
|
||||||
for (auto page : pages)
|
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->listIndex = counter;
|
||||||
page->setParentContainer(this);
|
page->setParentContainer(this);
|
||||||
counter++;
|
counter++;
|
||||||
|
@ -40,6 +40,8 @@ void ReplyList::remove(QNetworkReply *reply) {
|
|||||||
if (o2Reply) {
|
if (o2Reply) {
|
||||||
o2Reply->stop();
|
o2Reply->stop();
|
||||||
(void)replies_.removeOne(o2Reply);
|
(void)replies_.removeOne(o2Reply);
|
||||||
|
// we took ownership, we must free
|
||||||
|
delete o2Reply;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,6 @@ Exec=@Launcher_APP_BINARY_NAME@
|
|||||||
StartupNotify=true
|
StartupNotify=true
|
||||||
Icon=org.prismlauncher.PrismLauncher
|
Icon=org.prismlauncher.PrismLauncher
|
||||||
Categories=Game;ActionGame;AdventureGame;Simulation;
|
Categories=Game;ActionGame;AdventureGame;Simulation;
|
||||||
Keywords=game;minecraft;launcher;mc;multimc;polymc;
|
Keywords=game;minecraft;mc;
|
||||||
StartupWMClass=PrismLauncher
|
StartupWMClass=PrismLauncher
|
||||||
MimeType=application/zip;application/x-modrinth-modpack+zip
|
MimeType=application/zip;application/x-modrinth-modpack+zip
|
||||||
|
@ -90,9 +90,7 @@ slots:
|
|||||||
|
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
|
|
||||||
InstancePtr instance;
|
ModFolderModel m(tempDir.path(), nullptr, true);
|
||||||
|
|
||||||
ModFolderModel m(tempDir.path(), instance, true);
|
|
||||||
|
|
||||||
connect(&m, &ModFolderModel::updateFinished, &loop, &QEventLoop::quit);
|
connect(&m, &ModFolderModel::updateFinished, &loop, &QEventLoop::quit);
|
||||||
|
|
||||||
@ -116,8 +114,7 @@ slots:
|
|||||||
QString folder = source + '/';
|
QString folder = source + '/';
|
||||||
QTemporaryDir tempDir;
|
QTemporaryDir tempDir;
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
InstancePtr instance;
|
ModFolderModel m(tempDir.path(), nullptr, true);
|
||||||
ModFolderModel m(tempDir.path(), instance, true);
|
|
||||||
|
|
||||||
connect(&m, &ModFolderModel::updateFinished, &loop, &QEventLoop::quit);
|
connect(&m, &ModFolderModel::updateFinished, &loop, &QEventLoop::quit);
|
||||||
|
|
||||||
@ -140,8 +137,7 @@ slots:
|
|||||||
void test_addFromWatch()
|
void test_addFromWatch()
|
||||||
{
|
{
|
||||||
QString source = QFINDTESTDATA("testdata/ResourceFolderModel");
|
QString source = QFINDTESTDATA("testdata/ResourceFolderModel");
|
||||||
InstancePtr instance;
|
ModFolderModel model(source, nullptr);
|
||||||
ModFolderModel model(source, instance);
|
|
||||||
|
|
||||||
QCOMPARE(model.size(), 0);
|
QCOMPARE(model.size(), 0);
|
||||||
|
|
||||||
@ -161,9 +157,7 @@ slots:
|
|||||||
QString file_mod = QFINDTESTDATA("testdata/ResourceFolderModel/supercoolmod.jar");
|
QString file_mod = QFINDTESTDATA("testdata/ResourceFolderModel/supercoolmod.jar");
|
||||||
|
|
||||||
QTemporaryDir tmp;
|
QTemporaryDir tmp;
|
||||||
InstancePtr instance;
|
ResourceFolderModel model(QDir(tmp.path()), nullptr);
|
||||||
|
|
||||||
ResourceFolderModel model(QDir(tmp.path()), instance);
|
|
||||||
|
|
||||||
QCOMPARE(model.size(), 0);
|
QCOMPARE(model.size(), 0);
|
||||||
|
|
||||||
@ -214,8 +208,7 @@ slots:
|
|||||||
QString file_mod = QFINDTESTDATA("testdata/ResourceFolderModel/supercoolmod.jar");
|
QString file_mod = QFINDTESTDATA("testdata/ResourceFolderModel/supercoolmod.jar");
|
||||||
|
|
||||||
QTemporaryDir tmp;
|
QTemporaryDir tmp;
|
||||||
InstancePtr instance;
|
ResourceFolderModel model(tmp.path(), nullptr);
|
||||||
ResourceFolderModel model(tmp.path(), instance);
|
|
||||||
|
|
||||||
QCOMPARE(model.size(), 0);
|
QCOMPARE(model.size(), 0);
|
||||||
|
|
||||||
|
@ -75,9 +75,9 @@ class ResourceModelTest : public QObject {
|
|||||||
auto search_json = DummyResourceAPI::searchRequestResult();
|
auto search_json = DummyResourceAPI::searchRequestResult();
|
||||||
auto processed_response = model->documentToArray(search_json).first().toObject();
|
auto processed_response = model->documentToArray(search_json).first().toObject();
|
||||||
|
|
||||||
QVERIFY(processed_pack.addonId.toString() == Json::requireString(processed_response, "project_id"));
|
QVERIFY(processed_pack->addonId.toString() == Json::requireString(processed_response, "project_id"));
|
||||||
QVERIFY(processed_pack.description == Json::requireString(processed_response, "description"));
|
QVERIFY(processed_pack->description == Json::requireString(processed_response, "description"));
|
||||||
QVERIFY(processed_pack.authors.first().name == Json::requireString(processed_response, "author"));
|
QVERIFY(processed_pack->authors.first().name == Json::requireString(processed_response, "author"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user