diff options
-rw-r--r-- | gui/main-window.cpp | 8 | ||||
-rw-r--r-- | gui/mapping-window.cpp | 11 | ||||
-rw-r--r-- | logic/mappings.cpp | 6 | ||||
-rw-r--r-- | logic/mappings.hpp | 2 | ||||
-rw-r--r-- | migration/20160906_00-mappings.cpp | 40 | ||||
-rw-r--r-- | migration/migration.cpp | 25 | ||||
-rw-r--r-- | options/CMakeLists.txt | 1 | ||||
-rw-r--r-- | options/bundle.cpp | 25 | ||||
-rw-r--r-- | options/bundle.hpp | 3 | ||||
-rw-r--r-- | options/group.cpp | 97 | ||||
-rw-r--r-- | options/group.hpp | 35 | ||||
-rw-r--r-- | spline/spline.cpp | 9 | ||||
-rw-r--r-- | spline/spline.hpp | 1 |
13 files changed, 166 insertions, 97 deletions
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<QSettings> 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<QSettings> settings_ = options::group::ini_file(); - QSettings& settings(*settings_); - - for (const char* name : names) - { - QList<QPointF> points; + return group::with_settings_object([&](QSettings& settings) { + for (const char* name : names) + { + QList<QPointF> 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<QList<QPointF>> old_mappings = get_old_splines(); Mappings m = get_new_mappings(); - std::shared_ptr<QSettings> 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<QPointF>& 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<QSettings> 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<QSettings> 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<migration*> 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<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); @@ -134,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; @@ -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<QSettings> 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 <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); + 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<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)) + << "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/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); |