1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtTest/QSignalSpy>
43 #include <QTextDocument>
44 #include <QtQml/qqmlengine.h>
45 #include <QtQml/qqmlcomponent.h>
46 #include <QtQuick/private/qquicktext_p.h>
47 #include <private/qquicktext_p_p.h>
48 #include <private/qquickvaluetypes_p.h>
49 #include <QFontMetrics>
51 #include <QtQuick/QQuickView>
52 #include <private/qguiapplication_p.h>
54 #include <QtGui/QMouseEvent>
55 #include "../../shared/util.h"
56 #include "testhttpserver.h"
58 DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
60 Q_DECLARE_METATYPE(QQuickText::TextFormat)
62 class tst_qquicktext : public QQmlDataTest
73 void multilineElide_data();
74 void multilineElide();
75 void implicitElide_data();
79 void alignments_data();
83 void embeddedImages_data();
84 void embeddedImages();
89 // ### these tests may be trivial
90 void horizontalAlignment();
91 void horizontalAlignment_RightToLeft();
92 void verticalAlignment();
93 void hAlignImplicitWidth();
99 // QQuickFontValueType
104 void capitalization();
105 void letterSpacing();
110 void implicitSize_data();
113 void implicitSizeBinding_data();
114 void implicitSizeBinding();
116 void boundingRect_data();
121 void imgTagsBaseUrl_data();
122 void imgTagsBaseUrl();
123 void imgTagsAlign_data();
125 void imgTagsMultipleImages();
127 void imgTagsUpdates();
129 void fontSizeMode_data();
131 void fontSizeModeMultiline_data();
132 void fontSizeModeMultiline();
133 void multilengthStrings_data();
134 void multilengthStrings();
135 void fontFormatSizes_data();
136 void fontFormatSizes();
138 void baselineOffset_data();
139 void baselineOffset();
142 void htmlLists_data();
145 QStringList standard;
146 QStringList richText;
148 QStringList horizontalAlignmentmentStrings;
149 QStringList verticalAlignmentmentStrings;
151 QList<Qt::Alignment> verticalAlignmentments;
152 QList<Qt::Alignment> horizontalAlignmentments;
154 QStringList styleStrings;
155 QList<QQuickText::TextStyle> styles;
157 QStringList colorStrings;
161 QQuickView *createView(const QString &filename);
162 int numberOfNonWhitePixels(int fromX, int toX, const QImage &image);
165 tst_qquicktext::tst_qquicktext()
167 standard << "the quick brown fox jumped over the lazy dog"
168 << "the quick brown fox\n jumped over the lazy dog";
170 richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
171 << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
173 horizontalAlignmentmentStrings << "AlignLeft"
177 verticalAlignmentmentStrings << "AlignTop"
181 horizontalAlignmentments << Qt::AlignLeft
185 verticalAlignmentments << Qt::AlignTop
189 styleStrings << "Normal"
194 styles << QQuickText::Normal
195 << QQuickText::Outline
196 << QQuickText::Raised
197 << QQuickText::Sunken;
199 colorStrings << "aliceblue"
212 // need a different test to do alpha channel test
218 QQuickView *tst_qquicktext::createView(const QString &filename)
220 QQuickView *canvas = new QQuickView(0);
222 canvas->setSource(QUrl::fromLocalFile(filename));
226 void tst_qquicktext::text()
229 QQmlComponent textComponent(&engine);
230 textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
231 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
233 QVERIFY(textObject != 0);
234 QCOMPARE(textObject->text(), QString(""));
235 QVERIFY(textObject->width() == 0);
240 for (int i = 0; i < standard.size(); i++)
242 QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
243 QQmlComponent textComponent(&engine);
244 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
246 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
248 QVERIFY(textObject != 0);
249 QCOMPARE(textObject->text(), standard.at(i));
250 QVERIFY(textObject->width() > 0);
255 for (int i = 0; i < richText.size(); i++)
257 QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }";
258 QQmlComponent textComponent(&engine);
259 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
260 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
262 QVERIFY(textObject != 0);
263 QString expected = richText.at(i);
264 QCOMPARE(textObject->text(), expected.replace("\\\"", "\""));
265 QVERIFY(textObject->width() > 0);
271 void tst_qquicktext::width()
273 // uses Font metrics to find the width for standard and document to find the width for rich
275 QQmlComponent textComponent(&engine);
276 textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
277 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
279 QVERIFY(textObject != 0);
280 QCOMPARE(textObject->width(), 0.);
285 bool requiresUnhintedMetrics = !qmlDisableDistanceField();
287 for (int i = 0; i < standard.size(); i++)
289 QVERIFY(!Qt::mightBeRichText(standard.at(i))); // self-test
292 qreal metricWidth = 0.0;
294 if (requiresUnhintedMetrics) {
295 QString s = standard.at(i);
296 s.replace(QLatin1Char('\n'), QChar::LineSeparator);
298 QTextLayout layout(s);
299 layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic);
302 option.setUseDesignMetrics(true);
303 layout.setTextOption(option);
306 layout.beginLayout();
308 QTextLine line = layout.createLine();
315 metricWidth = layout.boundingRect().width();
318 metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
321 QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
322 QQmlComponent textComponent(&engine);
323 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
324 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
326 QVERIFY(textObject != 0);
327 QVERIFY(textObject->boundingRect().width() > 0);
328 QCOMPARE(textObject->width(), qreal(metricWidth));
329 QVERIFY(textObject->textFormat() == QQuickText::AutoText); // setting text doesn't change format
334 for (int i = 0; i < richText.size(); i++)
336 QVERIFY(Qt::mightBeRichText(richText.at(i))); // self-test
338 QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\"; textFormat: Text.RichText }";
339 QQmlComponent textComponent(&engine);
340 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
341 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
342 QVERIFY(textObject != 0);
344 QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
345 QVERIFY(textPrivate != 0);
346 QVERIFY(textPrivate->extra.isAllocated());
348 QTextDocument *doc = textPrivate->extra->doc;
351 QCOMPARE(int(textObject->width()), int(doc->idealWidth()));
352 QVERIFY(textObject->textFormat() == QQuickText::RichText);
358 void tst_qquicktext::wrap()
361 // for specified width and wrap set true
363 QQmlComponent textComponent(&engine);
364 textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; wrapMode: Text.WordWrap; width: 300 }", QUrl::fromLocalFile(""));
365 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
366 textHeight = textObject->height();
368 QVERIFY(textObject != 0);
369 QVERIFY(textObject->wrapMode() == QQuickText::WordWrap);
370 QCOMPARE(textObject->width(), 300.);
375 for (int i = 0; i < standard.size(); i++)
377 QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + standard.at(i) + "\" }";
378 QQmlComponent textComponent(&engine);
379 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
380 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
382 QVERIFY(textObject != 0);
383 QCOMPARE(textObject->width(), 30.);
384 QVERIFY(textObject->height() > textHeight);
386 int oldHeight = textObject->height();
387 textObject->setWidth(100);
388 QVERIFY(textObject->height() < oldHeight);
393 for (int i = 0; i < richText.size(); i++)
395 QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + richText.at(i) + "\" }";
396 QQmlComponent textComponent(&engine);
397 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
398 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
400 QVERIFY(textObject != 0);
401 QCOMPARE(textObject->width(), 30.);
402 QVERIFY(textObject->height() > textHeight);
404 qreal oldHeight = textObject->height();
405 textObject->setWidth(100);
406 QVERIFY(textObject->height() < oldHeight);
411 // richtext again with a fixed height
412 for (int i = 0; i < richText.size(); i++)
414 QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; height: 50; text: \"" + richText.at(i) + "\" }";
415 QQmlComponent textComponent(&engine);
416 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
417 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
419 QVERIFY(textObject != 0);
420 QCOMPARE(textObject->width(), 30.);
421 QVERIFY(textObject->implicitHeight() > textHeight);
423 qreal oldHeight = textObject->implicitHeight();
424 textObject->setWidth(100);
425 QVERIFY(textObject->implicitHeight() < oldHeight);
431 void tst_qquicktext::elide()
433 for (QQuickText::TextElideMode m = QQuickText::ElideLeft; m<=QQuickText::ElideNone; m=QQuickText::TextElideMode(int(m)+1)) {
434 const char* elidename[]={"ElideLeft", "ElideRight", "ElideMiddle", "ElideNone"};
435 QString elide = "elide: Text." + QString(elidename[int(m)]) + ";";
437 // XXX Poor coverage.
440 QQmlComponent textComponent(&engine);
441 textComponent.setData(("import QtQuick 2.0\nText { text: \"\"; "+elide+" width: 100 }").toLatin1(), QUrl::fromLocalFile(""));
442 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
444 QCOMPARE(textObject->elideMode(), m);
445 QCOMPARE(textObject->width(), 100.);
450 for (int i = 0; i < standard.size(); i++)
452 QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + standard.at(i) + "\" }";
453 QQmlComponent textComponent(&engine);
454 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
455 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
457 QCOMPARE(textObject->elideMode(), m);
458 QCOMPARE(textObject->width(), 100.);
460 if (m != QQuickText::ElideNone && !standard.at(i).contains('\n'))
461 QVERIFY(textObject->contentWidth() <= textObject->width());
466 for (int i = 0; i < richText.size(); i++)
468 QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + richText.at(i) + "\" }";
469 QQmlComponent textComponent(&engine);
470 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
471 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
473 QCOMPARE(textObject->elideMode(), m);
474 QCOMPARE(textObject->width(), 100.);
476 if (m != QQuickText::ElideNone && standard.at(i).contains("<br>"))
477 QVERIFY(textObject->contentWidth() <= textObject->width());
484 void tst_qquicktext::multilineElide_data()
486 QTest::addColumn<QQuickText::TextFormat>("format");
487 QTest::newRow("plain") << QQuickText::PlainText;
488 QTest::newRow("styled") << QQuickText::StyledText;
491 void tst_qquicktext::multilineElide()
493 QFETCH(QQuickText::TextFormat, format);
494 QQuickView *canvas = createView(testFile("multilineelide.qml"));
496 QQuickText *myText = qobject_cast<QQuickText*>(canvas->rootObject());
497 QVERIFY(myText != 0);
498 myText->setTextFormat(format);
500 QCOMPARE(myText->lineCount(), 3);
501 QCOMPARE(myText->truncated(), true);
503 qreal lineHeight = myText->contentHeight() / 3.;
505 // Set a valid height greater than the truncated content height and ensure the line count is
507 myText->setHeight(200);
508 QCOMPARE(myText->lineCount(), 3);
509 QCOMPARE(myText->truncated(), true);
511 // reduce size and ensure fewer lines are drawn
512 myText->setHeight(lineHeight * 2);
513 QCOMPARE(myText->lineCount(), 2);
515 myText->setHeight(lineHeight);
516 QCOMPARE(myText->lineCount(), 1);
518 myText->setHeight(5);
519 QCOMPARE(myText->lineCount(), 1);
521 myText->setHeight(lineHeight * 3);
522 QCOMPARE(myText->lineCount(), 3);
524 // remove max count and show all lines.
525 myText->setHeight(1000);
526 myText->resetMaximumLineCount();
528 QCOMPARE(myText->truncated(), false);
531 myText->setHeight(lineHeight * 2);
532 QCOMPARE(myText->lineCount(), 2);
533 QCOMPARE(myText->truncated(), true);
535 // change line height
536 myText->setLineHeight(1.1);
537 QCOMPARE(myText->lineCount(), 1);
542 void tst_qquicktext::implicitElide_data()
544 QTest::addColumn<QString>("width");
545 QTest::addColumn<QString>("initialText");
546 QTest::addColumn<QString>("text");
548 QTest::newRow("maximum width, empty")
549 << "Math.min(implicitWidth, 100)"
551 QTest::newRow("maximum width, short")
552 << "Math.min(implicitWidth, 100)"
554 QTest::newRow("maximum width, long")
555 << "Math.min(implicitWidth, 100)"
556 << "the quick brown fox jumped over the lazy dog";
557 QTest::newRow("reset width, empty")
558 << "implicitWidth > 100 ? 100 : undefined"
560 QTest::newRow("reset width, short")
561 << "implicitWidth > 100 ? 100 : undefined"
563 QTest::newRow("reset width, long")
564 << "implicitWidth > 100 ? 100 : undefined"
565 << "the quick brown fox jumped over the lazy dog";
568 void tst_qquicktext::implicitElide()
570 QFETCH(QString, width);
571 QFETCH(QString, initialText);
573 QString componentStr =
574 "import QtQuick 2.0\n"
576 "width: " + width + "\n"
577 "text: \"" + initialText + "\"\n"
578 "elide: Text.ElideRight\n"
580 QQmlComponent textComponent(&engine);
581 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
582 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
584 QVERIFY(textObject->contentWidth() <= textObject->width());
586 textObject->setText("the quick brown fox jumped over");
588 QVERIFY(textObject->contentWidth() > 0);
589 QVERIFY(textObject->contentWidth() <= textObject->width());
592 void tst_qquicktext::textFormat()
595 QQmlComponent textComponent(&engine);
596 textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
597 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
599 QVERIFY(textObject != 0);
600 QVERIFY(textObject->textFormat() == QQuickText::RichText);
602 QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
603 QVERIFY(textPrivate != 0);
604 QVERIFY(textPrivate->richText == true);
609 QQmlComponent textComponent(&engine);
610 textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\" }", QUrl::fromLocalFile(""));
611 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
613 QVERIFY(textObject != 0);
614 QVERIFY(textObject->textFormat() == QQuickText::AutoText);
616 QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
617 QVERIFY(textPrivate != 0);
618 QVERIFY(textPrivate->styledText == true);
623 QQmlComponent textComponent(&engine);
624 textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
625 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
627 QVERIFY(textObject != 0);
628 QVERIFY(textObject->textFormat() == QQuickText::PlainText);
635 void tst_qquicktext::alignments_data()
637 QTest::addColumn<int>("hAlign");
638 QTest::addColumn<int>("vAlign");
639 QTest::addColumn<QString>("expectfile");
641 QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << testFile("alignments_lt.png");
642 QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << testFile("alignments_rt.png");
643 QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << testFile("alignments_ct.png");
645 QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << testFile("alignments_lb.png");
646 QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << testFile("alignments_rb.png");
647 QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << testFile("alignments_cb.png");
649 QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << testFile("alignments_lc.png");
650 QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << testFile("alignments_rc.png");
651 QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << testFile("alignments_cc.png");
655 void tst_qquicktext::alignments()
657 QSKIP("Text alignment pixmap comparison tests will not work with scenegraph");
658 #if (0)// No widgets in scenegraph
661 QFETCH(QString, expectfile);
663 QQuickView *canvas = createView(testFile("alignments.qml"));
665 canvas->requestActivateWindow();
667 QTRY_COMPARE(QGuiApplication::activeWindow(), static_cast<QWidget *>(canvas));
669 QObject *ob = canvas->rootObject();
671 ob->setProperty("horizontalAlignment",hAlign);
672 ob->setProperty("verticalAlignment",vAlign);
673 QTRY_COMPARE(ob->property("running").toBool(),false);
674 QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32);
675 actual.fill(qRgb(255,255,255));
679 QImage expect(expectfile);
680 if (QGuiApplicationPrivate::graphics_system_name == "raster" || QGuiApplicationPrivate::graphics_system_name == "") {
681 QCOMPARE(actual,expect);
687 //the alignment tests may be trivial o.oa
688 void tst_qquicktext::horizontalAlignment()
690 //test one align each, and then test if two align fails.
692 for (int i = 0; i < standard.size(); i++)
694 for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
696 QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
697 QQmlComponent textComponent(&engine);
698 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
699 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
701 QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
707 for (int i = 0; i < richText.size(); i++)
709 for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
711 QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
712 QQmlComponent textComponent(&engine);
713 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
714 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
716 QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
724 void tst_qquicktext::horizontalAlignment_RightToLeft()
726 QQuickView *canvas = createView(testFile("horizontalAlignment_RightToLeft.qml"));
727 QQuickText *text = canvas->rootObject()->findChild<QQuickText*>("text");
731 QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(text);
732 QVERIFY(textPrivate != 0);
734 QTRY_VERIFY(textPrivate->layout.lineCount());
736 // implicit alignment should follow the reading direction of RTL text
737 QCOMPARE(text->hAlign(), QQuickText::AlignRight);
738 QCOMPARE(text->effectiveHAlign(), text->hAlign());
739 QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
741 // explicitly left aligned text
742 text->setHAlign(QQuickText::AlignLeft);
743 QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
744 QCOMPARE(text->effectiveHAlign(), text->hAlign());
745 QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
747 // explicitly right aligned text
748 text->setHAlign(QQuickText::AlignRight);
749 QCOMPARE(text->hAlign(), QQuickText::AlignRight);
750 QCOMPARE(text->effectiveHAlign(), text->hAlign());
751 QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
753 // change to rich text
754 QString textString = text->text();
755 text->setText(QString("<i>") + textString + QString("</i>"));
756 text->setTextFormat(QQuickText::RichText);
759 // implicitly aligned rich text should follow the reading direction of text
760 QCOMPARE(text->hAlign(), QQuickText::AlignRight);
761 QCOMPARE(text->effectiveHAlign(), text->hAlign());
762 QVERIFY(textPrivate->extra.isAllocated());
763 QVERIFY(textPrivate->extra->doc->defaultTextOption().alignment() & Qt::AlignLeft);
765 // explicitly left aligned rich text
766 text->setHAlign(QQuickText::AlignLeft);
767 QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
768 QCOMPARE(text->effectiveHAlign(), text->hAlign());
769 QVERIFY(textPrivate->extra->doc->defaultTextOption().alignment() & Qt::AlignRight);
771 // explicitly right aligned rich text
772 text->setHAlign(QQuickText::AlignRight);
773 QCOMPARE(text->hAlign(), QQuickText::AlignRight);
774 QCOMPARE(text->effectiveHAlign(), text->hAlign());
775 QVERIFY(textPrivate->extra->doc->defaultTextOption().alignment() & Qt::AlignLeft);
777 text->setText(textString);
778 text->setTextFormat(QQuickText::PlainText);
780 // explicitly center aligned
781 text->setHAlign(QQuickText::AlignHCenter);
782 QCOMPARE(text->hAlign(), QQuickText::AlignHCenter);
783 QCOMPARE(text->effectiveHAlign(), text->hAlign());
784 QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
785 QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().right() > canvas->width()/2);
787 // reseted alignment should go back to following the text reading direction
789 QCOMPARE(text->hAlign(), QQuickText::AlignRight);
790 QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
792 // mirror the text item
793 QQuickItemPrivate::get(text)->setLayoutMirror(true);
795 // mirrored implicit alignment should continue to follow the reading direction of the text
796 QCOMPARE(text->hAlign(), QQuickText::AlignRight);
797 QCOMPARE(text->effectiveHAlign(), QQuickText::AlignRight);
798 QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
800 // mirrored explicitly right aligned behaves as left aligned
801 text->setHAlign(QQuickText::AlignRight);
802 QCOMPARE(text->hAlign(), QQuickText::AlignRight);
803 QCOMPARE(text->effectiveHAlign(), QQuickText::AlignLeft);
804 QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
806 // mirrored explicitly left aligned behaves as right aligned
807 text->setHAlign(QQuickText::AlignLeft);
808 QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
809 QCOMPARE(text->effectiveHAlign(), QQuickText::AlignRight);
810 QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
813 QQuickItemPrivate::get(text)->setLayoutMirror(false);
816 // English text should be implicitly left aligned
817 text->setText("Hello world!");
818 QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
819 QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
821 // empty text with implicit alignment follows the system locale-based
822 // keyboard input direction from QInputMethod::inputDirection()
824 QCOMPARE(text->hAlign(), qApp->inputMethod()->inputDirection() == Qt::LeftToRight ?
825 QQuickText::AlignLeft : QQuickText::AlignRight);
826 text->setHAlign(QQuickText::AlignRight);
827 QCOMPARE(text->hAlign(), QQuickText::AlignRight);
831 // alignment of Text with no text set to it
832 QString componentStr = "import QtQuick 2.0\nText {}";
833 QQmlComponent textComponent(&engine);
834 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
835 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
836 QCOMPARE(textObject->hAlign(), qApp->inputMethod()->inputDirection() == Qt::LeftToRight ?
837 QQuickText::AlignLeft : QQuickText::AlignRight);
841 int tst_qquicktext::numberOfNonWhitePixels(int fromX, int toX, const QImage &image)
844 for (int x = fromX; x < toX; ++x) {
845 for (int y = 0; y < image.height(); ++y) {
846 if (image.pixel(x, y) != qRgb(255, 255, 255))
853 void tst_qquicktext::hAlignImplicitWidth()
855 QQuickView view(testFileUrl("hAlignImplicitWidth.qml"));
857 view.requestActivateWindow();
858 QTest::qWaitForWindowShown(&view);
860 QQuickText *text = view.rootObject()->findChild<QQuickText*>("textItem");
865 QImage image = view.grabFrameBuffer();
866 int left = numberOfNonWhitePixels(0, image.width() / 3, image);
867 int mid = numberOfNonWhitePixels(image.width() / 3, 2 * image.width() / 3, image);
868 int right = numberOfNonWhitePixels( 2 * image.width() / 3, image.width(), image);
870 QVERIFY(mid > right);
874 text->setHAlign(QQuickText::AlignHCenter);
875 QImage image = view.grabFrameBuffer();
876 int left = numberOfNonWhitePixels(0, image.width() / 3, image);
877 int mid = numberOfNonWhitePixels(image.width() / 3, 2 * image.width() / 3, image);
878 int right = numberOfNonWhitePixels( 2 * image.width() / 3, image.width(), image);
880 QVERIFY(mid > right);
884 text->setHAlign(QQuickText::AlignRight);
885 QImage image = view.grabFrameBuffer();
886 int left = numberOfNonWhitePixels(0, image.width() / 3, image);
887 int mid = numberOfNonWhitePixels(image.width() / 3, 2 * image.width() / 3, image);
888 int right = numberOfNonWhitePixels( 2 * image.width() / 3, image.width(), image);
890 QVERIFY(mid < right);
894 void tst_qquicktext::verticalAlignment()
896 //test one align each, and then test if two align fails.
898 for (int i = 0; i < standard.size(); i++)
900 for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
902 QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
903 QQmlComponent textComponent(&engine);
904 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
905 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
907 QVERIFY(textObject != 0);
908 QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
914 for (int i = 0; i < richText.size(); i++)
916 for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
918 QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
919 QQmlComponent textComponent(&engine);
920 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
921 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
923 QVERIFY(textObject != 0);
924 QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
932 void tst_qquicktext::font()
934 //test size, then bold, then italic, then family
936 QString componentStr = "import QtQuick 2.0\nText { font.pointSize: 40; text: \"Hello World\" }";
937 QQmlComponent textComponent(&engine);
938 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
939 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
941 QCOMPARE(textObject->font().pointSize(), 40);
942 QCOMPARE(textObject->font().bold(), false);
943 QCOMPARE(textObject->font().italic(), false);
949 QString componentStr = "import QtQuick 2.0\nText { font.pixelSize: 40; text: \"Hello World\" }";
950 QQmlComponent textComponent(&engine);
951 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
952 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
954 QCOMPARE(textObject->font().pixelSize(), 40);
955 QCOMPARE(textObject->font().bold(), false);
956 QCOMPARE(textObject->font().italic(), false);
962 QString componentStr = "import QtQuick 2.0\nText { font.bold: true; text: \"Hello World\" }";
963 QQmlComponent textComponent(&engine);
964 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
965 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
967 QCOMPARE(textObject->font().bold(), true);
968 QCOMPARE(textObject->font().italic(), false);
974 QString componentStr = "import QtQuick 2.0\nText { font.italic: true; text: \"Hello World\" }";
975 QQmlComponent textComponent(&engine);
976 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
977 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
979 QCOMPARE(textObject->font().italic(), true);
980 QCOMPARE(textObject->font().bold(), false);
986 QString componentStr = "import QtQuick 2.0\nText { font.family: \"Helvetica\"; text: \"Hello World\" }";
987 QQmlComponent textComponent(&engine);
988 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
989 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
991 QCOMPARE(textObject->font().family(), QString("Helvetica"));
992 QCOMPARE(textObject->font().bold(), false);
993 QCOMPARE(textObject->font().italic(), false);
999 QString componentStr = "import QtQuick 2.0\nText { font.family: \"\"; text: \"Hello World\" }";
1000 QQmlComponent textComponent(&engine);
1001 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1002 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1004 QCOMPARE(textObject->font().family(), QString(""));
1010 void tst_qquicktext::style()
1013 for (int i = 0; i < styles.size(); i++)
1015 QString componentStr = "import QtQuick 2.0\nText { style: \"" + styleStrings.at(i) + "\"; styleColor: \"white\"; text: \"Hello World\" }";
1016 QQmlComponent textComponent(&engine);
1017 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1018 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1020 QCOMPARE((int)textObject->style(), (int)styles.at(i));
1021 QCOMPARE(textObject->styleColor(), QColor("white"));
1025 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello World\" }";
1026 QQmlComponent textComponent(&engine);
1027 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1028 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1030 QRectF brPre = textObject->boundingRect();
1031 textObject->setStyle(QQuickText::Outline);
1032 QRectF brPost = textObject->boundingRect();
1034 QVERIFY(brPre.width() < brPost.width());
1035 QVERIFY(brPre.height() < brPost.height());
1040 void tst_qquicktext::color()
1043 for (int i = 0; i < colorStrings.size(); i++)
1045 QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
1046 QQmlComponent textComponent(&engine);
1047 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1048 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1050 QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
1051 QCOMPARE(textObject->styleColor(), QColor("black"));
1052 QCOMPARE(textObject->linkColor(), QColor("blue"));
1057 for (int i = 0; i < colorStrings.size(); i++)
1059 QString componentStr = "import QtQuick 2.0\nText { styleColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
1060 QQmlComponent textComponent(&engine);
1061 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1062 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1064 QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(i)));
1065 // default color to black?
1066 QCOMPARE(textObject->color(), QColor("black"));
1067 QCOMPARE(textObject->linkColor(), QColor("blue"));
1072 for (int i = 0; i < colorStrings.size(); i++)
1074 QString componentStr = "import QtQuick 2.0\nText { linkColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
1075 QQmlComponent textComponent(&engine);
1076 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1077 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1079 QCOMPARE(textObject->styleColor(), QColor("black"));
1080 QCOMPARE(textObject->color(), QColor("black"));
1081 QCOMPARE(textObject->linkColor(), QColor(colorStrings.at(i)));
1086 for (int i = 0; i < colorStrings.size(); i++)
1088 for (int j = 0; j < colorStrings.size(); j++)
1090 QString componentStr = "import QtQuick 2.0\nText { "
1091 "color: \"" + colorStrings.at(i) + "\"; "
1092 "styleColor: \"" + colorStrings.at(j) + "\"; "
1093 "linkColor: \"" + colorStrings.at(j) + "\"; "
1094 "text: \"Hello World\" }";
1095 QQmlComponent textComponent(&engine);
1096 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1097 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1099 QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
1100 QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(j)));
1101 QCOMPARE(textObject->linkColor(), QColor(colorStrings.at(j)));
1107 QString colorStr = "#AA001234";
1108 QColor testColor("#001234");
1109 testColor.setAlpha(170);
1111 QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStr + "\"; text: \"Hello World\" }";
1112 QQmlComponent textComponent(&engine);
1113 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1114 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1116 QCOMPARE(textObject->color(), testColor);
1120 QString colorStr = "#001234";
1121 QColor testColor(colorStr);
1123 QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStr + "\"; text: \"Hello World\" }";
1124 QQmlComponent textComponent(&engine);
1125 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1126 QScopedPointer<QObject> object(textComponent.create());
1127 QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
1129 QSignalSpy spy(textObject, SIGNAL(colorChanged()));
1131 QCOMPARE(textObject->color(), testColor);
1132 textObject->setColor(testColor);
1133 QCOMPARE(textObject->color(), testColor);
1134 QCOMPARE(spy.count(), 0);
1136 testColor = QColor("black");
1137 textObject->setColor(testColor);
1138 QCOMPARE(textObject->color(), testColor);
1139 QCOMPARE(spy.count(), 1);
1141 QString colorStr = "#001234";
1142 QColor testColor(colorStr);
1144 QString componentStr = "import QtQuick 2.0\nText { styleColor: \"" + colorStr + "\"; text: \"Hello World\" }";
1145 QQmlComponent textComponent(&engine);
1146 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1147 QScopedPointer<QObject> object(textComponent.create());
1148 QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
1150 QSignalSpy spy(textObject, SIGNAL(styleColorChanged()));
1152 QCOMPARE(textObject->styleColor(), testColor);
1153 textObject->setStyleColor(testColor);
1154 QCOMPARE(textObject->styleColor(), testColor);
1155 QCOMPARE(spy.count(), 0);
1157 testColor = QColor("black");
1158 textObject->setStyleColor(testColor);
1159 QCOMPARE(textObject->styleColor(), testColor);
1160 QCOMPARE(spy.count(), 1);
1162 QString colorStr = "#001234";
1163 QColor testColor(colorStr);
1165 QString componentStr = "import QtQuick 2.0\nText { linkColor: \"" + colorStr + "\"; text: \"Hello World\" }";
1166 QQmlComponent textComponent(&engine);
1167 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1168 QScopedPointer<QObject> object(textComponent.create());
1169 QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
1171 QSignalSpy spy(textObject, SIGNAL(linkColorChanged()));
1173 QCOMPARE(textObject->linkColor(), testColor);
1174 textObject->setLinkColor(testColor);
1175 QCOMPARE(textObject->linkColor(), testColor);
1176 QCOMPARE(spy.count(), 0);
1178 testColor = QColor("black");
1179 textObject->setLinkColor(testColor);
1180 QCOMPARE(textObject->linkColor(), testColor);
1181 QCOMPARE(spy.count(), 1);
1185 void tst_qquicktext::smooth()
1187 for (int i = 0; i < standard.size(); i++)
1190 QString componentStr = "import QtQuick 2.0\nText { smooth: false; text: \"" + standard.at(i) + "\" }";
1191 QQmlComponent textComponent(&engine);
1192 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1193 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1194 QCOMPARE(textObject->smooth(), false);
1199 QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
1200 QQmlComponent textComponent(&engine);
1201 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1202 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1203 QCOMPARE(textObject->smooth(), true);
1208 for (int i = 0; i < richText.size(); i++)
1211 QString componentStr = "import QtQuick 2.0\nText { smooth: false; text: \"" + richText.at(i) + "\" }";
1212 QQmlComponent textComponent(&engine);
1213 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1214 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1215 QCOMPARE(textObject->smooth(), false);
1220 QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }";
1221 QQmlComponent textComponent(&engine);
1222 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1223 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1224 QCOMPARE(textObject->smooth(), true);
1231 void tst_qquicktext::weight()
1234 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
1235 QQmlComponent textComponent(&engine);
1236 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1237 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1239 QVERIFY(textObject != 0);
1240 QCOMPARE((int)textObject->font().weight(), (int)QQuickFontValueType::Normal);
1245 QString componentStr = "import QtQuick 2.0\nText { font.weight: \"Bold\"; text: \"Hello world!\" }";
1246 QQmlComponent textComponent(&engine);
1247 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1248 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1250 QVERIFY(textObject != 0);
1251 QCOMPARE((int)textObject->font().weight(), (int)QQuickFontValueType::Bold);
1257 void tst_qquicktext::underline()
1259 QQuickView view(testFileUrl("underline.qml"));
1261 view.requestActivateWindow();
1262 QTest::qWaitForWindowShown(&view);
1263 QQuickText *textObject = view.rootObject()->findChild<QQuickText*>("myText");
1264 QVERIFY(textObject != 0);
1265 QCOMPARE(textObject->font().overline(), false);
1266 QCOMPARE(textObject->font().underline(), true);
1267 QCOMPARE(textObject->font().strikeOut(), false);
1270 void tst_qquicktext::overline()
1272 QQuickView view(testFileUrl("overline.qml"));
1274 view.requestActivateWindow();
1275 QTest::qWaitForWindowShown(&view);
1276 QQuickText *textObject = view.rootObject()->findChild<QQuickText*>("myText");
1277 QVERIFY(textObject != 0);
1278 QCOMPARE(textObject->font().overline(), true);
1279 QCOMPARE(textObject->font().underline(), false);
1280 QCOMPARE(textObject->font().strikeOut(), false);
1283 void tst_qquicktext::strikeout()
1285 QQuickView view(testFileUrl("strikeout.qml"));
1287 view.requestActivateWindow();
1288 QTest::qWaitForWindowShown(&view);
1289 QQuickText *textObject = view.rootObject()->findChild<QQuickText*>("myText");
1290 QVERIFY(textObject != 0);
1291 QCOMPARE(textObject->font().overline(), false);
1292 QCOMPARE(textObject->font().underline(), false);
1293 QCOMPARE(textObject->font().strikeOut(), true);
1296 void tst_qquicktext::capitalization()
1299 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
1300 QQmlComponent textComponent(&engine);
1301 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1302 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1304 QVERIFY(textObject != 0);
1305 QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::MixedCase);
1310 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllUppercase\" }";
1311 QQmlComponent textComponent(&engine);
1312 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1313 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1315 QVERIFY(textObject != 0);
1316 QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::AllUppercase);
1321 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllLowercase\" }";
1322 QQmlComponent textComponent(&engine);
1323 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1324 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1326 QVERIFY(textObject != 0);
1327 QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::AllLowercase);
1332 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"SmallCaps\" }";
1333 QQmlComponent textComponent(&engine);
1334 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1335 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1337 QVERIFY(textObject != 0);
1338 QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::SmallCaps);
1343 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"Capitalize\" }";
1344 QQmlComponent textComponent(&engine);
1345 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1346 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1348 QVERIFY(textObject != 0);
1349 QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::Capitalize);
1355 void tst_qquicktext::letterSpacing()
1358 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
1359 QQmlComponent textComponent(&engine);
1360 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1361 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1363 QVERIFY(textObject != 0);
1364 QCOMPARE(textObject->font().letterSpacing(), 0.0);
1369 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: -2 }";
1370 QQmlComponent textComponent(&engine);
1371 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1372 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1374 QVERIFY(textObject != 0);
1375 QCOMPARE(textObject->font().letterSpacing(), -2.);
1380 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: 3 }";
1381 QQmlComponent textComponent(&engine);
1382 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1383 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1385 QVERIFY(textObject != 0);
1386 QCOMPARE(textObject->font().letterSpacing(), 3.);
1392 void tst_qquicktext::wordSpacing()
1395 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
1396 QQmlComponent textComponent(&engine);
1397 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1398 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1400 QVERIFY(textObject != 0);
1401 QCOMPARE(textObject->font().wordSpacing(), 0.0);
1406 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: -50 }";
1407 QQmlComponent textComponent(&engine);
1408 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1409 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1411 QVERIFY(textObject != 0);
1412 QCOMPARE(textObject->font().wordSpacing(), -50.);
1417 QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: 200 }";
1418 QQmlComponent textComponent(&engine);
1419 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1420 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1422 QVERIFY(textObject != 0);
1423 QCOMPARE(textObject->font().wordSpacing(), 200.);
1432 class EventSender : public QQuickItem
1435 void sendEvent(QMouseEvent *event) {
1436 if (event->type() == QEvent::MouseButtonPress)
1437 mousePressEvent(event);
1438 else if (event->type() == QEvent::MouseButtonRelease)
1439 mouseReleaseEvent(event);
1441 qWarning() << "Trying to send unsupported event type";
1445 class LinkTest : public QObject
1454 void linkClicked(QString l) { link = l; }
1457 void tst_qquicktext::clickLink()
1460 QString componentStr = "import QtQuick 2.0\nText { text: \"<a href=\\\"http://qt.nokia.com\\\">Hello world!</a>\" }";
1461 QQmlComponent textComponent(&engine);
1462 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1463 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1465 QVERIFY(textObject != 0);
1468 QObject::connect(textObject, SIGNAL(linkActivated(QString)), &test, SLOT(linkClicked(QString)));
1471 QMouseEvent me(QEvent::MouseButtonPress,QPointF(textObject->x()/2, textObject->y()/2), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1472 static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me);
1477 QMouseEvent me(QEvent::MouseButtonRelease,QPointF(textObject->x()/2, textObject->y()/2), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1478 static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me);
1483 QCOMPARE(test.link, QLatin1String("http://qt.nokia.com"));
1489 void tst_qquicktext::baseUrl()
1491 QUrl localUrl("file:///tests/text.qml");
1492 QUrl remoteUrl("http://qt.nokia.com/test.qml");
1494 QQmlComponent textComponent(&engine);
1495 textComponent.setData("import QtQuick 2.0\n Text {}", localUrl);
1496 QQuickText *textObject = qobject_cast<QQuickText *>(textComponent.create());
1498 QCOMPARE(textObject->baseUrl(), localUrl);
1500 QSignalSpy spy(textObject, SIGNAL(baseUrlChanged()));
1502 textObject->setBaseUrl(localUrl);
1503 QCOMPARE(textObject->baseUrl(), localUrl);
1504 QCOMPARE(spy.count(), 0);
1506 textObject->setBaseUrl(remoteUrl);
1507 QCOMPARE(textObject->baseUrl(), remoteUrl);
1508 QCOMPARE(spy.count(), 1);
1510 textObject->resetBaseUrl();
1511 QCOMPARE(textObject->baseUrl(), localUrl);
1512 QCOMPARE(spy.count(), 2);
1515 void tst_qquicktext::embeddedImages_data()
1517 QTest::addColumn<QUrl>("qmlfile");
1518 QTest::addColumn<QString>("error");
1519 QTest::newRow("local") << testFileUrl("embeddedImagesLocal.qml") << "";
1520 QTest::newRow("local-error") << testFileUrl("embeddedImagesLocalError.qml")
1521 << testFileUrl("embeddedImagesLocalError.qml").toString()+":3:1: QML Text: Cannot open: " + testFileUrl("http/notexists.png").toString();
1522 QTest::newRow("local") << testFileUrl("embeddedImagesLocalRelative.qml") << "";
1523 QTest::newRow("remote") << testFileUrl("embeddedImagesRemote.qml") << "";
1524 QTest::newRow("remote-error") << testFileUrl("embeddedImagesRemoteError.qml")
1525 << testFileUrl("embeddedImagesRemoteError.qml").toString()+":3:1: QML Text: Error downloading http://127.0.0.1:14453/notexists.png - server replied: Not found";
1526 QTest::newRow("remote") << testFileUrl("embeddedImagesRemoteRelative.qml") << "";
1529 void tst_qquicktext::embeddedImages()
1533 QFETCH(QUrl, qmlfile);
1534 QFETCH(QString, error);
1536 TestHTTPServer server(14453);
1537 server.serveDirectory(testFile("http"));
1539 if (!error.isEmpty())
1540 QTest::ignoreMessage(QtWarningMsg, error.toLatin1());
1542 QQuickView *view = new QQuickView(qmlfile);
1544 view->requestActivateWindow();
1545 QTest::qWaitForWindowShown(view);
1546 QQuickText *textObject = qobject_cast<QQuickText*>(view->rootObject());
1548 QVERIFY(textObject != 0);
1549 QTRY_COMPARE(textObject->resourcesLoading(), 0);
1551 QPixmap pm(testFile("http/exists.png"));
1552 if (error.isEmpty()) {
1553 QCOMPARE(textObject->width(), double(pm.width()));
1554 QCOMPARE(textObject->height(), double(pm.height()));
1556 QVERIFY(16 != pm.width()); // check test is effective
1557 QCOMPARE(textObject->width(), 16.0); // default size of QTextDocument broken image icon
1558 QCOMPARE(textObject->height(), 16.0);
1564 void tst_qquicktext::lineCount()
1566 QQuickView *canvas = createView(testFile("lineCount.qml"));
1568 QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
1569 QVERIFY(myText != 0);
1571 QVERIFY(myText->lineCount() > 1);
1572 QVERIFY(!myText->truncated());
1573 QCOMPARE(myText->maximumLineCount(), INT_MAX);
1575 myText->setMaximumLineCount(2);
1576 QCOMPARE(myText->lineCount(), 2);
1577 QCOMPARE(myText->truncated(), true);
1578 QCOMPARE(myText->maximumLineCount(), 2);
1580 myText->resetMaximumLineCount();
1581 QCOMPARE(myText->maximumLineCount(), INT_MAX);
1582 QCOMPARE(myText->truncated(), false);
1584 myText->setElideMode(QQuickText::ElideRight);
1585 myText->setMaximumLineCount(2);
1586 QCOMPARE(myText->lineCount(), 2);
1587 QCOMPARE(myText->truncated(), true);
1588 QCOMPARE(myText->maximumLineCount(), 2);
1593 void tst_qquicktext::lineHeight()
1595 QQuickView *canvas = createView(testFile("lineHeight.qml"));
1597 QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
1598 QVERIFY(myText != 0);
1600 QVERIFY(myText->lineHeight() == 1);
1601 QVERIFY(myText->lineHeightMode() == QQuickText::ProportionalHeight);
1603 qreal h = myText->height();
1604 myText->setLineHeight(1.5);
1605 QCOMPARE(myText->height(), qreal(qCeil(h * 1.5)));
1607 myText->setLineHeightMode(QQuickText::FixedHeight);
1608 myText->setLineHeight(20);
1609 QCOMPARE(myText->height(), myText->lineCount() * 20.0);
1611 myText->setText("Lorem ipsum sit <b>amet</b>, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum.");
1612 myText->setLineHeightMode(QQuickText::ProportionalHeight);
1613 myText->setLineHeight(1.0);
1615 qreal h2 = myText->height();
1616 myText->setLineHeight(2.0);
1617 QVERIFY(myText->height() == h2 * 2.0);
1619 myText->setLineHeightMode(QQuickText::FixedHeight);
1620 myText->setLineHeight(10);
1621 QCOMPARE(myText->height(), myText->lineCount() * 10.0);
1626 void tst_qquicktext::implicitSize_data()
1628 QTest::addColumn<QString>("text");
1629 QTest::addColumn<QString>("width");
1630 QTest::addColumn<QString>("wrap");
1631 QTest::addColumn<QString>("elide");
1632 QTest::addColumn<QString>("format");
1633 QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideNone" << "Text.PlainText";
1634 QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone" << "Text.RichText";
1635 QTest::newRow("styledtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone" << "Text.StyledText";
1636 QTest::newRow("plain, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideNone" << "Text.PlainText";
1637 QTest::newRow("plain, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideRight" << "Text.PlainText";
1638 QTest::newRow("plain, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideRight" << "Text.PlainText";
1639 QTest::newRow("richtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone" << "Text.RichText";
1640 QTest::newRow("styledtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone" << "Text.StyledText";
1641 QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.PlainText";
1642 QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.RichText";
1643 QTest::newRow("styledtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.StyledText";
1644 QTest::newRow("plain_wrap, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.PlainText";
1645 QTest::newRow("plain_wrap, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideRight" << "Text.PlainText";
1646 QTest::newRow("plain_wrap, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideRight" << "Text.PlainText";
1647 QTest::newRow("richtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.RichText";
1648 QTest::newRow("styledtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.StyledText";
1651 void tst_qquicktext::implicitSize()
1653 QFETCH(QString, text);
1654 QFETCH(QString, width);
1655 QFETCH(QString, format);
1656 QFETCH(QString, wrap);
1657 QFETCH(QString, elide);
1658 QString componentStr = "import QtQuick 2.0\nText { "
1659 "property real iWidth: implicitWidth; "
1660 "text: \"" + text + "\"; "
1661 "width: " + width + "; "
1662 "textFormat: " + format + "; "
1663 "wrapMode: " + wrap + "; "
1664 "elide: " + elide + "; "
1665 "maximumLineCount: 2 }";
1666 QQmlComponent textComponent(&engine);
1667 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1668 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
1670 QVERIFY(textObject->width() < textObject->implicitWidth());
1671 QVERIFY(textObject->height() == textObject->implicitHeight());
1672 QCOMPARE(textObject->property("iWidth").toReal(), textObject->implicitWidth());
1674 textObject->resetWidth();
1675 QVERIFY(textObject->width() == textObject->implicitWidth());
1676 QVERIFY(textObject->height() == textObject->implicitHeight());
1681 void tst_qquicktext::contentSize()
1683 QString componentStr = "import QtQuick 2.0\nText { width: 75; height: 16; font.pixelSize: 10 }";
1684 QQmlComponent textComponent(&engine);
1685 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1686 QScopedPointer<QObject> object(textComponent.create());
1687 QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
1689 QSignalSpy spy(textObject, SIGNAL(contentSizeChanged()));
1691 textObject->setText("The quick red fox jumped over the lazy brown dog");
1693 QVERIFY(textObject->contentWidth() > textObject->width());
1694 QVERIFY(textObject->contentHeight() < textObject->height());
1695 QCOMPARE(spy.count(), 1);
1697 textObject->setWrapMode(QQuickText::WordWrap);
1698 QVERIFY(textObject->contentWidth() <= textObject->width());
1699 QVERIFY(textObject->contentHeight() > textObject->height());
1700 QCOMPARE(spy.count(), 2);
1702 textObject->setElideMode(QQuickText::ElideRight);
1703 QVERIFY(textObject->contentWidth() <= textObject->width());
1704 QVERIFY(textObject->contentHeight() < textObject->height());
1705 QCOMPARE(spy.count(), 3);
1707 qreal elidedWidth = textObject->contentWidth();
1709 textObject->setText("The quickredfoxjumpedoverthe lazy brown dog");
1710 QVERIFY(textObject->contentWidth() <= textObject->width());
1711 QVERIFY(textObject->contentHeight() < textObject->height());
1712 // this text probably won't have the same elided width, but it's not guaranteed.
1713 if (textObject->contentWidth() != elidedWidth)
1714 QCOMPARE(spy.count(), ++spyCount);
1716 QCOMPARE(spy.count(), spyCount);
1718 textObject->setElideMode(QQuickText::ElideNone);
1719 QVERIFY(textObject->contentWidth() > textObject->width());
1720 QVERIFY(textObject->contentHeight() > textObject->height());
1721 QCOMPARE(spy.count(), ++spyCount);
1724 void tst_qquicktext::implicitSizeBinding_data()
1726 implicitSize_data();
1729 void tst_qquicktext::implicitSizeBinding()
1731 QFETCH(QString, text);
1732 QFETCH(QString, wrap);
1733 QFETCH(QString, format);
1734 QString componentStr = "import QtQuick 2.0\nText { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + "; textFormat: " + format + " }";
1736 QQmlComponent textComponent(&engine);
1737 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1738 QScopedPointer<QObject> object(textComponent.create());
1739 QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
1741 QCOMPARE(textObject->width(), textObject->implicitWidth());
1742 QCOMPARE(textObject->height(), textObject->implicitHeight());
1744 textObject->resetWidth();
1745 QCOMPARE(textObject->width(), textObject->implicitWidth());
1746 QCOMPARE(textObject->height(), textObject->implicitHeight());
1748 textObject->resetHeight();
1749 QCOMPARE(textObject->width(), textObject->implicitWidth());
1750 QCOMPARE(textObject->height(), textObject->implicitHeight());
1753 void tst_qquicktext::boundingRect_data()
1755 QTest::addColumn<QString>("format");
1756 QTest::newRow("PlainText") << "Text.PlainText";
1757 QTest::newRow("StyledText") << "Text.StyledText";
1758 QTest::newRow("RichText") << "Text.RichText";
1761 void tst_qquicktext::boundingRect()
1763 QFETCH(QString, format);
1765 QQmlComponent component(&engine);
1766 component.setData("import QtQuick 2.0\n Text { textFormat:" + format.toUtf8() + "}", QUrl());
1767 QScopedPointer<QObject> object(component.create());
1768 QQuickText *text = qobject_cast<QQuickText *>(object.data());
1771 QCOMPARE(text->boundingRect().x(), qreal(0));
1772 QCOMPARE(text->boundingRect().y(), qreal(0));
1773 QCOMPARE(text->boundingRect().width(), qreal(0));
1774 QCOMPARE(text->boundingRect().height(), qreal(qCeil(QFontMetricsF(text->font()).height())));
1776 text->setText("Hello World");
1778 QTextLayout layout(text->text());
1779 layout.setFont(text->font());
1781 if (!qmlDisableDistanceField()) {
1783 option.setUseDesignMetrics(true);
1784 layout.setTextOption(option);
1786 layout.beginLayout();
1787 QTextLine line = layout.createLine();
1790 QCOMPARE(text->boundingRect().x(), qreal(0));
1791 QCOMPARE(text->boundingRect().y(), qreal(0));
1792 QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
1793 QCOMPARE(text->boundingRect().height(), line.height());
1795 // the size of the bounding rect shouldn't be bounded by the size of item.
1796 text->setWidth(text->width() / 2);
1797 QCOMPARE(text->boundingRect().x(), qreal(0));
1798 QCOMPARE(text->boundingRect().y(), qreal(0));
1799 QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
1800 QCOMPARE(text->boundingRect().height(), line.height());
1802 text->setHeight(text->height() * 2);
1803 QCOMPARE(text->boundingRect().x(), qreal(0));
1804 QCOMPARE(text->boundingRect().y(), qreal(0));
1805 QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
1806 QCOMPARE(text->boundingRect().height(), line.height());
1808 text->setHAlign(QQuickText::AlignRight);
1809 QCOMPARE(text->boundingRect().x(), text->width() - line.naturalTextWidth());
1810 QCOMPARE(text->boundingRect().y(), qreal(0));
1811 QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
1812 QCOMPARE(text->boundingRect().height(), line.height());
1814 text->setWrapMode(QQuickText::Wrap);
1815 QCOMPARE(text->boundingRect().right(), text->width());
1816 QCOMPARE(text->boundingRect().y(), qreal(0));
1817 QVERIFY(text->boundingRect().width() < line.naturalTextWidth());
1818 QVERIFY(text->boundingRect().height() > line.height());
1820 text->setVAlign(QQuickText::AlignBottom);
1821 QCOMPARE(text->boundingRect().right(), text->width());
1822 QCOMPARE(text->boundingRect().bottom(), text->height());
1823 QVERIFY(text->boundingRect().width() < line.naturalTextWidth());
1824 QVERIFY(text->boundingRect().height() > line.height());
1827 void tst_qquicktext::clipRect()
1829 QQmlComponent component(&engine);
1830 component.setData("import QtQuick 2.0\n Text {}", QUrl());
1831 QScopedPointer<QObject> object(component.create());
1832 QQuickText *text = qobject_cast<QQuickText *>(object.data());
1836 layout.setFont(text->font());
1838 QCOMPARE(text->clipRect().x(), qreal(0));
1839 QCOMPARE(text->clipRect().y(), qreal(0));
1840 QCOMPARE(text->clipRect().width(), text->width());
1841 QCOMPARE(text->clipRect().height(), text->height());
1843 text->setText("Hello World");
1845 QCOMPARE(text->clipRect().x(), qreal(0));
1846 QCOMPARE(text->clipRect().y(), qreal(0));
1847 QCOMPARE(text->clipRect().width(), text->width());
1848 QCOMPARE(text->clipRect().height(), text->height());
1850 // Clip rect follows the item not content dimensions.
1851 text->setWidth(text->width() / 2);
1852 QCOMPARE(text->clipRect().x(), qreal(0));
1853 QCOMPARE(text->clipRect().y(), qreal(0));
1854 QCOMPARE(text->clipRect().width(), text->width());
1855 QCOMPARE(text->clipRect().height(), text->height());
1857 text->setHeight(text->height() * 2);
1858 QCOMPARE(text->clipRect().x(), qreal(0));
1859 QCOMPARE(text->clipRect().y(), qreal(0));
1860 QCOMPARE(text->clipRect().width(), text->width());
1861 QCOMPARE(text->clipRect().height(), text->height());
1863 // Setting a style adds a small amount of padding to the clip rect.
1864 text->setStyle(QQuickText::Outline);
1865 QCOMPARE(text->clipRect().x(), qreal(-1));
1866 QCOMPARE(text->clipRect().y(), qreal(0));
1867 QCOMPARE(text->clipRect().width(), text->width() + 2);
1868 QCOMPARE(text->clipRect().height(), text->height() + 2);
1871 void tst_qquicktext::lineLaidOut()
1873 QQuickView *canvas = createView(testFile("lineLayout.qml"));
1875 QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
1876 QVERIFY(myText != 0);
1878 QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
1879 QVERIFY(textPrivate != 0);
1881 QVERIFY(!textPrivate->extra.isAllocated());
1883 #if defined(Q_OS_MAC)
1884 QVERIFY(myText->lineCount() == textPrivate->linesRects.count());
1887 for (int i = 0; i < textPrivate->layout.lineCount(); ++i) {
1888 QRectF r = textPrivate->layout.lineAt(i).rect();
1889 QVERIFY(r.width() == i * 15);
1891 QVERIFY(r.x() == r.width() + 30);
1893 QVERIFY(r.x() == r.width() * 2 + 60);
1894 QVERIFY(r.height() == 20);
1901 void tst_qquicktext::imgTagsBaseUrl_data()
1903 QTest::addColumn<QUrl>("src");
1904 QTest::addColumn<QUrl>("baseUrl");
1905 QTest::addColumn<QUrl>("contextUrl");
1906 QTest::addColumn<qreal>("imgHeight");
1908 QTest::newRow("absolute local")
1909 << testFileUrl("images/heart200.png")
1913 QTest::newRow("relative local context 1")
1914 << QUrl("images/heart200.png")
1916 << testFileUrl("/app.qml")
1918 QTest::newRow("relative local context 2")
1919 << QUrl("heart200.png")
1921 << testFileUrl("images/app.qml")
1923 QTest::newRow("relative local base 1")
1924 << QUrl("images/heart200.png")
1926 << testFileUrl("nonexistant/app.qml")
1928 QTest::newRow("relative local base 2")
1929 << QUrl("heart200.png")
1930 << testFileUrl("images/")
1931 << testFileUrl("nonexistant/app.qml")
1933 QTest::newRow("base relative to local context")
1934 << QUrl("heart200.png")
1935 << testFileUrl("images/")
1936 << testFileUrl("/app.qml")
1939 QTest::newRow("absolute remote")
1940 << QUrl("http://127.0.0.1:14453/images/heart200.png")
1944 QTest::newRow("relative remote base 1")
1945 << QUrl("images/heart200.png")
1946 << QUrl("http://127.0.0.1:14453/")
1947 << testFileUrl("nonexistant/app.qml")
1949 QTest::newRow("relative remote base 2")
1950 << QUrl("heart200.png")
1951 << QUrl("http://127.0.0.1:14453/images/")
1952 << testFileUrl("nonexistant/app.qml")
1956 void tst_qquicktext::imgTagsBaseUrl()
1959 QFETCH(QUrl, baseUrl);
1960 QFETCH(QUrl, contextUrl);
1961 QFETCH(qreal, imgHeight);
1963 TestHTTPServer server(14453);
1964 server.serveDirectory(testFile(""));
1966 QByteArray baseUrlFragment;
1967 if (!baseUrl.isEmpty())
1968 baseUrlFragment = "; baseUrl: \"" + baseUrl.toEncoded() + "\"";
1969 QByteArray componentStr = "import QtQuick 2.0\nText { text: \"This is a test <img src=\\\"" + src.toEncoded() + "\\\">\"" + baseUrlFragment + " }";
1971 QQmlComponent component(&engine);
1972 component.setData(componentStr, contextUrl);
1973 QScopedPointer<QObject> object(component.create());
1974 QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
1975 QVERIFY(textObject);
1977 QCoreApplication::processEvents();
1979 QTRY_COMPARE(textObject->height(), imgHeight);
1982 void tst_qquicktext::imgTagsAlign_data()
1984 QTest::addColumn<QString>("src");
1985 QTest::addColumn<int>("imgHeight");
1986 QTest::addColumn<QString>("align");
1987 QTest::newRow("heart-bottom") << "data/images/heart200.png" << 181 << "bottom";
1988 QTest::newRow("heart-middle") << "data/images/heart200.png" << 181 << "middle";
1989 QTest::newRow("heart-top") << "data/images/heart200.png" << 181 << "top";
1990 QTest::newRow("starfish-bottom") << "data/images/starfish_2.png" << 217 << "bottom";
1991 QTest::newRow("starfish-middle") << "data/images/starfish_2.png" << 217 << "middle";
1992 QTest::newRow("starfish-top") << "data/images/starfish_2.png" << 217 << "top";
1995 void tst_qquicktext::imgTagsAlign()
1997 QFETCH(QString, src);
1998 QFETCH(int, imgHeight);
1999 QFETCH(QString, align);
2000 QString componentStr = "import QtQuick 2.0\nText { text: \"This is a test <img src=\\\"" + src + "\\\" align=\\\"" + align + "\\\"> of image.\" }";
2001 QQmlComponent textComponent(&engine);
2002 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
2003 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
2005 QVERIFY(textObject != 0);
2006 QVERIFY(textObject->height() == imgHeight);
2008 QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
2009 QVERIFY(textPrivate != 0);
2011 QRectF br = textPrivate->layout.boundingRect();
2012 if (align == "bottom")
2013 QVERIFY(br.y() == imgHeight - br.height());
2014 else if (align == "middle")
2015 QVERIFY(br.y() == imgHeight / 2.0 - br.height() / 2.0);
2016 else if (align == "top")
2017 QVERIFY(br.y() == 0);
2022 void tst_qquicktext::imgTagsMultipleImages()
2024 QString componentStr = "import QtQuick 2.0\nText { text: \"This is a starfish<img src=\\\"data/images/starfish_2.png\\\" width=\\\"60\\\" height=\\\"60\\\" > and another one<img src=\\\"data/images/heart200.png\\\" width=\\\"85\\\" height=\\\"85\\\">.\" }";
2026 QQmlComponent textComponent(&engine);
2027 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
2028 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
2030 QVERIFY(textObject != 0);
2031 QVERIFY(textObject->height() == 85);
2033 QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
2034 QVERIFY(textPrivate != 0);
2035 QVERIFY(textPrivate->visibleImgTags.count() == 2);
2040 void tst_qquicktext::imgTagsElide()
2042 QQuickView *canvas = createView(testFile("imgTagsElide.qml"));
2043 QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
2044 QVERIFY(myText != 0);
2046 QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
2047 QVERIFY(textPrivate != 0);
2048 QVERIFY(textPrivate->visibleImgTags.count() == 0);
2049 myText->setMaximumLineCount(20);
2050 QTRY_VERIFY(textPrivate->visibleImgTags.count() == 1);
2056 void tst_qquicktext::imgTagsUpdates()
2058 QQuickView *canvas = createView(testFile("imgTagsUpdates.qml"));
2059 QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
2060 QVERIFY(myText != 0);
2062 QSignalSpy spy(myText, SIGNAL(contentSizeChanged()));
2064 QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
2065 QVERIFY(textPrivate != 0);
2067 myText->setText("This is a heart<img src=\"images/heart200.png\">.");
2068 QVERIFY(textPrivate->visibleImgTags.count() == 1);
2069 QVERIFY(spy.count() == 1);
2071 myText->setMaximumLineCount(2);
2072 myText->setText("This is another heart<img src=\"images/heart200.png\">.");
2073 QTRY_VERIFY(textPrivate->visibleImgTags.count() == 1);
2075 // if maximumLineCount is set and the img tag doesn't have an explicit size
2076 // we relayout twice.
2077 QVERIFY(spy.count() == 3);
2083 void tst_qquicktext::imgTagsError()
2085 QString componentStr = "import QtQuick 2.0\nText { text: \"This is a starfish<img src=\\\"data/images/starfish_2.pn\\\" width=\\\"60\\\" height=\\\"60\\\">.\" }";
2087 QQmlComponent textComponent(&engine);
2088 QTest::ignoreMessage(QtWarningMsg, "file::2:1: QML Text: Cannot open: file:data/images/starfish_2.pn");
2089 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
2090 QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
2092 QVERIFY(textObject != 0);
2096 void tst_qquicktext::fontSizeMode_data()
2098 QTest::addColumn<QString>("text");
2099 QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog";
2100 QTest::newRow("styled") << "<b>The quick red fox jumped over the lazy brown dog</b>";
2103 void tst_qquicktext::fontSizeMode()
2105 QFETCH(QString, text);
2107 QScopedPointer<QQuickView> canvas(createView(testFile("fontSizeMode.qml")));
2110 QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
2111 QVERIFY(myText != 0);
2113 myText->setText(text);
2114 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2116 qreal originalWidth = myText->contentWidth();
2117 qreal originalHeight = myText->contentHeight();
2119 // The original text unwrapped should exceed the width of the item.
2120 QVERIFY(originalWidth > myText->width());
2121 QVERIFY(originalHeight < myText->height());
2123 QFont font = myText->font();
2124 font.setPixelSize(64);
2126 myText->setFont(font);
2127 myText->setFontSizeMode(QQuickText::HorizontalFit);
2128 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2129 // Font size reduced to fit within the width of the item.
2130 qreal horizontalFitWidth = myText->contentWidth();
2131 qreal horizontalFitHeight = myText->contentHeight();
2132 QVERIFY(horizontalFitWidth <= myText->width() + 2); // rounding
2133 QVERIFY(horizontalFitHeight <= myText->height() + 2);
2135 // Elide won't affect the size with HorizontalFit.
2136 myText->setElideMode(QQuickText::ElideRight);
2137 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2138 QVERIFY(!myText->truncated());
2139 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2140 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2142 myText->setElideMode(QQuickText::ElideLeft);
2143 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2144 QVERIFY(!myText->truncated());
2145 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2146 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2148 myText->setElideMode(QQuickText::ElideMiddle);
2149 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2150 QVERIFY(!myText->truncated());
2151 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2152 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2154 myText->setElideMode(QQuickText::ElideNone);
2155 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2157 myText->setFontSizeMode(QQuickText::VerticalFit);
2158 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2159 // Font size increased to fill the height of the item.
2160 qreal verticalFitHeight = myText->contentHeight();
2161 QVERIFY(myText->contentWidth() > myText->width());
2162 QVERIFY(verticalFitHeight <= myText->height() + 2);
2163 QVERIFY(verticalFitHeight > originalHeight);
2165 // Elide won't affect the height of a single line with VerticalFit but will crop the width.
2166 myText->setElideMode(QQuickText::ElideRight);
2167 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2168 QVERIFY(myText->truncated());
2169 QVERIFY(myText->contentWidth() <= myText->width() + 2);
2170 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2172 myText->setElideMode(QQuickText::ElideLeft);
2173 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2174 QVERIFY(myText->truncated());
2175 QVERIFY(myText->contentWidth() <= myText->width() + 2);
2176 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2178 myText->setElideMode(QQuickText::ElideMiddle);
2179 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2180 QVERIFY(myText->truncated());
2181 QVERIFY(myText->contentWidth() <= myText->width() + 2);
2182 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2184 myText->setElideMode(QQuickText::ElideNone);
2185 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2187 myText->setFontSizeMode(QQuickText::Fit);
2188 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2189 // Should be the same as HorizontalFit with no wrapping.
2190 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2191 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2193 // Elide won't affect the size with Fit.
2194 myText->setElideMode(QQuickText::ElideRight);
2195 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2196 QVERIFY(!myText->truncated());
2197 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2198 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2200 myText->setElideMode(QQuickText::ElideLeft);
2201 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2202 QVERIFY(!myText->truncated());
2203 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2204 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2206 myText->setElideMode(QQuickText::ElideMiddle);
2207 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2208 QVERIFY(!myText->truncated());
2209 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2210 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2212 myText->setElideMode(QQuickText::ElideNone);
2213 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2215 myText->setFontSizeMode(QQuickText::FixedSize);
2216 myText->setWrapMode(QQuickText::Wrap);
2217 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2219 originalWidth = myText->contentWidth();
2220 originalHeight = myText->contentHeight();
2222 // The original text wrapped should exceed the height of the item.
2223 QVERIFY(originalWidth <= myText->width() + 2);
2224 QVERIFY(originalHeight > myText->height());
2226 myText->setFontSizeMode(QQuickText::HorizontalFit);
2227 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2228 // HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
2229 // same size as without text wrapping.
2230 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2231 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2233 // Elide won't affect the size with HorizontalFit.
2234 myText->setElideMode(QQuickText::ElideRight);
2235 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2236 QVERIFY(!myText->truncated());
2237 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2238 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2240 myText->setElideMode(QQuickText::ElideNone);
2241 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2243 myText->setFontSizeMode(QQuickText::VerticalFit);
2244 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2245 // VerticalFit should reduce the size to the wrapped text within the vertical height.
2246 verticalFitHeight = myText->contentHeight();
2247 qreal verticalFitWidth = myText->contentWidth();
2248 QVERIFY(myText->contentWidth() <= myText->width() + 2);
2249 QVERIFY(verticalFitHeight <= myText->height() + 2);
2250 QVERIFY(verticalFitHeight < originalHeight);
2252 // Elide won't affect the height or width of a wrapped text with VerticalFit.
2253 myText->setElideMode(QQuickText::ElideRight);
2254 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2255 QVERIFY(!myText->truncated());
2256 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2257 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2259 myText->setElideMode(QQuickText::ElideNone);
2260 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2262 myText->setFontSizeMode(QQuickText::Fit);
2263 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2264 // Should be the same as VerticalFit with wrapping.
2265 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2266 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2268 // Elide won't affect the size with Fit.
2269 myText->setElideMode(QQuickText::ElideRight);
2270 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2271 QVERIFY(!myText->truncated());
2272 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2273 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2275 myText->setElideMode(QQuickText::ElideNone);
2276 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2278 myText->setFontSizeMode(QQuickText::FixedSize);
2279 myText->setMaximumLineCount(2);
2280 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2282 // The original text wrapped should exceed the height of the item.
2283 QVERIFY(originalWidth <= myText->width() + 2);
2284 QVERIFY(originalHeight > myText->height());
2286 myText->setFontSizeMode(QQuickText::HorizontalFit);
2287 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2288 // HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
2289 // same size as without text wrapping.
2290 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2291 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2293 // Elide won't affect the size with HorizontalFit.
2294 myText->setElideMode(QQuickText::ElideRight);
2295 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2296 QVERIFY(!myText->truncated());
2297 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2298 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2300 myText->setElideMode(QQuickText::ElideNone);
2301 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2303 myText->setFontSizeMode(QQuickText::VerticalFit);
2304 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2305 // VerticalFit should reduce the size to the wrapped text within the vertical height.
2306 verticalFitHeight = myText->contentHeight();
2307 verticalFitWidth = myText->contentWidth();
2308 QVERIFY(myText->contentWidth() <= myText->width() + 2);
2309 QVERIFY(verticalFitHeight <= myText->height() + 2);
2310 QVERIFY(verticalFitHeight < originalHeight);
2312 // Elide won't affect the height or width of a wrapped text with VerticalFit.
2313 myText->setElideMode(QQuickText::ElideRight);
2314 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2315 QVERIFY(!myText->truncated());
2316 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2317 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2319 myText->setElideMode(QQuickText::ElideNone);
2320 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2322 myText->setFontSizeMode(QQuickText::Fit);
2323 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2324 // Should be the same as VerticalFit with wrapping.
2325 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2326 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2328 // Elide won't affect the size with Fit.
2329 myText->setElideMode(QQuickText::ElideRight);
2330 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2331 QVERIFY(!myText->truncated());
2332 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2333 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2335 myText->setElideMode(QQuickText::ElideNone);
2336 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2339 void tst_qquicktext::fontSizeModeMultiline_data()
2341 QTest::addColumn<QString>("text");
2342 QTest::newRow("plain") << "The quick red fox jumped\n over the lazy brown dog";
2343 QTest::newRow("styledtext") << "<b>The quick red fox jumped<br/> over the lazy brown dog</b>";
2346 void tst_qquicktext::fontSizeModeMultiline()
2348 QFETCH(QString, text);
2350 QScopedPointer<QQuickView> canvas(createView(testFile("fontSizeMode.qml")));
2353 QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
2354 QVERIFY(myText != 0);
2356 myText->setText(text);
2357 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2359 qreal originalWidth = myText->contentWidth();
2360 qreal originalHeight = myText->contentHeight();
2361 QCOMPARE(myText->lineCount(), 2);
2363 // The original text unwrapped should exceed the width and height of the item.
2364 QVERIFY(originalWidth > myText->width());
2365 QVERIFY(originalHeight > myText->height());
2367 QFont font = myText->font();
2368 font.setPixelSize(64);
2370 myText->setFont(font);
2371 myText->setFontSizeMode(QQuickText::HorizontalFit);
2372 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2373 // Font size reduced to fit within the width of the item.
2374 QCOMPARE(myText->lineCount(), 2);
2375 qreal horizontalFitWidth = myText->contentWidth();
2376 qreal horizontalFitHeight = myText->contentHeight();
2377 QVERIFY(horizontalFitWidth <= myText->width() + 2); // rounding
2378 QVERIFY(horizontalFitHeight > myText->height());
2380 // Right eliding will remove the last line
2381 myText->setElideMode(QQuickText::ElideRight);
2382 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2383 QVERIFY(myText->truncated());
2384 QCOMPARE(myText->lineCount(), 1);
2385 QVERIFY(myText->contentWidth() <= myText->width() + 2);
2386 QVERIFY(myText->contentHeight() <= myText->height() + 2);
2388 // Left or middle eliding wont have any effect.
2389 myText->setElideMode(QQuickText::ElideLeft);
2390 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2391 QVERIFY(!myText->truncated());
2392 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2393 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2395 myText->setElideMode(QQuickText::ElideMiddle);
2396 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2397 QVERIFY(!myText->truncated());
2398 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2399 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2401 myText->setElideMode(QQuickText::ElideNone);
2402 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2404 myText->setFontSizeMode(QQuickText::VerticalFit);
2405 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2406 // Font size reduced to fit within the height of the item.
2407 qreal verticalFitWidth = myText->contentWidth();
2408 qreal verticalFitHeight = myText->contentHeight();
2409 QVERIFY(verticalFitWidth <= myText->width() + 2);
2410 QVERIFY(verticalFitHeight <= myText->height() + 2);
2412 // Elide will have no effect.
2413 myText->setElideMode(QQuickText::ElideRight);
2414 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2415 QVERIFY(!myText->truncated());
2416 QVERIFY(myText->contentWidth() <= myText->width() + 2);
2417 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2418 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2420 myText->setElideMode(QQuickText::ElideLeft);
2421 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2422 QVERIFY(!myText->truncated());
2423 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2424 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2426 myText->setElideMode(QQuickText::ElideMiddle);
2427 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2428 QVERIFY(!myText->truncated());
2429 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2430 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2432 myText->setElideMode(QQuickText::ElideNone);
2433 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2435 myText->setFontSizeMode(QQuickText::Fit);
2436 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2437 // Should be the same as VerticalFit with no wrapping.
2438 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2439 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2441 // Elide won't affect the size with Fit.
2442 myText->setElideMode(QQuickText::ElideRight);
2443 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2444 QVERIFY(!myText->truncated());
2445 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2446 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2448 myText->setElideMode(QQuickText::ElideLeft);
2449 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2450 QVERIFY(!myText->truncated());
2451 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2452 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2454 myText->setElideMode(QQuickText::ElideMiddle);
2455 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2456 QVERIFY(!myText->truncated());
2457 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2458 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2460 myText->setElideMode(QQuickText::ElideNone);
2461 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2463 myText->setFontSizeMode(QQuickText::FixedSize);
2464 myText->setWrapMode(QQuickText::Wrap);
2465 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2467 originalWidth = myText->contentWidth();
2468 originalHeight = myText->contentHeight();
2470 // The original text wrapped should exceed the height of the item.
2471 QVERIFY(originalWidth <= myText->width() + 2);
2472 QVERIFY(originalHeight > myText->height());
2474 myText->setFontSizeMode(QQuickText::HorizontalFit);
2475 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2476 // HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
2477 // same size as without text wrapping.
2478 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2479 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2481 // Text will be elided vertically with HorizontalFit
2482 myText->setElideMode(QQuickText::ElideRight);
2483 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2484 QVERIFY(myText->truncated());
2485 QVERIFY(myText->contentWidth() <= myText->width() + 2);
2486 QVERIFY(myText->contentHeight() <= myText->height() + 2);
2488 myText->setElideMode(QQuickText::ElideNone);
2489 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2491 myText->setFontSizeMode(QQuickText::VerticalFit);
2492 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2493 // VerticalFit should reduce the size to the wrapped text within the vertical height.
2494 verticalFitHeight = myText->contentHeight();
2495 verticalFitWidth = myText->contentWidth();
2496 QVERIFY(myText->contentWidth() <= myText->width() + 2);
2497 QVERIFY(verticalFitHeight <= myText->height() + 2);
2498 QVERIFY(verticalFitHeight < originalHeight);
2500 // Elide won't affect the height or width of a wrapped text with VerticalFit.
2501 myText->setElideMode(QQuickText::ElideRight);
2502 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2503 QVERIFY(!myText->truncated());
2504 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2505 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2507 myText->setElideMode(QQuickText::ElideNone);
2508 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2510 myText->setFontSizeMode(QQuickText::Fit);
2511 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2512 // Should be the same as VerticalFit with wrapping.
2513 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2514 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2516 // Elide won't affect the size with Fit.
2517 myText->setElideMode(QQuickText::ElideRight);
2518 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2519 QVERIFY(!myText->truncated());
2520 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2521 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2523 myText->setElideMode(QQuickText::ElideNone);
2524 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2526 myText->setFontSizeMode(QQuickText::FixedSize);
2527 myText->setMaximumLineCount(2);
2528 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2530 // The original text wrapped should exceed the height of the item.
2531 QVERIFY(originalWidth <= myText->width() + 2);
2532 QVERIFY(originalHeight > myText->height());
2534 myText->setFontSizeMode(QQuickText::HorizontalFit);
2535 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2536 // HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
2537 // same size as without text wrapping.
2538 QCOMPARE(myText->contentWidth(), horizontalFitWidth);
2539 QCOMPARE(myText->contentHeight(), horizontalFitHeight);
2541 // Elide won't affect the size with HorizontalFit.
2542 myText->setElideMode(QQuickText::ElideRight);
2543 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2544 QVERIFY(myText->truncated());
2545 QVERIFY(myText->contentWidth() <= myText->width() + 2);
2546 QVERIFY(myText->contentHeight() <= myText->height() + 2);
2548 myText->setElideMode(QQuickText::ElideNone);
2549 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2551 myText->setFontSizeMode(QQuickText::VerticalFit);
2552 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2553 // VerticalFit should reduce the size to the wrapped text within the vertical height.
2554 verticalFitHeight = myText->contentHeight();
2555 verticalFitWidth = myText->contentWidth();
2556 QVERIFY(myText->contentWidth() <= myText->width() + 2);
2557 QVERIFY(verticalFitHeight <= myText->height() + 2);
2558 QVERIFY(verticalFitHeight < originalHeight);
2560 // Elide won't affect the height or width of a wrapped text with VerticalFit.
2561 myText->setElideMode(QQuickText::ElideRight);
2562 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2563 QVERIFY(!myText->truncated());
2564 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2565 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2567 myText->setElideMode(QQuickText::ElideNone);
2568 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2570 myText->setFontSizeMode(QQuickText::Fit);
2571 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2572 // Should be the same as VerticalFit with wrapping.
2573 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2574 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2576 // Elide won't affect the size with Fit.
2577 myText->setElideMode(QQuickText::ElideRight);
2578 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2579 QVERIFY(!myText->truncated());
2580 QCOMPARE(myText->contentWidth(), verticalFitWidth);
2581 QCOMPARE(myText->contentHeight(), verticalFitHeight);
2583 myText->setElideMode(QQuickText::ElideNone);
2584 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2587 void tst_qquicktext::multilengthStrings_data()
2589 QTest::addColumn<QString>("source");
2590 QTest::newRow("No Wrap") << testFile("multilengthStrings.qml");
2591 QTest::newRow("Wrap") << testFile("multilengthStringsWrapped.qml");
2594 void tst_qquicktext::multilengthStrings()
2596 QFETCH(QString, source);
2598 QScopedPointer<QQuickView> canvas(createView(source));
2601 QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
2602 QVERIFY(myText != 0);
2604 const QString longText = "the quick brown fox jumped over the lazy dog";
2605 const QString mediumText = "the brown fox jumped over the dog";
2606 const QString shortText = "fox jumped dog";
2608 myText->setText(longText);
2609 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2610 const qreal longWidth = myText->contentWidth();
2611 const qreal longHeight = myText->contentHeight();
2613 myText->setText(mediumText);
2614 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2615 const qreal mediumWidth = myText->contentWidth();
2616 const qreal mediumHeight = myText->contentHeight();
2618 myText->setText(shortText);
2619 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2620 const qreal shortWidth = myText->contentWidth();
2621 const qreal shortHeight = myText->contentHeight();
2623 myText->setElideMode(QQuickText::ElideRight);
2624 myText->setText(longText + QLatin1Char('\x9c') + mediumText + QLatin1Char('\x9c') + shortText);
2626 myText->setSize(QSizeF(longWidth, longHeight));
2627 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2629 QCOMPARE(myText->contentWidth(), longWidth);
2630 QCOMPARE(myText->contentHeight(), longHeight);
2631 QCOMPARE(myText->truncated(), false);
2633 myText->setSize(QSizeF(mediumWidth, mediumHeight));
2634 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2636 QCOMPARE(myText->contentWidth(), mediumWidth);
2637 QCOMPARE(myText->contentHeight(), mediumHeight);
2638 QCOMPARE(myText->truncated(), true);
2640 myText->setSize(QSizeF(shortWidth, shortHeight));
2641 QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
2643 QCOMPARE(myText->contentWidth(), shortWidth);
2644 QCOMPARE(myText->contentHeight(), shortHeight);
2645 QCOMPARE(myText->truncated(), true);
2648 void tst_qquicktext::fontFormatSizes_data()
2650 QTest::addColumn<QString>("text");
2651 QTest::addColumn<QString>("textWithTag");
2652 QTest::addColumn<bool>("fontIsBigger");
2654 QTest::newRow("fs1") << "Hello world!" << "Hello <font size=\"1\">world</font>!" << false;
2655 QTest::newRow("fs2") << "Hello world!" << "Hello <font size=\"2\">world</font>!" << false;
2656 QTest::newRow("fs3") << "Hello world!" << "Hello <font size=\"3\">world</font>!" << false;
2657 QTest::newRow("fs4") << "Hello world!" << "Hello <font size=\"4\">world</font>!" << true;
2658 QTest::newRow("fs5") << "Hello world!" << "Hello <font size=\"5\">world</font>!" << true;
2659 QTest::newRow("fs6") << "Hello world!" << "Hello <font size=\"6\">world</font>!" << true;
2660 QTest::newRow("fs7") << "Hello world!" << "Hello <font size=\"7\">world</font>!" << true;
2661 QTest::newRow("h1") << "This is<br/>a font<br/> size test." << "This is <h1>a font</h1> size test." << true;
2662 QTest::newRow("h2") << "This is<br/>a font<br/> size test." << "This is <h2>a font</h2> size test." << true;
2663 QTest::newRow("h3") << "This is<br/>a font<br/> size test." << "This is <h3>a font</h3> size test." << true;
2664 QTest::newRow("h4") << "This is<br/>a font<br/> size test." << "This is <h4>a font</h4> size test." << true;
2665 QTest::newRow("h5") << "This is<br/>a font<br/> size test." << "This is <h5>a font</h5> size test." << false;
2666 QTest::newRow("h6") << "This is<br/>a font<br/> size test." << "This is <h6>a font</h6> size test." << false;
2669 void tst_qquicktext::fontFormatSizes()
2671 QFETCH(QString, text);
2672 QFETCH(QString, textWithTag);
2673 QFETCH(bool, fontIsBigger);
2675 QQuickView *view = new QQuickView;
2677 view->setSource(testFileUrl("pointFontSizes.qml"));
2680 QQuickText *qtext = view->rootObject()->findChild<QQuickText*>("text");
2681 QQuickText *qtextWithTag = view->rootObject()->findChild<QQuickText*>("textWithTag");
2682 QVERIFY(qtext != 0);
2683 QVERIFY(qtextWithTag != 0);
2685 qtext->setText(text);
2686 qtextWithTag->setText(textWithTag);
2688 for (int size = 6; size < 100; size += 4) {
2689 view->rootObject()->setProperty("pointSize", size);
2691 QVERIFY(qtext->height() <= qtextWithTag->height());
2693 QVERIFY(qtext->height() >= qtextWithTag->height());
2698 view->setSource(testFileUrl("pixelFontSizes.qml"));
2699 QQuickText *qtext = view->rootObject()->findChild<QQuickText*>("text");
2700 QQuickText *qtextWithTag = view->rootObject()->findChild<QQuickText*>("textWithTag");
2701 QVERIFY(qtext != 0);
2702 QVERIFY(qtextWithTag != 0);
2704 qtext->setText(text);
2705 qtextWithTag->setText(textWithTag);
2707 for (int size = 6; size < 100; size += 4) {
2708 view->rootObject()->setProperty("pixelSize", size);
2710 QVERIFY(qtext->height() <= qtextWithTag->height());
2712 QVERIFY(qtext->height() >= qtextWithTag->height());
2718 typedef qreal (*ExpectedBaseline)(QQuickText *item);
2719 Q_DECLARE_METATYPE(ExpectedBaseline)
2721 static qreal expectedBaselineTop(QQuickText *item)
2723 QFontMetricsF fm(item->font());
2727 static qreal expectedBaselineBottom(QQuickText *item)
2729 QFontMetricsF fm(item->font());
2730 return item->height() - item->contentHeight() + fm.ascent();
2733 static qreal expectedBaselineCenter(QQuickText *item)
2735 QFontMetricsF fm(item->font());
2736 return ((item->height() - item->contentHeight()) / 2) + fm.ascent();
2739 static qreal expectedBaselineBold(QQuickText *item)
2741 QFont font = item->font();
2743 QFontMetricsF fm(font);
2747 static qreal expectedBaselineImage(QQuickText *item)
2749 QFontMetricsF fm(item->font());
2750 // The line is positioned so the bottom of the line is aligned with the bottom of the image,
2751 // or image height - line height and the baseline is line position + ascent. Because
2752 // QTextLine's height is rounded up this can give slightly different results to image height
2754 return 181 - qCeil(fm.height()) + fm.ascent();
2757 static qreal expectedBaselineCustom(QQuickText *item)
2759 QFontMetricsF fm(item->font());
2760 return 16 + fm.ascent();
2763 static qreal expectedBaselineScaled(QQuickText *item)
2765 QFont font = item->font();
2766 QTextLayout layout(item->text().replace(QLatin1Char('\n'), QChar::LineSeparator));
2768 layout.setFont(font);
2770 layout.beginLayout();
2771 for (QTextLine line = layout.createLine(); line.isValid(); line = layout.createLine()) {
2772 line.setLineWidth(FLT_MAX);
2773 width = qMax(line.naturalTextWidth(), width);
2777 if (width < item->width()) {
2778 QFontMetricsF fm(layout.font());
2781 font.setPointSize(font.pointSize() - 1);
2782 } while (font.pointSize() > 0);
2786 static qreal expectedBaselineFixedBottom(QQuickText *item)
2788 QFontMetricsF fm(item->font());
2789 qreal dy = item->text().contains(QLatin1Char('\n'))
2792 return dy + fm.ascent();
2795 static qreal expectedBaselineProportionalBottom(QQuickText *item)
2797 QFontMetricsF fm(item->font());
2798 qreal dy = item->text().contains(QLatin1Char('\n'))
2799 ? 200 - (qCeil(fm.height()) * 3)
2800 : 200 - (qCeil(fm.height()) * 1.5);
2801 return dy + fm.ascent();
2804 void tst_qquicktext::baselineOffset_data()
2806 qRegisterMetaType<ExpectedBaseline>();
2807 QTest::addColumn<QString>("text");
2808 QTest::addColumn<QString>("wrappedText");
2809 QTest::addColumn<QByteArray>("bindings");
2810 QTest::addColumn<ExpectedBaseline>("expectedBaseline");
2811 QTest::addColumn<ExpectedBaseline>("expectedBaselineEmpty");
2813 QTest::newRow("top align")
2816 << QByteArray("height: 200; verticalAlignment: Text.AlignTop")
2817 << &expectedBaselineTop
2818 << &expectedBaselineTop;
2819 QTest::newRow("bottom align")
2822 << QByteArray("height: 200; verticalAlignment: Text.AlignBottom")
2823 << &expectedBaselineBottom
2824 << &expectedBaselineBottom;
2825 QTest::newRow("center align")
2828 << QByteArray("height: 200; verticalAlignment: Text.AlignVCenter")
2829 << &expectedBaselineCenter
2830 << &expectedBaselineCenter;
2832 QTest::newRow("bold")
2833 << "<b>hello world</b>"
2834 << "<b>hello<br/>world</b>"
2835 << QByteArray("height: 200")
2836 << &expectedBaselineTop
2837 << &expectedBaselineBold;
2839 QTest::newRow("richText")
2840 << "<b>hello world</b>"
2841 << "<b>hello<br/>world</b>"
2842 << QByteArray("height: 200; textFormat: Text.RichText")
2843 << &expectedBaselineTop
2844 << &expectedBaselineTop;
2846 QTest::newRow("elided")
2849 << QByteArray("width: 20; height: 8; elide: Text.ElideRight")
2850 << &expectedBaselineTop
2851 << &expectedBaselineTop;
2853 QTest::newRow("elided bottom align")
2855 << "hello\nworld!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
2856 << QByteArray("width: 200; height: 200; elide: Text.ElideRight; verticalAlignment: Text.AlignBottom")
2857 << &expectedBaselineBottom
2858 << &expectedBaselineBottom;
2860 QTest::newRow("image")
2861 << "hello <img src=\"images/heart200.png\" /> world"
2862 << "hello <img src=\"images/heart200.png\" /><br/>world"
2863 << QByteArray("height: 200\n; baseUrl: \"") + testFileUrl("reference").toEncoded() + QByteArray("\"")
2864 << &expectedBaselineImage
2865 << &expectedBaselineTop;
2867 QTest::newRow("customLine")
2870 << QByteArray("height: 200; onLineLaidOut: line.y += 16")
2871 << &expectedBaselineCustom
2872 << &expectedBaselineCustom;
2874 QTest::newRow("scaled font")
2877 << QByteArray("width: 200; minimumPointSize: 1; font.pointSize: 64; fontSizeMode: Text.HorizontalFit")
2878 << &expectedBaselineScaled
2879 << &expectedBaselineTop;
2881 QTest::newRow("fixed line height top align")
2884 << QByteArray("height: 200; lineHeightMode: Text.FixedHeight; lineHeight: 20; verticalAlignment: Text.AlignTop")
2885 << &expectedBaselineTop
2886 << &expectedBaselineTop;
2888 QTest::newRow("fixed line height bottom align")
2891 << QByteArray("height: 200; lineHeightMode: Text.FixedHeight; lineHeight: 20; verticalAlignment: Text.AlignBottom")
2892 << &expectedBaselineFixedBottom
2893 << &expectedBaselineFixedBottom;
2895 QTest::newRow("proportional line height top align")
2898 << QByteArray("height: 200; lineHeightMode: Text.ProportionalHeight; lineHeight: 1.5; verticalAlignment: Text.AlignTop")
2899 << &expectedBaselineTop
2900 << &expectedBaselineTop;
2902 QTest::newRow("proportional line height bottom align")
2905 << QByteArray("height: 200; lineHeightMode: Text.ProportionalHeight; lineHeight: 1.5; verticalAlignment: Text.AlignBottom")
2906 << &expectedBaselineProportionalBottom
2907 << &expectedBaselineProportionalBottom;
2910 void tst_qquicktext::baselineOffset()
2912 QFETCH(QString, text);
2913 QFETCH(QString, wrappedText);
2914 QFETCH(QByteArray, bindings);
2915 QFETCH(ExpectedBaseline, expectedBaseline);
2916 QFETCH(ExpectedBaseline, expectedBaselineEmpty);
2918 QQmlComponent component(&engine);
2920 "import QtQuick 2.0\n"
2925 QScopedPointer<QObject> object(component.create());
2927 QQuickText *item = qobject_cast<QQuickText *>(object.data());
2931 qreal baseline = expectedBaselineEmpty(item);
2933 QCOMPARE(item->baselineOffset(), baseline);
2935 item->setText(text);
2936 if (expectedBaseline != expectedBaselineEmpty)
2937 baseline = expectedBaseline(item);
2939 QCOMPARE(item->baselineOffset(), baseline);
2941 item->setText(wrappedText);
2942 QCOMPARE(item->baselineOffset(), expectedBaseline(item));
2945 QFont font = item->font();
2946 font.setPointSize(font.pointSize() + 8);
2949 QCOMPARE(item->baselineOffset(), expectedBaseline(item));
2951 item->setText(text);
2952 qreal baseline = expectedBaseline(item);
2953 QCOMPARE(item->baselineOffset(), baseline);
2955 item->setText(QString());
2956 if (expectedBaselineEmpty != expectedBaseline)
2957 baseline = expectedBaselineEmpty(item);
2959 QCOMPARE(item->baselineOffset(), baseline);
2963 void tst_qquicktext::htmlLists()
2965 QFETCH(QString, text);
2966 QFETCH(int, nbLines);
2968 QQuickView *view = createView(testFile("htmlLists.qml"));
2969 QQuickText *textObject = view->rootObject()->findChild<QQuickText*>("myText");
2971 QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
2972 QVERIFY(textPrivate != 0);
2973 QVERIFY(textPrivate->extra.isAllocated());
2975 QVERIFY(textObject != 0);
2976 textObject->setText(text);
2979 view->requestActivateWindow();
2980 QTest::qWaitForWindowShown(view);
2982 QCOMPARE(textPrivate->extra->doc->lineCount(), nbLines);
2987 void tst_qquicktext::htmlLists_data()
2989 QTest::addColumn<QString>("text");
2990 QTest::addColumn<int>("nbLines");
2992 QTest::newRow("ordered list") << "<ol><li>one<li>two<li>three" << 3;
2993 QTest::newRow("ordered list closed") << "<ol><li>one</li></ol>" << 1;
2994 QTest::newRow("ordered list alpha") << "<ol type=\"a\"><li>one</li><li>two</li></ol>" << 2;
2995 QTest::newRow("ordered list upper alpha") << "<ol type=\"A\"><li>one</li><li>two</li></ol>" << 2;
2996 QTest::newRow("ordered list roman") << "<ol type=\"i\"><li>one</li><li>two</li></ol>" << 2;
2997 QTest::newRow("ordered list upper roman") << "<ol type=\"I\"><li>one</li><li>two</li></ol>" << 2;
2998 QTest::newRow("ordered list bad") << "<ol type=\"z\"><li>one</li><li>two</li></ol>" << 2;
2999 QTest::newRow("unordered list") << "<ul><li>one<li>two" << 2;
3000 QTest::newRow("unordered list closed") << "<ul><li>one</li><li>two</li></ul>" << 2;
3001 QTest::newRow("unordered list disc") << "<ul type=\"disc\"><li>one</li><li>two</li></ul>" << 2;
3002 QTest::newRow("unordered list square") << "<ul type=\"square\"><li>one</li><li>two</li></ul>" << 2;
3003 QTest::newRow("unordered list bad") << "<ul type=\"bad\"><li>one</li><li>two</li></ul>" << 2;
3006 QTEST_MAIN(tst_qquicktext)
3008 #include "tst_qquicktext.moc"