summaryrefslogtreecommitdiffhomepage
path: root/facetracknoir
diff options
context:
space:
mode:
Diffstat (limited to 'facetracknoir')
-rw-r--r--facetracknoir/options.h151
1 files changed, 71 insertions, 80 deletions
diff --git a/facetracknoir/options.h b/facetracknoir/options.h
index 291ac071..37377b55 100644
--- a/facetracknoir/options.h
+++ b/facetracknoir/options.h
@@ -28,10 +28,10 @@
#include <QDebug>
namespace options {
- template<typename T>
+ template<typename t>
// don't elide usages of the function, qvariant default implicit
// conversion results in nonsensical runtime behavior -sh
- inline T qcruft_to_t (const QVariant& t);
+ inline t qcruft_to_t (const QVariant& datum);
template<>
inline int qcruft_to_t<int>(const QVariant& t)
@@ -84,6 +84,7 @@ namespace options {
conf.endGroup();
}
static constexpr const char* org = "opentrack";
+
void save() {
QSettings s(ini_pathname(), QSettings::IniFormat);
s.beginGroup(name);
@@ -91,9 +92,9 @@ namespace options {
s.setValue(k, map[k]);
s.endGroup();
}
- template<typename T>
- T get(const QString& k) {
- return qcruft_to_t<T>(map.value(k));
+ template<typename t>
+ t get(const QString& k) {
+ return qcruft_to_t<t>(map.value(k));
}
void put(const QString& s, const QVariant& d)
{
@@ -105,7 +106,8 @@ namespace options {
}
};
- class impl_bundle {
+ class impl_bundle : public QObject {
+ Q_OBJECT
private:
QMutex mtx;
const QString group_name;
@@ -114,7 +116,8 @@ namespace options {
impl_bundle(const impl_bundle&) = delete;
impl_bundle& operator=(const impl_bundle&) = delete;
bool modified;
- long priv_cookie;
+ signals:
+ void changed();
public:
impl_bundle(const QString& group_name) :
mtx(QMutex::Recursive),
@@ -128,18 +131,20 @@ namespace options {
QMutexLocker l(&mtx);
saved = group(group_name);
transient = saved;
- priv_cookie++;
}
- void store(const QString& name, const QVariant& datum)
+ void store_kv(const QString& name, const QVariant& datum)
{
QMutexLocker l(&mtx);
- if (!transient.contains(name) || datum != transient.get<QVariant>(name))
+ auto old = transient.get<QVariant>(name);
+ if (!transient.contains(name) || datum != old)
{
if (!modified)
- qDebug() << "bundle" << group_name << "modified due to" << name << transient.get<QVariant>(name) << datum << "->" << datum;
+ qDebug() << "bundle" << group_name <<
+ "modified due to" << name <<
+ transient.get<QVariant>(name) <<
+ old << "->" << datum;
modified = true;
transient.put(name, datum);
- priv_cookie++;
}
}
bool contains(const QString& name)
@@ -147,10 +152,10 @@ namespace options {
QMutexLocker l(&mtx);
return transient.contains(name);
}
- template<typename T>
- T get(const QString& name) {
+ template<typename t>
+ t get(const QString& name) {
QMutexLocker l(&mtx);
- return transient.get<T>(name);
+ return transient.get<t>(name);
}
void save()
{
@@ -158,100 +163,85 @@ namespace options {
modified = false;
saved = transient;
transient.save();
+ emit changed();
}
void revert()
{
QMutexLocker l(&mtx);
modified = false;
transient = saved;
- priv_cookie++;
+ emit changed();
}
bool modifiedp() {
QMutexLocker l(&mtx);
return modified;
}
- long cookie() const {
- return priv_cookie;
- }
};
using pbundle = std::shared_ptr<impl_bundle>;
class base_value : public QObject {
Q_OBJECT
+#define DEFINE_SLOT(t) void setValue(t datum) { store(datum); }
+#define DEFINE_SIGNAL(t) void valueChanged(t);
public:
- base_value(pbundle b, const QString& name) : b(b), self_name(name), cookie_snap(0) {}
- virtual QVariant operator=(const QVariant& datum) = 0;
- template<typename T>
- QVariant operator=(const T& datum)
- {
- return this->operator =(qVariantFromValue<T>(datum));
- }
- protected:
- pbundle b;
- QString self_name;
- template<typename T>
- QVariant store(const T& datum)
- {
- b->store(self_name, qVariantFromValue<T>(datum));
- emit valueChanged(datum);
- return datum;
- }
- void maybe_lazy_change()
- {
- long cookie = b->cookie();
- if (cookie_snap != cookie)
- {
- cookie_snap = cookie;
- this->operator=(b->get<QVariant>(self_name));
- }
- }
- private:
- long cookie_snap;
+ base_value(pbundle b, const QString& name) : b(b), self_name(name) {}
public slots:
-#define DEFINE_SLOT(t) void setValue(t datum) { this->operator=(qVariantFromValue(datum)); }
DEFINE_SLOT(double)
DEFINE_SLOT(int)
DEFINE_SLOT(QString)
DEFINE_SLOT(bool)
signals:
-#define DEFINE_SIGNAL(t) void valueChanged(t);
- DEFINE_SIGNAL(double)
- DEFINE_SIGNAL(int)
- DEFINE_SIGNAL(QString)
- DEFINE_SIGNAL(bool)
+ DEFINE_SIGNAL(double);
+ DEFINE_SIGNAL(int);
+ DEFINE_SIGNAL(bool);
+ DEFINE_SIGNAL(QString);
+ // Qt5 moc really insists on that one -sh 20141012
+ DEFINE_SIGNAL(QVariant);
+ protected:
+ pbundle b;
+ QString self_name;
+
+ template<typename t>
+ void store(const t& datum)
+ {
+ b->store_kv(self_name, datum);
+ emit valueChanged(static_cast<t>(datum));
+ }
};
- template<typename T>
+ template<typename t>
class value : public base_value {
public:
- QVariant operator=(const QVariant& datum) {
- return store(qcruft_to_t<T>(datum));
+ t operator=(const t& datum)
+ {
+ store(qVariantFromValue<t>(datum));
+ return datum;
}
- static constexpr const Qt::ConnectionType QT_CONNTYPE = Qt::UniqueConnection;
- static constexpr const Qt::ConnectionType OPT_CONNTYPE = Qt::UniqueConnection;
- value(pbundle b, const QString& name, T def) : base_value(b, name)
+ static constexpr const Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection;
+ static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::AutoConnection;
+ value(pbundle b, const QString& name, t def) : base_value(b, name)
{
if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid)
- this->operator=(qVariantFromValue<T>(def));
+ *this = def;
}
- operator T()
+ operator t()
{
- maybe_lazy_change();
- return b->get<T>(self_name);
+ return b->get<t>(self_name);
}
};
- template<typename T, typename Q>
- inline void tie_setting(value<T>&, Q*);
+ template<typename t, typename q>
+ inline void tie_setting(value<t>&, q*);
template<>
inline void tie_setting(value<int>& v, QComboBox* cb)
{
cb->setCurrentIndex(v);
- base_value::connect(cb, SIGNAL(currentIndexChanged(int)), &v, SLOT(setValue(int)), v.QT_CONNTYPE);
- base_value::connect(&v, SIGNAL(valueChanged(int)), cb, SLOT(setCurrentIndex(int)), v.OPT_CONNTYPE);
+ v = cb->currentIndex();
+ base_value::connect(cb, SIGNAL(currentIndexChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(int)), cb, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE);
}
template<>
@@ -259,55 +249,56 @@ namespace options {
{
cb->setCurrentText(v);
v = cb->currentText();
- base_value::connect(cb, SIGNAL(currentTextChanged(QString)), &v, SLOT(setValue(QString)), v.QT_CONNTYPE);
- base_value::connect(&v, SIGNAL(valueChanged(QString)), cb, SLOT(setCurrentText(QString)), v.OPT_CONNTYPE);
+ base_value::connect(cb, SIGNAL(currentTextChanged(QString)), &v, SLOT(setValue(QString)), v.DIRECT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(QString)), cb, SLOT(setCurrentText(QString)), v.SAFE_CONNTYPE);
}
template<>
inline void tie_setting(value<bool>& v, QCheckBox* cb)
{
cb->setChecked(v);
- base_value::connect(cb, SIGNAL(toggled(bool)), &v, SLOT(setValue(bool)), v.QT_CONNTYPE);
- base_value::connect(&v, SIGNAL(valueChanged(bool)), cb, SLOT(setChecked(bool)), v.OPT_CONNTYPE);
+ base_value::connect(cb, SIGNAL(toggled(bool)), &v, SLOT(setValue(bool)), v.DIRECT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(bool)), cb, SLOT(setChecked(bool)), v.SAFE_CONNTYPE);
}
template<>
inline void tie_setting(value<double>& v, QDoubleSpinBox* dsb)
{
dsb->setValue(v);
- base_value::connect(dsb, SIGNAL(valueChanged(double)), &v, SLOT(setValue(double)), v.QT_CONNTYPE);
- base_value::connect(&v, SIGNAL(valueChanged(double)), dsb, SLOT(setValue(double)), v.OPT_CONNTYPE);
+ base_value::connect(dsb, SIGNAL(valueChanged(double)), &v, SLOT(setValue(double)), v.DIRECT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(double)), dsb, SLOT(setValue(double)), v.SAFE_CONNTYPE);
}
template<>
inline void tie_setting(value<int>& v, QSpinBox* sb)
{
sb->setValue(v);
- base_value::connect(sb, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.QT_CONNTYPE);
- base_value::connect(&v, SIGNAL(valueChanged(int)), sb, SLOT(setValue(int)), v.OPT_CONNTYPE);
+ base_value::connect(sb, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(int)), sb, SLOT(setValue(int)), v.SAFE_CONNTYPE);
}
template<>
inline void tie_setting(value<int>& v, QSlider* sl)
{
sl->setValue(v);
- base_value::connect(sl, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.QT_CONNTYPE);
- base_value::connect(&v, SIGNAL(valueChanged(int)), sl, SLOT(setValue(int)), v.OPT_CONNTYPE);
+ v = sl->value();
+ base_value::connect(sl, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(int)), sl, SLOT(setValue(int)), v.SAFE_CONNTYPE);
}
template<>
inline void tie_setting(value<QString>& v, QLineEdit* le)
{
le->setText(v);
- base_value::connect(le, SIGNAL(textChanged(QString)), &v, SLOT(setValue(QString)), v.QT_CONNTYPE);
- base_value::connect(&v, SIGNAL(valueChanged(QString)),le, SLOT(setText(QString)), v.OPT_CONNTYPE);
+ base_value::connect(le, SIGNAL(textChanged(QString)), &v, SLOT(setValue(QString)), v.DIRECT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(QString)),le, SLOT(setText(QString)), v.SAFE_CONNTYPE);
}
template<>
inline void tie_setting(value<QString>& v, QLabel* lb)
{
lb->setText(v);
- base_value::connect(&v, SIGNAL(valueChanged(QString)), lb, SLOT(setText(QString)), v.OPT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(QString)), lb, SLOT(setText(QString)), v.SAFE_CONNTYPE);
}
inline pbundle bundle(const QString& group) {