Files
noctalia-shell/Modules/Panels/Settings/Bar/BarWidgetSettingsDialog.qml
T
2025-11-28 20:55:50 +01:00

170 lines
4.4 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import QtQuick.Layouts
import qs.Commons
import qs.Services.UI
import qs.Widgets
// Widget Settings Dialog Component
Popup {
id: root
property int widgetIndex: -1
property var widgetData: null
property string widgetId: ""
property string sectionId: ""
signal updateWidgetSettings(string section, int index, var settings)
width: Math.max(content.implicitWidth + padding * 2, 500)
height: content.implicitHeight + padding * 2
padding: Style.marginXL
modal: true
dim: false
anchors.centerIn: parent
onOpened: {
// Load settings when popup opens with data
if (widgetData && widgetId) {
loadWidgetSettings();
}
// Request focus to ensure keyboard input works
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
// Title
RowLayout {
Layout.fillWidth: true
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("tooltips.close")
onClicked: root.close()
}
}
// Separator
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Color.mOutline
}
// Settings based on widget type
// Will be triggered via settingsLoader.setSource()
Loader {
id: settingsLoader
Layout.fillWidth: true
onLoaded: {
// Try to focus the first focusable item in the loaded settings
if (item) {
Qt.callLater(() => {
var firstInput = findFirstFocusable(item);
if (firstInput) {
firstInput.forceActiveFocus();
} else {
focusScope.forceActiveFocus();
}
});
}
}
function findFirstFocusable(item) {
if (!item)
return null;
// Check if this item can accept focus
if (item.focus !== undefined && item.focus === true)
return item;
// Check children
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;
}
}
// Action buttons
RowLayout {
Layout.fillWidth: true
Layout.topMargin: Style.marginM
spacing: Style.marginM
Item {
Layout.fillWidth: true
}
NButton {
text: I18n.tr("bar.widget-settings.dialog.cancel")
outlined: true
onClicked: root.close()
}
NButton {
text: I18n.tr("bar.widget-settings.dialog.apply")
icon: "check"
onClicked: {
if (settingsLoader.item && settingsLoader.item.saveSettings) {
var newSettings = settingsLoader.item.saveSettings();
root.updateWidgetSettings(root.sectionId, root.widgetIndex, newSettings);
root.close();
}
}
}
}
}
}
function loadWidgetSettings() {
const source = BarWidgetRegistry.widgetSettingsMap[widgetId];
if (source) {
var currentWidgetData = widgetData;
if (sectionId && widgetIndex >= 0) {
var widgets = Settings.data.bar.widgets[sectionId];
if (widgets && widgetIndex < widgets.length) {
currentWidgetData = widgets[widgetIndex];
}
}
settingsLoader.setSource(source, {
"widgetData": currentWidgetData,
"widgetMetadata": BarWidgetRegistry.widgetMetadata[widgetId]
});
}
}
}