diff --git a/extension.js b/extension.js index 16a23e0..eecb25f 100644 --- a/extension.js +++ b/extension.js @@ -1,363 +1,347 @@ -const St = imports.gi.St; -const Main = imports.ui.main; -const GLib = imports.gi.GLib; -const Mainloop = imports.mainloop; -const Gio = imports.gi.Gio; -const Gettext = imports.gettext; -const ExtensionUtils = imports.misc.extensionUtils; -const Me = ExtensionUtils.getCurrentExtension(); -const Domain = Gettext.domain(Me.metadata.uuid); -const _ = Domain.gettext; -const ngettext = Domain.ngettext; -const ExtManager = Main.extensionManager; - -let gschema; -var settings; - -var locations = {}; - -let cancellable = null; -let executeQueue = []; -let resultEvent; +import St from 'gi://St'; +import GLib from 'gi://GLib'; +import Gio from 'gi://Gio'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; const POSITIONS = { 0: 'left', 1: 'center', - 2: 'right' + 2: 'right', }; -function init() { - ExtensionUtils.initTranslations(Me.metadata.uuid); -} - -function enable() { - if (cancellable === null) { - cancellable = new Gio.Cancellable() - } +export default class Executor extends Extension { + enable() { + log('Executor enabled'); - log('Executor enabled'); - - gschema = Gio.SettingsSchemaSource.new_from_directory( - Me.dir.get_child('schemas').get_path(), - Gio.SettingsSchemaSource.get_default(), - false - ); - - settings = new Gio.Settings({ - settings_schema: gschema.lookup('org.gnome.shell.extensions.executor', true) - }); - - for (let position = 0; position < 3; position++) { - this.locations[position] = { - "name": POSITIONS[position], - "output": [], - "box": null, - "stopped": null, - "commandsSettings": { "commands": [] }, - "commandsOutput": [], - "lastIndex": null, - "activeChanged": null, - "indexChanged": null, - "commandsJsonChanged": null, - "locationClicked": null + if (!this.cancellable) { + this.cancellable = new Gio.Cancellable(); } - this.locations[position].stopped = false; - - this.locations[position].box = new St.BoxLayout({ style_class: 'panel-button', reactive: true }); - - this.locations[position].locationClicked = this.locations[position].box.connect( - 'button-press-event', () => { - if (this.settings.get_value('click-on-output-active').deep_unpack()) { - this.settings.set_int('location', position); - GLib.timeout_add( - GLib.PRIORITY_DEFAULT, - 100, - () => { - ExtManager.openExtensionPrefs(Me.metadata.uuid, '', {}); + this.stopped = false; + this.settings = this.getSettings(); + this.executeQueue = []; + this.locations = {}; + + for (let position = 0; position < 3; position++) { + this.locations[position] = { + name: POSITIONS[position], + output: [], + box: null, + stopped: null, + commandsSettings: {commands: []}, + commandsOutput: [], + lastIndex: null, + activeChanged: null, + indexChanged: null, + commandsJsonChanged: null, + locationClicked: null, + }; + + this.locations[position].stopped = false; + + this.locations[position].box = new St.BoxLayout({style_class: 'panel-button', reactive: true}); + + this.locations[position].locationClicked = this.locations[position].box.connect( + 'button-press-event', + () => { + if (this.settings.get_value('click-on-output-active').deep_unpack()) { + this.settings.set_int('location', position); + GLib.timeout_add(GLib.PRIORITY_DEFAULT, 100, () => { + this.openPreferences(); }); + } } - } - ); + ); - if (this.locations[position].box.get_parent()) { - this.locations[position].box.get_parent().remove_child(this.locations[position].box); - } - - this.onStatusChanged(this.locations[position]); - - this.locations[position].activeChanged = this.settings.connect( - 'changed::' + POSITIONS[position] + '-active', () => { - this.onStatusChanged(this.locations[position]) + if (this.locations[position].box.get_parent()) { + this.locations[position].box.get_parent().remove_child(this.locations[position].box); } - ); - this.locations[position].indexChanged = this.settings.connect( - 'changed::' + POSITIONS[position] + '-index', () => { - this.onStatusChanged(this.locations[position]) - } - ); - - this.locations[position].commandsJsonChanged = this.settings.connect( - 'changed::' + POSITIONS[position] + '-commands-json', () => { - this.onStatusChanged(this.locations[position]) - } - ); - } + this.onStatusChanged(this.locations[position]); - this.checkQueue(); -} + this.locations[position].activeChanged = this.settings.connect( + 'changed::' + POSITIONS[position] + '-active', + () => { + this.onStatusChanged(this.locations[position]); + } + ); -function disable() { - for (let position = 0; position < 3; position++) { - this.locations[position].stopped = true; + this.locations[position].indexChanged = this.settings.connect( + 'changed::' + POSITIONS[position] + '-index', + () => { + this.onStatusChanged(this.locations[position]); + } + ); - if (this.locations[position].box.get_parent()) { - this.locations[position].box.get_parent().remove_child(this.locations[position].box); + this.locations[position].commandsJsonChanged = this.settings.connect( + 'changed::' + POSITIONS[position] + '-commands-json', + () => { + this.onStatusChanged(this.locations[position]); + } + ); } - this.locations[position].box.disconnect(this.locations[position].locationClicked); + this.checkQueue(); + } - this.locations[position].box.remove_all_children(); - this.locations[position].box = null; + disable() { + this.stopped = true; - this.locations[position].commandsOutput = []; - this.locations[position].output = []; + for (let position = 0; position < 3; position++) { + this.locations[position].stopped = true; - this.settings.disconnect(this.locations[position].activeChanged); - this.settings.disconnect(this.locations[position].indexChanged); - this.settings.disconnect(this.locations[position].commandsJsonChanged); - } - settings = null; + if (this.locations[position].box.get_parent()) { + this.locations[position].box.get_parent().remove_child(this.locations[position].box); + } - log("Executor stopped"); -} + this.locations[position].box.disconnect(this.locations[position].locationClicked); -function initOutputLabels(location) { - location.box.remove_all_children(); - location.commandsSettings.commands.forEach(function (command, index) { - location.output[index] = new St.Label({ y_expand: true, y_align: 2 }); - location.box.add_child(location.output[index]); - }, this); + this.locations[position].box.remove_all_children(); + this.locations[position].box = null; -} + this.locations[position].commandsOutput = []; + this.locations[position].output = []; -function onStatusChanged(location) { - if (this.settings.get_value(location.name + '-active').deep_unpack()) { - if (location.box.get_parent()) { - location.box.get_parent().remove_child(location.box); + this.settings.disconnect(this.locations[position].activeChanged); + this.settings.disconnect(this.locations[position].indexChanged); + this.settings.disconnect(this.locations[position].commandsJsonChanged); } - location.stopped = false; - if (location.lastIndex === null) { - this.checkCommands(location, this.settings.get_value(location.name + '-commands-json').deep_unpack()); - location.lastIndex = settings.get_value(location.name + '-index').deep_unpack(); - } else if (settings.get_value(location.name + '-index').deep_unpack() !== location.lastIndex) { - location.lastIndex = settings.get_value(location.name + '-index').deep_unpack(); - } else { - this.checkCommands(location, this.settings.get_value(location.name + '-commands-json').deep_unpack()); - } + this.settings = null; + this.executeQueue = null; + this.locations = null; - Main.panel['_' + location.name + 'Box'].insert_child_at_index(location.box, location.lastIndex); + log('Executor stopped'); + } - } else { - location.stopped = true; - if (location.box.get_parent()) { - location.box.get_parent().remove_child(location.box); - } - this.removeOldCommands(location); - location.commandsOutput = []; - location.output = []; + initOutputLabels(location) { location.box.remove_all_children(); + location.commandsSettings.commands.forEach(function (command, index) { + location.output[index] = new St.Label({y_expand: true, y_align: 2}); + location.box.add_child(location.output[index]); + }, this); } -} -function removeOldCommands(location) { - executeQueue.forEach(function (command, index) { - if (command.locationName === location.name) { - executeQueue.splice(index, 1); + onStatusChanged(location) { + if (this.settings.get_value(location.name + '-active').deep_unpack()) { + if (location.box.get_parent()) { + location.box.get_parent().remove_child(location.box); + } + + location.stopped = false; + if (location.lastIndex === null) { + this.checkCommands(location, this.settings.get_value(location.name + '-commands-json').deep_unpack()); + location.lastIndex = this.settings.get_value(location.name + '-index').deep_unpack(); + } else if (this.settings.get_value(location.name + '-index').deep_unpack() !== location.lastIndex) { + location.lastIndex = this.settings.get_value(location.name + '-index').deep_unpack(); + } else { + this.checkCommands(location, this.settings.get_value(location.name + '-commands-json').deep_unpack()); + } + + Main.panel['_' + location.name + 'Box'].insert_child_at_index(location.box, location.lastIndex); + } else { + location.stopped = true; + if (location.box.get_parent()) { + location.box.get_parent().remove_child(location.box); + } + this.removeOldCommands(location); + location.commandsOutput = []; + location.output = []; + location.box.remove_all_children(); } - }, this); -} + } -function checkCommands(location, json) { - try { - location.commandsSettings = JSON.parse(json); - } catch (e) { - log('Error in json file for location: ' + location.name); + removeOldCommands(location) { + this.executeQueue.forEach(function (command, index) { + if (command.locationName === location.name) { + this.executeQueue.splice(index, 1); + } + }, this); } - this.initOutputLabels(location); + checkCommands(location, json) { + try { + location.commandsSettings = JSON.parse(json); + } catch (e) { + log('Error in json file for location: ' + location.name); + } - if (location.commandsSettings.commands.length > 0) { + this.initOutputLabels(location); - location.commandsSettings.commands.forEach(function (command, index) { - if (command.isActive || command.isActive == null) { - if (!executeQueue.some(c => c.uuid === command.uuid)) { - command.locationName = location.name; - command.index = index; - executeQueue.push(command); + if (location.commandsSettings.commands.length > 0) { + location.commandsSettings.commands.forEach(function (command, index) { + if (command.isActive || command.isActive == null) { + if (!this.executeQueue.some((c) => c.uuid === command.uuid)) { + command.locationName = location.name; + command.index = index; + this.executeQueue.push(command); + } } - } - }, this); - - //if (location.commandsSettings.commands.length < location.commandsOutput.length) { - location.commandsOutput = []; - //} + }, this); - this.resetOutput(location); + //if (location.commandsSettings.commands.length < location.commandsOutput.length) { + location.commandsOutput = []; + //} - } else { - log('No commands specified: ' + location.name); - location.commandsOutput = []; - this.resetOutput(location); + this.resetOutput(location); + } else { + log('No commands specified: ' + location.name); + location.commandsOutput = []; + this.resetOutput(location); + } } -} -function checkQueue() { - if (executeQueue.length > 0) { - let copy = executeQueue; - executeQueue = []; - this.handleCurrentQueue(copy); - } else { - GLib.timeout_add(0, 500, () => { - this.checkQueue() - return GLib.SOURCE_REMOVE; - }); + checkQueue() { + if (!this.stopped && this.executeQueue.length > 0) { + let copy = this.executeQueue; + this.executeQueue = []; + this.handleCurrentQueue(copy); + } else { + GLib.timeout_add(0, 500, () => { + this.checkQueue(); + return GLib.SOURCE_REMOVE; + }); + } } -} -function handleCurrentQueue(copy) { - let current = copy.shift(); + handleCurrentQueue(copy) { + let current = copy.shift(); - this.execCommand(current, ['bash', '-c', current.command]); + this.execCommand(current, ['bash', '-c', current.command]); - if (copy.length > 0) { - GLib.timeout_add(0, 50, () => { - if (copy.length > 0) { - this.handleCurrentQueue(copy) - } - return GLib.SOURCE_REMOVE; - }); - } else { - this.checkQueue(); + if (copy.length > 0) { + GLib.timeout_add(0, 50, () => { + if (copy.length > 0) { + this.handleCurrentQueue(copy); + } + return GLib.SOURCE_REMOVE; + }); + } else if (!this.stopped) { + this.checkQueue(); + } } -} -async function execCommand(command, argv, input = null, cancellable = null) { - try { - let flags = (Gio.SubprocessFlags.STDOUT_PIPE | - Gio.SubprocessFlags.STDERR_PIPE); + async execCommand(command, argv, input = null, cancellable = null) { + try { + let flags = Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE; - if (input !== null) - flags |= Gio.SubprocessFlags.STDIN_PIPE; + if (input !== null) flags |= Gio.SubprocessFlags.STDIN_PIPE; - let proc = Gio.Subprocess.new(argv, flags); + let proc = Gio.Subprocess.new(argv, flags); - return new Promise((resolve, reject) => { - proc.communicate_utf8_async(input, cancellable, (proc, res) => { - try { - let [, stdout, stderr] = proc.communicate_utf8_finish(res); + return new Promise((resolve, reject) => { + proc.communicate_utf8_async(input, cancellable, (proc, res) => { + try { + let [, stdout, stderr] = proc.communicate_utf8_finish(res); - if (!proc.get_successful()) { - let status = proc.get_exit_status(); + if (!proc.get_successful()) { + let status = proc.get_exit_status(); - log('Executor: error in command "' + command.command + '": ' + (stderr ? stderr.trim() : GLib.strerror(status))); + log( + 'Executor: error in command "' + + command.command + + '": ' + + (stderr ? stderr.trim() : GLib.strerror(status)) + ); - /*throw new Gio.IOErrorEnum({ - code: Gio.io_error_from_errno(status), - message: stderr ? stderr.trim() : GLib.strerror(status) - });*/ - } + /*throw new Gio.IOErrorEnum({ + code: Gio.io_error_from_errno(status), + message: stderr ? stderr.trim() : GLib.strerror(status) + });*/ + } - this.callback(command, stdout); - resolve(stdout); - } catch (e) { - reject(e); - } + this.callback(command, stdout); + resolve(stdout); + } catch (e) { + reject(e); + } + }); }); - }); - } catch (e) { - return Promise.reject(e); + } catch (e) { + return Promise.reject(e); + } } -} -function callback(command, stdout) { + callback(command, stdout) { + let entries = []; + let outputAsOneLine = ''; - let entries = []; - let outputAsOneLine = ''; - - if (stdout) { - stdout.split('\n').map(line => entries.push(line)); - entries.forEach(output => { - outputAsOneLine = outputAsOneLine + output; - }); - } else { - outputAsOneLine = ''; - } + if (stdout) { + stdout.split('\n').map((line) => entries.push(line)); + entries.forEach((output) => { + outputAsOneLine = outputAsOneLine + output; + }); + } else { + outputAsOneLine = ''; + } - let locationIndex = Object.keys(POSITIONS).find(key => POSITIONS[key] === command.locationName) + let locationIndex = Object.keys(POSITIONS).find((key) => POSITIONS[key] === command.locationName); - if (!this.locations[locationIndex].stopped) { - if (!this.locations[locationIndex].commandsSettings.commands.some(c => c.uuid === command.uuid)) { - this.locations[locationIndex].commandsOutput.splice(index, 1); - } else { - this.locations[locationIndex].commandsOutput[command.index] = outputAsOneLine + if (!this.locations[locationIndex].stopped) { + if (!this.locations[locationIndex].commandsSettings.commands.some((c) => c.uuid === command.uuid)) { + this.locations[locationIndex].commandsOutput.splice(index, 1); + } else { + this.locations[locationIndex].commandsOutput[command.index] = outputAsOneLine; - if (this.locations[locationIndex].commandsSettings.commands.length < this.locations[locationIndex].commandsOutput.length) { - this.locations[locationIndex].commandsOutput = []; - } + if ( + this.locations[locationIndex].commandsSettings.commands.length < + this.locations[locationIndex].commandsOutput.length + ) { + this.locations[locationIndex].commandsOutput = []; + } - GLib.timeout_add_seconds(0, command.interval, () => { - if (cancellable && !cancellable.is_cancelled()) { - if (!this.locations[locationIndex].stopped) { - if (!executeQueue.some(c => c.uuid === command.uuid)) { - executeQueue.push(command); + GLib.timeout_add_seconds(0, command.interval, () => { + if (this.cancellable && !this.cancellable.is_cancelled()) { + if (!this.stopped && !this.locations[locationIndex].stopped) { + if (!this.executeQueue.some((c) => c.uuid === command.uuid)) { + this.executeQueue.push(command); + } } } - } - return GLib.SOURCE_REMOVE; - }); - } - try { - this.setOutput(this.locations[locationIndex], command.index); - } catch (e) { - log('Caught exception while setting output: ' + e); + return GLib.SOURCE_REMOVE; + }); + } + try { + this.setOutput(this.locations[locationIndex], command.index); + } catch (e) { + log('Caught exception while setting output: ' + e); + } } } -} -function resetOutput(location) { - location.output.forEach(output => { - output.set_text(''); - }) -} + resetOutput(location) { + location.output.forEach((output) => { + output.set_text(''); + }); + } -async function setOutput(location, index) { - let executorRegex = new RegExp(/()/g); - let executorSettingsArray = location.commandsOutput[index].match(executorRegex); - let markupSet = false; + async setOutput(location, index) { + let executorRegex = new RegExp(/()/g); + let executorSettingsArray = location.commandsOutput[index].match(executorRegex); + let markupSet = false; - location.output[index].set_style_class_name(""); + location.output[index].set_style_class_name(''); - if (executorSettingsArray != null) { - executorSettingsArray.forEach(setting => { - location.commandsOutput[index] = location.commandsOutput[index].replace(setting, ""); + if (executorSettingsArray != null) { + executorSettingsArray.forEach((setting) => { + location.commandsOutput[index] = location.commandsOutput[index].replace(setting, ''); - let settingDivided = setting.substring(1, setting.length - 1).split("."); - - if (settingDivided[1] == "css") { - location.output[index].add_style_class_name(settingDivided[2]) - } else if (settingDivided[1] == "markup") { - markupSet = true - } - }) - } + let settingDivided = setting.substring(1, setting.length - 1).split('.'); - if (markupSet) { - location.output[index].get_clutter_text().set_markup(location.commandsOutput[index]); - } else { - location.output[index].set_text(location.commandsOutput[index]); + if (settingDivided[1] == 'css') { + location.output[index].add_style_class_name(settingDivided[2]); + } else if (settingDivided[1] == 'markup') { + markupSet = true; + } + }); + } + + if (markupSet) { + location.output[index].get_clutter_text().set_markup(location.commandsOutput[index]); + } else { + location.output[index].set_text(location.commandsOutput[index]); + } } } diff --git a/metadata.json b/metadata.json index cc42b09..66e1492 100644 --- a/metadata.json +++ b/metadata.json @@ -1,17 +1,9 @@ { - "name": "Executor", - "description": "Execute multiple shell commands periodically with separate intervals and display the output in gnome top bar.", - "uuid": "executor@raujonas.github.io", - "shell-version": [ - "3.30.2", - "3.36", - "3.38", - "40", - "41", - "42", - "43", - "44" - ], - "url": "https://github.com/raujonas/executor", - "version": 22 -} \ No newline at end of file + "name": "Executor", + "description": "Execute multiple shell commands periodically with separate intervals and display the output in gnome top bar.", + "uuid": "executor@raujonas.github.io", + "settings-schema": "org.gnome.shell.extensions.executor", + "shell-version": ["45"], + "url": "https://github.com/raujonas/executor", + "version": 24 +} diff --git a/prefs.js b/prefs.js index 7d7c31c..dab9ae6 100644 --- a/prefs.js +++ b/prefs.js @@ -1,196 +1,192 @@ -'use strict'; +import Gio from 'gi://Gio'; +import Gtk from 'gi://Gtk'; -const Gio = imports.gi.Gio; -const Gtk = imports.gi.Gtk; +import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; -const Gettext = imports.gettext; -const ExtensionUtils = imports.misc.extensionUtils; -const Me = ExtensionUtils.getCurrentExtension(); -const Domain = Gettext.domain(Me.metadata.uuid); -const _ = Domain.gettext; -const ngettext = Domain.ngettext; - -const Config = imports.misc.config; -const [major] = Config.PACKAGE_VERSION.split('.'); -const shellVersion = Number.parseInt(major); - -let gschema = Gio.SettingsSchemaSource.new_from_directory( - Me.dir.get_child('schemas').get_path(), - Gio.SettingsSchemaSource.get_default(), - false -); - -var settings = new Gio.Settings({ - settings_schema: gschema.lookup('org.gnome.shell.extensions.executor', true) -}); - -var notebook; const POSITIONS = { 0: 'left', 1: 'center', - 2: 'right' -}; -const POSTRANS = { - 0: _('Left'), - 1: _('Center'), - 2: _('Right') + 2: 'right', }; -function init() { - ExtensionUtils.initTranslations(Me.metadata.uuid); -} +export default class ExecutorPreferences extends ExtensionPreferences { + getPreferencesWidget() { + const postrans = { + 0: _('Left'), + 1: _('Center'), + 2: _('Right'), + }; + + this.settings = this.getSettings(); + + let prefsWidget = new Gtk.Grid({visible: true, column_homogeneous: true}); + this.notebook = new Gtk.Notebook({visible: true}); + prefsWidget.attach(this.notebook, 0, 0, 1, 1); + this.commandsArray = {}; + this.commandsArrayCopy = {}; + this.listBox = {}; + + for (let position = 0; position < 3; position++) { + this.commandsArray[position] = []; + this.commandsArrayCopy[position] = []; + try { + this.commandsArray[position] = JSON.parse( + this.settings.get_value(POSITIONS[position] + '-commands-json').deep_unpack() + ).commands; + this.commandsArrayCopy[position] = JSON.parse(JSON.stringify(this.commandsArray[position])); + } catch (e) { + log('Error in json file for position:', POSITIONS[position]); + this.settings.set_string( + POSITIONS[position] + '-commands-json', + '{"commands":[{"command":"echo Executor works!","interval":1}]}' + ); + } + + let grid = new Gtk.Grid({ + column_spacing: 12, + row_spacing: 12, + column_homogeneous: true, + hexpand: true, + vexpand: true, + margin_start: 14, + margin_end: 14, + margin_top: 14, + margin_bottom: 14, + visible: true, + }); + + let topHbox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL, spacing: 20, visible: true}); + grid.attach(topHbox, 0, 0, 2, 1); + + let active = new Gtk.Switch({ + visible: true, + halign: Gtk.Align.START, + valign: Gtk.Align.CENTER, + hexpand: true, + }); + active.set_active(this.settings.get_value(POSITIONS[position] + '-active').deep_unpack()); + active.connect('notify::active', () => { + this.activeClicked(active.get_active()); + }); + let index = new Gtk.SpinButton({ + adjustment: new Gtk.Adjustment({lower: 0, upper: 10, step_increment: 1}), + visible: true, + xalign: 0.5, + }); + index.set_size_request(100, 0); + topHbox.append(new Gtk.Label({label: _('Active:'), use_markup: true, visible: true})); + topHbox.append(active); + topHbox.append(new Gtk.Label({label: _('Index in status bar:'), visible: true, halign: Gtk.Align.END})); + topHbox.append(index); + + grid.attach(new Gtk.Separator({visible: true, orientation: Gtk.Orientation.VERTICAL}), 0, 1, 2, 1); + grid.attach( + new Gtk.Label({ + label: _('Command') + ' / ' + _('Interval in seconds') + ':', + visible: true, + halign: Gtk.Align.START, + }), + 0, + 2, + 2, + 1 + ); + + this.listBox[position] = new Gtk.ListBox({visible: true}); + this.listBox[position].set_selection_mode(0); + grid.attach(this.listBox[position], 0, 3, 2, 1); + this.populateCommandList(position); + grid.attach(new Gtk.Separator({visible: true, orientation: Gtk.Orientation.VERTICAL}), 0, 4, 2, 1); + + let buttonsHbox = new Gtk.Box({ + orientation: Gtk.Orientation.HORIZONTAL, + spacing: 10, + visible: true, + hexpand: true, + }); + + let addButton = new Gtk.Button({ + visible: true, + halign: Gtk.Align.START, + hexpand: true, + tooltip_text: _('Add new command'), + }); + let cancelButton = new Gtk.Button({ + visible: true, + halign: Gtk.Align.END, + hexpand: false, + tooltip_text: _('Revert to last saved commands'), + }); + let saveButton = new Gtk.Button({ + visible: true, + halign: Gtk.Align.END, + hexpand: false, + tooltip_text: _('Save commands'), + }); + + addButton.set_icon_name('list-add-symbolic'); + cancelButton.set_icon_name('document-revert-symbolic'); + saveButton.set_icon_name('document-save-symbolic'); -function buildPrefsWidget() { - let prefsWidget = new Gtk.Grid({ visible: true, column_homogeneous: true }); - this.notebook = new Gtk.Notebook({ visible: true }); - prefsWidget.attach(this.notebook, 0, 0, 1, 1); - this.commandsArray = {}; - this.commandsArrayCopy = {}; - this.listBox = {}; - let add; - shellVersion < 40 ? - add = 'add' : - add = 'append'; - for (let position = 0; position < 3; position++) { - this.commandsArray[position] = []; - this.commandsArrayCopy[position] = []; - try { - this.commandsArray[position] = JSON.parse(this.settings.get_value(POSITIONS[position] + '-commands-json').deep_unpack()).commands; - this.commandsArrayCopy[position] = JSON.parse(JSON.stringify(this.commandsArray[position])); - } catch (e) { - log('Error in json file for location: ' + location.name); - this.settings.set_string(POSITIONS[position] + '-commands-json', '{"commands":[{"command":"echo Executor works!","interval":1}]}'); + addButton.connect('clicked', this.addCommandToList.bind(this)); + cancelButton.connect('clicked', () => { + this.commandsArray[position] = JSON.parse(JSON.stringify(this.commandsArrayCopy[position])); + this.populateCommandList(position); + }); + saveButton.connect('clicked', this.saveCommands.bind(this)); + buttonsHbox.append(addButton); + buttonsHbox.append(cancelButton); + buttonsHbox.append(saveButton); + grid.attach(buttonsHbox, 0, 5, 2, 1); + + let pos = postrans[position]; + this.notebook.append_page(grid, new Gtk.Label({label: _(pos), visible: true, hexpand: true})); + + this.settings.bind(POSITIONS[position] + '-index', index, 'value', Gio.SettingsBindFlags.DEFAULT); } + /* General tab */ let grid = new Gtk.Grid({ - column_spacing: 12, row_spacing: 12, + column_spacing: 12, + row_spacing: 12, column_homogeneous: true, - hexpand: true, vexpand: true, - margin_start: 14, margin_end: 14, margin_top: 14, margin_bottom: 14, - visible: true + hexpand: true, + vexpand: true, + margin_start: 14, + margin_end: 14, + margin_top: 14, + margin_bottom: 14, + visible: true, }); - - let topHbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, spacing: 20, visible: true }); + let topHbox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL, spacing: 20, visible: true}); grid.attach(topHbox, 0, 0, 2, 1); - let active = new Gtk.Switch({ + let clickOnOutputActive = new Gtk.Switch({ visible: true, - halign: Gtk.Align.START, + halign: Gtk.Align.END, valign: Gtk.Align.CENTER, - hexpand: true - }); - active.set_active(this.settings.get_value(POSITIONS[position] + '-active').deep_unpack()); - active.connect("notify::active", () => { - this.activeClicked(active.get_active()); - }); - let index = new Gtk.SpinButton({ - adjustment: new Gtk.Adjustment({ lower: 0, upper: 10, step_increment: 1 }), visible: true, - xalign: 0.5 - }); - index.set_size_request(100, 0); - topHbox[add](new Gtk.Label({ label: _('Active:'), use_markup: true, visible: true })); - topHbox[add](active); - topHbox[add](new Gtk.Label({ label: _('Index in status bar:'), visible: true, halign: Gtk.Align.END })); - topHbox[add](index); - - grid.attach(new Gtk.Separator({ visible: true, orientation: Gtk.Orientation.VERTICAL }), 0, 1, 2, 1); - grid.attach(new Gtk.Label({ - label: _('Command') + ' / ' + _('Interval in seconds') + ':', - visible: true, halign: Gtk.Align.START - }), 0, 2, 2, 1); - - this.listBox[position] = new Gtk.ListBox({ visible: true }); - this.listBox[position].set_selection_mode(0); - grid.attach(this.listBox[position], 0, 3, 2, 1); - this.populateCommandList(position); - grid.attach(new Gtk.Separator({ visible: true, orientation: Gtk.Orientation.VERTICAL }), 0, 4, 2, 1); - - let buttonsHbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, spacing: 10, visible: true, hexpand: true }); - - let addButton = new Gtk.Button({ - visible: true, halign: Gtk.Align.START, hexpand: true, - tooltip_text: _('Add new command') + hexpand: true, }); - let cancelButton = new Gtk.Button({ - visible: true, halign: Gtk.Align.END, hexpand: false, - tooltip_text: _('Revert to last saved commands') + clickOnOutputActive.set_active(this.settings.get_value('click-on-output-active').deep_unpack()); + clickOnOutputActive.connect('notify::active', () => { + this.clickOnOutputActiveClicked(clickOnOutputActive.get_active()); }); - let saveButton = new Gtk.Button({ - visible: true, halign: Gtk.Align.END, hexpand: false, - tooltip_text: _('Save commands') - }); - - if (shellVersion < 40) { - addButton.set_image(new Gtk.Image({ icon_name: 'list-add-symbolic' })); // 'gtk-add' - cancelButton.set_image(new Gtk.Image({ icon_name: 'document-revert-symbolic' })); // 'gtk-revert-to-saved - saveButton.set_image(new Gtk.Image({ icon_name: 'document-save-symbolic' })); // 'gtk-save' - } else { - addButton.set_icon_name('list-add-symbolic'); - cancelButton.set_icon_name('document-revert-symbolic'); - saveButton.set_icon_name('document-save-symbolic'); - } - addButton.connect("clicked", this.addCommandToList.bind(this)); - cancelButton.connect("clicked", () => { - this.commandsArray[position] = JSON.parse(JSON.stringify(this.commandsArrayCopy[position])); - this.populateCommandList(position); + topHbox.append( + new Gtk.Label({label: _('Click on output in top bar active:'), use_markup: true, visible: true}) + ); + topHbox.append(clickOnOutputActive); + grid.attach(new Gtk.Separator({visible: true, orientation: Gtk.Orientation.VERTICAL}), 0, 1, 2, 1); + this.notebook.append_page(grid, new Gtk.Label({label: _('General'), visible: true, hexpand: true})); + /* End of general tab */ + + this.notebook.set_current_page(this.settings.get_value('location').deep_unpack()); + this.notebook.connect('switch-page', (notebook, page, index) => { + this.settings.set_int('location', index); }); - saveButton.connect("clicked", this.saveCommands.bind(this)); - buttonsHbox[add](addButton); - buttonsHbox[add](cancelButton); - buttonsHbox[add](saveButton); - grid.attach(buttonsHbox, 0, 5, 2, 1); - - let pos = POSTRANS[position]; - this.notebook.append_page(grid, new Gtk.Label({ label: _(pos), visible: true, hexpand: true })); - - this.settings.bind(POSITIONS[position] + '-index', index, 'value', Gio.SettingsBindFlags.DEFAULT); + return prefsWidget; } - /* General tab */ - let grid = new Gtk.Grid({ - column_spacing: 12, row_spacing: 12, - column_homogeneous: true, - hexpand: true, vexpand: true, - margin_start: 14, margin_end: 14, margin_top: 14, margin_bottom: 14, - visible: true - }); - let topHbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, spacing: 20, visible: true }); - grid.attach(topHbox, 0, 0, 2, 1); - - let clickOnOutputActive = new Gtk.Switch({ - visible: true, - halign: Gtk.Align.END, - valign: Gtk.Align.CENTER, - hexpand: true - }); - clickOnOutputActive.set_active(this.settings.get_value('click-on-output-active').deep_unpack()); - clickOnOutputActive.connect("notify::active", () => { - this.clickOnOutputActiveClicked(clickOnOutputActive.get_active()); - }); - topHbox[add](new Gtk.Label({ label: _('Click on output in top bar active:'), use_markup: true, visible: true })); - topHbox[add](clickOnOutputActive); - grid.attach(new Gtk.Separator({ visible: true, orientation: Gtk.Orientation.VERTICAL }), 0, 1, 2, 1); - this.notebook.append_page(grid, new Gtk.Label({ label: _('General'), visible: true, hexpand: true })); - /* End of general tab */ - - this.notebook.set_current_page(this.settings.get_value('location').deep_unpack()) - this.notebook.connect('switch-page', (notebook, page, index) => { - this.settings.set_int('location', index); - }) - return prefsWidget; -} - -function populateCommandList(page_number) { - - if (shellVersion < 40) { - - this.listBox[page_number].foreach((element) => this.listBox[page_number].remove(element)); - this.commandsArray[page_number].forEach((c, index) => { - this.listBox[page_number].add(this.prepareRow(c, index)); - }); - - } else { - + populateCommandList(page_number) { let child = this.listBox[page_number].get_first_child(); while (child != null) { let next = child.get_next_sibling(); @@ -201,170 +197,154 @@ function populateCommandList(page_number) { this.listBox[page_number].append(this.prepareRow(c, index)); }); } -} -function prepareRow(c, index) { - let add, addRow; - if (shellVersion < 40) { - add = 'add'; - addRow = 'add'; - } else { - add = 'append'; - addRow = 'set_child'; - } + prepareRow(c, index) { + let row = new Gtk.ListBoxRow({visible: true}); + let hbox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL, visible: true}); + row.set_child(hbox); + let isActiveButton = new Gtk.CheckButton({ + visible: true, + margin_end: 10, + tooltip_text: _('Command active'), + }); + if (c.isActive || c.isActive == null) { + isActiveButton.set_active(true); + } + isActiveButton.connect('toggled', () => { + isActiveButton.set_active(isActiveButton.get_active()); + }); + hbox.append(isActiveButton); + let command = new Gtk.Entry({visible: true, hexpand: true, margin_end: 10}); + command.set_text(c.command); + hbox.append(command); + let interval = new Gtk.SpinButton({ + adjustment: new Gtk.Adjustment({lower: 1, upper: 86400, step_increment: 1}), + xalign: 0.5, + visible: true, + margin_end: 10, + }); + interval.set_value(c.interval); + hbox.append(interval); + + let upButton = new Gtk.Button({ + visible: true, + margin_end: 4, + tooltip_text: _('Move command up'), + }); + let downButton = new Gtk.Button({ + visible: true, + margin_end: 4, + tooltip_text: _('Move command down'), + }); + let remove = new Gtk.Button({ + visible: true, + tooltip_text: _('Remove command'), + }); - let row = new Gtk.ListBoxRow({ visible: true }); - let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, visible: true }); - row[addRow](hbox); - let isActiveButton = new Gtk.CheckButton({ - visible: true, margin_end: 10, - tooltip_text: _('Command active') - }); - if (c.isActive || c.isActive == null) { - isActiveButton.set_active(true); - } - isActiveButton.connect("toggled", () => { - isActiveButton.set_active(isActiveButton.get_active()); - }); - hbox[add](isActiveButton); - let command = new Gtk.Entry({ visible: true, hexpand: true, margin_end: 10 }); - command.set_text(c.command); - hbox[add](command); - let interval = new Gtk.SpinButton({ - adjustment: new Gtk.Adjustment({ lower: 1, upper: 86400, step_increment: 1 }), - xalign: 0.5, visible: true, margin_end: 10 - }); - interval.set_value(c.interval); - hbox[add](interval); - - let upButton = new Gtk.Button({ - visible: true, margin_end: 4, - tooltip_text: _('Move command up') - }); - let downButton = new Gtk.Button({ - visible: true, margin_end: 4, - tooltip_text: _('Move command down') - }); - let remove = new Gtk.Button({ - visible: true, - tooltip_text: _('Remove command') - }); - if (shellVersion < 40) { - upButton.set_image(new Gtk.Image({ icon_name: 'go-up-symbolic' })); - downButton.set_image(new Gtk.Image({ icon_name: 'go-down-symbolic' })); - remove.set_image(new Gtk.Image({ icon_name: 'edit-delete-symbolic' })); - } else { upButton.set_icon_name('go-up-symbolic'); downButton.set_icon_name('go-down-symbolic'); remove.set_icon_name('edit-delete-symbolic'); - } - upButton.connect("clicked", () => { - this.moveCommandUp(index); - }); - downButton.connect("clicked", () => { - this.moveCommandDown(index); - }); - hbox[add](upButton); - hbox[add](downButton); - hbox[add](remove); - remove.connect("clicked", () => { - remove.set_sensitive(false); - this.removeCommandFromList(index); - }); - return row; -} -function addCommandToList() { - let position = this.notebook.get_current_page(); - this.commandsArray[position].push({ "command": "echo 'new command'", "interval": 1 }); - this.populateCommandList(position); -} + upButton.connect('clicked', () => { + this.moveCommandUp(index); + }); + downButton.connect('clicked', () => { + this.moveCommandDown(index); + }); + hbox.append(upButton); + hbox.append(downButton); + hbox.append(remove); + remove.connect('clicked', () => { + remove.set_sensitive(false); + this.removeCommandFromList(index); + }); + return row; + } -function removeCommandFromList(index) { - let position = this.notebook.get_current_page(); - this.commandsArray[position].splice(index, 1); - this.populateCommandList(position); -} + addCommandToList() { + let position = this.notebook.get_current_page(); + this.commandsArray[position].push({command: "echo 'new command'", interval: 1}); + this.populateCommandList(position); + } -function moveCommandUp(index) { - let position = this.notebook.get_current_page(); - this.arraymove(this.commandsArray[position], index, index - 1); - this.populateCommandList(position); -} + removeCommandFromList(index) { + let position = this.notebook.get_current_page(); + this.commandsArray[position].splice(index, 1); + this.populateCommandList(position); + } -function moveCommandDown(index) { - let position = this.notebook.get_current_page(); - this.arraymove(this.commandsArray[position], index, index + 1); - this.populateCommandList(position); -} + moveCommandUp(index) { + let position = this.notebook.get_current_page(); + this.arraymove(this.commandsArray[position], index, index - 1); + this.populateCommandList(position); + } -function arraymove(array, fromIndex, toIndex) { - let element = array[fromIndex]; - array.splice(fromIndex, 1); - array.splice(toIndex, 0, element); -} + moveCommandDown(index) { + let position = this.notebook.get_current_page(); + this.arraymove(this.commandsArray[position], index, index + 1); + this.populateCommandList(position); + } -function saveCommands() { + arraymove(array, fromIndex, toIndex) { + let element = array[fromIndex]; + array.splice(fromIndex, 1); + array.splice(toIndex, 0, element); + } - let position = this.notebook.get_current_page(); - this.commandsArray[position].splice(0, this.commandsArray[position].length); + saveCommands() { + let position = this.notebook.get_current_page(); + this.commandsArray[position].splice(0, this.commandsArray[position].length); - let count = 0; + let count = 0; - if (shellVersion < 40) { - this.listBox[position].foreach((element) => count++); - } else { let child = this.listBox[position].get_first_child(); while (child != null) { let next = child.get_next_sibling(); count++; child = next; } - } - for (let i = 0; i < count; i++) { - let isActive; - let command; - let interval; - if (shellVersion < 40) { - isActive = this.listBox[position].get_row_at_index(i).get_child().get_children()[0].get_active(); - command = this.listBox[position].get_row_at_index(i).get_child().get_children()[1].get_text(); - interval = this.listBox[position].get_row_at_index(i).get_child().get_children()[2].get_value(); - } else { + + for (let i = 0; i < count; i++) { let entry = this.listBox[position].get_row_at_index(i).get_child().get_first_child(); - isActive = entry.get_active(); + let isActive = entry.get_active(); entry = entry.get_next_sibling(); - command = entry.get_text(); + let command = entry.get_text(); entry = entry.get_next_sibling(); - interval = entry.get_value(); + let interval = entry.get_value(); + + this.commandsArray[position].push({ + isActive: isActive, + command: command, + interval: interval, + uuid: this.createUUID(), + }); } - this.commandsArray[position].push({ - "isActive": isActive, - "command": command, - "interval": interval, - "uuid": this.createUUID() - }); + + this.commandsArrayCopy[position] = JSON.parse(JSON.stringify(this.commandsArray[position])); + this.settings.set_string( + POSITIONS[position] + '-commands-json', + '{"commands":' + JSON.stringify(this.commandsArray[position]) + '}' + ); } - this.commandsArrayCopy[position] = JSON.parse(JSON.stringify(this.commandsArray[position])); - this.settings.set_string(POSITIONS[position] + '-commands-json', '{"commands":' + JSON.stringify(this.commandsArray[position]) + '}'); -} + createUUID() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + let r = (Math.random() * 16) | 0, + v = c == 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); + } -function createUUID() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); -} + activeClicked(isActive) { + let position = this.notebook.get_current_page(); + if (isActive) { + this.saveCommands(); + } -function activeClicked(isActive) { - let position = this.notebook.get_current_page(); - if (isActive) { - this.saveCommands(); + this.settings.set_boolean(POSITIONS[position] + '-active', isActive); } - this.settings.set_boolean(POSITIONS[position] + '-active', isActive); + clickOnOutputActiveClicked(isActive) { + this.settings.set_boolean('click-on-output-active', isActive); + } } - -function clickOnOutputActiveClicked(isActive) { - this.settings.set_boolean('click-on-output-active', isActive); -} \ No newline at end of file