add noctalia and fuzzel
This commit is contained in:
+379
@@ -0,0 +1,379 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.Commons
|
||||
import qs.Services.Compositor
|
||||
import qs.Widgets
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
spacing: Style.marginL
|
||||
Layout.fillWidth: true
|
||||
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-position-label")
|
||||
description: I18n.tr("panels.bar.appearance-position-description")
|
||||
model: [
|
||||
{
|
||||
"key": "top",
|
||||
"name": I18n.tr("positions.top")
|
||||
},
|
||||
{
|
||||
"key": "bottom",
|
||||
"name": I18n.tr("positions.bottom")
|
||||
},
|
||||
{
|
||||
"key": "left",
|
||||
"name": I18n.tr("positions.left")
|
||||
},
|
||||
{
|
||||
"key": "right",
|
||||
"name": I18n.tr("positions.right")
|
||||
}
|
||||
]
|
||||
currentKey: Settings.data.bar.position
|
||||
defaultValue: Settings.getDefaultValue("bar.position")
|
||||
onSelected: key => Settings.data.bar.position = key
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-density-label")
|
||||
description: I18n.tr("panels.bar.appearance-density-description")
|
||||
model: [
|
||||
{
|
||||
"key": "mini",
|
||||
"name": I18n.tr("options.bar.density-mini")
|
||||
},
|
||||
{
|
||||
"key": "compact",
|
||||
"name": I18n.tr("options.bar.density-compact")
|
||||
},
|
||||
{
|
||||
"key": "default",
|
||||
"name": I18n.tr("options.bar.density-default")
|
||||
},
|
||||
{
|
||||
"key": "comfortable",
|
||||
"name": I18n.tr("options.bar.density-comfortable")
|
||||
},
|
||||
{
|
||||
"key": "spacious",
|
||||
"name": I18n.tr("options.bar.density-spacious")
|
||||
}
|
||||
]
|
||||
currentKey: Settings.data.bar.density
|
||||
defaultValue: Settings.getDefaultValue("bar.density")
|
||||
onSelected: key => Settings.data.bar.density = key
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-type-label")
|
||||
description: I18n.tr("panels.bar.appearance-type-description")
|
||||
model: [
|
||||
{
|
||||
"key": "simple",
|
||||
"name": I18n.tr("options.bar.type-simple")
|
||||
},
|
||||
{
|
||||
"key": "floating",
|
||||
"name": I18n.tr("options.bar.type-floating")
|
||||
},
|
||||
{
|
||||
"key": "framed",
|
||||
"name": I18n.tr("options.bar.type-framed")
|
||||
}
|
||||
]
|
||||
currentKey: Settings.data.bar.barType
|
||||
defaultValue: Settings.getDefaultValue("bar.barType")
|
||||
onSelected: key => {
|
||||
Settings.data.bar.barType = key;
|
||||
}
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("common.display-mode")
|
||||
description: I18n.tr("panels.bar.appearance-display-mode-description")
|
||||
model: [
|
||||
{
|
||||
"key": "always_visible",
|
||||
"name": I18n.tr("hide-modes.visible")
|
||||
},
|
||||
{
|
||||
"key": "non_exclusive",
|
||||
"name": I18n.tr("hide-modes.non-exclusive")
|
||||
},
|
||||
{
|
||||
"key": "auto_hide",
|
||||
"name": I18n.tr("hide-modes.auto-hide")
|
||||
}
|
||||
]
|
||||
currentKey: Settings.data.bar.displayMode
|
||||
defaultValue: Settings.getDefaultValue("bar.displayMode")
|
||||
onSelected: key => Settings.data.bar.displayMode = key
|
||||
}
|
||||
|
||||
NToggle {
|
||||
label: I18n.tr("panels.bar.appearance-use-separate-opacity-label")
|
||||
description: I18n.tr("panels.bar.appearance-use-separate-opacity-description")
|
||||
checked: Settings.data.bar.useSeparateOpacity
|
||||
defaultValue: Settings.getDefaultValue("bar.useSeparateOpacity")
|
||||
onToggled: checked => Settings.data.bar.useSeparateOpacity = checked
|
||||
}
|
||||
|
||||
NValueSlider {
|
||||
Layout.fillWidth: true
|
||||
visible: Settings.data.bar.useSeparateOpacity
|
||||
label: I18n.tr("panels.bar.appearance-background-opacity-label")
|
||||
description: I18n.tr("panels.bar.appearance-background-opacity-description")
|
||||
from: 0
|
||||
to: 1
|
||||
stepSize: 0.01
|
||||
showReset: true
|
||||
value: Settings.data.bar.backgroundOpacity
|
||||
defaultValue: Settings.getDefaultValue("bar.backgroundOpacity")
|
||||
onMoved: value => Settings.data.bar.backgroundOpacity = value
|
||||
text: Math.floor(Settings.data.bar.backgroundOpacity * 100) + "%"
|
||||
}
|
||||
|
||||
NValueSlider {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-font-scale-label")
|
||||
description: I18n.tr("panels.bar.appearance-font-scale-description")
|
||||
from: 0.5
|
||||
to: 2.0
|
||||
stepSize: 0.01
|
||||
showReset: true
|
||||
value: Settings.data.bar.fontScale
|
||||
defaultValue: Settings.getDefaultValue("bar.fontScale")
|
||||
onMoved: value => Settings.data.bar.fontScale = value
|
||||
text: Math.floor(Settings.data.bar.fontScale * 100) + "%"
|
||||
}
|
||||
|
||||
NValueSlider {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-widget-spacing-label")
|
||||
description: I18n.tr("panels.bar.appearance-widget-spacing-description")
|
||||
from: 0
|
||||
to: 30
|
||||
stepSize: 1
|
||||
showReset: true
|
||||
value: Settings.data.bar.widgetSpacing
|
||||
defaultValue: Settings.getDefaultValue("bar.widgetSpacing")
|
||||
onMoved: value => Settings.data.bar.widgetSpacing = value
|
||||
text: Settings.data.bar.widgetSpacing + "px"
|
||||
}
|
||||
|
||||
NValueSlider {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-content-padding-label")
|
||||
description: I18n.tr("panels.bar.appearance-content-padding-description")
|
||||
from: 0
|
||||
to: 30
|
||||
stepSize: 1
|
||||
showReset: true
|
||||
value: Settings.data.bar.contentPadding
|
||||
defaultValue: Settings.getDefaultValue("bar.contentPadding")
|
||||
onMoved: value => Settings.data.bar.contentPadding = value
|
||||
text: Settings.data.bar.contentPadding + "px"
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-show-outline-label")
|
||||
description: I18n.tr("panels.bar.appearance-show-outline-description")
|
||||
checked: Settings.data.bar.showOutline
|
||||
defaultValue: Settings.getDefaultValue("bar.showOutline")
|
||||
onToggled: checked => Settings.data.bar.showOutline = checked
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-show-capsule-label")
|
||||
description: I18n.tr("panels.bar.appearance-show-capsule-description")
|
||||
checked: Settings.data.bar.showCapsule
|
||||
defaultValue: Settings.getDefaultValue("bar.showCapsule")
|
||||
onToggled: checked => Settings.data.bar.showCapsule = checked
|
||||
}
|
||||
|
||||
NColorChoice {
|
||||
Layout.fillWidth: true
|
||||
visible: Settings.data.bar.showCapsule
|
||||
label: I18n.tr("panels.bar.appearance-capsule-color-label")
|
||||
description: I18n.tr("panels.bar.appearance-capsule-color-description")
|
||||
noneColor: Color.mSurfaceVariant
|
||||
noneOnColor: Color.mOnSurfaceVariant
|
||||
currentKey: Settings.data.bar.capsuleColorKey
|
||||
onSelected: key => Settings.data.bar.capsuleColorKey = key
|
||||
}
|
||||
|
||||
NValueSlider {
|
||||
Layout.fillWidth: true
|
||||
visible: Settings.data.bar.showCapsule
|
||||
label: I18n.tr("panels.bar.appearance-capsule-opacity-label")
|
||||
description: I18n.tr("panels.bar.appearance-capsule-opacity-description")
|
||||
from: 0
|
||||
to: 1
|
||||
stepSize: 0.01
|
||||
showReset: true
|
||||
value: Settings.data.bar.capsuleOpacity
|
||||
defaultValue: Settings.getDefaultValue("bar.capsuleOpacity")
|
||||
onMoved: value => Settings.data.bar.capsuleOpacity = value
|
||||
text: Math.floor(Settings.data.bar.capsuleOpacity * 100) + "%"
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-enable-exclusion-zone-inset-label")
|
||||
description: I18n.tr("panels.bar.appearance-enable-exclusion-zone-inset-description")
|
||||
checked: Settings.data.bar.enableExclusionZoneInset
|
||||
defaultValue: Settings.getDefaultValue("bar.enableExclusionZoneInset")
|
||||
onToggled: checked => Settings.data.bar.enableExclusionZoneInset = checked
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
visible: CompositorService.isNiri
|
||||
label: I18n.tr("panels.bar.appearance-hide-on-overview-label")
|
||||
description: I18n.tr("panels.bar.appearance-hide-on-overview-description")
|
||||
checked: Settings.data.bar.hideOnOverview
|
||||
defaultValue: Settings.getDefaultValue("bar.hideOnOverview")
|
||||
onToggled: checked => Settings.data.bar.hideOnOverview = checked
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-outer-corners-label")
|
||||
description: I18n.tr("panels.bar.appearance-outer-corners-description")
|
||||
checked: Settings.data.bar.outerCorners
|
||||
visible: Settings.data.bar.barType === "simple"
|
||||
defaultValue: Settings.getDefaultValue("bar.outerCorners")
|
||||
onToggled: checked => Settings.data.bar.outerCorners = checked
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: Settings.data.bar.barType === "framed"
|
||||
spacing: Style.marginS
|
||||
Layout.fillWidth: true
|
||||
|
||||
NLabel {
|
||||
label: I18n.tr("panels.bar.appearance-frame-settings-label")
|
||||
description: I18n.tr("panels.bar.appearance-frame-settings-description")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginL
|
||||
|
||||
NValueSlider {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-frame-thickness")
|
||||
from: 4
|
||||
to: 24
|
||||
stepSize: 1
|
||||
showReset: true
|
||||
value: Settings.data.bar.frameThickness
|
||||
defaultValue: Settings.getDefaultValue("bar.frameThickness")
|
||||
onMoved: value => Settings.data.bar.frameThickness = value
|
||||
text: Settings.data.bar.frameThickness + "px"
|
||||
}
|
||||
|
||||
NValueSlider {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-frame-radius")
|
||||
from: 4
|
||||
to: 24
|
||||
stepSize: 1
|
||||
showReset: true
|
||||
value: Settings.data.bar.frameRadius
|
||||
defaultValue: Settings.getDefaultValue("bar.frameRadius")
|
||||
onMoved: value => Settings.data.bar.frameRadius = value
|
||||
text: Settings.data.bar.frameRadius + "px"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: Settings.data.bar.barType === "floating"
|
||||
spacing: Style.marginL
|
||||
Layout.fillWidth: true
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
NSpinBox {
|
||||
label: I18n.tr("panels.bar.appearance-margins-vertical")
|
||||
description: I18n.tr("panels.bar.appearance-margins-description")
|
||||
from: 0
|
||||
to: 500
|
||||
suffix: "px"
|
||||
value: Settings.data.bar.marginVertical
|
||||
defaultValue: Settings.getDefaultValue("bar.marginVertical")
|
||||
onValueChanged: Settings.data.bar.marginVertical = value
|
||||
}
|
||||
|
||||
NSpinBox {
|
||||
label: I18n.tr("panels.bar.appearance-margins-horizontal")
|
||||
description: I18n.tr("panels.bar.appearance-margins-description")
|
||||
from: 0
|
||||
to: 500
|
||||
suffix: "px"
|
||||
value: Settings.data.bar.marginHorizontal
|
||||
defaultValue: Settings.getDefaultValue("bar.marginHorizontal")
|
||||
onValueChanged: Settings.data.bar.marginHorizontal = value
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginS
|
||||
visible: Settings.data.bar.displayMode === "auto_hide"
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: Settings.data.bar.displayMode === "auto_hide"
|
||||
spacing: Style.marginS
|
||||
Layout.fillWidth: true
|
||||
|
||||
NValueSlider {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-auto-hide-delay-label")
|
||||
description: I18n.tr("panels.bar.appearance-auto-hide-delay-description")
|
||||
from: 100
|
||||
to: 2000
|
||||
stepSize: 100
|
||||
showReset: true
|
||||
value: Settings.data.bar.autoHideDelay
|
||||
defaultValue: Settings.getDefaultValue("bar.autoHideDelay")
|
||||
onMoved: value => Settings.data.bar.autoHideDelay = value
|
||||
text: Settings.data.bar.autoHideDelay + "ms"
|
||||
}
|
||||
|
||||
NValueSlider {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-auto-show-delay-label")
|
||||
description: I18n.tr("panels.bar.appearance-auto-show-delay-description")
|
||||
from: 0
|
||||
to: 500
|
||||
stepSize: 50
|
||||
showReset: true
|
||||
value: Settings.data.bar.autoShowDelay
|
||||
defaultValue: Settings.getDefaultValue("bar.autoShowDelay")
|
||||
onMoved: value => Settings.data.bar.autoShowDelay = value
|
||||
text: Settings.data.bar.autoShowDelay + "ms"
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-show-on-workspace-switch-label")
|
||||
description: I18n.tr("panels.bar.appearance-show-on-workspace-switch-description")
|
||||
checked: Settings.data.bar.showOnWorkspaceSwitch
|
||||
defaultValue: Settings.getDefaultValue("bar.showOnWorkspaceSwitch")
|
||||
onToggled: checked => Settings.data.bar.showOnWorkspaceSwitch = checked
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Services.Noctalia
|
||||
import qs.Services.UI
|
||||
import qs.Widgets
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
spacing: 0
|
||||
|
||||
// Helper functions to update arrays immutably
|
||||
function addMonitor(list, name) {
|
||||
const arr = (list || []).slice();
|
||||
if (!arr.includes(name))
|
||||
arr.push(name);
|
||||
return arr;
|
||||
}
|
||||
function removeMonitor(list, name) {
|
||||
return (list || []).filter(function (n) {
|
||||
return n !== name;
|
||||
});
|
||||
}
|
||||
|
||||
// Signal functions for widgets sub-tab (global widgets only).
|
||||
// These intentionally edit Settings.data.bar.widgets (global defaults),
|
||||
// not per-screen overrides. Per-screen editing is handled by MonitorWidgetsConfig.qml.
|
||||
function _addWidgetToSection(widgetId, section) {
|
||||
var newWidget = {
|
||||
"id": widgetId
|
||||
};
|
||||
if (BarWidgetRegistry.widgetHasUserSettings(widgetId)) {
|
||||
var metadata = BarWidgetRegistry.widgetMetadata[widgetId];
|
||||
if (metadata) {
|
||||
Object.keys(metadata).forEach(function (key) {
|
||||
newWidget[key] = metadata[key];
|
||||
});
|
||||
}
|
||||
}
|
||||
Settings.data.bar.widgets[section].push(newWidget);
|
||||
BarService.widgetsRevision++;
|
||||
}
|
||||
|
||||
function _removeWidgetFromSection(section, index) {
|
||||
var widgets = Settings.data.bar.widgets;
|
||||
if (index >= 0 && index < widgets[section].length) {
|
||||
var newArray = widgets[section].slice();
|
||||
var removedWidgets = newArray.splice(index, 1);
|
||||
widgets[section] = newArray;
|
||||
BarService.widgetsRevision++;
|
||||
|
||||
if (removedWidgets[0].id === "ControlCenter" && BarService.lookupWidget("ControlCenter") === undefined) {
|
||||
ToastService.showWarning(I18n.tr("toast.missing-control-center.label"), I18n.tr("toast.missing-control-center.description"), 6000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _reorderWidgetInSection(section, fromIndex, toIndex) {
|
||||
var widgets = Settings.data.bar.widgets;
|
||||
if (fromIndex >= 0 && fromIndex < widgets[section].length && toIndex >= 0 && toIndex < widgets[section].length) {
|
||||
var newArray = widgets[section].slice();
|
||||
var item = newArray[fromIndex];
|
||||
newArray.splice(fromIndex, 1);
|
||||
newArray.splice(toIndex, 0, item);
|
||||
widgets[section] = newArray;
|
||||
BarService.widgetsRevision++;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: _updateWidgetSettingsInSection does NOT increment revision
|
||||
// because it only changes settings, not widget structure
|
||||
function _updateWidgetSettingsInSection(section, index, settings) {
|
||||
Settings.data.bar.widgets[section][index] = settings;
|
||||
}
|
||||
|
||||
function _moveWidgetBetweenSections(fromSection, index, toSection) {
|
||||
var widgets = Settings.data.bar.widgets;
|
||||
if (index >= 0 && index < widgets[fromSection].length) {
|
||||
var widget = widgets[fromSection][index];
|
||||
var sourceArray = widgets[fromSection].slice();
|
||||
sourceArray.splice(index, 1);
|
||||
widgets[fromSection] = sourceArray;
|
||||
var targetArray = widgets[toSection].slice();
|
||||
targetArray.push(widget);
|
||||
widgets[toSection] = targetArray;
|
||||
BarService.widgetsRevision++;
|
||||
Logger.d("BarTab", "_moveWidgetBetweenSections: revision now", BarService.widgetsRevision);
|
||||
}
|
||||
}
|
||||
|
||||
function getWidgetLocations(widgetId) {
|
||||
if (!BarService)
|
||||
return [];
|
||||
const instances = BarService.getAllRegisteredWidgets();
|
||||
const locations = {};
|
||||
for (var i = 0; i < instances.length; i++) {
|
||||
if (instances[i].widgetId === widgetId) {
|
||||
const section = instances[i].section;
|
||||
if (section === "left")
|
||||
locations["arrow-bar-to-left"] = true;
|
||||
else if (section === "center")
|
||||
locations["layout-columns"] = true;
|
||||
else if (section === "right")
|
||||
locations["arrow-bar-to-right"] = true;
|
||||
}
|
||||
}
|
||||
return Object.keys(locations);
|
||||
}
|
||||
|
||||
function createBadges(isPlugin, locations) {
|
||||
const badges = [];
|
||||
if (isPlugin) {
|
||||
badges.push({
|
||||
"icon": "plugin",
|
||||
"color": Color.mSecondary
|
||||
});
|
||||
}
|
||||
locations.forEach(function (location) {
|
||||
badges.push({
|
||||
"icon": location,
|
||||
"color": Color.mOnSurfaceVariant
|
||||
});
|
||||
});
|
||||
return badges;
|
||||
}
|
||||
|
||||
function updateAvailableWidgetsModel() {
|
||||
availableWidgets.clear();
|
||||
const widgets = BarWidgetRegistry.getAvailableWidgets();
|
||||
widgets.forEach(entry => {
|
||||
const isPlugin = BarWidgetRegistry.isPluginWidget(entry);
|
||||
let displayName = entry;
|
||||
if (isPlugin) {
|
||||
const pluginId = entry.replace("plugin:", "");
|
||||
const manifest = PluginRegistry.getPluginManifest(pluginId);
|
||||
if (manifest && manifest.name) {
|
||||
displayName = manifest.name;
|
||||
} else {
|
||||
displayName = pluginId;
|
||||
}
|
||||
}
|
||||
availableWidgets.append({
|
||||
"key": entry,
|
||||
"name": displayName,
|
||||
"badges": createBadges(isPlugin, getWidgetLocations(entry))
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: availableWidgets
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
Qt.callLater(updateAvailableWidgetsModel);
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: BarService
|
||||
function onActiveWidgetsChanged() {
|
||||
updateAvailableWidgetsModel();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: BarWidgetRegistry
|
||||
function onPluginWidgetRegistryUpdated() {
|
||||
updateAvailableWidgetsModel();
|
||||
}
|
||||
}
|
||||
|
||||
NTabBar {
|
||||
id: subTabBar
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: Style.marginM
|
||||
distributeEvenly: true
|
||||
currentIndex: tabView.currentIndex
|
||||
|
||||
NTabButton {
|
||||
text: I18n.tr("common.appearance")
|
||||
tabIndex: 0
|
||||
checked: subTabBar.currentIndex === 0
|
||||
}
|
||||
NTabButton {
|
||||
text: I18n.tr("common.widgets")
|
||||
tabIndex: 1
|
||||
checked: subTabBar.currentIndex === 1
|
||||
}
|
||||
NTabButton {
|
||||
text: I18n.tr("common.behavior")
|
||||
tabIndex: 2
|
||||
checked: subTabBar.currentIndex === 2
|
||||
}
|
||||
NTabButton {
|
||||
text: I18n.tr("common.monitors")
|
||||
tabIndex: 3
|
||||
checked: subTabBar.currentIndex === 3
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Style.marginS
|
||||
}
|
||||
|
||||
NTabView {
|
||||
id: tabView
|
||||
currentIndex: subTabBar.currentIndex
|
||||
|
||||
AppearanceSubTab {}
|
||||
WidgetsSubTab {
|
||||
availableWidgets: availableWidgets
|
||||
addWidgetToSection: root._addWidgetToSection
|
||||
removeWidgetFromSection: root._removeWidgetFromSection
|
||||
reorderWidgetInSection: root._reorderWidgetInSection
|
||||
updateWidgetSettingsInSection: root._updateWidgetSettingsInSection
|
||||
moveWidgetBetweenSections: root._moveWidgetBetweenSections
|
||||
onOpenPluginSettings: manifest => pluginSettingsDialog.openPluginSettings(manifest)
|
||||
}
|
||||
BehaviorSubTab {}
|
||||
MonitorsSubTab {
|
||||
addMonitor: root.addMonitor
|
||||
removeMonitor: root.removeMonitor
|
||||
}
|
||||
}
|
||||
|
||||
NPluginSettingsPopup {
|
||||
id: pluginSettingsDialog
|
||||
parent: Overlay.overlay
|
||||
showToastOnSave: false
|
||||
}
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.Commons
|
||||
import qs.Services.Compositor
|
||||
import qs.Widgets
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
spacing: Style.marginL
|
||||
Layout.fillWidth: true
|
||||
|
||||
readonly property string effectiveWheelAction: Settings.data.bar.mouseWheelAction || "none"
|
||||
readonly property string effectiveMiddleClickAction: Settings.data.bar.middleClickAction || "none"
|
||||
readonly property string effectiveRightClickAction: Settings.data.bar.rightClickAction || "controlCenter"
|
||||
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.behavior-workspace-scroll-label")
|
||||
description: I18n.tr("panels.bar.behavior-workspace-scroll-description")
|
||||
model: {
|
||||
var items = [
|
||||
{
|
||||
"key": "none",
|
||||
"name": I18n.tr("common.none")
|
||||
},
|
||||
{
|
||||
"key": "volume",
|
||||
"name": I18n.tr("common.volume")
|
||||
},
|
||||
{
|
||||
"key": "workspace",
|
||||
"name": I18n.tr("panels.bar.behavior-workspace-scroll-option-workspace")
|
||||
}
|
||||
];
|
||||
if (CompositorService.isNiri) {
|
||||
items.push({
|
||||
"key": "content",
|
||||
"name": I18n.tr("panels.bar.behavior-workspace-scroll-option-content")
|
||||
});
|
||||
}
|
||||
return items;
|
||||
}
|
||||
currentKey: root.effectiveWheelAction
|
||||
defaultValue: Settings.getDefaultValue("bar.mouseWheelAction")
|
||||
onSelected: key => Settings.data.bar.mouseWheelAction = key
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.general.reverse-scrolling-label")
|
||||
description: I18n.tr("panels.general.reverse-scrolling-description")
|
||||
checked: Settings.data.bar.reverseScroll
|
||||
defaultValue: Settings.getDefaultValue("bar.reverseScroll")
|
||||
onToggled: checked => Settings.data.bar.reverseScroll = checked
|
||||
visible: Settings.data.bar.mouseWheelAction !== "none"
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.behavior-wheel-wrap-label")
|
||||
description: I18n.tr("panels.bar.behavior-wheel-wrap-description")
|
||||
checked: Settings.data.bar.mouseWheelWrap
|
||||
defaultValue: Settings.getDefaultValue("bar.mouseWheelWrap")
|
||||
onToggled: checked => Settings.data.bar.mouseWheelWrap = checked
|
||||
visible: Settings.data.bar.mouseWheelAction === "workspace"
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.behavior-middle-click-label")
|
||||
description: I18n.tr("panels.bar.behavior-middle-click-description")
|
||||
model: [
|
||||
{
|
||||
"key": "none",
|
||||
"name": I18n.tr("common.none")
|
||||
},
|
||||
{
|
||||
"key": "controlCenter",
|
||||
"name": I18n.tr("tooltips.open-control-center")
|
||||
},
|
||||
{
|
||||
"key": "settings",
|
||||
"name": I18n.tr("tooltips.open-settings")
|
||||
},
|
||||
{
|
||||
"key": "launcherPanel",
|
||||
"name": I18n.tr("actions.open-launcher")
|
||||
},
|
||||
{
|
||||
"key": "command",
|
||||
"name": I18n.tr("actions.run-custom-command")
|
||||
}
|
||||
]
|
||||
currentKey: root.effectiveMiddleClickAction
|
||||
defaultValue: Settings.getDefaultValue("bar.middleClickAction")
|
||||
onSelected: key => Settings.data.bar.middleClickAction = key
|
||||
}
|
||||
|
||||
NTextInput {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.behavior-middle-click-command-label")
|
||||
description: I18n.tr("panels.bar.behavior-middle-click-command-description")
|
||||
placeholderText: I18n.tr("panels.bar.behavior-middle-click-command-placeholder")
|
||||
text: Settings.data.bar.middleClickCommand
|
||||
fontFamily: Settings.data.ui.fontFixed
|
||||
onTextChanged: Settings.data.bar.middleClickCommand = text
|
||||
visible: Settings.data.bar.middleClickAction === "command"
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.behavior-middle-click-follow-mouse-label")
|
||||
description: I18n.tr("panels.bar.behavior-middle-click-follow-mouse-description")
|
||||
checked: Settings.data.bar.middleClickFollowMouse
|
||||
defaultValue: Settings.getDefaultValue("bar.middleClickFollowMouse")
|
||||
onToggled: checked => Settings.data.bar.middleClickFollowMouse = checked
|
||||
visible: Settings.data.bar.middleClickAction !== "none" && Settings.data.bar.middleClickAction !== "command" && !(Settings.data.bar.middleClickAction === "settings" && Settings.data.ui.settingsPanelMode === "window")
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.behavior-right-click-label")
|
||||
description: I18n.tr("panels.bar.behavior-right-click-description")
|
||||
model: [
|
||||
{
|
||||
"key": "none",
|
||||
"name": I18n.tr("common.none")
|
||||
},
|
||||
{
|
||||
"key": "controlCenter",
|
||||
"name": I18n.tr("tooltips.open-control-center")
|
||||
},
|
||||
{
|
||||
"key": "settings",
|
||||
"name": I18n.tr("tooltips.open-settings")
|
||||
},
|
||||
{
|
||||
"key": "launcherPanel",
|
||||
"name": I18n.tr("actions.open-launcher")
|
||||
},
|
||||
{
|
||||
"key": "command",
|
||||
"name": I18n.tr("actions.run-custom-command")
|
||||
}
|
||||
]
|
||||
currentKey: root.effectiveRightClickAction
|
||||
defaultValue: Settings.getDefaultValue("bar.rightClickAction")
|
||||
onSelected: key => Settings.data.bar.rightClickAction = key
|
||||
}
|
||||
|
||||
NTextInput {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.behavior-right-click-command-label")
|
||||
description: I18n.tr("panels.bar.behavior-right-click-command-description")
|
||||
placeholderText: I18n.tr("panels.bar.behavior-right-click-command-placeholder")
|
||||
text: Settings.data.bar.rightClickCommand
|
||||
fontFamily: Settings.data.ui.fontFixed
|
||||
onTextChanged: Settings.data.bar.rightClickCommand = text
|
||||
visible: Settings.data.bar.rightClickAction === "command"
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.behavior-right-click-follow-mouse-label")
|
||||
description: I18n.tr("panels.bar.behavior-right-click-follow-mouse-description")
|
||||
checked: Settings.data.bar.rightClickFollowMouse
|
||||
defaultValue: Settings.getDefaultValue("bar.rightClickFollowMouse")
|
||||
onToggled: checked => Settings.data.bar.rightClickFollowMouse = checked
|
||||
visible: Settings.data.bar.rightClickAction !== "none" && Settings.data.bar.rightClickAction !== "command" && !(Settings.data.bar.rightClickAction === "settings" && Settings.data.ui.settingsPanelMode === "window")
|
||||
}
|
||||
}
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import "../../Bar" as BarSettings
|
||||
import qs.Commons
|
||||
import qs.Services.Compositor
|
||||
import qs.Services.UI
|
||||
import qs.Widgets
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
spacing: Style.marginL
|
||||
Layout.fillWidth: true
|
||||
|
||||
property var addMonitor
|
||||
property var removeMonitor
|
||||
|
||||
NText {
|
||||
text: I18n.tr("panels.bar.monitors-desc-new")
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// Monitor cards
|
||||
Repeater {
|
||||
model: Quickshell.screens || []
|
||||
delegate: NBox {
|
||||
id: monitorCard
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: cardContent.implicitHeight + Style.margin2L
|
||||
color: Color.mSurface
|
||||
|
||||
required property var modelData
|
||||
readonly property string screenName: modelData.name || "Unknown"
|
||||
readonly property real compositorScale: {
|
||||
const info = CompositorService.displayScales[screenName];
|
||||
return (info && info.scale) ? info.scale : 1.0;
|
||||
}
|
||||
readonly property bool barEnabled: (Settings.data.bar.monitors || []).indexOf(screenName) !== -1
|
||||
readonly property bool hasOverride: Settings.hasScreenOverride(screenName)
|
||||
|
||||
// Track if override is enabled (controls both visibility AND whether overrides are applied)
|
||||
readonly property bool overrideEnabled: Settings.isScreenOverrideEnabled(screenName)
|
||||
|
||||
// Get effective values for this screen
|
||||
readonly property string effectivePosition: Settings.getBarPositionForScreen(screenName)
|
||||
readonly property string effectiveDensity: Settings.getBarDensityForScreen(screenName)
|
||||
|
||||
ColumnLayout {
|
||||
id: cardContent
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginL
|
||||
spacing: Style.marginM
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
// Header: Monitor name and specs
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginXXS
|
||||
|
||||
NText {
|
||||
Layout.fillWidth: true
|
||||
text: monitorCard.screenName
|
||||
pointSize: Style.fontSizeM
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnSurface
|
||||
}
|
||||
|
||||
NText {
|
||||
text: {
|
||||
return I18n.tr("system.monitor-description", {
|
||||
"model": monitorCard.modelData.model || I18n.tr("common.unknown"),
|
||||
"width": Math.round(monitorCard.modelData.width * monitorCard.compositorScale),
|
||||
"height": Math.round(monitorCard.modelData.height * monitorCard.compositorScale),
|
||||
"scale": monitorCard.compositorScale
|
||||
});
|
||||
}
|
||||
pointSize: Style.fontSizeS
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
}
|
||||
|
||||
// Enable bar toggle
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
checked: monitorCard.barEnabled
|
||||
onToggled: checked => {
|
||||
if (checked) {
|
||||
Settings.data.bar.monitors = root.addMonitor(Settings.data.bar.monitors, monitorCard.screenName);
|
||||
} else {
|
||||
Settings.data.bar.monitors = root.removeMonitor(Settings.data.bar.monitors, monitorCard.screenName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
visible: Settings.data.bar.monitors.includes(monitorCard.screenName)
|
||||
}
|
||||
|
||||
// Override section (only visible when bar is enabled)
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginS
|
||||
visible: monitorCard.barEnabled
|
||||
|
||||
// Override toggle
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.monitor-override-settings")
|
||||
description: I18n.tr("panels.bar.monitor-override-settings-description")
|
||||
checked: monitorCard.overrideEnabled
|
||||
onToggled: checked => {
|
||||
Settings.setScreenOverride(monitorCard.screenName, "enabled", checked);
|
||||
BarService.widgetsRevision++;
|
||||
}
|
||||
}
|
||||
|
||||
// Override controls (only visible when override toggle is on)
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginS
|
||||
visible: monitorCard.overrideEnabled
|
||||
|
||||
// Position override
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginS
|
||||
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-position-label")
|
||||
description: I18n.tr("panels.bar.appearance-position-description")
|
||||
model: [
|
||||
{
|
||||
"key": "top",
|
||||
"name": I18n.tr("positions.top")
|
||||
},
|
||||
{
|
||||
"key": "bottom",
|
||||
"name": I18n.tr("positions.bottom")
|
||||
},
|
||||
{
|
||||
"key": "left",
|
||||
"name": I18n.tr("positions.left")
|
||||
},
|
||||
{
|
||||
"key": "right",
|
||||
"name": I18n.tr("positions.right")
|
||||
}
|
||||
]
|
||||
currentKey: monitorCard.effectivePosition
|
||||
onSelected: key => Settings.setScreenOverride(monitorCard.screenName, "position", key)
|
||||
}
|
||||
}
|
||||
|
||||
// Density override
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginS
|
||||
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("panels.bar.appearance-density-label")
|
||||
description: I18n.tr("panels.bar.appearance-density-description")
|
||||
model: [
|
||||
{
|
||||
"key": "mini",
|
||||
"name": I18n.tr("options.bar.density-mini")
|
||||
},
|
||||
{
|
||||
"key": "compact",
|
||||
"name": I18n.tr("options.bar.density-compact")
|
||||
},
|
||||
{
|
||||
"key": "default",
|
||||
"name": I18n.tr("options.bar.density-default")
|
||||
},
|
||||
{
|
||||
"key": "comfortable",
|
||||
"name": I18n.tr("options.bar.density-comfortable")
|
||||
},
|
||||
{
|
||||
"key": "spacious",
|
||||
"name": I18n.tr("options.bar.density-spacious")
|
||||
}
|
||||
]
|
||||
currentKey: monitorCard.effectiveDensity
|
||||
onSelected: key => Settings.setScreenOverride(monitorCard.screenName, "density", key)
|
||||
}
|
||||
}
|
||||
|
||||
// DisplayMode override
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginS
|
||||
|
||||
NComboBox {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("common.display-mode")
|
||||
description: I18n.tr("panels.bar.appearance-display-mode-description")
|
||||
model: [
|
||||
{
|
||||
"key": "always_visible",
|
||||
"name": I18n.tr("hide-modes.visible")
|
||||
},
|
||||
{
|
||||
"key": "non_exclusive",
|
||||
"name": I18n.tr("hide-modes.non-exclusive")
|
||||
},
|
||||
{
|
||||
"key": "auto_hide",
|
||||
"name": I18n.tr("hide-modes.auto-hide")
|
||||
}
|
||||
]
|
||||
currentKey: Settings.getBarDisplayModeForScreen(monitorCard.screenName)
|
||||
onSelected: key => Settings.setScreenOverride(monitorCard.screenName, "displayMode", key)
|
||||
}
|
||||
}
|
||||
|
||||
// Widgets configuration button and Reset all
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginS
|
||||
|
||||
NButton {
|
||||
id: widgetConfigButton
|
||||
property bool expanded: false
|
||||
Layout.fillWidth: true
|
||||
fontSize: Style.fontSizeS
|
||||
text: I18n.tr("panels.bar.monitor-configure-widgets")
|
||||
icon: expanded ? "chevron-up" : "layout-grid"
|
||||
onClicked: expanded = !expanded
|
||||
}
|
||||
|
||||
NButton {
|
||||
visible: Settings.hasScreenOverride(monitorCard.screenName, "widgets")
|
||||
Layout.fillWidth: true
|
||||
fontSize: Style.fontSizeS
|
||||
text: I18n.tr("panels.bar.use-global-widgets")
|
||||
icon: "refresh"
|
||||
onClicked: {
|
||||
Settings.clearScreenOverride(monitorCard.screenName, "widgets");
|
||||
BarService.widgetsRevision++;
|
||||
}
|
||||
}
|
||||
|
||||
NButton {
|
||||
Layout.fillWidth: true
|
||||
fontSize: Style.fontSizeS
|
||||
text: I18n.tr("panels.bar.monitor-reset-all")
|
||||
icon: "restore"
|
||||
onClicked: {
|
||||
Settings.clearScreenOverride(monitorCard.screenName);
|
||||
BarService.widgetsRevision++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inline widget configuration
|
||||
BarSettings.MonitorWidgetsConfig {
|
||||
visible: widgetConfigButton.expanded
|
||||
screen: monitorCard.modelData
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Services.UI
|
||||
import qs.Widgets
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
spacing: Style.marginL
|
||||
Layout.fillWidth: true
|
||||
|
||||
property var availableWidgets
|
||||
property var addWidgetToSection
|
||||
property var removeWidgetFromSection
|
||||
property var reorderWidgetInSection
|
||||
property var updateWidgetSettingsInSection
|
||||
property var moveWidgetBetweenSections
|
||||
|
||||
signal openPluginSettings(var manifest)
|
||||
|
||||
// This sub-tab edits the global default widget configuration (Settings.data.bar.widgets).
|
||||
// Per-screen widget overrides are edited in MonitorWidgetsConfig.qml (Monitors sub-tab).
|
||||
|
||||
// determine bar orientation
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
readonly property bool barIsVertical: barPosition === "left" || barPosition === "right"
|
||||
|
||||
function getSectionIcons() {
|
||||
return {
|
||||
"left": "arrow-bar-to-up",
|
||||
"center": "layout-distribute-horizontal",
|
||||
"right": "arrow-bar-to-down"
|
||||
};
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("panels.bar.widgets-desc")
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// Left Section
|
||||
NSectionEditor {
|
||||
sectionName: root.barIsVertical ? I18n.tr("positions.top") : I18n.tr("positions.left")
|
||||
sectionId: "left"
|
||||
barIsVertical: root.barIsVertical
|
||||
settingsDialogComponent: Qt.resolvedUrl(Quickshell.shellDir + "/Modules/Panels/Settings/Bar/BarWidgetSettingsDialog.qml")
|
||||
widgetRegistry: BarWidgetRegistry
|
||||
widgetModel: Settings.data.bar.widgets.left
|
||||
sectionIcons: root.getSectionIcons()
|
||||
availableWidgets: root.availableWidgets
|
||||
onAddWidget: (widgetId, section) => root.addWidgetToSection(widgetId, section)
|
||||
onRemoveWidget: (section, index) => root.removeWidgetFromSection(section, index)
|
||||
onReorderWidget: (section, fromIndex, toIndex) => root.reorderWidgetInSection(section, fromIndex, toIndex)
|
||||
onUpdateWidgetSettings: (section, index, settings) => root.updateWidgetSettingsInSection(section, index, settings)
|
||||
onMoveWidget: (fromSection, index, toSection) => root.moveWidgetBetweenSections(fromSection, index, toSection)
|
||||
onOpenPluginSettingsRequested: manifest => root.openPluginSettings(manifest)
|
||||
}
|
||||
|
||||
// Center Section
|
||||
NSectionEditor {
|
||||
sectionName: I18n.tr("positions.center")
|
||||
sectionId: "center"
|
||||
barIsVertical: root.barIsVertical
|
||||
settingsDialogComponent: Qt.resolvedUrl(Quickshell.shellDir + "/Modules/Panels/Settings/Bar/BarWidgetSettingsDialog.qml")
|
||||
widgetRegistry: BarWidgetRegistry
|
||||
widgetModel: Settings.data.bar.widgets.center
|
||||
sectionIcons: root.getSectionIcons()
|
||||
availableWidgets: root.availableWidgets
|
||||
onAddWidget: (widgetId, section) => root.addWidgetToSection(widgetId, section)
|
||||
onRemoveWidget: (section, index) => root.removeWidgetFromSection(section, index)
|
||||
onReorderWidget: (section, fromIndex, toIndex) => root.reorderWidgetInSection(section, fromIndex, toIndex)
|
||||
onUpdateWidgetSettings: (section, index, settings) => root.updateWidgetSettingsInSection(section, index, settings)
|
||||
onMoveWidget: (fromSection, index, toSection) => root.moveWidgetBetweenSections(fromSection, index, toSection)
|
||||
onOpenPluginSettingsRequested: manifest => root.openPluginSettings(manifest)
|
||||
}
|
||||
|
||||
// Right Section
|
||||
NSectionEditor {
|
||||
sectionName: root.barIsVertical ? I18n.tr("positions.bottom") : I18n.tr("positions.right")
|
||||
sectionId: "right"
|
||||
barIsVertical: root.barIsVertical
|
||||
settingsDialogComponent: Qt.resolvedUrl(Quickshell.shellDir + "/Modules/Panels/Settings/Bar/BarWidgetSettingsDialog.qml")
|
||||
widgetRegistry: BarWidgetRegistry
|
||||
widgetModel: Settings.data.bar.widgets.right
|
||||
sectionIcons: root.getSectionIcons()
|
||||
availableWidgets: root.availableWidgets
|
||||
onAddWidget: (widgetId, section) => root.addWidgetToSection(widgetId, section)
|
||||
onRemoveWidget: (section, index) => root.removeWidgetFromSection(section, index)
|
||||
onReorderWidget: (section, fromIndex, toIndex) => root.reorderWidgetInSection(section, fromIndex, toIndex)
|
||||
onUpdateWidgetSettings: (section, index, settings) => root.updateWidgetSettingsInSection(section, index, settings)
|
||||
onMoveWidget: (fromSection, index, toSection) => root.moveWidgetBetweenSections(fromSection, index, toSection)
|
||||
onOpenPluginSettingsRequested: manifest => root.openPluginSettings(manifest)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user