dot/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/preferences/device.js

1080 lines
32 KiB
JavaScript

'use strict';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;
const Keybindings = imports.preferences.keybindings;
// Build a list of plugins and shortcuts for devices
const DEVICE_PLUGINS = [];
const DEVICE_SHORTCUTS = {};
for (let name in imports.service.plugins) {
let module = imports.service.plugins[name];
if (module.Metadata !== undefined) {
// Plugins
DEVICE_PLUGINS.push(name);
// Shortcuts (GActions without parameters
for (let [name, action] of Object.entries(module.Metadata.actions)) {
if (action.parameter_type === null) {
DEVICE_SHORTCUTS[name] = [action.icon_name, action.label];
}
}
}
}
// A GtkListBoxUpdateHeaderFunc for sections
function rowSeparators(row, before) {
let header = row.get_header();
if (before === null) {
if (header !== null) {
header.destroy();
}
return;
}
if (header === null) {
header = new Gtk.Separator({visible: true});
row.set_header(header);
}
}
// A GtkListBoxSortFunc for SectionRow rows
function title_sort(row1, row2) {
if (!row1.title || !row2.title) return 0;
return row1.title.localeCompare(row2.title);
}
/**
* A row for a section of settings
*/
const SectionRow = GObject.registerClass({
GTypeName: 'GSConnectSectionRow'
}, class SectionRow extends Gtk.ListBoxRow {
_init(params) {
super._init({
height_request: 56,
selectable: false,
visible: true
});
let grid = new Gtk.Grid({
column_spacing: 12,
margin_top: 8,
margin_right: 12,
margin_bottom: 8,
margin_left: 12,
visible: true
});
this.add(grid);
// Row Icon
this._icon = new Gtk.Image({
pixel_size: 32
});
grid.attach(this._icon, 0, 0, 1, 2);
// Row Title
this._title = new Gtk.Label({
halign: Gtk.Align.START,
hexpand: true,
valign: Gtk.Align.CENTER,
vexpand: true
});
grid.attach(this._title, 1, 0, 1, 1);
// Row Subtitle
this._subtitle = new Gtk.Label({
halign: Gtk.Align.START,
hexpand: true,
valign: Gtk.Align.CENTER,
vexpand: true
});
this._subtitle.get_style_context().add_class('dim-label');
grid.attach(this._subtitle, 1, 1, 1, 1);
Object.assign(this, params);
}
get icon_name() {
return this._icon.gicon.names[0];
}
set icon_name(icon_name) {
this._icon.visible = (icon_name);
this._icon.gicon = new Gio.ThemedIcon({name: icon_name});
}
get title() {
return this._title.label;
}
set title(text) {
this._title.visible = (text);
this._title.label = text;
}
get subtitle() {
return this._subtitle.label;
}
set subtitle(text) {
this._subtitle.visible = (text);
this._subtitle.label = text;
}
get widget() {
return this._widget;
}
set widget(widget) {
if (this._widget && this._widget instanceof Gtk.Widget) {
this._widget.destroy();
this._widget = null;
}
this._widget = widget;
this.get_child().attach(this.widget, 2, 0, 1, 2);
}
});
/**
* Command Editor Dialog
*/
const CommandEditor = GObject.registerClass({
GTypeName: 'GSConnectCommandEditor',
Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/command-editor.ui',
Children: [
'cancel-button', 'save-button',
'command-entry', 'name-entry'
]
}, class CommandEditor extends Gtk.Dialog {
_onBrowseCommand(entry, icon_pos, event) {
let filter = new Gtk.FileFilter();
filter.add_mime_type('application/x-executable');
let dialog = new Gtk.FileChooserDialog({
filter: filter,
modal: true,
transient_for: this
});
dialog.add_button(_('Cancel'), Gtk.ResponseType.CANCEL);
dialog.add_button(_('Open'), Gtk.ResponseType.OK);
dialog.set_default_response(Gtk.ResponseType.OK);
dialog.connect('response', (dialog, response_id) => {
if (response_id === Gtk.ResponseType.OK) {
this.command_entry.text = dialog.get_filename();
}
dialog.destroy();
});
dialog.show_all();
}
_onEntryChanged(entry, pspec) {
this.save_button.sensitive = (this.command_name && this.command_line);
}
get command_line() {
return this.command_entry.text;
}
set command_line(text) {
this.command_entry.text = text;
}
get command_name() {
return this.name_entry.text;
}
set command_name(text) {
this.name_entry.text = text;
}
});
var DevicePreferences = GObject.registerClass({
GTypeName: 'GSConnectDevicePreferences',
Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/device-preferences.ui',
Children: [
'sidebar', 'stack', 'infobar',
// Sharing
'sharing', 'sharing-page',
'desktop-list', 'clipboard', 'clipboard-sync', 'mousepad', 'mpris', 'systemvolume',
'share', 'share-list', 'receive-files', 'receive-directory',
// Battery
'battery',
'battery-device-label', 'battery-device', 'battery-device-list',
'battery-system-label', 'battery-system', 'battery-system-list',
// RunCommand
'runcommand', 'runcommand-page',
'command-list', 'command-add',
// Notifications
'notification', 'notification-page',
'notification-list', 'notification-apps',
// Telephony
'telephony', 'telephony-page',
'ringing-list', 'ringing-volume', 'talking-list', 'talking-volume',
// Shortcuts
'shortcuts-page',
'shortcuts-actions', 'shortcuts-actions-title', 'shortcuts-actions-list',
// Advanced
'advanced-page',
'plugin-list', 'experimental-list'
]
}, class DevicePreferences extends Gtk.Grid {
_init(device) {
super._init();
this.device = device;
// GSettings
this.settings = new Gio.Settings({
settings_schema: gsconnect.gschema.lookup(
'org.gnome.Shell.Extensions.GSConnect.Device',
true
),
path: '/org/gnome/shell/extensions/gsconnect/device/' + device.id + '/'
});
// Infobar
this.device.bind_property(
'paired',
this.infobar,
'reveal-child',
(GObject.BindingFlags.SYNC_CREATE |
GObject.BindingFlags.INVERT_BOOLEAN)
);
this._setupActions();
// Settings Pages
this._sharingSettings();
this._batterySettings();
this._runcommandSettings();
this._notificationSettings();
this._telephonySettings();
// --------------------------
this._keybindingSettings();
this._advancedSettings();
// Separate plugins and other settings
this.sidebar.set_header_func((row, before) => {
if (row.get_name() === 'shortcuts') {
row.set_header(new Gtk.Separator({visible: true}));
}
});
// Hide elements for any disabled plugins
for (let name of DEVICE_PLUGINS) {
if (this.hasOwnProperty(name)) {
this[name].visible = this.get_plugin_allowed(name);
}
}
}
get menu() {
if (this._menu === undefined) {
let menus = Gtk.Builder.new_from_resource(
'/org/gnome/Shell/Extensions/GSConnect/gtk/menus.ui'
);
menus.translation_domain = 'org.gnome.Shell.Extensions.GSConnect';
this._menu = menus.get_object('device-menu');
this._menu.prepend_section(null, this.device.menu);
this.insert_action_group('device', this.device.action_group);
}
return this._menu;
}
get_incoming_supported(type) {
let incoming = this.settings.get_strv('incoming-capabilities');
return incoming.includes(`kdeconnect.${type}`);
}
get_outgoing_supported(type) {
let outgoing = this.settings.get_strv('outgoing-capabilities');
return outgoing.includes(`kdeconnect.${type}`);
}
_onKeynavFailed(widget, direction) {
if (direction === Gtk.DirectionType.UP && widget.prev) {
widget.prev.child_focus(direction);
} else if (direction === Gtk.DirectionType.DOWN && widget.next) {
widget.next.child_focus(direction);
}
return true;
}
_onSwitcherRowSelected(box, row) {
this.stack.set_visible_child_name(row.get_name());
}
_onToggleRowActivated(box, row) {
let widget = row.get_child().get_child_at(1, 0);
widget.active = !widget.active;
}
_onEncryptionInfo() {
let dialog = new Gtk.MessageDialog({
buttons: Gtk.ButtonsType.OK,
text: _('Encryption Info'),
secondary_text: this.device.encryption_info,
modal: true,
transient_for: this.get_toplevel()
});
dialog.connect('response', (dialog) => dialog.destroy());
dialog.present();
}
_deviceAction(action, parameter) {
this.action_group.activate_action(action.name, parameter);
}
dispose() {
if (this.__disposed === undefined) {
this.__disposed = true;
if (this._commandEditor !== undefined) {
this._commandEditor.destroy();
}
// Device signals
this.device.action_group.disconnect(this._actionAddedId);
this.device.action_group.disconnect(this._actionRemovedId);
// GActions/GMenu
this.menu.run_dispose();
this.actions.run_dispose();
// GSettings
for (let settings of Object.values(this._pluginSettings)) {
settings.run_dispose();
}
this.settings.disconnect(this._keybindingsId);
this.settings.disconnect(this._pluginsId);
this.settings.run_dispose();
}
}
pluginSettings(name) {
if (this._pluginSettings === undefined) {
this._pluginSettings = {};
}
if (!this._pluginSettings.hasOwnProperty(name)) {
let meta = imports.service.plugins[name].Metadata;
this._pluginSettings[name] = new Gio.Settings({
settings_schema: gsconnect.gschema.lookup(meta.id, -1),
path: this.settings.path + 'plugin/' + name + '/'
});
}
return this._pluginSettings[name];
}
_setupActions() {
this.actions = new Gio.SimpleActionGroup();
this.insert_action_group('settings', this.actions);
let settings = this.pluginSettings('battery');
this.actions.add_action(settings.create_action('send-statistics'));
this.actions.add_action(settings.create_action('low-battery-notification'));
this.actions.add_action(settings.create_action('full-battery-notification'));
settings = this.pluginSettings('clipboard');
this.actions.add_action(settings.create_action('send-content'));
this.actions.add_action(settings.create_action('receive-content'));
settings = this.pluginSettings('contacts');
this.actions.add_action(settings.create_action('contacts-source'));
settings = this.pluginSettings('mousepad');
this.actions.add_action(settings.create_action('share-control'));
settings = this.pluginSettings('mpris');
this.actions.add_action(settings.create_action('share-players'));
settings = this.pluginSettings('notification');
this.actions.add_action(settings.create_action('send-notifications'));
this.actions.add_action(settings.create_action('send-active'));
settings = this.pluginSettings('photo');
this.actions.add_action(settings.create_action('share-camera'));
settings = this.pluginSettings('share');
this.actions.add_action(settings.create_action('receive-files'));
settings = this.pluginSettings('sms');
this.actions.add_action(settings.create_action('legacy-sms'));
settings = this.pluginSettings('systemvolume');
this.actions.add_action(settings.create_action('share-sinks'));
settings = this.pluginSettings('telephony');
this.actions.add_action(settings.create_action('ringing-volume'));
this.actions.add_action(settings.create_action('ringing-pause'));
this.actions.add_action(settings.create_action('talking-volume'));
this.actions.add_action(settings.create_action('talking-pause'));
this.actions.add_action(settings.create_action('talking-microphone'));
// Pair Actions
let encryption_info = new Gio.SimpleAction({name: 'encryption-info'});
encryption_info.connect('activate', this._onEncryptionInfo.bind(this));
this.actions.add_action(encryption_info);
let status_pair = new Gio.SimpleAction({name: 'pair'});
status_pair.connect('activate', this._deviceAction.bind(this.device));
this.settings.bind('paired', status_pair, 'enabled', 16);
this.actions.add_action(status_pair);
let status_unpair = new Gio.SimpleAction({name: 'unpair'});
status_unpair.connect('activate', this._deviceAction.bind(this.device));
this.settings.bind('paired', status_unpair, 'enabled', 0);
this.actions.add_action(status_unpair);
}
/**
* Sharing Settings
*/
_sharingSettings() {
// Share Plugin
let settings = this.pluginSettings('share');
settings.connect(
'changed::receive-directory',
this._onReceiveDirectoryChanged.bind(this)
);
this._onReceiveDirectoryChanged(settings, 'receive-directory');
// Visibility
this.desktop_list.foreach(row => {
let name = row.get_name();
row.visible = this.get_outgoing_supported(`${name}.request`);
});
// Separators & Sorting
this.desktop_list.set_header_func(rowSeparators);
this.desktop_list.set_sort_func((row1, row2) => {
row1 = row1.get_child().get_child_at(0, 0);
row2 = row2.get_child().get_child_at(0, 0);
return row1.label.localeCompare(row2.label);
});
this.share_list.set_header_func(rowSeparators);
// Scroll with keyboard focus
let sharing_box = this.sharing_page.get_child().get_child();
sharing_box.set_focus_vadjustment(this.sharing_page.vadjustment);
// Continue focus chain between lists
this.desktop_list.next = this.share_list;
this.share_list.prev = this.desktop_list;
}
_onReceiveDirectoryChanged(settings, key) {
let receiveDir = settings.get_string(key);
if (receiveDir.length === 0) {
receiveDir = GLib.get_user_special_dir(
GLib.UserDirectory.DIRECTORY_DOWNLOAD
);
// Account for some corner cases with a fallback
if (!receiveDir || receiveDir === GLib.get_home_dir()) {
receiveDir = GLib.build_filenamev([
GLib.get_home_dir(),
'Downloads'
]);
}
settings.set_string(key, receiveDir);
}
if (this.receive_directory.get_filename() !== receiveDir) {
this.receive_directory.set_filename(receiveDir);
}
}
_onReceiveDirectorySet(button) {
let settings = this.pluginSettings('share');
let receiveDir = settings.get_string('receive-directory');
let filename = button.get_filename();
if (filename !== receiveDir) {
settings.set_string('receive-directory', filename);
}
}
/**
* Battery Settings
*/
async _batterySettings() {
try {
this.battery_device_list.set_header_func(rowSeparators);
this.battery_system_list.set_header_func(rowSeparators);
// If the device can't handle statistics we're done
if (!this.get_incoming_supported('battery')) {
this.battery_system_label.visible = false;
this.battery_system.visible = false;
return;
}
// Check UPower for a battery
let hasBattery = await new Promise((resolve, reject) => {
Gio.DBus.system.call(
'org.freedesktop.UPower',
'/org/freedesktop/UPower/devices/DisplayDevice',
'org.freedesktop.DBus.Properties',
'Get',
new GLib.Variant('(ss)', [
'org.freedesktop.UPower.Device',
'IsPresent'
]),
null,
Gio.DBusCallFlags.NONE,
-1,
null,
(connection, res) => {
try {
let variant = connection.call_finish(res);
let value = variant.deepUnpack()[0];
let isPresent = value.get_boolean();
resolve(isPresent);
} catch (e) {
resolve(false);
}
}
);
});
this.battery_system_label.visible = hasBattery;
this.battery_system.visible = hasBattery;
} catch (e) {
this.battery_system_label.visible = false;
this.battery_system.visible = false;
}
}
/**
* RunCommand Page
*/
_runcommandSettings() {
// Scroll with keyboard focus
let runcommand_box = this.runcommand_page.get_child().get_child();
runcommand_box.set_focus_vadjustment(this.runcommand_page.vadjustment);
// Local Command List
let settings = this.pluginSettings('runcommand');
this._commands = settings.get_value('command-list').recursiveUnpack();
this.command_list.set_sort_func(this._sortCommands);
this.command_list.set_header_func(rowSeparators);
Object.keys(this._commands).map(uuid => this._insertCommand(uuid));
}
_sortCommands(row1, row2) {
if (!row1.title || !row2.title) return 1;
return row1.title.localeCompare(row2.title);
}
_insertCommand(uuid) {
let row = new SectionRow({
title: this._commands[uuid].name,
subtitle: this._commands[uuid].command,
activatable: false
});
row.set_name(uuid);
row._subtitle.ellipsize = Pango.EllipsizeMode.MIDDLE;
let editButton = new Gtk.Button({
image: new Gtk.Image({
icon_name: 'document-edit-symbolic',
pixel_size: 16,
visible: true
}),
tooltip_text: _('Edit'),
valign: Gtk.Align.CENTER,
vexpand: true,
visible: true
});
editButton.connect('clicked', this._onEditCommand.bind(this));
row.get_child().attach(editButton, 2, 0, 1, 2);
let deleteButton = new Gtk.Button({
image: new Gtk.Image({
icon_name: 'edit-delete-symbolic',
pixel_size: 16,
visible: true
}),
tooltip_text: _('Remove'),
valign: Gtk.Align.CENTER,
vexpand: true,
visible: true
});
deleteButton.connect('clicked', this._onDeleteCommand.bind(this));
row.get_child().attach(deleteButton, 3, 0, 1, 2);
this.command_list.add(row);
return row;
}
_onEditCommand(widget) {
if (this._commandEditor === undefined) {
this._commandEditor = new CommandEditor({
modal: true,
transient_for: this.get_toplevel(),
use_header_bar: true
});
this._commandEditor.connect(
'response',
this._onSaveCommand.bind(this)
);
this._commandEditor.resize(1, 1);
}
if (widget instanceof Gtk.Button) {
let row = widget.get_parent().get_parent();
let uuid = row.get_name();
this._commandEditor.uuid = uuid;
this._commandEditor.command_name = this._commands[uuid].name;
this._commandEditor.command_line = this._commands[uuid].command;
} else {
this._commandEditor.uuid = GLib.uuid_string_random();
this._commandEditor.command_name = '';
this._commandEditor.command_line = '';
}
this._commandEditor.show();
}
_onDeleteCommand(button) {
let row = button.get_parent().get_parent();
delete this._commands[row.get_name()];
row.destroy();
this.pluginSettings('runcommand').set_value(
'command-list',
GLib.Variant.full_pack(this._commands)
);
}
_onSaveCommand(dialog, response_id) {
if (response_id === Gtk.ResponseType.ACCEPT) {
this._commands[dialog.uuid] = {
name: dialog.command_name,
command: dialog.command_line
};
this.pluginSettings('runcommand').set_value(
'command-list',
GLib.Variant.full_pack(this._commands)
);
//
let row = null;
for (let child of this.command_list.get_children()) {
if (child.get_name() === dialog.uuid) {
row = child;
break;
}
}
if (row === null) {
this._insertCommand(dialog.uuid);
} else {
row.set_name(dialog.uuid);
row.title = dialog.command_name;
row.subtitle = dialog.command_line;
}
}
dialog.hide();
}
/**
* Notification Settings
*/
_notificationSettings() {
let settings = this.pluginSettings('notification');
settings.bind(
'send-notifications',
this.notification_apps,
'sensitive',
Gio.SettingsBindFlags.DEFAULT
);
// Separators & Sorting
this.notification_list.set_header_func(rowSeparators);
// Scroll with keyboard focus
let notification_box = this.notification_page.get_child().get_child();
notification_box.set_focus_vadjustment(this.notification_page.vadjustment);
// Continue focus chain between lists
this.notification_list.next = this.notification_apps;
this.notification_apps.prev = this.notification_list;
this.notification_apps.set_sort_func(title_sort);
this.notification_apps.set_header_func(rowSeparators);
this._populateApplications(settings);
}
_onNotificationRowActivated(box, row) {
let settings = this.pluginSettings('notification');
let applications = {};
try {
applications = JSON.parse(settings.get_string('applications'));
} catch (e) {
applications = {};
}
applications[row.title].enabled = !applications[row.title].enabled;
row.widget.label = applications[row.title].enabled ? _('On') : _('Off');
settings.set_string('applications', JSON.stringify(applications));
}
_populateApplications(settings) {
let applications = this._queryApplications(settings);
for (let name in applications) {
let row = new SectionRow({
icon_name: applications[name].iconName,
title: name,
height_request: 48,
widget: new Gtk.Label({
label: applications[name].enabled ? _('On') : _('Off'),
margin_start: 12,
margin_end: 12,
halign: Gtk.Align.END,
valign: Gtk.Align.CENTER,
vexpand: true,
visible: true
})
});
this.notification_apps.add(row);
}
}
_queryApplications(settings) {
let applications = {};
try {
applications = JSON.parse(settings.get_string('applications'));
} catch (e) {
applications = {};
}
// Scan applications that statically declare to show notifications
let appInfos = [];
let ignoreId = 'org.gnome.Shell.Extensions.GSConnect.desktop';
for (let appInfo of Gio.AppInfo.get_all()) {
if (appInfo.get_id() !== ignoreId &&
appInfo.get_boolean('X-GNOME-UsesNotifications')) {
appInfos.push(appInfo);
}
}
// Update GSettings
for (let appInfo of appInfos) {
let appName = appInfo.get_name();
if (appName && !applications[appName]) {
let icon = appInfo.get_icon();
icon = (icon) ? icon.to_string() : 'application-x-executable';
applications[appName] = {
iconName: icon,
enabled: true
};
}
}
settings.set_string('applications', JSON.stringify(applications));
return applications;
}
/**
* Telephony Settings
*/
_telephonySettings() {
// Continue focus chain between lists
this.ringing_list.next = this.talking_list;
this.talking_list.prev = this.ringing_list;
this.ringing_list.set_header_func(rowSeparators);
this.talking_list.set_header_func(rowSeparators);
}
/**
* Keyboard Shortcuts
*/
_keybindingSettings() {
// Scroll with keyboard focus
let shortcuts_box = this.shortcuts_page.get_child().get_child();
shortcuts_box.set_focus_vadjustment(this.shortcuts_page.vadjustment);
// Filter & Sort
this.shortcuts_actions_list.set_filter_func(this._filterPluginKeybindings.bind(this));
this.shortcuts_actions_list.set_header_func(rowSeparators);
this.shortcuts_actions_list.set_sort_func(title_sort);
// Init
for (let name in DEVICE_SHORTCUTS) {
this._addPluginKeybinding(name);
}
this._setPluginKeybindings();
// Watch for GAction and Keybinding changes
this._actionAddedId = this.device.action_group.connect(
'action-added',
() => this.shortcuts_actions_list.invalidate_filter()
);
this._actionRemovedId = this.device.action_group.connect(
'action-removed',
() => this.shortcuts_actions_list.invalidate_filter()
);
this._keybindingsId = this.settings.connect(
'changed::keybindings',
this._setPluginKeybindings.bind(this)
);
}
_addPluginKeybinding(name) {
let [icon_name, label] = DEVICE_SHORTCUTS[name];
let widget = new Gtk.Label({
label: _('Disabled'),
visible: true
});
widget.get_style_context().add_class('dim-label');
let row = new SectionRow({
icon_name: icon_name,
title: label,
widget: widget
});
row.height_request = 48;
row._icon.pixel_size = 16;
row.action = name;
this.shortcuts_actions_list.add(row);
}
_filterPluginKeybindings(row) {
return this.device.action_group.has_action(row.action);
}
_setPluginKeybindings() {
let keybindings = this.settings.get_value('keybindings').deepUnpack();
this.shortcuts_actions_list.foreach(row => {
if (keybindings[row.action]) {
let accel = Gtk.accelerator_parse(keybindings[row.action]);
row.widget.label = Gtk.accelerator_get_label(...accel);
} else {
row.widget.label = _('Disabled');
}
});
}
_onResetActionShortcuts(button) {
let keybindings = this.settings.get_value('keybindings').deepUnpack();
for (let action in keybindings) {
if (!action.includes('::')) {
delete keybindings[action];
}
}
this.settings.set_value(
'keybindings',
new GLib.Variant('a{ss}', keybindings)
);
}
async _onShortcutRowActivated(box, row) {
try {
let keybindings = this.settings.get_value('keybindings').deepUnpack();
let accelerator = await Keybindings.get_accelerator(
row.title,
keybindings[row.action]
);
if (accelerator) {
keybindings[row.action] = accelerator;
} else {
delete keybindings[row.action];
}
this.settings.set_value(
'keybindings',
new GLib.Variant('a{ss}', keybindings)
);
} catch (e) {
logError(e);
}
}
/**
* Advanced Page
*/
_advancedSettings() {
// Scroll with keyboard focus
let advanced_box = this.advanced_page.get_child().get_child();
advanced_box.set_focus_vadjustment(this.advanced_page.vadjustment);
//
this.plugin_list.set_header_func(rowSeparators);
// Continue focus chain between lists
this.plugin_list.next = this.experimental_list;
this.experimental_list.prev = this.plugin_list;
this.experimental_list.set_header_func(rowSeparators);
this._pluginsId = this.settings.connect(
'changed::supported-plugins',
this._populatePlugins.bind(this)
);
this._populatePlugins();
}
get_plugin_allowed(name) {
let disabled = this.settings.get_strv('disabled-plugins');
let supported = this.settings.get_strv('supported-plugins');
return supported.filter(name => !disabled.includes(name)).includes(name);
}
_addPlugin(name) {
let plugin = imports.service.plugins[name];
let row = new Gtk.ListBoxRow({
border_width: 0,
visible: true
});
let grid = new Gtk.Grid({
height_request: 32,
visible: true
});
row.add(grid);
let widget = new Gtk.CheckButton({
label: plugin.Metadata.label,
active: this.get_plugin_allowed(name),
hexpand: true,
tooltip_text: name,
valign: Gtk.Align.CENTER,
vexpand: true,
visible: true
});
grid.add(widget);
this.plugin_list.add(row);
widget._togglePluginId = widget.connect(
'notify::active',
this._togglePlugin.bind(this)
);
if (this.hasOwnProperty(name)) {
this[name].visible = widget.active;
}
}
_populatePlugins() {
let supported = this.settings.get_strv('supported-plugins');
for (let row of this.plugin_list.get_children()) {
let checkbutton = row.get_child().get_child_at(0, 0);
let name = checkbutton.tooltip_text;
if (supported.includes(name)) {
row.visible = true;
checkbutton.active = this.get_plugin_allowed(name);
} else {
row.visible = false;
if (this.hasOwnProperty(name)) {
this[name].visible = false;
}
}
supported.splice(supported.indexOf(name), 1);
}
for (let name of supported) {
this._addPlugin(name);
}
}
_togglePlugin(widget) {
try {
let name = widget.tooltip_text;
let disabled = this.settings.get_strv('disabled-plugins');
if (disabled.includes(name)) {
disabled.splice(disabled.indexOf(name), 1);
} else {
disabled.push(name);
}
this.settings.set_strv('disabled-plugins', disabled);
if (this.hasOwnProperty(name)) {
this[name].visible = !disabled.includes(name);
}
} catch (e) {
logError(e);
}
}
});