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 <QInputContext>
52 #include <QtWidgets/5.0.0/QtWidgets/private/qapplication_p.h>
54 #include "qplatformdefs.h"
56 Q_DECLARE_METATYPE(QDeclarative1TextInput::SelectionMode)
58 QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
60 // XXX This will be replaced by some clever persistent platform image store.
61 QString persistent_dir = SRCDIR "/data";
62 QString arch = "unknown-architecture"; // QTest needs to help with this.
64 QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png";
66 if (!QFile::exists(expectfile)) {
67 actual.save(expectfile);
68 qWarning() << "created" << expectfile;
74 class tst_qdeclarativetextinput : public QObject
79 tst_qdeclarativetextinput();
88 void isRightToLeft_data();
90 void moveCursorSelection_data();
91 void moveCursorSelection();
92 void moveCursorSelectionSequence_data();
93 void moveCursorSelectionSequence();
94 void mouseSelection_data();
95 void mouseSelection();
96 void deferEnableSelectByMouse_data();
97 void deferEnableSelectByMouse();
98 void deferDisableSelectByMouse_data();
99 void deferDisableSelectByMouse();
100 void dragMouseSelection();
101 void mouseSelectionMode_data();
102 void mouseSelectionMode();
104 void horizontalAlignment_data();
105 void horizontalAlignment();
106 void horizontalAlignment_RightToLeft();
115 void passwordCharacter();
116 void cursorDelegate();
117 void cursorVisible();
118 void cursorRectangle();
120 void navigation_RTL();
122 void canPasteEmpty();
126 void openInputPanelOnClick();
127 void openInputPanelOnFocus();
128 void setHAlignClearCache();
129 void focusOutClearSelection();
132 #ifdef QT_GUI_PASSWORD_ECHO_DELAY
133 void passwordEchoDelay();
135 void geometrySignals();
136 void testQtQuick11Attributes();
137 void testQtQuick11Attributes_data();
139 void preeditAutoScroll();
140 void preeditMicroFocus();
141 void inputContextMouseHandler();
142 void inputMethodComposing();
143 void cursorRectangleSize();
146 void simulateKey(QDeclarativeView *, int key);
147 QDeclarativeView *createView(const QString &filename);
149 QDeclarativeEngine engine;
150 QStringList standard;
151 QStringList colorStrings;
154 tst_qdeclarativetextinput::tst_qdeclarativetextinput()
156 standard << "the quick brown fox jumped over the lazy dog"
157 << "It's supercalifragisiticexpialidocious!"
162 colorStrings << "aliceblue"
176 void tst_qdeclarativetextinput::text()
179 QDeclarativeComponent textinputComponent(&engine);
180 textinputComponent.setData("import QtQuick 1.0\nTextInput { text: \"\" }", QUrl());
181 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
183 QVERIFY(textinputObject != 0);
184 QCOMPARE(textinputObject->text(), QString(""));
186 delete textinputObject;
189 for (int i = 0; i < standard.size(); i++)
191 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"" + standard.at(i) + "\" }";
192 QDeclarativeComponent textinputComponent(&engine);
193 textinputComponent.setData(componentStr.toLatin1(), QUrl());
194 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
196 QVERIFY(textinputObject != 0);
197 QCOMPARE(textinputObject->text(), standard.at(i));
199 delete textinputObject;
204 void tst_qdeclarativetextinput::width()
206 // uses Font metrics to find the width for standard
208 QDeclarativeComponent textinputComponent(&engine);
209 textinputComponent.setData("import QtQuick 1.0\nTextInput { text: \"\" }", QUrl());
210 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
212 QVERIFY(textinputObject != 0);
213 QCOMPARE(textinputObject->width(), 0.0);
215 delete textinputObject;
218 for (int i = 0; i < standard.size(); i++)
222 qreal metricWidth = fm.width(standard.at(i));
224 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"" + standard.at(i) + "\" }";
225 QDeclarativeComponent textinputComponent(&engine);
226 textinputComponent.setData(componentStr.toLatin1(), QUrl());
227 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
229 QVERIFY(textinputObject != 0);
230 int delta = abs(int(int(textinputObject->width()) - metricWidth));
231 QVERIFY(delta <= 3.0); // As best as we can hope for cross-platform.
233 delete textinputObject;
237 void tst_qdeclarativetextinput::font()
239 //test size, then bold, then italic, then family
241 QString componentStr = "import QtQuick 1.0\nTextInput { font.pointSize: 40; text: \"Hello World\" }";
242 QDeclarativeComponent textinputComponent(&engine);
243 textinputComponent.setData(componentStr.toLatin1(), QUrl());
244 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
246 QVERIFY(textinputObject != 0);
247 QCOMPARE(textinputObject->font().pointSize(), 40);
248 QCOMPARE(textinputObject->font().bold(), false);
249 QCOMPARE(textinputObject->font().italic(), false);
251 delete textinputObject;
255 QString componentStr = "import QtQuick 1.0\nTextInput { font.bold: true; text: \"Hello World\" }";
256 QDeclarativeComponent textinputComponent(&engine);
257 textinputComponent.setData(componentStr.toLatin1(), QUrl());
258 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
260 QVERIFY(textinputObject != 0);
261 QCOMPARE(textinputObject->font().bold(), true);
262 QCOMPARE(textinputObject->font().italic(), false);
264 delete textinputObject;
268 QString componentStr = "import QtQuick 1.0\nTextInput { font.italic: true; text: \"Hello World\" }";
269 QDeclarativeComponent textinputComponent(&engine);
270 textinputComponent.setData(componentStr.toLatin1(), QUrl());
271 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
273 QVERIFY(textinputObject != 0);
274 QCOMPARE(textinputObject->font().italic(), true);
275 QCOMPARE(textinputObject->font().bold(), false);
277 delete textinputObject;
281 QString componentStr = "import QtQuick 1.0\nTextInput { font.family: \"Helvetica\"; text: \"Hello World\" }";
282 QDeclarativeComponent textinputComponent(&engine);
283 textinputComponent.setData(componentStr.toLatin1(), QUrl());
284 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
286 QVERIFY(textinputObject != 0);
287 QCOMPARE(textinputObject->font().family(), QString("Helvetica"));
288 QCOMPARE(textinputObject->font().bold(), false);
289 QCOMPARE(textinputObject->font().italic(), false);
291 delete textinputObject;
295 QString componentStr = "import QtQuick 1.0\nTextInput { font.family: \"\"; text: \"Hello World\" }";
296 QDeclarativeComponent textinputComponent(&engine);
297 textinputComponent.setData(componentStr.toLatin1(), QUrl());
298 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
300 QVERIFY(textinputObject != 0);
301 QCOMPARE(textinputObject->font().family(), QString(""));
303 delete textinputObject;
307 void tst_qdeclarativetextinput::color()
310 for (int i = 0; i < colorStrings.size(); i++)
312 QString componentStr = "import QtQuick 1.0\nTextInput { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
313 QDeclarativeComponent textinputComponent(&engine);
314 textinputComponent.setData(componentStr.toLatin1(), QUrl());
315 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
316 QVERIFY(textinputObject != 0);
317 QCOMPARE(textinputObject->color(), QColor(colorStrings.at(i)));
319 delete textinputObject;
322 //test selection color
323 for (int i = 0; i < colorStrings.size(); i++)
325 QString componentStr = "import QtQuick 1.0\nTextInput { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
326 QDeclarativeComponent textinputComponent(&engine);
327 textinputComponent.setData(componentStr.toLatin1(), QUrl());
328 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
329 QVERIFY(textinputObject != 0);
330 QCOMPARE(textinputObject->selectionColor(), QColor(colorStrings.at(i)));
332 delete textinputObject;
335 //test selected text color
336 for (int i = 0; i < colorStrings.size(); i++)
338 QString componentStr = "import QtQuick 1.0\nTextInput { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
339 QDeclarativeComponent textinputComponent(&engine);
340 textinputComponent.setData(componentStr.toLatin1(), QUrl());
341 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
342 QVERIFY(textinputObject != 0);
343 QCOMPARE(textinputObject->selectedTextColor(), QColor(colorStrings.at(i)));
345 delete textinputObject;
349 QString colorStr = "#AA001234";
350 QColor testColor("#001234");
351 testColor.setAlpha(170);
353 QString componentStr = "import QtQuick 1.0\nTextInput { color: \"" + colorStr + "\"; text: \"Hello World\" }";
354 QDeclarativeComponent textinputComponent(&engine);
355 textinputComponent.setData(componentStr.toLatin1(), QUrl());
356 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
358 QVERIFY(textinputObject != 0);
359 QCOMPARE(textinputObject->color(), testColor);
361 delete textinputObject;
365 void tst_qdeclarativetextinput::selection()
367 QString testStr = standard[0];
368 QString componentStr = "import QtQuick 1.0\nTextInput { text: \""+ testStr +"\"; }";
369 QDeclarativeComponent textinputComponent(&engine);
370 textinputComponent.setData(componentStr.toLatin1(), QUrl());
371 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
372 QVERIFY(textinputObject != 0);
375 //Test selection follows cursor
376 for(int i=0; i<= testStr.size(); i++) {
377 textinputObject->setCursorPosition(i);
378 QCOMPARE(textinputObject->cursorPosition(), i);
379 QCOMPARE(textinputObject->selectionStart(), i);
380 QCOMPARE(textinputObject->selectionEnd(), i);
381 QVERIFY(textinputObject->selectedText().isNull());
383 //Test cursor follows selection
384 for(int i=0; i<= testStr.size(); i++) {
385 textinputObject->select(i,i);
386 QCOMPARE(textinputObject->cursorPosition(), i);
387 QCOMPARE(textinputObject->selectionStart(), i);
388 QCOMPARE(textinputObject->selectionEnd(), i);
391 textinputObject->setCursorPosition(0);
392 QVERIFY(textinputObject->cursorPosition() == 0);
393 QVERIFY(textinputObject->selectionStart() == 0);
394 QVERIFY(textinputObject->selectionEnd() == 0);
395 QVERIFY(textinputObject->selectedText().isNull());
397 // Verify invalid positions are ignored.
398 textinputObject->setCursorPosition(-1);
399 QVERIFY(textinputObject->cursorPosition() == 0);
400 QVERIFY(textinputObject->selectionStart() == 0);
401 QVERIFY(textinputObject->selectionEnd() == 0);
402 QVERIFY(textinputObject->selectedText().isNull());
404 textinputObject->setCursorPosition(textinputObject->text().count()+1);
405 QVERIFY(textinputObject->cursorPosition() == 0);
406 QVERIFY(textinputObject->selectionStart() == 0);
407 QVERIFY(textinputObject->selectionEnd() == 0);
408 QVERIFY(textinputObject->selectedText().isNull());
411 for(int i=0; i<= testStr.size(); i++) {
412 textinputObject->select(0,i);
413 QCOMPARE(testStr.mid(0,i), textinputObject->selectedText());
414 QCOMPARE(textinputObject->cursorPosition(), i);
416 for(int i=0; i<= testStr.size(); i++) {
417 textinputObject->select(i,testStr.size());
418 QCOMPARE(testStr.mid(i,testStr.size()-i), textinputObject->selectedText());
419 QCOMPARE(textinputObject->cursorPosition(), testStr.size());
422 textinputObject->setCursorPosition(0);
423 QVERIFY(textinputObject->cursorPosition() == 0);
424 QVERIFY(textinputObject->selectionStart() == 0);
425 QVERIFY(textinputObject->selectionEnd() == 0);
426 QVERIFY(textinputObject->selectedText().isNull());
428 //Test Error Ignoring behaviour
429 textinputObject->setCursorPosition(0);
430 QVERIFY(textinputObject->selectedText().isNull());
431 textinputObject->select(-10,0);
432 QVERIFY(textinputObject->selectedText().isNull());
433 textinputObject->select(100,110);
434 QVERIFY(textinputObject->selectedText().isNull());
435 textinputObject->select(0,-10);
436 QVERIFY(textinputObject->selectedText().isNull());
437 textinputObject->select(0,100);
438 QVERIFY(textinputObject->selectedText().isNull());
439 textinputObject->select(0,10);
440 QVERIFY(textinputObject->selectedText().size() == 10);
441 textinputObject->select(-10,10);
442 QVERIFY(textinputObject->selectedText().size() == 10);
443 textinputObject->select(100,101);
444 QVERIFY(textinputObject->selectedText().size() == 10);
445 textinputObject->select(0,-10);
446 QVERIFY(textinputObject->selectedText().size() == 10);
447 textinputObject->select(0,100);
448 QVERIFY(textinputObject->selectedText().size() == 10);
450 textinputObject->deselect();
451 QVERIFY(textinputObject->selectedText().isNull());
452 textinputObject->select(0,10);
453 QVERIFY(textinputObject->selectedText().size() == 10);
454 textinputObject->deselect();
455 QVERIFY(textinputObject->selectedText().isNull());
457 delete textinputObject;
460 void tst_qdeclarativetextinput::isRightToLeft_data()
462 QTest::addColumn<QString>("text");
463 QTest::addColumn<bool>("emptyString");
464 QTest::addColumn<bool>("firstCharacter");
465 QTest::addColumn<bool>("lastCharacter");
466 QTest::addColumn<bool>("middleCharacter");
467 QTest::addColumn<bool>("startString");
468 QTest::addColumn<bool>("midString");
469 QTest::addColumn<bool>("endString");
471 const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
472 QTest::newRow("Empty") << "" << false << false << false << false << false << false << false;
473 QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false;
474 QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false;
475 QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true;
476 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;
477 QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false;
480 void tst_qdeclarativetextinput::isRightToLeft()
482 QFETCH(QString, text);
483 QFETCH(bool, emptyString);
484 QFETCH(bool, firstCharacter);
485 QFETCH(bool, lastCharacter);
486 QFETCH(bool, middleCharacter);
487 QFETCH(bool, startString);
488 QFETCH(bool, midString);
489 QFETCH(bool, endString);
491 QDeclarative1TextInput textInput;
492 textInput.setText(text);
494 // first test that the right string is delivered to the QString::isRightToLeft()
495 QCOMPARE(textInput.isRightToLeft(0,0), text.mid(0,0).isRightToLeft());
496 QCOMPARE(textInput.isRightToLeft(0,1), text.mid(0,1).isRightToLeft());
497 QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft());
498 QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft());
499 QCOMPARE(textInput.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft());
500 QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft());
502 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
503 QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft());
505 // then test that the feature actually works
506 QCOMPARE(textInput.isRightToLeft(0,0), emptyString);
507 QCOMPARE(textInput.isRightToLeft(0,1), firstCharacter);
508 QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), lastCharacter);
509 QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter);
510 QCOMPARE(textInput.isRightToLeft(0,text.count()/4), startString);
511 QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), midString);
513 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
514 QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), endString);
517 void tst_qdeclarativetextinput::moveCursorSelection_data()
519 QTest::addColumn<QString>("testStr");
520 QTest::addColumn<int>("cursorPosition");
521 QTest::addColumn<int>("movePosition");
522 QTest::addColumn<QDeclarative1TextInput::SelectionMode>("mode");
523 QTest::addColumn<int>("selectionStart");
524 QTest::addColumn<int>("selectionEnd");
525 QTest::addColumn<bool>("reversible");
527 // () contains the text selected by the cursor.
528 // <> contains the actual selection.
530 QTest::newRow("(t)he|characters")
531 << standard[0] << 0 << 1 << QDeclarative1TextInput::SelectCharacters << 0 << 1 << true;
532 QTest::newRow("do(g)|characters")
533 << standard[0] << 43 << 44 << QDeclarative1TextInput::SelectCharacters << 43 << 44 << true;
534 QTest::newRow("jum(p)ed|characters")
535 << standard[0] << 23 << 24 << QDeclarative1TextInput::SelectCharacters << 23 << 24 << true;
536 QTest::newRow("jumped( )over|characters")
537 << standard[0] << 26 << 27 << QDeclarative1TextInput::SelectCharacters << 26 << 27 << true;
538 QTest::newRow("(the )|characters")
539 << standard[0] << 0 << 4 << QDeclarative1TextInput::SelectCharacters << 0 << 4 << true;
540 QTest::newRow("( dog)|characters")
541 << standard[0] << 40 << 44 << QDeclarative1TextInput::SelectCharacters << 40 << 44 << true;
542 QTest::newRow("( jumped )|characters")
543 << standard[0] << 19 << 27 << QDeclarative1TextInput::SelectCharacters << 19 << 27 << true;
544 QTest::newRow("th(e qu)ick|characters")
545 << standard[0] << 2 << 6 << QDeclarative1TextInput::SelectCharacters << 2 << 6 << true;
546 QTest::newRow("la(zy d)og|characters")
547 << standard[0] << 38 << 42 << QDeclarative1TextInput::SelectCharacters << 38 << 42 << true;
548 QTest::newRow("jum(ped ov)er|characters")
549 << standard[0] << 23 << 29 << QDeclarative1TextInput::SelectCharacters << 23 << 29 << true;
550 QTest::newRow("()the|characters")
551 << standard[0] << 0 << 0 << QDeclarative1TextInput::SelectCharacters << 0 << 0 << true;
552 QTest::newRow("dog()|characters")
553 << standard[0] << 44 << 44 << QDeclarative1TextInput::SelectCharacters << 44 << 44 << true;
554 QTest::newRow("jum()ped|characters")
555 << standard[0] << 23 << 23 << QDeclarative1TextInput::SelectCharacters << 23 << 23 << true;
557 QTest::newRow("<(t)he>|words")
558 << standard[0] << 0 << 1 << QDeclarative1TextInput::SelectWords << 0 << 3 << true;
559 QTest::newRow("<do(g)>|words")
560 << standard[0] << 43 << 44 << QDeclarative1TextInput::SelectWords << 41 << 44 << true;
561 QTest::newRow("<jum(p)ed>|words")
562 << standard[0] << 23 << 24 << QDeclarative1TextInput::SelectWords << 20 << 26 << true;
563 QTest::newRow("<jumped( )>over|words,ltr")
564 << standard[0] << 26 << 27 << QDeclarative1TextInput::SelectWords << 20 << 27 << false;
565 QTest::newRow("jumped<( )over>|words,rtl")
566 << standard[0] << 27 << 26 << QDeclarative1TextInput::SelectWords << 26 << 31 << false;
567 QTest::newRow("<(the )>quick|words,ltr")
568 << standard[0] << 0 << 4 << QDeclarative1TextInput::SelectWords << 0 << 4 << false;
569 QTest::newRow("<(the )quick>|words,rtl")
570 << standard[0] << 4 << 0 << QDeclarative1TextInput::SelectWords << 0 << 9 << false;
571 QTest::newRow("<lazy( dog)>|words,ltr")
572 << standard[0] << 40 << 44 << QDeclarative1TextInput::SelectWords << 36 << 44 << false;
573 QTest::newRow("lazy<( dog)>|words,rtl")
574 << standard[0] << 44 << 40 << QDeclarative1TextInput::SelectWords << 40 << 44 << false;
575 QTest::newRow("<fox( jumped )>over|words,ltr")
576 << standard[0] << 19 << 27 << QDeclarative1TextInput::SelectWords << 16 << 27 << false;
577 QTest::newRow("fox<( jumped )over>|words,rtl")
578 << standard[0] << 27 << 19 << QDeclarative1TextInput::SelectWords << 19 << 31 << false;
579 QTest::newRow("<th(e qu)ick>|words")
580 << standard[0] << 2 << 6 << QDeclarative1TextInput::SelectWords << 0 << 9 << true;
581 QTest::newRow("<la(zy d)og|words>")
582 << standard[0] << 38 << 42 << QDeclarative1TextInput::SelectWords << 36 << 44 << true;
583 QTest::newRow("<jum(ped ov)er>|words")
584 << standard[0] << 23 << 29 << QDeclarative1TextInput::SelectWords << 20 << 31 << true;
585 QTest::newRow("<()>the|words")
586 << standard[0] << 0 << 0 << QDeclarative1TextInput::SelectWords << 0 << 0 << true;
587 QTest::newRow("dog<()>|words")
588 << standard[0] << 44 << 44 << QDeclarative1TextInput::SelectWords << 44 << 44 << true;
589 QTest::newRow("jum<()>ped|words")
590 << standard[0] << 23 << 23 << QDeclarative1TextInput::SelectWords << 23 << 23 << true;
592 QTest::newRow("Hello<(,)> |words")
593 << standard[2] << 5 << 6 << QDeclarative1TextInput::SelectWords << 5 << 6 << true;
594 QTest::newRow("Hello<(, )>world|words,ltr")
595 << standard[2] << 5 << 7 << QDeclarative1TextInput::SelectWords << 5 << 7 << false;
596 QTest::newRow("Hello<(, )world>|words,rtl")
597 << standard[2] << 7 << 5 << QDeclarative1TextInput::SelectWords << 5 << 12 << false;
598 QTest::newRow("<Hel(lo, )>world|words,ltr")
599 << standard[2] << 3 << 7 << QDeclarative1TextInput::SelectWords << 0 << 7 << false;
600 QTest::newRow("<Hel(lo, )world>|words,rtl")
601 << standard[2] << 7 << 3 << QDeclarative1TextInput::SelectWords << 0 << 12 << false;
602 QTest::newRow("<Hel(lo)>,|words")
603 << standard[2] << 3 << 5 << QDeclarative1TextInput::SelectWords << 0 << 5 << true;
604 QTest::newRow("Hello<()>,|words")
605 << standard[2] << 5 << 5 << QDeclarative1TextInput::SelectWords << 5 << 5 << true;
606 QTest::newRow("Hello,<()>|words")
607 << standard[2] << 6 << 6 << QDeclarative1TextInput::SelectWords << 6 << 6 << true;
608 QTest::newRow("Hello<,( )>world|words,ltr")
609 << standard[2] << 6 << 7 << QDeclarative1TextInput::SelectWords << 5 << 7 << false;
610 QTest::newRow("Hello,<( )world>|words,rtl")
611 << standard[2] << 7 << 6 << QDeclarative1TextInput::SelectWords << 6 << 12 << false;
612 QTest::newRow("Hello<,( world)>|words,ltr")
613 << standard[2] << 6 << 12 << QDeclarative1TextInput::SelectWords << 5 << 12 << false;
614 QTest::newRow("Hello,<( world)>|words,rtl")
615 << standard[2] << 12 << 6 << QDeclarative1TextInput::SelectWords << 6 << 12 << false;
616 QTest::newRow("Hello<,( world!)>|words,ltr")
617 << standard[2] << 6 << 13 << QDeclarative1TextInput::SelectWords << 5 << 13 << false;
618 QTest::newRow("Hello,<( world!)>|words,rtl")
619 << standard[2] << 13 << 6 << QDeclarative1TextInput::SelectWords << 6 << 13 << false;
620 QTest::newRow("Hello<(, world!)>|words")
621 << standard[2] << 5 << 13 << QDeclarative1TextInput::SelectWords << 5 << 13 << true;
622 QTest::newRow("world<(!)>|words")
623 << standard[2] << 12 << 13 << QDeclarative1TextInput::SelectWords << 12 << 13 << true;
624 QTest::newRow("world!<()>)|words")
625 << standard[2] << 13 << 13 << QDeclarative1TextInput::SelectWords << 13 << 13 << true;
626 QTest::newRow("world<()>!)|words")
627 << standard[2] << 12 << 12 << QDeclarative1TextInput::SelectWords << 12 << 12 << true;
629 QTest::newRow("<(,)>olleH |words")
630 << standard[3] << 7 << 8 << QDeclarative1TextInput::SelectWords << 7 << 8 << true;
631 QTest::newRow("<dlrow( ,)>olleH|words,ltr")
632 << standard[3] << 6 << 8 << QDeclarative1TextInput::SelectWords << 1 << 8 << false;
633 QTest::newRow("dlrow<( ,)>olleH|words,rtl")
634 << standard[3] << 8 << 6 << QDeclarative1TextInput::SelectWords << 6 << 8 << false;
635 QTest::newRow("<dlrow( ,ol)leH>|words,ltr")
636 << standard[3] << 6 << 10 << QDeclarative1TextInput::SelectWords << 1 << 13 << false;
637 QTest::newRow("dlrow<( ,ol)leH>|words,rtl")
638 << standard[3] << 10 << 6 << QDeclarative1TextInput::SelectWords << 6 << 13 << false;
639 QTest::newRow(",<(ol)leH>,|words")
640 << standard[3] << 8 << 10 << QDeclarative1TextInput::SelectWords << 8 << 13 << true;
641 QTest::newRow(",<()>olleH|words")
642 << standard[3] << 8 << 8 << QDeclarative1TextInput::SelectWords << 8 << 8 << true;
643 QTest::newRow("<()>,olleH|words")
644 << standard[3] << 7 << 7 << QDeclarative1TextInput::SelectWords << 7 << 7 << true;
645 QTest::newRow("<dlrow( )>,olleH|words,ltr")
646 << standard[3] << 6 << 7 << QDeclarative1TextInput::SelectWords << 1 << 7 << false;
647 QTest::newRow("dlrow<( ),>olleH|words,rtl")
648 << standard[3] << 7 << 6 << QDeclarative1TextInput::SelectWords << 6 << 8 << false;
649 QTest::newRow("<(dlrow )>,olleH|words,ltr")
650 << standard[3] << 1 << 7 << QDeclarative1TextInput::SelectWords << 1 << 7 << false;
651 QTest::newRow("<(dlrow ),>olleH|words,rtl")
652 << standard[3] << 7 << 1 << QDeclarative1TextInput::SelectWords << 1 << 8 << false;
653 QTest::newRow("<(!dlrow )>,olleH|words,ltr")
654 << standard[3] << 0 << 7 << QDeclarative1TextInput::SelectWords << 0 << 7 << false;
655 QTest::newRow("<(!dlrow ),>olleH|words,rtl")
656 << standard[3] << 7 << 0 << QDeclarative1TextInput::SelectWords << 0 << 8 << false;
657 QTest::newRow("(!dlrow ,)olleH|words")
658 << standard[3] << 0 << 8 << QDeclarative1TextInput::SelectWords << 0 << 8 << true;
659 QTest::newRow("<(!)>dlrow|words")
660 << standard[3] << 0 << 1 << QDeclarative1TextInput::SelectWords << 0 << 1 << true;
661 QTest::newRow("<()>!dlrow|words")
662 << standard[3] << 0 << 0 << QDeclarative1TextInput::SelectWords << 0 << 0 << true;
663 QTest::newRow("!<()>dlrow|words")
664 << standard[3] << 1 << 1 << QDeclarative1TextInput::SelectWords << 1 << 1 << true;
666 QTest::newRow(" <s(pac)ey> text |words")
667 << standard[4] << 1 << 4 << QDeclarative1TextInput::SelectWords << 1 << 7 << true;
668 QTest::newRow(" spacey <t(ex)t> |words")
669 << standard[4] << 11 << 13 << QDeclarative1TextInput::SelectWords << 10 << 14 << true;
670 QTest::newRow("<( )>spacey text |words|ltr")
671 << standard[4] << 0 << 1 << QDeclarative1TextInput::SelectWords << 0 << 1 << false;
672 QTest::newRow("<( )spacey> text |words|rtl")
673 << standard[4] << 1 << 0 << QDeclarative1TextInput::SelectWords << 0 << 7 << false;
674 QTest::newRow("spacey <text( )>|words|ltr")
675 << standard[4] << 14 << 15 << QDeclarative1TextInput::SelectWords << 10 << 15 << false;
676 QTest::newRow("spacey text<( )>|words|rtl")
677 << standard[4] << 15 << 14 << QDeclarative1TextInput::SelectWords << 14 << 15 << false;
678 QTest::newRow("<()> spacey text |words")
679 << standard[4] << 0 << 0 << QDeclarative1TextInput::SelectWords << 0 << 0 << false;
680 QTest::newRow(" spacey text <()>|words")
681 << standard[4] << 15 << 15 << QDeclarative1TextInput::SelectWords << 15 << 15 << false;
684 void tst_qdeclarativetextinput::moveCursorSelection()
686 QFETCH(QString, testStr);
687 QFETCH(int, cursorPosition);
688 QFETCH(int, movePosition);
689 QFETCH(QDeclarative1TextInput::SelectionMode, mode);
690 QFETCH(int, selectionStart);
691 QFETCH(int, selectionEnd);
692 QFETCH(bool, reversible);
694 QString componentStr = "import QtQuick 1.1\nTextInput { text: \""+ testStr +"\"; }";
695 QDeclarativeComponent textinputComponent(&engine);
696 textinputComponent.setData(componentStr.toLatin1(), QUrl());
697 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
698 QVERIFY(textinputObject != 0);
700 textinputObject->setCursorPosition(cursorPosition);
701 textinputObject->moveCursorSelection(movePosition, mode);
703 QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
704 QCOMPARE(textinputObject->selectionStart(), selectionStart);
705 QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
708 textinputObject->setCursorPosition(movePosition);
709 textinputObject->moveCursorSelection(cursorPosition, mode);
711 QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
712 QCOMPARE(textinputObject->selectionStart(), selectionStart);
713 QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
716 delete textinputObject;
719 void tst_qdeclarativetextinput::moveCursorSelectionSequence_data()
721 QTest::addColumn<QString>("testStr");
722 QTest::addColumn<int>("cursorPosition");
723 QTest::addColumn<int>("movePosition1");
724 QTest::addColumn<int>("movePosition2");
725 QTest::addColumn<int>("selection1Start");
726 QTest::addColumn<int>("selection1End");
727 QTest::addColumn<int>("selection2Start");
728 QTest::addColumn<int>("selection2End");
730 // () contains the text selected by the cursor.
731 // <> contains the actual selection.
732 // ^ is the revised cursor position.
733 // {} contains the revised selection.
735 QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr")
740 QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl")
745 QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr")
750 QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl")
755 QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr")
760 QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl")
765 QTest::newRow("the {<quick() ^}bro)wn> fox|ltr")
770 QTest::newRow("the quick<( {^bro)wn>} fox|rtl")
775 QTest::newRow("the {<quick^}( bro)wn> fox|ltr")
780 QTest::newRow("the quick{<(^ bro)wn>} fox|rtl")
785 QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr")
790 QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl")
795 QTest::newRow("the {<^quick}( bro)wn> fox|ltr")
800 QTest::newRow("the {<^quick}( bro)wn> fox|rtl")
805 QTest::newRow("the{^ <quick}( bro)wn> fox|ltr")
810 QTest::newRow("the{^ <quick}( bro)wn> fox|rtl")
815 QTest::newRow("{t^he <quick}( bro)wn> fox|ltr")
820 QTest::newRow("{t^he <quick}( bro)wn> fox|rtl")
826 QTest::newRow("{<He(ll)o>, w^orld}!|ltr")
831 QTest::newRow("{<He(ll)o>, w^orld}!|rtl")
837 QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr")
842 QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl")
848 QTest::newRow("{<(^} sp)acey> text |ltr")
853 QTest::newRow("{<( ^}sp)acey> text |ltr")
858 QTest::newRow("<( {s^p)acey>} text |rtl")
863 QTest::newRow("<( {^sp)acey>} text |rtl")
869 QTest::newRow(" spacey <te(xt {^)>}|rtl")
874 QTest::newRow(" spacey <te(xt{^ )>}|rtl")
879 QTest::newRow(" spacey {<te(x^t} )>|ltr")
884 QTest::newRow(" spacey {<te(xt^} )>|ltr")
891 void tst_qdeclarativetextinput::moveCursorSelectionSequence()
893 QFETCH(QString, testStr);
894 QFETCH(int, cursorPosition);
895 QFETCH(int, movePosition1);
896 QFETCH(int, movePosition2);
897 QFETCH(int, selection1Start);
898 QFETCH(int, selection1End);
899 QFETCH(int, selection2Start);
900 QFETCH(int, selection2End);
902 QString componentStr = "import QtQuick 1.1\nTextInput { text: \""+ testStr +"\"; }";
903 QDeclarativeComponent textinputComponent(&engine);
904 textinputComponent.setData(componentStr.toLatin1(), QUrl());
905 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput*>(textinputComponent.create());
906 QVERIFY(textinputObject != 0);
908 textinputObject->setCursorPosition(cursorPosition);
910 textinputObject->moveCursorSelection(movePosition1, QDeclarative1TextInput::SelectWords);
911 QCOMPARE(textinputObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start));
912 QCOMPARE(textinputObject->selectionStart(), selection1Start);
913 QCOMPARE(textinputObject->selectionEnd(), selection1End);
915 textinputObject->moveCursorSelection(movePosition2, QDeclarative1TextInput::SelectWords);
916 QCOMPARE(textinputObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start));
917 QCOMPARE(textinputObject->selectionStart(), selection2Start);
918 QCOMPARE(textinputObject->selectionEnd(), selection2End);
920 delete textinputObject;
923 void tst_qdeclarativetextinput::mouseSelection_data()
925 QTest::addColumn<QString>("qmlfile");
926 QTest::addColumn<bool>("expectSelection");
929 QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << true;
930 QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << false;
931 QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << false;
932 QTest::newRow("on word selection") << SRCDIR "/data/mouseselection_true_words.qml" << true;
933 QTest::newRow("off word selection") << SRCDIR "/data/mouseselection_false_words.qml" << false;
934 QTest::newRow("on read only") << SRCDIR "/data/mouseselection_true_readonly.qml" << true;
935 QTest::newRow("off read only") << SRCDIR "/data/mouseselection_false_readonly.qml" << false;
938 void tst_qdeclarativetextinput::mouseSelection()
940 QFETCH(QString, qmlfile);
941 QFETCH(bool, expectSelection);
943 QDeclarativeView *canvas = createView(qmlfile);
946 QApplication::setActiveWindow(canvas);
947 QTest::qWaitForWindowShown(canvas);
948 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
950 QVERIFY(canvas->rootObject() != 0);
951 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
952 QVERIFY(textInputObject != 0);
954 // press-and-drag-and-release from x1 to x2
957 int y = textInputObject->height()/2;
958 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
959 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
960 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
961 QApplication::sendEvent(canvas->viewport(), &mv);
962 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
963 QString str = textInputObject->selectedText();
965 QVERIFY(str.length() > 3); // don't reallly care *what* was selected (and it's too sensitive to platform)
967 QVERIFY(str.isEmpty());
969 // Clicking and shift to clicking between the same points should select the same text.
970 textInputObject->setCursorPosition(0);
971 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::NoModifier, canvas->mapFromScene(QPoint(x1,y)));
972 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::ShiftModifier, canvas->mapFromScene(QPoint(x2,y)));
973 QCOMPARE(textInputObject->selectedText(), str);
978 void tst_qdeclarativetextinput::deferEnableSelectByMouse_data()
980 QTest::addColumn<QString>("qmlfile");
982 QTest::newRow("writable") << SRCDIR "/data/mouseselection_false.qml";
983 QTest::newRow("read only") << SRCDIR "/data/mouseselection_false_readonly.qml";
986 void tst_qdeclarativetextinput::deferEnableSelectByMouse()
988 // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed.
989 QFETCH(QString, qmlfile);
991 QDeclarativeView *canvas = createView(qmlfile);
994 QApplication::setActiveWindow(canvas);
995 QTest::qWaitForWindowShown(canvas);
996 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
998 QVERIFY(canvas->rootObject() != 0);
999 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1000 QVERIFY(textInputObject != 0);
1002 // press-and-drag-and-release from x1 to x2
1005 int y = textInputObject->height()/2;
1007 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1008 textInputObject->setSelectByMouse(true);
1009 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1010 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1011 QApplication::sendEvent(canvas->viewport(), &mv);
1012 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1013 QVERIFY(textInputObject->selectedText().isEmpty());
1018 void tst_qdeclarativetextinput::deferDisableSelectByMouse_data()
1020 QTest::addColumn<QString>("qmlfile");
1022 QTest::newRow("writable") << SRCDIR "/data/mouseselection_true.qml";
1023 QTest::newRow("read only") << SRCDIR "/data/mouseselection_true_readonly.qml";
1026 void tst_qdeclarativetextinput::deferDisableSelectByMouse()
1028 // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed.
1029 QFETCH(QString, qmlfile);
1031 QDeclarativeView *canvas = createView(qmlfile);
1034 QApplication::setActiveWindow(canvas);
1035 QTest::qWaitForWindowShown(canvas);
1036 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1038 QVERIFY(canvas->rootObject() != 0);
1039 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1040 QVERIFY(textInputObject != 0);
1042 // press-and-drag-and-release from x1 to x2
1045 int y = textInputObject->height()/2;
1047 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1048 textInputObject->setSelectByMouse(false);
1049 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1050 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1051 QApplication::sendEvent(canvas->viewport(), &mv);
1052 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1053 QVERIFY(textInputObject->selectedText().length() > 3);
1058 void tst_qdeclarativetextinput::dragMouseSelection()
1060 QString qmlfile = SRCDIR "/data/mouseselection_true.qml";
1062 QDeclarativeView *canvas = createView(qmlfile);
1065 QApplication::setActiveWindow(canvas);
1066 QTest::qWaitForWindowShown(canvas);
1067 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1069 QVERIFY(canvas->rootObject() != 0);
1070 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1071 QVERIFY(textInputObject != 0);
1073 // press-and-drag-and-release from x1 to x2
1076 int y = textInputObject->height()/2;
1077 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1079 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1080 QApplication::sendEvent(canvas->viewport(), &mv);
1082 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1084 QString str1 = textInputObject->selectedText();
1085 QVERIFY(str1.length() > 3);
1087 // press and drag the current selection.
1090 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1092 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1093 QApplication::sendEvent(canvas->viewport(), &mv);
1095 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1096 QString str2 = textInputObject->selectedText();
1097 QVERIFY(str2.length() > 3);
1099 QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved.
1103 void tst_qdeclarativetextinput::mouseSelectionMode_data()
1105 QTest::addColumn<QString>("qmlfile");
1106 QTest::addColumn<bool>("selectWords");
1109 QTest::newRow("SelectWords") << SRCDIR "/data/mouseselectionmode_words.qml" << true;
1110 QTest::newRow("SelectCharacters") << SRCDIR "/data/mouseselectionmode_characters.qml" << false;
1111 QTest::newRow("default") << SRCDIR "/data/mouseselectionmode_default.qml" << false;
1114 void tst_qdeclarativetextinput::mouseSelectionMode()
1116 QFETCH(QString, qmlfile);
1117 QFETCH(bool, selectWords);
1119 QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1121 QDeclarativeView *canvas = createView(qmlfile);
1124 QApplication::setActiveWindow(canvas);
1125 QTest::qWaitForWindowShown(canvas);
1126 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1128 QVERIFY(canvas->rootObject() != 0);
1129 QDeclarative1TextInput *textInputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1130 QVERIFY(textInputObject != 0);
1132 // press-and-drag-and-release from x1 to x2
1135 int y = textInputObject->height()/2;
1136 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1137 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1138 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1139 QApplication::sendEvent(canvas->viewport(), &mv);
1140 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1141 QString str = textInputObject->selectedText();
1143 QCOMPARE(str, text);
1145 QVERIFY(str.length() > 3);
1146 QVERIFY(str != text);
1152 void tst_qdeclarativetextinput::horizontalAlignment_data()
1154 QTest::addColumn<int>("hAlign");
1155 QTest::addColumn<QString>("expectfile");
1157 QTest::newRow("L") << int(Qt::AlignLeft) << "halign_left";
1158 QTest::newRow("R") << int(Qt::AlignRight) << "halign_right";
1159 QTest::newRow("C") << int(Qt::AlignHCenter) << "halign_center";
1162 void tst_qdeclarativetextinput::horizontalAlignment()
1164 QFETCH(int, hAlign);
1165 QFETCH(QString, expectfile);
1167 QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment.qml");
1170 QApplication::setActiveWindow(canvas);
1171 QTest::qWaitForWindowShown(canvas);
1172 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1173 QObject *ob = canvas->rootObject();
1175 ob->setProperty("horizontalAlignment",hAlign);
1176 QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32);
1177 actual.fill(qRgb(255,255,255));
1179 QPainter p(&actual);
1183 expectfile = createExpectedFileIfNotFound(expectfile, actual);
1185 QImage expect(expectfile);
1187 QCOMPARE(actual,expect);
1192 void tst_qdeclarativetextinput::horizontalAlignment_RightToLeft()
1194 QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml");
1195 QDeclarative1TextInput *textInput = canvas->rootObject()->findChild<QDeclarative1TextInput*>("text");
1196 QVERIFY(textInput != 0);
1199 const QString rtlText = textInput->text();
1201 QDeclarative1TextInputPrivate *textInputPrivate = QDeclarative1TextInputPrivate::get(textInput);
1202 QVERIFY(textInputPrivate != 0);
1203 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1205 // implicit alignment should follow the reading direction of RTL text
1206 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1207 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1208 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1210 // explicitly left aligned
1211 textInput->setHAlign(QDeclarative1TextInput::AlignLeft);
1212 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1213 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1214 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1216 // explicitly right aligned
1217 textInput->setHAlign(QDeclarative1TextInput::AlignRight);
1218 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1219 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1220 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1222 // explicitly center aligned
1223 textInput->setHAlign(QDeclarative1TextInput::AlignHCenter);
1224 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1225 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignHCenter);
1226 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1227 QVERIFY(-textInputPrivate->hscroll + textInputPrivate->width() > canvas->width()/2);
1229 // reseted alignment should go back to following the text reading direction
1230 textInput->resetHAlign();
1231 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1232 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1233 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1235 // mirror the text item
1236 QDeclarativeItemPrivate::get(textInput)->setLayoutMirror(true);
1238 // mirrored implicit alignment should continue to follow the reading direction of the text
1239 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1240 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1241 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1243 // explicitly right aligned behaves as left aligned
1244 textInput->setHAlign(QDeclarative1TextInput::AlignRight);
1245 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1246 QCOMPARE(textInput->effectiveHAlign(), QDeclarative1TextInput::AlignLeft);
1247 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1249 // mirrored explicitly left aligned behaves as right aligned
1250 textInput->setHAlign(QDeclarative1TextInput::AlignLeft);
1251 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1252 QCOMPARE(textInput->effectiveHAlign(), QDeclarative1TextInput::AlignRight);
1253 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1255 // disable mirroring
1256 QDeclarativeItemPrivate::get(textInput)->setLayoutMirror(false);
1257 QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
1258 textInput->resetHAlign();
1260 // English text should be implicitly left aligned
1261 textInput->setText("Hello world!");
1262 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1263 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1265 QApplication::setActiveWindow(canvas);
1266 QTest::qWaitForWindowShown(canvas);
1267 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1269 // If there is no commited text, the preedit text should determine the alignment.
1270 textInput->setText(QString());
1271 { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(canvas, &ev); }
1272 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1273 { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(canvas, &ev); }
1274 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
1276 #ifndef Q_OS_MAC // QTBUG-18040
1277 // empty text with implicit alignment follows the system locale-based
1278 // keyboard input direction from QApplication::keyboardInputDirection
1279 textInput->setText("");
1280 QCOMPARE(textInput->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
1281 QDeclarative1TextInput::AlignLeft : QDeclarative1TextInput::AlignRight);
1282 if (QApplication::keyboardInputDirection() == Qt::LeftToRight)
1283 QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
1285 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1286 textInput->setHAlign(QDeclarative1TextInput::AlignRight);
1287 QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
1288 QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
1293 #ifndef Q_OS_MAC // QTBUG-18040
1294 // alignment of TextInput with no text set to it
1295 QString componentStr = "import QtQuick 1.0\nTextInput {}";
1296 QDeclarativeComponent textComponent(&engine);
1297 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
1298 QDeclarative1TextInput *textObject = qobject_cast<QDeclarative1TextInput*>(textComponent.create());
1299 QCOMPARE(textObject->hAlign(), QApplication::keyboardInputDirection() == Qt::LeftToRight ?
1300 QDeclarative1TextInput::AlignLeft : QDeclarative1TextInput::AlignRight);
1305 void tst_qdeclarativetextinput::positionAt()
1307 QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml");
1308 QVERIFY(canvas->rootObject() != 0);
1311 QApplication::setActiveWindow(canvas);
1312 QTest::qWaitForWindowShown(canvas);
1314 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1315 QVERIFY(textinputObject != 0);
1317 // Check autoscrolled...
1318 QFontMetrics fm(textinputObject->font());
1320 int pos = textinputObject->positionAt(textinputObject->width()/2);
1321 int diff = abs(int(fm.width(textinputObject->text()) - (fm.width(textinputObject->text().left(pos))+textinputObject->width()/2)));
1323 // some tollerance for different fonts.
1330 int x = textinputObject->positionToRectangle(pos + 1).x() - 1;
1331 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorBetweenCharacters), pos + 1);
1332 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorOnCharacter), pos);
1334 // Check without autoscroll...
1335 textinputObject->setAutoScroll(false);
1336 pos = textinputObject->positionAt(textinputObject->width()/2);
1337 diff = abs(int(fm.width(textinputObject->text().left(pos))-textinputObject->width()/2));
1340 QEXPECT_FAIL("", "QTBUG-21017 fails", Continue);
1342 // some tollerance for different fonts.
1349 x = textinputObject->positionToRectangle(pos + 1).x() - 1;
1350 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorBetweenCharacters), pos + 1);
1351 QCOMPARE(textinputObject->positionAt(x, QDeclarative1TextInput::CursorOnCharacter), pos);
1353 const qreal x0 = textinputObject->positionToRectangle(pos).x();
1354 const qreal x1 = textinputObject->positionToRectangle(pos + 1).x();
1356 QString preeditText = textinputObject->text().mid(0, pos);
1357 textinputObject->setText(textinputObject->text().mid(pos));
1358 textinputObject->setCursorPosition(0);
1360 QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
1361 QApplication::sendEvent(canvas, &inputEvent);
1363 // Check all points within the preedit text return the same position.
1364 QCOMPARE(textinputObject->positionAt(0), 0);
1365 QCOMPARE(textinputObject->positionAt(x0 / 2), 0);
1366 QCOMPARE(textinputObject->positionAt(x0), 0);
1368 // Verify positioning returns to normal after the preedit text.
1369 QCOMPARE(textinputObject->positionAt(x1), 1);
1370 QCOMPARE(textinputObject->positionToRectangle(1).x(), x1);
1375 void tst_qdeclarativetextinput::maxLength()
1377 QDeclarativeView *canvas = createView(SRCDIR "/data/maxLength.qml");
1378 QVERIFY(canvas->rootObject() != 0);
1381 QApplication::setActiveWindow(canvas);
1382 QTest::qWaitForWindowShown(canvas);
1384 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1385 QVERIFY(textinputObject != 0);
1386 QVERIFY(textinputObject->text().isEmpty());
1387 QVERIFY(textinputObject->maxLength() == 10);
1388 foreach(const QString &str, standard){
1389 QVERIFY(textinputObject->text().length() <= 10);
1390 textinputObject->setText(str);
1391 QVERIFY(textinputObject->text().length() <= 10);
1394 textinputObject->setText("");
1395 QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
1396 for(int i=0; i<20; i++){
1397 QCOMPARE(textinputObject->text().length(), qMin(i,10));
1398 //simulateKey(canvas, Qt::Key_A);
1399 QTest::keyPress(canvas, Qt::Key_A);
1400 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1406 void tst_qdeclarativetextinput::masks()
1408 //Not a comprehensive test of the possible masks, that's done elsewhere (QLineEdit)
1409 //QString componentStr = "import QtQuick 1.0\nTextInput { inputMask: 'HHHHhhhh'; }";
1410 QDeclarativeView *canvas = createView(SRCDIR "/data/masks.qml");
1413 QVERIFY(canvas->rootObject() != 0);
1414 QDeclarative1TextInput *textinputObject = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1415 QVERIFY(textinputObject != 0);
1416 QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
1417 QVERIFY(textinputObject->text().length() == 0);
1418 QCOMPARE(textinputObject->inputMask(), QString("HHHHhhhh; "));
1419 for(int i=0; i<10; i++){
1420 QCOMPARE(qMin(i,8), textinputObject->text().length());
1421 QCOMPARE(i>=4, textinputObject->hasAcceptableInput());
1422 //simulateKey(canvas, Qt::Key_A);
1423 QTest::keyPress(canvas, Qt::Key_A);
1424 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1430 void tst_qdeclarativetextinput::validators()
1432 // Note that this test assumes that the validators are working properly
1433 // so you may need to run their tests first. All validators are checked
1434 // here to ensure that their exposure to QML is working.
1436 QDeclarativeView *canvas = createView(SRCDIR "/data/validators.qml");
1440 QVERIFY(canvas->rootObject() != 0);
1442 QDeclarative1TextInput *intInput = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("intInput")));
1444 intInput->setFocus(true);
1445 QTRY_VERIFY(intInput->hasActiveFocus());
1446 QTest::keyPress(canvas, Qt::Key_1);
1447 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1448 QCOMPARE(intInput->text(), QLatin1String("1"));
1449 QCOMPARE(intInput->hasAcceptableInput(), false);
1450 QTest::keyPress(canvas, Qt::Key_2);
1451 QTest::keyRelease(canvas, Qt::Key_2, Qt::NoModifier ,10);
1452 QCOMPARE(intInput->text(), QLatin1String("1"));
1453 QCOMPARE(intInput->hasAcceptableInput(), false);
1454 QTest::keyPress(canvas, Qt::Key_1);
1455 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1456 QCOMPARE(intInput->text(), QLatin1String("11"));
1457 QCOMPARE(intInput->hasAcceptableInput(), true);
1458 QTest::keyPress(canvas, Qt::Key_0);
1459 QTest::keyRelease(canvas, Qt::Key_0, Qt::NoModifier ,10);
1460 QCOMPARE(intInput->text(), QLatin1String("11"));
1461 QCOMPARE(intInput->hasAcceptableInput(), true);
1463 QDeclarative1TextInput *dblInput = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("dblInput")));
1464 QTRY_VERIFY(dblInput);
1465 dblInput->setFocus(true);
1466 QVERIFY(dblInput->hasActiveFocus() == true);
1467 QTest::keyPress(canvas, Qt::Key_1);
1468 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1469 QCOMPARE(dblInput->text(), QLatin1String("1"));
1470 QCOMPARE(dblInput->hasAcceptableInput(), false);
1471 QTest::keyPress(canvas, Qt::Key_2);
1472 QTest::keyRelease(canvas, Qt::Key_2, Qt::NoModifier ,10);
1473 QCOMPARE(dblInput->text(), QLatin1String("12"));
1474 QCOMPARE(dblInput->hasAcceptableInput(), true);
1475 QTest::keyPress(canvas, Qt::Key_Period);
1476 QTest::keyRelease(canvas, Qt::Key_Period, Qt::NoModifier ,10);
1477 QCOMPARE(dblInput->text(), QLatin1String("12."));
1478 QCOMPARE(dblInput->hasAcceptableInput(), true);
1479 QTest::keyPress(canvas, Qt::Key_1);
1480 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1481 QCOMPARE(dblInput->text(), QLatin1String("12.1"));
1482 QCOMPARE(dblInput->hasAcceptableInput(), true);
1483 QTest::keyPress(canvas, Qt::Key_1);
1484 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1485 QCOMPARE(dblInput->text(), QLatin1String("12.11"));
1486 QCOMPARE(dblInput->hasAcceptableInput(), true);
1487 QTest::keyPress(canvas, Qt::Key_1);
1488 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1489 QCOMPARE(dblInput->text(), QLatin1String("12.11"));
1490 QCOMPARE(dblInput->hasAcceptableInput(), true);
1492 QDeclarative1TextInput *strInput = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("strInput")));
1493 QTRY_VERIFY(strInput);
1494 strInput->setFocus(true);
1495 QVERIFY(strInput->hasActiveFocus() == true);
1496 QTest::keyPress(canvas, Qt::Key_1);
1497 QTest::keyRelease(canvas, Qt::Key_1, Qt::NoModifier ,10);
1498 QCOMPARE(strInput->text(), QLatin1String(""));
1499 QCOMPARE(strInput->hasAcceptableInput(), false);
1500 QTest::keyPress(canvas, Qt::Key_A);
1501 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1502 QCOMPARE(strInput->text(), QLatin1String("a"));
1503 QCOMPARE(strInput->hasAcceptableInput(), false);
1504 QTest::keyPress(canvas, Qt::Key_A);
1505 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1506 QCOMPARE(strInput->text(), QLatin1String("aa"));
1507 QCOMPARE(strInput->hasAcceptableInput(), true);
1508 QTest::keyPress(canvas, Qt::Key_A);
1509 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1510 QCOMPARE(strInput->text(), QLatin1String("aaa"));
1511 QCOMPARE(strInput->hasAcceptableInput(), true);
1512 QTest::keyPress(canvas, Qt::Key_A);
1513 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1514 QCOMPARE(strInput->text(), QLatin1String("aaaa"));
1515 QCOMPARE(strInput->hasAcceptableInput(), true);
1516 QTest::keyPress(canvas, Qt::Key_A);
1517 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
1518 QCOMPARE(strInput->text(), QLatin1String("aaaa"));
1519 QCOMPARE(strInput->hasAcceptableInput(), true);
1524 void tst_qdeclarativetextinput::inputMethods()
1526 QDeclarativeView *canvas = createView(SRCDIR "/data/inputmethods.qml");
1529 QApplication::setActiveWindow(canvas);
1530 QTest::qWaitForWindowShown(canvas);
1532 // test input method hints
1533 QVERIFY(canvas->rootObject() != 0);
1534 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
1535 QVERIFY(input != 0);
1536 QVERIFY(input->imHints() & Qt::ImhNoPredictiveText);
1537 QVERIFY(input->inputMethodHints() & Qt::ImhNoPredictiveText);
1538 input->setIMHints(Qt::ImhUppercaseOnly);
1539 QVERIFY(input->imHints() & Qt::ImhUppercaseOnly);
1540 QVERIFY(input->inputMethodHints() & Qt::ImhUppercaseOnly);
1542 QVERIFY(canvas->rootObject() != 0);
1544 input->setFocus(true);
1545 QVERIFY(input->hasActiveFocus() == true);
1546 // test that input method event is committed
1547 QInputMethodEvent event;
1548 event.setCommitString( "My ", -12, 0);
1549 QApplication::sendEvent(canvas, &event);
1550 QCOMPARE(input->text(), QString("My Hello world!"));
1552 input->setCursorPosition(2);
1553 event.setCommitString("Your", -2, 2);
1554 QApplication::sendEvent(canvas, &event);
1555 QCOMPARE(input->text(), QString("Your Hello world!"));
1556 QCOMPARE(input->cursorPosition(), 4);
1558 input->setCursorPosition(7);
1559 event.setCommitString("Goodbye", -2, 5);
1560 QApplication::sendEvent(canvas, &event);
1561 QCOMPARE(input->text(), QString("Your Goodbye world!"));
1562 QCOMPARE(input->cursorPosition(), 12);
1564 input->setCursorPosition(8);
1565 event.setCommitString("Our", -8, 4);
1566 QApplication::sendEvent(canvas, &event);
1567 QCOMPARE(input->text(), QString("Our Goodbye world!"));
1568 QCOMPARE(input->cursorPosition(), 7);
1574 TextInput element should only handle left/right keys until the cursor reaches
1575 the extent of the text, then they should ignore the keys.
1578 void tst_qdeclarativetextinput::navigation()
1580 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
1584 QVERIFY(canvas->rootObject() != 0);
1586 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1588 QVERIFY(input != 0);
1589 input->setCursorPosition(0);
1590 QTRY_VERIFY(input->hasActiveFocus() == true);
1591 simulateKey(canvas, Qt::Key_Left);
1592 QVERIFY(input->hasActiveFocus() == false);
1593 simulateKey(canvas, Qt::Key_Right);
1594 QVERIFY(input->hasActiveFocus() == true);
1595 //QT-2944: If text is selected, ensure we deselect upon cursor motion
1596 input->setCursorPosition(input->text().length());
1597 input->select(0,input->text().length());
1598 QVERIFY(input->selectionStart() != input->selectionEnd());
1599 simulateKey(canvas, Qt::Key_Right);
1600 QVERIFY(input->selectionStart() == input->selectionEnd());
1601 QVERIFY(input->selectionStart() == input->text().length());
1602 QVERIFY(input->hasActiveFocus() == true);
1603 simulateKey(canvas, Qt::Key_Right);
1604 QVERIFY(input->hasActiveFocus() == false);
1605 simulateKey(canvas, Qt::Key_Left);
1606 QVERIFY(input->hasActiveFocus() == true);
1608 // Up and Down should NOT do Home/End, even on Mac OS X (QTBUG-10438).
1609 input->setCursorPosition(2);
1610 QCOMPARE(input->cursorPosition(),2);
1611 simulateKey(canvas, Qt::Key_Up);
1612 QCOMPARE(input->cursorPosition(),2);
1613 simulateKey(canvas, Qt::Key_Down);
1614 QCOMPARE(input->cursorPosition(),2);
1619 void tst_qdeclarativetextinput::navigation_RTL()
1621 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
1625 QVERIFY(canvas->rootObject() != 0);
1627 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1629 QVERIFY(input != 0);
1630 const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
1631 input->setText(QString::fromUtf16(arabic_str, 11));
1633 input->setCursorPosition(0);
1634 QTRY_VERIFY(input->hasActiveFocus() == true);
1637 simulateKey(canvas, Qt::Key_Right);
1638 QVERIFY(input->hasActiveFocus() == false);
1641 simulateKey(canvas, Qt::Key_Left);
1642 QVERIFY(input->hasActiveFocus() == true);
1644 input->setCursorPosition(input->text().length());
1645 QVERIFY(input->hasActiveFocus() == true);
1648 simulateKey(canvas, Qt::Key_Left);
1649 QVERIFY(input->hasActiveFocus() == false);
1652 simulateKey(canvas, Qt::Key_Right);
1653 QVERIFY(input->hasActiveFocus() == true);
1658 void tst_qdeclarativetextinput::copyAndPaste() {
1659 #ifndef QT_NO_CLIPBOARD
1663 PasteboardRef pasteboard;
1664 OSStatus status = PasteboardCreate(0, &pasteboard);
1665 if (status == noErr)
1666 CFRelease(pasteboard);
1668 QSKIP("This machine doesn't support the clipboard", SkipAll);
1672 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }";
1673 QDeclarativeComponent textInputComponent(&engine);
1674 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1675 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1676 QVERIFY(textInput != 0);
1679 QCOMPARE(textInput->text().length(), 12);
1680 textInput->select(0, textInput->text().length());;
1682 QCOMPARE(textInput->selectedText(), QString("Hello world!"));
1683 QCOMPARE(textInput->selectedText().length(), 12);
1684 textInput->setCursorPosition(0);
1685 QVERIFY(textInput->canPaste());
1687 QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
1688 QCOMPARE(textInput->text().length(), 24);
1691 QVERIFY(textInput->canPaste());
1692 textInput->setReadOnly(true);
1693 QVERIFY(!textInput->canPaste());
1694 textInput->setReadOnly(false);
1695 QVERIFY(textInput->canPaste());
1698 textInput->setCursorPosition(0);
1699 textInput->selectWord();
1700 QCOMPARE(textInput->selectedText(), QString("Hello"));
1702 // select all and cut
1703 textInput->selectAll();
1705 QCOMPARE(textInput->text().length(), 0);
1707 QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
1708 QCOMPARE(textInput->text().length(), 24);
1710 // clear copy buffer
1711 QClipboard *clipboard = QApplication::clipboard();
1714 QVERIFY(!textInput->canPaste());
1716 // test that copy functionality is disabled
1717 // when echo mode is set to hide text/password mode
1720 QDeclarative1TextInput::EchoMode echoMode = QDeclarative1TextInput::EchoMode(index);
1721 textInput->setEchoMode(echoMode);
1722 textInput->setText("My password");
1723 textInput->select(0, textInput->text().length());;
1725 if (echoMode == QDeclarative1TextInput::Normal) {
1726 QVERIFY(!clipboard->text().isEmpty());
1727 QCOMPARE(clipboard->text(), QString("My password"));
1730 QVERIFY(clipboard->text().isEmpty());
1739 void tst_qdeclarativetextinput::canPasteEmpty() {
1740 #ifndef QT_NO_CLIPBOARD
1742 QApplication::clipboard()->clear();
1744 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }";
1745 QDeclarativeComponent textInputComponent(&engine);
1746 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1747 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1748 QVERIFY(textInput != 0);
1751 bool cp = !lc.isReadOnly() && QApplication::clipboard()->text().length() != 0;
1752 QCOMPARE(textInput->canPaste(), cp);
1757 void tst_qdeclarativetextinput::canPaste() {
1758 #ifndef QT_NO_CLIPBOARD
1760 QApplication::clipboard()->setText("Some text");
1762 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\" }";
1763 QDeclarativeComponent textInputComponent(&engine);
1764 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1765 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1766 QVERIFY(textInput != 0);
1769 bool cp = !lc.isReadOnly() && QApplication::clipboard()->text().length() != 0;
1770 QCOMPARE(textInput->canPaste(), cp);
1775 void tst_qdeclarativetextinput::passwordCharacter()
1777 QString componentStr = "import QtQuick 1.0\nTextInput { text: \"Hello world!\"; font.family: \"Helvetica\"; echoMode: TextInput.Password }";
1778 QDeclarativeComponent textInputComponent(&engine);
1779 textInputComponent.setData(componentStr.toLatin1(), QUrl());
1780 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput*>(textInputComponent.create());
1781 QVERIFY(textInput != 0);
1783 textInput->setPasswordCharacter("X");
1784 QSize contentsSize = textInput->contentsSize();
1785 textInput->setPasswordCharacter(".");
1786 // QTBUG-12383 content is updated and redrawn
1787 QVERIFY(contentsSize != textInput->contentsSize());
1792 void tst_qdeclarativetextinput::cursorDelegate()
1794 QDeclarativeView* view = createView(SRCDIR "/data/cursorTest.qml");
1797 QDeclarative1TextInput *textInputObject = view->rootObject()->findChild<QDeclarative1TextInput*>("textInputObject");
1798 QVERIFY(textInputObject != 0);
1799 QVERIFY(textInputObject->findChild<QDeclarativeItem*>("cursorInstance"));
1800 //Test Delegate gets created
1801 textInputObject->setFocus(true);
1802 QDeclarativeItem* delegateObject = textInputObject->findChild<QDeclarativeItem*>("cursorInstance");
1803 QVERIFY(delegateObject);
1804 //Test Delegate gets moved
1805 for(int i=0; i<= textInputObject->text().length(); i++){
1806 textInputObject->setCursorPosition(i);
1807 QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
1808 QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
1810 const QString preedit = "preedit";
1811 for (int i = 0; i <= preedit.length(); i++) {
1812 QInputMethodEvent event(preedit, QList<QInputMethodEvent::Attribute>()
1813 << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, 1, QVariant()));
1814 QApplication::sendEvent(view, &event);
1816 QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
1817 QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
1819 textInputObject->setCursorPosition(0);
1820 QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
1821 QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
1822 //Test Delegate gets deleted
1823 textInputObject->setCursorDelegate(0);
1824 QVERIFY(!textInputObject->findChild<QDeclarativeItem*>("cursorInstance"));
1829 void tst_qdeclarativetextinput::cursorVisible()
1831 QGraphicsScene scene;
1832 QGraphicsView view(&scene);
1834 QApplication::setActiveWindow(&view);
1835 QTest::qWaitForWindowShown(&view);
1836 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
1838 QDeclarative1TextInput input;
1839 QSignalSpy spy(&input, SIGNAL(cursorVisibleChanged(bool)));
1841 QCOMPARE(input.isCursorVisible(), false);
1843 input.setCursorVisible(true);
1844 QCOMPARE(input.isCursorVisible(), true);
1845 QCOMPARE(spy.count(), 1);
1847 input.setCursorVisible(false);
1848 QCOMPARE(input.isCursorVisible(), false);
1849 QCOMPARE(spy.count(), 2);
1851 input.setFocus(true);
1852 QCOMPARE(input.isCursorVisible(), false);
1853 QCOMPARE(spy.count(), 2);
1855 scene.addItem(&input);
1856 QCOMPARE(input.isCursorVisible(), true);
1857 QCOMPARE(spy.count(), 3);
1859 input.setFocus(false);
1860 QCOMPARE(input.isCursorVisible(), false);
1861 QCOMPARE(spy.count(), 4);
1863 input.setFocus(true);
1864 QCOMPARE(input.isCursorVisible(), true);
1865 QCOMPARE(spy.count(), 5);
1868 QCOMPARE(input.isCursorVisible(), false);
1869 QCOMPARE(spy.count(), 6);
1872 QCOMPARE(input.isCursorVisible(), true);
1873 QCOMPARE(spy.count(), 7);
1876 QCOMPARE(input.isCursorVisible(), false);
1877 QCOMPARE(spy.count(), 8);
1880 QCOMPARE(input.isCursorVisible(), true);
1881 QCOMPARE(spy.count(), 9);
1883 // on mac, setActiveWindow(0) on mac does not deactivate the current application
1884 // (you have to switch to a different app or hide the current app to trigger this)
1885 #if !defined(Q_WS_MAC)
1886 QApplication::setActiveWindow(0);
1887 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(0));
1888 QCOMPARE(input.isCursorVisible(), false);
1889 QCOMPARE(spy.count(), 10);
1891 QApplication::setActiveWindow(&view);
1892 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
1893 QCOMPARE(input.isCursorVisible(), true);
1894 QCOMPARE(spy.count(), 11);
1898 void tst_qdeclarativetextinput::cursorRectangle()
1900 QString text = "Hello World!";
1902 QDeclarative1TextInput input;
1903 input.setText(text);
1904 QFontMetricsF fm(input.font());
1905 input.setWidth(fm.width(text.mid(0, 5)));
1909 // some tolerance for different fonts.
1911 const int error = 2;
1913 const int error = 5;
1916 for (int i = 0; i <= 5; ++i) {
1917 input.setCursorPosition(i);
1918 r = input.cursorRectangle();
1919 int textWidth = fm.width(text.mid(0, i));
1921 QVERIFY(r.left() < textWidth + error);
1922 QVERIFY(r.right() > textWidth - error);
1923 QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
1926 // Check the cursor rectangle remains within the input bounding rect when auto scrolling.
1927 QVERIFY(r.left() < input.boundingRect().width());
1928 QVERIFY(r.right() >= input.width() - error);
1930 for (int i = 6; i < text.length(); ++i) {
1931 input.setCursorPosition(i);
1932 QCOMPARE(r, input.cursorRectangle());
1933 QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
1936 for (int i = text.length() - 2; i >= 0; --i) {
1937 input.setCursorPosition(i);
1938 r = input.cursorRectangle();
1939 QVERIFY(r.right() >= 0);
1940 QCOMPARE(input.inputMethodQuery(Qt::ImMicroFocus).toRect(), r);
1944 void tst_qdeclarativetextinput::readOnly()
1946 QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml");
1950 QVERIFY(canvas->rootObject() != 0);
1952 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1954 QVERIFY(input != 0);
1955 QTRY_VERIFY(input->hasActiveFocus() == true);
1956 QVERIFY(input->isReadOnly() == true);
1957 QString initial = input->text();
1958 for(int k=Qt::Key_0; k<=Qt::Key_Z; k++)
1959 simulateKey(canvas, k);
1960 simulateKey(canvas, Qt::Key_Return);
1961 simulateKey(canvas, Qt::Key_Space);
1962 simulateKey(canvas, Qt::Key_Escape);
1963 QCOMPARE(input->text(), initial);
1968 void tst_qdeclarativetextinput::echoMode()
1970 QDeclarativeView *canvas = createView(SRCDIR "/data/echoMode.qml");
1973 QApplication::setActiveWindow(canvas);
1974 QTest::qWaitForWindowShown(canvas);
1975 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1977 QVERIFY(canvas->rootObject() != 0);
1979 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1981 QVERIFY(input != 0);
1982 QTRY_VERIFY(input->hasActiveFocus() == true);
1983 QString initial = input->text();
1984 Qt::InputMethodHints ref;
1985 QCOMPARE(initial, QLatin1String("ABCDefgh"));
1986 QCOMPARE(input->echoMode(), QDeclarative1TextInput::Normal);
1987 QCOMPARE(input->displayText(), input->text());
1989 ref &= ~Qt::ImhHiddenText;
1990 ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
1991 QCOMPARE(input->inputMethodHints(), ref);
1992 QCOMPARE(input->imHints(), Qt::ImhNone);
1993 input->setEchoMode(QDeclarative1TextInput::NoEcho);
1994 QCOMPARE(input->text(), initial);
1995 QCOMPARE(input->displayText(), QLatin1String(""));
1996 QCOMPARE(input->passwordCharacter(), QLatin1String("*"));
1998 ref |= Qt::ImhHiddenText;
1999 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2000 QCOMPARE(input->inputMethodHints(), ref);
2001 QCOMPARE(input->imHints(), Qt::ImhNone);
2002 input->setEchoMode(QDeclarative1TextInput::Password);
2004 ref |= Qt::ImhHiddenText;
2005 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2006 QCOMPARE(input->text(), initial);
2007 QCOMPARE(input->displayText(), QLatin1String("********"));
2008 QCOMPARE(input->inputMethodHints(), ref);
2009 QCOMPARE(input->imHints(), Qt::ImhNone);
2010 input->setPasswordCharacter(QChar('Q'));
2011 QCOMPARE(input->passwordCharacter(), QLatin1String("Q"));
2012 QCOMPARE(input->text(), initial);
2013 QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
2014 input->setEchoMode(QDeclarative1TextInput::PasswordEchoOnEdit);
2015 //PasswordEchoOnEdit
2016 ref &= ~Qt::ImhHiddenText;
2017 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2018 QCOMPARE(input->inputMethodHints(), ref);
2019 QCOMPARE(input->imHints(), Qt::ImhNone);
2020 QCOMPARE(input->text(), initial);
2021 QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
2022 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("QQQQQQQQ"));
2023 QTest::keyPress(canvas, Qt::Key_A);//Clearing previous entry is part of PasswordEchoOnEdit
2024 QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
2025 QCOMPARE(input->text(), QLatin1String("a"));
2026 QCOMPARE(input->displayText(), QLatin1String("a"));
2027 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("a"));
2028 input->setFocus(false);
2029 QVERIFY(input->hasActiveFocus() == false);
2030 QCOMPARE(input->displayText(), QLatin1String("Q"));
2031 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("Q"));
2032 input->setFocus(true);
2033 QInputMethodEvent inputEvent;
2034 inputEvent.setCommitString(initial);
2035 QApplication::sendEvent(canvas, &inputEvent);
2036 QCOMPARE(input->text(), initial);
2037 QCOMPARE(input->displayText(), initial);
2038 QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial);
2040 // Test echo mode doesn't override imHints.
2041 input->setIMHints(Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2042 ref |= Qt::ImhDialableCharactersOnly;
2044 input->setEchoMode(QDeclarative1TextInput::Normal);
2045 ref |= Qt::ImhHiddenText;
2046 ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2047 QCOMPARE(input->inputMethodHints(), ref);
2048 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2050 input->setEchoMode(QDeclarative1TextInput::NoEcho);
2051 ref |= Qt::ImhHiddenText;
2052 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2053 QCOMPARE(input->inputMethodHints(), ref);
2054 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2056 input->setEchoMode(QDeclarative1TextInput::Password);
2057 ref |= Qt::ImhHiddenText;
2058 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2059 QCOMPARE(input->inputMethodHints(), ref);
2060 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2061 //PasswordEchoOnEdit
2062 input->setEchoMode(QDeclarative1TextInput::PasswordEchoOnEdit);
2063 ref &= ~Qt::ImhHiddenText;
2064 ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2065 QCOMPARE(input->inputMethodHints(), ref);
2066 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2068 input->setEchoMode(QDeclarative1TextInput::Normal);
2069 ref |= Qt::ImhHiddenText;
2070 ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
2071 QCOMPARE(input->inputMethodHints(), ref);
2072 QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly);
2078 #ifdef QT_GUI_PASSWORD_ECHO_DELAY
2079 void tst_qdeclarativetextinput::passwordEchoDelay()
2081 QDeclarativeView *canvas = createView(SRCDIR "/data/echoMode.qml");
2084 QApplication::setActiveWindow(canvas);
2085 QTest::qWaitForWindowShown(canvas);
2086 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
2088 QVERIFY(canvas->rootObject() != 0);
2090 QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
2092 QChar fillChar = QLatin1Char('*');
2094 input->setEchoMode(QDeclarativeTextInput::Password);
2095 QCOMPARE(input->displayText(), QString(8, fillChar));
2096 input->setText(QString());
2097 QCOMPARE(input->displayText(), QString());
2099 QTest::keyPress(canvas, '0');
2100 QTest::keyPress(canvas, '1');
2101 QTest::keyPress(canvas, '2');
2102 QCOMPARE(input->displayText(), QString(2, fillChar) + QLatin1Char('2'));
2103 QTest::keyPress(canvas, '3');
2104 QTest::keyPress(canvas, '4');
2105 QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
2106 QTest::keyPress(canvas, Qt::Key_Backspace);
2107 QCOMPARE(input->displayText(), QString(4, fillChar));
2108 QTest::keyPress(canvas, '4');
2109 QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
2110 QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
2111 QTRY_COMPARE(input->displayText(), QString(5, fillChar));
2112 QTest::keyPress(canvas, '5');
2113 QCOMPARE(input->displayText(), QString(5, fillChar) + QLatin1Char('5'));
2114 input->setFocus(false);
2115 QVERIFY(!input->hasFocus());
2116 QCOMPARE(input->displayText(), QString(6, fillChar));
2117 input->setFocus(true);
2118 QTRY_VERIFY(input->hasFocus());
2119 QCOMPARE(input->displayText(), QString(6, fillChar));
2120 QTest::keyPress(canvas, '6');
2121 QCOMPARE(input->displayText(), QString(6, fillChar) + QLatin1Char('6'));
2123 QInputMethodEvent ev;
2124 ev.setCommitString(QLatin1String("7"));
2125 QApplication::sendEvent(canvas, &ev);
2126 QCOMPARE(input->displayText(), QString(7, fillChar) + QLatin1Char('7'));
2133 void tst_qdeclarativetextinput::simulateKey(QDeclarativeView *view, int key)
2135 QKeyEvent press(QKeyEvent::KeyPress, key, 0);
2136 QKeyEvent release(QKeyEvent::KeyRelease, key, 0);
2138 QApplication::sendEvent(view, &press);
2139 QApplication::sendEvent(view, &release);
2142 QDeclarativeView *tst_qdeclarativetextinput::createView(const QString &filename)
2144 QDeclarativeView *canvas = new QDeclarativeView(0);
2146 canvas->setSource(QUrl::fromLocalFile(filename));
2150 class MyInputContext : public QInputContext
2153 MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false), updateReceived(false), eventType(QEvent::None) {}
2154 ~MyInputContext() {}
2156 QString identifierName() { return QString(); }
2157 QString language() { return QString(); }
2161 bool isComposing() const { return false; }
2163 bool filterEvent( const QEvent *event )
2165 if (event->type() == QEvent::RequestSoftwareInputPanel)
2166 openInputPanelReceived = true;
2167 if (event->type() == QEvent::CloseSoftwareInputPanel)
2168 closeInputPanelReceived = true;
2169 return false; //QInputContext::filterEvent(event);
2172 void update() { updateReceived = true; }
2174 void mouseHandler(int x, QMouseEvent *event)
2177 eventType = event->type();
2178 eventPosition = event->pos();
2179 eventGlobalPosition = event->globalPos();
2180 eventButton = event->button();
2181 eventButtons = event->buttons();
2182 eventModifiers = event->modifiers();
2185 void sendPreeditText(const QString &text, int cursor)
2187 QList<QInputMethodEvent::Attribute> attributes;
2188 attributes.append(QInputMethodEvent::Attribute(
2189 QInputMethodEvent::Cursor, cursor, text.length(), QVariant()));
2191 QInputMethodEvent event(text, attributes);
2195 bool openInputPanelReceived;
2196 bool closeInputPanelReceived;
2197 bool updateReceived;
2199 QEvent::Type eventType;
2200 QPoint eventPosition;
2201 QPoint eventGlobalPosition;
2202 Qt::MouseButton eventButton;
2203 Qt::MouseButtons eventButtons;
2204 Qt::KeyboardModifiers eventModifiers;
2207 void tst_qdeclarativetextinput::openInputPanelOnClick()
2209 QGraphicsScene scene;
2210 QGraphicsView view(&scene);
2212 view.setInputContext(&ic);
2213 QDeclarative1TextInput input;
2214 QSignalSpy focusOnPressSpy(&input, SIGNAL(activeFocusOnPressChanged(bool)));
2215 input.setText("Hello world");
2217 scene.addItem(&input);
2219 qApp->setAutoSipEnabled(true);
2220 QApplication::setActiveWindow(&view);
2221 QTest::qWaitForWindowShown(&view);
2222 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2224 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&input);
2225 QDeclarative1TextInputPrivate *inputPrivate = static_cast<QDeclarative1TextInputPrivate*>(pri);
2227 // input panel on click
2228 inputPrivate->showInputPanelOnFocus = false;
2230 QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
2231 view.style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
2232 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2233 QApplication::processEvents();
2234 if (behavior == QStyle::RSIP_OnMouseClickAndAlreadyFocused) {
2235 QCOMPARE(ic.openInputPanelReceived, false);
2236 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2237 QApplication::processEvents();
2238 QCOMPARE(ic.openInputPanelReceived, true);
2239 } else if (behavior == QStyle::RSIP_OnMouseClick) {
2240 QCOMPARE(ic.openInputPanelReceived, true);
2242 ic.openInputPanelReceived = false;
2244 // focus should not cause input panels to open or close
2245 input.setFocus(false);
2246 input.setFocus(true);
2247 input.setFocus(false);
2248 input.setFocus(true);
2249 input.setFocus(false);
2250 QCOMPARE(ic.openInputPanelReceived, false);
2251 QCOMPARE(ic.closeInputPanelReceived, false);
2254 void tst_qdeclarativetextinput::openInputPanelOnFocus()
2256 QGraphicsScene scene;
2257 QGraphicsView view(&scene);
2259 view.setInputContext(&ic);
2260 QDeclarative1TextInput input;
2261 QSignalSpy focusOnPressSpy(&input, SIGNAL(activeFocusOnPressChanged(bool)));
2262 input.setText("Hello world");
2264 scene.addItem(&input);
2266 qApp->setAutoSipEnabled(true);
2267 QApplication::setActiveWindow(&view);
2268 QTest::qWaitForWindowShown(&view);
2269 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2271 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&input);
2272 QDeclarative1TextInputPrivate *inputPrivate = static_cast<QDeclarative1TextInputPrivate*>(pri);
2273 inputPrivate->showInputPanelOnFocus = true;
2275 // test default values
2276 QVERIFY(input.focusOnPress());
2277 QCOMPARE(ic.openInputPanelReceived, false);
2278 QCOMPARE(ic.closeInputPanelReceived, false);
2280 // focus on press, input panel on focus
2281 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2282 QApplication::processEvents();
2283 QVERIFY(input.hasActiveFocus());
2284 QCOMPARE(ic.openInputPanelReceived, true);
2285 ic.openInputPanelReceived = false;
2287 // no events on release
2288 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2289 QCOMPARE(ic.openInputPanelReceived, false);
2290 ic.openInputPanelReceived = false;
2292 // if already focused, input panel can be opened on press
2293 QVERIFY(input.hasActiveFocus());
2294 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2295 QApplication::processEvents();
2296 QCOMPARE(ic.openInputPanelReceived, true);
2297 ic.openInputPanelReceived = false;
2299 // input method should stay enabled if focus
2300 // is lost to an item that also accepts inputs
2301 QDeclarative1TextInput anotherInput;
2302 scene.addItem(&anotherInput);
2303 anotherInput.setFocus(true);
2304 QApplication::processEvents();
2305 QCOMPARE(ic.openInputPanelReceived, true);
2306 ic.openInputPanelReceived = false;
2307 QCOMPARE(view.inputContext(), (QInputContext*)&ic);
2308 QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
2310 // input method should be disabled if focus
2311 // is lost to an item that doesn't accept inputs
2312 QDeclarativeItem item;
2313 scene.addItem(&item);
2314 item.setFocus(true);
2315 QApplication::processEvents();
2316 QCOMPARE(ic.openInputPanelReceived, false);
2317 QVERIFY(view.inputContext() == 0);
2318 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2320 // no automatic input panel events should
2321 // be sent if activeFocusOnPress is false
2322 input.setFocusOnPress(false);
2323 QCOMPARE(focusOnPressSpy.count(),1);
2324 input.setFocusOnPress(false);
2325 QCOMPARE(focusOnPressSpy.count(),1);
2326 input.setFocus(false);
2327 input.setFocus(true);
2328 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2329 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(input.scenePos()));
2330 QApplication::processEvents();
2331 QCOMPARE(ic.openInputPanelReceived, false);
2332 QCOMPARE(ic.closeInputPanelReceived, false);
2334 // one show input panel event should
2335 // be set when openSoftwareInputPanel is called
2336 input.openSoftwareInputPanel();
2337 QCOMPARE(ic.openInputPanelReceived, true);
2338 QCOMPARE(ic.closeInputPanelReceived, false);
2339 ic.openInputPanelReceived = false;
2341 // one close input panel event should
2342 // be sent when closeSoftwareInputPanel is called
2343 input.closeSoftwareInputPanel();
2344 QCOMPARE(ic.openInputPanelReceived, false);
2345 QCOMPARE(ic.closeInputPanelReceived, true);
2346 ic.closeInputPanelReceived = false;
2348 // set activeFocusOnPress back to true
2349 input.setFocusOnPress(true);
2350 QCOMPARE(focusOnPressSpy.count(),2);
2351 input.setFocusOnPress(true);
2352 QCOMPARE(focusOnPressSpy.count(),2);
2353 input.setFocus(false);
2354 QApplication::processEvents();
2355 QCOMPARE(ic.openInputPanelReceived, false);
2356 QCOMPARE(ic.closeInputPanelReceived, false);
2357 ic.closeInputPanelReceived = false;
2359 // input panel should not re-open
2360 // if focus has already been set
2361 input.setFocus(true);
2362 QCOMPARE(ic.openInputPanelReceived, true);
2363 ic.openInputPanelReceived = false;
2364 input.setFocus(true);
2365 QCOMPARE(ic.openInputPanelReceived, false);
2367 // input method should be disabled
2368 // if TextInput loses focus
2369 input.setFocus(false);
2370 QApplication::processEvents();
2371 QVERIFY(view.inputContext() == 0);
2372 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2374 // input method should not be enabled
2375 // if TextEdit is read only.
2376 input.setReadOnly(true);
2377 ic.openInputPanelReceived = false;
2378 input.setFocus(true);
2379 QApplication::processEvents();
2380 QCOMPARE(ic.openInputPanelReceived, false);
2381 QVERIFY(view.inputContext() == 0);
2382 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2385 class MyTextInput : public QDeclarative1TextInput
2388 MyTextInput(QDeclarativeItem *parent = 0) : QDeclarative1TextInput(parent)
2392 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
2395 QDeclarative1TextInput::paint(painter, option, widget);
2400 void tst_qdeclarativetextinput::setHAlignClearCache()
2402 QGraphicsScene scene;
2403 QGraphicsView view(&scene);
2405 input.setText("Hello world");
2406 scene.addItem(&input);
2408 QApplication::setActiveWindow(&view);
2409 QTest::qWaitForWindowShown(&view);
2411 QEXPECT_FAIL("", "QTBUG-21017 fails", Abort);
2413 QTRY_COMPARE(input.nbPaint, 1);
2414 input.setHAlign(QDeclarative1TextInput::AlignRight);
2415 QApplication::processEvents();
2416 //Changing the alignment should trigger a repaint
2417 QCOMPARE(input.nbPaint, 2);
2420 void tst_qdeclarativetextinput::focusOutClearSelection()
2422 QGraphicsScene scene;
2423 QGraphicsView view(&scene);
2424 QDeclarative1TextInput input;
2425 QDeclarative1TextInput input2;
2426 input.setText(QLatin1String("Hello world"));
2427 input.setFocus(true);
2428 scene.addItem(&input2);
2429 scene.addItem(&input);
2431 QApplication::setActiveWindow(&view);
2432 QTest::qWaitForWindowShown(&view);
2434 //The selection should work
2435 QTRY_COMPARE(input.selectedText(), QLatin1String("llo"));
2436 input2.setFocus(true);
2437 QApplication::processEvents();
2438 //The input lost the focus selection should be cleared
2439 QTRY_COMPARE(input.selectedText(), QLatin1String(""));
2442 void tst_qdeclarativetextinput::geometrySignals()
2444 QDeclarativeComponent component(&engine, SRCDIR "/data/geometrySignals.qml");
2445 QObject *o = component.create();
2447 QCOMPARE(o->property("bindingWidth").toInt(), 400);
2448 QCOMPARE(o->property("bindingHeight").toInt(), 500);
2452 void tst_qdeclarativetextinput::testQtQuick11Attributes()
2454 QFETCH(QString, code);
2455 QFETCH(QString, warning);
2456 QFETCH(QString, error);
2458 QDeclarativeEngine engine;
2461 QDeclarativeComponent valid(&engine);
2462 valid.setData("import QtQuick 1.1; TextInput { " + code.toUtf8() + " }", QUrl(""));
2463 obj = valid.create();
2465 QVERIFY(valid.errorString().isEmpty());
2468 QDeclarativeComponent invalid(&engine);
2469 invalid.setData("import QtQuick 1.0; TextInput { " + code.toUtf8() + " }", QUrl(""));
2470 QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
2471 obj = invalid.create();
2472 QCOMPARE(invalid.errorString(), error);
2476 void tst_qdeclarativetextinput::testQtQuick11Attributes_data()
2478 QTest::addColumn<QString>("code");
2479 QTest::addColumn<QString>("warning");
2480 QTest::addColumn<QString>("error");
2482 QTest::newRow("canPaste") << "property bool foo: canPaste"
2483 << "<Unknown File>:1: ReferenceError: Can't find variable: canPaste"
2486 QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)"
2487 << "<Unknown File>:1: ReferenceError: Can't find variable: moveCursorSelection"
2490 QTest::newRow("deselect") << "Component.onCompleted: deselect()"
2491 << "<Unknown File>:1: ReferenceError: Can't find variable: deselect"
2495 void tst_qdeclarativetextinput::preeditAutoScroll()
2497 QString committedText = "super";
2498 QString preeditText = "califragisiticexpialidocious!";
2500 QGraphicsScene scene;
2501 QGraphicsView view(&scene);
2503 view.setInputContext(&ic);
2504 QDeclarative1TextInput input;
2505 QFontMetricsF fm(input.font());
2506 input.setWidth(fm.width(committedText));
2507 input.setText(committedText);
2509 input.setFocus(true);
2510 scene.addItem(&input);
2512 QApplication::setActiveWindow(&view);
2513 QTest::qWaitForWindowShown(&view);
2514 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2516 QSignalSpy cursorRectangleSpy(&input, SIGNAL(cursorRectangleChanged()));
2517 int cursorRectangleChanges = 0;
2519 // test the text is scrolled so the preedit is visible.
2520 ic.sendPreeditText(preeditText.mid(0, 3), 1);
2522 QEXPECT_FAIL("", "QTBUG-21017 fails", Abort);
2524 QVERIFY(input.positionAt(0) != 0);
2525 QVERIFY(input.cursorRectangle().left() < input.boundingRect().width());
2526 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2528 // test the text is scrolled back when the preedit is removed.
2529 ic.sendEvent(QInputMethodEvent());
2530 QCOMPARE(input.positionAt(0), 0);
2531 QCOMPARE(input.positionAt(input.width()), 5);
2532 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2534 // some tolerance for different fonts.
2536 const int error = 2;
2538 const int error = 5;
2541 // test if the preedit is larger than the text input that the
2542 // character preceding the cursor is still visible.
2543 qreal x = input.positionToRectangle(0).x();
2544 for (int i = 0; i < 3; ++i) {
2545 ic.sendPreeditText(preeditText, i + 1);
2546 QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i)) - error);
2547 QVERIFY(input.positionToRectangle(0).x() < x);
2548 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2549 x = input.positionToRectangle(0).x();
2551 for (int i = 1; i >= 0; --i) {
2552 ic.sendPreeditText(preeditText, i + 1);
2553 QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i)) - error);
2554 QVERIFY(input.positionToRectangle(0).x() > x);
2555 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2556 x = input.positionToRectangle(0).x();
2559 // Test incrementing the preedit cursor doesn't cause further
2560 // scrolling when right most text is visible.
2561 ic.sendPreeditText(preeditText, preeditText.length() - 3);
2562 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2563 x = input.positionToRectangle(0).x();
2564 for (int i = 2; i >= 0; --i) {
2565 ic.sendPreeditText(preeditText, preeditText.length() - i);
2566 QCOMPARE(input.positionToRectangle(0).x(), x);
2567 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2569 for (int i = 1; i < 3; ++i) {
2570 ic.sendPreeditText(preeditText, preeditText.length() - i);
2571 QCOMPARE(input.positionToRectangle(0).x(), x);
2572 QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
2575 // Test disabling auto scroll.
2576 ic.sendEvent(QInputMethodEvent());
2578 input.setAutoScroll(false);
2579 ic.sendPreeditText(preeditText.mid(0, 3), 1);
2580 QCOMPARE(input.positionAt(0), 0);
2581 QCOMPARE(input.positionAt(input.width()), 5);
2583 ic.sendEvent(QInputMethodEvent());
2584 input.setAutoScroll(true);
2585 // Test committing pre-edit text at the start of the string. QTBUG-18789
2586 input.setCursorPosition(0);
2587 ic.sendPreeditText(input.text(), 5);
2588 QCOMPARE(input.positionAt(0), 0);
2590 QInputMethodEvent event;
2591 event.setCommitString(input.text());
2592 ic.sendEvent(event);
2594 QCOMPARE(input.positionAt(0), 0);
2595 QCOMPARE(input.positionAt(input.width()), 5);
2598 void tst_qdeclarativetextinput::preeditMicroFocus()
2600 QString preeditText = "super";
2602 QGraphicsScene scene;
2603 QGraphicsView view(&scene);
2605 view.setInputContext(&ic);
2606 QDeclarative1TextInput input;
2608 input.setAutoScroll(false);
2609 input.setFocus(true);
2610 scene.addItem(&input);
2612 QApplication::setActiveWindow(&view);
2613 QTest::qWaitForWindowShown(&view);
2614 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2617 QRect previousRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2619 // Verify that the micro focus rect is positioned the same for position 0 as
2620 // it would be if there was no preedit text.
2621 ic.updateReceived = false;
2622 ic.sendPreeditText(preeditText, 0);
2623 currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2624 QCOMPARE(currentRect, previousRect);
2625 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
2626 QCOMPARE(ic.updateReceived, true);
2629 // Verify that the micro focus rect moves to the left as the cursor position
2631 for (int i = 1; i <= 5; ++i) {
2632 ic.updateReceived = false;
2633 ic.sendPreeditText(preeditText, i);
2634 currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2635 QVERIFY(previousRect.left() < currentRect.left());
2636 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
2637 QCOMPARE(ic.updateReceived, true);
2639 previousRect = currentRect;
2642 // Verify that if there is no preedit cursor then the micro focus rect is the
2643 // same as it would be if it were positioned at the end of the preedit text.
2644 ic.sendPreeditText(preeditText, 0);
2645 ic.updateReceived = false;
2646 ic.sendEvent(QInputMethodEvent(preeditText, QList<QInputMethodEvent::Attribute>()));
2647 currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect();
2648 QCOMPARE(currentRect, previousRect);
2649 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
2650 QCOMPARE(ic.updateReceived, true);
2654 void tst_qdeclarativetextinput::inputContextMouseHandler()
2656 QString text = "supercalifragisiticexpialidocious!";
2658 QGraphicsScene scene;
2659 QGraphicsView view(&scene);
2661 view.setInputContext(&ic);
2662 QDeclarative1TextInput input;
2663 input.setWidth(200);
2664 input.setText(text.mid(0, 12));
2665 input.setCursorPosition(12);
2667 input.setFocus(true);
2668 scene.addItem(&input);
2670 QApplication::setActiveWindow(&view);
2671 QTest::qWaitForWindowShown(&view);
2672 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2674 QFontMetricsF fm(input.font());
2675 const qreal y = fm.height() / 2;
2677 QPoint position2 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 2)), y)));
2678 QPoint position8 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 8)), y)));
2679 QPoint position20 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 20)), y)));
2680 QPoint position27 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 27)), y)));
2681 QPoint globalPosition2 = view.viewport()->mapToGlobal(position2);
2682 QPoint globalposition8 = view.viewport()->mapToGlobal(position8);
2683 QPoint globalposition20 = view.viewport()->mapToGlobal(position20);
2684 QPoint globalposition27 = view.viewport()->mapToGlobal(position27);
2686 ic.sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>()));
2688 QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
2689 QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick);
2690 QCOMPARE(ic.eventPosition, position2);
2691 QCOMPARE(ic.eventGlobalPosition, globalPosition2);
2692 QCOMPARE(ic.eventButton, Qt::LeftButton);
2693 QCOMPARE(ic.eventModifiers, Qt::NoModifier);
2694 QVERIFY(ic.cursor < 0);
2695 ic.eventType = QEvent::None;
2697 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
2698 QCOMPARE(ic.eventType, QEvent::MouseButtonPress);
2699 QCOMPARE(ic.eventPosition, position2);
2700 QCOMPARE(ic.eventGlobalPosition, globalPosition2);
2701 QCOMPARE(ic.eventButton, Qt::LeftButton);
2702 QCOMPARE(ic.eventModifiers, Qt::NoModifier);
2703 QVERIFY(ic.cursor < 0);
2704 ic.eventType = QEvent::None;
2706 { QMouseEvent mv(QEvent::MouseMove, position8, globalposition8, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
2707 QApplication::sendEvent(view.viewport(), &mv); }
2708 QCOMPARE(ic.eventType, QEvent::None);
2710 { QMouseEvent mv(QEvent::MouseMove, position27, globalposition27, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
2711 QApplication::sendEvent(view.viewport(), &mv); }
2712 QCOMPARE(ic.eventType, QEvent::MouseMove);
2713 QCOMPARE(ic.eventPosition, position27);
2714 QCOMPARE(ic.eventGlobalPosition, globalposition27);
2715 QCOMPARE(ic.eventButton, Qt::LeftButton);
2716 QCOMPARE(ic.eventModifiers, Qt::NoModifier);
2717 QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); // 15 is expected but some platforms may be off by one.
2718 ic.eventType = QEvent::None;
2720 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position27);
2721 QCOMPARE(ic.eventType, QEvent::MouseButtonRelease);
2722 QCOMPARE(ic.eventPosition, position27);
2723 QCOMPARE(ic.eventGlobalPosition, globalposition27);
2724 QCOMPARE(ic.eventButton, Qt::LeftButton);
2725 QCOMPARE(ic.eventModifiers, Qt::NoModifier);
2726 QVERIFY(ic.cursor >= 14 && ic.cursor <= 16);
2727 ic.eventType = QEvent::None;
2729 // And in the other direction.
2730 QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, position27);
2731 QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick);
2732 QCOMPARE(ic.eventPosition, position27);
2733 QCOMPARE(ic.eventGlobalPosition, globalposition27);
2734 QCOMPARE(ic.eventButton, Qt::LeftButton);
2735 QCOMPARE(ic.eventModifiers, Qt::ControlModifier);
2736 QVERIFY(ic.cursor >= 14 && ic.cursor <= 16);
2737 ic.eventType = QEvent::None;
2739 QTest::mousePress(view.viewport(), Qt::RightButton, Qt::ControlModifier, position27);
2740 QCOMPARE(ic.eventType, QEvent::MouseButtonPress);
2741 QCOMPARE(ic.eventPosition, position27);
2742 QCOMPARE(ic.eventGlobalPosition, globalposition27);
2743 QCOMPARE(ic.eventButton, Qt::RightButton);
2744 QCOMPARE(ic.eventModifiers, Qt::ControlModifier);
2745 QVERIFY(ic.cursor >= 14 && ic.cursor <= 16);
2746 ic.eventType = QEvent::None;
2748 { QMouseEvent mv(QEvent::MouseMove, position20, globalposition20, Qt::RightButton, Qt::RightButton,Qt::ControlModifier);
2749 QApplication::sendEvent(view.viewport(), &mv); }
2750 QCOMPARE(ic.eventType, QEvent::MouseMove);
2751 QCOMPARE(ic.eventPosition, position20);
2752 QCOMPARE(ic.eventGlobalPosition, globalposition20);
2753 QCOMPARE(ic.eventButton, Qt::RightButton);
2754 QCOMPARE(ic.eventModifiers, Qt::ControlModifier);
2755 QVERIFY(ic.cursor >= 7 && ic.cursor <= 9);
2756 ic.eventType = QEvent::None;
2758 { QMouseEvent mv(QEvent::MouseMove, position2, globalPosition2, Qt::RightButton, Qt::RightButton,Qt::ControlModifier);
2759 QApplication::sendEvent(view.viewport(), &mv); }
2760 QCOMPARE(ic.eventType, QEvent::None);
2762 QTest::mouseRelease(view.viewport(), Qt::RightButton, Qt::ControlModifier, position2);
2763 QCOMPARE(ic.eventType, QEvent::MouseButtonRelease);
2764 QCOMPARE(ic.eventPosition, position2);
2765 QCOMPARE(ic.eventGlobalPosition, globalPosition2);
2766 QCOMPARE(ic.eventButton, Qt::RightButton);
2767 QCOMPARE(ic.eventModifiers, Qt::ControlModifier);
2768 QVERIFY(ic.cursor < 0);
2769 ic.eventType = QEvent::None;
2772 void tst_qdeclarativetextinput::inputMethodComposing()
2774 QString text = "supercalifragisiticexpialidocious!";
2776 QGraphicsScene scene;
2777 QGraphicsView view(&scene);
2779 view.setInputContext(&ic);
2780 QDeclarative1TextInput input;
2781 input.setWidth(200);
2782 input.setText(text.mid(0, 12));
2783 input.setCursorPosition(12);
2785 input.setFocus(true);
2786 scene.addItem(&input);
2788 QApplication::setActiveWindow(&view);
2789 QTest::qWaitForWindowShown(&view);
2790 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2792 QSignalSpy spy(&input, SIGNAL(inputMethodComposingChanged()));
2794 QCOMPARE(input.isInputMethodComposing(), false);
2796 ic.sendEvent(QInputMethodEvent(text.mid(3), QList<QInputMethodEvent::Attribute>()));
2797 QCOMPARE(input.isInputMethodComposing(), true);
2798 QCOMPARE(spy.count(), 1);
2800 ic.sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>()));
2801 QCOMPARE(input.isInputMethodComposing(), true);
2802 QCOMPARE(spy.count(), 1);
2804 ic.sendEvent(QInputMethodEvent());
2805 QCOMPARE(input.isInputMethodComposing(), false);
2806 QCOMPARE(spy.count(), 2);
2809 void tst_qdeclarativetextinput::cursorRectangleSize()
2811 QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml");
2812 QVERIFY(canvas->rootObject() != 0);
2815 QApplication::setActiveWindow(canvas);
2816 QTest::qWaitForWindowShown(canvas);
2818 QDeclarative1TextInput *textInput = qobject_cast<QDeclarative1TextInput *>(canvas->rootObject());
2819 QVERIFY(textInput != 0);
2820 textInput->setFocus(Qt::OtherFocusReason);
2821 QRectF cursorRect = textInput->positionToRectangle(textInput->cursorPosition());
2822 QRectF microFocusFromScene = canvas->scene()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
2823 QRectF microFocusFromApp= QApplication::focusWidget()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
2825 QCOMPARE(microFocusFromScene.size(), cursorRect.size());
2826 QCOMPARE(microFocusFromApp.size(), cursorRect.size());
2829 QTEST_MAIN(tst_qdeclarativetextinput)
2831 #include "tst_qdeclarativetextinput.moc"