overte/libraries/shared/src/SettingManager.cpp
Atlante45 80c0f2a21e Fix crash when passing --checkMinSpec flag
That flag caused a DLL to be loaded before Application was
	instanced.
	This triggers a Qt bug inside Q_COREAPP_STARTUP_FUNC that causes
	the previous registration pointing the startup function in
	the main executable to be overridden with the address of the
	function in the DLL (Since they both link the same static
	library)
	This leads to the correct function running in the wrong address
	space (the DLLs), hence not initializing some global variables
	correctly.
2018-02-22 16:29:38 -08:00

123 lines
3.4 KiB
C++

//
// SettingManager.cpp
//
//
// Created by Clement on 2/2/15.
// Copyright 2015 High Fidelity, Inc.
//
// 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"
namespace Setting {
Manager::~Manager() {
// Cleanup timer
stopTimer();
delete _saveTimer;
_saveTimer = nullptr;
}
// 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)) {
qWarning() << "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;
if (_pendingChanges.contains(key) && _pendingChanges[key] != UNSET_VALUE) {
loadedValue = _pendingChanges[key];
} else {
loadedValue = value(key);
}
if (loadedValue.isValid()) {
handle->setVariant(loadedValue);
}
});
}
void Manager::saveSetting(Interface* handle) {
const auto& key = handle->getKey();
QVariant handleValue = UNSET_VALUE;
if (handle->isSet()) {
handleValue = handle->getVariant();
}
withWriteLock([&] {
_pendingChanges[key] = handleValue;
});
}
static const int SAVE_INTERVAL_MSEC = 5 * 1000; // 5 sec
void Manager::startTimer() {
if (!_saveTimer) {
_saveTimer = new QTimer(this);
Q_CHECK_PTR(_saveTimer);
_saveTimer->setSingleShot(true); // We will restart it once settings are saved.
_saveTimer->setInterval(SAVE_INTERVAL_MSEC); // 5s, Qt::CoarseTimer acceptable
connect(_saveTimer, SIGNAL(timeout()), this, SLOT(saveAll()));
}
_saveTimer->start();
}
void Manager::stopTimer() {
if (_saveTimer) {
_saveTimer->stop();
}
}
void Manager::saveAll() {
bool forceSync = false;
withWriteLock([&] {
for (auto key : _pendingChanges.keys()) {
auto newValue = _pendingChanges[key];
auto savedValue = value(key, UNSET_VALUE);
if (newValue == savedValue) {
continue;
}
if (newValue == UNSET_VALUE || !newValue.isValid()) {
forceSync = true;
remove(key);
} else {
forceSync = true;
setValue(key, newValue);
}
}
_pendingChanges.clear();
});
if (forceSync) {
sync();
}
// Restart timer
if (_saveTimer) {
_saveTimer->start();
}
}
}