Search code examples
qmlqt6textedit

How to customize the line height of TextEdit


I've got two requirements for a custom Text element in QML:

1. Select and copy text

I'd like to display text and allow the user to copy it by selecting it with the mouse and copy via CTRL+C.

-> This works out-of-the-box by using a TextEdit/TextArea element with "readOnly" and "selectByMouse" both set to true.

2. Adjust text's line height

I'd like to be able to adjust the text's line height.

-> Seems NOT possible with TextEdit/TextArea.

-> Can be adjusted in a normal Text element by setting "lineHeight". But Text cannot be selected and copied by the user.


Is there a way to adjust either of the elements to perform the missing task?

What is the typical solution for this? Seems to be a simple enough requirement but I cannot find it discussed anywhere.


Edit:

Going by SMR's comment, I checked out the approach of setting it to RichText mode and modifying the content to set the line height. This is the richtext string of a multiline text:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
p, li { white-space: pre-wrap; }
hr { height: 1px; border-width: 0; }
li.unchecked::marker { content: "\2610"; }
li.checked::marker { content: "\2612"; }
</style></head><body style=" font-family:'Segoe UI'; font-size:15px; font-weight:400; font-style:normal;">
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Line one Line two Line three</p></body></html>

I extended the paragraphs' style by line-height inside of "Component.onCompleted()":

text.replace("text-indent:0px;", "text-indent:0px; line-height:" + desiredLineHeightInPx + "px;")

This works, but also puts whitespace above the first line. I tried to counteract that by setting a negative top margin, with no success:

var marginToCounteractLineHeight = desiredLineHeightInPx / 2
newText = text.replace("<p style=\" margin-top:0px;", "<p style=\" margin-top:-" + marginToCounteractLineHeight +"px;")

For now, I opted to use the Text element and put a MouseArea on top to transfer the text to an invisible TextEdit, on which I then select all and copy to clipboard (followed by an animation to inform the user):

    MouseArea {
        acceptedButtons: Qt.LeftButton
        onClicked {
             // Copy to TextEdit
             myInvisibleTextEdit.text = myText.text
             myInvisibleTextEdit.selectAll()
             myInvisibleTextEdit.copy()
             copyAnimation.start()
        }
    }

Solution

  • [REWRITE]

    Your TextEdit should already implement "CTRL+C" keyboard shortcut. If it's not working, you can declare an "CTRL+C" action for it. As to controlling TextEdit line height, you can set your textFormat: Text.RichText and supply an HTML body with style set to line-height:2

    TextEdit {
        id: textEdit
        text: `<body style="line-height:2">Hello World<br>
    Mary had a little lamb</body>`
        textFormat: Text.RichText
        font.pointSize: 12
        Action {
            text: "copy"
            shortcut: "Ctrl+C"
            onTriggered: textEdit.copy()
        }
        Component.onCompleted: select(3, 10)
    }
    

    You can Try it Online!