diff --git a/kde/gui/ChatBlockDelegate.qml b/kde/gui/ChatBlockDelegate.qml index d4f4676..caada67 100644 --- a/kde/gui/ChatBlockDelegate.qml +++ b/kde/gui/ChatBlockDelegate.qml @@ -193,52 +193,39 @@ Column { // Fast path: single TextEdit for the concatenated HTML. // Diagrams are handled separately via the segments list. // Editable for scratchpad use - changes are local only, not persisted. - Item { + TextEdit { + id: mainTextEdit width: root.width - height: mainTextEdit.height visible: !hasDiagrams() + text: root.blockRenderedHtml + textFormat: Text.RichText + selectByMouse: true + persistentSelection: true + wrapMode: TextEdit.Wrap + font.family: theme.fontFamily || Qt.application.font.family + font.pointSize: theme.fontSize > 0 ? theme.fontSize : 12 + selectionColor: theme.highlightColor + selectedTextColor: theme.highlightedTextColor - TextEdit { - id: mainTextEdit - width: parent.width - text: root.blockRenderedHtml - textFormat: Text.RichText - selectByMouse: true - persistentSelection: true - wrapMode: TextEdit.Wrap - font.family: theme.fontFamily || Qt.application.font.family - font.pointSize: theme.fontSize > 0 ? theme.fontSize : 12 - selectionColor: theme.highlightColor - selectedTextColor: theme.highlightedTextColor + // Double-click: bracket/quote pair or word select + TapHandler { + acceptedButtons: Qt.LeftButton + onDoubleTapped: function(eventPoint, button) { + var pos = eventPoint.position + if (!TextSelection.selectBracketPair(mainTextEdit, pos.x, pos.y)) { + TextSelection.selectWordAt(mainTextEdit, pos.x, pos.y) + } + } } // Acme-style mouse handling: B2=execute, B3=plumb // B1+B2=cut, B1+B3=paste (chord detection) - // Double-click on bracket: select text between matching pair MouseArea { anchors.fill: parent - acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton - z: 1 - - onDoubleClicked: function(mouse) { - if (mouse.button === Qt.LeftButton) { - // Delimiter under cursor: select the pair. - // Otherwise select the word ourselves (the overlay - // swallows the event, so TextEdit won't do it). - if (!TextSelection.selectBracketPair(mainTextEdit, mouse.x, mouse.y)) { - TextSelection.selectWordAt(mainTextEdit, mouse.x, mouse.y) - } - mouse.accepted = true - } - } + acceptedButtons: Qt.MiddleButton | Qt.RightButton + cursorShape: Qt.IBeamCursor onPressed: function(mouse) { - // Left button single clicks pass through to TextEdit for selection - if (mouse.button === Qt.LeftButton) { - mouse.accepted = false - return - } - if (mouse.buttons & Qt.LeftButton) { if (mouse.button === Qt.MiddleButton) { mainTextEdit.cut() @@ -261,7 +248,6 @@ Column { if (sel && sel.trim() !== "") { plumber.plumb(sel.trim(), sessionCwd()) } else { - // No selection - expand word and highlight it selectAndPlumb(mainTextEdit, mouse.x, mouse.y) } } @@ -401,29 +387,25 @@ Column { selectionColor: theme.highlightColor selectedTextColor: theme.highlightedTextColor - // Acme-style mouse handling with chord support - // B1+B2=cut, B1+B3=paste (chord detection) - // Double-click on bracket: select text between matching pair - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton - cursorShape: Qt.IBeamCursor - - onDoubleClicked: function(mouse) { - if (mouse.button === Qt.LeftButton) { - if (!TextSelection.selectBracketPair(textEdit, mouse.x, mouse.y)) { - TextSelection.selectWordAt(textEdit, mouse.x, mouse.y) - } - mouse.accepted = true + // Double-click: bracket/quote pair or word select + TapHandler { + acceptedButtons: Qt.LeftButton + onDoubleTapped: function(eventPoint, button) { + var pos = eventPoint.position + if (!TextSelection.selectBracketPair(textEdit, pos.x, pos.y)) { + TextSelection.selectWordAt(textEdit, pos.x, pos.y) } } + } + + // Acme-style mouse handling: B2=execute, B3=plumb + // B1+B2=cut, B1+B3=paste (chord detection) + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.MiddleButton | Qt.RightButton + cursorShape: Qt.IBeamCursor onPressed: function(mouse) { - if (mouse.button === Qt.LeftButton) { - mouse.accepted = false - return - } - if (mouse.buttons & Qt.LeftButton) { if (mouse.button === Qt.MiddleButton) { textEdit.cut() @@ -441,7 +423,6 @@ Column { } mouse.accepted = true } else if (mouse.button === Qt.RightButton) { - // B3: Plumb selection or word under cursor if (plumber.available()) { var sel = textEdit.selectedText if (sel && sel.trim() !== "") { diff --git a/kde/gui/ChatPane.qml b/kde/gui/ChatPane.qml index cb9a0fa..78c999d 100644 --- a/kde/gui/ChatPane.qml +++ b/kde/gui/ChatPane.qml @@ -467,11 +467,21 @@ Item { event.accepted = true } } + + // Double-click: bracket/quote pair or word select + TapHandler { + acceptedButtons: Qt.LeftButton + onDoubleTapped: function(eventPoint, button) { + var pos = eventPoint.position + if (!TextSelection.selectBracketPair(promptInput, pos.x, pos.y)) { + TextSelection.selectWordAt(promptInput, pos.x, pos.y) + } + } + } } } // Acme-style mouse chording overlay - // B1 double-click = bracket/quote pair or word select // B2 = execute selection // B3 = plumb selection / context menu // B1+B2 = cut (snarf) @@ -479,67 +489,43 @@ Item { MouseArea { id: chordArea anchors.fill: parent - acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton + acceptedButtons: Qt.MiddleButton | Qt.RightButton propagateComposedEvents: true cursorShape: Qt.IBeamCursor // Track if B1 (left) is currently held for chord detection property bool leftHeld: false - onDoubleClicked: function(mouse) { - if (mouse.button === Qt.LeftButton) { - // Map coordinates from chordArea to promptInput - var mappedPos = chordArea.mapToItem(promptInput, mouse.x, mouse.y) - if (!TextSelection.selectBracketPair(promptInput, mappedPos.x, mappedPos.y)) { - TextSelection.selectWordAt(promptInput, mappedPos.x, mappedPos.y) - } - mouse.accepted = true - } - } - onPressed: function(mouse) { - // Left button single clicks pass through to TextArea for selection - if (mouse.button === Qt.LeftButton) { - mouse.accepted = false - return - } - // Check if this is a chord (B1 already held) if (mouse.buttons & Qt.LeftButton) { leftHeld = true if (mouse.button === Qt.MiddleButton) { - // B1+B2 = cut promptInput.cut() mouse.accepted = true return } else if (mouse.button === Qt.RightButton) { - // B1+B3 = paste promptInput.paste() mouse.accepted = true return } } leftHeld = false - mouse.accepted = false // Let it propagate for non-chord + mouse.accepted = false } onClicked: function(mouse) { - // Only handle non-chord clicks if (leftHeld) { leftHeld = false return } if (mouse.button === Qt.MiddleButton) { - // B2: Execute selection as prompt var sel = promptInput.selectedText if (sel && sel.trim() !== "") { ollie.submit(sel.trim()) - } else { - // No selection - ignore } } else if (mouse.button === Qt.RightButton) { - // B3: Plumb selection or word under cursor if (!plumber.available()) return var sel = promptInput.selectedText if (sel && sel.trim() !== "") {