tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp
changeset 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 "../../../shared/util.h"
       
    43 #include "../shared/testhttpserver.h"
       
    44 #include <math.h>
       
    45 #include <QFile>
       
    46 #include <QTextDocument>
       
    47 #include <QtDeclarative/qdeclarativeengine.h>
       
    48 #include <QtDeclarative/qdeclarativecontext.h>
       
    49 #include <QtDeclarative/qdeclarativeexpression.h>
       
    50 #include <QtDeclarative/qdeclarativecomponent.h>
       
    51 #include <private/qdeclarativetextedit_p.h>
       
    52 #include <QFontMetrics>
       
    53 #include <QDeclarativeView>
       
    54 #include <QStyle>
       
    55 #include <QInputContext>
       
    56 
       
    57 class tst_qdeclarativetextedit : public QObject
       
    58 
       
    59 {
       
    60     Q_OBJECT
       
    61 public:
       
    62     tst_qdeclarativetextedit();
       
    63 
       
    64 private slots:
       
    65     void text();
       
    66     void width();
       
    67     void wrap();
       
    68     void textFormat();
       
    69 
       
    70     // ### these tests may be trivial    
       
    71     void hAlign();
       
    72     void vAlign();
       
    73     void font();
       
    74     void color();
       
    75     void textMargin();
       
    76     void persistentSelection();
       
    77     void focusOnPress();
       
    78     void selection();
       
    79     void mouseSelection_data();
       
    80     void mouseSelection();
       
    81     void inputMethodHints();
       
    82 
       
    83     void cursorDelegate();
       
    84     void delegateLoading_data();
       
    85     void delegateLoading();
       
    86     void navigation();
       
    87     void readOnly();
       
    88     void sendRequestSoftwareInputPanelEvent();
       
    89     void geometrySignals();
       
    90 private:
       
    91     void simulateKey(QDeclarativeView *, int key);
       
    92     QDeclarativeView *createView(const QString &filename);
       
    93 
       
    94     QStringList standard;
       
    95     QStringList richText;
       
    96 
       
    97     QStringList hAlignmentStrings;
       
    98     QStringList vAlignmentStrings;
       
    99 
       
   100     QList<Qt::Alignment> vAlignments;
       
   101     QList<Qt::Alignment> hAlignments;
       
   102 
       
   103     QStringList colorStrings;
       
   104 
       
   105     QDeclarativeEngine engine;
       
   106 };
       
   107 
       
   108 tst_qdeclarativetextedit::tst_qdeclarativetextedit()
       
   109 {
       
   110     standard << "the quick brown fox jumped over the lazy dog"
       
   111              << "the quick brown fox\n jumped over the lazy dog";
       
   112 
       
   113     richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
       
   114              << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
       
   115 
       
   116     hAlignmentStrings << "AlignLeft"
       
   117                       << "AlignRight"
       
   118                       << "AlignHCenter";
       
   119 
       
   120     vAlignmentStrings << "AlignTop"
       
   121                       << "AlignBottom"
       
   122                       << "AlignVCenter";
       
   123 
       
   124     hAlignments << Qt::AlignLeft
       
   125                 << Qt::AlignRight
       
   126                 << Qt::AlignHCenter;
       
   127 
       
   128     vAlignments << Qt::AlignTop
       
   129                 << Qt::AlignBottom
       
   130                 << Qt::AlignVCenter;
       
   131 
       
   132     colorStrings << "aliceblue"
       
   133                  << "antiquewhite"
       
   134                  << "aqua"
       
   135                  << "darkkhaki"
       
   136                  << "darkolivegreen"
       
   137                  << "dimgray"
       
   138                  << "palevioletred"
       
   139                  << "lightsteelblue"
       
   140                  << "#000000"
       
   141                  << "#AAAAAA"
       
   142                  << "#FFFFFF"
       
   143                  << "#2AC05F";
       
   144                  //
       
   145                  // need a different test to do alpha channel test
       
   146                  // << "#AA0011DD"
       
   147                  // << "#00F16B11";
       
   148                  // 
       
   149 }
       
   150 
       
   151 void tst_qdeclarativetextedit::text()
       
   152 {
       
   153     {
       
   154         QDeclarativeComponent texteditComponent(&engine);
       
   155         texteditComponent.setData("import Qt 4.7\nTextEdit {  text: \"\"  }", QUrl());
       
   156         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   157 
       
   158         QVERIFY(textEditObject != 0);
       
   159         QCOMPARE(textEditObject->text(), QString(""));
       
   160     }
       
   161 
       
   162     for (int i = 0; i < standard.size(); i++)
       
   163     {
       
   164         QString componentStr = "import Qt 4.7\nTextEdit { text: \"" + standard.at(i) + "\" }";
       
   165         QDeclarativeComponent texteditComponent(&engine);
       
   166         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   167         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   168 
       
   169         QVERIFY(textEditObject != 0);
       
   170         QCOMPARE(textEditObject->text(), standard.at(i));
       
   171     }
       
   172 
       
   173     for (int i = 0; i < richText.size(); i++)
       
   174     {
       
   175         QString componentStr = "import Qt 4.7\nTextEdit { text: \"" + richText.at(i) + "\" }";
       
   176         QDeclarativeComponent texteditComponent(&engine);
       
   177         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   178         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   179 
       
   180         QVERIFY(textEditObject != 0);
       
   181         QString actual = textEditObject->text();
       
   182         QString expected = richText.at(i);
       
   183         actual.replace(QRegExp(".*<body[^>]*>"),"");
       
   184         actual.replace(QRegExp("(<[^>]*>)+"),"<>");
       
   185         expected.replace(QRegExp("(<[^>]*>)+"),"<>");
       
   186         QCOMPARE(actual.simplified(),expected.simplified());
       
   187     }
       
   188 }
       
   189 
       
   190 void tst_qdeclarativetextedit::width()
       
   191 {
       
   192     // uses Font metrics to find the width for standard and document to find the width for rich
       
   193     {
       
   194         QDeclarativeComponent texteditComponent(&engine);
       
   195         texteditComponent.setData("import Qt 4.7\nTextEdit {  text: \"\" }", QUrl());
       
   196         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   197 
       
   198         QVERIFY(textEditObject != 0);
       
   199         QCOMPARE(textEditObject->width(), 1.);//+1 for cursor
       
   200     }
       
   201 
       
   202     for (int i = 0; i < standard.size(); i++)
       
   203     {
       
   204         QFont f;
       
   205         QFontMetricsF fm(f);
       
   206         qreal metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
       
   207         metricWidth = ceil(metricWidth);
       
   208 
       
   209         QString componentStr = "import Qt 4.7\nTextEdit { text: \"" + standard.at(i) + "\" }";
       
   210         QDeclarativeComponent texteditComponent(&engine);
       
   211         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   212         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   213 
       
   214         QVERIFY(textEditObject != 0);
       
   215         QCOMPARE(textEditObject->width(), qreal(metricWidth + 1 + 3));//+3 is the current way of accounting for space between cursor and last character.
       
   216     }
       
   217 
       
   218     for (int i = 0; i < richText.size(); i++)
       
   219     {
       
   220         QTextDocument document;
       
   221         document.setHtml(richText.at(i));
       
   222         document.setDocumentMargin(0);
       
   223 
       
   224         int documentWidth = ceil(document.idealWidth());
       
   225 
       
   226         QString componentStr = "import Qt 4.7\nTextEdit { text: \"" + richText.at(i) + "\" }";
       
   227         QDeclarativeComponent texteditComponent(&engine);
       
   228         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   229         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   230 
       
   231         QVERIFY(textEditObject != 0);
       
   232         QCOMPARE(textEditObject->width(), qreal(documentWidth + 1 + 3));
       
   233     }
       
   234 }
       
   235 
       
   236 void tst_qdeclarativetextedit::wrap()
       
   237 {
       
   238     // for specified width and wrap set true
       
   239     {
       
   240         QDeclarativeComponent texteditComponent(&engine);
       
   241         texteditComponent.setData("import Qt 4.7\nTextEdit {  text: \"\"; wrapMode: TextEdit.WordWrap; width: 300 }", QUrl());
       
   242         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   243 
       
   244         QVERIFY(textEditObject != 0);
       
   245         QCOMPARE(textEditObject->width(), 300.);
       
   246     }
       
   247 
       
   248     for (int i = 0; i < standard.size(); i++)
       
   249     {
       
   250         QString componentStr = "import Qt 4.7\nTextEdit {  wrapMode: TextEdit.WordWrap; width: 300; text: \"" + standard.at(i) + "\" }";
       
   251         QDeclarativeComponent texteditComponent(&engine);
       
   252         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   253         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   254 
       
   255         QVERIFY(textEditObject != 0);
       
   256         QCOMPARE(textEditObject->width(), 300.);
       
   257     }
       
   258 
       
   259     for (int i = 0; i < richText.size(); i++)
       
   260     {
       
   261         QString componentStr = "import Qt 4.7\nTextEdit {  wrapMode: TextEdit.WordWrap; width: 300; text: \"" + richText.at(i) + "\" }";
       
   262         QDeclarativeComponent texteditComponent(&engine);
       
   263         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   264         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   265 
       
   266         QVERIFY(textEditObject != 0);
       
   267         QCOMPARE(textEditObject->width(), 300.);
       
   268     }
       
   269 
       
   270 }
       
   271 
       
   272 void tst_qdeclarativetextedit::textFormat()
       
   273 {
       
   274     {
       
   275         QDeclarativeComponent textComponent(&engine);
       
   276         textComponent.setData("import Qt 4.7\nTextEdit { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
       
   277         QDeclarativeTextEdit *textObject = qobject_cast<QDeclarativeTextEdit*>(textComponent.create());
       
   278 
       
   279         QVERIFY(textObject != 0);
       
   280         QVERIFY(textObject->textFormat() == QDeclarativeTextEdit::RichText);
       
   281     }
       
   282     {
       
   283         QDeclarativeComponent textComponent(&engine);
       
   284         textComponent.setData("import Qt 4.7\nTextEdit { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
       
   285         QDeclarativeTextEdit *textObject = qobject_cast<QDeclarativeTextEdit*>(textComponent.create());
       
   286 
       
   287         QVERIFY(textObject != 0);
       
   288         QVERIFY(textObject->textFormat() == QDeclarativeTextEdit::PlainText);
       
   289     }
       
   290 }
       
   291 
       
   292 //the alignment tests may be trivial o.oa
       
   293 void tst_qdeclarativetextedit::hAlign()
       
   294 {
       
   295     //test one align each, and then test if two align fails.
       
   296 
       
   297     for (int i = 0; i < standard.size(); i++)
       
   298     {
       
   299         for (int j=0; j < hAlignmentStrings.size(); j++)
       
   300         {
       
   301             QString componentStr = "import Qt 4.7\nTextEdit {  horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
       
   302             QDeclarativeComponent texteditComponent(&engine);
       
   303             texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   304             QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   305 
       
   306             QVERIFY(textEditObject != 0);
       
   307             QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
       
   308         }
       
   309     }
       
   310 
       
   311     for (int i = 0; i < richText.size(); i++)
       
   312     {
       
   313         for (int j=0; j < hAlignmentStrings.size(); j++)
       
   314         {
       
   315             QString componentStr = "import Qt 4.7\nTextEdit {  horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
       
   316             QDeclarativeComponent texteditComponent(&engine);
       
   317             texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   318             QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   319 
       
   320             QVERIFY(textEditObject != 0);
       
   321             QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
       
   322         }
       
   323     }
       
   324 
       
   325 }
       
   326 
       
   327 void tst_qdeclarativetextedit::vAlign()
       
   328 {
       
   329     //test one align each, and then test if two align fails.
       
   330 
       
   331     for (int i = 0; i < standard.size(); i++)
       
   332     {
       
   333         for (int j=0; j < vAlignmentStrings.size(); j++)
       
   334         {
       
   335             QString componentStr = "import Qt 4.7\nTextEdit {  verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
       
   336             QDeclarativeComponent texteditComponent(&engine);
       
   337             texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   338             QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   339 
       
   340             QVERIFY(textEditObject != 0);
       
   341             QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
       
   342         }
       
   343     }
       
   344 
       
   345     for (int i = 0; i < richText.size(); i++)
       
   346     {
       
   347         for (int j=0; j < vAlignmentStrings.size(); j++)
       
   348         {
       
   349             QString componentStr = "import Qt 4.7\nTextEdit {  verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
       
   350             QDeclarativeComponent texteditComponent(&engine);
       
   351             texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   352             QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   353 
       
   354             QVERIFY(textEditObject != 0);
       
   355             QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
       
   356         }
       
   357     }
       
   358 
       
   359 }
       
   360 
       
   361 void tst_qdeclarativetextedit::font()
       
   362 {
       
   363     //test size, then bold, then italic, then family
       
   364     { 
       
   365         QString componentStr = "import Qt 4.7\nTextEdit {  font.pointSize: 40; text: \"Hello World\" }";
       
   366         QDeclarativeComponent texteditComponent(&engine);
       
   367         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   368         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   369 
       
   370         QVERIFY(textEditObject != 0);
       
   371         QCOMPARE(textEditObject->font().pointSize(), 40);
       
   372         QCOMPARE(textEditObject->font().bold(), false);
       
   373         QCOMPARE(textEditObject->font().italic(), false);
       
   374     }
       
   375 
       
   376     { 
       
   377         QString componentStr = "import Qt 4.7\nTextEdit {  font.bold: true; text: \"Hello World\" }";
       
   378         QDeclarativeComponent texteditComponent(&engine);
       
   379         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   380         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   381 
       
   382         QVERIFY(textEditObject != 0);
       
   383         QCOMPARE(textEditObject->font().bold(), true);
       
   384         QCOMPARE(textEditObject->font().italic(), false);
       
   385     }
       
   386 
       
   387     { 
       
   388         QString componentStr = "import Qt 4.7\nTextEdit {  font.italic: true; text: \"Hello World\" }";
       
   389         QDeclarativeComponent texteditComponent(&engine);
       
   390         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   391         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   392 
       
   393         QVERIFY(textEditObject != 0);
       
   394         QCOMPARE(textEditObject->font().italic(), true);
       
   395         QCOMPARE(textEditObject->font().bold(), false);
       
   396     }
       
   397  
       
   398     { 
       
   399         QString componentStr = "import Qt 4.7\nTextEdit {  font.family: \"Helvetica\"; text: \"Hello World\" }";
       
   400         QDeclarativeComponent texteditComponent(&engine);
       
   401         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   402         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   403 
       
   404         QVERIFY(textEditObject != 0);
       
   405         QCOMPARE(textEditObject->font().family(), QString("Helvetica"));
       
   406         QCOMPARE(textEditObject->font().bold(), false);
       
   407         QCOMPARE(textEditObject->font().italic(), false);
       
   408     }
       
   409 
       
   410     { 
       
   411         QString componentStr = "import Qt 4.7\nTextEdit {  font.family: \"\"; text: \"Hello World\" }";
       
   412         QDeclarativeComponent texteditComponent(&engine);
       
   413         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   414         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   415 
       
   416         QVERIFY(textEditObject != 0);
       
   417         QCOMPARE(textEditObject->font().family(), QString(""));
       
   418     }
       
   419 }
       
   420 
       
   421 void tst_qdeclarativetextedit::color()
       
   422 {
       
   423     //test normal
       
   424     for (int i = 0; i < colorStrings.size(); i++)
       
   425     { 
       
   426         QString componentStr = "import Qt 4.7\nTextEdit {  color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
       
   427         QDeclarativeComponent texteditComponent(&engine);
       
   428         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   429         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   430         //qDebug() << "textEditObject: " << textEditObject->color() << "vs. " << QColor(colorStrings.at(i));
       
   431         QVERIFY(textEditObject != 0);
       
   432         QCOMPARE(textEditObject->color(), QColor(colorStrings.at(i)));
       
   433     }
       
   434 
       
   435     //test selection
       
   436     for (int i = 0; i < colorStrings.size(); i++)
       
   437     {
       
   438         QString componentStr = "import Qt 4.7\nTextEdit {  selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
       
   439         QDeclarativeComponent texteditComponent(&engine);
       
   440         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   441         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   442         QVERIFY(textEditObject != 0);
       
   443         QCOMPARE(textEditObject->selectionColor(), QColor(colorStrings.at(i)));
       
   444     }
       
   445 
       
   446     //test selected text
       
   447     for (int i = 0; i < colorStrings.size(); i++)
       
   448     {
       
   449         QString componentStr = "import Qt 4.7\nTextEdit {  selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
       
   450         QDeclarativeComponent texteditComponent(&engine);
       
   451         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   452         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   453         QVERIFY(textEditObject != 0);
       
   454         QCOMPARE(textEditObject->selectedTextColor(), QColor(colorStrings.at(i)));
       
   455     }
       
   456 
       
   457     {
       
   458         QString colorStr = "#AA001234";
       
   459         QColor testColor("#001234");
       
   460         testColor.setAlpha(170);
       
   461 
       
   462         QString componentStr = "import Qt 4.7\nTextEdit {  color: \"" + colorStr + "\"; text: \"Hello World\" }";
       
   463         QDeclarativeComponent texteditComponent(&engine);
       
   464         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   465         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   466 
       
   467         QVERIFY(textEditObject != 0);
       
   468         QCOMPARE(textEditObject->color(), testColor);
       
   469     }
       
   470 }
       
   471 
       
   472 void tst_qdeclarativetextedit::textMargin()
       
   473 {
       
   474     for(qreal i=0; i<=10; i+=0.3){
       
   475         QString componentStr = "import Qt 4.7\nTextEdit {  textMargin: " + QString::number(i) + "; text: \"Hello World\" }";
       
   476         QDeclarativeComponent texteditComponent(&engine);
       
   477         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   478         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   479         QVERIFY(textEditObject != 0);
       
   480         QCOMPARE(textEditObject->textMargin(), i);
       
   481     }
       
   482 }
       
   483 
       
   484 void tst_qdeclarativetextedit::persistentSelection()
       
   485 {
       
   486     {
       
   487         QString componentStr = "import Qt 4.7\nTextEdit {  persistentSelection: true; text: \"Hello World\" }";
       
   488         QDeclarativeComponent texteditComponent(&engine);
       
   489         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   490         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   491         QVERIFY(textEditObject != 0);
       
   492         QCOMPARE(textEditObject->persistentSelection(), true);
       
   493     }
       
   494 
       
   495     {
       
   496         QString componentStr = "import Qt 4.7\nTextEdit {  persistentSelection: false; text: \"Hello World\" }";
       
   497         QDeclarativeComponent texteditComponent(&engine);
       
   498         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   499         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   500         QVERIFY(textEditObject != 0);
       
   501         QCOMPARE(textEditObject->persistentSelection(), false);
       
   502     }
       
   503 }
       
   504 
       
   505 void tst_qdeclarativetextedit::focusOnPress()
       
   506 {
       
   507     {
       
   508         QString componentStr = "import Qt 4.7\nTextEdit {  focusOnPress: true; text: \"Hello World\" }";
       
   509         QDeclarativeComponent texteditComponent(&engine);
       
   510         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   511         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   512         QVERIFY(textEditObject != 0);
       
   513         QCOMPARE(textEditObject->focusOnPress(), true);
       
   514     }
       
   515 
       
   516     {
       
   517         QString componentStr = "import Qt 4.7\nTextEdit {  focusOnPress: false; text: \"Hello World\" }";
       
   518         QDeclarativeComponent texteditComponent(&engine);
       
   519         texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   520         QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   521         QVERIFY(textEditObject != 0);
       
   522         QCOMPARE(textEditObject->focusOnPress(), false);
       
   523     }
       
   524 }
       
   525 
       
   526 void tst_qdeclarativetextedit::selection()
       
   527 {
       
   528     QString testStr = standard[0];//TODO: What should happen for multiline/rich text?
       
   529     QString componentStr = "import Qt 4.7\nTextEdit {  text: \""+ testStr +"\"; }";
       
   530     QDeclarativeComponent texteditComponent(&engine);
       
   531     texteditComponent.setData(componentStr.toLatin1(), QUrl());
       
   532     QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create());
       
   533     QVERIFY(textEditObject != 0);
       
   534 
       
   535 
       
   536     //Test selection follows cursor
       
   537     for(int i=0; i<= testStr.size(); i++) {
       
   538         textEditObject->setCursorPosition(i);
       
   539         QCOMPARE(textEditObject->cursorPosition(), i);
       
   540         QCOMPARE(textEditObject->selectionStart(), i);
       
   541         QCOMPARE(textEditObject->selectionEnd(), i);
       
   542         QVERIFY(textEditObject->selectedText().isNull());
       
   543     }
       
   544 
       
   545     textEditObject->setCursorPosition(0);
       
   546     QVERIFY(textEditObject->cursorPosition() == 0);
       
   547     QVERIFY(textEditObject->selectionStart() == 0);
       
   548     QVERIFY(textEditObject->selectionEnd() == 0);
       
   549     QVERIFY(textEditObject->selectedText().isNull());
       
   550 
       
   551     //Test selection
       
   552     for(int i=0; i<= testStr.size(); i++) {
       
   553         textEditObject->setSelectionEnd(i);
       
   554         QCOMPARE(testStr.mid(0,i), textEditObject->selectedText());
       
   555     }
       
   556     for(int i=0; i<= testStr.size(); i++) {
       
   557         textEditObject->setSelectionStart(i);
       
   558         QCOMPARE(testStr.mid(i,testStr.size()-i), textEditObject->selectedText());
       
   559     }
       
   560 
       
   561     textEditObject->setCursorPosition(0);
       
   562     QVERIFY(textEditObject->cursorPosition() == 0);
       
   563     QVERIFY(textEditObject->selectionStart() == 0);
       
   564     QVERIFY(textEditObject->selectionEnd() == 0);
       
   565     QVERIFY(textEditObject->selectedText().isNull());
       
   566 
       
   567     for(int i=0; i< testStr.size(); i++) {
       
   568         textEditObject->setSelectionStart(i);
       
   569         QCOMPARE(textEditObject->selectionEnd(), i);
       
   570         QCOMPARE(testStr.mid(i,0), textEditObject->selectedText());
       
   571         textEditObject->setSelectionEnd(i+1);
       
   572         QCOMPARE(textEditObject->selectionStart(), i);
       
   573         QCOMPARE(testStr.mid(i,1), textEditObject->selectedText());
       
   574     }
       
   575 
       
   576     for(int i= testStr.size() - 1; i>0; i--) {
       
   577         textEditObject->setSelectionEnd(i);
       
   578         QCOMPARE(testStr.mid(i,0), textEditObject->selectedText());
       
   579         textEditObject->setSelectionStart(i-1);
       
   580         QCOMPARE(testStr.mid(i-1,1), textEditObject->selectedText());
       
   581     }
       
   582 
       
   583     //Test Error Ignoring behaviour
       
   584     textEditObject->setCursorPosition(0);
       
   585     QVERIFY(textEditObject->selectedText().isNull());
       
   586     textEditObject->setSelectionStart(-10);
       
   587     QVERIFY(textEditObject->selectedText().isNull());
       
   588     textEditObject->setSelectionStart(100);
       
   589     QVERIFY(textEditObject->selectedText().isNull());
       
   590     textEditObject->setSelectionEnd(-10);
       
   591     QVERIFY(textEditObject->selectedText().isNull());
       
   592     textEditObject->setSelectionEnd(100);
       
   593     QVERIFY(textEditObject->selectedText().isNull());
       
   594     textEditObject->setSelectionStart(0);
       
   595     textEditObject->setSelectionEnd(10);
       
   596     QVERIFY(textEditObject->selectedText().size() == 10);
       
   597     textEditObject->setSelectionStart(-10);
       
   598     QVERIFY(textEditObject->selectedText().size() == 10);
       
   599     textEditObject->setSelectionStart(100);
       
   600     QVERIFY(textEditObject->selectedText().size() == 10);
       
   601     textEditObject->setSelectionEnd(-10);
       
   602     QVERIFY(textEditObject->selectedText().size() == 10);
       
   603     textEditObject->setSelectionEnd(100);
       
   604     QVERIFY(textEditObject->selectedText().size() == 10);
       
   605 }
       
   606 
       
   607 void tst_qdeclarativetextedit::mouseSelection_data()
       
   608 {
       
   609     QTest::addColumn<QString>("qmlfile");
       
   610     QTest::addColumn<bool>("expectSelection");
       
   611 
       
   612     // import installed
       
   613     QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << true;
       
   614     QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << false;
       
   615     QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << false;
       
   616 }
       
   617 
       
   618 void tst_qdeclarativetextedit::mouseSelection()
       
   619 {
       
   620     QFETCH(QString, qmlfile);
       
   621     QFETCH(bool, expectSelection);
       
   622 
       
   623     QDeclarativeView *canvas = createView(qmlfile);
       
   624 
       
   625     canvas->show();
       
   626     QApplication::setActiveWindow(canvas);
       
   627     QTest::qWaitForWindowShown(canvas);
       
   628     QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
       
   629 
       
   630     QVERIFY(canvas->rootObject() != 0);
       
   631     QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit *>(canvas->rootObject());
       
   632     QVERIFY(textEditObject != 0);
       
   633 
       
   634     // press-and-drag-and-release from x1 to x2
       
   635     int x1 = 10;
       
   636     int x2 = 70;
       
   637     int y = textEditObject->height()/2;
       
   638     QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
       
   639     //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
       
   640     QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
       
   641     QApplication::sendEvent(canvas->viewport(), &mv);
       
   642     QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
       
   643     QString str = textEditObject->selectedText();
       
   644     if (expectSelection)
       
   645         QVERIFY(str.length() > 3); // don't reallly care *what* was selected (and it's too sensitive to platform)
       
   646     else
       
   647         QVERIFY(str.isEmpty());
       
   648 }
       
   649 
       
   650 void tst_qdeclarativetextedit::inputMethodHints()
       
   651 {
       
   652     QDeclarativeView *canvas = createView(SRCDIR "/data/inputmethodhints.qml");
       
   653     canvas->show();
       
   654     canvas->setFocus();
       
   655 
       
   656     QVERIFY(canvas->rootObject() != 0);
       
   657     QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit *>(canvas->rootObject());
       
   658     QVERIFY(textEditObject != 0);
       
   659     QVERIFY(textEditObject->inputMethodHints() & Qt::ImhNoPredictiveText);
       
   660     textEditObject->setInputMethodHints(Qt::ImhUppercaseOnly);
       
   661     QVERIFY(textEditObject->inputMethodHints() & Qt::ImhUppercaseOnly);
       
   662 }
       
   663 
       
   664 void tst_qdeclarativetextedit::cursorDelegate()
       
   665 {
       
   666     QDeclarativeView* view = createView(SRCDIR "/data/cursorTest.qml");
       
   667     view->show();
       
   668     view->setFocus();
       
   669     QDeclarativeTextEdit *textEditObject = view->rootObject()->findChild<QDeclarativeTextEdit*>("textEditObject");
       
   670     QVERIFY(textEditObject != 0);
       
   671     QVERIFY(textEditObject->findChild<QDeclarativeItem*>("cursorInstance"));
       
   672     //Test Delegate gets created
       
   673     textEditObject->setFocus(true);
       
   674     QDeclarativeItem* delegateObject = textEditObject->findChild<QDeclarativeItem*>("cursorInstance");
       
   675     QVERIFY(delegateObject);
       
   676     //Test Delegate gets moved
       
   677     for(int i=0; i<= textEditObject->text().length(); i++){
       
   678         textEditObject->setCursorPosition(i);
       
   679         QCOMPARE(textEditObject->cursorRect().x(), qRound(delegateObject->x()));
       
   680         QCOMPARE(textEditObject->cursorRect().y(), qRound(delegateObject->y()));
       
   681     }
       
   682     textEditObject->setCursorPosition(0);
       
   683     QCOMPARE(textEditObject->cursorRect().x(), qRound(delegateObject->x()));
       
   684     QCOMPARE(textEditObject->cursorRect().y(), qRound(delegateObject->y()));
       
   685     //Test Delegate gets deleted
       
   686     textEditObject->setCursorDelegate(0);
       
   687     QVERIFY(!textEditObject->findChild<QDeclarativeItem*>("cursorInstance"));
       
   688 }
       
   689 
       
   690 void tst_qdeclarativetextedit::delegateLoading_data()
       
   691 {
       
   692     QTest::addColumn<QString>("qmlfile");
       
   693     QTest::addColumn<QString>("error");
       
   694 
       
   695     // import installed
       
   696     QTest::newRow("pass") << "cursorHttpTestPass.qml" << "";
       
   697     QTest::newRow("fail1") << "cursorHttpTestFail1.qml" << "<Unknown File>: Network error for URL http://localhost:42332/FailItem.qml ";
       
   698     QTest::newRow("fail2") << "cursorHttpTestFail2.qml" << "http://localhost:42332/ErrItem.qml:4:5: Fungus is not a type ";
       
   699 }
       
   700 
       
   701 void tst_qdeclarativetextedit::delegateLoading()
       
   702 {
       
   703     QFETCH(QString, qmlfile);
       
   704     QFETCH(QString, error);
       
   705 
       
   706     TestHTTPServer server(42332);
       
   707     server.serveDirectory(SRCDIR "/data/httpfail", TestHTTPServer::Disconnect);
       
   708     server.serveDirectory(SRCDIR "/data/httpslow", TestHTTPServer::Delay);
       
   709     server.serveDirectory(SRCDIR "/data/http");
       
   710 
       
   711     QDeclarativeView* view = new QDeclarativeView(0);
       
   712 
       
   713     view->setSource(QUrl(QLatin1String("http://localhost:42332/") + qmlfile));
       
   714     view->show();
       
   715     view->setFocus();
       
   716 
       
   717     if (!error.isEmpty()) {
       
   718         QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
       
   719         QTRY_VERIFY(view->status()==QDeclarativeView::Error);
       
   720         QTRY_VERIFY(!view->rootObject()); // there is fail item inside this test
       
   721     } else {
       
   722         QTRY_VERIFY(view->rootObject());//Wait for loading to finish.
       
   723         QDeclarativeTextEdit *textEditObject = view->rootObject()->findChild<QDeclarativeTextEdit*>("textEditObject");
       
   724         //    view->rootObject()->dumpObjectTree();
       
   725         QVERIFY(textEditObject != 0);
       
   726         textEditObject->setFocus(true);
       
   727         QDeclarativeItem *delegate;
       
   728         delegate = view->rootObject()->findChild<QDeclarativeItem*>("delegateOkay");
       
   729         QVERIFY(delegate);
       
   730         delegate = view->rootObject()->findChild<QDeclarativeItem*>("delegateSlow");
       
   731         QVERIFY(delegate);
       
   732 
       
   733         delete delegate;
       
   734     }
       
   735 
       
   736 
       
   737     //A test should be added here with a component which is ready but component.create() returns null
       
   738     //Not sure how to accomplish this with QDeclarativeTextEdits cursor delegate
       
   739     //###This was only needed for code coverage, and could be a case of overzealous defensive programming
       
   740     //delegate = view->rootObject()->findChild<QDeclarativeItem*>("delegateErrorB");
       
   741     //QVERIFY(!delegate);
       
   742 
       
   743     delete view;
       
   744 }
       
   745 
       
   746 /*
       
   747 TextEdit element should only handle left/right keys until the cursor reaches
       
   748 the extent of the text, then they should ignore the keys.
       
   749 */
       
   750 void tst_qdeclarativetextedit::navigation()
       
   751 {
       
   752     QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
       
   753     canvas->show();
       
   754     canvas->setFocus();
       
   755 
       
   756     QVERIFY(canvas->rootObject() != 0);
       
   757 
       
   758     QDeclarativeItem *input = qobject_cast<QDeclarativeItem *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
       
   759 
       
   760     QVERIFY(input != 0);
       
   761     QTRY_VERIFY(input->hasFocus() == true);
       
   762     simulateKey(canvas, Qt::Key_Left);
       
   763     QVERIFY(input->hasFocus() == false);
       
   764     simulateKey(canvas, Qt::Key_Right);
       
   765     QVERIFY(input->hasFocus() == true);
       
   766     simulateKey(canvas, Qt::Key_Right);
       
   767     QVERIFY(input->hasFocus() == false);
       
   768     simulateKey(canvas, Qt::Key_Left);
       
   769     QVERIFY(input->hasFocus() == true);
       
   770 }
       
   771 
       
   772 void tst_qdeclarativetextedit::readOnly()
       
   773 {
       
   774     QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml");
       
   775     canvas->show();
       
   776     canvas->setFocus();
       
   777 
       
   778     QVERIFY(canvas->rootObject() != 0);
       
   779 
       
   780     QDeclarativeTextEdit *edit = qobject_cast<QDeclarativeTextEdit *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
       
   781 
       
   782     QVERIFY(edit != 0);
       
   783     QTRY_VERIFY(edit->hasFocus() == true);
       
   784     QVERIFY(edit->isReadOnly() == true);
       
   785     QString initial = edit->text();
       
   786     for(int k=Qt::Key_0; k<=Qt::Key_Z; k++)
       
   787         simulateKey(canvas, k);
       
   788     simulateKey(canvas, Qt::Key_Return);
       
   789     simulateKey(canvas, Qt::Key_Space);
       
   790     simulateKey(canvas, Qt::Key_Escape);
       
   791     QCOMPARE(edit->text(), initial);
       
   792 }
       
   793 
       
   794 void tst_qdeclarativetextedit::simulateKey(QDeclarativeView *view, int key)
       
   795 {
       
   796     QKeyEvent press(QKeyEvent::KeyPress, key, 0);
       
   797     QKeyEvent release(QKeyEvent::KeyRelease, key, 0);
       
   798 
       
   799     QApplication::sendEvent(view, &press);
       
   800     QApplication::sendEvent(view, &release);
       
   801 }
       
   802 
       
   803 QDeclarativeView *tst_qdeclarativetextedit::createView(const QString &filename)
       
   804 {
       
   805     QDeclarativeView *canvas = new QDeclarativeView(0);
       
   806 
       
   807     canvas->setSource(QUrl::fromLocalFile(filename));
       
   808     return canvas;
       
   809 }
       
   810 
       
   811 class MyInputContext : public QInputContext
       
   812 {
       
   813 public:
       
   814     MyInputContext() : softwareInputPanelEventReceived(false) {}
       
   815     ~MyInputContext() {}
       
   816 
       
   817     QString identifierName() { return QString(); }
       
   818     QString language() { return QString(); }
       
   819 
       
   820     void reset() {}
       
   821 
       
   822     bool isComposing() const { return false; }
       
   823 
       
   824     bool filterEvent( const QEvent *event )
       
   825     {
       
   826         if (event->type() == QEvent::RequestSoftwareInputPanel)
       
   827             softwareInputPanelEventReceived = true;
       
   828         return QInputContext::filterEvent(event);
       
   829     }
       
   830     bool softwareInputPanelEventReceived;
       
   831 };
       
   832 
       
   833 void tst_qdeclarativetextedit::sendRequestSoftwareInputPanelEvent()
       
   834 {
       
   835     QGraphicsScene scene;
       
   836     QGraphicsView view(&scene);
       
   837     MyInputContext ic;
       
   838     view.viewport()->setInputContext(&ic);
       
   839     QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
       
   840             view.style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
       
   841     QDeclarativeTextEdit edit;
       
   842     edit.setText("Hello world");
       
   843     edit.setPos(0, 0);
       
   844     scene.addItem(&edit);
       
   845     view.show();
       
   846     qApp->setAutoSipEnabled(true);
       
   847     QApplication::setActiveWindow(&view);
       
   848     QTest::qWaitForWindowShown(&view);
       
   849     QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
       
   850     QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
       
   851     QApplication::processEvents();
       
   852     if (behavior == QStyle::RSIP_OnMouseClickAndAlreadyFocused) {
       
   853         QCOMPARE(ic.softwareInputPanelEventReceived, false);
       
   854         QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
       
   855         QApplication::processEvents();
       
   856         QCOMPARE(ic.softwareInputPanelEventReceived, true);
       
   857     } else if (behavior == QStyle::RSIP_OnMouseClick) {
       
   858         QCOMPARE(ic.softwareInputPanelEventReceived, true);
       
   859     }
       
   860 }
       
   861 
       
   862 void tst_qdeclarativetextedit::geometrySignals()
       
   863 {
       
   864     QDeclarativeComponent component(&engine, SRCDIR "/data/geometrySignals.qml");
       
   865     QObject *o = component.create();
       
   866     QVERIFY(o);
       
   867     QCOMPARE(o->property("bindingWidth").toInt(), 400);
       
   868     QCOMPARE(o->property("bindingHeight").toInt(), 500);
       
   869     delete o;
       
   870 }
       
   871 
       
   872 QTEST_MAIN(tst_qdeclarativetextedit)
       
   873 
       
   874 #include "tst_qdeclarativetextedit.moc"