From 12eb3b51c4c8c7ce90302d2c356fea09f2c42a5c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 29 Apr 2014 13:39:23 +0200 Subject: Fix incorrect repaints with plain text edit The plain text edit's smart repaint logic in QPlainTextDocumentLayout::documentChanged assumes that during a change inside just one block, the block is in the state before the edit and a call to layoutBlock() is going to bring it up-to-date. Then only a comparison of the bounding rect - before and after - is going to allow for smart repaints. The assumption of the layout being in the same state as before the edit got broken by commit cc57a2e90f18a39ce3c74b6ad0db9a64aa135ddf, which introduced code to use a QTextCursor within a slot connected to QTextDocument's contentsChange signal. The usage of the QTextCursor there ends up updating the layout of the block ahead of time, breaking the assumption and therefore the optimization, in the sense that during changes in the preedit that cause a change of height / line count, the old bounding rect in QPlainTextDocumentLayout::documentChanged and the new bounding rect will be the same. This causes a repaint of only the edited block, missing repaints of the following blocks, even though the line count effectively changed. So what's causing QTextCursor to mess with the layout is the attempt of updating the vertical movement x property. This patch inhibits the update, marking it as dirty for initialization later. This means that slots connected to this low-level signal cannot rely on the cursor's visual x position, but that doesn't seem useful anyway and isn't required for commit cc57a2e90f18a39ce3c74b6ad0db9a64aa135ddf. Task-number: QTBUG-38536 Change-Id: I5fae12d646a4b2d2cc22b9f2d021e5dc8cfdda94 Reviewed-by: Paul Olav Tvete Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Konstantin Ritt --- .../gui/text/qtextdocument/tst_qtextdocument.cpp | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'tests') diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp index 53aef40df0..59c951332e 100644 --- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp +++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp @@ -192,6 +192,8 @@ private slots: void QTBUG28998_linkColor(); + void textCursorUsageWithinContentsChange(); + private: void backgroundImage_checkExpectedHtml(const QTextDocument &doc); @@ -3021,5 +3023,50 @@ void tst_QTextDocument::QTBUG28998_linkColor() QCOMPARE(format.foreground(), pal.link()); } +class ContentsChangeHandler : public QObject +{ + Q_OBJECT +public: + ContentsChangeHandler(QTextDocument *doc) + : verticalMovementX(-1) + , doc(doc) + { + connect(doc, SIGNAL(contentsChange(int,int,int)), + this, SLOT(saveModifiedText(int, int, int))); + } + +private slots: + void saveModifiedText(int from, int /*charsRemoved*/, int charsAdded) + { + QTextCursor tmp(doc); + tmp.setPosition(from); + tmp.setPosition(from + charsAdded, QTextCursor::KeepAnchor); + text = tmp.selectedText(); + verticalMovementX = tmp.verticalMovementX(); + } + +public: + QString text; + int verticalMovementX; +private: + QTextDocument *doc; +}; + +void tst_QTextDocument::textCursorUsageWithinContentsChange() +{ + // force creation of layout + doc->documentLayout(); + + QTextCursor cursor(doc); + cursor.insertText("initial text"); + + ContentsChangeHandler handler(doc); + + cursor.insertText("new text"); + + QCOMPARE(handler.text, QString("new text")); + QCOMPARE(handler.verticalMovementX, -1); +} + QTEST_MAIN(tst_QTextDocument) #include "tst_qtextdocument.moc" -- cgit v1.2.3 From 7eae50a52d63b7f0434fdb75fc09b0901a0140cc Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 29 Apr 2014 09:06:08 +0200 Subject: Fix assert on justification of QTextLine with only spaces In the justification code, we unconditionally subtracted one from the line_length, but then compared the result to 0 afterwards, so we did not support when the line_length is 0 initially, which can happen if it only consists of spaces (in which case trailingSpaces will be non-zero and line_length will be zero.) The fix is to bail out for both strings of length 1 and length 0. [ChangeLog][Text] Fixed an assert when justifying a QTextLine which only contains spaces. Task-number: QTBUG-38520 Change-Id: Ib04993f47eb2f9f7fc49c4a5400f18f9682a72f2 Reviewed-by: Simon Hausmann Reviewed-by: Konstantin Ritt Reviewed-by: Lars Knoll --- tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'tests') diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp index d0482d77e2..26eaec0470 100644 --- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp @@ -122,6 +122,7 @@ private slots: void boundingRectForUnsetLineWidth(); void boundingRectForSetLineWidth(); void glyphLessItems(); + void justifyTrailingSpaces(); // QTextLine stuff void setNumColumnsWrapAtWordBoundaryOrAnywhere(); @@ -1996,5 +1997,19 @@ void tst_QTextLayout::cursorInNonStopChars() QVERIFY(line.cursorToX(2) == line.cursorToX(3)); } +void tst_QTextLayout::justifyTrailingSpaces() +{ + QTextLayout layout(QStringLiteral(" t"), testFont); + layout.setTextOption(QTextOption(Qt::AlignJustify)); + layout.beginLayout(); + + QTextLine line = layout.createLine(); + line.setLineWidth(5); + + layout.endLayout(); + + QVERIFY(qFuzzyIsNull(layout.lineAt(0).cursorToX(0))); +} + QTEST_MAIN(tst_QTextLayout) #include "tst_qtextlayout.moc" -- cgit v1.2.3