Fix multi-length string substitution.
authorAndrew den Exter <andrew.den-exter@nokia.com>
Tue, 14 Feb 2012 07:02:55 +0000 (17:02 +1000)
committerQt by Nokia <qt-info@nokia.com>
Thu, 16 Feb 2012 05:36:38 +0000 (06:36 +0100)
Multi-length string eliding was provided by QFontMetrics::elidedText()
which is no longer used for layouts.  So we instead have to do the
string substitution ourselves if the text doesn't fit before finally
eliding.

Change-Id: Iab2e54b332390290d656299a5be148f39f78df9d
Reviewed-by: Martin Jones <martin.jones@nokia.com>
src/quick/items/qquicktext.cpp
src/quick/items/qquicktext_p_p.h
tests/auto/qtquick2/qquicktext/data/multilengthStrings.qml [new file with mode: 0644]
tests/auto/qtquick2/qquicktext/data/multilengthStringsWrapped.qml [new file with mode: 0644]
tests/auto/qtquick2/qquicktext/tst_qquicktext.cpp

index 31f557f..241086c 100644 (file)
@@ -75,8 +75,8 @@ QQuickTextPrivate::QQuickTextPrivate()
   vAlign(QQuickText::AlignTop), elideMode(QQuickText::ElideNone),
   format(QQuickText::AutoText), wrapMode(QQuickText::NoWrap), lineHeight(1),
   lineHeightMode(QQuickText::ProportionalHeight), lineCount(1), maximumLineCount(INT_MAX),
-  maximumLineCountValid(false), fontSizeMode(QQuickText::FixedSize), minimumPixelSize(12),
-  minimumPointSize(12), updateOnComponentComplete(true),
+  maximumLineCountValid(false), fontSizeMode(QQuickText::FixedSize), multilengthEos(-1),
+  minimumPixelSize(12), minimumPointSize(12), updateOnComponentComplete(true),
   richText(false), styledText(false), singleline(false), internalWidthUpdate(false),
   requireImplicitWidth(false), truncated(false), hAlignImplicit(true), rightToLeftText(false),
   layoutTextElided(false), textHasChanged(true),
@@ -301,7 +301,8 @@ void QQuickTextPrivate::updateLayout()
                 QDeclarativeStyledText::parse(text, layout, imgTags, q->baseUrl(), qmlContext(q), !maximumLineCountValid);
             } else {
                 layout.clearAdditionalFormats();
-                QString tmp = text;
+                multilengthEos = text.indexOf(QLatin1Char('\x9c'));
+                QString tmp = multilengthEos != -1 ? text.mid(0, multilengthEos) : text;
                 tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
                 layout.setText(tmp);
             }
@@ -653,7 +654,7 @@ QRect QQuickTextPrivate::setupTextLayout()
     const bool verticalFit = fontSizeMode & QQuickText::VerticalFit
             && (q->heightValid() || (maximumLineCountValid && canWrap));
     const bool pixelSize = font.pixelSize() != -1;
-    const QString layoutText = layout.text();
+    QString layoutText = layout.text();
 
     int largeFont = pixelSize ? font.pixelSize() : font.pointSize();
     int smallFont = fontSizeMode != QQuickText::FixedSize
@@ -674,7 +675,9 @@ QRect QQuickTextPrivate::setupTextLayout()
 
     naturalWidth = 0;
 
-    do {
+    int eos = multilengthEos;
+
+    for (;;) {
         if (!once) {
             if (pixelSize)
                 scaledFont.setPixelSize(scaledFontSize);
@@ -796,6 +799,16 @@ QRect QQuickTextPrivate::setupTextLayout()
             }
         }
 
+        if (eos != -1 && elide) {
+            int start = eos + 1;
+            eos = text.indexOf(QLatin1Char('\x9c'),  start);
+            layoutText = text.mid(start, eos != -1 ? eos - start : -1);
+            layoutText.replace(QLatin1Char('\n'), QChar::LineSeparator);
+            layout.setText(layoutText);
+            textHasChanged = true;
+            continue;
+        }
+
         QRectF unelidedRect = br.united(line.naturalTextRect());
 
         if (horizontalFit) {
@@ -826,7 +839,13 @@ QRect QQuickTextPrivate::setupTextLayout()
                     break;
             }
         }
-    } while (horizontalFit || verticalFit);
+
+        if (!horizontalFit && !verticalFit)
+            break;
+    }
+
+    if (eos != multilengthEos)
+        truncated = true;
 
     if (elide) {
         if (!elideLayout)
@@ -1878,7 +1897,7 @@ void QQuickText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeo
             goto geomChangeDone; // Multiline eliding not affected if we're already at max line count and we get higher.
     }
 
-    if (d->updateOnComponentComplete) {
+    if (d->updateOnComponentComplete || d->textHasChanged) {
         // We need to re-elide
         d->updateLayout();
     } else {
index 6fdde31..0a7fc74 100644 (file)
@@ -104,6 +104,7 @@ public:
     int maximumLineCount;
     int maximumLineCountValid;
     QQuickText::FontSizeMode fontSizeMode;
+    int multilengthEos;
     int minimumPixelSize;
     int minimumPointSize;
     QPointF elidePos;
diff --git a/tests/auto/qtquick2/qquicktext/data/multilengthStrings.qml b/tests/auto/qtquick2/qquicktext/data/multilengthStrings.qml
new file mode 100644 (file)
index 0000000..d26576e
--- /dev/null
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+Item {
+    width: 300
+    height: 200
+
+    Text {
+        id: myText
+        objectName: "myText"
+        width: 100
+        font.pixelSize: 15
+        font.family: "Helvetica"
+    }
+}
diff --git a/tests/auto/qtquick2/qquicktext/data/multilengthStringsWrapped.qml b/tests/auto/qtquick2/qquicktext/data/multilengthStringsWrapped.qml
new file mode 100644 (file)
index 0000000..0da9bc3
--- /dev/null
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+Item {
+    width: 300
+    height: 200
+
+    Text {
+        id: myText
+        objectName: "myText"
+        width: 100
+        height: 36
+        font.pixelSize: 15
+        font.family: "Helvetica"
+        wrapMode: Text.Wrap
+    }
+}
index 4f1225e..cbe3d30 100644 (file)
@@ -120,6 +120,8 @@ private slots:
     void fontSizeMode();
     void fontSizeModeMultiline_data();
     void fontSizeModeMultiline();
+    void multilengthStrings_data();
+    void multilengthStrings();
 
 private:
     QStringList standard;
@@ -2362,6 +2364,70 @@ void tst_qquicktext::fontSizeModeMultiline()
     }
 }
 
+void tst_qquicktext::multilengthStrings_data()
+{
+    QTest::addColumn<QString>("source");
+    QTest::newRow("No Wrap") << testFile("multilengthStrings.qml");
+    QTest::newRow("Wrap") << testFile("multilengthStringsWrapped.qml");
+}
+
+void tst_qquicktext::multilengthStrings()
+{
+    QFETCH(QString, source);
+
+    QScopedPointer<QQuickView> canvas(createView(source));
+    canvas->show();
+
+    QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
+    QVERIFY(myText != 0);
+
+    const QString longText = "the quick brown fox jumped over the lazy dog";
+    const QString mediumText = "the brown fox jumped over the dog";
+    const QString shortText = "fox jumped dog";
+
+    myText->setText(longText);
+    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+    const qreal longWidth = myText->contentWidth();
+    const qreal longHeight = myText->contentHeight();
+
+    myText->setText(mediumText);
+    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+    const qreal mediumWidth = myText->contentWidth();
+    const qreal mediumHeight = myText->contentHeight();
+
+    myText->setText(shortText);
+    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+    const qreal shortWidth = myText->contentWidth();
+    const qreal shortHeight = myText->contentHeight();
+
+    myText->setElideMode(QQuickText::ElideRight);
+    myText->setText(longText + QLatin1Char('\x9c') + mediumText + QLatin1Char('\x9c') + shortText);
+
+    myText->setSize(QSizeF(longWidth, longHeight));
+    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+
+    QCOMPARE(myText->contentWidth(), longWidth);
+    QCOMPARE(myText->contentHeight(), longHeight);
+    QCOMPARE(myText->truncated(), false);
+
+    myText->setSize(QSizeF(mediumWidth, mediumHeight));
+    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+
+    QCOMPARE(myText->contentWidth(), mediumWidth);
+    QCOMPARE(myText->contentHeight(), mediumHeight);
+#ifdef Q_OS_MAC
+    QEXPECT_FAIL("Wrap", "QTBUG-24310", Continue);
+#endif
+    QCOMPARE(myText->truncated(), true);
+
+    myText->setSize(QSizeF(shortWidth, shortHeight));
+    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+
+    QCOMPARE(myText->contentWidth(), shortWidth);
+    QCOMPARE(myText->contentHeight(), shortHeight);
+    QCOMPARE(myText->truncated(), true);
+}
+
 QTEST_MAIN(tst_qquicktext)
 
 #include "tst_qquicktext.moc"