1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtTest/QSignalSpy>
43 #include "../../../shared/util.h"
44 #include <QtDeclarative/qdeclarativeengine.h>
46 #include <QtQuick1/qdeclarativeview.h>
47 #include <QtQuick1/private/qdeclarativetextinput_p.h>
48 #include <QtQuick1/private/qdeclarativetextinput_p_p.h>
52 #include <QInputContext>
53 #include <QtWidgets/5.0.0/QtWidgets/private/qapplication_p.h>
56 // In Symbian OS test data is located in applications private dir
60 Q_DECLARE_METATYPE(QDeclarative1TextInput::SelectionMode)
62 QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
64 // XXX This will be replaced by some clever persistent platform image store.
65 QString persistent_dir = SRCDIR "/data";
66 QString arch = "unknown-architecture"; // QTest needs to help with this.
68 QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png";
70 if (!QFile::exists(expectfile)) {
71 actual.save(expectfile);
72 qWarning() << "created" << expectfile;
78 class tst_qdeclarativetextinput : public QObject
83 tst_qdeclarativetextinput();
92 void isRightToLeft_data();
94 void moveCursorSelection_data();
95 void moveCursorSelection();
96 void moveCursorSelectionSequence_data();
97 void moveCursorSelectionSequence();
98 void mouseSelection_data();
99 void mouseSelection();
100 void deferEnableSelectByMouse_data();
101 void deferEnableSelectByMouse();
102 void deferDisableSelectByMouse_data();
103 void deferDisableSelectByMouse();
104 void dragMouseSelection();
105 void mouseSelectionMode_data();
106 void mouseSelectionMode();
108 void horizontalAlignment_data();
109 void horizontalAlignment();
110 void horizontalAlignment_RightToLeft();
119 void passwordCharacter();
120 void cursorDelegate();
121 void cursorVisible();
122 void cursorRectangle();
124 void navigation_RTL();
126 void canPasteEmpty();
130 void openInputPanelOnClick();
131 void openInputPanelOnFocus();
132 void setHAlignClearCache();
133 void focusOutClearSelection();
136 void geometrySignals();
137 void testQtQuick11Attributes();
138 void testQtQuick11Attributes_data();
140 void preeditAutoScroll();
141 void preeditMicroFocus();
142 void inputContextMouseHandler();
143 void inputMethodComposing();
144 void cursorRectangleSize();
147 void simulateKey(QDeclarativeView *, int key);
148 QDeclarativeView *createView(const QString &filename);
150 QDeclarativeEngine engine;
151 QStringList standard;
152 QStringList colorStrings;
155 tst_qdeclarativetextinput::tst_qdeclarativetextinput()
157 standard << "the quick brown fox jumped over the lazy dog"
158 << "It's supercalifragisiticexpialidocious!"
163 colorStrings << "aliceblue"
177 void tst_qdeclarativetextinput::text()
180 QDeclarativeComponent textinputComponent(&engine);
181 textinputComponent.setData("import QtQuick 1.0\nTextInput { text: \"\" }", QUrl());
182 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
184 QVERIFY(textinputObject != 0);
185 QCOMPARE(textinputObject->text(), QString(""));
187 delete textinputObject;
190 for (int i = 0; i < standard.size(); i++)
192 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"" + standard.at(i) + "\" }";
193 QDeclarativeComponent textinputComponent(&engine);
194 textinputComponent.setData(componentStr.toLatin1(), QUrl());
195 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
197 QVERIFY(textinputObject != 0);
198 QCOMPARE(textinputObject->text(), standard.at(i));
200 delete textinputObject;
205 void tst_qdeclarativetextinput::width()
207 // uses Font metrics to find the width for standard
209 QDeclarativeComponent textinputComponent(&engine);
210 textinputComponent.setData("import QtQuick 1.0\nTextInput { text: \"\" }", QUrl());
211 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
213 QVERIFY(textinputObject != 0);
214 QCOMPARE(textinputObject->width(), 0.0);
216 delete textinputObject;
219 for (int i = 0; i < standard.size(); i++)
223 qreal metricWidth = fm.width(standard.at(i));
225 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"" + standard.at(i) + "\" }";
226 QDeclarativeComponent textinputComponent(&engine);
227 textinputComponent.setData(componentStr.toLatin1(), QUrl());
228 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
230 QVERIFY(textinputObject != 0);
231 int delta = abs(int(int(textinputObject->width()) - metricWidth));
232 QVERIFY(delta <= 3.0); // As best as we can hope for cross-platform.
234 delete textinputObject;
238 void tst_qdeclarativetextinput::font()
240 //test size, then bold, then italic, then family
242 QString componentStr = "import QtQuick 1.0\nTextInput { font.pointSize: 40; text: \"Hello World\" }";
243 QDeclarativeComponent textinputComponent(&engine);
244 textinputComponent.setData(componentStr.toLatin1(), QUrl());
245 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
247 QVERIFY(textinputObject != 0);
248 QCOMPARE(textinputObject->font().pointSize(), 40);
249 QCOMPARE(textinputObject->font().bold(), false);
250 QCOMPARE(textinputObject->font().italic(), false);
252 delete textinputObject;
256 QString componentStr = "import QtQuick 1.0\nTextInput { font.bold: true; text: \"Hello World\" }";
257 QDeclarativeComponent textinputComponent(&engine);
258 textinputComponent.setData(componentStr.toLatin1(), QUrl());
259 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
261 QVERIFY(textinputObject != 0);
262 QCOMPARE(textinputObject->font().bold(), true);
263 QCOMPARE(textinputObject->font().italic(), false);
265 delete textinputObject;
269 QString componentStr = "import QtQuick 1.0\nTextInput { font.italic: true; text: \"Hello World\" }";
270 QDeclarativeComponent textinputComponent(&engine);
271 textinputComponent.setData(componentStr.toLatin1(), QUrl());
272 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
274 QVERIFY(textinputObject != 0);
275 QCOMPARE(textinputObject->font().italic(), true);
276 QCOMPARE(textinputObject->font().bold(), false);
278 delete textinputObject;
282 QString componentStr = "import QtQuick 1.0\nTextInput { font.family: \"Helvetica\"; text: \"Hello World\" }";
283 QDeclarativeComponent textinputComponent(&engine);
284 textinputComponent.setData(componentStr.toLatin1(), QUrl());
285 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
287 QVERIFY(textinputObject != 0);
288 QCOMPARE(textinputObject->font().family(), QString("Helvetica"));
289 QCOMPARE(textinputObject->font().bold(), false);
290 QCOMPARE(textinputObject->font().italic(), false);
292 delete textinputObject;
296 QString componentStr = "import QtQuick 1.0\nTextInput { font.family: \"\"; text: \"Hello World\" }";
297 QDeclarativeComponent textinputComponent(&engine);
298 textinputComponent.setData(componentStr.toLatin1(), QUrl());
299 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
301 QVERIFY(textinputObject != 0);
302 QCOMPARE(textinputObject->font().family(), QString(""));
304 delete textinputObject;
308 void tst_qdeclarativetextinput::color()
311 for (int i = 0; i < colorStrings.size(); i++)
313 QString componentStr = "import QtQuick 1.0\nTextInput { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
314 QDeclarativeComponent textinputComponent(&engine);
315 textinputComponent.setData(componentStr.toLatin1(), QUrl());
316 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
317 QVERIFY(textinputObject != 0);
318 QCOMPARE(textinputObject->color(), QColor(colorStrings.at(i)));
320 delete textinputObject;
323 //test selection color
324 for (int i = 0; i < colorStrings.size(); i++)
326 QString componentStr = "import QtQuick 1.0\nTextInput { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
327 QDeclarativeComponent textinputComponent(&engine);
328 textinputComponent.setData(componentStr.toLatin1(), QUrl());
329 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
330 QVERIFY(textinputObject != 0);
331 QCOMPARE(textinputObject->selectionColor(), QColor(colorStrings.at(i)));
333 delete textinputObject;
336 //test selected text color
337 for (int i = 0; i < colorStrings.size(); i++)
339 QString componentStr = "import QtQuick 1.0\nTextInput { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
340 QDeclarativeComponent textinputComponent(&engine);
341 textinputComponent.setData(componentStr.toLatin1(), QUrl());
342 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
343 QVERIFY(textinputObject != 0);
344 QCOMPARE(textinputObject->selectedTextColor(), QColor(colorStrings.at(i)));
346 delete textinputObject;
350 QString colorStr = "#AA001234";
351 QColor testColor("#001234");
352 testColor.setAlpha(170);
354 QString componentStr = "import QtQuick 1.0\nTextInput { color: \"" + colorStr + "\"; text: \"Hello World\" }";
355 QDeclarativeComponent textinputComponent(&engine);
356 textinputComponent.setData(componentStr.toLatin1(), QUrl());
357 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
359 QVERIFY(textinputObject != 0);
360 QCOMPARE(textinputObject->color(), testColor);
362 delete textinputObject;
366 void tst_qdeclarativetextinput::selection()
368 QString testStr = standard[0];
369 QString componentStr = "import QtQuick 1.0\nTextInput { text: \""+ testStr +"\"; }";
370 QDeclarativeComponent textinputComponent(&engine);
371 textinputComponent.setData(componentStr.toLatin1(), QUrl());
372 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
373 QVERIFY(textinputObject != 0);
376 //Test selection follows cursor
377 for(int i=0; i<= testStr.size(); i++) {
378 textinputObject->setCursorPosition(i);
379 QCOMPARE(textinputObject->cursorPosition(), i);
380 QCOMPARE(textinputObject->selectionStart(), i);
381 QCOMPARE(textinputObject->selectionEnd(), i);
382 QVERIFY(textinputObject->selectedText().isNull());
384 //Test cursor follows selection
385 for(int i=0; i<= testStr.size(); i++) {
386 textinputObject->select(i,i);
387 QCOMPARE(textinputObject->cursorPosition(), i);
388 QCOMPARE(textinputObject->selectionStart(), i);
389 QCOMPARE(textinputObject->selectionEnd(), i);
392 textinputObject->setCursorPosition(0);
393 QVERIFY(textinputObject->cursorPosition() == 0);
394 QVERIFY(textinputObject->selectionStart() == 0);
395 QVERIFY(textinputObject->selectionEnd() == 0);
396 QVERIFY(textinputObject->selectedText().isNull());
398 // Verify invalid positions are ignored.
399 textinputObject->setCursorPosition(-1);
400 QVERIFY(textinputObject->cursorPosition() == 0);
401 QVERIFY(textinputObject->selectionStart() == 0);
402 QVERIFY(textinputObject->selectionEnd() == 0);
403 QVERIFY(textinputObject->selectedText().isNull());
405 textinputObject->setCursorPosition(textinputObject->text().count()+1);
406 QVERIFY(textinputObject->cursorPosition() == 0);
407 QVERIFY(textinputObject->selectionStart() == 0);
408 QVERIFY(textinputObject->selectionEnd() == 0);
409 QVERIFY(textinputObject->selectedText().isNull());
412 for(int i=0; i<= testStr.size(); i++) {
413 textinputObject->select(0,i);
414 QCOMPARE(testStr.mid(0,i), textinputObject->selectedText());
415 QCOMPARE(textinputObject->cursorPosition(), i);
417 for(int i=0; i<= testStr.size(); i++) {
418 textinputObject->select(i,testStr.size());
419 QCOMPARE(testStr.mid(i,testStr.size()-i), textinputObject->selectedText());
420 QCOMPARE(textinputObject->cursorPosition(), testStr.size());
423 textinputObject->setCursorPosition(0);
424 QVERIFY(textinputObject->cursorPosition() == 0);
425 QVERIFY(textinputObject->selectionStart() == 0);
426 QVERIFY(textinputObject->selectionEnd() == 0);
427 QVERIFY(textinputObject->selectedText().isNull());
429 //Test Error Ignoring behaviour
430 textinputObject->setCursorPosition(0);
431 QVERIFY(textinputObject->selectedText().isNull());
432 textinputObject->select(-10,0);
433 QVERIFY(textinputObject->selectedText().isNull());
434 textinputObject->select(100,110);
435 QVERIFY(textinputObject->selectedText().isNull());
436 textinputObject->select(0,-10);
437 QVERIFY(textinputObject->selectedText().isNull());
438 textinputObject->select(0,100);
439 QVERIFY(textinputObject->selectedText().isNull());
440 textinputObject->select(0,10);
441 QVERIFY(textinputObject->selectedText().size() == 10);
442 textinputObject->select(-10,10);
443 QVERIFY(textinputObject->selectedText().size() == 10);
444 textinputObject->select(100,101);
445 QVERIFY(textinputObject->selectedText().size() == 10);
446 textinputObject->select(0,-10);
447 QVERIFY(textinputObject->selectedText().size() == 10);
448 textinputObject->select(0,100);
449 QVERIFY(textinputObject->selectedText().size() == 10);
451 textinputObject->deselect();
452 QVERIFY(textinputObject->selectedText().isNull());
453 textinputObject->select(0,10);
454 QVERIFY(textinputObject->selectedText().size() == 10);
455 textinputObject->deselect();
456 QVERIFY(textinputObject->selectedText().isNull());
458 delete textinputObject;
461 void tst_qdeclarativetextinput::isRightToLeft_data()
463 QTest::addColumn<QString>("text");
464 QTest::addColumn<bool>("emptyString");
465 QTest::addColumn<bool>("firstCharacter");
466 QTest::addColumn<bool>("lastCharacter");
467 QTest::addColumn<bool>("middleCharacter");
468 QTest::addColumn<bool>("startString");
469 QTest::addColumn<bool>("midString");
470 QTest::addColumn<bool>("endString");
472 const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
473 QTest::newRow("Empty") << "" << false << false << false << false << false << false << false;
474 QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false;
475 QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false;
476 QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true;
477 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;
478 QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false;
481 void tst_qdeclarativetextinput::isRightToLeft()
483 QFETCH(QString, text);
484 QFETCH(bool, emptyString);
485 QFETCH(bool, firstCharacter);
486 QFETCH(bool, lastCharacter);
487 QFETCH(bool, middleCharacter);
488 QFETCH(bool, startString);
489 QFETCH(bool, midString);
490 QFETCH(bool, endString);
492 QDeclarative1TextInput textInput;
493 textInput.setText(text);
495 // first test that the right string is delivered to the QString::isRightToLeft()
496 QCOMPARE(textInput.isRightToLeft(0,0), text.mid(0,0).isRightToLeft());
497 QCOMPARE(textInput.isRightToLeft(0,1), text.mid(0,1).isRightToLeft());
498 QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft());
499 QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft());
500 QCOMPARE(textInput.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft());
501 QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft());
503 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
504 QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft());
506 // then test that the feature actually works
507 QCOMPARE(textInput.isRightToLeft(0,0), emptyString);
508 QCOMPARE(textInput.isRightToLeft(0,1), firstCharacter);
509 QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), lastCharacter);
510 QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter);
511 QCOMPARE(textInput.isRightToLeft(0,text.count()/4), startString);
512 QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), midString);
514 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
515 QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), endString);
518 void tst_qdeclarativetextinput::moveCursorSelection_data()
520 QTest::addColumn<QString>("testStr");
521 QTest::addColumn<int>("cursorPosition");
522 QTest::addColumn<int>("movePosition");
523 QTest::addColumn<QDeclarative1TextInput::SelectionMode>("mode");
524 QTest::addColumn<int>("selectionStart");
525 QTest::addColumn<int>("selectionEnd");
526 QTest::addColumn<bool>("reversible");
528 // () contains the text selected by the cursor.
529 // <> contains the actual selection.
531 QTest::newRow("(t)he|characters")
532 << standard[0] << 0 << 1 << QDeclarative1TextInput::SelectCharacters << 0 << 1 << true;
533 QTest::newRow("do(g)|characters")
534 << standard[0] << 43 << 44 << QDeclarative1TextInput::SelectCharacters << 43 << 44 << true;
535 QTest::newRow("jum(p)ed|characters")
536 << standard[0] << 23 << 24 << QDeclarative1TextInput::SelectCharacters << 23 << 24 << true;
537 QTest::newRow("jumped( )over|characters")
538 << standard[0] << 26 << 27 << QDeclarative1TextInput::SelectCharacters << 26 << 27 << true;
539 QTest::newRow("(the )|characters")
540 << standard[0] << 0 << 4 << QDeclarative1TextInput::SelectCharacters << 0 << 4 << true;
541 QTest::newRow("( dog)|characters")
542 << standard[0] << 40 << 44 << QDeclarative1TextInput::SelectCharacters << 40 << 44 << true;
543 QTest::newRow("( jumped )|characters")
544 << standard[0] << 19 << 27 << QDeclarative1TextInput::SelectCharacters << 19 << 27 << true;
545 QTest::newRow("th(e qu)ick|characters")
546 << standard[0] << 2 << 6 << QDeclarative1TextInput::SelectCharacters << 2 << 6 << true;
547 QTest::newRow("la(zy d)og|characters")
548 << standard[0] << 38 << 42 << QDeclarative1TextInput::SelectCharacters << 38 << 42 << true;
549 QTest::newRow("jum(ped ov)er|characters")
550 << standard[0] << 23 << 29 << QDeclarative1TextInput::SelectCharacters << 23 << 29 << true;
551 QTest::newRow("()the|characters")
552 << standard[0] << 0 << 0 << QDeclarative1TextInput::SelectCharacters << 0 << 0 << true;
553 QTest::newRow("dog()|characters")
554 << standard[0] << 44 << 44 << QDeclarative1TextInput::SelectCharacters << 44 << 44 << true;
555 QTest::newRow("jum()ped|characters")
556 << standard[0] << 23 << 23 << QDeclarative1TextInput::SelectCharacters << 23 << 23 << true;
558 QTest::newRow("<(t)he>|words")
559 << standard[0] << 0 << 1 << QDeclarative1TextInput::SelectWords << 0 << 3 << true;
560 QTest::newRow("<do(g)>|words")
561 << standard[0] << 43 << 44 << QDeclarative1TextInput::SelectWords << 41 << 44 << true;
562 QTest::newRow("<jum(p)ed>|words")
563 << standard[0] << 23 << 24 << QDeclarative1TextInput::SelectWords << 20 << 26 << true;
564 QTest::newRow("<jumped( )>over|words,ltr")
565 << standard[0] << 26 << 27 << QDeclarative1TextInput::SelectWords << 20 << 27 << false;
566 QTest::newRow("jumped<( )over>|words,rtl")
567 << standard[0] << 27 << 26 << QDeclarative1TextInput::SelectWords << 26 << 31 << false;
568 QTest::newRow("<(the )>quick|words,ltr")
569 << standard[0] << 0 << 4 << QDeclarative1TextInput::SelectWords << 0 << 4 << false;
570 QTest::newRow("<(the )quick>|words,rtl")
571 << standard[0] << 4 << 0 << QDeclarative1TextInput::SelectWords << 0 << 9 << false;
572 QTest::newRow("<lazy( dog)>|words,ltr")
573 << standard[0] << 40 << 44 << QDeclarative1TextInput::SelectWords << 36 << 44 << false;
574 QTest::newRow("lazy<( dog)>|words,rtl")
575 << standard[0] << 44 << 40 << QDeclarative1TextInput::SelectWords << 40 << 44 << false;
576 QTest::newRow("<fox( jumped )>over|words,ltr")
577 << standard[0] << 19 << 27 << QDeclarative1TextInput::SelectWords << 16 << 27 << false;
578 QTest::newRow("fox<( jumped )over>|words,rtl")
579 << standard[0] << 27 << 19 << QDeclarative1TextInput::SelectWords << 19 << 31 << false;
580 QTest::newRow("<th(e qu)ick>|words")
581 << standard[0] << 2 << 6 << QDeclarative1TextInput::SelectWords << 0 << 9 << true;
582 QTest::newRow("<la(zy d)og|words>")
583 << standard[0] << 38 << 42 << QDeclarative1TextInput::SelectWords << 36 << 44 << true;
584 QTest::newRow("<jum(ped ov)er>|words")
585 << standard[0] << 23 << 29 << QDeclarative1TextInput::SelectWords << 20 << 31 << true;
586 QTest::newRow("<()>the|words")
587 << standard[0] << 0 << 0 << QDeclarative1TextInput::SelectWords << 0 << 0 << true;
588 QTest::newRow("dog<()>|words")
589 << standard[0] << 44 << 44 << QDeclarative1TextInput::SelectWords << 44 << 44 << true;
590 QTest::newRow("jum<()>ped|words")
591 << standard[0] << 23 << 23 << QDeclarative1TextInput::SelectWords << 23 << 23 << true;
593 QTest::newRow("Hello<(,)> |words")
594 << standard[2] << 5 << 6 << QDeclarative1TextInput::SelectWords << 5 << 6 << true;
595 QTest::newRow("Hello<(, )>world|words,ltr")
596 << standard[2] << 5 << 7 << QDeclarative1TextInput::SelectWords << 5 << 7 << false;
597 QTest::newRow("Hello<(, )world>|words,rtl")
598 << standard[2] << 7 << 5 << QDeclarative1TextInput::SelectWords << 5 << 12 << false;
599 QTest::newRow("<Hel(lo, )>world|words,ltr")
600 << standard[2] << 3 << 7 << QDeclarative1TextInput::SelectWords << 0 << 7 << false;
601 QTest::newRow("<Hel(lo, )world>|words,rtl")
602 << standard[2] << 7 << 3 << QDeclarative1TextInput::SelectWords << 0 << 12 << false;
603 QTest::newRow("<Hel(lo)>,|words")
604 << standard[2] << 3 << 5 << QDeclarative1TextInput::SelectWords << 0 << 5 << true;
605 QTest::newRow("Hello<()>,|words")
606 << standard[2] << 5 << 5 << QDeclarative1TextInput::SelectWords << 5 << 5 << true;
607 QTest::newRow("Hello,<()>|words")
608 << standard[2] << 6 << 6 << QDeclarative1TextInput::SelectWords << 6 << 6 << true;
609 QTest::newRow("Hello<,( )>world|words,ltr")
610 << standard[2] << 6 << 7 << QDeclarative1TextInput::SelectWords << 5 << 7 << false;
611 QTest::newRow("Hello,<( )world>|words,rtl")
612 << standard[2] << 7 << 6 << QDeclarative1TextInput::SelectWords << 6 << 12 << false;
613 QTest::newRow("Hello<,( world)>|words,ltr")
614 << standard[2] << 6 << 12 << QDeclarative1TextInput::SelectWords << 5 << 12 << false;
615 QTest::newRow("Hello,<( world)>|words,rtl")
616 << standard[2] << 12 << 6 << QDeclarative1TextInput::SelectWords << 6 << 12 << false;
617 QTest::newRow("Hello<,( world!)>|words,ltr")
618 << standard[2] << 6 << 13 << QDeclarative1TextInput::SelectWords << 5 << 13 << false;
619 QTest::newRow("Hello,<( world!)>|words,rtl")
620 << standard[2] << 13 << 6 << QDeclarative1TextInput::SelectWords << 6 << 13 << false;
621 QTest::newRow("Hello<(, world!)>|words")
622 << standard[2] << 5 << 13 << QDeclarative1TextInput::SelectWords << 5 << 13 << true;
623 QTest::newRow("world<(!)>|words")
624 << standard[2] << 12 << 13 << QDeclarative1TextInput::SelectWords << 12 << 13 << true;
625 QTest::newRow("world!<()>)|words")
626 << standard[2] << 13 << 13 << QDeclarative1TextInput::SelectWords << 13 << 13 << true;
627 QTest::newRow("world<()>!)|words")
628 << standard[2] << 12 << 12 << QDeclarative1TextInput::SelectWords << 12 << 12 << true;
630 QTest::newRow("<(,)>olleH |words")
631 << standard[3] << 7 << 8 << QDeclarative1TextInput::SelectWords << 7 << 8 << true;
632 QTest::newRow("<dlrow( ,)>olleH|words,ltr")
633 << standard[3] << 6 << 8 << QDeclarative1TextInput::SelectWords << 1 << 8 << false;
634 QTest::newRow("dlrow<( ,)>olleH|words,rtl")
635 << standard[3] << 8 << 6 << QDeclarative1TextInput::SelectWords << 6 << 8 << false;
636 QTest::newRow("<dlrow( ,ol)leH>|words,ltr")
637 << standard[3] << 6 << 10 << QDeclarative1TextInput::SelectWords << 1 << 13 << false;
638 QTest::newRow("dlrow<( ,ol)leH>|words,rtl")
639 << standard[3] << 10 << 6 << QDeclarative1TextInput::SelectWords << 6 << 13 << false;
640 QTest::newRow(",<(ol)leH>,|words")
641 << standard[3] << 8 << 10 << QDeclarative1TextInput::SelectWords << 8 << 13 << true;
642 QTest::newRow(",<()>olleH|words")
643 << standard[3] << 8 << 8 << QDeclarative1TextInput::SelectWords << 8 << 8 << true;
644 QTest::newRow("<()>,olleH|words")
645 << standard[3] << 7 << 7 << QDeclarative1TextInput::SelectWords << 7 << 7 << true;
646 QTest::newRow("<dlrow( )>,olleH|words,ltr")
647 << standard[3] << 6 << 7 << QDeclarative1TextInput::SelectWords << 1 << 7 << false;
648 QTest::newRow("dlrow<( ),>olleH|words,rtl")
649 << standard[3] << 7 << 6 << QDeclarative1TextInput::SelectWords << 6 << 8 << false;
650 QTest::newRow("<(dlrow )>,olleH|words,ltr")
651 << standard[3] << 1 << 7 << QDeclarative1TextInput::SelectWords << 1 << 7 << false;
652 QTest::newRow("<(dlrow ),>olleH|words,rtl")
653 << standard[3] << 7 << 1 << QDeclarative1TextInput::SelectWords << 1 << 8 << false;
654 QTest::newRow("<(!dlrow )>,olleH|words,ltr")
655 << standard[3] << 0 << 7 << QDeclarative1TextInput::SelectWords << 0 << 7 << false;
656 QTest::newRow("<(!dlrow ),>olleH|words,rtl")
657 << standard[3] << 7 << 0 << QDeclarative1TextInput::SelectWords << 0 << 8 << false;
658 QTest::newRow("(!dlrow ,)olleH|words")
659 << standard[3] << 0 << 8 << QDeclarative1TextInput::SelectWords << 0 << 8 << true;
660 QTest::newRow("<(!)>dlrow|words")
661 << standard[3] << 0 << 1 << QDeclarative1TextInput::SelectWords << 0 << 1 << true;
662 QTest::newRow("<()>!dlrow|words")
663 << standard[3] << 0 << 0 << QDeclarative1TextInput::SelectWords << 0 << 0 << true;
664 QTest::newRow("!<()>dlrow|words")
665 << standard[3] << 1 << 1 << QDeclarative1TextInput::SelectWords << 1 << 1 << true;
667 QTest::newRow(" <s(pac)ey> text |words")
668 << standard[4] << 1 << 4 << QDeclarative1TextInput::SelectWords << 1 << 7 << true;
669 QTest::newRow(" spacey <t(ex)t> |words")
670 << standard[4] << 11 << 13 << QDeclarative1TextInput::SelectWords << 10 << 14 << true;
671 QTest::newRow("<( )>spacey text |words|ltr")
672 << standard[4] << 0 << 1 << QDeclarative1TextInput::SelectWords << 0 << 1 << false;
673 QTest::newRow("<( )spacey> text |words|rtl")
674 << standard[4] << 1 << 0 << QDeclarative1TextInput::SelectWords << 0 << 7 << false;
675 QTest::newRow("spacey <text( )>|words|ltr")
676 << standard[4] << 14 << 15 << QDeclarative1TextInput::SelectWords << 10 << 15 << false;
677 QTest::newRow("spacey text<( )>|words|rtl")
678 << standard[4] << 15 << 14 << QDeclarative1TextInput::SelectWords << 14 << 15 << false;
679 QTest::newRow("<()> spacey text |words")
680 << standard[4] << 0 << 0 << QDeclarative1TextInput::SelectWords << 0 << 0 << false;
681 QTest::newRow(" spacey text <()>|words")
682 << standard[4] << 15 << 15 << QDeclarative1TextInput::SelectWords << 15 << 15 << false;
685 void tst_qdeclarativetextinput::moveCursorSelection()
687 QFETCH(QString, testStr);
688 QFETCH(int, cursorPosition);
689 QFETCH(int, movePosition);
690 QFETCH(QDeclarative1TextInput::SelectionMode, mode);
691 QFETCH(int, selectionStart);
692 QFETCH(int, selectionEnd);
693 QFETCH(bool, reversible);
695 QString componentStr = "import QtQuick 1.1\nTextInput { text: \""+ testStr +"\"; }";
696 QDeclarativeComponent textinputComponent(&engine);
697 textinputComponent.setData(componentStr.toLatin1(), QUrl());
698 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
699 QVERIFY(textinputObject != 0);
701 textinputObject->setCursorPosition(cursorPosition);
702 textinputObject->moveCursorSelection(movePosition, mode);
704 QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
705 QCOMPARE(textinputObject->selectionStart(), selectionStart);
706 QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
709 textinputObject->setCursorPosition(movePosition);
710 textinputObject->moveCursorSelection(cursorPosition, mode);
712 QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
713 QCOMPARE(textinputObject->selectionStart(), selectionStart);
714 QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
717 delete textinputObject;
720 void tst_qdeclarativetextinput::moveCursorSelectionSequence_data()
722 QTest::addColumn<QString>("testStr");
723 QTest::addColumn<int>("cursorPosition");
724 QTest::addColumn<int>("movePosition1");
725 QTest::addColumn<int>("movePosition2");
726 QTest::addColumn<int>("selection1Start");
727 QTest::addColumn<int>("selection1End");
728 QTest::addColumn<int>("selection2Start");
729 QTest::addColumn<int>("selection2End");
731 // () contains the text selected by the cursor.
732 // <> contains the actual selection.
733 // ^ is the revised cursor position.
734 // {} contains the revised selection.
736 QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr")
741 QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl")
746 QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr")
751 QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl")
756 QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr")
761 QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl")
766 QTest::newRow("the {<quick() ^}bro)wn> fox|ltr")
771 QTest::newRow("the quick<( {^bro)wn>} fox|rtl")
776 QTest::newRow("the {<quick^}( bro)wn> fox|ltr")
781 QTest::newRow("the quick{<(^ bro)wn>} fox|rtl")
786 QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr")
791 QTest::newRow("the {<qui^ck}( 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{^ <quick}( bro)wn> fox|ltr")
811 QTest::newRow("the{^ <quick}( bro)wn> fox|rtl")
816 QTest::newRow("{t^he <quick}( bro)wn> fox|ltr")
821 QTest::newRow("{t^he <quick}( bro)wn> fox|rtl")
827 QTest::newRow("{<He(ll)o>, w^orld}!|ltr")
832 QTest::newRow("{<He(ll)o>, w^orld}!|rtl")
838 QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr")
843 QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl")
849 QTest::newRow("{<(^} sp)acey> text |ltr")
854 QTest::newRow("{<( ^}sp)acey> text |ltr")
859 QTest::newRow("<( {s^p)acey>} text |rtl")
864 QTest::newRow("<( {^sp)acey>} text |rtl")
870 QTest::newRow(" spacey <te(xt {^)>}|rtl")
875 QTest::newRow(" spacey <te(xt{^ )>}|rtl")
880 QTest::newRow(" spacey {<te(x^t} )>|ltr")
885 QTest::newRow(" spacey {<te(xt^} )>|ltr")
892 void tst_qdeclarativetextinput::moveCursorSelectionSequence()
894 QFETCH(QString, testStr);
895 QFETCH(int, cursorPosition);
896 QFETCH(int, movePosition1);
897 QFETCH(int, movePosition2);
898 QFETCH(int, selection1Start);
899 QFETCH(int, selection1End);
900 QFETCH(int, selection2Start);
901 QFETCH(int, selection2End);
903 QString componentStr = "import QtQuick 1.1\nTextInput { text: \""+ testStr +"\"; }";
904 QDeclarativeComponent textinputComponent(&engine);
905 textinputComponent.setData(componentStr.toLatin1(), QUrl());
906 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
907 QVERIFY(textinputObject != 0);
909 textinputObject->setCursorPosition(cursorPosition);
911 textinputObject->moveCursorSelection(movePosition1, QDeclarative1TextInput::SelectWords);
912 QCOMPARE(textinputObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start));
913 QCOMPARE(textinputObject->selectionStart(), selection1Start);
914 QCOMPARE(textinputObject->selectionEnd(), selection1End);
916 textinputObject->moveCursorSelection(movePosition2, QDeclarative1TextInput::SelectWords);
917 QCOMPARE(textinputObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start));
918 QCOMPARE(textinputObject->selectionStart(), selection2Start);
919 QCOMPARE(textinputObject->selectionEnd(), selection2End);
921 delete textinputObject;
924 void tst_qdeclarativetextinput::mouseSelection_data()
926 QTest::addColumn<QString>("qmlfile");
927 QTest::addColumn<bool>("expectSelection");
930 QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << true;
931 QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << false;
932 QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << false;
933 QTest::newRow("on word selection") << SRCDIR "/data/mouseselection_true_words.qml" << true;
934 QTest::newRow("off word selection") << SRCDIR "/data/mouseselection_false_words.qml" << false;
935 QTest::newRow("on read only") << SRCDIR "/data/mouseselection_true_readonly.qml" << true;
936 QTest::newRow("off read only") << SRCDIR "/data/mouseselection_false_readonly.qml" << false;
939 void tst_qdeclarativetextinput::mouseSelection()
941 QFETCH(QString, qmlfile);
942 QFETCH(bool, expectSelection);
944 QDeclarativeView *canvas = createView(qmlfile);
947 QApplication::setActiveWindow(canvas);
948 QTest::qWaitForWindowShown(canvas);
949 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
951 QVERIFY(canvas->rootObject() != 0);
952 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
953 QVERIFY(textInputObject != 0);
955 // press-and-drag-and-release from x1 to x2
958 int y = textInputObject->height()/2;
959 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
960 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
961 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
962 QApplication::sendEvent(canvas->viewport(), &mv);
963 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
964 QString str = textInputObject->selectedText();
966 QVERIFY(str.length() > 3); // don't reallly care *what* was selected (and it's too sensitive to platform)
968 QVERIFY(str.isEmpty());
970 // Clicking and shift to clicking between the same points should select the same text.
971 textInputObject->setCursorPosition(0);
972 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::NoModifier, canvas->mapFromScene(QPoint(x1,y)));
973 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::ShiftModifier, canvas->mapFromScene(QPoint(x2,y)));
974 QCOMPARE(textInputObject->selectedText(), str);
979 void tst_qdeclarativetextinput::deferEnableSelectByMouse_data()
981 QTest::addColumn<QString>("qmlfile");
983 QTest::newRow("writable") << SRCDIR "/data/mouseselection_false.qml";
984 QTest::newRow("read only") << SRCDIR "/data/mouseselection_false_readonly.qml";
987 void tst_qdeclarativetextinput::deferEnableSelectByMouse()
989 // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed.
990 QFETCH(QString, qmlfile);
992 QDeclarativeView *canvas = createView(qmlfile);
995 QApplication::setActiveWindow(canvas);
996 QTest::qWaitForWindowShown(canvas);
997 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
999 QVERIFY(canvas->rootObject() != 0);
1000 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1001 QVERIFY(textInputObject != 0);
1003 // press-and-drag-and-release from x1 to x2
1006 int y = textInputObject->height()/2;
1008 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1009 textInputObject->setSelectByMouse(true);
1010 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1011 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1012 QApplication::sendEvent(canvas->viewport(), &mv);
1013 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1014 QVERIFY(textInputObject->selectedText().isEmpty());
1019 void tst_qdeclarativetextinput::deferDisableSelectByMouse_data()
1021 QTest::addColumn<QString>("qmlfile");
1023 QTest::newRow("writable") << SRCDIR "/data/mouseselection_true.qml";
1024 QTest::newRow("read only") << SRCDIR "/data/mouseselection_true_readonly.qml";
1027 void tst_qdeclarativetextinput::deferDisableSelectByMouse()
1029 // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed.
1030 QFETCH(QString, qmlfile);
1032 QDeclarativeView *canvas = createView(qmlfile);
1035 QApplication::setActiveWindow(canvas);
1036 QTest::qWaitForWindowShown(canvas);
1037 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1039 QVERIFY(canvas->rootObject() != 0);
1040 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1041 QVERIFY(textInputObject != 0);
1043 // press-and-drag-and-release from x1 to x2
1046 int y = textInputObject->height()/2;
1048 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1049 textInputObject->setSelectByMouse(false);
1050 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1051 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1052 QApplication::sendEvent(canvas->viewport(), &mv);
1053 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1054 QVERIFY(textInputObject->selectedText().length() > 3);
1059 void tst_qdeclarativetextinput::dragMouseSelection()
1061 QString qmlfile = SRCDIR "/data/mouseselection_true.qml";
1063 QDeclarativeView *canvas = createView(qmlfile);
1066 QApplication::setActiveWindow(canvas);
1067 QTest::qWaitForWindowShown(canvas);
1068 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1070 QVERIFY(canvas->rootObject() != 0);
1071 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1072 QVERIFY(textInputObject != 0);
1074 // press-and-drag-and-release from x1 to x2
1077 int y = textInputObject->height()/2;
1078 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1080 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1081 QApplication::sendEvent(canvas->viewport(), &mv);
1083 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1085 QString str1 = textInputObject->selectedText();
1086 QVERIFY(str1.length() > 3);
1088 // press and drag the current selection.
1091 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1093 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1094 QApplication::sendEvent(canvas->viewport(), &mv);
1096 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1097 QString str2 = textInputObject->selectedText();
1098 QVERIFY(str2.length() > 3);
1100 QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved.
1104 void tst_qdeclarativetextinput::mouseSelectionMode_data()
1106 QTest::addColumn<QString>("qmlfile");
1107 QTest::addColumn<bool>("selectWords");
1110 QTest::newRow("SelectWords") << SRCDIR "/data/mouseselectionmode_words.qml" << true;
1111 QTest::newRow("SelectCharacters") << SRCDIR "/data/mouseselectionmode_characters.qml" << false;
1112 QTest::newRow("default") << SRCDIR "/data/mouseselectionmode_default.qml" << false;
1115 void tst_qdeclarativetextinput::mouseSelectionMode()
1117 QFETCH(QString, qmlfile);
1118 QFETCH(bool, selectWords);
1120 QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1122 QDeclarativeView *canvas = createView(qmlfile);
1125 QApplication::setActiveWindow(canvas);
1126 QTest::qWaitForWindowShown(canvas);
1127 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1129 QVERIFY(canvas->rootObject() != 0);
1130 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1131 QVERIFY(textInputObject != 0);
1133 // press-and-drag-and-release from x1 to x2
1136 int y = textInputObject->height()/2;
1137 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1138 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1139 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1140 QApplication::sendEvent(canvas->viewport(), &mv);
1141 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1142 QString str = textInputObject->selectedText();
1144 QCOMPARE(str, text);
1146 QVERIFY(str.length() > 3);
1147 QVERIFY(str != text);
1153 void tst_qdeclarativetextinput::horizontalAlignment_data()
1155 QTest::addColumn<int>("hAlign");
1156 QTest::addColumn<QString>("expectfile");
1158 QTest::newRow("L") << int(Qt::AlignLeft) << "halign_left";
1159 QTest::newRow("R") << int(Qt::AlignRight) << "halign_right";
1160 QTest::newRow("C") << int(Qt::AlignHCenter) << "halign_center";
1163 void tst_qdeclarativetextinput::horizontalAlignment()
1165 QFETCH(int, hAlign);
1166 QFETCH(QString, expectfile);
1168 QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment.qml");
1171 QApplication::setActiveWindow(canvas);
1172 QTest::qWaitForWindowShown(canvas);
1173 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1174 QObject *ob = canvas->rootObject();
1176 ob->setProperty("horizontalAlignment",hAlign);
1177 QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32);
1178 actual.fill(qRgb(255,255,255));
1180 QPainter p(&actual);
1184 expectfile = createExpectedFileIfNotFound(expectfile, actual);
1186 QImage expect(expectfile);
1188 QCOMPARE(actual,expect);
1193 void tst_qdeclarativetextinput::horizontalAlignment_RightToLeft()
1195 QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml");
1196 QDeclarative1TextInput *textInput = canvas->rootObject()->findChild<QDeclarative1TextInput*>("text");
1197 QVERIFY(textInput != 0);
1200 QDeclarative1TextInputPrivate *textInputPrivate = QDeclarative1TextInputPrivate::get(textInput);
1201 QVERIFY(textInputPrivate != 0);
1202 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1204 // implicit alignment should follow the reading direction of RTL text
1205 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1206 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1207 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1209 // explicitly left aligned
1210 textInput->setHAlign(QDeclarative1TextInput::AlignLeft);
1211 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1212 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1213 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1215 // explicitly right aligned
1216 textInput->setHAlign(QDeclarative1TextInput::AlignRight);
1217 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1218 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1219 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1221 // explicitly center aligned
1222 textInput->setHAlign(QDeclarative1TextInput::AlignHCenter);
1223 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1224 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignHCenter);
1225 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1226 QVERIFY(-textInputPrivate->hscroll + textInputPrivate->width() > canvas->width()/2);
1228 // reseted alignment should go back to following the text reading direction
1229 textInput->resetHAlign();
1230 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1231 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1232 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1234 // mirror the text item
1235 QDeclarativeItemPrivate::get(textInput)->setLayoutMirror(true);
1237 // mirrored implicit alignment should continue to follow the reading direction of the text
1238 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1239 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1240 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1242 // explicitly right aligned behaves as left aligned
1243 textInput->setHAlign(QDeclarative1TextInput::AlignRight);
1244 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1245 QCOMPARE(textInput->effectiveHAlign(), QDeclarative1TextInput::AlignLeft);
1246 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1248 // mirrored explicitly left aligned behaves as right aligned
1249 textInput->setHAlign(QDeclarative1TextInput::AlignLeft);
1250 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1251 QCOMPARE(textInput->effectiveHAlign(), QDeclarative1TextInput::AlignRight);
1252 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1254 // disable mirroring
1255 QDeclarativeItemPrivate::get(textInput)->setLayoutMirror(false);
1256 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1257 textInput->resetHAlign();
1259 // English text should be implicitly left aligned
1260 textInput->setText("Hello world!");
1261 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1262 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1264 #ifndef Q_OS_MAC // QTBUG-18040
1265 // empty text with implicit alignment follows the system locale-based
1266 // keyboard input direction from QApplication::keyboardInputDirection
1267 textInput->setText("");
1268 QCOMPARE(textInput->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
1269 QDeclarative1TextInput::AlignLeft : QDeclarative1TextInput::AlignRight);
1270 if (QApplication::keyboardInputDirection() == Qt::LeftToRight)
1271 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1273 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1274 textInput->setHAlign(QDeclarative1TextInput::AlignRight);
1275 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1276 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1281 #ifndef Q_OS_MAC // QTBUG-18040
1282 // alignment of TextInput with no text set to it
1283 QString componentStr = "import QtQuick 1.0\nTextInput {}";
1284 QDeclarativeComponent textComponent(&engine);
1285 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1286 QDeclarative1TextInput *textObject = qobject_cast<QDeclarative1TextInput*>(textComponent.create());
1287 QCOMPARE(textObject->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
1288 QDeclarative1TextInput::AlignLeft : QDeclarative1TextInput::AlignRight);
1293 void tst_qdeclarativetextinput::positionAt()
1295 QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml");
1296 QVERIFY(canvas->rootObject() != 0);
1299 QApplication::setActiveWindow(canvas);
1300 QTest::qWaitForWindowShown(canvas);
1302 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1303 QVERIFY(textinputObject != 0);
1305 // Check autoscrolled...
1306 QFontMetrics fm(textinputObject->font());
1308 int pos = textinputObject->positionAt(textinputObject->width()/2);
1309 int diff = abs(int(fm.width(textinputObject->text()) - (fm.width(textinputObject->text().left(pos))+textinputObject->width()/2)));
1311 // some tollerance for different fonts.
1318 int x = textinputObject->positionToRectangle(pos + 1).x() - 1;
1319 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorBetweenCharacters), pos + 1);
1320 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorOnCharacter), pos);
1322 // Check without autoscroll...
1323 textinputObject->setAutoScroll(false);
1324 pos = textinputObject->positionAt(textinputObject->width()/2);
1325 diff = abs(int(fm.width(textinputObject->text().left(pos))-textinputObject->width()/2));
1328 QEXPECT_FAIL("", "QTBUG-21017 fails", Continue);
1330 // some tollerance for different fonts.
1337 x = textinputObject->positionToRectangle(pos + 1).x() - 1;
1338 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorBetweenCharacters), pos + 1);
1339 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorOnCharacter), pos);
1341 const qreal x0 = textinputObject->positionToRectangle(pos).x();
1342 const qreal x1 = textinputObject->positionToRectangle(pos + 1).x();
1344 QString preeditText = textinputObject->text().mid(0, pos);
1345 textinputObject->setText(textinputObject->text().mid(pos));
1346 textinputObject->setCursorPosition(0);
1348 QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
1349 QApplication::sendEvent(canvas, &inputEvent);
1351 // Check all points within the preedit text return the same position.
1352 QCOMPARE(textinputObject->positionAt(0), 0);
1353 QCOMPARE(textinputObject->positionAt(x0 / 2), 0);
1354 QCOMPARE(textinputObject->positionAt(x0), 0);
1356 // Verify positioning returns to normal after the preedit text.
1357 QCOMPARE(textinputObject->positionAt(x1), 1);
1358 QCOMPARE(textinputObject->positionToRectangle(1).x(), x1);
1363 void tst_qdeclarativetextinput::maxLength()
1365 QDeclarativeView *canvas = createView(SRCDIR "/data/maxLength.qml");
1366 QVERIFY(canvas->rootObject() != 0);
1369 QApplication::setActiveWindow(canvas);
1370 QTest::qWaitForWindowShown(canvas);
1372 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1373 QVERIFY(textinputObject != 0);
1374 QVERIFY(textinputObject->text().isEmpty());
1375 QVERIFY(textinputObject->maxLength() == 10);
1376 foreach(const QString &str, standard){
1377 QVERIFY(textinputObject->text().length() <= 10);
1378 textinputObject->setText(str);
1379 QVERIFY(textinputObject->text().length() <= 10);
1382 textinputObject->setText("");
1383 QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
1384 for(int i=0; i<20; i++){
1385 QCOMPARE(textinputObject->text().length(), qMin(i,10));
1386 //simulateKey(canvas, Qt::Key_A);
1387 QTest::keyPress(canvas, Qt::Key_A);
1388 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1394 void tst_qdeclarativetextinput::masks()
1396 //Not a comprehensive test of the possible masks, that's done elsewhere (QLineEdit)
1397 //QString componentStr = "import QtQuick 1.0\nTextInput { inputMask: 'HHHHhhhh'; }";
1398 QDeclarativeView *canvas = createView(SRCDIR "/data/masks.qml");
1401 QVERIFY(canvas->rootObject() != 0);
1402 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1403 QVERIFY(textinputObject != 0);
1404 QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
1405 QVERIFY(textinputObject->text().length() == 0);
1406 QCOMPARE(textinputObject->inputMask(), QString("HHHHhhhh; "));
1407 for(int i=0; i<10; i++){
1408 QCOMPARE(qMin(i,8), textinputObject->text().length());
1409 QCOMPARE(i>=4, textinputObject->hasAcceptableInput());
1410 //simulateKey(canvas, Qt::Key_A);
1411 QTest::keyPress(canvas, Qt::Key_A);
1412 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1418 void tst_qdeclarativetextinput::validators()
1420 // Note that this test assumes that the validators are working properly
1421 // so you may need to run their tests first. All validators are checked
1422 // here to ensure that their exposure to QML is working.
1424 QDeclarativeView *canvas = createView(SRCDIR "/data/validators.qml");
1428 QVERIFY(canvas->rootObject() != 0);
1430 QDeclarative1TextInput *intInput = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("intInput")));
1432 intInput->setFocus(true);
1433 QTRY_VERIFY(intInput->hasActiveFocus());
1434 QTest::keyPress(canvas, Qt::Key_1);
1435 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1436 QCOMPARE(intInput->text(), QLatin1String("1"));
1437 QCOMPARE(intInput->hasAcceptableInput(), false);
1438 QTest::keyPress(canvas, Qt::Key_2);
1439 QTest::keyRelease(canvas, Qt::Key_2, Qt::NoModifier ,10);
1440 QCOMPARE(intInput->text(), QLatin1String("1"));
1441 QCOMPARE(intInput->hasAcceptableInput(), false);
1442 QTest::keyPress(canvas, Qt::Key_1);
1443 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1444 QCOMPARE(intInput->text(), QLatin1String("11"));
1445 QCOMPARE(intInput->hasAcceptableInput(), true);
1446 QTest::keyPress(canvas, Qt::Key_0);
1447 QTest::keyRelease(canvas, Qt::Key_0, Qt::NoModifier ,10);
1448 QCOMPARE(intInput->text(), QLatin1String("11"));
1449 QCOMPARE(intInput->hasAcceptableInput(), true);
1451 QDeclarative1TextInput *dblInput = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("dblInput")));
1452 QTRY_VERIFY(dblInput);
1453 dblInput->setFocus(true);
1454 QVERIFY(dblInput->hasActiveFocus() == true);
1455 QTest::keyPress(canvas, Qt::Key_1);
1456 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1457 QCOMPARE(dblInput->text(), QLatin1String("1"));
1458 QCOMPARE(dblInput->hasAcceptableInput(), false);
1459 QTest::keyPress(canvas, Qt::Key_2);
1460 QTest::keyRelease(canvas, Qt::Key_2, Qt::NoModifier ,10);
1461 QCOMPARE(dblInput->text(), QLatin1String("12"));
1462 QCOMPARE(dblInput->hasAcceptableInput(), true);
1463 QTest::keyPress(canvas, Qt::Key_Period);
1464 QTest::keyRelease(canvas, Qt::Key_Period, Qt::NoModifier ,10);
1465 QCOMPARE(dblInput->text(), QLatin1String("12."));
1466 QCOMPARE(dblInput->hasAcceptableInput(), true);
1467 QTest::keyPress(canvas, Qt::Key_1);
1468 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1469 QCOMPARE(dblInput->text(), QLatin1String("12.1"));
1470 QCOMPARE(dblInput->hasAcceptableInput(), true);
1471 QTest::keyPress(canvas, Qt::Key_1);
1472 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1473 QCOMPARE(dblInput->text(), QLatin1String("12.11"));
1474 QCOMPARE(dblInput->hasAcceptableInput(), true);
1475 QTest::keyPress(canvas, Qt::Key_1);
1476 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1477 QCOMPARE(dblInput->text(), QLatin1String("12.11"));
1478 QCOMPARE(dblInput->hasAcceptableInput(), true);
1480 QDeclarative1TextInput *strInput = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("strInput")));
1481 QTRY_VERIFY(strInput);
1482 strInput->setFocus(true);
1483 QVERIFY(strInput->hasActiveFocus() == true);
1484 QTest::keyPress(canvas, Qt::Key_1);
1485 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1486 QCOMPARE(strInput->text(), QLatin1String(""));
1487 QCOMPARE(strInput->hasAcceptableInput(), false);
1488 QTest::keyPress(canvas, Qt::Key_A);
1489 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1490 QCOMPARE(strInput->text(), QLatin1String("a"));
1491 QCOMPARE(strInput->hasAcceptableInput(), false);
1492 QTest::keyPress(canvas, Qt::Key_A);
1493 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1494 QCOMPARE(strInput->text(), QLatin1String("aa"));
1495 QCOMPARE(strInput->hasAcceptableInput(), true);
1496 QTest::keyPress(canvas, Qt::Key_A);
1497 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1498 QCOMPARE(strInput->text(), QLatin1String("aaa"));
1499 QCOMPARE(strInput->hasAcceptableInput(), true);
1500 QTest::keyPress(canvas, Qt::Key_A);
1501 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1502 QCOMPARE(strInput->text(), QLatin1String("aaaa"));
1503 QCOMPARE(strInput->hasAcceptableInput(), true);
1504 QTest::keyPress(canvas, Qt::Key_A);
1505 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1506 QCOMPARE(strInput->text(), QLatin1String("aaaa"));
1507 QCOMPARE(strInput->hasAcceptableInput(), true);
1512 void tst_qdeclarativetextinput::inputMethods()
1514 QDeclarativeView *canvas = createView(SRCDIR "/data/inputmethods.qml");
1517 QApplication::setActiveWindow(canvas);
1518 QTest::qWaitForWindowShown(canvas);
1520 // test input method hints
1521 QVERIFY(canvas->rootObject() != 0);
1522 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1523 QVERIFY(input != 0);
1524 QVERIFY(input->imHints() & Qt::ImhNoPredictiveText);
1525 QVERIFY(input->inputMethodHints() & Qt::ImhNoPredictiveText);
1526 input->setIMHints(Qt::ImhUppercaseOnly);
1527 QVERIFY(input->imHints() & Qt::ImhUppercaseOnly);
1528 QVERIFY(input->inputMethodHints() & Qt::ImhUppercaseOnly);
1530 QVERIFY(canvas->rootObject() != 0);
1532 input->setFocus(true);
1533 QVERIFY(input->hasActiveFocus() == true);
1534 // test that input method event is committed
1535 QInputMethodEvent event;
1536 event.setCommitString( "My ", -12, 0);
1537 QApplication::sendEvent(canvas, &event);
1538 QCOMPARE(input->text(), QString("My Hello world!"));
1540 input->setCursorPosition(2);
1541 event.setCommitString("Your", -2, 2);
1542 QApplication::sendEvent(canvas, &event);
1543 QCOMPARE(input->text(), QString("Your Hello world!"));
1544 QCOMPARE(input->cursorPosition(), 4);
1546 input->setCursorPosition(7);
1547 event.setCommitString("Goodbye", -2, 5);
1548 QApplication::sendEvent(canvas, &event);
1549 QCOMPARE(input->text(), QString("Your Goodbye world!"));
1550 QCOMPARE(input->cursorPosition(), 12);
1552 input->setCursorPosition(8);
1553 event.setCommitString("Our", -8, 4);
1554 QApplication::sendEvent(canvas, &event);
1555 QCOMPARE(input->text(), QString("Our Goodbye world!"));
1556 QCOMPARE(input->cursorPosition(), 7);
1562 TextInput element should only handle left/right keys until the cursor reaches
1563 the extent of the text, then they should ignore the keys.
1566 void tst_qdeclarativetextinput::navigation()
1568 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
1572 QVERIFY(canvas->rootObject() != 0);
1574 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1576 QVERIFY(input != 0);
1577 input->setCursorPosition(0);
1578 QTRY_VERIFY(input->hasActiveFocus() == true);
1579 simulateKey(canvas, Qt::Key_Left);
1580 QVERIFY(input->hasActiveFocus() == false);
1581 simulateKey(canvas, Qt::Key_Right);
1582 QVERIFY(input->hasActiveFocus() == true);
1583 //QT-2944: If text is selected, ensure we deselect upon cursor motion
1584 input->setCursorPosition(input->text().length());
1585 input->select(0,input->text().length());
1586 QVERIFY(input->selectionStart() != input->selectionEnd());
1587 simulateKey(canvas, Qt::Key_Right);
1588 QVERIFY(input->selectionStart() == input->selectionEnd());
1589 QVERIFY(input->selectionStart() == input->text().length());
1590 QVERIFY(input->hasActiveFocus() == true);
1591 simulateKey(canvas, Qt::Key_Right);
1592 QVERIFY(input->hasActiveFocus() == false);
1593 simulateKey(canvas, Qt::Key_Left);
1594 QVERIFY(input->hasActiveFocus() == true);
1596 // Up and Down should NOT do Home/End, even on Mac OS X (QTBUG-10438).
1597 input->setCursorPosition(2);
1598 QCOMPARE(input->cursorPosition(),2);
1599 simulateKey(canvas, Qt::Key_Up);
1600 QCOMPARE(input->cursorPosition(),2);
1601 simulateKey(canvas, Qt::Key_Down);
1602 QCOMPARE(input->cursorPosition(),2);
1607 void tst_qdeclarativetextinput::navigation_RTL()
1609 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
1613 QVERIFY(canvas->rootObject() != 0);
1615 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1617 QVERIFY(input != 0);
1618 const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
1619 input->setText(QString::fromUtf16(arabic_str, 11));
1621 input->setCursorPosition(0);
1622 QTRY_VERIFY(input->hasActiveFocus() == true);
1625 simulateKey(canvas, Qt::Key_Right);
1626 QVERIFY(input->hasActiveFocus() == false);
1629 simulateKey(canvas, Qt::Key_Left);
1630 QVERIFY(input->hasActiveFocus() == true);
1632 input->setCursorPosition(input->text().length());
1633 QVERIFY(input->hasActiveFocus() == true);
1636 simulateKey(canvas, Qt::Key_Left);
1637 QVERIFY(input->hasActiveFocus() == false);
1640 simulateKey(canvas, Qt::Key_Right);
1641 QVERIFY(input->hasActiveFocus() == true);
1646 void tst_qdeclarativetextinput::copyAndPaste() {
1647 #ifndef QT_NO_CLIPBOARD
1651 PasteboardRef pasteboard;
1652 OSStatus status = PasteboardCreate(0, &pasteboard);
1653 if (status == noErr)
1654 CFRelease(pasteboard);
1656 QSKIP("This machine doesn't support the clipboard", SkipAll);
1660 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }";
1661 QDeclarativeComponent textInputComponent(&engine);
1662 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1663 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1664 QVERIFY(textInput != 0);
1667 QCOMPARE(textInput->text().length(), 12);
1668 textInput->select(0, textInput->text().length());;
1670 QCOMPARE(textInput->selectedText(), QString("Hello world!"));
1671 QCOMPARE(textInput->selectedText().length(), 12);
1672 textInput->setCursorPosition(0);
1673 QVERIFY(textInput->canPaste());
1675 QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
1676 QCOMPARE(textInput->text().length(), 24);
1679 QVERIFY(textInput->canPaste());
1680 textInput->setReadOnly(true);
1681 QVERIFY(!textInput->canPaste());
1682 textInput->setReadOnly(false);
1683 QVERIFY(textInput->canPaste());
1686 textInput->setCursorPosition(0);
1687 textInput->selectWord();
1688 QCOMPARE(textInput->selectedText(), QString("Hello"));
1690 // select all and cut
1691 textInput->selectAll();
1693 QCOMPARE(textInput->text().length(), 0);
1695 QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
1696 QCOMPARE(textInput->text().length(), 24);
1698 // clear copy buffer
1699 QClipboard *clipboard = QApplication::clipboard();
1702 QVERIFY(!textInput->canPaste());
1704 // test that copy functionality is disabled
1705 // when echo mode is set to hide text/password mode
1708 QDeclarative1TextInput::EchoMode echoMode = QDeclarative1TextInput::EchoMode(index);
1709 textInput->setEchoMode(echoMode);
1710 textInput->setText("My password");
1711 textInput->select(0, textInput->text().length());;
1713 if (echoMode == QDeclarative1TextInput::Normal) {
1714 QVERIFY(!clipboard->text().isEmpty());
1715 QCOMPARE(clipboard->text(), QString("My password"));
1718 QVERIFY(clipboard->text().isEmpty());
1727 void tst_qdeclarativetextinput::canPasteEmpty() {
1728 #ifndef QT_NO_CLIPBOARD
1730 QApplication::clipboard()->clear();
1732 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }";
1733 QDeclarativeComponent textInputComponent(&engine);
1734 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1735 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1736 QVERIFY(textInput != 0);
1739 bool cp = !lc.isReadOnly() && QApplication::clipboard()->text().length() != 0;
1740 QCOMPARE(textInput->canPaste(), cp);
1745 void tst_qdeclarativetextinput::canPaste() {
1746 #ifndef QT_NO_CLIPBOARD
1748 QApplication::clipboard()->setText("Some text");
1750 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }";
1751 QDeclarativeComponent textInputComponent(&engine);
1752 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1753 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1754 QVERIFY(textInput != 0);
1757 bool cp = !lc.isReadOnly() && QApplication::clipboard()->text().length() != 0;
1758 QCOMPARE(textInput->canPaste(), cp);
1763 void tst_qdeclarativetextinput::passwordCharacter()
1765 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\"; font.family: \"Helvetica\"; echoMode: TextInput.Password }";
1766 QDeclarativeComponent textInputComponent(&engine);
1767 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1768 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1769 QVERIFY(textInput != 0);
1771 textInput->setPasswordCharacter("X");
1772 QSize contentsSize = textInput->contentsSize();
1773 textInput->setPasswordCharacter(".");
1774 // QTBUG-12383 content is updated and redrawn
1775 QVERIFY(contentsSize != textInput->contentsSize());
1780 void tst_qdeclarativetextinput::cursorDelegate()
1782 QDeclarativeView* view = createView(SRCDIR "/data/cursorTest.qml");
1785 QDeclarative1TextInput *textInputObject = view->rootObject()->findChild<QDeclarative1TextInput*>("textInputObject");
1786 QVERIFY(textInputObject != 0);
1787 QVERIFY(textInputObject->findChild<QDeclarativeItem*>("cursorInstance"));
1788 //Test Delegate gets created
1789 textInputObject->setFocus(true);
1790 QDeclarativeItem* delegateObject = textInputObject->findChild<QDeclarativeItem*>("cursorInstance");
1791 QVERIFY(delegateObject);
1792 //Test Delegate gets moved
1793 for(int i=0; i<= textInputObject->text().length(); i++){
1794 textInputObject->setCursorPosition(i);
1795 QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
1796 QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
1798 const QString preedit = "preedit";
1799 for (int i = 0; i <= preedit.length(); i++) {
1800 QInputMethodEvent event(preedit, QList<QInputMethodEvent::Attribute>()
1801 << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, 1, QVariant()));
1802 QApplication::sendEvent(view, &event);
1804 QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
1805 QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
1807 textInputObject->setCursorPosition(0);
1808 QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
1809 QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
1810 //Test Delegate gets deleted
1811 textInputObject->setCursorDelegate(0);
1812 QVERIFY(!textInputObject->findChild<QDeclarativeItem*>("cursorInstance"));
1817 void tst_qdeclarativetextinput::cursorVisible()
1819 QGraphicsScene scene;
1820 QGraphicsView view(&scene);
1822 QApplication::setActiveWindow(&view);
1823 QTest::qWaitForWindowShown(&view);
1824 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
1826 QDeclarative1TextInput input;
1827 QSignalSpy spy(&input, SIGNAL(cursorVisibleChanged(bool)));
1829 QCOMPARE(input.isCursorVisible(), false);
1831 input.setCursorVisible(true);
1832 QCOMPARE(input.isCursorVisible(), true);
1833 QCOMPARE(spy.count(), 1);
1835 input.setCursorVisible(false);
1836 QCOMPARE(input.isCursorVisible(), false);
1837 QCOMPARE(spy.count(), 2);
1839 input.setFocus(true);
1840 QCOMPARE(input.isCursorVisible(), false);
1841 QCOMPARE(spy.count(), 2);
1843 scene.addItem(&input);
1844 QCOMPARE(input.isCursorVisible(), true);
1845 QCOMPARE(spy.count(), 3);
1847 input.setFocus(false);
1848 QCOMPARE(input.isCursorVisible(), false);
1849 QCOMPARE(spy.count(), 4);
1851 input.setFocus(true);
1852 QCOMPARE(input.isCursorVisible(), true);
1853 QCOMPARE(spy.count(), 5);
1856 QCOMPARE(input.isCursorVisible(), false);
1857 QCOMPARE(spy.count(), 6);
1860 QCOMPARE(input.isCursorVisible(), true);
1861 QCOMPARE(spy.count(), 7);
1864 QCOMPARE(input.isCursorVisible(), false);
1865 QCOMPARE(spy.count(), 8);
1868 QCOMPARE(input.isCursorVisible(), true);
1869 QCOMPARE(spy.count(), 9);
1871 // on mac, setActiveWindow(0) on mac does not deactivate the current application
1872 // (you have to switch to a different app or hide the current app to trigger this)
1873 #if !defined(Q_WS_MAC)
1874 QApplication::setActiveWindow(0);
1875 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(0));
1876 QCOMPARE(input.isCursorVisible(), false);
1877 QCOMPARE(spy.count(), 10);
1879 QApplication::setActiveWindow(&view);
1880 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
1881 QCOMPARE(input.isCursorVisible(), true);
1882 QCOMPARE(spy.count(), 11);
1886 void tst_qdeclarativetextinput::cursorRectangle()
1888 QString text = "Hello World!";
1890 QDeclarative1TextInput input;
1891 input.setText(text);
1892 QFontMetricsF fm(input.font());
1893 input.setWidth(fm.width(text.mid(0, 5)));
1897 // some tolerance for different fonts.
1899 const int error = 2;
1901 const int error = 5;
1904 for (int i = 0; i <= 5; ++i) {
1905 input.setCursorPosition(i);
1906 r = input.cursorRectangle();
1907 int textWidth = fm.width(text.mid(0, i));
1909 QVERIFY(r.left() < textWidth + error);
1910 QVERIFY(r.right() > textWidth - error);
1911 QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
1914 // Check the cursor rectangle remains within the input bounding rect when auto scrolling.
1915 QVERIFY(r.left() < input.boundingRect().width());
1916 QVERIFY(r.right() >= input.width() - error);
1918 for (int i = 6; i < text.length(); ++i) {
1919 input.setCursorPosition(i);
1920 QCOMPARE(r, input.cursorRectangle());
1921 QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
1924 for (int i = text.length() - 2; i >= 0; --i) {
1925 input.setCursorPosition(i);
1926 r = input.cursorRectangle();
1927 QVERIFY(r.right() >= 0);
1928 QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
1932 void tst_qdeclarativetextinput::readOnly()
1934 QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml");
1938 QVERIFY(canvas->rootObject() != 0);
1940 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1942 QVERIFY(input != 0);
1943 QTRY_VERIFY(input->hasActiveFocus() == true);
1944 QVERIFY(input->isReadOnly() == true);
1945 QString initial = input->text();
1946 for(int k=Qt::Key_0; k<=Qt::Key_Z; k++)
1947 simulateKey(canvas, k);
1948 simulateKey(canvas, Qt::Key_Return);
1949 simulateKey(canvas, Qt::Key_Space);
1950 simulateKey(canvas, Qt::Key_Escape);
1951 QCOMPARE(input->text(), initial);
1956 void tst_qdeclarativetextinput::echoMode()
1958 QDeclarativeView *canvas = createView(SRCDIR "/data/echoMode.qml");
1961 QApplication::setActiveWindow(canvas);
1962 QTest::qWaitForWindowShown(canvas);
1963 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1965 QVERIFY(canvas->rootObject() != 0);
1967 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1969 QVERIFY(input != 0);
1970 QTRY_VERIFY(input->hasActiveFocus() == true);
1971 QString initial = input->text();
1972 Qt::InputMethodHints ref;
1973 QCOMPARE(initial, QLatin1String("ABCDefgh"));
1974 QCOMPARE(input->echoMode(), QDeclarative1TextInput::Normal);
1975 QCOMPARE(input->displayText(), input->text());
1977 ref &= ~Qt::ImhHiddenText;
1978 ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
1979 QCOMPARE(input->inputMethodHints(), ref);
1980 QCOMPARE(input->imHints(), Qt::ImhNone);
1981 input->setEchoMode(QDeclarative1TextInput::NoEcho);
1982 QCOMPARE(input->text(), initial);
1983 QCOMPARE(input->displayText(), QLatin1String(""));
1984 QCOMPARE(input->passwordCharacter(), QLatin1String("*"));
1986 ref |= Qt::ImhHiddenText;
1987 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
1988 QCOMPARE(input->inputMethodHints(), ref);
1989 QCOMPARE(input->imHints(), Qt::ImhNone);
1990 input->setEchoMode(QDeclarative1TextInput::Password);
1992 ref |= Qt::ImhHiddenText;
1993 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
1994 QCOMPARE(input->text(), initial);
1995 QCOMPARE(input->displayText(), QLatin1String("********"));
1996 QCOMPARE(input->inputMethodHints(), ref);
1997 QCOMPARE(input->imHints(), Qt::ImhNone);
1998 input->setPasswordCharacter(QChar('Q'));
1999 QCOMPARE(input->passwordCharacter(), QLatin1String("Q"));
2000 QCOMPARE(input->text(), initial);
2001 QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
2002 input->setEchoMode(QDeclarative1TextInput::PasswordEchoOnEdit);
2003 //PasswordEchoOnEdit
2004 ref &= ~Qt::ImhHiddenText;
2005 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2006 QCOMPARE(input->inputMethodHints(), ref);
2007 QCOMPARE(input->imHints(), Qt::ImhNone);
2008 QCOMPARE(input->text(), initial);
2009 QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
2010 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("QQQQQQQQ"));
2011 QTest::keyPress(canvas, Qt::Key_A);//Clearing previous entry is part of PasswordEchoOnEdit
2012 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
2013 QCOMPARE(input->text(), QLatin1String("a"));
2014 QCOMPARE(input->displayText(), QLatin1String("a"));
2015 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("a"));
2016 input->setFocus(false);
2017 QVERIFY(input->hasActiveFocus() == false);
2018 QCOMPARE(input->displayText(), QLatin1String("Q"));
2019 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("Q"));
2020 input->setFocus(true);
2021 QInputMethodEvent inputEvent;
2022 inputEvent.setCommitString(initial);
2023 QApplication::sendEvent(canvas, &inputEvent);
2024 QCOMPARE(input->text(), initial);
2025 QCOMPARE(input->displayText(), initial);
2026 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial);
2028 // Test echo mode doesn't override imHints.
2029 input->setIMHints(Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2030 ref |= Qt::ImhDialableCharactersOnly;
2032 input->setEchoMode(QDeclarative1TextInput::Normal);
2033 ref |= Qt::ImhHiddenText;
2034 ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2035 QCOMPARE(input->inputMethodHints(), ref);
2036 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2038 input->setEchoMode(QDeclarative1TextInput::NoEcho);
2039 ref |= Qt::ImhHiddenText;
2040 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2041 QCOMPARE(input->inputMethodHints(), ref);
2042 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2044 input->setEchoMode(QDeclarative1TextInput::Password);
2045 ref |= Qt::ImhHiddenText;
2046 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2047 QCOMPARE(input->inputMethodHints(), ref);
2048 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2049 //PasswordEchoOnEdit
2050 input->setEchoMode(QDeclarative1TextInput::PasswordEchoOnEdit);
2051 ref &= ~Qt::ImhHiddenText;
2052 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2053 QCOMPARE(input->inputMethodHints(), ref);
2054 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2056 input->setEchoMode(QDeclarative1TextInput::Normal);
2057 ref |= Qt::ImhHiddenText;
2058 ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2059 QCOMPARE(input->inputMethodHints(), ref);
2060 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2065 void tst_qdeclarativetextinput::simulateKey(QDeclarativeView *view, int key)
2067 QKeyEvent press(QKeyEvent::KeyPress, key, 0);
2068 QKeyEvent release(QKeyEvent::KeyRelease, key, 0);
2070 QApplication::sendEvent(view, &press);
2071 QApplication::sendEvent(view, &release);
2074 QDeclarativeView *tst_qdeclarativetextinput::createView(const QString &filename)
2076 QDeclarativeView *canvas = new QDeclarativeView(0);
2078 canvas->setSource(QUrl::fromLocalFile(filename));
2082 class MyInputContext : public QInputContext
2085 MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false), updateReceived(false), eventType(QEvent::None) {}
2086 ~MyInputContext() {}
2088 QString identifierName() { return QString(); }
2089 QString language() { return QString(); }
2093 bool isComposing() const { return false; }
2095 bool filterEvent( const QEvent *event )
2097 if (event->type() == QEvent::RequestSoftwareInputPanel)
2098 openInputPanelReceived = true;
2099 if (event->type() == QEvent::CloseSoftwareInputPanel)
2100 closeInputPanelReceived = true;
2101 return QInputContext::filterEvent(event);
2104 void update() { updateReceived = true; }
2106 void mouseHandler(int x, QMouseEvent *event)
2109 eventType = event->type();
2110 eventPosition = event->pos();
2111 eventGlobalPosition = event->globalPos();
2112 eventButton = event->button();
2113 eventButtons = event->buttons();
2114 eventModifiers = event->modifiers();
2117 void sendPreeditText(const QString &text, int cursor)
2119 QList<QInputMethodEvent::Attribute> attributes;
2120 attributes.append(QInputMethodEvent::Attribute(
2121 QInputMethodEvent::Cursor, cursor, text.length(), QVariant()));
2123 QInputMethodEvent event(text, attributes);
2127 bool openInputPanelReceived;
2128 bool closeInputPanelReceived;
2129 bool updateReceived;
2131 QEvent::Type eventType;
2132 QPoint eventPosition;
2133 QPoint eventGlobalPosition;
2134 Qt::MouseButton eventButton;
2135 Qt::MouseButtons eventButtons;
2136 Qt::KeyboardModifiers eventModifiers;
2139 void tst_qdeclarativetextinput::openInputPanelOnClick()
2141 QGraphicsScene scene;
2142 QGraphicsView view(&scene);
2144 view.setInputContext(&ic);
2145 QDeclarative1TextInput input;
2146 QSignalSpy focusOnPressSpy(&input, SIGNAL(activeFocusOnPressChanged(bool)));
2147 input.setText("Hello world");
2149 scene.addItem(&input);
2151 qApp->setAutoSipEnabled(true);
2152 QApplication::setActiveWindow(&view);
2153 QTest::qWaitForWindowShown(&view);
2154 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2156 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&input);
2157 QDeclarative1TextInputPrivate *inputPrivate = static_cast<QDeclarative1TextInputPrivate*>(pri);
2159 // input panel on click
2160 inputPrivate->showInputPanelOnFocus = false;
2162 QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
2163 view.style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
2164 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2165 QApplication::processEvents();
2166 if (behavior == QStyle::RSIP_OnMouseClickAndAlreadyFocused) {
2167 QCOMPARE(ic.openInputPanelReceived, false);
2168 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2169 QApplication::processEvents();
2170 QCOMPARE(ic.openInputPanelReceived, true);
2171 } else if (behavior == QStyle::RSIP_OnMouseClick) {
2172 QCOMPARE(ic.openInputPanelReceived, true);
2174 ic.openInputPanelReceived = false;
2176 // focus should not cause input panels to open or close
2177 input.setFocus(false);
2178 input.setFocus(true);
2179 input.setFocus(false);
2180 input.setFocus(true);
2181 input.setFocus(false);
2182 QCOMPARE(ic.openInputPanelReceived, false);
2183 QCOMPARE(ic.closeInputPanelReceived, false);
2186 void tst_qdeclarativetextinput::openInputPanelOnFocus()
2188 QGraphicsScene scene;
2189 QGraphicsView view(&scene);
2191 view.setInputContext(&ic);
2192 QDeclarative1TextInput input;
2193 QSignalSpy focusOnPressSpy(&input, SIGNAL(activeFocusOnPressChanged(bool)));
2194 input.setText("Hello world");
2196 scene.addItem(&input);
2198 qApp->setAutoSipEnabled(true);
2199 QApplication::setActiveWindow(&view);
2200 QTest::qWaitForWindowShown(&view);
2201 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2203 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&input);
2204 QDeclarative1TextInputPrivate *inputPrivate = static_cast<QDeclarative1TextInputPrivate*>(pri);
2205 inputPrivate->showInputPanelOnFocus = true;
2207 // test default values
2208 QVERIFY(input.focusOnPress());
2209 QCOMPARE(ic.openInputPanelReceived, false);
2210 QCOMPARE(ic.closeInputPanelReceived, false);
2212 // focus on press, input panel on focus
2213 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2214 QApplication::processEvents();
2215 QVERIFY(input.hasActiveFocus());
2216 QCOMPARE(ic.openInputPanelReceived, true);
2217 ic.openInputPanelReceived = false;
2219 // no events on release
2220 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2221 QCOMPARE(ic.openInputPanelReceived, false);
2222 ic.openInputPanelReceived = false;
2224 // if already focused, input panel can be opened on press
2225 QVERIFY(input.hasActiveFocus());
2226 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2227 QApplication::processEvents();
2228 QCOMPARE(ic.openInputPanelReceived, true);
2229 ic.openInputPanelReceived = false;
2231 // input method should stay enabled if focus
2232 // is lost to an item that also accepts inputs
2233 QDeclarative1TextInput anotherInput;
2234 scene.addItem(&anotherInput);
2235 anotherInput.setFocus(true);
2236 QApplication::processEvents();
2237 QCOMPARE(ic.openInputPanelReceived, true);
2238 ic.openInputPanelReceived = false;
2239 QCOMPARE(view.inputContext(), (QInputContext*)&ic);
2240 QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
2242 // input method should be disabled if focus
2243 // is lost to an item that doesn't accept inputs
2244 QDeclarativeItem item;
2245 scene.addItem(&item);
2246 item.setFocus(true);
2247 QApplication::processEvents();
2248 QCOMPARE(ic.openInputPanelReceived, false);
2249 QVERIFY(view.inputContext() == 0);
2250 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2252 // no automatic input panel events should
2253 // be sent if activeFocusOnPress is false
2254 input.setFocusOnPress(false);
2255 QCOMPARE(focusOnPressSpy.count(),1);
2256 input.setFocusOnPress(false);
2257 QCOMPARE(focusOnPressSpy.count(),1);
2258 input.setFocus(false);
2259 input.setFocus(true);
2260 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2261 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2262 QApplication::processEvents();
2263 QCOMPARE(ic.openInputPanelReceived, false);
2264 QCOMPARE(ic.closeInputPanelReceived, false);
2266 // one show input panel event should
2267 // be set when openSoftwareInputPanel is called
2268 input.openSoftwareInputPanel();
2269 QCOMPARE(ic.openInputPanelReceived, true);
2270 QCOMPARE(ic.closeInputPanelReceived, false);
2271 ic.openInputPanelReceived = false;
2273 // one close input panel event should
2274 // be sent when closeSoftwareInputPanel is called
2275 input.closeSoftwareInputPanel();
2276 QCOMPARE(ic.openInputPanelReceived, false);
2277 QCOMPARE(ic.closeInputPanelReceived, true);
2278 ic.closeInputPanelReceived = false;
2280 // set activeFocusOnPress back to true
2281 input.setFocusOnPress(true);
2282 QCOMPARE(focusOnPressSpy.count(),2);
2283 input.setFocusOnPress(true);
2284 QCOMPARE(focusOnPressSpy.count(),2);
2285 input.setFocus(false);
2286 QApplication::processEvents();
2287 QCOMPARE(ic.openInputPanelReceived, false);
2288 QCOMPARE(ic.closeInputPanelReceived, false);
2289 ic.closeInputPanelReceived = false;
2291 // input panel should not re-open
2292 // if focus has already been set
2293 input.setFocus(true);
2294 QCOMPARE(ic.openInputPanelReceived, true);
2295 ic.openInputPanelReceived = false;
2296 input.setFocus(true);
2297 QCOMPARE(ic.openInputPanelReceived, false);
2299 // input method should be disabled
2300 // if TextInput loses focus
2301 input.setFocus(false);
2302 QApplication::processEvents();
2303 QVERIFY(view.inputContext() == 0);
2304 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2306 // input method should not be enabled
2307 // if TextEdit is read only.
2308 input.setReadOnly(true);
2309 ic.openInputPanelReceived = false;
2310 input.setFocus(true);
2311 QApplication::processEvents();
2312 QCOMPARE(ic.openInputPanelReceived, false);
2313 QVERIFY(view.inputContext() == 0);
2314 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2317 class MyTextInput : public QDeclarative1TextInput
2320 MyTextInput(QDeclarativeItem *parent = 0) : QDeclarative1TextInput(parent)
2324 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
2327 QDeclarative1TextInput::paint(painter, option, widget);
2332 void tst_qdeclarativetextinput::setHAlignClearCache()
2334 QGraphicsScene scene;
2335 QGraphicsView view(&scene);
2337 input.setText("Hello world");
2338 scene.addItem(&input);
2340 QApplication::setActiveWindow(&view);
2341 QTest::qWaitForWindowShown(&view);
2343 QEXPECT_FAIL("", "QTBUG-21017 fails", Abort);
2345 QTRY_COMPARE(input.nbPaint, 1);
2346 input.setHAlign(QDeclarative1TextInput::AlignRight);
2347 QApplication::processEvents();
2348 //Changing the alignment should trigger a repaint
2349 QCOMPARE(input.nbPaint, 2);
2352 void tst_qdeclarativetextinput::focusOutClearSelection()
2354 QGraphicsScene scene;
2355 QGraphicsView view(&scene);
2356 QDeclarative1TextInput input;
2357 QDeclarative1TextInput input2;
2358 input.setText(QLatin1String("Hello world"));
2359 input.setFocus(true);
2360 scene.addItem(&input2);
2361 scene.addItem(&input);
2363 QApplication::setActiveWindow(&view);
2364 QTest::qWaitForWindowShown(&view);
2366 //The selection should work
2367 QTRY_COMPARE(input.selectedText(), QLatin1String("llo"));
2368 input2.setFocus(true);
2369 QApplication::processEvents();
2370 //The input lost the focus selection should be cleared
2371 QTRY_COMPARE(input.selectedText(), QLatin1String(""));
2374 void tst_qdeclarativetextinput::geometrySignals()
2376 QDeclarativeComponent component(&engine, SRCDIR "/data/geometrySignals.qml");
2377 QObject *o = component.create();
2379 QCOMPARE(o->property("bindingWidth").toInt(), 400);
2380 QCOMPARE(o->property("bindingHeight").toInt(), 500);
2384 void tst_qdeclarativetextinput::testQtQuick11Attributes()
2386 QFETCH(QString, code);
2387 QFETCH(QString, warning);
2388 QFETCH(QString, error);
2390 QDeclarativeEngine engine;
2393 QDeclarativeComponent valid(&engine);
2394 valid.setData("import QtQuick 1.1; TextInput { " + code.toUtf8() + " }", QUrl(""));
2395 obj = valid.create();
2397 QVERIFY(valid.errorString().isEmpty());
2400 QDeclarativeComponent invalid(&engine);
2401 invalid.setData("import QtQuick 1.0; TextInput { " + code.toUtf8() + " }", QUrl(""));
2402 QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
2403 obj = invalid.create();
2404 QCOMPARE(invalid.errorString(), error);
2408 void tst_qdeclarativetextinput::testQtQuick11Attributes_data()
2410 QTest::addColumn<QString>("code");
2411 QTest::addColumn<QString>("warning");
2412 QTest::addColumn<QString>("error");
2414 QTest::newRow("canPaste") << "property bool foo: canPaste"
2415 << "<Unknown File>:1: ReferenceError: Can't find variable: canPaste"
2418 QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)"
2419 << "<Unknown File>:1: ReferenceError: Can't find variable: moveCursorSelection"
2422 QTest::newRow("deselect") << "Component.onCompleted: deselect()"
2423 << "<Unknown File>:1: ReferenceError: Can't find variable: deselect"
2427 void tst_qdeclarativetextinput::preeditAutoScroll()
2429 QString committedText = "super";
2430 QString preeditText = "califragisiticexpialidocious!";
2432 QGraphicsScene scene;
2433 QGraphicsView view(&scene);
2435 view.setInputContext(&ic);
2436 QDeclarative1TextInput input;
2437 QFontMetricsF fm(input.font());
2438 input.setWidth(fm.width(committedText));
2439 input.setText(committedText);
2441 input.setFocus(true);
2442 scene.addItem(&input);
2444 QApplication::setActiveWindow(&view);
2445 QTest::qWaitForWindowShown(&view);
2446 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2448 QSignalSpy cursorRectangleSpy(&input, SIGNAL(cursorRectangleChanged()));
2449 int cursorRectangleChanges = 0;
2451 // test the text is scrolled so the preedit is visible.
2452 ic.sendPreeditText(preeditText.mid(0, 3), 1);
2454 QEXPECT_FAIL("", "QTBUG-21017 fails", Abort);
2456 QVERIFY(input.positionAt(0) != 0);
2457 QVERIFY(input.cursorRectangle().left() < input.boundingRect().width());
2458 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2460 // test the text is scrolled back when the preedit is removed.
2461 ic.sendEvent(QInputMethodEvent());
2462 QCOMPARE(input.positionAt(0), 0);
2463 QCOMPARE(input.positionAt(input.width()), 5);
2464 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2466 // some tolerance for different fonts.
2468 const int error = 2;
2470 const int error = 5;
2473 // test if the preedit is larger than the text input that the
2474 // character preceding the cursor is still visible.
2475 qreal x = input.positionToRectangle(0).x();
2476 for (int i = 0; i < 3; ++i) {
2477 ic.sendPreeditText(preeditText, i + 1);
2478 QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i)) - error);
2479 QVERIFY(input.positionToRectangle(0).x() < x);
2480 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2481 x = input.positionToRectangle(0).x();
2483 for (int i = 1; i >= 0; --i) {
2484 ic.sendPreeditText(preeditText, i + 1);
2485 QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i)) - error);
2486 QVERIFY(input.positionToRectangle(0).x() > x);
2487 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2488 x = input.positionToRectangle(0).x();
2491 // Test incrementing the preedit cursor doesn't cause further
2492 // scrolling when right most text is visible.
2493 ic.sendPreeditText(preeditText, preeditText.length() - 3);
2494 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2495 x = input.positionToRectangle(0).x();
2496 for (int i = 2; i >= 0; --i) {
2497 ic.sendPreeditText(preeditText, preeditText.length() - i);
2498 QCOMPARE(input.positionToRectangle(0).x(), x);
2499 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2501 for (int i = 1; i < 3; ++i) {
2502 ic.sendPreeditText(preeditText, preeditText.length() - i);
2503 QCOMPARE(input.positionToRectangle(0).x(), x);
2504 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2507 // Test disabling auto scroll.
2508 ic.sendEvent(QInputMethodEvent());
2510 input.setAutoScroll(false);
2511 ic.sendPreeditText(preeditText.mid(0, 3), 1);
2512 QCOMPARE(input.positionAt(0), 0);
2513 QCOMPARE(input.positionAt(input.width()), 5);
2515 ic.sendEvent(QInputMethodEvent());
2516 input.setAutoScroll(true);
2517 // Test committing pre-edit text at the start of the string. QTBUG-18789
2518 input.setCursorPosition(0);
2519 ic.sendPreeditText(input.text(), 5);
2520 QCOMPARE(input.positionAt(0), 0);
2522 QInputMethodEvent event;
2523 event.setCommitString(input.text());
2524 ic.sendEvent(event);
2526 QCOMPARE(input.positionAt(0), 0);
2527 QCOMPARE(input.positionAt(input.width()), 5);
2530 void tst_qdeclarativetextinput::preeditMicroFocus()
2532 QString preeditText = "super";
2534 QGraphicsScene scene;
2535 QGraphicsView view(&scene);
2537 view.setInputContext(&ic);
2538 QDeclarative1TextInput input;
2540 input.setAutoScroll(false);
2541 input.setFocus(true);
2542 scene.addItem(&input);
2544 QApplication::setActiveWindow(&view);
2545 QTest::qWaitForWindowShown(&view);
2546 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2549 QRect previousRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2551 // Verify that the micro focus rect is positioned the same for position 0 as
2552 // it would be if there was no preedit text.
2553 ic.updateReceived = false;
2554 ic.sendPreeditText(preeditText, 0);
2555 currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2556 QCOMPARE(currentRect, previousRect);
2557 #if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
2558 QCOMPARE(ic.updateReceived, true);
2561 // Verify that the micro focus rect moves to the left as the cursor position
2563 for (int i = 1; i <= 5; ++i) {
2564 ic.updateReceived = false;
2565 ic.sendPreeditText(preeditText, i);
2566 currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2567 QVERIFY(previousRect.left() < currentRect.left());
2568 #if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
2569 QCOMPARE(ic.updateReceived, true);
2571 previousRect = currentRect;
2574 // Verify that if there is no preedit cursor then the micro focus rect is the
2575 // same as it would be if it were positioned at the end of the preedit text.
2576 ic.sendPreeditText(preeditText, 0);
2577 ic.updateReceived = false;
2578 ic.sendEvent(QInputMethodEvent(preeditText, QList<QInputMethodEvent::Attribute>()));
2579 currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2580 QCOMPARE(currentRect, previousRect);
2581 #if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
2582 QCOMPARE(ic.updateReceived, true);
2586 void tst_qdeclarativetextinput::inputContextMouseHandler()
2588 QString text = "supercalifragisiticexpialidocious!";
2590 QGraphicsScene scene;
2591 QGraphicsView view(&scene);
2593 view.setInputContext(&ic);
2594 QDeclarative1TextInput input;
2595 input.setWidth(200);
2596 input.setText(text.mid(0, 12));
2597 input.setCursorPosition(12);
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));
2606 QFontMetricsF fm(input.font());
2607 const qreal y = fm.height() / 2;
2609 QPoint position2 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 2)), y)));
2610 QPoint position8 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 8)), y)));
2611 QPoint position20 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 20)), y)));
2612 QPoint position27 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 27)), y)));
2613 QPoint globalPosition2 = view.viewport()->mapToGlobal(position2);
2614 QPoint globalposition8 = view.viewport()->mapToGlobal(position8);
2615 QPoint globalposition20 = view.viewport()->mapToGlobal(position20);
2616 QPoint globalposition27 = view.viewport()->mapToGlobal(position27);
2618 ic.sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>()));
2620 QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
2621 QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick);
2622 QCOMPARE(ic.eventPosition, position2);
2623 QCOMPARE(ic.eventGlobalPosition, globalPosition2);
2624 QCOMPARE(ic.eventButton, Qt::LeftButton);
2625 QCOMPARE(ic.eventModifiers, Qt::NoModifier);
2626 QVERIFY(ic.cursor < 0);
2627 ic.eventType = QEvent::None;
2629 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
2630 QCOMPARE(ic.eventType, QEvent::MouseButtonPress);
2631 QCOMPARE(ic.eventPosition, position2);
2632 QCOMPARE(ic.eventGlobalPosition, globalPosition2);
2633 QCOMPARE(ic.eventButton, Qt::LeftButton);
2634 QCOMPARE(ic.eventModifiers, Qt::NoModifier);
2635 QVERIFY(ic.cursor < 0);
2636 ic.eventType = QEvent::None;
2638 { QMouseEvent mv(QEvent::MouseMove, position8, globalposition8, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
2639 QApplication::sendEvent(view.viewport(), &mv); }
2640 QCOMPARE(ic.eventType, QEvent::None);
2642 { QMouseEvent mv(QEvent::MouseMove, position27, globalposition27, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
2643 QApplication::sendEvent(view.viewport(), &mv); }
2644 QCOMPARE(ic.eventType, QEvent::MouseMove);
2645 QCOMPARE(ic.eventPosition, position27);
2646 QCOMPARE(ic.eventGlobalPosition, globalposition27);
2647 QCOMPARE(ic.eventButton, Qt::LeftButton);
2648 QCOMPARE(ic.eventModifiers, Qt::NoModifier);
2649 QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); // 15 is expected but some platforms may be off by one.
2650 ic.eventType = QEvent::None;
2652 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position27);
2653 QCOMPARE(ic.eventType, QEvent::MouseButtonRelease);
2654 QCOMPARE(ic.eventPosition, position27);
2655 QCOMPARE(ic.eventGlobalPosition, globalposition27);
2656 QCOMPARE(ic.eventButton, Qt::LeftButton);
2657 QCOMPARE(ic.eventModifiers, Qt::NoModifier);
2658 QVERIFY(ic.cursor >= 14 && ic.cursor <= 16);
2659 ic.eventType = QEvent::None;
2661 // And in the other direction.
2662 QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, position27);
2663 QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick);
2664 QCOMPARE(ic.eventPosition, position27);
2665 QCOMPARE(ic.eventGlobalPosition, globalposition27);
2666 QCOMPARE(ic.eventButton, Qt::LeftButton);
2667 QCOMPARE(ic.eventModifiers, Qt::ControlModifier);
2668 QVERIFY(ic.cursor >= 14 && ic.cursor <= 16);
2669 ic.eventType = QEvent::None;
2671 QTest::mousePress(view.viewport(), Qt::RightButton, Qt::ControlModifier, position27);
2672 QCOMPARE(ic.eventType, QEvent::MouseButtonPress);
2673 QCOMPARE(ic.eventPosition, position27);
2674 QCOMPARE(ic.eventGlobalPosition, globalposition27);
2675 QCOMPARE(ic.eventButton, Qt::RightButton);
2676 QCOMPARE(ic.eventModifiers, Qt::ControlModifier);
2677 QVERIFY(ic.cursor >= 14 && ic.cursor <= 16);
2678 ic.eventType = QEvent::None;
2680 { QMouseEvent mv(QEvent::MouseMove, position20, globalposition20, Qt::RightButton, Qt::RightButton,Qt::ControlModifier);
2681 QApplication::sendEvent(view.viewport(), &mv); }
2682 QCOMPARE(ic.eventType, QEvent::MouseMove);
2683 QCOMPARE(ic.eventPosition, position20);
2684 QCOMPARE(ic.eventGlobalPosition, globalposition20);
2685 QCOMPARE(ic.eventButton, Qt::RightButton);
2686 QCOMPARE(ic.eventModifiers, Qt::ControlModifier);
2687 QVERIFY(ic.cursor >= 7 && ic.cursor <= 9);
2688 ic.eventType = QEvent::None;
2690 { QMouseEvent mv(QEvent::MouseMove, position2, globalPosition2, Qt::RightButton, Qt::RightButton,Qt::ControlModifier);
2691 QApplication::sendEvent(view.viewport(), &mv); }
2692 QCOMPARE(ic.eventType, QEvent::None);
2694 QTest::mouseRelease(view.viewport(), Qt::RightButton, Qt::ControlModifier, position2);
2695 QCOMPARE(ic.eventType, QEvent::MouseButtonRelease);
2696 QCOMPARE(ic.eventPosition, position2);
2697 QCOMPARE(ic.eventGlobalPosition, globalPosition2);
2698 QCOMPARE(ic.eventButton, Qt::RightButton);
2699 QCOMPARE(ic.eventModifiers, Qt::ControlModifier);
2700 QVERIFY(ic.cursor < 0);
2701 ic.eventType = QEvent::None;
2704 void tst_qdeclarativetextinput::inputMethodComposing()
2706 QString text = "supercalifragisiticexpialidocious!";
2708 QGraphicsScene scene;
2709 QGraphicsView view(&scene);
2711 view.setInputContext(&ic);
2712 QDeclarative1TextInput input;
2713 input.setWidth(200);
2714 input.setText(text.mid(0, 12));
2715 input.setCursorPosition(12);
2717 input.setFocus(true);
2718 scene.addItem(&input);
2720 QApplication::setActiveWindow(&view);
2721 QTest::qWaitForWindowShown(&view);
2722 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2724 QSignalSpy spy(&input, SIGNAL(inputMethodComposingChanged()));
2726 QCOMPARE(input.isInputMethodComposing(), false);
2728 ic.sendEvent(QInputMethodEvent(text.mid(3), QList<QInputMethodEvent::Attribute>()));
2729 QCOMPARE(input.isInputMethodComposing(), true);
2730 QCOMPARE(spy.count(), 1);
2732 ic.sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>()));
2733 QCOMPARE(input.isInputMethodComposing(), true);
2734 QCOMPARE(spy.count(), 1);
2736 ic.sendEvent(QInputMethodEvent());
2737 QCOMPARE(input.isInputMethodComposing(), false);
2738 QCOMPARE(spy.count(), 2);
2741 void tst_qdeclarativetextinput::cursorRectangleSize()
2743 QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml");
2744 QVERIFY(canvas->rootObject() != 0);
2747 QApplication::setActiveWindow(canvas);
2748 QTest::qWaitForWindowShown(canvas);
2750 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
2751 QVERIFY(textInput != 0);
2752 textInput->setFocus(Qt::OtherFocusReason);
2753 QRectF cursorRect = textInput->positionToRectangle(textInput->cursorPosition());
2754 QRectF microFocusFromScene = canvas->scene()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
2755 QRectF microFocusFromApp= QApplication::focusWidget()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
2757 QCOMPARE(microFocusFromScene.size(), cursorRect.size());
2758 QCOMPARE(microFocusFromApp.size(), cursorRect.size());
2761 QTEST_MAIN(tst_qdeclarativetextinput)
2763 #include "tst_qdeclarativetextinput.moc"