Speed up TextEdit construction time.
authorAndrew den Exter <andrew.den-exter@nokia.com>
Thu, 5 Jul 2012 00:18:43 +0000 (10:18 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 9 Jul 2012 07:05:32 +0000 (09:05 +0200)
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 <martin.jones@nokia.com>
src/quick/items/qquicktextcontrol.cpp
src/quick/items/qquicktextcontrol_p.h
src/quick/items/qquicktextcontrol_p_p.h
src/quick/items/qquicktextedit.cpp
src/quick/items/qquicktextedit_p_p.h
tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp

index 23bf2a7..d2ff4dc 100644 (file)
@@ -71,6 +71,8 @@
 #include <qstylehints.h>
 #include <qmetaobject.h>
 
+#include <private/qqmlglobal_p.h>
+
 // ### 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()
index e8abfc0..293a465 100644 (file)
@@ -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())
 };
 
 
index 24fa6da..b418042 100644 (file)
@@ -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
index d09c432..41b6e94 100644 (file)
@@ -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();
index 1fb8211..6e15736 100644 (file)
@@ -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)
     {
     }
 
index 1e063cb..c911715 100644 (file)
@@ -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()));