diff --git a/js/misc/util.js b/js/misc/util.js index 7c6d11124..0221e15af 100644 --- a/js/misc/util.js +++ b/js/misc/util.js @@ -4,6 +4,8 @@ const Clutter = imports.gi.Clutter; const Gio = imports.gi.Gio; const GLib = imports.gi.GLib; const Lang = imports.lang; +const Mainloop = imports.mainloop; +const Signals = imports.signals; const Shell = imports.gi.Shell; const St = imports.gi.St; @@ -398,3 +400,94 @@ function ensureActorVisibleInScrollView(scrollView, actor) { time: SCROLL_TIME, transition: 'easeOutQuad' }); } + +const AppSettingsMonitor = new Lang.Class({ + Name: 'AppSettingsMonitor', + + _init: function(appId, schemaId) { + this._appId = appId; + this._schemaId = schemaId; + + this._app = null; + this._settings = null; + this._handlers = []; + + this._schemaSource = Gio.SettingsSchemaSource.get_default(); + + this._appSystem = Shell.AppSystem.get_default(); + this._appSystem.connect('installed-changed', + Lang.bind(this, this._onInstalledChanged)); + this._onInstalledChanged(); + }, + + get available() { + return this._app != null && this._settings != null; + }, + + activateApp: function() { + if (this._app) + this._app.activate(); + }, + + watchSetting: function(key, callback) { + let handler = { id: 0, key: key, callback: callback }; + this._handlers.push(handler); + + this._connectHandler(handler); + }, + + _connectHandler: function(handler) { + if (!this._settings || handler.id > 0) + return; + + handler.id = this._settings.connect('changed::' + handler.key, + handler.callback); + handler.callback(this._settings, handler.key); + }, + + _disconnectHandler: function(handler) { + if (this._settings && handler.id > 0) + this._settings.disconnect(handler.id); + handler.id = 0; + }, + + _onInstalledChanged: function() { + let hadApp = (this._app != null); + this._app = this._appSystem.lookup_app(this._appId); + let haveApp = (this._app != null); + + if (hadApp == haveApp) + return; + + if (haveApp) + this._checkSettings(); + else + this._setSettings(null); + }, + + _setSettings(settings) { + this._handlers.forEach((handler) => { this._disconnectHandler(handler); }); + + let hadSettings = (this._settings != null); + this._settings = settings; + let haveSettings = (this._settings != null); + + this._handlers.forEach((handler) => { this._connectHandler(handler); }); + + if (hadSettings != haveSettings) + this.emit('available-changed'); + }, + + _checkSettings: function() { + let schema = this._schemaSource.lookup(this._schemaId, true); + if (schema) { + this._setSettings(new Gio.Settings({ settings_schema: schema })); + } else if (this._app) { + Mainloop.timeout_add_seconds(1, () => { + this._checkSettings(); + return GLib.SOURCE_REMOVE; + }); + } + } +}); +Signals.addSignalMethods(AppSettingsMonitor.prototype);