extensionPrefs: Attach extension object to each row

Each row represents an extension, so it makes sense to associate the
rows with the actual extensions instead of linking rows and extensions
by looking up the UUID in the external extensions map in ExtensionUtils.

This will also make it much easier to stop using the shared extension
loading / map in favor of the extension D-Bus API.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
This commit is contained in:
Didier Roche 2018-11-01 13:50:30 +01:00 committed by Florian Müllner
parent 4a3476266f
commit a7ec7583aa

View File

@ -27,59 +27,36 @@ var Application = GObject.registerClass({
flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE
}); });
this._extensionPrefsModules = {};
this._startupUuid = null; this._startupUuid = null;
this._loaded = false; this._loaded = false;
this._skipMainWindow = false; this._skipMainWindow = false;
} }
_extensionAvailable(uuid) { _showPrefs(uuid) {
let extension = ExtensionUtils.extensions[uuid]; let row = this._extensionSelector.get_children().find(c => {
return c.uuid === uuid && c.hasPrefs;
});
if (!extension) if (!row)
return false; return false;
if (!extension.dir.get_child('prefs.js').query_exists(null))
return false;
return true;
}
_getExtensionPrefsModule(extension) {
let uuid = extension.metadata.uuid;
if (this._extensionPrefsModules.hasOwnProperty(uuid))
return this._extensionPrefsModules[uuid];
ExtensionUtils.installImporter(extension);
let prefsModule = extension.imports.prefs;
prefsModule.init(extension.metadata);
this._extensionPrefsModules[uuid] = prefsModule;
return prefsModule;
}
_selectExtension(uuid) {
if (!this._extensionAvailable(uuid))
return;
let extension = ExtensionUtils.extensions[uuid];
let widget; let widget;
try { try {
let prefsModule = this._getExtensionPrefsModule(extension); widget = row.prefsModule.buildPrefsWidget();
widget = prefsModule.buildPrefsWidget();
} catch (e) { } catch (e) {
widget = this._buildErrorUI(extension, e); widget = this._buildErrorUI(row, e);
} }
let dialog = new Gtk.Window({ modal: !this._skipMainWindow, let dialog = new Gtk.Window({
type_hint: Gdk.WindowTypeHint.DIALOG }); modal: !this._skipMainWindow,
dialog.set_titlebar(new Gtk.HeaderBar({ show_close_button: true, type_hint: Gdk.WindowTypeHint.DIALOG
title: extension.metadata.name, });
visible: true })); dialog.set_titlebar(new Gtk.HeaderBar({
show_close_button: true,
title: row.name,
visible: true
}));
if (this._skipMainWindow) { if (this._skipMainWindow) {
this.add_window(dialog); this.add_window(dialog);
@ -96,7 +73,7 @@ var Application = GObject.registerClass({
dialog.show(); dialog.show();
} }
_buildErrorUI(extension, exc) { _buildErrorUI(row, exc) {
let scroll = new Gtk.ScrolledWindow({ let scroll = new Gtk.ScrolledWindow({
hscrollbar_policy: Gtk.PolicyType.NEVER, hscrollbar_policy: Gtk.PolicyType.NEVER,
propagate_natural_height: true propagate_natural_height: true
@ -168,7 +145,7 @@ var Application = GObject.registerClass({
let clipboard = Gtk.Clipboard.get_default(w.get_display()); let clipboard = Gtk.Clipboard.get_default(w.get_display());
// markdown for pasting in gitlab issues // markdown for pasting in gitlab issues
let lines = [ let lines = [
`The settings of extension ${extension.uuid} had an error:`, `The settings of extension ${row.uuid} had an error:`,
'```', '```',
`${exc}`, `${exc}`,
'```', '```',
@ -190,13 +167,13 @@ var Application = GObject.registerClass({
label: _("Homepage"), label: _("Homepage"),
tooltip_text: _("Visit extension homepage"), tooltip_text: _("Visit extension homepage"),
no_show_all: true, no_show_all: true,
visible: extension.metadata.url != null visible: row.url != null
}); });
toolbar.add(urlButton); toolbar.add(urlButton);
urlButton.connect('clicked', w => { urlButton.connect('clicked', w => {
let context = w.get_display().get_app_launch_context(); let context = w.get_display().get_app_launch_context();
Gio.AppInfo.launch_default_for_uri(extension.metadata.url, context); Gio.AppInfo.launch_default_for_uri(row.url, context);
}); });
let expandedBox = new Gtk.Box({ let expandedBox = new Gtk.Box({
@ -255,9 +232,7 @@ var Application = GObject.registerClass({
} }
_sortList(row1, row2) { _sortList(row1, row2) {
let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name; return row1.name.localeCompare(row2.name);
let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name;
return name1.localeCompare(name2);
} }
_updateHeader(row, before) { _updateHeader(row, before) {
@ -276,11 +251,10 @@ var Application = GObject.registerClass({
} }
_extensionFound(finder, extension) { _extensionFound(finder, extension) {
let row = new ExtensionRow(extension.uuid); let row = new ExtensionRow(extension);
row.prefsButton.visible = this._extensionAvailable(row.uuid);
row.prefsButton.connect('clicked', () => { row.prefsButton.connect('clicked', () => {
this._selectExtension(row.uuid); this._showPrefs(row.uuid);
}); });
row.show_all(); row.show_all();
@ -293,8 +267,8 @@ var Application = GObject.registerClass({
else else
this._mainStack.visible_child_name = 'placeholder'; this._mainStack.visible_child_name = 'placeholder';
if (this._startupUuid && this._extensionAvailable(this._startupUuid)) if (this._startupUuid)
this._selectExtension(this._startupUuid); this._showPrefs(this._startupUuid);
this._startupUuid = null; this._startupUuid = null;
this._skipMainWindow = false; this._skipMainWindow = false;
this._loaded = true; this._loaded = true;
@ -323,11 +297,9 @@ var Application = GObject.registerClass({
// Strip off "extension:///" prefix which fakes a URI, if it exists // Strip off "extension:///" prefix which fakes a URI, if it exists
uuid = stripPrefix(uuid, "extension:///"); uuid = stripPrefix(uuid, "extension:///");
if (this._extensionAvailable(uuid)) if (!this._loaded)
this._selectExtension(uuid);
else if (!this._loaded)
this._startupUuid = uuid; this._startupUuid = uuid;
else else if (!this._showPrefs(uuid))
this._skipMainWindow = false; this._skipMainWindow = false;
} }
return 0; return 0;
@ -511,10 +483,11 @@ class DescriptionLabel extends Gtk.Label {
var ExtensionRow = GObject.registerClass( var ExtensionRow = GObject.registerClass(
class ExtensionRow extends Gtk.ListBoxRow { class ExtensionRow extends Gtk.ListBoxRow {
_init(uuid) { _init(extension) {
super._init(); super._init();
this.uuid = uuid; this._extension = extension;
this._prefsModule = null;
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' }); this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
this._settings.connect('changed::enabled-extensions', () => { this._settings.connect('changed::enabled-extensions', () => {
@ -532,9 +505,23 @@ class ExtensionRow extends Gtk.ListBoxRow {
this._buildUI(); this._buildUI();
} }
_buildUI() { get uuid() {
let extension = ExtensionUtils.extensions[this.uuid]; return this._extension.uuid;
}
get name() {
return this._extension.metadata.name;
}
get hasPrefs() {
return this._extension.hasPrefs;
}
get url() {
return this._extension.metadata.url;
}
_buildUI() {
let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL,
hexpand: true, margin_end: 24, spacing: 24, hexpand: true, margin_end: 24, spacing: 24,
margin: 12 }); margin: 12 });
@ -544,19 +531,20 @@ class ExtensionRow extends Gtk.ListBoxRow {
spacing: 6, hexpand: true }); spacing: 6, hexpand: true });
hbox.add(vbox); hbox.add(vbox);
let name = GLib.markup_escape_text(extension.metadata.name, -1); let name = GLib.markup_escape_text(this.name, -1);
let label = new Gtk.Label({ label: '<b>' + name + '</b>', let label = new Gtk.Label({ label: '<b>' + name + '</b>',
use_markup: true, use_markup: true,
halign: Gtk.Align.START }); halign: Gtk.Align.START });
vbox.add(label); vbox.add(label);
let desc = extension.metadata.description.split('\n')[0]; let desc = this._extension.metadata.description.split('\n')[0];
label = new DescriptionLabel({ label: desc, wrap: true, lines: 2, label = new DescriptionLabel({ label: desc, wrap: true, lines: 2,
ellipsize: Pango.EllipsizeMode.END, ellipsize: Pango.EllipsizeMode.END,
xalign: 0, yalign: 0 }); xalign: 0, yalign: 0 });
vbox.add(label); vbox.add(label);
let button = new Gtk.Button({ valign: Gtk.Align.CENTER, let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
visible: this.hasPrefs,
no_show_all: true }); no_show_all: true });
button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic', button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
icon_size: Gtk.IconSize.BUTTON, icon_size: Gtk.IconSize.BUTTON,
@ -580,11 +568,10 @@ class ExtensionRow extends Gtk.ListBoxRow {
} }
_canEnable() { _canEnable() {
let extension = ExtensionUtils.extensions[this.uuid];
let checkVersion = !this._settings.get_boolean('disable-extension-version-validation'); let checkVersion = !this._settings.get_boolean('disable-extension-version-validation');
return !this._settings.get_boolean('disable-user-extensions') && return !this._settings.get_boolean('disable-user-extensions') &&
!(checkVersion && ExtensionUtils.isOutOfDate(extension)); !(checkVersion && ExtensionUtils.isOutOfDate(this._extension));
} }
_isEnabled() { _isEnabled() {
@ -612,6 +599,17 @@ class ExtensionRow extends Gtk.ListBoxRow {
} while (pos != -1); } while (pos != -1);
this._settings.set_strv('enabled-extensions', extensions); this._settings.set_strv('enabled-extensions', extensions);
} }
get prefsModule() {
if (!this._prefsModule) {
ExtensionUtils.installImporter(this._extension);
this._prefsModule = this._extension.imports.prefs;
this._prefsModule.init(this._extension.metadata);
}
return this._prefsModule;
}
}); });
function initEnvironment() { function initEnvironment() {