iso-profiles-settings/tromjaro/gnome/live-overlay/etc/skel/.local/share/gnome-shell/extensions/todo.txt@bart.libert.gmail.com/settings.js
2019-07-09 04:57:09 +03:00

490 lines
16 KiB
JavaScript

const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Params = imports.misc.params;
const Extension = imports.misc.extensionUtils.getCurrentExtension();
const Errors = Extension.imports.errors;
const File = Extension.imports.jsTextFile.JsTextFile;
const Utils = Extension.imports.utils;
var Settings = new Lang.Class({
Name: 'Settings',
_loadedSettings: null,
_settings: null,
_connectedSignals: [],
logger: null,
_jsonFileToDictionary: function(settingsFile) {
if (settingsFile === undefined) {
settingsFile = Extension.path + '/settings.json';
}
let jsonFile = new File(settingsFile);
try {
return JSON.parse(jsonFile.getLines().join(''));
}
catch (err) {
if (err.name == 'SyntaxError') {
throw new Errors.JsonError(settingsFile + ' is not a valid JSON file');
}
throw err;
}
},
_createGioSettings: function(schema, schemaDir) {
if (Utils.isValid(schemaDir)) {
schemaDir = Gio.File.new_for_path(schemaDir);
}
else {
schemaDir = Extension.dir.get_child('schemas');
}
let schemaSource;
const GioSSS = Gio.SettingsSchemaSource;
if (schemaDir.query_exists(null)) {
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(), GioSSS.get_default(), false);
}
else {
schemaSource = GioSSS.get_default();
}
let schemaObj = schemaSource.lookup(schema, true);
if (!schemaObj) {
throw new Error('Schema ' + schema + ' could not be found for extension ' + Extension.metadata.uuid +
'. Please check your installation.');
}
this._settings = new Gio.Settings({
settings_schema: schemaObj
});
},
_getFlatRecursive: function(toFlatten, resultDict) {
for (let element in toFlatten) {
if (toFlatten.hasOwnProperty(element)) {
if (element == 'type') {
continue;
}
if (this._isContainer(toFlatten[element])) {
resultDict[element] = toFlatten[element];
this._getFlatRecursive(toFlatten[element], resultDict);
continue;
}
resultDict[element] = toFlatten[element];
}
}
},
_getFlatSettings: function() {
let resultDict = {};
this._getFlatRecursive(this._loadedSettings, resultDict);
return resultDict;
},
_init: function(params) {
let parameters = Params.parse(params, {
settingsFile: undefined,
schema: null,
schemaDir: null,
logger: null
});
if (typeof parameters.logger == 'undefined' || parameters.logger === null) {
this.logger = Utils.getDefaultLogger();
this.logger.warning('Using default logger instead of injected one');
}
else {
this.logger = parameters.logger;
}
this._loadedSettings = this._jsonFileToDictionary(parameters.settingsFile);
this._flatSettings = this._getFlatSettings();
this._createGioSettings(parameters.schema, parameters.schemaDir);
this._connectedSignals = [];
},
_getProperty: function(element, property, errorValue, inCategory) {
let setting = this._getSetting(element, inCategory);
if (!Utils.isChildValid(setting, property)) {
return errorValue;
}
return setting[property];
},
getType: function(name, inCategory) {
return this._getProperty(name, 'type', null, inCategory);
},
getValueObject: function(setting) {
return this._getProperty(setting, 'value_object', null);
},
getSignature: function(setting) {
return this._getProperty(setting, 'signature', null);
},
exists: function(setting) {
return Utils.isValid(this._getSetting(setting));
},
_translatePath: function(path) {
return path.replace('$HOME', GLib.get_home_dir()).replace('~', GLib.get_home_dir());
},
_getFromSchema: function(setting) {
if (this.getType(setting) == 'boolean') {
return this._settings.get_boolean(setting);
}
if (this.getType(setting) == 'string') {
return this._settings.get_string(setting);
}
if (this.getType(setting) == 'path') {
return this._translatePath(this._settings.get_string(setting));
}
if (this.getType(setting) == 'integer') {
return this._settings.get_int(setting);
}
if (this.getType(setting) == 'dictionary') {
let valueObject = this.getValueObject(setting);
let value = this._settings.get_value(setting);
if (valueObject !== null) {
let dictionary = value.unpack();
let valueArray = valueObject.split('.');
let ctr = Extension.imports;
for (let element in valueArray) {
if (valueArray.hasOwnProperty(element)) {
ctr = ctr[valueArray[element]];
}
}
for (let key in dictionary) {
if (dictionary.hasOwnProperty(key)) {
dictionary[key] = new ctr(dictionary[key]);
}
}
return dictionary;
}
return value.deep_unpack();
}
if (this.getType(setting) == 'shortcut') {
return this._settings.get_strv(setting)[0];
}
return null;
},
_keyExistsInSchema: function(setting) {
return (this._settings.list_keys().indexOf(setting) != -1);
},
_jsonHasDefault: function(setting) {
return Utils.isChildValid(this._getSetting(setting), 'default_value');
},
_getDefaultFromJson: function(setting) {
return this._getProperty(setting, 'default_value', null);
},
_getTypeBasedDefault: function(setting) {
if (this.getType(setting) == 'boolean') {
return false;
}
if (this.getType(setting) == 'string') {
return '';
}
if (this.getType(setting) == 'path') {
return this._translatePath('~');
}
if (this.getType(setting) == 'integer') {
return 0;
}
if (this.getType(setting) == 'dictionary') {
return [];
}
this.logger.error('Could not return correct value for ' + setting);
return null;
},
get: function(setting) {
if (this.getType(setting) === null) {
return null;
}
if (this._keyExistsInSchema(setting)) {
return this._getFromSchema(setting);
}
if (this._jsonHasDefault(setting)) {
this.logger.info(setting + ' not found in schema, using default value from json file');
return this._getDefaultFromJson(setting);
}
this.logger.info(setting + ' not found in schema, trying to use type-based default value');
return this._getTypeBasedDefault(setting);
},
set: function(setting, value) {
this.logger.debug('Setting ' + setting + ' to ' + value);
if (this.getType(setting) == 'boolean') {
this._settings.set_boolean(setting, value);
return;
}
if (this.getType(setting) == 'string' || this.getType(setting) == 'path') {
if (typeof value == 'string') {
this._settings.set_string(setting, value);
return;
}
else {
throw new Errors.SettingsTypeError(setting, 'string', value);
}
}
if (this.getType(setting) == 'integer') {
if (typeof value == 'number') {
this._settings.set_int(setting, value);
return;
}
else {
throw new Errors.SettingsTypeError(setting, 'integer', value);
}
}
if (this.getType(setting) == 'dictionary') {
let variant = null;
if (this.getValueObject(setting) !== null) {
let keyType = new GLib.VariantType(this.getSignature(setting)).element().key();
let dictToWrite = [];
for (let key in value) {
if (value.hasOwnProperty(key)) {
dictToWrite.push(GLib.Variant.new_dict_entry(new GLib.Variant(keyType.dup_string(),
key), value[key].toVariant()));
}
}
variant = GLib.Variant.new_array(null, dictToWrite);
}
else {
variant = new GLib.Variant(this.getSignature(setting), value);
}
this._settings.set_value(setting, variant);
return;
}
if (this.getType(setting) == 'shortcut') {
this._settings.set_strv(setting, [value]);
return;
}
this.logger.error('Trying to set non-existing setting ' + setting);
},
getGioSettings: function() {
return this._settings;
},
registerForChange: function(setting, callback) {
this.logger.debug('Registering ' + callback + ' for ' + setting);
try {
this._connectedSignals.push(this._settings.connect('changed::' + setting, callback));
}
catch (err) {
this.logger.error('Could not register for changed signal on setting ' + setting + ' : ' + err);
}
},
unregisterCallbacks: function() {
if (this._connectedSignals !== null) {
this._connectedSignals.forEach(Lang.bind(this, function(signal) {
if (signal !== undefined && signal !== null && signal !== 0) {
this._settings.disconnect(signal);
}
}));
}
this._connectedSignals = [];
},
getCategory: function(name) {
let [setting, category, subcontainer] = this._recursiveSearch(name, this._loadedSettings);
if (!Utils.isValid(setting)) {
return null;
}
return category;
},
getSubContainer: function(name) {
let [setting, category, subcontainer] = this._recursiveSearch(name, this._loadedSettings);
if (!Utils.isValid(setting)) {
return null;
}
if (Utils.isValid(this._loadedSettings[category][name])) {
// TODO: the recursive search function should handle this case
return null;
}
return subcontainer;
},
getAllInCategory: function(category) {
if (!Utils.isValid(this._loadedSettings[category])) {
return [];
}
let toReturn = [];
let catArr = this._loadedSettings[category];
for (let key in catArr) {
if (catArr.hasOwnProperty(key)) {
if (key == 'type') {
continue;
}
if (this._isSubcontainer(catArr[key])) {
for (let subkey in catArr[key]) {
if (catArr[key].hasOwnProperty(subkey)) {
if (subkey == 'type') {
continue;
}
toReturn.push([subkey, catArr[key][subkey]]);
}
}
continue;
}
toReturn.push([key, catArr[key]]);
}
}
return toReturn;
},
getAllInSubcontainer: function(category, subcontainer) {
if (!Utils.isChildValid(this._loadedSettings[category], subcontainer)) {
return [];
}
let toReturn = [];
for (let key in this._loadedSettings[category][subcontainer]) {
if (this._loadedSettings[category][subcontainer].hasOwnProperty(key)) {
if (key == 'type') {
continue;
}
toReturn.push([key, this._loadedSettings[key]]);
}
}
return toReturn;
},
getAll: function(type) {
let toReturn = [];
for (let setting in this._flatSettings) {
if (this.getType(setting) == type) {
toReturn.push([setting, this._loadedSettings[setting]]);
}
}
return toReturn;
},
getAllCategories: function() {
let toReturn = [];
for (let category in this.getAll('category')) {
if (this.getAll('category').hasOwnProperty(category)) {
toReturn.push(this.getAll('category')[category][0]);
}
}
return toReturn;
},
getAllSubContainers: function(category) {
let toReturn = [];
for (let element in this._loadedSettings[category]) {
if (this._loadedSettings[category].hasOwnProperty(element)) {
if (element == 'type') {
continue;
}
let subElement = this._loadedSettings[category][element];
if (!Utils.isValid(subElement.type)) {
continue;
}
if (this._isSubcontainer(subElement)) {
toReturn.push(element);
}
}
}
return toReturn;
},
getSummary: function(setting) {
return this._getProperty(setting, 'summary', '');
},
getHumanName: function(setting) {
return this._getProperty(setting, 'human_name', setting);
},
getHelp: function(setting) {
return this._getProperty(setting, 'help', '');
},
getExtraParams: function(setting) {
return this._getProperty(setting, 'extra_params', null);
},
getWidget: function(setting) {
return this._getProperty(setting, 'widget', 'default');
},
getLevel: function(setting) {
return this._getProperty(setting, 'level', '0');
},
_isContainer: function(element) {
if (Object.prototype.hasOwnProperty.call(element, 'type') && element.type == 'category') {
return true;
}
return this._isSubcontainer(element);
},
_isSubcontainer: function(element) {
if (Object.prototype.hasOwnProperty.call(element, 'type') && element.type == 'subcategory') {
return true;
}
if (Object.prototype.hasOwnProperty.call(element, 'type') && element.type == 'subsection') {
return true;
}
return false;
},
_recursiveSearch: function(needle, haystack, lastCategory, lastSubcontainer) {
lastCategory = Utils.getDefaultIfInvalid(lastCategory, null);
lastSubcontainer = Utils.getDefaultIfInvalid(lastSubcontainer, null);
for (let element in haystack) {
if (haystack.hasOwnProperty(element)) {
let result = null;
if (this._isContainer(haystack[element])) {
if (this._isSubcontainer(haystack[element])) {
lastSubcontainer = element;
}
else {
lastCategory = element;
}
[result, lastCategory, lastSubcontainer] = this._recursiveSearch(needle, haystack[element],
lastCategory, lastSubcontainer);
}
if (element == needle) {
result = haystack[element];
}
if (result !== null) {
return [result, lastCategory, lastSubcontainer];
}
}
}
return [null, lastCategory, lastSubcontainer];
},
_getSetting: function(name, inCategory) {
let searchRoot = Utils.getFirstValidChild(this, ['_loadedSettings.inCategory', '_loadedSettings']);
let [setting, category, subcontainer] = this._recursiveSearch(name, searchRoot);
if (setting === null) {
this.logger.info('Non-existing setting requested: ' + name);
}
return setting;
},
hasSubcategories: function(category) {
let subcontainers = this.getAllSubContainers(category);
for (let i in subcontainers) {
if (this._getSetting(subcontainers[i]).type == 'subcategory') {
return true;
}
}
return false;
}
});
/* vi: set expandtab tabstop=4 shiftwidth=4: */