Merge pull request #3503 from birarda/domain-wizard

lock changes to settings in the domain-server master config file
This commit is contained in:
AndrewMeadows 2014-09-29 15:41:29 -07:00
commit c8882d68dd
10 changed files with 96 additions and 63 deletions

View file

@ -116,7 +116,7 @@
"advanced": true "advanced": true
}, },
{ {
"name": "I-print-stream-stats", "name": "print-stream-stats",
"type": "checkbox", "type": "checkbox",
"label": "Print Stream Stats:", "label": "Print Stream Stats:",
"help": "audio upstream and downstream stats of each agent printed to audio-mixer stdout", "help": "audio upstream and downstream stats of each agent printed to audio-mixer stdout",

View file

@ -52,6 +52,10 @@ span.port {
color: red; color: red;
} }
.locked {
color: blue;
}
.advanced-setting { .advanced-setting {
display: none; display: none;
} }

View file

@ -3,9 +3,11 @@ var Settings = {
}; };
var viewHelpers = { var viewHelpers = {
getFormGroup: function(groupName, setting, values, isAdvanced) { getFormGroup: function(groupName, setting, values, isAdvanced, isLocked) {
setting_id = groupName + "_" + setting.name setting_id = groupName + "_" + setting.name
console.log(setting.name + " in " + groupName + " is " + isLocked)
form_group = "<div class='form-group" + (isAdvanced ? " advanced-setting" : "") + "'>" form_group = "<div class='form-group" + (isAdvanced ? " advanced-setting" : "") + "'>"
if (_.has(values, groupName) && _.has(values[groupName], setting.name)) { if (_.has(values, groupName) && _.has(values[groupName], setting.name)) {
@ -16,20 +18,26 @@ var viewHelpers = {
setting_value = "" setting_value = ""
} }
label_class = 'control-label'
if (isLocked) {
label_class += ' locked'
}
if (setting.type === 'checkbox') { if (setting.type === 'checkbox') {
form_group += "<label class='control-label'>" + setting.label + "</label>" form_group += "<label class='" + label_class + "'>" + setting.label + "</label>"
form_group += "<div class='checkbox'>" form_group += "<div class='checkbox" + (isLocked ? " disabled" : "") + "'>"
form_group += "<label for='" + setting_id + "'>" form_group += "<label for='" + setting_id + "'>"
form_group += "<input type='checkbox' id='" + setting_id + "' " + (setting_value ? "checked" : "") + "/>" form_group += "<input type='checkbox' id='" + setting_id + "' " +
(setting_value ? "checked" : "") + (isLocked ? " disabled" : "") + "/>"
form_group += " " + setting.help + "</label>"; form_group += " " + setting.help + "</label>";
form_group += "</div>" form_group += "</div>"
} else { } else {
input_type = _.has(setting, 'type') ? setting.type : "text" input_type = _.has(setting, 'type') ? setting.type : "text"
form_group += "<label for='" + setting_id + "' class='control-label'>" + setting.label + "</label>"; form_group += "<label for='" + setting_id + "' class='" + label_class + "'>" + setting.label + "</label>";
form_group += "<input type='" + input_type + "' class='form-control' id='" + setting_id + form_group += "<input type='" + input_type + "' class='form-control' id='" + setting_id +
"' placeholder='" + (_.has(setting, 'placeholder') ? setting.placeholder : "") + "' placeholder='" + (_.has(setting, 'placeholder') ? setting.placeholder : "") +
"' value='" + setting_value + "'/>" "' value='" + setting_value + "'" + (isLocked ? " disabled" : "") + "/>"
form_group += "<span class='help-block'>" + setting.help + "</span>" form_group += "<span class='help-block'>" + setting.help + "</span>"
} }
@ -101,6 +109,12 @@ function reloadSettings() {
$('#panels').html(Settings.panelsTemplate(data)) $('#panels').html(Settings.panelsTemplate(data))
Settings.initialValues = form2js('settings-form', "_", false, cleanupFormValues, true); Settings.initialValues = form2js('settings-form', "_", false, cleanupFormValues, true);
// add tooltip to locked settings
$('label.locked').tooltip({
placement: 'right',
title: 'This setting is in the master config file and cannot be changed'
})
}); });
} }

View file

@ -38,10 +38,12 @@
<div class="panel-body"> <div class="panel-body">
<% split_settings = _.partition(group.settings, function(value, index) { return !value.advanced }) %> <% split_settings = _.partition(group.settings, function(value, index) { return !value.advanced }) %>
<% _.each(split_settings[0], function(setting) { %> <% _.each(split_settings[0], function(setting) { %>
<%= getFormGroup(group.name, setting, values, false) %> <%= getFormGroup(group.name, setting, values, false,
(_.has(locked, group.name) && _.has(locked[group.name], setting.name))) %>
<% }); %> <% }); %>
<% _.each(split_settings[1], function(setting) { %> <% _.each(split_settings[1], function(setting) { %>
<%= getFormGroup(group.name, setting, values, true) %> <%= getFormGroup(group.name, setting, values, true,
(_.has(locked, group.name) && _.has(locked[group.name], setting.name))) %>
<% }); %> <% }); %>
</div> </div>
</div> </div>

View file

@ -57,7 +57,7 @@ DomainServer::DomainServer(int argc, char* argv[]) :
setApplicationName("domain-server"); setApplicationName("domain-server");
QSettings::setDefaultFormat(QSettings::IniFormat); QSettings::setDefaultFormat(QSettings::IniFormat);
_settingsManager.loadSettingsMap(arguments()); _settingsManager.setupConfigMap(arguments());
installNativeEventFilter(&_shutdownEventListener); installNativeEventFilter(&_shutdownEventListener);
connect(&_shutdownEventListener, SIGNAL(receivedCloseEvent()), SLOT(quit())); connect(&_shutdownEventListener, SIGNAL(receivedCloseEvent()), SLOT(quit()));

View file

@ -28,7 +28,7 @@ const QString SETTINGS_DESCRIPTION_RELATIVE_PATH = "/resources/describe-settings
DomainServerSettingsManager::DomainServerSettingsManager() : DomainServerSettingsManager::DomainServerSettingsManager() :
_descriptionArray(), _descriptionArray(),
_settingsMap() _configMap()
{ {
// load the description object from the settings description // load the description object from the settings description
QFile descriptionFile(QCoreApplication::applicationDirPath() + SETTINGS_DESCRIPTION_RELATIVE_PATH); QFile descriptionFile(QCoreApplication::applicationDirPath() + SETTINGS_DESCRIPTION_RELATIVE_PATH);
@ -37,11 +37,8 @@ DomainServerSettingsManager::DomainServerSettingsManager() :
_descriptionArray = QJsonDocument::fromJson(descriptionFile.readAll()).array(); _descriptionArray = QJsonDocument::fromJson(descriptionFile.readAll()).array();
} }
void DomainServerSettingsManager::loadSettingsMap(const QStringList& argumentList) { void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList) {
_settingsMap = HifiConfigVariantMap::mergeMasterConfigWithUserConfig(argumentList); _configMap.loadMasterAndUserConfig(argumentList);
// figure out where we are supposed to persist our settings to
_settingsFilepath = HifiConfigVariantMap::userConfigFilepath(argumentList);
} }
const QString SETTINGS_PATH = "/settings.json"; const QString SETTINGS_PATH = "/settings.json";
@ -76,7 +73,7 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection
QJsonObject postedObject = postedDocument.object(); QJsonObject postedObject = postedDocument.object();
// we recurse one level deep below each group for the appropriate setting // we recurse one level deep below each group for the appropriate setting
recurseJSONObjectAndOverwriteSettings(postedObject, _settingsMap, _descriptionArray); recurseJSONObjectAndOverwriteSettings(postedObject, _configMap.getUserConfig(), _descriptionArray);
// store whatever the current _settingsMap is to file // store whatever the current _settingsMap is to file
persistToFile(); persistToFile();
@ -94,10 +91,13 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection
// setup a JSON Object with descriptions and non-omitted settings // setup a JSON Object with descriptions and non-omitted settings
const QString SETTINGS_RESPONSE_DESCRIPTION_KEY = "descriptions"; const QString SETTINGS_RESPONSE_DESCRIPTION_KEY = "descriptions";
const QString SETTINGS_RESPONSE_VALUE_KEY = "values"; const QString SETTINGS_RESPONSE_VALUE_KEY = "values";
const QString SETTINGS_RESPONSE_LOCKED_VALUES_KEY = "locked";
QJsonObject rootObject; QJsonObject rootObject;
rootObject[SETTINGS_RESPONSE_DESCRIPTION_KEY] = _descriptionArray; rootObject[SETTINGS_RESPONSE_DESCRIPTION_KEY] = _descriptionArray;
rootObject[SETTINGS_RESPONSE_VALUE_KEY] = responseObjectForType("", true); rootObject[SETTINGS_RESPONSE_VALUE_KEY] = responseObjectForType("", true);
rootObject[SETTINGS_RESPONSE_LOCKED_VALUES_KEY] = QJsonDocument::fromVariant(_configMap.getMasterConfig()).object();
connection->respond(HTTPConnection::StatusCode200, QJsonDocument(rootObject).toJson(), "application/json"); connection->respond(HTTPConnection::StatusCode200, QJsonDocument(rootObject).toJson(), "application/json");
} }
@ -145,7 +145,8 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty
// we need to check if the settings map has a value for this setting // we need to check if the settings map has a value for this setting
QVariant variantValue; QVariant variantValue;
QVariant settingsMapGroupValue = _settingsMap.value(groupObject[DESCRIPTION_NAME_KEY].toString()); QVariant settingsMapGroupValue = _configMap.getMergedConfig()
.value(groupObject[DESCRIPTION_NAME_KEY].toString());
if (!settingsMapGroupValue.isNull()) { if (!settingsMapGroupValue.isNull()) {
variantValue = settingsMapGroupValue.toMap().value(settingName); variantValue = settingsMapGroupValue.toMap().value(settingName);
@ -239,23 +240,19 @@ void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
} }
} }
QByteArray DomainServerSettingsManager::getJSONSettingsMap() const {
return QJsonDocument::fromVariant(_settingsMap).toJson();
}
void DomainServerSettingsManager::persistToFile() { void DomainServerSettingsManager::persistToFile() {
// make sure we have the dir the settings file is supposed to live in // make sure we have the dir the settings file is supposed to live in
QFileInfo settingsFileInfo(_settingsFilepath); QFileInfo settingsFileInfo(_configMap.getUserConfigFilename());
if (!settingsFileInfo.dir().exists()) { if (!settingsFileInfo.dir().exists()) {
settingsFileInfo.dir().mkpath("."); settingsFileInfo.dir().mkpath(".");
} }
QFile settingsFile(_settingsFilepath); QFile settingsFile(_configMap.getUserConfigFilename());
if (settingsFile.open(QIODevice::WriteOnly)) { if (settingsFile.open(QIODevice::WriteOnly)) {
settingsFile.write(getJSONSettingsMap()); settingsFile.write(QJsonDocument::fromVariant(_configMap.getUserConfig()).toJson());
} else { } else {
qCritical("Could not write to JSON settings file. Unable to persist settings."); qCritical("Could not write to JSON settings file. Unable to persist settings.");
} }

View file

@ -15,6 +15,7 @@
#include <QtCore/QJsonArray> #include <QtCore/QJsonArray>
#include <QtCore/QJsonDocument> #include <QtCore/QJsonDocument>
#include <HifiConfigVariantMap.h>
#include <HTTPManager.h> #include <HTTPManager.h>
class DomainServerSettingsManager : public QObject { class DomainServerSettingsManager : public QObject {
@ -24,10 +25,9 @@ public:
bool handlePublicHTTPRequest(HTTPConnection* connection, const QUrl& url); bool handlePublicHTTPRequest(HTTPConnection* connection, const QUrl& url);
bool handleAuthenticatedHTTPRequest(HTTPConnection* connection, const QUrl& url); bool handleAuthenticatedHTTPRequest(HTTPConnection* connection, const QUrl& url);
void loadSettingsMap(const QStringList& argumentList); void setupConfigMap(const QStringList& argumentList);
QByteArray getJSONSettingsMap() const; QVariantMap& getSettingsMap() { return _configMap.getMergedConfig(); }
QVariantMap& getSettingsMap() { return _settingsMap; }
private: private:
QJsonObject responseObjectForType(const QString& typeValue, bool isAuthenticated = false); QJsonObject responseObjectForType(const QString& typeValue, bool isAuthenticated = false);
void recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject, QVariantMap& settingsVariant, void recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject, QVariantMap& settingsVariant,
@ -35,8 +35,7 @@ private:
void persistToFile(); void persistToFile();
QJsonArray _descriptionArray; QJsonArray _descriptionArray;
QVariantMap _settingsMap; HifiConfigVariantMap _configMap;
QString _settingsFilepath;
}; };
#endif // hifi_DomainServerSettingsManager_h #endif // hifi_DomainServerSettingsManager_h

View file

@ -303,9 +303,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
// connect to the domainChangeRequired signal on AddressManager // connect to the domainChangeRequired signal on AddressManager
connect(&addressManager, &AddressManager::possibleDomainChangeRequired, connect(&addressManager, &AddressManager::possibleDomainChangeRequired,
this, &Application::changeDomainHostname); this, &Application::changeDomainHostname);
// when -url in command line, teleport to location
addressManager.handleLookupString(getCmdOption(argc, constArgv, "-url"));
_settings = new QSettings(this); _settings = new QSettings(this);
_numChangedSettings = 0; _numChangedSettings = 0;
@ -1797,7 +1794,14 @@ void Application::init() {
Menu::getInstance()->loadSettings(); Menu::getInstance()->loadSettings();
_audio.setReceivedAudioStreamSettings(Menu::getInstance()->getReceivedAudioStreamSettings()); _audio.setReceivedAudioStreamSettings(Menu::getInstance()->getReceivedAudioStreamSettings());
qDebug("Loaded settings"); qDebug() << "Loaded settings";
// when --url in command line, teleport to location
const QString HIFI_URL_COMMAND_LINE_KEY = "--url";
int urlIndex = arguments().indexOf(HIFI_URL_COMMAND_LINE_KEY);
if (urlIndex != -1) {
AddressManager::getInstance().handleLookupString(arguments().value(urlIndex + 1));
}
// initialize our face trackers after loading the menu settings // initialize our face trackers after loading the menu settings
_faceshift.init(); _faceshift.init();

View file

@ -87,43 +87,48 @@ QVariantMap HifiConfigVariantMap::mergeCLParametersWithJSONConfig(const QStringL
return mergedMap; return mergedMap;
} }
QVariantMap HifiConfigVariantMap::mergeMasterConfigWithUserConfig(const QStringList& argumentList) { HifiConfigVariantMap::HifiConfigVariantMap() :
_userConfigFilename(),
_masterConfig(),
_userConfig(),
_mergedConfig()
{
}
void HifiConfigVariantMap::loadMasterAndUserConfig(const QStringList& argumentList) {
// check if there is a master config file // check if there is a master config file
const QString MASTER_CONFIG_FILE_OPTION = "--master-config"; const QString MASTER_CONFIG_FILE_OPTION = "--master-config";
QVariantMap configVariantMap;
int masterConfigIndex = argumentList.indexOf(MASTER_CONFIG_FILE_OPTION); int masterConfigIndex = argumentList.indexOf(MASTER_CONFIG_FILE_OPTION);
if (masterConfigIndex != -1) { if (masterConfigIndex != -1) {
QString masterConfigFilepath = argumentList[masterConfigIndex + 1]; QString masterConfigFilepath = argumentList[masterConfigIndex + 1];
mergeMapWithJSONFile(configVariantMap, masterConfigFilepath); loadMapFromJSONFile(_masterConfig, masterConfigFilepath);
} }
// merge the existing configVariantMap with the user config file // load the user config
mergeMapWithJSONFile(configVariantMap, userConfigFilepath(argumentList));
return configVariantMap;
}
QString HifiConfigVariantMap::userConfigFilepath(const QStringList& argumentList) {
// we've loaded up the master config file, now fill in anything it didn't have with the user config file
const QString USER_CONFIG_FILE_OPTION = "--user-config"; const QString USER_CONFIG_FILE_OPTION = "--user-config";
int userConfigIndex = argumentList.indexOf(USER_CONFIG_FILE_OPTION); int userConfigIndex = argumentList.indexOf(USER_CONFIG_FILE_OPTION);
QString userConfigFilepath;
if (userConfigIndex != -1) { if (userConfigIndex != -1) {
userConfigFilepath = argumentList[userConfigIndex + 1]; _userConfigFilename = argumentList[userConfigIndex + 1];
} else { } else {
userConfigFilepath = QString("%1/%2/%3/config.json").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), _userConfigFilename = QString("%1/%2/%3/config.json").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation),
QCoreApplication::organizationName(), QCoreApplication::organizationName(),
QCoreApplication::applicationName()); QCoreApplication::applicationName());
} }
return userConfigFilepath; loadMapFromJSONFile(_userConfig, _userConfigFilename);
// the merged config is initially matched to the master config
_mergedConfig = _masterConfig;
// then we merge in anything missing from the user config
addMissingValuesToExistingMap(_mergedConfig, _userConfig);
} }
void HifiConfigVariantMap::mergeMapWithJSONFile(QVariantMap& existingMap, const QString& filename) { void HifiConfigVariantMap::loadMapFromJSONFile(QVariantMap& existingMap, const QString& filename) {
QFile configFile(filename); QFile configFile(filename);
if (configFile.exists()) { if (configFile.exists()) {
@ -131,12 +136,7 @@ void HifiConfigVariantMap::mergeMapWithJSONFile(QVariantMap& existingMap, const
configFile.open(QIODevice::ReadOnly); configFile.open(QIODevice::ReadOnly);
QJsonDocument configDocument = QJsonDocument::fromJson(configFile.readAll()); QJsonDocument configDocument = QJsonDocument::fromJson(configFile.readAll());
existingMap = configDocument.toVariant().toMap();
if (existingMap.isEmpty()) {
existingMap = configDocument.toVariant().toMap();
} else {
addMissingValuesToExistingMap(existingMap, configDocument.toVariant().toMap());
}
} else { } else {
qDebug() << "Could not find JSON config file at" << filename; qDebug() << "Could not find JSON config file at" << filename;

View file

@ -17,11 +17,24 @@
class HifiConfigVariantMap { class HifiConfigVariantMap {
public: public:
static QVariantMap mergeCLParametersWithJSONConfig(const QStringList& argumentList); static QVariantMap mergeCLParametersWithJSONConfig(const QStringList& argumentList);
static QVariantMap mergeMasterConfigWithUserConfig(const QStringList& argumentList);
static QString userConfigFilepath(const QStringList& argumentList); HifiConfigVariantMap();
void loadMasterAndUserConfig(const QStringList& argumentList);
const QVariantMap& getMasterConfig() const { return _masterConfig; }
QVariantMap& getUserConfig() { return _userConfig; }
QVariantMap& getMergedConfig() { return _mergedConfig; }
const QString& getUserConfigFilename() const { return _userConfigFilename; }
private: private:
static void mergeMapWithJSONFile(QVariantMap& existingMap, const QString& filename); QString _userConfigFilename;
static void addMissingValuesToExistingMap(QVariantMap& existingMap, const QVariantMap& newMap);
QVariantMap _masterConfig;
QVariantMap _userConfig;
QVariantMap _mergedConfig;
void loadMapFromJSONFile(QVariantMap& existingMap, const QString& filename);
void addMissingValuesToExistingMap(QVariantMap& existingMap, const QVariantMap& newMap);
}; };
const QVariant* valueForKeyPath(QVariantMap& variantMap, const QString& keyPath); const QVariant* valueForKeyPath(QVariantMap& variantMap, const QString& keyPath);