1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-21 00:19:29 +02:00

Fix installation of multiple mods at once

This commit is contained in:
Ivan Savenko
2024-11-19 22:15:05 +00:00
parent 00f97fb8cd
commit fef19f4846
7 changed files with 52 additions and 38 deletions

View File

@ -451,8 +451,8 @@ void CModListView::selectMod(const QModelIndex & index)
//FIXME: ensure that this is also reflected correctly in "Notes" section of mod description //FIXME: ensure that this is also reflected correctly in "Notes" section of mod description
bool hasInvalidDeps = !findInvalidDependencies(modName).empty(); bool hasInvalidDeps = !findInvalidDependencies(modName).empty();
ui->disableButton->setVisible(modStateModel->isModEnabled(mod.getID())); ui->disableButton->setVisible(modStateModel->isModInstalled(mod.getID()) && modStateModel->isModEnabled(mod.getID()));
ui->enableButton->setVisible(!modStateModel->isModEnabled(mod.getID())); ui->enableButton->setVisible(modStateModel->isModInstalled(mod.getID()) && !modStateModel->isModEnabled(mod.getID()));
ui->installButton->setVisible(mod.isAvailable() && !mod.isSubmod()); ui->installButton->setVisible(mod.isAvailable() && !mod.isSubmod());
ui->uninstallButton->setVisible(mod.isInstalled() && !mod.isSubmod()); ui->uninstallButton->setVisible(mod.isInstalled() && !mod.isSubmod());
ui->updateButton->setVisible(mod.isUpdateAvailable()); ui->updateButton->setVisible(mod.isUpdateAvailable());
@ -531,7 +531,7 @@ void CModListView::on_enableButton_clicked()
void CModListView::enableModByName(QString modName) void CModListView::enableModByName(QString modName)
{ {
manager->enableMod(modName); manager->enableMods({modName});
modModel->reloadRepositories(); modModel->reloadRepositories();
} }
@ -577,10 +577,11 @@ QStringList CModListView::getModsToInstall(QString mod)
QStringList dependencies = modStateModel->getMod(potentialToInstall).getDependencies(); QStringList dependencies = modStateModel->getMod(potentialToInstall).getDependencies();
for (const auto & dependency : dependencies) for (const auto & dependency : dependencies)
{ {
if (!processed.contains(dependency)) if (!processed.contains(dependency) && !candidates.contains(dependency))
candidates.push_back(dependency); candidates.push_back(dependency);
} }
} }
assert(result.removeDuplicates() == 0);
return result; return result;
} }
@ -900,12 +901,14 @@ void CModListView::installMods(QStringList archives)
{ {
if(modStateModel->getMod(mod).isInstalled()) if(modStateModel->getMod(mod).isInstalled())
{ {
if (modStateModel->isModEnabled(mod))
modsToEnable.push_back(mod);
manager->uninstallMod(mod); manager->uninstallMod(mod);
} }
else else
{ {
// installation of previously not present mod -> enable it // installation of previously not present mod -> enable it
if (modStateModel->isModEnabled(mod))
modsToEnable.push_back(mod); modsToEnable.push_back(mod);
} }
} }
@ -916,10 +919,7 @@ void CModListView::installMods(QStringList archives)
manager->installMod(modNames[i], archives[i]); manager->installMod(modNames[i], archives[i]);
} }
for(QString mod : modsToEnable) manager->enableMods(modsToEnable);
{
manager->enableMod(mod); // TODO: make it as a single action, so if mod 1 depends on mod 2 it would still activate
}
checkManagerErrors(); checkManagerErrors();

View File

@ -99,14 +99,22 @@ bool ModStateController::uninstallMod(QString modname)
return canUninstallMod(modname) && doUninstallMod(modname); return canUninstallMod(modname) && doUninstallMod(modname);
} }
bool ModStateController::enableMod(QString modname) bool ModStateController::enableMods(QStringList modlist)
{ {
return canEnableMod(modname) && doEnableMod(modname, true); for (const auto & modname : modlist)
if (!canEnableMod(modname))
return false;
modList->doEnableMods(modlist);
return true;
} }
bool ModStateController::disableMod(QString modname) bool ModStateController::disableMod(QString modname)
{ {
return canDisableMod(modname) && doEnableMod(modname, false); if (!canDisableMod(modname))
return false;
modList->doDisableMod(modname);
return true;
} }
bool ModStateController::canInstallMod(QString modname) bool ModStateController::canInstallMod(QString modname)
@ -170,16 +178,6 @@ bool ModStateController::canDisableMod(QString modname)
return true; return true;
} }
bool ModStateController::doEnableMod(QString mod, bool on)
{
if (on)
modList->doEnableMod(mod);
else
modList->doDisableMod(mod);
return true;
}
bool ModStateController::doInstallMod(QString modname, QString archivePath) bool ModStateController::doInstallMod(QString modname, QString archivePath)
{ {
const auto destDir = CLauncherDirs::modsPath() + QChar{'/'}; const auto destDir = CLauncherDirs::modsPath() + QChar{'/'};

View File

@ -24,7 +24,6 @@ class ModStateController : public QObject, public boost::noncopyable
std::shared_ptr<ModStateModel> modList; std::shared_ptr<ModStateModel> modList;
// check-free version of public method // check-free version of public method
bool doEnableMod(QString mod, bool on);
bool doInstallMod(QString mod, QString archivePath); bool doInstallMod(QString mod, QString archivePath);
bool doUninstallMod(QString mod); bool doUninstallMod(QString mod);
@ -47,7 +46,7 @@ public:
/// installs mod from zip archive located at archivePath /// installs mod from zip archive located at archivePath
bool installMod(QString mod, QString archivePath); bool installMod(QString mod, QString archivePath);
bool uninstallMod(QString mod); bool uninstallMod(QString mod);
bool enableMod(QString mod); bool enableMods(QStringList mod);
bool disableMod(QString mod); bool disableMod(QString mod);
bool canInstallMod(QString mod); bool canInstallMod(QString mod);

View File

@ -95,9 +95,14 @@ double ModStateModel::getInstalledModSizeMegabytes(QString modName) const
return modManager->getInstalledModSizeMegabytes(modName.toStdString()); return modManager->getInstalledModSizeMegabytes(modName.toStdString());
} }
void ModStateModel::doEnableMod(QString modname) void ModStateModel::doEnableMods(QStringList modList)
{ {
modManager->tryEnableMod(modname.toStdString()); std::vector<std::string> stdList;
for (const auto & entry : modList)
stdList.push_back(entry.toStdString());
modManager->tryEnableMods(stdList);
} }
void ModStateModel::doDisableMod(QString modname) void ModStateModel::doDisableMod(QString modname)

View File

@ -43,7 +43,7 @@ public:
bool isModUpdateAvailable(QString modName) const; bool isModUpdateAvailable(QString modName) const;
bool isModVisible(QString modName) const; bool isModVisible(QString modName) const;
void doEnableMod(QString modname); void doEnableMods(QStringList modList);
void doDisableMod(QString modname); void doDisableMod(QString modname);
bool isSubmod(QString modname); bool isSubmod(QString modname);

View File

@ -495,25 +495,35 @@ TModList ModManager::collectDependenciesRecursive(const TModID & modID) const
return result; return result;
} }
void ModManager::tryEnableMod(const TModID & modName) void ModManager::tryEnableMods(const TModList & modList)
{ {
auto requiredActiveMods = collectDependenciesRecursive(modName); TModList requiredActiveMods;
auto additionalActiveMods = getActiveMods(); TModList additionalActiveMods = getActiveMods();
for (const auto & modName : modList)
{
for (const auto & dependency : collectDependenciesRecursive(modName))
if (!vstd::contains(requiredActiveMods, dependency))
requiredActiveMods.push_back(dependency);
assert(!vstd::contains(additionalActiveMods, modName)); assert(!vstd::contains(additionalActiveMods, modName));
assert(vstd::contains(requiredActiveMods, modName));// FIXME: fails on attempt to enable broken mod / translation to other language assert(vstd::contains(requiredActiveMods, modName));// FIXME: fails on attempt to enable broken mod / translation to other language
}
ModDependenciesResolver testResolver(requiredActiveMods, *modsStorage); ModDependenciesResolver testResolver(requiredActiveMods, *modsStorage);
assert(testResolver.getBrokenMods().empty()); assert(testResolver.getBrokenMods().empty());
assert(vstd::contains(testResolver.getActiveMods(), modName));
testResolver.tryAddMods(additionalActiveMods, *modsStorage); testResolver.tryAddMods(additionalActiveMods, *modsStorage);
for (const auto & modName : modList)
{
assert(vstd::contains(testResolver.getActiveMods(), modName));
if (!vstd::contains(testResolver.getActiveMods(), modName)) if (!vstd::contains(testResolver.getActiveMods(), modName))
{ {
// FIXME: report? // FIXME: report?
return; return;
} }
}
updatePreset(testResolver); updatePreset(testResolver);
} }

View File

@ -117,6 +117,8 @@ class DLL_LINKAGE ModManager : boost::noncopyable
TModList collectDependenciesRecursive(const TModID & modID) const; TModList collectDependenciesRecursive(const TModID & modID) const;
void tryEnableMod(const TModID & modList);
public: public:
ModManager(const JsonNode & repositoryList); ModManager(const JsonNode & repositoryList);
ModManager(); ModManager();
@ -133,7 +135,7 @@ public:
void saveConfigurationState() const; void saveConfigurationState() const;
double getInstalledModSizeMegabytes(const TModID & modName) const; double getInstalledModSizeMegabytes(const TModID & modName) const;
void tryEnableMod(const TModID & modName); void tryEnableMods(const TModList & modList);
void tryDisableMod(const TModID & modName); void tryDisableMod(const TModID & modName);
}; };