mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 21:48:46 +02:00
227 lines
6.5 KiB
C++
227 lines
6.5 KiB
C++
//
|
|
// SettingManager.cpp
|
|
//
|
|
//
|
|
// Created by Clement on 2/2/15.
|
|
// Copyright 2015 High Fidelity, Inc.
|
|
// Copyright 2022 Overte e.V.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
#include "SettingManager.h"
|
|
|
|
#include <QtCore/QThread>
|
|
#include <QtCore/QDebug>
|
|
#include <QtCore/QUuid>
|
|
|
|
#include "SettingInterface.h"
|
|
|
|
Q_LOGGING_CATEGORY(settings_manager, "settings.manager")
|
|
Q_LOGGING_CATEGORY(settings_writer, "settings.manager.writer")
|
|
|
|
namespace Setting {
|
|
|
|
|
|
void WriteWorker::start() {
|
|
// QSettings seems to have some issues with moving to a new thread.
|
|
// Make sure the object is only created once the thread is already up and running.
|
|
init();
|
|
}
|
|
|
|
void WriteWorker::setValue(const QString key, const QVariant value) {
|
|
//qCDebug(settings_writer) << "Setting config " << key << "to" << value;
|
|
|
|
init();
|
|
|
|
if (!_qSettings->contains(key) || _qSettings->value(key) != value) {
|
|
_qSettings->setValue(key, value);
|
|
}
|
|
}
|
|
|
|
void WriteWorker::removeKey(const QString key) {
|
|
init();
|
|
_qSettings->remove(key);
|
|
}
|
|
|
|
void WriteWorker::clearAllSettings() {
|
|
init();
|
|
_qSettings->clear();
|
|
sync();
|
|
}
|
|
|
|
void WriteWorker::sync() {
|
|
//qCDebug(settings_writer) << "Forcing settings sync";
|
|
init();
|
|
_qSettings->sync();
|
|
}
|
|
|
|
void WriteWorker::threadFinished() {
|
|
qCDebug(settings_writer) << "Settings write worker syncing and terminating";
|
|
sync();
|
|
this->deleteLater();
|
|
}
|
|
|
|
void WriteWorker::terminate() {
|
|
qCDebug(settings_writer) << "Settings write worker being asked to terminate. Syncing and terminating.";
|
|
sync();
|
|
this->deleteLater();
|
|
QThread::currentThread()->exit(0);
|
|
}
|
|
|
|
Manager::Manager(QObject *parent) {
|
|
WriteWorker *worker = new WriteWorker();
|
|
|
|
// We operate purely from memory, and forward all changes to a thread that has writing the
|
|
// settings as its only job.
|
|
|
|
qCDebug(settings_manager) << "Initializing settings write thread";
|
|
|
|
_workerThread.setObjectName("Settings Writer");
|
|
worker->moveToThread(&_workerThread);
|
|
// connect(&_workerThread, &QThread::started, worker, &WriteWorker::start, Qt::QueuedConnection);
|
|
|
|
// All normal connections are queued, so that we're sure they happen asynchronously.
|
|
connect(&_workerThread, &QThread::finished, worker, &WriteWorker::threadFinished, Qt::QueuedConnection);
|
|
connect(this, &Manager::valueChanged, worker, &WriteWorker::setValue, Qt::QueuedConnection);
|
|
connect(this, &Manager::keyRemoved, worker, &WriteWorker::removeKey, Qt::QueuedConnection);
|
|
connect(this, &Manager::syncRequested, worker, &WriteWorker::sync, Qt::QueuedConnection);
|
|
connect(this, &Manager::clearAllSettingsRequested, worker, &WriteWorker::clearAllSettings, Qt::QueuedConnection);
|
|
|
|
// This one is blocking because we want to wait until it's actually processed.
|
|
connect(this, &Manager::terminationRequested, worker, &WriteWorker::terminate, Qt::BlockingQueuedConnection);
|
|
|
|
|
|
_workerThread.start();
|
|
|
|
// Load all current settings
|
|
QSettings settings;
|
|
_fileName = settings.fileName();
|
|
|
|
for(QString key : settings.allKeys()) {
|
|
//qCDebug(settings_manager) << "Loaded key" << key << "with value" << settings.value(key);
|
|
_settings[key] = settings.value(key);
|
|
}
|
|
}
|
|
|
|
|
|
Manager::~Manager() {
|
|
|
|
}
|
|
|
|
// Custom deleter does nothing, because we need to shutdown later than the dependency manager
|
|
void Manager::customDeleter() { }
|
|
|
|
void Manager::registerHandle(Interface* handle) {
|
|
const QString& key = handle->getKey();
|
|
withWriteLock([&] {
|
|
if (_handles.contains(key)) {
|
|
qCWarning(settings_manager) << "Setting::Manager::registerHandle(): Key registered more than once, overriding: " << key;
|
|
}
|
|
_handles.insert(key, handle);
|
|
});
|
|
}
|
|
|
|
void Manager::removeHandle(const QString& key) {
|
|
withWriteLock([&] {
|
|
_handles.remove(key);
|
|
});
|
|
}
|
|
|
|
void Manager::loadSetting(Interface* handle) {
|
|
const auto& key = handle->getKey();
|
|
|
|
withWriteLock([&] {
|
|
QVariant loadedValue = _settings[key];
|
|
|
|
if (loadedValue.isValid()) {
|
|
handle->setVariant(loadedValue);
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
void Manager::saveSetting(Interface* handle) {
|
|
const auto& key = handle->getKey();
|
|
|
|
if (handle->isSet()) {
|
|
QVariant handleValue = handle->getVariant();
|
|
|
|
withWriteLock([&] {
|
|
_settings[key] = handleValue;
|
|
});
|
|
|
|
emit valueChanged(key, handleValue);
|
|
} else {
|
|
withWriteLock([&] {
|
|
_settings.remove(key);
|
|
});
|
|
|
|
emit keyRemoved(key);
|
|
}
|
|
|
|
}
|
|
|
|
void Manager::forceSave() {
|
|
emit syncRequested();
|
|
}
|
|
|
|
void Manager::terminateThread() {
|
|
qCDebug(settings_manager) << "Terminating settings writer thread";
|
|
|
|
emit terminationRequested(); // This blocks
|
|
|
|
_workerThread.exit();
|
|
_workerThread.wait(THREAD_TERMINATION_TIMEOUT);
|
|
qCDebug(settings_manager) << "Settings writer terminated";
|
|
}
|
|
|
|
QString Manager::fileName() const {
|
|
return resultWithReadLock<QString>([&] {
|
|
return _fileName;
|
|
});
|
|
}
|
|
|
|
void Manager::remove(const QString &key) {
|
|
withWriteLock([&] {
|
|
_settings.remove(key);
|
|
});
|
|
|
|
emit keyRemoved(key);
|
|
}
|
|
|
|
QStringList Manager::allKeys() const {
|
|
return resultWithReadLock<QStringList>([&] {
|
|
return _settings.keys();
|
|
});
|
|
}
|
|
|
|
bool Manager::contains(const QString &key) const {
|
|
return resultWithReadLock<bool>([&] {
|
|
return _settings.contains(key);
|
|
});
|
|
}
|
|
|
|
void Manager::setValue(const QString &key, const QVariant &value) {
|
|
withWriteLock([&] {
|
|
_settings[key] = value;
|
|
});
|
|
|
|
emit valueChanged(key, value);
|
|
}
|
|
|
|
QVariant Manager::value(const QString &key, const QVariant &defaultValue) const {
|
|
return resultWithReadLock<QVariant>([&] {
|
|
return _settings.value(key, defaultValue);
|
|
});
|
|
}
|
|
|
|
void Manager::clearAllSettings() {
|
|
withWriteLock([&] {
|
|
_settings.clear();
|
|
});
|
|
|
|
emit clearAllSettingsRequested();
|
|
}
|
|
}
|