aboutsummaryrefslogtreecommitdiff
path: root/libs/installer_fomod_plus/installer/ui/FomodViewModel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/installer_fomod_plus/installer/ui/FomodViewModel.cpp')
-rw-r--r--libs/installer_fomod_plus/installer/ui/FomodViewModel.cpp746
1 files changed, 0 insertions, 746 deletions
diff --git a/libs/installer_fomod_plus/installer/ui/FomodViewModel.cpp b/libs/installer_fomod_plus/installer/ui/FomodViewModel.cpp
deleted file mode 100644
index b11674c..0000000
--- a/libs/installer_fomod_plus/installer/ui/FomodViewModel.cpp
+++ /dev/null
@@ -1,746 +0,0 @@
-#include "FomodViewModel.h"
-#include "xml/ModuleConfiguration.h"
-#include "lib/Logger.h"
-
-using GroupCallback = std::function<void(GroupRef)>;
-using PluginCallback = std::function<void(GroupRef, PluginRef)>;
-
-
-/*
---------------------------------------------------------------------------------
- Helpers
---------------------------------------------------------------------------------
-*/
-#pragma region Helpers
-
-bool isRadioLike(GroupRef group)
-{
- return group->getType() == SelectExactlyOne
- || (group->getType() == SelectAtMostOne && group->getPlugins().size() > 1);
-}
-
-bool moreThanOneSelected(GroupRef group)
-{
- auto selectedPlugins = group->getPlugins() | std::views::filter([](const auto& plugin) {
- return plugin->isSelected();
- });
- return std::ranges::distance(selectedPlugins) > 1;
-}
-
-bool anySelected(GroupRef group)
-{
- return std::ranges::any_of(group->getPlugins(), [](const auto& plugin) { return plugin->isSelected(); });
-}
-
-std::string pluginTypeEnumToString(const PluginTypeEnum type)
-{
- switch (type) {
- case PluginTypeEnum::Recommended:
- return "Recommended";
- case PluginTypeEnum::Required:
- return "Required";
- case PluginTypeEnum::Optional:
- return "Optional";
- case PluginTypeEnum::NotUsable:
- return "NotUsable";
- case PluginTypeEnum::CouldBeUsable:
- return "CouldBeUsable";
- default:
- return "Unknown";
- }
-}
-
-#pragma endregion
-
-/*
---------------------------------------------------------------------------------
- Lifecycle
---------------------------------------------------------------------------------
-*/
-#pragma region ViewModel Lifecycle
-
-/**
- * @brief FomodViewModel constructor
- *
- * @note DO NOT USE DIRECTLY. We should only use FomodViewModel::create() to create a new instance.
- * @see FomodViewModel::create
- *
- * @param organizer The organizer instance passed from the IInstaller
- * @param fomodFile The ModuleConfiguration instance created from the raw ModuleConfiguration.xml file
- * @param infoFile The FomodInfoFile instance created from the raw info.xml file
- *
- * @return A FomodViewModel instance
- */
-FomodViewModel::FomodViewModel(MOBase::IOrganizer* organizer,
- std::unique_ptr<ModuleConfiguration> fomodFile,
- std::unique_ptr<FomodInfoFile> infoFile)
- : mOrganizer(organizer), mFomodFile(std::move(fomodFile)), mInfoFile(std::move(infoFile)),
- mConditionTester(organizer),
- mInfoViewModel(std::make_shared<InfoViewModel>(mInfoFile))
-{
- mFlags = std::make_shared<FlagMap>();
-}
-
-/**
- *
- * @param organizer The organizer instance passed from the IInstaller
- * @param fomodFile The ModuleConfiguration instance created from the raw ModuleConfiguration.xml file
- * @param infoFile The FomodInfoFile instance created from the raw info.xml file
- * @return A shared pointer to the FomodViewModel instance
- */
-std::shared_ptr<FomodViewModel> FomodViewModel::create(MOBase::IOrganizer* organizer,
- std::unique_ptr<ModuleConfiguration> fomodFile,
- std::unique_ptr<FomodInfoFile> infoFile)
-{
- auto viewModel = std::make_shared<FomodViewModel>(organizer, std::move(fomodFile), std::move(infoFile));
- if (viewModel->mFlags == nullptr) {
- viewModel->mFlags = std::make_shared<FlagMap>();
- }
- viewModel->createStepViewModels();
-
- // Handle FOMODs with no steps
- if (viewModel->mSteps.empty()) {
- viewModel->mInitialized = true;
- viewModel->logMessage(INFO, "FOMOD with no steps - initialization complete");
- return viewModel;
- }
-
- viewModel->processPluginConditions(-1); // please dont judge me. ill fix this someday.
- viewModel->enforceGroupConstraints();
- viewModel->updateVisibleSteps();
- viewModel->mInitialized = true;
- viewModel->mCurrentStepIndex = viewModel->mVisibleStepIndices.front();
- viewModel->mActiveStep = viewModel->mSteps.at(viewModel->mVisibleStepIndices.front());
- viewModel->mActivePlugin = viewModel->getFirstPluginForActiveStep();
- viewModel->getActiveStep()->setVisited(true);
- viewModel->logMessage(DEBUG, "VIEWMODEL INITIALIZED");
- viewModel->logMessage(DEBUG, viewModel->toString());
- return viewModel;
-}
-#pragma endregion
-
-/*
---------------------------------------------------------------------------------
- Traversal Functions
---------------------------------------------------------------------------------
-*/
-#pragma region Traversal Functions
-
-void FomodViewModel::forEachGroup(const GroupCallback& callback) const
-{
- for (const auto& stepViewModel : mSteps) {
- for (const auto& groupViewModel : stepViewModel->getGroups()) {
- callback(groupViewModel);
- }
- }
-}
-
-void FomodViewModel::forEachPlugin(const PluginCallback& callback) const
-{
- for (const auto& stepViewModel : mSteps) {
- for (const auto& groupViewModel : stepViewModel->getGroups()) {
- for (const auto& pluginViewModel : groupViewModel->getPlugins()) {
- callback(groupViewModel, pluginViewModel);
- }
- }
- }
-}
-
-void FomodViewModel::forEachFuturePlugin(const int fromStepIndex, const PluginCallback& callback) const
-{
- for (int i = fromStepIndex + 1; i < mSteps.size(); ++i) {
- for (const auto& groupViewModel : mSteps[i]->getGroups()) {
- for (const auto& pluginViewModel : groupViewModel->getPlugins()) {
- callback(groupViewModel, pluginViewModel);
- }
- }
- }
-}
-#pragma endregion
-
-/*
---------------------------------------------------------------------------------
- Initialization
---------------------------------------------------------------------------------
-*/
-#pragma region Initializers
-void FomodViewModel::createStepViewModels()
-{
- shared_ptr_list<StepViewModel> stepViewModels;
-
- // Handle legacy FOMODs with no install steps
- if (mFomodFile->installSteps.installSteps.empty()) {
- logMessage(INFO, "No install steps found - creating default step for legacy FOMOD");
- return;
- }
-
- for (int stepIndex = 0; stepIndex < mFomodFile->installSteps.installSteps.size(); ++stepIndex) {
- const auto& installStep = mFomodFile->installSteps.installSteps[stepIndex];
- shared_ptr_list<GroupViewModel> groupViewModels;
-
- for (int groupIndex = 0; groupIndex < installStep.optionalFileGroups.groups.size(); ++groupIndex) {
- const auto& group = installStep.optionalFileGroups.groups[groupIndex];
- shared_ptr_list<PluginViewModel> pluginViewModels;
-
- for (int pluginIndex = 0; pluginIndex < group.plugins.plugins.size(); ++pluginIndex) {
- const auto& plugin = group.plugins.plugins[pluginIndex];
- auto pluginViewModel = std::make_shared<PluginViewModel>(std::make_shared<Plugin>(plugin), false, true,
- pluginIndex);
-
- pluginViewModel->setStepIndex(stepIndex);
- pluginViewModel->setGroupIndex(groupIndex);
- pluginViewModels.emplace_back(pluginViewModel); // Assuming default values for selected and enabled
- }
- auto groupViewModel = std::make_shared<GroupViewModel>(std::make_shared<Group>(group), pluginViewModels,
- groupIndex, stepIndex);
- if (groupViewModel->getType() == SelectAtMostOne && groupViewModel->getPlugins().size() > 1) {
- createNonePluginForGroup(groupViewModel);
- }
- groupViewModels.emplace_back(groupViewModel);
- }
- auto stepViewModel = std::make_shared<StepViewModel>(std::make_shared<InstallStep>(installStep),
- std::move(groupViewModels), stepIndex);
- stepViewModels.emplace_back(stepViewModel);
-
- }
- mSteps = std::move(stepViewModels);
-}
-
-void FomodViewModel::createNonePluginForGroup(GroupRef group)
-{
- const auto nonePlugin = std::make_shared<Plugin>();
- nonePlugin->name = "None";
- nonePlugin->typeDescriptor.type = PluginTypeEnum::Optional;
- const int newIndex = static_cast<int>(group->getPlugins().size());
- const auto nonePluginViewModel = std::make_shared<PluginViewModel>(nonePlugin, true, true, newIndex);
- group->addPlugin(nonePluginViewModel);
-}
-#pragma endregion
-
-/*
---------------------------------------------------------------------------------
- Group Constraints
---------------------------------------------------------------------------------
-*/
-#pragma region Group Constraints
-
-void FomodViewModel::enforceRadioGroupConstraints(GroupRef group) const
-{
- if (!isRadioLike(group)) {
- return;
- }
-
- logMessage(INFO, "Enforcing group constraints for group " + group->getName());
-
- if (group->getType() == SelectExactlyOne && group->getPlugins().size() == 1) {
- logMessage(INFO,
- "Disabling " + group->getPlugins().at(0)->getName() + " because it's the only plugin.");
- group->getPlugins().at(0)->setEnabled(false);
- }
-
- if (moreThanOneSelected(group)) {
- logMessage(ERR, "More than one plugin is selected in a SelectExactlyOne group. Deselecting all.");
- for (const auto& plugin : group->getPlugins()) {
- plugin->setSelected(false); // don't call toggle here, that'll do the radio stuff.
- }
- }
-
- if (anySelected(group)) {
- logMessage(INFO, "At least one plugin is selected. Nothing to enforce.");
- return;
- }
-
- // First, try to select the first Recommended plugin
- for (const auto& plugin : group->getPlugins()) {
- if (mConditionTester.getPluginTypeDescriptorState(plugin->getPlugin(), mFlags) == PluginTypeEnum::Recommended) {
- logMessage(INFO, "Selecting " + plugin->getName() + " because it's the first recommended plugin.");
- togglePlugin(group, plugin, true);
- return;
- }
- }
-
- // If no Recommended plugin is found, select the first one that isn't NotUsable
- for (const auto& plugin : group->getPlugins()) {
- if (mConditionTester.getPluginTypeDescriptorState(plugin->getPlugin(), mFlags) != PluginTypeEnum::NotUsable) {
- logMessage(INFO, "Selecting " + plugin->getName() + " because it's the first usable plugin.");
- togglePlugin(group, plugin, true);
- return;
- }
- }
-}
-
-void FomodViewModel::enforceSelectAllConstraint(GroupRef groupViewModel) const
-{
- if (groupViewModel->getType() != SelectAll) {
- return;
- }
-
- for (const auto& pluginViewModel : groupViewModel->getPlugins()) {
- togglePlugin(groupViewModel, pluginViewModel, true);
- pluginViewModel->setEnabled(false);
- }
-
-}
-
-void FomodViewModel::enforceSelectAtLeastOneConstraint(GroupRef group) const
-{
- if (group->getType() != SelectAtLeastOne || group->getPlugins().size() != 1) {
- return;
- }
-
- const auto plugin = group->getPlugins().front();
- if (mConditionTester.getPluginTypeDescriptorState(plugin->getPlugin(), mFlags) != PluginTypeEnum::NotUsable) {
- logMessage(DEBUG, "Selecting " + plugin->getName() + " because it's the only plugin in a SelectAtLeastOne.");
- togglePlugin(group, plugin, true);
- plugin->setEnabled(false);
- }
-}
-
-void FomodViewModel::enforceGroupConstraints() const
-{
- forEachGroup([this](const auto& groupViewModel) {
- enforceRadioGroupConstraints(groupViewModel);
- enforceSelectAllConstraint(groupViewModel);
- enforceSelectAtLeastOneConstraint(groupViewModel);
- });
-}
-
-#pragma endregion
-
-/*
---------------------------------------------------------------------------------
- Plugin Constraints
---------------------------------------------------------------------------------
-*/
-#pragma region Plugin Constraints
-
-void FomodViewModel::processPlugin(GroupRef group, PluginRef plugin) const
-{
- if (group->getType() == SelectAll) {
- return;
- }
- const auto typeDescriptor = mConditionTester.getPluginTypeDescriptorState(plugin->plugin, mFlags);
-
- if (typeDescriptor == plugin->getCurrentPluginType()) {
- return;
- }
-
- logMessage(DEBUG,
- "Plugin " + plugin->getName() + " in group " + std::to_string(group->getOwnIndex()) + " has changed type from "
- + pluginTypeEnumToString(plugin->getCurrentPluginType()) + " to " + pluginTypeEnumToString(typeDescriptor));
-
- plugin->setCurrentPluginType(typeDescriptor);
-
- const bool isOnlyPlugin = group->getPlugins().size() == 1
- && (group->getType() == SelectExactlyOne || group->getType() == SelectAtLeastOne);
-
- // check if step hasVisited, if it hasn't been, set it to unchecked if it's optional.
- const auto stepNotVisitedYet = !mSteps[group->getStepIndex()]->getHasVisited();
-
- switch (typeDescriptor) {
- case PluginTypeEnum::Recommended:
- plugin->setEnabled(true);
- if (!plugin->isSelected()) {
- togglePlugin(group, plugin, true);
- }
- break;
- case PluginTypeEnum::Required:
- plugin->setEnabled(false);
- if (!plugin->isSelected()) {
- togglePlugin(group, plugin, true);
- }
- break;
- case PluginTypeEnum::Optional:
- if (!isOnlyPlugin) {
- plugin->setEnabled(true);
- }
- // In the case where we're changing flags to make something optional from Recommended, set it back to unchecked.
- if (plugin->isSelected() & stepNotVisitedYet && group->getType() == SelectAny) {
- togglePlugin(group, plugin, false);
- }
- break;
- case PluginTypeEnum::NotUsable:
- plugin->setEnabled(false);
- if (plugin->isSelected()) {
- togglePlugin(group, plugin, false);
- }
- break;
- case PluginTypeEnum::CouldBeUsable:
- plugin->setEnabled(true);
- break;
- default: ;
- }
-}
-
-void FomodViewModel::processPluginConditions(const int fromStepIndex) const
-{
- // We only want to update plugins that haven't been seen yet. Otherwise, we could undo manual selections by the user.
- if (fromStepIndex >= 0) {
- logMessage(DEBUG, "Processing plugins from step " + std::to_string(fromStepIndex));
- forEachFuturePlugin(fromStepIndex, [this](const auto& groupViewModel, const auto& pluginViewModel) {
- processPlugin(groupViewModel, pluginViewModel);
- });
- } else {
- forEachPlugin([this](const auto& groupViewModel, const auto& pluginViewModel) {
- processPlugin(groupViewModel, pluginViewModel);
- });
- }
-}
-
-void FomodViewModel::setFlagForPluginState(PluginRef plugin) const
-{
- if (plugin->isSelected()) {
- mFlags->setFlagsForPlugin(plugin);
- } else {
- mFlags->unsetFlagsForPlugin(plugin);
- }
-}
-
-/*
- * In an exclusive group, this gets called for the deselected plugin and then the selected plugin.
- * So if we're unselecting modB to select modA, we will get calls like
- * togglePlugin(group, modB, false)
- * togglePlugin(group, modA, true)
- */
-bool FomodViewModel::togglePlugin(GroupRef group, PluginRef plugin, const bool selected) const
-{
- if (plugin->isSelected() == selected) {
- logMessage(DEBUG, "Plugin " + plugin->getName() + " is already " + (selected ? "selected" : "deselected"));
- return false;
- }
-
- // Disable other radio options first.
- if (selected && isRadioLike(group)) {
- for (const auto& otherPlugin : group->getPlugins()) {
- if (otherPlugin != plugin && plugin->isSelected()) {
- logMessage(DEBUG,
- "Deselecting " + otherPlugin->getName() + " because " + plugin->getName() + " was selected.");
- otherPlugin->setSelected(false);
- setFlagForPluginState(otherPlugin);
- }
- }
- }
-
- const auto stepIndex = group->getStepIndex();
-
- logMessage(INFO, "Toggling " + plugin->getName() + " to " + (selected ? "true" : "false"));
- plugin->setSelected(selected);
- setFlagForPluginState(plugin);
-
- if (mInitialized) {
- mActivePlugin = plugin;
- }
- processPluginConditions(stepIndex);
- updateVisibleSteps();
- return true;
-}
-
-void FomodViewModel::markManuallySet(PluginRef plugin)
-{
- plugin->manuallySet = true;
-}
-
-#pragma endregion
-
-/*
---------------------------------------------------------------------------------
- Step Constraints
---------------------------------------------------------------------------------
-*/
-#pragma region Step Constraints
-
-void FomodViewModel::updateVisibleSteps() const
-{
- mVisibleStepIndices.clear();
- mFlags->clearAll();
-
- for (int i = 0; i < mSteps.size(); ++i) {
- if (i == 0) {
- rebuildConditionFlagsForStep(i);
- }
-
- // This also depends on previous flags that may have set this particular flag.
- if (mConditionTester.isStepVisible(mFlags, mSteps[i]->getVisibilityConditions(), i, mSteps)) {
- mVisibleStepIndices.push_back(i);
- rebuildConditionFlagsForStep(i);
- }
- }
- if (mFlags->getFlagCount() > 0) {
- logMessage(DEBUG, mFlags->toString());
- }
-}
-
-void FomodViewModel::rebuildConditionFlagsForStep(const int stepIndex) const
-{
- for (const auto& group : mSteps[stepIndex]->getGroups()) {
- for (const auto& plugin : group->getPlugins()) {
- setFlagForPluginState(plugin);
- }
- }
-}
-#pragma endregion
-
-/*
---------------------------------------------------------------------------------
- Navigation/UI
---------------------------------------------------------------------------------
-*/
-#pragma region Navigation/UI
-
-void FomodViewModel::stepBack()
-{
- if (mSteps.empty()) {
- return; // No steps to move back to
- }
-
- logMessage(DEBUG, "Stepping back from step " + std::to_string(mCurrentStepIndex));
- const auto it = std::ranges::find(mVisibleStepIndices, mCurrentStepIndex);
- if (it != mVisibleStepIndices.end() && it != mVisibleStepIndices.begin()) {
- mCurrentStepIndex = *std::prev(it);
- mActiveStep = mSteps[mCurrentStepIndex];
- mActivePlugin = getFirstPluginForActiveStep();
- }
- logMessage(DEBUG, "Stepped back to step " + std::to_string(mCurrentStepIndex));
-}
-
-void FomodViewModel::stepForward()
-{
- if (mSteps.empty()) {
- return; // No steps to move forward to
- }
-
- logMessage(DEBUG, "Stepping forward from step " + std::to_string(mCurrentStepIndex));
- const auto it = std::ranges::find(mVisibleStepIndices, mCurrentStepIndex);
- if (it != mVisibleStepIndices.end() && std::next(it) != mVisibleStepIndices.end()) {
- mCurrentStepIndex = *std::next(it);
- mActiveStep = mSteps[mCurrentStepIndex];
- mActivePlugin = getFirstPluginForActiveStep();
- }
- mActiveStep->setVisited(true);
- logMessage(DEBUG, "Stepped forward to step " + std::to_string(mCurrentStepIndex));
-}
-
-bool FomodViewModel::isLastVisibleStep() const
-{
- if (mSteps.empty()) {
- return true; // Legacy FOMODs are always "last step"
- }
- return !mVisibleStepIndices.empty() && mCurrentStepIndex == mVisibleStepIndices.back();
-}
-
-bool FomodViewModel::isFirstVisibleStep() const
-{
- if (mSteps.empty()) {
- return true; // Legacy FOMODs are always "first step"
- }
- return !mVisibleStepIndices.empty() && mCurrentStepIndex == mVisibleStepIndices.front();
-}
-
-void FomodViewModel::preinstall(const std::shared_ptr<MOBase::IFileTree>& tree, const QString& fomodPath)
-{
- mFileInstaller = std::make_shared<
- FileInstaller>(mOrganizer, fomodPath, tree, std::move(mFomodFile), mFlags, mSteps);
-}
-
-
-std::string FomodViewModel::getDisplayImage() const
-{
- // if the active plugin has an image, return it
- if (mActivePlugin && !mActivePlugin->getImagePath().empty()) {
- return mActivePlugin->getImagePath();
- }
- return mCurrentStepIndex == 0 ? mFomodFile->moduleImage.path : "";
-}
-
-std::shared_ptr<PluginViewModel> FomodViewModel::getFirstPluginForActiveStep() const
-{
- if (!mActiveStep) {
- return nullptr;
- }
-
- const auto& groups = mActiveStep->getGroups();
- if (groups.empty()) {
- return nullptr;
- }
-
- const auto& plugins = groups.front()->getPlugins();
- if (plugins.empty()) {
- return nullptr;
- }
-
- return plugins.front();
-}
-#pragma endregion
-
-/*
---------------------------------------------------------------------------------
- Utility
---------------------------------------------------------------------------------
-*/
-#pragma region Utility
-std::string FomodViewModel::toString() const
-{
- std::string viewModel = "\n";
- for (const auto& step : mSteps) {
-
- const auto isVisible = std::ranges::find(mVisibleStepIndices, step->getOwnIndex()) != mVisibleStepIndices.end();
- viewModel += "Step " + std::to_string(step->getOwnIndex()) + ": " + step->getName() + "[Visible: " +
- std::to_string(isVisible) + "]\n";
-
- for (const auto& group : step->getGroups()) {
-
- viewModel += "\tGroup " + std::to_string(group->getOwnIndex()) + ": " + group->getName() + "\n";
-
- for (const auto& plugin : group->getPlugins()) {
- viewModel += "\t\tPlugin: " + plugin->getName() + "[Selected: " + (plugin->isSelected()
- ? "TRUE"
- : "FALSE") + "]\n";
- }
- }
- }
- viewModel += "\n";
- std::ostringstream oss;
- std::ranges::transform(mVisibleStepIndices,
- std::ostream_iterator<std::string>(oss, ", "),
- [](const int i) { return std::to_string(i); });
-
- std::string stepList = oss.str();
- stepList.erase(stepList.length() - 2);
-
- viewModel += "Visible Steps: [" + stepList + "]\n";
- viewModel += mFlags->toString();
- return viewModel;
-}
-
-
-void FomodViewModel::resetToDefaults()
-{
- logMessage(INFO, "Resetting all choices to author defaults");
-
- // Clear all flags first
- mFlags->clearAll();
-
- // Reset all plugins to deselected and clear visited states
- for (const auto& step : mSteps) {
- step->setVisited(false);
- for (const auto& group : step->getGroups()) {
- for (const auto& plugin : group->getPlugins()) {
- plugin->setSelected(false);
- plugin->setEnabled(true);
- plugin->manuallySet = false;
- plugin->setCurrentPluginType(PluginTypeEnum::UNKNOWN);
- }
- }
- }
-
- // Re-run the initial constraint enforcement to restore author defaults
- processPluginConditions(-1);
- enforceGroupConstraints();
- updateVisibleSteps();
-
- // Reset to first step
- mCurrentStepIndex = mVisibleStepIndices.empty() ? 0 : mVisibleStepIndices.front();
- mActiveStep = mSteps.empty() ? nullptr : mSteps.at(mCurrentStepIndex);
- mActivePlugin = getFirstPluginForActiveStep();
- if (mActiveStep) {
- mActiveStep->setVisited(true);
- }
-
- logMessage(DEBUG, "Reset complete. Current state:\n" + toString());
-}
-
-void FomodViewModel::selectFromJson(nlohmann::json json) const
-{
- const auto jsonSteps = json["steps"];
- const auto stepCount = jsonSteps.size();
-
- for (int stepIndex = 0; stepIndex < stepCount; ++stepIndex) {
-
- if (stepIndex > mSteps.size() - 1) {
- logMessage(ERR, "Step index " + std::to_string(stepIndex) + " is out of bounds.");
- continue;
- }
-
- const auto currentStep = mSteps[stepIndex];
- const auto step = jsonSteps[stepIndex];
- const auto groupCount = step["groups"].size();
-
- logMessage(DEBUG, "Selecting plugins for step " + std::to_string(stepIndex));
- logMessage(DEBUG, "There are " + std::to_string(groupCount) + " groups.");
-
- for (int groupIndex = 0; groupIndex < groupCount; ++groupIndex) {
- if (groupIndex > currentStep->getGroups().size() - 1) {
- logMessage(ERR, "Group index " + std::to_string(groupIndex) + " is out of bounds.");
- continue;
- }
-
- const auto group = step["groups"][groupIndex];
- const auto currentGroup = currentStep->getGroups()[groupIndex];
-
- for (const auto jsonPlugin : group["plugins"]) {
-
- const auto& allPlugins = currentGroup->getPlugins();
- const auto searchName = jsonPlugin.get<std::string>();
-
- logMessage(DEBUG, "Looking for plugin " + searchName);
-
- const auto currentPlugin = std::ranges::find_if(allPlugins,
- [searchName](PluginRef p) {
- return p->getName() == searchName;
- });
-
- if (currentPlugin == allPlugins.end()) {
- logMessage(DEBUG, "Plugin " + searchName + " not found in group " + currentGroup->getName());
- continue;
- }
-
- if ((*currentPlugin)->isSelected()) {
- logMessage(DEBUG, "Plugin " + searchName + " is already selected.");
- continue;
- }
- logMessage(DEBUG, "Toggle plugin " + searchName + " to selected.");
- if (!(*currentPlugin)->isEnabled()) {
- logMessage(DEBUG, "Plugin " + searchName + " is not enabled.");
- continue;
- }
- togglePlugin(currentGroup, *currentPlugin, true);
- }
-
- if (!group.contains("deselected")) {
- continue;
- }
-
- // Do the opposite of the above. For unchecked plugins, disable them.
- for (const auto jsonPlugin : group["deselected"]) {
-
- const auto& allPlugins = currentGroup->getPlugins();
- const auto searchName = jsonPlugin.get<std::string>();
-
- logMessage(DEBUG, "Looking for plugin to disable: " + searchName);
-
- const auto currentPlugin = std::ranges::find_if(allPlugins,
- [searchName](PluginRef p) {
- return p->getName() == searchName;
- });
-
- if (currentPlugin == allPlugins.end()) {
- logMessage(DEBUG, "Plugin " + searchName + " not found in group " + currentGroup->getName());
- continue;
- }
-
- if (!(*currentPlugin)->isSelected()) {
- logMessage(DEBUG, "Plugin " + searchName + " is already deselected.");
- continue;
- }
- logMessage(DEBUG, "Toggle plugin " + searchName + " to deselected.");
- if (!(*currentPlugin)->isEnabled()) {
- logMessage(DEBUG, "Plugin " + searchName + " is not enabled.");
- continue;
- }
- togglePlugin(currentGroup, *currentPlugin, false);
- (*currentPlugin)->manuallySet = true; // To preserve this state when serializing JSON.
- }
- }
- }
-}
-#pragma endregion