1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtTest/QSignalSpy>
43 #include "../../../shared/util.h"
44 #include "../../declarative/shared/testhttpserver.h"
47 #include <QTextDocument>
48 #include <QtDeclarative/qdeclarativeengine.h>
49 #include <QtDeclarative/qdeclarativecontext.h>
50 #include <QtDeclarative/qdeclarativeexpression.h>
51 #include <QtDeclarative/qdeclarativecomponent.h>
52 #include <QtQuick1/private/qdeclarativetextedit_p.h>
53 #include <QtQuick1/private/qdeclarativetextedit_p_p.h>
54 #include <QFontMetrics>
55 #include <QtQuick1/QDeclarativeView>
58 #include <QInputContext>
61 #include <private/qapplication_p.h>
62 #include <private/qtextcontrol_p.h>
65 // In Symbian OS test data is located in applications private dir
69 Q_DECLARE_METATYPE(QDeclarative1TextEdit::SelectionMode)
71 QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
73 // XXX This will be replaced by some clever persistent platform image store.
74 QString persistent_dir = SRCDIR "/data";
75 QString arch = "unknown-architecture"; // QTest needs to help with this.
77 QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png";
79 if (!QFile::exists(expectfile)) {
80 actual.save(expectfile);
81 qWarning() << "created" << expectfile;
88 class tst_qdeclarativetextedit : public QObject
93 tst_qdeclarativetextedit();
101 void alignments_data();
103 // ### these tests may be trivial
105 void hAlign_RightToLeft();
110 void persistentSelection();
113 void isRightToLeft_data();
114 void isRightToLeft();
116 void moveCursorSelection_data();
117 void moveCursorSelection();
118 void moveCursorSelectionSequence_data();
119 void moveCursorSelectionSequence();
120 void mouseSelection_data();
121 void mouseSelection();
122 void multilineMouseSelection();
123 void deferEnableSelectByMouse_data();
124 void deferEnableSelectByMouse();
125 void deferDisableSelectByMouse_data();
126 void deferDisableSelectByMouse();
127 void mouseSelectionMode_data();
128 void mouseSelectionMode();
129 void dragMouseSelection();
130 void inputMethodHints();
134 void cursorDelegate();
135 void cursorVisible();
136 void delegateLoading_data();
137 void delegateLoading();
142 void canPasteEmpty();
144 void openInputPanelOnClick();
145 void openInputPanelOnFocus();
146 void geometrySignals();
147 void pastingRichText_QTBUG_14003();
148 void implicitSize_data();
150 void testQtQuick11Attributes();
151 void testQtQuick11Attributes_data();
153 void preeditMicroFocus();
154 void inputContextMouseHandler();
155 void inputMethodComposing();
156 void cursorRectangleSize();
159 void simulateKey(QDeclarativeView *, int key, Qt::KeyboardModifiers modifiers = 0);
160 QDeclarativeView *createView(const QString &filename);
162 QStringList standard;
163 QStringList richText;
165 QStringList hAlignmentStrings;
166 QStringList vAlignmentStrings;
168 QList<Qt::Alignment> vAlignments;
169 QList<Qt::Alignment> hAlignments;
171 QStringList colorStrings;
173 QDeclarativeEngine engine;
176 tst_qdeclarativetextedit::tst_qdeclarativetextedit()
178 standard << "the quick brown fox jumped over the lazy dog"
179 << "the quick brown fox\n jumped over the lazy dog"
183 richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
184 << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
186 hAlignmentStrings << "AlignLeft"
190 vAlignmentStrings << "AlignTop"
194 hAlignments << Qt::AlignLeft
198 vAlignments << Qt::AlignTop
202 colorStrings << "aliceblue"
215 // need a different test to do alpha channel test
221 void tst_qdeclarativetextedit::text()
224 QDeclarativeComponent texteditComponent(&engine);
225 texteditComponent.setData("import QtQuick 1.0\nTextEdit { text: \"\" }", QUrl());
226 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
228 QVERIFY(textEditObject != 0);
229 QCOMPARE(textEditObject->text(), QString(""));
232 for (int i = 0; i < standard.size(); i++)
234 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"" + standard.at(i) + "\" }";
235 QDeclarativeComponent texteditComponent(&engine);
236 texteditComponent.setData(componentStr.toLatin1(), QUrl());
237 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
239 QVERIFY(textEditObject != 0);
240 QCOMPARE(textEditObject->text(), standard.at(i));
243 for (int i = 0; i < richText.size(); i++)
245 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"" + richText.at(i) + "\" }";
246 QDeclarativeComponent texteditComponent(&engine);
247 texteditComponent.setData(componentStr.toLatin1(), QUrl());
248 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
250 QVERIFY(textEditObject != 0);
251 QString actual = textEditObject->text();
252 QString expected = richText.at(i);
253 actual.replace(QRegExp(".*<body[^>]*>"),"");
254 actual.replace(QRegExp("(<[^>]*>)+"),"<>");
255 expected.replace(QRegExp("(<[^>]*>)+"),"<>");
256 QCOMPARE(actual.simplified(),expected.simplified());
260 void tst_qdeclarativetextedit::width()
262 // uses Font metrics to find the width for standard and document to find the width for rich
264 QDeclarativeComponent texteditComponent(&engine);
265 texteditComponent.setData("import QtQuick 1.0\nTextEdit { text: \"\" }", QUrl());
266 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
268 QVERIFY(textEditObject != 0);
269 QCOMPARE(textEditObject->width(), 0.0);
272 for (int i = 0; i < standard.size(); i++)
276 qreal metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
277 metricWidth = ceil(metricWidth);
279 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"" + standard.at(i) + "\" }";
280 QDeclarativeComponent texteditComponent(&engine);
281 texteditComponent.setData(componentStr.toLatin1(), QUrl());
282 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
284 QVERIFY(textEditObject != 0);
285 QCOMPARE(textEditObject->width(), qreal(metricWidth));
288 for (int i = 0; i < richText.size(); i++)
290 QTextDocument document;
291 document.setHtml(richText.at(i));
292 document.setDocumentMargin(0);
294 int documentWidth = ceil(document.idealWidth());
296 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"" + richText.at(i) + "\" }";
297 QDeclarativeComponent texteditComponent(&engine);
298 texteditComponent.setData(componentStr.toLatin1(), QUrl());
299 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
301 QVERIFY(textEditObject != 0);
302 QCOMPARE(textEditObject->width(), qreal(documentWidth));
306 void tst_qdeclarativetextedit::wrap()
308 // for specified width and wrap set true
310 QDeclarativeComponent texteditComponent(&engine);
311 texteditComponent.setData("import QtQuick 1.0\nTextEdit { text: \"\"; wrapMode: TextEdit.WordWrap; width: 300 }", QUrl());
312 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
314 QVERIFY(textEditObject != 0);
315 QCOMPARE(textEditObject->width(), 300.);
318 for (int i = 0; i < standard.size(); i++)
320 QString componentStr = "import QtQuick 1.0\nTextEdit { wrapMode: TextEdit.WordWrap; width: 300; text: \"" + standard.at(i) + "\" }";
321 QDeclarativeComponent texteditComponent(&engine);
322 texteditComponent.setData(componentStr.toLatin1(), QUrl());
323 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
325 QVERIFY(textEditObject != 0);
326 QCOMPARE(textEditObject->width(), 300.);
329 for (int i = 0; i < richText.size(); i++)
331 QString componentStr = "import QtQuick 1.0\nTextEdit { wrapMode: TextEdit.WordWrap; width: 300; text: \"" + richText.at(i) + "\" }";
332 QDeclarativeComponent texteditComponent(&engine);
333 texteditComponent.setData(componentStr.toLatin1(), QUrl());
334 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
336 QVERIFY(textEditObject != 0);
337 QCOMPARE(textEditObject->width(), 300.);
342 void tst_qdeclarativetextedit::textFormat()
345 QDeclarativeComponent textComponent(&engine);
346 textComponent.setData("import QtQuick 1.0\nTextEdit { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
347 QDeclarative1TextEdit *textObject = qobject_cast<QDeclarative1TextEdit*>(textComponent.create());
349 QVERIFY(textObject != 0);
350 QVERIFY(textObject->textFormat() == QDeclarative1TextEdit::RichText);
353 QDeclarativeComponent textComponent(&engine);
354 textComponent.setData("import QtQuick 1.0\nTextEdit { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
355 QDeclarative1TextEdit *textObject = qobject_cast<QDeclarative1TextEdit*>(textComponent.create());
357 QVERIFY(textObject != 0);
358 QVERIFY(textObject->textFormat() == QDeclarative1TextEdit::PlainText);
362 void tst_qdeclarativetextedit::alignments_data()
364 QTest::addColumn<int>("hAlign");
365 QTest::addColumn<int>("vAlign");
366 QTest::addColumn<QString>("expectfile");
368 QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << "alignments_lt";
369 QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << "alignments_rt";
370 QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << "alignments_ct";
372 QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << "alignments_lb";
373 QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << "alignments_rb";
374 QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << "alignments_cb";
376 QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << "alignments_lc";
377 QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << "alignments_rc";
378 QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << "alignments_cc";
382 void tst_qdeclarativetextedit::alignments()
386 QFETCH(QString, expectfile);
388 QDeclarativeView *canvas = createView(SRCDIR "/data/alignments.qml");
391 QApplication::setActiveWindow(canvas);
392 QTest::qWaitForWindowShown(canvas);
393 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
395 QObject *ob = canvas->rootObject();
397 ob->setProperty("horizontalAlignment",hAlign);
398 ob->setProperty("verticalAlignment",vAlign);
399 QTRY_COMPARE(ob->property("running").toBool(),false);
400 QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32);
401 actual.fill(qRgb(255,255,255));
405 expectfile = createExpectedFileIfNotFound(expectfile, actual);
407 QImage expect(expectfile);
409 QCOMPARE(actual,expect);
415 //the alignment tests may be trivial o.oa
416 void tst_qdeclarativetextedit::hAlign()
418 //test one align each, and then test if two align fails.
420 for (int i = 0; i < standard.size(); i++)
422 for (int j=0; j < hAlignmentStrings.size(); j++)
424 QString componentStr = "import QtQuick 1.0\nTextEdit { horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
425 QDeclarativeComponent texteditComponent(&engine);
426 texteditComponent.setData(componentStr.toLatin1(), QUrl());
427 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
429 QVERIFY(textEditObject != 0);
430 QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
434 for (int i = 0; i < richText.size(); i++)
436 for (int j=0; j < hAlignmentStrings.size(); j++)
438 QString componentStr = "import QtQuick 1.0\nTextEdit { horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
439 QDeclarativeComponent texteditComponent(&engine);
440 texteditComponent.setData(componentStr.toLatin1(), QUrl());
441 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
443 QVERIFY(textEditObject != 0);
444 QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
450 void tst_qdeclarativetextedit::hAlign_RightToLeft()
452 QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml");
453 QDeclarative1TextEdit *textEdit = canvas->rootObject()->findChild<QDeclarative1TextEdit*>("text");
454 QVERIFY(textEdit != 0);
457 // implicit alignment should follow the reading direction of text
458 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
459 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
461 // explicitly left aligned
462 textEdit->setHAlign(QDeclarative1TextEdit::AlignLeft);
463 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignLeft);
464 QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2);
466 // explicitly right aligned
467 textEdit->setHAlign(QDeclarative1TextEdit::AlignRight);
468 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
469 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
471 QString textString = textEdit->text();
472 textEdit->setText(QString("<i>") + textString + QString("</i>"));
473 textEdit->resetHAlign();
475 // implicitly aligned rich text should follow the reading direction of RTL text
476 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
477 QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
478 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
480 // explicitly left aligned rich text
481 textEdit->setHAlign(QDeclarative1TextEdit::AlignLeft);
482 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignLeft);
483 QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
484 QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2);
486 // explicitly right aligned rich text
487 textEdit->setHAlign(QDeclarative1TextEdit::AlignRight);
488 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
489 QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
490 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
492 textEdit->setText(textString);
494 // explicitly center aligned
495 textEdit->setHAlign(QDeclarative1TextEdit::AlignHCenter);
496 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignHCenter);
497 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
499 // reseted alignment should go back to following the text reading direction
500 textEdit->resetHAlign();
501 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
502 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
504 // mirror the text item
505 QDeclarativeItemPrivate::get(textEdit)->setLayoutMirror(true);
507 // mirrored implicit alignment should continue to follow the reading direction of the text
508 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
509 QCOMPARE(textEdit->effectiveHAlign(), QDeclarative1TextEdit::AlignRight);
510 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
512 // mirrored explicitly right aligned behaves as left aligned
513 textEdit->setHAlign(QDeclarative1TextEdit::AlignRight);
514 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
515 QCOMPARE(textEdit->effectiveHAlign(), QDeclarative1TextEdit::AlignLeft);
516 QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2);
518 // mirrored explicitly left aligned behaves as right aligned
519 textEdit->setHAlign(QDeclarative1TextEdit::AlignLeft);
520 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignLeft);
521 QCOMPARE(textEdit->effectiveHAlign(), QDeclarative1TextEdit::AlignRight);
522 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
525 QDeclarativeItemPrivate::get(textEdit)->setLayoutMirror(false);
526 textEdit->resetHAlign();
528 // English text should be implicitly left aligned
529 textEdit->setText("Hello world!");
530 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignLeft);
531 QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2);
533 #ifndef Q_OS_MAC // QTBUG-18040
534 // empty text with implicit alignment follows the system locale-based
535 // keyboard input direction from QApplication::keyboardInputDirection
536 textEdit->setText("");
537 QCOMPARE(textEdit->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
538 QDeclarative1TextEdit::AlignLeft : QDeclarative1TextEdit::AlignRight);
539 if (QApplication::keyboardInputDirection() == Qt::LeftToRight)
540 QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2);
542 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
543 textEdit->setHAlign(QDeclarative1TextEdit::AlignRight);
544 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
545 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
550 #ifndef Q_OS_MAC // QTBUG-18040
551 // alignment of TextEdit with no text set to it
552 QString componentStr = "import QtQuick 1.0\nTextEdit {}";
553 QDeclarativeComponent textComponent(&engine);
554 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
555 QDeclarative1TextEdit *textObject = qobject_cast<QDeclarative1TextEdit*>(textComponent.create());
556 QCOMPARE(textObject->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
557 QDeclarative1TextEdit::AlignLeft : QDeclarative1TextEdit::AlignRight);
562 void tst_qdeclarativetextedit::vAlign()
564 //test one align each, and then test if two align fails.
566 for (int i = 0; i < standard.size(); i++)
568 for (int j=0; j < vAlignmentStrings.size(); j++)
570 QString componentStr = "import QtQuick 1.0\nTextEdit { verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
571 QDeclarativeComponent texteditComponent(&engine);
572 texteditComponent.setData(componentStr.toLatin1(), QUrl());
573 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
575 QVERIFY(textEditObject != 0);
576 QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
580 for (int i = 0; i < richText.size(); i++)
582 for (int j=0; j < vAlignmentStrings.size(); j++)
584 QString componentStr = "import QtQuick 1.0\nTextEdit { verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
585 QDeclarativeComponent texteditComponent(&engine);
586 texteditComponent.setData(componentStr.toLatin1(), QUrl());
587 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
589 QVERIFY(textEditObject != 0);
590 QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
596 void tst_qdeclarativetextedit::font()
598 //test size, then bold, then italic, then family
600 QString componentStr = "import QtQuick 1.0\nTextEdit { font.pointSize: 40; text: \"Hello World\" }";
601 QDeclarativeComponent texteditComponent(&engine);
602 texteditComponent.setData(componentStr.toLatin1(), QUrl());
603 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
605 QVERIFY(textEditObject != 0);
606 QCOMPARE(textEditObject->font().pointSize(), 40);
607 QCOMPARE(textEditObject->font().bold(), false);
608 QCOMPARE(textEditObject->font().italic(), false);
612 QString componentStr = "import QtQuick 1.0\nTextEdit { font.bold: true; text: \"Hello World\" }";
613 QDeclarativeComponent texteditComponent(&engine);
614 texteditComponent.setData(componentStr.toLatin1(), QUrl());
615 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
617 QVERIFY(textEditObject != 0);
618 QCOMPARE(textEditObject->font().bold(), true);
619 QCOMPARE(textEditObject->font().italic(), false);
623 QString componentStr = "import QtQuick 1.0\nTextEdit { font.italic: true; text: \"Hello World\" }";
624 QDeclarativeComponent texteditComponent(&engine);
625 texteditComponent.setData(componentStr.toLatin1(), QUrl());
626 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
628 QVERIFY(textEditObject != 0);
629 QCOMPARE(textEditObject->font().italic(), true);
630 QCOMPARE(textEditObject->font().bold(), false);
634 QString componentStr = "import QtQuick 1.0\nTextEdit { font.family: \"Helvetica\"; text: \"Hello World\" }";
635 QDeclarativeComponent texteditComponent(&engine);
636 texteditComponent.setData(componentStr.toLatin1(), QUrl());
637 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
639 QVERIFY(textEditObject != 0);
640 QCOMPARE(textEditObject->font().family(), QString("Helvetica"));
641 QCOMPARE(textEditObject->font().bold(), false);
642 QCOMPARE(textEditObject->font().italic(), false);
646 QString componentStr = "import QtQuick 1.0\nTextEdit { font.family: \"\"; text: \"Hello World\" }";
647 QDeclarativeComponent texteditComponent(&engine);
648 texteditComponent.setData(componentStr.toLatin1(), QUrl());
649 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
651 QVERIFY(textEditObject != 0);
652 QCOMPARE(textEditObject->font().family(), QString(""));
656 void tst_qdeclarativetextedit::color()
660 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"Hello World\" }";
661 QDeclarativeComponent texteditComponent(&engine);
662 texteditComponent.setData(componentStr.toLatin1(), QUrl());
663 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
665 QDeclarative1TextEditPrivate *textEditPrivate = static_cast<QDeclarative1TextEditPrivate*>(QDeclarativeItemPrivate::get(textEditObject));
667 QVERIFY(textEditObject);
668 QVERIFY(textEditPrivate);
669 QVERIFY(textEditPrivate->control);
671 QPalette pal = textEditPrivate->control->palette();
672 QCOMPARE(textEditPrivate->color, QColor("black"));
673 QCOMPARE(textEditPrivate->color, pal.color(QPalette::Text));
676 for (int i = 0; i < colorStrings.size(); i++)
678 QString componentStr = "import QtQuick 1.0\nTextEdit { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
679 QDeclarativeComponent texteditComponent(&engine);
680 texteditComponent.setData(componentStr.toLatin1(), QUrl());
681 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
682 //qDebug() << "textEditObject: " << textEditObject->color() << "vs. " << QColor(colorStrings.at(i));
683 QVERIFY(textEditObject != 0);
684 QCOMPARE(textEditObject->color(), QColor(colorStrings.at(i)));
688 for (int i = 0; i < colorStrings.size(); i++)
690 QString componentStr = "import QtQuick 1.0\nTextEdit { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
691 QDeclarativeComponent texteditComponent(&engine);
692 texteditComponent.setData(componentStr.toLatin1(), QUrl());
693 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
694 QVERIFY(textEditObject != 0);
695 QCOMPARE(textEditObject->selectionColor(), QColor(colorStrings.at(i)));
699 for (int i = 0; i < colorStrings.size(); i++)
701 QString componentStr = "import QtQuick 1.0\nTextEdit { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
702 QDeclarativeComponent texteditComponent(&engine);
703 texteditComponent.setData(componentStr.toLatin1(), QUrl());
704 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
705 QVERIFY(textEditObject != 0);
706 QCOMPARE(textEditObject->selectedTextColor(), QColor(colorStrings.at(i)));
710 QString colorStr = "#AA001234";
711 QColor testColor("#001234");
712 testColor.setAlpha(170);
714 QString componentStr = "import QtQuick 1.0\nTextEdit { color: \"" + colorStr + "\"; text: \"Hello World\" }";
715 QDeclarativeComponent texteditComponent(&engine);
716 texteditComponent.setData(componentStr.toLatin1(), QUrl());
717 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
719 QVERIFY(textEditObject != 0);
720 QCOMPARE(textEditObject->color(), testColor);
724 void tst_qdeclarativetextedit::textMargin()
726 for(qreal i=0; i<=10; i+=0.3){
727 QString componentStr = "import QtQuick 1.0\nTextEdit { textMargin: " + QString::number(i) + "; text: \"Hello World\" }";
728 QDeclarativeComponent texteditComponent(&engine);
729 texteditComponent.setData(componentStr.toLatin1(), QUrl());
730 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
731 QVERIFY(textEditObject != 0);
732 QCOMPARE(textEditObject->textMargin(), i);
736 void tst_qdeclarativetextedit::persistentSelection()
739 QString componentStr = "import QtQuick 1.0\nTextEdit { persistentSelection: true; text: \"Hello World\" }";
740 QDeclarativeComponent texteditComponent(&engine);
741 texteditComponent.setData(componentStr.toLatin1(), QUrl());
742 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
743 QVERIFY(textEditObject != 0);
744 QCOMPARE(textEditObject->persistentSelection(), true);
748 QString componentStr = "import QtQuick 1.0\nTextEdit { persistentSelection: false; text: \"Hello World\" }";
749 QDeclarativeComponent texteditComponent(&engine);
750 texteditComponent.setData(componentStr.toLatin1(), QUrl());
751 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
752 QVERIFY(textEditObject != 0);
753 QCOMPARE(textEditObject->persistentSelection(), false);
757 void tst_qdeclarativetextedit::focusOnPress()
760 QString componentStr = "import QtQuick 1.0\nTextEdit { activeFocusOnPress: true; text: \"Hello World\" }";
761 QDeclarativeComponent texteditComponent(&engine);
762 texteditComponent.setData(componentStr.toLatin1(), QUrl());
763 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
764 QVERIFY(textEditObject != 0);
765 QCOMPARE(textEditObject->focusOnPress(), true);
769 QString componentStr = "import QtQuick 1.0\nTextEdit { activeFocusOnPress: false; text: \"Hello World\" }";
770 QDeclarativeComponent texteditComponent(&engine);
771 texteditComponent.setData(componentStr.toLatin1(), QUrl());
772 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
773 QVERIFY(textEditObject != 0);
774 QCOMPARE(textEditObject->focusOnPress(), false);
778 void tst_qdeclarativetextedit::selection()
780 QString testStr = standard[0];//TODO: What should happen for multiline/rich text?
781 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \""+ testStr +"\"; }";
782 QDeclarativeComponent texteditComponent(&engine);
783 texteditComponent.setData(componentStr.toLatin1(), QUrl());
784 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
785 QVERIFY(textEditObject != 0);
788 //Test selection follows cursor
789 for(int i=0; i<= testStr.size(); i++) {
790 textEditObject->setCursorPosition(i);
791 QCOMPARE(textEditObject->cursorPosition(), i);
792 QCOMPARE(textEditObject->selectionStart(), i);
793 QCOMPARE(textEditObject->selectionEnd(), i);
794 QVERIFY(textEditObject->selectedText().isNull());
796 //Test cursor follows selection
797 for(int i=0; i<= testStr.size(); i++) {
798 textEditObject->select(i,i);
799 QCOMPARE(textEditObject->cursorPosition(), i);
800 QCOMPARE(textEditObject->selectionStart(), i);
801 QCOMPARE(textEditObject->selectionEnd(), i);
805 textEditObject->setCursorPosition(0);
806 QVERIFY(textEditObject->cursorPosition() == 0);
807 QVERIFY(textEditObject->selectionStart() == 0);
808 QVERIFY(textEditObject->selectionEnd() == 0);
809 QVERIFY(textEditObject->selectedText().isNull());
811 // Verify invalid positions are ignored.
812 textEditObject->setCursorPosition(-1);
813 QVERIFY(textEditObject->cursorPosition() == 0);
814 QVERIFY(textEditObject->selectionStart() == 0);
815 QVERIFY(textEditObject->selectionEnd() == 0);
816 QVERIFY(textEditObject->selectedText().isNull());
818 textEditObject->setCursorPosition(textEditObject->text().count()+1);
819 QVERIFY(textEditObject->cursorPosition() == 0);
820 QVERIFY(textEditObject->selectionStart() == 0);
821 QVERIFY(textEditObject->selectionEnd() == 0);
822 QVERIFY(textEditObject->selectedText().isNull());
825 for(int i=0; i<= testStr.size(); i++) {
826 textEditObject->select(0,i);
827 QCOMPARE(testStr.mid(0,i), textEditObject->selectedText());
828 QCOMPARE(textEditObject->cursorPosition(), i);
830 for(int i=0; i<= testStr.size(); i++) {
831 textEditObject->select(i,testStr.size());
832 QCOMPARE(testStr.mid(i,testStr.size()-i), textEditObject->selectedText());
833 QCOMPARE(textEditObject->cursorPosition(), testStr.size());
836 textEditObject->setCursorPosition(0);
837 QVERIFY(textEditObject->cursorPosition() == 0);
838 QVERIFY(textEditObject->selectionStart() == 0);
839 QVERIFY(textEditObject->selectionEnd() == 0);
840 QVERIFY(textEditObject->selectedText().isNull());
842 //Test Error Ignoring behaviour
843 textEditObject->setCursorPosition(0);
844 QVERIFY(textEditObject->selectedText().isNull());
845 textEditObject->select(-10,0);
846 QVERIFY(textEditObject->selectedText().isNull());
847 textEditObject->select(100,101);
848 QVERIFY(textEditObject->selectedText().isNull());
849 textEditObject->select(0,-10);
850 QVERIFY(textEditObject->selectedText().isNull());
851 textEditObject->select(0,100);
852 QVERIFY(textEditObject->selectedText().isNull());
853 textEditObject->select(0,10);
854 QVERIFY(textEditObject->selectedText().size() == 10);
855 textEditObject->select(-10,0);
856 QVERIFY(textEditObject->selectedText().size() == 10);
857 textEditObject->select(100,101);
858 QVERIFY(textEditObject->selectedText().size() == 10);
859 textEditObject->select(0,-10);
860 QVERIFY(textEditObject->selectedText().size() == 10);
861 textEditObject->select(0,100);
862 QVERIFY(textEditObject->selectedText().size() == 10);
864 textEditObject->deselect();
865 QVERIFY(textEditObject->selectedText().isNull());
866 textEditObject->select(0,10);
867 QVERIFY(textEditObject->selectedText().size() == 10);
868 textEditObject->deselect();
869 QVERIFY(textEditObject->selectedText().isNull());
872 void tst_qdeclarativetextedit::isRightToLeft_data()
874 QTest::addColumn<QString>("text");
875 QTest::addColumn<bool>("emptyString");
876 QTest::addColumn<bool>("firstCharacter");
877 QTest::addColumn<bool>("lastCharacter");
878 QTest::addColumn<bool>("middleCharacter");
879 QTest::addColumn<bool>("startString");
880 QTest::addColumn<bool>("midString");
881 QTest::addColumn<bool>("endString");
883 const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
884 QTest::newRow("Empty") << "" << false << false << false << false << false << false << false;
885 QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false;
886 QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false;
887 QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true;
888 QTest::newRow("Bidi RTL + LTR + RTL") << QString::fromUtf16(arabic_str, 11) + QString("Hello world") + QString::fromUtf16(arabic_str, 11) << false << true << true << false << true << true << true;
889 QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false;
892 void tst_qdeclarativetextedit::isRightToLeft()
894 QFETCH(QString, text);
895 QFETCH(bool, emptyString);
896 QFETCH(bool, firstCharacter);
897 QFETCH(bool, lastCharacter);
898 QFETCH(bool, middleCharacter);
899 QFETCH(bool, startString);
900 QFETCH(bool, midString);
901 QFETCH(bool, endString);
903 QDeclarative1TextEdit textEdit;
904 textEdit.setText(text);
906 // first test that the right string is delivered to the QString::isRightToLeft()
907 QCOMPARE(textEdit.isRightToLeft(0,0), text.mid(0,0).isRightToLeft());
908 QCOMPARE(textEdit.isRightToLeft(0,1), text.mid(0,1).isRightToLeft());
909 QCOMPARE(textEdit.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft());
910 QCOMPARE(textEdit.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft());
911 QCOMPARE(textEdit.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft());
912 QCOMPARE(textEdit.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft());
914 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextEdit: isRightToLeft(start, end) called with the end property being smaller than the start.");
915 QCOMPARE(textEdit.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft());
917 // then test that the feature actually works
918 QCOMPARE(textEdit.isRightToLeft(0,0), emptyString);
919 QCOMPARE(textEdit.isRightToLeft(0,1), firstCharacter);
920 QCOMPARE(textEdit.isRightToLeft(text.count()-2, text.count()-1), lastCharacter);
921 QCOMPARE(textEdit.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter);
922 QCOMPARE(textEdit.isRightToLeft(0,text.count()/4), startString);
923 QCOMPARE(textEdit.isRightToLeft(text.count()/4,3*text.count()/4), midString);
925 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextEdit: isRightToLeft(start, end) called with the end property being smaller than the start.");
926 QCOMPARE(textEdit.isRightToLeft(3*text.count()/4,text.count()-1), endString);
929 void tst_qdeclarativetextedit::keySelection()
931 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
933 QApplication::setActiveWindow(canvas);
934 QTest::qWaitForWindowShown(canvas);
935 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
938 QVERIFY(canvas->rootObject() != 0);
940 QDeclarative1TextEdit *input = qobject_cast<QDeclarative1TextEdit *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
943 QTRY_VERIFY(input->hasActiveFocus() == true);
945 QSignalSpy spy(input, SIGNAL(selectionChanged()));
947 simulateKey(canvas, Qt::Key_Right, Qt::ShiftModifier);
948 QVERIFY(input->hasActiveFocus() == true);
949 QCOMPARE(input->selectedText(), QString("a"));
950 QCOMPARE(spy.count(), 1);
951 simulateKey(canvas, Qt::Key_Right);
952 QVERIFY(input->hasActiveFocus() == true);
953 QCOMPARE(input->selectedText(), QString());
954 QCOMPARE(spy.count(), 2);
955 simulateKey(canvas, Qt::Key_Right);
956 QVERIFY(input->hasActiveFocus() == false);
957 QCOMPARE(input->selectedText(), QString());
958 QCOMPARE(spy.count(), 2);
960 simulateKey(canvas, Qt::Key_Left);
961 QVERIFY(input->hasActiveFocus() == true);
962 QCOMPARE(spy.count(), 2);
963 simulateKey(canvas, Qt::Key_Left, Qt::ShiftModifier);
964 QVERIFY(input->hasActiveFocus() == true);
965 QCOMPARE(input->selectedText(), QString("a"));
966 QCOMPARE(spy.count(), 3);
967 simulateKey(canvas, Qt::Key_Left);
968 QVERIFY(input->hasActiveFocus() == true);
969 QCOMPARE(input->selectedText(), QString());
970 QCOMPARE(spy.count(), 4);
971 simulateKey(canvas, Qt::Key_Left);
972 QVERIFY(input->hasActiveFocus() == false);
973 QCOMPARE(input->selectedText(), QString());
974 QCOMPARE(spy.count(), 4);
979 void tst_qdeclarativetextedit::moveCursorSelection_data()
981 QTest::addColumn<QString>("testStr");
982 QTest::addColumn<int>("cursorPosition");
983 QTest::addColumn<int>("movePosition");
984 QTest::addColumn<QDeclarative1TextEdit::SelectionMode>("mode");
985 QTest::addColumn<int>("selectionStart");
986 QTest::addColumn<int>("selectionEnd");
987 QTest::addColumn<bool>("reversible");
989 QTest::newRow("(t)he|characters")
990 << standard[0] << 0 << 1 << QDeclarative1TextEdit::SelectCharacters << 0 << 1 << true;
991 QTest::newRow("do(g)|characters")
992 << standard[0] << 43 << 44 << QDeclarative1TextEdit::SelectCharacters << 43 << 44 << true;
993 QTest::newRow("jum(p)ed|characters")
994 << standard[0] << 23 << 24 << QDeclarative1TextEdit::SelectCharacters << 23 << 24 << true;
995 QTest::newRow("jumped( )over|characters")
996 << standard[0] << 26 << 27 << QDeclarative1TextEdit::SelectCharacters << 26 << 27 << true;
997 QTest::newRow("(the )|characters")
998 << standard[0] << 0 << 4 << QDeclarative1TextEdit::SelectCharacters << 0 << 4 << true;
999 QTest::newRow("( dog)|characters")
1000 << standard[0] << 40 << 44 << QDeclarative1TextEdit::SelectCharacters << 40 << 44 << true;
1001 QTest::newRow("( jumped )|characters")
1002 << standard[0] << 19 << 27 << QDeclarative1TextEdit::SelectCharacters << 19 << 27 << true;
1003 QTest::newRow("th(e qu)ick|characters")
1004 << standard[0] << 2 << 6 << QDeclarative1TextEdit::SelectCharacters << 2 << 6 << true;
1005 QTest::newRow("la(zy d)og|characters")
1006 << standard[0] << 38 << 42 << QDeclarative1TextEdit::SelectCharacters << 38 << 42 << true;
1007 QTest::newRow("jum(ped ov)er|characters")
1008 << standard[0] << 23 << 29 << QDeclarative1TextEdit::SelectCharacters << 23 << 29 << true;
1009 QTest::newRow("()the|characters")
1010 << standard[0] << 0 << 0 << QDeclarative1TextEdit::SelectCharacters << 0 << 0 << true;
1011 QTest::newRow("dog()|characters")
1012 << standard[0] << 44 << 44 << QDeclarative1TextEdit::SelectCharacters << 44 << 44 << true;
1013 QTest::newRow("jum()ped|characters")
1014 << standard[0] << 23 << 23 << QDeclarative1TextEdit::SelectCharacters << 23 << 23 << true;
1016 QTest::newRow("<(t)he>|words")
1017 << standard[0] << 0 << 1 << QDeclarative1TextEdit::SelectWords << 0 << 3 << true;
1018 QTest::newRow("<do(g)>|words")
1019 << standard[0] << 43 << 44 << QDeclarative1TextEdit::SelectWords << 41 << 44 << true;
1020 QTest::newRow("<jum(p)ed>|words")
1021 << standard[0] << 23 << 24 << QDeclarative1TextEdit::SelectWords << 20 << 26 << true;
1022 QTest::newRow("<jumped( )>over|words")
1023 << standard[0] << 26 << 27 << QDeclarative1TextEdit::SelectWords << 20 << 27 << false;
1024 QTest::newRow("jumped<( )over>|words,reversed")
1025 << standard[0] << 27 << 26 << QDeclarative1TextEdit::SelectWords << 26 << 31 << false;
1026 QTest::newRow("<(the )>quick|words")
1027 << standard[0] << 0 << 4 << QDeclarative1TextEdit::SelectWords << 0 << 4 << false;
1028 QTest::newRow("<(the )quick>|words,reversed")
1029 << standard[0] << 4 << 0 << QDeclarative1TextEdit::SelectWords << 0 << 9 << false;
1030 QTest::newRow("<lazy( dog)>|words")
1031 << standard[0] << 40 << 44 << QDeclarative1TextEdit::SelectWords << 36 << 44 << false;
1032 QTest::newRow("lazy<( dog)>|words,reversed")
1033 << standard[0] << 44 << 40 << QDeclarative1TextEdit::SelectWords << 40 << 44 << false;
1034 QTest::newRow("<fox( jumped )>over|words")
1035 << standard[0] << 19 << 27 << QDeclarative1TextEdit::SelectWords << 16 << 27 << false;
1036 QTest::newRow("fox<( jumped )over>|words,reversed")
1037 << standard[0] << 27 << 19 << QDeclarative1TextEdit::SelectWords << 19 << 31 << false;
1038 QTest::newRow("<th(e qu)ick>|words")
1039 << standard[0] << 2 << 6 << QDeclarative1TextEdit::SelectWords << 0 << 9 << true;
1040 QTest::newRow("<la(zy d)og|words>")
1041 << standard[0] << 38 << 42 << QDeclarative1TextEdit::SelectWords << 36 << 44 << true;
1042 QTest::newRow("<jum(ped ov)er>|words")
1043 << standard[0] << 23 << 29 << QDeclarative1TextEdit::SelectWords << 20 << 31 << true;
1044 QTest::newRow("<()>the|words")
1045 << standard[0] << 0 << 0 << QDeclarative1TextEdit::SelectWords << 0 << 0 << true;
1046 QTest::newRow("dog<()>|words")
1047 << standard[0] << 44 << 44 << QDeclarative1TextEdit::SelectWords << 44 << 44 << true;
1048 QTest::newRow("jum<()>ped|words")
1049 << standard[0] << 23 << 23 << QDeclarative1TextEdit::SelectWords << 23 << 23 << true;
1051 QTest::newRow("Hello<(,)> |words")
1052 << standard[2] << 5 << 6 << QDeclarative1TextEdit::SelectWords << 5 << 6 << true;
1053 QTest::newRow("Hello<(, )>world|words")
1054 << standard[2] << 5 << 7 << QDeclarative1TextEdit::SelectWords << 5 << 7 << false;
1055 QTest::newRow("Hello<(, )world>|words,reversed")
1056 << standard[2] << 7 << 5 << QDeclarative1TextEdit::SelectWords << 5 << 12 << false;
1057 QTest::newRow("<Hel(lo, )>world|words")
1058 << standard[2] << 3 << 7 << QDeclarative1TextEdit::SelectWords << 0 << 7 << false;
1059 QTest::newRow("<Hel(lo, )world>|words,reversed")
1060 << standard[2] << 7 << 3 << QDeclarative1TextEdit::SelectWords << 0 << 12 << false;
1061 QTest::newRow("<Hel(lo)>,|words")
1062 << standard[2] << 3 << 5 << QDeclarative1TextEdit::SelectWords << 0 << 5 << true;
1063 QTest::newRow("Hello<()>,|words")
1064 << standard[2] << 5 << 5 << QDeclarative1TextEdit::SelectWords << 5 << 5 << true;
1065 QTest::newRow("Hello,<()>|words")
1066 << standard[2] << 6 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 6 << true;
1067 QTest::newRow("Hello<,( )>world|words")
1068 << standard[2] << 6 << 7 << QDeclarative1TextEdit::SelectWords << 5 << 7 << false;
1069 QTest::newRow("Hello,<( )world>|words,reversed")
1070 << standard[2] << 7 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 12 << false;
1071 QTest::newRow("Hello<,( world)>|words")
1072 << standard[2] << 6 << 12 << QDeclarative1TextEdit::SelectWords << 5 << 12 << false;
1073 QTest::newRow("Hello,<( world)>|words,reversed")
1074 << standard[2] << 12 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 12 << false;
1075 QTest::newRow("Hello<,( world!)>|words")
1076 << standard[2] << 6 << 13 << QDeclarative1TextEdit::SelectWords << 5 << 13 << false;
1077 QTest::newRow("Hello,<( world!)>|words,reversed")
1078 << standard[2] << 13 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 13 << false;
1079 QTest::newRow("Hello<(, world!)>|words")
1080 << standard[2] << 5 << 13 << QDeclarative1TextEdit::SelectWords << 5 << 13 << true;
1081 QTest::newRow("world<(!)>|words")
1082 << standard[2] << 12 << 13 << QDeclarative1TextEdit::SelectWords << 12 << 13 << true;
1083 QTest::newRow("world!<()>)|words")
1084 << standard[2] << 13 << 13 << QDeclarative1TextEdit::SelectWords << 13 << 13 << true;
1085 QTest::newRow("world<()>!)|words")
1086 << standard[2] << 12 << 12 << QDeclarative1TextEdit::SelectWords << 12 << 12 << true;
1088 QTest::newRow("<(,)>olleH |words")
1089 << standard[3] << 7 << 8 << QDeclarative1TextEdit::SelectWords << 7 << 8 << true;
1090 QTest::newRow("<dlrow( ,)>olleH|words")
1091 << standard[3] << 6 << 8 << QDeclarative1TextEdit::SelectWords << 1 << 8 << false;
1092 QTest::newRow("dlrow<( ,)>olleH|words,reversed")
1093 << standard[3] << 8 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 8 << false;
1094 QTest::newRow("<dlrow( ,ol)leH>|words")
1095 << standard[3] << 6 << 10 << QDeclarative1TextEdit::SelectWords << 1 << 13 << false;
1096 QTest::newRow("dlrow<( ,ol)leH>|words,reversed")
1097 << standard[3] << 10 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 13 << false;
1098 QTest::newRow(",<(ol)leH>,|words")
1099 << standard[3] << 8 << 10 << QDeclarative1TextEdit::SelectWords << 8 << 13 << true;
1100 QTest::newRow(",<()>olleH|words")
1101 << standard[3] << 8 << 8 << QDeclarative1TextEdit::SelectWords << 8 << 8 << true;
1102 QTest::newRow("<()>,olleH|words")
1103 << standard[3] << 7 << 7 << QDeclarative1TextEdit::SelectWords << 7 << 7 << true;
1104 QTest::newRow("<dlrow( )>,olleH|words")
1105 << standard[3] << 6 << 7 << QDeclarative1TextEdit::SelectWords << 1 << 7 << false;
1106 QTest::newRow("dlrow<( ),>olleH|words,reversed")
1107 << standard[3] << 7 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 8 << false;
1108 QTest::newRow("<(dlrow )>,olleH|words")
1109 << standard[3] << 1 << 7 << QDeclarative1TextEdit::SelectWords << 1 << 7 << false;
1110 QTest::newRow("<(dlrow ),>olleH|words,reversed")
1111 << standard[3] << 7 << 1 << QDeclarative1TextEdit::SelectWords << 1 << 8 << false;
1112 QTest::newRow("<(!dlrow )>,olleH|words")
1113 << standard[3] << 0 << 7 << QDeclarative1TextEdit::SelectWords << 0 << 7 << false;
1114 QTest::newRow("<(!dlrow ),>olleH|words,reversed")
1115 << standard[3] << 7 << 0 << QDeclarative1TextEdit::SelectWords << 0 << 8 << false;
1116 QTest::newRow("(!dlrow ,)olleH|words")
1117 << standard[3] << 0 << 8 << QDeclarative1TextEdit::SelectWords << 0 << 8 << true;
1118 QTest::newRow("<(!)>dlrow|words")
1119 << standard[3] << 0 << 1 << QDeclarative1TextEdit::SelectWords << 0 << 1 << true;
1120 QTest::newRow("<()>!dlrow|words")
1121 << standard[3] << 0 << 0 << QDeclarative1TextEdit::SelectWords << 0 << 0 << true;
1122 QTest::newRow("!<()>dlrow|words")
1123 << standard[3] << 1 << 1 << QDeclarative1TextEdit::SelectWords << 1 << 1 << true;
1126 void tst_qdeclarativetextedit::moveCursorSelection()
1128 QFETCH(QString, testStr);
1129 QFETCH(int, cursorPosition);
1130 QFETCH(int, movePosition);
1131 QFETCH(QDeclarative1TextEdit::SelectionMode, mode);
1132 QFETCH(int, selectionStart);
1133 QFETCH(int, selectionEnd);
1134 QFETCH(bool, reversible);
1136 QString componentStr = "import QtQuick 1.1\nTextEdit { text: \""+ testStr +"\"; }";
1137 QDeclarativeComponent textinputComponent(&engine);
1138 textinputComponent.setData(componentStr.toLatin1(), QUrl());
1139 QDeclarative1TextEdit *texteditObject = qobject_cast<QDeclarative1TextEdit*>(textinputComponent.create());
1140 QVERIFY(texteditObject != 0);
1142 texteditObject->setCursorPosition(cursorPosition);
1143 texteditObject->moveCursorSelection(movePosition, mode);
1145 QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
1146 QCOMPARE(texteditObject->selectionStart(), selectionStart);
1147 QCOMPARE(texteditObject->selectionEnd(), selectionEnd);
1150 texteditObject->setCursorPosition(movePosition);
1151 texteditObject->moveCursorSelection(cursorPosition, mode);
1153 QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
1154 QCOMPARE(texteditObject->selectionStart(), selectionStart);
1155 QCOMPARE(texteditObject->selectionEnd(), selectionEnd);
1159 void tst_qdeclarativetextedit::moveCursorSelectionSequence_data()
1161 QTest::addColumn<QString>("testStr");
1162 QTest::addColumn<int>("cursorPosition");
1163 QTest::addColumn<int>("movePosition1");
1164 QTest::addColumn<int>("movePosition2");
1165 QTest::addColumn<int>("selection1Start");
1166 QTest::addColumn<int>("selection1End");
1167 QTest::addColumn<int>("selection2Start");
1168 QTest::addColumn<int>("selection2End");
1170 QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr")
1175 QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl")
1180 QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr")
1185 QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl")
1190 QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr")
1195 QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl")
1200 QTest::newRow("the {<quick() ^}bro)wn> fox|ltr")
1205 QTest::newRow("the quick<(^ {^bro)wn>} fox|rtl")
1210 QTest::newRow("the {<quick^}( bro)wn> fox|ltr")
1215 QTest::newRow("the quick{<(^ bro)wn>} fox|rtl")
1220 QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr")
1225 QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl")
1230 QTest::newRow("the {<^quick}( bro)wn> fox|ltr")
1235 QTest::newRow("the {<^quick}( bro)wn> fox|rtl")
1240 QTest::newRow("the{^ <quick}( bro)wn> fox|ltr")
1245 QTest::newRow("the{^ <quick}( bro)wn> fox|rtl")
1250 QTest::newRow("{t^he <quick}( bro)wn> fox|ltr")
1255 QTest::newRow("{t^he <quick}( bro)wn> fox|rtl")
1261 QTest::newRow("{<He(ll)o>, w^orld}!|ltr")
1266 QTest::newRow("{<He(ll)o>, w^orld}!|rtl")
1272 QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr")
1277 QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl")
1284 void tst_qdeclarativetextedit::moveCursorSelectionSequence()
1286 QFETCH(QString, testStr);
1287 QFETCH(int, cursorPosition);
1288 QFETCH(int, movePosition1);
1289 QFETCH(int, movePosition2);
1290 QFETCH(int, selection1Start);
1291 QFETCH(int, selection1End);
1292 QFETCH(int, selection2Start);
1293 QFETCH(int, selection2End);
1295 QString componentStr = "import QtQuick 1.1\nTextEdit { text: \""+ testStr +"\"; }";
1296 QDeclarativeComponent texteditComponent(&engine);
1297 texteditComponent.setData(componentStr.toLatin1(), QUrl());
1298 QDeclarative1TextEdit *texteditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
1299 QVERIFY(texteditObject != 0);
1301 texteditObject->setCursorPosition(cursorPosition);
1303 texteditObject->moveCursorSelection(movePosition1, QDeclarative1TextEdit::SelectWords);
1304 QCOMPARE(texteditObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start));
1305 QCOMPARE(texteditObject->selectionStart(), selection1Start);
1306 QCOMPARE(texteditObject->selectionEnd(), selection1End);
1308 texteditObject->moveCursorSelection(movePosition2, QDeclarative1TextEdit::SelectWords);
1309 QCOMPARE(texteditObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start));
1310 QCOMPARE(texteditObject->selectionStart(), selection2Start);
1311 QCOMPARE(texteditObject->selectionEnd(), selection2End);
1315 void tst_qdeclarativetextedit::mouseSelection_data()
1317 QTest::addColumn<QString>("qmlfile");
1318 QTest::addColumn<bool>("expectSelection");
1321 QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << true;
1322 QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << false;
1323 QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << false;
1324 QTest::newRow("on word selection") << SRCDIR "/data/mouseselection_true_words.qml" << true;
1325 QTest::newRow("off word selection") << SRCDIR "/data/mouseselection_false_words.qml" << false;
1328 void tst_qdeclarativetextedit::mouseSelection()
1330 QFETCH(QString, qmlfile);
1331 QFETCH(bool, expectSelection);
1333 QDeclarativeView *canvas = createView(qmlfile);
1336 QApplication::setActiveWindow(canvas);
1337 QTest::qWaitForWindowShown(canvas);
1338 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1340 QVERIFY(canvas->rootObject() != 0);
1341 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1342 QVERIFY(textEditObject != 0);
1344 // press-and-drag-and-release from x1 to x2
1347 int y = textEditObject->height()/2;
1348 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1349 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1350 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1351 QApplication::sendEvent(canvas->viewport(), &mv);
1352 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1353 QString str = textEditObject->selectedText();
1354 if (expectSelection)
1355 QVERIFY(str.length() > 3); // don't reallly care *what* was selected (and it's too sensitive to platform)
1357 QVERIFY(str.isEmpty());
1359 // Clicking and shift to clicking between the same points should select the same text.
1360 textEditObject->setCursorPosition(0);
1361 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::NoModifier, canvas->mapFromScene(QPoint(x1,y)));
1362 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::ShiftModifier, canvas->mapFromScene(QPoint(x2,y)));
1363 QCOMPARE(textEditObject->selectedText(), str);
1368 void tst_qdeclarativetextedit::multilineMouseSelection()
1370 QDeclarativeView *canvas = createView(SRCDIR "/data/mouseselection_multiline.qml");
1373 QApplication::setActiveWindow(canvas);
1374 QTest::qWaitForWindowShown(canvas);
1375 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1377 QVERIFY(canvas->rootObject() != 0);
1378 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1379 QVERIFY(textEditObject != 0);
1381 // press-and-drag from x1,y1 to x2,y1
1383 int x2 = textEditObject->width() - 10;
1384 int y1 = textEditObject->height() / 4;
1385 int y2 = textEditObject->height() * 3 / 4;
1386 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y1)));
1387 QMouseEvent mv1(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y1)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1388 QApplication::sendEvent(canvas->viewport(), &mv1);
1389 QString str1 = textEditObject->selectedText();
1390 QVERIFY(str1.length() > 3); // don't reallly care *what* was selected (and it's too sensitive to platform)
1392 // drag-and-release from x2,y1 to x2,y2
1393 QMouseEvent mv2(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y2)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1394 QApplication::sendEvent(canvas->viewport(), &mv2);
1395 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y2)));
1396 QString str2 = textEditObject->selectedText();
1397 QVERIFY(str1 != str2);
1398 QVERIFY(str2.length() > 3);
1403 void tst_qdeclarativetextedit::deferEnableSelectByMouse_data()
1405 QTest::addColumn<QString>("qmlfile");
1407 QTest::newRow("writable") << SRCDIR "/data/mouseselection_false.qml";
1408 QTest::newRow("read only") << SRCDIR "/data/mouseselection_false_readonly.qml";
1411 void tst_qdeclarativetextedit::deferEnableSelectByMouse()
1413 // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed.
1414 QFETCH(QString, qmlfile);
1416 QDeclarativeView *canvas = createView(qmlfile);
1419 QApplication::setActiveWindow(canvas);
1420 QTest::qWaitForWindowShown(canvas);
1421 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1423 QVERIFY(canvas->rootObject() != 0);
1424 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1425 QVERIFY(textEditObject != 0);
1427 // press-and-drag-and-release from x1 to x2
1430 int y = textEditObject->height()/2;
1432 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1433 textEditObject->setSelectByMouse(true);
1434 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1435 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1436 QApplication::sendEvent(canvas->viewport(), &mv);
1437 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1438 QVERIFY(textEditObject->selectedText().isEmpty());
1443 void tst_qdeclarativetextedit::deferDisableSelectByMouse_data()
1445 QTest::addColumn<QString>("qmlfile");
1447 QTest::newRow("writable") << SRCDIR "/data/mouseselection_true.qml";
1448 QTest::newRow("read only") << SRCDIR "/data/mouseselection_true_readonly.qml";
1451 void tst_qdeclarativetextedit::deferDisableSelectByMouse()
1453 // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed.
1454 QFETCH(QString, qmlfile);
1456 QDeclarativeView *canvas = createView(qmlfile);
1459 QApplication::setActiveWindow(canvas);
1460 QTest::qWaitForWindowShown(canvas);
1461 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1463 QVERIFY(canvas->rootObject() != 0);
1464 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1465 QVERIFY(textEditObject != 0);
1467 // press-and-drag-and-release from x1 to x2
1470 int y = textEditObject->height()/2;
1472 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1473 textEditObject->setSelectByMouse(false);
1474 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1475 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1476 QApplication::sendEvent(canvas->viewport(), &mv);
1477 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1478 QVERIFY(textEditObject->selectedText().length() > 3);
1483 void tst_qdeclarativetextedit::dragMouseSelection()
1485 QString qmlfile = SRCDIR "/data/mouseselection_true.qml";
1487 QDeclarativeView *canvas = createView(qmlfile);
1490 QApplication::setActiveWindow(canvas);
1491 QTest::qWaitForWindowShown(canvas);
1492 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1494 QVERIFY(canvas->rootObject() != 0);
1495 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1496 QVERIFY(textEditObject != 0);
1498 textEditObject->setAcceptDrops(true);
1500 // press-and-drag-and-release from x1 to x2
1503 int y = textEditObject->height()/2;
1504 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1506 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1507 QApplication::sendEvent(canvas->viewport(), &mv);
1509 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1510 QString str1 = textEditObject->selectedText();
1511 QVERIFY(str1.length() > 3);
1513 // press and drag the current selection.
1516 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1518 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1519 QApplication::sendEvent(canvas->viewport(), &mv);
1521 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1522 QString str2 = textEditObject->selectedText();
1523 QVERIFY(str2.length() > 3);
1525 QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved.
1530 void tst_qdeclarativetextedit::mouseSelectionMode_data()
1532 QTest::addColumn<QString>("qmlfile");
1533 QTest::addColumn<bool>("selectWords");
1536 QTest::newRow("SelectWords") << SRCDIR "/data/mouseselectionmode_words.qml" << true;
1537 QTest::newRow("SelectCharacters") << SRCDIR "/data/mouseselectionmode_characters.qml" << false;
1538 QTest::newRow("default") << SRCDIR "/data/mouseselectionmode_default.qml" << false;
1541 void tst_qdeclarativetextedit::mouseSelectionMode()
1543 QFETCH(QString, qmlfile);
1544 QFETCH(bool, selectWords);
1546 QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1548 QDeclarativeView *canvas = createView(qmlfile);
1551 QApplication::setActiveWindow(canvas);
1552 QTest::qWaitForWindowShown(canvas);
1553 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1555 QVERIFY(canvas->rootObject() != 0);
1556 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1557 QVERIFY(textEditObject != 0);
1559 // press-and-drag-and-release from x1 to x2
1562 int y = textEditObject->height()/2;
1563 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1564 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1565 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1566 QApplication::sendEvent(canvas->viewport(), &mv);
1567 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1568 QString str = textEditObject->selectedText();
1570 QCOMPARE(str, text);
1572 QVERIFY(str.length() > 3);
1573 QVERIFY(str != text);
1576 // Clicking and shift to clicking between the same points should select the same text.
1577 textEditObject->setCursorPosition(0);
1578 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::NoModifier, canvas->mapFromScene(QPoint(x1,y)));
1579 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::ShiftModifier, canvas->mapFromScene(QPoint(x2,y)));
1580 QCOMPARE(textEditObject->selectedText(), str);
1585 void tst_qdeclarativetextedit::inputMethodHints()
1587 QDeclarativeView *canvas = createView(SRCDIR "/data/inputmethodhints.qml");
1591 QVERIFY(canvas->rootObject() != 0);
1592 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1593 QVERIFY(textEditObject != 0);
1594 QVERIFY(textEditObject->inputMethodHints() & Qt::ImhNoPredictiveText);
1595 textEditObject->setInputMethodHints(Qt::ImhUppercaseOnly);
1596 QVERIFY(textEditObject->inputMethodHints() & Qt::ImhUppercaseOnly);
1601 void tst_qdeclarativetextedit::positionAt()
1603 QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml");
1604 QVERIFY(canvas->rootObject() != 0);
1607 QApplication::setActiveWindow(canvas);
1608 QTest::qWaitForWindowShown(canvas);
1610 QDeclarative1TextEdit *texteditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1611 QVERIFY(texteditObject != 0);
1613 QFontMetrics fm(texteditObject->font());
1614 const int y0 = fm.height() / 2;
1615 const int y1 = fm.height() * 3 / 2;
1617 int pos = texteditObject->positionAt(texteditObject->width()/2, y0);
1618 int diff = abs(int(fm.width(texteditObject->text().left(pos))-texteditObject->width()/2));
1621 QEXPECT_FAIL("", "QTBUG-21016 fails", Continue);
1623 // some tollerance for different fonts.
1630 const qreal x0 = texteditObject->positionToRectangle(pos).x();
1631 const qreal x1 = texteditObject->positionToRectangle(pos + 1).x();
1633 QString preeditText = texteditObject->text().mid(0, pos);
1634 texteditObject->setText(texteditObject->text().mid(pos));
1635 texteditObject->setCursorPosition(0);
1637 QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
1638 QApplication::sendEvent(canvas, &inputEvent);
1640 // Check all points within the preedit text return the same position.
1641 QCOMPARE(texteditObject->positionAt(0, y0), 0);
1642 QCOMPARE(texteditObject->positionAt(x0 / 2, y0), 0);
1643 QCOMPARE(texteditObject->positionAt(x0, y0), 0);
1645 // Verify positioning returns to normal after the preedit text.
1646 QCOMPARE(texteditObject->positionAt(x1, y0), 1);
1647 QCOMPARE(texteditObject->positionToRectangle(1).x(), x1);
1649 QVERIFY(texteditObject->positionAt(x0 / 2, y1) > 0);
1654 void tst_qdeclarativetextedit::cursorDelegate()
1656 QDeclarativeView* view = createView(SRCDIR "/data/cursorTest.qml");
1659 QDeclarative1TextEdit *textEditObject = view->rootObject()->findChild<QDeclarative1TextEdit*>("textEditObject");
1660 QVERIFY(textEditObject != 0);
1661 QVERIFY(textEditObject->findChild<QDeclarativeItem*>("cursorInstance"));
1662 //Test Delegate gets created
1663 textEditObject->setFocus(true);
1664 QDeclarativeItem* delegateObject = textEditObject->findChild<QDeclarativeItem*>("cursorInstance");
1665 QVERIFY(delegateObject);
1666 //Test Delegate gets moved
1667 for(int i=0; i<= textEditObject->text().length(); i++){
1668 textEditObject->setCursorPosition(i);
1669 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1670 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1672 const QString preedit = "preedit";
1673 for (int i = 0; i <= preedit.length(); i++) {
1674 QInputMethodEvent event(preedit, QList<QInputMethodEvent::Attribute>()
1675 << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, 1, QVariant()));
1676 QApplication::sendEvent(view, &event);
1678 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1679 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1681 // Clear preedit text;
1682 QInputMethodEvent event;
1683 QApplication::sendEvent(view, &event);
1685 // Test delegate gets moved on mouse press.
1686 textEditObject->setSelectByMouse(true);
1687 textEditObject->setCursorPosition(0);
1688 qDebug() << textEditObject->boundingRect() << textEditObject->positionToRectangle(5).center() << view->mapFromScene(textEditObject->positionToRectangle(5).center());
1689 QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(textEditObject->positionToRectangle(5).center()));
1690 QVERIFY(textEditObject->cursorPosition() != 0);
1691 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1692 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1694 textEditObject->setReadOnly(true);
1695 textEditObject->setCursorPosition(0);
1696 QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(textEditObject->positionToRectangle(5).center()));
1697 QVERIFY(textEditObject->cursorPosition() != 0);
1698 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1699 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1701 textEditObject->setCursorPosition(0);
1702 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1703 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1704 QVERIFY(textEditObject->cursorRectangle().y() >= 0);
1705 QVERIFY(textEditObject->cursorRectangle().y() < textEditObject->cursorRectangle().height());
1706 textEditObject->setVAlign(QDeclarative1TextEdit::AlignVCenter);
1707 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1708 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1709 QVERIFY(textEditObject->cursorRectangle().y() > (textEditObject->height() / 2) - textEditObject->cursorRectangle().height());
1710 QVERIFY(textEditObject->cursorRectangle().y() < (textEditObject->height() / 2) + textEditObject->cursorRectangle().height());
1711 textEditObject->setVAlign(QDeclarative1TextEdit::AlignBottom);
1712 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1713 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1714 QVERIFY(textEditObject->cursorRectangle().y() > textEditObject->height() - (textEditObject->cursorRectangle().height() * 2));
1715 QVERIFY(textEditObject->cursorRectangle().y() < textEditObject->height());
1717 //Test Delegate gets deleted
1718 textEditObject->setCursorDelegate(0);
1719 QVERIFY(!textEditObject->findChild<QDeclarativeItem*>("cursorInstance"));
1724 void tst_qdeclarativetextedit::cursorVisible()
1726 QGraphicsScene scene;
1727 QGraphicsView view(&scene);
1729 QApplication::setActiveWindow(&view);
1730 QTest::qWaitForWindowShown(&view);
1731 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
1734 QDeclarative1TextEdit edit;
1735 QSignalSpy spy(&edit, SIGNAL(cursorVisibleChanged(bool)));
1737 QCOMPARE(edit.isCursorVisible(), false);
1739 edit.setCursorVisible(true);
1740 QCOMPARE(edit.isCursorVisible(), true);
1741 QCOMPARE(spy.count(), 1);
1743 edit.setCursorVisible(false);
1744 QCOMPARE(edit.isCursorVisible(), false);
1745 QCOMPARE(spy.count(), 2);
1747 edit.setFocus(true);
1748 QCOMPARE(edit.isCursorVisible(), false);
1749 QCOMPARE(spy.count(), 2);
1751 scene.addItem(&edit);
1752 QCOMPARE(edit.isCursorVisible(), true);
1753 QCOMPARE(spy.count(), 3);
1755 edit.setFocus(false);
1756 QCOMPARE(edit.isCursorVisible(), false);
1757 QCOMPARE(spy.count(), 4);
1759 edit.setFocus(true);
1760 QCOMPARE(edit.isCursorVisible(), true);
1761 QCOMPARE(spy.count(), 5);
1764 QCOMPARE(edit.isCursorVisible(), false);
1765 QCOMPARE(spy.count(), 6);
1768 QCOMPARE(edit.isCursorVisible(), true);
1769 QCOMPARE(spy.count(), 7);
1772 QCOMPARE(edit.isCursorVisible(), false);
1773 QCOMPARE(spy.count(), 8);
1776 QCOMPARE(edit.isCursorVisible(), true);
1777 QCOMPARE(spy.count(), 9);
1779 // on mac, setActiveWindow(0) on mac does not deactivate the current application
1780 // (you have to switch to a different app or hide the current app to trigger this)
1781 #if !defined(Q_WS_MAC)
1782 QApplication::setActiveWindow(0);
1783 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(0));
1784 QCOMPARE(edit.isCursorVisible(), false);
1785 QCOMPARE(spy.count(), 10);
1787 QApplication::setActiveWindow(&view);
1788 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
1789 QCOMPARE(edit.isCursorVisible(), true);
1790 QCOMPARE(spy.count(), 11);
1794 void tst_qdeclarativetextedit::delegateLoading_data()
1796 QTest::addColumn<QString>("qmlfile");
1797 QTest::addColumn<QString>("error");
1800 QTest::newRow("pass") << "cursorHttpTestPass.qml" << "";
1801 QTest::newRow("fail1") << "cursorHttpTestFail1.qml" << "http://localhost:42332/FailItem.qml: Remote host closed the connection ";
1802 QTest::newRow("fail2") << "cursorHttpTestFail2.qml" << "http://localhost:42332/ErrItem.qml:4:5: Fungus is not a type ";
1805 void tst_qdeclarativetextedit::delegateLoading()
1807 QFETCH(QString, qmlfile);
1808 QFETCH(QString, error);
1810 TestHTTPServer server(42332);
1811 server.serveDirectory(SRCDIR "/data/httpfail", TestHTTPServer::Disconnect);
1812 server.serveDirectory(SRCDIR "/data/httpslow", TestHTTPServer::Delay);
1813 server.serveDirectory(SRCDIR "/data/http");
1815 QDeclarativeView* view = new QDeclarativeView(0);
1817 view->setSource(QUrl(QLatin1String("http://localhost:42332/") + qmlfile));
1821 if (!error.isEmpty()) {
1822 QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
1823 QTRY_VERIFY(view->status()==QDeclarativeView::Error);
1824 QTRY_VERIFY(!view->rootObject()); // there is fail item inside this test
1826 QTRY_VERIFY(view->rootObject());//Wait for loading to finish.
1827 QDeclarative1TextEdit *textEditObject = view->rootObject()->findChild<QDeclarative1TextEdit*>("textEditObject");
1828 // view->rootObject()->dumpObjectTree();
1829 QVERIFY(textEditObject != 0);
1830 textEditObject->setFocus(true);
1831 QDeclarativeItem *delegate;
1832 delegate = view->rootObject()->findChild<QDeclarativeItem*>("delegateOkay");
1834 delegate = view->rootObject()->findChild<QDeclarativeItem*>("delegateSlow");
1841 //A test should be added here with a component which is ready but component.create() returns null
1842 //Not sure how to accomplish this with QDeclarative1TextEdits cursor delegate
1843 //###This was only needed for code coverage, and could be a case of overzealous defensive programming
1844 //delegate = view->rootObject()->findChild<QDeclarativeItem*>("delegateErrorB");
1845 //QVERIFY(!delegate);
1851 TextEdit element should only handle left/right keys until the cursor reaches
1852 the extent of the text, then they should ignore the keys.
1854 void tst_qdeclarativetextedit::navigation()
1856 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
1860 QVERIFY(canvas->rootObject() != 0);
1862 QDeclarativeItem *input = qobject_cast<QDeclarativeItem *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1864 QVERIFY(input != 0);
1865 QTRY_VERIFY(input->hasActiveFocus() == true);
1866 simulateKey(canvas, Qt::Key_Left);
1867 QVERIFY(input->hasActiveFocus() == false);
1868 simulateKey(canvas, Qt::Key_Right);
1869 QVERIFY(input->hasActiveFocus() == true);
1870 simulateKey(canvas, Qt::Key_Right);
1871 QVERIFY(input->hasActiveFocus() == true);
1872 simulateKey(canvas, Qt::Key_Right);
1873 QVERIFY(input->hasActiveFocus() == false);
1874 simulateKey(canvas, Qt::Key_Left);
1875 QVERIFY(input->hasActiveFocus() == true);
1880 void tst_qdeclarativetextedit::copyAndPaste() {
1881 #ifndef QT_NO_CLIPBOARD
1885 PasteboardRef pasteboard;
1886 OSStatus status = PasteboardCreate(0, &pasteboard);
1887 if (status == noErr)
1888 CFRelease(pasteboard);
1890 QSKIP("This machine doesn't support the clipboard", SkipAll);
1894 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"Hello world!\" }";
1895 QDeclarativeComponent textEditComponent(&engine);
1896 textEditComponent.setData(componentStr.toLatin1(), QUrl());
1897 QDeclarative1TextEdit *textEdit = qobject_cast<QDeclarative1TextEdit*>(textEditComponent.create());
1898 QVERIFY(textEdit != 0);
1901 QCOMPARE(textEdit->text().length(), 12);
1902 textEdit->select(0, textEdit->text().length());;
1904 QCOMPARE(textEdit->selectedText(), QString("Hello world!"));
1905 QCOMPARE(textEdit->selectedText().length(), 12);
1906 textEdit->setCursorPosition(0);
1907 QVERIFY(textEdit->canPaste());
1909 QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
1910 QCOMPARE(textEdit->text().length(), 24);
1913 QVERIFY(textEdit->canPaste());
1914 textEdit->setReadOnly(true);
1915 QVERIFY(!textEdit->canPaste());
1916 textEdit->setReadOnly(false);
1917 QVERIFY(textEdit->canPaste());
1920 // test that document and internal text attribute are in sync
1921 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(textEdit);
1922 QDeclarative1TextEditPrivate *editPrivate = static_cast<QDeclarative1TextEditPrivate*>(pri);
1923 QCOMPARE(textEdit->text(), editPrivate->text);
1926 textEdit->setCursorPosition(0);
1927 textEdit->selectWord();
1928 QCOMPARE(textEdit->selectedText(), QString("Hello"));
1930 // select all and cut
1931 textEdit->selectAll();
1933 QCOMPARE(textEdit->text().length(), 0);
1935 QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
1936 QCOMPARE(textEdit->text().length(), 24);
1940 void tst_qdeclarativetextedit::canPaste() {
1941 #ifndef QT_NO_CLIPBOARD
1943 QApplication::clipboard()->setText("Some text");
1945 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"Hello world!\" }";
1946 QDeclarativeComponent textEditComponent(&engine);
1947 textEditComponent.setData(componentStr.toLatin1(), QUrl());
1948 QDeclarative1TextEdit *textEdit = qobject_cast<QDeclarative1TextEdit*>(textEditComponent.create());
1949 QVERIFY(textEdit != 0);
1951 // check initial value - QTBUG-17765
1953 QCOMPARE(textEdit->canPaste(), tc.canPaste());
1958 void tst_qdeclarativetextedit::canPasteEmpty() {
1959 #ifndef QT_NO_CLIPBOARD
1961 QApplication::clipboard()->clear();
1963 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"Hello world!\" }";
1964 QDeclarativeComponent textEditComponent(&engine);
1965 textEditComponent.setData(componentStr.toLatin1(), QUrl());
1966 QDeclarative1TextEdit *textEdit = qobject_cast<QDeclarative1TextEdit*>(textEditComponent.create());
1967 QVERIFY(textEdit != 0);
1969 // check initial value - QTBUG-17765
1971 QCOMPARE(textEdit->canPaste(), tc.canPaste());
1976 void tst_qdeclarativetextedit::readOnly()
1978 QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml");
1982 QVERIFY(canvas->rootObject() != 0);
1984 QDeclarative1TextEdit *edit = qobject_cast<QDeclarative1TextEdit *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1987 QTRY_VERIFY(edit->hasActiveFocus() == true);
1988 QVERIFY(edit->isReadOnly() == true);
1989 QString initial = edit->text();
1990 for(int k=Qt::Key_0; k<=Qt::Key_Z; k++)
1991 simulateKey(canvas, k);
1992 simulateKey(canvas, Qt::Key_Return);
1993 simulateKey(canvas, Qt::Key_Space);
1994 simulateKey(canvas, Qt::Key_Escape);
1995 QCOMPARE(edit->text(), initial);
2000 void tst_qdeclarativetextedit::simulateKey(QDeclarativeView *view, int key, Qt::KeyboardModifiers modifiers)
2002 QKeyEvent press(QKeyEvent::KeyPress, key, modifiers);
2003 QKeyEvent release(QKeyEvent::KeyRelease, key, modifiers);
2005 QApplication::sendEvent(view, &press);
2006 QApplication::sendEvent(view, &release);
2009 QDeclarativeView *tst_qdeclarativetextedit::createView(const QString &filename)
2011 QDeclarativeView *canvas = new QDeclarativeView(0);
2013 canvas->setSource(QUrl::fromLocalFile(filename));
2017 class MyInputContext : public QInputContext
2020 MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false), updateReceived(false), eventType(QEvent::None) {}
2021 ~MyInputContext() {}
2023 QString identifierName() { return QString(); }
2024 QString language() { return QString(); }
2028 bool isComposing() const { return false; }
2030 bool filterEvent( const QEvent *event )
2032 if (event->type() == QEvent::RequestSoftwareInputPanel)
2033 openInputPanelReceived = true;
2034 if (event->type() == QEvent::CloseSoftwareInputPanel)
2035 closeInputPanelReceived = true;
2036 return QInputContext::filterEvent(event);
2039 void update() { updateReceived = true; }
2041 void sendPreeditText(const QString &text, int cursor)
2043 QList<QInputMethodEvent::Attribute> attributes;
2044 attributes.append(QInputMethodEvent::Attribute(
2045 QInputMethodEvent::Cursor, cursor, text.length(), QVariant()));
2047 QInputMethodEvent event(text, attributes);
2051 void mouseHandler(int x, QMouseEvent *event)
2054 eventType = event->type();
2055 eventPosition = event->pos();
2056 eventGlobalPosition = event->globalPos();
2057 eventButton = event->button();
2058 eventButtons = event->buttons();
2059 eventModifiers = event->modifiers();
2062 bool openInputPanelReceived;
2063 bool closeInputPanelReceived;
2064 bool updateReceived;
2066 QEvent::Type eventType;
2067 QPoint eventPosition;
2068 QPoint eventGlobalPosition;
2069 Qt::MouseButton eventButton;
2070 Qt::MouseButtons eventButtons;
2071 Qt::KeyboardModifiers eventModifiers;
2074 void tst_qdeclarativetextedit::textInput()
2076 QGraphicsScene scene;
2077 QGraphicsView view(&scene);
2078 QDeclarative1TextEdit edit;
2079 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&edit);
2080 QDeclarative1TextEditPrivate *editPrivate = static_cast<QDeclarative1TextEditPrivate*>(pri);
2082 scene.addItem(&edit);
2084 QApplication::setActiveWindow(&view);
2085 QTest::qWaitForWindowShown(&view);
2086 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2087 edit.setFocus(true);
2088 QVERIFY(edit.hasActiveFocus() == true);
2090 // test that input method event is committed
2091 QInputMethodEvent event;
2092 event.setCommitString( "Hello world!", 0, 0);
2093 QApplication::sendEvent(&view, &event);
2094 QCOMPARE(edit.text(), QString("Hello world!"));
2097 // test that document and internal text attribute are in sync
2098 QCOMPARE(editPrivate->text, QString("Hello world!"));
2101 void tst_qdeclarativetextedit::openInputPanelOnClick()
2103 QGraphicsScene scene;
2104 QGraphicsView view(&scene);
2106 view.setInputContext(&ic);
2107 QDeclarative1TextEdit edit;
2108 QSignalSpy focusOnPressSpy(&edit, SIGNAL(activeFocusOnPressChanged(bool)));
2109 edit.setText("Hello world");
2111 scene.addItem(&edit);
2113 qApp->setAutoSipEnabled(true);
2114 QApplication::setActiveWindow(&view);
2115 QTest::qWaitForWindowShown(&view);
2116 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2118 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&edit);
2119 QDeclarative1TextEditPrivate *editPrivate = static_cast<QDeclarative1TextEditPrivate*>(pri);
2121 // input panel on click
2122 editPrivate->showInputPanelOnFocus = false;
2124 QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
2125 view.style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
2126 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2127 QApplication::processEvents();
2128 if (behavior == QStyle::RSIP_OnMouseClickAndAlreadyFocused) {
2129 QCOMPARE(ic.openInputPanelReceived, false);
2130 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2131 QApplication::processEvents();
2132 QCOMPARE(ic.openInputPanelReceived, true);
2133 } else if (behavior == QStyle::RSIP_OnMouseClick) {
2134 QCOMPARE(ic.openInputPanelReceived, true);
2136 ic.openInputPanelReceived = false;
2138 // focus should not cause input panels to open or close
2139 edit.setFocus(false);
2140 edit.setFocus(true);
2141 edit.setFocus(false);
2142 edit.setFocus(true);
2143 edit.setFocus(false);
2144 QApplication::processEvents();
2145 QCOMPARE(ic.openInputPanelReceived, false);
2146 QCOMPARE(ic.closeInputPanelReceived, false);
2149 void tst_qdeclarativetextedit::openInputPanelOnFocus()
2151 QGraphicsScene scene;
2152 QGraphicsView view(&scene);
2154 view.setInputContext(&ic);
2155 QDeclarative1TextEdit edit;
2156 QSignalSpy focusOnPressSpy(&edit, SIGNAL(activeFocusOnPressChanged(bool)));
2157 edit.setText("Hello world");
2159 scene.addItem(&edit);
2161 qApp->setAutoSipEnabled(true);
2162 QApplication::setActiveWindow(&view);
2163 QTest::qWaitForWindowShown(&view);
2164 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2166 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&edit);
2167 QDeclarative1TextEditPrivate *editPrivate = static_cast<QDeclarative1TextEditPrivate*>(pri);
2168 editPrivate->showInputPanelOnFocus = true;
2170 // test default values
2171 QVERIFY(edit.focusOnPress());
2172 QCOMPARE(ic.openInputPanelReceived, false);
2173 QCOMPARE(ic.closeInputPanelReceived, false);
2175 // focus on press, input panel on focus
2176 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2177 QApplication::processEvents();
2178 QVERIFY(edit.hasActiveFocus());
2179 QCOMPARE(ic.openInputPanelReceived, true);
2180 ic.openInputPanelReceived = false;
2182 // no events on release
2183 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2184 QCOMPARE(ic.openInputPanelReceived, false);
2185 ic.openInputPanelReceived = false;
2187 // if already focused, input panel can be opened on press
2188 QVERIFY(edit.hasActiveFocus());
2189 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2190 QApplication::processEvents();
2191 QCOMPARE(ic.openInputPanelReceived, true);
2192 ic.openInputPanelReceived = false;
2194 // input method should stay enabled if focus
2195 // is lost to an item that also accepts inputs
2196 QDeclarative1TextEdit anotherEdit;
2197 scene.addItem(&anotherEdit);
2198 anotherEdit.setFocus(true);
2199 QApplication::processEvents();
2200 QCOMPARE(ic.openInputPanelReceived, true);
2201 ic.openInputPanelReceived = false;
2202 QCOMPARE(view.inputContext(), (QInputContext*)&ic);
2203 QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
2205 // input method should be disabled if focus
2206 // is lost to an item that doesn't accept inputs
2207 QDeclarativeItem item;
2208 scene.addItem(&item);
2209 item.setFocus(true);
2210 QApplication::processEvents();
2211 QCOMPARE(ic.openInputPanelReceived, false);
2212 QVERIFY(view.inputContext() == 0);
2213 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2215 // no automatic input panel events should
2216 // be sent if activeFocusOnPress is false
2217 edit.setFocusOnPress(false);
2218 QCOMPARE(focusOnPressSpy.count(),1);
2219 edit.setFocusOnPress(false);
2220 QCOMPARE(focusOnPressSpy.count(),1);
2221 edit.setFocus(false);
2222 edit.setFocus(true);
2223 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2224 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2225 QApplication::processEvents();
2226 QCOMPARE(ic.openInputPanelReceived, false);
2227 QCOMPARE(ic.closeInputPanelReceived, false);
2229 // one show input panel event should
2230 // be set when openSoftwareInputPanel is called
2231 edit.openSoftwareInputPanel();
2232 QCOMPARE(ic.openInputPanelReceived, true);
2233 QCOMPARE(ic.closeInputPanelReceived, false);
2234 ic.openInputPanelReceived = false;
2236 // one close input panel event should
2237 // be sent when closeSoftwareInputPanel is called
2238 edit.closeSoftwareInputPanel();
2239 QCOMPARE(ic.openInputPanelReceived, false);
2240 QCOMPARE(ic.closeInputPanelReceived, true);
2241 ic.closeInputPanelReceived = false;
2243 // set activeFocusOnPress back to true
2244 edit.setFocusOnPress(true);
2245 QCOMPARE(focusOnPressSpy.count(),2);
2246 edit.setFocusOnPress(true);
2247 QCOMPARE(focusOnPressSpy.count(),2);
2248 edit.setFocus(false);
2249 QApplication::processEvents();
2250 QCOMPARE(ic.openInputPanelReceived, false);
2251 QCOMPARE(ic.closeInputPanelReceived, false);
2252 ic.closeInputPanelReceived = false;
2254 // input panel should not re-open
2255 // if focus has already been set
2256 edit.setFocus(true);
2257 QCOMPARE(ic.openInputPanelReceived, true);
2258 ic.openInputPanelReceived = false;
2259 edit.setFocus(true);
2260 QCOMPARE(ic.openInputPanelReceived, false);
2262 // input method should be disabled
2263 // if TextEdit loses focus
2264 edit.setFocus(false);
2265 QApplication::processEvents();
2266 QVERIFY(view.inputContext() == 0);
2267 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2269 // input method should not be enabled
2270 // if TextEdit is read only.
2271 edit.setReadOnly(true);
2272 ic.openInputPanelReceived = false;
2273 edit.setFocus(true);
2274 QApplication::processEvents();
2275 QCOMPARE(ic.openInputPanelReceived, false);
2276 QVERIFY(view.inputContext() == 0);
2277 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2280 void tst_qdeclarativetextedit::geometrySignals()
2282 QDeclarativeComponent component(&engine, SRCDIR "/data/geometrySignals.qml");
2283 QObject *o = component.create();
2285 QCOMPARE(o->property("bindingWidth").toInt(), 400);
2286 QCOMPARE(o->property("bindingHeight").toInt(), 500);
2290 void tst_qdeclarativetextedit::pastingRichText_QTBUG_14003()
2292 #ifndef QT_NO_CLIPBOARD
2293 QString componentStr = "import QtQuick 1.0\nTextEdit { textFormat: TextEdit.PlainText }";
2294 QDeclarativeComponent component(&engine);
2295 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
2296 QDeclarative1TextEdit *obj = qobject_cast<QDeclarative1TextEdit*>(component.create());
2298 QTRY_VERIFY(obj != 0);
2299 QTRY_VERIFY(obj->textFormat() == QDeclarative1TextEdit::PlainText);
2301 QMimeData *mData = new QMimeData;
2302 mData->setHtml("<font color=\"red\">Hello</font>");
2303 QApplication::clipboard()->setMimeData(mData);
2306 QTRY_VERIFY(obj->text() == "");
2307 QTRY_VERIFY(obj->textFormat() == QDeclarative1TextEdit::PlainText);
2311 void tst_qdeclarativetextedit::implicitSize_data()
2313 QTest::addColumn<QString>("text");
2314 QTest::addColumn<QString>("wrap");
2315 QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap";
2316 QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.NoWrap";
2317 QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap";
2318 QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.Wrap";
2321 void tst_qdeclarativetextedit::implicitSize()
2323 QFETCH(QString, text);
2324 QFETCH(QString, wrap);
2325 QString componentStr = "import QtQuick 1.1\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }";
2326 QDeclarativeComponent textComponent(&engine);
2327 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
2328 QDeclarative1TextEdit *textObject = qobject_cast<QDeclarative1TextEdit*>(textComponent.create());
2330 QVERIFY(textObject->width() < textObject->implicitWidth());
2331 QVERIFY(textObject->height() == textObject->implicitHeight());
2333 textObject->resetWidth();
2334 QVERIFY(textObject->width() == textObject->implicitWidth());
2335 QVERIFY(textObject->height() == textObject->implicitHeight());
2338 void tst_qdeclarativetextedit::testQtQuick11Attributes()
2340 QFETCH(QString, code);
2341 QFETCH(QString, warning);
2342 QFETCH(QString, error);
2344 QDeclarativeEngine engine;
2347 QDeclarativeComponent valid(&engine);
2348 valid.setData("import QtQuick 1.1; TextEdit { " + code.toUtf8() + " }", QUrl(""));
2349 obj = valid.create();
2351 QVERIFY(valid.errorString().isEmpty());
2354 QDeclarativeComponent invalid(&engine);
2355 invalid.setData("import QtQuick 1.0; TextEdit { " + code.toUtf8() + " }", QUrl(""));
2356 QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
2357 obj = invalid.create();
2358 QCOMPARE(invalid.errorString(), error);
2362 void tst_qdeclarativetextedit::testQtQuick11Attributes_data()
2364 QTest::addColumn<QString>("code");
2365 QTest::addColumn<QString>("warning");
2366 QTest::addColumn<QString>("error");
2368 QTest::newRow("canPaste") << "property bool foo: canPaste"
2369 << "<Unknown File>:1: ReferenceError: Can't find variable: canPaste"
2372 QTest::newRow("lineCount") << "property int foo: lineCount"
2373 << "<Unknown File>:1: ReferenceError: Can't find variable: lineCount"
2376 QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)"
2377 << "<Unknown File>:1: ReferenceError: Can't find variable: moveCursorSelection"
2380 QTest::newRow("deselect") << "Component.onCompleted: deselect()"
2381 << "<Unknown File>:1: ReferenceError: Can't find variable: deselect"
2384 QTest::newRow("onLinkActivated") << "onLinkActivated: {}"
2385 << "QDeclarativeComponent: Component is not ready"
2386 << ":1 \"TextEdit.onLinkActivated\" is not available in QtQuick 1.0.\n";
2389 void tst_qdeclarativetextedit::preeditMicroFocus()
2391 QString preeditText = "super";
2393 QGraphicsScene scene;
2394 QGraphicsView view(&scene);
2396 view.setInputContext(&ic);
2397 QDeclarative1TextEdit edit;
2398 edit.setFocus(true);
2399 scene.addItem(&edit);
2401 QApplication::setActiveWindow(&view);
2402 QTest::qWaitForWindowShown(&view);
2403 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2405 QSignalSpy cursorRectangleSpy(&edit, SIGNAL(cursorRectangleChanged()));
2408 QRect previousRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect();
2410 // Verify that the micro focus rect is positioned the same for position 0 as
2411 // it would be if there was no preedit text.
2412 ic.updateReceived = false;
2413 ic.sendPreeditText(preeditText, 0);
2414 currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect();
2415 QCOMPARE(currentRect, previousRect);
2416 #if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
2417 QCOMPARE(ic.updateReceived, false); // The cursor position hasn't changed.
2419 QCOMPARE(cursorRectangleSpy.count(), 0);
2421 // Verify that the micro focus rect moves to the left as the cursor position
2423 for (int i = 1; i <= 5; ++i) {
2424 ic.updateReceived = false;
2425 ic.sendPreeditText(preeditText, i);
2426 currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect();
2427 QVERIFY(previousRect.left() < currentRect.left());
2428 #if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
2429 QCOMPARE(ic.updateReceived, true);
2431 QVERIFY(cursorRectangleSpy.count() > 0);
2432 cursorRectangleSpy.clear();
2433 previousRect = currentRect;
2436 // Verify that if there is no preedit cursor then the micro focus rect is the
2437 // same as it would be if it were positioned at the end of the preedit text.
2438 ic.sendPreeditText(preeditText, 0);
2439 ic.updateReceived = false;
2440 ic.sendEvent(QInputMethodEvent(preeditText, QList<QInputMethodEvent::Attribute>()));
2441 currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect();
2442 QCOMPARE(currentRect, previousRect);
2443 #if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
2444 QCOMPARE(ic.updateReceived, true);
2446 QVERIFY(cursorRectangleSpy.count() > 0);
2449 void tst_qdeclarativetextedit::inputContextMouseHandler()
2451 QString text = "supercalifragisiticexpialidocious!";
2453 QGraphicsScene scene;
2454 QGraphicsView view(&scene);
2456 view.setInputContext(&ic);
2457 QDeclarative1TextEdit edit;
2460 edit.setText(text.mid(0, 12));
2462 edit.setCursorPosition(12);
2463 edit.setFocus(true);
2464 scene.addItem(&edit);
2466 QApplication::setActiveWindow(&view);
2467 QTest::qWaitForWindowShown(&view);
2468 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2471 QFontMetricsF fm(edit.font());
2472 const qreal y = fm.height() / 2;
2474 QPoint position2 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 2)), y)));
2475 QPoint position8 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 8)), y)));
2476 QPoint position20 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 20)), y)));
2477 QPoint position27 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 27)), y)));
2478 QPoint globalPosition2 = view.viewport()->mapToGlobal(position2);
2479 QPoint globalposition8 = view.viewport()->mapToGlobal(position8);
2480 QPoint globalposition20 = view.viewport()->mapToGlobal(position20);
2481 QPoint globalposition27 = view.viewport()->mapToGlobal(position27);
2483 ic.sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>()));
2485 QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
2486 QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick);
2487 QCOMPARE(ic.eventPosition, position2);
2488 QCOMPARE(ic.eventGlobalPosition, globalPosition2);
2489 QCOMPARE(ic.eventButton, Qt::LeftButton);
2490 QCOMPARE(ic.eventModifiers, Qt::NoModifier);
2491 QVERIFY(ic.cursor < 0);
2492 ic.eventType = QEvent::None;
2494 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
2495 QCOMPARE(ic.eventType, QEvent::MouseButtonPress);
2496 QCOMPARE(ic.eventPosition, position2);
2497 QCOMPARE(ic.eventGlobalPosition, globalPosition2);
2498 QCOMPARE(ic.eventButton, Qt::LeftButton);
2499 QCOMPARE(ic.eventModifiers, Qt::NoModifier);
2500 QVERIFY(ic.cursor < 0);
2501 ic.eventType = QEvent::None;
2503 { QMouseEvent mv(QEvent::MouseMove, position8, globalposition8, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
2504 QApplication::sendEvent(view.viewport(), &mv); }
2505 QCOMPARE(ic.eventType, QEvent::None);
2507 { QMouseEvent mv(QEvent::MouseMove, position27, globalposition27, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
2508 QApplication::sendEvent(view.viewport(), &mv); }
2509 QCOMPARE(ic.eventType, QEvent::MouseMove);
2510 QCOMPARE(ic.eventPosition, position27);
2511 QCOMPARE(ic.eventGlobalPosition, globalposition27);
2512 QCOMPARE(ic.eventButton, Qt::LeftButton);
2513 QCOMPARE(ic.eventModifiers, Qt::NoModifier);
2514 QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); // 15 is expected but some platforms may be off by one.
2515 ic.eventType = QEvent::None;
2517 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position27);
2518 QCOMPARE(ic.eventType, QEvent::MouseButtonRelease);
2519 QCOMPARE(ic.eventPosition, position27);
2520 QCOMPARE(ic.eventGlobalPosition, globalposition27);
2521 QCOMPARE(ic.eventButton, Qt::LeftButton);
2522 QCOMPARE(ic.eventModifiers, Qt::NoModifier);
2523 QVERIFY(ic.cursor >= 14 && ic.cursor <= 16);
2524 ic.eventType = QEvent::None;
2526 // And in the other direction.
2527 QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, position27);
2528 QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick);
2529 QCOMPARE(ic.eventPosition, position27);
2530 QCOMPARE(ic.eventGlobalPosition, globalposition27);
2531 QCOMPARE(ic.eventButton, Qt::LeftButton);
2532 QCOMPARE(ic.eventModifiers, Qt::ControlModifier);
2533 QVERIFY(ic.cursor >= 14 && ic.cursor <= 16);
2534 ic.eventType = QEvent::None;
2536 QTest::mousePress(view.viewport(), Qt::RightButton, Qt::ControlModifier, position27);
2537 QCOMPARE(ic.eventType, QEvent::MouseButtonPress);
2538 QCOMPARE(ic.eventPosition, position27);
2539 QCOMPARE(ic.eventGlobalPosition, globalposition27);
2540 QCOMPARE(ic.eventButton, Qt::RightButton);
2541 QCOMPARE(ic.eventModifiers, Qt::ControlModifier);
2542 QVERIFY(ic.cursor >= 14 && ic.cursor <= 16);
2543 ic.eventType = QEvent::None;
2545 { QMouseEvent mv(QEvent::MouseMove, position20, globalposition20, Qt::RightButton, Qt::RightButton,Qt::ControlModifier);
2546 QApplication::sendEvent(view.viewport(), &mv); }
2547 QCOMPARE(ic.eventType, QEvent::MouseMove);
2548 QCOMPARE(ic.eventPosition, position20);
2549 QCOMPARE(ic.eventGlobalPosition, globalposition20);
2550 QCOMPARE(ic.eventButton, Qt::RightButton);
2551 QCOMPARE(ic.eventModifiers, Qt::ControlModifier);
2552 QVERIFY(ic.cursor >= 7 && ic.cursor <= 9);
2553 ic.eventType = QEvent::None;
2555 { QMouseEvent mv(QEvent::MouseMove, position2, globalPosition2, Qt::RightButton, Qt::RightButton,Qt::ControlModifier);
2556 QApplication::sendEvent(view.viewport(), &mv); }
2557 QCOMPARE(ic.eventType, QEvent::None);
2559 QTest::mouseRelease(view.viewport(), Qt::RightButton, Qt::ControlModifier, position2);
2560 QCOMPARE(ic.eventType, QEvent::MouseButtonRelease);
2561 QCOMPARE(ic.eventPosition, position2);
2562 QCOMPARE(ic.eventGlobalPosition, globalPosition2);
2563 QCOMPARE(ic.eventButton, Qt::RightButton);
2564 QCOMPARE(ic.eventModifiers, Qt::ControlModifier);
2565 QVERIFY(ic.cursor < 0);
2566 ic.eventType = QEvent::None;
2569 void tst_qdeclarativetextedit::inputMethodComposing()
2571 QString text = "supercalifragisiticexpialidocious!";
2573 QGraphicsScene scene;
2574 QGraphicsView view(&scene);
2576 view.setInputContext(&ic);
2577 QDeclarative1TextEdit edit;
2579 edit.setText(text.mid(0, 12));
2580 edit.setCursorPosition(12);
2582 edit.setFocus(true);
2583 scene.addItem(&edit);
2585 QApplication::setActiveWindow(&view);
2586 QTest::qWaitForWindowShown(&view);
2587 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2589 QSignalSpy spy(&edit, SIGNAL(inputMethodComposingChanged()));
2591 QCOMPARE(edit.isInputMethodComposing(), false);
2593 ic.sendEvent(QInputMethodEvent(text.mid(3), QList<QInputMethodEvent::Attribute>()));
2594 QCOMPARE(edit.isInputMethodComposing(), true);
2595 QCOMPARE(spy.count(), 1);
2597 ic.sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>()));
2598 QCOMPARE(edit.isInputMethodComposing(), true);
2599 QCOMPARE(spy.count(), 1);
2601 ic.sendEvent(QInputMethodEvent());
2602 QCOMPARE(edit.isInputMethodComposing(), false);
2603 QCOMPARE(spy.count(), 2);
2606 void tst_qdeclarativetextedit::cursorRectangleSize()
2608 QDeclarativeView *canvas = createView(SRCDIR "/data/CursorRect.qml");
2609 QVERIFY(canvas->rootObject() != 0);
2612 QApplication::setActiveWindow(canvas);
2613 QTest::qWaitForWindowShown(canvas);
2615 QDeclarative1TextEdit *textEdit = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
2616 QVERIFY(textEdit != 0);
2617 textEdit->setFocus(Qt::OtherFocusReason);
2618 QRectF cursorRect = textEdit->positionToRectangle(textEdit->cursorPosition());
2619 QRectF microFocusFromScene = canvas->scene()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
2620 QRectF microFocusFromApp= QApplication::focusWidget()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
2622 QCOMPARE(microFocusFromScene.size(), cursorRect.size());
2623 QCOMPARE(microFocusFromApp.size(), cursorRect.size());
2625 QTEST_MAIN(tst_qdeclarativetextedit)
2627 #include "tst_qdeclarativetextedit.moc"