Merge branch 'custom-buttons'
This commit is contained in:
commit
902cdc39e0
15 changed files with 835 additions and 398 deletions
|
|
@ -100,6 +100,31 @@ Singleton {
|
||||||
Logger.log("Settings", "Settings loaded successfully")
|
Logger.log("Settings", "Settings loaded successfully")
|
||||||
isLoaded = true
|
isLoaded = true
|
||||||
|
|
||||||
|
for (var i = 0; i < adapter.bar.widgets.left.length; i++) {
|
||||||
|
var obj = adapter.bar.widgets.left[i]
|
||||||
|
if (typeof obj === "string") {
|
||||||
|
adapter.bar.widgets.left[i] = {
|
||||||
|
"id": obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < adapter.bar.widgets.center.length; i++) {
|
||||||
|
var obj = adapter.bar.widgets.center[i]
|
||||||
|
if (typeof obj === "string") {
|
||||||
|
adapter.bar.widgets.center[i] = {
|
||||||
|
"id": obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < adapter.bar.widgets.right.length; i++) {
|
||||||
|
var obj = adapter.bar.widgets.right[i]
|
||||||
|
if (typeof obj === "string") {
|
||||||
|
adapter.bar.widgets.right[i] = {
|
||||||
|
"id": obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Emit the signal
|
// Emit the signal
|
||||||
root.settingsLoaded()
|
root.settingsLoaded()
|
||||||
|
|
||||||
|
|
@ -126,6 +151,8 @@ Singleton {
|
||||||
JsonAdapter {
|
JsonAdapter {
|
||||||
id: adapter
|
id: adapter
|
||||||
|
|
||||||
|
property int settingsVersion: 1
|
||||||
|
|
||||||
// bar
|
// bar
|
||||||
property JsonObject bar: JsonObject {
|
property JsonObject bar: JsonObject {
|
||||||
property string position: "top" // Possible values: "top", "bottom"
|
property string position: "top" // Possible values: "top", "bottom"
|
||||||
|
|
@ -140,9 +167,39 @@ Singleton {
|
||||||
// Widget configuration for modular bar system
|
// Widget configuration for modular bar system
|
||||||
property JsonObject widgets
|
property JsonObject widgets
|
||||||
widgets: JsonObject {
|
widgets: JsonObject {
|
||||||
property list<string> left: ["SystemMonitor", "ActiveWindow", "MediaMini"]
|
property list<var> left: [{
|
||||||
property list<string> center: ["Workspace"]
|
"id": "SystemMonitor"
|
||||||
property list<string> right: ["ScreenRecorderIndicator", "Tray", "NotificationHistory", "WiFi", "Bluetooth", "Battery", "Volume", "Brightness", "NightLight", "Clock", "SidePanelToggle"]
|
}, {
|
||||||
|
"id": "ActiveWindow"
|
||||||
|
}, {
|
||||||
|
"id": "MediaMini"
|
||||||
|
}]
|
||||||
|
property list<var> center: [{
|
||||||
|
"id": "Workspace"
|
||||||
|
}]
|
||||||
|
property list<var> right: [{
|
||||||
|
"id": "ScreenRecorderIndicator"
|
||||||
|
}, {
|
||||||
|
"id": "Tray"
|
||||||
|
}, {
|
||||||
|
"id": "NotificationHistory"
|
||||||
|
}, {
|
||||||
|
"id": "WiFi"
|
||||||
|
}, {
|
||||||
|
"id": "Bluetooth"
|
||||||
|
}, {
|
||||||
|
"id": "Battery"
|
||||||
|
}, {
|
||||||
|
"id": "Volume"
|
||||||
|
}, {
|
||||||
|
"id": "Brightness"
|
||||||
|
}, {
|
||||||
|
"id": "NightLight"
|
||||||
|
}, {
|
||||||
|
"id": "Clock"
|
||||||
|
}, {
|
||||||
|
"id": "SidePanelToggle"
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ Variants {
|
||||||
Repeater {
|
Repeater {
|
||||||
model: Settings.data.bar.widgets.left
|
model: Settings.data.bar.widgets.left
|
||||||
delegate: NWidgetLoader {
|
delegate: NWidgetLoader {
|
||||||
widgetName: modelData
|
widgetId: (modelData.id !== undefined ? modelData.id : "")
|
||||||
widgetProps: {
|
widgetProps: {
|
||||||
"screen": root.modelData || null,
|
"screen": root.modelData || null,
|
||||||
"scaling": ScalingService.getScreenScale(screen),
|
"scaling": ScalingService.getScreenScale(screen),
|
||||||
|
|
@ -100,8 +100,7 @@ Variants {
|
||||||
Repeater {
|
Repeater {
|
||||||
model: Settings.data.bar.widgets.center
|
model: Settings.data.bar.widgets.center
|
||||||
delegate: NWidgetLoader {
|
delegate: NWidgetLoader {
|
||||||
|
widgetId: (modelData.id !== undefined ? modelData.id : "")
|
||||||
widgetName: modelData
|
|
||||||
widgetProps: {
|
widgetProps: {
|
||||||
"screen": root.modelData || null,
|
"screen": root.modelData || null,
|
||||||
"scaling": ScalingService.getScreenScale(screen),
|
"scaling": ScalingService.getScreenScale(screen),
|
||||||
|
|
@ -129,7 +128,7 @@ Variants {
|
||||||
Repeater {
|
Repeater {
|
||||||
model: Settings.data.bar.widgets.right
|
model: Settings.data.bar.widgets.right
|
||||||
delegate: NWidgetLoader {
|
delegate: NWidgetLoader {
|
||||||
widgetName: modelData
|
widgetId: (modelData.id !== undefined ? modelData.id : "")
|
||||||
widgetProps: {
|
widgetProps: {
|
||||||
"screen": root.modelData || null,
|
"screen": root.modelData || null,
|
||||||
"scaling": ScalingService.getScreenScale(screen),
|
"scaling": ScalingService.getScreenScale(screen),
|
||||||
|
|
|
||||||
87
Modules/Bar/Widgets/CustomButton.qml
Normal file
87
Modules/Bar/Widgets/CustomButton.qml
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import qs.Commons
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
import qs.Modules.SettingsPanel
|
||||||
|
|
||||||
|
NIconButton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
// Widget properties passed from Bar.qml
|
||||||
|
property var screen
|
||||||
|
property real scaling: 1.0
|
||||||
|
|
||||||
|
property string barSection: ""
|
||||||
|
property int sectionWidgetIndex: -1
|
||||||
|
property int sectionWidgetsCount: 0
|
||||||
|
|
||||||
|
// Get user settings from Settings data
|
||||||
|
property var widgetSettings: {
|
||||||
|
var section = barSection.replace("Section", "").toLowerCase()
|
||||||
|
if (section && sectionWidgetIndex >= 0) {
|
||||||
|
var widgets = Settings.data.bar.widgets[section]
|
||||||
|
if (widgets && sectionWidgetIndex < widgets.length) {
|
||||||
|
return widgets[sectionWidgetIndex]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use settings or defaults from BarWidgetRegistry
|
||||||
|
readonly property string userIcon: widgetSettings.icon || BarWidgetRegistry.widgetMetadata["CustomButton"].icon
|
||||||
|
readonly property string userLeftClickExec: widgetSettings.leftClickExec
|
||||||
|
|| BarWidgetRegistry.widgetMetadata["CustomButton"].leftClickExec
|
||||||
|
readonly property string userRightClickExec: widgetSettings.rightClickExec
|
||||||
|
|| BarWidgetRegistry.widgetMetadata["CustomButton"].rightClickExec
|
||||||
|
readonly property string userMiddleClickExec: widgetSettings.middleClickExec
|
||||||
|
|| BarWidgetRegistry.widgetMetadata["CustomButton"].middleClickExec
|
||||||
|
readonly property bool hasExec: (userLeftClickExec || userRightClickExec || userMiddleClickExec)
|
||||||
|
|
||||||
|
icon: userIcon
|
||||||
|
tooltipText: {
|
||||||
|
if (!hasExec) {
|
||||||
|
return "Custom Button - Configure in settings"
|
||||||
|
} else {
|
||||||
|
var lines = []
|
||||||
|
if (userLeftClickExec !== "") {
|
||||||
|
lines.push(`Left click: <i>${userLeftClickExec}</i>`)
|
||||||
|
}
|
||||||
|
if (userRightClickExec !== "") {
|
||||||
|
lines.push(`Right click: <i>${userRightClickExec}</i>`)
|
||||||
|
}
|
||||||
|
if (userLeftClickExec !== "") {
|
||||||
|
lines.push(`Middle click: <i>${userMiddleClickExec}</i>`)
|
||||||
|
}
|
||||||
|
return lines.join("<br/>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opacity: hasExec ? Style.opacityFull : Style.opacityMedium
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (userLeftClickExec) {
|
||||||
|
Quickshell.execDetached(userLeftClickExec.split(" "))
|
||||||
|
Logger.log("CustomButton", `Executing command: ${userLeftClickExec}`)
|
||||||
|
} else if (!hasExec) {
|
||||||
|
// No script was defined, open settings
|
||||||
|
var settingsPanel = PanelService.getPanel("settingsPanel")
|
||||||
|
settingsPanel.requestedTab = SettingsPanel.Tab.Bar
|
||||||
|
settingsPanel.open(screen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onRightClicked: {
|
||||||
|
if (userRightClickExec) {
|
||||||
|
Quickshell.execDetached(userRightClickExec.split(" "))
|
||||||
|
Logger.log("CustomButton", `Executing command: ${userRightClickExec}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMiddleClicked: {
|
||||||
|
if (userMiddleClickExec) {
|
||||||
|
Quickshell.execDetached(userMiddleClickExec.split(" "))
|
||||||
|
Logger.log("CustomButton", `Executing command: ${userMiddleClickExec}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -93,7 +93,7 @@ Item {
|
||||||
}
|
}
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var settingsPanel = PanelService.getPanel("settingsPanel")
|
var settingsPanel = PanelService.getPanel("settingsPanel")
|
||||||
settingsPanel.requestedTab = SettingsPanel.Tab.AudioService
|
settingsPanel.requestedTab = SettingsPanel.Tab.Audio
|
||||||
settingsPanel.open(screen)
|
settingsPanel.open(screen)
|
||||||
}
|
}
|
||||||
onRightClicked: {
|
onRightClicked: {
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ Item {
|
||||||
}
|
}
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var settingsPanel = PanelService.getPanel("settingsPanel")
|
var settingsPanel = PanelService.getPanel("settingsPanel")
|
||||||
settingsPanel.requestedTab = SettingsPanel.Tab.AudioService
|
settingsPanel.requestedTab = SettingsPanel.Tab.Audio
|
||||||
settingsPanel.open(screen)
|
settingsPanel.open(screen)
|
||||||
}
|
}
|
||||||
onRightClicked: {
|
onRightClicked: {
|
||||||
|
|
|
||||||
432
Modules/SettingsPanel/Extras/BarSectionEditor.qml
Normal file
432
Modules/SettingsPanel/Extras/BarSectionEditor.qml
Normal file
|
|
@ -0,0 +1,432 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Effects
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Commons
|
||||||
|
import qs.Widgets
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
NBox {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string sectionName: ""
|
||||||
|
property string sectionId: ""
|
||||||
|
property var widgetModel: []
|
||||||
|
property var availableWidgets: []
|
||||||
|
|
||||||
|
signal addWidget(string widgetId, string section)
|
||||||
|
signal removeWidget(string section, int index)
|
||||||
|
signal reorderWidget(string section, int fromIndex, int toIndex)
|
||||||
|
signal updateWidgetSettings(string section, int index, var settings)
|
||||||
|
|
||||||
|
color: Color.mSurface
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.minimumHeight: {
|
||||||
|
var widgetCount = widgetModel.length
|
||||||
|
if (widgetCount === 0)
|
||||||
|
return 140 * scaling
|
||||||
|
|
||||||
|
var availableWidth = parent.width
|
||||||
|
var avgWidgetWidth = 150 * scaling
|
||||||
|
var widgetsPerRow = Math.max(1, Math.floor(availableWidth / avgWidgetWidth))
|
||||||
|
var rows = Math.ceil(widgetCount / widgetsPerRow)
|
||||||
|
|
||||||
|
return (50 + 20 + (rows * 48) + ((rows - 1) * Style.marginS) + 20) * scaling
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate widget color from name checksum
|
||||||
|
function getWidgetColor(widget) {
|
||||||
|
const totalSum = JSON.stringify(widget).split('').reduce((acc, character) => {
|
||||||
|
return acc + character.charCodeAt(0)
|
||||||
|
}, 0)
|
||||||
|
switch (totalSum % 10) {
|
||||||
|
case 0:
|
||||||
|
return Color.mPrimary
|
||||||
|
case 1:
|
||||||
|
return Color.mSecondary
|
||||||
|
case 2:
|
||||||
|
return Color.mTertiary
|
||||||
|
case 3:
|
||||||
|
return Color.mError
|
||||||
|
case 4:
|
||||||
|
return Color.mOnSurface
|
||||||
|
case 5:
|
||||||
|
return Qt.darker(Color.mPrimary, 1.3)
|
||||||
|
case 6:
|
||||||
|
return Qt.darker(Color.mSecondary, 1.3)
|
||||||
|
case 7:
|
||||||
|
return Qt.darker(Color.mTertiary, 1.3)
|
||||||
|
case 8:
|
||||||
|
return Qt.darker(Color.mError, 1.3)
|
||||||
|
case 9:
|
||||||
|
return Qt.darker(Color.mOnSurface, 1.3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Style.marginL * scaling
|
||||||
|
spacing: Style.marginM * scaling
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: sectionName + " Section"
|
||||||
|
font.pointSize: Style.fontSizeL * scaling
|
||||||
|
font.weight: Style.fontWeightBold
|
||||||
|
color: Color.mSecondary
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
NComboBox {
|
||||||
|
id: comboBox
|
||||||
|
model: availableWidgets
|
||||||
|
label: ""
|
||||||
|
description: ""
|
||||||
|
placeholder: "Select a widget to add..."
|
||||||
|
onSelected: key => comboBox.currentKey = key
|
||||||
|
popupHeight: 240 * scaling
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
NIconButton {
|
||||||
|
icon: "add"
|
||||||
|
|
||||||
|
colorBg: Color.mPrimary
|
||||||
|
colorFg: Color.mOnPrimary
|
||||||
|
colorBgHover: Color.mSecondary
|
||||||
|
colorFgHover: Color.mOnSecondary
|
||||||
|
enabled: comboBox.currentKey !== ""
|
||||||
|
tooltipText: "Add widget to section"
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
Layout.leftMargin: Style.marginS * scaling
|
||||||
|
onClicked: {
|
||||||
|
if (comboBox.currentKey !== "") {
|
||||||
|
addWidget(comboBox.currentKey, sectionId)
|
||||||
|
comboBox.currentKey = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drag and Drop Widget Area
|
||||||
|
// Replace your Flow section with this:
|
||||||
|
|
||||||
|
// Drag and Drop Widget Area - use Item container
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.minimumHeight: 65 * scaling
|
||||||
|
|
||||||
|
Flow {
|
||||||
|
id: widgetFlow
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: Style.marginS * scaling
|
||||||
|
flow: Flow.LeftToRight
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: widgetModel
|
||||||
|
delegate: Rectangle {
|
||||||
|
id: widgetItem
|
||||||
|
required property int index
|
||||||
|
required property var modelData
|
||||||
|
|
||||||
|
width: widgetContent.implicitWidth + Style.marginL * scaling
|
||||||
|
height: Style.baseWidgetSize * 1.15 * scaling
|
||||||
|
radius: Style.radiusL * scaling
|
||||||
|
color: root.getWidgetColor(modelData)
|
||||||
|
border.color: Color.mOutline
|
||||||
|
border.width: Math.max(1, Style.borderS * scaling)
|
||||||
|
|
||||||
|
// Store the widget index for drag operations
|
||||||
|
property int widgetIndex: index
|
||||||
|
readonly property int buttonsWidth: Math.round(20 * scaling)
|
||||||
|
readonly property int buttonsCount: 1 + BarWidgetRegistry.widgetHasUserSettings(modelData.id)
|
||||||
|
|
||||||
|
// Visual feedback during drag
|
||||||
|
states: State {
|
||||||
|
when: flowDragArea.draggedIndex === index
|
||||||
|
PropertyChanges {
|
||||||
|
target: widgetItem
|
||||||
|
scale: 1.1
|
||||||
|
opacity: 0.9
|
||||||
|
z: 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: widgetContent
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: Style.marginXXS * scaling
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: modelData.id
|
||||||
|
font.pointSize: Style.fontSizeS * scaling
|
||||||
|
color: Color.mOnPrimary
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
Layout.preferredWidth: 80 * scaling
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: 0
|
||||||
|
Layout.preferredWidth: buttonsCount * buttonsWidth
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
active: BarWidgetRegistry.widgetHasUserSettings(modelData.id)
|
||||||
|
sourceComponent: NIconButton {
|
||||||
|
icon: "settings"
|
||||||
|
sizeRatio: 0.6
|
||||||
|
colorBorder: Color.applyOpacity(Color.mOutline, "40")
|
||||||
|
colorBg: Color.mOnSurface
|
||||||
|
colorFg: Color.mOnPrimary
|
||||||
|
colorBgHover: Color.applyOpacity(Color.mOnPrimary, "40")
|
||||||
|
colorFgHover: Color.mOnPrimary
|
||||||
|
onClicked: {
|
||||||
|
var dialog = Qt.createComponent("BarWidgetSettingsDialog.qml").createObject(root, {
|
||||||
|
"widgetIndex": index,
|
||||||
|
"widgetData": modelData,
|
||||||
|
"widgetId": modelData.id,
|
||||||
|
"parent": Overlay.overlay
|
||||||
|
})
|
||||||
|
dialog.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NIconButton {
|
||||||
|
icon: "close"
|
||||||
|
sizeRatio: 0.6
|
||||||
|
colorBorder: Color.applyOpacity(Color.mOutline, "40")
|
||||||
|
colorBg: Color.mOnSurface
|
||||||
|
colorFg: Color.mOnPrimary
|
||||||
|
colorBgHover: Color.applyOpacity(Color.mOnPrimary, "40")
|
||||||
|
colorFgHover: Color.mOnPrimary
|
||||||
|
onClicked: {
|
||||||
|
removeWidget(sectionId, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MouseArea outside Flow, covering the same area
|
||||||
|
MouseArea {
|
||||||
|
id: flowDragArea
|
||||||
|
anchors.fill: parent
|
||||||
|
z: 999 // Above all widgets to ensure it gets events first
|
||||||
|
|
||||||
|
// Critical properties for proper event handling
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
preventStealing: false // Prevent child items from stealing events
|
||||||
|
propagateComposedEvents: draggedIndex != -1 // Don't propagate to children during drag
|
||||||
|
hoverEnabled: draggedIndex != -1
|
||||||
|
|
||||||
|
property point startPos: Qt.point(0, 0)
|
||||||
|
property bool dragStarted: false
|
||||||
|
property int draggedIndex: -1
|
||||||
|
property real dragThreshold: 15 * scaling
|
||||||
|
property Item draggedWidget: null
|
||||||
|
property point clickOffsetInWidget: Qt.point(0, 0)
|
||||||
|
property point originalWidgetPos: Qt.point(0, 0) // ADD THIS: Store original position
|
||||||
|
|
||||||
|
onPressed: mouse => {
|
||||||
|
startPos = Qt.point(mouse.x, mouse.y)
|
||||||
|
dragStarted = false
|
||||||
|
draggedIndex = -1
|
||||||
|
draggedWidget = null
|
||||||
|
|
||||||
|
// Find which widget was clicked
|
||||||
|
for (var i = 0; i < widgetModel.length; i++) {
|
||||||
|
const widget = widgetFlow.children[i]
|
||||||
|
if (widget && widget.widgetIndex !== undefined) {
|
||||||
|
if (mouse.x >= widget.x && mouse.x <= widget.x + widget.width && mouse.y >= widget.y
|
||||||
|
&& mouse.y <= widget.y + widget.height) {
|
||||||
|
|
||||||
|
const localX = mouse.x - widget.x
|
||||||
|
const buttonsStartX = widget.width - (widget.buttonsCount * widget.buttonsWidth)
|
||||||
|
|
||||||
|
if (localX < buttonsStartX) {
|
||||||
|
draggedIndex = widget.widgetIndex
|
||||||
|
draggedWidget = widget
|
||||||
|
|
||||||
|
// Calculate and store where within the widget the user clicked
|
||||||
|
const clickOffsetX = mouse.x - widget.x
|
||||||
|
const clickOffsetY = mouse.y - widget.y
|
||||||
|
clickOffsetInWidget = Qt.point(clickOffsetX, clickOffsetY)
|
||||||
|
|
||||||
|
// STORE ORIGINAL POSITION
|
||||||
|
originalWidgetPos = Qt.point(widget.x, widget.y)
|
||||||
|
|
||||||
|
// Immediately set prevent stealing to true when drag candidate is found
|
||||||
|
preventStealing = true
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
// Click was on buttons - allow event propagation
|
||||||
|
mouse.accepted = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onPositionChanged: mouse => {
|
||||||
|
if (draggedIndex !== -1) {
|
||||||
|
const deltaX = mouse.x - startPos.x
|
||||||
|
const deltaY = mouse.y - startPos.y
|
||||||
|
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
|
||||||
|
|
||||||
|
if (!dragStarted && distance > dragThreshold) {
|
||||||
|
dragStarted = true
|
||||||
|
//Logger.log("BarSectionEditor", "Drag started")
|
||||||
|
|
||||||
|
// Enable visual feedback
|
||||||
|
if (draggedWidget) {
|
||||||
|
draggedWidget.z = 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dragStarted && draggedWidget) {
|
||||||
|
// Adjust position to account for where within the widget the user clicked
|
||||||
|
draggedWidget.x = mouse.x - clickOffsetInWidget.x
|
||||||
|
draggedWidget.y = mouse.y - clickOffsetInWidget.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onReleased: mouse => {
|
||||||
|
if (dragStarted && draggedWidget) {
|
||||||
|
// Find drop target using improved logic
|
||||||
|
let targetIndex = -1
|
||||||
|
let minDistance = Infinity
|
||||||
|
const mouseX = mouse.x
|
||||||
|
const mouseY = mouse.y
|
||||||
|
|
||||||
|
// Check if we should insert at the beginning
|
||||||
|
let insertAtBeginning = true
|
||||||
|
let insertAtEnd = true
|
||||||
|
|
||||||
|
// Check if the dragged item is already the last item
|
||||||
|
let isLastItem = true
|
||||||
|
for (var k = 0; k < widgetModel.length; k++) {
|
||||||
|
if (k !== draggedIndex && k > draggedIndex) {
|
||||||
|
isLastItem = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < widgetModel.length; i++) {
|
||||||
|
if (i !== draggedIndex) {
|
||||||
|
const widget = widgetFlow.children[i]
|
||||||
|
if (widget && widget.widgetIndex !== undefined) {
|
||||||
|
const centerX = widget.x + widget.width / 2
|
||||||
|
const centerY = widget.y + widget.height / 2
|
||||||
|
const distance = Math.sqrt(Math.pow(mouseX - centerX, 2) + Math.pow(mouseY - centerY, 2))
|
||||||
|
|
||||||
|
// Check if mouse is to the right of this widget
|
||||||
|
if (mouseX > widget.x + widget.width / 2) {
|
||||||
|
insertAtBeginning = false
|
||||||
|
}
|
||||||
|
// Check if mouse is to the left of this widget
|
||||||
|
if (mouseX < widget.x + widget.width / 2) {
|
||||||
|
insertAtEnd = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distance < minDistance) {
|
||||||
|
minDistance = distance
|
||||||
|
targetIndex = widget.widgetIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If dragging the last item to the right, don't reorder
|
||||||
|
if (isLastItem && insertAtEnd) {
|
||||||
|
insertAtEnd = false
|
||||||
|
targetIndex = -1
|
||||||
|
//Logger.log("BarSectionEditor", "Last item dropped to right - no reordering needed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine final target index based on position
|
||||||
|
let finalTargetIndex = targetIndex
|
||||||
|
|
||||||
|
if (insertAtBeginning && widgetModel.length > 1) {
|
||||||
|
// Insert at the very beginning (position 0)
|
||||||
|
finalTargetIndex = 0
|
||||||
|
//Logger.log("BarSectionEditor", "Inserting at beginning")
|
||||||
|
} else if (insertAtEnd && widgetModel.length > 1) {
|
||||||
|
// Insert at the very end
|
||||||
|
let maxIndex = -1
|
||||||
|
for (var j = 0; j < widgetModel.length; j++) {
|
||||||
|
if (j !== draggedIndex) {
|
||||||
|
maxIndex = Math.max(maxIndex, j)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finalTargetIndex = maxIndex
|
||||||
|
//Logger.log("BarSectionEditor", "Inserting at end, target:", finalTargetIndex)
|
||||||
|
} else if (targetIndex !== -1) {
|
||||||
|
// Normal case - determine if we should insert before or after the target
|
||||||
|
const targetWidget = widgetFlow.children[targetIndex]
|
||||||
|
if (targetWidget) {
|
||||||
|
const targetCenterX = targetWidget.x + targetWidget.width / 2
|
||||||
|
if (mouseX > targetCenterX) {
|
||||||
|
// Mouse is to the right of target center, insert after
|
||||||
|
//Logger.log("BarSectionEditor", "Inserting after widget at index:", targetIndex)
|
||||||
|
} else {
|
||||||
|
// Mouse is to the left of target center, insert before
|
||||||
|
finalTargetIndex = targetIndex
|
||||||
|
//Logger.log("BarSectionEditor", "Inserting before widget at index:", targetIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Logger.log("BarSectionEditor", "Final drop target index:", finalTargetIndex)
|
||||||
|
|
||||||
|
// Check if reordering is needed
|
||||||
|
if (finalTargetIndex !== -1 && finalTargetIndex !== draggedIndex) {
|
||||||
|
// Reordering will happen - reset position for the Flow to handle
|
||||||
|
draggedWidget.x = 0
|
||||||
|
draggedWidget.y = 0
|
||||||
|
draggedWidget.z = 0
|
||||||
|
reorderWidget(sectionId, draggedIndex, finalTargetIndex)
|
||||||
|
} else {
|
||||||
|
// No reordering - restore original position
|
||||||
|
draggedWidget.x = originalWidgetPos.x
|
||||||
|
draggedWidget.y = originalWidgetPos.y
|
||||||
|
draggedWidget.z = 0
|
||||||
|
//Logger.log("BarSectionEditor", "No reordering - restoring original position")
|
||||||
|
}
|
||||||
|
} else if (draggedIndex !== -1 && !dragStarted) {
|
||||||
|
|
||||||
|
// This was a click without drag - could add click handling here if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset everything
|
||||||
|
dragStarted = false
|
||||||
|
draggedIndex = -1
|
||||||
|
draggedWidget = null
|
||||||
|
preventStealing = false // Allow normal event propagation again
|
||||||
|
originalWidgetPos = Qt.point(0, 0) // Reset stored position
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle case where mouse leaves the area during drag
|
||||||
|
onExited: {
|
||||||
|
if (dragStarted && draggedWidget) {
|
||||||
|
// Restore original position when mouse leaves area
|
||||||
|
draggedWidget.x = originalWidgetPos.x
|
||||||
|
draggedWidget.y = originalWidgetPos.y
|
||||||
|
draggedWidget.z = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
160
Modules/SettingsPanel/Extras/BarWidgetSettingsDialog.qml
Normal file
160
Modules/SettingsPanel/Extras/BarWidgetSettingsDialog.qml
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Effects
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Commons
|
||||||
|
import qs.Widgets
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
// Widget Settings Dialog Component
|
||||||
|
Popup {
|
||||||
|
id: settingsPopup
|
||||||
|
|
||||||
|
property int widgetIndex: -1
|
||||||
|
property var widgetData: null
|
||||||
|
property string widgetId: ""
|
||||||
|
|
||||||
|
// Center popup in parent
|
||||||
|
x: (parent.width - width) * 0.5
|
||||||
|
y: (parent.height - height) * 0.5
|
||||||
|
|
||||||
|
width: 420 * scaling
|
||||||
|
height: content.implicitHeight + padding * 2
|
||||||
|
padding: Style.marginXL * scaling
|
||||||
|
modal: true
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
id: bgRect
|
||||||
|
color: Color.mSurface
|
||||||
|
radius: Style.radiusL * scaling
|
||||||
|
border.color: Color.mPrimary
|
||||||
|
border.width: Style.borderM * scaling
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: content
|
||||||
|
width: parent.width
|
||||||
|
spacing: Style.marginM * scaling
|
||||||
|
|
||||||
|
// Title
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: "Widget Settings: " + settingsPopup.widgetId
|
||||||
|
font.pointSize: Style.fontSizeL * scaling
|
||||||
|
font.weight: Style.fontWeightBold
|
||||||
|
color: Color.mPrimary
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
NIconButton {
|
||||||
|
icon: "close"
|
||||||
|
onClicked: settingsPopup.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 1
|
||||||
|
color: Color.mOutline
|
||||||
|
}
|
||||||
|
|
||||||
|
// Settings based on widget type
|
||||||
|
Loader {
|
||||||
|
id: settingsLoader
|
||||||
|
Layout.fillWidth: true
|
||||||
|
sourceComponent: {
|
||||||
|
if (settingsPopup.widgetId === "CustomButton") {
|
||||||
|
return customButtonSettings
|
||||||
|
}
|
||||||
|
// Add more widget settings components here as needed
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action buttons
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: Style.marginM * scaling
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
NButton {
|
||||||
|
text: "Cancel"
|
||||||
|
outlined: true
|
||||||
|
onClicked: settingsPopup.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
NButton {
|
||||||
|
text: "Save"
|
||||||
|
onClicked: {
|
||||||
|
if (settingsLoader.item && settingsLoader.item.saveSettings) {
|
||||||
|
var newSettings = settingsLoader.item.saveSettings()
|
||||||
|
root.updateWidgetSettings(sectionId, settingsPopup.widgetIndex, newSettings)
|
||||||
|
settingsPopup.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomButton settings component
|
||||||
|
Component {
|
||||||
|
id: customButtonSettings
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.marginM * scaling
|
||||||
|
|
||||||
|
function saveSettings() {
|
||||||
|
var settings = Object.assign({}, settingsPopup.widgetData)
|
||||||
|
settings.icon = iconInput.text
|
||||||
|
settings.leftClickExec = leftClickExecInput.text
|
||||||
|
settings.rightClickExec = rightClickExecInput.text
|
||||||
|
settings.middleClickExec = middleClickExecInput.text
|
||||||
|
return settings
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icon setting
|
||||||
|
NTextInput {
|
||||||
|
id: iconInput
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.bottomMargin: Style.marginXL * scaling
|
||||||
|
label: "Icon Name"
|
||||||
|
description: "Use Material Icon names from the icon set."
|
||||||
|
text: settingsPopup.widgetData.icon || ""
|
||||||
|
placeholderText: "Enter icon name (e.g., favorite, home, settings)"
|
||||||
|
}
|
||||||
|
|
||||||
|
NTextInput {
|
||||||
|
id: leftClickExecInput
|
||||||
|
Layout.fillWidth: true
|
||||||
|
label: "Left Click Command"
|
||||||
|
description: "Command or application to run when left clicked."
|
||||||
|
text: settingsPopup.widgetData.leftClickExec || ""
|
||||||
|
placeholderText: "Enter command to execute (app or custom script)"
|
||||||
|
}
|
||||||
|
|
||||||
|
NTextInput {
|
||||||
|
id: rightClickExecInput
|
||||||
|
Layout.fillWidth: true
|
||||||
|
label: "Right Click Command"
|
||||||
|
description: "Command or application to run when right clicked."
|
||||||
|
text: settingsPopup.widgetData.rightClickExec || ""
|
||||||
|
placeholderText: "Enter command to execute (app or custom script)"
|
||||||
|
}
|
||||||
|
|
||||||
|
NTextInput {
|
||||||
|
id: middleClickExecInput
|
||||||
|
Layout.fillWidth: true
|
||||||
|
label: "Middle Click Command"
|
||||||
|
description: "Command or application to run when middle clicked."
|
||||||
|
text: settingsPopup.widgetData.middleClickExec || ""
|
||||||
|
placeholderText: "Enter command to execute (app or custom script)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,13 +24,12 @@ NPanel {
|
||||||
panelAnchorHorizontalCenter: true
|
panelAnchorHorizontalCenter: true
|
||||||
panelAnchorVerticalCenter: true
|
panelAnchorVerticalCenter: true
|
||||||
|
|
||||||
// Enable keyboard focus for settings panel
|
|
||||||
panelKeyboardFocus: true
|
panelKeyboardFocus: true
|
||||||
|
|
||||||
// Tabs enumeration, order is NOT relevant
|
// Tabs enumeration, order is NOT relevant
|
||||||
enum Tab {
|
enum Tab {
|
||||||
About,
|
About,
|
||||||
AudioService,
|
Audio,
|
||||||
Bar,
|
Bar,
|
||||||
Launcher,
|
Launcher,
|
||||||
Brightness,
|
Brightness,
|
||||||
|
|
@ -131,7 +130,7 @@ NPanel {
|
||||||
"icon": "apps",
|
"icon": "apps",
|
||||||
"source": launcherTab
|
"source": launcherTab
|
||||||
}, {
|
}, {
|
||||||
"id": SettingsPanel.Tab.AudioService,
|
"id": SettingsPanel.Tab.Audio,
|
||||||
"label": "Audio",
|
"label": "Audio",
|
||||||
"icon": "volume_up",
|
"icon": "volume_up",
|
||||||
"source": audioTab
|
"source": audioTab
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import QtQuick.Layouts
|
||||||
import qs.Commons
|
import qs.Commons
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
import qs.Modules.SettingsPanel.Extras
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
@ -157,36 +158,39 @@ ColumnLayout {
|
||||||
spacing: Style.marginM * scaling
|
spacing: Style.marginM * scaling
|
||||||
|
|
||||||
// Left Section
|
// Left Section
|
||||||
NSectionEditor {
|
BarSectionEditor {
|
||||||
sectionName: "Left"
|
sectionName: "Left"
|
||||||
sectionId: "left"
|
sectionId: "left"
|
||||||
widgetModel: Settings.data.bar.widgets.left
|
widgetModel: Settings.data.bar.widgets.left
|
||||||
availableWidgets: availableWidgets
|
availableWidgets: availableWidgets
|
||||||
onAddWidget: (widgetName, section) => addWidgetToSection(widgetName, section)
|
onAddWidget: (widgetId, section) => _addWidgetToSection(widgetId, section)
|
||||||
onRemoveWidget: (section, index) => removeWidgetFromSection(section, index)
|
onRemoveWidget: (section, index) => _removeWidgetFromSection(section, index)
|
||||||
onReorderWidget: (section, fromIndex, toIndex) => reorderWidgetInSection(section, fromIndex, toIndex)
|
onReorderWidget: (section, fromIndex, toIndex) => _reorderWidgetInSection(section, fromIndex, toIndex)
|
||||||
|
onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsInSection(section, index, settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Center Section
|
// Center Section
|
||||||
NSectionEditor {
|
BarSectionEditor {
|
||||||
sectionName: "Center"
|
sectionName: "Center"
|
||||||
sectionId: "center"
|
sectionId: "center"
|
||||||
widgetModel: Settings.data.bar.widgets.center
|
widgetModel: Settings.data.bar.widgets.center
|
||||||
availableWidgets: availableWidgets
|
availableWidgets: availableWidgets
|
||||||
onAddWidget: (widgetName, section) => addWidgetToSection(widgetName, section)
|
onAddWidget: (widgetId, section) => _addWidgetToSection(widgetId, section)
|
||||||
onRemoveWidget: (section, index) => removeWidgetFromSection(section, index)
|
onRemoveWidget: (section, index) => _removeWidgetFromSection(section, index)
|
||||||
onReorderWidget: (section, fromIndex, toIndex) => reorderWidgetInSection(section, fromIndex, toIndex)
|
onReorderWidget: (section, fromIndex, toIndex) => _reorderWidgetInSection(section, fromIndex, toIndex)
|
||||||
|
onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsInSection(section, index, settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right Section
|
// Right Section
|
||||||
NSectionEditor {
|
BarSectionEditor {
|
||||||
sectionName: "Right"
|
sectionName: "Right"
|
||||||
sectionId: "right"
|
sectionId: "right"
|
||||||
widgetModel: Settings.data.bar.widgets.right
|
widgetModel: Settings.data.bar.widgets.right
|
||||||
availableWidgets: availableWidgets
|
availableWidgets: availableWidgets
|
||||||
onAddWidget: (widgetName, section) => addWidgetToSection(widgetName, section)
|
onAddWidget: (widgetId, section) => _addWidgetToSection(widgetId, section)
|
||||||
onRemoveWidget: (section, index) => removeWidgetFromSection(section, index)
|
onRemoveWidget: (section, index) => _removeWidgetFromSection(section, index)
|
||||||
onReorderWidget: (section, fromIndex, toIndex) => reorderWidgetInSection(section, fromIndex, toIndex)
|
onReorderWidget: (section, fromIndex, toIndex) => _reorderWidgetInSection(section, fromIndex, toIndex)
|
||||||
|
onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsInSection(section, index, settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -197,60 +201,55 @@ ColumnLayout {
|
||||||
Layout.bottomMargin: Style.marginXL * scaling
|
Layout.bottomMargin: Style.marginXL * scaling
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions
|
// ---------------------------------
|
||||||
function addWidgetToSection(widgetName, section) {
|
// Signal functions
|
||||||
//Logger.log("BarTab", "Adding widget", widgetName, "to section", section)
|
// ---------------------------------
|
||||||
var sectionArray = Settings.data.bar.widgets[section]
|
function _addWidgetToSection(widgetId, section) {
|
||||||
|
var newWidget = {
|
||||||
if (sectionArray) {
|
"id": widgetId
|
||||||
// Create a new array to avoid modifying the original
|
}
|
||||||
var newArray = sectionArray.slice()
|
if (BarWidgetRegistry.widgetHasUserSettings(widgetId)) {
|
||||||
newArray.push(widgetName)
|
var metadata = BarWidgetRegistry.widgetMetadata[widgetId]
|
||||||
//Logger.log("BarTab", "Widget added. New array:", JSON.stringify(newArray))
|
if (metadata) {
|
||||||
|
Object.keys(metadata).forEach(function (key) {
|
||||||
// Assign the new array
|
if (key !== "allowUserSettings") {
|
||||||
Settings.data.bar.widgets[section] = newArray
|
newWidget[key] = metadata[key]
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Settings.data.bar.widgets[section].push(newWidget)
|
||||||
|
}
|
||||||
|
|
||||||
function removeWidgetFromSection(section, index) {
|
function _removeWidgetFromSection(section, index) {
|
||||||
// Logger.log("BarTab", "Removing widget from section", section, "at index", index)
|
if (index >= 0 && index < Settings.data.bar.widgets[section].length) {
|
||||||
var sectionArray = Settings.data.bar.widgets[section]
|
var newArray = Settings.data.bar.widgets[section].slice()
|
||||||
|
|
||||||
//Logger.log("BarTab", "Current section array:", JSON.stringify(sectionArray))
|
|
||||||
if (sectionArray && index >= 0 && index < sectionArray.length) {
|
|
||||||
// Create a new array to avoid modifying the original
|
|
||||||
var newArray = sectionArray.slice()
|
|
||||||
newArray.splice(index, 1)
|
newArray.splice(index, 1)
|
||||||
//Logger.log("BarTab", "Widget removed. New array:", JSON.stringify(newArray))
|
|
||||||
|
|
||||||
// Assign the new array
|
|
||||||
Settings.data.bar.widgets[section] = newArray
|
Settings.data.bar.widgets[section] = newArray
|
||||||
} else {
|
|
||||||
|
|
||||||
//Logger.log("BarTab", "Invalid section or index:", section, index, "array length:",
|
|
||||||
// sectionArray ? sectionArray.length : "null")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function reorderWidgetInSection(section, fromIndex, toIndex) {
|
function _reorderWidgetInSection(section, fromIndex, toIndex) {
|
||||||
//Logger.log("BarTab", "Reordering widget in section", section, "from", fromIndex, "to", toIndex)
|
if (fromIndex >= 0 && fromIndex < Settings.data.bar.widgets[section].length && toIndex >= 0
|
||||||
var sectionArray = Settings.data.bar.widgets[section]
|
&& toIndex < Settings.data.bar.widgets[section].length) {
|
||||||
if (sectionArray && fromIndex >= 0 && fromIndex < sectionArray.length && toIndex >= 0
|
|
||||||
&& toIndex < sectionArray.length) {
|
|
||||||
|
|
||||||
// Create a new array to avoid modifying the original
|
// Create a new array to avoid modifying the original
|
||||||
var newArray = sectionArray.slice()
|
var newArray = Settings.data.bar.widgets[section].slice()
|
||||||
var item = newArray[fromIndex]
|
var item = newArray[fromIndex]
|
||||||
newArray.splice(fromIndex, 1)
|
newArray.splice(fromIndex, 1)
|
||||||
newArray.splice(toIndex, 0, item)
|
newArray.splice(toIndex, 0, item)
|
||||||
Logger.log("BarTab", "Widget reordered. New array:", JSON.stringify(newArray))
|
|
||||||
|
|
||||||
// Assign the new array
|
|
||||||
Settings.data.bar.widgets[section] = newArray
|
Settings.data.bar.widgets[section] = newArray
|
||||||
|
//Logger.log("BarTab", "Widget reordered. New array:", JSON.stringify(newArray))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _updateWidgetSettingsInSection(section, index, settings) {
|
||||||
|
// Update the widget settings in the Settings data
|
||||||
|
Settings.data.bar.widgets[section][index] = settings
|
||||||
|
//Logger.log("BarTab", `Updated widget settings for ${settings.id} in ${section} section`)
|
||||||
|
}
|
||||||
|
|
||||||
// Base list model for all combo boxes
|
// Base list model for all combo boxes
|
||||||
ListModel {
|
ListModel {
|
||||||
id: availableWidgets
|
id: availableWidgets
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
NPanel {
|
NPanel {
|
||||||
id: panel
|
id: root
|
||||||
|
|
||||||
panelWidth: 460 * scaling
|
panelWidth: 460 * scaling
|
||||||
panelHeight: 708 * scaling
|
panelHeight: 708 * scaling
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ Singleton {
|
||||||
"Bluetooth": bluetoothComponent,
|
"Bluetooth": bluetoothComponent,
|
||||||
"Brightness": brightnessComponent,
|
"Brightness": brightnessComponent,
|
||||||
"Clock": clockComponent,
|
"Clock": clockComponent,
|
||||||
|
"CustomButton": customButtonComponent,
|
||||||
"DarkModeToggle": darkModeToggle,
|
"DarkModeToggle": darkModeToggle,
|
||||||
"KeyboardLayout": keyboardLayoutComponent,
|
"KeyboardLayout": keyboardLayoutComponent,
|
||||||
"MediaMini": mediaMiniComponent,
|
"MediaMini": mediaMiniComponent,
|
||||||
|
|
@ -33,6 +34,16 @@ Singleton {
|
||||||
"Workspace": workspaceComponent
|
"Workspace": workspaceComponent
|
||||||
})
|
})
|
||||||
|
|
||||||
|
property var widgetMetadata: ({
|
||||||
|
"CustomButton": {
|
||||||
|
"allowUserSettings": true,
|
||||||
|
"icon": "favorite",
|
||||||
|
"leftClickExec": "",
|
||||||
|
"rightClickExec": "",
|
||||||
|
"middleClickExec": ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Component definitions - these are loaded once at startup
|
// Component definitions - these are loaded once at startup
|
||||||
property Component activeWindowComponent: Component {
|
property Component activeWindowComponent: Component {
|
||||||
ActiveWindow {}
|
ActiveWindow {}
|
||||||
|
|
@ -52,6 +63,9 @@ Singleton {
|
||||||
property Component clockComponent: Component {
|
property Component clockComponent: Component {
|
||||||
Clock {}
|
Clock {}
|
||||||
}
|
}
|
||||||
|
property Component customButtonComponent: Component {
|
||||||
|
CustomButton {}
|
||||||
|
}
|
||||||
property Component darkModeToggle: Component {
|
property Component darkModeToggle: Component {
|
||||||
DarkModeToggle {}
|
DarkModeToggle {}
|
||||||
}
|
}
|
||||||
|
|
@ -100,20 +114,25 @@ Singleton {
|
||||||
|
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
// Helper function to get widget component by name
|
// Helper function to get widget component by name
|
||||||
function getWidget(name) {
|
function getWidget(id) {
|
||||||
return widgets[name] || null
|
return widgets[id] || null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to check if widget exists
|
// Helper function to check if widget exists
|
||||||
function hasWidget(name) {
|
function hasWidget(id) {
|
||||||
return name in widgets
|
return id in widgets
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get list of available widget names
|
// Get list of available widget id
|
||||||
function getAvailableWidgets() {
|
function getAvailableWidgets() {
|
||||||
return Object.keys(widgets)
|
return Object.keys(widgets)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to check if widget has user settings
|
||||||
|
function widgetHasUserSettings(id) {
|
||||||
|
return (widgetMetadata[id] !== undefined) && (widgetMetadata[id].allowUserSettings === true)
|
||||||
|
}
|
||||||
|
|
||||||
function getNPillDirection(widget) {
|
function getNPillDirection(widget) {
|
||||||
try {
|
try {
|
||||||
if (widget.barSection === "leftSection") {
|
if (widget.barSection === "leftSection") {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ Rectangle {
|
||||||
signal exited
|
signal exited
|
||||||
signal clicked
|
signal clicked
|
||||||
signal rightClicked
|
signal rightClicked
|
||||||
|
signal middleClicked
|
||||||
|
|
||||||
implicitWidth: size
|
implicitWidth: size
|
||||||
implicitHeight: size
|
implicitHeight: size
|
||||||
|
|
@ -59,7 +60,7 @@ Rectangle {
|
||||||
enabled: root.enabled
|
enabled: root.enabled
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
cursorShape: root.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
cursorShape: root.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: {
|
onEntered: {
|
||||||
hovering = true
|
hovering = true
|
||||||
|
|
@ -83,6 +84,8 @@ Rectangle {
|
||||||
root.clicked()
|
root.clicked()
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
root.rightClicked()
|
root.rightClicked()
|
||||||
|
} else if (mouse.button === Qt.MiddleButton) {
|
||||||
|
root.middleClicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,321 +0,0 @@
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import qs.Commons
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
NBox {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property string sectionName: ""
|
|
||||||
property string sectionId: ""
|
|
||||||
property var widgetModel: []
|
|
||||||
property var availableWidgets: []
|
|
||||||
|
|
||||||
signal addWidget(string widgetName, string section)
|
|
||||||
signal removeWidget(string section, int index)
|
|
||||||
signal reorderWidget(string section, int fromIndex, int toIndex)
|
|
||||||
|
|
||||||
color: Color.mSurface
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.minimumHeight: {
|
|
||||||
var widgetCount = widgetModel.length
|
|
||||||
if (widgetCount === 0)
|
|
||||||
return 140 * scaling
|
|
||||||
|
|
||||||
var availableWidth = parent.width
|
|
||||||
var avgWidgetWidth = 150 * scaling
|
|
||||||
var widgetsPerRow = Math.max(1, Math.floor(availableWidth / avgWidgetWidth))
|
|
||||||
var rows = Math.ceil(widgetCount / widgetsPerRow)
|
|
||||||
|
|
||||||
return (50 + 20 + (rows * 48) + ((rows - 1) * Style.marginS) + 20) * scaling
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate widget color from name checksum
|
|
||||||
function getWidgetColor(name) {
|
|
||||||
const totalSum = name.split('').reduce((acc, character) => {
|
|
||||||
return acc + character.charCodeAt(0)
|
|
||||||
}, 0)
|
|
||||||
switch (totalSum % 5) {
|
|
||||||
case 0:
|
|
||||||
return Color.mPrimary
|
|
||||||
case 1:
|
|
||||||
return Color.mSecondary
|
|
||||||
case 2:
|
|
||||||
return Color.mTertiary
|
|
||||||
case 3:
|
|
||||||
return Color.mError
|
|
||||||
case 4:
|
|
||||||
return Color.mOnSurface
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Style.marginL * scaling
|
|
||||||
spacing: Style.marginM * scaling
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: sectionName + " Section"
|
|
||||||
font.pointSize: Style.fontSizeL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
NComboBox {
|
|
||||||
id: comboBox
|
|
||||||
model: availableWidgets
|
|
||||||
label: ""
|
|
||||||
description: ""
|
|
||||||
placeholder: "Select a widget to add..."
|
|
||||||
onSelected: key => comboBox.currentKey = key
|
|
||||||
popupHeight: 240 * scaling
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
NIconButton {
|
|
||||||
icon: "add"
|
|
||||||
|
|
||||||
colorBg: Color.mPrimary
|
|
||||||
colorFg: Color.mOnPrimary
|
|
||||||
colorBgHover: Color.mSecondary
|
|
||||||
colorFgHover: Color.mOnSecondary
|
|
||||||
enabled: comboBox.currentKey !== ""
|
|
||||||
tooltipText: "Add widget to section"
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
Layout.leftMargin: Style.marginS * scaling
|
|
||||||
onClicked: {
|
|
||||||
if (comboBox.currentKey !== "") {
|
|
||||||
addWidget(comboBox.currentKey, sectionId)
|
|
||||||
comboBox.currentKey = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drag and Drop Widget Area
|
|
||||||
Flow {
|
|
||||||
id: widgetFlow
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.minimumHeight: 65 * scaling
|
|
||||||
spacing: Style.marginS * scaling
|
|
||||||
flow: Flow.LeftToRight
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: widgetModel
|
|
||||||
delegate: Rectangle {
|
|
||||||
id: widgetItem
|
|
||||||
required property int index
|
|
||||||
required property string modelData
|
|
||||||
|
|
||||||
width: widgetContent.implicitWidth + Style.marginL * scaling
|
|
||||||
height: 40 * scaling
|
|
||||||
radius: Style.radiusL * scaling
|
|
||||||
color: root.getWidgetColor(modelData)
|
|
||||||
border.color: Color.mOutline
|
|
||||||
border.width: Math.max(1, Style.borderS * scaling)
|
|
||||||
|
|
||||||
// Drag properties
|
|
||||||
Drag.keys: ["widget"]
|
|
||||||
Drag.active: mouseArea.drag.active
|
|
||||||
Drag.hotSpot.x: width / 2
|
|
||||||
Drag.hotSpot.y: height / 2
|
|
||||||
|
|
||||||
// Store the widget index for drag operations
|
|
||||||
property int widgetIndex: index
|
|
||||||
|
|
||||||
// Visual feedback during drag
|
|
||||||
states: State {
|
|
||||||
when: mouseArea.drag.active
|
|
||||||
PropertyChanges {
|
|
||||||
target: widgetItem
|
|
||||||
scale: 1.1
|
|
||||||
opacity: 0.9
|
|
||||||
z: 1000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
id: widgetContent
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: Style.marginXS * scaling
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: modelData
|
|
||||||
font.pointSize: Style.fontSizeS * scaling
|
|
||||||
color: Color.mOnPrimary
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
elide: Text.ElideRight
|
|
||||||
Layout.preferredWidth: 80 * scaling
|
|
||||||
}
|
|
||||||
|
|
||||||
NIconButton {
|
|
||||||
icon: "close"
|
|
||||||
sizeRatio: 0.6
|
|
||||||
colorBorder: Color.applyOpacity(Color.mOutline, "40")
|
|
||||||
colorBg: Color.mOnSurface
|
|
||||||
colorFg: Color.mOnPrimary
|
|
||||||
colorBgHover: Color.applyOpacity(Color.mOnPrimary, "40")
|
|
||||||
colorFgHover: Color.mOnPrimary
|
|
||||||
onClicked: {
|
|
||||||
removeWidget(sectionId, index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mouse area for drag and drop
|
|
||||||
MouseArea {
|
|
||||||
id: mouseArea
|
|
||||||
anchors.fill: parent
|
|
||||||
drag.target: parent
|
|
||||||
|
|
||||||
onPressed: mouse => {
|
|
||||||
// Check if the click is on the close button area
|
|
||||||
const closeButtonX = widgetContent.x + widgetContent.width - 20 * scaling
|
|
||||||
const closeButtonY = widgetContent.y
|
|
||||||
const closeButtonWidth = 20 * scaling
|
|
||||||
const closeButtonHeight = 20 * scaling
|
|
||||||
|
|
||||||
if (mouseX >= closeButtonX && mouseX <= closeButtonX + closeButtonWidth
|
|
||||||
&& mouseY >= closeButtonY && mouseY <= closeButtonY + closeButtonHeight) {
|
|
||||||
// Click is on the close button, don't start drag
|
|
||||||
mouse.accepted = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//Logger.log("NSectionEditor", `Started dragging widget: ${modelData} at index ${index}`)
|
|
||||||
// Bring to front when starting drag
|
|
||||||
widgetItem.z = 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
onReleased: {
|
|
||||||
//Logger.log("NSectionEditor", `Released widget: ${modelData} at index ${index}`)
|
|
||||||
// Reset z-index when drag ends
|
|
||||||
widgetItem.z = 0
|
|
||||||
|
|
||||||
// Get the global mouse position
|
|
||||||
const globalDropX = mouseArea.mouseX + widgetItem.x + widgetFlow.x
|
|
||||||
const globalDropY = mouseArea.mouseY + widgetItem.y + widgetFlow.y
|
|
||||||
|
|
||||||
// Find which widget the drop position is closest to
|
|
||||||
let targetIndex = -1
|
|
||||||
let minDistance = Infinity
|
|
||||||
|
|
||||||
for (var i = 0; i < widgetModel.length; i++) {
|
|
||||||
if (i !== index) {
|
|
||||||
// Get the position of other widgets
|
|
||||||
const otherWidget = widgetFlow.children[i]
|
|
||||||
if (otherWidget && otherWidget.widgetIndex !== undefined) {
|
|
||||||
// Calculate the center of the other widget
|
|
||||||
const otherCenterX = otherWidget.x + otherWidget.width / 2 + widgetFlow.x
|
|
||||||
const otherCenterY = otherWidget.y + otherWidget.height / 2 + widgetFlow.y
|
|
||||||
|
|
||||||
// Calculate distance to the center of this widget
|
|
||||||
const distance = Math.sqrt(Math.pow(globalDropX - otherCenterX,
|
|
||||||
2) + Math.pow(globalDropY - otherCenterY, 2))
|
|
||||||
|
|
||||||
if (distance < minDistance) {
|
|
||||||
minDistance = distance
|
|
||||||
targetIndex = otherWidget.widgetIndex
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only reorder if we found a valid target and it's different from current position
|
|
||||||
if (targetIndex !== -1 && targetIndex !== index) {
|
|
||||||
const fromIndex = index
|
|
||||||
const toIndex = targetIndex
|
|
||||||
// Logger.log(
|
|
||||||
// "NSectionEditor",
|
|
||||||
// `Dropped widget from index ${fromIndex} to position ${toIndex} (distance: ${minDistance.toFixed(
|
|
||||||
// 2)})`)
|
|
||||||
reorderWidget(sectionId, fromIndex, toIndex)
|
|
||||||
} else {
|
|
||||||
Logger.warn("NSectionEditor", `No valid drop target found for widget at index ${index}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drop zone at the beginning (positioned absolutely)
|
|
||||||
DropArea {
|
|
||||||
id: startDropZone
|
|
||||||
width: 40 * scaling
|
|
||||||
height: 40 * scaling
|
|
||||||
x: widgetFlow.x
|
|
||||||
y: widgetFlow.y + (widgetFlow.height - height) / 2
|
|
||||||
keys: ["widget"]
|
|
||||||
z: 1001 // Above the Flow
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: startDropZone.containsDrag ? Color.applyOpacity(Color.mPrimary, "20") : Color.transparent
|
|
||||||
border.color: startDropZone.containsDrag ? Color.mPrimary : Color.transparent
|
|
||||||
border.width: startDropZone.containsDrag ? 2 : 0
|
|
||||||
radius: Style.radiusS * scaling
|
|
||||||
}
|
|
||||||
|
|
||||||
onEntered: function (drag) {//Logger.log("NSectionEditor", "Entered start drop zone")
|
|
||||||
}
|
|
||||||
|
|
||||||
onDropped: function (drop) {
|
|
||||||
//Logger.log("NSectionEditor", "Dropped on start zone")
|
|
||||||
if (drop.source && drop.source.widgetIndex !== undefined) {
|
|
||||||
const fromIndex = drop.source.widgetIndex
|
|
||||||
const toIndex = 0 // Insert at the beginning
|
|
||||||
if (fromIndex !== toIndex) {
|
|
||||||
//Logger.log("NSectionEditor", `Dropped widget from index ${fromIndex} to beginning`)
|
|
||||||
reorderWidget(sectionId, fromIndex, toIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drop zone at the end (positioned absolutely)
|
|
||||||
DropArea {
|
|
||||||
id: endDropZone
|
|
||||||
width: 40 * scaling
|
|
||||||
height: 40 * scaling
|
|
||||||
x: widgetFlow.x + widgetFlow.width - width
|
|
||||||
y: widgetFlow.y + (widgetFlow.height - height) / 2
|
|
||||||
keys: ["widget"]
|
|
||||||
z: 1001 // Above the Flow
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: endDropZone.containsDrag ? Color.applyOpacity(Color.mPrimary, "20") : Color.transparent
|
|
||||||
border.color: endDropZone.containsDrag ? Color.mPrimary : Color.transparent
|
|
||||||
border.width: endDropZone.containsDrag ? 2 : 0
|
|
||||||
radius: Style.radiusS * scaling
|
|
||||||
}
|
|
||||||
|
|
||||||
onEntered: function (drag) {//Logger.log("NSectionEditor", "Entered end drop zone")
|
|
||||||
}
|
|
||||||
|
|
||||||
onDropped: function (drop) {
|
|
||||||
//Logger.log("NSectionEditor", "Dropped on end zone")
|
|
||||||
if (drop.source && drop.source.widgetIndex !== undefined) {
|
|
||||||
const fromIndex = drop.source.widgetIndex
|
|
||||||
const toIndex = widgetModel.length // Insert at the end
|
|
||||||
if (fromIndex !== toIndex) {
|
|
||||||
//Logger.log("NSectionEditor", `Dropped widget from index ${fromIndex} to end`)
|
|
||||||
reorderWidget(sectionId, fromIndex, toIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -39,10 +39,13 @@ ColumnLayout {
|
||||||
// Container
|
// Container
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: frame
|
id: frame
|
||||||
implicitWidth: parent.width
|
|
||||||
implicitHeight: Style.baseWidgetSize * 1.1 * scaling
|
Layout.fillWidth: true
|
||||||
Layout.minimumWidth: 80 * scaling
|
Layout.minimumWidth: 80 * scaling
|
||||||
Layout.maximumWidth: root.inputMaxWidth
|
Layout.maximumWidth: root.inputMaxWidth
|
||||||
|
|
||||||
|
implicitWidth: parent.width
|
||||||
|
implicitHeight: Style.baseWidgetSize * 1.1 * scaling
|
||||||
radius: Style.radiusM * scaling
|
radius: Style.radiusM * scaling
|
||||||
color: Color.mSurface
|
color: Color.mSurface
|
||||||
border.color: Color.mOutline
|
border.color: Color.mOutline
|
||||||
|
|
@ -76,7 +79,7 @@ ColumnLayout {
|
||||||
readOnly: root.readOnly
|
readOnly: root.readOnly
|
||||||
enabled: root.enabled
|
enabled: root.enabled
|
||||||
color: Color.mOnSurface
|
color: Color.mOnSurface
|
||||||
placeholderTextColor: Color.mOnSurfaceVariant
|
placeholderTextColor: Qt.alpha(Color.mOnSurfaceVariant, 0.6)
|
||||||
background: null
|
background: null
|
||||||
font.family: fontFamily
|
font.family: fontFamily
|
||||||
font.pointSize: fontSize
|
font.pointSize: fontSize
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import qs.Commons
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string widgetName: ""
|
property string widgetId: ""
|
||||||
property var widgetProps: ({})
|
property var widgetProps: ({})
|
||||||
property bool enabled: true
|
property bool enabled: true
|
||||||
|
|
||||||
|
|
@ -27,12 +27,12 @@ Item {
|
||||||
id: loader
|
id: loader
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
active: Settings.isLoaded && enabled && widgetName !== ""
|
active: Settings.isLoaded && enabled && widgetId !== ""
|
||||||
sourceComponent: {
|
sourceComponent: {
|
||||||
if (!active) {
|
if (!active) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return BarWidgetRegistry.getWidget(widgetName)
|
return BarWidgetRegistry.getWidget(widgetId)
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
|
|
@ -49,14 +49,14 @@ Item {
|
||||||
item.onLoaded()
|
item.onLoaded()
|
||||||
}
|
}
|
||||||
|
|
||||||
//Logger.log("NWidgetLoader", "Loaded", widgetName, "on screen", item.screen.name)
|
//Logger.log("NWidgetLoader", "Loaded", widgetId, "on screen", item.screen.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error handling
|
// Error handling
|
||||||
onWidgetNameChanged: {
|
onWidgetIdChanged: {
|
||||||
if (widgetName && !BarWidgetRegistry.hasWidget(widgetName)) {
|
if (widgetId && !BarWidgetRegistry.hasWidget(widgetId)) {
|
||||||
Logger.warn("WidgetLoader", "Widget not found in registry:", widgetName)
|
Logger.warn("WidgetLoader", "Widget not found in registry:", widgetId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue