mirror of
https://github.com/PrismLauncher/PrismLauncher.git
synced 2026-06-29 01:54:20 +03:00
suppoer non mods deps
fixes #3962 Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
parent
245ff2b555
commit
2e45d135c5
17 changed files with 282 additions and 205 deletions
|
|
@ -21,53 +21,108 @@
|
|||
#include <QDebug>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include "Json.h"
|
||||
#include "QObjectPtr.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "minecraft/mod/MetadataHandler.h"
|
||||
#include "minecraft/mod/ModFolderModel.h"
|
||||
#include "minecraft/mod/ResourceFolderModel.h"
|
||||
#include "modplatform/ModIndex.h"
|
||||
#include "modplatform/ResourceAPI.h"
|
||||
#include "tasks/SequentialTask.h"
|
||||
#include "ui/pages/modplatform/ModModel.h"
|
||||
|
||||
static Version mcVersion(BaseInstance* inst)
|
||||
namespace {
|
||||
Version mcVersion(BaseInstance* inst)
|
||||
{
|
||||
return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion();
|
||||
}
|
||||
|
||||
static ModPlatform::ModLoaderTypes mcLoaders(BaseInstance* inst)
|
||||
ModPlatform::ModLoaderTypes mcLoaders(BaseInstance* inst)
|
||||
{
|
||||
return static_cast<MinecraftInstance*>(inst)->getPackProfile()->getSupportedModLoaders().value();
|
||||
}
|
||||
|
||||
static bool checkDependencies(std::shared_ptr<GetModDependenciesTask::PackDependency> sel,
|
||||
Version mcVersion,
|
||||
ModPlatform::ModLoaderTypes loaders)
|
||||
bool checkDependencies(const std::shared_ptr<GetModDependenciesTask::PackDependency>& sel,
|
||||
const Version& mcVersion,
|
||||
ModPlatform::ModLoaderTypes loaders)
|
||||
{
|
||||
return (sel->pack->versions.isEmpty() || sel->version.mcVersion.contains(mcVersion.toString())) &&
|
||||
(!loaders || !sel->version.loaders || sel->version.loaders & loaders);
|
||||
(!loaders || !sel->version.loaders || (sel->version.loaders & loaders) != 0U);
|
||||
}
|
||||
|
||||
// super lax compare (but not fuzzy)
|
||||
// convert to lowercase
|
||||
// convert all speratores to whitespace
|
||||
// simplify sequence of internal whitespace to a single space
|
||||
// efectivly compare two strings ignoring all separators and case
|
||||
bool laxCompare(const QString& fsfilename, const QString& metadataFilename, bool excludeDigits = false)
|
||||
{
|
||||
// allowed character seperators
|
||||
QList<QChar> allowedSeperators = { '-', '+', '.', '_' };
|
||||
if (excludeDigits) {
|
||||
allowedSeperators.append({ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' });
|
||||
}
|
||||
|
||||
// copy in lowercase
|
||||
auto fsName = fsfilename.toLower();
|
||||
auto metaName = metadataFilename.toLower();
|
||||
|
||||
// replace all potential allowed seperatores with whitespace
|
||||
for (auto sep : allowedSeperators) {
|
||||
fsName = fsName.replace(sep, ' ');
|
||||
metaName = metaName.replace(sep, ' ');
|
||||
}
|
||||
|
||||
// remove extraneous whitespace
|
||||
fsName = fsName.simplified();
|
||||
metaName = metaName.simplified();
|
||||
|
||||
return fsName.compare(metaName) == 0;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
GetModDependenciesTask::GetModDependenciesTask(BaseInstance* instance,
|
||||
ModFolderModel* folder,
|
||||
QList<std::shared_ptr<PackDependency>> selected)
|
||||
: SequentialTask(tr("Get dependencies")), m_selected(selected), m_version(mcVersion(instance)), m_loaderType(mcLoaders(instance))
|
||||
: SequentialTask(tr("Get dependencies"))
|
||||
, m_selected(std::move(selected))
|
||||
, m_version(mcVersion(instance))
|
||||
, m_loaderType(mcLoaders(instance))
|
||||
{
|
||||
for (auto mod : folder->allMods()) {
|
||||
m_mods_file_names << mod->fileinfo().fileName();
|
||||
if (auto meta = mod->metadata(); meta)
|
||||
for (auto* mod : folder->allMods()) {
|
||||
m_modsFileNames << mod->fileinfo().fileName();
|
||||
if (auto meta = mod->metadata(); meta) {
|
||||
m_mods.append(meta);
|
||||
}
|
||||
}
|
||||
|
||||
auto* mInstance = dynamic_cast<MinecraftInstance*>(instance);
|
||||
if (mInstance) {
|
||||
for (auto* model : mInstance->resourceLists()) {
|
||||
if (model) {
|
||||
for (auto* mod : model->allResources()) { // only append meta
|
||||
if (auto meta = mod->metadata(); meta) {
|
||||
m_mods.append(meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prepare();
|
||||
}
|
||||
|
||||
void GetModDependenciesTask::prepare()
|
||||
{
|
||||
for (auto sel : m_selected) {
|
||||
if (checkDependencies(sel, m_version, m_loaderType))
|
||||
for (auto dep : getDependenciesForVersion(sel->version, sel->pack->provider)) {
|
||||
for (const auto& sel : m_selected) {
|
||||
if (checkDependencies(sel, m_version, m_loaderType)) {
|
||||
for (const auto& dep : getDependenciesForVersion(sel->version, sel->pack->provider)) {
|
||||
addTask(prepareDependencyTask(dep, sel->pack->provider, 20));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +131,7 @@ ModPlatform::Dependency GetModDependenciesTask::getOverride(const ModPlatform::D
|
|||
{
|
||||
if (auto isQuilt = (m_loaderType & ModPlatform::Quilt) != 0U; isQuilt || (m_loaderType & ModPlatform::Fabric) != 0U) {
|
||||
auto overide = ModPlatform::getOverrideDeps();
|
||||
auto over = std::find_if(overide.cbegin(), overide.cend(), [dep, providerName, isQuilt](const auto& o) {
|
||||
auto over = std::ranges::find_if(overide, [dep, providerName, isQuilt](const auto& o) {
|
||||
return o.provider == providerName && dep.addonId == (isQuilt ? o.fabric : o.quilt);
|
||||
});
|
||||
if (over != overide.cend()) {
|
||||
|
|
@ -89,51 +144,53 @@ ModPlatform::Dependency GetModDependenciesTask::getOverride(const ModPlatform::D
|
|||
QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version,
|
||||
const ModPlatform::ResourceProvider providerName)
|
||||
{
|
||||
QList<ModPlatform::Dependency> c_dependencies;
|
||||
for (auto ver_dep : version.dependencies) {
|
||||
if (ver_dep.type != ModPlatform::DependencyType::REQUIRED) {
|
||||
QList<ModPlatform::Dependency> cDependencies;
|
||||
for (auto verDep : version.dependencies) {
|
||||
if (verDep.type != ModPlatform::DependencyType::REQUIRED) {
|
||||
continue;
|
||||
}
|
||||
ver_dep = getOverride(ver_dep, providerName);
|
||||
auto isOnlyVersion = providerName == ModPlatform::ResourceProvider::MODRINTH && ver_dep.addonId.toString().isEmpty();
|
||||
if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(),
|
||||
[&ver_dep, isOnlyVersion](const ModPlatform::Dependency& i) {
|
||||
return isOnlyVersion ? i.version == ver_dep.version : i.addonId == ver_dep.addonId;
|
||||
});
|
||||
dep != c_dependencies.end()) {
|
||||
verDep = getOverride(verDep, providerName);
|
||||
auto isOnlyVersion = providerName == ModPlatform::ResourceProvider::MODRINTH && verDep.addonId.toString().isEmpty();
|
||||
if (auto dep = std::ranges::find_if(cDependencies,
|
||||
[&verDep, isOnlyVersion](const ModPlatform::Dependency& i) {
|
||||
return isOnlyVersion ? i.version == verDep.version : i.addonId == verDep.addonId;
|
||||
});
|
||||
dep != cDependencies.end()) {
|
||||
continue; // check the current dependency list
|
||||
}
|
||||
|
||||
if (auto dep = std::find_if(m_selected.begin(), m_selected.end(),
|
||||
[&ver_dep, providerName, isOnlyVersion](const std::shared_ptr<PackDependency>& i) {
|
||||
return i->pack->provider == providerName && (isOnlyVersion ? i->version.version == ver_dep.version
|
||||
: i->pack->addonId == ver_dep.addonId);
|
||||
});
|
||||
if (auto dep =
|
||||
std::ranges::find_if(m_selected,
|
||||
[&verDep, providerName, isOnlyVersion](const std::shared_ptr<PackDependency>& i) {
|
||||
return i->pack->provider == providerName &&
|
||||
(isOnlyVersion ? i->version.version == verDep.version : i->pack->addonId == verDep.addonId);
|
||||
});
|
||||
dep != m_selected.end()) {
|
||||
continue; // check the selected versions
|
||||
}
|
||||
|
||||
if (auto dep = std::find_if(m_mods.begin(), m_mods.end(),
|
||||
[&ver_dep, providerName, isOnlyVersion](const std::shared_ptr<Metadata::ModStruct>& i) {
|
||||
return i->provider == providerName &&
|
||||
(isOnlyVersion ? i->file_id == ver_dep.version : i->project_id == ver_dep.addonId);
|
||||
});
|
||||
if (auto dep = std::ranges::find_if(m_mods,
|
||||
[&verDep, providerName, isOnlyVersion](const std::shared_ptr<Metadata::ModStruct>& i) {
|
||||
return i->provider == providerName &&
|
||||
(isOnlyVersion ? i->file_id == verDep.version : i->project_id == verDep.addonId);
|
||||
});
|
||||
dep != m_mods.end()) {
|
||||
continue; // check the existing mods
|
||||
}
|
||||
|
||||
if (auto dep = std::find_if(m_pack_dependencies.begin(), m_pack_dependencies.end(),
|
||||
[&ver_dep, providerName, isOnlyVersion](const std::shared_ptr<PackDependency>& i) {
|
||||
return i->pack->provider == providerName && (isOnlyVersion ? i->version.version == ver_dep.addonId
|
||||
: i->pack->addonId == ver_dep.addonId);
|
||||
});
|
||||
dep != m_pack_dependencies.end()) { // check loaded dependencies
|
||||
if (auto dep =
|
||||
std::ranges::find_if(m_packDependencies,
|
||||
[&verDep, providerName, isOnlyVersion](const std::shared_ptr<PackDependency>& i) {
|
||||
return i->pack->provider == providerName &&
|
||||
(isOnlyVersion ? i->version.version == verDep.addonId : i->pack->addonId == verDep.addonId);
|
||||
});
|
||||
dep != m_packDependencies.end()) { // check loaded dependencies
|
||||
continue;
|
||||
}
|
||||
|
||||
c_dependencies.append(ver_dep);
|
||||
cDependencies.append(verDep);
|
||||
}
|
||||
return c_dependencies;
|
||||
return cDependencies;
|
||||
}
|
||||
|
||||
Task::Ptr GetModDependenciesTask::getProjectInfoTask(std::shared_ptr<PackDependency> pDep)
|
||||
|
|
@ -141,12 +198,11 @@ Task::Ptr GetModDependenciesTask::getProjectInfoTask(std::shared_ptr<PackDepende
|
|||
auto provider = pDep->pack->provider;
|
||||
auto [info, responseInfo] = getAPI(provider)->getProject(pDep->pack->addonId.toString());
|
||||
connect(info.get(), &NetJob::succeeded, [this, responseInfo, provider, pDep] {
|
||||
QJsonParseError parse_error{};
|
||||
QJsonDocument doc = QJsonDocument::fromJson(*responseInfo, &parse_error);
|
||||
if (parse_error.error != QJsonParseError::NoError) {
|
||||
QJsonParseError parseError{};
|
||||
QJsonDocument doc = QJsonDocument::fromJson(*responseInfo, &parseError);
|
||||
if (parseError.error != QJsonParseError::NoError) {
|
||||
removePack(pDep->pack->addonId);
|
||||
qWarning() << "Error while parsing JSON response for mod info at" << parse_error.offset
|
||||
<< "reason:" << parse_error.errorString();
|
||||
qWarning() << "Error while parsing JSON response for mod info at" << parseError.offset << "reason:" << parseError.errorString();
|
||||
qDebug() << *responseInfo;
|
||||
return;
|
||||
}
|
||||
|
|
@ -178,7 +234,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
|
|||
pDep->pack->addonId = dep.addonId;
|
||||
pDep->pack->provider = providerName;
|
||||
|
||||
m_pack_dependencies.append(pDep);
|
||||
m_packDependencies.append(pDep);
|
||||
|
||||
auto provider = providerName;
|
||||
|
||||
|
|
@ -223,10 +279,10 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
|
|||
}
|
||||
if (dep.addonId.toString().isEmpty() && !pDep->version.addonId.toString().isEmpty()) {
|
||||
pDep->pack->addonId = pDep->version.addonId;
|
||||
auto dep_ = getOverride({ .addonId = pDep->version.addonId, .type = pDep->dependency.type, .version = "" }, provider);
|
||||
if (dep_.addonId != pDep->version.addonId) {
|
||||
auto overrideDep = getOverride({ .addonId = pDep->version.addonId, .type = pDep->dependency.type, .version = "" }, provider);
|
||||
if (overrideDep.addonId != pDep->version.addonId) {
|
||||
removePack(pDep->version.addonId);
|
||||
addTask(prepareDependencyTask(dep_, provider, level));
|
||||
addTask(prepareDependencyTask(overrideDep, provider, level));
|
||||
} else {
|
||||
addTask(getProjectInfoTask(pDep));
|
||||
}
|
||||
|
|
@ -235,8 +291,8 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen
|
|||
removePack(pDep->version.addonId);
|
||||
return;
|
||||
}
|
||||
for (const auto& dep_ : getDependenciesForVersion(pDep->version, provider)) {
|
||||
addTask(prepareDependencyTask(dep_, provider, level - 1));
|
||||
for (const auto& dependency : getDependenciesForVersion(pDep->version, provider)) {
|
||||
addTask(prepareDependencyTask(dependency, provider, level - 1));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -253,7 +309,7 @@ void GetModDependenciesTask::removePack(const QVariant& addonId)
|
|||
{
|
||||
auto pred = [addonId](const std::shared_ptr<PackDependency>& v) { return v->pack->addonId == addonId; };
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
|
||||
m_pack_dependencies.removeIf(pred);
|
||||
m_packDependencies.removeIf(pred);
|
||||
#else
|
||||
for (auto it = m_pack_dependencies.begin(); it != m_pack_dependencies.end();)
|
||||
if (pred(*it))
|
||||
|
|
@ -266,82 +322,55 @@ void GetModDependenciesTask::removePack(const QVariant& addonId)
|
|||
auto GetModDependenciesTask::getExtraInfo() -> QHash<QString, PackDependencyExtraInfo>
|
||||
{
|
||||
QHash<QString, PackDependencyExtraInfo> rby;
|
||||
auto fullList = m_selected + m_pack_dependencies;
|
||||
auto fullList = m_selected + m_packDependencies;
|
||||
for (auto& mod : fullList) {
|
||||
auto addonId = mod->pack->addonId;
|
||||
auto provider = mod->pack->provider;
|
||||
auto version = mod->version.fileId;
|
||||
auto req = QStringList();
|
||||
for (auto& smod : fullList) {
|
||||
if (provider != smod->pack->provider)
|
||||
if (provider != smod->pack->provider) {
|
||||
continue;
|
||||
}
|
||||
auto deps = smod->version.dependencies;
|
||||
if (auto dep = std::find_if(deps.begin(), deps.end(),
|
||||
[addonId, provider, version](const ModPlatform::Dependency& d) {
|
||||
return d.type == ModPlatform::DependencyType::REQUIRED &&
|
||||
(provider == ModPlatform::ResourceProvider::MODRINTH && d.addonId.toString().isEmpty()
|
||||
? version == d.version
|
||||
: d.addonId == addonId);
|
||||
});
|
||||
if (auto dep =
|
||||
std::ranges::find_if(deps,
|
||||
[addonId, provider, version](const ModPlatform::Dependency& d) {
|
||||
return d.type == ModPlatform::DependencyType::REQUIRED &&
|
||||
(provider == ModPlatform::ResourceProvider::MODRINTH && d.addonId.toString().isEmpty()
|
||||
? version == d.version
|
||||
: d.addonId == addonId);
|
||||
});
|
||||
dep != deps.end()) {
|
||||
req.append(smod->pack->name);
|
||||
}
|
||||
}
|
||||
rby[addonId.toString()] = { maybeInstalled(mod), req };
|
||||
rby[addonId.toString()] = { .maybeInstalled = maybeInstalled(mod), .requiredBy = req };
|
||||
}
|
||||
return rby;
|
||||
}
|
||||
|
||||
// super lax compare (but not fuzzy)
|
||||
// convert to lowercase
|
||||
// convert all speratores to whitespace
|
||||
// simplify sequence of internal whitespace to a single space
|
||||
// efectivly compare two strings ignoring all separators and case
|
||||
auto laxCompare = [](QString fsfilename, QString metadataFilename, bool excludeDigits = false) {
|
||||
// allowed character seperators
|
||||
QList<QChar> allowedSeperators = { '-', '+', '.', '_' };
|
||||
if (excludeDigits)
|
||||
allowedSeperators.append({ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' });
|
||||
|
||||
// copy in lowercase
|
||||
auto fsName = fsfilename.toLower();
|
||||
auto metaName = metadataFilename.toLower();
|
||||
|
||||
// replace all potential allowed seperatores with whitespace
|
||||
for (auto sep : allowedSeperators) {
|
||||
fsName = fsName.replace(sep, ' ');
|
||||
metaName = metaName.replace(sep, ' ');
|
||||
}
|
||||
|
||||
// remove extraneous whitespace
|
||||
fsName = fsName.simplified();
|
||||
metaName = metaName.simplified();
|
||||
|
||||
return fsName.compare(metaName) == 0;
|
||||
};
|
||||
|
||||
bool GetModDependenciesTask::isLocalyInstalled(std::shared_ptr<PackDependency> pDep)
|
||||
{
|
||||
return pDep->version.fileName.isEmpty() ||
|
||||
std::ranges::find_if(m_selected,
|
||||
[pDep](const std::shared_ptr<PackDependency>& i) {
|
||||
return !i->version.fileName.isEmpty() && laxCompare(i->version.fileName, pDep->version.fileName);
|
||||
}) != m_selected.end() || // check the selected versions
|
||||
|
||||
std::find_if(m_selected.begin(), m_selected.end(),
|
||||
[pDep](std::shared_ptr<PackDependency> i) {
|
||||
return !i->version.fileName.isEmpty() && laxCompare(i->version.fileName, pDep->version.fileName);
|
||||
}) != m_selected.end() || // check the selected versions
|
||||
std::ranges::find_if(m_modsFileNames,
|
||||
[pDep](const QString& i) { return !i.isEmpty() && laxCompare(i, pDep->version.fileName); }) !=
|
||||
m_modsFileNames.end() || // check the existing mods
|
||||
|
||||
std::find_if(m_mods_file_names.begin(), m_mods_file_names.end(),
|
||||
[pDep](QString i) { return !i.isEmpty() && laxCompare(i, pDep->version.fileName); }) !=
|
||||
m_mods_file_names.end() || // check the existing mods
|
||||
|
||||
std::find_if(m_pack_dependencies.begin(), m_pack_dependencies.end(), [pDep](std::shared_ptr<PackDependency> i) {
|
||||
std::ranges::find_if(m_packDependencies, [pDep](std::shared_ptr<PackDependency> i) {
|
||||
return pDep->pack->addonId != i->pack->addonId && !i->version.fileName.isEmpty() &&
|
||||
laxCompare(pDep->version.fileName, i->version.fileName);
|
||||
}) != m_pack_dependencies.end(); // check loaded dependencies
|
||||
}) != m_packDependencies.end(); // check loaded dependencies
|
||||
}
|
||||
|
||||
bool GetModDependenciesTask::maybeInstalled(std::shared_ptr<PackDependency> pDep)
|
||||
{
|
||||
return std::find_if(m_mods_file_names.begin(), m_mods_file_names.end(), [pDep](QString i) {
|
||||
return std::ranges::find_if(m_modsFileNames, [pDep](const QString& i) {
|
||||
return !i.isEmpty() && laxCompare(i, pDep->version.fileName, true);
|
||||
}) != m_mods_file_names.end(); // check the existing mods
|
||||
}) != m_modsFileNames.end(); // check the existing mods
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
#include <QDir>
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
|
|
@ -49,13 +48,13 @@ class GetModDependenciesTask : public SequentialTask {
|
|||
};
|
||||
|
||||
struct PackDependencyExtraInfo {
|
||||
bool maybe_installed{};
|
||||
QStringList required_by;
|
||||
bool maybeInstalled{};
|
||||
QStringList requiredBy;
|
||||
};
|
||||
|
||||
explicit GetModDependenciesTask(BaseInstance* instance, ModFolderModel* folder, QList<std::shared_ptr<PackDependency>> selected);
|
||||
|
||||
auto getDependecies() const -> QList<std::shared_ptr<PackDependency>> { return m_pack_dependencies; }
|
||||
auto getDependecies() const -> QList<std::shared_ptr<PackDependency>> { return m_packDependencies; }
|
||||
QHash<QString, PackDependencyExtraInfo> getExtraInfo();
|
||||
|
||||
private:
|
||||
|
|
@ -80,10 +79,10 @@ class GetModDependenciesTask : public SequentialTask {
|
|||
bool maybeInstalled(std::shared_ptr<PackDependency> pDep);
|
||||
|
||||
private:
|
||||
QList<std::shared_ptr<PackDependency>> m_pack_dependencies;
|
||||
QList<std::shared_ptr<PackDependency>> m_packDependencies;
|
||||
QList<std::shared_ptr<Metadata::ModStruct>> m_mods;
|
||||
QList<std::shared_ptr<PackDependency>> m_selected;
|
||||
QStringList m_mods_file_names;
|
||||
QStringList m_modsFileNames;
|
||||
|
||||
Version m_version;
|
||||
ModPlatform::ModLoaderTypes m_loaderType;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <compare>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include "modplatform/ResourceType.h"
|
||||
|
||||
class QIODevice;
|
||||
|
||||
|
|
@ -181,6 +182,8 @@ struct IndexedPack {
|
|||
bool extraDataLoaded = true;
|
||||
ExtraPackData extraData;
|
||||
|
||||
ResourceType resourceType = ResourceType::Unknown;
|
||||
|
||||
// For internal use, not provided by APIs
|
||||
bool isVersionSelected(int index) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
namespace ModPlatform {
|
||||
|
||||
enum class ResourceType { Mod, ResourcePack, ShaderPack, Modpack, DataPack, World, Screenshots, TexturePack, Unknown };
|
||||
enum class ResourceType : std::uint8_t { Mod, ResourcePack, ShaderPack, Modpack, DataPack, World, Screenshots, TexturePack, Unknown };
|
||||
|
||||
namespace ResourceTypeUtils {
|
||||
static const std::set<ResourceType> VALID_RESOURCES = { ResourceType::DataPack, ResourceType::ResourcePack, ResourceType::TexturePack,
|
||||
|
|
|
|||
|
|
@ -86,30 +86,6 @@ void Flame::FileResolvingTask::executeTask()
|
|||
m_task->start();
|
||||
}
|
||||
|
||||
ModPlatform::ResourceType getResourceType(int classId)
|
||||
{
|
||||
switch (classId) {
|
||||
case 17: // Worlds
|
||||
return ModPlatform::ResourceType::World;
|
||||
case 6: // Mods
|
||||
return ModPlatform::ResourceType::Mod;
|
||||
case 12: // Resource Packs
|
||||
// return ModPlatform::ResourceType::ResourcePack; // not really a resourcepack
|
||||
/* fallthrough */
|
||||
case 4546: // Customization
|
||||
// return ModPlatform::ResourceType::ShaderPack; // not really a shaderPack
|
||||
/* fallthrough */
|
||||
case 4471: // Modpacks
|
||||
/* fallthrough */
|
||||
case 5: // Bukkit Plugins
|
||||
/* fallthrough */
|
||||
case 4559: // Addons
|
||||
/* fallthrough */
|
||||
default:
|
||||
return ModPlatform::ResourceType::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
void Flame::FileResolvingTask::netJobFinished(QByteArray* response)
|
||||
{
|
||||
setProgress(1, 3);
|
||||
|
|
@ -171,8 +147,8 @@ void Flame::FileResolvingTask::netJobFinished(QByteArray* response)
|
|||
|
||||
getFlameProjects();
|
||||
return;
|
||||
}
|
||||
if (APPLICATION->settings()->get("FallbackMRBlockedMods").toBool()){
|
||||
}
|
||||
if (APPLICATION->settings()->get("FallbackMRBlockedMods").toBool()) {
|
||||
try {
|
||||
auto entries = Json::requireObject(doc);
|
||||
for (auto& out : m_manifest.files) {
|
||||
|
|
@ -253,8 +229,7 @@ void Flame::FileResolvingTask::getFlameProjects()
|
|||
|
||||
setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(file->version.fileName));
|
||||
FlameMod::loadIndexedPack(file->pack, entry_obj);
|
||||
file->resourceType = getResourceType(Json::requireInteger(entry_obj, "classId", "modClassId"));
|
||||
if (file->resourceType == ModPlatform::ResourceType::World) {
|
||||
if (file->pack.resourceType == ModPlatform::ResourceType::World) {
|
||||
file->targetFolder = "saves";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,14 +162,41 @@ std::pair<Task::Ptr, QByteArray*> FlameAPI::getFile(const QString& addonId, cons
|
|||
QList<ResourceAPI::SortingMethod> FlameAPI::getSortingMethods() const
|
||||
{
|
||||
// https://docs.curseforge.com/?python#tocS_ModsSearchSortField
|
||||
return { { 1, "Featured", QObject::tr("Sort by Featured") },
|
||||
{ 2, "Popularity", QObject::tr("Sort by Popularity") },
|
||||
{ 3, "LastUpdated", QObject::tr("Sort by Last Updated") },
|
||||
{ 4, "Name", QObject::tr("Sort by Name") },
|
||||
{ 5, "Author", QObject::tr("Sort by Author") },
|
||||
{ 6, "TotalDownloads", QObject::tr("Sort by Downloads") },
|
||||
{ 7, "Category", QObject::tr("Sort by Category") },
|
||||
{ 8, "GameVersion", QObject::tr("Sort by Game Version") } };
|
||||
return { { .index = 1, .name = "Featured", .readable_name = QObject::tr("Sort by Featured") },
|
||||
{ .index = 2, .name = "Popularity", .readable_name = QObject::tr("Sort by Popularity") },
|
||||
{ .index = 3, .name = "LastUpdated", .readable_name = QObject::tr("Sort by Last Updated") },
|
||||
{ .index = 4, .name = "Name", .readable_name = QObject::tr("Sort by Name") },
|
||||
{ .index = 5, .name = "Author", .readable_name = QObject::tr("Sort by Author") },
|
||||
{ .index = 6, .name = "TotalDownloads", .readable_name = QObject::tr("Sort by Downloads") },
|
||||
{ .index = 7, .name = "Category", .readable_name = QObject::tr("Sort by Category") },
|
||||
{ .index = 8, .name = "GameVersion", .readable_name = QObject::tr("Sort by Game Version") } };
|
||||
}
|
||||
|
||||
namespace {
|
||||
const auto g_classIDMappings = std::array{
|
||||
std::pair{ ModPlatform::ResourceType::Mod, 6 }, std::pair{ ModPlatform::ResourceType::ResourcePack, 12 },
|
||||
std::pair{ ModPlatform::ResourceType::World, 17 }, std::pair{ ModPlatform::ResourceType::ShaderPack, 6552 },
|
||||
std::pair{ ModPlatform::ResourceType::Modpack, 4471 }, std::pair{ ModPlatform::ResourceType::DataPack, 6945 },
|
||||
};
|
||||
}
|
||||
|
||||
int FlameAPI::getClassId(ModPlatform::ResourceType type)
|
||||
{
|
||||
for (auto&& [e, classId] : g_classIDMappings) {
|
||||
if (e == type) {
|
||||
return classId;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ModPlatform::ResourceType FlameAPI::getResourceType(int classId)
|
||||
{
|
||||
for (auto&& [type, c] : g_classIDMappings) {
|
||||
if (c == classId) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return ModPlatform::ResourceType::Unknown;
|
||||
}
|
||||
|
||||
std::pair<Task::Ptr, QByteArray*> FlameAPI::getCategories(ModPlatform::ResourceType type)
|
||||
|
|
|
|||
|
|
@ -39,23 +39,10 @@ class FlameAPI : public ResourceAPI {
|
|||
return loaders & (ModPlatform::NeoForge | ModPlatform::Forge | ModPlatform::Fabric | ModPlatform::Quilt);
|
||||
}
|
||||
|
||||
static ModPlatform::ResourceType getResourceType(int classId);
|
||||
|
||||
private:
|
||||
static int getClassId(ModPlatform::ResourceType type)
|
||||
{
|
||||
switch (type) {
|
||||
default:
|
||||
case ModPlatform::ResourceType::Mod:
|
||||
return 6;
|
||||
case ModPlatform::ResourceType::ResourcePack:
|
||||
return 12;
|
||||
case ModPlatform::ResourceType::ShaderPack:
|
||||
return 6552;
|
||||
case ModPlatform::ResourceType::Modpack:
|
||||
return 4471;
|
||||
case ModPlatform::ResourceType::DataPack:
|
||||
return 6945;
|
||||
}
|
||||
}
|
||||
static int getClassId(ModPlatform::ResourceType type);
|
||||
|
||||
static int getMappedModLoader(ModPlatform::ModLoaderType loaders)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ bool FlameCreationTask::updateInstance()
|
|||
// Remove repeated files, we don't need to download them!
|
||||
auto files_iterator = files.begin();
|
||||
while (files_iterator != files.end()) {
|
||||
auto const& file = files_iterator;
|
||||
const auto& file = files_iterator;
|
||||
|
||||
auto old_file = old_files.find(file.key());
|
||||
if (old_file != old_files.end()) {
|
||||
|
|
@ -511,7 +511,7 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop)
|
|||
QList<BlockedMod> blocked_mods;
|
||||
auto anyBlocked = false;
|
||||
for (const auto& result : results.values()) {
|
||||
if (result.resourceType != ModPlatform::ResourceType::Mod) {
|
||||
if (result.pack.resourceType != ModPlatform::ResourceType::Mod) {
|
||||
m_otherResources.append(std::make_pair(result.version.fileName, result.targetFolder));
|
||||
}
|
||||
|
||||
|
|
@ -602,14 +602,14 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop)
|
|||
|
||||
/// @brief copy the matched blocked mods to the instance staging area
|
||||
/// @param blocked_mods list of the blocked mods and their matched paths
|
||||
void FlameCreationTask::copyBlockedMods(QList<BlockedMod> const& blocked_mods)
|
||||
void FlameCreationTask::copyBlockedMods(const QList<BlockedMod>& blocked_mods)
|
||||
{
|
||||
setStatus(tr("Copying Blocked Mods..."));
|
||||
setAbortable(false);
|
||||
int i = 0;
|
||||
int total = blocked_mods.length();
|
||||
setProgress(i, total);
|
||||
for (auto const& mod : blocked_mods) {
|
||||
for (const auto& mod : blocked_mods) {
|
||||
if (!mod.matched) {
|
||||
qDebug() << mod.name << "was not matched to a local file, skipping copy";
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ void FlameMod::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj)
|
|||
}
|
||||
}
|
||||
|
||||
pack.resourceType = FlameAPI::getResourceType(obj["classId"].toInt(0));
|
||||
pack.extraDataLoaded = false;
|
||||
loadURLs(pack, obj);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@
|
|||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include "modplatform/ModIndex.h"
|
||||
#include "modplatform/ResourceType.h"
|
||||
|
||||
namespace Flame {
|
||||
struct File {
|
||||
|
|
@ -55,7 +54,6 @@ struct File {
|
|||
|
||||
// our
|
||||
QString targetFolder = QStringLiteral("mods");
|
||||
ModPlatform::ResourceType resourceType;
|
||||
};
|
||||
|
||||
struct Modloader {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
#include "ModrinthAPI.h"
|
||||
#include <array>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Json.h"
|
||||
#include "modplatform/ResourceType.h"
|
||||
#include "net/ApiDownload.h"
|
||||
#include "net/ApiUpload.h"
|
||||
#include "net/NetJob.h"
|
||||
|
|
@ -122,6 +124,37 @@ QList<ResourceAPI::SortingMethod> ModrinthAPI::getSortingMethods() const
|
|||
{ .index = 4, .name = "newest", .readable_name = QObject::tr("Sort by Newest") },
|
||||
{ .index = 5, .name = "updated", .readable_name = QObject::tr("Sort by Last Updated") } };
|
||||
}
|
||||
namespace {
|
||||
const auto resourceTypeMap = std::array{
|
||||
std::pair{ ModPlatform::ResourceType::Mod, "mod" }, std::pair{ ModPlatform::ResourceType::ResourcePack, "resourcepack" },
|
||||
std::pair{ ModPlatform::ResourceType::ShaderPack, "shader" }, std::pair{ ModPlatform::ResourceType::DataPack, "datapack" },
|
||||
std::pair{ ModPlatform::ResourceType::Modpack, "modpack" },
|
||||
};
|
||||
}
|
||||
|
||||
ModPlatform::ResourceType ModrinthAPI::getResourceType(const QString& param)
|
||||
{
|
||||
for (const auto& [key, value] : resourceTypeMap) {
|
||||
if (value == param) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Invalid resource type for Modrinth API!" << param;
|
||||
return ModPlatform::ResourceType::Unknown;
|
||||
}
|
||||
|
||||
QString ModrinthAPI::resourceTypeParameter(ModPlatform::ResourceType type)
|
||||
{
|
||||
for (const auto& [key, value] : resourceTypeMap) {
|
||||
if (key == type) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Invalid resource type for Modrinth API!" << static_cast<std::uint8_t>(type);
|
||||
return "";
|
||||
}
|
||||
|
||||
std::pair<Task::Ptr, QByteArray*> ModrinthAPI::getModCategories()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -100,28 +100,10 @@ class ModrinthAPI : public ResourceAPI {
|
|||
}
|
||||
return v;
|
||||
}
|
||||
static ModPlatform::ResourceType getResourceType(const QString& param);
|
||||
|
||||
private:
|
||||
static QString resourceTypeParameter(ModPlatform::ResourceType type)
|
||||
{
|
||||
switch (type) {
|
||||
case ModPlatform::ResourceType::Mod:
|
||||
return "mod";
|
||||
case ModPlatform::ResourceType::ResourcePack:
|
||||
return "resourcepack";
|
||||
case ModPlatform::ResourceType::ShaderPack:
|
||||
return "shader";
|
||||
case ModPlatform::ResourceType::DataPack:
|
||||
return "datapack";
|
||||
case ModPlatform::ResourceType::Modpack:
|
||||
return "modpack";
|
||||
default:
|
||||
qWarning() << "Invalid resource type for Modrinth API!";
|
||||
break;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
static QString resourceTypeParameter(ModPlatform::ResourceType type);
|
||||
|
||||
QString createFacets(const SearchArgs& args) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ void Modrinth::loadIndexedPack(ModPlatform::IndexedPack& pack, QJsonObject& obj)
|
|||
|
||||
pack.provider = ModPlatform::ResourceProvider::MODRINTH;
|
||||
pack.name = Json::requireString(obj, "title");
|
||||
pack.resourceType = ModrinthAPI::getResourceType(obj["project_type"].toString());
|
||||
|
||||
pack.slug = obj["slug"].toString("");
|
||||
if (!pack.slug.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <utility>
|
||||
|
||||
#include "Application.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "ResourceDownloadTask.h"
|
||||
|
||||
#include "minecraft/PackProfile.h"
|
||||
|
|
@ -50,12 +51,16 @@
|
|||
|
||||
namespace ResourceDownload {
|
||||
|
||||
ResourceDownloadDialog::ResourceDownloadDialog(QWidget* parent, ResourceFolderModel* baseModel, bool suppressInitialSearch)
|
||||
ResourceDownloadDialog::ResourceDownloadDialog(QWidget* parent,
|
||||
ResourceFolderModel* baseModel,
|
||||
BaseInstance* inst,
|
||||
bool suppressInitialSearch)
|
||||
: QDialog(parent)
|
||||
, m_base_model(baseModel)
|
||||
, m_buttons(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel)
|
||||
, m_vertical_layout(this)
|
||||
, m_suppressInitialSearch(suppressInitialSearch)
|
||||
, m_instance(inst)
|
||||
{
|
||||
setObjectName(QStringLiteral("ResourceDownloadDialog"));
|
||||
|
||||
|
|
@ -200,9 +205,9 @@ void ResourceDownloadDialog::confirm()
|
|||
confirmDialog->appendResource({ .name = task->getName(),
|
||||
.filename = task->getFilename(),
|
||||
.provider = ModPlatform::ProviderCapabilities::name(task->getProvider()),
|
||||
.required_by = extraInfo.required_by,
|
||||
.required_by = extraInfo.requiredBy,
|
||||
.version_type = task->getVersion().version_type.toString(),
|
||||
.enabled = !extraInfo.maybe_installed });
|
||||
.enabled = !extraInfo.maybeInstalled });
|
||||
}
|
||||
|
||||
if (confirmDialog->exec() != 0) {
|
||||
|
|
@ -237,7 +242,32 @@ ResourcePage* ResourceDownloadDialog::selectedPage()
|
|||
void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& ver, QString downloadReason)
|
||||
{
|
||||
removeResource(pack->name);
|
||||
selectedPage()->addResourceToPage(pack, ver, getBaseModel(), std::move(downloadReason));
|
||||
auto* model = getBaseModel();
|
||||
auto* instance = dynamic_cast<MinecraftInstance*>(m_instance);
|
||||
if (instance) {
|
||||
switch (pack->resourceType) {
|
||||
case ModPlatform::ResourceType::Mod:
|
||||
model = instance->loaderModList();
|
||||
break;
|
||||
case ModPlatform::ResourceType::ResourcePack:
|
||||
model = instance->resourcePackList();
|
||||
break;
|
||||
case ModPlatform::ResourceType::ShaderPack:
|
||||
model = instance->shaderPackList();
|
||||
break;
|
||||
case ModPlatform::ResourceType::DataPack:
|
||||
model = instance->dataPackList();
|
||||
break;
|
||||
// case ModPlatform::ResourceType::World:
|
||||
// model = instance->worldList();
|
||||
case ModPlatform::ResourceType::TexturePack:
|
||||
model = instance->texturePackList();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
selectedPage()->addResourceToPage(pack, ver, model, std::move(downloadReason));
|
||||
setButtonStatus();
|
||||
}
|
||||
|
||||
|
|
@ -289,13 +319,25 @@ void ResourceDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* s
|
|||
}
|
||||
|
||||
ModDownloadDialog::ModDownloadDialog(QWidget* parent, ModFolderModel* mods, BaseInstance* instance, bool suppressInitialSearch)
|
||||
: ResourceDownloadDialog(parent, mods, suppressInitialSearch), m_instance(instance)
|
||||
: ResourceDownloadDialog(parent, mods, instance, suppressInitialSearch), m_instance(instance)
|
||||
{
|
||||
setWindowTitle(dialogTitle());
|
||||
|
||||
initializeContainer();
|
||||
connectButtons();
|
||||
|
||||
// need to load all resources for dependency task
|
||||
auto* mInstance = dynamic_cast<MinecraftInstance*>(instance);
|
||||
if (mInstance) {
|
||||
for (auto* model : mInstance->resourceLists()) {
|
||||
if (model) {
|
||||
if (model->empty()) {
|
||||
model->startWatching();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!geometrySaveKey().isEmpty()) {
|
||||
restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get(geometrySaveKey()).toString().toUtf8()));
|
||||
}
|
||||
|
|
@ -340,7 +382,7 @@ ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent,
|
|||
ResourcePackFolderModel* resourcePacks,
|
||||
BaseInstance* instance,
|
||||
bool suppressInitialSearch)
|
||||
: ResourceDownloadDialog(parent, resourcePacks, suppressInitialSearch), m_instance(instance)
|
||||
: ResourceDownloadDialog(parent, resourcePacks, instance, suppressInitialSearch), m_instance(instance)
|
||||
{
|
||||
setWindowTitle(dialogTitle());
|
||||
|
||||
|
|
@ -372,7 +414,7 @@ TexturePackDownloadDialog::TexturePackDownloadDialog(QWidget* parent,
|
|||
TexturePackFolderModel* resourcePacks,
|
||||
BaseInstance* instance,
|
||||
bool suppressInitialSearch)
|
||||
: ResourceDownloadDialog(parent, resourcePacks, suppressInitialSearch), m_instance(instance)
|
||||
: ResourceDownloadDialog(parent, resourcePacks, instance, suppressInitialSearch), m_instance(instance)
|
||||
{
|
||||
setWindowTitle(dialogTitle());
|
||||
|
||||
|
|
@ -404,7 +446,7 @@ ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent,
|
|||
ShaderPackFolderModel* shaders,
|
||||
BaseInstance* instance,
|
||||
bool suppressInitialSearch)
|
||||
: ResourceDownloadDialog(parent, shaders, suppressInitialSearch), m_instance(instance)
|
||||
: ResourceDownloadDialog(parent, shaders, instance, suppressInitialSearch), m_instance(instance)
|
||||
{
|
||||
setWindowTitle(dialogTitle());
|
||||
|
||||
|
|
@ -452,7 +494,7 @@ DataPackDownloadDialog::DataPackDownloadDialog(QWidget* parent,
|
|||
DataPackFolderModel* dataPacks,
|
||||
BaseInstance* instance,
|
||||
bool suppressInitialSearch)
|
||||
: ResourceDownloadDialog(parent, dataPacks, suppressInitialSearch), m_instance(instance)
|
||||
: ResourceDownloadDialog(parent, dataPacks, instance, suppressInitialSearch), m_instance(instance)
|
||||
{
|
||||
setWindowTitle(dialogTitle());
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider {
|
|||
public:
|
||||
using DownloadTaskPtr = shared_qobject_ptr<ResourceDownloadTask>;
|
||||
|
||||
ResourceDownloadDialog(QWidget* parent, ResourceFolderModel* baseModel, bool suppressInitialSearch = false);
|
||||
ResourceDownloadDialog(QWidget* parent, ResourceFolderModel* baseModel, BaseInstance* instance, bool suppressInitialSearch = false);
|
||||
|
||||
void initializeContainer();
|
||||
void connectButtons();
|
||||
|
|
@ -95,8 +95,8 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider {
|
|||
QDialogButtonBox m_buttons;
|
||||
QVBoxLayout m_vertical_layout;
|
||||
|
||||
protected:
|
||||
bool m_suppressInitialSearch = false;
|
||||
BaseInstance* m_instance = nullptr;
|
||||
};
|
||||
|
||||
class ModDownloadDialog final : public ResourceDownloadDialog {
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ void ResourceUpdateDialog::checkCandidates()
|
|||
ScrollMessageBox messageDialog(m_parent, tr("Failed to check for updates"),
|
||||
tr("Could not check or get the following resources for updates:<br>"
|
||||
"Do you wish to proceed without those resources?"),
|
||||
text, "Disable unavailable mods");
|
||||
text, tr("Disable unavailable mods"));
|
||||
messageDialog.setModal(true);
|
||||
if (messageDialog.exec() == QDialog::Rejected) {
|
||||
m_aborted = true;
|
||||
|
|
@ -244,10 +244,10 @@ void ResourceUpdateDialog::checkCandidates()
|
|||
auto extraInfo = dependencyExtraInfo.value(dep->version.addonId.toString());
|
||||
CheckUpdateTask::Update updatable = {
|
||||
dep->pack->name, dep->version.hash, tr("Not installed"), dep->version.version, dep->version.version_type,
|
||||
changelog, dep->pack->provider, downloadTask, !extraInfo.maybe_installed
|
||||
changelog, dep->pack->provider, downloadTask, !extraInfo.maybeInstalled,
|
||||
};
|
||||
|
||||
appendResource(updatable, extraInfo.required_by);
|
||||
appendResource(updatable, extraInfo.requiredBy);
|
||||
m_tasks.insert(updatable.name, updatable.download);
|
||||
}
|
||||
}
|
||||
|
|
@ -517,7 +517,7 @@ void ResourceUpdateDialog::appendResource(const CheckUpdateTask::Update& info, Q
|
|||
ui->modTreeWidget->addTopLevelItem(itemTop);
|
||||
}
|
||||
|
||||
auto ResourceUpdateDialog::getTasks() -> const QList<ResourceDownloadTask::Ptr>
|
||||
auto ResourceUpdateDialog::getTasks() const -> QList<ResourceDownloadTask::Ptr>
|
||||
{
|
||||
QList<ResourceDownloadTask::Ptr> list;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class ResourceUpdateDialog final : public ReviewMessageBox {
|
|||
|
||||
void appendResource(const CheckUpdateTask::Update& info, QStringList requiredBy = {});
|
||||
|
||||
const QList<ResourceDownloadTask::Ptr> getTasks();
|
||||
QList<ResourceDownloadTask::Ptr> getTasks() const;
|
||||
auto indexDir() const -> QDir { return m_resourceModel->indexDir(); }
|
||||
|
||||
auto noUpdates() const -> bool { return m_noUpdates; };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue