partial build fix of qtquick1 autotests
[profile/ivi/qtdeclarative.git] / tests / auto / qtquick1 / qdeclarativetext / tst_qdeclarativetext.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <qtest.h>
42 #include <QTextDocument>
43 #include <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativecomponent.h>
45 #include <QtQuick1/private/qdeclarativetext_p.h>
46 #include <QtQuick1/private/qdeclarativetext_p_p.h>
47 #include <private/qdeclarativevaluetype_p.h>
48 #include <QFontMetrics>
49 #include <QGraphicsSceneMouseEvent>
50 #include <qmath.h>
51 #include <QtQuick1/QDeclarativeView>
52 #include <QtWidgets/5.0.0/QtWidgets/private/qapplication_p.h>
53 #include <limits.h>
54
55 #include "../../../shared/util.h"
56 #include "testhttpserver.h"
57
58 #ifdef Q_OS_SYMBIAN
59 // In Symbian OS test data is located in applications private dir
60 #define SRCDIR "."
61 #endif
62
63 class tst_qdeclarativetext : public QObject
64
65 {
66     Q_OBJECT
67 public:
68     tst_qdeclarativetext();
69
70 private slots:
71     void text();
72     void width();
73     void wrap();
74     void elide();
75     void textFormat();
76
77     void alignments_data();
78     void alignments();
79
80     void embeddedImages_data();
81     void embeddedImages();
82
83     void lineCount();
84     void lineHeight();
85
86     // ### these tests may be trivial    
87     void horizontalAlignment();
88     void horizontalAlignment_RightToLeft();
89     void verticalAlignment();
90     void font();
91     void style();
92     void color();
93     void smooth();
94
95     // QDeclarativeFontValueType
96     void weight();
97     void underline();
98     void overline();
99     void strikeout();
100     void capitalization();
101     void letterSpacing();
102     void wordSpacing();
103
104     void clickLink();
105
106     void QTBUG_12291();
107     void implicitSize_data();
108     void implicitSize();
109     void testQtQuick11Attributes();
110     void testQtQuick11Attributes_data();
111
112     void qtbug_14734();
113 private:
114     QStringList standard;
115     QStringList richText;
116
117     QStringList horizontalAlignmentmentStrings;
118     QStringList verticalAlignmentmentStrings;
119
120     QList<Qt::Alignment> verticalAlignmentments;
121     QList<Qt::Alignment> horizontalAlignmentments;
122
123     QStringList styleStrings;
124     QList<QDeclarative1Text::TextStyle> styles;
125
126     QStringList colorStrings;
127
128     QDeclarativeEngine engine;
129
130     QDeclarativeView *createView(const QString &filename);
131 };
132
133 tst_qdeclarativetext::tst_qdeclarativetext()
134 {
135     standard << "the quick brown fox jumped over the lazy dog"
136             << "the quick brown fox\n jumped over the lazy dog";
137
138     richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
139             << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
140
141     horizontalAlignmentmentStrings << "AlignLeft"
142             << "AlignRight"
143             << "AlignHCenter";
144
145     verticalAlignmentmentStrings << "AlignTop"
146             << "AlignBottom"
147             << "AlignVCenter";
148
149     horizontalAlignmentments << Qt::AlignLeft
150             << Qt::AlignRight
151             << Qt::AlignHCenter;
152
153     verticalAlignmentments << Qt::AlignTop
154             << Qt::AlignBottom
155             << Qt::AlignVCenter;
156
157     styleStrings << "Normal"
158             << "Outline"
159             << "Raised"
160             << "Sunken";
161
162     styles << QDeclarative1Text::Normal
163             << QDeclarative1Text::Outline
164             << QDeclarative1Text::Raised
165             << QDeclarative1Text::Sunken;
166
167     colorStrings << "aliceblue"
168             << "antiquewhite"
169             << "aqua"
170             << "darkkhaki"
171             << "darkolivegreen"
172             << "dimgray"
173             << "palevioletred"
174             << "lightsteelblue"
175             << "#000000"
176             << "#AAAAAA"
177             << "#FFFFFF"
178             << "#2AC05F";
179     //
180     // need a different test to do alpha channel test
181     // << "#AA0011DD"
182     // << "#00F16B11";
183     //
184 }
185
186 QDeclarativeView *tst_qdeclarativetext::createView(const QString &filename)
187 {
188     QDeclarativeView *canvas = new QDeclarativeView(0);
189
190     canvas->setSource(QUrl::fromLocalFile(filename));
191     return canvas;
192 }
193
194 void tst_qdeclarativetext::text()
195 {
196     {
197         QDeclarativeComponent textComponent(&engine);
198         textComponent.setData("import QtQuick 1.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
199         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
200
201         QVERIFY(textObject != 0);
202         QCOMPARE(textObject->text(), QString(""));
203         QVERIFY(textObject->width() == 0);
204
205         delete textObject;
206     }
207
208     for (int i = 0; i < standard.size(); i++)
209     {
210         QString componentStr = "import QtQuick 1.0\nText { text: \"" + standard.at(i) + "\" }";
211         QDeclarativeComponent textComponent(&engine);
212         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
213
214         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
215
216         QVERIFY(textObject != 0);
217         QCOMPARE(textObject->text(), standard.at(i));
218         QVERIFY(textObject->width() > 0);
219
220         delete textObject;
221     }
222
223     for (int i = 0; i < richText.size(); i++)
224     {
225         QString componentStr = "import QtQuick 1.0\nText { text: \"" + richText.at(i) + "\" }";
226         QDeclarativeComponent textComponent(&engine);
227         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
228         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
229
230         QVERIFY(textObject != 0);
231         QString expected = richText.at(i);
232         QCOMPARE(textObject->text(), expected.replace("\\\"", "\""));
233         QVERIFY(textObject->width() > 0);
234
235         delete textObject;
236     }
237 }
238
239 void tst_qdeclarativetext::width()
240 {
241     // uses Font metrics to find the width for standard and document to find the width for rich
242     {
243         QDeclarativeComponent textComponent(&engine);
244         textComponent.setData("import QtQuick 1.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
245         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
246
247         QVERIFY(textObject != 0);
248         QCOMPARE(textObject->width(), 0.);
249
250         delete textObject;
251     }
252
253     for (int i = 0; i < standard.size(); i++)
254     {
255         QVERIFY(!Qt::mightBeRichText(standard.at(i))); // self-test
256
257         QFont f;
258         QFontMetricsF fm(f);
259         qreal metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
260         metricWidth = qCeil(metricWidth);
261
262         QString componentStr = "import QtQuick 1.0\nText { text: \"" + standard.at(i) + "\" }";
263         QDeclarativeComponent textComponent(&engine);
264         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
265         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
266
267         QVERIFY(textObject != 0);
268         QVERIFY(textObject->boundingRect().width() > 0);
269         QCOMPARE(textObject->width(), qreal(metricWidth));
270         QVERIFY(textObject->textFormat() == QDeclarative1Text::AutoText); // setting text doesn't change format
271
272         delete textObject;
273     }
274
275     for (int i = 0; i < richText.size(); i++)
276     {
277         QVERIFY(Qt::mightBeRichText(richText.at(i))); // self-test
278
279         QTextDocument document;
280         document.setHtml(richText.at(i));
281         document.setDocumentMargin(0);
282
283         int documentWidth = document.idealWidth();
284
285         QString componentStr = "import QtQuick 1.0\nText { text: \"" + richText.at(i) + "\" }";
286         QDeclarativeComponent textComponent(&engine);
287         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
288         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
289
290         QVERIFY(textObject != 0);
291         QCOMPARE(textObject->width(), qreal(documentWidth));
292         QVERIFY(textObject->textFormat() == QDeclarative1Text::AutoText); // setting text doesn't change format
293
294         delete textObject;
295     }
296 }
297
298 void tst_qdeclarativetext::wrap()
299 {
300     int textHeight = 0;
301     // for specified width and wrap set true
302     {
303         QDeclarativeComponent textComponent(&engine);
304         textComponent.setData("import QtQuick 1.0\nText { text: \"Hello\"; wrapMode: Text.WordWrap; width: 300 }", QUrl::fromLocalFile(""));
305         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
306         textHeight = textObject->height();
307
308         QVERIFY(textObject != 0);
309         QVERIFY(textObject->wrapMode() == QDeclarative1Text::WordWrap);
310         QCOMPARE(textObject->width(), 300.);
311
312         delete textObject;
313     }
314
315     for (int i = 0; i < standard.size(); i++)
316     {
317         QString componentStr = "import QtQuick 1.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + standard.at(i) + "\" }";
318         QDeclarativeComponent textComponent(&engine);
319         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
320         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
321
322         QVERIFY(textObject != 0);
323         QCOMPARE(textObject->width(), 30.);
324         QVERIFY(textObject->height() > textHeight);
325
326         int oldHeight = textObject->height();
327         textObject->setWidth(100);
328         QVERIFY(textObject->height() < oldHeight);
329
330         delete textObject;
331     }
332
333     for (int i = 0; i < richText.size(); i++)
334     {
335         QString componentStr = "import QtQuick 1.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + richText.at(i) + "\" }";
336         QDeclarativeComponent textComponent(&engine);
337         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
338         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
339
340         QVERIFY(textObject != 0);
341         QCOMPARE(textObject->width(), 30.);
342         QVERIFY(textObject->height() > textHeight);
343
344         qreal oldHeight = textObject->height();
345         textObject->setWidth(100);
346         QVERIFY(textObject->height() < oldHeight);
347
348         delete textObject;
349     }
350
351     // richtext again with a fixed height
352     for (int i = 0; i < richText.size(); i++)
353     {
354         QString componentStr = "import QtQuick 1.0\nText { wrapMode: Text.WordWrap; width: 30; height: 50; text: \"" + richText.at(i) + "\" }";
355         QDeclarativeComponent textComponent(&engine);
356         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
357         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
358
359         QVERIFY(textObject != 0);
360         QCOMPARE(textObject->width(), 30.);
361         QVERIFY(textObject->implicitHeight() > textHeight);
362
363         qreal oldHeight = textObject->implicitHeight();
364         textObject->setWidth(100);
365         QVERIFY(textObject->implicitHeight() < oldHeight);
366
367         delete textObject;
368     }
369 }
370
371 void tst_qdeclarativetext::elide()
372 {
373     for (QDeclarative1Text::TextElideMode m = QDeclarative1Text::ElideLeft; m<=QDeclarative1Text::ElideNone; m=QDeclarative1Text::TextElideMode(int(m)+1)) {
374         const char* elidename[]={"ElideLeft", "ElideRight", "ElideMiddle", "ElideNone"};
375         QString elide = "elide: Text." + QString(elidename[int(m)]) + ";";
376
377         // XXX Poor coverage.
378
379         {
380             QDeclarativeComponent textComponent(&engine);
381             textComponent.setData(("import QtQuick 1.0\nText { text: \"\"; "+elide+" width: 100 }").toLatin1(), QUrl::fromLocalFile(""));
382             QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
383
384             QCOMPARE(textObject->elideMode(), m);
385             QCOMPARE(textObject->width(), 100.);
386
387             delete textObject;
388         }
389
390         for (int i = 0; i < standard.size(); i++)
391         {
392             QString componentStr = "import QtQuick 1.0\nText { "+elide+" width: 100; text: \"" + standard.at(i) + "\" }";
393             QDeclarativeComponent textComponent(&engine);
394             textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
395             QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
396
397             QCOMPARE(textObject->elideMode(), m);
398             QCOMPARE(textObject->width(), 100.);
399
400             delete textObject;
401         }
402
403         // richtext - does nothing
404         for (int i = 0; i < richText.size(); i++)
405         {
406             QString componentStr = "import QtQuick 1.0\nText { "+elide+" width: 100; text: \"" + richText.at(i) + "\" }";
407             QDeclarativeComponent textComponent(&engine);
408             textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
409             QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
410
411             QCOMPARE(textObject->elideMode(), m);
412             QCOMPARE(textObject->width(), 100.);
413
414             delete textObject;
415         }
416     }
417
418     // QTBUG-18627
419     QUrl qmlfile = QUrl::fromLocalFile(SRCDIR "/data/elideimplicitwidth.qml");
420     QDeclarativeComponent textComponent(&engine, qmlfile);
421     QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(textComponent.create());
422     QVERIFY(item != 0);
423     QVERIFY(item->implicitWidth() > item->width());
424 }
425
426 void tst_qdeclarativetext::textFormat()
427 {
428     {
429         QDeclarativeComponent textComponent(&engine);
430         textComponent.setData("import QtQuick 1.0\nText { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
431         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
432
433         QVERIFY(textObject != 0);
434         QVERIFY(textObject->textFormat() == QDeclarative1Text::RichText);
435
436         delete textObject;
437     }
438     {
439         QDeclarativeComponent textComponent(&engine);
440         textComponent.setData("import QtQuick 1.0\nText { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
441         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
442
443         QVERIFY(textObject != 0);
444         QVERIFY(textObject->textFormat() == QDeclarative1Text::PlainText);
445
446         delete textObject;
447     }
448 }
449
450
451 void tst_qdeclarativetext::alignments_data()
452 {
453     QTest::addColumn<int>("hAlign");
454     QTest::addColumn<int>("vAlign");
455     QTest::addColumn<QString>("expectfile");
456
457     QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << SRCDIR "/data/alignments_lt.png";
458     QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << SRCDIR "/data/alignments_rt.png";
459     QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << SRCDIR "/data/alignments_ct.png";
460
461     QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << SRCDIR "/data/alignments_lb.png";
462     QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << SRCDIR "/data/alignments_rb.png";
463     QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << SRCDIR "/data/alignments_cb.png";
464
465     QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << SRCDIR "/data/alignments_lc.png";
466     QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << SRCDIR "/data/alignments_rc.png";
467     QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << SRCDIR "/data/alignments_cc.png";
468 }
469
470
471 void tst_qdeclarativetext::alignments()
472 {
473     QFETCH(int, hAlign);
474     QFETCH(int, vAlign);
475     QFETCH(QString, expectfile);
476
477 #ifdef Q_WS_X11
478     // Font-specific, but not likely platform-specific, so only test on one platform
479     QFont fn;
480     fn.setRawName("-misc-fixed-medium-r-*-*-8-*-*-*-*-*-*-*");
481     QApplication::setFont(fn);
482 #endif
483
484     QDeclarativeView *canvas = createView(SRCDIR "/data/alignments.qml");
485
486     canvas->show();
487     QApplication::setActiveWindow(canvas);
488     QTest::qWaitForWindowShown(canvas);
489     QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
490
491     QObject *ob = canvas->rootObject();
492     QVERIFY(ob != 0);
493     ob->setProperty("horizontalAlignment",hAlign);
494     ob->setProperty("verticalAlignment",vAlign);
495     QTRY_COMPARE(ob->property("running").toBool(),false);
496     QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32);
497     actual.fill(qRgb(255,255,255));
498     QPainter p(&actual);
499     canvas->render(&p);
500
501     QImage expect(expectfile);
502
503 #ifdef Q_WS_X11
504     // Font-specific, but not likely platform-specific, so only test on one platform
505     if (QApplicationPrivate::graphics_system_name == "raster" || QApplicationPrivate::graphics_system_name == "") {
506         QCOMPARE(actual,expect);
507     }
508 #endif
509
510     delete canvas;
511 }
512
513 //the alignment tests may be trivial o.oa
514 void tst_qdeclarativetext::horizontalAlignment()
515 {
516     //test one align each, and then test if two align fails.
517
518     for (int i = 0; i < standard.size(); i++)
519     {
520         for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
521         {
522             QString componentStr = "import QtQuick 1.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
523             QDeclarativeComponent textComponent(&engine);
524             textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
525             QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
526
527             QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
528
529             delete textObject;
530         }
531     }
532
533     for (int i = 0; i < richText.size(); i++)
534     {
535         for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
536         {
537             QString componentStr = "import QtQuick 1.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
538             QDeclarativeComponent textComponent(&engine);
539             textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
540             QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
541
542             QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
543
544             delete textObject;
545         }
546     }
547
548 }
549
550 void tst_qdeclarativetext::horizontalAlignment_RightToLeft()
551 {
552     QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml");
553     QDeclarative1Text *text = canvas->rootObject()->findChild<QDeclarative1Text*>("text");
554     QVERIFY(text != 0);
555     canvas->show();
556
557     QDeclarative1TextPrivate *textPrivate = QDeclarative1TextPrivate::get(text);
558     QVERIFY(textPrivate != 0);
559
560     // implicit alignment should follow the reading direction of RTL text
561     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignRight);
562     QCOMPARE(text->effectiveHAlign(), text->hAlign());
563     QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
564
565     // explicitly left aligned text
566     text->setHAlign(QDeclarative1Text::AlignLeft);
567     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignLeft);
568     QCOMPARE(text->effectiveHAlign(), text->hAlign());
569     QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
570
571     // explicitly right aligned text
572     text->setHAlign(QDeclarative1Text::AlignRight);
573     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignRight);
574     QCOMPARE(text->effectiveHAlign(), text->hAlign());
575     QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
576
577     // change to rich text
578     QString textString = text->text();
579     text->setText(QString("<i>") + textString + QString("</i>"));
580     text->setTextFormat(QDeclarative1Text::RichText);
581     text->resetHAlign();
582
583     // implicitly aligned rich text should follow the reading direction of text
584     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignRight);
585     QCOMPARE(text->effectiveHAlign(), text->hAlign());
586     QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignLeft);
587
588     // explicitly left aligned rich text
589     text->setHAlign(QDeclarative1Text::AlignLeft);
590     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignLeft);
591     QCOMPARE(text->effectiveHAlign(), text->hAlign());
592     QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignRight);
593
594     // explicitly right aligned rich text
595     text->setHAlign(QDeclarative1Text::AlignRight);
596     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignRight);
597     QCOMPARE(text->effectiveHAlign(), text->hAlign());
598     QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignLeft);
599
600     text->setText(textString);
601     text->setTextFormat(QDeclarative1Text::PlainText);
602
603     // explicitly center aligned
604     text->setHAlign(QDeclarative1Text::AlignHCenter);
605     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignHCenter);
606     QCOMPARE(text->effectiveHAlign(), text->hAlign());
607     QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
608     QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().right() > canvas->width()/2);
609
610     // reseted alignment should go back to following the text reading direction
611     text->resetHAlign();
612     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignRight);
613     QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
614
615     // mirror the text item
616     QDeclarativeItemPrivate::get(text)->setLayoutMirror(true);
617
618     // mirrored implicit alignment should continue to follow the reading direction of the text
619     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignRight);
620     QCOMPARE(text->effectiveHAlign(), QDeclarative1Text::AlignRight);
621     QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
622
623     // mirrored explicitly right aligned behaves as left aligned
624     text->setHAlign(QDeclarative1Text::AlignRight);
625     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignRight);
626     QCOMPARE(text->effectiveHAlign(), QDeclarative1Text::AlignLeft);
627     QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
628
629     // mirrored explicitly left aligned behaves as right aligned
630     text->setHAlign(QDeclarative1Text::AlignLeft);
631     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignLeft);
632     QCOMPARE(text->effectiveHAlign(), QDeclarative1Text::AlignRight);
633     QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
634
635     // disable mirroring
636     QDeclarativeItemPrivate::get(text)->setLayoutMirror(false);
637     text->resetHAlign();
638
639     // English text should be implicitly left aligned
640     text->setText("Hello world!");
641     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignLeft);
642     QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
643
644 #ifndef Q_OS_MAC    // QTBUG-18040
645     // empty text with implicit alignment follows the system locale-based
646     // keyboard input direction from QApplication::keyboardInputDirection
647     text->setText("");
648     QCOMPARE(text->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
649                                   QDeclarative1Text::AlignLeft : QDeclarative1Text::AlignRight);
650     text->setHAlign(QDeclarative1Text::AlignRight);
651     QCOMPARE(text->hAlign(), QDeclarative1Text::AlignRight);
652 #endif
653
654     delete canvas;
655
656 #ifndef Q_OS_MAC    // QTBUG-18040
657     // alignment of Text with no text set to it
658     QString componentStr = "import QtQuick 1.0\nText {}";
659     QDeclarativeComponent textComponent(&engine);
660     textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
661     QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
662     QCOMPARE(textObject->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
663                                   QDeclarative1Text::AlignLeft : QDeclarative1Text::AlignRight);
664     delete textObject;
665 #endif
666 }
667
668 void tst_qdeclarativetext::verticalAlignment()
669 {
670     //test one align each, and then test if two align fails.
671
672     for (int i = 0; i < standard.size(); i++)
673     {
674         for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
675         {
676             QString componentStr = "import QtQuick 1.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
677             QDeclarativeComponent textComponent(&engine);
678             textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
679             QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
680
681             QVERIFY(textObject != 0);
682             QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
683
684             delete textObject;
685         }
686     }
687
688     for (int i = 0; i < richText.size(); i++)
689     {
690         for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
691         {
692             QString componentStr = "import QtQuick 1.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
693             QDeclarativeComponent textComponent(&engine);
694             textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
695             QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
696
697             QVERIFY(textObject != 0);
698             QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
699
700             delete textObject;
701         }
702     }
703
704     //confirm that bounding rect is correctly positioned.
705     QString componentStr = "import QtQuick 1.0\nText { height: 80; text: \"Hello\" }";
706     QDeclarativeComponent textComponent(&engine);
707     textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
708     QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
709     QVERIFY(textObject != 0);
710     QRectF br = textObject->boundingRect();
711     QVERIFY(br.y() == 0);
712
713     textObject->setVAlign(QDeclarative1Text::AlignVCenter);
714     br = textObject->boundingRect();
715     QCOMPARE(qFloor(br.y()), qFloor((80.0 - br.height())/2));
716
717     textObject->setVAlign(QDeclarative1Text::AlignBottom);
718     br = textObject->boundingRect();
719     QCOMPARE(qFloor(br.y()), qFloor(80.0 - br.height()));
720
721     delete textObject;
722 }
723
724 void tst_qdeclarativetext::font()
725 {
726     //test size, then bold, then italic, then family
727     {
728         QString componentStr = "import QtQuick 1.0\nText { font.pointSize: 40; text: \"Hello World\" }";
729         QDeclarativeComponent textComponent(&engine);
730         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
731         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
732
733         QCOMPARE(textObject->font().pointSize(), 40);
734         QCOMPARE(textObject->font().bold(), false);
735         QCOMPARE(textObject->font().italic(), false);
736
737         delete textObject;
738     }
739
740     {
741         QString componentStr = "import QtQuick 1.0\nText { font.pixelSize: 40; text: \"Hello World\" }";
742         QDeclarativeComponent textComponent(&engine);
743         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
744         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
745
746         QCOMPARE(textObject->font().pixelSize(), 40);
747         QCOMPARE(textObject->font().bold(), false);
748         QCOMPARE(textObject->font().italic(), false);
749
750         delete textObject;
751     }
752
753     { 
754         QString componentStr = "import QtQuick 1.0\nText { font.bold: true; text: \"Hello World\" }";
755         QDeclarativeComponent textComponent(&engine);
756         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
757         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
758
759         QCOMPARE(textObject->font().bold(), true);
760         QCOMPARE(textObject->font().italic(), false);
761
762         delete textObject;
763     }
764
765     { 
766         QString componentStr = "import QtQuick 1.0\nText { font.italic: true; text: \"Hello World\" }";
767         QDeclarativeComponent textComponent(&engine);
768         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
769         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
770
771         QCOMPARE(textObject->font().italic(), true);
772         QCOMPARE(textObject->font().bold(), false);
773
774         delete textObject;
775     }
776
777     { 
778         QString componentStr = "import QtQuick 1.0\nText { font.family: \"Helvetica\"; text: \"Hello World\" }";
779         QDeclarativeComponent textComponent(&engine);
780         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
781         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
782
783         QCOMPARE(textObject->font().family(), QString("Helvetica"));
784         QCOMPARE(textObject->font().bold(), false);
785         QCOMPARE(textObject->font().italic(), false);
786
787         delete textObject;
788     }
789
790     { 
791         QString componentStr = "import QtQuick 1.0\nText { font.family: \"\"; text: \"Hello World\" }";
792         QDeclarativeComponent textComponent(&engine);
793         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
794         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
795
796         QCOMPARE(textObject->font().family(), QString(""));
797
798         delete textObject;
799     }
800 }
801
802 void tst_qdeclarativetext::style()
803 {
804     //test style
805     for (int i = 0; i < styles.size(); i++)
806     { 
807         QString componentStr = "import QtQuick 1.0\nText { style: \"" + styleStrings.at(i) + "\"; styleColor: \"white\"; text: \"Hello World\" }";
808         QDeclarativeComponent textComponent(&engine);
809         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
810         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
811
812         QCOMPARE((int)textObject->style(), (int)styles.at(i));
813         QCOMPARE(textObject->styleColor(), QColor("white"));
814
815         delete textObject;
816     }
817     QString componentStr = "import QtQuick 1.0\nText { text: \"Hello World\" }";
818     QDeclarativeComponent textComponent(&engine);
819     textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
820     QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
821
822     QRectF brPre = textObject->boundingRect();
823     textObject->setStyle(QDeclarative1Text::Outline);
824     QRectF brPost = textObject->boundingRect();
825
826     QVERIFY(brPre.width() < brPost.width());
827     QVERIFY(brPre.height() < brPost.height());
828
829     delete textObject;
830 }
831
832 void tst_qdeclarativetext::color()
833 {
834     //test style
835     for (int i = 0; i < colorStrings.size(); i++)
836     { 
837         QString componentStr = "import QtQuick 1.0\nText { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
838         QDeclarativeComponent textComponent(&engine);
839         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
840         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
841
842         QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
843         QCOMPARE(textObject->styleColor(), QColor());
844
845         delete textObject;
846     }
847
848     for (int i = 0; i < colorStrings.size(); i++)
849     { 
850         QString componentStr = "import QtQuick 1.0\nText { styleColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
851         QDeclarativeComponent textComponent(&engine);
852         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
853         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
854
855         QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(i)));
856         // default color to black?
857         QCOMPARE(textObject->color(), QColor("black"));
858
859         delete textObject;
860     }
861     
862     for (int i = 0; i < colorStrings.size(); i++)
863     { 
864         for (int j = 0; j < colorStrings.size(); j++)
865         {
866             QString componentStr = "import QtQuick 1.0\nText { color: \"" + colorStrings.at(i) + "\"; styleColor: \"" + colorStrings.at(j) + "\"; text: \"Hello World\" }";
867             QDeclarativeComponent textComponent(&engine);
868             textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
869             QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
870
871             QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
872             QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(j)));
873
874             delete textObject;
875         }
876     }
877     {
878         QString colorStr = "#AA001234";
879         QColor testColor("#001234");
880         testColor.setAlpha(170);
881
882         QString componentStr = "import QtQuick 1.0\nText { color: \"" + colorStr + "\"; text: \"Hello World\" }";
883         QDeclarativeComponent textComponent(&engine);
884         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
885         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
886
887         QCOMPARE(textObject->color(), testColor);
888
889         delete textObject;
890     }
891 }
892
893 void tst_qdeclarativetext::smooth()
894 {
895     for (int i = 0; i < standard.size(); i++)
896     {
897         {
898             QString componentStr = "import QtQuick 1.0\nText { smooth: true; text: \"" + standard.at(i) + "\" }";
899             QDeclarativeComponent textComponent(&engine);
900             textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
901             QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
902             QCOMPARE(textObject->smooth(), true);
903
904             delete textObject;
905         }
906         {
907             QString componentStr = "import QtQuick 1.0\nText { text: \"" + standard.at(i) + "\" }";
908             QDeclarativeComponent textComponent(&engine);
909             textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
910             QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
911             QCOMPARE(textObject->smooth(), false);
912
913             delete textObject;
914         }
915     }
916     for (int i = 0; i < richText.size(); i++)
917     {
918         {
919             QString componentStr = "import QtQuick 1.0\nText { smooth: true; text: \"" + richText.at(i) + "\" }";
920             QDeclarativeComponent textComponent(&engine);
921             textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
922             QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
923             QCOMPARE(textObject->smooth(), true);
924
925             delete textObject;
926         }
927         {
928             QString componentStr = "import QtQuick 1.0\nText { text: \"" + richText.at(i) + "\" }";
929             QDeclarativeComponent textComponent(&engine);
930             textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
931             QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
932             QCOMPARE(textObject->smooth(), false);
933
934             delete textObject;
935         }
936     }
937 }
938
939 void tst_qdeclarativetext::weight()
940 {
941     {
942         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\" }";
943         QDeclarativeComponent textComponent(&engine);
944         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
945         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
946
947         QVERIFY(textObject != 0);
948         QCOMPARE((int)textObject->font().weight(), (int)QDeclarativeFontValueType::Normal);
949
950         delete textObject;
951     }
952     {
953         QString componentStr = "import QtQuick 1.0\nText { font.weight: \"Bold\"; text: \"Hello world!\" }";
954         QDeclarativeComponent textComponent(&engine);
955         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
956         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
957
958         QVERIFY(textObject != 0);
959         QCOMPARE((int)textObject->font().weight(), (int)QDeclarativeFontValueType::Bold);
960
961         delete textObject;
962     }
963 }
964
965 void tst_qdeclarativetext::underline()
966 {
967     {
968         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\" }";
969         QDeclarativeComponent textComponent(&engine);
970         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
971         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
972
973         QVERIFY(textObject != 0);
974         QCOMPARE(textObject->font().underline(), false);
975
976         delete textObject;
977     }
978     {
979         QString componentStr = "import QtQuick 1.0\nText { font.underline: true; text: \"Hello world!\" }";
980         QDeclarativeComponent textComponent(&engine);
981         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
982         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
983
984         QVERIFY(textObject != 0);
985         QCOMPARE(textObject->font().underline(), true);
986
987         delete textObject;
988     }
989 }
990
991 void tst_qdeclarativetext::overline()
992 {
993     {
994         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\" }";
995         QDeclarativeComponent textComponent(&engine);
996         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
997         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
998
999         QVERIFY(textObject != 0);
1000         QCOMPARE(textObject->font().overline(), false);
1001
1002         delete textObject;
1003     }
1004     {
1005         QString componentStr = "import QtQuick 1.0\nText { font.overline: true; text: \"Hello world!\" }";
1006         QDeclarativeComponent textComponent(&engine);
1007         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1008         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1009
1010         QVERIFY(textObject != 0);
1011         QCOMPARE(textObject->font().overline(), true);
1012
1013         delete textObject;
1014     }
1015 }
1016
1017 void tst_qdeclarativetext::strikeout()
1018 {
1019     {
1020         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\" }";
1021         QDeclarativeComponent textComponent(&engine);
1022         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1023         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1024
1025         QVERIFY(textObject != 0);
1026         QCOMPARE(textObject->font().strikeOut(), false);
1027
1028         delete textObject;
1029     }
1030     {
1031         QString componentStr = "import QtQuick 1.0\nText { font.strikeout: true; text: \"Hello world!\" }";
1032         QDeclarativeComponent textComponent(&engine);
1033         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1034         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1035
1036         QVERIFY(textObject != 0);
1037         QCOMPARE(textObject->font().strikeOut(), true);
1038
1039         delete textObject;
1040     }
1041 }
1042
1043 void tst_qdeclarativetext::capitalization()
1044 {
1045     {
1046         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\" }";
1047         QDeclarativeComponent textComponent(&engine);
1048         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1049         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1050
1051         QVERIFY(textObject != 0);
1052         QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::MixedCase);
1053
1054         delete textObject;
1055     }
1056     {
1057         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\"; font.capitalization: \"AllUppercase\" }";
1058         QDeclarativeComponent textComponent(&engine);
1059         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1060         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1061
1062         QVERIFY(textObject != 0);
1063         QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::AllUppercase);
1064
1065         delete textObject;
1066     }
1067     {
1068         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\"; font.capitalization: \"AllLowercase\" }";
1069         QDeclarativeComponent textComponent(&engine);
1070         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1071         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1072
1073         QVERIFY(textObject != 0);
1074         QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::AllLowercase);
1075
1076         delete textObject;
1077     }
1078     {
1079         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\"; font.capitalization: \"SmallCaps\" }";
1080         QDeclarativeComponent textComponent(&engine);
1081         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1082         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1083
1084         QVERIFY(textObject != 0);
1085         QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::SmallCaps);
1086
1087         delete textObject;
1088     }
1089     {
1090         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\"; font.capitalization: \"Capitalize\" }";
1091         QDeclarativeComponent textComponent(&engine);
1092         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1093         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1094
1095         QVERIFY(textObject != 0);
1096         QCOMPARE((int)textObject->font().capitalization(), (int)QDeclarativeFontValueType::Capitalize);
1097
1098         delete textObject;
1099     }
1100 }
1101
1102 void tst_qdeclarativetext::letterSpacing()
1103 {
1104     {
1105         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\" }";
1106         QDeclarativeComponent textComponent(&engine);
1107         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1108         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1109
1110         QVERIFY(textObject != 0);
1111         QCOMPARE(textObject->font().letterSpacing(), 0.0);
1112
1113         delete textObject;
1114     }
1115     {
1116         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\"; font.letterSpacing: -2 }";
1117         QDeclarativeComponent textComponent(&engine);
1118         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1119         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1120
1121         QVERIFY(textObject != 0);
1122         QCOMPARE(textObject->font().letterSpacing(), -2.);
1123
1124         delete textObject;
1125     }
1126     {
1127         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\"; font.letterSpacing: 3 }";
1128         QDeclarativeComponent textComponent(&engine);
1129         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1130         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1131
1132         QVERIFY(textObject != 0);
1133         QCOMPARE(textObject->font().letterSpacing(), 3.);
1134
1135         delete textObject;
1136     }
1137 }
1138
1139 void tst_qdeclarativetext::wordSpacing()
1140 {
1141     {
1142         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\" }";
1143         QDeclarativeComponent textComponent(&engine);
1144         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1145         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1146
1147         QVERIFY(textObject != 0);
1148         QCOMPARE(textObject->font().wordSpacing(), 0.0);
1149
1150         delete textObject;
1151     }
1152     {
1153         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\"; font.wordSpacing: -50 }";
1154         QDeclarativeComponent textComponent(&engine);
1155         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1156         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1157
1158         QVERIFY(textObject != 0);
1159         QCOMPARE(textObject->font().wordSpacing(), -50.);
1160
1161         delete textObject;
1162     }
1163     {
1164         QString componentStr = "import QtQuick 1.0\nText { text: \"Hello world!\"; font.wordSpacing: 200 }";
1165         QDeclarativeComponent textComponent(&engine);
1166         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1167         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1168
1169         QVERIFY(textObject != 0);
1170         QCOMPARE(textObject->font().wordSpacing(), 200.);
1171
1172         delete textObject;
1173     }
1174 }
1175
1176 void tst_qdeclarativetext::QTBUG_12291()
1177 {
1178     QDeclarativeView *canvas = createView(SRCDIR "/data/rotated.qml");
1179
1180     canvas->show();
1181     QApplication::setActiveWindow(canvas);
1182     QTest::qWaitForWindowShown(canvas);
1183     QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1184
1185     QObject *ob = canvas->rootObject();
1186     QVERIFY(ob != 0);
1187
1188     QDeclarative1Text *text = ob->findChild<QDeclarative1Text*>("text");
1189     QVERIFY(text);
1190     QVERIFY(text->boundingRect().isValid());
1191
1192     delete canvas;
1193 }
1194
1195 class EventSender : public QGraphicsItem
1196 {
1197 public:
1198     void sendEvent(QEvent *event) { sceneEvent(event); }
1199 };
1200
1201 class LinkTest : public QObject
1202 {
1203     Q_OBJECT
1204 public:
1205     LinkTest() {}
1206
1207     QString link;
1208
1209 public slots:
1210     void linkClicked(QString l) { link = l; }
1211 };
1212
1213 void tst_qdeclarativetext::clickLink()
1214 {
1215     {
1216         QString componentStr = "import QtQuick 1.0\nText { text: \"<a href=\\\"http://qt.nokia.com\\\">Hello world!</a>\" }";
1217         QDeclarativeComponent textComponent(&engine);
1218         textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1219         QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1220
1221         QVERIFY(textObject != 0);
1222
1223         LinkTest test;
1224         QObject::connect(textObject, SIGNAL(linkActivated(QString)), &test, SLOT(linkClicked(QString)));
1225
1226         {
1227             QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMousePress);
1228             me.setPos(QPointF(textObject->x()/2, textObject->y()/2));
1229             me.setButton(Qt::LeftButton);
1230             static_cast<EventSender*>(static_cast<QGraphicsItem*>(textObject))->sendEvent(&me);
1231         }
1232
1233         {
1234             QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMouseRelease);
1235             me.setPos(QPointF(textObject->x()/2, textObject->y()/2));
1236             me.setButton(Qt::LeftButton);
1237             static_cast<EventSender*>(static_cast<QGraphicsItem*>(textObject))->sendEvent(&me);
1238         }
1239
1240         QCOMPARE(test.link, QLatin1String("http://qt.nokia.com"));
1241
1242         delete textObject;
1243     }
1244 }
1245
1246 void tst_qdeclarativetext::embeddedImages_data()
1247 {
1248     QTest::addColumn<QUrl>("qmlfile");
1249     QTest::addColumn<QString>("error");
1250     QTest::newRow("local") << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesLocal.qml") << "";
1251     QTest::newRow("local-error") << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesLocalError.qml")
1252         << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesLocalError.qml").toString()+":3:1: QML Text: Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/http/notexists.png").toString();
1253     QTest::newRow("remote") << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesRemote.qml") << "";
1254     QTest::newRow("remote-error") << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesRemoteError.qml")
1255         << QUrl::fromLocalFile(SRCDIR "/data/embeddedImagesRemoteError.qml").toString()+":3:1: QML Text: Error downloading http://127.0.0.1:14453/notexists.png - server replied: Not found";
1256 }
1257
1258 void tst_qdeclarativetext::embeddedImages()
1259 {
1260     // Tests QTBUG-9900
1261
1262     QFETCH(QUrl, qmlfile);
1263     QFETCH(QString, error);
1264
1265     TestHTTPServer server(14453);
1266     server.serveDirectory(SRCDIR "/data/http");
1267
1268     if (!error.isEmpty())
1269         QTest::ignoreMessage(QtWarningMsg, error.toLatin1());
1270     
1271     QDeclarativeComponent textComponent(&engine, qmlfile);
1272     QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1273
1274     QVERIFY(textObject != 0);
1275
1276     QTRY_COMPARE(textObject->resourcesLoading(), 0);
1277
1278     QPixmap pm(SRCDIR "/data/http/exists.png");
1279     if (error.isEmpty()) {
1280         QCOMPARE(textObject->width(), double(pm.width()));
1281         QCOMPARE(textObject->height(), double(pm.height()));
1282     } else {
1283         QVERIFY(16 != pm.width()); // check test is effective
1284         QCOMPARE(textObject->width(), 16.0); // default size of QTextDocument broken image icon
1285         QCOMPARE(textObject->height(), 16.0);
1286     }
1287
1288     delete textObject;
1289 }
1290
1291 void tst_qdeclarativetext::lineCount()
1292 {
1293     QDeclarativeView *canvas = createView(SRCDIR "/data/lineCount.qml");
1294
1295     QDeclarative1Text *myText = canvas->rootObject()->findChild<QDeclarative1Text*>("myText");
1296     QVERIFY(myText != 0);
1297
1298     QVERIFY(myText->lineCount() > 1);
1299     QVERIFY(!myText->truncated());
1300     QCOMPARE(myText->maximumLineCount(), INT_MAX);
1301
1302     myText->setMaximumLineCount(2);
1303     QCOMPARE(myText->lineCount(), 2);
1304     QCOMPARE(myText->truncated(), true);
1305     QCOMPARE(myText->maximumLineCount(), 2);
1306
1307     myText->resetMaximumLineCount();
1308     QCOMPARE(myText->maximumLineCount(), INT_MAX);
1309     QCOMPARE(myText->truncated(), false);
1310
1311     myText->setElideMode(QDeclarative1Text::ElideRight);
1312     myText->setMaximumLineCount(2);
1313     QCOMPARE(myText->lineCount(), 2);
1314     QCOMPARE(myText->truncated(), true);
1315     QCOMPARE(myText->maximumLineCount(), 2);
1316
1317     delete canvas;
1318 }
1319
1320 void tst_qdeclarativetext::lineHeight()
1321 {
1322     QDeclarativeView *canvas = createView(SRCDIR "/data/lineHeight.qml");
1323
1324     QDeclarative1Text *myText = canvas->rootObject()->findChild<QDeclarative1Text*>("myText");
1325     QVERIFY(myText != 0);
1326
1327     QVERIFY(myText->lineHeight() == 1);
1328     QVERIFY(myText->lineHeightMode() == QDeclarative1Text::ProportionalHeight);
1329
1330     qreal h = myText->height();
1331     myText->setLineHeight(1.5);
1332 #ifdef Q_WS_QPA
1333     QEXPECT_FAIL("", "QTBUG-21015 fails", Continue);
1334 #endif
1335     QVERIFY(myText->height() == h * 1.5);
1336
1337     myText->setLineHeightMode(QDeclarative1Text::FixedHeight);
1338     myText->setLineHeight(20);
1339     QCOMPARE(myText->height(), myText->lineCount() * 20.0);
1340
1341     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.");
1342     myText->setLineHeightMode(QDeclarative1Text::ProportionalHeight);
1343     myText->setLineHeight(1.0);
1344
1345     qreal h2 = myText->height();
1346     myText->setLineHeight(2.0);
1347     QEXPECT_FAIL("", "QTBUG-17325", Continue);
1348     QVERIFY(myText->height() == h2 * 2.0);
1349
1350     myText->setLineHeightMode(QDeclarative1Text::FixedHeight);
1351     myText->setLineHeight(10);
1352     QEXPECT_FAIL("", "QTBUG-17325", Continue);
1353     QCOMPARE(myText->height(), myText->lineCount() * 10.0);
1354
1355     delete canvas;
1356 }
1357
1358 void tst_qdeclarativetext::implicitSize_data()
1359 {
1360     QTest::addColumn<QString>("text");
1361     QTest::addColumn<QString>("wrap");
1362     QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "Text.NoWrap";
1363     QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "Text.NoWrap";
1364     QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "Text.Wrap";
1365     QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "Text.Wrap";
1366 }
1367
1368 void tst_qdeclarativetext::implicitSize()
1369 {
1370     QFETCH(QString, text);
1371     QFETCH(QString, wrap);
1372     QString componentStr = "import QtQuick 1.1\nText { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }";
1373     QDeclarativeComponent textComponent(&engine);
1374     textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1375     QDeclarative1Text *textObject = qobject_cast<QDeclarative1Text*>(textComponent.create());
1376
1377     QVERIFY(textObject->width() < textObject->implicitWidth());
1378     QVERIFY(textObject->height() == textObject->implicitHeight());
1379
1380     textObject->resetWidth();
1381     QVERIFY(textObject->width() == textObject->implicitWidth());
1382     QVERIFY(textObject->height() == textObject->implicitHeight());
1383
1384     delete textObject;
1385 }
1386
1387 void tst_qdeclarativetext::testQtQuick11Attributes()
1388 {
1389     QFETCH(QString, code);
1390     QFETCH(QString, warning);
1391     QFETCH(QString, error);
1392
1393     QDeclarativeEngine engine;
1394     QObject *obj;
1395
1396     QDeclarativeComponent valid(&engine);
1397     valid.setData("import QtQuick 1.1; Text { " + code.toUtf8() + " }", QUrl(""));
1398     obj = valid.create();
1399     QVERIFY(obj);
1400     QVERIFY(valid.errorString().isEmpty());
1401     delete obj;
1402
1403     QDeclarativeComponent invalid(&engine);
1404     invalid.setData("import QtQuick 1.0; Text { " + code.toUtf8() + " }", QUrl(""));
1405     QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
1406     obj = invalid.create();
1407     QCOMPARE(invalid.errorString(), error);
1408     delete obj;
1409 }
1410
1411 void tst_qdeclarativetext::testQtQuick11Attributes_data()
1412 {
1413     QTest::addColumn<QString>("code");
1414     QTest::addColumn<QString>("warning");
1415     QTest::addColumn<QString>("error");
1416
1417     QTest::newRow("maximumLineCount") << "maximumLineCount: 4"
1418         << "QDeclarativeComponent: Component is not ready"
1419         << ":1 \"Text.maximumLineCount\" is not available in QtQuick 1.0.\n";
1420
1421     QTest::newRow("lineHeight") << "lineHeight: 2"
1422         << "QDeclarativeComponent: Component is not ready"
1423         << ":1 \"Text.lineHeight\" is not available in QtQuick 1.0.\n";
1424
1425     QTest::newRow("lineHeightMode") << "lineHeightMode: Text.ProportionalHeight"
1426         << "QDeclarativeComponent: Component is not ready"
1427         << ":1 \"Text.lineHeightMode\" is not available in QtQuick 1.0.\n";
1428
1429     QTest::newRow("lineCount") << "property int foo: lineCount"
1430         << "<Unknown File>:1: ReferenceError: Can't find variable: lineCount"
1431         << "";
1432
1433     QTest::newRow("truncated") << "property bool foo: truncated"
1434         << "<Unknown File>:1: ReferenceError: Can't find variable: truncated"
1435         << "";
1436 }
1437
1438 void tst_qdeclarativetext::qtbug_14734()
1439 {
1440     QDeclarativeView *canvas = createView(SRCDIR "/data/qtbug_14734.qml");
1441     QVERIFY(canvas);
1442
1443     canvas->show();
1444     QApplication::setActiveWindow(canvas);
1445     QTest::qWaitForWindowShown(canvas);
1446     QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1447
1448     delete canvas;
1449 }
1450
1451 QTEST_MAIN(tst_qdeclarativetext)
1452
1453 #include "tst_qdeclarativetext.moc"