[gnome] Update extensions
This commit is contained in:
@ -3,7 +3,7 @@ import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
|
||||
import { WindowRow } from './window_row.js';
|
||||
import { ApplicationRow } from './applications_management/application_row.js';
|
||||
|
||||
|
||||
const make_array = prefs_group => {
|
||||
@ -30,8 +30,10 @@ export const Applications = GObject.registerClass({
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/applications.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'blur',
|
||||
'customize',
|
||||
'sigma',
|
||||
'brightness',
|
||||
'opacity',
|
||||
'dynamic_opacity',
|
||||
'blur_on_overview',
|
||||
'enable_all',
|
||||
'whitelist',
|
||||
@ -54,6 +56,10 @@ export const Applications = GObject.registerClass({
|
||||
'opacity', this._opacity, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.applications.settings.bind(
|
||||
'dynamic-opacity', this._dynamic_opacity, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.applications.settings.bind(
|
||||
'blur-on-overview', this._blur_on_overview, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
@ -62,8 +68,14 @@ export const Applications = GObject.registerClass({
|
||||
'enable-all', this._enable_all, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._customize.connect_to(this.preferences, this.preferences.applications, false);
|
||||
this.preferences.applications.settings.bind(
|
||||
'sigma', this._sigma, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.applications.settings.bind(
|
||||
'brightness', this._brightness, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
// connect 'enable all' button to whitelist/blacklist visibility
|
||||
this._enable_all.bind_property(
|
||||
@ -82,16 +94,16 @@ export const Applications = GObject.registerClass({
|
||||
|
||||
// listen to app row addition
|
||||
this._add_window_whitelist.connect('clicked',
|
||||
_ => this.add_to_whitelist()
|
||||
() => this.add_to_whitelist()
|
||||
);
|
||||
this._add_window_blacklist.connect('clicked',
|
||||
_ => this.add_to_blacklist()
|
||||
() => this.add_to_blacklist()
|
||||
);
|
||||
|
||||
// add initial applications
|
||||
this.add_widgets_from_lists();
|
||||
|
||||
this.preferences.connect('reset', _ => {
|
||||
this.preferences.connect('reset', () => {
|
||||
this.remove_all_widgets();
|
||||
this.add_widgets_from_lists();
|
||||
});
|
||||
@ -137,12 +149,12 @@ export const Applications = GObject.registerClass({
|
||||
}
|
||||
|
||||
add_to_whitelist(app_name = null) {
|
||||
let window_row = new WindowRow('whitelist', this, app_name);
|
||||
let window_row = new ApplicationRow('whitelist', this, app_name);
|
||||
this._whitelist.add(window_row);
|
||||
}
|
||||
|
||||
add_to_blacklist(app_name = null) {
|
||||
let window_row = new WindowRow('blacklist', this, app_name);
|
||||
let window_row = new ApplicationRow('blacklist', this, app_name);
|
||||
this._blacklist.add(window_row);
|
||||
}
|
||||
|
||||
|
||||
@ -4,19 +4,19 @@ import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
import Gtk from 'gi://Gtk';
|
||||
|
||||
import { pick, on_picking, on_picked } from '../dbus/client.js';
|
||||
import { pick, on_picking, on_picked } from '../../dbus/client.js';
|
||||
|
||||
|
||||
export const WindowRow = GObject.registerClass({
|
||||
GTypeName: 'WindowRow',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/window-row.ui', GLib.UriFlags.NONE),
|
||||
export const ApplicationRow = GObject.registerClass({
|
||||
GTypeName: 'ApplicationRow',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../../ui/application-row.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'window_picker',
|
||||
'window_class',
|
||||
'picking_failure_toast',
|
||||
'window_not_found_toast'
|
||||
],
|
||||
}, class WindowRow extends Adw.ExpanderRow {
|
||||
}, class ApplicationRow extends Adw.ExpanderRow {
|
||||
constructor(list, app_page, app_name) {
|
||||
super({});
|
||||
this._list = list;
|
||||
@ -25,7 +25,7 @@ export const WindowRow = GObject.registerClass({
|
||||
// add a 'remove' button before the text
|
||||
let action_row = this.child.get_first_child().get_first_child();
|
||||
let remove_button = new Gtk.Button({
|
||||
'icon-name': 'remove-window-symbolic',
|
||||
'icon-name': 'remove-row-symbolic',
|
||||
'width-request': 38,
|
||||
'height-request': 38,
|
||||
'margin-top': 6,
|
||||
@ -36,7 +36,7 @@ export const WindowRow = GObject.registerClass({
|
||||
action_row.add_prefix(remove_button);
|
||||
|
||||
// connect the button to the whitelist / blacklist removal
|
||||
remove_button.connect('clicked', _ => this._remove_row());
|
||||
remove_button.connect('clicked', () => this._remove_row());
|
||||
|
||||
// bind row title to text buffer
|
||||
this._window_class.buffer.bind_property(
|
||||
@ -54,11 +54,11 @@ export const WindowRow = GObject.registerClass({
|
||||
}
|
||||
|
||||
// pick a window when the picker button is clicked
|
||||
this._window_picker.connect('clicked', _ => this._do_pick_window());
|
||||
this._window_picker.connect('clicked', () => this._do_pick_window());
|
||||
|
||||
// update list on text buffer change
|
||||
this._window_class.connect('changed',
|
||||
_ => this._update_rows_titles()
|
||||
() => this._update_rows_titles()
|
||||
);
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ export const WindowRow = GObject.registerClass({
|
||||
// a mechanism to know if the extension is listening correcly
|
||||
let has_responded = false;
|
||||
let should_take_answer = true;
|
||||
setTimeout(_ => {
|
||||
setTimeout(() => {
|
||||
if (!has_responded) {
|
||||
// show toast about failure
|
||||
this._app_page._preferences_window.add_toast(
|
||||
@ -90,7 +90,7 @@ export const WindowRow = GObject.registerClass({
|
||||
}
|
||||
}, 250);
|
||||
|
||||
on_picking(_ =>
|
||||
on_picking(() =>
|
||||
has_responded = true
|
||||
);
|
||||
|
||||
@ -1,163 +0,0 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
import Gtk from 'gi://Gtk';
|
||||
|
||||
|
||||
/// Given a component (described by its preferences node), a gschema key and
|
||||
/// a Gtk.ColorButton, binds everything transparently.
|
||||
let bind_color = function (component, key, widget) {
|
||||
let property_name = key.replaceAll('-', '_').toUpperCase();
|
||||
|
||||
let parse_color = _ => {
|
||||
let [r, g, b, a] = component[property_name];
|
||||
let w = widget.rgba;
|
||||
w.red = r;
|
||||
w.green = g;
|
||||
w.blue = b;
|
||||
w.alpha = a;
|
||||
widget.rgba = w;
|
||||
};
|
||||
component.settings.connect('changed::' + key, parse_color);
|
||||
|
||||
widget.connect('color-set', _ => {
|
||||
let c = widget.rgba;
|
||||
component[property_name] = [c.red, c.green, c.blue, c.alpha];
|
||||
});
|
||||
|
||||
parse_color();
|
||||
};
|
||||
|
||||
export const CustomizeRow = GObject.registerClass({
|
||||
GTypeName: 'CustomizeRow',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/customize-row.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'sigma',
|
||||
'brightness',
|
||||
'color',
|
||||
'color_row',
|
||||
'noise_amount',
|
||||
'noise_amount_row',
|
||||
'noise_lightness',
|
||||
'noise_lightness_row',
|
||||
'noise_color_notice'
|
||||
],
|
||||
}, class CustomizeRow extends Adw.ExpanderRow {
|
||||
/// Makes the required connections between the widgets and the preferences.
|
||||
///
|
||||
/// This function may be bound to another object than CustomizeRow, if we
|
||||
/// are using it for the General page; some things will then change (no
|
||||
/// expansion row, and no notice)
|
||||
///
|
||||
/// The color_and_noise parameter is either a boolean (true by default) or
|
||||
/// a widget; and permits selecting weather or not we want to show the color
|
||||
/// and noise buttons to the user. If it is a widget, it means we need to
|
||||
/// dynamically update their visibility, according to the widget's state.
|
||||
connect_to(settings, component_settings, color_and_noise = true) {
|
||||
let s = component_settings.settings;
|
||||
|
||||
// is not fired if in General page
|
||||
if (this instanceof CustomizeRow)
|
||||
// bind the customize button
|
||||
s.bind(
|
||||
'customize', this, 'enable-expansion',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
// bind sigma and brightness
|
||||
s.bind(
|
||||
'sigma', this._sigma, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
s.bind(
|
||||
'brightness', this._brightness, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
// bind the color button
|
||||
bind_color(component_settings, 'color', this._color);
|
||||
|
||||
// bind noise sliders
|
||||
s.bind(
|
||||
'noise-amount', this._noise_amount, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
s.bind(
|
||||
'noise-lightness', this._noise_lightness, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
// color_and_noise is either a boolean or a widget, if true, or it is a
|
||||
// widget, this will appropriately show the required preferences about
|
||||
// setting the color and noise
|
||||
if (color_and_noise) {
|
||||
// if we gave the static_blur widget, we are dealing with the panel,
|
||||
// and binding it to enable/disable the required components when
|
||||
// switching between static and dynamic blur
|
||||
if (color_and_noise instanceof Gtk.Switch) {
|
||||
// bind its state to dynamically toggle the notice and rows
|
||||
color_and_noise.bind_property(
|
||||
'active', this._color_row, 'visible',
|
||||
GObject.BindingFlags.SYNC_CREATE
|
||||
);
|
||||
color_and_noise.bind_property(
|
||||
'active', this._noise_amount_row, 'visible',
|
||||
GObject.BindingFlags.SYNC_CREATE
|
||||
);
|
||||
color_and_noise.bind_property(
|
||||
'active', this._noise_lightness_row, 'visible',
|
||||
GObject.BindingFlags.SYNC_CREATE
|
||||
);
|
||||
color_and_noise.bind_property(
|
||||
'active', this._noise_color_notice, 'visible',
|
||||
GObject.BindingFlags.INVERT_BOOLEAN
|
||||
);
|
||||
|
||||
// only way to get the correct state when first opening the
|
||||
// window...
|
||||
setTimeout(_ => {
|
||||
let is_visible = color_and_noise.active;
|
||||
this._color_row.visible = is_visible;
|
||||
this._noise_amount_row.visible = is_visible;
|
||||
this._noise_lightness_row.visible = is_visible;
|
||||
this._noise_color_notice.visible = !is_visible;
|
||||
}, 10);
|
||||
}
|
||||
|
||||
// if in General page, there is no notice at all
|
||||
if (this instanceof CustomizeRow) {
|
||||
// disable the notice
|
||||
this._noise_color_notice.visible = false;
|
||||
}
|
||||
} else {
|
||||
// enable the notice and disable color and noise preferences
|
||||
this._color_row.visible = false;
|
||||
this._noise_amount_row.visible = false;
|
||||
this._noise_lightness_row.visible = false;
|
||||
this._noise_color_notice.visible = true;
|
||||
}
|
||||
|
||||
// now we bind the color-and-noise preference to the sensitivity of the
|
||||
// associated widgets, this will grey them out if the user choose not to
|
||||
// have color and noise enabled
|
||||
// note: I would love to bind to the visibility instead, but this part
|
||||
// is already dirty enough, it would look like I obfuscate my code
|
||||
// intentionally... (I am not)
|
||||
settings.settings.bind(
|
||||
'color-and-noise',
|
||||
this._color_row, 'sensitive',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
settings.settings.bind(
|
||||
'color-and-noise',
|
||||
this._noise_amount_row, 'sensitive',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
settings.settings.bind(
|
||||
'color-and-noise',
|
||||
this._noise_lightness_row, 'sensitive',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
};
|
||||
});
|
||||
@ -9,31 +9,49 @@ export const Dash = GObject.registerClass({
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/dash.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'blur',
|
||||
'customize',
|
||||
'static_blur',
|
||||
'corner_radius',
|
||||
'pipeline_choose_row',
|
||||
'mode_static',
|
||||
'mode_dynamic',
|
||||
'sigma_row',
|
||||
'sigma',
|
||||
'brightness_row',
|
||||
'brightness',
|
||||
'override_background',
|
||||
'style_dash_to_dock',
|
||||
'unblur_in_overview'
|
||||
],
|
||||
}, class Dash extends Adw.PreferencesPage {
|
||||
constructor(preferences) {
|
||||
constructor(preferences, pipelines_manager, pipelines_page) {
|
||||
super({});
|
||||
|
||||
this.preferences = preferences;
|
||||
this.pipelines_manager = pipelines_manager;
|
||||
this.pipelines_page = pipelines_page;
|
||||
|
||||
this.preferences.dash_to_dock.settings.bind(
|
||||
'blur', this._blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._pipeline_choose_row.initialize(
|
||||
this.preferences.dash_to_dock, this.pipelines_manager, this.pipelines_page
|
||||
);
|
||||
|
||||
this.change_blur_mode(this.preferences.dash_to_dock.STATIC_BLUR, true);
|
||||
|
||||
this._mode_static.connect('toggled',
|
||||
() => this.preferences.dash_to_dock.STATIC_BLUR = this._mode_static.active
|
||||
);
|
||||
this.preferences.dash_to_dock.STATIC_BLUR_changed(
|
||||
() => this.change_blur_mode(this.preferences.dash_to_dock.STATIC_BLUR, false)
|
||||
);
|
||||
|
||||
this.preferences.dash_to_dock.settings.bind(
|
||||
'static-blur',
|
||||
this._static_blur, 'active',
|
||||
'sigma', this._sigma, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.dash_to_dock.settings.bind(
|
||||
'corner-radius',
|
||||
this._corner_radius, 'value',
|
||||
'brightness', this._brightness, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.dash_to_dock.settings.bind(
|
||||
@ -49,7 +67,15 @@ export const Dash = GObject.registerClass({
|
||||
'unblur-in-overview', this._unblur_in_overview, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
}
|
||||
|
||||
this._customize.connect_to(this.preferences, this.preferences.dash_to_dock, false);
|
||||
change_blur_mode(is_static_blur, first_run) {
|
||||
this._mode_static.set_active(is_static_blur);
|
||||
if (first_run)
|
||||
this._mode_dynamic.set_active(!is_static_blur);
|
||||
|
||||
this._pipeline_choose_row.set_visible(is_static_blur);
|
||||
this._sigma_row.set_visible(!is_static_blur);
|
||||
this._brightness_row.set_visible(!is_static_blur);
|
||||
}
|
||||
});
|
||||
@ -1,49 +0,0 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
|
||||
import { CustomizeRow } from './customize_row.js';
|
||||
|
||||
|
||||
export const General = GObject.registerClass({
|
||||
GTypeName: 'General',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/general.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'sigma',
|
||||
'brightness',
|
||||
'color',
|
||||
'color_row',
|
||||
'noise_amount',
|
||||
'noise_amount_row',
|
||||
'noise_lightness',
|
||||
'noise_lightness_row',
|
||||
'color_and_noise',
|
||||
'hack_level',
|
||||
'debug',
|
||||
'reset'
|
||||
],
|
||||
}, class General extends Adw.PreferencesPage {
|
||||
constructor(preferences) {
|
||||
super({});
|
||||
|
||||
this.preferences = preferences;
|
||||
|
||||
CustomizeRow.prototype.connect_to.call(this, preferences, preferences);
|
||||
|
||||
this.preferences.settings.bind(
|
||||
'color-and-noise', this._color_and_noise, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.settings.bind(
|
||||
'hacks-level', this._hack_level, 'selected',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.settings.bind(
|
||||
'debug', this._debug, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._reset.connect('clicked', _ => this.preferences.reset());
|
||||
}
|
||||
});
|
||||
@ -25,7 +25,8 @@ function addMenuToHeader(window, builder) {
|
||||
const pages_stack = page.get_parent(); // AdwViewStack
|
||||
const content_stack = pages_stack.get_parent().get_parent(); // GtkStack
|
||||
const preferences = content_stack.get_parent(); // GtkBox
|
||||
const headerbar = preferences.get_first_child(); // AdwHeaderBar
|
||||
const headerbar = preferences.get_first_child().get_next_sibling()
|
||||
.get_first_child().get_first_child().get_first_child(); // AdwHeaderBar
|
||||
headerbar.pack_start(builder.get_object('info_menu'));
|
||||
|
||||
// setup menu actions
|
||||
@ -60,7 +61,7 @@ function addMenuToHeader(window, builder) {
|
||||
let act = new Gio.SimpleAction({ name: action.name });
|
||||
act.connect(
|
||||
'activate',
|
||||
_ => Gtk.show_uri(window, action.link, Gdk.CURRENT_TIME)
|
||||
() => Gtk.show_uri(window, action.link, Gdk.CURRENT_TIME)
|
||||
);
|
||||
actionGroup.add_action(act);
|
||||
});
|
||||
|
||||
@ -9,41 +9,78 @@ export const Other = GObject.registerClass({
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/other.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'lockscreen_blur',
|
||||
'lockscreen_customize',
|
||||
'lockscreen_pipeline_choose_row',
|
||||
|
||||
'screenshot_blur',
|
||||
'screenshot_customize',
|
||||
'screenshot_pipeline_choose_row',
|
||||
|
||||
'window_list_blur',
|
||||
'window_list_customize',
|
||||
'window_list_sigma',
|
||||
'window_list_brightness',
|
||||
|
||||
'coverflow_alt_tab_blur',
|
||||
'coverflow_alt_tab_pipeline_choose_row',
|
||||
|
||||
'hack_level',
|
||||
'debug',
|
||||
'reset'
|
||||
],
|
||||
}, class Overview extends Adw.PreferencesPage {
|
||||
constructor(preferences) {
|
||||
constructor(preferences, pipelines_manager, pipelines_page) {
|
||||
super({});
|
||||
|
||||
this.preferences = preferences;
|
||||
this.pipelines_manager = pipelines_manager;
|
||||
this.pipelines_page = pipelines_page;
|
||||
|
||||
this.preferences.lockscreen.settings.bind(
|
||||
'blur', this._lockscreen_blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._lockscreen_customize.connect_to(this.preferences, this.preferences.lockscreen);
|
||||
this._lockscreen_pipeline_choose_row.initialize(
|
||||
this.preferences.lockscreen, this.pipelines_manager, this.pipelines_page
|
||||
);
|
||||
|
||||
this.preferences.screenshot.settings.bind(
|
||||
'blur', this._screenshot_blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._screenshot_customize.connect_to(this.preferences, this.preferences.screenshot);
|
||||
this._screenshot_pipeline_choose_row.initialize(
|
||||
this.preferences.screenshot, this.pipelines_manager, this.pipelines_page
|
||||
);
|
||||
|
||||
this.preferences.window_list.settings.bind(
|
||||
'blur', this._window_list_blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._window_list_customize.connect_to(
|
||||
this.preferences, this.preferences.window_list, false
|
||||
this.preferences.window_list.settings.bind(
|
||||
'sigma', this._window_list_sigma, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.window_list.settings.bind(
|
||||
'brightness', this._window_list_brightness, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this.preferences.coverflow_alt_tab.settings.bind(
|
||||
'blur', this._coverflow_alt_tab_blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this._coverflow_alt_tab_pipeline_choose_row.initialize(
|
||||
this.preferences.coverflow_alt_tab, this.pipelines_manager, this.pipelines_page
|
||||
);
|
||||
|
||||
this.preferences.settings.bind(
|
||||
'hacks-level', this._hack_level, 'selected',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.settings.bind(
|
||||
'debug', this._debug, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._reset.connect('clicked', () => this.preferences.reset());
|
||||
}
|
||||
});
|
||||
@ -9,39 +9,51 @@ export const Overview = GObject.registerClass({
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/overview.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'overview_blur',
|
||||
'overview_customize',
|
||||
'pipeline_choose_row',
|
||||
'overview_style_components',
|
||||
|
||||
'appfolder_blur',
|
||||
'appfolder_customize',
|
||||
'appfolder_sigma',
|
||||
'appfolder_brightness',
|
||||
'appfolder_style_dialogs'
|
||||
],
|
||||
}, class Overview extends Adw.PreferencesPage {
|
||||
constructor(preferences) {
|
||||
constructor(preferences, pipelines_manager, pipelines_page) {
|
||||
super({});
|
||||
|
||||
this.preferences = preferences;
|
||||
this.pipelines_manager = pipelines_manager;
|
||||
this.pipelines_page = pipelines_page;
|
||||
|
||||
this.preferences.overview.settings.bind(
|
||||
'blur', this._overview_blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._pipeline_choose_row.initialize(
|
||||
this.preferences.overview, this.pipelines_manager, this.pipelines_page
|
||||
);
|
||||
|
||||
this.preferences.overview.settings.bind(
|
||||
'style-components', this._overview_style_components, 'selected',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._overview_customize.connect_to(this.preferences, this.preferences.overview);
|
||||
|
||||
this.preferences.appfolder.settings.bind(
|
||||
'blur', this._appfolder_blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.appfolder.settings.bind(
|
||||
'sigma', this._appfolder_sigma, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.appfolder.settings.bind(
|
||||
'brightness', this._appfolder_brightness, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.appfolder.settings.bind(
|
||||
'style-dialogs', this._appfolder_style_dialogs, 'selected',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._appfolder_customize.connect_to(this.preferences, this.preferences.appfolder, false);
|
||||
}
|
||||
});
|
||||
@ -9,8 +9,13 @@ export const Panel = GObject.registerClass({
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/panel.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'blur',
|
||||
'customize',
|
||||
'static_blur',
|
||||
'pipeline_choose_row',
|
||||
'mode_static',
|
||||
'mode_dynamic',
|
||||
'sigma_row',
|
||||
'sigma',
|
||||
'brightness_row',
|
||||
'brightness',
|
||||
'unblur_in_overview',
|
||||
'force_light_text',
|
||||
'override_background',
|
||||
@ -20,17 +25,37 @@ export const Panel = GObject.registerClass({
|
||||
'dtp_blur_original_panel'
|
||||
],
|
||||
}, class Panel extends Adw.PreferencesPage {
|
||||
constructor(preferences) {
|
||||
constructor(preferences, pipelines_manager, pipelines_page) {
|
||||
super({});
|
||||
|
||||
this.preferences = preferences;
|
||||
this.pipelines_manager = pipelines_manager;
|
||||
this.pipelines_page = pipelines_page;
|
||||
|
||||
this.preferences.panel.settings.bind(
|
||||
'blur', this._blur, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._pipeline_choose_row.initialize(
|
||||
this.preferences.panel, this.pipelines_manager, this.pipelines_page
|
||||
);
|
||||
|
||||
this.change_blur_mode(this.preferences.panel.STATIC_BLUR, true);
|
||||
|
||||
this._mode_static.connect('toggled',
|
||||
() => this.preferences.panel.STATIC_BLUR = this._mode_static.active
|
||||
);
|
||||
this.preferences.panel.STATIC_BLUR_changed(
|
||||
() => this.change_blur_mode(this.preferences.panel.STATIC_BLUR, false)
|
||||
);
|
||||
|
||||
this.preferences.panel.settings.bind(
|
||||
'static-blur', this._static_blur, 'active',
|
||||
'sigma', this._sigma, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.panel.settings.bind(
|
||||
'brightness', this._brightness, 'value',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
this.preferences.panel.settings.bind(
|
||||
@ -55,9 +80,6 @@ export const Panel = GObject.registerClass({
|
||||
this._override_background_dynamically, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
|
||||
this._customize.connect_to(this.preferences, this.preferences.panel, this._static_blur);
|
||||
|
||||
this.preferences.hidetopbar.settings.bind(
|
||||
'compatibility', this._hidetopbar_compatibility, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
@ -67,4 +89,14 @@ export const Panel = GObject.registerClass({
|
||||
Gio.SettingsBindFlags.DEFAULT
|
||||
);
|
||||
}
|
||||
|
||||
change_blur_mode(is_static_blur, first_run) {
|
||||
this._mode_static.set_active(is_static_blur);
|
||||
if (first_run)
|
||||
this._mode_dynamic.set_active(!is_static_blur);
|
||||
|
||||
this._pipeline_choose_row.set_visible(is_static_blur);
|
||||
this._sigma_row.set_visible(!is_static_blur);
|
||||
this._brightness_row.set_visible(!is_static_blur);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,98 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
|
||||
|
||||
import { PipelineGroup } from './pipelines_management/pipeline_group.js';
|
||||
import { EffectsDialog } from './pipelines_management/effects_dialog.js';
|
||||
|
||||
|
||||
export const Pipelines = GObject.registerClass({
|
||||
GTypeName: 'Pipelines',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../ui/pipelines.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'add_pipeline'
|
||||
],
|
||||
}, class Pipelines extends Adw.PreferencesPage {
|
||||
constructor(preferences, pipelines_manager, window) {
|
||||
super({});
|
||||
|
||||
this.preferences = preferences;
|
||||
this.pipelines_manager = pipelines_manager;
|
||||
this.window = window;
|
||||
|
||||
this.pipelines_map = new Map;
|
||||
|
||||
for (let pipeline_id in this.pipelines_manager.pipelines)
|
||||
this.add_pipeline(pipeline_id, false);
|
||||
|
||||
this.preferences.connect('reset', _ => {
|
||||
this.pipelines_map.forEach((_infos, pid) => this.remove_pipeline(pid));
|
||||
for (let pipeline_id in this.pipelines_manager.pipelines)
|
||||
this.add_pipeline(pipeline_id, false);
|
||||
});
|
||||
|
||||
this._add_pipeline.connect(
|
||||
"clicked",
|
||||
() => this.pipelines_manager.create_pipeline(_("New pipeline"))
|
||||
);
|
||||
|
||||
this.pipelines_manager.connect(
|
||||
"pipeline-created",
|
||||
(_obj, id, _pipeline) => this.add_pipeline(id, true)
|
||||
);
|
||||
}
|
||||
|
||||
add_pipeline(pipeline_id, scroll_to_bottom) {
|
||||
let pipeline = this.pipelines_manager.pipelines[pipeline_id];
|
||||
let pipeline_group = new PipelineGroup(
|
||||
this.pipelines_manager, pipeline_id, pipeline, this
|
||||
);
|
||||
|
||||
let pipeline_destroyed_id = this.pipelines_manager.connect(
|
||||
pipeline_id + "::pipeline-destroyed",
|
||||
() => this.remove_pipeline(pipeline_id)
|
||||
);
|
||||
|
||||
let pipeline_renamed_id = this.pipelines_manager.connect(
|
||||
pipeline_id + "::pipeline-renamed",
|
||||
(_obj, name) => this.rename_pipeline(pipeline_id, name)
|
||||
);
|
||||
|
||||
this.pipelines_map.set(pipeline_id, {
|
||||
pipeline_group, pipeline_destroyed_id, pipeline_renamed_id
|
||||
});
|
||||
|
||||
this.add(pipeline_group);
|
||||
|
||||
// scroll to the bottom of the page
|
||||
if (scroll_to_bottom) {
|
||||
this.window.set_visible_page(this);
|
||||
setTimeout(() => {
|
||||
const scroll_adjustment = this.get_first_child().get_vadjustment();
|
||||
scroll_adjustment.value = scroll_adjustment.get_upper();
|
||||
}, 10);
|
||||
pipeline_group._title.grab_focus();
|
||||
}
|
||||
}
|
||||
|
||||
remove_pipeline(pipeline_id) {
|
||||
let pipeline_infos = this.pipelines_map.get(pipeline_id);
|
||||
if (pipeline_infos) {
|
||||
this.pipelines_manager.disconnect(pipeline_infos.pipeline_destroyed_id);
|
||||
this.remove(pipeline_infos.pipeline_group);
|
||||
this.pipelines_map.delete(pipeline_id);
|
||||
}
|
||||
}
|
||||
|
||||
rename_pipeline(pipeline_id, name) {
|
||||
let pipeline_infos = this.pipelines_map.get(pipeline_id);
|
||||
if (pipeline_infos)
|
||||
pipeline_infos.pipeline_group.set_title(name.length > 0 ? name : " ");
|
||||
}
|
||||
|
||||
open_effects_dialog(pipeline_id) {
|
||||
let dialog = new EffectsDialog(this.pipelines_manager, pipeline_id);
|
||||
dialog.present(this.window);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,222 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gtk from 'gi://Gtk';
|
||||
import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
|
||||
|
||||
import { get_supported_effects } from '../../effects/effects.js';
|
||||
|
||||
|
||||
export const EffectRow = GObject.registerClass({
|
||||
GTypeName: 'EffectRow',
|
||||
InternalChildren: [],
|
||||
}, class EffectRow extends Adw.ExpanderRow {
|
||||
constructor(effect, effects_dialog) {
|
||||
super({});
|
||||
|
||||
this.SUPPORTED_EFFECTS = get_supported_effects(_);
|
||||
|
||||
this.effect = effect;
|
||||
this.effects_dialog = effects_dialog;
|
||||
this.pipeline_id = effects_dialog.pipeline_id;
|
||||
this.pipelines_manager = effects_dialog.pipelines_manager;
|
||||
|
||||
if (effect.type in this.SUPPORTED_EFFECTS) {
|
||||
this.set_title(this.SUPPORTED_EFFECTS[effect.type].name);
|
||||
this.set_subtitle(this.SUPPORTED_EFFECTS[effect.type].description);
|
||||
this.populate_options();
|
||||
}
|
||||
else {
|
||||
this._warn(`could not assign effect ${effect.type} to its correct name`);
|
||||
this.set_title(effect.type);
|
||||
}
|
||||
|
||||
let prefix_bin = new Gtk.Box({
|
||||
spacing: 6
|
||||
});
|
||||
this.add_prefix(prefix_bin);
|
||||
|
||||
let move_bin = new Gtk.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
'width-request': 38,
|
||||
'height-request': 38,
|
||||
'margin-top': 6,
|
||||
'margin-bottom': 6
|
||||
});
|
||||
prefix_bin.append(move_bin);
|
||||
move_bin.add_css_class('linked');
|
||||
|
||||
this._move_up_button = new Gtk.Button({
|
||||
'icon-name': 'go-up-symbolic',
|
||||
'width-request': 38,
|
||||
'height-request': 19
|
||||
});
|
||||
this._move_down_button = new Gtk.Button({
|
||||
'icon-name': 'go-down-symbolic',
|
||||
'width-request': 38,
|
||||
'height-request': 19
|
||||
});
|
||||
this._move_up_button.add_css_class('flat');
|
||||
this._move_down_button.add_css_class('flat');
|
||||
move_bin.append(this._move_up_button);
|
||||
move_bin.append(this._move_down_button);
|
||||
|
||||
this._move_up_button.connect('clicked', () => effects_dialog.move_row_by(this, -1));
|
||||
this._move_down_button.connect('clicked', () => effects_dialog.move_row_by(this, +1));
|
||||
|
||||
let remove_button = new Gtk.Button({
|
||||
'icon-name': 'remove-row-symbolic',
|
||||
'width-request': 38,
|
||||
'height-request': 38,
|
||||
'margin-top': 6,
|
||||
'margin-bottom': 6,
|
||||
'valign': Gtk.Align.CENTER
|
||||
});
|
||||
prefix_bin.append(remove_button);
|
||||
remove_button.add_css_class('destructive-action');
|
||||
|
||||
remove_button.connect('clicked', () => effects_dialog.remove_row(this));
|
||||
}
|
||||
|
||||
populate_options() {
|
||||
const editable_params = this.SUPPORTED_EFFECTS[this.effect.type].editable_params;
|
||||
|
||||
if (Object.keys(editable_params).length == 0)
|
||||
this.enable_expansion = false;
|
||||
|
||||
for (const param_key in editable_params) {
|
||||
let param = editable_params[param_key];
|
||||
let row;
|
||||
switch (param.type) {
|
||||
case "integer":
|
||||
row = new Adw.SpinRow({
|
||||
adjustment: new Gtk.Adjustment({
|
||||
lower: param.min,
|
||||
upper: param.max,
|
||||
step_increment: param.increment
|
||||
})
|
||||
});
|
||||
row.adjustment.set_value(this.get_effect_param(param_key));
|
||||
row.adjustment.connect(
|
||||
'value-changed', () => this.set_effect_param(param_key, row.adjustment.value)
|
||||
);
|
||||
break;
|
||||
|
||||
case "float":
|
||||
row = new Adw.ActionRow;
|
||||
let scale = new Gtk.Scale({
|
||||
valign: Gtk.Align.CENTER,
|
||||
hexpand: true,
|
||||
width_request: 200,
|
||||
draw_value: true,
|
||||
value_pos: Gtk.PositionType.RIGHT,
|
||||
digits: param.digits,
|
||||
adjustment: new Gtk.Adjustment({
|
||||
lower: param.min,
|
||||
upper: param.max,
|
||||
step_increment: param.increment,
|
||||
page_increment: param.big_increment
|
||||
})
|
||||
});
|
||||
// TODO check if it's a good idea to set the default parameter, as the "good"
|
||||
// value really change depending on the user wallpaper... if so, do for dynamic
|
||||
// blur too
|
||||
scale.add_mark(
|
||||
this.get_default_effect_param(param_key), Gtk.PositionType.BOTTOM, null
|
||||
);
|
||||
row.add_suffix(scale);
|
||||
scale.adjustment.set_value(this.get_effect_param(param_key));
|
||||
scale.adjustment.connect(
|
||||
'value-changed', () => this.set_effect_param(param_key, scale.adjustment.value)
|
||||
);
|
||||
break;
|
||||
|
||||
case "boolean":
|
||||
row = new Adw.SwitchRow;
|
||||
row.set_active(this.get_effect_param(param_key));
|
||||
row.connect(
|
||||
'notify::active', () => this.set_effect_param(param_key, row.active)
|
||||
);
|
||||
break;
|
||||
|
||||
case "dropdown":
|
||||
row = new Adw.ComboRow({ model: new Gtk.StringList });
|
||||
param.options.forEach(option => row.model.append(option));
|
||||
row.selected = this.get_effect_param(param_key);
|
||||
row.connect(
|
||||
'notify::selected', () => this.set_effect_param(param_key, row.selected)
|
||||
);
|
||||
break;
|
||||
|
||||
case "rgba":
|
||||
row = new Adw.ActionRow;
|
||||
let color_button = new Gtk.ColorButton({
|
||||
valign: Gtk.Align.CENTER,
|
||||
width_request: 75,
|
||||
height_request: 45,
|
||||
show_editor: true,
|
||||
use_alpha: true
|
||||
});
|
||||
row.add_suffix(color_button);
|
||||
// set original color
|
||||
let c = color_button.get_rgba().copy();
|
||||
[c.red, c.green, c.blue, c.alpha] = this.get_effect_param(param_key);
|
||||
color_button.set_rgba(c);
|
||||
// update on on 'color-set'
|
||||
color_button.connect(
|
||||
'color-set', () => {
|
||||
let c = color_button.get_rgba();
|
||||
this.set_effect_param(param_key, [c.red, c.green, c.blue, c.alpha]);
|
||||
}
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
row = new Adw.ActionRow;
|
||||
break;
|
||||
}
|
||||
row.set_title(param.name);
|
||||
row.set_subtitle(param.description);
|
||||
this.add_row(row);
|
||||
}
|
||||
}
|
||||
|
||||
get_effect_param(key) {
|
||||
let effects = this.pipelines_manager.pipelines[this.pipeline_id].effects;
|
||||
const gsettings_effect = effects.find(e => e.id == this.effect.id);
|
||||
|
||||
if ('params' in gsettings_effect && key in gsettings_effect.params)
|
||||
return gsettings_effect.params[key];
|
||||
else
|
||||
return this.get_default_effect_param(key);
|
||||
}
|
||||
|
||||
get_default_effect_param(key) {
|
||||
return this.SUPPORTED_EFFECTS[this.effect.type].class.default_params[key];
|
||||
}
|
||||
|
||||
set_effect_param(key, value) {
|
||||
// we must pay attention not to change the effects in the pipelines manager before updating
|
||||
// it in gsettings, else it won't be updated (or every effect will be)
|
||||
let effects = this.pipelines_manager.pipelines[this.pipeline_id].effects;
|
||||
const effect_index = effects.findIndex(e => e.id == this.effect.id);
|
||||
|
||||
if (effect_index >= 0) {
|
||||
effects[effect_index] = {
|
||||
...this.effect, params: { ...this.effect.params }
|
||||
};
|
||||
effects[effect_index].params[key] = value;
|
||||
this.effect = effects[effect_index];
|
||||
}
|
||||
else
|
||||
this._warn(`effect not found when setting key ${key}`);
|
||||
|
||||
this.pipelines_manager.update_pipeline_effects(this.pipeline_id, effects, false);
|
||||
}
|
||||
|
||||
_warn(str) {
|
||||
console.warn(
|
||||
`[Blur my Shell > effect row] pipeline '${this.pipeline_id}',`
|
||||
+ ` effect '${this.effect.id}': ${str}`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,174 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gtk from 'gi://Gtk';
|
||||
import Gio from 'gi://Gio';
|
||||
import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
|
||||
|
||||
import { EffectRow } from './effect_row.js';
|
||||
import { get_effects_groups, get_supported_effects } from '../../effects/effects.js';
|
||||
|
||||
export const EffectsDialog = GObject.registerClass({
|
||||
GTypeName: 'EffectsDialog',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../../ui/effects-dialog.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
"add_effect",
|
||||
"add_effect_alt_menu",
|
||||
"effects_list"
|
||||
],
|
||||
}, class EffectsDialog extends Adw.PreferencesDialog {
|
||||
constructor(pipelines_manager, pipeline_id) {
|
||||
super({});
|
||||
|
||||
this.EFFECTS_GROUPS = get_effects_groups(_);
|
||||
this.SUPPORTED_EFFECTS = get_supported_effects(_);
|
||||
|
||||
this.pipelines_manager = pipelines_manager;
|
||||
this.pipeline_id = pipeline_id;
|
||||
|
||||
let pipeline = pipelines_manager.pipelines[pipeline_id];
|
||||
|
||||
this.set_title(pipeline.name.length > 0 ? _(`Effects for "${pipeline.name}"`) : _("Effects"));
|
||||
|
||||
pipeline.effects.forEach(effect => {
|
||||
const effect_row = new EffectRow(effect, this);
|
||||
this._effects_list.add(effect_row);
|
||||
this.update_rows_insensitive_mover(effect_row);
|
||||
});
|
||||
|
||||
// setup advanced effects chooser action
|
||||
this.show_advanced_effects = false;
|
||||
let action_group = new Gio.SimpleActionGroup();
|
||||
this.insert_action_group('effects-dialog', action_group);
|
||||
let advanced_effects_action = Gio.SimpleAction.new_stateful(
|
||||
'advanced-effects-bool',
|
||||
null,
|
||||
GLib.Variant.new_boolean(this.show_advanced_effects)
|
||||
);
|
||||
advanced_effects_action.connect(
|
||||
'change-state',
|
||||
(_, state) => {
|
||||
this.show_advanced_effects = state.get_boolean();
|
||||
this.build_effects_chooser();
|
||||
advanced_effects_action.set_state(state);
|
||||
}
|
||||
);
|
||||
action_group.add_action(advanced_effects_action);
|
||||
|
||||
this.build_effects_chooser();
|
||||
this._add_effect.connect('clicked', () => this.effects_chooser_dialog.present(this));
|
||||
}
|
||||
|
||||
build_effects_chooser() {
|
||||
this.effects_chooser_dialog = new Adw.Dialog({
|
||||
presentation_mode: Adw.DialogPresentationMode.BOTTOM_SHEET,
|
||||
content_width: 450
|
||||
});
|
||||
|
||||
let page = new Adw.PreferencesPage;
|
||||
this.effects_chooser_dialog.set_child(page);
|
||||
|
||||
for (const effects_group in this.EFFECTS_GROUPS) {
|
||||
const group_infos = this.EFFECTS_GROUPS[effects_group];
|
||||
|
||||
let group = new Adw.PreferencesGroup({
|
||||
title: group_infos.name
|
||||
});
|
||||
page.add(group);
|
||||
|
||||
for (const effect_type of group_infos.contains) {
|
||||
if (!(effect_type in this.SUPPORTED_EFFECTS))
|
||||
continue;
|
||||
|
||||
if (!this.show_advanced_effects && this.SUPPORTED_EFFECTS[effect_type].is_advanced)
|
||||
continue;
|
||||
|
||||
let action_row = new Adw.ActionRow({
|
||||
title: this.SUPPORTED_EFFECTS[effect_type].name,
|
||||
subtitle: this.SUPPORTED_EFFECTS[effect_type].description
|
||||
});
|
||||
let select_button = new Gtk.Button({
|
||||
'icon-name': 'select-row-symbolic',
|
||||
'width-request': 38,
|
||||
'height-request': 38,
|
||||
'margin-top': 6,
|
||||
'margin-bottom': 6
|
||||
});
|
||||
group.add(action_row);
|
||||
|
||||
select_button.add_css_class('flat');
|
||||
action_row.add_suffix(select_button);
|
||||
action_row.set_activatable_widget(select_button);
|
||||
select_button.connect('clicked', () => {
|
||||
this.append_effect(effect_type);
|
||||
this.effects_chooser_dialog.close();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
append_effect(effect_type) {
|
||||
const effect = {
|
||||
type: effect_type, id: "effect_" + ("" + Math.random()).slice(2, 16)
|
||||
};
|
||||
this.pipelines_manager.update_pipeline_effects(
|
||||
this.pipeline_id,
|
||||
[...this.pipelines_manager.pipelines[this.pipeline_id].effects, effect]
|
||||
);
|
||||
|
||||
const effect_row = new EffectRow(effect, this);
|
||||
this._effects_list.add(effect_row);
|
||||
this.move_row_by(effect_row, 0);
|
||||
this.update_rows_insensitive_mover(effect_row);
|
||||
}
|
||||
|
||||
move_row_by(row, number) {
|
||||
const effects = this.pipelines_manager.pipelines[this.pipeline_id].effects;
|
||||
const effect_index = effects.findIndex(e => e.id == row.effect.id);
|
||||
|
||||
if (effect_index >= 0) {
|
||||
effects.splice(effect_index, 1);
|
||||
effects.splice(effect_index + number, 0, row.effect);
|
||||
|
||||
const listbox = row.get_parent();
|
||||
listbox.set_sort_func((row_a, row_b) => {
|
||||
const id_a = effects.findIndex(e => e.id == row_a.effect.id);
|
||||
const id_b = effects.findIndex(e => e.id == row_b.effect.id);
|
||||
return id_a > id_b;
|
||||
});
|
||||
|
||||
this.update_rows_insensitive_mover(row);
|
||||
|
||||
this.pipelines_manager.update_pipeline_effects(
|
||||
this.pipeline_id, effects
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
update_rows_insensitive_mover(any_row) {
|
||||
if (this._insensitive_top)
|
||||
this._insensitive_top.set_sensitive(true);
|
||||
if (this._insensitive_bottom)
|
||||
this._insensitive_bottom.set_sensitive(true);
|
||||
|
||||
const listbox = any_row.get_parent();
|
||||
this._insensitive_top = listbox.get_first_child()._move_up_button;
|
||||
this._insensitive_top?.set_sensitive(false);
|
||||
this._insensitive_bottom = listbox.get_last_child()._move_down_button;
|
||||
this._insensitive_bottom?.set_sensitive(false);
|
||||
}
|
||||
|
||||
remove_row(row) {
|
||||
const effects = this.pipelines_manager.pipelines[this.pipeline_id].effects;
|
||||
const effect_index = effects.findIndex(e => e.id == row.effect.id);
|
||||
|
||||
if (effect_index >= 0) {
|
||||
effects.splice(effect_index, 1);
|
||||
this.pipelines_manager.update_pipeline_effects(
|
||||
this.pipeline_id, effects
|
||||
);
|
||||
}
|
||||
|
||||
this._effects_list.remove(row);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,106 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gtk from 'gi://Gtk';
|
||||
import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
|
||||
|
||||
|
||||
export const PipelineChooseRow = GObject.registerClass({
|
||||
GTypeName: 'PipelineChooseRow',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../../ui/pipeline-choose-row.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
'pipeline_choose',
|
||||
'pipeline_model',
|
||||
'pipeline_edit'
|
||||
],
|
||||
}, class PipelineChooseRow extends Adw.ActionRow {
|
||||
initialize(preferences, pipelines_manager, pipelines_page) {
|
||||
this.preferences = preferences;
|
||||
this.pipelines_manager = pipelines_manager;
|
||||
this.pipelines_page = pipelines_page;
|
||||
|
||||
this.create_pipelines_list();
|
||||
|
||||
// display the correct pipeline name in the drop-down instead of their ids
|
||||
const closure_func = string_object => {
|
||||
const pipeline_id = string_object.get_string();
|
||||
if (pipeline_id == 'create_new')
|
||||
return _("Create new pipeline");
|
||||
if (pipeline_id in this.pipelines_manager.pipelines)
|
||||
return this.pipelines_manager.pipelines[pipeline_id].name;
|
||||
else
|
||||
return "";
|
||||
};
|
||||
|
||||
const expression = new Gtk.ClosureExpression(GObject.TYPE_STRING, closure_func, []);
|
||||
this._pipeline_choose.expression = expression;
|
||||
|
||||
// TODO fix the expression not being re-evaluated other than by setting it again
|
||||
this.pipelines_manager.connect(
|
||||
'pipeline-names-changed',
|
||||
() => this._pipeline_choose.expression = new Gtk.ClosureExpression(
|
||||
GObject.TYPE_STRING, closure_func, []
|
||||
)
|
||||
);
|
||||
|
||||
this.preferences.PIPELINE_changed(() => this.on_settings_pipeline_changed());
|
||||
|
||||
this.pipelines_manager.connect('pipeline-list-changed', () => this.create_pipelines_list());
|
||||
|
||||
this._pipeline_choose.connect('notify::selected', () => this.on_selected_pipeline_changed());
|
||||
|
||||
this._pipeline_edit.connect(
|
||||
'clicked',
|
||||
() => this.pipelines_page.open_effects_dialog(this.preferences.PIPELINE)
|
||||
);
|
||||
}
|
||||
|
||||
on_selected_pipeline_changed() {
|
||||
if (!this._pipeline_choose.selected_item || this._is_creating_pipelines_list)
|
||||
return;
|
||||
|
||||
const pipeline_id = this._pipeline_choose.selected_item.get_string();
|
||||
if (pipeline_id == 'create_new') {
|
||||
const id = this.pipelines_manager.create_pipeline(_("New pipeline"));
|
||||
this.preferences.PIPELINE = id;
|
||||
}
|
||||
else
|
||||
this.preferences.PIPELINE = pipeline_id;
|
||||
}
|
||||
|
||||
on_settings_pipeline_changed() {
|
||||
for (let i = 0; i < this._pipeline_model.n_items; i++) {
|
||||
const pipeline_id = this._pipeline_model.get_string(i);
|
||||
// if we have more pipelines than we should have: rebuild...
|
||||
// that is the case when resetting the preferences for example
|
||||
if (!(pipeline_id in this.pipelines_manager)) {
|
||||
this.create_pipelines_list();
|
||||
return;
|
||||
}
|
||||
if (pipeline_id == this.preferences.PIPELINE)
|
||||
this._pipeline_choose.set_selected(i);
|
||||
}
|
||||
}
|
||||
|
||||
create_pipelines_list() {
|
||||
// prevent the pipeline selector from being updated while re-creating the list
|
||||
this._is_creating_pipelines_list = true;
|
||||
|
||||
// remove ancient items
|
||||
this._pipeline_model.splice(0, this._pipeline_model.n_items, null);
|
||||
|
||||
// add new ones
|
||||
let i = 0;
|
||||
for (let pipeline_id in this.pipelines_manager.pipelines) {
|
||||
this._pipeline_model.append(pipeline_id);
|
||||
if (pipeline_id == this.preferences.PIPELINE)
|
||||
this._pipeline_choose.set_selected(i);
|
||||
i++;
|
||||
}
|
||||
this._pipeline_model.append('create_new');
|
||||
|
||||
// now update the drop-down selector
|
||||
this._is_creating_pipelines_list = false;
|
||||
this.on_selected_pipeline_changed();
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,99 @@
|
||||
import Adw from 'gi://Adw';
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gtk from 'gi://Gtk';
|
||||
import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
|
||||
|
||||
import { get_supported_effects } from '../../effects/effects.js';
|
||||
|
||||
|
||||
export const PipelineGroup = GObject.registerClass({
|
||||
GTypeName: 'PipelineGroup',
|
||||
Template: GLib.uri_resolve_relative(import.meta.url, '../../ui/pipeline-group.ui', GLib.UriFlags.NONE),
|
||||
InternalChildren: [
|
||||
"title",
|
||||
"effects_description_row",
|
||||
"manage_effects"
|
||||
],
|
||||
}, class PipelineGroup extends Adw.PreferencesGroup {
|
||||
constructor(pipelines_manager, pipeline_id, pipeline, pipelines_page) {
|
||||
super({});
|
||||
|
||||
this.SUPPORTED_EFFECTS = get_supported_effects(_);
|
||||
|
||||
this._pipelines_manager = pipelines_manager;
|
||||
this._pipelines_page = pipelines_page;
|
||||
this._pipeline_id = pipeline_id;
|
||||
|
||||
// set the description
|
||||
this.set_description(_(`Pipeline id: "${pipeline_id}"`));
|
||||
|
||||
// set the title and connect it to the text entry
|
||||
this.set_title(pipeline.name.length > 0 ? pipeline.name : " ");
|
||||
this._title.set_text(pipeline.name);
|
||||
this._title.connect(
|
||||
'changed',
|
||||
() => pipelines_manager.rename_pipeline(pipeline_id, this._title.get_text())
|
||||
);
|
||||
|
||||
// the bin containing the actions
|
||||
let prefix_bin = new Gtk.Box;
|
||||
prefix_bin.add_css_class('linked');
|
||||
this._title.add_prefix(prefix_bin);
|
||||
|
||||
// add a 'remove' button if we are not the default pipeline
|
||||
if (pipeline_id != "pipeline_default") {
|
||||
let remove_button = new Gtk.Button({
|
||||
'icon-name': 'remove-row-symbolic',
|
||||
'width-request': 38,
|
||||
'height-request': 38,
|
||||
'margin-top': 6,
|
||||
'margin-bottom': 6
|
||||
});
|
||||
remove_button.add_css_class('destructive-action');
|
||||
prefix_bin.append(remove_button);
|
||||
remove_button.connect('clicked', () => pipelines_manager.delete_pipeline(pipeline_id));
|
||||
}
|
||||
// add a 'duplicate' button
|
||||
let duplicate_button = new Gtk.Button({
|
||||
'icon-name': 'duplicate-row-symbolic',
|
||||
'width-request': 38,
|
||||
'height-request': 38,
|
||||
'margin-top': 6,
|
||||
'margin-bottom': 6
|
||||
});
|
||||
prefix_bin.append(duplicate_button);
|
||||
duplicate_button.connect('clicked', () => pipelines_manager.duplicate_pipeline(pipeline_id));
|
||||
|
||||
this.update_effects_description_row();
|
||||
this._pipelines_manager.connect(
|
||||
pipeline_id + '::pipeline-updated',
|
||||
() => this.update_effects_description_row()
|
||||
);
|
||||
|
||||
this._manage_effects.connect(
|
||||
'clicked',
|
||||
() => pipelines_page.open_effects_dialog(pipeline_id)
|
||||
);
|
||||
}
|
||||
|
||||
update_effects_description_row() {
|
||||
const effects = this._pipelines_manager.pipelines[this._pipeline_id].effects;
|
||||
|
||||
if (effects.length == 0)
|
||||
this._effects_description_row.set_title(_("No effect"));
|
||||
else if (effects.length == 1)
|
||||
this._effects_description_row.set_title(_("1 effect"));
|
||||
else
|
||||
this._effects_description_row.set_title(_(`${effects.length} effects`));
|
||||
|
||||
let subtitle = "";
|
||||
effects.forEach(effect => {
|
||||
if (effect.type in this.SUPPORTED_EFFECTS)
|
||||
subtitle += _(`${this.SUPPORTED_EFFECTS[effect.type].name}, `);
|
||||
else
|
||||
subtitle += _("Unknown effect, ");
|
||||
});
|
||||
this._effects_description_row.set_subtitle(subtitle.slice(0, -2));
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user