DebugConsole output: add text selection & copying
This commit is contained in:
parent
4cc4229728
commit
192112ab4e
|
@ -4,6 +4,7 @@
|
||||||
import QtQuick 2.12
|
import QtQuick 2.12
|
||||||
import QtQuick.Window 2.12
|
import QtQuick.Window 2.12
|
||||||
import QtQuick.Layouts 1.12
|
import QtQuick.Layouts 1.12
|
||||||
|
import Clipboard 0.1
|
||||||
import "Base"
|
import "Base"
|
||||||
import "ShortcutBundles"
|
import "ShortcutBundles"
|
||||||
|
|
||||||
|
@ -21,6 +22,9 @@ HDrawer {
|
||||||
property int maxHistoryLength: 4096
|
property int maxHistoryLength: 4096
|
||||||
property var textBeforeHistoryNavigation: null // null or string
|
property var textBeforeHistoryNavigation: null // null or string
|
||||||
|
|
||||||
|
property int selectedOutputDelegateIndex: -1
|
||||||
|
property string selectedOutputText: ""
|
||||||
|
|
||||||
property string help: qsTr(
|
property string help: qsTr(
|
||||||
`Javascript debugging console
|
`Javascript debugging console
|
||||||
|
|
||||||
|
@ -44,7 +48,7 @@ HDrawer {
|
||||||
property bool doUselessThing: false
|
property bool doUselessThing: false
|
||||||
property real baseGIFSpeed: 1.0
|
property real baseGIFSpeed: 1.0
|
||||||
|
|
||||||
readonly property alias commandsView: commandsView
|
readonly property alias outputList: outputList
|
||||||
|
|
||||||
function toggle(targetItem=null, js="", addToHistory=false) {
|
function toggle(targetItem=null, js="", addToHistory=false) {
|
||||||
if (debugConsole.visible) {
|
if (debugConsole.visible) {
|
||||||
|
@ -101,7 +105,7 @@ HDrawer {
|
||||||
output = err.toString()
|
output = err.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
commandsView.model.insert(0, { input, output, error })
|
outputList.model.insert(0, { input, output, error })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,7 +120,7 @@ HDrawer {
|
||||||
position: 0
|
position: 0
|
||||||
|
|
||||||
onTargetChanged: {
|
onTargetChanged: {
|
||||||
commandsView.model.insert(0, {
|
outputList.model.insert(0, {
|
||||||
input: "t = " + String(target),
|
input: "t = " + String(target),
|
||||||
output: "",
|
output: "",
|
||||||
error: false,
|
error: false,
|
||||||
|
@ -158,7 +162,7 @@ HDrawer {
|
||||||
anchors.leftMargin: 1
|
anchors.leftMargin: 1
|
||||||
|
|
||||||
HListView {
|
HListView {
|
||||||
id: commandsView
|
id: outputList
|
||||||
spacing: theme.spacing
|
spacing: theme.spacing
|
||||||
topMargin: theme.spacing
|
topMargin: theme.spacing
|
||||||
bottomMargin: topMargin
|
bottomMargin: topMargin
|
||||||
|
@ -172,35 +176,86 @@ HDrawer {
|
||||||
|
|
||||||
model: ListModel {}
|
model: ListModel {}
|
||||||
|
|
||||||
delegate: HColumnLayout {
|
delegate: HSelectableLabel {
|
||||||
width: commandsView.width -
|
id: delegate
|
||||||
commandsView.leftMargin - commandsView.rightMargin
|
width: outputList.width -
|
||||||
|
outputList.leftMargin - outputList.rightMargin
|
||||||
|
|
||||||
HLabel {
|
text:
|
||||||
text: "> " + model.input.replace(/\n/g, "\n> ")
|
`<div style="white-space: pre-wrap">` +
|
||||||
wrapMode: HLabel.Wrap
|
`<font color="${theme.chat.message.quote}">` +
|
||||||
color: theme.chat.message.quote
|
utils.plain2Html(model.input) +
|
||||||
font.family: theme.fontFamily.mono
|
"</font>" +
|
||||||
visible: Boolean(model.input)
|
(
|
||||||
|
model.output ?
|
||||||
|
"<br>" + utils.plain2Html(model.output) :
|
||||||
|
""
|
||||||
|
) +
|
||||||
|
"</div>"
|
||||||
|
|
||||||
Layout.fillWidth: true
|
textFormat: HSelectableLabel.RichText
|
||||||
|
wrapMode: HLabel.Wrap
|
||||||
|
color: model.error ? theme.colors.errorText : theme.colors.text
|
||||||
|
font.family: theme.fontFamily.mono
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
onSelectedTextChanged: if (selectedText) {
|
||||||
|
selectedOutputDelegateIndex = model.index
|
||||||
|
selectedOutputText = selectedText
|
||||||
|
} else if (selectedOutputDelegateIndex === model.index) {
|
||||||
|
selectedOutputDelegateIndex = -1
|
||||||
|
selectedOutputText = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
HLabel {
|
Connections {
|
||||||
text: model.output
|
target: debugConsole
|
||||||
wrapMode: HLabel.Wrap
|
onSelectedOutputDelegateIndexChanged: {
|
||||||
color: model.error ?
|
if (selectedOutputDelegateIndex !== model.index)
|
||||||
theme.colors.errorText : theme.colors.text
|
delegate.deselect()
|
||||||
font.family: theme.fontFamily.mono
|
}
|
||||||
visible: Boolean(model.output)
|
}
|
||||||
|
|
||||||
Layout.fillWidth: true
|
TapHandler {
|
||||||
|
acceptedButtons: Qt.RightButton
|
||||||
|
gesturePolicy: TapHandler.ReleaseWithinBounds
|
||||||
|
acceptedPointerTypes:
|
||||||
|
PointerDevice.GenericPointer | PointerDevice.Pen
|
||||||
|
|
||||||
|
onTapped: menu.popup()
|
||||||
|
}
|
||||||
|
|
||||||
|
TapHandler {
|
||||||
|
acceptedPointerTypes:
|
||||||
|
PointerDevice.Finger | PointerDevice.Pen
|
||||||
|
|
||||||
|
onLongPressed: menu.popup()
|
||||||
|
}
|
||||||
|
|
||||||
|
HMenu {
|
||||||
|
id: menu
|
||||||
|
implicitWidth: Math.min(window.width, 150)
|
||||||
|
z: 10000
|
||||||
|
|
||||||
|
HMenuItem {
|
||||||
|
icon.name: "copy-text"
|
||||||
|
text: qsTr("Copy")
|
||||||
|
onTriggered: {
|
||||||
|
if (delegate.selectedText) {
|
||||||
|
delegate.copy()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delegate.selectAll()
|
||||||
|
delegate.copy()
|
||||||
|
delegate.deselect()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FlickShortcuts {
|
FlickShortcuts {
|
||||||
active: debugConsole.visible
|
active: debugConsole.visible
|
||||||
flickable: commandsView
|
flickable: outputList
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -260,6 +315,17 @@ HDrawer {
|
||||||
|
|
||||||
Keys.onEscapePressed: debugConsole.close()
|
Keys.onEscapePressed: debugConsole.close()
|
||||||
|
|
||||||
|
Keys.onPressed: ev => {
|
||||||
|
if (
|
||||||
|
ev.matches(StandardKey.Copy) &&
|
||||||
|
! inputArea.selectedText &&
|
||||||
|
selectedOutputText
|
||||||
|
) {
|
||||||
|
ev.accepted = true
|
||||||
|
Clipboard.text = selectedOutputText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,6 +196,13 @@ QtObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function plain2Html(text) {
|
||||||
|
// Escape html, convert `\n` into `<br>` tags and `\t` into four spaces
|
||||||
|
return escapeHtml(text).replace(/\n/g, "<br>")
|
||||||
|
.replace(/\t/g, " " * 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function htmlColorize(text, color) {
|
function htmlColorize(text, color) {
|
||||||
return `<font color="${color}">${text}</font>`
|
return `<font color="${color}">${text}</font>`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user