PyQt6 QTextEdit bug

Michael Rosenberg msrosenberg at vcu.edu
Wed May 31 01:07:31 BST 2023


Windows 11 / Python 3.11 / PyQt 6.5.0

I believe I've discovered a bug in the QTextEdit of PyQT6, specifically how
it exports the current text via toHTML() or toMarkdown() depending on how
text is added to the QTextEdit. Here is some sample code, as simplified as
I could manage it.

First, let's look at some code that works as expected:

from PyQt6.QtWidgets import QApplication, QWidget, QTextEdit, QVBoxLayout

import sys

app = QApplication(sys.argv)

window = QWidget()
layout = QVBoxLayout()
window.setLayout(layout)
text_edit = QTextEdit()
layout.addWidget(text_edit)

text_edit.append("<h1>Main Header</h1><h2>Secondary Header</h2><p>Test
paragraph.</p>")

print(text_edit.toHtml())
print()
print(text_edit.toMarkdown())
window.show()

app.exec()

Two things to note of this code when executed. First, the appearance of the
text displayed in the QTextEdit is correct and second, the printed html and
markdown are correct, namely:

<!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:9pt;
font-weight:400; font-style:normal;">
<h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px;
margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style="
font-size:xx-large; font-weight:700;">Main Header</span></h1>
<h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px;
margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style="
font-size:x-large; font-weight:700;">Secondary Header</span></h2>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px;
margin-right:0px; -qt-block-indent:0; text-indent:0px;">Test
paragraph.</p></body></html>

# Main Header

## Secondary Header

Test paragraph.

Now, let's make a minor modification to the above code. Instead of adding
the entire desired HTML text to the QTextEdit all at once, let's append
each line one after the other:

from PyQt6.QtWidgets import QApplication, QWidget, QTextEdit, QVBoxLayout

import sys

app = QApplication(sys.argv)

window = QWidget()
layout = QVBoxLayout()
window.setLayout(layout)
text_edit = QTextEdit()
layout.addWidget(text_edit)

text_edit.append("<h1>Main Header</h1>")
text_edit.append("<h2>Secondary Header</h2>")
text_edit.append("<p>Test paragraph.</p>")

print(text_edit.toHtml())
print(text_edit.toMarkdown())
window.show()

app.exec()

The appearance of the text in the QTextEdit window is exactly the same as
previously, but in the HTML and Markdown output, every line has been
converted to a first level header:

<!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:9pt;
font-weight:400; font-style:normal;">
<h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px;
margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style="
font-size:xx-large; font-weight:700;">Main Header</span></h1>
<h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px;
margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style="
font-size:x-large; font-weight:700;">Secondary Header</span></h1>
<h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px;
margin-right:0px; -qt-block-indent:0; text-indent:0px;">Test
paragraph.</h1></body></html>

# Main Header

# Secondary Header

# Test paragraph.

I'm pretty sure this behavior is wrong, particularly as the visual output
in the GUI is identical in both cases (i.e., displaying the text correctly
as a level 1 header, level 2 header, and general text paragraph). I suppose
this could be a Qt6 bug and not PyQt6, but I don't use C so cannot directly
test whether this behavior is unique to PyQt or general to Qt.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Michael S. Rosenberg, PhD
Director, Center for Biological Data Science
Virginia Commonwealth University
msrosenberg at vcu.edu
https://cbds.vcu.edu
https://www.rosenberglab.net
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*I often send emails outside standard work hours; *
*please do not feel obligated to respond outside of your**s.*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20230530/00883fe2/attachment.htm>


More information about the PyQt mailing list