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 <QtDeclarative/qdeclarativeengine.h>
45 #include <QtQuick1/qdeclarativeview.h>
46 #include <QtQuick1/private/qdeclarativetextinput_p.h>
47 #include <QtQuick1/private/qdeclarativetextinput_p_p.h>
51 #include <QtCore/qmath.h>
52 #include <private/qapplication_p.h>
53 #include <private/qinputpanel_p.h>
55 #include "qplatformdefs.h"
57 Q_DECLARE_METATYPE(QDeclarative1TextInput::SelectionMode)
59 QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
61 // XXX This will be replaced by some clever persistent platform image store.
62 QString persistent_dir = SRCDIR "/data";
63 QString arch = "unknown-architecture"; // QTest needs to help with this.
65 QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png";
67 if (!QFile::exists(expectfile)) {
68 actual.save(expectfile);
69 qWarning() << "created" << expectfile;
75 void sendPreeditText(const QString &text, int cursor)
77 QList<QInputMethodEvent::Attribute> attributes;
78 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursor,
79 text.length(), QVariant()));
80 QInputMethodEvent event(text, attributes);
81 QApplication::sendEvent(qApp->inputPanel()->inputItem(), &event);
85 class PlatformInputContext : public QPlatformInputContext
88 PlatformInputContext()
89 : m_visible(false), m_action(QInputPanel::Click), m_cursorPosition(0),
90 m_invokeActionCallCount(0), m_showInputPanelCallCount(0), m_hideInputPanelCallCount(0),
95 virtual void showInputPanel()
98 m_showInputPanelCallCount++;
100 virtual void hideInputPanel()
103 m_hideInputPanelCallCount++;
105 virtual bool isInputPanelVisible() const
109 virtual void invokeAction(QInputPanel::Action action, int cursorPosition)
111 m_invokeActionCallCount++;
113 m_cursorPosition = cursorPosition;
115 virtual void update(Qt::InputMethodQueries)
121 m_cursorPosition = 0;
122 m_invokeActionCallCount = 0;
124 m_showInputPanelCallCount = 0;
125 m_hideInputPanelCallCount = 0;
126 m_updateCallCount = 0;
130 QInputPanel::Action m_action;
131 int m_cursorPosition;
132 int m_invokeActionCallCount;
133 int m_showInputPanelCallCount;
134 int m_hideInputPanelCallCount;
135 int m_updateCallCount;
139 class tst_qdeclarativetextinput : public QObject
144 tst_qdeclarativetextinput();
154 void isRightToLeft_data();
155 void isRightToLeft();
156 void moveCursorSelection_data();
157 void moveCursorSelection();
158 void moveCursorSelectionSequence_data();
159 void moveCursorSelectionSequence();
160 void mouseSelection_data();
161 void mouseSelection();
162 void deferEnableSelectByMouse_data();
163 void deferEnableSelectByMouse();
164 void deferDisableSelectByMouse_data();
165 void deferDisableSelectByMouse();
166 void dragMouseSelection();
167 void mouseSelectionMode_data();
168 void mouseSelectionMode();
170 void horizontalAlignment_data();
171 void horizontalAlignment();
172 void horizontalAlignment_RightToLeft();
181 void passwordCharacter();
182 void cursorDelegate();
183 void cursorVisible();
184 void cursorRectangle();
186 void navigation_RTL();
188 void canPasteEmpty();
192 void openInputPanelOnClick();
193 void openInputPanelOnFocus();
194 void setHAlignClearCache();
195 void focusOutClearSelection();
198 #ifdef QT_GUI_PASSWORD_ECHO_DELAY
199 void passwordEchoDelay();
201 void geometrySignals();
202 void testQtQuick11Attributes();
203 void testQtQuick11Attributes_data();
205 void preeditAutoScroll();
206 void preeditMicroFocus();
207 void inputContextMouseHandler();
208 void inputMethodComposing();
209 void cursorRectangleSize();
212 void simulateKey(QDeclarativeView *, int key);
213 QDeclarativeView *createView(const QString &filename);
215 QDeclarativeEngine engine;
216 QStringList standard;
217 QStringList colorStrings;
221 tst_qdeclarativetextinput::tst_qdeclarativetextinput()
223 standard << "the quick brown fox jumped over the lazy dog"
224 << "It's supercalifragisiticexpialidocious!"
229 colorStrings << "aliceblue"
243 void tst_qdeclarativetextinput::cleanup()
245 // ensure not even skipped tests with custom input context leave it dangling
246 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
247 inputPanelPrivate->testContext = 0;
250 void tst_qdeclarativetextinput::text()
253 QDeclarativeComponent textinputComponent(&engine);
254 textinputComponent.setData("import QtQuick 1.0\nTextInput { text: \"\" }", QUrl());
255 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
257 QVERIFY(textinputObject != 0);
258 QCOMPARE(textinputObject->text(), QString(""));
260 delete textinputObject;
263 for (int i = 0; i < standard.size(); i++)
265 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"" + standard.at(i) + "\" }";
266 QDeclarativeComponent textinputComponent(&engine);
267 textinputComponent.setData(componentStr.toLatin1(), QUrl());
268 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
270 QVERIFY(textinputObject != 0);
271 QCOMPARE(textinputObject->text(), standard.at(i));
273 delete textinputObject;
278 void tst_qdeclarativetextinput::width()
280 // uses Font metrics to find the width for standard
282 QDeclarativeComponent textinputComponent(&engine);
283 textinputComponent.setData("import QtQuick 1.0\nTextInput { text: \"\" }", QUrl());
284 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
286 QVERIFY(textinputObject != 0);
287 QCOMPARE(textinputObject->width(), 0.0);
289 delete textinputObject;
292 for (int i = 0; i < standard.size(); i++)
296 qreal metricWidth = fm.width(standard.at(i));
298 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"" + standard.at(i) + "\" }";
299 QDeclarativeComponent textinputComponent(&engine);
300 textinputComponent.setData(componentStr.toLatin1(), QUrl());
301 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
303 QVERIFY(textinputObject != 0);
304 int delta = abs(int(int(textinputObject->width()) - metricWidth));
305 QVERIFY(delta <= 3.0); // As best as we can hope for cross-platform.
307 delete textinputObject;
311 void tst_qdeclarativetextinput::font()
313 //test size, then bold, then italic, then family
315 QString componentStr = "import QtQuick 1.0\nTextInput { font.pointSize: 40; text: \"Hello World\" }";
316 QDeclarativeComponent textinputComponent(&engine);
317 textinputComponent.setData(componentStr.toLatin1(), QUrl());
318 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
320 QVERIFY(textinputObject != 0);
321 QCOMPARE(textinputObject->font().pointSize(), 40);
322 QCOMPARE(textinputObject->font().bold(), false);
323 QCOMPARE(textinputObject->font().italic(), false);
325 delete textinputObject;
329 QString componentStr = "import QtQuick 1.0\nTextInput { font.bold: true; text: \"Hello World\" }";
330 QDeclarativeComponent textinputComponent(&engine);
331 textinputComponent.setData(componentStr.toLatin1(), QUrl());
332 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
334 QVERIFY(textinputObject != 0);
335 QCOMPARE(textinputObject->font().bold(), true);
336 QCOMPARE(textinputObject->font().italic(), false);
338 delete textinputObject;
342 QString componentStr = "import QtQuick 1.0\nTextInput { font.italic: true; text: \"Hello World\" }";
343 QDeclarativeComponent textinputComponent(&engine);
344 textinputComponent.setData(componentStr.toLatin1(), QUrl());
345 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
347 QVERIFY(textinputObject != 0);
348 QCOMPARE(textinputObject->font().italic(), true);
349 QCOMPARE(textinputObject->font().bold(), false);
351 delete textinputObject;
355 QString componentStr = "import QtQuick 1.0\nTextInput { font.family: \"Helvetica\"; text: \"Hello World\" }";
356 QDeclarativeComponent textinputComponent(&engine);
357 textinputComponent.setData(componentStr.toLatin1(), QUrl());
358 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
360 QVERIFY(textinputObject != 0);
361 QCOMPARE(textinputObject->font().family(), QString("Helvetica"));
362 QCOMPARE(textinputObject->font().bold(), false);
363 QCOMPARE(textinputObject->font().italic(), false);
365 delete textinputObject;
369 QString componentStr = "import QtQuick 1.0\nTextInput { font.family: \"\"; text: \"Hello World\" }";
370 QDeclarativeComponent textinputComponent(&engine);
371 textinputComponent.setData(componentStr.toLatin1(), QUrl());
372 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
374 QVERIFY(textinputObject != 0);
375 QCOMPARE(textinputObject->font().family(), QString(""));
377 delete textinputObject;
381 void tst_qdeclarativetextinput::color()
384 for (int i = 0; i < colorStrings.size(); i++)
386 QString componentStr = "import QtQuick 1.0\nTextInput { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
387 QDeclarativeComponent textinputComponent(&engine);
388 textinputComponent.setData(componentStr.toLatin1(), QUrl());
389 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
390 QVERIFY(textinputObject != 0);
391 QCOMPARE(textinputObject->color(), QColor(colorStrings.at(i)));
393 delete textinputObject;
396 //test selection color
397 for (int i = 0; i < colorStrings.size(); i++)
399 QString componentStr = "import QtQuick 1.0\nTextInput { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
400 QDeclarativeComponent textinputComponent(&engine);
401 textinputComponent.setData(componentStr.toLatin1(), QUrl());
402 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
403 QVERIFY(textinputObject != 0);
404 QCOMPARE(textinputObject->selectionColor(), QColor(colorStrings.at(i)));
406 delete textinputObject;
409 //test selected text color
410 for (int i = 0; i < colorStrings.size(); i++)
412 QString componentStr = "import QtQuick 1.0\nTextInput { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
413 QDeclarativeComponent textinputComponent(&engine);
414 textinputComponent.setData(componentStr.toLatin1(), QUrl());
415 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
416 QVERIFY(textinputObject != 0);
417 QCOMPARE(textinputObject->selectedTextColor(), QColor(colorStrings.at(i)));
419 delete textinputObject;
423 QString colorStr = "#AA001234";
424 QColor testColor("#001234");
425 testColor.setAlpha(170);
427 QString componentStr = "import QtQuick 1.0\nTextInput { color: \"" + colorStr + "\"; text: \"Hello World\" }";
428 QDeclarativeComponent textinputComponent(&engine);
429 textinputComponent.setData(componentStr.toLatin1(), QUrl());
430 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
432 QVERIFY(textinputObject != 0);
433 QCOMPARE(textinputObject->color(), testColor);
435 delete textinputObject;
439 void tst_qdeclarativetextinput::selection()
441 QString testStr = standard[0];
442 QString componentStr = "import QtQuick 1.0\nTextInput { text: \""+ testStr +"\"; }";
443 QDeclarativeComponent textinputComponent(&engine);
444 textinputComponent.setData(componentStr.toLatin1(), QUrl());
445 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
446 QVERIFY(textinputObject != 0);
449 //Test selection follows cursor
450 for(int i=0; i<= testStr.size(); i++) {
451 textinputObject->setCursorPosition(i);
452 QCOMPARE(textinputObject->cursorPosition(), i);
453 QCOMPARE(textinputObject->selectionStart(), i);
454 QCOMPARE(textinputObject->selectionEnd(), i);
455 QVERIFY(textinputObject->selectedText().isNull());
457 //Test cursor follows selection
458 for(int i=0; i<= testStr.size(); i++) {
459 textinputObject->select(i,i);
460 QCOMPARE(textinputObject->cursorPosition(), i);
461 QCOMPARE(textinputObject->selectionStart(), i);
462 QCOMPARE(textinputObject->selectionEnd(), i);
465 textinputObject->setCursorPosition(0);
466 QVERIFY(textinputObject->cursorPosition() == 0);
467 QVERIFY(textinputObject->selectionStart() == 0);
468 QVERIFY(textinputObject->selectionEnd() == 0);
469 QVERIFY(textinputObject->selectedText().isNull());
471 // Verify invalid positions are ignored.
472 textinputObject->setCursorPosition(-1);
473 QVERIFY(textinputObject->cursorPosition() == 0);
474 QVERIFY(textinputObject->selectionStart() == 0);
475 QVERIFY(textinputObject->selectionEnd() == 0);
476 QVERIFY(textinputObject->selectedText().isNull());
478 textinputObject->setCursorPosition(textinputObject->text().count()+1);
479 QVERIFY(textinputObject->cursorPosition() == 0);
480 QVERIFY(textinputObject->selectionStart() == 0);
481 QVERIFY(textinputObject->selectionEnd() == 0);
482 QVERIFY(textinputObject->selectedText().isNull());
485 for(int i=0; i<= testStr.size(); i++) {
486 textinputObject->select(0,i);
487 QCOMPARE(testStr.mid(0,i), textinputObject->selectedText());
488 QCOMPARE(textinputObject->cursorPosition(), i);
490 for(int i=0; i<= testStr.size(); i++) {
491 textinputObject->select(i,testStr.size());
492 QCOMPARE(testStr.mid(i,testStr.size()-i), textinputObject->selectedText());
493 QCOMPARE(textinputObject->cursorPosition(), testStr.size());
496 textinputObject->setCursorPosition(0);
497 QVERIFY(textinputObject->cursorPosition() == 0);
498 QVERIFY(textinputObject->selectionStart() == 0);
499 QVERIFY(textinputObject->selectionEnd() == 0);
500 QVERIFY(textinputObject->selectedText().isNull());
502 //Test Error Ignoring behaviour
503 textinputObject->setCursorPosition(0);
504 QVERIFY(textinputObject->selectedText().isNull());
505 textinputObject->select(-10,0);
506 QVERIFY(textinputObject->selectedText().isNull());
507 textinputObject->select(100,110);
508 QVERIFY(textinputObject->selectedText().isNull());
509 textinputObject->select(0,-10);
510 QVERIFY(textinputObject->selectedText().isNull());
511 textinputObject->select(0,100);
512 QVERIFY(textinputObject->selectedText().isNull());
513 textinputObject->select(0,10);
514 QVERIFY(textinputObject->selectedText().size() == 10);
515 textinputObject->select(-10,10);
516 QVERIFY(textinputObject->selectedText().size() == 10);
517 textinputObject->select(100,101);
518 QVERIFY(textinputObject->selectedText().size() == 10);
519 textinputObject->select(0,-10);
520 QVERIFY(textinputObject->selectedText().size() == 10);
521 textinputObject->select(0,100);
522 QVERIFY(textinputObject->selectedText().size() == 10);
524 textinputObject->deselect();
525 QVERIFY(textinputObject->selectedText().isNull());
526 textinputObject->select(0,10);
527 QVERIFY(textinputObject->selectedText().size() == 10);
528 textinputObject->deselect();
529 QVERIFY(textinputObject->selectedText().isNull());
531 delete textinputObject;
534 void tst_qdeclarativetextinput::isRightToLeft_data()
536 QTest::addColumn<QString>("text");
537 QTest::addColumn<bool>("emptyString");
538 QTest::addColumn<bool>("firstCharacter");
539 QTest::addColumn<bool>("lastCharacter");
540 QTest::addColumn<bool>("middleCharacter");
541 QTest::addColumn<bool>("startString");
542 QTest::addColumn<bool>("midString");
543 QTest::addColumn<bool>("endString");
545 const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
546 QTest::newRow("Empty") << "" << false << false << false << false << false << false << false;
547 QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false;
548 QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false;
549 QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true;
550 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;
551 QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false;
554 void tst_qdeclarativetextinput::isRightToLeft()
556 QFETCH(QString, text);
557 QFETCH(bool, emptyString);
558 QFETCH(bool, firstCharacter);
559 QFETCH(bool, lastCharacter);
560 QFETCH(bool, middleCharacter);
561 QFETCH(bool, startString);
562 QFETCH(bool, midString);
563 QFETCH(bool, endString);
565 QDeclarative1TextInput textInput;
566 textInput.setText(text);
568 // first test that the right string is delivered to the QString::isRightToLeft()
569 QCOMPARE(textInput.isRightToLeft(0,0), text.mid(0,0).isRightToLeft());
570 QCOMPARE(textInput.isRightToLeft(0,1), text.mid(0,1).isRightToLeft());
571 QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft());
572 QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft());
573 QCOMPARE(textInput.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft());
574 QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft());
576 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
577 QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft());
579 // then test that the feature actually works
580 QCOMPARE(textInput.isRightToLeft(0,0), emptyString);
581 QCOMPARE(textInput.isRightToLeft(0,1), firstCharacter);
582 QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), lastCharacter);
583 QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter);
584 QCOMPARE(textInput.isRightToLeft(0,text.count()/4), startString);
585 QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), midString);
587 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
588 QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), endString);
591 void tst_qdeclarativetextinput::moveCursorSelection_data()
593 QTest::addColumn<QString>("testStr");
594 QTest::addColumn<int>("cursorPosition");
595 QTest::addColumn<int>("movePosition");
596 QTest::addColumn<QDeclarative1TextInput::SelectionMode>("mode");
597 QTest::addColumn<int>("selectionStart");
598 QTest::addColumn<int>("selectionEnd");
599 QTest::addColumn<bool>("reversible");
601 // () contains the text selected by the cursor.
602 // <> contains the actual selection.
604 QTest::newRow("(t)he|characters")
605 << standard[0] << 0 << 1 << QDeclarative1TextInput::SelectCharacters << 0 << 1 << true;
606 QTest::newRow("do(g)|characters")
607 << standard[0] << 43 << 44 << QDeclarative1TextInput::SelectCharacters << 43 << 44 << true;
608 QTest::newRow("jum(p)ed|characters")
609 << standard[0] << 23 << 24 << QDeclarative1TextInput::SelectCharacters << 23 << 24 << true;
610 QTest::newRow("jumped( )over|characters")
611 << standard[0] << 26 << 27 << QDeclarative1TextInput::SelectCharacters << 26 << 27 << true;
612 QTest::newRow("(the )|characters")
613 << standard[0] << 0 << 4 << QDeclarative1TextInput::SelectCharacters << 0 << 4 << true;
614 QTest::newRow("( dog)|characters")
615 << standard[0] << 40 << 44 << QDeclarative1TextInput::SelectCharacters << 40 << 44 << true;
616 QTest::newRow("( jumped )|characters")
617 << standard[0] << 19 << 27 << QDeclarative1TextInput::SelectCharacters << 19 << 27 << true;
618 QTest::newRow("th(e qu)ick|characters")
619 << standard[0] << 2 << 6 << QDeclarative1TextInput::SelectCharacters << 2 << 6 << true;
620 QTest::newRow("la(zy d)og|characters")
621 << standard[0] << 38 << 42 << QDeclarative1TextInput::SelectCharacters << 38 << 42 << true;
622 QTest::newRow("jum(ped ov)er|characters")
623 << standard[0] << 23 << 29 << QDeclarative1TextInput::SelectCharacters << 23 << 29 << true;
624 QTest::newRow("()the|characters")
625 << standard[0] << 0 << 0 << QDeclarative1TextInput::SelectCharacters << 0 << 0 << true;
626 QTest::newRow("dog()|characters")
627 << standard[0] << 44 << 44 << QDeclarative1TextInput::SelectCharacters << 44 << 44 << true;
628 QTest::newRow("jum()ped|characters")
629 << standard[0] << 23 << 23 << QDeclarative1TextInput::SelectCharacters << 23 << 23 << true;
631 QTest::newRow("<(t)he>|words")
632 << standard[0] << 0 << 1 << QDeclarative1TextInput::SelectWords << 0 << 3 << true;
633 QTest::newRow("<do(g)>|words")
634 << standard[0] << 43 << 44 << QDeclarative1TextInput::SelectWords << 41 << 44 << true;
635 QTest::newRow("<jum(p)ed>|words")
636 << standard[0] << 23 << 24 << QDeclarative1TextInput::SelectWords << 20 << 26 << true;
637 QTest::newRow("<jumped( )>over|words,ltr")
638 << standard[0] << 26 << 27 << QDeclarative1TextInput::SelectWords << 20 << 27 << false;
639 QTest::newRow("jumped<( )over>|words,rtl")
640 << standard[0] << 27 << 26 << QDeclarative1TextInput::SelectWords << 26 << 31 << false;
641 QTest::newRow("<(the )>quick|words,ltr")
642 << standard[0] << 0 << 4 << QDeclarative1TextInput::SelectWords << 0 << 4 << false;
643 QTest::newRow("<(the )quick>|words,rtl")
644 << standard[0] << 4 << 0 << QDeclarative1TextInput::SelectWords << 0 << 9 << false;
645 QTest::newRow("<lazy( dog)>|words,ltr")
646 << standard[0] << 40 << 44 << QDeclarative1TextInput::SelectWords << 36 << 44 << false;
647 QTest::newRow("lazy<( dog)>|words,rtl")
648 << standard[0] << 44 << 40 << QDeclarative1TextInput::SelectWords << 40 << 44 << false;
649 QTest::newRow("<fox( jumped )>over|words,ltr")
650 << standard[0] << 19 << 27 << QDeclarative1TextInput::SelectWords << 16 << 27 << false;
651 QTest::newRow("fox<( jumped )over>|words,rtl")
652 << standard[0] << 27 << 19 << QDeclarative1TextInput::SelectWords << 19 << 31 << false;
653 QTest::newRow("<th(e qu)ick>|words")
654 << standard[0] << 2 << 6 << QDeclarative1TextInput::SelectWords << 0 << 9 << true;
655 QTest::newRow("<la(zy d)og|words>")
656 << standard[0] << 38 << 42 << QDeclarative1TextInput::SelectWords << 36 << 44 << true;
657 QTest::newRow("<jum(ped ov)er>|words")
658 << standard[0] << 23 << 29 << QDeclarative1TextInput::SelectWords << 20 << 31 << true;
659 QTest::newRow("<()>the|words")
660 << standard[0] << 0 << 0 << QDeclarative1TextInput::SelectWords << 0 << 0 << true;
661 QTest::newRow("dog<()>|words")
662 << standard[0] << 44 << 44 << QDeclarative1TextInput::SelectWords << 44 << 44 << true;
663 QTest::newRow("jum<()>ped|words")
664 << standard[0] << 23 << 23 << QDeclarative1TextInput::SelectWords << 23 << 23 << true;
666 QTest::newRow("Hello<(,)> |words")
667 << standard[2] << 5 << 6 << QDeclarative1TextInput::SelectWords << 5 << 6 << true;
668 QTest::newRow("Hello<(, )>world|words,ltr")
669 << standard[2] << 5 << 7 << QDeclarative1TextInput::SelectWords << 5 << 7 << false;
670 QTest::newRow("Hello<(, )world>|words,rtl")
671 << standard[2] << 7 << 5 << QDeclarative1TextInput::SelectWords << 5 << 12 << false;
672 QTest::newRow("<Hel(lo, )>world|words,ltr")
673 << standard[2] << 3 << 7 << QDeclarative1TextInput::SelectWords << 0 << 7 << false;
674 QTest::newRow("<Hel(lo, )world>|words,rtl")
675 << standard[2] << 7 << 3 << QDeclarative1TextInput::SelectWords << 0 << 12 << false;
676 QTest::newRow("<Hel(lo)>,|words")
677 << standard[2] << 3 << 5 << QDeclarative1TextInput::SelectWords << 0 << 5 << true;
678 QTest::newRow("Hello<()>,|words")
679 << standard[2] << 5 << 5 << QDeclarative1TextInput::SelectWords << 5 << 5 << true;
680 QTest::newRow("Hello,<()>|words")
681 << standard[2] << 6 << 6 << QDeclarative1TextInput::SelectWords << 6 << 6 << true;
682 QTest::newRow("Hello<,( )>world|words,ltr")
683 << standard[2] << 6 << 7 << QDeclarative1TextInput::SelectWords << 5 << 7 << false;
684 QTest::newRow("Hello,<( )world>|words,rtl")
685 << standard[2] << 7 << 6 << QDeclarative1TextInput::SelectWords << 6 << 12 << false;
686 QTest::newRow("Hello<,( world)>|words,ltr")
687 << standard[2] << 6 << 12 << QDeclarative1TextInput::SelectWords << 5 << 12 << false;
688 QTest::newRow("Hello,<( world)>|words,rtl")
689 << standard[2] << 12 << 6 << QDeclarative1TextInput::SelectWords << 6 << 12 << false;
690 QTest::newRow("Hello<,( world!)>|words,ltr")
691 << standard[2] << 6 << 13 << QDeclarative1TextInput::SelectWords << 5 << 13 << false;
692 QTest::newRow("Hello,<( world!)>|words,rtl")
693 << standard[2] << 13 << 6 << QDeclarative1TextInput::SelectWords << 6 << 13 << false;
694 QTest::newRow("Hello<(, world!)>|words")
695 << standard[2] << 5 << 13 << QDeclarative1TextInput::SelectWords << 5 << 13 << true;
696 QTest::newRow("world<(!)>|words")
697 << standard[2] << 12 << 13 << QDeclarative1TextInput::SelectWords << 12 << 13 << true;
698 QTest::newRow("world!<()>)|words")
699 << standard[2] << 13 << 13 << QDeclarative1TextInput::SelectWords << 13 << 13 << true;
700 QTest::newRow("world<()>!)|words")
701 << standard[2] << 12 << 12 << QDeclarative1TextInput::SelectWords << 12 << 12 << true;
703 QTest::newRow("<(,)>olleH |words")
704 << standard[3] << 7 << 8 << QDeclarative1TextInput::SelectWords << 7 << 8 << true;
705 QTest::newRow("<dlrow( ,)>olleH|words,ltr")
706 << standard[3] << 6 << 8 << QDeclarative1TextInput::SelectWords << 1 << 8 << false;
707 QTest::newRow("dlrow<( ,)>olleH|words,rtl")
708 << standard[3] << 8 << 6 << QDeclarative1TextInput::SelectWords << 6 << 8 << false;
709 QTest::newRow("<dlrow( ,ol)leH>|words,ltr")
710 << standard[3] << 6 << 10 << QDeclarative1TextInput::SelectWords << 1 << 13 << false;
711 QTest::newRow("dlrow<( ,ol)leH>|words,rtl")
712 << standard[3] << 10 << 6 << QDeclarative1TextInput::SelectWords << 6 << 13 << false;
713 QTest::newRow(",<(ol)leH>,|words")
714 << standard[3] << 8 << 10 << QDeclarative1TextInput::SelectWords << 8 << 13 << true;
715 QTest::newRow(",<()>olleH|words")
716 << standard[3] << 8 << 8 << QDeclarative1TextInput::SelectWords << 8 << 8 << true;
717 QTest::newRow("<()>,olleH|words")
718 << standard[3] << 7 << 7 << QDeclarative1TextInput::SelectWords << 7 << 7 << true;
719 QTest::newRow("<dlrow( )>,olleH|words,ltr")
720 << standard[3] << 6 << 7 << QDeclarative1TextInput::SelectWords << 1 << 7 << false;
721 QTest::newRow("dlrow<( ),>olleH|words,rtl")
722 << standard[3] << 7 << 6 << QDeclarative1TextInput::SelectWords << 6 << 8 << false;
723 QTest::newRow("<(dlrow )>,olleH|words,ltr")
724 << standard[3] << 1 << 7 << QDeclarative1TextInput::SelectWords << 1 << 7 << false;
725 QTest::newRow("<(dlrow ),>olleH|words,rtl")
726 << standard[3] << 7 << 1 << QDeclarative1TextInput::SelectWords << 1 << 8 << false;
727 QTest::newRow("<(!dlrow )>,olleH|words,ltr")
728 << standard[3] << 0 << 7 << QDeclarative1TextInput::SelectWords << 0 << 7 << false;
729 QTest::newRow("<(!dlrow ),>olleH|words,rtl")
730 << standard[3] << 7 << 0 << QDeclarative1TextInput::SelectWords << 0 << 8 << false;
731 QTest::newRow("(!dlrow ,)olleH|words")
732 << standard[3] << 0 << 8 << QDeclarative1TextInput::SelectWords << 0 << 8 << true;
733 QTest::newRow("<(!)>dlrow|words")
734 << standard[3] << 0 << 1 << QDeclarative1TextInput::SelectWords << 0 << 1 << true;
735 QTest::newRow("<()>!dlrow|words")
736 << standard[3] << 0 << 0 << QDeclarative1TextInput::SelectWords << 0 << 0 << true;
737 QTest::newRow("!<()>dlrow|words")
738 << standard[3] << 1 << 1 << QDeclarative1TextInput::SelectWords << 1 << 1 << true;
740 QTest::newRow(" <s(pac)ey> text |words")
741 << standard[4] << 1 << 4 << QDeclarative1TextInput::SelectWords << 1 << 7 << true;
742 QTest::newRow(" spacey <t(ex)t> |words")
743 << standard[4] << 11 << 13 << QDeclarative1TextInput::SelectWords << 10 << 14 << true;
744 QTest::newRow("<( )>spacey text |words|ltr")
745 << standard[4] << 0 << 1 << QDeclarative1TextInput::SelectWords << 0 << 1 << false;
746 QTest::newRow("<( )spacey> text |words|rtl")
747 << standard[4] << 1 << 0 << QDeclarative1TextInput::SelectWords << 0 << 7 << false;
748 QTest::newRow("spacey <text( )>|words|ltr")
749 << standard[4] << 14 << 15 << QDeclarative1TextInput::SelectWords << 10 << 15 << false;
750 QTest::newRow("spacey text<( )>|words|rtl")
751 << standard[4] << 15 << 14 << QDeclarative1TextInput::SelectWords << 14 << 15 << false;
752 QTest::newRow("<()> spacey text |words")
753 << standard[4] << 0 << 0 << QDeclarative1TextInput::SelectWords << 0 << 0 << false;
754 QTest::newRow(" spacey text <()>|words")
755 << standard[4] << 15 << 15 << QDeclarative1TextInput::SelectWords << 15 << 15 << false;
758 void tst_qdeclarativetextinput::moveCursorSelection()
760 QFETCH(QString, testStr);
761 QFETCH(int, cursorPosition);
762 QFETCH(int, movePosition);
763 QFETCH(QDeclarative1TextInput::SelectionMode, mode);
764 QFETCH(int, selectionStart);
765 QFETCH(int, selectionEnd);
766 QFETCH(bool, reversible);
768 QString componentStr = "import QtQuick 1.1\nTextInput { text: \""+ testStr +"\"; }";
769 QDeclarativeComponent textinputComponent(&engine);
770 textinputComponent.setData(componentStr.toLatin1(), QUrl());
771 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
772 QVERIFY(textinputObject != 0);
774 textinputObject->setCursorPosition(cursorPosition);
775 textinputObject->moveCursorSelection(movePosition, mode);
777 QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
778 QCOMPARE(textinputObject->selectionStart(), selectionStart);
779 QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
782 textinputObject->setCursorPosition(movePosition);
783 textinputObject->moveCursorSelection(cursorPosition, mode);
785 QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
786 QCOMPARE(textinputObject->selectionStart(), selectionStart);
787 QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
790 delete textinputObject;
793 void tst_qdeclarativetextinput::moveCursorSelectionSequence_data()
795 QTest::addColumn<QString>("testStr");
796 QTest::addColumn<int>("cursorPosition");
797 QTest::addColumn<int>("movePosition1");
798 QTest::addColumn<int>("movePosition2");
799 QTest::addColumn<int>("selection1Start");
800 QTest::addColumn<int>("selection1End");
801 QTest::addColumn<int>("selection2Start");
802 QTest::addColumn<int>("selection2End");
804 // () contains the text selected by the cursor.
805 // <> contains the actual selection.
806 // ^ is the revised cursor position.
807 // {} contains the revised selection.
809 QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr")
814 QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl")
819 QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr")
824 QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl")
829 QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr")
834 QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl")
839 QTest::newRow("the {<quick() ^}bro)wn> fox|ltr")
844 QTest::newRow("the quick<( {^bro)wn>} fox|rtl")
849 QTest::newRow("the {<quick^}( bro)wn> fox|ltr")
854 QTest::newRow("the quick{<(^ bro)wn>} fox|rtl")
859 QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr")
864 QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl")
869 QTest::newRow("the {<^quick}( bro)wn> fox|ltr")
874 QTest::newRow("the {<^quick}( bro)wn> fox|rtl")
879 QTest::newRow("the{^ <quick}( bro)wn> fox|ltr")
884 QTest::newRow("the{^ <quick}( bro)wn> fox|rtl")
889 QTest::newRow("{t^he <quick}( bro)wn> fox|ltr")
894 QTest::newRow("{t^he <quick}( bro)wn> fox|rtl")
900 QTest::newRow("{<He(ll)o>, w^orld}!|ltr")
905 QTest::newRow("{<He(ll)o>, w^orld}!|rtl")
911 QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr")
916 QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl")
922 QTest::newRow("{<(^} sp)acey> text |ltr")
927 QTest::newRow("{<( ^}sp)acey> text |ltr")
932 QTest::newRow("<( {s^p)acey>} text |rtl")
937 QTest::newRow("<( {^sp)acey>} text |rtl")
943 QTest::newRow(" spacey <te(xt {^)>}|rtl")
948 QTest::newRow(" spacey <te(xt{^ )>}|rtl")
953 QTest::newRow(" spacey {<te(x^t} )>|ltr")
958 QTest::newRow(" spacey {<te(xt^} )>|ltr")
965 void tst_qdeclarativetextinput::moveCursorSelectionSequence()
967 QFETCH(QString, testStr);
968 QFETCH(int, cursorPosition);
969 QFETCH(int, movePosition1);
970 QFETCH(int, movePosition2);
971 QFETCH(int, selection1Start);
972 QFETCH(int, selection1End);
973 QFETCH(int, selection2Start);
974 QFETCH(int, selection2End);
976 QString componentStr = "import QtQuick 1.1\nTextInput { text: \""+ testStr +"\"; }";
977 QDeclarativeComponent textinputComponent(&engine);
978 textinputComponent.setData(componentStr.toLatin1(), QUrl());
979 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
980 QVERIFY(textinputObject != 0);
982 textinputObject->setCursorPosition(cursorPosition);
984 textinputObject->moveCursorSelection(movePosition1, QDeclarative1TextInput::SelectWords);
985 QCOMPARE(textinputObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start));
986 QCOMPARE(textinputObject->selectionStart(), selection1Start);
987 QCOMPARE(textinputObject->selectionEnd(), selection1End);
989 textinputObject->moveCursorSelection(movePosition2, QDeclarative1TextInput::SelectWords);
990 QCOMPARE(textinputObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start));
991 QCOMPARE(textinputObject->selectionStart(), selection2Start);
992 QCOMPARE(textinputObject->selectionEnd(), selection2End);
994 delete textinputObject;
997 void tst_qdeclarativetextinput::mouseSelection_data()
999 QTest::addColumn<QString>("qmlfile");
1000 QTest::addColumn<bool>("expectSelection");
1003 QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << true;
1004 QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << false;
1005 QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << false;
1006 QTest::newRow("on word selection") << SRCDIR "/data/mouseselection_true_words.qml" << true;
1007 QTest::newRow("off word selection") << SRCDIR "/data/mouseselection_false_words.qml" << false;
1008 QTest::newRow("on read only") << SRCDIR "/data/mouseselection_true_readonly.qml" << true;
1009 QTest::newRow("off read only") << SRCDIR "/data/mouseselection_false_readonly.qml" << false;
1012 void tst_qdeclarativetextinput::mouseSelection()
1014 QFETCH(QString, qmlfile);
1015 QFETCH(bool, expectSelection);
1017 QDeclarativeView *canvas = createView(qmlfile);
1020 QApplication::setActiveWindow(canvas);
1021 QTest::qWaitForWindowShown(canvas);
1022 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1024 QVERIFY(canvas->rootObject() != 0);
1025 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1026 QVERIFY(textInputObject != 0);
1028 // press-and-drag-and-release from x1 to x2
1031 int y = textInputObject->height()/2;
1032 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1033 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1034 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1035 QApplication::sendEvent(canvas->viewport(), &mv);
1036 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1037 QString str = textInputObject->selectedText();
1038 if (expectSelection)
1039 QVERIFY(str.length() > 3); // don't reallly care *what* was selected (and it's too sensitive to platform)
1041 QVERIFY(str.isEmpty());
1043 // Clicking and shift to clicking between the same points should select the same text.
1044 textInputObject->setCursorPosition(0);
1045 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::NoModifier, canvas->mapFromScene(QPoint(x1,y)));
1046 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::ShiftModifier, canvas->mapFromScene(QPoint(x2,y)));
1047 QCOMPARE(textInputObject->selectedText(), str);
1052 void tst_qdeclarativetextinput::deferEnableSelectByMouse_data()
1054 QTest::addColumn<QString>("qmlfile");
1056 QTest::newRow("writable") << SRCDIR "/data/mouseselection_false.qml";
1057 QTest::newRow("read only") << SRCDIR "/data/mouseselection_false_readonly.qml";
1060 void tst_qdeclarativetextinput::deferEnableSelectByMouse()
1062 // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed.
1063 QFETCH(QString, qmlfile);
1065 QDeclarativeView *canvas = createView(qmlfile);
1068 QApplication::setActiveWindow(canvas);
1069 QTest::qWaitForWindowShown(canvas);
1070 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1072 QVERIFY(canvas->rootObject() != 0);
1073 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1074 QVERIFY(textInputObject != 0);
1076 // press-and-drag-and-release from x1 to x2
1079 int y = textInputObject->height()/2;
1081 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1082 textInputObject->setSelectByMouse(true);
1083 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1084 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1085 QApplication::sendEvent(canvas->viewport(), &mv);
1086 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1087 QVERIFY(textInputObject->selectedText().isEmpty());
1092 void tst_qdeclarativetextinput::deferDisableSelectByMouse_data()
1094 QTest::addColumn<QString>("qmlfile");
1096 QTest::newRow("writable") << SRCDIR "/data/mouseselection_true.qml";
1097 QTest::newRow("read only") << SRCDIR "/data/mouseselection_true_readonly.qml";
1100 void tst_qdeclarativetextinput::deferDisableSelectByMouse()
1102 // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed.
1103 QFETCH(QString, qmlfile);
1105 QDeclarativeView *canvas = createView(qmlfile);
1108 QApplication::setActiveWindow(canvas);
1109 QTest::qWaitForWindowShown(canvas);
1110 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1112 QVERIFY(canvas->rootObject() != 0);
1113 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1114 QVERIFY(textInputObject != 0);
1116 // press-and-drag-and-release from x1 to x2
1119 int y = textInputObject->height()/2;
1121 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1122 textInputObject->setSelectByMouse(false);
1123 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1124 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1125 QApplication::sendEvent(canvas->viewport(), &mv);
1126 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1127 QVERIFY(textInputObject->selectedText().length() > 3);
1132 void tst_qdeclarativetextinput::dragMouseSelection()
1134 QString qmlfile = SRCDIR "/data/mouseselection_true.qml";
1136 QDeclarativeView *canvas = createView(qmlfile);
1139 QApplication::setActiveWindow(canvas);
1140 QTest::qWaitForWindowShown(canvas);
1141 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1143 QVERIFY(canvas->rootObject() != 0);
1144 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1145 QVERIFY(textInputObject != 0);
1147 // press-and-drag-and-release from x1 to x2
1150 int y = textInputObject->height()/2;
1151 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1153 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1154 QApplication::sendEvent(canvas->viewport(), &mv);
1156 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1158 QString str1 = textInputObject->selectedText();
1159 QVERIFY(str1.length() > 3);
1161 // press and drag the current selection.
1164 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1166 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1167 QApplication::sendEvent(canvas->viewport(), &mv);
1169 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1170 QString str2 = textInputObject->selectedText();
1171 QVERIFY(str2.length() > 3);
1173 QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved.
1177 void tst_qdeclarativetextinput::mouseSelectionMode_data()
1179 QTest::addColumn<QString>("qmlfile");
1180 QTest::addColumn<bool>("selectWords");
1183 QTest::newRow("SelectWords") << SRCDIR "/data/mouseselectionmode_words.qml" << true;
1184 QTest::newRow("SelectCharacters") << SRCDIR "/data/mouseselectionmode_characters.qml" << false;
1185 QTest::newRow("default") << SRCDIR "/data/mouseselectionmode_default.qml" << false;
1188 void tst_qdeclarativetextinput::mouseSelectionMode()
1190 QFETCH(QString, qmlfile);
1191 QFETCH(bool, selectWords);
1193 QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1195 QDeclarativeView *canvas = createView(qmlfile);
1198 QApplication::setActiveWindow(canvas);
1199 QTest::qWaitForWindowShown(canvas);
1200 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1202 QVERIFY(canvas->rootObject() != 0);
1203 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1204 QVERIFY(textInputObject != 0);
1206 // press-and-drag-and-release from x1 to x2
1209 int y = textInputObject->height()/2;
1210 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1211 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1212 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1213 QApplication::sendEvent(canvas->viewport(), &mv);
1214 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1215 QString str = textInputObject->selectedText();
1217 QCOMPARE(str, text);
1219 QVERIFY(str.length() > 3);
1220 QVERIFY(str != text);
1226 void tst_qdeclarativetextinput::horizontalAlignment_data()
1228 QTest::addColumn<int>("hAlign");
1229 QTest::addColumn<QString>("expectfile");
1231 QTest::newRow("L") << int(Qt::AlignLeft) << "halign_left";
1232 QTest::newRow("R") << int(Qt::AlignRight) << "halign_right";
1233 QTest::newRow("C") << int(Qt::AlignHCenter) << "halign_center";
1236 void tst_qdeclarativetextinput::horizontalAlignment()
1238 QFETCH(int, hAlign);
1239 QFETCH(QString, expectfile);
1241 QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment.qml");
1244 QApplication::setActiveWindow(canvas);
1245 QTest::qWaitForWindowShown(canvas);
1246 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1247 QObject *ob = canvas->rootObject();
1249 ob->setProperty("horizontalAlignment",hAlign);
1250 QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32);
1251 actual.fill(qRgb(255,255,255));
1253 QPainter p(&actual);
1257 expectfile = createExpectedFileIfNotFound(expectfile, actual);
1259 QImage expect(expectfile);
1261 QCOMPARE(actual,expect);
1266 void tst_qdeclarativetextinput::horizontalAlignment_RightToLeft()
1268 QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml");
1269 QDeclarative1TextInput *textInput = canvas->rootObject()->findChild<QDeclarative1TextInput*>("text");
1270 QVERIFY(textInput != 0);
1273 const QString rtlText = textInput->text();
1275 QDeclarative1TextInputPrivate *textInputPrivate = QDeclarative1TextInputPrivate::get(textInput);
1276 QVERIFY(textInputPrivate != 0);
1277 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1279 // implicit alignment should follow the reading direction of RTL text
1280 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1281 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1282 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1284 // explicitly left aligned
1285 textInput->setHAlign(QDeclarative1TextInput::AlignLeft);
1286 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1287 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1288 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1290 // explicitly right aligned
1291 textInput->setHAlign(QDeclarative1TextInput::AlignRight);
1292 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1293 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1294 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1296 // explicitly center aligned
1297 textInput->setHAlign(QDeclarative1TextInput::AlignHCenter);
1298 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1299 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignHCenter);
1300 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1301 QVERIFY(-textInputPrivate->hscroll + textInputPrivate->width() > canvas->width()/2);
1303 // reseted alignment should go back to following the text reading direction
1304 textInput->resetHAlign();
1305 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1306 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1307 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1309 // mirror the text item
1310 QDeclarativeItemPrivate::get(textInput)->setLayoutMirror(true);
1312 // mirrored implicit alignment should continue to follow the reading direction of the text
1313 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1314 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1315 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1317 // explicitly right aligned behaves as left aligned
1318 textInput->setHAlign(QDeclarative1TextInput::AlignRight);
1319 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1320 QCOMPARE(textInput->effectiveHAlign(), QDeclarative1TextInput::AlignLeft);
1321 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1323 // mirrored explicitly left aligned behaves as right aligned
1324 textInput->setHAlign(QDeclarative1TextInput::AlignLeft);
1325 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1326 QCOMPARE(textInput->effectiveHAlign(), QDeclarative1TextInput::AlignRight);
1327 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1329 // disable mirroring
1330 QDeclarativeItemPrivate::get(textInput)->setLayoutMirror(false);
1331 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1332 textInput->resetHAlign();
1334 // English text should be implicitly left aligned
1335 textInput->setText("Hello world!");
1336 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1337 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1339 QApplication::setActiveWindow(canvas);
1340 QTest::qWaitForWindowShown(canvas);
1341 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1343 // If there is no commited text, the preedit text should determine the alignment.
1344 textInput->setText(QString());
1345 { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(canvas, &ev); }
1346 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1347 { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(canvas, &ev); }
1348 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1350 // Clear pre-edit text. TextInput should maybe do this itself on setText, but that may be
1351 // redundant as an actual input method may take care of it.
1352 { QInputMethodEvent ev; QApplication::sendEvent(canvas, &ev); }
1354 #ifndef Q_OS_MAC // QTBUG-18040
1355 // empty text with implicit alignment follows the system locale-based
1356 // keyboard input direction from QApplication::keyboardInputDirection
1357 textInput->setText("");
1358 QCOMPARE(textInput->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
1359 QDeclarative1TextInput::AlignLeft : QDeclarative1TextInput::AlignRight);
1360 if (QApplication::keyboardInputDirection() == Qt::LeftToRight)
1361 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1363 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1364 textInput->setHAlign(QDeclarative1TextInput::AlignRight);
1365 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1366 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1371 #ifndef Q_OS_MAC // QTBUG-18040
1372 // alignment of TextInput with no text set to it
1373 QString componentStr = "import QtQuick 1.0\nTextInput {}";
1374 QDeclarativeComponent textComponent(&engine);
1375 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1376 QDeclarative1TextInput *textObject = qobject_cast<QDeclarative1TextInput*>(textComponent.create());
1377 QCOMPARE(textObject->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
1378 QDeclarative1TextInput::AlignLeft : QDeclarative1TextInput::AlignRight);
1383 void tst_qdeclarativetextinput::positionAt()
1385 QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml");
1386 QVERIFY(canvas->rootObject() != 0);
1389 QApplication::setActiveWindow(canvas);
1390 QTest::qWaitForWindowShown(canvas);
1392 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1393 QVERIFY(textinputObject != 0);
1395 // Check autoscrolled...
1397 int pos = textinputObject->positionAt(textinputObject->width()/2);
1399 QTextLayout layout(textinputObject->text());
1400 layout.setFont(textinputObject->font());
1401 layout.beginLayout();
1402 QTextLine line = layout.createLine();
1405 int textLeftWidthBegin = qFloor(line.cursorToX(pos - 1));
1406 int textLeftWidthEnd = qCeil(line.cursorToX(pos + 1));
1407 int textWidth = floor(line.horizontalAdvance());
1409 QVERIFY(textLeftWidthBegin <= textWidth - textinputObject->width() / 2);
1410 QVERIFY(textLeftWidthEnd >= textWidth - textinputObject->width() / 2);
1412 int x = textinputObject->positionToRectangle(pos + 1).x() - 1;
1413 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorBetweenCharacters), pos + 1);
1414 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorOnCharacter), pos);
1416 // Check without autoscroll...
1417 textinputObject->setAutoScroll(false);
1418 pos = textinputObject->positionAt(textinputObject->width()/2);
1420 textLeftWidthBegin = qFloor(line.cursorToX(pos - 1));
1421 textLeftWidthEnd = qCeil(line.cursorToX(pos + 1));
1423 QVERIFY(textLeftWidthBegin <= textinputObject->width() / 2);
1424 QVERIFY(textLeftWidthEnd >= textinputObject->width() / 2);
1426 x = textinputObject->positionToRectangle(pos + 1).x() - 1;
1427 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorBetweenCharacters), pos + 1);
1428 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorOnCharacter), pos);
1430 const qreal x0 = textinputObject->positionToRectangle(pos).x();
1431 const qreal x1 = textinputObject->positionToRectangle(pos + 1).x();
1433 QString preeditText = textinputObject->text().mid(0, pos);
1434 textinputObject->setText(textinputObject->text().mid(pos));
1435 textinputObject->setCursorPosition(0);
1437 QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
1438 QApplication::sendEvent(canvas, &inputEvent);
1440 // Check all points within the preedit text return the same position.
1441 QCOMPARE(textinputObject->positionAt(0), 0);
1442 QCOMPARE(textinputObject->positionAt(x0 / 2), 0);
1443 QCOMPARE(textinputObject->positionAt(x0), 0);
1445 // Verify positioning returns to normal after the preedit text.
1446 QCOMPARE(textinputObject->positionAt(x1), 1);
1447 QCOMPARE(textinputObject->positionToRectangle(1).x(), x1);
1452 void tst_qdeclarativetextinput::maxLength()
1454 QDeclarativeView *canvas = createView(SRCDIR "/data/maxLength.qml");
1455 QVERIFY(canvas->rootObject() != 0);
1458 QApplication::setActiveWindow(canvas);
1459 QTest::qWaitForWindowShown(canvas);
1461 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1462 QVERIFY(textinputObject != 0);
1463 QVERIFY(textinputObject->text().isEmpty());
1464 QVERIFY(textinputObject->maxLength() == 10);
1465 foreach(const QString &str, standard){
1466 QVERIFY(textinputObject->text().length() <= 10);
1467 textinputObject->setText(str);
1468 QVERIFY(textinputObject->text().length() <= 10);
1471 textinputObject->setText("");
1472 QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
1473 for(int i=0; i<20; i++){
1474 QCOMPARE(textinputObject->text().length(), qMin(i,10));
1475 //simulateKey(canvas, Qt::Key_A);
1476 QTest::keyPress(canvas, Qt::Key_A);
1477 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1483 void tst_qdeclarativetextinput::masks()
1485 //Not a comprehensive test of the possible masks, that's done elsewhere (QLineEdit)
1486 //QString componentStr = "import QtQuick 1.0\nTextInput { inputMask: 'HHHHhhhh'; }";
1487 QDeclarativeView *canvas = createView(SRCDIR "/data/masks.qml");
1490 QVERIFY(canvas->rootObject() != 0);
1491 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1492 QVERIFY(textinputObject != 0);
1493 QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
1494 QVERIFY(textinputObject->text().length() == 0);
1495 QCOMPARE(textinputObject->inputMask(), QString("HHHHhhhh; "));
1496 for(int i=0; i<10; i++){
1497 QCOMPARE(qMin(i,8), textinputObject->text().length());
1498 QCOMPARE(i>=4, textinputObject->hasAcceptableInput());
1499 //simulateKey(canvas, Qt::Key_A);
1500 QTest::keyPress(canvas, Qt::Key_A);
1501 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1507 void tst_qdeclarativetextinput::validators()
1509 // Note that this test assumes that the validators are working properly
1510 // so you may need to run their tests first. All validators are checked
1511 // here to ensure that their exposure to QML is working.
1513 QDeclarativeView *canvas = createView(SRCDIR "/data/validators.qml");
1517 QVERIFY(canvas->rootObject() != 0);
1519 QDeclarative1TextInput *intInput = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("intInput")));
1521 intInput->setFocus(true);
1522 QTRY_VERIFY(intInput->hasActiveFocus());
1523 QTest::keyPress(canvas, Qt::Key_1);
1524 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1525 QCOMPARE(intInput->text(), QLatin1String("1"));
1526 QCOMPARE(intInput->hasAcceptableInput(), false);
1527 QTest::keyPress(canvas, Qt::Key_2);
1528 QTest::keyRelease(canvas, Qt::Key_2, Qt::NoModifier ,10);
1529 QCOMPARE(intInput->text(), QLatin1String("1"));
1530 QCOMPARE(intInput->hasAcceptableInput(), false);
1531 QTest::keyPress(canvas, Qt::Key_1);
1532 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1533 QCOMPARE(intInput->text(), QLatin1String("11"));
1534 QCOMPARE(intInput->hasAcceptableInput(), true);
1535 QTest::keyPress(canvas, Qt::Key_0);
1536 QTest::keyRelease(canvas, Qt::Key_0, Qt::NoModifier ,10);
1537 QCOMPARE(intInput->text(), QLatin1String("11"));
1538 QCOMPARE(intInput->hasAcceptableInput(), true);
1540 QDeclarative1TextInput *dblInput = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("dblInput")));
1541 QTRY_VERIFY(dblInput);
1542 dblInput->setFocus(true);
1543 QVERIFY(dblInput->hasActiveFocus() == true);
1544 QTest::keyPress(canvas, Qt::Key_1);
1545 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1546 QCOMPARE(dblInput->text(), QLatin1String("1"));
1547 QCOMPARE(dblInput->hasAcceptableInput(), false);
1548 QTest::keyPress(canvas, Qt::Key_2);
1549 QTest::keyRelease(canvas, Qt::Key_2, Qt::NoModifier ,10);
1550 QCOMPARE(dblInput->text(), QLatin1String("12"));
1551 QCOMPARE(dblInput->hasAcceptableInput(), true);
1552 QTest::keyPress(canvas, Qt::Key_Period);
1553 QTest::keyRelease(canvas, Qt::Key_Period, Qt::NoModifier ,10);
1554 QCOMPARE(dblInput->text(), QLatin1String("12."));
1555 QCOMPARE(dblInput->hasAcceptableInput(), true);
1556 QTest::keyPress(canvas, Qt::Key_1);
1557 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1558 QCOMPARE(dblInput->text(), QLatin1String("12.1"));
1559 QCOMPARE(dblInput->hasAcceptableInput(), true);
1560 QTest::keyPress(canvas, Qt::Key_1);
1561 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1562 QCOMPARE(dblInput->text(), QLatin1String("12.11"));
1563 QCOMPARE(dblInput->hasAcceptableInput(), true);
1564 QTest::keyPress(canvas, Qt::Key_1);
1565 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1566 QCOMPARE(dblInput->text(), QLatin1String("12.11"));
1567 QCOMPARE(dblInput->hasAcceptableInput(), true);
1569 QDeclarative1TextInput *strInput = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("strInput")));
1570 QTRY_VERIFY(strInput);
1571 strInput->setFocus(true);
1572 QVERIFY(strInput->hasActiveFocus() == true);
1573 QTest::keyPress(canvas, Qt::Key_1);
1574 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1575 QCOMPARE(strInput->text(), QLatin1String(""));
1576 QCOMPARE(strInput->hasAcceptableInput(), false);
1577 QTest::keyPress(canvas, Qt::Key_A);
1578 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1579 QCOMPARE(strInput->text(), QLatin1String("a"));
1580 QCOMPARE(strInput->hasAcceptableInput(), false);
1581 QTest::keyPress(canvas, Qt::Key_A);
1582 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1583 QCOMPARE(strInput->text(), QLatin1String("aa"));
1584 QCOMPARE(strInput->hasAcceptableInput(), true);
1585 QTest::keyPress(canvas, Qt::Key_A);
1586 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1587 QCOMPARE(strInput->text(), QLatin1String("aaa"));
1588 QCOMPARE(strInput->hasAcceptableInput(), true);
1589 QTest::keyPress(canvas, Qt::Key_A);
1590 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1591 QCOMPARE(strInput->text(), QLatin1String("aaaa"));
1592 QCOMPARE(strInput->hasAcceptableInput(), true);
1593 QTest::keyPress(canvas, Qt::Key_A);
1594 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1595 QCOMPARE(strInput->text(), QLatin1String("aaaa"));
1596 QCOMPARE(strInput->hasAcceptableInput(), true);
1601 void tst_qdeclarativetextinput::inputMethods()
1603 QDeclarativeView *canvas = createView(SRCDIR "/data/inputmethods.qml");
1606 QApplication::setActiveWindow(canvas);
1607 QTest::qWaitForWindowShown(canvas);
1609 // test input method hints
1610 QVERIFY(canvas->rootObject() != 0);
1611 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1612 QVERIFY(input != 0);
1613 QVERIFY(input->imHints() & Qt::ImhNoPredictiveText);
1614 QVERIFY(input->inputMethodHints() & Qt::ImhNoPredictiveText);
1615 input->setIMHints(Qt::ImhUppercaseOnly);
1616 QVERIFY(input->imHints() & Qt::ImhUppercaseOnly);
1617 QVERIFY(input->inputMethodHints() & Qt::ImhUppercaseOnly);
1619 QVERIFY(canvas->rootObject() != 0);
1621 input->setFocus(true);
1622 QVERIFY(input->hasActiveFocus() == true);
1623 // test that input method event is committed
1624 QInputMethodEvent event;
1625 event.setCommitString( "My ", -12, 0);
1626 QApplication::sendEvent(canvas, &event);
1627 QCOMPARE(input->text(), QString("My Hello world!"));
1629 input->setCursorPosition(2);
1630 event.setCommitString("Your", -2, 2);
1631 QApplication::sendEvent(canvas, &event);
1632 QCOMPARE(input->text(), QString("Your Hello world!"));
1633 QCOMPARE(input->cursorPosition(), 4);
1635 input->setCursorPosition(7);
1636 event.setCommitString("Goodbye", -2, 5);
1637 QApplication::sendEvent(canvas, &event);
1638 QCOMPARE(input->text(), QString("Your Goodbye world!"));
1639 QCOMPARE(input->cursorPosition(), 12);
1641 input->setCursorPosition(8);
1642 event.setCommitString("Our", -8, 4);
1643 QApplication::sendEvent(canvas, &event);
1644 QCOMPARE(input->text(), QString("Our Goodbye world!"));
1645 QCOMPARE(input->cursorPosition(), 7);
1647 // test that basic tentative commit gets to text property on preedit state
1649 QList<QInputMethodEvent::Attribute> attributes;
1650 QInputMethodEvent preeditEvent("test", attributes);
1651 preeditEvent.setTentativeCommitString("test");
1652 QApplication::sendEvent(canvas, &preeditEvent);
1653 QCOMPARE(input->text(), QString("test"));
1655 // tentative commit not allowed present in surrounding text
1656 QInputMethodQueryEvent queryEvent(Qt::ImSurroundingText);
1657 QApplication::sendEvent(canvas, &queryEvent);
1658 QCOMPARE(queryEvent.value(Qt::ImSurroundingText).toString(), QString(""));
1660 // if text with tentative commit does not validate, not allowed to be part of text property
1661 input->setText(""); // ensure input state is reset
1662 QValidator *validator = new QIntValidator(0, 100);
1663 input->setValidator(validator);
1664 QApplication::sendEvent(canvas, &preeditEvent);
1665 QCOMPARE(input->text(), QString(""));
1666 input->setValidator(0);
1673 TextInput element should only handle left/right keys until the cursor reaches
1674 the extent of the text, then they should ignore the keys.
1677 void tst_qdeclarativetextinput::navigation()
1679 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
1683 QVERIFY(canvas->rootObject() != 0);
1685 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1687 QVERIFY(input != 0);
1688 input->setCursorPosition(0);
1689 QTRY_VERIFY(input->hasActiveFocus() == true);
1690 simulateKey(canvas, Qt::Key_Left);
1691 QVERIFY(input->hasActiveFocus() == false);
1692 simulateKey(canvas, Qt::Key_Right);
1693 QVERIFY(input->hasActiveFocus() == true);
1694 //QT-2944: If text is selected, ensure we deselect upon cursor motion
1695 input->setCursorPosition(input->text().length());
1696 input->select(0,input->text().length());
1697 QVERIFY(input->selectionStart() != input->selectionEnd());
1698 simulateKey(canvas, Qt::Key_Right);
1699 QVERIFY(input->selectionStart() == input->selectionEnd());
1700 QVERIFY(input->selectionStart() == input->text().length());
1701 QVERIFY(input->hasActiveFocus() == true);
1702 simulateKey(canvas, Qt::Key_Right);
1703 QVERIFY(input->hasActiveFocus() == false);
1704 simulateKey(canvas, Qt::Key_Left);
1705 QVERIFY(input->hasActiveFocus() == true);
1707 // Up and Down should NOT do Home/End, even on Mac OS X (QTBUG-10438).
1708 input->setCursorPosition(2);
1709 QCOMPARE(input->cursorPosition(),2);
1710 simulateKey(canvas, Qt::Key_Up);
1711 QCOMPARE(input->cursorPosition(),2);
1712 simulateKey(canvas, Qt::Key_Down);
1713 QCOMPARE(input->cursorPosition(),2);
1718 void tst_qdeclarativetextinput::navigation_RTL()
1720 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
1724 QVERIFY(canvas->rootObject() != 0);
1726 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1728 QVERIFY(input != 0);
1729 const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
1730 input->setText(QString::fromUtf16(arabic_str, 11));
1732 input->setCursorPosition(0);
1733 QTRY_VERIFY(input->hasActiveFocus() == true);
1736 simulateKey(canvas, Qt::Key_Right);
1737 QVERIFY(input->hasActiveFocus() == false);
1740 simulateKey(canvas, Qt::Key_Left);
1741 QVERIFY(input->hasActiveFocus() == true);
1743 input->setCursorPosition(input->text().length());
1744 QVERIFY(input->hasActiveFocus() == true);
1747 simulateKey(canvas, Qt::Key_Left);
1748 QVERIFY(input->hasActiveFocus() == false);
1751 simulateKey(canvas, Qt::Key_Right);
1752 QVERIFY(input->hasActiveFocus() == true);
1757 void tst_qdeclarativetextinput::copyAndPaste() {
1758 #ifndef QT_NO_CLIPBOARD
1762 PasteboardRef pasteboard;
1763 OSStatus status = PasteboardCreate(0, &pasteboard);
1764 if (status == noErr)
1765 CFRelease(pasteboard);
1767 QSKIP("This machine doesn't support the clipboard");
1771 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }";
1772 QDeclarativeComponent textInputComponent(&engine);
1773 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1774 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1775 QVERIFY(textInput != 0);
1778 QCOMPARE(textInput->text().length(), 12);
1779 textInput->select(0, textInput->text().length());;
1781 QCOMPARE(textInput->selectedText(), QString("Hello world!"));
1782 QCOMPARE(textInput->selectedText().length(), 12);
1783 textInput->setCursorPosition(0);
1784 QVERIFY(textInput->canPaste());
1786 QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
1787 QCOMPARE(textInput->text().length(), 24);
1790 QVERIFY(textInput->canPaste());
1791 textInput->setReadOnly(true);
1792 QVERIFY(!textInput->canPaste());
1793 textInput->setReadOnly(false);
1794 QVERIFY(textInput->canPaste());
1797 textInput->setCursorPosition(0);
1798 textInput->selectWord();
1799 QCOMPARE(textInput->selectedText(), QString("Hello"));
1801 // select all and cut
1802 textInput->selectAll();
1804 QCOMPARE(textInput->text().length(), 0);
1806 QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
1807 QCOMPARE(textInput->text().length(), 24);
1809 // clear copy buffer
1810 QClipboard *clipboard = QApplication::clipboard();
1813 QVERIFY(!textInput->canPaste());
1815 // test that copy functionality is disabled
1816 // when echo mode is set to hide text/password mode
1819 QDeclarative1TextInput::EchoMode echoMode = QDeclarative1TextInput::EchoMode(index);
1820 textInput->setEchoMode(echoMode);
1821 textInput->setText("My password");
1822 textInput->select(0, textInput->text().length());;
1824 if (echoMode == QDeclarative1TextInput::Normal) {
1825 QVERIFY(!clipboard->text().isEmpty());
1826 QCOMPARE(clipboard->text(), QString("My password"));
1829 QVERIFY(clipboard->text().isEmpty());
1838 void tst_qdeclarativetextinput::canPasteEmpty() {
1839 #ifndef QT_NO_CLIPBOARD
1841 QApplication::clipboard()->clear();
1843 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }";
1844 QDeclarativeComponent textInputComponent(&engine);
1845 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1846 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1847 QVERIFY(textInput != 0);
1849 QWidgetLineControl lc;
1850 bool cp = !lc.isReadOnly() && QApplication::clipboard()->text().length() != 0;
1851 QCOMPARE(textInput->canPaste(), cp);
1856 void tst_qdeclarativetextinput::canPaste() {
1857 #ifndef QT_NO_CLIPBOARD
1859 QApplication::clipboard()->setText("Some text");
1861 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }";
1862 QDeclarativeComponent textInputComponent(&engine);
1863 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1864 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1865 QVERIFY(textInput != 0);
1867 QWidgetLineControl lc;
1868 bool cp = !lc.isReadOnly() && QApplication::clipboard()->text().length() != 0;
1869 QCOMPARE(textInput->canPaste(), cp);
1874 void tst_qdeclarativetextinput::passwordCharacter()
1876 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\"; font.family: \"Helvetica\"; echoMode: TextInput.Password }";
1877 QDeclarativeComponent textInputComponent(&engine);
1878 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1879 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1880 QVERIFY(textInput != 0);
1882 textInput->setPasswordCharacter("X");
1883 QSize contentsSize = textInput->contentsSize();
1884 textInput->setPasswordCharacter(".");
1885 // QTBUG-12383 content is updated and redrawn
1886 QVERIFY(contentsSize != textInput->contentsSize());
1891 void tst_qdeclarativetextinput::cursorDelegate()
1893 QDeclarativeView* view = createView(SRCDIR "/data/cursorTest.qml");
1896 QDeclarative1TextInput *textInputObject = view->rootObject()->findChild<QDeclarative1TextInput*>("textInputObject");
1897 QVERIFY(textInputObject != 0);
1898 QVERIFY(textInputObject->findChild<QDeclarativeItem*>("cursorInstance"));
1899 //Test Delegate gets created
1900 textInputObject->setFocus(true);
1901 QDeclarativeItem* delegateObject = textInputObject->findChild<QDeclarativeItem*>("cursorInstance");
1902 QVERIFY(delegateObject);
1903 //Test Delegate gets moved
1904 for(int i=0; i<= textInputObject->text().length(); i++){
1905 textInputObject->setCursorPosition(i);
1906 QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
1907 QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
1909 const QString preedit = "preedit";
1910 for (int i = 0; i <= preedit.length(); i++) {
1911 QInputMethodEvent event(preedit, QList<QInputMethodEvent::Attribute>()
1912 << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, 1, QVariant()));
1913 QApplication::sendEvent(view, &event);
1915 QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
1916 QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
1918 textInputObject->setCursorPosition(0);
1919 QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
1920 QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
1921 //Test Delegate gets deleted
1922 textInputObject->setCursorDelegate(0);
1923 QVERIFY(!textInputObject->findChild<QDeclarativeItem*>("cursorInstance"));
1928 void tst_qdeclarativetextinput::cursorVisible()
1930 QGraphicsScene scene;
1931 QGraphicsView view(&scene);
1933 QApplication::setActiveWindow(&view);
1934 QTest::qWaitForWindowShown(&view);
1935 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
1937 QDeclarative1TextInput input;
1938 QSignalSpy spy(&input, SIGNAL(cursorVisibleChanged(bool)));
1940 QCOMPARE(input.isCursorVisible(), false);
1942 input.setCursorVisible(true);
1943 QCOMPARE(input.isCursorVisible(), true);
1944 QCOMPARE(spy.count(), 1);
1946 input.setCursorVisible(false);
1947 QCOMPARE(input.isCursorVisible(), false);
1948 QCOMPARE(spy.count(), 2);
1950 input.setFocus(true);
1951 QCOMPARE(input.isCursorVisible(), false);
1952 QCOMPARE(spy.count(), 2);
1954 scene.addItem(&input);
1955 QCOMPARE(input.isCursorVisible(), true);
1956 QCOMPARE(spy.count(), 3);
1958 input.setFocus(false);
1959 QCOMPARE(input.isCursorVisible(), false);
1960 QCOMPARE(spy.count(), 4);
1962 input.setFocus(true);
1963 QCOMPARE(input.isCursorVisible(), true);
1964 QCOMPARE(spy.count(), 5);
1967 QCOMPARE(input.isCursorVisible(), false);
1968 QCOMPARE(spy.count(), 6);
1971 QCOMPARE(input.isCursorVisible(), true);
1972 QCOMPARE(spy.count(), 7);
1975 QCOMPARE(input.isCursorVisible(), false);
1976 QCOMPARE(spy.count(), 8);
1979 QCOMPARE(input.isCursorVisible(), true);
1980 QCOMPARE(spy.count(), 9);
1982 // on mac, setActiveWindow(0) on mac does not deactivate the current application
1983 // (you have to switch to a different app or hide the current app to trigger this)
1984 #if !defined(Q_WS_MAC)
1985 QApplication::setActiveWindow(0);
1986 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(0));
1987 QCOMPARE(input.isCursorVisible(), false);
1988 QCOMPARE(spy.count(), 10);
1990 QApplication::setActiveWindow(&view);
1991 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
1992 QCOMPARE(input.isCursorVisible(), true);
1993 QCOMPARE(spy.count(), 11);
1997 void tst_qdeclarativetextinput::cursorRectangle()
1999 QString text = "Hello World!";
2001 QDeclarative1TextInput input;
2002 input.setText(text);
2003 QFontMetricsF fm(input.font());
2004 input.setWidth(fm.width(text.mid(0, 5)));
2008 // some tolerance for different fonts.
2010 const int error = 2;
2012 const int error = 5;
2015 for (int i = 0; i <= 5; ++i) {
2016 input.setCursorPosition(i);
2017 r = input.cursorRectangle();
2018 int textWidth = fm.width(text.mid(0, i));
2020 QVERIFY(r.left() < textWidth + error);
2021 QVERIFY(r.right() > textWidth - error);
2022 QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
2025 // Check the cursor rectangle remains within the input bounding rect when auto scrolling.
2026 QVERIFY(r.left() < input.boundingRect().width());
2027 QVERIFY(r.right() >= input.width() - error);
2029 for (int i = 6; i < text.length(); ++i) {
2030 input.setCursorPosition(i);
2031 QCOMPARE(r, input.cursorRectangle());
2032 QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
2035 for (int i = text.length() - 2; i >= 0; --i) {
2036 input.setCursorPosition(i);
2037 r = input.cursorRectangle();
2038 QVERIFY(r.right() >= 0);
2039 QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
2043 void tst_qdeclarativetextinput::readOnly()
2045 QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml");
2049 QVERIFY(canvas->rootObject() != 0);
2051 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
2053 QVERIFY(input != 0);
2054 QTRY_VERIFY(input->hasActiveFocus() == true);
2055 QVERIFY(input->isReadOnly() == true);
2056 QString initial = input->text();
2057 for(int k=Qt::Key_0; k<=Qt::Key_Z; k++)
2058 simulateKey(canvas, k);
2059 simulateKey(canvas, Qt::Key_Return);
2060 simulateKey(canvas, Qt::Key_Space);
2061 simulateKey(canvas, Qt::Key_Escape);
2062 QCOMPARE(input->text(), initial);
2067 void tst_qdeclarativetextinput::echoMode()
2069 QDeclarativeView *canvas = createView(SRCDIR "/data/echoMode.qml");
2072 QApplication::setActiveWindow(canvas);
2073 QTest::qWaitForWindowShown(canvas);
2074 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
2076 QVERIFY(canvas->rootObject() != 0);
2078 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
2080 QVERIFY(input != 0);
2081 QTRY_VERIFY(input->hasActiveFocus() == true);
2082 QString initial = input->text();
2083 Qt::InputMethodHints ref;
2084 QCOMPARE(initial, QLatin1String("ABCDefgh"));
2085 QCOMPARE(input->echoMode(), QDeclarative1TextInput::Normal);
2086 QCOMPARE(input->displayText(), input->text());
2088 ref &= ~Qt::ImhHiddenText;
2089 ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2090 QCOMPARE(input->inputMethodHints(), ref);
2091 QCOMPARE(input->imHints(), Qt::ImhNone);
2092 input->setEchoMode(QDeclarative1TextInput::NoEcho);
2093 QCOMPARE(input->text(), initial);
2094 QCOMPARE(input->displayText(), QLatin1String(""));
2095 QCOMPARE(input->passwordCharacter(), QLatin1String("*"));
2097 ref |= Qt::ImhHiddenText;
2098 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2099 QCOMPARE(input->inputMethodHints(), ref);
2100 QCOMPARE(input->imHints(), Qt::ImhNone);
2101 input->setEchoMode(QDeclarative1TextInput::Password);
2103 ref |= Qt::ImhHiddenText;
2104 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2105 QCOMPARE(input->text(), initial);
2106 QCOMPARE(input->displayText(), QLatin1String("********"));
2107 QCOMPARE(input->inputMethodHints(), ref);
2108 QCOMPARE(input->imHints(), Qt::ImhNone);
2109 input->setPasswordCharacter(QChar('Q'));
2110 QCOMPARE(input->passwordCharacter(), QLatin1String("Q"));
2111 QCOMPARE(input->text(), initial);
2112 QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
2113 input->setEchoMode(QDeclarative1TextInput::PasswordEchoOnEdit);
2114 //PasswordEchoOnEdit
2115 ref &= ~Qt::ImhHiddenText;
2116 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2117 QCOMPARE(input->inputMethodHints(), ref);
2118 QCOMPARE(input->imHints(), Qt::ImhNone);
2119 QCOMPARE(input->text(), initial);
2120 QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
2121 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("QQQQQQQQ"));
2122 QTest::keyPress(canvas, Qt::Key_A);//Clearing previous entry is part of PasswordEchoOnEdit
2123 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
2124 QCOMPARE(input->text(), QLatin1String("a"));
2125 QCOMPARE(input->displayText(), QLatin1String("a"));
2126 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("a"));
2127 input->setFocus(false);
2128 QVERIFY(input->hasActiveFocus() == false);
2129 QCOMPARE(input->displayText(), QLatin1String("Q"));
2130 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("Q"));
2131 input->setFocus(true);
2132 QInputMethodEvent inputEvent;
2133 inputEvent.setCommitString(initial);
2134 QApplication::sendEvent(canvas, &inputEvent);
2135 QCOMPARE(input->text(), initial);
2136 QCOMPARE(input->displayText(), initial);
2137 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial);
2139 // Test echo mode doesn't override imHints.
2140 input->setIMHints(Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2141 ref |= Qt::ImhDialableCharactersOnly;
2143 input->setEchoMode(QDeclarative1TextInput::Normal);
2144 ref |= Qt::ImhHiddenText;
2145 ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2146 QCOMPARE(input->inputMethodHints(), ref);
2147 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2149 input->setEchoMode(QDeclarative1TextInput::NoEcho);
2150 ref |= Qt::ImhHiddenText;
2151 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2152 QCOMPARE(input->inputMethodHints(), ref);
2153 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2155 input->setEchoMode(QDeclarative1TextInput::Password);
2156 ref |= Qt::ImhHiddenText;
2157 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2158 QCOMPARE(input->inputMethodHints(), ref);
2159 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2160 //PasswordEchoOnEdit
2161 input->setEchoMode(QDeclarative1TextInput::PasswordEchoOnEdit);
2162 ref &= ~Qt::ImhHiddenText;
2163 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2164 QCOMPARE(input->inputMethodHints(), ref);
2165 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2167 input->setEchoMode(QDeclarative1TextInput::Normal);
2168 ref |= Qt::ImhHiddenText;
2169 ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2170 QCOMPARE(input->inputMethodHints(), ref);
2171 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2177 #ifdef QT_GUI_PASSWORD_ECHO_DELAY
2178 void tst_qdeclarativetextinput::passwordEchoDelay()
2180 QDeclarativeView *canvas = createView(SRCDIR "/data/echoMode.qml");
2183 QApplication::setActiveWindow(canvas);
2184 QTest::qWaitForWindowShown(canvas);
2185 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
2187 QVERIFY(canvas->rootObject() != 0);
2189 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
2191 QChar fillChar = QLatin1Char('*');
2193 input->setEchoMode(QDeclarativeTextInput::Password);
2194 QCOMPARE(input->displayText(), QString(8, fillChar));
2195 input->setText(QString());
2196 QCOMPARE(input->displayText(), QString());
2198 QTest::keyPress(canvas, '0');
2199 QTest::keyPress(canvas, '1');
2200 QTest::keyPress(canvas, '2');
2201 QCOMPARE(input->displayText(), QString(2, fillChar) + QLatin1Char('2'));
2202 QTest::keyPress(canvas, '3');
2203 QTest::keyPress(canvas, '4');
2204 QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
2205 QTest::keyPress(canvas, Qt::Key_Backspace);
2206 QCOMPARE(input->displayText(), QString(4, fillChar));
2207 QTest::keyPress(canvas, '4');
2208 QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
2209 QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
2210 QTRY_COMPARE(input->displayText(), QString(5, fillChar));
2211 QTest::keyPress(canvas, '5');
2212 QCOMPARE(input->displayText(), QString(5, fillChar) + QLatin1Char('5'));
2213 input->setFocus(false);
2214 QVERIFY(!input->hasFocus());
2215 QCOMPARE(input->displayText(), QString(6, fillChar));
2216 input->setFocus(true);
2217 QTRY_VERIFY(input->hasFocus());
2218 QCOMPARE(input->displayText(), QString(6, fillChar));
2219 QTest::keyPress(canvas, '6');
2220 QCOMPARE(input->displayText(), QString(6, fillChar) + QLatin1Char('6'));
2222 QInputMethodEvent ev;
2223 ev.setCommitString(QLatin1String("7"));
2224 QApplication::sendEvent(canvas, &ev);
2225 QCOMPARE(input->displayText(), QString(7, fillChar) + QLatin1Char('7'));
2232 void tst_qdeclarativetextinput::simulateKey(QDeclarativeView *view, int key)
2234 QKeyEvent press(QKeyEvent::KeyPress, key, 0);
2235 QKeyEvent release(QKeyEvent::KeyRelease, key, 0);
2237 QApplication::sendEvent(view, &press);
2238 QApplication::sendEvent(view, &release);
2241 QDeclarativeView *tst_qdeclarativetextinput::createView(const QString &filename)
2243 QDeclarativeView *canvas = new QDeclarativeView(0);
2245 canvas->setSource(QUrl::fromLocalFile(filename));
2250 void tst_qdeclarativetextinput::openInputPanelOnClick()
2252 PlatformInputContext ic;
2253 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
2254 inputPanelPrivate->testContext = ⁣
2256 QGraphicsScene scene;
2257 QGraphicsView view(&scene);
2258 QDeclarative1TextInput input;
2259 QSignalSpy focusOnPressSpy(&input, SIGNAL(activeFocusOnPressChanged(bool)));
2260 input.setText("Hello world");
2262 scene.addItem(&input);
2264 qApp->setAutoSipEnabled(true);
2265 QApplication::setActiveWindow(&view);
2266 QTest::qWaitForWindowShown(&view);
2267 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2269 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&input);
2270 QDeclarative1TextInputPrivate *inputPrivate = static_cast<QDeclarative1TextInputPrivate*>(pri);
2272 // input panel on click
2273 inputPrivate->showInputPanelOnFocus = false;
2275 QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
2276 view.style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
2277 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2278 QApplication::processEvents();
2279 if (behavior == QStyle::RSIP_OnMouseClickAndAlreadyFocused) {
2280 QCOMPARE(ic.isInputPanelVisible(), false);
2281 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2282 QApplication::processEvents();
2283 QCOMPARE(ic.isInputPanelVisible(), true);
2284 } else if (behavior == QStyle::RSIP_OnMouseClick) {
2285 QCOMPARE(ic.isInputPanelVisible(), true);
2288 ic.m_showInputPanelCallCount = 0;
2289 ic.m_hideInputPanelCallCount = 0;
2291 // focus should not cause input panels to open or close
2292 input.setFocus(false);
2293 input.setFocus(true);
2294 input.setFocus(false);
2295 input.setFocus(true);
2296 input.setFocus(false);
2297 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2298 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2301 void tst_qdeclarativetextinput::openInputPanelOnFocus()
2303 PlatformInputContext ic;
2304 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
2305 inputPanelPrivate->testContext = ⁣
2309 QGraphicsScene scene;
2310 QGraphicsView view(&scene);
2311 QDeclarative1TextInput input;
2312 QSignalSpy focusOnPressSpy(&input, SIGNAL(activeFocusOnPressChanged(bool)));
2313 input.setText("Hello world");
2315 scene.addItem(&input);
2317 qApp->setAutoSipEnabled(true);
2318 QApplication::setActiveWindow(&view);
2319 QTest::qWaitForWindowShown(&view);
2320 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2322 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&input);
2323 QDeclarative1TextInputPrivate *inputPrivate = static_cast<QDeclarative1TextInputPrivate*>(pri);
2324 inputPrivate->showInputPanelOnFocus = true;
2326 // test default values
2327 QVERIFY(input.focusOnPress());
2328 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2329 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2331 // focus on press, input panel on focus
2332 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2333 QApplication::processEvents();
2334 QVERIFY(input.hasActiveFocus());
2335 QCOMPARE(ic.isInputPanelVisible(), true);
2338 // no events on release
2339 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2340 QCOMPARE(ic.isInputPanelVisible(), false);
2343 // if already focused, input panel can be opened on press
2344 QVERIFY(input.hasActiveFocus());
2345 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2346 QApplication::processEvents();
2347 QCOMPARE(ic.isInputPanelVisible(), true);
2350 // input method should stay enabled if focus
2351 // is lost to an item that also accepts inputs
2352 QDeclarative1TextInput anotherInput;
2353 scene.addItem(&anotherInput);
2354 anotherInput.setFocus(true);
2355 QApplication::processEvents();
2356 QCOMPARE(ic.isInputPanelVisible(), true);
2358 QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
2360 // input method should be disabled if focus
2361 // is lost to an item that doesn't accept inputs
2362 QDeclarativeItem item;
2363 scene.addItem(&item);
2364 item.setFocus(true);
2365 QApplication::processEvents();
2366 QCOMPARE(ic.isInputPanelVisible(), false);
2367 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2370 // no automatic input panel events should
2371 // be sent if activeFocusOnPress is false
2372 input.setFocusOnPress(false);
2373 QCOMPARE(focusOnPressSpy.count(),1);
2374 input.setFocusOnPress(false);
2375 QCOMPARE(focusOnPressSpy.count(),1);
2376 input.setFocus(false);
2377 input.setFocus(true);
2378 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2379 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2380 QApplication::processEvents();
2381 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2382 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2384 // one show input panel event should
2385 // be set when openSoftwareInputPanel is called
2386 input.openSoftwareInputPanel();
2387 QCOMPARE(ic.isInputPanelVisible(), true);
2388 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2391 // one close input panel event should
2392 // be sent when closeSoftwareInputPanel is called
2393 input.closeSoftwareInputPanel();
2394 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2395 QVERIFY(ic.m_hideInputPanelCallCount > 0);
2398 // set activeFocusOnPress back to true
2399 input.setFocusOnPress(true);
2400 QCOMPARE(focusOnPressSpy.count(),2);
2401 input.setFocusOnPress(true);
2402 QCOMPARE(focusOnPressSpy.count(),2);
2403 input.setFocus(false);
2404 QApplication::processEvents();
2405 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2406 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2409 // input panel should not re-open
2410 // if focus has already been set
2411 input.setFocus(true);
2412 QCOMPARE(ic.isInputPanelVisible(), true);
2414 input.setFocus(true);
2415 QCOMPARE(ic.isInputPanelVisible(), false);
2417 // input method should be disabled
2418 // if TextInput loses focus
2419 input.setFocus(false);
2420 QApplication::processEvents();
2421 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2423 // input method should not be enabled
2424 // if TextEdit is read only.
2425 input.setReadOnly(true);
2427 input.setFocus(true);
2428 QApplication::processEvents();
2429 QCOMPARE(ic.isInputPanelVisible(), false);
2430 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2433 class MyTextInput : public QDeclarative1TextInput
2436 MyTextInput(QDeclarativeItem *parent = 0) : QDeclarative1TextInput(parent)
2440 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
2443 QDeclarative1TextInput::paint(painter, option, widget);
2448 void tst_qdeclarativetextinput::setHAlignClearCache()
2450 QGraphicsScene scene;
2451 QGraphicsView view(&scene);
2453 input.setText("Hello world");
2454 scene.addItem(&input);
2456 QApplication::setActiveWindow(&view);
2457 QTest::qWaitForWindowShown(&view);
2458 QTRY_VERIFY(input.nbPaint >= 1);
2460 input.setHAlign(QDeclarative1TextInput::AlignRight);
2461 QApplication::processEvents();
2462 //Changing the alignment should trigger a repaint
2463 QTRY_VERIFY(input.nbPaint >= 1);
2466 void tst_qdeclarativetextinput::focusOutClearSelection()
2468 QGraphicsScene scene;
2469 QGraphicsView view(&scene);
2470 QDeclarative1TextInput input;
2471 QDeclarative1TextInput input2;
2472 input.setText(QLatin1String("Hello world"));
2473 input.setFocus(true);
2474 scene.addItem(&input2);
2475 scene.addItem(&input);
2477 QApplication::setActiveWindow(&view);
2478 QTest::qWaitForWindowShown(&view);
2480 //The selection should work
2481 QTRY_COMPARE(input.selectedText(), QLatin1String("llo"));
2482 input2.setFocus(true);
2483 QApplication::processEvents();
2484 //The input lost the focus selection should be cleared
2485 QTRY_COMPARE(input.selectedText(), QLatin1String(""));
2488 void tst_qdeclarativetextinput::geometrySignals()
2490 QDeclarativeComponent component(&engine, SRCDIR "/data/geometrySignals.qml");
2491 QObject *o = component.create();
2493 QCOMPARE(o->property("bindingWidth").toInt(), 400);
2494 QCOMPARE(o->property("bindingHeight").toInt(), 500);
2498 void tst_qdeclarativetextinput::testQtQuick11Attributes()
2500 QFETCH(QString, code);
2501 QFETCH(QString, warning);
2502 QFETCH(QString, error);
2504 QDeclarativeEngine engine;
2507 QDeclarativeComponent valid(&engine);
2508 valid.setData("import QtQuick 1.1; TextInput { " + code.toUtf8() + " }", QUrl(""));
2509 obj = valid.create();
2511 QVERIFY(valid.errorString().isEmpty());
2514 QDeclarativeComponent invalid(&engine);
2515 invalid.setData("import QtQuick 1.0; TextInput { " + code.toUtf8() + " }", QUrl(""));
2516 QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
2517 obj = invalid.create();
2518 QCOMPARE(invalid.errorString(), error);
2522 void tst_qdeclarativetextinput::testQtQuick11Attributes_data()
2524 QTest::addColumn<QString>("code");
2525 QTest::addColumn<QString>("warning");
2526 QTest::addColumn<QString>("error");
2528 QTest::newRow("canPaste") << "property bool foo: canPaste"
2529 << "<Unknown File>:1: ReferenceError: Can't find variable: canPaste"
2532 QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)"
2533 << "<Unknown File>:1: ReferenceError: Can't find variable: moveCursorSelection"
2536 QTest::newRow("deselect") << "Component.onCompleted: deselect()"
2537 << "<Unknown File>:1: ReferenceError: Can't find variable: deselect"
2541 void tst_qdeclarativetextinput::preeditAutoScroll()
2543 QString committedText = "super";
2544 QString preeditText = "califragisiticexpialidocious!";
2546 QGraphicsScene scene;
2547 QGraphicsView view(&scene);
2548 QDeclarative1TextInput input;
2549 QFontMetricsF fm(input.font());
2550 input.setWidth(fm.width(committedText));
2551 input.setText(committedText);
2553 input.setFocus(true);
2554 scene.addItem(&input);
2556 QApplication::setActiveWindow(&view);
2557 QTest::qWaitForWindowShown(&view);
2558 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2560 QSignalSpy cursorRectangleSpy(&input, SIGNAL(cursorRectangleChanged()));
2561 int cursorRectangleChanges = 0;
2563 // test the text is scrolled so the preedit is visible.
2564 sendPreeditText(preeditText.mid(0, 3), 1);
2565 QVERIFY(input.positionAt(0) != 0);
2566 QVERIFY(input.cursorRectangle().left() < input.boundingRect().width());
2567 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2569 // test the text is scrolled back when the preedit is removed.
2570 QInputMethodEvent emptyEvent;
2571 QApplication::sendEvent(&view, &emptyEvent);
2572 QCOMPARE(input.positionAt(0), 0);
2573 QCOMPARE(input.positionAt(input.width()), 5);
2574 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2576 // some tolerance for different fonts.
2578 const int error = 2;
2580 const int error = 5;
2583 // test if the preedit is larger than the text input that the
2584 // character preceding the cursor is still visible.
2585 qreal x = input.positionToRectangle(0).x();
2586 for (int i = 0; i < 3; ++i) {
2587 sendPreeditText(preeditText, i + 1);
2588 QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i)) - error);
2589 QVERIFY(input.positionToRectangle(0).x() < x);
2590 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2591 x = input.positionToRectangle(0).x();
2593 for (int i = 1; i >= 0; --i) {
2594 sendPreeditText(preeditText, i + 1);
2595 QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i)) - error);
2596 QVERIFY(input.positionToRectangle(0).x() > x);
2597 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2598 x = input.positionToRectangle(0).x();
2601 // Test incrementing the preedit cursor doesn't cause further
2602 // scrolling when right most text is visible.
2603 sendPreeditText(preeditText, preeditText.length() - 3);
2604 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2605 x = input.positionToRectangle(0).x();
2606 for (int i = 2; i >= 0; --i) {
2607 sendPreeditText(preeditText, preeditText.length() - i);
2608 QCOMPARE(input.positionToRectangle(0).x(), x);
2609 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2611 for (int i = 1; i < 3; ++i) {
2612 sendPreeditText(preeditText, preeditText.length() - i);
2613 QCOMPARE(input.positionToRectangle(0).x(), x);
2614 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2617 // Test disabling auto scroll.
2618 QApplication::sendEvent(&view, &emptyEvent);
2620 input.setAutoScroll(false);
2621 sendPreeditText(preeditText.mid(0, 3), 1);
2622 QCOMPARE(input.positionAt(0), 0);
2623 QCOMPARE(input.positionAt(input.width()), 5);
2625 QApplication::sendEvent(&view, &emptyEvent);
2626 input.setAutoScroll(true);
2627 // Test committing pre-edit text at the start of the string. QTBUG-18789
2628 input.setCursorPosition(0);
2629 sendPreeditText(input.text(), 5);
2630 QCOMPARE(input.positionAt(0), 0);
2632 QInputMethodEvent event;
2633 event.setCommitString(input.text());
2634 QApplication::sendEvent(&view, &emptyEvent);
2636 QCOMPARE(input.positionAt(0), 0);
2637 QCOMPARE(input.positionAt(input.width()), 5);
2640 void tst_qdeclarativetextinput::preeditMicroFocus()
2642 QString preeditText = "super";
2643 PlatformInputContext ic;
2644 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
2645 inputPanelPrivate->testContext = ⁣
2647 QGraphicsScene scene;
2648 QGraphicsView view(&scene);
2649 QDeclarative1TextInput input;
2651 input.setAutoScroll(false);
2652 input.setFocus(true);
2653 scene.addItem(&input);
2655 QApplication::setActiveWindow(&view);
2656 QTest::qWaitForWindowShown(&view);
2657 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2660 QRect previousRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2662 // Verify that the micro focus rect is positioned the same for position 0 as
2663 // it would be if there was no preedit text.
2665 sendPreeditText(preeditText, 0);
2666 currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2667 QCOMPARE(currentRect, previousRect);
2668 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
2669 QVERIFY(ic.updateCallCount > 0);
2672 // Verify that the micro focus rect moves to the left as the cursor position
2674 for (int i = 1; i <= 5; ++i) {
2676 sendPreeditText(preeditText, i);
2677 currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2678 QVERIFY(previousRect.left() < currentRect.left());
2679 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
2680 QVERIFY(ic.updateCallCount > 0);
2682 previousRect = currentRect;
2685 // Verify that if there is no preedit cursor then the micro focus rect is the
2686 // same as it would be if it were positioned at the end of the preedit text.
2687 sendPreeditText(preeditText, 0);
2689 QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
2690 QApplication::sendEvent(qApp->inputPanel()->inputItem(), &imEvent);
2691 currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2692 QCOMPARE(currentRect, previousRect);
2693 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
2694 QVERIFY(ic.updateCallCount > 0);
2698 void tst_qdeclarativetextinput::inputContextMouseHandler()
2700 PlatformInputContext platformInputContext;
2701 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
2702 inputPanelPrivate->testContext = &platformInputContext;
2704 QString text = "supercalifragisiticexpialidocious!";
2706 QGraphicsScene scene;
2707 QGraphicsView view(&scene);
2709 QDeclarative1TextInput input;
2710 input.setWidth(200);
2711 input.setCursorPosition(12);
2713 input.setFocus(true);
2714 scene.addItem(&input);
2716 QApplication::setActiveWindow(&view);
2717 QTest::qWaitForWindowShown(&view);
2718 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2720 QFontMetricsF fm(input.font());
2721 const qreal y = fm.height() / 2;
2723 QPoint position2 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 2)), y)));
2725 QInputMethodEvent inputEvent(text.mid(0, 5), QList<QInputMethodEvent::Attribute>());
2726 QApplication::sendEvent(&view, &inputEvent);
2728 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
2729 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
2730 QApplication::processEvents();
2732 QCOMPARE(platformInputContext.m_action, QInputPanel::Click);
2733 QCOMPARE(platformInputContext.m_invokeActionCallCount, 1);
2734 QCOMPARE(platformInputContext.m_cursorPosition, 2);
2737 void tst_qdeclarativetextinput::inputMethodComposing()
2739 QString text = "supercalifragisiticexpialidocious!";
2741 QGraphicsScene scene;
2742 QGraphicsView view(&scene);
2743 QDeclarative1TextInput input;
2744 input.setWidth(200);
2745 input.setText(text.mid(0, 12));
2746 input.setCursorPosition(12);
2748 input.setFocus(true);
2749 scene.addItem(&input);
2751 QApplication::setActiveWindow(&view);
2752 QTest::qWaitForWindowShown(&view);
2753 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2755 QSignalSpy spy(&input, SIGNAL(inputMethodComposingChanged()));
2757 QCOMPARE(input.isInputMethodComposing(), false);
2760 QInputMethodEvent inputEvent(text.mid(3), QList<QInputMethodEvent::Attribute>());
2761 QApplication::sendEvent(qApp->inputPanel()->inputItem(), &inputEvent);
2764 QCOMPARE(input.isInputMethodComposing(), true);
2765 QCOMPARE(spy.count(), 1);
2768 QInputMethodEvent inputEvent(text.mid(12), QList<QInputMethodEvent::Attribute>());
2769 QApplication::sendEvent(qApp->inputPanel()->inputItem(), &inputEvent);
2772 QCOMPARE(input.isInputMethodComposing(), true);
2773 QCOMPARE(spy.count(), 1);
2776 QInputMethodEvent inputEvent;
2777 QApplication::sendEvent(qApp->inputPanel()->inputItem(), &inputEvent);
2779 QCOMPARE(input.isInputMethodComposing(), false);
2780 QCOMPARE(spy.count(), 2);
2783 void tst_qdeclarativetextinput::cursorRectangleSize()
2785 QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml");
2786 QVERIFY(canvas->rootObject() != 0);
2789 QApplication::setActiveWindow(canvas);
2790 QTest::qWaitForWindowShown(canvas);
2792 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
2793 QVERIFY(textInput != 0);
2794 textInput->setFocus(Qt::OtherFocusReason);
2795 QRectF cursorRect = textInput->positionToRectangle(textInput->cursorPosition());
2796 QRectF microFocusFromScene = canvas->scene()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
2797 QRectF microFocusFromApp= QApplication::focusWidget()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
2799 QCOMPARE(microFocusFromScene.size(), cursorRect.size());
2800 QCOMPARE(microFocusFromApp.size(), cursorRect.size());
2803 QTEST_MAIN(tst_qdeclarativetextinput)
2805 #include "tst_qdeclarativetextinput.moc"