Fix eliding when text width is reset by an implicitWidth change.
authorAndrew den Exter <andrew.den-exter@nokia.com>
Fri, 20 Apr 2012 01:40:40 +0000 (11:40 +1000)
committerQt by Nokia <qt-info@nokia.com>
Fri, 20 Apr 2012 06:05:15 +0000 (08:05 +0200)
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 <martin.jones@nokia.com>

src/quick/items/qquickitem.cpp
src/quick/items/qquicktext.cpp
tests/auto/quick/qquickitem2/data/implicitsize.qml
tests/auto/quick/qquickitem2/tst_qquickitem.cpp
tests/auto/quick/qquicktext/tst_qquicktext.cpp

index 628e19d..cf06dc2 100644 (file)
@@ -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;
index f52138c..2a6a6da 100644 (file)
@@ -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))
index cc6aaf7..756e230 100644 (file)
@@ -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 })
+    }
 }
index 34f5187..44b0558 100644 (file)
@@ -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;
 }
 
index 125e056..297fa01 100644 (file)
@@ -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<QString>("width");
+    QTest::addColumn<QString>("initialText");
+    QTest::addColumn<QString>("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<QQuickText*>(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()
 {
     {