diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2017-12-14 10:40:53 +0100 |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2018-04-26 07:11:43 +0000 |
commit | 78be6b2aa4da54cb41ed60a31abfb7312fb44c9a (patch) | |
tree | b22190dbb6bcf121f359c46704da7e87bab7c176 /src/quick/items/qquicktext.cpp | |
parent | 9f731b6841bbc9b7425a95303369d05be895f949 (diff) |
Fix issue where updated text in layout is not correctly rewrapped
When the text element is inside a Qt Quick layout and we set the implicit width,
this can trigger the Layout to resize the width further down in the stack. At
this point, a recursion guard we have in place to protect against binding
loops will cause us to ignore the size update. The end result is that the text
width has changed, but the contents have not been updated to reflect this.
This change detects this case by checking if the width of the text changed
while the recursion guard was in place, and if it was, we call updateSize()
again to make sure everything is up-to-date.
I added a second admittedly ugly recursion guard for this out of paranoia.
I haven't seen any case where this might cause an infinite recursion, but
it seemed better to be on the safe side.
[ChangeLog][Text] Fixed an issue where updating text inside a layout would
not cause it to correctly adapt to its new width.
Task-number: QTBUG-53279
Change-Id: I1e421a7073428fa490a24be36208a2077f5836dd
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/quick/items/qquicktext.cpp')
-rw-r--r-- | src/quick/items/qquicktext.cpp | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index 9eaf9f8d6d..dd66930ef7 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -88,6 +88,7 @@ QQuickTextPrivate::QQuickTextPrivate() , truncated(false), hAlignImplicit(true), rightToLeftText(false) , layoutTextElided(false), textHasChanged(true), needToUpdateLayout(false), formatModifiesFontSize(false) , polishSize(false) + , updateSizeRecursionGuard(false) { implicitAntialiasing = true; } @@ -442,6 +443,7 @@ void QQuickTextPrivate::updateSize() //### need to confirm cost of always setting these for richText internalWidthUpdate = true; + qreal oldWidth = q->width(); qreal iWidth = -1; if (!q->widthValid()) iWidth = size.width(); @@ -449,24 +451,35 @@ void QQuickTextPrivate::updateSize() q->setImplicitSize(iWidth + hPadding, size.height() + vPadding); internalWidthUpdate = false; - if (iWidth == -1) - q->setImplicitHeight(size.height() + vPadding); - - QTextBlock firstBlock = extra->doc->firstBlock(); - while (firstBlock.layout()->lineCount() == 0) - firstBlock = firstBlock.next(); - - QTextBlock lastBlock = extra->doc->lastBlock(); - while (lastBlock.layout()->lineCount() == 0) - lastBlock = lastBlock.previous(); - - if (firstBlock.lineCount() > 0 && lastBlock.lineCount() > 0) { - QTextLine firstLine = firstBlock.layout()->lineAt(0); - QTextLine lastLine = lastBlock.layout()->lineAt(lastBlock.layout()->lineCount() - 1); - advance = QSizeF(lastLine.horizontalAdvance(), - (lastLine.y() + lastBlock.layout()->position().y()) - (firstLine.y() + firstBlock.layout()->position().y())); + // If the implicit width update caused a recursive change of the width, + // we will have skipped integral parts of the layout due to the + // internalWidthUpdate recursion guard. To make sure everything is up + // to date, we need to run a second pass over the layout when updateSize() + // is done. + if (!qFuzzyCompare(q->width(), oldWidth) && !updateSizeRecursionGuard) { + updateSizeRecursionGuard = true; + updateSize(); + updateSizeRecursionGuard = false; } else { - advance = QSizeF(); + if (iWidth == -1) + q->setImplicitHeight(size.height() + vPadding); + + QTextBlock firstBlock = extra->doc->firstBlock(); + while (firstBlock.layout()->lineCount() == 0) + firstBlock = firstBlock.next(); + + QTextBlock lastBlock = extra->doc->lastBlock(); + while (lastBlock.layout()->lineCount() == 0) + lastBlock = lastBlock.previous(); + + if (firstBlock.lineCount() > 0 && lastBlock.lineCount() > 0) { + QTextLine firstLine = firstBlock.layout()->lineAt(0); + QTextLine lastLine = lastBlock.layout()->lineAt(lastBlock.layout()->lineCount() - 1); + advance = QSizeF(lastLine.horizontalAdvance(), + (lastLine.y() + lastBlock.layout()->position().y()) - (firstLine.y() + firstBlock.layout()->position().y())); + } else { + advance = QSizeF(); + } } } |