QTextCursor and html tables
-
I have a very strange problem with an existing Qt5.10 Applciation and QTextCursor.
In the application, we have a text input area where the user can paste text from antwhere (word doc, web pages .. etc).
We also need to sanatize this pasted text before the appliction can accept it.
Part of this sanatization requires us to use a cursor to go through the document - this is required. But certain users of the application have reported hangs in the app when certain rich text gets pasted. We have narrowed the text that causes the to an odd sequence - and empty table followed by text.
Let me give an example
#include "qtguiapplication1.h" #include <QTextEdit> #include <QTextDocument> #include <QTextDocumentFragment> #include <QTextCursor> QtGuiApplication1::QtGuiApplication1(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); QTextEdit textEdit{}; const std::string sourceMimeDataInHtmlFormat = R"( <html> <body> <table> <tr> <td> </td> </tr> </table> foo </body> </html> )"; QString testHtml = QString::fromStdString(sourceMimeDataInHtmlFormat); textEdit.insertHtml(testHtml); QTextCursor cursor{}; while ((cursor = textEdit.document()->find("foo")) != QTextCursor{}) { cursor.select(QTextCursor::BlockUnderCursor); cursor.removeSelectedText(); } }
So as you can see,
sourceMimeDataInHtmlFormat
is a simple table with an empty cell followed by the word "foo"
The simple while loop gets stuck in an infinite loop with the above code.If the table cell contains text .... any text, the problem doesn't happen! While loop behaves as expected.
Any idea what could be the problem here?
-
Hi
It seems it's not able to select as its not a block for it.
So BlockUnderCursor fails to select the text and it can find it over and over.
(checked with qDebug() << "sel:" << cursor.selectedText(); )so if you do LineUnderCursor instead.
QTextCursor cursor{};
while ((cursor = ui->textEdit->document()->find("foo")) != QTextCursor{})
{
cursor.select(QTextCursor::LineUnderCursor);
cursor.removeSelectedText();
qDebug() << "this" << cursor.selectedText();
}it works.
So it seems the empty table somehow makes BlockUnderCursor fail
but im not sure why exactly. -
Hi
It seems it's not able to select as its not a block for it.
So BlockUnderCursor fails to select the text and it can find it over and over.
(checked with qDebug() << "sel:" << cursor.selectedText(); )so if you do LineUnderCursor instead.
QTextCursor cursor{};
while ((cursor = ui->textEdit->document()->find("foo")) != QTextCursor{})
{
cursor.select(QTextCursor::LineUnderCursor);
cursor.removeSelectedText();
qDebug() << "this" << cursor.selectedText();
}it works.
So it seems the empty table somehow makes BlockUnderCursor fail
but im not sure why exactly.Thanks @mrjj - that has somewhat solved it.
It seems that
cursor.select(QTextCursor::LineUnderCursor)
behaves slightly different tocursor.select(QTextCursor::BlockUnderCursor)
for certain input types.
But it certainly helps me. So thanks again.This is what I have now:
QTextEdit textEdit{}; const std::string sourceMimeDataInHtmlFormat = R"( <html> <body> <table> <tr> <td> </td> </tr> </table> <p>foo</p> <p>bar</p> <p>foo</p> <p>bar</p> </body> </html> )"; QString testHtml = QString::fromStdString(sourceMimeDataInHtmlFormat); textEdit.insertHtml(testHtml); QTextCursor cursor{}; QTextCursor::SelectionType selectionType = QTextCursor::BlockUnderCursor; while ((cursor = textEdit.document()->find("foo")) != QTextCursor{}) { cursor.select(selectionType); if (cursor.selectedText().isEmpty()) { // We can get stuck in this while loop forever for certain types of HTML. // Change the selection type for the next time through the loop so we are sure to select the text selectionType = QTextCursor::LineUnderCursor; } else { selectionType = QTextCursor::BlockUnderCursor; } cursor.removeSelectedText(); } ```
-
Thanks @mrjj - that has somewhat solved it.
It seems that
cursor.select(QTextCursor::LineUnderCursor)
behaves slightly different tocursor.select(QTextCursor::BlockUnderCursor)
for certain input types.
But it certainly helps me. So thanks again.This is what I have now:
QTextEdit textEdit{}; const std::string sourceMimeDataInHtmlFormat = R"( <html> <body> <table> <tr> <td> </td> </tr> </table> <p>foo</p> <p>bar</p> <p>foo</p> <p>bar</p> </body> </html> )"; QString testHtml = QString::fromStdString(sourceMimeDataInHtmlFormat); textEdit.insertHtml(testHtml); QTextCursor cursor{}; QTextCursor::SelectionType selectionType = QTextCursor::BlockUnderCursor; while ((cursor = textEdit.document()->find("foo")) != QTextCursor{}) { cursor.select(selectionType); if (cursor.selectedText().isEmpty()) { // We can get stuck in this while loop forever for certain types of HTML. // Change the selection type for the next time through the loop so we are sure to select the text selectionType = QTextCursor::LineUnderCursor; } else { selectionType = QTextCursor::BlockUnderCursor; } cursor.removeSelectedText(); } ```