1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
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 <QtDeclarative/qdeclarativeengine.h>
45 #include <QtQuick1/qdeclarativeview.h>
46 #include <QtQuick1/private/qdeclarativetextinput_p.h>
47 #include <QtQuick1/private/qdeclarativetextinput_p_p.h>
51 #include <QtCore/qmath.h>
52 #include <private/qapplication_p.h>
53 #include <private/qinputpanel_p.h>
54 #include "../../shared/platforminputcontext.h"
56 #include "qplatformdefs.h"
58 Q_DECLARE_METATYPE(QDeclarative1TextInput::SelectionMode)
60 QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
62 // XXX This will be replaced by some clever persistent platform image store.
63 QString persistent_dir = SRCDIR "/data";
64 QString arch = "unknown-architecture"; // QTest needs to help with this.
66 QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png";
68 if (!QFile::exists(expectfile)) {
69 actual.save(expectfile);
70 qWarning() << "created" << expectfile;
76 void sendPreeditText(const QString &text, int cursor)
78 QList<QInputMethodEvent::Attribute> attributes;
79 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursor,
80 text.length(), QVariant()));
81 QInputMethodEvent event(text, attributes);
82 QApplication::sendEvent(qApp->inputPanel()->inputItem(), &event);
86 class tst_qdeclarativetextinput : public QObject
91 tst_qdeclarativetextinput();
101 void isRightToLeft_data();
102 void isRightToLeft();
103 void moveCursorSelection_data();
104 void moveCursorSelection();
105 void moveCursorSelectionSequence_data();
106 void moveCursorSelectionSequence();
107 void mouseSelection_data();
108 void mouseSelection();
109 void deferEnableSelectByMouse_data();
110 void deferEnableSelectByMouse();
111 void deferDisableSelectByMouse_data();
112 void deferDisableSelectByMouse();
113 void dragMouseSelection();
114 void mouseSelectionMode_data();
115 void mouseSelectionMode();
117 void horizontalAlignment_data();
118 void horizontalAlignment();
119 void horizontalAlignment_RightToLeft();
128 void passwordCharacter();
129 void cursorDelegate();
130 void cursorVisible();
131 void cursorRectangle();
133 void navigation_RTL();
135 void canPasteEmpty();
139 void openInputPanelOnClick();
140 void openInputPanelOnFocus();
141 void setHAlignClearCache();
142 void focusOutClearSelection();
145 #ifdef QT_GUI_PASSWORD_ECHO_DELAY
146 void passwordEchoDelay();
148 void geometrySignals();
149 void testQtQuick11Attributes();
150 void testQtQuick11Attributes_data();
152 void preeditAutoScroll();
153 void preeditMicroFocus();
154 void inputContextMouseHandler();
155 void inputMethodComposing();
156 void cursorRectangleSize();
159 void simulateKey(QDeclarativeView *, int key);
160 QDeclarativeView *createView(const QString &filename);
162 QDeclarativeEngine engine;
163 QStringList standard;
164 QStringList colorStrings;
168 tst_qdeclarativetextinput::tst_qdeclarativetextinput()
170 standard << "the quick brown fox jumped over the lazy dog"
171 << "It's supercalifragisiticexpialidocious!"
176 colorStrings << "aliceblue"
190 void tst_qdeclarativetextinput::cleanup()
192 // ensure not even skipped tests with custom input context leave it dangling
193 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
194 inputPanelPrivate->testContext = 0;
197 void tst_qdeclarativetextinput::text()
200 QDeclarativeComponent textinputComponent(&engine);
201 textinputComponent.setData("import QtQuick 1.0\nTextInput { text: \"\" }", QUrl());
202 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
204 QVERIFY(textinputObject != 0);
205 QCOMPARE(textinputObject->text(), QString(""));
207 delete textinputObject;
210 for (int i = 0; i < standard.size(); i++)
212 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"" + standard.at(i) + "\" }";
213 QDeclarativeComponent textinputComponent(&engine);
214 textinputComponent.setData(componentStr.toLatin1(), QUrl());
215 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
217 QVERIFY(textinputObject != 0);
218 QCOMPARE(textinputObject->text(), standard.at(i));
220 delete textinputObject;
225 void tst_qdeclarativetextinput::width()
227 // uses Font metrics to find the width for standard
229 QDeclarativeComponent textinputComponent(&engine);
230 textinputComponent.setData("import QtQuick 1.0\nTextInput { text: \"\" }", QUrl());
231 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
233 QVERIFY(textinputObject != 0);
234 QCOMPARE(textinputObject->width(), 0.0);
236 delete textinputObject;
239 for (int i = 0; i < standard.size(); i++)
243 qreal metricWidth = fm.width(standard.at(i));
245 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"" + standard.at(i) + "\" }";
246 QDeclarativeComponent textinputComponent(&engine);
247 textinputComponent.setData(componentStr.toLatin1(), QUrl());
248 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
250 QVERIFY(textinputObject != 0);
251 int delta = abs(int(int(textinputObject->width()) - metricWidth));
252 QVERIFY(delta <= 3.0); // As best as we can hope for cross-platform.
254 delete textinputObject;
258 void tst_qdeclarativetextinput::font()
260 //test size, then bold, then italic, then family
262 QString componentStr = "import QtQuick 1.0\nTextInput { font.pointSize: 40; text: \"Hello World\" }";
263 QDeclarativeComponent textinputComponent(&engine);
264 textinputComponent.setData(componentStr.toLatin1(), QUrl());
265 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
267 QVERIFY(textinputObject != 0);
268 QCOMPARE(textinputObject->font().pointSize(), 40);
269 QCOMPARE(textinputObject->font().bold(), false);
270 QCOMPARE(textinputObject->font().italic(), false);
272 delete textinputObject;
276 QString componentStr = "import QtQuick 1.0\nTextInput { font.bold: true; text: \"Hello World\" }";
277 QDeclarativeComponent textinputComponent(&engine);
278 textinputComponent.setData(componentStr.toLatin1(), QUrl());
279 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
281 QVERIFY(textinputObject != 0);
282 QCOMPARE(textinputObject->font().bold(), true);
283 QCOMPARE(textinputObject->font().italic(), false);
285 delete textinputObject;
289 QString componentStr = "import QtQuick 1.0\nTextInput { font.italic: true; text: \"Hello World\" }";
290 QDeclarativeComponent textinputComponent(&engine);
291 textinputComponent.setData(componentStr.toLatin1(), QUrl());
292 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
294 QVERIFY(textinputObject != 0);
295 QCOMPARE(textinputObject->font().italic(), true);
296 QCOMPARE(textinputObject->font().bold(), false);
298 delete textinputObject;
302 QString componentStr = "import QtQuick 1.0\nTextInput { font.family: \"Helvetica\"; text: \"Hello World\" }";
303 QDeclarativeComponent textinputComponent(&engine);
304 textinputComponent.setData(componentStr.toLatin1(), QUrl());
305 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
307 QVERIFY(textinputObject != 0);
308 QCOMPARE(textinputObject->font().family(), QString("Helvetica"));
309 QCOMPARE(textinputObject->font().bold(), false);
310 QCOMPARE(textinputObject->font().italic(), false);
312 delete textinputObject;
316 QString componentStr = "import QtQuick 1.0\nTextInput { font.family: \"\"; text: \"Hello World\" }";
317 QDeclarativeComponent textinputComponent(&engine);
318 textinputComponent.setData(componentStr.toLatin1(), QUrl());
319 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
321 QVERIFY(textinputObject != 0);
322 QCOMPARE(textinputObject->font().family(), QString(""));
324 delete textinputObject;
328 void tst_qdeclarativetextinput::color()
331 for (int i = 0; i < colorStrings.size(); i++)
333 QString componentStr = "import QtQuick 1.0\nTextInput { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
334 QDeclarativeComponent textinputComponent(&engine);
335 textinputComponent.setData(componentStr.toLatin1(), QUrl());
336 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
337 QVERIFY(textinputObject != 0);
338 QCOMPARE(textinputObject->color(), QColor(colorStrings.at(i)));
340 delete textinputObject;
343 //test selection color
344 for (int i = 0; i < colorStrings.size(); i++)
346 QString componentStr = "import QtQuick 1.0\nTextInput { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
347 QDeclarativeComponent textinputComponent(&engine);
348 textinputComponent.setData(componentStr.toLatin1(), QUrl());
349 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
350 QVERIFY(textinputObject != 0);
351 QCOMPARE(textinputObject->selectionColor(), QColor(colorStrings.at(i)));
353 delete textinputObject;
356 //test selected text color
357 for (int i = 0; i < colorStrings.size(); i++)
359 QString componentStr = "import QtQuick 1.0\nTextInput { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
360 QDeclarativeComponent textinputComponent(&engine);
361 textinputComponent.setData(componentStr.toLatin1(), QUrl());
362 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
363 QVERIFY(textinputObject != 0);
364 QCOMPARE(textinputObject->selectedTextColor(), QColor(colorStrings.at(i)));
366 delete textinputObject;
370 QString colorStr = "#AA001234";
371 QColor testColor("#001234");
372 testColor.setAlpha(170);
374 QString componentStr = "import QtQuick 1.0\nTextInput { color: \"" + colorStr + "\"; text: \"Hello World\" }";
375 QDeclarativeComponent textinputComponent(&engine);
376 textinputComponent.setData(componentStr.toLatin1(), QUrl());
377 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
379 QVERIFY(textinputObject != 0);
380 QCOMPARE(textinputObject->color(), testColor);
382 delete textinputObject;
386 void tst_qdeclarativetextinput::selection()
388 QString testStr = standard[0];
389 QString componentStr = "import QtQuick 1.0\nTextInput { text: \""+ testStr +"\"; }";
390 QDeclarativeComponent textinputComponent(&engine);
391 textinputComponent.setData(componentStr.toLatin1(), QUrl());
392 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
393 QVERIFY(textinputObject != 0);
396 //Test selection follows cursor
397 for(int i=0; i<= testStr.size(); i++) {
398 textinputObject->setCursorPosition(i);
399 QCOMPARE(textinputObject->cursorPosition(), i);
400 QCOMPARE(textinputObject->selectionStart(), i);
401 QCOMPARE(textinputObject->selectionEnd(), i);
402 QVERIFY(textinputObject->selectedText().isNull());
404 //Test cursor follows selection
405 for(int i=0; i<= testStr.size(); i++) {
406 textinputObject->select(i,i);
407 QCOMPARE(textinputObject->cursorPosition(), i);
408 QCOMPARE(textinputObject->selectionStart(), i);
409 QCOMPARE(textinputObject->selectionEnd(), i);
412 textinputObject->setCursorPosition(0);
413 QVERIFY(textinputObject->cursorPosition() == 0);
414 QVERIFY(textinputObject->selectionStart() == 0);
415 QVERIFY(textinputObject->selectionEnd() == 0);
416 QVERIFY(textinputObject->selectedText().isNull());
418 // Verify invalid positions are ignored.
419 textinputObject->setCursorPosition(-1);
420 QVERIFY(textinputObject->cursorPosition() == 0);
421 QVERIFY(textinputObject->selectionStart() == 0);
422 QVERIFY(textinputObject->selectionEnd() == 0);
423 QVERIFY(textinputObject->selectedText().isNull());
425 textinputObject->setCursorPosition(textinputObject->text().count()+1);
426 QVERIFY(textinputObject->cursorPosition() == 0);
427 QVERIFY(textinputObject->selectionStart() == 0);
428 QVERIFY(textinputObject->selectionEnd() == 0);
429 QVERIFY(textinputObject->selectedText().isNull());
432 for(int i=0; i<= testStr.size(); i++) {
433 textinputObject->select(0,i);
434 QCOMPARE(testStr.mid(0,i), textinputObject->selectedText());
435 QCOMPARE(textinputObject->cursorPosition(), i);
437 for(int i=0; i<= testStr.size(); i++) {
438 textinputObject->select(i,testStr.size());
439 QCOMPARE(testStr.mid(i,testStr.size()-i), textinputObject->selectedText());
440 QCOMPARE(textinputObject->cursorPosition(), testStr.size());
443 textinputObject->setCursorPosition(0);
444 QVERIFY(textinputObject->cursorPosition() == 0);
445 QVERIFY(textinputObject->selectionStart() == 0);
446 QVERIFY(textinputObject->selectionEnd() == 0);
447 QVERIFY(textinputObject->selectedText().isNull());
449 //Test Error Ignoring behaviour
450 textinputObject->setCursorPosition(0);
451 QVERIFY(textinputObject->selectedText().isNull());
452 textinputObject->select(-10,0);
453 QVERIFY(textinputObject->selectedText().isNull());
454 textinputObject->select(100,110);
455 QVERIFY(textinputObject->selectedText().isNull());
456 textinputObject->select(0,-10);
457 QVERIFY(textinputObject->selectedText().isNull());
458 textinputObject->select(0,100);
459 QVERIFY(textinputObject->selectedText().isNull());
460 textinputObject->select(0,10);
461 QVERIFY(textinputObject->selectedText().size() == 10);
462 textinputObject->select(-10,10);
463 QVERIFY(textinputObject->selectedText().size() == 10);
464 textinputObject->select(100,101);
465 QVERIFY(textinputObject->selectedText().size() == 10);
466 textinputObject->select(0,-10);
467 QVERIFY(textinputObject->selectedText().size() == 10);
468 textinputObject->select(0,100);
469 QVERIFY(textinputObject->selectedText().size() == 10);
471 textinputObject->deselect();
472 QVERIFY(textinputObject->selectedText().isNull());
473 textinputObject->select(0,10);
474 QVERIFY(textinputObject->selectedText().size() == 10);
475 textinputObject->deselect();
476 QVERIFY(textinputObject->selectedText().isNull());
478 delete textinputObject;
481 void tst_qdeclarativetextinput::isRightToLeft_data()
483 QTest::addColumn<QString>("text");
484 QTest::addColumn<bool>("emptyString");
485 QTest::addColumn<bool>("firstCharacter");
486 QTest::addColumn<bool>("lastCharacter");
487 QTest::addColumn<bool>("middleCharacter");
488 QTest::addColumn<bool>("startString");
489 QTest::addColumn<bool>("midString");
490 QTest::addColumn<bool>("endString");
492 const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
493 QTest::newRow("Empty") << "" << false << false << false << false << false << false << false;
494 QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false;
495 QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false;
496 QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true;
497 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;
498 QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false;
501 void tst_qdeclarativetextinput::isRightToLeft()
503 QFETCH(QString, text);
504 QFETCH(bool, emptyString);
505 QFETCH(bool, firstCharacter);
506 QFETCH(bool, lastCharacter);
507 QFETCH(bool, middleCharacter);
508 QFETCH(bool, startString);
509 QFETCH(bool, midString);
510 QFETCH(bool, endString);
512 QDeclarative1TextInput textInput;
513 textInput.setText(text);
515 // first test that the right string is delivered to the QString::isRightToLeft()
516 QCOMPARE(textInput.isRightToLeft(0,0), text.mid(0,0).isRightToLeft());
517 QCOMPARE(textInput.isRightToLeft(0,1), text.mid(0,1).isRightToLeft());
518 QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft());
519 QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft());
520 QCOMPARE(textInput.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft());
521 QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft());
523 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
524 QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft());
526 // then test that the feature actually works
527 QCOMPARE(textInput.isRightToLeft(0,0), emptyString);
528 QCOMPARE(textInput.isRightToLeft(0,1), firstCharacter);
529 QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), lastCharacter);
530 QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter);
531 QCOMPARE(textInput.isRightToLeft(0,text.count()/4), startString);
532 QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), midString);
534 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
535 QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), endString);
538 void tst_qdeclarativetextinput::moveCursorSelection_data()
540 QTest::addColumn<QString>("testStr");
541 QTest::addColumn<int>("cursorPosition");
542 QTest::addColumn<int>("movePosition");
543 QTest::addColumn<QDeclarative1TextInput::SelectionMode>("mode");
544 QTest::addColumn<int>("selectionStart");
545 QTest::addColumn<int>("selectionEnd");
546 QTest::addColumn<bool>("reversible");
548 // () contains the text selected by the cursor.
549 // <> contains the actual selection.
551 QTest::newRow("(t)he|characters")
552 << standard[0] << 0 << 1 << QDeclarative1TextInput::SelectCharacters << 0 << 1 << true;
553 QTest::newRow("do(g)|characters")
554 << standard[0] << 43 << 44 << QDeclarative1TextInput::SelectCharacters << 43 << 44 << true;
555 QTest::newRow("jum(p)ed|characters")
556 << standard[0] << 23 << 24 << QDeclarative1TextInput::SelectCharacters << 23 << 24 << true;
557 QTest::newRow("jumped( )over|characters")
558 << standard[0] << 26 << 27 << QDeclarative1TextInput::SelectCharacters << 26 << 27 << true;
559 QTest::newRow("(the )|characters")
560 << standard[0] << 0 << 4 << QDeclarative1TextInput::SelectCharacters << 0 << 4 << true;
561 QTest::newRow("( dog)|characters")
562 << standard[0] << 40 << 44 << QDeclarative1TextInput::SelectCharacters << 40 << 44 << true;
563 QTest::newRow("( jumped )|characters")
564 << standard[0] << 19 << 27 << QDeclarative1TextInput::SelectCharacters << 19 << 27 << true;
565 QTest::newRow("th(e qu)ick|characters")
566 << standard[0] << 2 << 6 << QDeclarative1TextInput::SelectCharacters << 2 << 6 << true;
567 QTest::newRow("la(zy d)og|characters")
568 << standard[0] << 38 << 42 << QDeclarative1TextInput::SelectCharacters << 38 << 42 << true;
569 QTest::newRow("jum(ped ov)er|characters")
570 << standard[0] << 23 << 29 << QDeclarative1TextInput::SelectCharacters << 23 << 29 << true;
571 QTest::newRow("()the|characters")
572 << standard[0] << 0 << 0 << QDeclarative1TextInput::SelectCharacters << 0 << 0 << true;
573 QTest::newRow("dog()|characters")
574 << standard[0] << 44 << 44 << QDeclarative1TextInput::SelectCharacters << 44 << 44 << true;
575 QTest::newRow("jum()ped|characters")
576 << standard[0] << 23 << 23 << QDeclarative1TextInput::SelectCharacters << 23 << 23 << true;
578 QTest::newRow("<(t)he>|words")
579 << standard[0] << 0 << 1 << QDeclarative1TextInput::SelectWords << 0 << 3 << true;
580 QTest::newRow("<do(g)>|words")
581 << standard[0] << 43 << 44 << QDeclarative1TextInput::SelectWords << 41 << 44 << true;
582 QTest::newRow("<jum(p)ed>|words")
583 << standard[0] << 23 << 24 << QDeclarative1TextInput::SelectWords << 20 << 26 << true;
584 QTest::newRow("<jumped( )>over|words,ltr")
585 << standard[0] << 26 << 27 << QDeclarative1TextInput::SelectWords << 20 << 27 << false;
586 QTest::newRow("jumped<( )over>|words,rtl")
587 << standard[0] << 27 << 26 << QDeclarative1TextInput::SelectWords << 26 << 31 << false;
588 QTest::newRow("<(the )>quick|words,ltr")
589 << standard[0] << 0 << 4 << QDeclarative1TextInput::SelectWords << 0 << 4 << false;
590 QTest::newRow("<(the )quick>|words,rtl")
591 << standard[0] << 4 << 0 << QDeclarative1TextInput::SelectWords << 0 << 9 << false;
592 QTest::newRow("<lazy( dog)>|words,ltr")
593 << standard[0] << 40 << 44 << QDeclarative1TextInput::SelectWords << 36 << 44 << false;
594 QTest::newRow("lazy<( dog)>|words,rtl")
595 << standard[0] << 44 << 40 << QDeclarative1TextInput::SelectWords << 40 << 44 << false;
596 QTest::newRow("<fox( jumped )>over|words,ltr")
597 << standard[0] << 19 << 27 << QDeclarative1TextInput::SelectWords << 16 << 27 << false;
598 QTest::newRow("fox<( jumped )over>|words,rtl")
599 << standard[0] << 27 << 19 << QDeclarative1TextInput::SelectWords << 19 << 31 << false;
600 QTest::newRow("<th(e qu)ick>|words")
601 << standard[0] << 2 << 6 << QDeclarative1TextInput::SelectWords << 0 << 9 << true;
602 QTest::newRow("<la(zy d)og|words>")
603 << standard[0] << 38 << 42 << QDeclarative1TextInput::SelectWords << 36 << 44 << true;
604 QTest::newRow("<jum(ped ov)er>|words")
605 << standard[0] << 23 << 29 << QDeclarative1TextInput::SelectWords << 20 << 31 << true;
606 QTest::newRow("<()>the|words")
607 << standard[0] << 0 << 0 << QDeclarative1TextInput::SelectWords << 0 << 0 << true;
608 QTest::newRow("dog<()>|words")
609 << standard[0] << 44 << 44 << QDeclarative1TextInput::SelectWords << 44 << 44 << true;
610 QTest::newRow("jum<()>ped|words")
611 << standard[0] << 23 << 23 << QDeclarative1TextInput::SelectWords << 23 << 23 << true;
613 QTest::newRow("Hello<(,)> |words")
614 << standard[2] << 5 << 6 << QDeclarative1TextInput::SelectWords << 5 << 6 << true;
615 QTest::newRow("Hello<(, )>world|words,ltr")
616 << standard[2] << 5 << 7 << QDeclarative1TextInput::SelectWords << 5 << 7 << false;
617 QTest::newRow("Hello<(, )world>|words,rtl")
618 << standard[2] << 7 << 5 << QDeclarative1TextInput::SelectWords << 5 << 12 << false;
619 QTest::newRow("<Hel(lo, )>world|words,ltr")
620 << standard[2] << 3 << 7 << QDeclarative1TextInput::SelectWords << 0 << 7 << false;
621 QTest::newRow("<Hel(lo, )world>|words,rtl")
622 << standard[2] << 7 << 3 << QDeclarative1TextInput::SelectWords << 0 << 12 << false;
623 QTest::newRow("<Hel(lo)>,|words")
624 << standard[2] << 3 << 5 << QDeclarative1TextInput::SelectWords << 0 << 5 << true;
625 QTest::newRow("Hello<()>,|words")
626 << standard[2] << 5 << 5 << QDeclarative1TextInput::SelectWords << 5 << 5 << true;
627 QTest::newRow("Hello,<()>|words")
628 << standard[2] << 6 << 6 << QDeclarative1TextInput::SelectWords << 6 << 6 << true;
629 QTest::newRow("Hello<,( )>world|words,ltr")
630 << standard[2] << 6 << 7 << QDeclarative1TextInput::SelectWords << 5 << 7 << false;
631 QTest::newRow("Hello,<( )world>|words,rtl")
632 << standard[2] << 7 << 6 << QDeclarative1TextInput::SelectWords << 6 << 12 << false;
633 QTest::newRow("Hello<,( world)>|words,ltr")
634 << standard[2] << 6 << 12 << QDeclarative1TextInput::SelectWords << 5 << 12 << false;
635 QTest::newRow("Hello,<( world)>|words,rtl")
636 << standard[2] << 12 << 6 << QDeclarative1TextInput::SelectWords << 6 << 12 << false;
637 QTest::newRow("Hello<,( world!)>|words,ltr")
638 << standard[2] << 6 << 13 << QDeclarative1TextInput::SelectWords << 5 << 13 << false;
639 QTest::newRow("Hello,<( world!)>|words,rtl")
640 << standard[2] << 13 << 6 << QDeclarative1TextInput::SelectWords << 6 << 13 << false;
641 QTest::newRow("Hello<(, world!)>|words")
642 << standard[2] << 5 << 13 << QDeclarative1TextInput::SelectWords << 5 << 13 << true;
643 QTest::newRow("world<(!)>|words")
644 << standard[2] << 12 << 13 << QDeclarative1TextInput::SelectWords << 12 << 13 << true;
645 QTest::newRow("world!<()>)|words")
646 << standard[2] << 13 << 13 << QDeclarative1TextInput::SelectWords << 13 << 13 << true;
647 QTest::newRow("world<()>!)|words")
648 << standard[2] << 12 << 12 << QDeclarative1TextInput::SelectWords << 12 << 12 << true;
650 QTest::newRow("<(,)>olleH |words")
651 << standard[3] << 7 << 8 << QDeclarative1TextInput::SelectWords << 7 << 8 << true;
652 QTest::newRow("<dlrow( ,)>olleH|words,ltr")
653 << standard[3] << 6 << 8 << QDeclarative1TextInput::SelectWords << 1 << 8 << false;
654 QTest::newRow("dlrow<( ,)>olleH|words,rtl")
655 << standard[3] << 8 << 6 << QDeclarative1TextInput::SelectWords << 6 << 8 << false;
656 QTest::newRow("<dlrow( ,ol)leH>|words,ltr")
657 << standard[3] << 6 << 10 << QDeclarative1TextInput::SelectWords << 1 << 13 << false;
658 QTest::newRow("dlrow<( ,ol)leH>|words,rtl")
659 << standard[3] << 10 << 6 << QDeclarative1TextInput::SelectWords << 6 << 13 << false;
660 QTest::newRow(",<(ol)leH>,|words")
661 << standard[3] << 8 << 10 << QDeclarative1TextInput::SelectWords << 8 << 13 << true;
662 QTest::newRow(",<()>olleH|words")
663 << standard[3] << 8 << 8 << QDeclarative1TextInput::SelectWords << 8 << 8 << true;
664 QTest::newRow("<()>,olleH|words")
665 << standard[3] << 7 << 7 << QDeclarative1TextInput::SelectWords << 7 << 7 << true;
666 QTest::newRow("<dlrow( )>,olleH|words,ltr")
667 << standard[3] << 6 << 7 << QDeclarative1TextInput::SelectWords << 1 << 7 << false;
668 QTest::newRow("dlrow<( ),>olleH|words,rtl")
669 << standard[3] << 7 << 6 << QDeclarative1TextInput::SelectWords << 6 << 8 << false;
670 QTest::newRow("<(dlrow )>,olleH|words,ltr")
671 << standard[3] << 1 << 7 << QDeclarative1TextInput::SelectWords << 1 << 7 << false;
672 QTest::newRow("<(dlrow ),>olleH|words,rtl")
673 << standard[3] << 7 << 1 << QDeclarative1TextInput::SelectWords << 1 << 8 << false;
674 QTest::newRow("<(!dlrow )>,olleH|words,ltr")
675 << standard[3] << 0 << 7 << QDeclarative1TextInput::SelectWords << 0 << 7 << false;
676 QTest::newRow("<(!dlrow ),>olleH|words,rtl")
677 << standard[3] << 7 << 0 << QDeclarative1TextInput::SelectWords << 0 << 8 << false;
678 QTest::newRow("(!dlrow ,)olleH|words")
679 << standard[3] << 0 << 8 << QDeclarative1TextInput::SelectWords << 0 << 8 << true;
680 QTest::newRow("<(!)>dlrow|words")
681 << standard[3] << 0 << 1 << QDeclarative1TextInput::SelectWords << 0 << 1 << true;
682 QTest::newRow("<()>!dlrow|words")
683 << standard[3] << 0 << 0 << QDeclarative1TextInput::SelectWords << 0 << 0 << true;
684 QTest::newRow("!<()>dlrow|words")
685 << standard[3] << 1 << 1 << QDeclarative1TextInput::SelectWords << 1 << 1 << true;
687 QTest::newRow(" <s(pac)ey> text |words")
688 << standard[4] << 1 << 4 << QDeclarative1TextInput::SelectWords << 1 << 7 << true;
689 QTest::newRow(" spacey <t(ex)t> |words")
690 << standard[4] << 11 << 13 << QDeclarative1TextInput::SelectWords << 10 << 14 << true;
691 QTest::newRow("<( )>spacey text |words|ltr")
692 << standard[4] << 0 << 1 << QDeclarative1TextInput::SelectWords << 0 << 1 << false;
693 QTest::newRow("<( )spacey> text |words|rtl")
694 << standard[4] << 1 << 0 << QDeclarative1TextInput::SelectWords << 0 << 7 << false;
695 QTest::newRow("spacey <text( )>|words|ltr")
696 << standard[4] << 14 << 15 << QDeclarative1TextInput::SelectWords << 10 << 15 << false;
697 QTest::newRow("spacey text<( )>|words|rtl")
698 << standard[4] << 15 << 14 << QDeclarative1TextInput::SelectWords << 14 << 15 << false;
699 QTest::newRow("<()> spacey text |words")
700 << standard[4] << 0 << 0 << QDeclarative1TextInput::SelectWords << 0 << 0 << false;
701 QTest::newRow(" spacey text <()>|words")
702 << standard[4] << 15 << 15 << QDeclarative1TextInput::SelectWords << 15 << 15 << false;
705 void tst_qdeclarativetextinput::moveCursorSelection()
707 QFETCH(QString, testStr);
708 QFETCH(int, cursorPosition);
709 QFETCH(int, movePosition);
710 QFETCH(QDeclarative1TextInput::SelectionMode, mode);
711 QFETCH(int, selectionStart);
712 QFETCH(int, selectionEnd);
713 QFETCH(bool, reversible);
715 QString componentStr = "import QtQuick 1.1\nTextInput { text: \""+ testStr +"\"; }";
716 QDeclarativeComponent textinputComponent(&engine);
717 textinputComponent.setData(componentStr.toLatin1(), QUrl());
718 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
719 QVERIFY(textinputObject != 0);
721 textinputObject->setCursorPosition(cursorPosition);
722 textinputObject->moveCursorSelection(movePosition, mode);
724 QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
725 QCOMPARE(textinputObject->selectionStart(), selectionStart);
726 QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
729 textinputObject->setCursorPosition(movePosition);
730 textinputObject->moveCursorSelection(cursorPosition, mode);
732 QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
733 QCOMPARE(textinputObject->selectionStart(), selectionStart);
734 QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
737 delete textinputObject;
740 void tst_qdeclarativetextinput::moveCursorSelectionSequence_data()
742 QTest::addColumn<QString>("testStr");
743 QTest::addColumn<int>("cursorPosition");
744 QTest::addColumn<int>("movePosition1");
745 QTest::addColumn<int>("movePosition2");
746 QTest::addColumn<int>("selection1Start");
747 QTest::addColumn<int>("selection1End");
748 QTest::addColumn<int>("selection2Start");
749 QTest::addColumn<int>("selection2End");
751 // () contains the text selected by the cursor.
752 // <> contains the actual selection.
753 // ^ is the revised cursor position.
754 // {} contains the revised selection.
756 QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr")
761 QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl")
766 QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr")
771 QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl")
776 QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr")
781 QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl")
786 QTest::newRow("the {<quick() ^}bro)wn> fox|ltr")
791 QTest::newRow("the quick<( {^bro)wn>} fox|rtl")
796 QTest::newRow("the {<quick^}( bro)wn> fox|ltr")
801 QTest::newRow("the quick{<(^ bro)wn>} fox|rtl")
806 QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr")
811 QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl")
816 QTest::newRow("the {<^quick}( bro)wn> fox|ltr")
821 QTest::newRow("the {<^quick}( bro)wn> fox|rtl")
826 QTest::newRow("the{^ <quick}( bro)wn> fox|ltr")
831 QTest::newRow("the{^ <quick}( bro)wn> fox|rtl")
836 QTest::newRow("{t^he <quick}( bro)wn> fox|ltr")
841 QTest::newRow("{t^he <quick}( bro)wn> fox|rtl")
847 QTest::newRow("{<He(ll)o>, w^orld}!|ltr")
852 QTest::newRow("{<He(ll)o>, w^orld}!|rtl")
858 QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr")
863 QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl")
869 QTest::newRow("{<(^} sp)acey> text |ltr")
874 QTest::newRow("{<( ^}sp)acey> text |ltr")
879 QTest::newRow("<( {s^p)acey>} text |rtl")
884 QTest::newRow("<( {^sp)acey>} text |rtl")
890 QTest::newRow(" spacey <te(xt {^)>}|rtl")
895 QTest::newRow(" spacey <te(xt{^ )>}|rtl")
900 QTest::newRow(" spacey {<te(x^t} )>|ltr")
905 QTest::newRow(" spacey {<te(xt^} )>|ltr")
912 void tst_qdeclarativetextinput::moveCursorSelectionSequence()
914 QFETCH(QString, testStr);
915 QFETCH(int, cursorPosition);
916 QFETCH(int, movePosition1);
917 QFETCH(int, movePosition2);
918 QFETCH(int, selection1Start);
919 QFETCH(int, selection1End);
920 QFETCH(int, selection2Start);
921 QFETCH(int, selection2End);
923 QString componentStr = "import QtQuick 1.1\nTextInput { text: \""+ testStr +"\"; }";
924 QDeclarativeComponent textinputComponent(&engine);
925 textinputComponent.setData(componentStr.toLatin1(), QUrl());
926 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
927 QVERIFY(textinputObject != 0);
929 textinputObject->setCursorPosition(cursorPosition);
931 textinputObject->moveCursorSelection(movePosition1, QDeclarative1TextInput::SelectWords);
932 QCOMPARE(textinputObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start));
933 QCOMPARE(textinputObject->selectionStart(), selection1Start);
934 QCOMPARE(textinputObject->selectionEnd(), selection1End);
936 textinputObject->moveCursorSelection(movePosition2, QDeclarative1TextInput::SelectWords);
937 QCOMPARE(textinputObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start));
938 QCOMPARE(textinputObject->selectionStart(), selection2Start);
939 QCOMPARE(textinputObject->selectionEnd(), selection2End);
941 delete textinputObject;
944 void tst_qdeclarativetextinput::mouseSelection_data()
946 QTest::addColumn<QString>("qmlfile");
947 QTest::addColumn<bool>("expectSelection");
950 QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << true;
951 QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << false;
952 QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << false;
953 QTest::newRow("on word selection") << SRCDIR "/data/mouseselection_true_words.qml" << true;
954 QTest::newRow("off word selection") << SRCDIR "/data/mouseselection_false_words.qml" << false;
955 QTest::newRow("on read only") << SRCDIR "/data/mouseselection_true_readonly.qml" << true;
956 QTest::newRow("off read only") << SRCDIR "/data/mouseselection_false_readonly.qml" << false;
959 void tst_qdeclarativetextinput::mouseSelection()
961 QFETCH(QString, qmlfile);
962 QFETCH(bool, expectSelection);
964 QDeclarativeView *canvas = createView(qmlfile);
967 QApplication::setActiveWindow(canvas);
968 QTest::qWaitForWindowShown(canvas);
969 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
971 QVERIFY(canvas->rootObject() != 0);
972 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
973 QVERIFY(textInputObject != 0);
975 // press-and-drag-and-release from x1 to x2
978 int y = textInputObject->height()/2;
979 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
980 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
981 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
982 QApplication::sendEvent(canvas->viewport(), &mv);
983 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
984 QString str = textInputObject->selectedText();
986 QVERIFY(str.length() > 3); // don't reallly care *what* was selected (and it's too sensitive to platform)
988 QVERIFY(str.isEmpty());
990 // Clicking and shift to clicking between the same points should select the same text.
991 textInputObject->setCursorPosition(0);
992 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::NoModifier, canvas->mapFromScene(QPoint(x1,y)));
993 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::ShiftModifier, canvas->mapFromScene(QPoint(x2,y)));
994 QCOMPARE(textInputObject->selectedText(), str);
999 void tst_qdeclarativetextinput::deferEnableSelectByMouse_data()
1001 QTest::addColumn<QString>("qmlfile");
1003 QTest::newRow("writable") << SRCDIR "/data/mouseselection_false.qml";
1004 QTest::newRow("read only") << SRCDIR "/data/mouseselection_false_readonly.qml";
1007 void tst_qdeclarativetextinput::deferEnableSelectByMouse()
1009 // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed.
1010 QFETCH(QString, qmlfile);
1012 QDeclarativeView *canvas = createView(qmlfile);
1015 QApplication::setActiveWindow(canvas);
1016 QTest::qWaitForWindowShown(canvas);
1017 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1019 QVERIFY(canvas->rootObject() != 0);
1020 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1021 QVERIFY(textInputObject != 0);
1023 // press-and-drag-and-release from x1 to x2
1026 int y = textInputObject->height()/2;
1028 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1029 textInputObject->setSelectByMouse(true);
1030 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1031 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1032 QApplication::sendEvent(canvas->viewport(), &mv);
1033 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1034 QVERIFY(textInputObject->selectedText().isEmpty());
1039 void tst_qdeclarativetextinput::deferDisableSelectByMouse_data()
1041 QTest::addColumn<QString>("qmlfile");
1043 QTest::newRow("writable") << SRCDIR "/data/mouseselection_true.qml";
1044 QTest::newRow("read only") << SRCDIR "/data/mouseselection_true_readonly.qml";
1047 void tst_qdeclarativetextinput::deferDisableSelectByMouse()
1049 // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed.
1050 QFETCH(QString, qmlfile);
1052 QDeclarativeView *canvas = createView(qmlfile);
1055 QApplication::setActiveWindow(canvas);
1056 QTest::qWaitForWindowShown(canvas);
1057 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1059 QVERIFY(canvas->rootObject() != 0);
1060 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1061 QVERIFY(textInputObject != 0);
1063 // press-and-drag-and-release from x1 to x2
1066 int y = textInputObject->height()/2;
1068 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1069 textInputObject->setSelectByMouse(false);
1070 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1071 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1072 QApplication::sendEvent(canvas->viewport(), &mv);
1073 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1074 QVERIFY(textInputObject->selectedText().length() > 3);
1079 void tst_qdeclarativetextinput::dragMouseSelection()
1081 QString qmlfile = SRCDIR "/data/mouseselection_true.qml";
1083 QDeclarativeView *canvas = createView(qmlfile);
1086 QApplication::setActiveWindow(canvas);
1087 QTest::qWaitForWindowShown(canvas);
1088 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1090 QVERIFY(canvas->rootObject() != 0);
1091 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1092 QVERIFY(textInputObject != 0);
1094 // press-and-drag-and-release from x1 to x2
1097 int y = textInputObject->height()/2;
1098 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1100 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1101 QApplication::sendEvent(canvas->viewport(), &mv);
1103 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1105 QString str1 = textInputObject->selectedText();
1106 QVERIFY(str1.length() > 3);
1108 // press and drag the current selection.
1111 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1113 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1114 QApplication::sendEvent(canvas->viewport(), &mv);
1116 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1117 QString str2 = textInputObject->selectedText();
1118 QVERIFY(str2.length() > 3);
1120 QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved.
1124 void tst_qdeclarativetextinput::mouseSelectionMode_data()
1126 QTest::addColumn<QString>("qmlfile");
1127 QTest::addColumn<bool>("selectWords");
1130 QTest::newRow("SelectWords") << SRCDIR "/data/mouseselectionmode_words.qml" << true;
1131 QTest::newRow("SelectCharacters") << SRCDIR "/data/mouseselectionmode_characters.qml" << false;
1132 QTest::newRow("default") << SRCDIR "/data/mouseselectionmode_default.qml" << false;
1135 void tst_qdeclarativetextinput::mouseSelectionMode()
1137 QFETCH(QString, qmlfile);
1138 QFETCH(bool, selectWords);
1140 QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1142 QDeclarativeView *canvas = createView(qmlfile);
1145 QApplication::setActiveWindow(canvas);
1146 QTest::qWaitForWindowShown(canvas);
1147 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1149 QVERIFY(canvas->rootObject() != 0);
1150 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1151 QVERIFY(textInputObject != 0);
1153 // press-and-drag-and-release from x1 to x2
1156 int y = textInputObject->height()/2;
1157 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1158 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1159 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1160 QApplication::sendEvent(canvas->viewport(), &mv);
1161 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1162 QString str = textInputObject->selectedText();
1164 QCOMPARE(str, text);
1166 QVERIFY(str.length() > 3);
1167 QVERIFY(str != text);
1173 void tst_qdeclarativetextinput::horizontalAlignment_data()
1175 QTest::addColumn<int>("hAlign");
1176 QTest::addColumn<QString>("expectfile");
1178 QTest::newRow("L") << int(Qt::AlignLeft) << "halign_left";
1179 QTest::newRow("R") << int(Qt::AlignRight) << "halign_right";
1180 QTest::newRow("C") << int(Qt::AlignHCenter) << "halign_center";
1183 void tst_qdeclarativetextinput::horizontalAlignment()
1185 QFETCH(int, hAlign);
1186 QFETCH(QString, expectfile);
1188 QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment.qml");
1191 QApplication::setActiveWindow(canvas);
1192 QTest::qWaitForWindowShown(canvas);
1193 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1194 QObject *ob = canvas->rootObject();
1196 ob->setProperty("horizontalAlignment",hAlign);
1197 QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32);
1198 actual.fill(qRgb(255,255,255));
1200 QPainter p(&actual);
1204 expectfile = createExpectedFileIfNotFound(expectfile, actual);
1206 QImage expect(expectfile);
1208 QCOMPARE(actual,expect);
1213 void tst_qdeclarativetextinput::horizontalAlignment_RightToLeft()
1215 QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml");
1216 QDeclarative1TextInput *textInput = canvas->rootObject()->findChild<QDeclarative1TextInput*>("text");
1217 QVERIFY(textInput != 0);
1220 const QString rtlText = textInput->text();
1222 QDeclarative1TextInputPrivate *textInputPrivate = QDeclarative1TextInputPrivate::get(textInput);
1223 QVERIFY(textInputPrivate != 0);
1224 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1226 // implicit alignment should follow the reading direction of RTL text
1227 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1228 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1229 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1231 // explicitly left aligned
1232 textInput->setHAlign(QDeclarative1TextInput::AlignLeft);
1233 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1234 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1235 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1237 // explicitly right aligned
1238 textInput->setHAlign(QDeclarative1TextInput::AlignRight);
1239 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1240 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1241 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1243 // explicitly center aligned
1244 textInput->setHAlign(QDeclarative1TextInput::AlignHCenter);
1245 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1246 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignHCenter);
1247 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1248 QVERIFY(-textInputPrivate->hscroll + textInputPrivate->width() > canvas->width()/2);
1250 // reseted alignment should go back to following the text reading direction
1251 textInput->resetHAlign();
1252 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1253 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1254 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1256 // mirror the text item
1257 QDeclarativeItemPrivate::get(textInput)->setLayoutMirror(true);
1259 // mirrored implicit alignment should continue to follow the reading direction of the text
1260 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1261 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1262 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1264 // explicitly right aligned behaves as left aligned
1265 textInput->setHAlign(QDeclarative1TextInput::AlignRight);
1266 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1267 QCOMPARE(textInput->effectiveHAlign(), QDeclarative1TextInput::AlignLeft);
1268 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1270 // mirrored explicitly left aligned behaves as right aligned
1271 textInput->setHAlign(QDeclarative1TextInput::AlignLeft);
1272 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1273 QCOMPARE(textInput->effectiveHAlign(), QDeclarative1TextInput::AlignRight);
1274 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1276 // disable mirroring
1277 QDeclarativeItemPrivate::get(textInput)->setLayoutMirror(false);
1278 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1279 textInput->resetHAlign();
1281 // English text should be implicitly left aligned
1282 textInput->setText("Hello world!");
1283 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1284 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1286 QApplication::setActiveWindow(canvas);
1287 QTest::qWaitForWindowShown(canvas);
1288 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1290 // If there is no commited text, the preedit text should determine the alignment.
1291 textInput->setText(QString());
1292 { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(canvas, &ev); }
1293 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1294 { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(canvas, &ev); }
1295 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1297 // Clear pre-edit text. TextInput should maybe do this itself on setText, but that may be
1298 // redundant as an actual input method may take care of it.
1299 { QInputMethodEvent ev; QApplication::sendEvent(canvas, &ev); }
1301 #ifndef Q_OS_MAC // QTBUG-18040
1302 // empty text with implicit alignment follows the system locale-based
1303 // keyboard input direction from QInputPanel::inputDirection
1304 textInput->setText("");
1305 QCOMPARE(textInput->hAlign(), qApp->inputPanel()->inputDirection() == Qt::LeftToRight ?
1306 QDeclarative1TextInput::AlignLeft : QDeclarative1TextInput::AlignRight);
1307 if (qApp->inputPanel()->inputDirection() == Qt::LeftToRight)
1308 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1310 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1311 textInput->setHAlign(QDeclarative1TextInput::AlignRight);
1312 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1313 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1318 #ifndef Q_OS_MAC // QTBUG-18040
1319 // alignment of TextInput with no text set to it
1320 QString componentStr = "import QtQuick 1.0\nTextInput {}";
1321 QDeclarativeComponent textComponent(&engine);
1322 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1323 QDeclarative1TextInput *textObject = qobject_cast<QDeclarative1TextInput*>(textComponent.create());
1324 QCOMPARE(textObject->hAlign(), qApp->inputPanel()->inputDirection() == Qt::LeftToRight ?
1325 QDeclarative1TextInput::AlignLeft : QDeclarative1TextInput::AlignRight);
1330 void tst_qdeclarativetextinput::positionAt()
1332 QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml");
1333 QVERIFY(canvas->rootObject() != 0);
1336 QApplication::setActiveWindow(canvas);
1337 QTest::qWaitForWindowShown(canvas);
1339 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1340 QVERIFY(textinputObject != 0);
1342 // Check autoscrolled...
1344 int pos = textinputObject->positionAt(textinputObject->width()/2);
1346 QTextLayout layout(textinputObject->text());
1347 layout.setFont(textinputObject->font());
1348 layout.beginLayout();
1349 QTextLine line = layout.createLine();
1352 int textLeftWidthBegin = qFloor(line.cursorToX(pos - 1));
1353 int textLeftWidthEnd = qCeil(line.cursorToX(pos + 1));
1354 int textWidth = floor(line.horizontalAdvance());
1356 QVERIFY(textLeftWidthBegin <= textWidth - textinputObject->width() / 2);
1357 QVERIFY(textLeftWidthEnd >= textWidth - textinputObject->width() / 2);
1359 int x = textinputObject->positionToRectangle(pos + 1).x() - 1;
1360 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorBetweenCharacters), pos + 1);
1361 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorOnCharacter), pos);
1363 // Check without autoscroll...
1364 textinputObject->setAutoScroll(false);
1365 pos = textinputObject->positionAt(textinputObject->width()/2);
1367 textLeftWidthBegin = qFloor(line.cursorToX(pos - 1));
1368 textLeftWidthEnd = qCeil(line.cursorToX(pos + 1));
1370 QVERIFY(textLeftWidthBegin <= textinputObject->width() / 2);
1371 QVERIFY(textLeftWidthEnd >= textinputObject->width() / 2);
1373 x = textinputObject->positionToRectangle(pos + 1).x() - 1;
1374 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorBetweenCharacters), pos + 1);
1375 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorOnCharacter), pos);
1377 const qreal x0 = textinputObject->positionToRectangle(pos).x();
1378 const qreal x1 = textinputObject->positionToRectangle(pos + 1).x();
1380 QString preeditText = textinputObject->text().mid(0, pos);
1381 textinputObject->setText(textinputObject->text().mid(pos));
1382 textinputObject->setCursorPosition(0);
1384 QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
1385 QApplication::sendEvent(canvas, &inputEvent);
1387 // Check all points within the preedit text return the same position.
1388 QCOMPARE(textinputObject->positionAt(0), 0);
1389 QCOMPARE(textinputObject->positionAt(x0 / 2), 0);
1390 QCOMPARE(textinputObject->positionAt(x0), 0);
1392 // Verify positioning returns to normal after the preedit text.
1393 QCOMPARE(textinputObject->positionAt(x1), 1);
1394 QCOMPARE(textinputObject->positionToRectangle(1).x(), x1);
1399 void tst_qdeclarativetextinput::maxLength()
1401 QDeclarativeView *canvas = createView(SRCDIR "/data/maxLength.qml");
1402 QVERIFY(canvas->rootObject() != 0);
1405 QApplication::setActiveWindow(canvas);
1406 QTest::qWaitForWindowShown(canvas);
1408 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1409 QVERIFY(textinputObject != 0);
1410 QVERIFY(textinputObject->text().isEmpty());
1411 QVERIFY(textinputObject->maxLength() == 10);
1412 foreach(const QString &str, standard){
1413 QVERIFY(textinputObject->text().length() <= 10);
1414 textinputObject->setText(str);
1415 QVERIFY(textinputObject->text().length() <= 10);
1418 textinputObject->setText("");
1419 QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
1420 for(int i=0; i<20; i++){
1421 QCOMPARE(textinputObject->text().length(), qMin(i,10));
1422 //simulateKey(canvas, Qt::Key_A);
1423 QTest::keyPress(canvas, Qt::Key_A);
1424 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1430 void tst_qdeclarativetextinput::masks()
1432 //Not a comprehensive test of the possible masks, that's done elsewhere (QLineEdit)
1433 //QString componentStr = "import QtQuick 1.0\nTextInput { inputMask: 'HHHHhhhh'; }";
1434 QDeclarativeView *canvas = createView(SRCDIR "/data/masks.qml");
1437 QVERIFY(canvas->rootObject() != 0);
1438 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1439 QVERIFY(textinputObject != 0);
1440 QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
1441 QVERIFY(textinputObject->text().length() == 0);
1442 QCOMPARE(textinputObject->inputMask(), QString("HHHHhhhh; "));
1443 for(int i=0; i<10; i++){
1444 QCOMPARE(qMin(i,8), textinputObject->text().length());
1445 QCOMPARE(i>=4, textinputObject->hasAcceptableInput());
1446 //simulateKey(canvas, Qt::Key_A);
1447 QTest::keyPress(canvas, Qt::Key_A);
1448 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1454 void tst_qdeclarativetextinput::validators()
1456 // Note that this test assumes that the validators are working properly
1457 // so you may need to run their tests first. All validators are checked
1458 // here to ensure that their exposure to QML is working.
1460 QDeclarativeView *canvas = createView(SRCDIR "/data/validators.qml");
1464 QVERIFY(canvas->rootObject() != 0);
1466 QDeclarative1TextInput *intInput = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("intInput")));
1468 intInput->setFocus(true);
1469 QTRY_VERIFY(intInput->hasActiveFocus());
1470 QTest::keyPress(canvas, Qt::Key_1);
1471 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1472 QCOMPARE(intInput->text(), QLatin1String("1"));
1473 QCOMPARE(intInput->hasAcceptableInput(), false);
1474 QTest::keyPress(canvas, Qt::Key_2);
1475 QTest::keyRelease(canvas, Qt::Key_2, Qt::NoModifier ,10);
1476 QCOMPARE(intInput->text(), QLatin1String("1"));
1477 QCOMPARE(intInput->hasAcceptableInput(), false);
1478 QTest::keyPress(canvas, Qt::Key_1);
1479 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1480 QCOMPARE(intInput->text(), QLatin1String("11"));
1481 QCOMPARE(intInput->hasAcceptableInput(), true);
1482 QTest::keyPress(canvas, Qt::Key_0);
1483 QTest::keyRelease(canvas, Qt::Key_0, Qt::NoModifier ,10);
1484 QCOMPARE(intInput->text(), QLatin1String("11"));
1485 QCOMPARE(intInput->hasAcceptableInput(), true);
1487 QDeclarative1TextInput *dblInput = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("dblInput")));
1488 QTRY_VERIFY(dblInput);
1489 dblInput->setFocus(true);
1490 QVERIFY(dblInput->hasActiveFocus() == true);
1491 QTest::keyPress(canvas, Qt::Key_1);
1492 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1493 QCOMPARE(dblInput->text(), QLatin1String("1"));
1494 QCOMPARE(dblInput->hasAcceptableInput(), false);
1495 QTest::keyPress(canvas, Qt::Key_2);
1496 QTest::keyRelease(canvas, Qt::Key_2, Qt::NoModifier ,10);
1497 QCOMPARE(dblInput->text(), QLatin1String("12"));
1498 QCOMPARE(dblInput->hasAcceptableInput(), true);
1499 QTest::keyPress(canvas, Qt::Key_Period);
1500 QTest::keyRelease(canvas, Qt::Key_Period, Qt::NoModifier ,10);
1501 QCOMPARE(dblInput->text(), QLatin1String("12."));
1502 QCOMPARE(dblInput->hasAcceptableInput(), true);
1503 QTest::keyPress(canvas, Qt::Key_1);
1504 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1505 QCOMPARE(dblInput->text(), QLatin1String("12.1"));
1506 QCOMPARE(dblInput->hasAcceptableInput(), true);
1507 QTest::keyPress(canvas, Qt::Key_1);
1508 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1509 QCOMPARE(dblInput->text(), QLatin1String("12.11"));
1510 QCOMPARE(dblInput->hasAcceptableInput(), true);
1511 QTest::keyPress(canvas, Qt::Key_1);
1512 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1513 QCOMPARE(dblInput->text(), QLatin1String("12.11"));
1514 QCOMPARE(dblInput->hasAcceptableInput(), true);
1516 QDeclarative1TextInput *strInput = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("strInput")));
1517 QTRY_VERIFY(strInput);
1518 strInput->setFocus(true);
1519 QVERIFY(strInput->hasActiveFocus() == true);
1520 QTest::keyPress(canvas, Qt::Key_1);
1521 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1522 QCOMPARE(strInput->text(), QLatin1String(""));
1523 QCOMPARE(strInput->hasAcceptableInput(), false);
1524 QTest::keyPress(canvas, Qt::Key_A);
1525 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1526 QCOMPARE(strInput->text(), QLatin1String("a"));
1527 QCOMPARE(strInput->hasAcceptableInput(), false);
1528 QTest::keyPress(canvas, Qt::Key_A);
1529 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1530 QCOMPARE(strInput->text(), QLatin1String("aa"));
1531 QCOMPARE(strInput->hasAcceptableInput(), true);
1532 QTest::keyPress(canvas, Qt::Key_A);
1533 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1534 QCOMPARE(strInput->text(), QLatin1String("aaa"));
1535 QCOMPARE(strInput->hasAcceptableInput(), true);
1536 QTest::keyPress(canvas, Qt::Key_A);
1537 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1538 QCOMPARE(strInput->text(), QLatin1String("aaaa"));
1539 QCOMPARE(strInput->hasAcceptableInput(), true);
1540 QTest::keyPress(canvas, Qt::Key_A);
1541 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1542 QCOMPARE(strInput->text(), QLatin1String("aaaa"));
1543 QCOMPARE(strInput->hasAcceptableInput(), true);
1548 void tst_qdeclarativetextinput::inputMethods()
1550 QDeclarativeView *canvas = createView(SRCDIR "/data/inputmethods.qml");
1553 QApplication::setActiveWindow(canvas);
1554 QTest::qWaitForWindowShown(canvas);
1556 // test input method hints
1557 QVERIFY(canvas->rootObject() != 0);
1558 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1559 QVERIFY(input != 0);
1560 QVERIFY(input->imHints() & Qt::ImhNoPredictiveText);
1561 QVERIFY(input->inputMethodHints() & Qt::ImhNoPredictiveText);
1562 input->setIMHints(Qt::ImhUppercaseOnly);
1563 QVERIFY(input->imHints() & Qt::ImhUppercaseOnly);
1564 QVERIFY(input->inputMethodHints() & Qt::ImhUppercaseOnly);
1566 QVERIFY(canvas->rootObject() != 0);
1568 input->setFocus(true);
1569 QVERIFY(input->hasActiveFocus() == true);
1570 // test that input method event is committed
1571 QInputMethodEvent event;
1572 event.setCommitString( "My ", -12, 0);
1573 QApplication::sendEvent(canvas, &event);
1574 QCOMPARE(input->text(), QString("My Hello world!"));
1576 input->setCursorPosition(2);
1577 event.setCommitString("Your", -2, 2);
1578 QApplication::sendEvent(canvas, &event);
1579 QCOMPARE(input->text(), QString("Your Hello world!"));
1580 QCOMPARE(input->cursorPosition(), 4);
1582 input->setCursorPosition(7);
1583 event.setCommitString("Goodbye", -2, 5);
1584 QApplication::sendEvent(canvas, &event);
1585 QCOMPARE(input->text(), QString("Your Goodbye world!"));
1586 QCOMPARE(input->cursorPosition(), 12);
1588 input->setCursorPosition(8);
1589 event.setCommitString("Our", -8, 4);
1590 QApplication::sendEvent(canvas, &event);
1591 QCOMPARE(input->text(), QString("Our Goodbye world!"));
1592 QCOMPARE(input->cursorPosition(), 7);
1594 // test that basic tentative commit gets to text property on preedit state
1596 QList<QInputMethodEvent::Attribute> attributes;
1597 QInputMethodEvent preeditEvent("test", attributes);
1598 preeditEvent.setTentativeCommitString("test");
1599 QApplication::sendEvent(canvas, &preeditEvent);
1600 QCOMPARE(input->text(), QString("test"));
1602 // tentative commit not allowed present in surrounding text
1603 QInputMethodQueryEvent queryEvent(Qt::ImSurroundingText);
1604 QApplication::sendEvent(canvas, &queryEvent);
1605 QCOMPARE(queryEvent.value(Qt::ImSurroundingText).toString(), QString(""));
1607 // if text with tentative commit does not validate, not allowed to be part of text property
1608 input->setText(""); // ensure input state is reset
1609 QValidator *validator = new QIntValidator(0, 100);
1610 input->setValidator(validator);
1611 QApplication::sendEvent(canvas, &preeditEvent);
1612 QCOMPARE(input->text(), QString(""));
1613 input->setValidator(0);
1620 TextInput element should only handle left/right keys until the cursor reaches
1621 the extent of the text, then they should ignore the keys.
1624 void tst_qdeclarativetextinput::navigation()
1626 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
1630 QVERIFY(canvas->rootObject() != 0);
1632 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1634 QVERIFY(input != 0);
1635 input->setCursorPosition(0);
1636 QTRY_VERIFY(input->hasActiveFocus() == true);
1637 simulateKey(canvas, Qt::Key_Left);
1638 QVERIFY(input->hasActiveFocus() == false);
1639 simulateKey(canvas, Qt::Key_Right);
1640 QVERIFY(input->hasActiveFocus() == true);
1641 //QT-2944: If text is selected, ensure we deselect upon cursor motion
1642 input->setCursorPosition(input->text().length());
1643 input->select(0,input->text().length());
1644 QVERIFY(input->selectionStart() != input->selectionEnd());
1645 simulateKey(canvas, Qt::Key_Right);
1646 QVERIFY(input->selectionStart() == input->selectionEnd());
1647 QVERIFY(input->selectionStart() == input->text().length());
1648 QVERIFY(input->hasActiveFocus() == true);
1649 simulateKey(canvas, Qt::Key_Right);
1650 QVERIFY(input->hasActiveFocus() == false);
1651 simulateKey(canvas, Qt::Key_Left);
1652 QVERIFY(input->hasActiveFocus() == true);
1654 // Up and Down should NOT do Home/End, even on Mac OS X (QTBUG-10438).
1655 input->setCursorPosition(2);
1656 QCOMPARE(input->cursorPosition(),2);
1657 simulateKey(canvas, Qt::Key_Up);
1658 QCOMPARE(input->cursorPosition(),2);
1659 simulateKey(canvas, Qt::Key_Down);
1660 QCOMPARE(input->cursorPosition(),2);
1665 void tst_qdeclarativetextinput::navigation_RTL()
1667 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
1671 QVERIFY(canvas->rootObject() != 0);
1673 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1675 QVERIFY(input != 0);
1676 const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
1677 input->setText(QString::fromUtf16(arabic_str, 11));
1679 input->setCursorPosition(0);
1680 QTRY_VERIFY(input->hasActiveFocus() == true);
1683 simulateKey(canvas, Qt::Key_Right);
1684 QVERIFY(input->hasActiveFocus() == false);
1687 simulateKey(canvas, Qt::Key_Left);
1688 QVERIFY(input->hasActiveFocus() == true);
1690 input->setCursorPosition(input->text().length());
1691 QVERIFY(input->hasActiveFocus() == true);
1694 simulateKey(canvas, Qt::Key_Left);
1695 QVERIFY(input->hasActiveFocus() == false);
1698 simulateKey(canvas, Qt::Key_Right);
1699 QVERIFY(input->hasActiveFocus() == true);
1704 void tst_qdeclarativetextinput::copyAndPaste() {
1705 #ifndef QT_NO_CLIPBOARD
1709 PasteboardRef pasteboard;
1710 OSStatus status = PasteboardCreate(0, &pasteboard);
1711 if (status == noErr)
1712 CFRelease(pasteboard);
1714 QSKIP("This machine doesn't support the clipboard");
1718 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }";
1719 QDeclarativeComponent textInputComponent(&engine);
1720 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1721 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1722 QVERIFY(textInput != 0);
1725 QCOMPARE(textInput->text().length(), 12);
1726 textInput->select(0, textInput->text().length());;
1728 QCOMPARE(textInput->selectedText(), QString("Hello world!"));
1729 QCOMPARE(textInput->selectedText().length(), 12);
1730 textInput->setCursorPosition(0);
1731 QVERIFY(textInput->canPaste());
1733 QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
1734 QCOMPARE(textInput->text().length(), 24);
1737 QVERIFY(textInput->canPaste());
1738 textInput->setReadOnly(true);
1739 QVERIFY(!textInput->canPaste());
1740 textInput->setReadOnly(false);
1741 QVERIFY(textInput->canPaste());
1744 textInput->setCursorPosition(0);
1745 textInput->selectWord();
1746 QCOMPARE(textInput->selectedText(), QString("Hello"));
1748 // select all and cut
1749 textInput->selectAll();
1751 QCOMPARE(textInput->text().length(), 0);
1753 QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
1754 QCOMPARE(textInput->text().length(), 24);
1756 // clear copy buffer
1757 QClipboard *clipboard = QApplication::clipboard();
1760 QVERIFY(!textInput->canPaste());
1762 // test that copy functionality is disabled
1763 // when echo mode is set to hide text/password mode
1766 QDeclarative1TextInput::EchoMode echoMode = QDeclarative1TextInput::EchoMode(index);
1767 textInput->setEchoMode(echoMode);
1768 textInput->setText("My password");
1769 textInput->select(0, textInput->text().length());;
1771 if (echoMode == QDeclarative1TextInput::Normal) {
1772 QVERIFY(!clipboard->text().isEmpty());
1773 QCOMPARE(clipboard->text(), QString("My password"));
1776 QVERIFY(clipboard->text().isEmpty());
1785 void tst_qdeclarativetextinput::canPasteEmpty() {
1786 #ifndef QT_NO_CLIPBOARD
1788 QApplication::clipboard()->clear();
1790 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }";
1791 QDeclarativeComponent textInputComponent(&engine);
1792 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1793 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1794 QVERIFY(textInput != 0);
1796 QWidgetLineControl lc;
1797 bool cp = !lc.isReadOnly() && QApplication::clipboard()->text().length() != 0;
1798 QCOMPARE(textInput->canPaste(), cp);
1803 void tst_qdeclarativetextinput::canPaste() {
1804 #ifndef QT_NO_CLIPBOARD
1806 QApplication::clipboard()->setText("Some text");
1808 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }";
1809 QDeclarativeComponent textInputComponent(&engine);
1810 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1811 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1812 QVERIFY(textInput != 0);
1814 QWidgetLineControl lc;
1815 bool cp = !lc.isReadOnly() && QApplication::clipboard()->text().length() != 0;
1816 QCOMPARE(textInput->canPaste(), cp);
1821 void tst_qdeclarativetextinput::passwordCharacter()
1823 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\"; font.family: \"Helvetica\"; echoMode: TextInput.Password }";
1824 QDeclarativeComponent textInputComponent(&engine);
1825 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1826 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1827 QVERIFY(textInput != 0);
1829 textInput->setPasswordCharacter("X");
1830 QSize contentsSize = textInput->contentsSize();
1831 textInput->setPasswordCharacter(".");
1832 // QTBUG-12383 content is updated and redrawn
1833 QVERIFY(contentsSize != textInput->contentsSize());
1838 void tst_qdeclarativetextinput::cursorDelegate()
1840 QDeclarativeView* view = createView(SRCDIR "/data/cursorTest.qml");
1843 QDeclarative1TextInput *textInputObject = view->rootObject()->findChild<QDeclarative1TextInput*>("textInputObject");
1844 QVERIFY(textInputObject != 0);
1845 QVERIFY(textInputObject->findChild<QDeclarativeItem*>("cursorInstance"));
1846 //Test Delegate gets created
1847 textInputObject->setFocus(true);
1848 QDeclarativeItem* delegateObject = textInputObject->findChild<QDeclarativeItem*>("cursorInstance");
1849 QVERIFY(delegateObject);
1850 //Test Delegate gets moved
1851 for(int i=0; i<= textInputObject->text().length(); i++){
1852 textInputObject->setCursorPosition(i);
1853 QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
1854 QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
1856 const QString preedit = "preedit";
1857 for (int i = 0; i <= preedit.length(); i++) {
1858 QInputMethodEvent event(preedit, QList<QInputMethodEvent::Attribute>()
1859 << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, 1, QVariant()));
1860 QApplication::sendEvent(view, &event);
1862 QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
1863 QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
1865 textInputObject->setCursorPosition(0);
1866 QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
1867 QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
1868 //Test Delegate gets deleted
1869 textInputObject->setCursorDelegate(0);
1870 QVERIFY(!textInputObject->findChild<QDeclarativeItem*>("cursorInstance"));
1875 void tst_qdeclarativetextinput::cursorVisible()
1877 QGraphicsScene scene;
1878 QGraphicsView view(&scene);
1880 QApplication::setActiveWindow(&view);
1881 QTest::qWaitForWindowShown(&view);
1882 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
1884 QDeclarative1TextInput input;
1885 QSignalSpy spy(&input, SIGNAL(cursorVisibleChanged(bool)));
1887 QCOMPARE(input.isCursorVisible(), false);
1889 input.setCursorVisible(true);
1890 QCOMPARE(input.isCursorVisible(), true);
1891 QCOMPARE(spy.count(), 1);
1893 input.setCursorVisible(false);
1894 QCOMPARE(input.isCursorVisible(), false);
1895 QCOMPARE(spy.count(), 2);
1897 input.setFocus(true);
1898 QCOMPARE(input.isCursorVisible(), false);
1899 QCOMPARE(spy.count(), 2);
1901 scene.addItem(&input);
1902 QCOMPARE(input.isCursorVisible(), true);
1903 QCOMPARE(spy.count(), 3);
1905 input.setFocus(false);
1906 QCOMPARE(input.isCursorVisible(), false);
1907 QCOMPARE(spy.count(), 4);
1909 input.setFocus(true);
1910 QCOMPARE(input.isCursorVisible(), true);
1911 QCOMPARE(spy.count(), 5);
1914 QCOMPARE(input.isCursorVisible(), false);
1915 QCOMPARE(spy.count(), 6);
1918 QCOMPARE(input.isCursorVisible(), true);
1919 QCOMPARE(spy.count(), 7);
1922 QCOMPARE(input.isCursorVisible(), false);
1923 QCOMPARE(spy.count(), 8);
1926 QCOMPARE(input.isCursorVisible(), true);
1927 QCOMPARE(spy.count(), 9);
1929 // on mac, setActiveWindow(0) on mac does not deactivate the current application
1930 // (you have to switch to a different app or hide the current app to trigger this)
1931 #if !defined(Q_WS_MAC)
1932 QApplication::setActiveWindow(0);
1933 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(0));
1934 QCOMPARE(input.isCursorVisible(), false);
1935 QCOMPARE(spy.count(), 10);
1937 QApplication::setActiveWindow(&view);
1938 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
1939 QCOMPARE(input.isCursorVisible(), true);
1940 QCOMPARE(spy.count(), 11);
1944 void tst_qdeclarativetextinput::cursorRectangle()
1946 QString text = "Hello World!";
1948 QDeclarative1TextInput input;
1949 input.setText(text);
1950 QFontMetricsF fm(input.font());
1951 input.setWidth(fm.width(text.mid(0, 5)));
1955 // some tolerance for different fonts.
1957 const int error = 2;
1959 const int error = 5;
1962 for (int i = 0; i <= 5; ++i) {
1963 input.setCursorPosition(i);
1964 r = input.cursorRectangle();
1965 int textWidth = fm.width(text.mid(0, i));
1967 QVERIFY(r.left() < textWidth + error);
1968 QVERIFY(r.right() > textWidth - error);
1969 QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
1972 // Check the cursor rectangle remains within the input bounding rect when auto scrolling.
1973 QVERIFY(r.left() < input.boundingRect().width());
1974 QVERIFY(r.right() >= input.width() - error);
1976 for (int i = 6; i < text.length(); ++i) {
1977 input.setCursorPosition(i);
1978 QCOMPARE(r, input.cursorRectangle());
1979 QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
1982 for (int i = text.length() - 2; i >= 0; --i) {
1983 input.setCursorPosition(i);
1984 r = input.cursorRectangle();
1985 QVERIFY(r.right() >= 0);
1986 QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
1990 void tst_qdeclarativetextinput::readOnly()
1992 QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml");
1996 QVERIFY(canvas->rootObject() != 0);
1998 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
2000 QVERIFY(input != 0);
2001 QTRY_VERIFY(input->hasActiveFocus() == true);
2002 QVERIFY(input->isReadOnly() == true);
2003 QString initial = input->text();
2004 for(int k=Qt::Key_0; k<=Qt::Key_Z; k++)
2005 simulateKey(canvas, k);
2006 simulateKey(canvas, Qt::Key_Return);
2007 simulateKey(canvas, Qt::Key_Space);
2008 simulateKey(canvas, Qt::Key_Escape);
2009 QCOMPARE(input->text(), initial);
2014 void tst_qdeclarativetextinput::echoMode()
2016 QDeclarativeView *canvas = createView(SRCDIR "/data/echoMode.qml");
2019 QApplication::setActiveWindow(canvas);
2020 QTest::qWaitForWindowShown(canvas);
2021 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
2023 QVERIFY(canvas->rootObject() != 0);
2025 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
2027 QVERIFY(input != 0);
2028 QTRY_VERIFY(input->hasActiveFocus() == true);
2029 QString initial = input->text();
2030 Qt::InputMethodHints ref;
2031 QCOMPARE(initial, QLatin1String("ABCDefgh"));
2032 QCOMPARE(input->echoMode(), QDeclarative1TextInput::Normal);
2033 QCOMPARE(input->displayText(), input->text());
2035 ref &= ~Qt::ImhHiddenText;
2036 ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2037 QCOMPARE(input->inputMethodHints(), ref);
2038 QCOMPARE(input->imHints(), Qt::ImhNone);
2039 input->setEchoMode(QDeclarative1TextInput::NoEcho);
2040 QCOMPARE(input->text(), initial);
2041 QCOMPARE(input->displayText(), QLatin1String(""));
2042 QCOMPARE(input->passwordCharacter(), QLatin1String("*"));
2044 ref |= Qt::ImhHiddenText;
2045 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2046 QCOMPARE(input->inputMethodHints(), ref);
2047 QCOMPARE(input->imHints(), Qt::ImhNone);
2048 input->setEchoMode(QDeclarative1TextInput::Password);
2050 ref |= Qt::ImhHiddenText;
2051 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2052 QCOMPARE(input->text(), initial);
2053 QCOMPARE(input->displayText(), QLatin1String("********"));
2054 QCOMPARE(input->inputMethodHints(), ref);
2055 QCOMPARE(input->imHints(), Qt::ImhNone);
2056 input->setPasswordCharacter(QChar('Q'));
2057 QCOMPARE(input->passwordCharacter(), QLatin1String("Q"));
2058 QCOMPARE(input->text(), initial);
2059 QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
2060 input->setEchoMode(QDeclarative1TextInput::PasswordEchoOnEdit);
2061 //PasswordEchoOnEdit
2062 ref &= ~Qt::ImhHiddenText;
2063 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2064 QCOMPARE(input->inputMethodHints(), ref);
2065 QCOMPARE(input->imHints(), Qt::ImhNone);
2066 QCOMPARE(input->text(), initial);
2067 QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
2068 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("QQQQQQQQ"));
2069 QTest::keyPress(canvas, Qt::Key_A);//Clearing previous entry is part of PasswordEchoOnEdit
2070 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
2071 QCOMPARE(input->text(), QLatin1String("a"));
2072 QCOMPARE(input->displayText(), QLatin1String("a"));
2073 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("a"));
2074 input->setFocus(false);
2075 QVERIFY(input->hasActiveFocus() == false);
2076 QCOMPARE(input->displayText(), QLatin1String("Q"));
2077 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("Q"));
2078 input->setFocus(true);
2079 QInputMethodEvent inputEvent;
2080 inputEvent.setCommitString(initial);
2081 QApplication::sendEvent(canvas, &inputEvent);
2082 QCOMPARE(input->text(), initial);
2083 QCOMPARE(input->displayText(), initial);
2084 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial);
2086 // Test echo mode doesn't override imHints.
2087 input->setIMHints(Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2088 ref |= Qt::ImhDialableCharactersOnly;
2090 input->setEchoMode(QDeclarative1TextInput::Normal);
2091 ref |= Qt::ImhHiddenText;
2092 ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2093 QCOMPARE(input->inputMethodHints(), ref);
2094 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2096 input->setEchoMode(QDeclarative1TextInput::NoEcho);
2097 ref |= Qt::ImhHiddenText;
2098 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2099 QCOMPARE(input->inputMethodHints(), ref);
2100 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2102 input->setEchoMode(QDeclarative1TextInput::Password);
2103 ref |= Qt::ImhHiddenText;
2104 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2105 QCOMPARE(input->inputMethodHints(), ref);
2106 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2107 //PasswordEchoOnEdit
2108 input->setEchoMode(QDeclarative1TextInput::PasswordEchoOnEdit);
2109 ref &= ~Qt::ImhHiddenText;
2110 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2111 QCOMPARE(input->inputMethodHints(), ref);
2112 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2114 input->setEchoMode(QDeclarative1TextInput::Normal);
2115 ref |= Qt::ImhHiddenText;
2116 ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2117 QCOMPARE(input->inputMethodHints(), ref);
2118 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2124 #ifdef QT_GUI_PASSWORD_ECHO_DELAY
2125 void tst_qdeclarativetextinput::passwordEchoDelay()
2127 QDeclarativeView *canvas = createView(SRCDIR "/data/echoMode.qml");
2130 QApplication::setActiveWindow(canvas);
2131 QTest::qWaitForWindowShown(canvas);
2132 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
2134 QVERIFY(canvas->rootObject() != 0);
2136 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
2138 QChar fillChar = QLatin1Char('*');
2140 input->setEchoMode(QDeclarativeTextInput::Password);
2141 QCOMPARE(input->displayText(), QString(8, fillChar));
2142 input->setText(QString());
2143 QCOMPARE(input->displayText(), QString());
2145 QTest::keyPress(canvas, '0');
2146 QTest::keyPress(canvas, '1');
2147 QTest::keyPress(canvas, '2');
2148 QCOMPARE(input->displayText(), QString(2, fillChar) + QLatin1Char('2'));
2149 QTest::keyPress(canvas, '3');
2150 QTest::keyPress(canvas, '4');
2151 QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
2152 QTest::keyPress(canvas, Qt::Key_Backspace);
2153 QCOMPARE(input->displayText(), QString(4, fillChar));
2154 QTest::keyPress(canvas, '4');
2155 QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
2156 QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
2157 QTRY_COMPARE(input->displayText(), QString(5, fillChar));
2158 QTest::keyPress(canvas, '5');
2159 QCOMPARE(input->displayText(), QString(5, fillChar) + QLatin1Char('5'));
2160 input->setFocus(false);
2161 QVERIFY(!input->hasFocus());
2162 QCOMPARE(input->displayText(), QString(6, fillChar));
2163 input->setFocus(true);
2164 QTRY_VERIFY(input->hasFocus());
2165 QCOMPARE(input->displayText(), QString(6, fillChar));
2166 QTest::keyPress(canvas, '6');
2167 QCOMPARE(input->displayText(), QString(6, fillChar) + QLatin1Char('6'));
2169 QInputMethodEvent ev;
2170 ev.setCommitString(QLatin1String("7"));
2171 QApplication::sendEvent(canvas, &ev);
2172 QCOMPARE(input->displayText(), QString(7, fillChar) + QLatin1Char('7'));
2179 void tst_qdeclarativetextinput::simulateKey(QDeclarativeView *view, int key)
2181 QKeyEvent press(QKeyEvent::KeyPress, key, 0);
2182 QKeyEvent release(QKeyEvent::KeyRelease, key, 0);
2184 QApplication::sendEvent(view, &press);
2185 QApplication::sendEvent(view, &release);
2188 QDeclarativeView *tst_qdeclarativetextinput::createView(const QString &filename)
2190 QDeclarativeView *canvas = new QDeclarativeView(0);
2192 canvas->setSource(QUrl::fromLocalFile(filename));
2197 void tst_qdeclarativetextinput::openInputPanelOnClick()
2199 PlatformInputContext ic;
2200 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
2201 inputPanelPrivate->testContext = ⁣
2203 QGraphicsScene scene;
2204 QGraphicsView view(&scene);
2205 QDeclarative1TextInput input;
2206 QSignalSpy focusOnPressSpy(&input, SIGNAL(activeFocusOnPressChanged(bool)));
2207 input.setText("Hello world");
2209 scene.addItem(&input);
2211 qApp->setAutoSipEnabled(true);
2212 QApplication::setActiveWindow(&view);
2213 QTest::qWaitForWindowShown(&view);
2214 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2216 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&input);
2217 QDeclarative1TextInputPrivate *inputPrivate = static_cast<QDeclarative1TextInputPrivate*>(pri);
2219 // input panel on click
2220 inputPrivate->showInputPanelOnFocus = false;
2222 QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
2223 view.style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
2224 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2225 QApplication::processEvents();
2226 if (behavior == QStyle::RSIP_OnMouseClickAndAlreadyFocused) {
2227 QCOMPARE(ic.isInputPanelVisible(), false);
2228 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2229 QApplication::processEvents();
2230 QCOMPARE(ic.isInputPanelVisible(), true);
2231 } else if (behavior == QStyle::RSIP_OnMouseClick) {
2232 QCOMPARE(ic.isInputPanelVisible(), true);
2235 ic.m_showInputPanelCallCount = 0;
2236 ic.m_hideInputPanelCallCount = 0;
2238 // focus should not cause input panels to open or close
2239 input.setFocus(false);
2240 input.setFocus(true);
2241 input.setFocus(false);
2242 input.setFocus(true);
2243 input.setFocus(false);
2244 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2245 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2248 void tst_qdeclarativetextinput::openInputPanelOnFocus()
2250 PlatformInputContext ic;
2251 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
2252 inputPanelPrivate->testContext = ⁣
2256 QGraphicsScene scene;
2257 QGraphicsView view(&scene);
2258 QDeclarative1TextInput input;
2259 QSignalSpy focusOnPressSpy(&input, SIGNAL(activeFocusOnPressChanged(bool)));
2260 input.setText("Hello world");
2262 scene.addItem(&input);
2264 qApp->setAutoSipEnabled(true);
2265 QApplication::setActiveWindow(&view);
2266 QTest::qWaitForWindowShown(&view);
2267 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2269 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&input);
2270 QDeclarative1TextInputPrivate *inputPrivate = static_cast<QDeclarative1TextInputPrivate*>(pri);
2271 inputPrivate->showInputPanelOnFocus = true;
2273 // test default values
2274 QVERIFY(input.focusOnPress());
2275 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2276 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2278 // focus on press, input panel on focus
2279 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2280 QApplication::processEvents();
2281 QVERIFY(input.hasActiveFocus());
2282 QCOMPARE(ic.isInputPanelVisible(), true);
2285 // no events on release
2286 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2287 QCOMPARE(ic.isInputPanelVisible(), false);
2290 // if already focused, input panel can be opened on press
2291 QVERIFY(input.hasActiveFocus());
2292 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2293 QApplication::processEvents();
2294 QCOMPARE(ic.isInputPanelVisible(), true);
2297 // input method should stay enabled if focus
2298 // is lost to an item that also accepts inputs
2299 QDeclarative1TextInput anotherInput;
2300 scene.addItem(&anotherInput);
2301 anotherInput.setFocus(true);
2302 QApplication::processEvents();
2303 QCOMPARE(ic.isInputPanelVisible(), true);
2305 QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
2307 // input method should be disabled if focus
2308 // is lost to an item that doesn't accept inputs
2309 QDeclarativeItem item;
2310 scene.addItem(&item);
2311 item.setFocus(true);
2312 QApplication::processEvents();
2313 QCOMPARE(ic.isInputPanelVisible(), false);
2314 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2317 // no automatic input panel events should
2318 // be sent if activeFocusOnPress is false
2319 input.setFocusOnPress(false);
2320 QCOMPARE(focusOnPressSpy.count(),1);
2321 input.setFocusOnPress(false);
2322 QCOMPARE(focusOnPressSpy.count(),1);
2323 input.setFocus(false);
2324 input.setFocus(true);
2325 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2326 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2327 QApplication::processEvents();
2328 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2329 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2331 // one show input panel event should
2332 // be set when openSoftwareInputPanel is called
2333 input.openSoftwareInputPanel();
2334 QCOMPARE(ic.isInputPanelVisible(), true);
2335 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2338 // one close input panel event should
2339 // be sent when closeSoftwareInputPanel is called
2340 input.closeSoftwareInputPanel();
2341 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2342 QVERIFY(ic.m_hideInputPanelCallCount > 0);
2345 // set activeFocusOnPress back to true
2346 input.setFocusOnPress(true);
2347 QCOMPARE(focusOnPressSpy.count(),2);
2348 input.setFocusOnPress(true);
2349 QCOMPARE(focusOnPressSpy.count(),2);
2350 input.setFocus(false);
2351 QApplication::processEvents();
2352 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2353 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2356 // input panel should not re-open
2357 // if focus has already been set
2358 input.setFocus(true);
2359 QCOMPARE(ic.isInputPanelVisible(), true);
2361 input.setFocus(true);
2362 QCOMPARE(ic.isInputPanelVisible(), false);
2364 // input method should be disabled
2365 // if TextInput loses focus
2366 input.setFocus(false);
2367 QApplication::processEvents();
2368 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2370 // input method should not be enabled
2371 // if TextEdit is read only.
2372 input.setReadOnly(true);
2374 input.setFocus(true);
2375 QApplication::processEvents();
2376 QCOMPARE(ic.isInputPanelVisible(), false);
2377 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2380 class MyTextInput : public QDeclarative1TextInput
2383 MyTextInput(QDeclarativeItem *parent = 0) : QDeclarative1TextInput(parent)
2387 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
2390 QDeclarative1TextInput::paint(painter, option, widget);
2395 void tst_qdeclarativetextinput::setHAlignClearCache()
2397 QGraphicsScene scene;
2398 QGraphicsView view(&scene);
2400 input.setText("Hello world");
2401 scene.addItem(&input);
2403 QApplication::setActiveWindow(&view);
2404 QTest::qWaitForWindowShown(&view);
2405 QTRY_VERIFY(input.nbPaint >= 1);
2407 input.setHAlign(QDeclarative1TextInput::AlignRight);
2408 QApplication::processEvents();
2409 //Changing the alignment should trigger a repaint
2410 QTRY_VERIFY(input.nbPaint >= 1);
2413 void tst_qdeclarativetextinput::focusOutClearSelection()
2415 QGraphicsScene scene;
2416 QGraphicsView view(&scene);
2417 QDeclarative1TextInput input;
2418 QDeclarative1TextInput input2;
2419 input.setText(QLatin1String("Hello world"));
2420 input.setFocus(true);
2421 scene.addItem(&input2);
2422 scene.addItem(&input);
2424 QApplication::setActiveWindow(&view);
2425 QTest::qWaitForWindowShown(&view);
2427 //The selection should work
2428 QTRY_COMPARE(input.selectedText(), QLatin1String("llo"));
2429 input2.setFocus(true);
2430 QApplication::processEvents();
2431 //The input lost the focus selection should be cleared
2432 QTRY_COMPARE(input.selectedText(), QLatin1String(""));
2435 void tst_qdeclarativetextinput::geometrySignals()
2437 QDeclarativeComponent component(&engine, SRCDIR "/data/geometrySignals.qml");
2438 QObject *o = component.create();
2440 QCOMPARE(o->property("bindingWidth").toInt(), 400);
2441 QCOMPARE(o->property("bindingHeight").toInt(), 500);
2445 void tst_qdeclarativetextinput::testQtQuick11Attributes()
2447 QFETCH(QString, code);
2448 QFETCH(QString, warning);
2449 QFETCH(QString, error);
2451 QDeclarativeEngine engine;
2454 QDeclarativeComponent valid(&engine);
2455 valid.setData("import QtQuick 1.1; TextInput { " + code.toUtf8() + " }", QUrl(""));
2456 obj = valid.create();
2458 QVERIFY(valid.errorString().isEmpty());
2461 QDeclarativeComponent invalid(&engine);
2462 invalid.setData("import QtQuick 1.0; TextInput { " + code.toUtf8() + " }", QUrl(""));
2463 QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
2464 obj = invalid.create();
2465 QCOMPARE(invalid.errorString(), error);
2469 void tst_qdeclarativetextinput::testQtQuick11Attributes_data()
2471 QTest::addColumn<QString>("code");
2472 QTest::addColumn<QString>("warning");
2473 QTest::addColumn<QString>("error");
2475 QTest::newRow("canPaste") << "property bool foo: canPaste"
2476 << "<Unknown File>:1: ReferenceError: Can't find variable: canPaste"
2479 QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)"
2480 << "<Unknown File>:1: ReferenceError: Can't find variable: moveCursorSelection"
2483 QTest::newRow("deselect") << "Component.onCompleted: deselect()"
2484 << "<Unknown File>:1: ReferenceError: Can't find variable: deselect"
2488 void tst_qdeclarativetextinput::preeditAutoScroll()
2490 QString committedText = "super";
2491 QString preeditText = "califragisiticexpialidocious!";
2493 QGraphicsScene scene;
2494 QGraphicsView view(&scene);
2495 QDeclarative1TextInput input;
2496 QFontMetricsF fm(input.font());
2497 input.setWidth(fm.width(committedText));
2498 input.setText(committedText);
2500 input.setFocus(true);
2501 scene.addItem(&input);
2503 QApplication::setActiveWindow(&view);
2504 QTest::qWaitForWindowShown(&view);
2505 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2507 QSignalSpy cursorRectangleSpy(&input, SIGNAL(cursorRectangleChanged()));
2508 int cursorRectangleChanges = 0;
2510 // test the text is scrolled so the preedit is visible.
2511 sendPreeditText(preeditText.mid(0, 3), 1);
2512 QVERIFY(input.positionAt(0) != 0);
2513 QVERIFY(input.cursorRectangle().left() < input.boundingRect().width());
2514 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2516 // test the text is scrolled back when the preedit is removed.
2517 QInputMethodEvent emptyEvent;
2518 QApplication::sendEvent(&view, &emptyEvent);
2519 QCOMPARE(input.positionAt(0), 0);
2520 QCOMPARE(input.positionAt(input.width()), 5);
2521 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2523 // some tolerance for different fonts.
2525 const int error = 2;
2527 const int error = 5;
2530 // test if the preedit is larger than the text input that the
2531 // character preceding the cursor is still visible.
2532 qreal x = input.positionToRectangle(0).x();
2533 for (int i = 0; i < 3; ++i) {
2534 sendPreeditText(preeditText, i + 1);
2535 QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i)) - error);
2536 QVERIFY(input.positionToRectangle(0).x() < x);
2537 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2538 x = input.positionToRectangle(0).x();
2540 for (int i = 1; i >= 0; --i) {
2541 sendPreeditText(preeditText, i + 1);
2542 QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i)) - error);
2543 QVERIFY(input.positionToRectangle(0).x() > x);
2544 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2545 x = input.positionToRectangle(0).x();
2548 // Test incrementing the preedit cursor doesn't cause further
2549 // scrolling when right most text is visible.
2550 sendPreeditText(preeditText, preeditText.length() - 3);
2551 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2552 x = input.positionToRectangle(0).x();
2553 for (int i = 2; i >= 0; --i) {
2554 sendPreeditText(preeditText, preeditText.length() - i);
2555 QCOMPARE(input.positionToRectangle(0).x(), x);
2556 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2558 for (int i = 1; i < 3; ++i) {
2559 sendPreeditText(preeditText, preeditText.length() - i);
2560 QCOMPARE(input.positionToRectangle(0).x(), x);
2561 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2564 // Test disabling auto scroll.
2565 QApplication::sendEvent(&view, &emptyEvent);
2567 input.setAutoScroll(false);
2568 sendPreeditText(preeditText.mid(0, 3), 1);
2569 QCOMPARE(input.positionAt(0), 0);
2570 QCOMPARE(input.positionAt(input.width()), 5);
2572 QApplication::sendEvent(&view, &emptyEvent);
2573 input.setAutoScroll(true);
2574 // Test committing pre-edit text at the start of the string. QTBUG-18789
2575 input.setCursorPosition(0);
2576 sendPreeditText(input.text(), 5);
2577 QCOMPARE(input.positionAt(0), 0);
2579 QInputMethodEvent event;
2580 event.setCommitString(input.text());
2581 QApplication::sendEvent(&view, &emptyEvent);
2583 QCOMPARE(input.positionAt(0), 0);
2584 QCOMPARE(input.positionAt(input.width()), 5);
2587 void tst_qdeclarativetextinput::preeditMicroFocus()
2589 QString preeditText = "super";
2590 PlatformInputContext ic;
2591 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
2592 inputPanelPrivate->testContext = ⁣
2594 QGraphicsScene scene;
2595 QGraphicsView view(&scene);
2596 QDeclarative1TextInput input;
2598 input.setAutoScroll(false);
2599 input.setFocus(true);
2600 scene.addItem(&input);
2602 QApplication::setActiveWindow(&view);
2603 QTest::qWaitForWindowShown(&view);
2604 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2607 QRect previousRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2609 // Verify that the micro focus rect is positioned the same for position 0 as
2610 // it would be if there was no preedit text.
2612 sendPreeditText(preeditText, 0);
2613 currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2614 QCOMPARE(currentRect, previousRect);
2615 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
2616 QVERIFY(ic.updateCallCount > 0);
2619 // Verify that the micro focus rect moves to the left as the cursor position
2621 for (int i = 1; i <= 5; ++i) {
2623 sendPreeditText(preeditText, i);
2624 currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2625 QVERIFY(previousRect.left() < currentRect.left());
2626 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
2627 QVERIFY(ic.updateCallCount > 0);
2629 previousRect = currentRect;
2632 // Verify that if there is no preedit cursor then the micro focus rect is the
2633 // same as it would be if it were positioned at the end of the preedit text.
2634 sendPreeditText(preeditText, 0);
2636 QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
2637 QApplication::sendEvent(qApp->inputPanel()->inputItem(), &imEvent);
2638 currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2639 QCOMPARE(currentRect, previousRect);
2640 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
2641 QVERIFY(ic.updateCallCount > 0);
2645 void tst_qdeclarativetextinput::inputContextMouseHandler()
2647 PlatformInputContext platformInputContext;
2648 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
2649 inputPanelPrivate->testContext = &platformInputContext;
2651 QString text = "supercalifragisiticexpialidocious!";
2653 QGraphicsScene scene;
2654 QGraphicsView view(&scene);
2656 QDeclarative1TextInput input;
2657 input.setWidth(200);
2658 input.setCursorPosition(12);
2660 input.setFocus(true);
2661 scene.addItem(&input);
2663 QApplication::setActiveWindow(&view);
2664 QTest::qWaitForWindowShown(&view);
2665 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2667 QFontMetricsF fm(input.font());
2668 const qreal y = fm.height() / 2;
2670 QPoint position2 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 2)), y)));
2672 QInputMethodEvent inputEvent(text.mid(0, 5), QList<QInputMethodEvent::Attribute>());
2673 QApplication::sendEvent(&view, &inputEvent);
2675 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
2676 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
2677 QApplication::processEvents();
2679 QCOMPARE(platformInputContext.m_action, QInputPanel::Click);
2680 QCOMPARE(platformInputContext.m_invokeActionCallCount, 1);
2681 QCOMPARE(platformInputContext.m_cursorPosition, 2);
2684 void tst_qdeclarativetextinput::inputMethodComposing()
2686 QString text = "supercalifragisiticexpialidocious!";
2688 QGraphicsScene scene;
2689 QGraphicsView view(&scene);
2690 QDeclarative1TextInput input;
2691 input.setWidth(200);
2692 input.setText(text.mid(0, 12));
2693 input.setCursorPosition(12);
2695 input.setFocus(true);
2696 scene.addItem(&input);
2698 QApplication::setActiveWindow(&view);
2699 QTest::qWaitForWindowShown(&view);
2700 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2702 QSignalSpy spy(&input, SIGNAL(inputMethodComposingChanged()));
2704 QCOMPARE(input.isInputMethodComposing(), false);
2707 QInputMethodEvent inputEvent(text.mid(3), QList<QInputMethodEvent::Attribute>());
2708 QApplication::sendEvent(qApp->inputPanel()->inputItem(), &inputEvent);
2711 QCOMPARE(input.isInputMethodComposing(), true);
2712 QCOMPARE(spy.count(), 1);
2715 QInputMethodEvent inputEvent(text.mid(12), QList<QInputMethodEvent::Attribute>());
2716 QApplication::sendEvent(qApp->inputPanel()->inputItem(), &inputEvent);
2719 QCOMPARE(input.isInputMethodComposing(), true);
2720 QCOMPARE(spy.count(), 1);
2723 QInputMethodEvent inputEvent;
2724 QApplication::sendEvent(qApp->inputPanel()->inputItem(), &inputEvent);
2726 QCOMPARE(input.isInputMethodComposing(), false);
2727 QCOMPARE(spy.count(), 2);
2730 void tst_qdeclarativetextinput::cursorRectangleSize()
2732 QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml");
2733 QVERIFY(canvas->rootObject() != 0);
2736 QApplication::setActiveWindow(canvas);
2737 QTest::qWaitForWindowShown(canvas);
2739 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
2740 QVERIFY(textInput != 0);
2741 textInput->setFocus(Qt::OtherFocusReason);
2742 QRectF cursorRect = textInput->positionToRectangle(textInput->cursorPosition());
2743 QRectF microFocusFromScene = canvas->scene()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
2744 QRectF microFocusFromApp= QApplication::focusWidget()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
2746 QCOMPARE(microFocusFromScene.size(), cursorRect.size());
2747 QCOMPARE(microFocusFromApp.size(), cursorRect.size());
2750 QTEST_MAIN(tst_qdeclarativetextinput)
2752 #include "tst_qdeclarativetextinput.moc"