BarSettings: better D&D

This commit is contained in:
LemmyCook 2025-09-04 00:27:38 -04:00
parent 9e819084af
commit 4a45e73125
2 changed files with 315 additions and 252 deletions

View file

@ -117,8 +117,8 @@ NBox {
// Drag and Drop Widget Area // Drag and Drop Widget Area
// Replace your Flow section with this: // Replace your Flow section with this:
// Drag and Drop Widget Area - use Item container // Drag and Drop Widget Area - use Item container
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Layout.minimumHeight: 65 * scaling Layout.minimumHeight: 65 * scaling
@ -217,7 +217,7 @@ Item {
} }
} }
// MouseArea outside Flow, covering the same area // MouseArea outside Flow, covering the same area
MouseArea { MouseArea {
id: flowDragArea id: flowDragArea
anchors.fill: parent anchors.fill: parent
@ -225,16 +225,17 @@ Item {
// Critical properties for proper event handling // Critical properties for proper event handling
acceptedButtons: Qt.LeftButton acceptedButtons: Qt.LeftButton
preventStealing: true // Prevent child items from stealing events preventStealing: false // Prevent child items from stealing events
propagateComposedEvents: false // Don't propagate to children during drag propagateComposedEvents: draggedIndex != -1 // Don't propagate to children during drag
hoverEnabled: true hoverEnabled: draggedIndex != -1
property point startPos: Qt.point(0, 0) property point startPos: Qt.point(0, 0)
property bool dragStarted: false property bool dragStarted: false
property int draggedIndex: -1 property int draggedIndex: -1
property real dragThreshold: 15 * scaling property real dragThreshold: 15 * scaling
property Item draggedWidget: null property Item draggedWidget: null
property point clickOffsetInWidget: Qt.point(0, 0) // Add this line property point clickOffsetInWidget: Qt.point(0, 0)
property point originalWidgetPos: Qt.point(0, 0) // ADD THIS: Store original position
onPressed: mouse => { onPressed: mouse => {
startPos = Qt.point(mouse.x, mouse.y) startPos = Qt.point(mouse.x, mouse.y)
@ -242,14 +243,12 @@ Item {
draggedIndex = -1 draggedIndex = -1
draggedWidget = null draggedWidget = null
console.log("Mouse pressed at:", mouse.x, mouse.y)
// Find which widget was clicked // Find which widget was clicked
for (var i = 0; i < widgetModel.length; i++) { for (var i = 0; i < widgetModel.length; i++) {
const widget = widgetFlow.children[i] const widget = widgetFlow.children[i]
if (widget && widget.widgetIndex !== undefined) { if (widget && widget.widgetIndex !== undefined) {
if (mouse.x >= widget.x && mouse.x <= widget.x + widget.width && if (mouse.x >= widget.x && mouse.x <= widget.x + widget.width && mouse.y >= widget.y
mouse.y >= widget.y && mouse.y <= widget.y + widget.height) { && mouse.y <= widget.y + widget.height) {
const localX = mouse.x - widget.x const localX = mouse.x - widget.x
const buttonsStartX = widget.width - (widget.buttonsCount * widget.buttonsWidth) const buttonsStartX = widget.width - (widget.buttonsCount * widget.buttonsWidth)
@ -259,19 +258,17 @@ Item {
draggedWidget = widget draggedWidget = widget
// Calculate and store where within the widget the user clicked // Calculate and store where within the widget the user clicked
const clickOffsetX = mouse.x - widget.x // Distance from widget's left edge const clickOffsetX = mouse.x - widget.x
const clickOffsetY = mouse.y - widget.y // Distance from widget's top edge const clickOffsetY = mouse.y - widget.y
clickOffsetInWidget = Qt.point(clickOffsetX, clickOffsetY) clickOffsetInWidget = Qt.point(clickOffsetX, clickOffsetY)
Logger.log("BarSectionEditor", "Selected widget:", widgetModel[i].id, "at index", i) // STORE ORIGINAL POSITION
Logger.log("BarSectionEditor", "Widget position:", widget.x, widget.y) originalWidgetPos = Qt.point(widget.x, widget.y)
Logger.log("BarSectionEditor", "Mouse position:", mouse.x, mouse.y)
Logger.log("BarSectionEditor", "Click offset within widget:", clickOffsetInWidget.x, clickOffsetInWidget.y)
// Immediately set prevent stealing to true when drag candidate is found // Immediately set prevent stealing to true when drag candidate is found
preventStealing = true preventStealing = true
break break
}else { } else {
// Click was on buttons - allow event propagation // Click was on buttons - allow event propagation
mouse.accepted = false mouse.accepted = false
return return
@ -287,11 +284,9 @@ Item {
const deltaY = mouse.y - startPos.y const deltaY = mouse.y - startPos.y
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY) const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
//Logger.log("BarSectionEditor", "Position changed - distance:", distance.toFixed(2))
if (!dragStarted && distance > dragThreshold) { if (!dragStarted && distance > dragThreshold) {
dragStarted = true dragStarted = true
Logger.log("BarSectionEditor", "Drag started") //Logger.log("BarSectionEditor", "Drag started")
// Enable visual feedback // Enable visual feedback
if (draggedWidget) { if (draggedWidget) {
@ -309,9 +304,24 @@ Item {
onReleased: mouse => { onReleased: mouse => {
if (dragStarted && draggedWidget) { if (dragStarted && draggedWidget) {
// Find drop target using current mouse position // Find drop target using improved logic
let targetIndex = -1 let targetIndex = -1
let minDistance = Infinity 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++) { for (var i = 0; i < widgetModel.length; i++) {
if (i !== draggedIndex) { if (i !== draggedIndex) {
@ -319,7 +329,16 @@ Item {
if (widget && widget.widgetIndex !== undefined) { if (widget && widget.widgetIndex !== undefined) {
const centerX = widget.x + widget.width / 2 const centerX = widget.x + widget.width / 2
const centerY = widget.y + widget.height / 2 const centerY = widget.y + widget.height / 2
const distance = Math.sqrt(Math.pow(mouse.x - centerX, 2) + Math.pow(mouse.y - centerY, 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) { if (distance < minDistance) {
minDistance = distance minDistance = distance
@ -329,23 +348,65 @@ Item {
} }
} }
Logger.log("BarSectionEditor", "Drop target index:", targetIndex) // 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")
}
// Reset widget position and z-order // 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.x = 0
draggedWidget.y = 0 draggedWidget.y = 0
draggedWidget.z = 0 draggedWidget.z = 0
reorderWidget(sectionId, draggedIndex, finalTargetIndex)
if (targetIndex !== -1 && targetIndex !== draggedIndex) { } else {
reorderWidget(sectionId, draggedIndex, targetIndex) // 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) { } else if (draggedIndex !== -1 && !dragStarted) {
// This was a click without drag - simulate click on the widget
// Find the clicked widget and trigger appropriate action // This was a click without drag - could add click handling here if needed
const widget = draggedWidget
if (widget) {
// Could add click handling here if needed
}
} }
// Reset everything // Reset everything
@ -353,18 +414,19 @@ Item {
draggedIndex = -1 draggedIndex = -1
draggedWidget = null draggedWidget = null
preventStealing = false // Allow normal event propagation again preventStealing = false // Allow normal event propagation again
originalWidgetPos = Qt.point(0, 0) // Reset stored position
} }
// Handle case where mouse leaves the area during drag // Handle case where mouse leaves the area during drag
onExited: { onExited: {
if (dragStarted && draggedWidget) { if (dragStarted && draggedWidget) {
// Reset position but keep drag state until release // Restore original position when mouse leaves area
draggedWidget.x = 0 draggedWidget.x = originalWidgetPos.x
draggedWidget.y = 0 draggedWidget.y = originalWidgetPos.y
draggedWidget.z = 0 draggedWidget.z = 0
} }
} }
} }
} }
} }
} }

View file

@ -163,10 +163,10 @@ ColumnLayout {
sectionId: "left" sectionId: "left"
widgetModel: Settings.data.bar.widgets.left widgetModel: Settings.data.bar.widgets.left
availableWidgets: availableWidgets availableWidgets: availableWidgets
onAddWidget: (widgetId, section) => addWidgetToSection(widgetId, 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) onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsInSection(section, index, settings)
} }
// Center Section // Center Section
@ -175,10 +175,10 @@ ColumnLayout {
sectionId: "center" sectionId: "center"
widgetModel: Settings.data.bar.widgets.center widgetModel: Settings.data.bar.widgets.center
availableWidgets: availableWidgets availableWidgets: availableWidgets
onAddWidget: (widgetId, section) => addWidgetToSection(widgetId, 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) onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsInSection(section, index, settings)
} }
// Right Section // Right Section
@ -187,10 +187,10 @@ ColumnLayout {
sectionId: "right" sectionId: "right"
widgetModel: Settings.data.bar.widgets.right widgetModel: Settings.data.bar.widgets.right
availableWidgets: availableWidgets availableWidgets: availableWidgets
onAddWidget: (widgetId, section) => addWidgetToSection(widgetId, 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) onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsInSection(section, index, settings)
} }
} }
} }
@ -202,14 +202,9 @@ ColumnLayout {
} }
// --------------------------------- // ---------------------------------
// Helper functions // Signal functions
function updateWidgetSettingsInSection(section, index, settings) { // ---------------------------------
// Update the widget settings in the Settings data function _addWidgetToSection(widgetId, section) {
Settings.data.bar.widgets[section][index] = settings
//Logger.log("BarTab", `Updated widget settings for ${settings.id} in ${section} section`)
}
function addWidgetToSection(widgetId, section) {
var newWidget = { var newWidget = {
"id": widgetId "id": widgetId
} }
@ -226,7 +221,7 @@ ColumnLayout {
Settings.data.bar.widgets[section].push(newWidget) Settings.data.bar.widgets[section].push(newWidget)
} }
function removeWidgetFromSection(section, index) { function _removeWidgetFromSection(section, index) {
if (index >= 0 && index < Settings.data.bar.widgets[section].length) { if (index >= 0 && index < Settings.data.bar.widgets[section].length) {
var newArray = Settings.data.bar.widgets[section].slice() var newArray = Settings.data.bar.widgets[section].slice()
newArray.splice(index, 1) newArray.splice(index, 1)
@ -234,7 +229,7 @@ ColumnLayout {
} }
} }
function reorderWidgetInSection(section, fromIndex, toIndex) { function _reorderWidgetInSection(section, fromIndex, toIndex) {
if (fromIndex >= 0 && fromIndex < Settings.data.bar.widgets[section].length && toIndex >= 0 if (fromIndex >= 0 && fromIndex < Settings.data.bar.widgets[section].length && toIndex >= 0
&& toIndex < Settings.data.bar.widgets[section].length) { && toIndex < Settings.data.bar.widgets[section].length) {
@ -249,6 +244,12 @@ ColumnLayout {
} }
} }
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