summaryrefslogtreecommitdiffhomepage
path: root/options
diff options
context:
space:
mode:
Diffstat (limited to 'options')
-rw-r--r--options/base-value.cpp17
-rw-r--r--options/base-value.hpp23
-rw-r--r--options/bundle.cpp104
-rw-r--r--options/bundle.hpp33
-rw-r--r--options/connector.cpp12
-rw-r--r--options/connector.hpp14
-rw-r--r--options/defs.hpp9
-rw-r--r--options/globals.cpp23
-rw-r--r--options/globals.hpp7
-rw-r--r--options/group.cpp19
-rw-r--r--options/group.hpp2
-rw-r--r--options/metatype.cpp19
-rw-r--r--options/scoped.cpp13
-rw-r--r--options/scoped.hpp9
-rw-r--r--options/slider.cpp2
-rw-r--r--options/slider.hpp4
-rw-r--r--options/value-traits.hpp29
-rw-r--r--options/value.cpp3
-rw-r--r--options/value.hpp136
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