/* * Copyright 2022 zhrexl * Copyright 2024 Dave Prowse * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * SPDX-FileCopyrightText: 2024 Dave Prowse * SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileContributor: Modified by Dave Prowse */ /* eslint version: 9.16 (2024) */ import Adw from 'gi://Adw'; import Gdk from 'gi://Gdk'; import Gtk from 'gi://Gtk'; import GObject from 'gi://GObject'; import { gettext } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; import { CURATED_UUID as UUID } from '../utils.js'; import * as Shortcuts from '../shortcuts.js'; const _ = (string) => string ? gettext(string) : ""; const MARGIN = 10; const ROWBOX_MARGIN_PARAMS = { margin_top: MARGIN / 2, margin_bottom: MARGIN / 2, margin_start: MARGIN, margin_end: MARGIN, spacing: 4 }; const PreferencesPage = GObject.registerClass({ GTypeName: `${UUID}-PreferencesPage` }, class Preferences extends Adw.PreferencesPage { constructor(extensionPreferences, window) { super({}); this.set_title("Preferences"); this.set_name('prefs'); this.set_icon_name("preferences-system-symbolic"); // Use cached settings from extensionPreferences let settings = window._settings; let schema = settings.settings_schema; let grp_Global = Adw.PreferencesGroup.new(); grp_Global.set_title("Global"); Shortcuts.GLOBAL_KEYBINDINGS.forEach((settingKeys) => { let globalKeybindingsRow = new Adw.ActionRow(); let globalKeybindingsWidget = new ShortCutWidget(settings, settingKeys); let name = settings.settings_schema.get_key(settingKeys).get_summary(); globalKeybindingsRow.set_title(name); globalKeybindingsRow.add_suffix(globalKeybindingsWidget); globalKeybindingsWidget.valign = Gtk.Align.CENTER; grp_Global.add(globalKeybindingsRow); }); Shortcuts.GLOBAL_KEYBINDINGS_SWITCHES.forEach((settingKeys) => { let ActionRow = Adw.ActionRow.new(); let ActionRow_switch = Gtk.Switch.new(); let persistentOverTogglesKey = schema.get_key(settingKeys); ActionRow.set_title(persistentOverTogglesKey.get_summary()); let description = persistentOverTogglesKey.get_description(); if (description) ActionRow.set_subtitle(persistentOverTogglesKey.get_description()); ActionRow.add_suffix(ActionRow_switch); ActionRow_switch.valign = Gtk.Align.CENTER; settings.bind(settingKeys, ActionRow_switch, 'active', 0); grp_Global.add(ActionRow); }); let grp_Internal = Adw.PreferencesGroup.new(); grp_Internal.set_title("Internal"); // Use cached internalShortcutSettings let internalShortcutSettings = window._internalShortcutSettings; // Rest of the code stays the same... Shortcuts.INTERNAL_KEYBINDINGS.forEach((settingKeys) => { let globalKeybindingsRow = new Adw.ActionRow(); let globalKeybindingsWidget = new ShortCutWidget(internalShortcutSettings, settingKeys); let name = internalShortcutSettings.settings_schema.get_key(settingKeys).get_summary(); globalKeybindingsRow.set_title(name); globalKeybindingsRow.add_suffix(globalKeybindingsWidget); globalKeybindingsWidget.valign = Gtk.Align.CENTER; grp_Internal.add(globalKeybindingsRow); }); let resetButton = new Gtk.Button({ label: _("Reset settings"), halign: Gtk.Align.CENTER }); resetButton.get_style_context().add_class('destructive-action'); resetButton.connect('clicked', () => { internalShortcutSettings.settings_schema.list_keys().forEach(key => internalShortcutSettings.reset(key)); settings.settings_schema.list_keys().forEach(key => settings.reset(key)); }); resetButton.set_margin_top(12); this.add(grp_Global); this.add(grp_Internal); grp_Internal.add(resetButton); } }); //TODO: ShortCutWidget should not allow two identicals shortcuts const ShortCutWidget = GObject.registerClass({ GTypeName: `${UUID}-ShortCutWidget` }, class ShortCutWidget extends Gtk.Button { constructor(settings, settingsKeys) { super({}); this._settings = settings; this._settingsKeys = settingsKeys; let key = settings.get_strv(settingsKeys)[0]; this.shortcutlabel = Gtk.ShortcutLabel.new(key); this.evck = Gtk.EventControllerKey.new(); this.allow_changes = false; this.add_controller(this.evck); //TODO: This needs testing if (key == null) this.set_label(_("Click here to set new shortcut...")); else this.set_child(this.shortcutlabel); this.get_style_context().add_class('flat'); this.connect('clicked', this.clicked.bind(this)); this.evck.connect('key-pressed', this.key_pressed.bind(this)); this.evck.connect('key-released', this.key_released.bind(this)); this._settings.connect('changed', this.on_settings_changed.bind(this)); } on_settings_changed() { let key = this._settings.get_strv(this._settingsKeys)[0]; this.shortcutlabel.set_accelerator(key); } clicked() { this.set_label(_("Press the new shortcut...")); this.allow_changes = true; } key_released(widget, keyval, keycode, state) { if (this.allow_changes == false) return Gdk.EVENT_STOP; else this.allow_changes = false; let value = this.shortcutlabel.get_accelerator(); this._settings.set_strv(this._settingsKeys, [value]); } key_pressed(widget, keyval, keycode, state) { if (this.allow_changes == false) return Gdk.EVENT_STOP; let mask = state & Gtk.accelerator_get_default_mod_mask(); let binding = Gtk.accelerator_name_with_keycode(null, keyval, keycode, mask); this.shortcutlabel.set_accelerator(binding); this.set_child(this.shortcutlabel); return Gdk.EVENT_STOP; } }); export default PreferencesPage;