From b932af1c97e9efa37c1555715f0dc54eea76bac3 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 11 Mar 2023 14:14:16 +0100 Subject: [PATCH] Move string and number variables to separate files --- CMakeLists.txt | 4 ++ src/utils/variable-number.hpp | 35 ++++++++++++++ src/utils/variable-number.tpp | 66 ++++++++++++++++++++++++++ src/utils/variable-string.cpp | 73 +++++++++++++++++++++++++++++ src/utils/variable-string.hpp | 37 +++++++++++++++ src/utils/variable.cpp | 88 +++++++++-------------------------- src/utils/variable.hpp | 33 ++----------- 7 files changed, 240 insertions(+), 96 deletions(-) create mode 100644 src/utils/variable-number.hpp create mode 100644 src/utils/variable-number.tpp create mode 100644 src/utils/variable-string.cpp create mode 100644 src/utils/variable-string.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 40ceca0e..ce751298 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -286,8 +286,12 @@ target_sources( src/utils/variable.hpp src/utils/variable-line-edit.cpp src/utils/variable-line-edit.hpp + src/utils/variable-number.tpp + src/utils/variable-number.hpp src/utils/variable-spinbox.cpp src/utils/variable-spinbox.hpp + src/utils/variable-string.cpp + src/utils/variable-string.hpp src/utils/variable-text-edit.cpp src/utils/variable-text-edit.hpp src/utils/volume-control.cpp diff --git a/src/utils/variable-number.hpp b/src/utils/variable-number.hpp new file mode 100644 index 00000000..4a92e93c --- /dev/null +++ b/src/utils/variable-number.hpp @@ -0,0 +1,35 @@ +#pragma once +#include "variable.hpp" + +#include + +template class NumberVariable { +public: + NumberVariable() = default; + NumberVariable(T); + + void Save(obs_data_t *obj, const char *name) const; + void Load(obs_data_t *obj, const char *name); + + T GetValue() const; + T GetFixedValue() const { return _value; } + void SetValue(T val) { _value = val; } + void SetValue(const std::weak_ptr &var) { _variable = var; } + operator T() const; + + enum class Type { FIXED_VALUE, VARIABLE }; + Type GetType() const { return _type; } + bool IsFixedType() const { return _type == Type::FIXED_VALUE; } + std::weak_ptr GetVariable() const { return _variable; } + +private: + Type _type = Type::FIXED_VALUE; + T _value = {}; + std::weak_ptr _variable; + + friend class GenericVaraiableSpinbox; + friend class VariableSpinBox; + friend class VariableDoubleSpinBox; +}; + +#include "variable-number.tpp" diff --git a/src/utils/variable-number.tpp b/src/utils/variable-number.tpp new file mode 100644 index 00000000..220ead8c --- /dev/null +++ b/src/utils/variable-number.tpp @@ -0,0 +1,66 @@ + +template class NumberVariable; +template class NumberVariable; + +template +inline NumberVariable::NumberVariable(T value) : _value(value) +{ +} + +template +void NumberVariable::Save(obs_data_t *obj, const char *name) const +{ + auto data = obs_data_create(); + if constexpr (std::is_same::value) { + obs_data_set_int(data, "value", _value); + } else if constexpr (std::is_same::value) { + obs_data_set_double(data, "value", _value); + } else { + assert(false); + } + auto var = _variable.lock(); + if (var) { + obs_data_set_string(data, "variable", var->Name().c_str()); + } + obs_data_set_int(data, "type", static_cast(_type)); + obs_data_set_obj(obj, name, data); + obs_data_release(data); +} + +template +void NumberVariable::Load(obs_data_t *obj, const char *name) +{ + auto data = obs_data_get_obj(obj, name); + if constexpr (std::is_same::value) { + _value = obs_data_get_int(data, "value"); + } else if constexpr (std::is_same::value) { + _value = obs_data_get_double(data, "value"); + } else { + assert(false); + } + auto variableName = obs_data_get_string(data, "variable"); + _variable = GetWeakVariableByName(variableName); + _type = static_cast(obs_data_get_int(data, "type")); + obs_data_release(data); +} + +template T NumberVariable::GetValue() const +{ + if (_type == Type::VARIABLE) { + auto var = _variable.lock(); + if (!var) { + return {}; + } + double value; + if (!var->DoubleValue(value)) { + return 0.0; + } + return value; + } + return _value; +} + +template NumberVariable::operator T() const +{ + return GetValue(); +} diff --git a/src/utils/variable-string.cpp b/src/utils/variable-string.cpp new file mode 100644 index 00000000..8ebb73f4 --- /dev/null +++ b/src/utils/variable-string.cpp @@ -0,0 +1,73 @@ +#include "variable-string.hpp" + +#include +#include + +void StringVariable::Resolve() +{ + if (switcher->variables.empty()) { + _resolvedValue = _value; + return; + } + if (_lastResolve == GetLastVariableChangeTime()) { + return; + } + _resolvedValue = SubstitueVariables(_value); + _lastResolve = GetLastVariableChangeTime(); +} + +StringVariable::operator std::string() +{ + Resolve(); + return _resolvedValue; +} + +StringVariable::operator QVariant() const +{ + return QVariant::fromValue(*this); +} + +void StringVariable::operator=(std::string value) +{ + _value = value; + _lastResolve = {}; +} + +void StringVariable::operator=(const char *value) +{ + _value = value; + _lastResolve = {}; +} + +void StringVariable::Load(obs_data_t *obj, const char *name) +{ + _value = obs_data_get_string(obj, name); + Resolve(); +} + +void StringVariable::Save(obs_data_t *obj, const char *name) const +{ + obs_data_set_string(obj, name, _value.c_str()); +} + +const char *StringVariable::c_str() +{ + Resolve(); + return _resolvedValue.c_str(); +} + +const char *StringVariable::c_str() const +{ + // Just assume that the value was previously resolved already + return _resolvedValue.c_str(); +} + +std::string SubstitueVariables(std::string str) +{ + for (const auto &v : switcher->variables) { + const auto &variable = std::dynamic_pointer_cast(v); + const std::string pattern = "${" + variable->Name() + "}"; + replaceAll(str, pattern, variable->Value()); + } + return str; +} diff --git a/src/utils/variable-string.hpp b/src/utils/variable-string.hpp new file mode 100644 index 00000000..43dc5517 --- /dev/null +++ b/src/utils/variable-string.hpp @@ -0,0 +1,37 @@ +#pragma once +#include "variable.hpp" + +#include +#include + +// Helper class which automatically resovles variables contained in strings +// when reading its value as a std::string + +class StringVariable { +public: + StringVariable() : _value(""){}; + StringVariable(std::string str) : _value(std::move(str)){}; + StringVariable(const char *str) : _value(str){}; + operator std::string(); + operator QVariant() const; + void operator=(std::string); + void operator=(const char *value); + const char *c_str(); + const char *c_str() const; + + const std::string &UnresolvedValue() const { return _value; } + + void Load(obs_data_t *obj, const char *name); + void Save(obs_data_t *obj, const char *name) const; + +private: + void Resolve(); + + std::string _value = ""; + std::string _resolvedValue = ""; + std::chrono::high_resolution_clock::time_point _lastResolve{}; +}; + +Q_DECLARE_METATYPE(StringVariable); + +std::string SubstitueVariables(std::string str); diff --git a/src/utils/variable.cpp b/src/utils/variable.cpp index 1c7a2f94..5e39068b 100644 --- a/src/utils/variable.cpp +++ b/src/utils/variable.cpp @@ -4,9 +4,14 @@ #include // Keep track of the last time a variable was changed to save some work when -// when resolving strings containing variables +// when resolving strings containing variables, etc. static std::chrono::high_resolution_clock::time_point lastVariableChange{}; +std::chrono::high_resolution_clock::time_point GetLastVariableChangeTime() +{ + return lastVariableChange; +} + Variable::Variable() : Item() { lastVariableChange = std::chrono::high_resolution_clock::now(); @@ -102,73 +107,13 @@ QStringList GetVariablesNameList() return list; } -void VariableResolvingString::Resolve() +std::string GetWeakVariableName(std::weak_ptr var_) { - if (switcher->variables.empty()) { - _resolvedValue = _value; - return; + auto var = var_.lock(); + if (!var) { + return "invalid variable selection"; } - if (_lastResolve == lastVariableChange) { - return; - } - _resolvedValue = SubstitueVariables(_value); - _lastResolve = lastVariableChange; -} - -VariableResolvingString::operator std::string() -{ - Resolve(); - return _resolvedValue; -} - -VariableResolvingString::operator QVariant() const -{ - return QVariant::fromValue(*this); -} - -void VariableResolvingString::operator=(std::string value) -{ - _value = value; - _lastResolve = {}; -} - -void VariableResolvingString::operator=(const char *value) -{ - _value = value; - _lastResolve = {}; -} - -void VariableResolvingString::Load(obs_data_t *obj, const char *name) -{ - _value = obs_data_get_string(obj, name); - Resolve(); -} - -void VariableResolvingString::Save(obs_data_t *obj, const char *name) const -{ - obs_data_set_string(obj, name, _value.c_str()); -} - -const char *VariableResolvingString::c_str() -{ - Resolve(); - return _resolvedValue.c_str(); -} - -const char *VariableResolvingString::c_str() const -{ - // Just assume that the value was previously resolved already - return _resolvedValue.c_str(); -} - -std::string SubstitueVariables(std::string str) -{ - for (const auto &v : switcher->variables) { - const auto &variable = std::dynamic_pointer_cast(v); - const std::string pattern = "${" + variable->Name() + "}"; - replaceAll(str, pattern, variable->Value()); - } - return str; + return var->Name(); } void SwitcherData::saveVariables(obs_data_t *obj) @@ -329,3 +274,14 @@ void VariableSelection::SetVariable(const std::string &variable) _selection->setCurrentIndex(0); } } + +void VariableSelection::SetVariable(const std::weak_ptr &variable_) +{ + const QSignalBlocker blocker(_selection); + auto var = variable_.lock(); + if (var) { + SetVariable(var->Name()); + } else { + _selection->setCurrentIndex(0); + } +} diff --git a/src/utils/variable.hpp b/src/utils/variable.hpp index 167f4aca..20559f03 100644 --- a/src/utils/variable.hpp +++ b/src/utils/variable.hpp @@ -39,41 +39,13 @@ private: friend VariableSettingsDialog; }; -// Helper class which automatically resovles variables contained in strings -// when reading its value as a std::string -class VariableResolvingString { -public: - VariableResolvingString() : _value(""){}; - VariableResolvingString(std::string str) : _value(std::move(str)){}; - VariableResolvingString(const char *str) : _value(str){}; - operator std::string(); - operator QVariant() const; - void operator=(std::string); - void operator=(const char *value); - const char *c_str(); - const char *c_str() const; - - const std::string &UnresolvedValue() const { return _value; } - - void Load(obs_data_t *obj, const char *name); - void Save(obs_data_t *obj, const char *name) const; - -private: - void Resolve(); - - std::string _value = ""; - std::string _resolvedValue = ""; - std::chrono::high_resolution_clock::time_point _lastResolve{}; -}; - -Q_DECLARE_METATYPE(VariableResolvingString); - Variable *GetVariableByName(const std::string &name); Variable *GetVariableByQString(const QString &name); std::weak_ptr GetWeakVariableByName(const std::string &name); std::weak_ptr GetWeakVariableByQString(const QString &name); QStringList GetVariablesNameList(); -std::string SubstitueVariables(std::string str); +std::string GetWeakVariableName(std::weak_ptr); +std::chrono::high_resolution_clock::time_point GetLastVariableChangeTime(); class VariableSettingsDialog : public ItemSettingsDialog { Q_OBJECT @@ -97,4 +69,5 @@ class VariableSelection : public ItemSelection { public: VariableSelection(QWidget *parent = 0); void SetVariable(const std::string &); + void SetVariable(const std::weak_ptr &); };