From eca445fdf76ee59f7dae07f8833e2f00da26dd89 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 11 Jan 2012 11:00:36 +1000 Subject: [PATCH] Avoid creating unnecessary copies of TextEdit's text data. Delay rebuilding the text data from QTextDocument until it is actually requested rather than everytime the contents of the document change. Change-Id: Ibfdc9e9e0372010f0731fb02a223c8b59a67f2c3 Reviewed-by: Martin Jones --- src/quick/items/qquicktextcontrol.cpp | 2 +- src/quick/items/qquicktextedit.cpp | 41 ++++++++++++---------- src/quick/items/qquicktextedit_p.h | 2 +- src/quick/items/qquicktextedit_p_p.h | 2 ++ .../qtquick2/qquicktextedit/tst_qquicktextedit.cpp | 6 ++-- 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index 4f9475f..69a2a27 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -624,7 +624,7 @@ QQuickTextControl::QQuickTextControl(QTextDocument *doc, QObject *parent) : QObject(*new QQuickTextControlPrivate, parent) { Q_D(QQuickTextControl); - d->init(Qt::RichText, QString(), doc); + d->init(Qt::PlainText, QString(), doc); } QQuickTextControl::~QQuickTextControl() diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index e971ef7..f56a21b 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -127,13 +127,17 @@ QQuickTextEdit::QQuickTextEdit(QQuickItem *parent) QString QQuickTextEdit::text() const { Q_D(const QQuickTextEdit); - + if (!d->textCached) { + QQuickTextEditPrivate *d = const_cast(d_func()); #ifndef QT_NO_TEXTHTMLPARSER - if (d->richText) - return d->control->toHtml(); - else + if (d->richText) + d->text = d->control->toHtml(); + else #endif - return d->control->toPlainText(); + d->text = d->control->toPlainText(); + d->textCached = true; + } + return d->text; } /*! @@ -320,21 +324,21 @@ void QQuickTextEdit::setTextFormat(TextFormat format) Q_D(QQuickTextEdit); if (format == d->format) return; + bool wasRich = d->richText; - d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text)); + d->richText = format == RichText || (format == AutoText && (wasRich || Qt::mightBeRichText(text()))); +#ifndef QT_NO_TEXTHTMLPARSER if (wasRich && !d->richText) { - d->control->setPlainText(d->text); + d->control->setPlainText(!d->textCached ? d->control->toHtml() : d->text); updateSize(); } else if (!wasRich && d->richText) { -#ifndef QT_NO_TEXTHTMLPARSER - d->control->setHtml(d->text); -#else - d->control->setPlainText(d->text); -#endif + d->control->setHtml(!d->textCached ? d->control->toPlainText() : d->text); updateSize(); d->useImageFallback = qmlEnableImageCache(); } +#endif + d->format = format; d->control->setAcceptRichText(d->format != PlainText); emit textFormatChanged(d->format); @@ -553,7 +557,7 @@ bool QQuickTextEditPrivate::determineHorizontalAlignment() Q_Q(QQuickTextEdit); if (hAlignImplicit && q->isComponentComplete()) { bool alignToRight; - if (text.isEmpty()) { + if (document->isEmpty()) { const QString preeditText = control->textCursor().block().layout()->preeditAreaText(); alignToRight = preeditText.isEmpty() ? qApp->inputPanel()->inputDirection() == Qt::RightToLeft @@ -864,7 +868,7 @@ int QQuickTextEdit::cursorPosition() const void QQuickTextEdit::setCursorPosition(int pos) { Q_D(QQuickTextEdit); - if (pos < 0 || pos > d->text.length()) + if (pos < 0 || pos >= d->document->characterCount()) // characterCount includes the terminating null. return; QTextCursor cursor = d->control->textCursor(); if (cursor.position() == pos && cursor.anchor() == pos) @@ -1338,7 +1342,7 @@ void QQuickTextEdit::selectWord() void QQuickTextEdit::select(int start, int end) { Q_D(QQuickTextEdit); - if (start < 0 || end < 0 || start > d->text.length() || end > d->text.length()) + if (start < 0 || end < 0 || start >= d->document->characterCount() || end >= d->document->characterCount()) return; QTextCursor cursor = d->control->textCursor(); cursor.beginEditBlock(); @@ -1359,12 +1363,11 @@ void QQuickTextEdit::select(int start, int end) */ bool QQuickTextEdit::isRightToLeft(int start, int end) { - Q_D(QQuickTextEdit); if (start > end) { qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start."; return false; } else { - return d->text.mid(start, end - start).isRightToLeft(); + return getText(start, end).isRightToLeft(); } } @@ -1772,13 +1775,13 @@ void QQuickTextEditPrivate::init() void QQuickTextEdit::q_textChanged() { Q_D(QQuickTextEdit); - d->text = text(); + d->textCached = false; d->rightToLeftText = d->document->begin().layout()->engine()->isRightToLeft(); d->determineHorizontalAlignment(); d->updateDefaultTextOption(); updateSize(); updateTotalLines(); - emit textChanged(d->text); + emit textChanged(); } void QQuickTextEdit::moveCursorDelegate() diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h index f37b7cd..e127416 100644 --- a/src/quick/items/qquicktextedit_p.h +++ b/src/quick/items/qquicktextedit_p.h @@ -227,7 +227,7 @@ public: Q_INVOKABLE QString getFormattedText(int start, int end) const; Q_SIGNALS: - void textChanged(const QString &); + void textChanged(); void paintedSizeChanged(); void cursorPositionChanged(); void cursorRectangleChanged(); diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h index fe2172d..bf7edf5 100644 --- a/src/quick/items/qquicktextedit_p_p.h +++ b/src/quick/items/qquicktextedit_p_p.h @@ -74,6 +74,7 @@ public: documentDirty(true), dirty(false), richText(false), cursorVisible(false), focusOnPress(true), persistentSelection(true), requireImplicitWidth(false), selectByMouse(false), canPaste(false), canPasteValid(false), hAlignImplicit(true), rightToLeftText(false), useImageFallback(false), + textCached(false), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), cursorComponent(0), cursor(0), format(QQuickTextEdit::PlainText), document(0), wrapMode(QQuickTextEdit::NoWrap), mouseSelectionMode(QQuickTextEdit::SelectCharacters), @@ -114,6 +115,7 @@ public: bool hAlignImplicit:1; bool rightToLeftText:1; bool useImageFallback:1; + bool textCached:1; qreal textMargin; int lastSelectionStart; diff --git a/tests/auto/qtquick2/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/qtquick2/qquicktextedit/tst_qquicktextedit.cpp index 40dc438..ba63e04 100644 --- a/tests/auto/qtquick2/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/qtquick2/qquicktextedit/tst_qquicktextedit.cpp @@ -2077,7 +2077,7 @@ void tst_qquicktextedit::textInput() QVERIFY(edit->hasActiveFocus() == true); // test that input method event is committed and change signal is emitted - QSignalSpy spy(edit, SIGNAL(textChanged(QString))); + QSignalSpy spy(edit, SIGNAL(textChanged())); QInputMethodEvent event; event.setCommitString( "Hello world!", 0, 0); QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event); @@ -2804,7 +2804,7 @@ void tst_qquicktextedit::insert() QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged())); QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged())); QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged())); - QSignalSpy textSpy(textEdit, SIGNAL(textChanged(QString))); + QSignalSpy textSpy(textEdit, SIGNAL(textChanged())); QSignalSpy cursorPositionSpy(textEdit, SIGNAL(cursorPositionChanged())); textEdit->insert(insertPosition, insertText); @@ -3049,7 +3049,7 @@ void tst_qquicktextedit::remove() QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged())); QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged())); QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged())); - QSignalSpy textSpy(textEdit, SIGNAL(textChanged(QString))); + QSignalSpy textSpy(textEdit, SIGNAL(textChanged())); QSignalSpy cursorPositionSpy(textEdit, SIGNAL(cursorPositionChanged())); textEdit->remove(removeStart, removeEnd); -- 2.7.4