diff options
Diffstat (limited to 'options')
-rw-r--r-- | options/base-value.cpp | 17 | ||||
-rw-r--r-- | options/base-value.hpp | 23 | ||||
-rw-r--r-- | options/bundle.cpp | 104 | ||||
-rw-r--r-- | options/bundle.hpp | 33 | ||||
-rw-r--r-- | options/connector.cpp | 12 | ||||
-rw-r--r-- | options/connector.hpp | 14 | ||||
-rw-r--r-- | options/defs.hpp | 9 | ||||
-rw-r--r-- | options/globals.cpp | 23 | ||||
-rw-r--r-- | options/globals.hpp | 7 | ||||
-rw-r--r-- | options/group.cpp | 19 | ||||
-rw-r--r-- | options/group.hpp | 2 | ||||
-rw-r--r-- | options/metatype.cpp | 19 | ||||
-rw-r--r-- | options/scoped.cpp | 13 | ||||
-rw-r--r-- | options/scoped.hpp | 9 | ||||
-rw-r--r-- | options/slider.cpp | 2 | ||||
-rw-r--r-- | options/slider.hpp | 4 | ||||
-rw-r--r-- | options/value-traits.hpp | 29 | ||||
-rw-r--r-- | options/value.cpp | 3 | ||||
-rw-r--r-- | options/value.hpp | 136 |
19 files changed, 245 insertions, 233 deletions
diff --git a/options/base-value.cpp b/options/base-value.cpp index ec96fe6c..d4ec4b6c 100644 --- a/options/base-value.cpp +++ b/options/base-value.cpp @@ -2,7 +2,7 @@ using namespace options; -value_::value_(bundle const& b, const QString& name) : +value_::value_(bundle const& b, const QString& name) noexcept : b(b), self_name(name) { b->on_value_created(this); @@ -12,18 +12,3 @@ value_::~value_() { b->on_value_destructed(this); } - -void value_::notify() const -{ - bundle_value_changed(); -} - -namespace options::detail { - -void set_value_to_default(value_* val) -{ - val->set_to_default(); -} - -} // ns options::detail - diff --git a/options/base-value.hpp b/options/base-value.hpp index 14eaeb10..722107a4 100644 --- a/options/base-value.hpp +++ b/options/base-value.hpp @@ -9,15 +9,15 @@ #include "compat/macros.hpp" #include "value-traits.hpp" +#include <utility> + #include <QObject> #include <QString> #include <QList> #include <QPointF> #include <QVariant> -#include <utility> - -#define OTR_OPTIONS_SLOT(t) void setValue(t datum) { store_(datum); } +#define OTR_OPTIONS_SLOT(t) void setValue(t datum) noexcept { store_(datum); } #define OTR_OPTIONS_SIGNAL(t) void valueChanged(t) const namespace options { @@ -26,17 +26,14 @@ class OTR_OPTIONS_EXPORT value_ : public QObject { Q_OBJECT - friend class detail::connector; - template<typename t> using signal_sig = void(value_::*)(cv_qualified<t>) const; public: QString name() const { return self_name; } - value_(bundle const& b, const QString& name); + value_(bundle const& b, const QString& name) noexcept; ~value_() override; - // no C++17 "constexpr inline" for data declarations in MSVC template<typename t> static constexpr auto value_changed() { @@ -65,7 +62,8 @@ protected: bundle b; QString self_name; - virtual void store_variant(const QVariant& x) = 0; + virtual void store_variant(QVariant&&) noexcept = 0; + virtual void store_variant(const QVariant&) noexcept = 0; template<typename t> void store_(const t& datum) @@ -91,12 +89,9 @@ public slots: OTR_OPTIONS_SLOT(const QList<slider_value>&) OTR_OPTIONS_SLOT(const QList<QPointF>&) - virtual void bundle_value_changed() const = 0; - virtual void set_to_default() = 0; - - void notify() const; - - friend void ::options::detail::set_value_to_default(value_* val); + virtual void set_to_default() noexcept = 0; + virtual void notify() const = 0; + virtual QVariant get_variant() const noexcept = 0; }; } //ns options diff --git a/options/bundle.cpp b/options/bundle.cpp index 8db4f906..a17b04fb 100644 --- a/options/bundle.cpp +++ b/options/bundle.cpp @@ -13,22 +13,14 @@ #include <cstdlib> #include <QThread> -#include <QApplication> +#include <QCoreApplication> using namespace options; using namespace options::globals; namespace options::detail { -mutex::mutex(QMutex::RecursionMode mode) : QMutex(mode) {} - -mutex::operator QMutex*() const -{ - return const_cast<QMutex*>(static_cast<const QMutex*>(this)); -} - bundle::bundle(const QString& group_name) : - mtx(QMutex::Recursive), group_name(group_name), saved(group_name), transient(saved) @@ -37,58 +29,68 @@ bundle::bundle(const QString& group_name) : bundle::~bundle() = default; -void bundle::reload() +void bundle::reload_no_notify() +{ + if (group_name.isEmpty()) + return; + + QMutexLocker l{&mtx}; + + saved = group(group_name); + transient = saved; +} + +void bundle::notify() { - if (!group_name.isEmpty()) { QMutexLocker l(&mtx); + connector::notify_all_values(); + } - // XXX what do we do when values are and aren't equal? - // see QPointF -sh 20180830 - - // XXX we could probably skip assigning to `saved' -sh 20180830 - saved = group(group_name); - transient = saved; + emit reloading(); + emit changed(); +} +void bundle::reload() +{ + { + QMutexLocker l{&mtx}; + reload_no_notify(); connector::notify_all_values(); - emit reloading(); - emit changed(); } + emit reloading(); + emit changed(); } void bundle::set_all_to_default() { - QMutexLocker l(&mtx); - - forall([](value_* val) { - set_value_to_default(val); - }); + connector::set_all_to_default_(); } void bundle::store_kv(const QString& name, const QVariant& new_value) { - QMutexLocker l(&mtx); + if (group_name.isEmpty()) + return; - if (!group_name.isEmpty()) { - transient.put(name, new_value); - mark_ini_modified(); - + QMutexLocker l{&mtx}; + transient.put(name, new_value); connector::notify_values(name); - emit changed(); } + + emit changed(); } QVariant bundle::get_variant(const QString& name) const { - QMutexLocker l(mtx); + QMutexLocker l{&mtx}; return transient.get_variant(name); } bool bundle::contains(const QString &name) const { - QMutexLocker l(mtx); + QMutexLocker l{&mtx}; return transient.contains(name); } @@ -101,8 +103,7 @@ void bundle::save() return; { - QMutexLocker l(&mtx); - + QMutexLocker l{&mtx}; saved = transient; saved.save(); } @@ -110,7 +111,7 @@ void bundle::save() emit saving(); } -void bundler::after_profile_changed_() +void bundler::reload_no_notify_() { QMutexLocker l(&implsgl_mtx); @@ -121,16 +122,38 @@ void bundler::after_profile_changed_() if (bundle_) { //qDebug() << "bundle: reverting" << kv.first << "due to profile change"; - bundle_->reload(); + bundle_->reload_no_notify(); } } } -void bundler::refresh_all_bundles() +void bundler::notify_() { - bundler_singleton().after_profile_changed_(); + QMutexLocker l(&implsgl_mtx); + + for (auto& kv : implsgl_data) + { + weak bundle = kv.second; + shared bundle_ = bundle.lock(); + if (bundle_) + { + //qDebug() << "bundle: reverting" << kv.first << "due to profile change"; + bundle_->notify(); + } + } } +void bundler::reload_() +{ + QMutexLocker l(&implsgl_mtx); + notify_(); + reload_no_notify_(); +} + +void bundler::notify() { singleton().notify_(); } +void bundler::reload_no_notify() { singleton().reload_no_notify_(); } +void bundler::reload() { singleton().reload_(); } + bundler::bundler() = default; bundler::~bundler() = default; @@ -139,7 +162,6 @@ std::shared_ptr<bundler::v> bundler::make_bundle_(const k& key) QMutexLocker l(&implsgl_mtx); using iter = decltype(implsgl_data.cbegin()); - const iter it = implsgl_data.find(key); if (it != implsgl_data.end()) @@ -168,7 +190,7 @@ std::shared_ptr<bundler::v> bundler::make_bundle_(const k& key) return shr; } -bundler& bundler::bundler_singleton() +bundler& bundler::singleton() { static bundler ret; return ret; @@ -181,7 +203,7 @@ namespace options { std::shared_ptr<bundle_> make_bundle(const QString& name) { if (!name.isEmpty()) - return detail::bundler::bundler_singleton().make_bundle_(name); + return detail::bundler::singleton().make_bundle_(name); else return std::make_shared<bundle_>(QString()); } diff --git a/options/bundle.hpp b/options/bundle.hpp index 9ab7f74c..c1bb716d 100644 --- a/options/bundle.hpp +++ b/options/bundle.hpp @@ -29,14 +29,8 @@ #include "export.hpp" namespace options::detail { - class OTR_OPTIONS_EXPORT mutex final : public QMutex - { - public: - explicit mutex(QMutex::RecursionMode mode); - cc_noinline operator QMutex*() const; // NOLINT - }; - class bundle; + struct bundler; } // ns options::detail namespace options { @@ -51,11 +45,15 @@ class OTR_OPTIONS_EXPORT bundle final : public QObject, public connector { Q_OBJECT - mutex mtx; + friend struct bundler; + + mutable QMutex mtx { QMutex::Recursive }; const QString group_name; group saved; group transient; + void reload_no_notify(); + signals: void reloading(); void saving() const; @@ -65,7 +63,7 @@ public: bundle(const bundle&) = delete; bundle& operator=(const bundle&) = delete; - QMutex* get_mtx() const override { return mtx; } + QMutex* get_mtx() const override { return &mtx; } QString name() const { return group_name; } explicit bundle(const QString& group_name); @@ -75,6 +73,7 @@ public: bool contains(const QString& name) const; QVariant get_variant(const QString& name) const; + void notify(); public slots: void save(); @@ -89,19 +88,25 @@ struct OTR_OPTIONS_EXPORT bundler final using weak = std::weak_ptr<v>; using shared = std::shared_ptr<v>; - static void refresh_all_bundles(); + static void notify(); + static void reload_no_notify(); + + void reload(); private: QMutex implsgl_mtx { QMutex::Recursive }; std::unordered_map<k, weak> implsgl_data {}; - void after_profile_changed_(); + void notify_(); + void reload_no_notify_(); + + void reload_(); - friend OTR_OPTIONS_EXPORT + friend std::shared_ptr<v> options::make_bundle(const QString& name); - [[nodiscard]] std::shared_ptr<v> make_bundle_(const k& key); - [[nodiscard]] static bundler& bundler_singleton(); + std::shared_ptr<v> make_bundle_(const k& key); + static bundler& singleton(); bundler(); ~bundler(); diff --git a/options/connector.cpp b/options/connector.cpp index 838a2e0e..40c99a82 100644 --- a/options/connector.cpp +++ b/options/connector.cpp @@ -17,7 +17,6 @@ connector::~connector() = default; void connector::on_value_destructed(value_type val) { const QString& name = val->name(); - QMutexLocker l(get_mtx()); const auto it = connected_values.find(name); @@ -68,14 +67,21 @@ void connector::notify_values(const QString& name) const auto it = connected_values.find(name); if (it != connected_values.cend()) for (value_type val : it->second) - val->bundle_value_changed(); + val->notify(); } void connector::notify_all_values() const { for (const auto& [k, v] : connected_values) for (value_type val : v) - val->bundle_value_changed(); + val->notify(); +} + +void connector::set_all_to_default_() +{ + for (auto& pair : connected_values) + for (auto& val : pair.second) + val->set_to_default(); } } // ns options::detail diff --git a/options/connector.hpp b/options/connector.hpp index 11aa94da..e22cb20f 100644 --- a/options/connector.hpp +++ b/options/connector.hpp @@ -39,23 +39,11 @@ protected: void notify_values(const QString& name) const; void notify_all_values() const; virtual QMutex* get_mtx() const = 0; - - template<typename F> - void forall(F&& fun) - { - QMutexLocker l(get_mtx()); - - for (auto& pair : connected_values) - for (auto& val : pair.second) - fun(val); - } + void set_all_to_default_(); public: connector(); virtual ~connector(); - - connector(const connector&) = default; - connector& operator=(const connector&) = default; }; } // ns options::detail diff --git a/options/defs.hpp b/options/defs.hpp index a71a56e2..9ea4f3b3 100644 --- a/options/defs.hpp +++ b/options/defs.hpp @@ -1,11 +1,6 @@ #pragma once -#include "compat/macros.hpp" - -#include <QString> -#include <QMetaType> - -#define OPENTRACK_CONFIG_FILENAME_KEY "settings-filename" -#define OPENTRACK_DEFAULT_CONFIG "default.ini" +#define OPENTRACK_PROFILE_FILENAME_KEY "settings-filename" +#define OPENTRACK_DEFAULT_PROFILE "default.ini" diff --git a/options/globals.cpp b/options/globals.cpp index 33327090..0f0e536b 100644 --- a/options/globals.cpp +++ b/options/globals.cpp @@ -11,14 +11,15 @@ namespace options::globals::detail { ini_ctx::ini_ctx() = default; -bool is_portable_installation() +static bool is_portable_installation() { #if defined _WIN32 // must keep consistent between invocations static const bool ret = QFile::exists(OPENTRACK_BASE_PATH + "/portable.txt"); return ret; -#endif +#else return false; +#endif } saver_::~saver_() @@ -104,9 +105,9 @@ bool is_ini_modified() QString ini_filename() { return with_global_settings_object([&](QSettings& settings) { - const QString ret = settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); + const QString ret = settings.value(OPENTRACK_PROFILE_FILENAME_KEY, OPENTRACK_DEFAULT_PROFILE).toString(); if (ret.size() == 0) - return QStringLiteral(OPENTRACK_DEFAULT_CONFIG); + return QStringLiteral(OPENTRACK_DEFAULT_PROFILE); return ret; }); } @@ -116,7 +117,7 @@ QString ini_pathname() const auto dir = ini_directory(); if (dir.isEmpty()) return {}; - return dir + "/" + ini_filename(); + return dir + QStringLiteral("/") + ini_filename(); } QString ini_combine(const QString& filename) @@ -128,9 +129,9 @@ QStringList ini_list() { const auto dirname = ini_directory(); if (dirname == "") - return QStringList(); + return {}; QDir settings_dir(dirname); - QStringList list = settings_dir.entryList( QStringList { "*.ini" } , QDir::Files, QDir::Name ); + QStringList list = settings_dir.entryList( QStringList { QStringLiteral("*.ini") } , QDir::Files, QDir::Name ); std::sort(list.begin(), list.end()); return list; } @@ -142,7 +143,7 @@ void mark_ini_modified(bool value) ini.mtx.unlock(); } -QString ini_directory() +static QString ini_directory_() { QString dir; @@ -172,4 +173,10 @@ QString ini_directory() return dir; } +QString ini_directory() +{ + static const QString dir = ini_directory_(); + return dir; +} + } // ns options::globals diff --git a/options/globals.hpp b/options/globals.hpp index 8032e5d8..ae7f8e4d 100644 --- a/options/globals.hpp +++ b/options/globals.hpp @@ -29,12 +29,12 @@ struct OTR_OPTIONS_EXPORT saver_ final { ini_ctx& ctx; - cc_noinline ~saver_(); - explicit cc_noinline saver_(ini_ctx& ini); + never_inline ~saver_(); + explicit never_inline saver_(ini_ctx& ini); }; template<typename F> -cc_noinline +never_inline auto with_settings_object_(ini_ctx& ini, F&& fun) { saver_ saver { ini }; @@ -44,7 +44,6 @@ auto with_settings_object_(ini_ctx& ini, F&& fun) OTR_OPTIONS_EXPORT ini_ctx& cur_settings(); OTR_OPTIONS_EXPORT ini_ctx& global_settings(); -OTR_OPTIONS_EXPORT bool is_portable_installation(); } // ns options::globals::detail diff --git a/options/group.cpp b/options/group.cpp index af66aaf2..41655d5e 100644 --- a/options/group.cpp +++ b/options/group.cpp @@ -22,7 +22,11 @@ using namespace options::globals; group::group(const QString& name) : name(name) { - if (name == "") + constexpr unsigned reserved_buckets = 64; + kvs.reserve(reserved_buckets); + kvs.max_load_factor(0.4375); + + if (name.isEmpty()) return; with_settings_object([&](QSettings& conf) { @@ -35,7 +39,7 @@ group::group(const QString& name) : name(name) void group::save() const { - if (name == "") + if (name.isEmpty()) return; with_settings_object([&](QSettings& s) { @@ -46,12 +50,15 @@ void group::save() const }); } -void group::put(const QString &s, const QVariant &d) +void group::put(const QString& s, const QVariant& d) { - kvs[s] = d; + if (d.isNull()) + kvs.erase(s); + else + kvs[s] = d; } -bool group::contains(const QString &s) const +bool group::contains(const QString& s) const { const auto it = kvs.find(s); return it != kvs.cend(); @@ -63,7 +70,7 @@ QVariant group::get_variant(const QString& name) const if (it != kvs.cend()) return it->second; - return QVariant(); + return {}; } } // ns options::detail diff --git a/options/group.hpp b/options/group.hpp index 76bb939b..45e9353c 100644 --- a/options/group.hpp +++ b/options/group.hpp @@ -31,7 +31,7 @@ namespace options::detail { void put(const QString& s, const QVariant& d); bool contains(const QString& s) const; - cc_noinline QVariant get_variant(const QString& name) const; + never_inline QVariant get_variant(const QString& name) const; }; } // ns options::detail diff --git a/options/metatype.cpp b/options/metatype.cpp index a4629aa6..3b8ec690 100644 --- a/options/metatype.cpp +++ b/options/metatype.cpp @@ -1,4 +1,5 @@ #include <QMetaType> +#include "compat/macros.hpp" namespace options::detail { @@ -13,19 +14,15 @@ int declare_metatype_for_type(const char* str) } // ns options::detail -#define OPENTRACK_DEFINE_METATYPE2(t, ctr) \ - OPENTRACK_DEFINE_METATYPE3(t, ctr) - -#define OPENTRACK_DEFINE_METATYPE3(t, ctr) \ - OPENTRACK_DEFINE_METATYPE4(t, init_metatype_ ## ctr) - -#define OPENTRACK_DEFINE_METATYPE4(t, sym) \ - class sym { /* NOLINT */ \ - static const int dribble; \ - } sym; /* NOLINT */ \ +#define OPENTRACK_DEFINE_METATYPE2(t, sym) \ + class sym { /* NOLINT */ \ + static const int dribble; \ + }; /* NOLINT */ \ + static sym sym; \ const int sym :: dribble = ::options::detail::declare_metatype_for_type<t>(#t); -#define OPENTRACK_DEFINE_METATYPE(t) OPENTRACK_DEFINE_METATYPE2(t, __COUNTER__) +#define OPENTRACK_DEFINE_METATYPE(t) \ + OPENTRACK_DEFINE_METATYPE2(t, PP_CAT(init, __COUNTER__)) #define OPENTRACK_METATYPE_(x) OPENTRACK_DEFINE_METATYPE(x) #include "metatype.hpp" diff --git a/options/scoped.cpp b/options/scoped.cpp index 8f1ef202..ef5b94d6 100644 --- a/options/scoped.cpp +++ b/options/scoped.cpp @@ -10,17 +10,17 @@ namespace options { // XXX hack: the flag shouldn't be here as action at distance -sh 20160926 -static std::atomic_bool teardown_flag(false); -static void set_teardown_flag(bool value); +static std::atomic<bool> teardown_flag{false}; +[[nodiscard]] static bool set_teardown_flag(bool value); static void ensure_thread(); static bool is_tracker_teardown(); -static void set_teardown_flag(bool value) +static bool set_teardown_flag(bool value) { // flag being set means "opts" is about to go out of scope due to tracker stop // in this case we don't reload options. we only want to reload when cancel is pressed. ensure_thread(); - teardown_flag = value; + return teardown_flag.exchange(value); } static void ensure_thread() @@ -59,14 +59,13 @@ opts::opts(const QString &name) : b(make_bundle(name)) { } -with_tracker_teardown::with_tracker_teardown() : old_value(teardown_flag) +with_tracker_teardown::with_tracker_teardown() : old_value{set_teardown_flag(true)} { - set_teardown_flag(true); } with_tracker_teardown::~with_tracker_teardown() { - set_teardown_flag(old_value); + (void)set_teardown_flag(old_value); } } // ns options diff --git a/options/scoped.hpp b/options/scoped.hpp index 452708f4..dd7dbacf 100644 --- a/options/scoped.hpp +++ b/options/scoped.hpp @@ -6,8 +6,6 @@ #include "export.hpp" -#include <atomic> - namespace options { struct OTR_OPTIONS_EXPORT with_tracker_teardown final @@ -26,11 +24,12 @@ struct OTR_OPTIONS_EXPORT opts bundle b; - virtual ~opts(); - explicit opts(const QString& name); - opts& operator=(const opts&) = delete; opts(const opts&) = delete; + +protected: + explicit opts(const QString& name); + ~opts(); }; } diff --git a/options/slider.cpp b/options/slider.cpp index aea3c48a..b64358c1 100644 --- a/options/slider.cpp +++ b/options/slider.cpp @@ -86,7 +86,7 @@ QDataStream& operator << (QDataStream& out, const options::slider_value& v) QDebug operator << (QDebug dbg, const options::slider_value& v) { return dbg << QStringLiteral("slider_value(cur=%1, min=%2, max=%3)") - .arg(v.cur()).arg(v.min()).arg(v.max()).toUtf8().data(); + .arg(v.cur()).arg(v.min()).arg(v.max()).toUtf8().constData(); } QDataStream& operator >> (QDataStream& in, options::slider_value& v) diff --git a/options/slider.hpp b/options/slider.hpp index 1dd9ec7c..abf39685 100644 --- a/options/slider.hpp +++ b/options/slider.hpp @@ -34,11 +34,11 @@ namespace options slider_value& operator=(const slider_value& v) = default; slider_value(const slider_value& v) = default; - slider_value() : slider_value{0, 0, 0} {}; + slider_value() : slider_value{0, 0, 0} {} bool operator==(const slider_value& v) const; bool operator!=(const slider_value& v) const; - operator double() const { return cur_; } + constexpr operator double() const { return cur_; } double cur() const { return cur_; } double min() const { return min_; } double max() const { return max_; } diff --git a/options/value-traits.hpp b/options/value-traits.hpp index f5b74f73..aeb34cfa 100644 --- a/options/value-traits.hpp +++ b/options/value-traits.hpp @@ -3,12 +3,11 @@ #include "slider.hpp" #include "export.hpp" -#include <QString> - #include <cmath> -#include <cinttypes> #include <type_traits> +#include <QString> + namespace options::detail { template<typename t, typename Enable = void> @@ -46,8 +45,7 @@ struct default_value_traits return self::qvariant_from_storage(self::storage_from_value(val)); } - static constexpr inline - value_type pass_value(const value_type& x) + static constexpr value_type pass_value(const value_type& x) { if constexpr(std::is_same_v<value_type, stored_type>) return x; @@ -79,26 +77,13 @@ struct value_traits : default_value_traits<t> {}; template<> struct value_traits<double> : default_value_traits<double> { - static bool is_equal(value_type x, value_type y) - { - if (x == y) - return true; - else - { - using I = std::int64_t; - constexpr int K = 1000; - - value_type x_, y_; - - return I(std::modf(x, &x_) * K) == I(std::modf(y, &y_) * K) && - I(x_) == I(y_); - } - } + static bool is_equal(value_type x, value_type y) { return std::fabs(x - y) < 1e-6; } }; -template<> struct value_traits<float> : value_traits<float, double> +template<> +struct value_traits<float> : default_value_traits<float> { - static constexpr inline value_type pass_value(const value_type& x) { return x; } + static bool is_equal(value_type x, value_type y) { return std::fabs(x - y) < 1e-6f; } }; template<> diff --git a/options/value.cpp b/options/value.cpp index e0be69ae..81a094e6 100644 --- a/options/value.cpp +++ b/options/value.cpp @@ -1,6 +1,5 @@ // instantiate the "template class" value<t> symbols -#include "compat/linkage-macros.hpp" -#define OTR_INST_VALUE(x) OTR_TEMPLATE_EXPORT(x) +#define OTR_OPTIONS_INST_VALUE OTR_TEMPLATE_EXPORT #include "value.hpp" diff --git a/options/value.hpp b/options/value.hpp index ea180b27..940e2a15 100644 --- a/options/value.hpp +++ b/options/value.hpp @@ -35,18 +35,17 @@ namespace options::detail { namespace options { -template<typename u> +template<typename t> class value final : public value_ { - using t = remove_cvref_t<u>; + static_assert(std::is_same_v<t, remove_cvref_t<t>>); const t def; - using traits = detail::value_traits<t>; - cc_noinline - t get() const + never_inline + auto get() const noexcept { - if (self_name.isEmpty() || !b->contains(self_name)) + if (!b->contains(self_name)) return traits::pass_value(def); QVariant variant = b->get_variant(self_name); @@ -57,18 +56,9 @@ class value final : public value_ return traits::pass_value(traits::value_with_default(traits::value_from_qvariant(variant), def)); } - friend class detail::connector; - void bundle_value_changed() const override - { - if (!self_name.isEmpty()) - emit valueChanged(traits::storage_from_value(get())); - } - - void store_variant(const QVariant& value) override + never_inline + void store_variant(QVariant&& value) noexcept override { - if (self_name.isEmpty()) - return; - if (traits::is_equal(get(), traits::value_from_qvariant(value))) return; @@ -78,76 +68,110 @@ class value final : public value_ b->store_kv(self_name, traits::qvariant_from_value(def)); } + never_inline + void store_variant(const QVariant& value) noexcept override + { + QVariant copy{value}; + store_variant(std::move(copy)); + } + + bool is_null() const + { + return self_name.isEmpty() || b->name().isEmpty(); + } + public: - cc_noinline - value<u>& operator=(const t& datum) + QVariant get_variant() const noexcept override + { + if (QVariant ret{b->get_variant(self_name)}; ret.isValid() && !ret.isNull()) + return ret; + + return traits::qvariant_from_value(def); + } + + void notify() const override + { + if (!is_null()) + emit valueChanged(traits::storage_from_value(get())); + } + + auto& operator=(t&& datum) noexcept { store_variant(traits::qvariant_from_value(traits::pass_value(datum))); + return *this; + } + auto& operator=(const t& datum) noexcept + { + t copy{datum}; + *this = std::move(copy); return *this; } - static constexpr inline Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection; - static constexpr inline Qt::ConnectionType SAFE_CONNTYPE = Qt::QueuedConnection; + auto& operator=(const value<t>& datum) noexcept + { + *this = *datum; + return *this; + } + + static constexpr Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection; + static constexpr Qt::ConnectionType SAFE_CONNTYPE = Qt::QueuedConnection; - cc_noinline - value(bundle b, const QString& name, t def) : - value_(b, name), def(std::move(def)) + value(bundle b, const QString& name, t def) noexcept : value_(b, name), def(std::move(def)) { } - cc_noinline + value(const value<t>& other) noexcept : value{other.b, other.self_name, other.def} {} + t default_value() const { return def; } - cc_noinline - void set_to_default() override + void set_to_default() noexcept override { *this = def; } - operator t() const { return get(); } // NOLINT + operator t() const { return get(); } - template<typename w, typename = decltype(static_cast<w>(std::declval<t>()))> - explicit cc_forceinline operator w() const { return to<w>(); } + template<typename u> + explicit force_inline operator u() const { return to<u>(); } - auto operator->() const + auto operator->() const noexcept { - return detail::dereference_wrapper<t>{get()}; + return detail::dereference_wrapper{get()}; } - cc_forceinline t operator()() const { return get(); } - cc_forceinline t operator*() const { return get(); } + force_inline auto operator()() const noexcept { return get(); } + force_inline auto operator*() const noexcept { return get(); } - template<typename w> - w to() const + template<typename u> + u to() const noexcept { - return static_cast<w>(get()); + return static_cast<u>(get()); } }; -// some linker problems -#if !defined OTR_INST_VALUE -# define OTR_INST_VALUE OTR_TEMPLATE_IMPORT +#if !defined OTR_OPTIONS_INST_VALUE +# define OTR_OPTIONS_INST_VALUE OTR_TEMPLATE_IMPORT #endif -OTR_INST_VALUE(value<double>) -OTR_INST_VALUE(value<float>) -OTR_INST_VALUE(value<int>) -OTR_INST_VALUE(value<bool>) -OTR_INST_VALUE(value<QString>) -OTR_INST_VALUE(value<slider_value>) -OTR_INST_VALUE(value<QPointF>) -OTR_INST_VALUE(value<QVariant>) -OTR_INST_VALUE(value<QList<double>>) -OTR_INST_VALUE(value<QList<float>>) -OTR_INST_VALUE(value<QList<int>>) -OTR_INST_VALUE(value<QList<bool>>) -OTR_INST_VALUE(value<QList<QString>>) -OTR_INST_VALUE(value<QList<slider_value>>) -OTR_INST_VALUE(value<QList<QPointF>>) -OTR_INST_VALUE(value<QList<QVariant>>) +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 |