summaryrefslogtreecommitdiffhomepage
path: root/options/value.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'options/value.hpp')
-rw-r--r--options/value.hpp316
1 files changed, 151 insertions, 165 deletions
diff --git a/options/value.hpp b/options/value.hpp
index 020cbeea..9a7487b8 100644
--- a/options/value.hpp
+++ b/options/value.hpp
@@ -10,226 +10,212 @@
#include "export.hpp"
-#include "compat/util.hpp"
-
-#include "connector.hpp"
#include "bundle.hpp"
#include "slider.hpp"
-#include <type_traits>
-#include <typeinfo>
-#include <typeindex>
-#include <QString>
-#include <QPointF>
-#include <QList>
-
-#define OPENTRACK_DEFINE_SLOT(t) void setValue(t datum) { store(datum); }
-#define OPENTRACK_DEFINE_SIGNAL(t) void valueChanged(t) const
-namespace options {
+#include "base-value.hpp"
+#include "value-traits.hpp"
-namespace detail {
-template<typename t> struct value_type_traits { using type = t;};
-template<> struct value_type_traits<QString> { using type = const QString&; };
-template<> struct value_type_traits<slider_value> { using type = const slider_value&; };
-template<typename u> struct value_type_traits<QList<u>>
-{
- using type = const QList<u>&;
-};
-template<typename t> using value_type_t = typename value_type_traits<t>::type;
-}
+#include <type_traits>
+#include <utility>
-class OTR_OPTIONS_EXPORT base_value : public QObject
-{
- Q_OBJECT
- friend class ::options::detail::connector;
-
- using comparator = bool(*)(const QVariant& val1, const QVariant& val2);
-public:
- QString name() const { return self_name; }
- base_value(bundle b, const QString& name, comparator cmp, std::type_index type_idx);
- ~base_value() override;
-signals:
- OPENTRACK_DEFINE_SIGNAL(double);
- OPENTRACK_DEFINE_SIGNAL(float);
- OPENTRACK_DEFINE_SIGNAL(int);
- OPENTRACK_DEFINE_SIGNAL(bool);
- OPENTRACK_DEFINE_SIGNAL(const QString&);
- OPENTRACK_DEFINE_SIGNAL(const slider_value&);
- OPENTRACK_DEFINE_SIGNAL(const QPointF&);
- OPENTRACK_DEFINE_SIGNAL(const QVariant&);
-
- OPENTRACK_DEFINE_SIGNAL(const QList<double>&);
- OPENTRACK_DEFINE_SIGNAL(const QList<float>&);
- OPENTRACK_DEFINE_SIGNAL(const QList<int>&);
- OPENTRACK_DEFINE_SIGNAL(const QList<bool>&);
- OPENTRACK_DEFINE_SIGNAL(const QList<QString>&);
- OPENTRACK_DEFINE_SIGNAL(const QList<slider_value>&);
- OPENTRACK_DEFINE_SIGNAL(const QList<QPointF>&);
-protected:
- bundle b;
- QString self_name;
- comparator cmp;
- std::type_index type_index;
-
- void store(const QVariant& datum)
- {
- b->store_kv(self_name, datum);
- }
+#include <QMetaType>
+namespace options::detail {
template<typename t>
- void store(const t& datum)
+ class dereference_wrapper final
{
- b->store_kv(self_name, QVariant::fromValue(datum));
- }
+ t x;
+ public:
+ constexpr t const* operator->() const { return &x; }
+ constexpr t* operator->() { return &x; }
+ constexpr explicit dereference_wrapper(t&& x) : x(x) {}
+ };
+} // ns options::detail
-public slots:
- OPENTRACK_DEFINE_SLOT(double)
- OPENTRACK_DEFINE_SLOT(int)
- OPENTRACK_DEFINE_SLOT(bool)
- OPENTRACK_DEFINE_SLOT(const QString&)
- OPENTRACK_DEFINE_SLOT(const slider_value&)
- OPENTRACK_DEFINE_SLOT(const QPointF&)
- OPENTRACK_DEFINE_SLOT(const QVariant&)
-
- OPENTRACK_DEFINE_SLOT(const QList<double>&)
- OPENTRACK_DEFINE_SLOT(const QList<float>&)
- OPENTRACK_DEFINE_SLOT(const QList<int>&)
- OPENTRACK_DEFINE_SLOT(const QList<bool>&)
- OPENTRACK_DEFINE_SLOT(const QList<QString>&)
- OPENTRACK_DEFINE_SLOT(const QList<slider_value>&)
- OPENTRACK_DEFINE_SLOT(const QList<QPointF>&)
-
- virtual void reload() = 0;
- virtual void bundle_value_changed() const = 0;
- virtual void set_to_default() = 0;
-};
+namespace options {
-namespace detail {
template<typename t>
-struct value_get_traits
+class value final : public value_
{
- static inline t get(const t& val, const t&)
- {
- return val;
- }
-};
+ static_assert(std::is_same_v<t, std::remove_cvref_t<t>>);
+ mutable QMutex mtx;
+ const t def;
+ mutable t cached_value;
+ using traits = detail::value_traits<t>;
-template<>
-struct value_get_traits<slider_value>
-{
- using t = slider_value;
- static inline t get(const t& val, const t& def)
+ never_inline
+ auto get() const noexcept
{
- return t(val.cur(), def.min(), def.max());
- }
-};
+ if (!b->contains(self_name))
+ return traits::pass_value(def);
-template<typename t, typename Enable = void>
-struct value_element_type
-{
- using type = typename std::remove_reference<typename std::remove_cv<t>::type>::type;
-};
+ QVariant variant = b->get_variant(self_name);
-// Qt uses int a lot in slots so use it for all enums
-template<typename t>
-struct value_element_type<t, typename std::enable_if<std::is_enum<t>::value>::type>
-{
- using type = int;
-};
+ if (variant.isNull() || !variant.isValid())
+ return traits::pass_value(def);
-template<> struct value_element_type<float, void> { using type = double; };
+ return traits::pass_value(traits::value_with_default(traits::value_from_qvariant(variant), def));
+ }
-template<typename t> using value_element_type_t = typename value_element_type<t>::type;
+ never_inline
+ void store_variant(QVariant&& value) noexcept override
+ {
+ if (traits::is_equal(get(), traits::value_from_qvariant(value)))
+ return;
-}
+ if (is_null())
+ return;
-template<typename t>
-class value final : public base_value
-{
- static bool is_equal(const QVariant& val1, const QVariant& val2)
+ if (value.isValid() && !value.isNull())
+ b->store_kv(self_name, value);
+ else
+ b->store_kv(self_name, traits::qvariant_from_value(def));
+ }
+
+ never_inline
+ void store_variant(const QVariant& value) noexcept override
{
- return val1.value<element_type>() == val2.value<element_type>();
+ QVariant copy{value};
+ store_variant(std::move(copy));
}
-public:
- using element_type = detail::value_element_type_t<t>;
+ bool is_null() const
+ {
+ return self_name.isEmpty() || b->name().isEmpty();
+ }
- OTR_NEVER_INLINE
- t operator=(const t& datum)
+public:
+ QVariant get_variant() const noexcept override
{
- const element_type tmp = static_cast<element_type>(datum);
- if (tmp != get())
- store(tmp);
- return datum;
+ if (QVariant ret{b->get_variant(self_name)}; ret.isValid() && !ret.isNull())
+ return ret;
+
+ return traits::qvariant_from_value(def);
}
- static constexpr const Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection;
- static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::QueuedConnection;
+ never_inline
+ void notify_() const override
+ {
+ auto x = get();
+ {
+ QMutexLocker l(&mtx);
+ cached_value = x;
+ }
+ maybe_trace("notify +");
+ emit valueChanged(traits::storage_from_value(x));
+ maybe_trace("notify -");
+ }
- OTR_NEVER_INLINE
- value(bundle b, const QString& name, t def) :
- base_value(b, name, &is_equal, std::type_index(typeid(element_type))), def(def)
+ never_inline
+ void notify() const override
{
- QObject::connect(b.get(), SIGNAL(reloading()),
- this, SLOT(reload()),
- DIRECT_CONNTYPE);
- if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid)
- *this = def;
+ if (is_null())
+ return;
+
+ auto x = get();
+ {
+ QMutexLocker l(&mtx);
+ if (traits::is_equal(x, cached_value))
+ {
+ //maybe_trace("notify ~");
+ return;
+ }
+ else
+ {
+ cached_value = x;
+ l.unlock();
+ maybe_trace("notify +");
+ emit valueChanged(traits::storage_from_value(x));
+ maybe_trace("notify -");
+ }
+ }
}
- OTR_NEVER_INLINE
- value(bundle b, const char* name, t def) : value(b, QString(name), def)
+ auto& operator=(t&& datum) noexcept
{
+ if (is_null())
+ return *this;
+
+ store_variant(traits::qvariant_from_value(traits::pass_value(datum)));
+ maybe_trace("set-value");
+ return *this;
}
- t default_value() const
+ auto& operator=(const t& datum) noexcept
{
- return def;
+ if (is_null())
+ return *this;
+
+ t copy{datum};
+ *this = std::move(copy);
+ return *this;
}
- OTR_NEVER_INLINE
- void set_to_default() override
+ auto& operator=(const value<t>& datum) noexcept
{
- *this = def;
+ *this = *datum;
+ return *this;
}
- OTR_NEVER_INLINE
- operator t() const { return get(); }
+ static constexpr Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection;
+ static constexpr Qt::ConnectionType SAFE_CONNTYPE = Qt::QueuedConnection;
- OTR_NEVER_INLINE
- void reload() override
+ value(bundle b, const QString& name, t def) noexcept : value_(b, name), def(std::move(def)), cached_value{get()}
{
- *this = static_cast<t>(*this);
}
- void bundle_value_changed() const override
+ //value(const value<t>& other) noexcept : value{other.b, other.self_name, other.def} {}
+ value(const value<t>&) = delete;
+
+ t default_value() const
{
- emit valueChanged(static_cast<detail::value_type_t<t>>(get()));
+ return def;
}
- OTR_NEVER_INLINE
- t operator()() const
+ void set_to_default() noexcept override
{
- return static_cast<t>(get());
+ *this = def;
}
+ operator t() const { return get(); }
+
template<typename u>
- OTR_NEVER_INLINE
- u to() const
+ explicit force_inline operator u() const { return to<u>(); }
+
+ auto operator->() const noexcept
{
- return static_cast<u>(get());
+ return detail::dereference_wrapper<t>{get()};
}
-private:
- OTR_NEVER_INLINE
- t get() const
+ force_inline auto operator()() const noexcept { return get(); }
+ force_inline auto operator*() const noexcept { return get(); }
+
+ template<typename u>
+ u to() const noexcept
{
- t val = b->contains(self_name)
- ? static_cast<t>(b->get<element_type>(self_name))
- : def;
- return detail::value_get_traits<t>::get(val, def);
+ return static_cast<u>(get());
}
-
- const t def;
};
+#if !defined OTR_OPTIONS_INST_VALUE
+# define OTR_OPTIONS_INST_VALUE OTR_TEMPLATE_IMPORT
+#endif
+
+OTR_OPTIONS_INST_VALUE(value<double>)
+OTR_OPTIONS_INST_VALUE(value<float>)
+OTR_OPTIONS_INST_VALUE(value<int>)
+OTR_OPTIONS_INST_VALUE(value<bool>)
+OTR_OPTIONS_INST_VALUE(value<QString>)
+OTR_OPTIONS_INST_VALUE(value<slider_value>)
+OTR_OPTIONS_INST_VALUE(value<QPointF>)
+OTR_OPTIONS_INST_VALUE(value<QVariant>)
+OTR_OPTIONS_INST_VALUE(value<QList<double>>)
+OTR_OPTIONS_INST_VALUE(value<QList<float>>)
+OTR_OPTIONS_INST_VALUE(value<QList<int>>)
+OTR_OPTIONS_INST_VALUE(value<QList<bool>>)
+OTR_OPTIONS_INST_VALUE(value<QList<QString>>)
+OTR_OPTIONS_INST_VALUE(value<QList<slider_value>>)
+OTR_OPTIONS_INST_VALUE(value<QList<QPointF>>)
+OTR_OPTIONS_INST_VALUE(value<QList<QVariant>>)
+
} // ns options