summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gui/main-window.cpp8
-rw-r--r--gui/mapping-window.cpp11
-rw-r--r--logic/mappings.cpp6
-rw-r--r--logic/mappings.hpp2
-rw-r--r--migration/20160906_00-mappings.cpp40
-rw-r--r--migration/migration.cpp25
-rw-r--r--options/CMakeLists.txt1
-rw-r--r--options/bundle.cpp25
-rw-r--r--options/bundle.hpp3
-rw-r--r--options/group.cpp97
-rw-r--r--options/group.hpp35
-rw-r--r--spline/spline.cpp9
-rw-r--r--spline/spline.hpp1
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);