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