diff options
-rw-r--r-- | options/bundle.cpp | 7 | ||||
-rw-r--r-- | options/bundle.hpp | 13 | ||||
-rw-r--r-- | options/connector.cpp | 71 | ||||
-rw-r--r-- | options/connector.hpp | 42 | ||||
-rw-r--r-- | options/value.hpp | 16 |
5 files changed, 143 insertions, 6 deletions
diff --git a/options/bundle.cpp b/options/bundle.cpp index fa1a214c..a080bb77 100644 --- a/options/bundle.cpp +++ b/options/bundle.cpp @@ -1,4 +1,7 @@ #include "bundle.hpp" +#include "value.hpp" + +using options::base_value; namespace options { @@ -20,6 +23,8 @@ void bundle::reload() QMutexLocker l(&mtx); saved = group(group_name); transient = saved; + + connector::notify_all_values(); } emit reloading(); } @@ -29,6 +34,8 @@ void bundle::store_kv(const QString& name, const QVariant& datum) QMutexLocker l(&mtx); transient.put(name, datum); + + connector::notify_values(name); } bool bundle::contains(const QString &name) const diff --git a/options/bundle.hpp b/options/bundle.hpp index 0283c911..841df273 100644 --- a/options/bundle.hpp +++ b/options/bundle.hpp @@ -1,9 +1,13 @@ #pragma once +#include "group.hpp" +#include "connector.hpp" + #include <memory> #include <tuple> #include <map> #include <memory> +#include <vector> #include <QObject> #include <QString> @@ -13,7 +17,6 @@ #include <QDebug> -#include "group.hpp" #include "compat/util.hpp" #include "export.hpp" @@ -21,21 +24,25 @@ namespace options { namespace detail { -class OPENTRACK_OPTIONS_EXPORT bundle final : public QObject +class OPENTRACK_OPTIONS_EXPORT bundle final : public QObject, public virtual connector { Q_OBJECT -protected: +private: QMutex mtx; const QString group_name; group saved; group transient; + bundle(const bundle&) = delete; bundle& operator=(const bundle&) = delete; + QMutex* get_mtx() override { return &mtx; } + signals: void reloading(); void saving() const; public: bundle(const QString& group_name); + ~bundle() override {} QString name() { return group_name; } void reload(); void store_kv(const QString& name, const QVariant& datum); diff --git a/options/connector.cpp b/options/connector.cpp new file mode 100644 index 00000000..4ba532d4 --- /dev/null +++ b/options/connector.cpp @@ -0,0 +1,71 @@ +#include "connector.hpp" +#include "value.hpp" + +namespace options { +namespace detail { + +connector::~connector() {} + +void connector::on_bundle_destructed(const QString& name, const base_value* val) +{ + QMutexLocker l(get_mtx()); + + auto it = connected_values.find(name); + if (it != connected_values.end()) + { + std::vector<const base_value*>& values = (*it).second; + for (auto it = values.begin(); it != values.end(); ) + { + if (*it == val) + { + values.erase(it); + break; + } + } + } +} + +void connector::on_bundle_created(const QString& name, const base_value* val) +{ + QMutexLocker l(get_mtx()); + auto it = connected_values.find(name); + + if (it != connected_values.end()) + { + std::vector<const base_value*>& values = (*it).second; + values.push_back(val); + } + else + { + std::vector<const base_value*> vec; + vec.push_back(val); + connected_values[name] = vec; + } +} + +void connector::notify_values(const QString& name) const +{ + auto it = connected_values.find(name); + if (it != connected_values.end()) + { + for (const base_value* val : (*it).second) + { + val->bundle_value_changed(); + } + } +} + +void connector::notify_all_values() const +{ + for (auto& pair : connected_values) + for (const base_value* val : pair.second) + val->bundle_value_changed(); +} + +connector::connector() +{ +} + +} + +} diff --git a/options/connector.hpp b/options/connector.hpp new file mode 100644 index 00000000..dea9fd0f --- /dev/null +++ b/options/connector.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include <map> +#include <vector> +#include <QString> +#include <QMutex> +#include <QMutexLocker> + +#include "export.hpp" + +namespace options { + +class base_value; + +namespace detail { + +class OPENTRACK_OPTIONS_EXPORT connector +{ + friend class ::options::base_value; + + std::map<QString, std::vector<const base_value*>> connected_values; + + void on_bundle_destructed(const QString& name, const base_value* val); + void on_bundle_created(const QString& name, const base_value* val); + +protected: + void notify_values(const QString& name) const; + void notify_all_values() const; + virtual QMutex* get_mtx() = 0; + +public: + connector(); + virtual ~connector(); + + connector(const connector&) = default; + connector& operator=(const connector&) = default; + connector(connector&&) = default; + connector& operator=(connector&&) = default; +}; + +} +} diff --git a/options/value.hpp b/options/value.hpp index d09924c5..4d067af1 100644 --- a/options/value.hpp +++ b/options/value.hpp @@ -1,5 +1,7 @@ #pragma once +#include "connector.hpp" + #include "bundle.hpp" #include "slider.hpp" #include <type_traits> @@ -17,7 +19,7 @@ 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<typename std::remove_const<typename std::remove_reference<u>::type>::type>&; + using type = const QList<u>&; }; template<typename t> using value_type_t = typename value_type_traits<t>::type; } @@ -27,7 +29,10 @@ class OPENTRACK_OPTIONS_EXPORT base_value : public QObject Q_OBJECT public: QString name() const { return self_name; } - base_value(bundle b, const QString& name) : b(b), self_name(name) {} + base_value(bundle b, const QString& name) : b(b), self_name(name) + { + b->on_bundle_created(name, this); + } signals: OPENTRACK_DEFINE_SIGNAL(double); OPENTRACK_DEFINE_SIGNAL(float); @@ -52,7 +57,6 @@ protected: void store(const t& datum) { b->store_kv(self_name, QVariant::fromValue(datum)); - emit valueChanged(static_cast<detail::value_type_t<t>>(datum)); } void store(float datum) @@ -77,6 +81,7 @@ public slots: OPENTRACK_DEFINE_SLOT(const QList<QPointF>&) public slots: virtual void reload() = 0; + virtual void bundle_value_changed() const = 0; }; namespace detail { @@ -159,6 +164,11 @@ public: *this = static_cast<t>(*this); } + void bundle_value_changed() const override + { + emit valueChanged(static_cast<detail::value_type_t<t>>(get())); + } + private: t def; }; |