From 1735814d423355b8d8a3e1448a15e36089826370 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 20 Oct 2025 01:01:10 +0300 Subject: [PATCH] add confirmation dialog Signed-off-by: Trial97 --- launcher/minecraft/mod/ModFolderModel.cpp | 82 +++++++++++++++++++---- launcher/minecraft/mod/ModFolderModel.h | 2 + 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 72ab66e61..2bcbf1fcb 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -38,8 +38,9 @@ #include "ModFolderModel.h" #include -#include +#include #include +#include #include #include #include @@ -56,6 +57,7 @@ #include "minecraft/mod/ResourceFolderModel.h" #include "minecraft/mod/tasks/LocalModParseTask.h" #include "modplatform/ModIndex.h" +#include "ui/dialogs/CustomMessageBox.h" ModFolderModel::ModFolderModel(const QDir& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent) : ResourceFolderModel(QDir(dir), instance, is_indexed, create_dir, parent) @@ -262,7 +264,7 @@ void ModFolderModel::onParseSucceeded(int ticket, QString mod_id) emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1)); } -Mod* findById(QList mods, QString modId) +Mod* findById(QSet mods, QString modId) { auto found = std::find_if(mods.begin(), mods.end(), [modId](Mod* m) { return m->mod_id() == modId; }); return found != mods.end() ? *found : nullptr; @@ -273,7 +275,8 @@ void ModFolderModel::onParseFinished() if (hasPendingParseTasks()) { return; } - auto mods = allMods(); + auto modsList = allMods(); + auto mods = QSet(modsList.begin(), modsList.end()); auto findByProjectID = [mods](QVariant modId, ModPlatform::ResourceProvider provider) -> Mod* { auto found = std::find_if(mods.begin(), mods.end(), [modId, provider](Mod* m) { @@ -311,9 +314,9 @@ void ModFolderModel::onParseFinished() } } -QList collectMods(QList mods, QHash> relation, std::set& seen) +QSet collectMods(QSet mods, QHash> relation, std::set& seen) { - QList affectedList = {}; + QSet affectedList = {}; for (auto mod : mods) { auto id = mod->mod_id(); if (seen.count(id) == 0) { @@ -341,16 +344,17 @@ QModelIndexList ModFolderModel::getAffectedMods(const QModelIndexList& indexes, return {}; QModelIndexList affectedList = {}; - auto affectedMods = selectedMods(indexes); + auto affectedModsList = selectedMods(indexes); + auto affectedMods = QSet(affectedModsList.begin(), affectedModsList.end()); std::set seen; switch (action) { case EnableAction::ENABLE: { - affectedMods << collectMods(affectedMods, m_requires, seen); + affectedMods = collectMods(affectedMods, m_requires, seen); break; } case EnableAction::DISABLE: { - affectedMods << collectMods(affectedMods, m_requiredBy, seen); + affectedMods = collectMods(affectedMods, m_requiredBy, seen); break; } case EnableAction::TOGGLE: { @@ -374,10 +378,11 @@ bool ModFolderModel::setResourceEnabled(const QModelIndexList& indexes, EnableAc return {}; QModelIndexList affectedList = {}; - auto indexedMods = selectedMods(indexes); + auto indexedModsList = selectedMods(indexes); + auto indexedMods = QSet(indexedModsList.begin(), indexedModsList.end()); - QList toEnable = {}; - QList toDisable = {}; + QSet toEnable = {}; + QSet toDisable = {}; std::set seen; switch (action) { @@ -401,11 +406,11 @@ bool ModFolderModel::setResourceEnabled(const QModelIndexList& indexes, EnableAc } } - toEnable << collectMods(toEnable, m_requires, seen); - toDisable << collectMods(toDisable, m_requiredBy, seen); + auto requiredToEnable = collectMods(toEnable, m_requires, seen); + auto requiredToDisable = collectMods(toDisable, m_requiredBy, seen); toDisable.removeIf([toEnable](Mod* m) { return toEnable.contains(m); }); - auto toList = [this](QList mods, bool shouldBeEnabled) { + auto toList = [this](QSet mods, bool shouldBeEnabled) { QModelIndexList list; for (auto mod : mods) { if (shouldBeEnabled != mod->enabled()) { @@ -416,6 +421,26 @@ bool ModFolderModel::setResourceEnabled(const QModelIndexList& indexes, EnableAc return list; }; + if (requiredToEnable.size() > 0 || requiredToDisable.size() > 0) { + auto box = CustomMessageBox::selectable( + nullptr, tr("Confirm toggle"), + tr("Toggling this mod(s) will cause changes to other mods.\n") + + (requiredToEnable.size() > 0 ? tr("%1 mod(s) will be enabled\n").arg(requiredToEnable.size()) : "") + + (requiredToDisable.size() > 0 ? tr("%1 mod(s) will be disabled\n").arg(requiredToDisable.size()) : "") + + tr("Do you want to automatically apply these related changes?\nIgnoring them may break the game."), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::No); + auto b = box->button(QMessageBox::No); + b->setText(tr("No, just toggle selected")); + auto response = box->exec(); + + if (response == QMessageBox::Yes) { + toEnable |= requiredToEnable; + toDisable |= requiredToDisable; + } else if (response == QMessageBox::Cancel) { + return false; + } + } + auto disableStatus = ResourceFolderModel::setResourceEnabled(toList(toDisable, false), EnableAction::DISABLE); auto enableStatus = ResourceFolderModel::setResourceEnabled(toList(toEnable, true), EnableAction::ENABLE); return disableStatus && enableStatus; @@ -429,11 +454,40 @@ QStringList reqToList(QSet l) } return req; } + QStringList ModFolderModel::requiresList(QString id) { return reqToList(m_requires[id]); } + QStringList ModFolderModel::requiredByList(QString id) { return reqToList(m_requiredBy[id]); } + +bool ModFolderModel::deleteResources(const QModelIndexList& indexes) +{ + auto deleteInvalid = [](QSet& mods) { + for (auto it = mods.begin(); it != mods.end();) { + auto mod = *it; + // the QFileInfo::exists is used instead of mod->fileinfo().exists + // because the later somehow caches that the file exists + if (!mod || !QFileInfo::exists(mod->fileinfo().absoluteFilePath())) { + it = mods.erase(it); + } else { + ++it; + } + } + }; + auto rsp = ResourceFolderModel::deleteResources(indexes); + for (auto mod : allMods()) { + auto id = mod->mod_id(); + deleteInvalid(m_requiredBy[id]); + deleteInvalid(m_requires[id]); + mod->setRequiredByCount(m_requiredBy[id].count()); + mod->setRequiresCount(m_requires[id].count()); + int row = m_resources_index[mod->internal_id()]; + emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1)); + } + return rsp; +} diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index e47c18405..4de875abc 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -90,6 +90,8 @@ class ModFolderModel : public ResourceFolderModel { bool isValid(); bool setResourceEnabled(const QModelIndexList& indexes, EnableAction action) override; + bool deleteResources(const QModelIndexList& indexes) override; + QModelIndexList getAffectedMods(const QModelIndexList& indexes, EnableAction action); RESOURCE_HELPERS(Mod)