mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 15:40:04 +00:00
Settings variable abstract base, additional validation, and reading/writing JSON
This commit is contained in:
parent
1ad67de71b
commit
46c4dd3780
7 changed files with 408 additions and 17 deletions
|
|
@ -111,12 +111,14 @@ set(HDR_SETTINGS source/scwx/qt/settings/general_settings.hpp
|
|||
source/scwx/qt/settings/map_settings.hpp
|
||||
source/scwx/qt/settings/palette_settings.hpp
|
||||
source/scwx/qt/settings/settings_container.hpp
|
||||
source/scwx/qt/settings/settings_variable.hpp)
|
||||
source/scwx/qt/settings/settings_variable.hpp
|
||||
source/scwx/qt/settings/settings_variable_base.hpp)
|
||||
set(SRC_SETTINGS source/scwx/qt/settings/general_settings.cpp
|
||||
source/scwx/qt/settings/map_settings.cpp
|
||||
source/scwx/qt/settings/palette_settings.cpp
|
||||
source/scwx/qt/settings/settings_container.cpp
|
||||
source/scwx/qt/settings/settings_variable.cpp)
|
||||
source/scwx/qt/settings/settings_variable.cpp
|
||||
source/scwx/qt/settings/settings_variable_base.cpp)
|
||||
set(HDR_TYPES source/scwx/qt/types/qt_types.hpp
|
||||
source/scwx/qt/types/radar_product_record.hpp
|
||||
source/scwx/qt/types/text_event_key.hpp)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ namespace settings
|
|||
{
|
||||
|
||||
static const std::string logPrefix_ = "scwx::qt::settings::settings_container";
|
||||
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
||||
|
||||
template<class Container>
|
||||
class SettingsContainer<Container>::Impl
|
||||
|
|
@ -61,16 +62,29 @@ bool SettingsContainer<Container>::SetValueOrDefault(const Container& c)
|
|||
}
|
||||
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_;
|
||||
}
|
||||
|
|
@ -143,6 +157,21 @@ bool SettingsContainer<Container>::ValidateElement(const T& value) const
|
|||
(p->elementValidator_ == nullptr || p->elementValidator_(value)));
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
bool SettingsContainer<Container>::Equals(const SettingsVariableBase& o) const
|
||||
{
|
||||
// This is only ever called with SettingsContainer<Container>, so static_cast
|
||||
// is safe
|
||||
const SettingsContainer<Container>& v =
|
||||
static_cast<const SettingsContainer<Container>&>(o);
|
||||
|
||||
// Don't compare validator
|
||||
return SettingsVariable<Container>::Equals(o) &&
|
||||
p->elementDefault_ == v.p->elementDefault_ &&
|
||||
p->elementMinimum_ == v.p->elementMinimum_ &&
|
||||
p->elementMaximum_ == v.p->elementMaximum_;
|
||||
}
|
||||
|
||||
} // namespace settings
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
|
|
|
|||
|
|
@ -24,25 +24,83 @@ public:
|
|||
SettingsContainer(SettingsContainer&&) noexcept;
|
||||
SettingsContainer& operator=(SettingsContainer&&) noexcept;
|
||||
|
||||
/**
|
||||
* Sets the current value of the settings variable. If the value is out of
|
||||
* range, the value is set to the minimum or maximum. If the value fails
|
||||
* validation, the value is set to default.
|
||||
*
|
||||
* @param c Container value to set
|
||||
*
|
||||
* @return true if the value is valid, false if the value was modified.
|
||||
*/
|
||||
bool SetValueOrDefault(const Container& c) override;
|
||||
|
||||
/**
|
||||
* Validate the container value against the defined parameters of the
|
||||
* settings variable.
|
||||
*
|
||||
* @param c Container value to validate
|
||||
*
|
||||
* @return true if the value is valid, false if the value failed validation.
|
||||
*/
|
||||
bool Validate(const Container& c) const override;
|
||||
|
||||
/**
|
||||
* Validate the element value against the defined parameters of the settings
|
||||
* variable.
|
||||
*
|
||||
* @param value Element value to validate
|
||||
*
|
||||
* @return true if the value is valid, false if the value failed validation.
|
||||
*/
|
||||
bool ValidateElement(const T& value) const;
|
||||
|
||||
/**
|
||||
* Gets the default element value of the settings variable.
|
||||
*
|
||||
* @return Default element value
|
||||
*/
|
||||
T GetElementDefault() const;
|
||||
|
||||
/**
|
||||
* Sets the default element value of the settings variable.
|
||||
*
|
||||
* @param value Default element value
|
||||
*/
|
||||
void SetElementDefault(const T& value);
|
||||
|
||||
/**
|
||||
* Sets the minimum element value of the settings variable.
|
||||
*
|
||||
* @param value Minimum element value
|
||||
*/
|
||||
void SetElementMinimum(const T& value);
|
||||
|
||||
/**
|
||||
* Sets the maximum element value of the settings variable.
|
||||
*
|
||||
* @param value Maximum element value
|
||||
*/
|
||||
void SetElementMaximum(const T& value);
|
||||
|
||||
/**
|
||||
* Sets a custom validator function for each element of the settings
|
||||
* variable.
|
||||
*
|
||||
* @param validator Element validator function
|
||||
*/
|
||||
void SetElementValidator(std::function<bool(const T&)> validator);
|
||||
|
||||
protected:
|
||||
virtual bool Equals(const SettingsVariableBase& o) const override;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> p;
|
||||
};
|
||||
|
||||
#ifdef SETTINGS_CONTAINER_IMPLEMENTATION
|
||||
template class SettingsContainer<std::vector<int64_t>>;
|
||||
template class SettingsContainer<std::vector<std::int64_t>>;
|
||||
#endif
|
||||
|
||||
} // namespace settings
|
||||
|
|
|
|||
|
|
@ -3,6 +3,11 @@
|
|||
#include <scwx/qt/settings/settings_variable.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <boost/json.hpp>
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
|
|
@ -11,16 +16,16 @@ namespace settings
|
|||
{
|
||||
|
||||
static const std::string logPrefix_ = "scwx::qt::settings::settings_variable";
|
||||
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
||||
|
||||
template<class T>
|
||||
class SettingsVariable<T>::Impl
|
||||
{
|
||||
public:
|
||||
explicit Impl(const std::string& name) : name_ {name} {}
|
||||
explicit Impl() {}
|
||||
|
||||
~Impl() {}
|
||||
|
||||
const std::string name_;
|
||||
T value_ {};
|
||||
T default_ {};
|
||||
std::optional<T> staged_ {};
|
||||
|
|
@ -31,7 +36,7 @@ public:
|
|||
|
||||
template<class T>
|
||||
SettingsVariable<T>::SettingsVariable(const std::string& name) :
|
||||
p(std::make_unique<Impl>(name))
|
||||
SettingsVariableBase(name), p(std::make_unique<Impl>())
|
||||
{
|
||||
}
|
||||
template<class T>
|
||||
|
|
@ -44,9 +49,16 @@ SettingsVariable<T>&
|
|||
SettingsVariable<T>::operator=(SettingsVariable&&) noexcept = default;
|
||||
|
||||
template<class T>
|
||||
std::string SettingsVariable<T>::name() const
|
||||
inline auto FormatParameter(const T& value)
|
||||
{
|
||||
return p->name_;
|
||||
if constexpr (std::is_integral_v<T> || std::is_same_v<T, std::string>)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return fmt::join(value, ", ");
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
|
@ -81,14 +93,26 @@ bool SettingsVariable<T>::SetValueOrDefault(const T& value)
|
|||
}
|
||||
else if (p->minimum_.has_value() && value < p->minimum_)
|
||||
{
|
||||
logger_->warn("{0} less than minimum ({1} < {2}), setting to: {2}",
|
||||
name(),
|
||||
FormatParameter<T>(value),
|
||||
FormatParameter<T>(*p->minimum_));
|
||||
p->value_ = *p->minimum_;
|
||||
}
|
||||
else if (p->maximum_.has_value() && value > p->maximum_)
|
||||
{
|
||||
logger_->warn("{0} greater than maximum ({1} > {2}), setting to: {2}",
|
||||
name(),
|
||||
FormatParameter<T>(value),
|
||||
FormatParameter<T>(*p->maximum_));
|
||||
p->value_ = *p->maximum_;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger_->warn("{} validation failed ({}), setting to default: {}",
|
||||
name(),
|
||||
FormatParameter<T>(value),
|
||||
FormatParameter<T>(p->default_));
|
||||
p->value_ = p->default_;
|
||||
}
|
||||
|
||||
|
|
@ -164,6 +188,59 @@ bool SettingsVariable<T>::Validate(const T& value) const
|
|||
(p->validator_ == nullptr || p->validator_(value))); // User-validation
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool SettingsVariable<T>::ReadValue(const boost::json::object& json)
|
||||
{
|
||||
const boost::json::value* jv = json.if_contains(name());
|
||||
bool validated = false;
|
||||
|
||||
if (jv != nullptr)
|
||||
{
|
||||
try
|
||||
{
|
||||
validated = SetValueOrDefault(boost::json::value_to<T>(*jv));
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
logger_->warn("{} is invalid ({}), setting to default: {}",
|
||||
name(),
|
||||
ex.what(),
|
||||
FormatParameter<T>(p->default_));
|
||||
p->value_ = p->default_;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger_->debug("{} is not present, setting to default: {}",
|
||||
name(),
|
||||
FormatParameter<T>(p->default_));
|
||||
p->value_ = p->default_;
|
||||
}
|
||||
|
||||
return validated;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void SettingsVariable<T>::WriteValue(boost::json::object& json) const
|
||||
{
|
||||
json[name()] = boost::json::value_from<T&>(p->value_);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool SettingsVariable<T>::Equals(const SettingsVariableBase& o) const
|
||||
{
|
||||
// This is only ever called with SettingsVariable<T>, so static_cast is safe
|
||||
const SettingsVariable<T>& v = static_cast<const SettingsVariable<T>&>(o);
|
||||
|
||||
// Don't compare validator
|
||||
return SettingsVariableBase::Equals(o) && //
|
||||
p->value_ == v.p->value_ && //
|
||||
p->default_ == v.p->default_ && //
|
||||
p->staged_ == v.p->staged_ && //
|
||||
p->minimum_ == v.p->minimum_ && //
|
||||
p->maximum_ == v.p->maximum_;
|
||||
}
|
||||
|
||||
} // namespace settings
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <scwx/qt/settings/settings_variable_base.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
|
|
@ -12,7 +12,7 @@ namespace settings
|
|||
{
|
||||
|
||||
template<class T>
|
||||
class SettingsVariable
|
||||
class SettingsVariable : public SettingsVariableBase
|
||||
{
|
||||
public:
|
||||
explicit SettingsVariable(const std::string& name);
|
||||
|
|
@ -24,25 +24,120 @@ public:
|
|||
SettingsVariable(SettingsVariable&&) noexcept;
|
||||
SettingsVariable& operator=(SettingsVariable&&) noexcept;
|
||||
|
||||
std::string name() const;
|
||||
/**
|
||||
* Gets the current value of the settings variable.
|
||||
*
|
||||
* @return Current value
|
||||
*/
|
||||
T GetValue() const;
|
||||
|
||||
T GetValue() const;
|
||||
bool SetValue(const T& value);
|
||||
/**
|
||||
* Sets the current value of the settings variable.
|
||||
*
|
||||
* @param value Value to set
|
||||
*
|
||||
* @return true if the current value was set, false if the value failed
|
||||
* validation.
|
||||
*/
|
||||
bool SetValue(const T& value);
|
||||
|
||||
/**
|
||||
* Sets the current value of the settings variable. If the value is out of
|
||||
* range, the value is set to the minimum or maximum. If the value fails
|
||||
* validation, the value is set to default.
|
||||
*
|
||||
* @param value Value to set
|
||||
*
|
||||
* @return true if the value is valid, false if the value was modified.
|
||||
*/
|
||||
virtual bool SetValueOrDefault(const T& value);
|
||||
void SetValueToDefault();
|
||||
|
||||
/**
|
||||
* Sets the current value of the settings variable to default.
|
||||
*/
|
||||
void SetValueToDefault() override;
|
||||
|
||||
/**
|
||||
* Sets the staged value of the settings variable.
|
||||
*
|
||||
* @param value Value to stage
|
||||
*
|
||||
* @return true if the staged value was set, false if the value failed
|
||||
* validation.
|
||||
*/
|
||||
bool StageValue(const T& value);
|
||||
|
||||
/**
|
||||
* Sets the current value of the settings variable to the staged value.
|
||||
*/
|
||||
void Commit();
|
||||
|
||||
/**
|
||||
* Validate the value against the defined parameters of the settings
|
||||
* variable.
|
||||
*
|
||||
* @param value Value to validate
|
||||
*
|
||||
* @return true if the value is valid, false if the value failed validation.
|
||||
*/
|
||||
virtual bool Validate(const T& value) const;
|
||||
|
||||
/**
|
||||
* Gets the default value of the settings variable.
|
||||
*
|
||||
* @return Default value
|
||||
*/
|
||||
T GetDefault() const;
|
||||
|
||||
/**
|
||||
* Sets the default value of the settings variable.
|
||||
*
|
||||
* @param value Default value
|
||||
*/
|
||||
void SetDefault(const T& value);
|
||||
|
||||
/**
|
||||
* Sets the minimum value of the settings variable.
|
||||
*
|
||||
* @param value Minimum value
|
||||
*/
|
||||
void SetMinimum(const T& value);
|
||||
|
||||
/**
|
||||
* Sets the maximum value of the settings variable.
|
||||
*
|
||||
* @param value Maximum value
|
||||
*/
|
||||
void SetMaximum(const T& value);
|
||||
|
||||
/**
|
||||
* Sets a custom validator function for the settings variable.
|
||||
*
|
||||
* @param validator Validator function
|
||||
*/
|
||||
void SetValidator(std::function<bool(const T&)> validator);
|
||||
|
||||
/**
|
||||
* Reads the value from the JSON object. If the read value is out of range,
|
||||
* the value is set to the minimum or maximum. If the read value fails
|
||||
* validation, the value is set to default.
|
||||
*
|
||||
* @param json JSON object to read
|
||||
*
|
||||
* @return true if the read value is valid, false if the value was modified.
|
||||
*/
|
||||
virtual bool ReadValue(const boost::json::object& json) override;
|
||||
|
||||
/**
|
||||
* Writes the current value to the JSON object.
|
||||
*
|
||||
* @param json JSON object to write
|
||||
*/
|
||||
virtual void WriteValue(boost::json::object& json) const override;
|
||||
|
||||
protected:
|
||||
virtual bool Equals(const SettingsVariableBase& o) const override;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> p;
|
||||
|
|
@ -50,11 +145,11 @@ private:
|
|||
|
||||
#ifdef SETTINGS_VARIABLE_IMPLEMENTATION
|
||||
template class SettingsVariable<bool>;
|
||||
template class SettingsVariable<int64_t>;
|
||||
template class SettingsVariable<std::int64_t>;
|
||||
template class SettingsVariable<std::string>;
|
||||
|
||||
// Containers are not to be used directly
|
||||
template class SettingsVariable<std::vector<int64_t>>;
|
||||
template class SettingsVariable<std::vector<std::int64_t>>;
|
||||
#endif
|
||||
|
||||
} // namespace settings
|
||||
|
|
|
|||
54
scwx-qt/source/scwx/qt/settings/settings_variable_base.cpp
Normal file
54
scwx-qt/source/scwx/qt/settings/settings_variable_base.cpp
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#include <scwx/qt/settings/settings_variable_base.hpp>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
{
|
||||
namespace settings
|
||||
{
|
||||
|
||||
static const std::string logPrefix_ =
|
||||
"scwx::qt::settings::settings_variable_base";
|
||||
|
||||
class SettingsVariableBase::Impl
|
||||
{
|
||||
public:
|
||||
explicit Impl(const std::string& name) : name_ {name} {}
|
||||
|
||||
~Impl() {}
|
||||
|
||||
const std::string name_;
|
||||
};
|
||||
|
||||
SettingsVariableBase::SettingsVariableBase(const std::string& name) :
|
||||
p(std::make_unique<Impl>(name))
|
||||
{
|
||||
}
|
||||
|
||||
SettingsVariableBase::~SettingsVariableBase() = default;
|
||||
|
||||
SettingsVariableBase::SettingsVariableBase(SettingsVariableBase&&) noexcept =
|
||||
default;
|
||||
|
||||
SettingsVariableBase&
|
||||
SettingsVariableBase::operator=(SettingsVariableBase&&) noexcept = default;
|
||||
|
||||
std::string SettingsVariableBase::name() const
|
||||
{
|
||||
return p->name_;
|
||||
}
|
||||
|
||||
bool SettingsVariableBase::Equals(const SettingsVariableBase& o) const
|
||||
{
|
||||
return p->name_ == o.p->name_;
|
||||
}
|
||||
|
||||
bool operator==(const SettingsVariableBase& lhs,
|
||||
const SettingsVariableBase& rhs)
|
||||
{
|
||||
return typeid(lhs) == typeid(rhs) && lhs.Equals(rhs);
|
||||
}
|
||||
|
||||
} // namespace settings
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
76
scwx-qt/source/scwx/qt/settings/settings_variable_base.hpp
Normal file
76
scwx-qt/source/scwx/qt/settings/settings_variable_base.hpp
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
{
|
||||
namespace settings
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Settings Variable base class
|
||||
*/
|
||||
class SettingsVariableBase
|
||||
{
|
||||
protected:
|
||||
explicit SettingsVariableBase(const std::string& name);
|
||||
~SettingsVariableBase();
|
||||
|
||||
public:
|
||||
SettingsVariableBase(const SettingsVariableBase&) = delete;
|
||||
SettingsVariableBase& operator=(const SettingsVariableBase&) = delete;
|
||||
|
||||
SettingsVariableBase(SettingsVariableBase&&) noexcept;
|
||||
SettingsVariableBase& operator=(SettingsVariableBase&&) noexcept;
|
||||
|
||||
std::string name() const;
|
||||
|
||||
/**
|
||||
* Sets the current value of the settings variable to default.
|
||||
*/
|
||||
virtual void SetValueToDefault() = 0;
|
||||
|
||||
/**
|
||||
* Sets the current value of the settings variable to the staged value.
|
||||
*/
|
||||
virtual void Commit() = 0;
|
||||
|
||||
/**
|
||||
* Reads the value from the JSON object. If the read value is out of range,
|
||||
* the value is set to the minimum or maximum. If the read value fails
|
||||
* validation, the value is set to default.
|
||||
*
|
||||
* @param json JSON object to read
|
||||
*
|
||||
* @return true if the read value is valid, false if the value was modified.
|
||||
*/
|
||||
virtual bool ReadValue(const boost::json::object& json) = 0;
|
||||
|
||||
/**
|
||||
* Writes the current value to the JSON object.
|
||||
*
|
||||
* @param json JSON object to write
|
||||
*/
|
||||
virtual void WriteValue(boost::json::object& json) const = 0;
|
||||
|
||||
protected:
|
||||
friend bool operator==(const SettingsVariableBase& lhs,
|
||||
const SettingsVariableBase& rhs);
|
||||
virtual bool Equals(const SettingsVariableBase& o) const;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> p;
|
||||
};
|
||||
|
||||
bool operator==(const SettingsVariableBase& lhs,
|
||||
const SettingsVariableBase& rhs);
|
||||
|
||||
} // namespace settings
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
Loading…
Add table
Add a link
Reference in a new issue