/* Copyright (c) 2013-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 "bundle.hpp" #include "value.hpp" #include #include using options::base_value; namespace options { namespace detail { bundle::bundle(const QString& group_name) : mtx(QMutex::Recursive), group_name(group_name), saved(group_name), transient(saved) { } bundle::~bundle() { } void bundle::reload() { if (group_name.size()) { QMutexLocker l(&mtx); saved = group(group_name); const bool has_changes = is_modified(); transient = saved; if (has_changes) { connector::notify_all_values(); emit reloading(); emit changed(); } } } 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) { QMutexLocker l(&mtx); transient.put(name, datum); if (group_name.size()) connector::notify_values(name); emit changed(); } bool bundle::contains(const QString &name) const { QMutexLocker l(mtx); return transient.contains(name); } void bundle::save() { if (QThread::currentThread() != qApp->thread()) qDebug() << "group::save - current thread not ui thread"; if (group_name.size() == 0) return; bool modified_ = false; { QMutexLocker l(&mtx); if (is_modified()) { //qDebug() << "bundle" << group_name << "changed, saving"; modified_ = true; saved = transient; saved.save(); } } if (modified_) emit saving(); } bool bundle::is_modified() const { QMutexLocker l(mtx); for (const auto& kv : transient.kvs) { const QVariant other = saved.get(kv.first); if (!saved.contains(kv.first) || !is_equal(kv.first, kv.second, other)) { //if (logspam) // qDebug() << "bundle" << group_name << "modified" << "key" << kv.first << "-" << other << "<>" << kv.second; return true; } } for (const auto& kv : saved.kvs) { if (!transient.contains(kv.first)) { //if (logspam) // qDebug() << "bundle" << group_name << "modified" << "key" << kv.first << "-" << other << "<>" << kv.second; return true; } } return false; } void bundler::after_profile_changed_() { QMutexLocker l(&implsgl_mtx); for (auto& kv : implsgl_data) { weak bundle = kv.second; shared bundle_ = bundle.lock(); if (bundle_) { //qDebug() << "bundle: reverting" << kv.first << "due to profile change"; bundle_->reload(); } } } void bundler::refresh_all_bundles() { singleton().after_profile_changed_(); } bundler::bundler() : implsgl_mtx(QMutex::Recursive) { } bundler::~bundler() { //qDebug() << "exit: bundle singleton"; } std::shared_ptr bundler::make_bundle(const bundler::k& key) { QMutexLocker l(&implsgl_mtx); auto it = implsgl_data.find(key); if (it != implsgl_data.end()) { std::shared_ptr ptr = it->second.lock(); if (ptr != nullptr) return ptr; else qDebug() << "ERROR: nonexistent bundle" << key; } auto shr = shared(new v(key), [this, key](v* ptr) { QMutexLocker l(&implsgl_mtx); auto it = implsgl_data.find(key); if (it != implsgl_data.end()) implsgl_data.erase(it); else qDebug() << "ERROR: can't find self-bundle!"; delete ptr; }); implsgl_data[key] = weak(shr); return shr; } OTR_OPTIONS_EXPORT bundler& singleton() { static bundler ret; return ret; } QMutex* bundle::get_mtx() const { return mtx; } } // end options::detail OTR_OPTIONS_EXPORT std::shared_ptr make_bundle(const QString& name) { if (name.size()) return detail::singleton().make_bundle(name); else return std::make_shared(QString()); } } // end options