summaryrefslogtreecommitdiffhomepage
path: root/options
diff options
context:
space:
mode:
authorStanisław Halik <sthalik@misaki.pl>2017-05-14 16:22:09 +0200
committerGitHub <noreply@github.com>2017-05-14 16:22:09 +0200
commit5c23666b58bb1dd4aea15c0d62a2f716d5be7f52 (patch)
treee6497e9b55c073be209ec673ef05e62bf57a2c8f /options
parent4701dd3b0c8323a11cf7d5ad09c579a9864a41bd (diff)
parentc392181211b245e74292424500265323c960c1aa (diff)
Merge branch 'unstable' into unstable
Diffstat (limited to 'options')
-rw-r--r--options/CMakeLists.txt1
-rw-r--r--options/base-value.cpp27
-rw-r--r--options/base-value.hpp85
-rw-r--r--options/bundle.cpp28
-rw-r--r--options/bundle.hpp3
-rw-r--r--options/connector.cpp7
-rw-r--r--options/group.cpp99
-rw-r--r--options/group.hpp35
-rw-r--r--options/scoped.cpp2
-rw-r--r--options/tie.hpp17
-rw-r--r--options/value-traits.hpp50
-rw-r--r--options/value.cpp35
-rw-r--r--options/value.hpp166
13 files changed, 334 insertions, 221 deletions
diff --git a/options/CMakeLists.txt b/options/CMakeLists.txt
index cbebeb87..0c4b53a5 100644
--- a/options/CMakeLists.txt
+++ b/options/CMakeLists.txt
@@ -2,3 +2,4 @@ otr_module(options NO-COMPAT BIN)
if(NOT WIN32 AND NOT APPLE)
target_link_libraries(opentrack-options rt)
endif()
+target_link_libraries(opentrack-options opentrack-compat)
diff --git a/options/base-value.cpp b/options/base-value.cpp
new file mode 100644
index 00000000..29f4b496
--- /dev/null
+++ b/options/base-value.cpp
@@ -0,0 +1,27 @@
+#include "base-value.hpp"
+
+using namespace options;
+
+base_value::base_value(bundle b, const QString& name, base_value::comparator cmp, std::type_index type_idx) :
+ b(b),
+ self_name(name),
+ cmp(cmp),
+ type_index(type_idx)
+{
+ b->on_value_created(name, this);
+}
+
+base_value::~base_value()
+{
+ b->on_value_destructed(self_name, this);
+}
+
+void base_value::store(const QVariant& datum)
+{
+ b->store_kv(self_name, datum);
+}
+
+void ::options::detail::set_base_value_to_default(base_value* val)
+{
+ val->set_to_default();
+}
diff --git a/options/base-value.hpp b/options/base-value.hpp
new file mode 100644
index 00000000..4f90e3fc
--- /dev/null
+++ b/options/base-value.hpp
@@ -0,0 +1,85 @@
+#pragma once
+
+#include "bundle.hpp"
+#include "slider.hpp"
+#include "connector.hpp"
+
+#include "export.hpp"
+
+#include <QObject>
+#include <QString>
+#include <QList>
+#include <QPointF>
+#include <QVariant>
+
+#include <typeindex>
+
+#define OPENTRACK_DEFINE_SLOT(t) void setValue(t datum) { store(datum); }
+#define OPENTRACK_DEFINE_SIGNAL(t) void valueChanged(t) const
+
+namespace options {
+
+class OTR_OPTIONS_EXPORT base_value : public QObject
+{
+ Q_OBJECT
+ friend class 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);
+
+ template<typename t>
+ void store(const t& datum)
+ {
+ b->store_kv(self_name, QVariant::fromValue(datum));
+ }
+
+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;
+};
+
+} //ns options
diff --git a/options/bundle.cpp b/options/bundle.cpp
index 43f4a8e3..c78df274 100644
--- a/options/bundle.cpp
+++ b/options/bundle.cpp
@@ -31,12 +31,12 @@ bundle::~bundle()
{
}
-void bundle::reload(std::shared_ptr<QSettings> settings)
+void bundle::reload()
{
if (group_name.size())
{
QMutexLocker l(&mtx);
- saved = group(group_name, settings);
+ saved = group(group_name);
const bool has_changes = is_modified();
transient = saved;
@@ -51,7 +51,12 @@ void bundle::reload(std::shared_ptr<QSettings> settings)
void bundle::set_all_to_default()
{
+ QMutexLocker l(&mtx);
+
forall([](const QString&, base_value* val) { set_base_value_to_default(val); });
+
+ if (is_modified())
+ group::mark_ini_modified();
}
void bundle::store_kv(const QString& name, const QVariant& datum)
@@ -72,10 +77,10 @@ bool bundle::contains(const QString &name) const
return transient.contains(name);
}
-void bundle::save_deferred(QSettings& s)
+void bundle::save()
{
if (QThread::currentThread() != qApp->thread())
- qCritical() << "group::save - current thread not ui thread";
+ qDebug() << "group::save - current thread not ui thread";
if (group_name.size() == 0)
return;
@@ -84,12 +89,13 @@ void bundle::save_deferred(QSettings& s)
{
QMutexLocker l(&mtx);
+
if (is_modified())
{
//qDebug() << "bundle" << group_name << "changed, saving";
modified_ = true;
saved = transient;
- saved.save_deferred(s);
+ saved.save();
}
}
@@ -97,11 +103,6 @@ void bundle::save_deferred(QSettings& s)
emit saving();
}
-void bundle::save()
-{
- save_deferred(*group::ini_file());
-}
-
bool bundle::is_modified() const
{
QMutexLocker l(mtx);
@@ -119,8 +120,7 @@ bool bundle::is_modified() const
for (const auto& kv : saved.kvs)
{
- const QVariant other = transient.get<QVariant>(kv.first);
- if (!transient.contains(kv.first) || !is_equal(kv.first, kv.second, other))
+ if (!transient.contains(kv.first))
{
//if (logspam)
// qDebug() << "bundle" << group_name << "modified" << "key" << kv.first << "-" << other << "<>" << kv.second;
@@ -135,8 +135,6 @@ void bundler::after_profile_changed_()
{
QMutexLocker l(&implsgl_mtx);
- std::shared_ptr<QSettings> s = group::ini_file();
-
for (auto& kv : implsgl_data)
{
weak bundle = kv.second;
@@ -144,7 +142,7 @@ void bundler::after_profile_changed_()
if (bundle_)
{
//qDebug() << "bundle: reverting" << kv.first << "due to profile change";
- bundle_->reload(s);
+ bundle_->reload();
}
}
}
diff --git a/options/bundle.hpp b/options/bundle.hpp
index f05999a7..63ee82d0 100644
--- a/options/bundle.hpp
+++ b/options/bundle.hpp
@@ -81,8 +81,7 @@ public:
}
public slots:
void save();
- void reload(std::shared_ptr<QSettings> settings = group::ini_file());
- void save_deferred(QSettings& s);
+ void reload();
void set_all_to_default();
};
diff --git a/options/connector.cpp b/options/connector.cpp
index 63d70ca7..075a57e1 100644
--- a/options/connector.cpp
+++ b/options/connector.cpp
@@ -83,11 +83,12 @@ void connector::on_value_created(const QString& name, value_type val)
QMutexLocker l(get_mtx());
- if (on_value_destructed_impl(name, val))
+ int i = 1;
+ while (on_value_destructed_impl(name, val))
{
qWarning() << "options/connector: value created twice;"
- << "bundle"
- << val->b->name()
+ << "cnt" << i++
+ << "bundle" << val->b->name()
<< "value-name" << name
<< "value-ptr" << quintptr(val);
}
diff --git a/options/group.cpp b/options/group.cpp
index 9a4bd912..60e8a7b4 100644
--- a/options/group.cpp
+++ b/options/group.cpp
@@ -8,46 +8,49 @@
#include "group.hpp"
#include "defs.hpp"
+
+#include "compat/timer.hpp"
+
+#include <cmath>
+
#include <QStandardPaths>
#include <QDir>
-
#include <QDebug>
namespace options {
-group::group(const QString& name, std::shared_ptr<QSettings> conf) : name(name)
+group::group(const QString& name) : name(name)
{
if (name == "")
return;
- conf->beginGroup(name);
- for (auto& k_ : conf->childKeys())
- {
- auto tmp = k_.toUtf8();
- QString k(tmp);
- kvs[k] = conf->value(k_);
- }
- conf->endGroup();
-}
-
-group::group(const QString& name) : group(name, ini_file())
-{
+ with_settings_object([&](QSettings& conf) {
+ conf.beginGroup(name);
+ for (auto& k_ : conf.childKeys())
+ {
+ auto tmp = k_.toUtf8();
+ QString k(tmp);
+ QVariant val = conf.value(k_);
+ if (val.type() != QVariant::Invalid)
+ kvs[k] = std::move(val);
+ }
+ conf.endGroup();
+ });
}
void group::save() const
{
- save_deferred(*ini_file());
-}
-
-void group::save_deferred(QSettings& s) const
-{
if (name == "")
return;
- s.beginGroup(name);
- for (auto& i : kvs)
- s.setValue(i.first, i.second);
- s.endGroup();
+ with_settings_object([&](QSettings& s) {
+ s.beginGroup(name);
+ for (auto& i : kvs)
+ s.setValue(i.first, i.second);
+ s.endGroup();
+
+ mark_ini_modified();
+ });
}
void group::put(const QString &s, const QVariant &d)
@@ -103,12 +106,52 @@ QStringList group::ini_list()
return list;
}
-std::shared_ptr<QSettings> group::ini_file()
+void group::mark_ini_modified()
+{
+ QMutexLocker l(&cur_ini_mtx);
+ ini_modifiedp = true;
+}
+
+QString group::cur_ini_pathname;
+std::shared_ptr<QSettings> group::cur_ini;
+QMutex group::cur_ini_mtx(QMutex::Recursive);
+int group::ini_refcount = 0;
+bool group::ini_modifiedp = false;
+
+std::shared_ptr<QSettings> group::cur_settings_object()
{
- const auto pathname = ini_pathname();
- if (pathname != "")
- return std::make_shared<QSettings>(ini_pathname(), QSettings::IniFormat);
- return std::make_shared<QSettings>();
+ const QString pathname = ini_pathname();
+
+ if (pathname.isEmpty())
+ return std::make_shared<QSettings>();
+
+ QMutexLocker l(&cur_ini_mtx);
+
+ if (pathname != cur_ini_pathname)
+ {
+ cur_ini = std::make_shared<QSettings>(pathname, QSettings::IniFormat);
+ cur_ini_pathname = pathname;
+ }
+
+ return cur_ini;
}
+group::saver_::~saver_()
+{
+ if (--ini_refcount == 0 && ini_modifiedp)
+ {
+ ini_modifiedp = false;
+ static Timer t;
+ const double tm = t.elapsed_seconds();
+ qDebug() << QStringLiteral("%1.%2").arg(int(tm)).arg(int(std::fmod(tm, 1.)*10)).toLatin1().data()
+ << "saving .ini file" << cur_ini_pathname;
+ s.sync();
+ }
}
+
+group::saver_::saver_(QSettings& s, QMutex& mtx) : s(s), mtx(mtx), lck(&mtx)
+{
+ ini_refcount++;
+}
+
+} // ns options
diff --git a/options/group.hpp b/options/group.hpp
index e2a8058c..b0e13a6a 100644
--- a/options/group.hpp
+++ b/options/group.hpp
@@ -1,13 +1,16 @@
#pragma once
#include "export.hpp"
+
#include "compat/util.hpp"
+
#include <map>
#include <memory>
#include <QString>
#include <QList>
#include <QVariant>
#include <QSettings>
+#include <QMutex>
namespace options {
@@ -15,12 +18,27 @@ namespace options {
class OTR_OPTIONS_EXPORT group final
{
QString name;
+
+ static QString cur_ini_pathname;
+ static std::shared_ptr<QSettings> cur_ini;
+ static QMutex cur_ini_mtx;
+ static int ini_refcount;
+ static bool ini_modifiedp;
+ struct OTR_OPTIONS_EXPORT saver_ final
+ {
+ QSettings& s;
+ QMutex& mtx;
+ QMutexLocker lck;
+
+ ~saver_();
+ saver_(QSettings& s, QMutex&);
+ };
+ static std::shared_ptr<QSettings> cur_settings_object();
+
public:
std::map<QString, QVariant> kvs;
- group(const QString& name, mem<QSettings> s);
group(const QString& name);
void save() const;
- void save_deferred(QSettings& s) const;
void put(const QString& s, const QVariant& d);
bool contains(const QString& s) const;
static QString ini_directory();
@@ -28,9 +46,11 @@ public:
static QString ini_pathname();
static QString ini_combine(const QString& filename);
static QStringList ini_list();
- static std::shared_ptr<QSettings> ini_file();
+
+ static void mark_ini_modified();
template<typename t>
+ OTR_NEVER_INLINE
t get(const QString& k) const
{
auto value = kvs.find(k);
@@ -38,6 +58,15 @@ public:
return value->second.value<t>();
return t();
}
+
+ template<typename F>
+ OTR_NEVER_INLINE
+ static auto with_settings_object(F&& fun)
+ {
+ saver_ saver { *cur_settings_object(), cur_ini_mtx };
+
+ return fun(static_cast<QSettings&>(saver.s));
+ }
};
}
diff --git a/options/scoped.cpp b/options/scoped.cpp
index 96f4a261..58a4ee02 100644
--- a/options/scoped.cpp
+++ b/options/scoped.cpp
@@ -2,8 +2,8 @@
#include <QApplication>
#include <QThread>
-// for std::abort()
#include <cstdlib>
+#include <atomic>
#include <QDebug>
diff --git a/options/tie.hpp b/options/tie.hpp
index a3b5a19f..94fe5d49 100644
--- a/options/tie.hpp
+++ b/options/tie.hpp
@@ -58,6 +58,23 @@ void tie_setting(value<t>& v, QLabel* lb, const QString& format, const xs&... ar
v.SAFE_CONNTYPE);
}
+// Clang 3.9 has a bug
+// error: missing default argument on parameter 'args'
+
+// cf. http://stackoverflow.com/questions/29098835/can-parameter-pack-function-arguments-be-defaulted
+
+template<typename t, typename F, typename... xs>
+decltype((void)((std::declval<F>())(std::declval<const t&>())))
+tie_setting(value<t>& v, QLabel* lb, F&& fun, const QString& fmt = QStringLiteral("%1"), const xs&... args)
+{
+ auto closure = [=](const t& x) { lb->setText(fmt.arg(fun(x), args...)); };
+
+ closure(v());
+ base_value::connect(&v, static_cast<void(base_value::*)(const t&) const>(&base_value::valueChanged),
+ lb, closure,
+ v.SAFE_CONNTYPE);
+}
+
OTR_OPTIONS_EXPORT void tie_setting(value<int>& v, QComboBox* cb);
OTR_OPTIONS_EXPORT void tie_setting(value<QString>& v, QComboBox* cb);
OTR_OPTIONS_EXPORT void tie_setting(value<QVariant>& v, QComboBox* cb);
diff --git a/options/value-traits.hpp b/options/value-traits.hpp
new file mode 100644
index 00000000..cf12649c
--- /dev/null
+++ b/options/value-traits.hpp
@@ -0,0 +1,50 @@
+#include "export.hpp"
+
+#include "compat/functional.hpp"
+#include "slider.hpp"
+
+#include <QString>
+
+#include <type_traits>
+
+namespace options {
+namespace detail {
+
+template<typename t, typename u = t, typename Enable = void>
+struct default_value_traits
+{
+ using element_type = remove_qualifiers<t>;
+ using value_type = u;
+
+ static inline value_type from_value(const value_type& val, const value_type&) { return val; }
+ static inline value_type from_storage(const element_type& x) { return static_cast<value_type>(x); }
+ static inline element_type to_storage(const value_type& val) { return static_cast<element_type>(val); }
+};
+
+template<typename t, typename u = t, typename Enable = void>
+struct value_traits : default_value_traits<t, u, Enable>
+{
+};
+
+template<>
+struct value_traits<slider_value> : default_value_traits<slider_value>
+{
+ static inline slider_value from_value(const slider_value& val, const slider_value& def)
+ {
+ return slider_value(val.cur(), def.min(), def.max());
+ }
+};
+
+// Qt uses int a lot in slots so use it for all enums
+template<typename t>
+struct value_traits<t, t, std::enable_if_t<std::is_enum<t>::value>> : public default_value_traits<int, t>
+{
+};
+
+template<>
+struct value_traits<float> : public default_value_traits<float, double, void>
+{
+};
+
+} // ns detail
+} // ns options
diff --git a/options/value.cpp b/options/value.cpp
deleted file mode 100644
index d3d24a58..00000000
--- a/options/value.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (c) 2015-2016, Stanislaw Halik <sthalik@misaki.pl>
-
- * Permission to use, copy, modify, and/or distribute this
- * software for any purpose with or without fee is hereby granted,
- * provided that the above copyright notice and this permission
- * notice appear in all copies.
- */
-
-#include "value.hpp"
-
-namespace options {
-
-base_value::base_value(bundle b, const QString& name, base_value::comparator cmp, std::type_index type_idx) :
- b(b),
- self_name(name),
- cmp(cmp),
- type_index(type_idx)
-{
- b->on_value_created(name, this);
-}
-
-base_value::~base_value()
-{
- b->on_value_destructed(self_name, this);
-}
-
-namespace detail
-{
- void set_base_value_to_default(base_value* val)
- {
- val->set_to_default();
- }
-}
-
-} // ns options
diff --git a/options/value.hpp b/options/value.hpp
index 020cbeea..ebb2096c 100644
--- a/options/value.hpp
+++ b/options/value.hpp
@@ -12,153 +12,59 @@
#include "compat/util.hpp"
-#include "connector.hpp"
#include "bundle.hpp"
#include "slider.hpp"
+#include "base-value.hpp"
+#include "value-traits.hpp"
+
+#include <cstdio>
#include <type_traits>
#include <typeinfo>
#include <typeindex>
+#include <utility>
+
+#include <QVariant>
#include <QString>
#include <QPointF>
#include <QList>
+#include <QMutex>
-#define OPENTRACK_DEFINE_SLOT(t) void setValue(t datum) { store(datum); }
-#define OPENTRACK_DEFINE_SIGNAL(t) void valueChanged(t) const
namespace options {
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;
-}
-
-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);
- }
-
- template<typename t>
- void store(const t& datum)
- {
- b->store_kv(self_name, QVariant::fromValue(datum));
- }
+OTR_OPTIONS_EXPORT void acct_lookup(bool is_fresh);
-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;
-};
+} // ns detail
-namespace detail {
template<typename t>
-struct value_get_traits
+class value final : public base_value
{
- static inline t get(const t& val, const t&)
- {
- return val;
- }
-};
+ using traits = detail::value_traits<t, t, void>;
+ using element_type = typename traits::element_type;
-template<>
-struct value_get_traits<slider_value>
-{
- using t = slider_value;
- static inline t get(const t& val, const t& def)
+ static bool is_equal(const QVariant& val1, const QVariant& val2)
{
- return t(val.cur(), def.min(), def.max());
+ return val1.value<element_type>() == val2.value<element_type>();
}
-};
-template<typename t, typename Enable = void>
-struct value_element_type
-{
- using type = typename std::remove_reference<typename std::remove_cv<t>::type>::type;
-};
-
-// 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;
-};
-
-template<> struct value_element_type<float, void> { using type = double; };
-
-template<typename t> using value_element_type_t = typename value_element_type<t>::type;
+ OTR_NEVER_INLINE
+ t get() const
+ {
+ if (!b->contains(self_name) || b->get<QVariant>(self_name).type() == QVariant::Invalid)
+ return def;
-}
+ const element_type x(b->get<element_type>(self_name));
-template<typename t>
-class value final : public base_value
-{
- static bool is_equal(const QVariant& val1, const QVariant& val2)
- {
- return val1.value<element_type>() == val2.value<element_type>();
+ return traits::from_value(traits::from_storage(x), def);
}
public:
- using element_type = detail::value_element_type_t<t>;
-
OTR_NEVER_INLINE
t operator=(const t& datum)
{
- const element_type tmp = static_cast<element_type>(datum);
- if (tmp != get())
- store(tmp);
+ if (datum != get())
+ store(traits::to_storage(datum));
return datum;
}
@@ -167,13 +73,12 @@ public:
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)
+ base_value(b, name, &is_equal, std::type_index(typeid(element_type))),
+ def(def)
{
QObject::connect(b.get(), SIGNAL(reloading()),
this, SLOT(reload()),
DIRECT_CONNTYPE);
- if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid)
- *this = def;
}
OTR_NEVER_INLINE
@@ -181,6 +86,7 @@ public:
{
}
+ OTR_NEVER_INLINE
t default_value() const
{
return def;
@@ -193,7 +99,7 @@ public:
}
OTR_NEVER_INLINE
- operator t() const { return get(); }
+ operator t() const { return std::forward<t>(get()); }
OTR_NEVER_INLINE
void reload() override
@@ -201,34 +107,26 @@ public:
*this = static_cast<t>(*this);
}
+ OTR_NEVER_INLINE
void bundle_value_changed() const override
{
- emit valueChanged(static_cast<detail::value_type_t<t>>(get()));
+ emit valueChanged(traits::to_storage(get()));
}
OTR_NEVER_INLINE
t operator()() const
{
- return static_cast<t>(get());
+ return get();
}
template<typename u>
OTR_NEVER_INLINE
u to() const
{
- return static_cast<u>(get());
+ return static_cast<u>(std::forward<t>(get()));
}
private:
- OTR_NEVER_INLINE
- t get() const
- {
- 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);
- }
-
const t def;
};