QTextDocument: add setLayoutEnabled()
This allows to set up everything first - without paying for the layout calculation at every step - and only then trigger the layout once. Results: 0.065 msecs to create a QGraphicsTextItem with some text (layouted) 0.036 msecs to set everything up in a QGraphicsTextItem with 0 width Change-Id: I138bd1d58941d029bc0a36d2730216778f1fbd97 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
2996ca031e
commit
09c7457f4a
@ -634,6 +634,40 @@ bool QTextDocument::useDesignMetrics() const
|
||||
return d->defaultTextOption.useDesignMetrics();
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QTextDocument::layoutEnabled
|
||||
\since 6.4
|
||||
\brief whether QTextDocument should recalculate the layout after every change
|
||||
|
||||
If this property is set to true, any change to the document triggers a layout,
|
||||
which makes everything work as expected but takes time.
|
||||
|
||||
Temporarily disabling the layout can save time when making multiple changes
|
||||
(not just text content, but also default font, default text option....)
|
||||
so that the document is only laid out once at the end. This can be useful when
|
||||
the text width or page size isn't yet known, for instance.
|
||||
|
||||
By default, this property is \c true.
|
||||
|
||||
\sa setTextWidth
|
||||
*/
|
||||
|
||||
void QTextDocument::setLayoutEnabled(bool b)
|
||||
{
|
||||
Q_D(QTextDocument);
|
||||
if (d->layoutEnabled == b)
|
||||
return;
|
||||
d->layoutEnabled = b;
|
||||
if (b && d->lout)
|
||||
d->lout->documentChanged(0, 0, d->length());
|
||||
}
|
||||
|
||||
bool QTextDocument::isLayoutEnabled() const
|
||||
{
|
||||
Q_D(const QTextDocument);
|
||||
return d->layoutEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 4.2
|
||||
|
||||
|
@ -62,6 +62,7 @@ class Q_GUI_EXPORT QTextDocument : public QObject
|
||||
Q_PROPERTY(QSizeF pageSize READ pageSize WRITE setPageSize)
|
||||
Q_PROPERTY(QFont defaultFont READ defaultFont WRITE setDefaultFont)
|
||||
Q_PROPERTY(bool useDesignMetrics READ useDesignMetrics WRITE setUseDesignMetrics)
|
||||
Q_PROPERTY(bool layoutEnabled READ isLayoutEnabled WRITE setLayoutEnabled)
|
||||
Q_PROPERTY(QSizeF size READ size)
|
||||
Q_PROPERTY(qreal textWidth READ textWidth WRITE setTextWidth)
|
||||
Q_PROPERTY(int blockCount READ blockCount)
|
||||
@ -218,6 +219,9 @@ public:
|
||||
void setUseDesignMetrics(bool b);
|
||||
bool useDesignMetrics() const;
|
||||
|
||||
void setLayoutEnabled(bool b);
|
||||
bool isLayoutEnabled() const;
|
||||
|
||||
void drawContents(QPainter *painter, const QRectF &rect = QRectF());
|
||||
|
||||
void setTextWidth(qreal width);
|
||||
|
@ -291,6 +291,8 @@ public:
|
||||
return get(object->document());
|
||||
}
|
||||
|
||||
bool canLayout() const { return layoutEnabled && !pageSize.isNull(); }
|
||||
|
||||
private:
|
||||
QTextDocumentPrivate(const QTextDocumentPrivate& m);
|
||||
QTextDocumentPrivate& operator= (const QTextDocumentPrivate& m);
|
||||
@ -337,6 +339,7 @@ private:
|
||||
|
||||
public:
|
||||
bool inContentsChange;
|
||||
bool layoutEnabled = true;
|
||||
QTextOption defaultTextOption;
|
||||
Qt::CursorMoveStyle defaultCursorMoveStyle;
|
||||
#ifndef QT_NO_CSSPARSER
|
||||
|
@ -3754,7 +3754,7 @@ void QTextDocumentLayout::documentChanged(int from, int oldLength, int length)
|
||||
for (; blockIt.isValid() && blockIt != endIt; blockIt = blockIt.next())
|
||||
blockIt.clearLayout();
|
||||
|
||||
if (d->docPrivate->pageSize.isNull())
|
||||
if (!d->docPrivate->canLayout())
|
||||
return;
|
||||
|
||||
QRectF updateRect;
|
||||
@ -4032,7 +4032,7 @@ QRectF QTextDocumentLayout::tableCellBoundingRect(QTextTable *table, const QText
|
||||
QRectF QTextDocumentLayout::tableBoundingRect(QTextTable *table) const
|
||||
{
|
||||
Q_D(const QTextDocumentLayout);
|
||||
if (d->docPrivate->pageSize.isNull())
|
||||
if (!d->docPrivate->canLayout())
|
||||
return QRectF();
|
||||
d->ensureLayoutFinished();
|
||||
|
||||
@ -4059,7 +4059,7 @@ QRectF QTextDocumentLayout::tableBoundingRect(QTextTable *table) const
|
||||
QRectF QTextDocumentLayout::frameBoundingRect(QTextFrame *frame) const
|
||||
{
|
||||
Q_D(const QTextDocumentLayout);
|
||||
if (d->docPrivate->pageSize.isNull())
|
||||
if (!d->docPrivate->canLayout())
|
||||
return QRectF();
|
||||
d->ensureLayoutFinished();
|
||||
return d->frameBoundingRectInternal(frame);
|
||||
@ -4088,7 +4088,7 @@ QRectF QTextDocumentLayoutPrivate::frameBoundingRectInternal(QTextFrame *frame)
|
||||
QRectF QTextDocumentLayout::blockBoundingRect(const QTextBlock &block) const
|
||||
{
|
||||
Q_D(const QTextDocumentLayout);
|
||||
if (d->docPrivate->pageSize.isNull() || !block.isValid() || !block.isVisible())
|
||||
if (!d->docPrivate->canLayout() || !block.isValid() || !block.isVisible())
|
||||
return QRectF();
|
||||
d->ensureLayoutedByPosition(block.position() + block.length());
|
||||
QTextFrame *frame = d->document->frameAt(block.position());
|
||||
|
@ -180,6 +180,8 @@ private slots:
|
||||
void insertHtmlWithComments_data();
|
||||
void insertHtmlWithComments();
|
||||
|
||||
void delayedLayout();
|
||||
|
||||
private:
|
||||
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
|
||||
void buildRegExpData();
|
||||
@ -3931,5 +3933,24 @@ void tst_QTextDocument::insertHtmlWithComments()
|
||||
QCOMPARE(blockContent, expectedBlocks);
|
||||
}
|
||||
|
||||
void tst_QTextDocument::delayedLayout()
|
||||
{
|
||||
QTextDocument doc;
|
||||
doc.setHtml("<html>Foobar</html>");
|
||||
QCOMPARE(doc.blockCount(), 1);
|
||||
|
||||
doc.setLayoutEnabled(false);
|
||||
|
||||
// Force creation of a layout
|
||||
QVERIFY(doc.documentLayout());
|
||||
|
||||
QTextBlock block = doc.begin();
|
||||
QTextLayout *layout = block.layout();
|
||||
QCOMPARE(layout->lineCount(), 0); // layout didn't happen yet
|
||||
|
||||
doc.setLayoutEnabled(true);
|
||||
QCOMPARE(layout->lineCount(), 1); // layout happened
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QTextDocument)
|
||||
#include "tst_qtextdocument.moc"
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <QGraphicsItem>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
#include <QTextDocument>
|
||||
|
||||
class tst_QGraphicsItem : public QObject
|
||||
{
|
||||
@ -33,6 +34,7 @@ private slots:
|
||||
void shear();
|
||||
void translate();
|
||||
void createTextItem();
|
||||
void createTextItemNoLayouting();
|
||||
};
|
||||
|
||||
tst_QGraphicsItem::tst_QGraphicsItem()
|
||||
@ -216,5 +218,22 @@ void tst_QGraphicsItem::createTextItem()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QGraphicsItem::createTextItemNoLayouting()
|
||||
{
|
||||
// Ensure QFontDatabase loaded the font beforehand
|
||||
QFontInfo(qApp->font()).family();
|
||||
const QString text = "This is some text";
|
||||
QBENCHMARK {
|
||||
QGraphicsTextItem item;
|
||||
item.document()->setLayoutEnabled(false);
|
||||
// Prepare everything
|
||||
item.setPlainText(text);
|
||||
QTextOption option = item.document()->defaultTextOption();
|
||||
option.setAlignment(Qt::AlignHCenter);
|
||||
item.document()->setDefaultTextOption(option);
|
||||
// And (in a real app) enable layouting here
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QGraphicsItem)
|
||||
#include "tst_qgraphicsitem.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user