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