From 04794c29cee0d97fb3b32e1c71a072e34ee37e9c Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 20 Apr 2012 11:40:40 +1000 Subject: [PATCH] Fix eliding when text width is reset by an implicitWidth change. After emitting implicit size changed signals, reevaluate any conditions that were dependent on the validity of the item dimensions. Change-Id: Ie4ee0c87a22cf82752c207c69d426056c36ede67 Reviewed-by: Martin Jones --- src/quick/items/qquickitem.cpp | 14 ++++-- src/quick/items/qquicktext.cpp | 45 +++++++---------- tests/auto/quick/qquickitem2/data/implicitsize.qml | 15 ++++++ tests/auto/quick/qquickitem2/tst_qquickitem.cpp | 42 ++++++++++++++++ tests/auto/quick/qquicktext/tst_qquicktext.cpp | 52 ++++++++++++++++++++ 5 files changed, 138 insertions(+), 30 deletions(-) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 628e19d..cf06dc2 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -4600,7 +4600,9 @@ void QQuickItem::setImplicitWidth(qreal w) if (d->width == w || widthValid()) { if (changed) d->implicitWidthChanged(); - return; + if (d->width == w || widthValid()) + return; + changed = false; } qreal oldWidth = d->width; @@ -4695,7 +4697,9 @@ void QQuickItem::setImplicitHeight(qreal h) if (d->height == h || heightValid()) { if (changed) d->implicitHeightChanged(); - return; + if (d->height == h || heightValid()) + return; + changed = false; } qreal oldHeight = d->height; @@ -4724,12 +4728,14 @@ void QQuickItem::setImplicitSize(qreal w, qreal h) if (d->width == w || widthValid()) { if (wChanged) d->implicitWidthChanged(); - wDone = true; + wDone = d->width == w || widthValid(); + wChanged = false; } if (d->height == h || heightValid()) { if (hChanged) d->implicitHeightChanged(); - hDone = true; + hDone = d->height == h || heightValid(); + hChanged = false; } if (wDone && hDone) return; diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index f52138c..2a6a6da 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -700,8 +700,9 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth, qreal *cons layout.setTextOption(textOption); layout.setFont(font); - if ((q->widthValid() && q->width() <= 0. && elideMode != QQuickText::ElideNone) - || (q->heightValid() && q->height() <= 0. && wrapMode != QQuickText::NoWrap && elideMode == QQuickText::ElideRight)) { + if (!requireImplicitWidth + && ((q->widthValid() && q->width() <= 0. && elideMode != QQuickText::ElideNone) + || (q->heightValid() && q->height() <= 0. && wrapMode != QQuickText::NoWrap && elideMode == QQuickText::ElideRight))) { // we are elided and we have a zero width or height if (!truncated) { truncated = true; @@ -712,25 +713,6 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth, qreal *cons emit q->lineCountChanged(); } - if (requireImplicitWidth) { - // Layout to determine the implicit width. - layout.beginLayout(); - - for (int i = 0; i < maximumLineCount(); ++i) { - QTextLine line = layout.createLine(); - if (!line.isValid()) - break; - } - layout.endLayout(); - *naturalWidth = layout.maximumWidth(); - layout.clearLayout(); - - bool wasInLayout = internalWidthUpdate; - internalWidthUpdate = true; - q->setImplicitWidth(*naturalWidth); - internalWidthUpdate = wasInLayout; - } - QFontMetricsF fm(font); qreal height = (lineHeightMode() == QQuickText::FixedHeight) ? lineHeight() : fm.height() * lineHeight(); *baseline = fm.ascent(); @@ -743,15 +725,16 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth, qreal *cons const bool customLayout = isLineLaidOutConnected(); const bool wasTruncated = truncated; - const bool singlelineElide = elideMode != QQuickText::ElideNone && q->widthValid(); - const bool multilineElide = elideMode == QQuickText::ElideRight + bool singlelineElide = elideMode != QQuickText::ElideNone && q->widthValid(); + bool multilineElide = elideMode == QQuickText::ElideRight && q->widthValid() && (q->heightValid() || maximumLineCountValid); - const bool canWrap = wrapMode != QQuickText::NoWrap && q->widthValid(); + bool canWrap = wrapMode != QQuickText::NoWrap && q->widthValid(); - const bool horizontalFit = fontSizeMode() & QQuickText::HorizontalFit && q->widthValid(); - const bool verticalFit = fontSizeMode() & QQuickText::VerticalFit + bool horizontalFit = fontSizeMode() & QQuickText::HorizontalFit && q->widthValid(); + bool verticalFit = fontSizeMode() & QQuickText::VerticalFit && (q->heightValid() || (maximumLineCountValid && canWrap)); + const bool pixelSize = font.pixelSize() != -1; QString layoutText = layout.text(); @@ -922,6 +905,16 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth, qreal *cons q->setImplicitWidth(*naturalWidth); internalWidthUpdate = wasInLayout; + singlelineElide = elideMode != QQuickText::ElideNone && q->widthValid(); + multilineElide = elideMode == QQuickText::ElideRight + && q->widthValid() + && (q->heightValid() || maximumLineCountValid); + canWrap = wrapMode != QQuickText::NoWrap && q->widthValid(); + + horizontalFit = fontSizeMode() & QQuickText::HorizontalFit && q->widthValid(); + verticalFit = fontSizeMode() & QQuickText::VerticalFit + && (q->heightValid() || (maximumLineCountValid && canWrap)); + const qreal oldWidth = lineWidth; lineWidth = q->widthValid() && q->width() > 0 ? q->width() : FLT_MAX; if (lineWidth != oldWidth && (singlelineElide || multilineElide || canWrap || horizontalFit)) diff --git a/tests/auto/quick/qquickitem2/data/implicitsize.qml b/tests/auto/quick/qquickitem2/data/implicitsize.qml index cc6aaf7..756e230 100644 --- a/tests/auto/quick/qquickitem2/data/implicitsize.qml +++ b/tests/auto/quick/qquickitem2/data/implicitsize.qml @@ -16,4 +16,19 @@ Item { implicitWidth = 150 implicitHeight = 80 } + + function increaseImplicit() { + implicitWidth = 200 + implicitHeight = 100 + } + + function assignImplicitBinding() { + width = Qt.binding(function() { return implicitWidth < 175 ? implicitWidth : 175 }) + height = Qt.binding(function() { return implicitHeight < 90 ? implicitHeight : 90 }) + } + + function assignUndefinedBinding() { + width = Qt.binding(function() { return implicitWidth < 175 ? undefined : 175 }) + height = Qt.binding(function() { return implicitHeight < 90 ? undefined : 90 }) + } } diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index 34f5187..44b0558 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -1350,6 +1350,48 @@ void tst_QQuickItem::implicitSize() QCOMPARE(item->width(), qreal(150)); QCOMPARE(item->height(), qreal(80)); + QMetaObject::invokeMethod(item, "assignImplicitBinding"); + + QCOMPARE(item->implicitWidth(), qreal(150)); + QCOMPARE(item->implicitHeight(), qreal(80)); + QCOMPARE(item->width(), qreal(150)); + QCOMPARE(item->height(), qreal(80)); + + QMetaObject::invokeMethod(item, "increaseImplicit"); + + QCOMPARE(item->implicitWidth(), qreal(200)); + QCOMPARE(item->implicitHeight(), qreal(100)); + QCOMPARE(item->width(), qreal(175)); + QCOMPARE(item->height(), qreal(90)); + + QMetaObject::invokeMethod(item, "changeImplicit"); + + QCOMPARE(item->implicitWidth(), qreal(150)); + QCOMPARE(item->implicitHeight(), qreal(80)); + QCOMPARE(item->width(), qreal(150)); + QCOMPARE(item->height(), qreal(80)); + + QMetaObject::invokeMethod(item, "assignUndefinedBinding"); + + QCOMPARE(item->implicitWidth(), qreal(150)); + QCOMPARE(item->implicitHeight(), qreal(80)); + QCOMPARE(item->width(), qreal(150)); + QCOMPARE(item->height(), qreal(80)); + + QMetaObject::invokeMethod(item, "increaseImplicit"); + + QCOMPARE(item->implicitWidth(), qreal(200)); + QCOMPARE(item->implicitHeight(), qreal(100)); + QCOMPARE(item->width(), qreal(175)); + QCOMPARE(item->height(), qreal(90)); + + QMetaObject::invokeMethod(item, "changeImplicit"); + + QCOMPARE(item->implicitWidth(), qreal(150)); + QCOMPARE(item->implicitHeight(), qreal(80)); + QCOMPARE(item->width(), qreal(150)); + QCOMPARE(item->height(), qreal(80)); + delete canvas; } diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index 125e056..297fa01 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -72,6 +72,8 @@ private slots: void elide(); void multilineElide_data(); void multilineElide(); + void implicitElide_data(); + void implicitElide(); void textFormat(); void alignments_data(); @@ -531,6 +533,56 @@ void tst_qquicktext::multilineElide() delete canvas; } +void tst_qquicktext::implicitElide_data() +{ + QTest::addColumn("width"); + QTest::addColumn("initialText"); + QTest::addColumn("text"); + + QTest::newRow("maximum width, empty") + << "Math.min(implicitWidth, 100)" + << ""; + QTest::newRow("maximum width, short") + << "Math.min(implicitWidth, 100)" + << "the"; + QTest::newRow("maximum width, long") + << "Math.min(implicitWidth, 100)" + << "the quick brown fox jumped over the lazy dog"; + QTest::newRow("reset width, empty") + << "implicitWidth > 100 ? 100 : undefined" + << ""; + QTest::newRow("reset width, short") + << "implicitWidth > 100 ? 100 : undefined" + << "the"; + QTest::newRow("reset width, long") + << "implicitWidth > 100 ? 100 : undefined" + << "the quick brown fox jumped over the lazy dog"; +} + +void tst_qquicktext::implicitElide() +{ + QFETCH(QString, width); + QFETCH(QString, initialText); + + QString componentStr = + "import QtQuick 2.0\n" + "Text {\n" + "width: " + width + "\n" + "text: \"" + initialText + "\"\n" + "elide: Text.ElideRight\n" + "}"; + QQmlComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickText *textObject = qobject_cast(textComponent.create()); + + QVERIFY(textObject->contentWidth() <= textObject->width()); + + textObject->setText("the quick brown fox jumped over"); + + QVERIFY(textObject->contentWidth() > 0); + QVERIFY(textObject->contentWidth() <= textObject->width()); +} + void tst_qquicktext::textFormat() { { -- 1.7.2.5