remove finishEdit() call, fix double textChanged on delete

There is a known bug where duplicate textChanged signals are
triggered on backspace/delete. The bug has been seen on Windows,
Mac, and Linux. Gabi showed that this duplicate signal is caused by
two calls to finishEdit(), one direct and one nested,
in QTextCursorPrivate::remove().

To attempt a fix, I removed the direct call and do not change the
nested call. This change only affects text buffers when they
receive remove commands.

This seems to fix the problem, shown by the test project
uploaded to the bug tracker and also in countTextChangedOnRemove
in tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp.

Further analysis of finishEdit() and QTextCursorPrivate::remove():
finishEdit() calls signals contentsChanged() as long as a valid block
is being edited. Remove() calls finishEdit for all non-table edits,
so finishEdit will be called for most cases.

Methods in the public QTextCursor all seem to set adjusted_anchor
and anchor, none reading it directly, so I haven't found publicly
observable consequences to "adjusted_anchor = anchor = position;".

Task-number: QTBUG-15003
Change-Id: Ic35f25ee81c4007867b47cd8be03c146a673f86d
Reviewed-by: Graham Coleman <ravelite@gmail.com>
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
This commit is contained in:
Graham Coleman 2013-11-16 08:26:53 +01:00 committed by The Qt Project
parent cd91d8ad02
commit 92b2275c3d
2 changed files with 15 additions and 1 deletions

View File

@ -174,7 +174,6 @@ void QTextCursorPrivate::remove()
} else {
priv->remove(pos1, pos2-pos1, op);
adjusted_anchor = anchor = position;
priv->finishEdit();
}
}

View File

@ -203,6 +203,8 @@ private slots:
void highlightLongLine();
void countTextChangedOnRemove();
private:
void createSelection();
int blockCount() const;
@ -2499,6 +2501,19 @@ void tst_QTextEdit::highlightLongLine()
QVERIFY(true);
}
//check for bug 15003, are there multiple textChanged() signals on remove?
void tst_QTextEdit::countTextChangedOnRemove()
{
QTextEdit edit;
edit.insertPlainText("Hello");
QSignalSpy spy(&edit, SIGNAL(textChanged()));
QKeyEvent event(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
QCoreApplication::instance()->notify(&edit, &event);
QCOMPARE(spy.count(), 1);
}
QTEST_MAIN(tst_QTextEdit)
#include "tst_qtextedit.moc"