chore(clang-tidy): modernize the code

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97 committed 2026-09-20 23:28:58 +03:00
1 parent e135750f75
commit 02b26b6ccc
32 files changed
+598 -527

No files matched your search

+17 -18
View File
@@ -33,7 +33,6 @@
#include "tasks/Task.h"
namespace {
class ParsingValidator : public Net::Validator {
public: /* con/des */
explicit ParsingValidator(Meta::BaseEntity* entity) : m_entity(entity) {};
@@ -66,19 +65,19 @@ 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)
@@ -88,11 +87,11 @@ void BaseEntity::setSha256(QString 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()
@@ -104,26 +103,26 @@ void BaseEntityLoadTask::executeTask()
auto parse = [this, &hashMatches, fname] -> Result<> {
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"));
TRY_INTO(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) {
return std::unexpected(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) {
TRY(Json::requireObject(fileData, fname).and_then([this](const auto& v) { return m_entity->parse(v); }));
m_entity->m_load_status = BaseEntity::LoadStatus::Local;
m_entity->m_loadStatus = BaseEntity::LoadStatus::Local;
}
return {};
};
@@ -132,21 +131,21 @@ void BaseEntityLoadTask::executeTask()
qCritical() << QString("Unable to parse file %1: %2").arg(fname, res.error());
// 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({});
@@ -165,8 +164,8 @@ void BaseEntityLoadTask::executeTask()
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();
});
+8 -8
View File
@@ -30,7 +30,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,11 +47,11 @@ class BaseEntity {
[[nodiscard]] Task::Ptr loadTask(Net::Mode loadType = Net::Mode::Online, bool forceReload = false);
protected:
QString m_sha256; // the expected sha256
QString m_file_sha256; // the file sha256
QString m_sha256; // the expected sha256
QString m_fileSha256; // the file sha256
private:
LoadStatus m_load_status = LoadStatus::NotLoaded;
LoadStatus m_loadStatus = LoadStatus::NotLoaded;
Task::Ptr m_task;
};
@@ -62,14 +62,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
+69 -51
View File
@@ -43,7 +43,6 @@
#include <algorithm>
#include "MTPixmapCache.h"
#include "MetadataHandler.h"
#include "Resource.h"
#include "Version.h"
#include "minecraft/mod/ModDetails.h"
@@ -78,21 +77,22 @@ int compareVersionLists(const QStringList& leftVersions, const QStringList& righ
} // namespace
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:
@@ -100,43 +100,52 @@ int Mod::compare(const Resource& other, SortType type) const
case SortType::Name:
case SortType::Date:
case SortType::Size:
case SortType::Version:
return Resource::compare(other, type);
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 = compareVersionLists(mcVersions(), cast_other->mcVersions());
if (compare_result != 0)
return compare_result;
auto compareResult = compareVersionLists(mcVersions(), castOther->mcVersions());
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;
}
}
@@ -145,8 +154,9 @@ int Mod::compare(const Resource& other, SortType type) 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()) {
@@ -159,23 +169,25 @@ bool Mod::applyFilter(const 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();
}
@@ -189,10 +201,10 @@ auto Mod::homepage() const -> QString
{
QString metaUrl = Resource::homepage();
if (metaUrl.isEmpty())
if (metaUrl.isEmpty()) {
return details().homeurl;
else
return metaUrl;
}
return metaUrl;
}
auto Mod::loaders() const -> QString
@@ -211,16 +223,18 @@ auto Mod::loaders() const -> QString
auto Mod::side() const -> QString
{
if (metadata())
if (metadata()) {
return metadata()->side.toString();
}
return ModPlatform::SideType(ModPlatform::SideType::UniversalSide).toString();
}
auto Mod::mcVersions() const -> QStringList
{
if (metadata())
if (metadata()) {
return metadata()->mcVersions;
}
return {};
}
@@ -232,8 +246,9 @@ auto Mod::mcVersionsString() const -> QString
auto Mod::releaseType() const -> QString
{
if (metadata())
if (metadata()) {
return metadata()->releaseType.toString();
}
return ModPlatform::IndexedVersionType(ModPlatform::IndexedVersionType::Unknown).toString();
}
@@ -253,7 +268,7 @@ void Mod::finishResolvingWithDetails(ModDetails&& details)
m_isResolving = false;
m_isResolved = true;
m_local_details = std::move(details);
m_localDetails = std::move(details);
if (!iconPath().isEmpty()) {
m_packImageCacheKey.wasReadAttempt = false;
}
@@ -269,18 +284,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;
@@ -290,20 +306,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...";
@@ -311,8 +329,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 {};
@@ -320,7 +338,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
+9 -9
View File
@@ -49,12 +49,12 @@
class Mod : public Resource {
public:
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 override;
auto homepage() const -> QString override;
auto description() const -> QString;
@@ -75,11 +75,11 @@ 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);
@@ -89,16 +89,16 @@ class Mod : public Resource {
[[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;
+20 -20
View File
@@ -69,12 +69,12 @@ ModFolderModel::ModFolderModel(const QDir& dir, MinecraftInstance* instance, boo
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 };
m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files);
@@ -139,14 +139,14 @@ QVariant ModFolderModel::data(const QModelIndex& index, int role) const
case Qt::ToolTipRole:
switch (column) {
case RequiredByColumn: {
const auto list = requiredByList(at(row).mod_id());
const auto list = requiredByList(at(row).modId());
if (!list.isEmpty()) {
return list.join(QLatin1Char('\n'));
}
break;
}
case RequiresColumn: {
const auto list = requiresList(at(row).mod_id());
const auto list = requiresList(at(row).modId());
if (!list.isEmpty()) {
return list.join(QLatin1Char('\n'));
}
@@ -160,12 +160,12 @@ QVariant ModFolderModel::data(const QModelIndex& index, int role) const
if (column == ActiveColumn) {
return at(row).enabled() ? Qt::Checked : Qt::Unchecked;
}
return QVariant();
return {};
case Qt::UserRole:
if (column == LockUpdateColumn) {
return at(row).lockUpdate();
}
return QVariant();
return {};
default:
break;
}
@@ -307,7 +307,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
@@ -325,17 +325,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()) {
@@ -344,17 +344,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));
}
@@ -368,11 +368,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)) {
if (shouldBeEnabled != affected->enabled()) {
@@ -416,7 +416,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);
}
@@ -554,12 +554,12 @@ bool ModFolderModel::deleteResources(const QModelIndexList& indexes)
};
auto res = 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));
}
+4 -3
View File
@@ -109,7 +109,7 @@ auto Resource::provider() const -> QString
auto Resource::version() const -> QString
{
if (metadata()) {
return metadata()->version_number;
return metadata()->versionNumber;
}
return QObject::tr("Unknown");
@@ -118,7 +118,7 @@ auto Resource::version() 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 {};
@@ -126,8 +126,9 @@ auto Resource::homepage() const -> QString
bool Resource::lockUpdate() const
{
if (metadata())
if (metadata()) {
return metadata()->lockUpdate;
}
return false;
}
+3 -3
View File
@@ -81,7 +81,7 @@ enum class SortType : std::uint8_t {
Requires,
RequiredBy,
Filename,
LOCK_UPDATE
LockUpdate
};
enum class EnableAction : std::uint8_t { ENABLE, DISABLE, TOGGLE };
@@ -98,9 +98,9 @@ class Resource {
public:
using Ptr = std::shared_ptr<Resource>;
Resource(const QFileInfo& fileInfo);
explicit Resource(const QFileInfo& fileInfo);
Resource(const QString& filePath) : Resource(QFileInfo(filePath)) {}
explicit Resource(const QString& filePath) : Resource(QFileInfo(filePath)) {}
virtual ~Resource() = default;
+10 -7
View File
@@ -318,9 +318,9 @@ bool ResourceFolderModel::setResourceEnabled(const QModelIndexList& indexes, Ena
return succeeded;
}
static QMutex s_updateTaskMutex;
bool ResourceFolderModel::update()
{
static QMutex s_updateTaskMutex;
// We hold a lock here to prevent race conditions on the m_current_update_task reset.
QMutexLocker lock(&s_updateTaskMutex);
@@ -369,7 +369,7 @@ bool ResourceFolderModel::update()
return true;
}
void ResourceFolderModel::resolveResource(Resource::Ptr res)
void ResourceFolderModel::resolveResource(const Resource::Ptr& res)
{
if (!res->shouldResolve()) {
return;
@@ -600,6 +600,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 == LockUpdateColumn) {
return at(row).lockUpdate();
@@ -675,7 +676,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);
@@ -804,7 +805,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 */
@@ -1010,14 +1011,16 @@ QList<Resource*> ResourceFolderModel::selectedResources(const QModelIndexList& i
bool ResourceFolderModel::setUpdateLock(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];
+5 -5
View File
@@ -109,7 +109,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; }
@@ -165,7 +165,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);
@@ -174,7 +174,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; }
@@ -248,8 +248,8 @@ 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::Version, SortType::Date,
SortType::Provider, SortType::Size, SortType::Filename };
QList<SortType> m_columnSortKeys = { SortType::Enabled, SortType::Name, SortType::Version, SortType::Date,
SortType::Provider, SortType::Size, SortType::Filename, SortType::LockUpdate };
QStringList m_columnNames = { "Enable", "Name", "Version", "Last Modified", "Provider", "Size", "File Name", "Update" };
QStringList m_columnNamesTranslated = { tr("Enable"), tr("Name"), tr("Version"), tr("Last Modified"),
tr("Provider"), tr("Size"), tr("File Name"), tr("Update") };
@@ -55,7 +55,7 @@ ResourcePackFolderModel::ResourcePackFolderModel(const QDir& dir,
m_columnNamesTranslated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Version"), tr("Pack Format"), tr("Last Modified"),
tr("Provider"), tr("Size"), tr("File Name"), tr("Update") });
m_columnSortKeys = { SortType::Enabled, SortType::Name, SortType::Name, SortType::Version, SortType::PackFormat,
SortType::Date, SortType::Provider, SortType::Size, SortType::Filename, SortType::LOCK_UPDATE };
SortType::Date, 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, QHeaderView::Interactive };
@@ -103,6 +103,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 == LockUpdateColumn) {
return at(row).lockUpdate();
@@ -49,10 +49,10 @@ TexturePackFolderModel::TexturePackFolderModel(const QDir& dir,
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)
@@ -89,8 +89,9 @@ QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const
}
return {};
case Qt::UserRole:
if (column == LockUpdateColumn)
if (column == LockUpdateColumn) {
return at(row).lockUpdate();
}
return {};
default:
break;
@@ -166,7 +166,7 @@ QList<ModPlatform::Dependency> GetModDependenciesTask::getDependenciesForVersion
}
auto isInstalledMod = [&verDep, providerName, isOnlyVersion](const std::shared_ptr<Metadata::ModStruct>& i) {
return i->provider == providerName && (isOnlyVersion ? i->file_id == verDep.version : i->project_id == verDep.addonId);
return i->provider == providerName && (isOnlyVersion ? i->fileId == verDep.version : i->projectId == verDep.addonId);
};
if (std::ranges::any_of(m_mods, isInstalledMod)) {
continue; // check the existing mods
@@ -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(std::move(project)), m_version(std::move(version)), m_lockUpdate(lockUpdate)
: m_indexDir(indexDir), m_project(std::move(project)), m_version(std::move(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!";
@@ -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;
@@ -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::get().getVersionsURL({ .pack = project, .mcVersions = m_gameVersions });
if (!versionsUrlOptional.has_value()) {
continue;
@@ -68,7 +68,7 @@ void FlameCheckUpdate::getLatestVersionCallback(Resource* resource, QByteArray*
// Fake pack with the necessary info to pass to the download task :)
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;
return FlameMod::loadIndexedPackVersions(*pack.get(), doc);
};
@@ -97,14 +97,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");
@@ -126,7 +126,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;
}
@@ -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;
}
@@ -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)
@@ -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
@@ -61,7 +61,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,
[this, resource](const QString& hash) { m_mappings.insert(hash, resource); });
@@ -177,12 +177,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 ((version.hash != hash && version.isPreferred) || (resource->status() == ResourceStatus::NotInstalled)) {
auto downloadTask = makeShared<ResourceDownloadTask>(pack, version, 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");
+97 -91
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.hashType;
mod.hash = mod_version.hash;
mod.hashFormat = modVersion.hashType;
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.isValid() ? 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::SideType::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.versionType;
mod.releaseType = modVersion.versionType;
mod.version_number = mod_version.versionNumber;
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.versionNumber;
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", dep.type.toString().toStdString() } };
if (!dep.version.isEmpty()) {
tbl.emplace("version", dep.version.toStdString());
@@ -218,7 +218,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() },
@@ -226,60 +226,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 {};
}
@@ -323,49 +325,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.provider = Provider::MODRINTH;
mod.mod_id() = stringEntry(*mod_provider_table, "mod-id");
mod.version() = stringEntry(*mod_provider_table, "version");
mod.fileId = intEntry(*modProviderTable, "file-id");
mod.projectId = intEntry(*modProviderTable, "project-id");
} else {
qCritical() << QString("No mod provider on mod metadata!");
return {};
modProviderTable = updateTable[ModPlatform::ProviderCapabilities::name(Provider::MODRINTH)].as_table();
if (modProviderTable != nullptr) {
mod.provider = Provider::MODRINTH;
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");
@@ -382,13 +387,14 @@ 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 {};
+12 -12
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
@@ -350,7 +350,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);
}
GetModDependenciesTask::Ptr ResourceDownloadDialog::getModDependenciesTask()
+19 -19
View File
@@ -29,30 +29,30 @@
DataPackPage::DataPackPage(MinecraftInstance* 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)
@@ -60,7 +60,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()
@@ -123,7 +123,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();
@@ -175,7 +175,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;
@@ -203,7 +203,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;
@@ -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(MinecraftInstance* 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(MinecraftInstance* instance, Resour
});
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();
}
@@ -198,12 +203,12 @@ void ExternalResourcesPage::closedImpl()
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);
}
@@ -230,17 +235,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);
}
@@ -252,7 +259,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);
}
}
@@ -260,7 +267,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;
@@ -269,8 +276,9 @@ 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;
}
}
}
@@ -294,8 +302,9 @@ void ExternalResourcesPage::removeItem()
QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
->exec();
if (response != QMessageBox::Yes)
if (response != QMessageBox::Yes) {
return;
}
}
removeItems(selection);
@@ -310,31 +319,33 @@ 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);
}
}
}
@@ -350,8 +361,8 @@ 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 hasUpdatesEnabled = hasSelection && std::ranges::any_of(selectedResources, [](Resource* resource) {
return resource->metadata() && !resource->lockUpdate();
@@ -362,21 +373,21 @@ void ExternalResourcesPage::updateActions()
const bool allSelectedUpdatesDisabled =
hasSelection && std::ranges::all_of(selectedResources, [](Resource* resource) { return resource->lockUpdate(); });
ui->actionUpdateItem->setEnabled(!m_model->empty() && !allSelectedUpdatesDisabled);
ui->actionResetItemMetadata->setEnabled(hasSelection);
m_ui->actionUpdateItem->setEnabled(!m_model->empty() && !allSelectedUpdatesDisabled);
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(),
[](Resource* resource) { return !resource->homepage().isEmpty(); }));
m_ui->actionViewHomepage->setEnabled(hasSelection && std::any_of(selectedResources.begin(), selectedResources.end(),
[](Resource* resource) { return !resource->homepage().isEmpty(); }));
ui->actionEnableUpdates->setEnabled(hasUpdatesDisabled);
ui->actionDisableUpdates->setEnabled(hasUpdatesEnabled);
ui->actionExportMetadata->setEnabled(!m_model->empty());
m_ui->actionEnableUpdates->setEnabled(hasUpdatesDisabled);
m_ui->actionDisableUpdates->setEnabled(hasUpdatesEnabled);
m_ui->actionExportMetadata->setEnabled(!m_model->empty());
}
void ExternalResourcesPage::updateFrame(const QModelIndex& current, [[maybe_unused]] const QModelIndex& previous)
@@ -384,7 +395,7 @@ void ExternalResourcesPage::updateFrame(const QModelIndex& current, [[maybe_unus
auto sourceCurrent = m_filterModel->mapToSource(current);
int row = sourceCurrent.row();
const Resource& resource = m_model->at(row);
ui->frame->updateWithResource(resource);
m_ui->frame->updateWithResource(resource);
}
QString ExternalResourcesPage::extraHeaderInfoString()
@@ -393,28 +404,30 @@ QString ExternalResourcesPage::extraHeaderInfoString()
auto enabledCount = std::ranges::count_if(all, [](Resource* res) { return res->enabled(); });
auto installedCount = m_model->size();
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 enabled, %3 selected)").arg(installedCount).arg(enabledCount).arg(count);
}
}
if (enabledCount != 0)
if (enabledCount != 0) {
return tr(" (%1 installed, %2 enabled)").arg(installedCount).arg(enabledCount);
}
return tr(" (%1 installed)").arg(installedCount);
}
void ExternalResourcesPage::enableUpdates()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection());
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection());
m_model->setUpdateLock(selection.indexes(), EnableAction::ENABLE);
updateActions();
}
void ExternalResourcesPage::disableUpdates()
{
auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection());
auto selection = m_filterModel->mapSelectionToSource(m_ui->treeView->selectionModel()->selection());
m_model->setUpdateLock(selection.indexes(), EnableAction::DISABLE);
updateActions();
}
@@ -20,14 +20,14 @@ class ExternalResourcesPage : public QMainWindow, public BasePage {
public:
explicit ExternalResourcesPage(MinecraftInstance* 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;
@@ -37,7 +37,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:
@@ -60,8 +60,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();
@@ -69,7 +69,7 @@ class ExternalResourcesPage : public QMainWindow, public BasePage {
protected:
MinecraftInstance* m_instance = nullptr;
Ui::ExternalResourcesPage* ui = nullptr;
Ui::ExternalResourcesPage* m_ui = nullptr;
ResourceFolderModel* m_model;
QSortFilterProxyModel* m_filterModel = nullptr;
+30 -30
View File
@@ -72,16 +72,16 @@
ModFolderPage::ModFolderPage(MinecraftInstance* 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, [this] { 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, [this] { updateMods(); });
m_ui->actionsToolbar->insertActionBefore(m_ui->actionAddItem, m_ui->actionUpdateItem);
auto* updateMenu = new QMenu(this);
@@ -101,32 +101,32 @@ ModFolderPage::ModFolderPage(MinecraftInstance* inst, ModFolderModel* model, QWi
ModPlatform::IndexedVersionType::Alpha });
});
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
@@ -139,7 +139,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)
@@ -253,7 +253,7 @@ void ModFolderPage::updateMods(bool includeDeps, std::vector<ModPlatform::Indexe
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, std::vector<ModPlatform::Indexe
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;
@@ -356,7 +356,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;
@@ -372,7 +372,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();
+21 -21
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()
@@ -143,7 +143,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();
@@ -196,7 +196,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;
@@ -224,7 +224,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;
+20 -20
View File
@@ -48,33 +48,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()
@@ -138,7 +138,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();
@@ -191,7 +191,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;
@@ -219,7 +219,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;
+22 -22
View File
@@ -45,35 +45,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)
@@ -81,7 +81,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()
@@ -144,7 +144,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();
@@ -197,7 +197,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;
@@ -225,7 +225,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;
+1 -1
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;
@@ -51,7 +51,7 @@ bool ResourceModel::isPackInstalled(ModPlatform::IndexedPack::Ptr pack) const
for (qsizetype i = 0; i < m_resourceList->size(); ++i) {
auto& resource = m_resourceList->at(i);
if (auto meta = resource.metadata(); meta && meta->provider == pack->provider && meta->project_id == pack->addonId) {
if (auto meta = resource.metadata(); meta && meta->provider == pack->provider && meta->projectId == pack->addonId) {
return true;
}
}
@@ -67,7 +67,7 @@ QVariant ResourceModel::getInstalledPackVersion(ModPlatform::IndexedPack::Ptr pa
for (qsizetype i = 0; i < m_resourceList->size(); ++i) {
auto& resource = m_resourceList->at(i);
if (auto meta = resource.metadata(); meta) {
if (meta->provider == pack->provider && meta->project_id == pack->addonId) {
if (meta->provider == pack->provider && meta->projectId == pack->addonId) {
return meta->version();
}
}
+5 -5
View File
@@ -46,14 +46,14 @@ class PackwizTest : public QObject {
QCOMPARE(metadata.side, ModPlatform::SideType::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::SideType::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);
}
};