Files
noctalia-shell/Modules/Panels/Settings/DesktopWidgets/DesktopWidgetSettingsDialog.qml
T
Spyridon Siarapis 1be78b5063 chore: format
2026-03-08 18:41:34 +01:00

276 lines
8.0 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell
import qs.Commons
import qs.Services.Noctalia
import qs.Services.UI
import qs.Widgets
Popup {
id: root
property int widgetIndex: -1
property var widgetData: null
property string widgetId: ""
property string sectionId: "" // Not used for desktop widgets, but required by NSectionEditor
property var screen: null
property var settingsCache: ({})
readonly property real maxHeight: (screen ? screen.height : (parent ? parent.height : 800)) * 0.8
signal updateWidgetSettings(string section, int index, var settings)
width: Math.max(content.implicitWidth + padding * 2, 500)
height: Math.min(content.implicitHeight + padding * 2, maxHeight)
padding: Style.marginXL
modal: true
dim: false
// Center in parent
x: Math.round((parent.width - width) / 2)
y: Math.round((parent.height - height) / 2)
onOpened: {
if (widgetData && widgetId) {
loadWidgetSettings();
}
forceActiveFocus();
}
background: Rectangle {
id: bgRect
color: Color.mSurface
radius: Style.radiusL
border.color: Color.mPrimary
border.width: Style.borderM
}
contentItem: FocusScope {
id: focusScope
focus: true
ColumnLayout {
id: content
anchors.fill: parent
spacing: Style.marginM
RowLayout {
id: titleRow
Layout.fillWidth: true
Layout.preferredHeight: implicitHeight
NText {
text: I18n.tr("system.widget-settings-title", {
"widget": root.widgetId
})
pointSize: Style.fontSizeL
font.weight: Style.fontWeightBold
color: Color.mPrimary
Layout.fillWidth: true
}
NIconButton {
icon: "close"
tooltipText: I18n.tr("common.close")
onClicked: saveAndClose()
}
}
Rectangle {
id: separator
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Color.mOutline
}
// Scrollable settings area
NScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: 100
gradientColor: Color.mSurface
ColumnLayout {
width: scrollView.availableWidth
spacing: Style.marginM
Loader {
id: settingsLoader
Layout.fillWidth: true
onLoaded: {
if (item) {
Qt.callLater(() => {
var firstInput = findFirstFocusable(item);
if (firstInput) {
firstInput.forceActiveFocus();
} else {
focusScope.forceActiveFocus();
}
});
}
}
function findFirstFocusable(item) {
if (!item)
return null;
if (item.focus !== undefined && item.focus === true)
return item;
if (item.children) {
for (var i = 0; i < item.children.length; i++) {
var child = item.children[i];
if (child && child.focus !== undefined && child.focus === true)
return child;
var found = findFirstFocusable(child);
if (found)
return found;
}
}
return null;
}
}
}
}
}
}
// Mouse area for a draggable popup
MouseArea {
x: titleRow.x
y: titleRow.y
width: titleRow.width
height: titleRow.height
z: -1
cursorShape: Qt.OpenHandCursor
property real pressX: 0
property real pressY: 0
onPressed: mouse => {
pressX = mouse.x;
pressY = mouse.y;
cursorShape = Qt.ClosedHandCursor;
}
onReleased: {
cursorShape = Qt.OpenHandCursor;
}
onPositionChanged: mouse => {
if (pressed) {
var deltaX = mouse.x - pressX;
var deltaY = mouse.y - pressY;
root.x += deltaX;
root.y += deltaY;
}
}
}
Timer {
id: saveTimer
running: false
interval: 150
onTriggered: {
root.updateWidgetSettings(root.sectionId, root.widgetIndex, root.settingsCache);
}
}
Connections {
target: settingsLoader.item
ignoreUnknownSignals: true
function onSettingsChanged(newSettings) {
if (newSettings) {
root.settingsCache = newSettings;
saveTimer.start();
}
}
function onSettingsSaved(newSettings) {
if (newSettings) {
root.updateWidgetSettings(root.sectionId, root.widgetIndex, newSettings);
}
}
}
function saveAndClose() {
if (settingsLoader.item && typeof settingsLoader.item.saveSettings === 'function') {
var newSettings = settingsLoader.item.saveSettings();
if (newSettings) {
root.updateWidgetSettings(root.sectionId, root.widgetIndex, newSettings);
}
}
root.close();
}
function loadWidgetSettings() {
// Handle plugin widgets
if (DesktopWidgetRegistry.isPluginWidget(widgetId)) {
var pluginId = widgetId.replace("plugin:", "");
var manifest = PluginRegistry.getPluginManifest(pluginId);
var pluginDir = PluginRegistry.getPluginDir(pluginId);
var loadVersion = PluginRegistry.pluginLoadVersions[pluginId] || 0;
var api = PluginService.getPluginAPI(pluginId);
var settingsPath;
if (manifest && manifest.entryPoints && manifest.entryPoints.desktopWidgetSettings) {
settingsPath = "file://" + pluginDir + "/" + manifest.entryPoints.desktopWidgetSettings;
var widgetSettings = {};
widgetSettings.data = widgetData || {};
widgetSettings.metadata = DesktopWidgetRegistry.widgetMetadata[widgetId] || {};
widgetSettings.save = function () {
var newSettings = Object.assign({}, widgetSettings.data);
root.settingsCache = newSettings;
saveTimer.start();
};
settingsLoader.setSource(settingsPath + "?v=" + loadVersion, {
"pluginApi": api,
"widgetSettings": widgetSettings
});
} else {
Logger.w("DesktopWidgetSettingsDialog", "Plugin does not have desktop widget settings:", pluginId);
// Fallback to the plugin settings
if (manifest && manifest.entryPoints && manifest.entryPoints.settings) {
settingsPath = "file://" + pluginDir + "/" + manifest.entryPoints.settings;
settingsLoader.setSource(settingsPath + "?v=" + loadVersion, {
"pluginApi": api
});
} else {
Logger.w("DesktopWidgetSettingsDialog", "Plugin does not have settings:", pluginId);
}
}
return;
}
// Handle core widgets
const source = DesktopWidgetRegistry.widgetSettingsMap[widgetId];
if (source) {
var currentWidgetData = widgetData;
var monitorWidgets = Settings.data.desktopWidgets.monitorWidgets || [];
for (var i = 0; i < monitorWidgets.length; i++) {
if (monitorWidgets[i].name === sectionId) {
var widgets = monitorWidgets[i].widgets || [];
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
currentWidgetData = widgets[widgetIndex];
}
break;
}
}
var fullPath = Qt.resolvedUrl(Quickshell.shellDir + "/Modules/Panels/Settings/DesktopWidgets/" + source);
settingsLoader.setSource(fullPath, {
"widgetData": currentWidgetData,
"widgetMetadata": DesktopWidgetRegistry.widgetMetadata[widgetId]
});
}
}
}