#include #include namespace scwx::qt::settings { static const std::string logPrefix_ = "scwx::qt::settings::settings_container"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); template class SettingsContainer::Impl { public: explicit Impl() {} ~Impl() {} T elementDefault_ {}; std::optional elementMinimum_ {}; std::optional elementMaximum_ {}; std::function elementValidator_ {nullptr}; }; template SettingsContainer::SettingsContainer(const std::string& name) : SettingsVariable(name), p(std::make_unique()) { } template SettingsContainer::~SettingsContainer() = default; template SettingsContainer::SettingsContainer(SettingsContainer&&) noexcept = default; template SettingsContainer& SettingsContainer::operator=(SettingsContainer&&) noexcept = default; template bool SettingsContainer::SetValueOrDefault(const Container& c) { bool validated = true; Container validatedValues; validatedValues.reserve(c.size()); std::transform( c.cbegin(), c.cend(), std::back_inserter(validatedValues), [&](auto& value) { if (ValidateElement(value)) { return value; } else if (p->elementMinimum_.has_value() && value < p->elementMinimum_) { logger_->warn("{0} less than minimum ({1} < {2}), setting to: {2}", this->name(), value, *p->elementMinimum_); validated = false; return *p->elementMinimum_; } else if (p->elementMaximum_.has_value() && value > p->elementMaximum_) { logger_->warn( "{0} greater than maximum ({1} > {2}), setting to: {2}", this->name(), value, *p->elementMaximum_); validated = false; return *p->elementMaximum_; } else { logger_->warn("{} validation failed ({}), setting to default: {}", this->name(), value, p->elementDefault_); validated = false; return p->elementDefault_; } }); return SettingsVariable::SetValueOrDefault(validatedValues) && validated; } template SettingsContainer::T SettingsContainer::GetElementDefault() const { return p->elementDefault_; } template void SettingsContainer::SetElementDefault(const T& value) { p->elementDefault_ = value; } template void SettingsContainer::SetElementMinimum(const T& value) { p->elementMinimum_ = value; } template void SettingsContainer::SetElementMaximum(const T& value) { p->elementMaximum_ = value; } template void SettingsContainer::SetElementValidator( std::function validator) { p->elementValidator_ = validator; } template bool SettingsContainer::Validate(const Container& c) const { if (!SettingsVariable::Validate(c)) { return false; } for (auto& element : c) { if (!ValidateElement(element)) { return false; } } return true; } template bool SettingsContainer::ValidateElement(const T& value) const { return ( // Validate minimum (!p->elementMinimum_.has_value() || value >= p->elementMinimum_) && // Validate maximum (!p->elementMaximum_.has_value() || value <= p->elementMaximum_) && // User-validation (p->elementValidator_ == nullptr || p->elementValidator_(value))); } template bool SettingsContainer::Equals(const SettingsVariableBase& o) const { // This is only ever called with SettingsContainer, so static_cast // is safe const SettingsContainer& v = static_cast&>(o); // Don't compare validator return SettingsVariable::Equals(o) && p->elementDefault_ == v.p->elementDefault_ && p->elementMinimum_ == v.p->elementMinimum_ && p->elementMaximum_ == v.p->elementMaximum_; } template class SettingsContainer>; } // namespace scwx::qt::settings