chore(clang-tidy): modernize the code

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97 2026-05-11 23:16:39 +03:00
parent 18f04b1e29
commit 9c88eb9bc0
No known key found for this signature in database
GPG key ID: 55EF5DA53DB36318
36 changed files with 713 additions and 632 deletions

View file

@ -15,6 +15,8 @@
#include "BaseEntity.h"
#include <utility>
#include "Exception.h"
#include "FileSystem.h"
#include "Json.h"
@ -26,19 +28,18 @@
#include "net/NetJob.h"
#include "Application.h"
#include "settings/SettingsObject.h"
#include "BuildConfig.h"
#include "settings/SettingsObject.h"
#include "tasks/Task.h"
namespace Meta {
namespace {
class ParsingValidator : public Net::Validator {
public: /* con/des */
ParsingValidator(BaseEntity* entity) : m_entity(entity) {};
virtual ~ParsingValidator() = default;
explicit ParsingValidator(Meta::BaseEntity* entity) : m_entity(entity) {};
~ParsingValidator() override = default;
public: /* methods */
bool init(QNetworkRequest&) override
bool init(QNetworkRequest& /*request*/) override
{
m_data.clear();
return true;
@ -53,7 +54,7 @@ class ParsingValidator : public Net::Validator {
m_data.clear();
return true;
}
bool validate(QNetworkReply&) override
bool validate(QNetworkReply& /*reply*/) override
{
auto fname = m_entity->localFilename();
try {
@ -69,12 +70,14 @@ class ParsingValidator : public Net::Validator {
private: /* data */
QByteArray m_data;
BaseEntity* m_entity;
Meta::BaseEntity* m_entity;
};
} // namespace
namespace Meta {
QUrl BaseEntity::url() const
{
auto s = APPLICATION->settings();
auto* s = APPLICATION->settings();
QString metaOverride = s->get("MetaURLOverride").toString();
if (metaOverride.isEmpty()) {
return QUrl(BuildConfig.META_URL).resolved(localFilename());
@ -82,33 +85,33 @@ QUrl BaseEntity::url() const
return QUrl(metaOverride).resolved(localFilename());
}
Task::Ptr BaseEntity::loadTask(Net::Mode mode, bool forceReload)
Task::Ptr BaseEntity::loadTask(Net::Mode loadType, bool forceReload)
{
if (m_task && m_task->isRunning()) {
return m_task;
}
m_task.reset(new BaseEntityLoadTask(this, mode, forceReload));
m_task.reset(new BaseEntityLoadTask(this, loadType, forceReload));
return m_task;
}
bool BaseEntity::isLoaded() const
{
// consider it loaded only if the main hash is either empty and was remote loadded or the hashes match and was loaded
return m_sha256.isEmpty() ? m_load_status == LoadStatus::Remote : m_load_status != LoadStatus::NotLoaded && m_sha256 == m_file_sha256;
return m_sha256.isEmpty() ? m_loadStatus == LoadStatus::Remote : m_loadStatus != LoadStatus::NotLoaded && m_sha256 == m_fileSha256;
}
void BaseEntity::setSha256(QString sha256)
{
m_sha256 = sha256;
m_sha256 = std::move(sha256);
}
BaseEntity::LoadStatus BaseEntity::status() const
{
return m_load_status;
return m_loadStatus;
}
BaseEntityLoadTask::BaseEntityLoadTask(BaseEntity* parent, Net::Mode mode, bool forceReload)
: m_entity(parent), m_mode(mode), m_force_reload(forceReload)
: m_entity(parent), m_mode(mode), m_forceReload(forceReload)
{}
void BaseEntityLoadTask::executeTask()
@ -120,47 +123,47 @@ void BaseEntityLoadTask::executeTask()
try {
QByteArray fileData;
// read local file if nothing is loaded yet
if (m_entity->m_load_status == BaseEntity::LoadStatus::NotLoaded || m_entity->m_file_sha256.isEmpty()) {
if (m_entity->m_loadStatus == BaseEntity::LoadStatus::NotLoaded || m_entity->m_fileSha256.isEmpty()) {
setStatus(tr("Loading local file"));
fileData = FS::read(fname);
m_entity->m_file_sha256 = Hashing::hash(fileData, Hashing::Algorithm::Sha256);
m_entity->m_fileSha256 = Hashing::hash(fileData, Hashing::Algorithm::Sha256);
}
// on online the hash needs to match
const auto& expected = m_entity->m_sha256;
const auto& actual = m_entity->m_file_sha256;
const auto& actual = m_entity->m_fileSha256;
hashMatches = expected == actual;
if (m_mode == Net::Mode::Online && !m_entity->m_sha256.isEmpty() && !hashMatches) {
throw Exception(QString("Checksum mismatch, expected sha256: %1, got: %2").arg(expected, actual));
}
// load local file
if (m_entity->m_load_status == BaseEntity::LoadStatus::NotLoaded) {
if (m_entity->m_loadStatus == BaseEntity::LoadStatus::NotLoaded) {
auto doc = Json::requireDocument(fileData, fname);
auto obj = Json::requireObject(doc, fname);
m_entity->parse(obj);
m_entity->m_load_status = BaseEntity::LoadStatus::Local;
m_entity->m_loadStatus = BaseEntity::LoadStatus::Local;
}
} catch (const Exception& e) {
qCritical() << QString("Unable to parse file %1: %2").arg(fname, e.cause());
// just make sure it's gone and we never consider it again.
FS::deletePath(fname);
m_entity->m_load_status = BaseEntity::LoadStatus::NotLoaded;
m_entity->m_loadStatus = BaseEntity::LoadStatus::NotLoaded;
}
}
// if we need remote update, run the update task
auto wasLoadedOffline = m_entity->m_load_status != BaseEntity::LoadStatus::NotLoaded && m_mode == Net::Mode::Offline;
auto wasLoadedOffline = m_entity->m_loadStatus != BaseEntity::LoadStatus::NotLoaded && m_mode == Net::Mode::Offline;
// if has is not present allways fetch from remote(e.g. the main index file), else only fetch if hash doesn't match
auto wasLoadedRemote = m_entity->m_sha256.isEmpty() ? m_entity->m_load_status == BaseEntity::LoadStatus::Remote : hashMatches;
if (wasLoadedOffline || (wasLoadedRemote && !m_force_reload)) {
auto wasLoadedRemote = m_entity->m_sha256.isEmpty() ? m_entity->m_loadStatus == BaseEntity::LoadStatus::Remote : hashMatches;
if (wasLoadedOffline || (wasLoadedRemote && !m_forceReload)) {
emitSucceeded();
return;
}
m_task.reset(new NetJob(QObject::tr("Download of meta file %1").arg(m_entity->localFilename()), APPLICATION->network()));
auto url = m_entity->url();
auto entry = APPLICATION->metacache()->resolveEntry("meta", m_entity->localFilename());
if (m_force_reload) {
if (m_forceReload) {
// clear validators so manual refreshes fetch a fresh body
entry->setETag({});
entry->setRemoteChangedTimestamp({});
@ -171,15 +174,16 @@ void BaseEntityLoadTask::executeTask()
* The validator parses the file and loads it into the object.
* If that fails, the file is not written to storage.
*/
if (!m_entity->m_sha256.isEmpty())
if (!m_entity->m_sha256.isEmpty()) {
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Algorithm::Sha256, m_entity->m_sha256));
}
dl->addValidator(new ParsingValidator(m_entity));
m_task->addNetAction(dl);
m_task->setAskRetry(false);
connect(m_task.get(), &Task::failed, this, &BaseEntityLoadTask::emitFailed);
connect(m_task.get(), &Task::succeeded, this, [this]() {
m_entity->m_load_status = BaseEntity::LoadStatus::Remote;
m_entity->m_file_sha256 = m_entity->m_sha256;
m_entity->m_loadStatus = BaseEntity::LoadStatus::Remote;
m_entity->m_fileSha256 = m_entity->m_sha256;
emitSucceeded();
});

View file

@ -29,7 +29,7 @@ class BaseEntity {
public: /* types */
using Ptr = std::shared_ptr<BaseEntity>;
enum class LoadStatus { NotLoaded, Local, Remote };
enum class LoadStatus : std::uint8_t { NotLoaded, Local, Remote };
public:
virtual ~BaseEntity() = default;
@ -47,10 +47,10 @@ class BaseEntity {
protected:
QString m_sha256; // the expected sha256
QString m_file_sha256; // the file sha256
QString m_fileSha256; // the file sha256
private:
LoadStatus m_load_status = LoadStatus::NotLoaded;
LoadStatus m_loadStatus = LoadStatus::NotLoaded;
Task::Ptr m_task;
};
@ -61,14 +61,14 @@ class BaseEntityLoadTask : public Task {
explicit BaseEntityLoadTask(BaseEntity* parent, Net::Mode mode, bool forceReload);
~BaseEntityLoadTask() override = default;
virtual void executeTask() override;
virtual bool canAbort() const override;
virtual bool abort() override;
void executeTask() override;
bool canAbort() const override;
bool abort() override;
private:
BaseEntity* m_entity;
Net::Mode m_mode;
bool m_force_reload = false;
bool m_forceReload = false;
NetJob::Ptr m_task;
};
} // namespace Meta

View file

@ -230,7 +230,7 @@ int DataPack::compare(const Resource& other, SortType type) const
return 0;
}
bool DataPack::applyFilter(QRegularExpression filter) const
bool DataPack::applyFilter(const QRegularExpression& filter) const
{
if (filter.match(description()).hasMatch()) {
return true;

View file

@ -61,7 +61,7 @@ class DataPack : public Resource {
bool valid() const override;
[[nodiscard]] int compare(const Resource& other, SortType type) const override;
[[nodiscard]] bool applyFilter(QRegularExpression filter) const override;
[[nodiscard]] bool applyFilter(const QRegularExpression& filter) const override;
QString packFormatStr() const;

View file

@ -42,28 +42,28 @@
#include <QString>
#include "MTPixmapCache.h"
#include "MetadataHandler.h"
#include "Resource.h"
#include "Version.h"
#include "minecraft/mod/ModDetails.h"
#include "minecraft/mod/tasks/LocalModParseTask.h"
#include "modplatform/ModIndex.h"
Mod::Mod(const QFileInfo& file) : Resource(file), m_local_details()
Mod::Mod(const QFileInfo& file) : Resource(file)
{
m_enabled = (file.suffix() != "disabled");
}
void Mod::setDetails(const ModDetails& details)
{
m_local_details = details;
m_localDetails = details;
}
int Mod::compare(const Resource& other, SortType type) const
{
auto cast_other = dynamic_cast<const Mod*>(&other);
if (!cast_other)
const auto* castOther = dynamic_cast<const Mod*>(&other);
if (!castOther) {
return Resource::compare(other, type);
}
switch (type) {
default:
@ -73,60 +73,71 @@ int Mod::compare(const Resource& other, SortType type) const
case SortType::Size:
return Resource::compare(other, type);
case SortType::Version: {
auto this_ver = Version(version());
auto other_ver = Version(cast_other->version());
if (this_ver > other_ver)
auto thisVer = Version(version());
auto otherVer = Version(castOther->version());
if (thisVer > otherVer) {
return 1;
if (this_ver < other_ver)
}
if (thisVer < otherVer) {
return -1;
}
break;
}
case SortType::Side: {
auto compare_result = QString::compare(side(), cast_other->side(), Qt::CaseInsensitive);
if (compare_result != 0)
return compare_result;
auto compareResult = QString::compare(side(), castOther->side(), Qt::CaseInsensitive);
if (compareResult != 0) {
return compareResult;
}
break;
}
case SortType::McVersions: {
auto compare_result = QString::compare(mcVersions(), cast_other->mcVersions(), Qt::CaseInsensitive);
if (compare_result != 0)
return compare_result;
auto compareResult = QString::compare(mcVersions(), castOther->mcVersions(), Qt::CaseInsensitive);
if (compareResult != 0) {
return compareResult;
}
break;
}
case SortType::Loaders: {
auto compare_result = QString::compare(loaders(), cast_other->loaders(), Qt::CaseInsensitive);
if (compare_result != 0)
return compare_result;
auto compareResult = QString::compare(loaders(), castOther->loaders(), Qt::CaseInsensitive);
if (compareResult != 0) {
return compareResult;
}
break;
}
case SortType::ReleaseType: {
auto compare_result = QString::compare(releaseType(), cast_other->releaseType(), Qt::CaseInsensitive);
if (compare_result != 0)
return compare_result;
auto compareResult = QString::compare(releaseType(), castOther->releaseType(), Qt::CaseInsensitive);
if (compareResult != 0) {
return compareResult;
}
break;
}
case SortType::RequiredBy: {
if (requiredByCount() > cast_other->requiredByCount())
if (requiredByCount() > castOther->requiredByCount()) {
return 1;
if (requiredByCount() < cast_other->requiredByCount())
}
if (requiredByCount() < castOther->requiredByCount()) {
return -1;
}
break;
}
case SortType::Requires: {
if (requiresCount() > cast_other->requiresCount())
if (requiresCount() > castOther->requiresCount()) {
return 1;
if (requiresCount() < cast_other->requiresCount())
}
if (requiresCount() < castOther->requiresCount()) {
return -1;
}
break;
}
}
return 0;
}
bool Mod::applyFilter(QRegularExpression filter) const
bool Mod::applyFilter(const QRegularExpression& filter) const
{
if (filter.match(description()).hasMatch())
if (filter.match(description()).hasMatch()) {
return true;
}
for (auto& author : authors()) {
if (filter.match(author).hasMatch()) {
@ -139,23 +150,25 @@ bool Mod::applyFilter(QRegularExpression filter) const
auto Mod::details() const -> const ModDetails&
{
return m_local_details;
return m_localDetails;
}
auto Mod::name() const -> QString
{
auto d_name = details().name;
if (!d_name.isEmpty())
return d_name;
auto dName = details().name;
if (!dName.isEmpty()) {
return dName;
}
return Resource::name();
}
auto Mod::mod_id() const -> QString
auto Mod::modId() const -> QString
{
auto d_mod_id = details().mod_id;
if (!d_mod_id.isEmpty())
return d_mod_id;
auto dModId = details().mod_id;
if (!dModId.isEmpty()) {
return dModId;
}
return Resource::name();
}
@ -169,9 +182,9 @@ auto Mod::homepage() const -> QString
{
QString metaUrl = Resource::homepage();
if (metaUrl.isEmpty())
if (metaUrl.isEmpty()) {
return details().homeurl;
else
}
return metaUrl;
}
@ -191,24 +204,27 @@ auto Mod::loaders() const -> QString
auto Mod::side() const -> QString
{
if (metadata())
if (metadata()) {
return ModPlatform::SideUtils::toString(metadata()->side);
}
return ModPlatform::SideUtils::toString(ModPlatform::Side::UniversalSide);
}
auto Mod::mcVersions() const -> QString
{
if (metadata())
if (metadata()) {
return metadata()->mcVersions.join(", ");
}
return {};
}
auto Mod::releaseType() const -> QString
{
if (metadata())
if (metadata()) {
return metadata()->releaseType.toString();
}
return ModPlatform::IndexedVersionType(ModPlatform::IndexedVersionType::Unknown).toString();
}
@ -225,10 +241,10 @@ auto Mod::authors() const -> QStringList
void Mod::finishResolvingWithDetails(ModDetails&& details)
{
m_is_resolving = false;
m_is_resolved = true;
m_isResolving = false;
m_isResolved = true;
m_local_details = std::move(details);
m_localDetails = std::move(details);
if (!iconPath().isEmpty()) {
m_packImageCacheKey.wasReadAttempt = false;
}
@ -244,18 +260,19 @@ auto Mod::issueTracker() const -> QString
return details().issue_tracker;
}
QPixmap Mod::setIcon(QImage new_image) const
QPixmap Mod::setIcon(const QImage& newImage) const
{
QMutexLocker locker(&m_data_lock);
QMutexLocker locker(&m_dataLock);
Q_ASSERT(!new_image.isNull());
Q_ASSERT(!newImage.isNull());
if (m_packImageCacheKey.key.isValid())
if (m_packImageCacheKey.key.isValid()) {
PixmapCache::remove(m_packImageCacheKey.key);
}
// scale the image to avoid flooding the pixmapcache
auto pixmap =
QPixmap::fromImage(new_image.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
QPixmap::fromImage(newImage.scaled({ 64, 64 }, Qt::AspectRatioMode::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
m_packImageCacheKey.key = PixmapCache::insert(pixmap);
m_packImageCacheKey.wasEverUsed = true;
@ -265,20 +282,22 @@ QPixmap Mod::setIcon(QImage new_image) const
QPixmap Mod::icon(QSize size, Qt::AspectRatioMode mode) const
{
auto pixmap_transform = [&size, &mode](QPixmap pixmap) {
if (size.isNull())
auto pixmapTransform = [&size, &mode](QPixmap pixmap) {
if (size.isNull()) {
return pixmap;
}
return pixmap.scaled(size, mode, Qt::SmoothTransformation);
};
QPixmap cached_image;
if (PixmapCache::find(m_packImageCacheKey.key, &cached_image)) {
return pixmap_transform(cached_image);
QPixmap cachedImage;
if (PixmapCache::find(m_packImageCacheKey.key, &cachedImage)) {
return pixmapTransform(cachedImage);
}
// No valid image we can get
if ((!m_packImageCacheKey.wasEverUsed && m_packImageCacheKey.wasReadAttempt) || iconPath().isEmpty())
if ((!m_packImageCacheKey.wasEverUsed && m_packImageCacheKey.wasReadAttempt) || iconPath().isEmpty()) {
return {};
}
if (m_packImageCacheKey.wasEverUsed) {
qDebug() << "Mod" << name() << "Had it's icon evicted from the cache. reloading...";
@ -286,8 +305,8 @@ QPixmap Mod::icon(QSize size, Qt::AspectRatioMode mode) const
}
// Image got evicted from the cache or an attempt to load it has not been made. load it and retry.
m_packImageCacheKey.wasReadAttempt = true;
if (ModUtils::loadIconFile(*this, &cached_image)) {
return pixmap_transform(cached_image);
if (ModUtils::loadIconFile(*this, &cachedImage)) {
return pixmapTransform(cachedImage);
}
// Image failed to load
return {};
@ -295,7 +314,7 @@ QPixmap Mod::icon(QSize size, Qt::AspectRatioMode mode) const
bool Mod::valid() const
{
return !m_local_details.mod_id.isEmpty();
return !m_localDetails.mod_id.isEmpty();
}
QStringList Mod::dependencies() const

View file

@ -54,12 +54,12 @@ class Mod : public Resource {
using WeakPtr = QPointer<Mod>;
Mod() = default;
Mod(const QFileInfo& file);
Mod(QString file_path) : Mod(QFileInfo(file_path)) {}
explicit Mod(const QFileInfo& file);
explicit Mod(const QString& filePath) : Mod(QFileInfo(filePath)) {}
auto details() const -> const ModDetails&;
auto name() const -> QString override;
auto mod_id() const -> QString;
auto modId() const -> QString;
auto version() const -> QString;
auto homepage() const -> QString override;
auto description() const -> QString;
@ -79,30 +79,30 @@ class Mod : public Resource {
void setRequiresCount(int value);
/** Get the intneral path to the mod's icon file*/
QString iconPath() const { return m_local_details.icon_file; }
QString iconPath() const { return m_localDetails.icon_file; }
/** Gets the icon of the mod, converted to a QPixmap for drawing, and scaled to size. */
QPixmap icon(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const;
/** Thread-safe. */
QPixmap setIcon(QImage new_image) const;
QPixmap setIcon(const QImage& newImage) const;
void setDetails(const ModDetails& details);
bool valid() const override;
[[nodiscard]] int compare(const Resource& other, SortType type) const override;
[[nodiscard]] bool applyFilter(QRegularExpression filter) const override;
[[nodiscard]] bool applyFilter(const QRegularExpression& filter) const override;
// Delete all the files of this mod
auto destroy(QDir& index_dir, bool preserve_metadata = false, bool attempt_trash = true) -> bool;
auto destroy(QDir& indexDir, bool preserveMetadata = false, bool attemptTrash = true) -> bool;
// Delete the metadata only
void destroyMetadata(QDir& index_dir);
void destroyMetadata(QDir& indexDir);
void finishResolvingWithDetails(ModDetails&& details);
protected:
ModDetails m_local_details;
ModDetails m_localDetails;
mutable QMutex m_data_lock;
mutable QMutex m_dataLock;
struct {
QPixmapCache::Key key;

View file

@ -69,12 +69,12 @@ ModFolderModel::ModFolderModel(const QDir& dir, BaseInstance* instance, bool isI
tr("Requires"), tr("Required By"), tr("File Name"), tr("Update") });
m_columnSortKeys = { SortType::Enabled, SortType::Name, SortType::Name, SortType::Version, SortType::Date,
SortType::Provider, SortType::Size, SortType::Side, SortType::Loaders, SortType::McVersions,
SortType::ReleaseType, SortType::Requires, SortType::RequiredBy, SortType::Filename, SortType::LOCK_UPDATE };
SortType::ReleaseType, SortType::Requires, SortType::RequiredBy, SortType::Filename, SortType::LockUpdate };
m_columnResizeModes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive,
QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive,
QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive,
QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive };
m_columnsHideable = { false, true, false, true, true, true, true, true, true, true, true, true, true, true };
m_columnsHideable = { false, true, false, true, true, true, true, true, true, true, true, true, true, true, true };
connect(this, &ModFolderModel::parseFinished, this, &ModFolderModel::onParseFinished);
}
@ -137,13 +137,15 @@ QVariant ModFolderModel::data(const QModelIndex& index, int role) const
}
break;
case Qt::CheckStateRole:
if (column == ActiveColumn)
if (column == ActiveColumn) {
return at(row).enabled() ? Qt::Checked : Qt::Unchecked;
return QVariant();
}
return {};
case Qt::UserRole:
if (column == LockUpdateCoumn)
if (column == LockUpdateCoumn) {
return at(row).lockUpdate();
return QVariant();
}
return {};
default:
break;
}
@ -285,7 +287,7 @@ void ModFolderModel::onParseSucceeded(int ticket, const QString& resourceId)
namespace {
Mod* findById(QSet<Mod*> mods, const QString& resourceId)
{
auto found = std::ranges::find_if(mods, [resourceId](Mod* m) { return m->mod_id() == resourceId; });
auto found = std::ranges::find_if(mods, [resourceId](Mod* m) { return m->modId() == resourceId; });
return found != mods.end() ? *found : nullptr;
}
} // namespace
@ -303,17 +305,17 @@ void ModFolderModel::onParseFinished()
auto findByProjectID = [mods](const QVariant& modId, ModPlatform::ResourceProvider provider) -> Mod* {
auto found = std::ranges::find_if(mods, [modId, provider](Mod* m) {
return m->metadata() && m->metadata()->provider == provider && m->metadata()->project_id == modId;
return m->metadata() && m->metadata()->provider == provider && m->metadata()->projectId == modId;
});
return found != mods.end() ? *found : nullptr;
};
for (auto* mod : mods) {
auto id = mod->mod_id();
auto id = mod->modId();
for (const auto& dep : mod->dependencies()) {
auto* d = findById(mods, dep);
if (d) {
m_requires[id] << d;
m_requiredBy[d->mod_id()] << mod;
m_requiredBy[d->modId()] << mod;
}
}
if (mod->metadata()) {
@ -322,17 +324,17 @@ void ModFolderModel::onParseFinished()
auto* d = findByProjectID(dep.addonId, mod->metadata()->provider);
if (d) {
m_requires[id] << d;
m_requiredBy[d->mod_id()] << mod;
m_requiredBy[d->modId()] << mod;
}
}
}
}
}
for (auto* mod : mods) {
auto id = mod->mod_id();
auto id = mod->modId();
if (mod->requiredByCount() != m_requiredBy[id].count() || mod->requiresCount() != m_requires[id].count()) {
mod->setRequiredByCount(m_requiredBy[id].count());
mod->setRequiresCount(m_requires[id].count());
mod->setRequiredByCount(static_cast<int>(m_requiredBy[id].count()));
mod->setRequiresCount(static_cast<int>(m_requires[id].count()));
int row = m_resourcesIndex[mod->internalId()];
emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1));
}
@ -346,11 +348,11 @@ QSet<Mod*> collectMods(const QSet<Mod*>& mods, QHash<QString, QSet<Mod*>> relati
QSet<Mod*> affectedList = {};
QSet<Mod*> needToCheck = {};
for (auto* mod : mods) {
auto id = mod->mod_id();
auto id = mod->modId();
if (!seen.contains(id)) {
seen.insert(id);
for (auto* affected : relation[id]) {
auto affectedId = affected->mod_id();
auto affectedId = affected->modId();
if (findById(mods, affectedId) == nullptr && !seen.contains(affectedId)) {
seen.insert(affectedId);
@ -395,7 +397,7 @@ QModelIndexList ModFolderModel::getAffectedMods(const QModelIndexList& indexes,
}
}
for (auto* affected : affectedMods) {
auto affectedId = affected->mod_id();
auto affectedId = affected->modId();
auto row = m_resourcesIndex[affected->internalId()];
affectedList << index(row, 0);
}
@ -457,20 +459,20 @@ bool ModFolderModel::setResourceEnabled(const QModelIndexList& indexes, EnableAc
if (requiredToEnable.size() > 0 && requiredToDisable.size() > 0) {
title = tr("Confirm toggle");
message = tr("Toggling these mod(s) will cause changes to other mods.\n") +
tr("%n mod(s) will be enabled\n", "", requiredToEnable.size()) +
tr("%n mod(s) will be disabled\n", "", requiredToDisable.size()) +
tr("%n mod(s) will be enabled\n", "", static_cast<int>(requiredToEnable.size())) +
tr("%n mod(s) will be disabled\n", "", static_cast<int>(requiredToDisable.size())) +
tr("Do you want to automatically apply these related changes?\nIgnoring them may break the game.");
noButton = tr("Only Toggle Selected");
yesButton = tr("Toggle Required Mods");
} else if (requiredToEnable.size() > 0) {
title = tr("Confirm enable");
message = tr("The enabled mod(s) require %n mod(s).\n", "", requiredToEnable.size()) +
message = tr("The enabled mod(s) require %n mod(s).\n", "", static_cast<int>(requiredToEnable.size())) +
tr("Would you like to enable them as well?\nIgnoring them may break the game.");
noButton = tr("Only Enable Selected");
yesButton = tr("Enable Required");
} else {
title = tr("Confirm disable");
message = tr("The disabled mod(s) are required by %n mod(s).\n", "", requiredToDisable.size()) +
message = tr("The disabled mod(s) are required by %n mod(s).\n", "", static_cast<int>(requiredToDisable.size())) +
tr("Would you like to disable them as well?\nIgnoring them may break the game.");
noButton = tr("Only Disable Selected");
yesButton = tr("Disable Required");
@ -532,12 +534,12 @@ bool ModFolderModel::deleteResources(const QModelIndexList& indexes)
};
auto rsp = ResourceFolderModel::deleteResources(indexes);
for (auto* mod : allMods()) {
auto id = mod->mod_id();
auto id = mod->modId();
deleteInvalid(m_requiredBy[id]);
deleteInvalid(m_requires[id]);
if (mod->requiredByCount() != m_requiredBy[id].count() || mod->requiresCount() != m_requires[id].count()) {
mod->setRequiredByCount(m_requiredBy[id].count());
mod->setRequiresCount(m_requires[id].count());
mod->setRequiredByCount(static_cast<int>(m_requiredBy[id].count()));
mod->setRequiresCount(static_cast<int>(m_requires[id].count()));
int row = m_resourcesIndex[mod->internalId()];
emit dataChanged(index(row, RequiresColumn), index(row, RequiredByColumn));
}

View file

@ -11,16 +11,16 @@
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
Resource::Resource(QObject* parent) : QObject(parent), m_size_info(0) {}
Resource::Resource(QObject* parent) : QObject(parent), m_sizeInfo(0) {}
Resource::Resource(QFileInfo fileInfo) : m_size_info(0)
Resource::Resource(const QFileInfo& fileInfo) : m_sizeInfo(0)
{
setFile(fileInfo);
}
void Resource::setFile(QFileInfo fileInfo)
{
m_file_info = std::move(fileInfo);
m_fileInfo = std::move(fileInfo);
parseFile();
}
@ -37,23 +37,23 @@ std::tuple<QString, qint64> calculateFileSize(const QFileInfo& file)
}
return { QString("%1 %2").arg(QString::number(count), str), count };
}
return { StringUtils::humanReadableFileSize(file.size(), true), file.size() };
return { StringUtils::humanReadableFileSize(static_cast<double>(file.size()), true), file.size() };
}
} // namespace
void Resource::parseFile()
{
QString fileName{ m_file_info.fileName() };
QString fileName{ m_fileInfo.fileName() };
m_type = ResourceType::UNKNOWN;
m_internal_id = fileName;
m_internalId = fileName;
std::tie(m_size_str, m_size_info) = calculateFileSize(m_file_info);
if (m_file_info.isDir()) {
std::tie(m_sizeStr, m_sizeInfo) = calculateFileSize(m_fileInfo);
if (m_fileInfo.isDir()) {
m_type = ResourceType::FOLDER;
m_name = fileName;
} else if (m_file_info.isFile()) {
} else if (m_fileInfo.isFile()) {
if (fileName.endsWith(".disabled")) {
fileName.chop(9);
m_enabled = false;
@ -75,7 +75,7 @@ void Resource::parseFile()
m_name = fileName;
}
m_changed_date_time = m_file_info.lastModified();
m_changedDateTime = m_fileInfo.lastModified();
}
auto Resource::name() const -> QString
@ -108,7 +108,7 @@ auto Resource::provider() const -> QString
auto Resource::homepage() const -> QString
{
if (metadata()) {
return ModPlatform::getMetaURL(metadata()->provider, metadata()->project_id);
return ModPlatform::getMetaURL(metadata()->provider, metadata()->projectId);
}
return {};
@ -116,8 +116,9 @@ auto Resource::homepage() const -> QString
bool Resource::lockUpdate() const
{
if (metadata())
if (metadata()) {
return metadata()->lockUpdate;
}
return false;
}
@ -128,7 +129,7 @@ void Resource::setMetadata(std::shared_ptr<Metadata::ModStruct>&& metadata)
setStatus(ResourceStatus::Installed);
}
m_metadata = metadata;
m_metadata = std::move(metadata);
}
QStringList Resource::issues() const
@ -229,7 +230,7 @@ int Resource::compare(const Resource& other, SortType type) const
return 0;
}
bool Resource::applyFilter(QRegularExpression filter) const
bool Resource::applyFilter(const QRegularExpression& filter) const
{
if (filter.match(name()).hasMatch()) {
return true;
@ -246,7 +247,7 @@ bool Resource::enable(EnableAction action)
return false;
}
QString path = m_file_info.absoluteFilePath();
QString path = m_fileInfo.absoluteFilePath();
QFile file(path);
bool enable = true;
@ -299,7 +300,7 @@ auto Resource::destroy(const QDir& indexDir, bool preserveMetadata, bool attempt
destroyMetadata(indexDir);
}
return (attemptTrash && FS::trash(m_file_info.filePath())) || FS::deletePath(m_file_info.filePath());
return (attemptTrash && FS::trash(m_fileInfo.filePath())) || FS::deletePath(m_fileInfo.filePath());
}
auto Resource::destroyMetadata(const QDir& indexDir) -> void
@ -321,20 +322,20 @@ bool Resource::isSymLinkUnder(const QString& instPath) const
auto instDir = QDir(instPath);
auto relAbsPath = instDir.relativeFilePath(m_file_info.absoluteFilePath());
auto relCanonPath = instDir.relativeFilePath(m_file_info.canonicalFilePath());
auto relAbsPath = instDir.relativeFilePath(m_fileInfo.absoluteFilePath());
auto relCanonPath = instDir.relativeFilePath(m_fileInfo.canonicalFilePath());
return relAbsPath != relCanonPath;
}
bool Resource::isMoreThanOneHardLink() const
{
return FS::hardLinkCount(m_file_info.absoluteFilePath()) > 1;
return FS::hardLinkCount(m_fileInfo.absoluteFilePath()) > 1;
}
auto Resource::getOriginalFileName() const -> QString
{
auto fileName = m_file_info.fileName();
auto fileName = m_fileInfo.fileName();
if (!m_enabled) {
fileName.chop(9);
}

View file

@ -79,7 +79,7 @@ enum class SortType : std::uint8_t {
Requires,
RequiredBy,
Filename,
LOCK_UPDATE
LockUpdate
};
enum class EnableAction : std::uint8_t { ENABLE, DISABLE, TOGGLE };
@ -95,23 +95,23 @@ class Resource : public QObject {
public:
using Ptr = shared_qobject_ptr<Resource>;
Resource(QObject* parent = nullptr);
Resource(QFileInfo fileInfo);
Resource(const QString& filePath) : Resource(QFileInfo(filePath)) {}
explicit Resource(QObject* parent = nullptr);
explicit Resource(const QFileInfo& fileInfo);
explicit Resource(const QString& filePath) : Resource(QFileInfo(filePath)) {}
~Resource() override = default;
void setFile(QFileInfo fileInfo);
void parseFile();
auto fileinfo() const -> QFileInfo { return m_file_info; }
auto dateTimeChanged() const -> QDateTime { return m_changed_date_time; }
auto internalId() const -> QString { return m_internal_id; }
auto fileinfo() const -> QFileInfo { return m_fileInfo; }
auto dateTimeChanged() const -> QDateTime { return m_changedDateTime; }
auto internalId() const -> QString { return m_internalId; }
auto type() const -> ResourceType { return m_type; }
bool enabled() const { return m_enabled; }
auto getOriginalFileName() const -> QString;
QString sizeStr() const { return m_size_str; }
qint64 sizeInfo() const { return m_size_info; }
QString sizeStr() const { return m_sizeStr; }
qint64 sizeInfo() const { return m_sizeInfo; }
virtual auto name() const -> QString;
virtual bool valid() const { return m_type != ResourceType::UNKNOWN; }
@ -145,7 +145,7 @@ class Resource : public QObject {
/** Returns whether the given filter should filter out 'this' (false),
* or if such filter includes the Resource (true).
*/
virtual bool applyFilter(QRegularExpression filter) const;
virtual bool applyFilter(const QRegularExpression& filter) const;
/** Changes the enabled property, according to 'action'.
*
@ -153,15 +153,15 @@ class Resource : public QObject {
*/
bool enable(EnableAction action);
auto shouldResolve() const -> bool { return !m_is_resolving && !m_is_resolved; }
auto isResolving() const -> bool { return m_is_resolving; }
auto isResolved() const -> bool { return m_is_resolved; }
auto resolutionTicket() const -> int { return m_resolution_ticket; }
auto shouldResolve() const -> bool { return !m_isResolving && !m_isResolved; }
auto isResolving() const -> bool { return m_isResolving; }
auto isResolved() const -> bool { return m_isResolved; }
auto resolutionTicket() const -> int { return m_resolutionTicket; }
void setResolving(bool resolving, int resolutionTicket)
{
m_is_resolving = resolving;
m_resolution_ticket = resolutionTicket;
m_isResolving = resolving;
m_resolutionTicket = resolutionTicket;
}
// Delete all files of this resource.
@ -169,7 +169,7 @@ class Resource : public QObject {
// Delete the metadata only.
auto destroyMetadata(const QDir& indexDir) -> void;
auto isSymLink() const -> bool { return m_file_info.isSymLink(); }
auto isSymLink() const -> bool { return m_fileInfo.isSymLink(); }
/**
* @brief Take a instance path, checks if the file pointed to by the resource is a symlink or under a symlink in that instance
@ -184,12 +184,12 @@ class Resource : public QObject {
protected:
/* The file corresponding to this resource. */
QFileInfo m_file_info;
QFileInfo m_fileInfo;
/* The cached date when this file was last changed. */
QDateTime m_changed_date_time;
QDateTime m_changedDateTime;
/* Internal ID for internal purposes. Properties such as human-readability should not be assumed. */
QString m_internal_id;
QString m_internalId;
/* Name as reported via the file name. In the absence of a better name, this is shown to the user. */
QString m_name;
@ -207,9 +207,9 @@ class Resource : public QObject {
QList<const char*> m_issues;
/* Used to keep trach of pending / concluded actions on the resource. */
bool m_is_resolving = false;
bool m_is_resolved = false;
int m_resolution_ticket = 0;
QString m_size_str;
qint64 m_size_info;
bool m_isResolving = false;
bool m_isResolved = false;
int m_resolutionTicket = 0;
QString m_sizeStr;
qint64 m_sizeInfo;
};

View file

@ -320,9 +320,9 @@ bool ResourceFolderModel::setResourceEnabled(const QModelIndexList& indexes, Ena
return succeeded;
}
static QMutex s_update_task_mutex;
bool ResourceFolderModel::update()
{
static QMutex s_update_task_mutex;
// We hold a lock here to prevent race conditions on the m_current_update_task reset.
QMutexLocker lock(&s_update_task_mutex);
@ -371,7 +371,7 @@ bool ResourceFolderModel::update()
return true;
}
void ResourceFolderModel::resolveResource(Resource::Ptr res)
void ResourceFolderModel::resolveResource(const Resource::Ptr& res)
{
if (!res->shouldResolve()) {
return;
@ -597,6 +597,7 @@ QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const
if (column == ActiveColumn) {
return m_resources[row]->enabled() ? Qt::Checked : Qt::Unchecked;
}
[[fallthrough]];
case Qt::UserRole:
if (column == LockUpdateCoumn) {
return at(row).lockUpdate();
@ -669,7 +670,7 @@ QVariant ResourceFolderModel::headerData(int section, [[maybe_unused]] Qt::Orien
return {};
}
void ResourceFolderModel::setupHeaderAction(QAction* act, int column)
void ResourceFolderModel::setupHeaderAction(QAction* act, int column) const
{
Q_ASSERT(act);
@ -798,7 +799,7 @@ QSortFilterProxyModel* ResourceFolderModel::createFilterProxyModel(QObject* pare
SortType ResourceFolderModel::columnToSortKey(size_t column) const
{
Q_ASSERT(m_columnSortKeys.size() == columnCount());
return m_columnSortKeys.at(column);
return m_columnSortKeys.at(static_cast<qsizetype>(column));
}
/* Standard Proxy Model for createFilterProxyModel */
@ -1004,14 +1005,16 @@ QList<Resource*> ResourceFolderModel::selectedResources(const QModelIndexList& i
bool ResourceFolderModel::setModUpdate(const QModelIndexList& indexes, EnableAction action)
{
if (indexes.isEmpty())
if (indexes.isEmpty()) {
return true;
}
bool succeeded = true;
auto updateColumn = columnNames(false).indexOf("Update");
auto updateColumn = static_cast<int>(columnNames(false).indexOf("Update"));
for (const auto& idx : indexes) {
if (!validateIndex(idx) || idx.column() != updateColumn)
if (!validateIndex(idx) || idx.column() != updateColumn) {
continue;
}
int row = idx.row();
auto& resource = m_resources[row];

View file

@ -113,7 +113,7 @@ class ResourceFolderModel : public QAbstractListModel {
virtual bool update();
/** Creates a new parse task, if needed, for 'res' and start it.*/
virtual void resolveResource(Resource::Ptr res);
virtual void resolveResource(const Resource::Ptr& res);
qsizetype size() const { return m_resources.size(); }
[[nodiscard]] bool empty() const { return size() == 0; }
@ -168,7 +168,7 @@ class ResourceFolderModel : public QAbstractListModel {
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
void setupHeaderAction(QAction* act, int column);
void setupHeaderAction(QAction* act, int column) const;
void saveColumns(QTreeView* tree);
void loadColumns(QTreeView* tree);
QMenu* createHeaderContextMenu(QTreeView* tree);
@ -177,7 +177,7 @@ class ResourceFolderModel : public QAbstractListModel {
*
* The actual comparisons and filtering are done directly by the Resource, so to modify behavior go there instead!
*/
QSortFilterProxyModel* createFilterProxyModel(QObject* parent = nullptr);
static QSortFilterProxyModel* createFilterProxyModel(QObject* parent = nullptr);
SortType columnToSortKey(size_t column) const;
QList<QHeaderView::ResizeMode> columnResizeModes() const { return m_columnResizeModes; }
@ -251,15 +251,15 @@ class ResourceFolderModel : public QAbstractListModel {
protected:
// Represents the relationship between a column's index (represented by the list index), and it's sorting key.
// As such, the order in with they appear is very important!
QList<SortType> m_columnSortKeys = { SortType::Enabled, SortType::Name, SortType::Date,
SortType::Provider, SortType::Size, SortType::Filename };
QList<SortType> m_columnSortKeys = { SortType::Enabled, SortType::Name, SortType::Date, SortType::Provider,
SortType::Size, SortType::Filename, SortType::LockUpdate };
QStringList m_columnNames = { "Enable", "Name", "Last Modified", "Provider", "Size", "File Name", "Update" };
QStringList m_columnNamesTranslated = { tr("Enable"), tr("Name"), tr("Last Modified"), tr("Provider"),
tr("Size"), tr("File Name"), tr("Update") };
QList<QHeaderView::ResizeMode> m_columnResizeModes = { QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive,
QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive,
QHeaderView::Interactive };
QList<bool> m_columnsHideable = { false, false, true, true, true, true };
QList<bool> m_columnsHideable = { false, false, true, true, true, true, true };
QDir m_dir;
BaseInstance* m_instance;

View file

@ -50,11 +50,11 @@ ResourcePackFolderModel::ResourcePackFolderModel(const QDir& dir, BaseInstance*
m_columnNamesTranslated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified"), tr("Provider"),
tr("Size"), tr("File Name"), tr("Update") });
m_columnSortKeys = { SortType::Enabled, SortType::Name, SortType::Name, SortType::PackFormat, SortType::Date,
SortType::Provider, SortType::Size, SortType::Filename, SortType::LOCK_UPDATE };
SortType::Provider, SortType::Size, SortType::Filename, SortType::LockUpdate };
m_columnResizeModes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch,
QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive,
QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive };
m_columnsHideable = { false, true, false, true, true, true, true, true };
m_columnsHideable = { false, true, false, true, true, true, true, true, true };
}
QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const
@ -98,6 +98,7 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const
if (column == ActiveColumn) {
return at(row).enabled() ? Qt::Checked : Qt::Unchecked;
}
[[fallthrough]];
case Qt::UserRole:
if (column == LockUpdateCoumn) {
return at(row).lockUpdate();

View file

@ -45,10 +45,10 @@ TexturePackFolderModel::TexturePackFolderModel(const QDir& dir, BaseInstance* in
m_columnNamesTranslated = QStringList(
{ tr("Enable"), tr("Image"), tr("Name"), tr("Last Modified"), tr("Provider"), tr("Size"), tr("File Name"), tr("Update") });
m_columnSortKeys = { SortType::Enabled, SortType::Name, SortType::Name, SortType::Date,
SortType::Provider, SortType::Size, SortType::Filename, SortType::LOCK_UPDATE };
SortType::Provider, SortType::Size, SortType::Filename, SortType::LockUpdate };
m_columnResizeModes = { QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::Interactive,
QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive, QHeaderView::Interactive };
m_columnsHideable = { false, true, false, true, true, true, true };
m_columnsHideable = { false, true, false, true, true, true, true, true };
}
Task* TexturePackFolderModel::createParseTask(Resource& resource)
@ -85,8 +85,9 @@ QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const
}
return {};
case Qt::UserRole:
if (column == LockUpdateCoumn)
if (column == LockUpdateCoumn) {
return at(row).lockUpdate();
}
return {};
default:
break;

View file

@ -89,51 +89,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;
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 != c_dependencies.end()) {
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) {
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 == ver_dep.version : i->project_id == ver_dep.addonId);
(isOnlyVersion ? i->fileId == verDep.version : i->projectId == 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);
if (auto dep =
std::ranges::find_if(m_pack_dependencies,
[&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_pack_dependencies.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 +143,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;
}

View file

@ -26,21 +26,21 @@
#include <windows.h>
#endif
LocalResourceUpdateTask::LocalResourceUpdateTask(QDir index_dir,
LocalResourceUpdateTask::LocalResourceUpdateTask(const QDir& indexDir,
ModPlatform::IndexedPack& project,
ModPlatform::IndexedVersion& version,
bool lockUpdate)
: m_index_dir(index_dir), m_project(project), m_version(version), m_lockUpdate(lockUpdate)
: m_indexDir(indexDir), m_project(project), m_version(version), m_lockUpdate(lockUpdate)
{
// Ensure a '.index' folder exists in the mods folder, and create it if it does not
if (!FS::ensureFolderPathExists(index_dir.path())) {
emitFailed(QString("Unable to create index directory at %1!").arg(index_dir.absolutePath()));
if (!FS::ensureFolderPathExists(indexDir.path())) {
emitFailed(QString("Unable to create index directory at %1!").arg(indexDir.absolutePath()));
return;
}
#ifdef Q_OS_WIN32
std::wstring wpath = index_dir.path().toStdWString();
if (index_dir.dirName().startsWith('.')) {
std::wstring wpath = indexDir.path().toStdWString();
if (indexDir.dirName().startsWith('.')) {
SetFileAttributesW(wpath.c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
} else {
// fix shaderpacks folder being hidden by Prism Launcher 10.0.1
@ -53,17 +53,18 @@ void LocalResourceUpdateTask::executeTask()
{
setStatus(tr("Updating index for resource:\n%1").arg(m_project.name));
auto old_metadata = Metadata::get(m_index_dir, m_project.addonId);
if (old_metadata.isValid()) {
emit hasOldResource(old_metadata.name, old_metadata.filename);
if (m_project.slug.isEmpty())
m_project.slug = old_metadata.slug;
auto oldMetadata = Metadata::get(m_indexDir, m_project.addonId);
if (oldMetadata.isValid()) {
emit hasOldResource(oldMetadata.name, oldMetadata.filename);
if (m_project.slug.isEmpty()) {
m_project.slug = oldMetadata.slug;
}
}
auto pw_mod = Metadata::create(m_index_dir, m_project, m_version);
if (pw_mod.isValid()) {
pw_mod.lockUpdate = m_lockUpdate;
Metadata::update(m_index_dir, pw_mod);
auto pwMod = Metadata::create(m_indexDir, m_project, m_version);
if (pwMod.isValid()) {
pwMod.lockUpdate = m_lockUpdate;
Metadata::update(m_indexDir, pwMod);
emitSucceeded();
} else {
qCritical() << "Tried to update an invalid resource!";

View file

@ -28,7 +28,7 @@ class LocalResourceUpdateTask : public Task {
public:
using Ptr = shared_qobject_ptr<LocalResourceUpdateTask>;
explicit LocalResourceUpdateTask(QDir index_dir,
explicit LocalResourceUpdateTask(const QDir& indexDir,
ModPlatform::IndexedPack& project,
ModPlatform::IndexedVersion& version,
bool lockUpdate = false);
@ -44,7 +44,7 @@ class LocalResourceUpdateTask : public Task {
void hasOldResource(QString name, QString filename);
private:
QDir m_index_dir;
QDir m_indexDir;
ModPlatform::IndexedPack m_project;
ModPlatform::IndexedVersion m_version;
bool m_lockUpdate = false;

View file

@ -45,7 +45,7 @@ void FlameCheckUpdate::executeTask()
connect(netJob, &Task::details, this, &FlameCheckUpdate::setDetails);
for (auto* resource : m_resources) {
auto project = std::make_shared<ModPlatform::IndexedPack>();
project->addonId = resource->metadata()->project_id.toString();
project->addonId = resource->metadata()->projectId.toString();
auto versionsUrlOptional = FlameAPI().getVersionsURL({ .pack = project, .mcVersions = m_gameVersions });
if (!versionsUrlOptional.has_value()) {
continue;
@ -75,7 +75,7 @@ void FlameCheckUpdate::getLatestVersionCallback(Resource* resource, QByteArray*
auto pack = std::make_shared<ModPlatform::IndexedPack>();
pack->name = resource->name();
pack->slug = resource->metadata()->slug;
pack->addonId = resource->metadata()->project_id;
pack->addonId = resource->metadata()->projectId;
pack->provider = ModPlatform::ResourceProvider::FLAME;
try {
auto obj = Json::requireObject(doc);
@ -105,14 +105,14 @@ void FlameCheckUpdate::getLatestVersionCallback(Resource* resource, QByteArray*
return;
}
if (latestVer->downloadUrl.isEmpty() && latestVer->fileId != resource->metadata()->file_id) {
if (latestVer->downloadUrl.isEmpty() && latestVer->fileId != resource->metadata()->fileId) {
m_blocked[resource] = latestVer->fileId.toString();
return;
}
if (!latestVer->hash.isEmpty() &&
(resource->metadata()->hash != latestVer->hash || resource->status() == ResourceStatus::NotInstalled)) {
auto oldVersion = resource->metadata()->version_number;
auto oldVersion = resource->metadata()->versionNumber;
if (oldVersion.isEmpty()) {
if (resource->status() == ResourceStatus::NotInstalled) {
oldVersion = tr("Not installed");
@ -134,7 +134,7 @@ void FlameCheckUpdate::collectBlockedMods()
QStringList addonIds;
QHash<QString, Resource*> quickSearch;
for (const auto& resource : m_blocked.keys()) {
auto addonId = resource->metadata()->project_id.toString();
auto addonId = resource->metadata()->projectId.toString();
addonIds.append(addonId);
quickSearch[addonId] = resource;
}

View file

@ -117,7 +117,7 @@ void FlamePackExportTask::collectHashes()
}
if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) {
resolvedFiles.insert(mod->fileinfo().absoluteFilePath(),
{ mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), true,
{ mod->metadata()->projectId.toInt(), mod->metadata()->fileId.toInt(), mod->enabled(), true,
mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") });
continue;
}

View file

@ -20,30 +20,35 @@
#include <QJsonDocument>
#include <QJsonObject>
namespace ExportToModList {
QString toHTML(QList<Mod*> mods, OptionalData extraData)
namespace {
QString toHTML(const QList<Mod*>& mods, ExportToModList::OptionalData extraData)
{
QStringList lines;
for (auto mod : mods) {
for (auto* mod : mods) {
auto meta = mod->metadata();
auto modName = mod->name().toHtmlEscaped();
if (extraData & Url) {
if ((extraData & ExportToModList::Url) != 0) {
auto url = mod->homepage().toHtmlEscaped();
if (!url.isEmpty())
if (!url.isEmpty()) {
modName = QString("<a href=\"%1\">%2</a>").arg(url, modName);
}
}
auto line = modName;
if (extraData & Version) {
if ((extraData & ExportToModList::Version) != 0) {
auto ver = mod->version();
if (ver.isEmpty() && meta != nullptr)
if (ver.isEmpty() && meta != nullptr) {
ver = meta->version().toString();
if (!ver.isEmpty())
}
if (!ver.isEmpty()) {
line += QString(" [%1]").arg(ver.toHtmlEscaped());
}
if (extraData & Authors && !mod->authors().isEmpty())
}
if (((extraData & ExportToModList::Authors) != 0) && !mod->authors().isEmpty()) {
line += " by " + mod->authors().join(", ").toHtmlEscaped();
if (extraData & FileName)
}
if ((extraData & ExportToModList::FileName) != 0) {
line += QString(" (%1)").arg(mod->fileinfo().fileName().toHtmlEscaped());
}
lines.append(QString("<li>%1</li>").arg(line));
}
@ -52,93 +57,109 @@ QString toHTML(QList<Mod*> mods, OptionalData extraData)
QString toMarkdownEscaped(QString src)
{
for (auto ch : "\\`*_{}[]<>()#+-.!|")
for (auto ch : "\\`*_{}[]<>()#+-.!|") {
src.replace(ch, QString("\\%1").arg(ch));
}
return src;
}
QString toMarkdown(QList<Mod*> mods, OptionalData extraData)
QString toMarkdown(const QList<Mod*>& mods, ExportToModList::OptionalData extraData)
{
QStringList lines;
for (auto mod : mods) {
for (auto* mod : mods) {
auto meta = mod->metadata();
auto modName = toMarkdownEscaped(mod->name());
if (extraData & Url) {
if ((extraData & ExportToModList::Url) != 0) {
auto url = mod->homepage();
if (!url.isEmpty())
if (!url.isEmpty()) {
modName = QString("[%1](%2)").arg(modName, url);
}
}
auto line = modName;
if (extraData & Version) {
if ((extraData & ExportToModList::Version) != 0) {
auto ver = toMarkdownEscaped(mod->version());
if (ver.isEmpty() && meta != nullptr)
if (ver.isEmpty() && meta != nullptr) {
ver = toMarkdownEscaped(meta->version().toString());
if (!ver.isEmpty())
}
if (!ver.isEmpty()) {
line += QString(" [%1]").arg(ver);
}
if (extraData & Authors && !mod->authors().isEmpty())
}
if (((extraData & ExportToModList::Authors) != 0) && !mod->authors().isEmpty()) {
line += " by " + toMarkdownEscaped(mod->authors().join(", "));
if (extraData & FileName)
}
if ((extraData & ExportToModList::FileName) != 0) {
line += QString(" (%1)").arg(toMarkdownEscaped(mod->fileinfo().fileName()));
}
lines << "- " + line;
}
return lines.join("\n");
}
QString toPlainTXT(QList<Mod*> mods, OptionalData extraData)
QString toPlainTXT(const QList<Mod*>& mods, ExportToModList::OptionalData extraData)
{
QStringList lines;
for (auto mod : mods) {
for (auto* mod : mods) {
auto meta = mod->metadata();
auto modName = mod->name();
auto line = modName;
if (extraData & Url) {
if ((extraData & ExportToModList::Url) != 0) {
auto url = mod->homepage();
if (!url.isEmpty())
if (!url.isEmpty()) {
line += QString(" (%1)").arg(url);
}
if (extraData & Version) {
}
if ((extraData & ExportToModList::Version) != 0) {
auto ver = mod->version();
if (ver.isEmpty() && meta != nullptr)
if (ver.isEmpty() && meta != nullptr) {
ver = meta->version().toString();
if (!ver.isEmpty())
}
if (!ver.isEmpty()) {
line += QString(" [%1]").arg(ver);
}
if (extraData & Authors && !mod->authors().isEmpty())
}
if (((extraData & ExportToModList::Authors) != 0) && !mod->authors().isEmpty()) {
line += " by " + mod->authors().join(", ");
if (extraData & FileName)
}
if ((extraData & ExportToModList::FileName) != 0) {
line += QString(" (%1)").arg(mod->fileinfo().fileName());
}
lines << line;
}
return lines.join("\n");
}
QString toJSON(QList<Mod*> mods, OptionalData extraData)
QString toJSON(const QList<Mod*>& mods, ExportToModList::OptionalData extraData)
{
QJsonArray lines;
for (auto mod : mods) {
for (auto* mod : mods) {
auto meta = mod->metadata();
auto modName = mod->name();
QJsonObject line;
line["name"] = modName;
if (extraData & Url) {
if ((extraData & ExportToModList::Url) != 0) {
auto url = mod->homepage();
if (!url.isEmpty())
if (!url.isEmpty()) {
line["url"] = url;
}
if (extraData & Version) {
}
if ((extraData & ExportToModList::Version) != 0) {
auto ver = mod->version();
if (ver.isEmpty() && meta != nullptr)
if (ver.isEmpty() && meta != nullptr) {
ver = meta->version().toString();
if (!ver.isEmpty())
}
if (!ver.isEmpty()) {
line["version"] = ver;
}
if (extraData & Authors && !mod->authors().isEmpty())
}
if (((extraData & ExportToModList::Authors) != 0) && !mod->authors().isEmpty()) {
line["authors"] = QJsonArray::fromStringList(mod->authors());
if (extraData & FileName)
}
if ((extraData & ExportToModList::FileName) != 0) {
line["filename"] = mod->fileinfo().fileName();
}
lines << line;
}
QJsonDocument doc;
@ -146,39 +167,45 @@ QString toJSON(QList<Mod*> mods, OptionalData extraData)
return doc.toJson();
}
QString toCSV(QList<Mod*> mods, OptionalData extraData)
QString toCSV(const QList<Mod*>& mods, ExportToModList::OptionalData extraData)
{
QStringList lines;
for (auto mod : mods) {
for (auto* mod : mods) {
QStringList data;
auto meta = mod->metadata();
auto modName = mod->name();
data << modName;
if (extraData & Url)
if ((extraData & ExportToModList::Url) != 0) {
data << mod->homepage();
if (extraData & Version) {
}
if ((extraData & ExportToModList::Version) != 0) {
auto ver = mod->version();
if (ver.isEmpty() && meta != nullptr)
if (ver.isEmpty() && meta != nullptr) {
ver = meta->version().toString();
}
data << ver;
}
if (extraData & Authors) {
if ((extraData & ExportToModList::Authors) != 0) {
QString authors;
if (mod->authors().length() == 1)
if (mod->authors().length() == 1) {
authors = mod->authors().back();
else if (mod->authors().length() > 1)
} else if (mod->authors().length() > 1) {
authors = QString("\"%1\"").arg(mod->authors().join(","));
}
data << authors;
}
if (extraData & FileName)
if ((extraData & ExportToModList::FileName) != 0) {
data << mod->fileinfo().fileName();
}
lines << data.join(",");
}
return lines.join("\n");
}
} // namespace
namespace ExportToModList {
QString exportToModList(QList<Mod*> mods, Formats format, OptionalData extraData)
QString exportToModList(const QList<Mod*>& mods, Formats format, OptionalData extraData)
{
switch (format) {
case HTML:
@ -197,17 +224,18 @@ QString exportToModList(QList<Mod*> mods, Formats format, OptionalData extraData
}
}
QString exportToModList(QList<Mod*> mods, QString lineTemplate)
QString exportToModList(const QList<Mod*>& mods, const QString& lineTemplate)
{
QStringList lines;
for (auto mod : mods) {
for (auto* mod : mods) {
auto meta = mod->metadata();
auto modName = mod->name();
auto modID = mod->mod_id();
auto modID = mod->modId();
auto url = mod->homepage();
auto ver = mod->version();
if (ver.isEmpty() && meta != nullptr)
if (ver.isEmpty() && meta != nullptr) {
ver = meta->version().toString();
}
auto authors = mod->authors().join(", ");
auto filename = mod->fileinfo().fileName();
lines << QString(lineTemplate)

View file

@ -22,10 +22,10 @@
namespace ExportToModList {
enum Formats { HTML, MARKDOWN, PLAINTXT, JSON, CSV, CUSTOM };
enum OptionalDataValue { None = 0, Authors = 1 << 0, Url = 1 << 1, Version = 1 << 2, FileName = 1 << 3 };
enum Formats : std::uint8_t { HTML, MARKDOWN, PLAINTXT, JSON, CSV, CUSTOM };
enum OptionalDataValue : std::uint8_t { None = 0, Authors = 1U << 0U, Url = 1U << 1U, Version = 1U << 2U, FileName = 1U << 3U };
Q_DECLARE_FLAGS(OptionalData, OptionalDataValue)
QString exportToModList(QList<Mod*> mods, Formats format, OptionalData extraData);
QString exportToModList(QList<Mod*> mods, QString lineTemplate);
QString exportToModList(const QList<Mod*>& mods, Formats format, OptionalData extraData);
QString exportToModList(const QList<Mod*>& mods, const QString& lineTemplate);
} // namespace ExportToModList

View file

@ -62,7 +62,7 @@ void ModrinthCheckUpdate::executeTask()
// Sadly the API can only handle one hash type per call, se we
// need to generate a new hash if the current one is innadequate
// (though it will rarely happen, if at all)
if (resource->metadata()->hash_format != m_hashType) {
if (resource->metadata()->hashFormat != m_hashType) {
auto hashTask = Hashing::createHasher(resource->fileinfo().absoluteFilePath(), ModPlatform::ResourceProvider::MODRINTH);
connect(hashTask.get(), &Hashing::Hasher::resultsReady,
[this, resource](const QString& hash) { m_mappings.insert(hash, resource); });
@ -176,12 +176,12 @@ void ModrinthCheckUpdate::checkVersionsResponse(QByteArray* response, std::optio
auto pack = std::make_shared<ModPlatform::IndexedPack>();
pack->name = resource->name();
pack->slug = resource->metadata()->slug;
pack->addonId = resource->metadata()->project_id;
pack->addonId = resource->metadata()->projectId;
pack->provider = ModPlatform::ResourceProvider::MODRINTH;
if ((projectVer.hash != hash && projectVer.is_preferred) || (resource->status() == ResourceStatus::NotInstalled)) {
auto downloadTask = makeShared<ResourceDownloadTask>(pack, projectVer, m_resourceModel, true, "update");
QString oldVersion = resource->metadata()->version_number;
QString oldVersion = resource->metadata()->versionNumber;
if (oldVersion.isEmpty()) {
if (resource->status() == ResourceStatus::NotInstalled) {
oldVersion = tr("Not installed");

View file

@ -26,7 +26,6 @@
#include <compare>
#include <sstream>
#include <string>
#include <utility>
#include "FileSystem.h"
#include "StringUtils.h"
@ -105,45 +104,45 @@ bool sortMCVersions(const QString& a, const QString& b)
}
} // namespace
auto V1::createModFormat([[maybe_unused]] const QDir& index_dir,
ModPlatform::IndexedPack& mod_pack,
ModPlatform::IndexedVersion& mod_version) -> Mod
auto V1::createModFormat([[maybe_unused]] const QDir& indexDir, ModPlatform::IndexedPack& modPack, ModPlatform::IndexedVersion& modVersion)
-> Mod
{
Mod mod;
mod.slug = mod_pack.slug;
mod.name = mod_pack.name;
mod.filename = mod_version.fileName;
mod.slug = modPack.slug;
mod.name = modPack.name;
mod.filename = modVersion.fileName;
if (mod_pack.provider == ModPlatform::ResourceProvider::FLAME) {
if (modPack.provider == ModPlatform::ResourceProvider::FLAME) {
mod.mode = "metadata:curseforge";
} else {
mod.mode = "url";
mod.url = mod_version.downloadUrl;
mod.url = modVersion.downloadUrl;
}
mod.hash_format = mod_version.hash_type;
mod.hash = mod_version.hash;
mod.hashFormat = modVersion.hash_type;
mod.hash = modVersion.hash;
mod.provider = mod_pack.provider;
mod.file_id = mod_version.fileId;
mod.project_id = mod_pack.addonId;
mod.side = mod_version.side == ModPlatform::Side::NoSide ? mod_pack.side : mod_version.side;
mod.loaders = mod_version.loaders;
mod.mcVersions = mod_version.mcVersion;
mod.provider = modPack.provider;
mod.fileId = modVersion.fileId;
mod.projectId = modPack.addonId;
mod.side = modVersion.side == ModPlatform::Side::NoSide ? modPack.side : modVersion.side;
mod.loaders = modVersion.loaders;
mod.mcVersions = modVersion.mcVersion;
mod.mcVersions.removeDuplicates();
std::ranges::sort(mod.mcVersions, sortMCVersions);
mod.releaseType = mod_version.version_type;
mod.releaseType = modVersion.version_type;
mod.version_number = mod_version.version_number;
if (mod.version_number.isNull()) // on CurseForge, there is only a version name - not a version number
mod.version_number = mod_version.version;
mod.versionNumber = modVersion.version_number;
if (mod.versionNumber.isNull()) { // on CurseForge, there is only a version name - not a version number
mod.versionNumber = modVersion.version;
}
mod.dependencies = mod_version.dependencies;
mod.dependencies = modVersion.dependencies;
return mod;
}
void V1::updateModIndex(const QDir& index_dir, Mod& mod)
void V1::updateModIndex(const QDir& indexDir, Mod& mod)
{
if (!mod.isValid()) {
qCritical() << QString("Tried to update metadata of an invalid mod!");
@ -152,43 +151,44 @@ void V1::updateModIndex(const QDir& index_dir, Mod& mod)
// Ensure the corresponding mod's info exists, and create it if not
auto normalized_fname = indexFileName(mod.slug);
auto real_fname = getRealIndexName(index_dir, normalized_fname);
auto normalizedFname = indexFileName(mod.slug);
auto realFname = getRealIndexName(indexDir, normalizedFname);
QFile index_file(index_dir.absoluteFilePath(real_fname));
QFile indexFile(indexDir.absoluteFilePath(realFname));
if (real_fname != normalized_fname)
index_file.rename(normalized_fname);
if (realFname != normalizedFname) {
indexFile.rename(normalizedFname);
}
// There's already data on there!
// TODO: We should do more stuff here, as the user is likely trying to
// override a file. In this case, check versions and ask the user what
// they want to do!
if (index_file.exists()) {
index_file.remove();
if (indexFile.exists()) {
indexFile.remove();
} else {
FS::ensureFilePathExists(index_file.fileName());
FS::ensureFilePathExists(indexFile.fileName());
}
toml::table update;
switch (mod.provider) {
case (ModPlatform::ResourceProvider::FLAME):
if (mod.file_id.toInt() == 0 || mod.project_id.toInt() == 0) {
qCritical() << QString("Did not write file %1 because missing information!").arg(normalized_fname);
if (mod.fileId.toInt() == 0 || mod.projectId.toInt() == 0) {
qCritical() << QString("Did not write file %1 because missing information!").arg(normalizedFname);
return;
}
update = toml::table{
{ "file-id", mod.file_id.toInt() },
{ "project-id", mod.project_id.toInt() },
{ "file-id", mod.fileId.toInt() },
{ "project-id", mod.projectId.toInt() },
};
break;
case (ModPlatform::ResourceProvider::MODRINTH):
if (mod.mod_id().toString().isEmpty() || mod.version().toString().isEmpty()) {
qCritical() << QString("Did not write file %1 because missing information!").arg(normalized_fname);
if (mod.modId().toString().isEmpty() || mod.version().toString().isEmpty()) {
qCritical() << QString("Did not write file %1 because missing information!").arg(normalizedFname);
return;
}
update = toml::table{
{ "mod-id", mod.mod_id().toString().toStdString() },
{ "mod-id", mod.modId().toString().toStdString() },
{ "version", mod.version().toString().toStdString() },
};
break;
@ -199,17 +199,17 @@ void V1::updateModIndex(const QDir& index_dir, Mod& mod)
loaders.push_back(getModLoaderAsString(loader).toStdString());
}
toml::array mcVersions;
for (auto version : mod.mcVersions) {
for (const auto& version : mod.mcVersions) {
mcVersions.push_back(version.toStdString());
}
if (!index_file.open(QIODevice::ReadWrite)) {
qCritical() << "Could not open file" << normalized_fname << "error:" << index_file.errorString();
if (!indexFile.open(QIODevice::ReadWrite)) {
qCritical() << "Could not open file" << normalizedFname << "error:" << indexFile.errorString();
return;
}
toml::array deps;
for (auto dep : mod.dependencies) {
for (const auto& dep : mod.dependencies) {
auto tbl = toml::table{ { "addonId", dep.addonId.toString().toStdString() },
{ "type", ModPlatform::DependencyTypeUtils::toString(dep.type).toStdString() } };
if (!dep.version.isEmpty()) {
@ -219,7 +219,7 @@ void V1::updateModIndex(const QDir& index_dir, Mod& mod)
}
// Put TOML data into the file
QTextStream in_stream(&index_file);
QTextStream inStream(&indexFile);
{
auto tbl = toml::table{ { "name", mod.name.toStdString() },
{ "filename", mod.filename.toStdString() },
@ -227,60 +227,62 @@ void V1::updateModIndex(const QDir& index_dir, Mod& mod)
{ "x-prismlauncher-loaders", loaders },
{ "x-prismlauncher-mc-versions", mcVersions },
{ "x-prismlauncher-release-type", mod.releaseType.toString().toStdString() },
{ "x-prismlauncher-version-number", mod.version_number.toStdString() },
{ "x-prismlauncher-version-number", mod.versionNumber.toStdString() },
{ "x-prismlauncher-dependencies", deps },
{ "x-prismlauncher-lock-update", mod.lockUpdate },
{ "download",
toml::table{
{ "mode", mod.mode.toStdString() },
{ "url", mod.url.toString().toStdString() },
{ "hash-format", mod.hash_format.toStdString() },
{ "hash-format", mod.hashFormat.toStdString() },
{ "hash", mod.hash.toStdString() },
} },
{ "update", toml::table{ { ModPlatform::ProviderCapabilities::name(mod.provider), update } } } };
std::stringstream ss;
ss << tbl;
in_stream << QString::fromStdString(ss.str());
inStream << QString::fromStdString(ss.str());
}
index_file.flush();
index_file.close();
indexFile.flush();
indexFile.close();
}
void V1::deleteModIndex(const QDir& index_dir, QString& mod_slug)
void V1::deleteModIndex(const QDir& indexDir, QString& modSlug)
{
auto normalized_fname = indexFileName(mod_slug);
auto real_fname = getRealIndexName(index_dir, normalized_fname);
if (real_fname.isEmpty())
return;
QFile index_file(index_dir.absoluteFilePath(real_fname));
if (!index_file.exists()) {
qWarning() << QString("Tried to delete non-existent mod metadata for %1!").arg(mod_slug);
auto normalizedFname = indexFileName(modSlug);
auto realFname = getRealIndexName(indexDir, normalizedFname);
if (realFname.isEmpty()) {
return;
}
if (!index_file.remove()) {
qWarning() << QString("Failed to remove metadata for mod %1!").arg(mod_slug);
QFile indexFile(indexDir.absoluteFilePath(realFname));
if (!indexFile.exists()) {
qWarning() << QString("Tried to delete non-existent mod metadata for %1!").arg(modSlug);
return;
}
if (!indexFile.remove()) {
qWarning() << QString("Failed to remove metadata for mod %1!").arg(modSlug);
}
}
auto V1::getIndexForMod(const QDir& index_dir, QString slug) -> Mod
auto V1::getIndexForMod(const QDir& indexDir, const QString& slug) -> Mod
{
Mod mod;
auto normalized_fname = indexFileName(slug);
auto real_fname = getRealIndexName(index_dir, normalized_fname, true);
if (real_fname.isEmpty())
auto normalizedFname = indexFileName(slug);
auto realFname = getRealIndexName(indexDir, normalizedFname, true);
if (realFname.isEmpty()) {
return {};
}
toml::table table;
#if TOML_EXCEPTIONS
try {
table = toml::parse_file(StringUtils::toStdString(index_dir.absoluteFilePath(real_fname)));
table = toml::parse_file(StringUtils::toStdString(indexDir.absoluteFilePath(realFname)));
} catch (const toml::parse_error& err) {
qWarning() << QString("Could not open file %1!").arg(normalized_fname);
qWarning() << QString("Could not open file %1!").arg(normalizedFname);
qWarning() << "Reason:" << QString(err.what());
return {};
}
@ -324,49 +326,52 @@ auto V1::getIndexForMod(const QDir& index_dir, QString slug) -> Mod
std::ranges::sort(mod.mcVersions, sortMCVersions);
}
}
mod.version_number = table["x-prismlauncher-version-number"].value_or("");
mod.versionNumber = table["x-prismlauncher-version-number"].value_or("");
{ // [download] info
auto download_table = table["download"].as_table();
if (!download_table) {
auto* downloadTable = table["download"].as_table();
if (!downloadTable) {
qCritical() << QString("No [download] section found on mod metadata!");
return {};
}
mod.mode = stringEntry(*download_table, "mode");
mod.url = stringEntry(*download_table, "url");
mod.hash_format = stringEntry(*download_table, "hash-format");
mod.hash = stringEntry(*download_table, "hash");
mod.mode = stringEntry(*downloadTable, "mode");
mod.url = stringEntry(*downloadTable, "url");
mod.hashFormat = stringEntry(*downloadTable, "hash-format");
mod.hash = stringEntry(*downloadTable, "hash");
}
{ // [update] info
using Provider = ModPlatform::ResourceProvider;
auto update_table = table["update"];
if (!update_table || !update_table.is_table()) {
auto updateTable = table["update"];
if (!updateTable || !updateTable.is_table()) {
qCritical() << QString("No [update] section found on mod metadata!");
return {};
}
toml::table* mod_provider_table = nullptr;
if ((mod_provider_table = update_table[ModPlatform::ProviderCapabilities::name(Provider::FLAME)].as_table())) {
auto* modProviderTable = updateTable[ModPlatform::ProviderCapabilities::name(Provider::FLAME)].as_table();
if (modProviderTable != nullptr) {
mod.provider = Provider::FLAME;
mod.file_id = intEntry(*mod_provider_table, "file-id");
mod.project_id = intEntry(*mod_provider_table, "project-id");
} else if ((mod_provider_table = update_table[ModPlatform::ProviderCapabilities::name(Provider::MODRINTH)].as_table())) {
mod.fileId = intEntry(*modProviderTable, "file-id");
mod.projectId = intEntry(*modProviderTable, "project-id");
} else {
modProviderTable = updateTable[ModPlatform::ProviderCapabilities::name(Provider::MODRINTH)].as_table();
if (modProviderTable != nullptr) {
mod.provider = Provider::MODRINTH;
mod.mod_id() = stringEntry(*mod_provider_table, "mod-id");
mod.version() = stringEntry(*mod_provider_table, "version");
mod.modId() = stringEntry(*modProviderTable, "mod-id");
mod.version() = stringEntry(*modProviderTable, "version");
} else {
qCritical() << QString("No mod provider on mod metadata!");
return {};
}
}
}
{ // dependencies
auto deps = table["x-prismlauncher-dependencies"].as_array();
auto* deps = table["x-prismlauncher-dependencies"].as_array();
if (deps) {
for (auto&& depNode : *deps) {
auto dep = depNode.as_table();
auto* dep = depNode.as_table();
if (dep) {
ModPlatform::Dependency d;
d.addonId = stringEntry(*dep, "addonId");
@ -383,14 +388,15 @@ auto V1::getIndexForMod(const QDir& index_dir, QString slug) -> Mod
return mod;
}
auto V1::getIndexForMod(const QDir& index_dir, QVariant& mod_id) -> Mod
auto V1::getIndexForMod(const QDir& indexDir, QVariant& modId) -> Mod
{
for (auto& file_name : index_dir.entryList(QDir::Filter::Files)) {
auto mod = getIndexForMod(index_dir, file_name);
for (auto& fileName : indexDir.entryList(QDir::Filter::Files)) {
auto mod = getIndexForMod(indexDir, fileName);
if (mod.mod_id() == mod_id)
if (mod.modId() == modId) {
return mod;
}
}
return {};
}

View file

@ -44,51 +44,51 @@ class V1 {
// [download]
QString mode{};
QUrl url{};
QString hash_format{};
QString hashFormat{};
QString hash{};
// [update]
ModPlatform::ResourceProvider provider{};
QVariant file_id{};
QVariant project_id{};
QString version_number{};
QVariant fileId{};
QVariant projectId{};
QString versionNumber{};
QList<ModPlatform::Dependency> dependencies;
bool lockUpdate;
public:
// This is a totally heuristic, but should work for now.
auto isValid() const -> bool { return !slug.isEmpty() && !project_id.isNull(); }
auto isValid() const -> bool { return !slug.isEmpty() && !projectId.isNull(); }
// Different providers can use different names for the same thing
// Modrinth-specific
auto mod_id() -> QVariant& { return project_id; }
auto version() -> QVariant& { return file_id; }
auto modId() -> QVariant& { return projectId; }
auto version() -> QVariant& { return fileId; }
};
/* Generates the object representing the information in a mod.pw.toml file via
* its common representation in the launcher, when downloading mods.
* */
static auto createModFormat(const QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod;
static auto createModFormat(const QDir& indexDir, ModPlatform::IndexedPack& modPack, ModPlatform::IndexedVersion& modVersion) -> Mod;
/* Updates the mod index for the provided mod.
* This creates a new index if one does not exist already
* TODO: Ask the user if they want to override, and delete the old mod's files, or keep the old one.
* */
static void updateModIndex(const QDir& index_dir, Mod& mod);
static void updateModIndex(const QDir& indexDir, Mod& mod);
/* Deletes the metadata for the mod with the given slug. If the metadata doesn't exist, it does nothing. */
static void deleteModIndex(const QDir& index_dir, QString& mod_slug);
static void deleteModIndex(const QDir& indexDir, QString& modSlug);
/* Gets the metadata for a mod with a particular file name.
* If the mod doesn't have a metadata, it simply returns an empty Mod object.
* */
static auto getIndexForMod(const QDir& index_dir, QString slug) -> Mod;
static auto getIndexForMod(const QDir& indexDir, const QString& slug) -> Mod;
/* Gets the metadata for a mod with a particular id.
* If the mod doesn't have a metadata, it simply returns an empty Mod object.
* */
static auto getIndexForMod(const QDir& index_dir, QVariant& mod_id) -> Mod;
static auto getIndexForMod(const QDir& indexDir, QVariant& modId) -> Mod;
};
} // namespace Packwiz

View file

@ -445,7 +445,7 @@ void ResourceDownloadDialog::setResourceMetadata(const std::shared_ptr<Metadata:
m_container->hidePageList();
m_buttons.hide();
auto* page = selectedPage();
page->openProject(meta->project_id);
page->openProject(meta->projectId);
}
DataPackDownloadDialog::DataPackDownloadDialog(QWidget* parent,

View file

@ -412,6 +412,7 @@ void ResourceUpdateDialog::onMetadataEnsured(Resource* resource)
}
}
namespace {
ModPlatform::ResourceProvider next(ModPlatform::ResourceProvider p)
{
switch (p) {
@ -423,6 +424,7 @@ ModPlatform::ResourceProvider next(ModPlatform::ResourceProvider p)
return ModPlatform::ResourceProvider::FLAME;
}
} // namespace
void ResourceUpdateDialog::onMetadataFailed(Resource* resource, bool tryOthers, ModPlatform::ResourceProvider firstChoice)
{
@ -517,7 +519,7 @@ void ResourceUpdateDialog::appendResource(const CheckUpdateTask::Update& info, Q
ui->modTreeWidget->addTopLevelItem(itemTop);
}
auto ResourceUpdateDialog::getTasks() -> const QList<ResourceDownloadTask::Ptr>
auto ResourceUpdateDialog::getTasks() -> QList<ResourceDownloadTask::Ptr>
{
QList<ResourceDownloadTask::Ptr> list;

View file

@ -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();
auto indexDir() const -> QDir { return m_resourceModel->indexDir(); }
auto noUpdates() const -> bool { return m_noUpdates; };

View file

@ -28,30 +28,30 @@
DataPackPage::DataPackPage(BaseInstance* instance, DataPackFolderModel* model, QWidget* parent)
: ExternalResourcesPage(instance, model, parent), m_model(model)
{
ui->actionDownloadItem->setText(tr("Download Packs"));
ui->actionDownloadItem->setToolTip(tr("Download data packs from online mod platforms"));
ui->actionDownloadItem->setEnabled(true);
ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionDownloadItem);
m_ui->actionDownloadItem->setText(tr("Download Packs"));
m_ui->actionDownloadItem->setToolTip(tr("Download data packs from online mod platforms"));
m_ui->actionDownloadItem->setEnabled(true);
m_ui->actionsToolbar->insertActionBefore(m_ui->actionAddItem, m_ui->actionDownloadItem);
connect(ui->actionDownloadItem, &QAction::triggered, this, &DataPackPage::downloadDataPacks);
connect(m_ui->actionDownloadItem, &QAction::triggered, this, &DataPackPage::downloadDataPacks);
ui->actionUpdateItem->setToolTip(tr("Try to check or update all selected data packs (all data packs if none are selected)"));
connect(ui->actionUpdateItem, &QAction::triggered, this, &DataPackPage::updateDataPacks);
ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionUpdateItem);
m_ui->actionUpdateItem->setToolTip(tr("Try to check or update all selected data packs (all data packs if none are selected)"));
connect(m_ui->actionUpdateItem, &QAction::triggered, this, &DataPackPage::updateDataPacks);
m_ui->actionsToolbar->insertActionBefore(m_ui->actionAddItem, m_ui->actionUpdateItem);
auto* updateMenu = new QMenu(this);
auto* update = updateMenu->addAction(ui->actionUpdateItem->text());
auto* update = updateMenu->addAction(m_ui->actionUpdateItem->text());
connect(update, &QAction::triggered, this, &DataPackPage::updateDataPacks);
updateMenu->addAction(ui->actionResetItemMetadata);
connect(ui->actionResetItemMetadata, &QAction::triggered, this, &DataPackPage::deleteDataPackMetadata);
updateMenu->addAction(m_ui->actionResetItemMetadata);
connect(m_ui->actionResetItemMetadata, &QAction::triggered, this, &DataPackPage::deleteDataPackMetadata);
ui->actionUpdateItem->setMenu(updateMenu);
m_ui->actionUpdateItem->setMenu(updateMenu);
ui->actionChangeVersion->setToolTip(tr("Change a data pack's version."));
connect(ui->actionChangeVersion, &QAction::triggered, this, &DataPackPage::changeDataPackVersion);
ui->actionsToolbar->insertActionAfter(ui->actionUpdateItem, ui->actionChangeVersion);
m_ui->actionChangeVersion->setToolTip(tr("Change a data pack's version."));
connect(m_ui->actionChangeVersion, &QAction::triggered, this, &DataPackPage::changeDataPackVersion);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionUpdateItem, m_ui->actionChangeVersion);
}
void DataPackPage::updateFrame(const QModelIndex& current, [[maybe_unused]] const QModelIndex& previous)
@ -59,7 +59,7 @@ void DataPackPage::updateFrame(const QModelIndex& current, [[maybe_unused]] cons
auto sourceCurrent = m_filterModel->mapToSource(current);
int row = sourceCurrent.row();
auto& dp = m_model->at(row);
ui->frame->updateWithDataPack(dp);
m_ui->frame->updateWithDataPack(dp);
}
void DataPackPage::downloadDataPacks()
@ -138,7 +138,7 @@ void DataPackPage::updateDataPacks()
return;
}
}
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
auto modsList = m_model->selectedResources(selection);
bool useAll = modsList.empty();
@ -198,7 +198,7 @@ void DataPackPage::updateDataPacks()
void DataPackPage::deleteDataPackMetadata()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
auto selectionCount = m_model->selectedDataPacks(selection).length();
if (selectionCount == 0) {
return;
@ -230,7 +230,7 @@ void DataPackPage::changeDataPackVersion()
return;
}
const QModelIndexList rows = ui->treeView->selectionModel()->selectedRows();
const QModelIndexList rows = m_ui->treeView->selectionModel()->selectedRows();
if (rows.count() != 1) {
return;

View file

@ -38,7 +38,6 @@
#include "ui_ExternalResourcesPage.h"
#include "DesktopServices.h"
#include "Version.h"
#include "minecraft/mod/ResourceFolderModel.h"
#include "ui/GuiUtil.h"
@ -48,6 +47,7 @@
#include <QStyledItemDelegate>
#include <algorithm>
namespace {
class LockDelegate : public QStyledItemDelegate {
public:
explicit LockDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) {}
@ -67,13 +67,13 @@ class LockDelegate : public QStyledItemDelegate {
option.widget->style()->drawControl(QStyle::CE_ItemViewItem, &option, painter);
int size = qMin(option.rect.width(), option.rect.height()) * 0.75;
QRect iconRect(option.rect.center().x() - size / 2, option.rect.center().y() - size / 2, size, size);
int size = qMin(option.rect.width(), option.rect.height()) * 3 / 4;
QRect iconRect(option.rect.center().x() - (size / 2), option.rect.center().y() - (size / 2), size, size);
icon.paint(painter, iconRect);
}
bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) override
bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& /*option*/, const QModelIndex& index) override
{
if (event->type() == QEvent::MouseButtonRelease) {
bool locked = index.data(Qt::UserRole).toBool();
@ -83,53 +83,57 @@ class LockDelegate : public QStyledItemDelegate {
return event->type() == QEvent::MouseButtonDblClick; // if double click ignore it
}
};
} // namespace
ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, ResourceFolderModel* model, QWidget* parent)
: QMainWindow(parent), m_instance(instance), ui(new Ui::ExternalResourcesPage), m_model(model)
: QMainWindow(parent)
, m_instance(instance)
, m_ui(new Ui::ExternalResourcesPage)
, m_model(model)
, m_filterModel(ResourceFolderModel::createFilterProxyModel(this))
{
ui->setupUi(this);
m_ui->setupUi(this);
ui->actionsToolbar->insertSpacer(ui->actionViewFolder);
m_ui->actionsToolbar->insertSpacer(m_ui->actionViewFolder);
m_filterModel = model->createFilterProxyModel(this);
m_filterModel->setDynamicSortFilter(true);
m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
m_filterModel->setSourceModel(m_model);
m_filterModel->setFilterKeyColumn(-1);
ui->treeView->setModel(m_filterModel);
m_ui->treeView->setModel(m_filterModel);
// keep the Update at the end of the list(otherwise there will be a need to iterate over the columns)
int lockColumn = model->columnNames(false).size() - 1;
ui->treeView->setItemDelegateForColumn(lockColumn, new LockDelegate(ui->treeView));
auto lockColumn = static_cast<int>(model->columnNames(false).size()) - 1;
m_ui->treeView->setItemDelegateForColumn(lockColumn, new LockDelegate(m_ui->treeView));
// must come after setModel
ui->treeView->setResizeModes(m_model->columnResizeModes());
m_ui->treeView->setResizeModes(m_model->columnResizeModes());
ui->treeView->installEventFilter(this);
ui->treeView->sortByColumn(1, Qt::AscendingOrder);
ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
m_ui->treeView->installEventFilter(this);
m_ui->treeView->sortByColumn(1, Qt::AscendingOrder);
m_ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
// The default function names by Qt are pretty ugly, so let's just connect the actions manually,
// to make it easier to read :)
connect(ui->actionAddItem, &QAction::triggered, this, &ExternalResourcesPage::addItem);
connect(ui->actionRemoveItem, &QAction::triggered, this, &ExternalResourcesPage::removeItem);
connect(ui->actionEnableItem, &QAction::triggered, this, &ExternalResourcesPage::enableItem);
connect(ui->actionDisableItem, &QAction::triggered, this, &ExternalResourcesPage::disableItem);
connect(ui->actionViewHomepage, &QAction::triggered, this, &ExternalResourcesPage::viewHomepage);
connect(ui->actionViewConfigs, &QAction::triggered, this, &ExternalResourcesPage::viewConfigs);
connect(ui->actionViewFolder, &QAction::triggered, this, &ExternalResourcesPage::viewFolder);
connect(m_ui->actionAddItem, &QAction::triggered, this, &ExternalResourcesPage::addItem);
connect(m_ui->actionRemoveItem, &QAction::triggered, this, &ExternalResourcesPage::removeItem);
connect(m_ui->actionEnableItem, &QAction::triggered, this, &ExternalResourcesPage::enableItem);
connect(m_ui->actionDisableItem, &QAction::triggered, this, &ExternalResourcesPage::disableItem);
connect(m_ui->actionViewHomepage, &QAction::triggered, this, &ExternalResourcesPage::viewHomepage);
connect(m_ui->actionViewConfigs, &QAction::triggered, this, &ExternalResourcesPage::viewConfigs);
connect(m_ui->actionViewFolder, &QAction::triggered, this, &ExternalResourcesPage::viewFolder);
connect(ui->treeView, &ModListView::customContextMenuRequested, this, &ExternalResourcesPage::ShowContextMenu);
connect(ui->treeView, &ModListView::activated, this, &ExternalResourcesPage::itemActivated);
connect(m_ui->treeView, &ModListView::customContextMenuRequested, this, &ExternalResourcesPage::showContextMenu);
connect(m_ui->treeView, &ModListView::activated, this, &ExternalResourcesPage::itemActivated);
connect(ui->actionEnableUpdates, &QAction::triggered, this, &ExternalResourcesPage::enableUpdates);
connect(ui->actionDisableUpdates, &QAction::triggered, this, &ExternalResourcesPage::disableUpdates);
connect(m_ui->actionEnableUpdates, &QAction::triggered, this, &ExternalResourcesPage::enableUpdates);
connect(m_ui->actionDisableUpdates, &QAction::triggered, this, &ExternalResourcesPage::disableUpdates);
auto selection_model = ui->treeView->selectionModel();
auto* selectionModel = m_ui->treeView->selectionModel();
connect(selection_model, &QItemSelectionModel::currentChanged, this, [this](const QModelIndex& current, const QModelIndex& previous) {
connect(selectionModel, &QItemSelectionModel::currentChanged, this, [this](const QModelIndex& current, const QModelIndex& previous) {
if (!current.isValid()) {
ui->frame->clear();
m_ui->frame->clear();
return;
}
@ -137,52 +141,53 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, ResourceFol
});
auto updateExtra = [this]() {
if (updateExtraInfo)
if (updateExtraInfo) {
updateExtraInfo(id(), extraHeaderInfoString());
}
};
connect(selection_model, &QItemSelectionModel::selectionChanged, this, updateExtra);
connect(selectionModel, &QItemSelectionModel::selectionChanged, this, updateExtra);
connect(model, &ResourceFolderModel::updateFinished, this, updateExtra);
connect(model, &ResourceFolderModel::parseFinished, this, updateExtra);
connect(selection_model, &QItemSelectionModel::selectionChanged, this, [this] { updateActions(); });
connect(selectionModel, &QItemSelectionModel::selectionChanged, this, [this] { updateActions(); });
connect(m_model, &ResourceFolderModel::rowsInserted, this, [this] { updateActions(); });
connect(m_model, &ResourceFolderModel::rowsRemoved, this, [this] { updateActions(); });
auto viewHeader = ui->treeView->header();
auto* viewHeader = m_ui->treeView->header();
viewHeader->setContextMenuPolicy(Qt::CustomContextMenu);
connect(viewHeader, &QHeaderView::customContextMenuRequested, this, &ExternalResourcesPage::ShowHeaderContextMenu);
connect(viewHeader, &QHeaderView::customContextMenuRequested, this, &ExternalResourcesPage::showHeaderContextMenu);
m_model->loadColumns(ui->treeView);
connect(ui->treeView->header(), &QHeaderView::sectionResized, this, [this] { m_model->saveColumns(ui->treeView); });
connect(ui->filterEdit, &QLineEdit::textChanged, this, &ExternalResourcesPage::filterTextChanged);
m_model->loadColumns(m_ui->treeView);
connect(m_ui->treeView->header(), &QHeaderView::sectionResized, this, [this] { m_model->saveColumns(m_ui->treeView); });
connect(m_ui->filterEdit, &QLineEdit::textChanged, this, &ExternalResourcesPage::filterTextChanged);
updateActions();
}
ExternalResourcesPage::~ExternalResourcesPage()
{
delete ui;
delete m_ui;
}
QMenu* ExternalResourcesPage::createPopupMenu()
{
QMenu* filteredMenu = QMainWindow::createPopupMenu();
filteredMenu->removeAction(ui->actionsToolbar->toggleViewAction());
filteredMenu->removeAction(m_ui->actionsToolbar->toggleViewAction());
return filteredMenu;
}
void ExternalResourcesPage::ShowContextMenu(const QPoint& pos)
void ExternalResourcesPage::showContextMenu(const QPoint& pos)
{
auto menu = ui->actionsToolbar->createContextMenu(this, tr("Context menu"));
menu->exec(ui->treeView->mapToGlobal(pos));
auto* menu = m_ui->actionsToolbar->createContextMenu(this, tr("Context menu"));
menu->exec(m_ui->treeView->mapToGlobal(pos));
delete menu;
}
void ExternalResourcesPage::ShowHeaderContextMenu(const QPoint& pos)
void ExternalResourcesPage::showHeaderContextMenu(const QPoint& pos)
{
auto menu = m_model->createHeaderContextMenu(ui->treeView);
menu->exec(ui->treeView->mapToGlobal(pos));
auto* menu = m_model->createHeaderContextMenu(m_ui->treeView);
menu->exec(m_ui->treeView->mapToGlobal(pos));
menu->deleteLater();
}
@ -190,27 +195,27 @@ void ExternalResourcesPage::openedImpl()
{
m_model->startWatching();
auto const setting_name = QString("WideBarVisibility_%1").arg(id());
m_wide_bar_setting = APPLICATION->settings()->getOrRegisterSetting(setting_name);
const auto settingName = QString("WideBarVisibility_%1").arg(id());
m_wideBarSetting = APPLICATION->settings()->getOrRegisterSetting(settingName);
ui->actionsToolbar->setVisibilityState(QByteArray::fromBase64(m_wide_bar_setting->get().toString().toUtf8()));
m_ui->actionsToolbar->setVisibilityState(QByteArray::fromBase64(m_wideBarSetting->get().toString().toUtf8()));
}
void ExternalResourcesPage::closedImpl()
{
m_model->stopWatching();
m_wide_bar_setting->set(QString::fromUtf8(ui->actionsToolbar->getVisibilityState().toBase64()));
m_wideBarSetting->set(QString::fromUtf8(m_ui->actionsToolbar->getVisibilityState().toBase64()));
}
void ExternalResourcesPage::retranslate()
{
ui->retranslateUi(this);
m_ui->retranslateUi(this);
}
void ExternalResourcesPage::itemActivated(const QModelIndex&)
void ExternalResourcesPage::itemActivated(const QModelIndex& /*unused*/)
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection());
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection());
m_model->setResourceEnabled(selection.indexes(), EnableAction::TOGGLE);
}
@ -237,17 +242,19 @@ bool ExternalResourcesPage::listFilter(QKeyEvent* keyEvent)
default:
break;
}
return QWidget::eventFilter(ui->treeView, keyEvent);
return QWidget::eventFilter(m_ui->treeView, keyEvent);
}
bool ExternalResourcesPage::eventFilter(QObject* obj, QEvent* ev)
{
if (ev->type() != QEvent::KeyPress)
if (ev->type() != QEvent::KeyPress) {
return QWidget::eventFilter(obj, ev);
}
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(ev);
if (obj == ui->treeView)
auto* keyEvent = static_cast<QKeyEvent*>(ev);
if (obj == m_ui->treeView) {
return listFilter(keyEvent);
}
return QWidget::eventFilter(obj, ev);
}
@ -259,7 +266,7 @@ void ExternalResourcesPage::addItem()
m_fileSelectionFilter.arg(displayName()), APPLICATION->settings()->get("CentralModsDir").toString(), this->parentWidget());
if (!list.isEmpty()) {
for (auto filename : list) {
for (const auto& filename : list) {
m_model->installResource(filename);
}
}
@ -267,7 +274,7 @@ void ExternalResourcesPage::addItem()
void ExternalResourcesPage::removeItem()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection());
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection());
int count = 0;
bool folder = false;
@ -276,10 +283,11 @@ void ExternalResourcesPage::removeItem()
count++;
// if a folder is selected, show the confirmation dialog
if (m_model->at(i.row()).fileinfo().isDir())
if (m_model->at(i.row()).fileinfo().isDir()) {
folder = true;
}
}
}
QString text;
bool multiple = count > 1;
@ -301,9 +309,10 @@ void ExternalResourcesPage::removeItem()
QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
->exec();
if (response != QMessageBox::Yes)
if (response != QMessageBox::Yes) {
return;
}
}
removeItems(selection);
}
@ -317,32 +326,34 @@ void ExternalResourcesPage::removeItems(const QItemSelection& selection)
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
->exec();
if (response != QMessageBox::Yes)
if (response != QMessageBox::Yes) {
return;
}
}
m_model->deleteResources(selection.indexes());
}
void ExternalResourcesPage::enableItem()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection());
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection());
m_model->setResourceEnabled(selection.indexes(), EnableAction::ENABLE);
}
void ExternalResourcesPage::disableItem()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection());
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection());
m_model->setResourceEnabled(selection.indexes(), EnableAction::DISABLE);
}
void ExternalResourcesPage::viewHomepage()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
for (auto resource : m_model->selectedResources(selection)) {
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
for (auto* resource : m_model->selectedResources(selection)) {
auto url = resource->homepage();
if (!url.isEmpty())
if (!url.isEmpty()) {
DesktopServices::openUrl(url);
}
}
}
void ExternalResourcesPage::viewConfigs()
@ -357,55 +368,56 @@ void ExternalResourcesPage::viewFolder()
void ExternalResourcesPage::updateActions()
{
const bool hasSelection = ui->treeView->selectionModel()->hasSelection();
const QModelIndexList selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
const bool hasSelection = m_ui->treeView->selectionModel()->hasSelection();
const QModelIndexList selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
const QList<Resource*> selectedResources = m_model->selectedResources(selection);
const bool hasMeta = hasSelection && std::any_of(selectedResources.begin(), selectedResources.end(),
[](Resource* resource) { return resource->metadata(); });
ui->actionUpdateItem->setEnabled(!m_model->empty());
ui->actionResetItemMetadata->setEnabled(hasSelection);
m_ui->actionUpdateItem->setEnabled(!m_model->empty());
m_ui->actionResetItemMetadata->setEnabled(hasSelection);
ui->actionChangeVersion->setEnabled(selectedResources.size() == 1 && selectedResources[0]->metadata() != nullptr);
m_ui->actionChangeVersion->setEnabled(selectedResources.size() == 1 && selectedResources[0]->metadata() != nullptr);
ui->actionRemoveItem->setEnabled(hasSelection);
ui->actionEnableItem->setEnabled(hasSelection);
ui->actionDisableItem->setEnabled(hasSelection);
m_ui->actionRemoveItem->setEnabled(hasSelection);
m_ui->actionEnableItem->setEnabled(hasSelection);
m_ui->actionDisableItem->setEnabled(hasSelection);
ui->actionViewHomepage->setEnabled(hasSelection && std::any_of(selectedResources.begin(), selectedResources.end(),
m_ui->actionViewHomepage->setEnabled(hasSelection && std::any_of(selectedResources.begin(), selectedResources.end(),
[](Resource* resource) { return !resource->homepage().isEmpty(); }));
ui->actionEnableUpdates->setEnabled(hasMeta);
ui->actionDisableUpdates->setEnabled(hasMeta);
ui->actionExportMetadata->setEnabled(!m_model->empty());
m_ui->actionEnableUpdates->setEnabled(hasMeta);
m_ui->actionDisableUpdates->setEnabled(hasMeta);
m_ui->actionExportMetadata->setEnabled(!m_model->empty());
}
void ExternalResourcesPage::updateFrame(const QModelIndex& current, [[maybe_unused]] const QModelIndex& previous)
{
auto sourceCurrent = m_filterModel->mapToSource(current);
int row = sourceCurrent.row();
Resource const& resource = m_model->at(row);
ui->frame->updateWithResource(resource);
const Resource& resource = m_model->at(row);
m_ui->frame->updateWithResource(resource);
}
QString ExternalResourcesPage::extraHeaderInfoString()
{
if (ui && ui->treeView && ui->treeView->selectionModel()) {
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
if (auto count = std::count_if(selection.cbegin(), selection.cend(), [](auto v) { return v.column() == 0; }); count != 0)
if (m_ui && m_ui->treeView && m_ui->treeView->selectionModel()) {
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
if (auto count = std::count_if(selection.cbegin(), selection.cend(), [](auto v) { return v.column() == 0; }); count != 0) {
return tr(" (%1 installed, %2 selected)").arg(m_model->size()).arg(count);
}
}
return tr(" (%1 installed)").arg(m_model->size());
}
void ExternalResourcesPage::enableUpdates()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection());
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection());
m_model->setModUpdate(selection.indexes(), EnableAction::ENABLE);
}
void ExternalResourcesPage::disableUpdates()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection());
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection());
m_model->setModUpdate(selection.indexes(), EnableAction::DISABLE);
}

View file

@ -21,14 +21,14 @@ class ExternalResourcesPage : public QMainWindow, public BasePage {
public:
explicit ExternalResourcesPage(BaseInstance* instance, ResourceFolderModel* model, QWidget* parent = nullptr);
virtual ~ExternalResourcesPage();
~ExternalResourcesPage() override;
virtual QString displayName() const override = 0;
virtual QIcon icon() const override = 0;
virtual QString id() const override = 0;
virtual QString helpPage() const override = 0;
QString displayName() const override = 0;
QIcon icon() const override = 0;
QString id() const override = 0;
QString helpPage() const override = 0;
virtual bool shouldDisplay() const override = 0;
bool shouldDisplay() const override = 0;
QString extraHeaderInfoString();
void openedImpl() override;
@ -38,7 +38,7 @@ class ExternalResourcesPage : public QMainWindow, public BasePage {
protected:
bool eventFilter(QObject* obj, QEvent* ev) override;
bool listFilter(QKeyEvent* ev);
bool listFilter(QKeyEvent* keyEvent);
QMenu* createPopupMenu() override;
public slots:
@ -61,8 +61,8 @@ class ExternalResourcesPage : public QMainWindow, public BasePage {
virtual void viewFolder();
virtual void viewConfigs();
void ShowContextMenu(const QPoint& pos);
void ShowHeaderContextMenu(const QPoint& pos);
void showContextMenu(const QPoint& pos);
void showHeaderContextMenu(const QPoint& pos);
void enableUpdates();
void disableUpdates();
@ -70,12 +70,12 @@ class ExternalResourcesPage : public QMainWindow, public BasePage {
protected:
BaseInstance* m_instance = nullptr;
Ui::ExternalResourcesPage* ui = nullptr;
Ui::ExternalResourcesPage* m_ui = nullptr;
ResourceFolderModel* m_model;
QSortFilterProxyModel* m_filterModel = nullptr;
QString m_fileSelectionFilter;
QString m_viewFilter;
std::shared_ptr<Setting> m_wide_bar_setting = nullptr;
std::shared_ptr<Setting> m_wideBarSetting = nullptr;
};

View file

@ -70,48 +70,48 @@
ModFolderPage::ModFolderPage(BaseInstance* inst, ModFolderModel* model, QWidget* parent)
: ExternalResourcesPage(inst, model, parent), m_model(model)
{
ui->actionDownloadItem->setText(tr("Download Mods"));
ui->actionDownloadItem->setToolTip(tr("Download mods from online mod platforms"));
ui->actionDownloadItem->setEnabled(true);
ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionDownloadItem);
m_ui->actionDownloadItem->setText(tr("Download Mods"));
m_ui->actionDownloadItem->setToolTip(tr("Download mods from online mod platforms"));
m_ui->actionDownloadItem->setEnabled(true);
m_ui->actionsToolbar->insertActionBefore(m_ui->actionAddItem, m_ui->actionDownloadItem);
connect(ui->actionDownloadItem, &QAction::triggered, this, &ModFolderPage::downloadMods);
connect(m_ui->actionDownloadItem, &QAction::triggered, this, &ModFolderPage::downloadMods);
ui->actionUpdateItem->setToolTip(tr("Try to check or update all selected mods (all mods if none are selected)"));
connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods);
ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionUpdateItem);
m_ui->actionUpdateItem->setToolTip(tr("Try to check or update all selected mods (all mods if none are selected)"));
connect(m_ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods);
m_ui->actionsToolbar->insertActionBefore(m_ui->actionAddItem, m_ui->actionUpdateItem);
auto* updateMenu = new QMenu(this);
auto* update = updateMenu->addAction(tr("Check for Updates"));
connect(update, &QAction::triggered, this, &ModFolderPage::updateMods);
updateMenu->addAction(ui->actionVerifyItemDependencies);
connect(ui->actionVerifyItemDependencies, &QAction::triggered, this, [this] { updateMods(true); });
updateMenu->addAction(m_ui->actionVerifyItemDependencies);
connect(m_ui->actionVerifyItemDependencies, &QAction::triggered, this, [this] { updateMods(true); });
auto depsDisabled = APPLICATION->settings()->getSetting("ModDependenciesDisabled");
ui->actionVerifyItemDependencies->setVisible(!depsDisabled->get().toBool());
m_ui->actionVerifyItemDependencies->setVisible(!depsDisabled->get().toBool());
connect(depsDisabled.get(), &Setting::SettingChanged, this,
[this](const Setting&, const QVariant& value) { ui->actionVerifyItemDependencies->setVisible(!value.toBool()); });
[this](const Setting&, const QVariant& value) { m_ui->actionVerifyItemDependencies->setVisible(!value.toBool()); });
updateMenu->addAction(ui->actionResetItemMetadata);
connect(ui->actionResetItemMetadata, &QAction::triggered, this, &ModFolderPage::deleteModMetadata);
updateMenu->addAction(m_ui->actionResetItemMetadata);
connect(m_ui->actionResetItemMetadata, &QAction::triggered, this, &ModFolderPage::deleteModMetadata);
ui->actionUpdateItem->setMenu(updateMenu);
m_ui->actionUpdateItem->setMenu(updateMenu);
ui->actionChangeVersion->setToolTip(tr("Change a mod's version."));
connect(ui->actionChangeVersion, &QAction::triggered, this, &ModFolderPage::changeModVersion);
ui->actionsToolbar->insertActionAfter(ui->actionUpdateItem, ui->actionChangeVersion);
m_ui->actionChangeVersion->setToolTip(tr("Change a mod's version."));
connect(m_ui->actionChangeVersion, &QAction::triggered, this, &ModFolderPage::changeModVersion);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionUpdateItem, m_ui->actionChangeVersion);
ui->actionViewHomepage->setToolTip(tr("View the homepages of all selected mods."));
m_ui->actionViewHomepage->setToolTip(tr("View the homepages of all selected mods."));
ui->actionExportMetadata->setToolTip(tr("Export mod's metadata to text."));
connect(ui->actionExportMetadata, &QAction::triggered, this, &ModFolderPage::exportModMetadata);
ui->actionsToolbar->insertActionAfter(ui->actionViewHomepage, ui->actionExportMetadata);
m_ui->actionExportMetadata->setToolTip(tr("Export mod's metadata to text."));
connect(m_ui->actionExportMetadata, &QAction::triggered, this, &ModFolderPage::exportModMetadata);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionViewHomepage, m_ui->actionExportMetadata);
ui->actionsToolbar->insertActionAfter(ui->actionViewFolder, ui->actionViewConfigs);
ui->actionsToolbar->insertActionAfter(ui->actionUpdateItem, ui->actionEnableUpdates);
ui->actionsToolbar->insertActionAfter(ui->actionEnableUpdates, ui->actionDisableUpdates);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionViewFolder, m_ui->actionViewConfigs);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionUpdateItem, m_ui->actionEnableUpdates);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionEnableUpdates, m_ui->actionDisableUpdates);
}
bool ModFolderPage::shouldDisplay() const
@ -124,7 +124,7 @@ void ModFolderPage::updateFrame(const QModelIndex& current, [[maybe_unused]] con
auto sourceCurrent = m_filterModel->mapToSource(current);
int row = sourceCurrent.row();
const Mod& mod = m_model->at(row);
ui->frame->updateWithMod(mod);
m_ui->frame->updateWithMod(mod);
}
void ModFolderPage::removeItems(const QItemSelection& selection)
@ -251,7 +251,7 @@ void ModFolderPage::updateMods(bool includeDeps)
return;
}
}
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
auto modsList = m_model->selectedResources(selection);
bool useAll = modsList.empty();
@ -311,7 +311,7 @@ void ModFolderPage::updateMods(bool includeDeps)
void ModFolderPage::deleteModMetadata()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
auto selectionCount = m_model->selectedMods(selection).length();
if (selectionCount == 0) {
return;
@ -348,7 +348,7 @@ void ModFolderPage::changeModVersion()
QMessageBox::critical(this, tr("Error"), tr("Mod updates are unavailable when metadata is disabled!"));
return;
}
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
auto modsList = m_model->selectedMods(selection);
if (modsList.length() != 1 || modsList[0]->metadata() == nullptr) {
return;
@ -364,7 +364,7 @@ void ModFolderPage::changeModVersion()
void ModFolderPage::exportModMetadata()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
auto selectedMods = m_model->selectedMods(selection);
if (selectedMods.length() == 0) {
selectedMods = m_model->allMods();

View file

@ -45,33 +45,33 @@
ResourcePackPage::ResourcePackPage(MinecraftInstance* instance, ResourcePackFolderModel* model, QWidget* parent)
: ExternalResourcesPage(instance, model, parent), m_model(model)
{
ui->actionDownloadItem->setText(tr("Download Packs"));
ui->actionDownloadItem->setToolTip(tr("Download resource packs from online mod platforms"));
ui->actionDownloadItem->setEnabled(true);
ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionDownloadItem);
m_ui->actionDownloadItem->setText(tr("Download Packs"));
m_ui->actionDownloadItem->setToolTip(tr("Download resource packs from online mod platforms"));
m_ui->actionDownloadItem->setEnabled(true);
m_ui->actionsToolbar->insertActionBefore(m_ui->actionAddItem, m_ui->actionDownloadItem);
connect(ui->actionDownloadItem, &QAction::triggered, this, &ResourcePackPage::downloadResourcePacks);
connect(m_ui->actionDownloadItem, &QAction::triggered, this, &ResourcePackPage::downloadResourcePacks);
ui->actionUpdateItem->setToolTip(tr("Try to check or update all selected resource packs (all resource packs if none are selected)"));
connect(ui->actionUpdateItem, &QAction::triggered, this, &ResourcePackPage::updateResourcePacks);
ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionUpdateItem);
m_ui->actionUpdateItem->setToolTip(tr("Try to check or update all selected resource packs (all resource packs if none are selected)"));
connect(m_ui->actionUpdateItem, &QAction::triggered, this, &ResourcePackPage::updateResourcePacks);
m_ui->actionsToolbar->insertActionBefore(m_ui->actionAddItem, m_ui->actionUpdateItem);
auto* updateMenu = new QMenu(this);
auto* update = updateMenu->addAction(ui->actionUpdateItem->text());
auto* update = updateMenu->addAction(m_ui->actionUpdateItem->text());
connect(update, &QAction::triggered, this, &ResourcePackPage::updateResourcePacks);
updateMenu->addAction(ui->actionResetItemMetadata);
connect(ui->actionResetItemMetadata, &QAction::triggered, this, &ResourcePackPage::deleteResourcePackMetadata);
updateMenu->addAction(m_ui->actionResetItemMetadata);
connect(m_ui->actionResetItemMetadata, &QAction::triggered, this, &ResourcePackPage::deleteResourcePackMetadata);
ui->actionUpdateItem->setMenu(updateMenu);
m_ui->actionUpdateItem->setMenu(updateMenu);
ui->actionChangeVersion->setToolTip(tr("Change a mod's version."));
connect(ui->actionChangeVersion, &QAction::triggered, this, &ResourcePackPage::changeResourcePackVersion);
ui->actionsToolbar->insertActionAfter(ui->actionUpdateItem, ui->actionChangeVersion);
m_ui->actionChangeVersion->setToolTip(tr("Change a mod's version."));
connect(m_ui->actionChangeVersion, &QAction::triggered, this, &ResourcePackPage::changeResourcePackVersion);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionUpdateItem, m_ui->actionChangeVersion);
ui->actionsToolbar->insertActionAfter(ui->actionUpdateItem, ui->actionEnableUpdates);
ui->actionsToolbar->insertActionAfter(ui->actionEnableUpdates, ui->actionDisableUpdates);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionUpdateItem, m_ui->actionEnableUpdates);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionEnableUpdates, m_ui->actionDisableUpdates);
}
void ResourcePackPage::updateFrame(const QModelIndex& current, [[maybe_unused]] const QModelIndex& previous)
@ -79,7 +79,7 @@ void ResourcePackPage::updateFrame(const QModelIndex& current, [[maybe_unused]]
auto sourceCurrent = m_filterModel->mapToSource(current);
int row = sourceCurrent.row();
auto& rp = m_model->at(row);
ui->frame->updateWithResourcePack(rp);
m_ui->frame->updateWithResourcePack(rp);
}
void ResourcePackPage::downloadResourcePacks()
@ -158,7 +158,7 @@ void ResourcePackPage::updateResourcePacks()
return;
}
}
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
auto modsList = m_model->selectedResources(selection);
bool useAll = modsList.empty();
@ -218,7 +218,7 @@ void ResourcePackPage::updateResourcePacks()
void ResourcePackPage::deleteResourcePackMetadata()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
auto selectionCount = m_model->selectedResourcePacks(selection).length();
if (selectionCount == 0) {
return;
@ -250,7 +250,7 @@ void ResourcePackPage::changeResourcePackVersion()
return;
}
const QModelIndexList rows = ui->treeView->selectionModel()->selectedRows();
const QModelIndexList rows = m_ui->treeView->selectionModel()->selectedRows();
if (rows.count() != 1) {
return;

View file

@ -50,33 +50,33 @@
ShaderPackPage::ShaderPackPage(MinecraftInstance* instance, ShaderPackFolderModel* model, QWidget* parent)
: ExternalResourcesPage(instance, model, parent), m_model(model)
{
ui->actionDownloadItem->setText(tr("Download Packs"));
ui->actionDownloadItem->setToolTip(tr("Download shader packs from online mod platforms"));
ui->actionDownloadItem->setEnabled(true);
ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionDownloadItem);
m_ui->actionDownloadItem->setText(tr("Download Packs"));
m_ui->actionDownloadItem->setToolTip(tr("Download shader packs from online mod platforms"));
m_ui->actionDownloadItem->setEnabled(true);
m_ui->actionsToolbar->insertActionBefore(m_ui->actionAddItem, m_ui->actionDownloadItem);
connect(ui->actionDownloadItem, &QAction::triggered, this, &ShaderPackPage::downloadShaderPack);
connect(m_ui->actionDownloadItem, &QAction::triggered, this, &ShaderPackPage::downloadShaderPack);
ui->actionUpdateItem->setToolTip(tr("Try to check or update all selected shader packs (all shader packs if none are selected)"));
connect(ui->actionUpdateItem, &QAction::triggered, this, &ShaderPackPage::updateShaderPacks);
ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionUpdateItem);
m_ui->actionUpdateItem->setToolTip(tr("Try to check or update all selected shader packs (all shader packs if none are selected)"));
connect(m_ui->actionUpdateItem, &QAction::triggered, this, &ShaderPackPage::updateShaderPacks);
m_ui->actionsToolbar->insertActionBefore(m_ui->actionAddItem, m_ui->actionUpdateItem);
auto* updateMenu = new QMenu(this);
auto* update = updateMenu->addAction(ui->actionUpdateItem->text());
auto* update = updateMenu->addAction(m_ui->actionUpdateItem->text());
connect(update, &QAction::triggered, this, &ShaderPackPage::updateShaderPacks);
updateMenu->addAction(ui->actionResetItemMetadata);
connect(ui->actionResetItemMetadata, &QAction::triggered, this, &ShaderPackPage::deleteShaderPackMetadata);
updateMenu->addAction(m_ui->actionResetItemMetadata);
connect(m_ui->actionResetItemMetadata, &QAction::triggered, this, &ShaderPackPage::deleteShaderPackMetadata);
ui->actionUpdateItem->setMenu(updateMenu);
m_ui->actionUpdateItem->setMenu(updateMenu);
ui->actionChangeVersion->setToolTip(tr("Change a shader pack's version."));
connect(ui->actionChangeVersion, &QAction::triggered, this, &ShaderPackPage::changeShaderPackVersion);
ui->actionsToolbar->insertActionAfter(ui->actionUpdateItem, ui->actionChangeVersion);
m_ui->actionChangeVersion->setToolTip(tr("Change a shader pack's version."));
connect(m_ui->actionChangeVersion, &QAction::triggered, this, &ShaderPackPage::changeShaderPackVersion);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionUpdateItem, m_ui->actionChangeVersion);
ui->actionsToolbar->insertActionAfter(ui->actionUpdateItem, ui->actionEnableUpdates);
ui->actionsToolbar->insertActionAfter(ui->actionEnableUpdates, ui->actionDisableUpdates);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionUpdateItem, m_ui->actionEnableUpdates);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionEnableUpdates, m_ui->actionDisableUpdates);
}
void ShaderPackPage::downloadShaderPack()
@ -155,7 +155,7 @@ void ShaderPackPage::updateShaderPacks()
return;
}
}
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
auto modsList = m_model->selectedResources(selection);
bool useAll = modsList.empty();
@ -215,7 +215,7 @@ void ShaderPackPage::updateShaderPacks()
void ShaderPackPage::deleteShaderPackMetadata()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
auto selectionCount = m_model->selectedShaderPacks(selection).length();
if (selectionCount == 0) {
return;
@ -247,7 +247,7 @@ void ShaderPackPage::changeShaderPackVersion()
return;
}
const QModelIndexList rows = ui->treeView->selectionModel()->selectedRows();
const QModelIndexList rows = m_ui->treeView->selectionModel()->selectedRows();
if (rows.count() != 1) {
return;

View file

@ -49,35 +49,35 @@
TexturePackPage::TexturePackPage(MinecraftInstance* instance, TexturePackFolderModel* model, QWidget* parent)
: ExternalResourcesPage(instance, model, parent), m_model(model)
{
ui->actionDownloadItem->setText(tr("Download Packs"));
ui->actionDownloadItem->setToolTip(tr("Download texture packs from online mod platforms"));
ui->actionDownloadItem->setEnabled(true);
ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionDownloadItem);
m_ui->actionDownloadItem->setText(tr("Download Packs"));
m_ui->actionDownloadItem->setToolTip(tr("Download texture packs from online mod platforms"));
m_ui->actionDownloadItem->setEnabled(true);
m_ui->actionsToolbar->insertActionBefore(m_ui->actionAddItem, m_ui->actionDownloadItem);
connect(ui->actionDownloadItem, &QAction::triggered, this, &TexturePackPage::downloadTexturePacks);
connect(m_ui->actionDownloadItem, &QAction::triggered, this, &TexturePackPage::downloadTexturePacks);
ui->actionUpdateItem->setToolTip(tr("Try to check or update all selected texture packs (all texture packs if none are selected)"));
connect(ui->actionUpdateItem, &QAction::triggered, this, &TexturePackPage::updateTexturePacks);
ui->actionsToolbar->insertActionBefore(ui->actionAddItem, ui->actionUpdateItem);
m_ui->actionUpdateItem->setToolTip(tr("Try to check or update all selected texture packs (all texture packs if none are selected)"));
connect(m_ui->actionUpdateItem, &QAction::triggered, this, &TexturePackPage::updateTexturePacks);
m_ui->actionsToolbar->insertActionBefore(m_ui->actionAddItem, m_ui->actionUpdateItem);
auto* updateMenu = new QMenu(this);
auto* update = updateMenu->addAction(ui->actionUpdateItem->text());
auto* update = updateMenu->addAction(m_ui->actionUpdateItem->text());
connect(update, &QAction::triggered, this, &TexturePackPage::updateTexturePacks);
updateMenu->addAction(ui->actionResetItemMetadata);
connect(ui->actionResetItemMetadata, &QAction::triggered, this, &TexturePackPage::deleteTexturePackMetadata);
updateMenu->addAction(m_ui->actionResetItemMetadata);
connect(m_ui->actionResetItemMetadata, &QAction::triggered, this, &TexturePackPage::deleteTexturePackMetadata);
ui->actionUpdateItem->setMenu(updateMenu);
m_ui->actionUpdateItem->setMenu(updateMenu);
ui->actionChangeVersion->setToolTip(tr("Change a texture pack's version."));
connect(ui->actionChangeVersion, &QAction::triggered, this, &TexturePackPage::changeTexturePackVersion);
ui->actionsToolbar->insertActionAfter(ui->actionUpdateItem, ui->actionChangeVersion);
m_ui->actionChangeVersion->setToolTip(tr("Change a texture pack's version."));
connect(m_ui->actionChangeVersion, &QAction::triggered, this, &TexturePackPage::changeTexturePackVersion);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionUpdateItem, m_ui->actionChangeVersion);
ui->actionViewHomepage->setToolTip(tr("View the homepages of all selected texture packs."));
m_ui->actionViewHomepage->setToolTip(tr("View the homepages of all selected texture packs."));
ui->actionsToolbar->insertActionAfter(ui->actionUpdateItem, ui->actionEnableUpdates);
ui->actionsToolbar->insertActionAfter(ui->actionEnableUpdates, ui->actionDisableUpdates);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionUpdateItem, m_ui->actionEnableUpdates);
m_ui->actionsToolbar->insertActionAfter(m_ui->actionEnableUpdates, m_ui->actionDisableUpdates);
}
void TexturePackPage::updateFrame(const QModelIndex& current, [[maybe_unused]] const QModelIndex& previous)
@ -85,7 +85,7 @@ void TexturePackPage::updateFrame(const QModelIndex& current, [[maybe_unused]] c
auto sourceCurrent = m_filterModel->mapToSource(current);
int row = sourceCurrent.row();
auto& rp = m_model->at(row);
ui->frame->updateWithTexturePack(rp);
m_ui->frame->updateWithTexturePack(rp);
}
void TexturePackPage::downloadTexturePacks()
@ -163,7 +163,7 @@ void TexturePackPage::updateTexturePacks()
return;
}
}
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
auto modsList = m_model->selectedResources(selection);
bool useAll = modsList.empty();
@ -223,7 +223,7 @@ void TexturePackPage::updateTexturePacks()
void TexturePackPage::deleteTexturePackMetadata()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes();
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection()).indexes();
auto selectionCount = m_model->selectedTexturePacks(selection).length();
if (selectionCount == 0) {
return;
@ -255,7 +255,7 @@ void TexturePackPage::changeTexturePackVersion()
return;
}
const QModelIndexList rows = ui->treeView->selectionModel()->selectedRows();
const QModelIndexList rows = m_ui->treeView->selectionModel()->selectedRows();
if (rows.count() != 1) {
return;

View file

@ -55,7 +55,7 @@ class TexturePackPage : public ExternalResourcesPage {
QString id() const override { return "texturepacks"; }
QString helpPage() const override { return "Texture-packs"; }
virtual bool shouldDisplay() const override { return m_instance->traits().contains("texturepacks"); }
bool shouldDisplay() const override { return m_instance->traits().contains("texturepacks"); }
public slots:
void updateFrame(const QModelIndex& current, const QModelIndex& previous) override;

View file

@ -22,7 +22,7 @@ ModModel::ModModel(BaseInstance& base_inst, ResourceAPI* api, QString debugName,
ResourceAPI::SearchArgs ModModel::createSearchArguments()
{
auto profile = static_cast<MinecraftInstance const&>(m_base_instance).getPackProfile();
auto profile = static_cast<const MinecraftInstance&>(m_base_instance).getPackProfile();
Q_ASSERT(profile);
Q_ASSERT(m_filter);
@ -50,7 +50,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(const QModelIndex& entry)
{
auto pack = m_packs[entry.row()];
auto profile = static_cast<MinecraftInstance const&>(m_base_instance).getPackProfile();
auto profile = static_cast<const MinecraftInstance&>(m_base_instance).getPackProfile();
Q_ASSERT(profile);
Q_ASSERT(m_filter);
@ -88,7 +88,7 @@ bool ModModel::isPackInstalled(ModPlatform::IndexedPack::Ptr pack) const
auto allMods = static_cast<MinecraftInstance&>(m_base_instance).loaderModList()->allMods();
return std::any_of(allMods.cbegin(), allMods.cend(), [pack](Mod* mod) {
if (auto meta = mod->metadata(); meta)
return meta->provider == pack->provider && meta->project_id == pack->addonId;
return meta->provider == pack->provider && meta->projectId == pack->addonId;
return false;
});
}
@ -97,7 +97,7 @@ QVariant ModModel::getInstalledPackVersion(ModPlatform::IndexedPack::Ptr pack) c
{
auto allMods = static_cast<MinecraftInstance&>(m_base_instance).loaderModList()->allMods();
for (auto mod : allMods) {
if (auto meta = mod->metadata(); meta && meta->provider == pack->provider && meta->project_id == pack->addonId) {
if (auto meta = mod->metadata(); meta && meta->provider == pack->provider && meta->projectId == pack->addonId) {
return meta->version();
}
}

View file

@ -46,14 +46,14 @@ class PackwizTest : public QObject {
QCOMPARE(metadata.side, ModPlatform::Side::ClientSide);
QCOMPARE(metadata.url, QUrl("https://cdn.modrinth.com/data/kYq5qkSL/versions/1.1.1+1.18/borderless-mining-1.1.1+1.18.jar"));
QCOMPARE(metadata.hash_format, "sha512");
QCOMPARE(metadata.hashFormat, "sha512");
QCOMPARE(metadata.hash,
"c8fe6e15ddea32668822dddb26e1851e5f03834be4bcb2eff9c0da7fdc086a9b6cead78e31a44d3bc66335cba11144ee0337c6d5346f1ba6362306449"
"9b3188d");
QCOMPARE(metadata.provider, ModPlatform::ResourceProvider::MODRINTH);
QCOMPARE(metadata.version(), "ug2qKTPR");
QCOMPARE(metadata.mod_id(), "kYq5qkSL");
QCOMPARE(metadata.modId(), "kYq5qkSL");
}
void loadFromFile_Curseforge()
@ -76,12 +76,12 @@ class PackwizTest : public QObject {
QCOMPARE(metadata.side, ModPlatform::Side::UniversalSide);
QCOMPARE(metadata.url, QUrl("https://edge.forgecdn.net/files/3509/43/screenshot-to-clipboard-1.0.7-fabric.jar"));
QCOMPARE(metadata.hash_format, "murmur2");
QCOMPARE(metadata.hashFormat, "murmur2");
QCOMPARE(metadata.hash, "1781245820");
QCOMPARE(metadata.provider, ModPlatform::ResourceProvider::FLAME);
QCOMPARE(metadata.file_id, 3509043);
QCOMPARE(metadata.project_id, 327154);
QCOMPARE(metadata.fileId, 3509043);
QCOMPARE(metadata.projectId, 327154);
}
};