From 4598939ee2fad1238609ca43717199fd4e98c75f Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 5 Jul 2012 10:18:43 +1000 Subject: [PATCH] Speed up TextEdit construction time. Defer setting content on the QTextDocument until componentComplete() to avoid unnecessary layouts and move one time setup for the text document from setContent to the constructor. Reduces the construction time of a TextEdit with RichText textFormat by about a third. Change-Id: Idde0772063bf769cde984efddd68589c55a7431a Reviewed-by: Martin Jones --- src/quick/items/qquicktextcontrol.cpp | 77 ++++++++-------------- src/quick/items/qquicktextcontrol_p.h | 2 - src/quick/items/qquicktextcontrol_p_p.h | 6 +- src/quick/items/qquicktextedit.cpp | 26 ++++++-- src/quick/items/qquicktextedit_p_p.h | 2 +- .../quick/qquicktextedit/tst_qquicktextedit.cpp | 8 ++- 6 files changed, 52 insertions(+), 69 deletions(-) diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index 23bf2a7..d2ff4dc 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -71,6 +71,8 @@ #include #include +#include + // ### these should come from QStyleHints const int textCursorWidth = 1; const bool fullWidthSelection = true; @@ -279,16 +281,7 @@ void QQuickTextControlPrivate::updateCurrentCharFormat() cursorRectangleChanged = true; } -void QQuickTextControlPrivate::init(Qt::TextFormat format, const QString &text, QTextDocument *document) -{ - Q_Q(QQuickTextControl); - setContent(format, text, document); - - doc->setUndoRedoEnabled(interactionFlags & Qt::TextEditable); - q->setCursorWidth(-1); -} - -void QQuickTextControlPrivate::setContent(Qt::TextFormat format, const QString &text, QTextDocument *document) +void QQuickTextControlPrivate::setContent(Qt::TextFormat format, const QString &text) { Q_Q(QQuickTextControl); @@ -298,33 +291,11 @@ void QQuickTextControlPrivate::setContent(Qt::TextFormat format, const QString & // set char format then. const QTextCharFormat charFormatForInsertion = cursor.charFormat(); - bool clearDocument = true; - if (!doc) { - if (document) { - doc = document; - clearDocument = false; - } else { - doc = new QTextDocument(q); - } - _q_documentLayoutChanged(); - cursor = QTextCursor(doc); - -// #### doc->documentLayout()->setPaintDevice(viewport); - - QObject::connect(doc, SIGNAL(contentsChanged()), q, SLOT(_q_updateCurrentCharFormatAndSelection())); - QObject::connect(doc, SIGNAL(cursorPositionChanged(QTextCursor)), q, SLOT(_q_emitCursorPosChanged(QTextCursor))); - QObject::connect(doc, SIGNAL(documentLayoutChanged()), q, SLOT(_q_documentLayoutChanged())); - } - bool previousUndoRedoState = doc->isUndoRedoEnabled(); - if (!document) - doc->setUndoRedoEnabled(false); + doc->setUndoRedoEnabled(false); - //Saving the index save some time. - static int contentsChangedIndex = QMetaMethod::fromSignal(&QTextDocument::contentsChanged).methodIndex(); - static int textChangedIndex = QMetaMethod::fromSignal(&QQuickTextControl::textChanged).methodIndex(); // avoid multiple textChanged() signals being emitted - QMetaObject::disconnect(doc, contentsChangedIndex, q, textChangedIndex); + qmlobject_disconnect(doc, QTextDocument, SIGNAL(contentsChanged()), q, QQuickTextControl, SIGNAL(textChanged())); if (!text.isEmpty()) { // clear 'our' cursor for insertion to prevent @@ -354,18 +325,16 @@ void QQuickTextControlPrivate::setContent(Qt::TextFormat format, const QString & doc->setUndoRedoEnabled(false); } cursor = QTextCursor(doc); - } else if (clearDocument) { + } else { doc->clear(); } cursor.setCharFormat(charFormatForInsertion); - QMetaObject::connect(doc, contentsChangedIndex, q, textChangedIndex); + qmlobject_connect(doc, QTextDocument, SIGNAL(contentsChanged()), q, QQuickTextControl, SIGNAL(textChanged())); emit q->textChanged(); - if (!document) - doc->setUndoRedoEnabled(previousUndoRedoState); + doc->setUndoRedoEnabled(previousUndoRedoState); _q_updateCurrentCharFormatAndSelection(); - if (!document) - doc->setModified(false); + doc->setModified(false); q->updateCursorRectangle(true); emit q->cursorPositionChanged(); @@ -474,16 +443,6 @@ void QQuickTextControlPrivate::_q_emitCursorPosChanged(const QTextCursor &someCu } } -void QQuickTextControlPrivate::_q_documentLayoutChanged() -{ - Q_Q(QQuickTextControl); - QAbstractTextDocumentLayout *layout = doc->documentLayout(); - QObject::connect(layout, SIGNAL(update(QRectF)), q, SIGNAL(updateRequest())); - QObject::connect(layout, SIGNAL(updateBlock(QTextBlock)), q, SIGNAL(updateRequest())); - QObject::connect(layout, SIGNAL(documentSizeChanged(QSizeF)), q, SIGNAL(documentSizeChanged(QSizeF))); - -} - void QQuickTextControlPrivate::setBlinkingCursorEnabled(bool enable) { Q_Q(QQuickTextControl); @@ -611,7 +570,23 @@ QQuickTextControl::QQuickTextControl(QTextDocument *doc, QObject *parent) : QObject(*new QQuickTextControlPrivate, parent) { Q_D(QQuickTextControl); - d->init(Qt::PlainText, QString(), doc); + Q_ASSERT(doc); + + QAbstractTextDocumentLayout *layout = doc->documentLayout(); + qmlobject_connect(layout, QAbstractTextDocumentLayout, SIGNAL(update(QRectF)), this, QQuickTextControl, SIGNAL(updateRequest())); + qmlobject_connect(layout, QAbstractTextDocumentLayout, SIGNAL(updateBlock(QTextBlock)), this, QQuickTextControl, SIGNAL(updateRequest())); + qmlobject_connect(doc, QTextDocument, SIGNAL(contentsChanged()), this, QQuickTextControl, SIGNAL(textChanged())); + qmlobject_connect(doc, QTextDocument, SIGNAL(contentsChanged()), this, QQuickTextControl, SLOT(_q_updateCurrentCharFormatAndSelection())); + qmlobject_connect(doc, QTextDocument, SIGNAL(cursorPositionChanged(QTextCursor)), this, QQuickTextControl, SLOT(_q_emitCursorPosChanged(QTextCursor))); + + layout->setProperty("cursorWidth", textCursorWidth); + + d->doc = doc; + d->cursor = QTextCursor(doc); + d->lastCharFormat = d->cursor.charFormat(); + doc->setPageSize(QSizeF(0, 0)); + doc->setModified(false); + doc->setUndoRedoEnabled(true); } QQuickTextControl::~QQuickTextControl() diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h index e8abfc0..293a465 100644 --- a/src/quick/items/qquicktextcontrol_p.h +++ b/src/quick/items/qquicktextcontrol_p.h @@ -150,7 +150,6 @@ Q_SIGNALS: // control signals void updateCursorRequest(); void updateRequest(); - void documentSizeChanged(const QSizeF &); void cursorRectangleChanged(); void linkActivated(const QString &link); @@ -175,7 +174,6 @@ private: Q_DISABLE_COPY(QQuickTextControl) Q_PRIVATE_SLOT(d_func(), void _q_updateCurrentCharFormatAndSelection()) Q_PRIVATE_SLOT(d_func(), void _q_emitCursorPosChanged(const QTextCursor &)) - Q_PRIVATE_SLOT(d_func(), void _q_documentLayoutChanged()) }; diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h index 24fa6da..b418042 100644 --- a/src/quick/items/qquicktextcontrol_p_p.h +++ b/src/quick/items/qquicktextcontrol_p_p.h @@ -76,10 +76,7 @@ public: void updateCurrentCharFormat(); - void init(Qt::TextFormat format = Qt::RichText, const QString &text = QString(), - QTextDocument *document = 0); - void setContent(Qt::TextFormat format = Qt::RichText, const QString &text = QString(), - QTextDocument *document = 0); + void setContent(Qt::TextFormat format, const QString &text); void paste(const QMimeData *source); @@ -159,7 +156,6 @@ public: bool cursorRectangleChanged : 1; void _q_copyLink(); - void _q_documentLayoutChanged(); }; QT_END_NAMESPACE diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index d09c432..41b6e94 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -260,7 +260,9 @@ void QQuickTextEdit::setText(const QString &text) d->document->clearResources(); d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text)); - if (d->richText) { + if (!isComponentComplete()) { + d->text = text; + } else if (d->richText) { #ifndef QT_NO_TEXTHTMLPARSER d->control->setHtml(text); #else @@ -326,12 +328,14 @@ void QQuickTextEdit::setTextFormat(TextFormat format) d->richText = format == RichText || (format == AutoText && (wasRich || Qt::mightBeRichText(text()))); #ifndef QT_NO_TEXTHTMLPARSER - if (wasRich && !d->richText) { - d->control->setPlainText(!d->textCached ? d->control->toHtml() : d->text); - updateSize(); - } else if (!wasRich && d->richText) { - d->control->setHtml(!d->textCached ? d->control->toPlainText() : d->text); - updateSize(); + if (isComponentComplete()) { + if (wasRich && !d->richText) { + d->control->setPlainText(!d->textCached ? d->control->toHtml() : d->text); + updateSize(); + } else if (!wasRich && d->richText) { + d->control->setHtml(!d->textCached ? d->control->toPlainText() : d->text); + updateSize(); + } } #endif @@ -1161,6 +1165,14 @@ void QQuickTextEdit::componentComplete() QQuickImplicitSizeItem::componentComplete(); d->document->setBaseUrl(baseUrl(), d->richText); +#ifndef QT_NO_TEXTHTML_PARSER + if (d->richText) + d->control->setHtml(d->text); + else +#endif + if (!d->text.isEmpty()) + d->control->setPlainText(d->text); + if (d->dirty) { d->determineHorizontalAlignment(); d->updateDefaultTextOption(); diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h index 1fb8211..6e15736 100644 --- a/src/quick/items/qquicktextedit_p_p.h +++ b/src/quick/items/qquicktextedit_p_p.h @@ -82,7 +82,7 @@ public: , documentDirty(true), dirty(false), richText(false), cursorVisible(false), cursorPending(false) , focusOnPress(true), persistentSelection(false), requireImplicitWidth(false) , selectByMouse(false), canPaste(false), canPasteValid(false), hAlignImplicit(true) - , textCached(false), inLayout(false) + , textCached(true), inLayout(false) { } diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index 1e063cb..c911715 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -2417,7 +2417,8 @@ void tst_qquicktextedit::canPaste() { QVERIFY(textEdit != 0); // check initial value - QTBUG-17765 - QQuickTextControl tc(0); + QTextDocument document; + QQuickTextControl tc(&document); QCOMPARE(textEdit->canPaste(), tc.canPaste()); #endif @@ -2435,7 +2436,8 @@ void tst_qquicktextedit::canPasteEmpty() { QVERIFY(textEdit != 0); // check initial value - QTBUG-17765 - QQuickTextControl tc(0); + QTextDocument document; + QQuickTextControl tc(&document); QCOMPARE(textEdit->canPaste(), tc.canPaste()); #endif @@ -3820,7 +3822,7 @@ void tst_qquicktextedit::remove() textEdit->setTextFormat(textFormat); textEdit->select(selectionStart, selectionEnd); - QSignalSpy selectionSpy(textEdit, SIGNAL(seletedTextChanged())); + QSignalSpy selectionSpy(textEdit, SIGNAL(selectedTextChanged())); QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged())); QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged())); QSignalSpy textSpy(textEdit, SIGNAL(textChanged())); -- 2.7.4