diff options
Diffstat (limited to 'opentrack/options.hpp')
-rw-r--r-- | opentrack/options.hpp | 123 |
1 files changed, 80 insertions, 43 deletions
diff --git a/opentrack/options.hpp b/opentrack/options.hpp index 6c15d729..5eae754f 100644 --- a/opentrack/options.hpp +++ b/opentrack/options.hpp @@ -26,17 +26,21 @@ #include <QSlider> #include <QLineEdit> #include <QLabel> +#include <QTabWidget> #include <QCoreApplication> #include <cinttypes> #include <QDebug> +#include <memory> +template<typename t> using mem = std::shared_ptr<t>; + namespace options { template<typename k, typename v> using map = std::map<k, v>; using std::string; - + template<typename t> // don't elide usages of the function, qvariant default implicit // conversion results in nonsensical runtime behavior -sh @@ -77,12 +81,6 @@ namespace options { private: map<string, QVariant> kvs; string name; - static const QString ini_pathname() - { - QSettings settings(group::org); - return settings.value("SettingsFile", - QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString(); - } public: group(const string& name) : name(name) { @@ -97,8 +95,8 @@ namespace options { } conf.endGroup(); } - static constexpr const char* org = "opentrack"; - + static constexpr const char* org = "opentrack-2.3"; + void save() { QSettings s(ini_pathname(), QSettings::IniFormat); @@ -110,26 +108,41 @@ namespace options { s.setValue(k, i.second); } s.endGroup(); + s.sync(); } - + template<typename t> t get(const string& k) { return qcruft_to_t<t>(kvs[k]); } - + void put(const string& s, const QVariant& d) { kvs[s] = d; } - + bool contains(const string& s) { return kvs.count(s) != 0; } + + static constexpr const char* filename_key = "settings-file"; + static constexpr const char* default_path = "/settings/default.ini"; + + static const QString ini_pathname() + { + QSettings settings(group::org); + return settings.value(filename_key, QCoreApplication::applicationDirPath() + default_path).toString(); + } + static const mem<QSettings> ini_file() + { + return std::make_shared<QSettings>(ini_pathname(), QSettings::IniFormat); + } }; class impl_bundle : public QObject { + Q_OBJECT protected: QMutex mtx; const string group_name; @@ -138,6 +151,9 @@ namespace options { bool modified; impl_bundle(const impl_bundle&) = delete; impl_bundle& operator=(const impl_bundle&) = delete; + signals: + void reloading(); + void saving(); public: impl_bundle(const string& group_name) : mtx(QMutex::Recursive), @@ -147,28 +163,29 @@ namespace options { modified(false) { } - + string name() { return group_name; } - + void reload() { - QMutexLocker l(&mtx); - saved = group(group_name); - transient = saved; - modified = false; + { + QMutexLocker l(&mtx); + saved = group(group_name); + transient = saved; + modified = false; + } + emit reloading(); } - - bool store_kv(const string& name, const QVariant& datum) + + void store_kv(const string& name, const QVariant& datum) { QMutexLocker l(&mtx); - + auto old = transient.get<QVariant>(name); if (!transient.contains(name) || datum != old) { modified = true; transient.put(name, datum); - return true; } - return false; } bool contains(const string& name) { @@ -183,10 +200,13 @@ namespace options { } void save() { - QMutexLocker l(&mtx); - modified = false; - saved = transient; - transient.save(); + { + QMutexLocker l(&mtx); + modified = false; + saved = transient; + transient.save(); + } + emit saving(); } bool modifiedp() { @@ -194,9 +214,9 @@ namespace options { return modified; } }; - + class opt_bundle; - + namespace { template<typename k, typename v, typename cnt = int> @@ -210,51 +230,52 @@ namespace options { map<k, tt> implsgl_data; public: opt_singleton() : implsgl_mtx(QMutex::Recursive) {} - + static opt_singleton<k, v>& datum() { static auto ret = std::make_shared<opt_singleton<k, v>>(); return *ret; } - + pbundle bundle(const k& key) { QMutexLocker l(&implsgl_mtx); - + if (implsgl_data.count(key) != 0) return std::get<1>(implsgl_data[key]); + qDebug() << "bundle +" << QString::fromStdString(key); + auto shr = std::make_shared<v>(key); implsgl_data[key] = tt(cnt(1), shr); return shr; } - + void bundle_decf(const k& key) { QMutexLocker l(&implsgl_mtx); - + if (--std::get<0>(implsgl_data[key]) == 0) implsgl_data.erase(key); } - + ~opt_singleton() { implsgl_data.clear(); } }; - + using pbundle = std::shared_ptr<opt_bundle>; using t_fact = opt_singleton<string, opt_bundle>; } - + static inline t_fact::pbundle bundle(const string name) { return t_fact::datum().bundle(name); } - + class opt_bundle : public impl_bundle { public: opt_bundle() : impl_bundle("i-have-no-name") {} opt_bundle(const string& group_name) : impl_bundle(group_name) { - qDebug() << "bundle +" << QString::fromStdString(group_name); } - + ~opt_bundle() { qDebug() << "bundle -" << QString::fromStdString(group_name); @@ -281,16 +302,18 @@ namespace options { template<typename t> void store(const t& datum) { - if (b->store_kv(self_name, datum)) - emit valueChanged(static_cast<t>(datum)); + b->store_kv(self_name, datum); + emit valueChanged(static_cast<t>(datum)); } public slots: DEFINE_SLOT(double) DEFINE_SLOT(int) DEFINE_SLOT(QString) DEFINE_SLOT(bool) + public slots: + virtual void reload() = 0; }; - + static inline string string_from_qstring(const QString& datum) { auto tmp = datum.toUtf8(); @@ -309,6 +332,9 @@ namespace options { static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::UniqueConnection; value(pbundle b, const string& name, t def) : base_value(b, name) { + QObject::connect(b.get(), SIGNAL(reloading()), + this, SLOT(reload()), + DIRECT_CONNTYPE); if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid) *this = def; } @@ -319,6 +345,9 @@ namespace options { { return b->get<t>(self_name); } + void reload() override { + *this = static_cast<t>(*this); + } }; template<typename t, typename q> @@ -389,4 +418,12 @@ namespace options { lb->setText(v); base_value::connect(&v, SIGNAL(valueChanged(QString)), lb, SLOT(setText(QString)), v.SAFE_CONNTYPE); } + + template<> + inline void tie_setting(value<int>& v, QTabWidget* t) + { + t->setCurrentIndex(v); + base_value::connect(t, SIGNAL(currentChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(int)), t, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE); + } } |