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 commitcc57a2e90f
, 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 commitcc57a2e90f
. Task-number: QTBUG-38536 Change-Id: I5fae12d646a4b2d2cc22b9f2d021e5dc8cfdda94 Reviewed-by: Paul Olav Tvete <paul.tvete@digia.com> Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com> Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
This commit is contained in:
parent
88756dc46f
commit
12eb3b51c4
@ -132,7 +132,7 @@ QTextCursorPrivate::AdjustResult QTextCursorPrivate::adjustPosition(int position
|
||||
|
||||
void QTextCursorPrivate::setX()
|
||||
{
|
||||
if (priv->isInEditBlock()) {
|
||||
if (priv->isInEditBlock() || priv->inContentsChange) {
|
||||
x = -1; // mark dirty
|
||||
return;
|
||||
}
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user