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:
@ -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,13 +901,15 @@ 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();
|
||||||
|
|
||||||
|
@ -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{'/'};
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -495,24 +495,34 @@ 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();
|
||||||
|
|
||||||
assert(!vstd::contains(additionalActiveMods, modName));
|
for (const auto & modName : modList)
|
||||||
assert(vstd::contains(requiredActiveMods, modName));// FIXME: fails on attempt to enable broken mod / translation to other language
|
{
|
||||||
|
for (const auto & dependency : collectDependenciesRecursive(modName))
|
||||||
|
if (!vstd::contains(requiredActiveMods, dependency))
|
||||||
|
requiredActiveMods.push_back(dependency);
|
||||||
|
|
||||||
|
assert(!vstd::contains(additionalActiveMods, modName));
|
||||||
|
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);
|
||||||
|
|
||||||
if (!vstd::contains(testResolver.getActiveMods(), modName))
|
for (const auto & modName : modList)
|
||||||
{
|
{
|
||||||
// FIXME: report?
|
assert(vstd::contains(testResolver.getActiveMods(), modName));
|
||||||
return;
|
if (!vstd::contains(testResolver.getActiveMods(), modName))
|
||||||
|
{
|
||||||
|
// FIXME: report?
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePreset(testResolver);
|
updatePreset(testResolver);
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user