From 6f91be9eec668a2cb27f5065ac86ff1d55f1034b Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 6 May 2017 10:36:46 +0200 Subject: options/bundle: skip needless compare-twice --- options/bundle.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'options') diff --git a/options/bundle.cpp b/options/bundle.cpp index 43f4a8e3..4d44521f 100644 --- a/options/bundle.cpp +++ b/options/bundle.cpp @@ -119,8 +119,7 @@ bool bundle::is_modified() const for (const auto& kv : saved.kvs) { - const QVariant other = transient.get(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; -- cgit v1.2.3 From 87c09c0ab5e1334e9877ee6fd7adeb1eb70d5929 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 6 May 2017 13:15:16 +0200 Subject: options: don't create QSettings all the time Update usages. --- gui/main-window.cpp | 8 ++++ gui/mapping-window.cpp | 11 ++--- logic/mappings.cpp | 6 +-- logic/mappings.hpp | 2 +- migration/20160906_00-mappings.cpp | 40 +++++++--------- migration/migration.cpp | 25 ++++++---- options/CMakeLists.txt | 1 + options/bundle.cpp | 25 +++++----- options/bundle.hpp | 3 +- options/group.cpp | 97 +++++++++++++++++++++++++++----------- options/group.hpp | 35 ++++++++++++-- spline/spline.cpp | 9 +--- spline/spline.hpp | 1 - 13 files changed, 166 insertions(+), 97 deletions(-) (limited to 'options') diff --git a/gui/main-window.cpp b/gui/main-window.cpp index d64858c4..96be298e 100644 --- a/gui/main-window.cpp +++ b/gui/main-window.cpp @@ -277,6 +277,14 @@ void MainWindow::die_on_config_not_writable() bool MainWindow::maybe_die_on_config_not_writable(const QString& current, QStringList* ini_list_) { + const bool writable = + group::with_settings_object([&](QSettings& s) { + return s.isWritable(); + }); + + if (writable) + return false; + const bool open = QFile(group::ini_combine(current)).open(QFile::ReadWrite); const QStringList ini_list = group::ini_list(); diff --git a/gui/mapping-window.cpp b/gui/mapping-window.cpp index 0ee8c562..0a5d3049 100644 --- a/gui/mapping-window.cpp +++ b/gui/mapping-window.cpp @@ -114,18 +114,15 @@ void MapWidget::closeEvent(QCloseEvent*) void MapWidget::save_dialog() { - mem settings_ = group::ini_file(); - QSettings& settings = *settings_; - - s.b_map->save_deferred(settings); + s.b_map->save(); for (int i = 0; i < 6; i++) { m.forall([&](Map& s) { - s.spline_main.save(settings); - s.spline_alt.save(settings); - s.opts.b_mapping_window->save_deferred(settings); + s.spline_main.save(); + s.spline_alt.save(); + s.opts.b_mapping_window->save(); }); } } diff --git a/logic/mappings.cpp b/logic/mappings.cpp index d7764375..bae8c2c0 100644 --- a/logic/mappings.cpp +++ b/logic/mappings.cpp @@ -11,10 +11,10 @@ Map::Map(QString primary, QString secondary, int max_x, int max_y, axis_opts& op spline_alt.set_max_input(opts.clamp); } -void Map::save(QSettings& s) +void Map::save() { - spline_main.save(s); - spline_alt.save(s); + spline_main.save(); + spline_alt.save(); } void Map::load() diff --git a/logic/mappings.hpp b/logic/mappings.hpp index 4e0f7218..b3587749 100644 --- a/logic/mappings.hpp +++ b/logic/mappings.hpp @@ -17,7 +17,7 @@ struct OTR_LOGIC_EXPORT Map final { Map(QString primary, QString secondary, int max_x, int max_y, axis_opts& opts); - void save(QSettings& s); + void save(); void load(); axis_opts& opts; diff --git a/migration/20160906_00-mappings.cpp b/migration/20160906_00-mappings.cpp index 58674843..a5184825 100644 --- a/migration/20160906_00-mappings.cpp +++ b/migration/20160906_00-mappings.cpp @@ -36,31 +36,30 @@ struct mappings_from_2_3_0_rc11 : migration "rz", "rz_alt", }; - std::shared_ptr settings_ = options::group::ini_file(); - QSettings& settings(*settings_); - - for (const char* name : names) - { - QList points; + return group::with_settings_object([&](QSettings& settings) { + for (const char* name : names) + { + QList points; - settings.beginGroup(QString("Curves-%1").arg(name)); + settings.beginGroup(QString("Curves-%1").arg(name)); - const int max = settings.value("point-count", 0).toInt(); + const int max = settings.value("point-count", 0).toInt(); - for (int i = 0; i < max; i++) - { - QPointF new_point(settings.value(QString("point-%1-x").arg(i), 0).toDouble(), - settings.value(QString("point-%1-y").arg(i), 0).toDouble()); + for (int i = 0; i < max; i++) + { + QPointF new_point(settings.value(QString("point-%1-x").arg(i), 0).toDouble(), + settings.value(QString("point-%1-y").arg(i), 0).toDouble()); - points.append(new_point); - } + points.append(new_point); + } - settings.endGroup(); + settings.endGroup(); - ret.append(points); - } + ret.append(points); + } - return ret; + return ret; + }); } QString unique_date() const override { return "20160909_00"; } @@ -94,9 +93,6 @@ struct mappings_from_2_3_0_rc11 : migration const QList> old_mappings = get_old_splines(); Mappings m = get_new_mappings(); - std::shared_ptr s_ = options::group::ini_file(); - QSettings& s = *s_; - for (int i = 0; i < 12; i++) { spline& spl = (i % 2) == 0 ? m(i / 2).spline_main : m(i / 2).spline_alt; @@ -104,7 +100,7 @@ struct mappings_from_2_3_0_rc11 : migration const QList& points = old_mappings[i]; for (const QPointF& pt : points) spl.add_point(pt); - spl.save(s); + spl.save(); } } }; diff --git a/migration/migration.cpp b/migration/migration.cpp index bb8386fc..747ea06b 100644 --- a/migration/migration.cpp +++ b/migration/migration.cpp @@ -78,11 +78,11 @@ QString migrator::last_migration_time() { QString ret; - std::shared_ptr s(options::group::ini_file()); - - s->beginGroup("migrations"); - ret = s->value("last-migration-at", "19700101_00").toString(); - s->endGroup(); + options::group::with_settings_object([&](QSettings& s) { + s.beginGroup("migrations"); + ret = s.value("last-migration-at", "19700101_00").toString(); + s.endGroup(); + }); return ret; } @@ -102,11 +102,16 @@ QString migrator::time_after_migrations() void migrator::set_last_migration_time(const QString& val) { - std::shared_ptr s(options::group::ini_file()); - - s->beginGroup("migrations"); - s->setValue("last-migration-at", val); - s->endGroup(); + options::group::with_settings_object([&](QSettings& s) { + s.beginGroup("migrations"); + const QString old_value = s.value("last-migration-at", "").toString(); + if (val != old_value) + { + s.setValue("last-migration-at", val); + options::group::mark_ini_modified(); + } + s.endGroup(); + }); } std::vector migrator::sorted_migrations() 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/bundle.cpp b/options/bundle.cpp index 4d44521f..c78df274 100644 --- a/options/bundle.cpp +++ b/options/bundle.cpp @@ -31,12 +31,12 @@ bundle::~bundle() { } -void bundle::reload(std::shared_ptr 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 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); @@ -134,8 +135,6 @@ void bundler::after_profile_changed_() { QMutexLocker l(&implsgl_mtx); - std::shared_ptr s = group::ini_file(); - for (auto& kv : implsgl_data) { weak bundle = kv.second; @@ -143,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 settings = group::ini_file()); - void save_deferred(QSettings& s); + void reload(); void set_all_to_default(); }; diff --git a/options/group.cpp b/options/group.cpp index 9a4bd912..028e3e48 100644 --- a/options/group.cpp +++ b/options/group.cpp @@ -8,46 +8,47 @@ #include "group.hpp" #include "defs.hpp" + +#include "compat/timer.hpp" + +#include + #include #include - #include namespace options { -group::group(const QString& name, std::shared_ptr 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); + kvs[k] = conf.value(k_); + } + 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 +104,52 @@ QStringList group::ini_list() return list; } -std::shared_ptr group::ini_file() +void group::mark_ini_modified() +{ + QMutexLocker l(&cur_ini_mtx); + ini_modifiedp = true; +} + +QString group::cur_ini_pathname; +std::shared_ptr group::cur_ini; +QMutex group::cur_ini_mtx(QMutex::Recursive); +int group::ini_refcount = 0; +bool group::ini_modifiedp = false; + +std::shared_ptr group::cur_settings_object() { - const auto pathname = ini_pathname(); - if (pathname != "") - return std::make_shared(ini_pathname(), QSettings::IniFormat); - return std::make_shared(); + const QString pathname = ini_pathname(); + + if (pathname.isEmpty()) + return std::make_shared(); + + QMutexLocker l(&cur_ini_mtx); + + if (pathname != cur_ini_pathname) + { + cur_ini = std::make_shared(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)) + << "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 #include #include #include #include #include +#include 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 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 cur_settings_object(); + public: std::map kvs; - group(const QString& name, mem 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 ini_file(); + + static void mark_ini_modified(); template + OTR_NEVER_INLINE t get(const QString& k) const { auto value = kvs.find(k); @@ -38,6 +58,15 @@ public: return value->second.value(); return t(); } + + template + OTR_NEVER_INLINE + static auto with_settings_object(F&& fun) + { + saver_ saver { *cur_settings_object(), cur_ini_mtx }; + + return fun(static_cast(saver.s)); + } }; } diff --git a/spline/spline.cpp b/spline/spline.cpp index 195d68d6..58703e02 100644 --- a/spline/spline.cpp +++ b/spline/spline.cpp @@ -341,15 +341,10 @@ void spline::reload() s->b->reload(); } -void spline::save(QSettings& settings) -{ - QMutexLocker foo(&_mutex); - s->b->save_deferred(settings); -} - void spline::save() { - save(*group::ini_file()); + QMutexLocker foo(&_mutex); + s->b->save(); } void spline::set_bundle(bundle b) diff --git a/spline/spline.hpp b/spline/spline.hpp index 067967b5..146837c8 100644 --- a/spline/spline.hpp +++ b/spline/spline.hpp @@ -70,7 +70,6 @@ public: using settings = spline_detail::settings; void reload(); - void save(QSettings& s); void save(); void set_bundle(bundle b); -- cgit v1.2.3 From 33580cee78020e8389834ea271556320f33521e4 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 6 May 2017 13:26:02 +0200 Subject: options/tie: allow for custom-formatting the ini value --- options/tie.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'options') 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& 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 +decltype((void)((std::declval())(std::declval()))) +tie_setting(value& 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(&base_value::valueChanged), + lb, closure, + v.SAFE_CONNTYPE); +} + OTR_OPTIONS_EXPORT void tie_setting(value& v, QComboBox* cb); OTR_OPTIONS_EXPORT void tie_setting(value& v, QComboBox* cb); OTR_OPTIONS_EXPORT void tie_setting(value& v, QComboBox* cb); -- cgit v1.2.3 From e07bde4423eee88d9f9a02b179480de3129d9c93 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 7 May 2017 08:08:38 +0200 Subject: options/group: nicely format debug timestamp --- options/group.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'options') diff --git a/options/group.cpp b/options/group.cpp index 028e3e48..3f800ff0 100644 --- a/options/group.cpp +++ b/options/group.cpp @@ -141,7 +141,7 @@ group::saver_::~saver_() 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)) + qDebug() << QStringLiteral("%1.%2").arg(int(tm)).arg(int(std::fmod(tm, 1.)*10)).toLatin1().data() << "saving .ini file" << cur_ini_pathname; s.sync(); } -- cgit v1.2.3 From 4c4c783d023cf1bb6a8d7d883bf8d3384f7b7da1 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 12 May 2017 15:43:50 +0200 Subject: minor fixes only --- dinput/keybinding-worker.cpp | 5 +++-- options/connector.cpp | 7 ++++--- options/group.cpp | 4 +++- options/scoped.cpp | 2 +- pose-widget/pose-widget.cpp | 4 ++-- pose-widget/pose-widget.hpp | 2 +- 6 files changed, 14 insertions(+), 10 deletions(-) (limited to 'options') diff --git a/dinput/keybinding-worker.cpp b/dinput/keybinding-worker.cpp index b94b762e..0e16ac71 100644 --- a/dinput/keybinding-worker.cpp +++ b/dinput/keybinding-worker.cpp @@ -9,6 +9,7 @@ #ifdef _WIN32 #include "keybinding-worker.hpp" +#include "compat/util.hpp" #include #include #include @@ -18,8 +19,8 @@ bool Key::should_process() { if (!enabled || (keycode == 0 && guid == "")) return false; - bool ret = !held || timer.elapsed_ms() > 100; - timer.start(); + bool ret = prog1(!held || timer.elapsed_ms() > 100, + timer.start()); return ret; } 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 3f800ff0..60e8a7b4 100644 --- a/options/group.cpp +++ b/options/group.cpp @@ -30,7 +30,9 @@ group::group(const QString& name) : name(name) { auto tmp = k_.toUtf8(); QString k(tmp); - kvs[k] = conf.value(k_); + QVariant val = conf.value(k_); + if (val.type() != QVariant::Invalid) + kvs[k] = std::move(val); } conf.endGroup(); }); 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 #include -// for std::abort() #include +#include #include diff --git a/pose-widget/pose-widget.cpp b/pose-widget/pose-widget.cpp index 54278c34..8646df30 100644 --- a/pose-widget/pose-widget.cpp +++ b/pose-widget/pose-widget.cpp @@ -47,7 +47,7 @@ void pose_widget::paintEvent(QPaintEvent* event) xform.with_image_lock([&](const QImage& image) { - p.drawImage(event->rect(), image, offset, offset); + p.drawImage(event->rect(), image, QRect(offset, offset, pose_transform::w, pose_transform::h)); }); } @@ -71,7 +71,7 @@ void pose_transform::run() project_quad_texture(); end: - portable::sleep(9); + portable::sleep(23); } } diff --git a/pose-widget/pose-widget.hpp b/pose-widget/pose-widget.hpp index 1d34778a..a27bf4b9 100644 --- a/pose-widget/pose-widget.hpp +++ b/pose-widget/pose-widget.hpp @@ -37,7 +37,7 @@ using lock_guard = std::unique_lock; class pose_widget; -class pose_transform final : private QThread +struct pose_transform final : private QThread { pose_transform(QWidget* dst); ~pose_transform(); -- cgit v1.2.3 From f7ab2dc5a54c573cd7408a68cb1e93174827719e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 12 May 2017 15:44:05 +0200 Subject: options: split up value.hpp header Also combine the traits classes and make them more useful. --- options/base-value.cpp | 27 ++++++++ options/base-value.hpp | 85 ++++++++++++++++++++++++ options/value-traits.hpp | 50 ++++++++++++++ options/value.cpp | 35 ---------- options/value.hpp | 166 +++++++++-------------------------------------- 5 files changed, 194 insertions(+), 169 deletions(-) create mode 100644 options/base-value.cpp create mode 100644 options/base-value.hpp create mode 100644 options/value-traits.hpp delete mode 100644 options/value.cpp (limited to 'options') 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 +#include +#include +#include +#include + +#include + +#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&); + OPENTRACK_DEFINE_SIGNAL(const QList&); + OPENTRACK_DEFINE_SIGNAL(const QList&); + OPENTRACK_DEFINE_SIGNAL(const QList&); + OPENTRACK_DEFINE_SIGNAL(const QList&); + OPENTRACK_DEFINE_SIGNAL(const QList&); + OPENTRACK_DEFINE_SIGNAL(const QList&); +protected: + bundle b; + QString self_name; + comparator cmp; + std::type_index type_index; + + void store(const QVariant& datum); + + template + 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&) + OPENTRACK_DEFINE_SLOT(const QList&) + OPENTRACK_DEFINE_SLOT(const QList&) + OPENTRACK_DEFINE_SLOT(const QList&) + OPENTRACK_DEFINE_SLOT(const QList&) + OPENTRACK_DEFINE_SLOT(const QList&) + OPENTRACK_DEFINE_SLOT(const QList&) + + virtual void reload() = 0; + virtual void bundle_value_changed() const = 0; + virtual void set_to_default() = 0; +}; + +} //ns options 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 + +#include + +namespace options { +namespace detail { + +template +struct default_value_traits +{ + using element_type = remove_qualifiers; + 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(x); } + static inline element_type to_storage(const value_type& val) { return static_cast(val); } +}; + +template +struct value_traits : default_value_traits +{ +}; + +template<> +struct value_traits : default_value_traits +{ + 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 +struct value_traits::value>> : public default_value_traits +{ +}; + +template<> +struct value_traits : public default_value_traits +{ +}; + +} // 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 - - * 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 #include #include #include +#include + +#include #include #include #include +#include -#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 struct value_type_traits { using type = t;}; -template<> struct value_type_traits { using type = const QString&; }; -template<> struct value_type_traits { using type = const slider_value&; }; -template struct value_type_traits> -{ - using type = const QList&; -}; -template using value_type_t = typename value_type_traits::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&); - OPENTRACK_DEFINE_SIGNAL(const QList&); - OPENTRACK_DEFINE_SIGNAL(const QList&); - OPENTRACK_DEFINE_SIGNAL(const QList&); - OPENTRACK_DEFINE_SIGNAL(const QList&); - OPENTRACK_DEFINE_SIGNAL(const QList&); - OPENTRACK_DEFINE_SIGNAL(const QList&); -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 - 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&) - OPENTRACK_DEFINE_SLOT(const QList&) - OPENTRACK_DEFINE_SLOT(const QList&) - OPENTRACK_DEFINE_SLOT(const QList&) - OPENTRACK_DEFINE_SLOT(const QList&) - OPENTRACK_DEFINE_SLOT(const QList&) - OPENTRACK_DEFINE_SLOT(const QList&) - - virtual void reload() = 0; - virtual void bundle_value_changed() const = 0; - virtual void set_to_default() = 0; -}; +} // ns detail -namespace detail { template -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; + using element_type = typename traits::element_type; -template<> -struct value_get_traits -{ - 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() == val2.value(); } -}; -template -struct value_element_type -{ - using type = typename std::remove_reference::type>::type; -}; - -// Qt uses int a lot in slots so use it for all enums -template -struct value_element_type::value>::type> -{ - using type = int; -}; - -template<> struct value_element_type { using type = double; }; - -template using value_element_type_t = typename value_element_type::type; + OTR_NEVER_INLINE + t get() const + { + if (!b->contains(self_name) || b->get(self_name).type() == QVariant::Invalid) + return def; -} + const element_type x(b->get(self_name)); -template -class value final : public base_value -{ - static bool is_equal(const QVariant& val1, const QVariant& val2) - { - return val1.value() == val2.value(); + return traits::from_value(traits::from_storage(x), def); } public: - using element_type = detail::value_element_type_t; - OTR_NEVER_INLINE t operator=(const t& datum) { - const element_type tmp = static_cast(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(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(get()); } OTR_NEVER_INLINE void reload() override @@ -201,34 +107,26 @@ public: *this = static_cast(*this); } + OTR_NEVER_INLINE void bundle_value_changed() const override { - emit valueChanged(static_cast>(get())); + emit valueChanged(traits::to_storage(get())); } OTR_NEVER_INLINE t operator()() const { - return static_cast(get()); + return get(); } template OTR_NEVER_INLINE u to() const { - return static_cast(get()); + return static_cast(std::forward(get())); } private: - OTR_NEVER_INLINE - t get() const - { - t val = b->contains(self_name) - ? static_cast(b->get(self_name)) - : def; - return detail::value_get_traits::get(val, def); - } - const t def; }; -- cgit v1.2.3