Fix drag start properly; lazy-load body editor; stop make reconfigure
Three fixes: Drag: the previous attempt removed Drag.active=true before startDrag(), but startDrag() *requires* an active drag — so it errored "startDrag() drag must be active" and no drag began (the no-drop cursor). Use the idiomatic automatic-drag pattern instead: bind the proxy's Drag.active to the grip MouseArea's drag.active and set drag.target to the proxy; with dragType Automatic, Qt starts the OS drag itself when the threshold is crossed — no startDrag() call. Lifecycle is driven off Drag.onActiveChanged / onReleased. Body editor: wrap it in a Loader (active: editingBody) so the TextArea is only instantiated when the user opens the editor, not once per row. This avoids the per-row Breeze "Unable to assign TextArea to QQuickTextInput" instantiation error and is lighter. Makefile: the ui target ran `cmake -S ui -B ui/build` on every invocation, reconfiguring the tree each time (which could leave the QML cache stale relative to edited .qml). Configure only when ui/build/Makefile is absent; otherwise just `cmake --build`. GUI builds clean.
This commit is contained in:
parent
b2efe6ea27
commit
4c2250ba3c
4
Makefile
4
Makefile
|
|
@ -24,7 +24,9 @@ debug:
|
||||||
|
|
||||||
ui:
|
ui:
|
||||||
ifeq ($(HAS_QT6_QML),yes)
|
ifeq ($(HAS_QT6_QML),yes)
|
||||||
cmake -S ui -B ui/build -DCMAKE_BUILD_TYPE=Release
|
@if [ ! -f ui/build/Makefile ]; then \
|
||||||
|
cmake -S ui -B ui/build -DCMAKE_BUILD_TYPE=Release; \
|
||||||
|
fi
|
||||||
cmake --build ui/build -j
|
cmake --build ui/build -j
|
||||||
else
|
else
|
||||||
@echo "Skipping UI build: Qt6 Qml not found"
|
@echo "Skipping UI build: Qt6 Qml not found"
|
||||||
|
|
|
||||||
|
|
@ -554,6 +554,7 @@ ListView {
|
||||||
Layout.preferredHeight: outline.baseFontSize + 8
|
Layout.preferredHeight: outline.baseFontSize + 8
|
||||||
radius: 3
|
radius: 3
|
||||||
readonly property bool active: gripMouse.pressed
|
readonly property bool active: gripMouse.pressed
|
||||||
|
|| gripMouse.drag.active
|
||||||
color: active ? theme.highlightColor
|
color: active ? theme.highlightColor
|
||||||
: (gripMouse.containsMouse ? theme.alternateBaseColor : "transparent")
|
: (gripMouse.containsMouse ? theme.alternateBaseColor : "transparent")
|
||||||
|
|
||||||
|
|
@ -566,16 +567,29 @@ ListView {
|
||||||
opacity: gripMouse.containsMouse || gripLabel.active ? 1.0 : 0.4
|
opacity: gripMouse.containsMouse || gripLabel.active ? 1.0 : 0.4
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invisible proxy that carries the drag payload. Starting a
|
// Invisible proxy that carries the drag payload. Binding
|
||||||
// Qt Automatic drag on it hands the gesture to the window's
|
// Drag.active to the MouseArea's drag.active and using
|
||||||
// drag manager, independent of this (destructible) delegate.
|
// dragType Automatic makes Qt start an OS-level drag by
|
||||||
|
// itself (no startDrag() call) when the drag threshold is
|
||||||
|
// crossed. The OS drag is scene/window-level, so it is
|
||||||
|
// delivered to DropAreas and survives the view springing to
|
||||||
|
// another file mid-drag.
|
||||||
Item {
|
Item {
|
||||||
id: dragProxy
|
id: dragProxy
|
||||||
anchors.fill: parent
|
visible: false
|
||||||
|
width: 1; height: 1
|
||||||
|
Drag.active: gripMouse.drag.active
|
||||||
Drag.dragType: Drag.Automatic
|
Drag.dragType: Drag.Automatic
|
||||||
Drag.supportedActions: Qt.MoveAction
|
Drag.supportedActions: Qt.MoveAction
|
||||||
Drag.proposedAction: Qt.MoveAction
|
Drag.proposedAction: Qt.MoveAction
|
||||||
Drag.keys: ["ork-section"]
|
Drag.keys: ["ork-section"]
|
||||||
|
Drag.onActiveChanged: {
|
||||||
|
if (!Drag.active && outline.dragActive) {
|
||||||
|
// Drag ended. A drop on the outline committed via
|
||||||
|
// the DropArea; otherwise clean up here.
|
||||||
|
outline.commitDrop()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|
@ -585,30 +599,26 @@ ListView {
|
||||||
cursorShape: gripLabel.active ? Qt.ClosedHandCursor
|
cursorShape: gripLabel.active ? Qt.ClosedHandCursor
|
||||||
: Qt.OpenHandCursor
|
: Qt.OpenHandCursor
|
||||||
preventStealing: true
|
preventStealing: true
|
||||||
property bool started: false
|
// Dragging this (invisible, unanchored) proxy provides
|
||||||
onPressed: started = false
|
// the drag.active signal the proxy's Drag binds to.
|
||||||
onPositionChanged: (mouse) => {
|
drag.target: dragProxy
|
||||||
if (started) return
|
drag.threshold: 4
|
||||||
started = true
|
onPressed: {
|
||||||
// Record the drag source in the model (survives a
|
// Record the drag source and payload up front; the
|
||||||
// later file switch) and begin the OS drag. For a
|
// Automatic drag auto-starts once the threshold is
|
||||||
// Drag.Automatic drag, startDrag() activates it —
|
// crossed.
|
||||||
// do NOT set Drag.active manually first.
|
|
||||||
docModel.beginDrag(del.index)
|
docModel.beginDrag(del.index)
|
||||||
outline.dragActive = true
|
outline.dragActive = true
|
||||||
dragProxy.Drag.mimeData = {
|
dragProxy.Drag.mimeData = {
|
||||||
"text/plain": docModel.dragSourceDoc()
|
"text/plain": docModel.dragSourceDoc()
|
||||||
+ "\t" + docModel.dragSourceId()
|
+ "\t" + docModel.dragSourceId()
|
||||||
}
|
}
|
||||||
dragProxy.Drag.startDrag()
|
|
||||||
}
|
}
|
||||||
onReleased: {
|
onReleased: {
|
||||||
// startDrag() blocks until the OS drag finishes, so
|
// A plain click (no drag) never activated the drag:
|
||||||
// by here the drop (if any) has been handled by a
|
// clear the state we set in onPressed.
|
||||||
// DropArea. Clear any drag state that a drop didn't.
|
if (outline.dragActive && !drag.active)
|
||||||
if (outline.dragActive)
|
|
||||||
outline.commitDrop()
|
outline.commitDrop()
|
||||||
started = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1291,20 +1301,21 @@ ListView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inline body editor. Replaces the rendered segments while
|
// Inline body editor. Loaded lazily (only when the user opens
|
||||||
// editing. Seeded with the raw body text; a toolbar inserts a
|
// the editor) so the TextArea is not instantiated per row —
|
||||||
// timestamp at the cursor; Save writes via setBody (one 9P
|
// avoiding a Breeze style instantiation error and saving memory.
|
||||||
// write, server reparses), Cancel/Escape discards.
|
Loader {
|
||||||
ColumnLayout {
|
id: bodyEditLoader
|
||||||
id: bodyEditColumn
|
active: del.editingBody
|
||||||
visible: del.editingBody
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
spacing: 4
|
sourceComponent: ColumnLayout {
|
||||||
|
id: bodyEditColumn
|
||||||
|
spacing: 4
|
||||||
|
|
||||||
function saveBody() {
|
function saveBody() {
|
||||||
docModel.setBody(del.index, bodyEditor.text)
|
docModel.setBody(del.index, bodyEditor.text)
|
||||||
del.editingBody = false
|
del.editingBody = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bordered scroll frame holding the editor. Uses the
|
// Bordered scroll frame holding the editor. Uses the
|
||||||
// Flickable + TextArea.flickable idiom (not ScrollView),
|
// Flickable + TextArea.flickable idiom (not ScrollView),
|
||||||
|
|
@ -1388,6 +1399,7 @@ ListView {
|
||||||
onClicked: bodyEditColumn.saveBody()
|
onClicked: bodyEditColumn.saveBody()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue