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();
|
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
|
\since 4.2
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ class Q_GUI_EXPORT QTextDocument : public QObject
|
|||||||
Q_PROPERTY(QSizeF pageSize READ pageSize WRITE setPageSize)
|
Q_PROPERTY(QSizeF pageSize READ pageSize WRITE setPageSize)
|
||||||
Q_PROPERTY(QFont defaultFont READ defaultFont WRITE setDefaultFont)
|
Q_PROPERTY(QFont defaultFont READ defaultFont WRITE setDefaultFont)
|
||||||
Q_PROPERTY(bool useDesignMetrics READ useDesignMetrics WRITE setUseDesignMetrics)
|
Q_PROPERTY(bool useDesignMetrics READ useDesignMetrics WRITE setUseDesignMetrics)
|
||||||
|
Q_PROPERTY(bool layoutEnabled READ isLayoutEnabled WRITE setLayoutEnabled)
|
||||||
Q_PROPERTY(QSizeF size READ size)
|
Q_PROPERTY(QSizeF size READ size)
|
||||||
Q_PROPERTY(qreal textWidth READ textWidth WRITE setTextWidth)
|
Q_PROPERTY(qreal textWidth READ textWidth WRITE setTextWidth)
|
||||||
Q_PROPERTY(int blockCount READ blockCount)
|
Q_PROPERTY(int blockCount READ blockCount)
|
||||||
@ -218,6 +219,9 @@ public:
|
|||||||
void setUseDesignMetrics(bool b);
|
void setUseDesignMetrics(bool b);
|
||||||
bool useDesignMetrics() const;
|
bool useDesignMetrics() const;
|
||||||
|
|
||||||
|
void setLayoutEnabled(bool b);
|
||||||
|
bool isLayoutEnabled() const;
|
||||||
|
|
||||||
void drawContents(QPainter *painter, const QRectF &rect = QRectF());
|
void drawContents(QPainter *painter, const QRectF &rect = QRectF());
|
||||||
|
|
||||||
void setTextWidth(qreal width);
|
void setTextWidth(qreal width);
|
||||||
|
@ -291,6 +291,8 @@ public:
|
|||||||
return get(object->document());
|
return get(object->document());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool canLayout() const { return layoutEnabled && !pageSize.isNull(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTextDocumentPrivate(const QTextDocumentPrivate& m);
|
QTextDocumentPrivate(const QTextDocumentPrivate& m);
|
||||||
QTextDocumentPrivate& operator= (const QTextDocumentPrivate& m);
|
QTextDocumentPrivate& operator= (const QTextDocumentPrivate& m);
|
||||||
@ -337,6 +339,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
bool inContentsChange;
|
bool inContentsChange;
|
||||||
|
bool layoutEnabled = true;
|
||||||
QTextOption defaultTextOption;
|
QTextOption defaultTextOption;
|
||||||
Qt::CursorMoveStyle defaultCursorMoveStyle;
|
Qt::CursorMoveStyle defaultCursorMoveStyle;
|
||||||
#ifndef QT_NO_CSSPARSER
|
#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())
|
for (; blockIt.isValid() && blockIt != endIt; blockIt = blockIt.next())
|
||||||
blockIt.clearLayout();
|
blockIt.clearLayout();
|
||||||
|
|
||||||
if (d->docPrivate->pageSize.isNull())
|
if (!d->docPrivate->canLayout())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QRectF updateRect;
|
QRectF updateRect;
|
||||||
@ -4032,7 +4032,7 @@ QRectF QTextDocumentLayout::tableCellBoundingRect(QTextTable *table, const QText
|
|||||||
QRectF QTextDocumentLayout::tableBoundingRect(QTextTable *table) const
|
QRectF QTextDocumentLayout::tableBoundingRect(QTextTable *table) const
|
||||||
{
|
{
|
||||||
Q_D(const QTextDocumentLayout);
|
Q_D(const QTextDocumentLayout);
|
||||||
if (d->docPrivate->pageSize.isNull())
|
if (!d->docPrivate->canLayout())
|
||||||
return QRectF();
|
return QRectF();
|
||||||
d->ensureLayoutFinished();
|
d->ensureLayoutFinished();
|
||||||
|
|
||||||
@ -4059,7 +4059,7 @@ QRectF QTextDocumentLayout::tableBoundingRect(QTextTable *table) const
|
|||||||
QRectF QTextDocumentLayout::frameBoundingRect(QTextFrame *frame) const
|
QRectF QTextDocumentLayout::frameBoundingRect(QTextFrame *frame) const
|
||||||
{
|
{
|
||||||
Q_D(const QTextDocumentLayout);
|
Q_D(const QTextDocumentLayout);
|
||||||
if (d->docPrivate->pageSize.isNull())
|
if (!d->docPrivate->canLayout())
|
||||||
return QRectF();
|
return QRectF();
|
||||||
d->ensureLayoutFinished();
|
d->ensureLayoutFinished();
|
||||||
return d->frameBoundingRectInternal(frame);
|
return d->frameBoundingRectInternal(frame);
|
||||||
@ -4088,7 +4088,7 @@ QRectF QTextDocumentLayoutPrivate::frameBoundingRectInternal(QTextFrame *frame)
|
|||||||
QRectF QTextDocumentLayout::blockBoundingRect(const QTextBlock &block) const
|
QRectF QTextDocumentLayout::blockBoundingRect(const QTextBlock &block) const
|
||||||
{
|
{
|
||||||
Q_D(const QTextDocumentLayout);
|
Q_D(const QTextDocumentLayout);
|
||||||
if (d->docPrivate->pageSize.isNull() || !block.isValid() || !block.isVisible())
|
if (!d->docPrivate->canLayout() || !block.isValid() || !block.isVisible())
|
||||||
return QRectF();
|
return QRectF();
|
||||||
d->ensureLayoutedByPosition(block.position() + block.length());
|
d->ensureLayoutedByPosition(block.position() + block.length());
|
||||||
QTextFrame *frame = d->document->frameAt(block.position());
|
QTextFrame *frame = d->document->frameAt(block.position());
|
||||||
|
@ -180,6 +180,8 @@ private slots:
|
|||||||
void insertHtmlWithComments_data();
|
void insertHtmlWithComments_data();
|
||||||
void insertHtmlWithComments();
|
void insertHtmlWithComments();
|
||||||
|
|
||||||
|
void delayedLayout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
|
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
|
||||||
void buildRegExpData();
|
void buildRegExpData();
|
||||||
@ -3931,5 +3933,24 @@ void tst_QTextDocument::insertHtmlWithComments()
|
|||||||
QCOMPARE(blockContent, expectedBlocks);
|
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)
|
QTEST_MAIN(tst_QTextDocument)
|
||||||
#include "tst_qtextdocument.moc"
|
#include "tst_qtextdocument.moc"
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <QGraphicsItem>
|
#include <QGraphicsItem>
|
||||||
#include <QGraphicsScene>
|
#include <QGraphicsScene>
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
|
#include <QTextDocument>
|
||||||
|
|
||||||
class tst_QGraphicsItem : public QObject
|
class tst_QGraphicsItem : public QObject
|
||||||
{
|
{
|
||||||
@ -33,6 +34,7 @@ private slots:
|
|||||||
void shear();
|
void shear();
|
||||||
void translate();
|
void translate();
|
||||||
void createTextItem();
|
void createTextItem();
|
||||||
|
void createTextItemNoLayouting();
|
||||||
};
|
};
|
||||||
|
|
||||||
tst_QGraphicsItem::tst_QGraphicsItem()
|
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)
|
QTEST_MAIN(tst_QGraphicsItem)
|
||||||
#include "tst_qgraphicsitem.moc"
|
#include "tst_qgraphicsitem.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user