diff options
-rw-r--r-- | facetracknoir/options.h | 131 |
1 files changed, 83 insertions, 48 deletions
diff --git a/facetracknoir/options.h b/facetracknoir/options.h index de445e69..b55d2bf0 100644 --- a/facetracknoir/options.h +++ b/facetracknoir/options.h @@ -10,6 +10,7 @@ #include <memory> #include <tuple> #include <map> +#include <string> #include <QObject> #include <QSettings> @@ -34,6 +35,7 @@ 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 @@ -73,8 +75,8 @@ namespace options { // snapshot of qsettings group at given time class group { private: - map<QString, QVariant> map; - QString name; + map<string, QVariant> map; + string name; static const QString ini_pathname() { QSettings settings(group::org); @@ -82,12 +84,17 @@ namespace options { QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString(); } public: - group(const QString& name) : name(name) + group(const string& name) : name(name) { QSettings conf(ini_pathname(), QSettings::IniFormat); - conf.beginGroup(name); - for (auto& k : conf.childKeys()) - map[k] = conf.value(k); + auto q_name = QString::fromStdString(name); + conf.beginGroup(q_name); + for (auto& k_ : conf.childKeys()) + { + auto tmp = k_.toUtf8(); + string k(tmp); + map[k] = conf.value(k_); + } conf.endGroup(); } static constexpr const char* org = "opentrack"; @@ -95,24 +102,28 @@ namespace options { void save() { QSettings s(ini_pathname(), QSettings::IniFormat); - s.beginGroup(name); + auto q_name = QString::fromStdString(name); + s.beginGroup(q_name); for (auto& i : map) - s.setValue(i.first, i.second); + { + auto k = QString::fromStdString(i.first); + s.setValue(k, i.second); + } s.endGroup(); } template<typename t> - t get(const QString& k) + t get(const string& k) { return qcruft_to_t<t>(map[k]); } - void put(const QString& s, const QVariant& d) + void put(const string& s, const QVariant& d) { map[s] = d; } - bool contains(const QString& s) + bool contains(const string& s) { return map.count(s) != 0; } @@ -122,14 +133,14 @@ namespace options { Q_OBJECT protected: QMutex mtx; - const QString group_name; + const string group_name; group saved; group transient; bool modified; impl_bundle(const impl_bundle&) = delete; impl_bundle& operator=(const impl_bundle&) = delete; public: - impl_bundle(const QString& group_name) : + impl_bundle(const string& group_name) : mtx(QMutex::Recursive), group_name(group_name), saved(group_name), @@ -138,7 +149,7 @@ namespace options { { } - QString name() { return group_name; } + string name() { return group_name; } void reload() { QMutexLocker l(&mtx); @@ -147,30 +158,26 @@ namespace options { modified = false; } - bool store_kv(const QString& name, const QVariant& datum) + bool store_kv(const string& name, const QVariant& datum) { QMutexLocker l(&mtx); auto old = transient.get<QVariant>(name); if (!transient.contains(name) || datum != old) { - if (!modified) - qDebug() << "bundle" << (intptr_t)static_cast<void*>(this) << - "modified as per" << name << old << "->" << datum; - modified = true; transient.put(name, datum); return true; } return false; } - bool contains(const QString& name) + bool contains(const string& name) { QMutexLocker l(&mtx); return transient.contains(name); } template<typename t> - t get(const QString& name) + t get(const string& name) { QMutexLocker l(&mtx); return transient.get<t>(name); @@ -190,53 +197,72 @@ namespace options { }; class opt_bundle; - using pbundle = std::shared_ptr<opt_bundle>; - namespace { - using tt = std::tuple<int, pbundle>; + namespace + { + template<typename k, typename v, typename cnt = int> + struct opt_singleton + { + public: + using pbundle = std::shared_ptr<v>; + using tt = std::tuple<cnt, pbundle>; + private: + QMutex implsgl_mtx; + map<k, tt> implsgl_data; + public: + opt_singleton() : implsgl_mtx(QMutex::Recursive) {} + + pbundle bundle(const k& key) + { + QMutexLocker l(&implsgl_mtx); + + if (implsgl_data.count(key) != 0) + return std::get<1>(implsgl_data[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(); } + }; - QMutex implsgl_mtx(QMutex::Recursive); - map<QString, tt> implsgl_bundles; + using pbundle = std::shared_ptr<opt_bundle>; + using t_fact = opt_singleton<string, opt_bundle>; + static t_fact* opt_factory = new t_fact; } + + static inline t_fact::pbundle bundle(const string name) { return opt_factory->bundle(name); } class opt_bundle : public impl_bundle { public: opt_bundle() : impl_bundle("i-have-no-name") {} - opt_bundle(const QString& group_name) : impl_bundle(group_name) {} + opt_bundle(const string& group_name) : impl_bundle(group_name) {} ~opt_bundle() { - QMutexLocker l(&implsgl_mtx); - - if (--std::get<0>(implsgl_bundles[this->group_name]) == 0) - { - qDebug() << "bundle" << this->group_name << "not used anymore"; - implsgl_bundles.erase(this->group_name); - } + opt_factory->bundle_decf(this->group_name); } }; - - inline pbundle bundle(const QString& group) { - QMutexLocker l(&implsgl_mtx); - - if (implsgl_bundles.count(group) != 0) - return std::get<1>(implsgl_bundles[group]); - - auto shr = std::make_shared<opt_bundle>(group); - implsgl_bundles[group] = tt(1,shr); - return shr; - } class base_value : public QObject { Q_OBJECT #define DEFINE_SLOT(t) void setValue(t datum) { store(datum); } #define DEFINE_SIGNAL(t) void valueChanged(const t&) public: - base_value(pbundle b, const QString& name) : b(b), self_name(name), reentrancy_count(0) {} + base_value(pbundle b, const string& name) : b(b), self_name(name), reentrancy_count(0) {} protected: pbundle b; - QString self_name; + string self_name; template<typename t> void store(const t& datum) @@ -260,6 +286,12 @@ namespace options { DEFINE_SIGNAL(bool); DEFINE_SIGNAL(QString); }; + + static inline string string_from_qstring(const QString& datum) + { + auto tmp = datum.toUtf8(); + return string(tmp.constData()); + } template<typename t> class value : public base_value { @@ -271,11 +303,14 @@ namespace options { } static constexpr const Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection; static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::BlockingQueuedConnection; - value(pbundle b, const QString& name, t def) : base_value(b, name) + value(pbundle b, const string& name, t def) : base_value(b, name) { if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid) *this = def; } + value(pbundle b, const QString& name, t def) : value(b, string_from_qstring(name), def) {} + value(pbundle b, const char* name, t def) : value(b, string(name), def) {} + operator t() { return b->get<t>(self_name); |