1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtTest/QSignalSpy>
43 #include "../../shared/testhttpserver.h"
46 #include <QTextDocument>
47 #include <QtDeclarative/qdeclarativeengine.h>
48 #include <QtDeclarative/qdeclarativecontext.h>
49 #include <QtDeclarative/qdeclarativeexpression.h>
50 #include <QtDeclarative/qdeclarativecomponent.h>
51 #include <QtQuick1/private/qdeclarativetextedit_p.h>
52 #include <QtQuick1/private/qdeclarativetextedit_p_p.h>
53 #include <QFontMetrics>
54 #include <QtQuick1/QDeclarativeView>
59 #include <private/qapplication_p.h>
60 #include <private/qwidgettextcontrol_p.h>
61 #include <private/qinputpanel_p.h>
62 #include "../../shared/platforminputcontext.h"
65 Q_DECLARE_METATYPE(QDeclarative1TextEdit::SelectionMode)
67 QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
69 // XXX This will be replaced by some clever persistent platform image store.
70 QString persistent_dir = SRCDIR "/data";
71 QString arch = "unknown-architecture"; // QTest needs to help with this.
73 QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png";
75 if (!QFile::exists(expectfile)) {
76 actual.save(expectfile);
77 qWarning() << "created" << expectfile;
83 void sendPreeditText(const QString &text, int cursor)
85 QList<QInputMethodEvent::Attribute> attributes;
86 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursor,
87 text.length(), QVariant()));
88 QInputMethodEvent event(text, attributes);
89 QApplication::sendEvent(qApp->inputPanel()->inputItem(), &event);
93 class tst_qdeclarativetextedit : public QObject
98 tst_qdeclarativetextedit();
108 void alignments_data();
110 // ### these tests may be trivial
112 void hAlign_RightToLeft();
117 void persistentSelection();
120 void isRightToLeft_data();
121 void isRightToLeft();
123 void moveCursorSelection_data();
124 void moveCursorSelection();
125 void moveCursorSelectionSequence_data();
126 void moveCursorSelectionSequence();
127 void mouseSelection_data();
128 void mouseSelection();
129 void multilineMouseSelection();
130 void deferEnableSelectByMouse_data();
131 void deferEnableSelectByMouse();
132 void deferDisableSelectByMouse_data();
133 void deferDisableSelectByMouse();
134 void mouseSelectionMode_data();
135 void mouseSelectionMode();
136 void dragMouseSelection();
137 void inputMethodHints();
141 void cursorDelegate();
142 void cursorVisible();
143 void delegateLoading_data();
144 void delegateLoading();
149 void canPasteEmpty();
151 void openInputPanelOnClick();
152 void openInputPanelOnFocus();
153 void geometrySignals();
154 void pastingRichText_QTBUG_14003();
155 void implicitSize_data();
157 void testQtQuick11Attributes();
158 void testQtQuick11Attributes_data();
160 void preeditMicroFocus();
161 void inputContextMouseHandler();
162 void inputMethodComposing();
163 void cursorRectangleSize();
166 void simulateKey(QDeclarativeView *, int key, Qt::KeyboardModifiers modifiers = 0);
167 QDeclarativeView *createView(const QString &filename);
169 QStringList standard;
170 QStringList richText;
172 QStringList hAlignmentStrings;
173 QStringList vAlignmentStrings;
175 QList<Qt::Alignment> vAlignments;
176 QList<Qt::Alignment> hAlignments;
178 QStringList colorStrings;
180 QDeclarativeEngine engine;
183 tst_qdeclarativetextedit::tst_qdeclarativetextedit()
185 standard << "the quick brown fox jumped over the lazy dog"
186 << "the quick brown fox\n jumped over the lazy dog"
190 richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
191 << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
193 hAlignmentStrings << "AlignLeft"
197 vAlignmentStrings << "AlignTop"
201 hAlignments << Qt::AlignLeft
205 vAlignments << Qt::AlignTop
209 colorStrings << "aliceblue"
222 // need a different test to do alpha channel test
228 void tst_qdeclarativetextedit::cleanup()
230 // ensure not even skipped tests with custom input context leave it dangling
231 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
232 inputPanelPrivate->testContext = 0;
235 void tst_qdeclarativetextedit::text()
238 QDeclarativeComponent texteditComponent(&engine);
239 texteditComponent.setData("import QtQuick 1.0\nTextEdit { text: \"\" }", QUrl());
240 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
242 QVERIFY(textEditObject != 0);
243 QCOMPARE(textEditObject->text(), QString(""));
246 for (int i = 0; i < standard.size(); i++)
248 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"" + standard.at(i) + "\" }";
249 QDeclarativeComponent texteditComponent(&engine);
250 texteditComponent.setData(componentStr.toLatin1(), QUrl());
251 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
253 QVERIFY(textEditObject != 0);
254 QCOMPARE(textEditObject->text(), standard.at(i));
257 for (int i = 0; i < richText.size(); i++)
259 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"" + richText.at(i) + "\" }";
260 QDeclarativeComponent texteditComponent(&engine);
261 texteditComponent.setData(componentStr.toLatin1(), QUrl());
262 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
264 QVERIFY(textEditObject != 0);
265 QString actual = textEditObject->text();
266 QString expected = richText.at(i);
267 actual.replace(QRegExp(".*<body[^>]*>"),"");
268 actual.replace(QRegExp("(<[^>]*>)+"),"<>");
269 expected.replace(QRegExp("(<[^>]*>)+"),"<>");
270 QCOMPARE(actual.simplified(),expected.simplified());
274 void tst_qdeclarativetextedit::width()
276 // uses Font metrics to find the width for standard and document to find the width for rich
278 QDeclarativeComponent texteditComponent(&engine);
279 texteditComponent.setData("import QtQuick 1.0\nTextEdit { text: \"\" }", QUrl());
280 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
282 QVERIFY(textEditObject != 0);
283 QCOMPARE(textEditObject->width(), 0.0);
286 for (int i = 0; i < standard.size(); i++)
290 qreal metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
291 metricWidth = ceil(metricWidth);
293 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"" + standard.at(i) + "\" }";
294 QDeclarativeComponent texteditComponent(&engine);
295 texteditComponent.setData(componentStr.toLatin1(), QUrl());
296 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
298 QVERIFY(textEditObject != 0);
299 QCOMPARE(textEditObject->width(), qreal(metricWidth));
302 for (int i = 0; i < richText.size(); i++)
304 QTextDocument document;
305 document.setHtml(richText.at(i));
306 document.setDocumentMargin(0);
308 int documentWidth = ceil(document.idealWidth());
310 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"" + richText.at(i) + "\" }";
311 QDeclarativeComponent texteditComponent(&engine);
312 texteditComponent.setData(componentStr.toLatin1(), QUrl());
313 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
315 QVERIFY(textEditObject != 0);
316 QCOMPARE(textEditObject->width(), qreal(documentWidth));
320 void tst_qdeclarativetextedit::wrap()
322 // for specified width and wrap set true
324 QDeclarativeComponent texteditComponent(&engine);
325 texteditComponent.setData("import QtQuick 1.0\nTextEdit { text: \"\"; wrapMode: TextEdit.WordWrap; width: 300 }", QUrl());
326 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
328 QVERIFY(textEditObject != 0);
329 QCOMPARE(textEditObject->width(), 300.);
332 for (int i = 0; i < standard.size(); i++)
334 QString componentStr = "import QtQuick 1.0\nTextEdit { wrapMode: TextEdit.WordWrap; width: 300; text: \"" + standard.at(i) + "\" }";
335 QDeclarativeComponent texteditComponent(&engine);
336 texteditComponent.setData(componentStr.toLatin1(), QUrl());
337 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
339 QVERIFY(textEditObject != 0);
340 QCOMPARE(textEditObject->width(), 300.);
343 for (int i = 0; i < richText.size(); i++)
345 QString componentStr = "import QtQuick 1.0\nTextEdit { wrapMode: TextEdit.WordWrap; width: 300; text: \"" + richText.at(i) + "\" }";
346 QDeclarativeComponent texteditComponent(&engine);
347 texteditComponent.setData(componentStr.toLatin1(), QUrl());
348 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
350 QVERIFY(textEditObject != 0);
351 QCOMPARE(textEditObject->width(), 300.);
356 void tst_qdeclarativetextedit::textFormat()
359 QDeclarativeComponent textComponent(&engine);
360 textComponent.setData("import QtQuick 1.0\nTextEdit { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
361 QDeclarative1TextEdit *textObject = qobject_cast<QDeclarative1TextEdit*>(textComponent.create());
363 QVERIFY(textObject != 0);
364 QVERIFY(textObject->textFormat() == QDeclarative1TextEdit::RichText);
367 QDeclarativeComponent textComponent(&engine);
368 textComponent.setData("import QtQuick 1.0\nTextEdit { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
369 QDeclarative1TextEdit *textObject = qobject_cast<QDeclarative1TextEdit*>(textComponent.create());
371 QVERIFY(textObject != 0);
372 QVERIFY(textObject->textFormat() == QDeclarative1TextEdit::PlainText);
376 void tst_qdeclarativetextedit::alignments_data()
378 QTest::addColumn<int>("hAlign");
379 QTest::addColumn<int>("vAlign");
380 QTest::addColumn<QString>("expectfile");
382 QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << "alignments_lt";
383 QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << "alignments_rt";
384 QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << "alignments_ct";
386 QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << "alignments_lb";
387 QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << "alignments_rb";
388 QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << "alignments_cb";
390 QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << "alignments_lc";
391 QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << "alignments_rc";
392 QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << "alignments_cc";
396 void tst_qdeclarativetextedit::alignments()
400 QFETCH(QString, expectfile);
402 QDeclarativeView *canvas = createView(SRCDIR "/data/alignments.qml");
405 QApplication::setActiveWindow(canvas);
406 QTest::qWaitForWindowShown(canvas);
407 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
409 QObject *ob = canvas->rootObject();
411 ob->setProperty("horizontalAlignment",hAlign);
412 ob->setProperty("verticalAlignment",vAlign);
413 QTRY_COMPARE(ob->property("running").toBool(),false);
414 QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32);
415 actual.fill(qRgb(255,255,255));
419 expectfile = createExpectedFileIfNotFound(expectfile, actual);
421 QImage expect(expectfile);
423 QCOMPARE(actual,expect);
429 //the alignment tests may be trivial o.oa
430 void tst_qdeclarativetextedit::hAlign()
432 //test one align each, and then test if two align fails.
434 for (int i = 0; i < standard.size(); i++)
436 for (int j=0; j < hAlignmentStrings.size(); j++)
438 QString componentStr = "import QtQuick 1.0\nTextEdit { horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
439 QDeclarativeComponent texteditComponent(&engine);
440 texteditComponent.setData(componentStr.toLatin1(), QUrl());
441 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
443 QVERIFY(textEditObject != 0);
444 QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
448 for (int i = 0; i < richText.size(); i++)
450 for (int j=0; j < hAlignmentStrings.size(); j++)
452 QString componentStr = "import QtQuick 1.0\nTextEdit { horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
453 QDeclarativeComponent texteditComponent(&engine);
454 texteditComponent.setData(componentStr.toLatin1(), QUrl());
455 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
457 QVERIFY(textEditObject != 0);
458 QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
464 void tst_qdeclarativetextedit::hAlign_RightToLeft()
466 QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml");
467 QDeclarative1TextEdit *textEdit = canvas->rootObject()->findChild<QDeclarative1TextEdit*>("text");
468 QVERIFY(textEdit != 0);
471 const QString rtlText = textEdit->text();
473 // implicit alignment should follow the reading direction of text
474 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
475 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
477 // explicitly left aligned
478 textEdit->setHAlign(QDeclarative1TextEdit::AlignLeft);
479 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignLeft);
480 QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2);
482 // explicitly right aligned
483 textEdit->setHAlign(QDeclarative1TextEdit::AlignRight);
484 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
485 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
487 QString textString = textEdit->text();
488 textEdit->setText(QString("<i>") + textString + QString("</i>"));
489 textEdit->resetHAlign();
491 // implicitly aligned rich text should follow the reading direction of RTL text
492 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
493 QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
494 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
496 // explicitly left aligned rich text
497 textEdit->setHAlign(QDeclarative1TextEdit::AlignLeft);
498 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignLeft);
499 QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
500 QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2);
502 // explicitly right aligned rich text
503 textEdit->setHAlign(QDeclarative1TextEdit::AlignRight);
504 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
505 QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
506 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
508 textEdit->setText(textString);
510 // explicitly center aligned
511 textEdit->setHAlign(QDeclarative1TextEdit::AlignHCenter);
512 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignHCenter);
513 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
515 // reseted alignment should go back to following the text reading direction
516 textEdit->resetHAlign();
517 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
518 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
520 // mirror the text item
521 QDeclarativeItemPrivate::get(textEdit)->setLayoutMirror(true);
523 // mirrored implicit alignment should continue to follow the reading direction of the text
524 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
525 QCOMPARE(textEdit->effectiveHAlign(), QDeclarative1TextEdit::AlignRight);
526 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
528 // mirrored explicitly right aligned behaves as left aligned
529 textEdit->setHAlign(QDeclarative1TextEdit::AlignRight);
530 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
531 QCOMPARE(textEdit->effectiveHAlign(), QDeclarative1TextEdit::AlignLeft);
532 QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2);
534 // mirrored explicitly left aligned behaves as right aligned
535 textEdit->setHAlign(QDeclarative1TextEdit::AlignLeft);
536 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignLeft);
537 QCOMPARE(textEdit->effectiveHAlign(), QDeclarative1TextEdit::AlignRight);
538 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
541 QDeclarativeItemPrivate::get(textEdit)->setLayoutMirror(false);
542 textEdit->resetHAlign();
544 // English text should be implicitly left aligned
545 textEdit->setText("Hello world!");
546 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignLeft);
547 QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2);
549 QApplication::setActiveWindow(canvas);
550 QTest::qWaitForWindowShown(canvas);
551 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
553 textEdit->setText(QString());
554 { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(canvas, &ev); }
555 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
556 { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(canvas, &ev); }
557 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignLeft);
559 #ifndef Q_OS_MAC // QTBUG-18040
560 // empty text with implicit alignment follows the system locale-based
561 // keyboard input direction from QInputPanel::inputDirection
562 textEdit->setText("");
563 QCOMPARE(textEdit->hAlign(), qApp->inputPanel()->inputDirection() == Qt::LeftToRight ?
564 QDeclarative1TextEdit::AlignLeft : QDeclarative1TextEdit::AlignRight);
565 if (qApp->inputPanel()->inputDirection() == Qt::LeftToRight)
566 QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2);
568 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
569 textEdit->setHAlign(QDeclarative1TextEdit::AlignRight);
570 QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
571 QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
576 #ifndef Q_OS_MAC // QTBUG-18040
577 // alignment of TextEdit with no text set to it
578 QString componentStr = "import QtQuick 1.0\nTextEdit {}";
579 QDeclarativeComponent textComponent(&engine);
580 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
581 QDeclarative1TextEdit *textObject = qobject_cast<QDeclarative1TextEdit*>(textComponent.create());
582 QCOMPARE(textObject->hAlign(), qApp->inputPanel()->inputDirection() == Qt::LeftToRight ?
583 QDeclarative1TextEdit::AlignLeft : QDeclarative1TextEdit::AlignRight);
588 void tst_qdeclarativetextedit::vAlign()
590 //test one align each, and then test if two align fails.
592 for (int i = 0; i < standard.size(); i++)
594 for (int j=0; j < vAlignmentStrings.size(); j++)
596 QString componentStr = "import QtQuick 1.0\nTextEdit { verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
597 QDeclarativeComponent texteditComponent(&engine);
598 texteditComponent.setData(componentStr.toLatin1(), QUrl());
599 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
601 QVERIFY(textEditObject != 0);
602 QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
606 for (int i = 0; i < richText.size(); i++)
608 for (int j=0; j < vAlignmentStrings.size(); j++)
610 QString componentStr = "import QtQuick 1.0\nTextEdit { verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
611 QDeclarativeComponent texteditComponent(&engine);
612 texteditComponent.setData(componentStr.toLatin1(), QUrl());
613 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
615 QVERIFY(textEditObject != 0);
616 QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
622 void tst_qdeclarativetextedit::font()
624 //test size, then bold, then italic, then family
626 QString componentStr = "import QtQuick 1.0\nTextEdit { font.pointSize: 40; text: \"Hello World\" }";
627 QDeclarativeComponent texteditComponent(&engine);
628 texteditComponent.setData(componentStr.toLatin1(), QUrl());
629 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
631 QVERIFY(textEditObject != 0);
632 QCOMPARE(textEditObject->font().pointSize(), 40);
633 QCOMPARE(textEditObject->font().bold(), false);
634 QCOMPARE(textEditObject->font().italic(), false);
638 QString componentStr = "import QtQuick 1.0\nTextEdit { font.bold: true; text: \"Hello World\" }";
639 QDeclarativeComponent texteditComponent(&engine);
640 texteditComponent.setData(componentStr.toLatin1(), QUrl());
641 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
643 QVERIFY(textEditObject != 0);
644 QCOMPARE(textEditObject->font().bold(), true);
645 QCOMPARE(textEditObject->font().italic(), false);
649 QString componentStr = "import QtQuick 1.0\nTextEdit { font.italic: true; text: \"Hello World\" }";
650 QDeclarativeComponent texteditComponent(&engine);
651 texteditComponent.setData(componentStr.toLatin1(), QUrl());
652 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
654 QVERIFY(textEditObject != 0);
655 QCOMPARE(textEditObject->font().italic(), true);
656 QCOMPARE(textEditObject->font().bold(), false);
660 QString componentStr = "import QtQuick 1.0\nTextEdit { font.family: \"Helvetica\"; text: \"Hello World\" }";
661 QDeclarativeComponent texteditComponent(&engine);
662 texteditComponent.setData(componentStr.toLatin1(), QUrl());
663 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
665 QVERIFY(textEditObject != 0);
666 QCOMPARE(textEditObject->font().family(), QString("Helvetica"));
667 QCOMPARE(textEditObject->font().bold(), false);
668 QCOMPARE(textEditObject->font().italic(), false);
672 QString componentStr = "import QtQuick 1.0\nTextEdit { font.family: \"\"; text: \"Hello World\" }";
673 QDeclarativeComponent texteditComponent(&engine);
674 texteditComponent.setData(componentStr.toLatin1(), QUrl());
675 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
677 QVERIFY(textEditObject != 0);
678 QCOMPARE(textEditObject->font().family(), QString(""));
682 void tst_qdeclarativetextedit::color()
686 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"Hello World\" }";
687 QDeclarativeComponent texteditComponent(&engine);
688 texteditComponent.setData(componentStr.toLatin1(), QUrl());
689 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
691 QDeclarative1TextEditPrivate *textEditPrivate = static_cast<QDeclarative1TextEditPrivate*>(QDeclarativeItemPrivate::get(textEditObject));
693 QVERIFY(textEditObject);
694 QVERIFY(textEditPrivate);
695 QVERIFY(textEditPrivate->control);
697 QPalette pal = textEditPrivate->control->palette();
698 QCOMPARE(textEditPrivate->color, QColor("black"));
699 QCOMPARE(textEditPrivate->color, pal.color(QPalette::Text));
702 for (int i = 0; i < colorStrings.size(); i++)
704 QString componentStr = "import QtQuick 1.0\nTextEdit { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
705 QDeclarativeComponent texteditComponent(&engine);
706 texteditComponent.setData(componentStr.toLatin1(), QUrl());
707 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
708 //qDebug() << "textEditObject: " << textEditObject->color() << "vs. " << QColor(colorStrings.at(i));
709 QVERIFY(textEditObject != 0);
710 QCOMPARE(textEditObject->color(), QColor(colorStrings.at(i)));
714 for (int i = 0; i < colorStrings.size(); i++)
716 QString componentStr = "import QtQuick 1.0\nTextEdit { selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
717 QDeclarativeComponent texteditComponent(&engine);
718 texteditComponent.setData(componentStr.toLatin1(), QUrl());
719 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
720 QVERIFY(textEditObject != 0);
721 QCOMPARE(textEditObject->selectionColor(), QColor(colorStrings.at(i)));
725 for (int i = 0; i < colorStrings.size(); i++)
727 QString componentStr = "import QtQuick 1.0\nTextEdit { selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
728 QDeclarativeComponent texteditComponent(&engine);
729 texteditComponent.setData(componentStr.toLatin1(), QUrl());
730 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
731 QVERIFY(textEditObject != 0);
732 QCOMPARE(textEditObject->selectedTextColor(), QColor(colorStrings.at(i)));
736 QString colorStr = "#AA001234";
737 QColor testColor("#001234");
738 testColor.setAlpha(170);
740 QString componentStr = "import QtQuick 1.0\nTextEdit { color: \"" + colorStr + "\"; text: \"Hello World\" }";
741 QDeclarativeComponent texteditComponent(&engine);
742 texteditComponent.setData(componentStr.toLatin1(), QUrl());
743 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
745 QVERIFY(textEditObject != 0);
746 QCOMPARE(textEditObject->color(), testColor);
750 void tst_qdeclarativetextedit::textMargin()
752 for(qreal i=0; i<=10; i+=0.3){
753 QString componentStr = "import QtQuick 1.0\nTextEdit { textMargin: " + QString::number(i) + "; text: \"Hello World\" }";
754 QDeclarativeComponent texteditComponent(&engine);
755 texteditComponent.setData(componentStr.toLatin1(), QUrl());
756 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
757 QVERIFY(textEditObject != 0);
758 QCOMPARE(textEditObject->textMargin(), i);
762 void tst_qdeclarativetextedit::persistentSelection()
765 QString componentStr = "import QtQuick 1.0\nTextEdit { persistentSelection: true; text: \"Hello World\" }";
766 QDeclarativeComponent texteditComponent(&engine);
767 texteditComponent.setData(componentStr.toLatin1(), QUrl());
768 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
769 QVERIFY(textEditObject != 0);
770 QCOMPARE(textEditObject->persistentSelection(), true);
774 QString componentStr = "import QtQuick 1.0\nTextEdit { persistentSelection: false; text: \"Hello World\" }";
775 QDeclarativeComponent texteditComponent(&engine);
776 texteditComponent.setData(componentStr.toLatin1(), QUrl());
777 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
778 QVERIFY(textEditObject != 0);
779 QCOMPARE(textEditObject->persistentSelection(), false);
783 void tst_qdeclarativetextedit::focusOnPress()
786 QString componentStr = "import QtQuick 1.0\nTextEdit { activeFocusOnPress: true; text: \"Hello World\" }";
787 QDeclarativeComponent texteditComponent(&engine);
788 texteditComponent.setData(componentStr.toLatin1(), QUrl());
789 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
790 QVERIFY(textEditObject != 0);
791 QCOMPARE(textEditObject->focusOnPress(), true);
795 QString componentStr = "import QtQuick 1.0\nTextEdit { activeFocusOnPress: false; text: \"Hello World\" }";
796 QDeclarativeComponent texteditComponent(&engine);
797 texteditComponent.setData(componentStr.toLatin1(), QUrl());
798 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
799 QVERIFY(textEditObject != 0);
800 QCOMPARE(textEditObject->focusOnPress(), false);
804 void tst_qdeclarativetextedit::selection()
806 QString testStr = standard[0];//TODO: What should happen for multiline/rich text?
807 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \""+ testStr +"\"; }";
808 QDeclarativeComponent texteditComponent(&engine);
809 texteditComponent.setData(componentStr.toLatin1(), QUrl());
810 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
811 QVERIFY(textEditObject != 0);
814 //Test selection follows cursor
815 for(int i=0; i<= testStr.size(); i++) {
816 textEditObject->setCursorPosition(i);
817 QCOMPARE(textEditObject->cursorPosition(), i);
818 QCOMPARE(textEditObject->selectionStart(), i);
819 QCOMPARE(textEditObject->selectionEnd(), i);
820 QVERIFY(textEditObject->selectedText().isNull());
822 //Test cursor follows selection
823 for(int i=0; i<= testStr.size(); i++) {
824 textEditObject->select(i,i);
825 QCOMPARE(textEditObject->cursorPosition(), i);
826 QCOMPARE(textEditObject->selectionStart(), i);
827 QCOMPARE(textEditObject->selectionEnd(), i);
831 textEditObject->setCursorPosition(0);
832 QVERIFY(textEditObject->cursorPosition() == 0);
833 QVERIFY(textEditObject->selectionStart() == 0);
834 QVERIFY(textEditObject->selectionEnd() == 0);
835 QVERIFY(textEditObject->selectedText().isNull());
837 // Verify invalid positions are ignored.
838 textEditObject->setCursorPosition(-1);
839 QVERIFY(textEditObject->cursorPosition() == 0);
840 QVERIFY(textEditObject->selectionStart() == 0);
841 QVERIFY(textEditObject->selectionEnd() == 0);
842 QVERIFY(textEditObject->selectedText().isNull());
844 textEditObject->setCursorPosition(textEditObject->text().count()+1);
845 QVERIFY(textEditObject->cursorPosition() == 0);
846 QVERIFY(textEditObject->selectionStart() == 0);
847 QVERIFY(textEditObject->selectionEnd() == 0);
848 QVERIFY(textEditObject->selectedText().isNull());
851 for(int i=0; i<= testStr.size(); i++) {
852 textEditObject->select(0,i);
853 QCOMPARE(testStr.mid(0,i), textEditObject->selectedText());
854 QCOMPARE(textEditObject->cursorPosition(), i);
856 for(int i=0; i<= testStr.size(); i++) {
857 textEditObject->select(i,testStr.size());
858 QCOMPARE(testStr.mid(i,testStr.size()-i), textEditObject->selectedText());
859 QCOMPARE(textEditObject->cursorPosition(), testStr.size());
862 textEditObject->setCursorPosition(0);
863 QVERIFY(textEditObject->cursorPosition() == 0);
864 QVERIFY(textEditObject->selectionStart() == 0);
865 QVERIFY(textEditObject->selectionEnd() == 0);
866 QVERIFY(textEditObject->selectedText().isNull());
868 //Test Error Ignoring behaviour
869 textEditObject->setCursorPosition(0);
870 QVERIFY(textEditObject->selectedText().isNull());
871 textEditObject->select(-10,0);
872 QVERIFY(textEditObject->selectedText().isNull());
873 textEditObject->select(100,101);
874 QVERIFY(textEditObject->selectedText().isNull());
875 textEditObject->select(0,-10);
876 QVERIFY(textEditObject->selectedText().isNull());
877 textEditObject->select(0,100);
878 QVERIFY(textEditObject->selectedText().isNull());
879 textEditObject->select(0,10);
880 QVERIFY(textEditObject->selectedText().size() == 10);
881 textEditObject->select(-10,0);
882 QVERIFY(textEditObject->selectedText().size() == 10);
883 textEditObject->select(100,101);
884 QVERIFY(textEditObject->selectedText().size() == 10);
885 textEditObject->select(0,-10);
886 QVERIFY(textEditObject->selectedText().size() == 10);
887 textEditObject->select(0,100);
888 QVERIFY(textEditObject->selectedText().size() == 10);
890 textEditObject->deselect();
891 QVERIFY(textEditObject->selectedText().isNull());
892 textEditObject->select(0,10);
893 QVERIFY(textEditObject->selectedText().size() == 10);
894 textEditObject->deselect();
895 QVERIFY(textEditObject->selectedText().isNull());
898 void tst_qdeclarativetextedit::isRightToLeft_data()
900 QTest::addColumn<QString>("text");
901 QTest::addColumn<bool>("emptyString");
902 QTest::addColumn<bool>("firstCharacter");
903 QTest::addColumn<bool>("lastCharacter");
904 QTest::addColumn<bool>("middleCharacter");
905 QTest::addColumn<bool>("startString");
906 QTest::addColumn<bool>("midString");
907 QTest::addColumn<bool>("endString");
909 const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
910 QTest::newRow("Empty") << "" << false << false << false << false << false << false << false;
911 QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false;
912 QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false;
913 QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true;
914 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;
915 QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false;
918 void tst_qdeclarativetextedit::isRightToLeft()
920 QFETCH(QString, text);
921 QFETCH(bool, emptyString);
922 QFETCH(bool, firstCharacter);
923 QFETCH(bool, lastCharacter);
924 QFETCH(bool, middleCharacter);
925 QFETCH(bool, startString);
926 QFETCH(bool, midString);
927 QFETCH(bool, endString);
929 QDeclarative1TextEdit textEdit;
930 textEdit.setText(text);
932 // first test that the right string is delivered to the QString::isRightToLeft()
933 QCOMPARE(textEdit.isRightToLeft(0,0), text.mid(0,0).isRightToLeft());
934 QCOMPARE(textEdit.isRightToLeft(0,1), text.mid(0,1).isRightToLeft());
935 QCOMPARE(textEdit.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft());
936 QCOMPARE(textEdit.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft());
937 QCOMPARE(textEdit.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft());
938 QCOMPARE(textEdit.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft());
940 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextEdit: isRightToLeft(start, end) called with the end property being smaller than the start.");
941 QCOMPARE(textEdit.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft());
943 // then test that the feature actually works
944 QCOMPARE(textEdit.isRightToLeft(0,0), emptyString);
945 QCOMPARE(textEdit.isRightToLeft(0,1), firstCharacter);
946 QCOMPARE(textEdit.isRightToLeft(text.count()-2, text.count()-1), lastCharacter);
947 QCOMPARE(textEdit.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter);
948 QCOMPARE(textEdit.isRightToLeft(0,text.count()/4), startString);
949 QCOMPARE(textEdit.isRightToLeft(text.count()/4,3*text.count()/4), midString);
951 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextEdit: isRightToLeft(start, end) called with the end property being smaller than the start.");
952 QCOMPARE(textEdit.isRightToLeft(3*text.count()/4,text.count()-1), endString);
955 void tst_qdeclarativetextedit::keySelection()
957 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
959 QApplication::setActiveWindow(canvas);
960 QTest::qWaitForWindowShown(canvas);
961 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
964 QVERIFY(canvas->rootObject() != 0);
966 QDeclarative1TextEdit *input = qobject_cast<QDeclarative1TextEdit *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
969 QTRY_VERIFY(input->hasActiveFocus() == true);
971 QSignalSpy spy(input, SIGNAL(selectionChanged()));
973 simulateKey(canvas, Qt::Key_Right, Qt::ShiftModifier);
974 QVERIFY(input->hasActiveFocus() == true);
975 QCOMPARE(input->selectedText(), QString("a"));
976 QCOMPARE(spy.count(), 1);
977 simulateKey(canvas, Qt::Key_Right);
978 QVERIFY(input->hasActiveFocus() == true);
979 QCOMPARE(input->selectedText(), QString());
980 QCOMPARE(spy.count(), 2);
981 simulateKey(canvas, Qt::Key_Right);
982 QVERIFY(input->hasActiveFocus() == false);
983 QCOMPARE(input->selectedText(), QString());
984 QCOMPARE(spy.count(), 2);
986 simulateKey(canvas, Qt::Key_Left);
987 QVERIFY(input->hasActiveFocus() == true);
988 QCOMPARE(spy.count(), 2);
989 simulateKey(canvas, Qt::Key_Left, Qt::ShiftModifier);
990 QVERIFY(input->hasActiveFocus() == true);
991 QCOMPARE(input->selectedText(), QString("a"));
992 QCOMPARE(spy.count(), 3);
993 simulateKey(canvas, Qt::Key_Left);
994 QVERIFY(input->hasActiveFocus() == true);
995 QCOMPARE(input->selectedText(), QString());
996 QCOMPARE(spy.count(), 4);
997 simulateKey(canvas, Qt::Key_Left);
998 QVERIFY(input->hasActiveFocus() == false);
999 QCOMPARE(input->selectedText(), QString());
1000 QCOMPARE(spy.count(), 4);
1005 void tst_qdeclarativetextedit::moveCursorSelection_data()
1007 QTest::addColumn<QString>("testStr");
1008 QTest::addColumn<int>("cursorPosition");
1009 QTest::addColumn<int>("movePosition");
1010 QTest::addColumn<QDeclarative1TextEdit::SelectionMode>("mode");
1011 QTest::addColumn<int>("selectionStart");
1012 QTest::addColumn<int>("selectionEnd");
1013 QTest::addColumn<bool>("reversible");
1015 QTest::newRow("(t)he|characters")
1016 << standard[0] << 0 << 1 << QDeclarative1TextEdit::SelectCharacters << 0 << 1 << true;
1017 QTest::newRow("do(g)|characters")
1018 << standard[0] << 43 << 44 << QDeclarative1TextEdit::SelectCharacters << 43 << 44 << true;
1019 QTest::newRow("jum(p)ed|characters")
1020 << standard[0] << 23 << 24 << QDeclarative1TextEdit::SelectCharacters << 23 << 24 << true;
1021 QTest::newRow("jumped( )over|characters")
1022 << standard[0] << 26 << 27 << QDeclarative1TextEdit::SelectCharacters << 26 << 27 << true;
1023 QTest::newRow("(the )|characters")
1024 << standard[0] << 0 << 4 << QDeclarative1TextEdit::SelectCharacters << 0 << 4 << true;
1025 QTest::newRow("( dog)|characters")
1026 << standard[0] << 40 << 44 << QDeclarative1TextEdit::SelectCharacters << 40 << 44 << true;
1027 QTest::newRow("( jumped )|characters")
1028 << standard[0] << 19 << 27 << QDeclarative1TextEdit::SelectCharacters << 19 << 27 << true;
1029 QTest::newRow("th(e qu)ick|characters")
1030 << standard[0] << 2 << 6 << QDeclarative1TextEdit::SelectCharacters << 2 << 6 << true;
1031 QTest::newRow("la(zy d)og|characters")
1032 << standard[0] << 38 << 42 << QDeclarative1TextEdit::SelectCharacters << 38 << 42 << true;
1033 QTest::newRow("jum(ped ov)er|characters")
1034 << standard[0] << 23 << 29 << QDeclarative1TextEdit::SelectCharacters << 23 << 29 << true;
1035 QTest::newRow("()the|characters")
1036 << standard[0] << 0 << 0 << QDeclarative1TextEdit::SelectCharacters << 0 << 0 << true;
1037 QTest::newRow("dog()|characters")
1038 << standard[0] << 44 << 44 << QDeclarative1TextEdit::SelectCharacters << 44 << 44 << true;
1039 QTest::newRow("jum()ped|characters")
1040 << standard[0] << 23 << 23 << QDeclarative1TextEdit::SelectCharacters << 23 << 23 << true;
1042 QTest::newRow("<(t)he>|words")
1043 << standard[0] << 0 << 1 << QDeclarative1TextEdit::SelectWords << 0 << 3 << true;
1044 QTest::newRow("<do(g)>|words")
1045 << standard[0] << 43 << 44 << QDeclarative1TextEdit::SelectWords << 41 << 44 << true;
1046 QTest::newRow("<jum(p)ed>|words")
1047 << standard[0] << 23 << 24 << QDeclarative1TextEdit::SelectWords << 20 << 26 << true;
1048 QTest::newRow("<jumped( )>over|words")
1049 << standard[0] << 26 << 27 << QDeclarative1TextEdit::SelectWords << 20 << 27 << false;
1050 QTest::newRow("jumped<( )over>|words,reversed")
1051 << standard[0] << 27 << 26 << QDeclarative1TextEdit::SelectWords << 26 << 31 << false;
1052 QTest::newRow("<(the )>quick|words")
1053 << standard[0] << 0 << 4 << QDeclarative1TextEdit::SelectWords << 0 << 4 << false;
1054 QTest::newRow("<(the )quick>|words,reversed")
1055 << standard[0] << 4 << 0 << QDeclarative1TextEdit::SelectWords << 0 << 9 << false;
1056 QTest::newRow("<lazy( dog)>|words")
1057 << standard[0] << 40 << 44 << QDeclarative1TextEdit::SelectWords << 36 << 44 << false;
1058 QTest::newRow("lazy<( dog)>|words,reversed")
1059 << standard[0] << 44 << 40 << QDeclarative1TextEdit::SelectWords << 40 << 44 << false;
1060 QTest::newRow("<fox( jumped )>over|words")
1061 << standard[0] << 19 << 27 << QDeclarative1TextEdit::SelectWords << 16 << 27 << false;
1062 QTest::newRow("fox<( jumped )over>|words,reversed")
1063 << standard[0] << 27 << 19 << QDeclarative1TextEdit::SelectWords << 19 << 31 << false;
1064 QTest::newRow("<th(e qu)ick>|words")
1065 << standard[0] << 2 << 6 << QDeclarative1TextEdit::SelectWords << 0 << 9 << true;
1066 QTest::newRow("<la(zy d)og|words>")
1067 << standard[0] << 38 << 42 << QDeclarative1TextEdit::SelectWords << 36 << 44 << true;
1068 QTest::newRow("<jum(ped ov)er>|words")
1069 << standard[0] << 23 << 29 << QDeclarative1TextEdit::SelectWords << 20 << 31 << true;
1070 QTest::newRow("<()>the|words")
1071 << standard[0] << 0 << 0 << QDeclarative1TextEdit::SelectWords << 0 << 0 << true;
1072 QTest::newRow("dog<()>|words")
1073 << standard[0] << 44 << 44 << QDeclarative1TextEdit::SelectWords << 44 << 44 << true;
1074 QTest::newRow("jum<()>ped|words")
1075 << standard[0] << 23 << 23 << QDeclarative1TextEdit::SelectWords << 23 << 23 << true;
1077 QTest::newRow("Hello<(,)> |words")
1078 << standard[2] << 5 << 6 << QDeclarative1TextEdit::SelectWords << 5 << 6 << true;
1079 QTest::newRow("Hello<(, )>world|words")
1080 << standard[2] << 5 << 7 << QDeclarative1TextEdit::SelectWords << 5 << 7 << false;
1081 QTest::newRow("Hello<(, )world>|words,reversed")
1082 << standard[2] << 7 << 5 << QDeclarative1TextEdit::SelectWords << 5 << 12 << false;
1083 QTest::newRow("<Hel(lo, )>world|words")
1084 << standard[2] << 3 << 7 << QDeclarative1TextEdit::SelectWords << 0 << 7 << false;
1085 QTest::newRow("<Hel(lo, )world>|words,reversed")
1086 << standard[2] << 7 << 3 << QDeclarative1TextEdit::SelectWords << 0 << 12 << false;
1087 QTest::newRow("<Hel(lo)>,|words")
1088 << standard[2] << 3 << 5 << QDeclarative1TextEdit::SelectWords << 0 << 5 << true;
1089 QTest::newRow("Hello<()>,|words")
1090 << standard[2] << 5 << 5 << QDeclarative1TextEdit::SelectWords << 5 << 5 << true;
1091 QTest::newRow("Hello,<()>|words")
1092 << standard[2] << 6 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 6 << true;
1093 QTest::newRow("Hello<,( )>world|words")
1094 << standard[2] << 6 << 7 << QDeclarative1TextEdit::SelectWords << 5 << 7 << false;
1095 QTest::newRow("Hello,<( )world>|words,reversed")
1096 << standard[2] << 7 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 12 << false;
1097 QTest::newRow("Hello<,( world)>|words")
1098 << standard[2] << 6 << 12 << QDeclarative1TextEdit::SelectWords << 5 << 12 << false;
1099 QTest::newRow("Hello,<( world)>|words,reversed")
1100 << standard[2] << 12 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 12 << false;
1101 QTest::newRow("Hello<,( world!)>|words")
1102 << standard[2] << 6 << 13 << QDeclarative1TextEdit::SelectWords << 5 << 13 << false;
1103 QTest::newRow("Hello,<( world!)>|words,reversed")
1104 << standard[2] << 13 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 13 << false;
1105 QTest::newRow("Hello<(, world!)>|words")
1106 << standard[2] << 5 << 13 << QDeclarative1TextEdit::SelectWords << 5 << 13 << true;
1107 QTest::newRow("world<(!)>|words")
1108 << standard[2] << 12 << 13 << QDeclarative1TextEdit::SelectWords << 12 << 13 << true;
1109 QTest::newRow("world!<()>)|words")
1110 << standard[2] << 13 << 13 << QDeclarative1TextEdit::SelectWords << 13 << 13 << true;
1111 QTest::newRow("world<()>!)|words")
1112 << standard[2] << 12 << 12 << QDeclarative1TextEdit::SelectWords << 12 << 12 << true;
1114 QTest::newRow("<(,)>olleH |words")
1115 << standard[3] << 7 << 8 << QDeclarative1TextEdit::SelectWords << 7 << 8 << true;
1116 QTest::newRow("<dlrow( ,)>olleH|words")
1117 << standard[3] << 6 << 8 << QDeclarative1TextEdit::SelectWords << 1 << 8 << false;
1118 QTest::newRow("dlrow<( ,)>olleH|words,reversed")
1119 << standard[3] << 8 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 8 << false;
1120 QTest::newRow("<dlrow( ,ol)leH>|words")
1121 << standard[3] << 6 << 10 << QDeclarative1TextEdit::SelectWords << 1 << 13 << false;
1122 QTest::newRow("dlrow<( ,ol)leH>|words,reversed")
1123 << standard[3] << 10 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 13 << false;
1124 QTest::newRow(",<(ol)leH>,|words")
1125 << standard[3] << 8 << 10 << QDeclarative1TextEdit::SelectWords << 8 << 13 << true;
1126 QTest::newRow(",<()>olleH|words")
1127 << standard[3] << 8 << 8 << QDeclarative1TextEdit::SelectWords << 8 << 8 << true;
1128 QTest::newRow("<()>,olleH|words")
1129 << standard[3] << 7 << 7 << QDeclarative1TextEdit::SelectWords << 7 << 7 << true;
1130 QTest::newRow("<dlrow( )>,olleH|words")
1131 << standard[3] << 6 << 7 << QDeclarative1TextEdit::SelectWords << 1 << 7 << false;
1132 QTest::newRow("dlrow<( ),>olleH|words,reversed")
1133 << standard[3] << 7 << 6 << QDeclarative1TextEdit::SelectWords << 6 << 8 << false;
1134 QTest::newRow("<(dlrow )>,olleH|words")
1135 << standard[3] << 1 << 7 << QDeclarative1TextEdit::SelectWords << 1 << 7 << false;
1136 QTest::newRow("<(dlrow ),>olleH|words,reversed")
1137 << standard[3] << 7 << 1 << QDeclarative1TextEdit::SelectWords << 1 << 8 << false;
1138 QTest::newRow("<(!dlrow )>,olleH|words")
1139 << standard[3] << 0 << 7 << QDeclarative1TextEdit::SelectWords << 0 << 7 << false;
1140 QTest::newRow("<(!dlrow ),>olleH|words,reversed")
1141 << standard[3] << 7 << 0 << QDeclarative1TextEdit::SelectWords << 0 << 8 << false;
1142 QTest::newRow("(!dlrow ,)olleH|words")
1143 << standard[3] << 0 << 8 << QDeclarative1TextEdit::SelectWords << 0 << 8 << true;
1144 QTest::newRow("<(!)>dlrow|words")
1145 << standard[3] << 0 << 1 << QDeclarative1TextEdit::SelectWords << 0 << 1 << true;
1146 QTest::newRow("<()>!dlrow|words")
1147 << standard[3] << 0 << 0 << QDeclarative1TextEdit::SelectWords << 0 << 0 << true;
1148 QTest::newRow("!<()>dlrow|words")
1149 << standard[3] << 1 << 1 << QDeclarative1TextEdit::SelectWords << 1 << 1 << true;
1152 void tst_qdeclarativetextedit::moveCursorSelection()
1154 QFETCH(QString, testStr);
1155 QFETCH(int, cursorPosition);
1156 QFETCH(int, movePosition);
1157 QFETCH(QDeclarative1TextEdit::SelectionMode, mode);
1158 QFETCH(int, selectionStart);
1159 QFETCH(int, selectionEnd);
1160 QFETCH(bool, reversible);
1162 QString componentStr = "import QtQuick 1.1\nTextEdit { text: \""+ testStr +"\"; }";
1163 QDeclarativeComponent textinputComponent(&engine);
1164 textinputComponent.setData(componentStr.toLatin1(), QUrl());
1165 QDeclarative1TextEdit *texteditObject = qobject_cast<QDeclarative1TextEdit*>(textinputComponent.create());
1166 QVERIFY(texteditObject != 0);
1168 texteditObject->setCursorPosition(cursorPosition);
1169 texteditObject->moveCursorSelection(movePosition, mode);
1171 QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
1172 QCOMPARE(texteditObject->selectionStart(), selectionStart);
1173 QCOMPARE(texteditObject->selectionEnd(), selectionEnd);
1176 texteditObject->setCursorPosition(movePosition);
1177 texteditObject->moveCursorSelection(cursorPosition, mode);
1179 QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
1180 QCOMPARE(texteditObject->selectionStart(), selectionStart);
1181 QCOMPARE(texteditObject->selectionEnd(), selectionEnd);
1185 void tst_qdeclarativetextedit::moveCursorSelectionSequence_data()
1187 QTest::addColumn<QString>("testStr");
1188 QTest::addColumn<int>("cursorPosition");
1189 QTest::addColumn<int>("movePosition1");
1190 QTest::addColumn<int>("movePosition2");
1191 QTest::addColumn<int>("selection1Start");
1192 QTest::addColumn<int>("selection1End");
1193 QTest::addColumn<int>("selection2Start");
1194 QTest::addColumn<int>("selection2End");
1196 QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr")
1201 QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl")
1206 QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr")
1211 QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl")
1216 QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr")
1221 QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl")
1226 QTest::newRow("the {<quick() ^}bro)wn> fox|ltr")
1231 QTest::newRow("the quick<(^ {^bro)wn>} fox|rtl")
1236 QTest::newRow("the {<quick^}( bro)wn> fox|ltr")
1241 QTest::newRow("the quick{<(^ bro)wn>} fox|rtl")
1246 QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr")
1251 QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl")
1256 QTest::newRow("the {<^quick}( bro)wn> fox|ltr")
1261 QTest::newRow("the {<^quick}( bro)wn> fox|rtl")
1266 QTest::newRow("the{^ <quick}( bro)wn> fox|ltr")
1271 QTest::newRow("the{^ <quick}( bro)wn> fox|rtl")
1276 QTest::newRow("{t^he <quick}( bro)wn> fox|ltr")
1281 QTest::newRow("{t^he <quick}( bro)wn> fox|rtl")
1287 QTest::newRow("{<He(ll)o>, w^orld}!|ltr")
1292 QTest::newRow("{<He(ll)o>, w^orld}!|rtl")
1298 QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr")
1303 QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl")
1310 void tst_qdeclarativetextedit::moveCursorSelectionSequence()
1312 QFETCH(QString, testStr);
1313 QFETCH(int, cursorPosition);
1314 QFETCH(int, movePosition1);
1315 QFETCH(int, movePosition2);
1316 QFETCH(int, selection1Start);
1317 QFETCH(int, selection1End);
1318 QFETCH(int, selection2Start);
1319 QFETCH(int, selection2End);
1321 QString componentStr = "import QtQuick 1.1\nTextEdit { text: \""+ testStr +"\"; }";
1322 QDeclarativeComponent texteditComponent(&engine);
1323 texteditComponent.setData(componentStr.toLatin1(), QUrl());
1324 QDeclarative1TextEdit *texteditObject = qobject_cast<QDeclarative1TextEdit*>(texteditComponent.create());
1325 QVERIFY(texteditObject != 0);
1327 texteditObject->setCursorPosition(cursorPosition);
1329 texteditObject->moveCursorSelection(movePosition1, QDeclarative1TextEdit::SelectWords);
1330 QCOMPARE(texteditObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start));
1331 QCOMPARE(texteditObject->selectionStart(), selection1Start);
1332 QCOMPARE(texteditObject->selectionEnd(), selection1End);
1334 texteditObject->moveCursorSelection(movePosition2, QDeclarative1TextEdit::SelectWords);
1335 QCOMPARE(texteditObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start));
1336 QCOMPARE(texteditObject->selectionStart(), selection2Start);
1337 QCOMPARE(texteditObject->selectionEnd(), selection2End);
1341 void tst_qdeclarativetextedit::mouseSelection_data()
1343 QTest::addColumn<QString>("qmlfile");
1344 QTest::addColumn<int>("from");
1345 QTest::addColumn<int>("to");
1346 QTest::addColumn<QString>("selectedText");
1349 QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << 4 << 9 << "45678";
1350 QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << 4 << 9 << QString();
1351 QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << 4 << 9 << QString();
1352 QTest::newRow("off word selection") << SRCDIR "/data/mouseselection_false_words.qml" << 4 << 9 << QString();
1353 QTest::newRow("on word selection (4,9)") << SRCDIR "/data/mouseselection_true_words.qml" << 4 << 9 << "0123456789";
1354 QTest::newRow("on word selection (2,13)") << SRCDIR "/data/mouseselection_true_words.qml" << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1355 QTest::newRow("on word selection (2,30)") << SRCDIR "/data/mouseselection_true_words.qml" << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1356 QTest::newRow("on word selection (9,13)") << SRCDIR "/data/mouseselection_true_words.qml" << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1357 QTest::newRow("on word selection (9,30)") << SRCDIR "/data/mouseselection_true_words.qml" << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1358 QTest::newRow("on word selection (13,2)") << SRCDIR "/data/mouseselection_true_words.qml" << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1359 QTest::newRow("on word selection (20,2)") << SRCDIR "/data/mouseselection_true_words.qml" << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1360 QTest::newRow("on word selection (12,9)") << SRCDIR "/data/mouseselection_true_words.qml" << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1361 QTest::newRow("on word selection (30,9)") << SRCDIR "/data/mouseselection_true_words.qml" << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1364 void tst_qdeclarativetextedit::mouseSelection()
1366 QFETCH(QString, qmlfile);
1369 QFETCH(QString, selectedText);
1371 QDeclarativeView *canvas = createView(qmlfile);
1374 QApplication::setActiveWindow(canvas);
1375 QTest::qWaitForWindowShown(canvas);
1376 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1378 QVERIFY(canvas->rootObject() != 0);
1379 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1380 QVERIFY(textEditObject != 0);
1382 // press-and-drag-and-release from x1 to x2
1383 QPoint p1 = canvas->mapFromScene(textEditObject->positionToRectangle(from).center());
1384 QPoint p2 = canvas->mapFromScene(textEditObject->positionToRectangle(to).center());
1385 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, p1);
1386 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1387 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(p2), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1388 QApplication::sendEvent(canvas->viewport(), &mv);
1389 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, p2);
1390 QCOMPARE(textEditObject->selectedText(), selectedText);
1392 // Clicking and shift to clicking between the same points should select the same text.
1393 textEditObject->setCursorPosition(0);
1394 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::NoModifier, p1);
1395 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::ShiftModifier, p2);
1396 QCOMPARE(textEditObject->selectedText(), selectedText);
1401 void tst_qdeclarativetextedit::multilineMouseSelection()
1403 QDeclarativeView *canvas = createView(SRCDIR "/data/mouseselection_multiline.qml");
1406 QApplication::setActiveWindow(canvas);
1407 QTest::qWaitForWindowShown(canvas);
1408 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1410 QVERIFY(canvas->rootObject() != 0);
1411 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1412 QVERIFY(textEditObject != 0);
1414 // press-and-drag from x1,y1 to x2,y1
1416 int x2 = textEditObject->width() - 10;
1417 int y1 = textEditObject->height() / 4;
1418 int y2 = textEditObject->height() * 3 / 4;
1419 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y1)));
1420 QMouseEvent mv1(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y1)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1421 QApplication::sendEvent(canvas->viewport(), &mv1);
1422 QString str1 = textEditObject->selectedText();
1423 QVERIFY(str1.length() > 3); // don't reallly care *what* was selected (and it's too sensitive to platform)
1425 // drag-and-release from x2,y1 to x2,y2
1426 QMouseEvent mv2(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y2)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1427 QApplication::sendEvent(canvas->viewport(), &mv2);
1428 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y2)));
1429 QString str2 = textEditObject->selectedText();
1430 QVERIFY(str1 != str2);
1431 QVERIFY(str2.length() > 3);
1436 void tst_qdeclarativetextedit::deferEnableSelectByMouse_data()
1438 QTest::addColumn<QString>("qmlfile");
1440 QTest::newRow("writable") << SRCDIR "/data/mouseselection_false.qml";
1441 QTest::newRow("read only") << SRCDIR "/data/mouseselection_false_readonly.qml";
1444 void tst_qdeclarativetextedit::deferEnableSelectByMouse()
1446 // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed.
1447 QFETCH(QString, qmlfile);
1449 QDeclarativeView *canvas = createView(qmlfile);
1452 QApplication::setActiveWindow(canvas);
1453 QTest::qWaitForWindowShown(canvas);
1454 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1456 QVERIFY(canvas->rootObject() != 0);
1457 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1458 QVERIFY(textEditObject != 0);
1460 // press-and-drag-and-release from x1 to x2
1463 int y = textEditObject->height()/2;
1465 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1466 textEditObject->setSelectByMouse(true);
1467 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1468 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1469 QApplication::sendEvent(canvas->viewport(), &mv);
1470 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1471 QVERIFY(textEditObject->selectedText().isEmpty());
1476 void tst_qdeclarativetextedit::deferDisableSelectByMouse_data()
1478 QTest::addColumn<QString>("qmlfile");
1480 QTest::newRow("writable") << SRCDIR "/data/mouseselection_true.qml";
1481 QTest::newRow("read only") << SRCDIR "/data/mouseselection_true_readonly.qml";
1484 void tst_qdeclarativetextedit::deferDisableSelectByMouse()
1486 // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed.
1487 QFETCH(QString, qmlfile);
1489 QDeclarativeView *canvas = createView(qmlfile);
1492 QApplication::setActiveWindow(canvas);
1493 QTest::qWaitForWindowShown(canvas);
1494 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1496 QVERIFY(canvas->rootObject() != 0);
1497 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1498 QVERIFY(textEditObject != 0);
1500 // press-and-drag-and-release from x1 to x2
1503 int y = textEditObject->height()/2;
1505 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1506 textEditObject->setSelectByMouse(false);
1507 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1508 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1509 QApplication::sendEvent(canvas->viewport(), &mv);
1510 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1511 QVERIFY(textEditObject->selectedText().length() > 3);
1516 void tst_qdeclarativetextedit::dragMouseSelection()
1518 QString qmlfile = SRCDIR "/data/mouseselection_true.qml";
1520 QDeclarativeView *canvas = createView(qmlfile);
1523 QApplication::setActiveWindow(canvas);
1524 QTest::qWaitForWindowShown(canvas);
1525 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1527 QVERIFY(canvas->rootObject() != 0);
1528 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1529 QVERIFY(textEditObject != 0);
1531 textEditObject->setAcceptDrops(true);
1533 // press-and-drag-and-release from x1 to x2
1536 int y = textEditObject->height()/2;
1537 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1539 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1540 QApplication::sendEvent(canvas->viewport(), &mv);
1542 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1543 QString str1 = textEditObject->selectedText();
1544 QVERIFY(str1.length() > 3);
1546 // press and drag the current selection.
1549 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1551 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1552 QApplication::sendEvent(canvas->viewport(), &mv);
1554 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1555 QString str2 = textEditObject->selectedText();
1556 QVERIFY(str2.length() > 3);
1558 QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved.
1563 void tst_qdeclarativetextedit::mouseSelectionMode_data()
1565 QTest::addColumn<QString>("qmlfile");
1566 QTest::addColumn<bool>("selectWords");
1569 QTest::newRow("SelectWords") << SRCDIR "/data/mouseselectionmode_words.qml" << true;
1570 QTest::newRow("SelectCharacters") << SRCDIR "/data/mouseselectionmode_characters.qml" << false;
1571 QTest::newRow("default") << SRCDIR "/data/mouseselectionmode_default.qml" << false;
1574 void tst_qdeclarativetextedit::mouseSelectionMode()
1576 QFETCH(QString, qmlfile);
1577 QFETCH(bool, selectWords);
1579 QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1581 QDeclarativeView *canvas = createView(qmlfile);
1584 QApplication::setActiveWindow(canvas);
1585 QTest::qWaitForWindowShown(canvas);
1586 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
1588 QVERIFY(canvas->rootObject() != 0);
1589 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1590 QVERIFY(textEditObject != 0);
1592 // press-and-drag-and-release from x1 to x2
1595 int y = textEditObject->height()/2;
1596 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y)));
1597 //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
1598 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1599 QApplication::sendEvent(canvas->viewport(), &mv);
1600 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y)));
1601 QString str = textEditObject->selectedText();
1603 QCOMPARE(str, text);
1605 QVERIFY(str.length() > 3);
1606 QVERIFY(str != text);
1609 // Clicking and shift to clicking between the same points should select the same text.
1610 textEditObject->setCursorPosition(0);
1611 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::NoModifier, canvas->mapFromScene(QPoint(x1,y)));
1612 QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::ShiftModifier, canvas->mapFromScene(QPoint(x2,y)));
1613 QCOMPARE(textEditObject->selectedText(), str);
1618 void tst_qdeclarativetextedit::inputMethodHints()
1620 QDeclarativeView *canvas = createView(SRCDIR "/data/inputmethodhints.qml");
1624 QVERIFY(canvas->rootObject() != 0);
1625 QDeclarative1TextEdit *textEditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1626 QVERIFY(textEditObject != 0);
1627 QVERIFY(textEditObject->inputMethodHints() & Qt::ImhNoPredictiveText);
1628 textEditObject->setInputMethodHints(Qt::ImhUppercaseOnly);
1629 QVERIFY(textEditObject->inputMethodHints() & Qt::ImhUppercaseOnly);
1634 void tst_qdeclarativetextedit::positionAt()
1636 QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml");
1637 QVERIFY(canvas->rootObject() != 0);
1640 QApplication::setActiveWindow(canvas);
1641 QTest::qWaitForWindowShown(canvas);
1643 QDeclarative1TextEdit *texteditObject = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
1644 QVERIFY(texteditObject != 0);
1646 QTextLayout layout(texteditObject->text());
1647 layout.setFont(texteditObject->font());
1649 layout.beginLayout();
1650 QTextLine line = layout.createLine();
1653 const int y0 = line.height() / 2;
1654 const int y1 = line.height() * 3 / 2;
1656 int pos = texteditObject->positionAt(texteditObject->width()/2, y0);
1658 int widthBegin = floor(line.cursorToX(pos - 1));
1659 int widthEnd = ceil(line.cursorToX(pos + 1));
1661 QVERIFY(widthBegin <= texteditObject->width() / 2);
1662 QVERIFY(widthEnd >= texteditObject->width() / 2);
1664 const qreal x0 = texteditObject->positionToRectangle(pos).x();
1665 const qreal x1 = texteditObject->positionToRectangle(pos + 1).x();
1667 QString preeditText = texteditObject->text().mid(0, pos);
1668 texteditObject->setText(texteditObject->text().mid(pos));
1669 texteditObject->setCursorPosition(0);
1671 QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
1672 QApplication::sendEvent(canvas, &inputEvent);
1674 // Check all points within the preedit text return the same position.
1675 QCOMPARE(texteditObject->positionAt(0, y0), 0);
1676 QCOMPARE(texteditObject->positionAt(x0 / 2, y0), 0);
1677 QCOMPARE(texteditObject->positionAt(x0, y0), 0);
1679 // Verify positioning returns to normal after the preedit text.
1680 QCOMPARE(texteditObject->positionAt(x1, y0), 1);
1681 QCOMPARE(texteditObject->positionToRectangle(1).x(), x1);
1683 QVERIFY(texteditObject->positionAt(x0 / 2, y1) > 0);
1688 void tst_qdeclarativetextedit::cursorDelegate()
1690 QDeclarativeView* view = createView(SRCDIR "/data/cursorTest.qml");
1693 QDeclarative1TextEdit *textEditObject = view->rootObject()->findChild<QDeclarative1TextEdit*>("textEditObject");
1694 QVERIFY(textEditObject != 0);
1695 QVERIFY(textEditObject->findChild<QDeclarativeItem*>("cursorInstance"));
1696 //Test Delegate gets created
1697 textEditObject->setFocus(true);
1698 QDeclarativeItem* delegateObject = textEditObject->findChild<QDeclarativeItem*>("cursorInstance");
1699 QVERIFY(delegateObject);
1700 //Test Delegate gets moved
1701 for(int i=0; i<= textEditObject->text().length(); i++){
1702 textEditObject->setCursorPosition(i);
1703 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1704 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1706 const QString preedit = "preedit";
1707 for (int i = 0; i <= preedit.length(); i++) {
1708 QInputMethodEvent event(preedit, QList<QInputMethodEvent::Attribute>()
1709 << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, 1, QVariant()));
1710 QApplication::sendEvent(view, &event);
1712 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1713 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1715 // Clear preedit text;
1716 QInputMethodEvent event;
1717 QApplication::sendEvent(view, &event);
1720 // Test delegate gets moved on mouse press.
1721 textEditObject->setSelectByMouse(true);
1722 textEditObject->setCursorPosition(0);
1723 const QPoint point1 = view->mapFromScene(textEditObject->positionToRectangle(5).center());
1724 QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, point1);
1725 QVERIFY(textEditObject->cursorPosition() != 0);
1726 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1727 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1729 // Test delegate gets moved on mouse drag
1730 textEditObject->setCursorPosition(0);
1731 const QPoint point2 = view->mapFromScene(textEditObject->positionToRectangle(10).center());
1732 QTest::mousePress(view->viewport(), Qt::LeftButton, 0, point1);
1733 QMouseEvent mv(QEvent::MouseMove, point2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1734 QApplication::sendEvent(view->viewport(), &mv);
1735 QTest::mouseRelease(view->viewport(), Qt::LeftButton, 0, point2);
1736 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1737 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1739 textEditObject->setReadOnly(true);
1740 textEditObject->setCursorPosition(0);
1741 QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(textEditObject->positionToRectangle(5).center()));
1742 QVERIFY(textEditObject->cursorPosition() != 0);
1743 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1744 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1746 textEditObject->setCursorPosition(0);
1747 QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(textEditObject->positionToRectangle(5).center()));
1748 QVERIFY(textEditObject->cursorPosition() != 0);
1749 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1750 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1752 textEditObject->setCursorPosition(0);
1753 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1754 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1755 QVERIFY(textEditObject->cursorRectangle().y() >= 0);
1756 QVERIFY(textEditObject->cursorRectangle().y() < textEditObject->cursorRectangle().height());
1757 textEditObject->setVAlign(QDeclarative1TextEdit::AlignVCenter);
1758 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1759 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1760 QVERIFY(textEditObject->cursorRectangle().y() > (textEditObject->height() / 2) - textEditObject->cursorRectangle().height());
1761 QVERIFY(textEditObject->cursorRectangle().y() < (textEditObject->height() / 2) + textEditObject->cursorRectangle().height());
1762 textEditObject->setVAlign(QDeclarative1TextEdit::AlignBottom);
1763 QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
1764 QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
1765 QVERIFY(textEditObject->cursorRectangle().y() > textEditObject->height() - (textEditObject->cursorRectangle().height() * 2));
1766 QVERIFY(textEditObject->cursorRectangle().y() < textEditObject->height());
1768 //Test Delegate gets deleted
1769 textEditObject->setCursorDelegate(0);
1770 QVERIFY(!textEditObject->findChild<QDeclarativeItem*>("cursorInstance"));
1775 void tst_qdeclarativetextedit::cursorVisible()
1777 QGraphicsScene scene;
1778 QGraphicsView view(&scene);
1780 QApplication::setActiveWindow(&view);
1781 QTest::qWaitForWindowShown(&view);
1782 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
1785 QDeclarative1TextEdit edit;
1786 QSignalSpy spy(&edit, SIGNAL(cursorVisibleChanged(bool)));
1788 QCOMPARE(edit.isCursorVisible(), false);
1790 edit.setCursorVisible(true);
1791 QCOMPARE(edit.isCursorVisible(), true);
1792 QCOMPARE(spy.count(), 1);
1794 edit.setCursorVisible(false);
1795 QCOMPARE(edit.isCursorVisible(), false);
1796 QCOMPARE(spy.count(), 2);
1798 edit.setFocus(true);
1799 QCOMPARE(edit.isCursorVisible(), false);
1800 QCOMPARE(spy.count(), 2);
1802 scene.addItem(&edit);
1803 QCOMPARE(edit.isCursorVisible(), true);
1804 QCOMPARE(spy.count(), 3);
1806 edit.setFocus(false);
1807 QCOMPARE(edit.isCursorVisible(), false);
1808 QCOMPARE(spy.count(), 4);
1810 edit.setFocus(true);
1811 QCOMPARE(edit.isCursorVisible(), true);
1812 QCOMPARE(spy.count(), 5);
1815 QCOMPARE(edit.isCursorVisible(), false);
1816 QCOMPARE(spy.count(), 6);
1819 QCOMPARE(edit.isCursorVisible(), true);
1820 QCOMPARE(spy.count(), 7);
1823 QCOMPARE(edit.isCursorVisible(), false);
1824 QCOMPARE(spy.count(), 8);
1827 QCOMPARE(edit.isCursorVisible(), true);
1828 QCOMPARE(spy.count(), 9);
1830 // on mac, setActiveWindow(0) on mac does not deactivate the current application
1831 // (you have to switch to a different app or hide the current app to trigger this)
1832 #if !defined(Q_WS_MAC)
1833 QApplication::setActiveWindow(0);
1834 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(0));
1835 QCOMPARE(edit.isCursorVisible(), false);
1836 QCOMPARE(spy.count(), 10);
1838 QApplication::setActiveWindow(&view);
1839 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
1840 QCOMPARE(edit.isCursorVisible(), true);
1841 QCOMPARE(spy.count(), 11);
1845 void tst_qdeclarativetextedit::delegateLoading_data()
1847 QTest::addColumn<QString>("qmlfile");
1848 QTest::addColumn<QString>("error");
1851 QTest::newRow("pass") << "cursorHttpTestPass.qml" << "";
1852 QTest::newRow("fail1") << "cursorHttpTestFail1.qml" << "http://localhost:42332/FailItem.qml: Remote host closed the connection ";
1853 QTest::newRow("fail2") << "cursorHttpTestFail2.qml" << "http://localhost:42332/ErrItem.qml:4:5: Fungus is not a type ";
1856 void tst_qdeclarativetextedit::delegateLoading()
1858 QFETCH(QString, qmlfile);
1859 QFETCH(QString, error);
1861 TestHTTPServer server(42332);
1862 server.serveDirectory(SRCDIR "/data/httpfail", TestHTTPServer::Disconnect);
1863 server.serveDirectory(SRCDIR "/data/httpslow", TestHTTPServer::Delay);
1864 server.serveDirectory(SRCDIR "/data/http");
1866 QDeclarativeView* view = new QDeclarativeView(0);
1868 view->setSource(QUrl(QLatin1String("http://localhost:42332/") + qmlfile));
1872 if (!error.isEmpty()) {
1873 QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
1874 QTRY_VERIFY(view->status()==QDeclarativeView::Error);
1875 QTRY_VERIFY(!view->rootObject()); // there is fail item inside this test
1877 QTRY_VERIFY(view->rootObject());//Wait for loading to finish.
1878 QDeclarative1TextEdit *textEditObject = view->rootObject()->findChild<QDeclarative1TextEdit*>("textEditObject");
1879 // view->rootObject()->dumpObjectTree();
1880 QVERIFY(textEditObject != 0);
1881 textEditObject->setFocus(true);
1882 QDeclarativeItem *delegate;
1883 delegate = view->rootObject()->findChild<QDeclarativeItem*>("delegateOkay");
1885 delegate = view->rootObject()->findChild<QDeclarativeItem*>("delegateSlow");
1892 //A test should be added here with a component which is ready but component.create() returns null
1893 //Not sure how to accomplish this with QDeclarative1TextEdits cursor delegate
1894 //###This was only needed for code coverage, and could be a case of overzealous defensive programming
1895 //delegate = view->rootObject()->findChild<QDeclarativeItem*>("delegateErrorB");
1896 //QVERIFY(!delegate);
1902 TextEdit element should only handle left/right keys until the cursor reaches
1903 the extent of the text, then they should ignore the keys.
1905 void tst_qdeclarativetextedit::navigation()
1907 QDeclarativeView *canvas = createView(SRCDIR "/data/navigation.qml");
1911 QVERIFY(canvas->rootObject() != 0);
1913 QDeclarativeItem *input = qobject_cast<QDeclarativeItem *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
1915 QVERIFY(input != 0);
1916 QTRY_VERIFY(input->hasActiveFocus() == true);
1917 simulateKey(canvas, Qt::Key_Left);
1918 QVERIFY(input->hasActiveFocus() == false);
1919 simulateKey(canvas, Qt::Key_Right);
1920 QVERIFY(input->hasActiveFocus() == true);
1921 simulateKey(canvas, Qt::Key_Right);
1922 QVERIFY(input->hasActiveFocus() == true);
1923 simulateKey(canvas, Qt::Key_Right);
1924 QVERIFY(input->hasActiveFocus() == false);
1925 simulateKey(canvas, Qt::Key_Left);
1926 QVERIFY(input->hasActiveFocus() == true);
1931 void tst_qdeclarativetextedit::copyAndPaste() {
1932 #ifndef QT_NO_CLIPBOARD
1936 PasteboardRef pasteboard;
1937 OSStatus status = PasteboardCreate(0, &pasteboard);
1938 if (status == noErr)
1939 CFRelease(pasteboard);
1941 QSKIP("This machine doesn't support the clipboard");
1945 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"Hello world!\" }";
1946 QDeclarativeComponent textEditComponent(&engine);
1947 textEditComponent.setData(componentStr.toLatin1(), QUrl());
1948 QDeclarative1TextEdit *textEdit = qobject_cast<QDeclarative1TextEdit*>(textEditComponent.create());
1949 QVERIFY(textEdit != 0);
1952 QCOMPARE(textEdit->text().length(), 12);
1953 textEdit->select(0, textEdit->text().length());;
1955 QCOMPARE(textEdit->selectedText(), QString("Hello world!"));
1956 QCOMPARE(textEdit->selectedText().length(), 12);
1957 textEdit->setCursorPosition(0);
1958 QVERIFY(textEdit->canPaste());
1960 QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
1961 QCOMPARE(textEdit->text().length(), 24);
1964 QVERIFY(textEdit->canPaste());
1965 textEdit->setReadOnly(true);
1966 QVERIFY(!textEdit->canPaste());
1967 textEdit->setReadOnly(false);
1968 QVERIFY(textEdit->canPaste());
1971 // test that document and internal text attribute are in sync
1972 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(textEdit);
1973 QDeclarative1TextEditPrivate *editPrivate = static_cast<QDeclarative1TextEditPrivate*>(pri);
1974 QCOMPARE(textEdit->text(), editPrivate->text);
1977 textEdit->setCursorPosition(0);
1978 textEdit->selectWord();
1979 QCOMPARE(textEdit->selectedText(), QString("Hello"));
1981 // select all and cut
1982 textEdit->selectAll();
1984 QCOMPARE(textEdit->text().length(), 0);
1986 QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
1987 QCOMPARE(textEdit->text().length(), 24);
1991 void tst_qdeclarativetextedit::canPaste() {
1992 #ifndef QT_NO_CLIPBOARD
1994 QApplication::clipboard()->setText("Some text");
1996 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"Hello world!\" }";
1997 QDeclarativeComponent textEditComponent(&engine);
1998 textEditComponent.setData(componentStr.toLatin1(), QUrl());
1999 QDeclarative1TextEdit *textEdit = qobject_cast<QDeclarative1TextEdit*>(textEditComponent.create());
2000 QVERIFY(textEdit != 0);
2002 // check initial value - QTBUG-17765
2003 QWidgetTextControl tc;
2004 QCOMPARE(textEdit->canPaste(), tc.canPaste());
2009 void tst_qdeclarativetextedit::canPasteEmpty() {
2010 #ifndef QT_NO_CLIPBOARD
2012 QApplication::clipboard()->clear();
2014 QString componentStr = "import QtQuick 1.0\nTextEdit { text: \"Hello world!\" }";
2015 QDeclarativeComponent textEditComponent(&engine);
2016 textEditComponent.setData(componentStr.toLatin1(), QUrl());
2017 QDeclarative1TextEdit *textEdit = qobject_cast<QDeclarative1TextEdit*>(textEditComponent.create());
2018 QVERIFY(textEdit != 0);
2020 // check initial value - QTBUG-17765
2021 QWidgetTextControl tc;
2022 QCOMPARE(textEdit->canPaste(), tc.canPaste());
2027 void tst_qdeclarativetextedit::readOnly()
2029 QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml");
2033 QVERIFY(canvas->rootObject() != 0);
2035 QDeclarative1TextEdit *edit = qobject_cast<QDeclarative1TextEdit *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
2038 QTRY_VERIFY(edit->hasActiveFocus() == true);
2039 QVERIFY(edit->isReadOnly() == true);
2040 QString initial = edit->text();
2041 for(int k=Qt::Key_0; k<=Qt::Key_Z; k++)
2042 simulateKey(canvas, k);
2043 simulateKey(canvas, Qt::Key_Return);
2044 simulateKey(canvas, Qt::Key_Space);
2045 simulateKey(canvas, Qt::Key_Escape);
2046 QCOMPARE(edit->text(), initial);
2051 void tst_qdeclarativetextedit::simulateKey(QDeclarativeView *view, int key, Qt::KeyboardModifiers modifiers)
2053 QKeyEvent press(QKeyEvent::KeyPress, key, modifiers);
2054 QKeyEvent release(QKeyEvent::KeyRelease, key, modifiers);
2056 QApplication::sendEvent(view, &press);
2057 QApplication::sendEvent(view, &release);
2060 QDeclarativeView *tst_qdeclarativetextedit::createView(const QString &filename)
2062 QDeclarativeView *canvas = new QDeclarativeView(0);
2064 canvas->setSource(QUrl::fromLocalFile(filename));
2068 void tst_qdeclarativetextedit::textInput()
2070 QGraphicsScene scene;
2071 QGraphicsView view(&scene);
2072 QDeclarative1TextEdit edit;
2073 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&edit);
2074 QDeclarative1TextEditPrivate *editPrivate = static_cast<QDeclarative1TextEditPrivate*>(pri);
2076 scene.addItem(&edit);
2078 QApplication::setActiveWindow(&view);
2079 QTest::qWaitForWindowShown(&view);
2080 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2081 edit.setFocus(true);
2082 QVERIFY(edit.hasActiveFocus() == true);
2084 // test that input method event is committed
2085 QInputMethodEvent event;
2086 event.setCommitString( "Hello world!", 0, 0);
2087 QApplication::sendEvent(&view, &event);
2088 QCOMPARE(edit.text(), QString("Hello world!"));
2091 // test that document and internal text attribute are in sync
2092 QCOMPARE(editPrivate->text, QString("Hello world!"));
2095 void tst_qdeclarativetextedit::openInputPanelOnClick()
2097 PlatformInputContext ic;
2098 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
2099 inputPanelPrivate->testContext = ⁣
2101 QGraphicsScene scene;
2102 QGraphicsView view(&scene);
2103 QDeclarative1TextEdit edit;
2104 QSignalSpy focusOnPressSpy(&edit, SIGNAL(activeFocusOnPressChanged(bool)));
2105 edit.setText("Hello world");
2107 scene.addItem(&edit);
2109 qApp->setAutoSipEnabled(true);
2110 QApplication::setActiveWindow(&view);
2111 QTest::qWaitForWindowShown(&view);
2112 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2114 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&edit);
2115 QDeclarative1TextEditPrivate *editPrivate = static_cast<QDeclarative1TextEditPrivate*>(pri);
2117 // input panel on click
2118 editPrivate->showInputPanelOnFocus = false;
2120 QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
2121 view.style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
2122 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2123 QApplication::processEvents();
2124 if (behavior == QStyle::RSIP_OnMouseClickAndAlreadyFocused) {
2125 QCOMPARE(ic.isInputPanelVisible(), false);
2126 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2127 QApplication::processEvents();
2128 QCOMPARE(ic.isInputPanelVisible(), true);
2129 } else if (behavior == QStyle::RSIP_OnMouseClick) {
2130 QCOMPARE(ic.isInputPanelVisible(), true);
2134 // focus should not cause input panels to open or close
2135 edit.setFocus(false);
2136 edit.setFocus(true);
2137 edit.setFocus(false);
2138 edit.setFocus(true);
2139 edit.setFocus(false);
2140 QApplication::processEvents();
2141 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2142 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2145 void tst_qdeclarativetextedit::openInputPanelOnFocus()
2147 PlatformInputContext ic;
2148 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
2149 inputPanelPrivate->testContext = ⁣
2151 QGraphicsScene scene;
2152 QGraphicsView view(&scene);
2153 QDeclarative1TextEdit edit;
2154 QSignalSpy focusOnPressSpy(&edit, SIGNAL(activeFocusOnPressChanged(bool)));
2155 edit.setText("Hello world");
2157 scene.addItem(&edit);
2159 qApp->setAutoSipEnabled(true);
2160 QApplication::setActiveWindow(&view);
2161 QTest::qWaitForWindowShown(&view);
2162 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2164 QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&edit);
2165 QDeclarative1TextEditPrivate *editPrivate = static_cast<QDeclarative1TextEditPrivate*>(pri);
2166 editPrivate->showInputPanelOnFocus = true;
2168 // test default values
2169 QVERIFY(edit.focusOnPress());
2170 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2171 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2173 // focus on press, input panel on focus
2174 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2175 QApplication::processEvents();
2176 QVERIFY(edit.hasActiveFocus());
2177 QCOMPARE(ic.isInputPanelVisible(), true);
2180 // no events on release
2181 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2182 QCOMPARE(ic.isInputPanelVisible(), false);
2185 // if already focused, input panel can be opened on press
2186 QVERIFY(edit.hasActiveFocus());
2187 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2188 QApplication::processEvents();
2189 QCOMPARE(ic.isInputPanelVisible(), true);
2192 // input method should stay enabled if focus
2193 // is lost to an item that also accepts inputs
2194 QDeclarative1TextEdit anotherEdit;
2195 scene.addItem(&anotherEdit);
2196 anotherEdit.setFocus(true);
2197 QApplication::processEvents();
2198 QCOMPARE(ic.isInputPanelVisible(), true);
2200 QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
2202 // input method should be disabled if focus
2203 // is lost to an item that doesn't accept inputs
2204 QDeclarativeItem item;
2205 scene.addItem(&item);
2206 item.setFocus(true);
2207 QApplication::processEvents();
2208 QCOMPARE(ic.isInputPanelVisible(), false);
2209 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2211 // no automatic input panel events should
2212 // be sent if activeFocusOnPress is false
2213 edit.setFocusOnPress(false);
2214 QCOMPARE(focusOnPressSpy.count(),1);
2215 edit.setFocusOnPress(false);
2216 QCOMPARE(focusOnPressSpy.count(),1);
2217 edit.setFocus(false);
2218 edit.setFocus(true);
2219 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2220 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos()));
2221 QApplication::processEvents();
2222 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2223 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2225 // one show input panel event should
2226 // be set when openSoftwareInputPanel is called
2227 edit.openSoftwareInputPanel();
2228 QCOMPARE(ic.isInputPanelVisible(), true);
2229 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2232 // one close input panel event should
2233 // be sent when closeSoftwareInputPanel is called
2234 edit.closeSoftwareInputPanel();
2235 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2236 QVERIFY(ic.m_hideInputPanelCallCount > 0);
2239 // set activeFocusOnPress back to true
2240 edit.setFocusOnPress(true);
2241 QCOMPARE(focusOnPressSpy.count(),2);
2242 edit.setFocusOnPress(true);
2243 QCOMPARE(focusOnPressSpy.count(),2);
2244 edit.setFocus(false);
2245 QApplication::processEvents();
2246 QCOMPARE(ic.m_showInputPanelCallCount, 0);
2247 QCOMPARE(ic.m_hideInputPanelCallCount, 0);
2250 // input panel should not re-open
2251 // if focus has already been set
2252 edit.setFocus(true);
2253 QCOMPARE(ic.isInputPanelVisible(), true);
2255 edit.setFocus(true);
2256 QCOMPARE(ic.isInputPanelVisible(), false);
2258 // input method should be disabled
2259 // if TextEdit loses focus
2260 edit.setFocus(false);
2261 QApplication::processEvents();
2262 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2264 // input method should not be enabled
2265 // if TextEdit is read only.
2266 edit.setReadOnly(true);
2268 edit.setFocus(true);
2269 QApplication::processEvents();
2270 QCOMPARE(ic.isInputPanelVisible(), false);
2271 QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled));
2274 void tst_qdeclarativetextedit::geometrySignals()
2276 QDeclarativeComponent component(&engine, SRCDIR "/data/geometrySignals.qml");
2277 QObject *o = component.create();
2279 QCOMPARE(o->property("bindingWidth").toInt(), 400);
2280 QCOMPARE(o->property("bindingHeight").toInt(), 500);
2284 void tst_qdeclarativetextedit::pastingRichText_QTBUG_14003()
2286 #ifndef QT_NO_CLIPBOARD
2287 QString componentStr = "import QtQuick 1.0\nTextEdit { textFormat: TextEdit.PlainText }";
2288 QDeclarativeComponent component(&engine);
2289 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
2290 QDeclarative1TextEdit *obj = qobject_cast<QDeclarative1TextEdit*>(component.create());
2292 QTRY_VERIFY(obj != 0);
2293 QTRY_VERIFY(obj->textFormat() == QDeclarative1TextEdit::PlainText);
2295 QMimeData *mData = new QMimeData;
2296 mData->setHtml("<font color=\"red\">Hello</font>");
2297 QApplication::clipboard()->setMimeData(mData);
2300 QTRY_VERIFY(obj->text() == "");
2301 QTRY_VERIFY(obj->textFormat() == QDeclarative1TextEdit::PlainText);
2305 void tst_qdeclarativetextedit::implicitSize_data()
2307 QTest::addColumn<QString>("text");
2308 QTest::addColumn<QString>("wrap");
2309 QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap";
2310 QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.NoWrap";
2311 QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap";
2312 QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.Wrap";
2315 void tst_qdeclarativetextedit::implicitSize()
2317 QFETCH(QString, text);
2318 QFETCH(QString, wrap);
2319 QString componentStr = "import QtQuick 1.1\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }";
2320 QDeclarativeComponent textComponent(&engine);
2321 textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
2322 QDeclarative1TextEdit *textObject = qobject_cast<QDeclarative1TextEdit*>(textComponent.create());
2324 QVERIFY(textObject->width() < textObject->implicitWidth());
2325 QVERIFY(textObject->height() == textObject->implicitHeight());
2327 textObject->resetWidth();
2328 QVERIFY(textObject->width() == textObject->implicitWidth());
2329 QVERIFY(textObject->height() == textObject->implicitHeight());
2332 void tst_qdeclarativetextedit::testQtQuick11Attributes()
2334 QFETCH(QString, code);
2335 QFETCH(QString, warning);
2336 QFETCH(QString, error);
2338 QDeclarativeEngine engine;
2341 QDeclarativeComponent valid(&engine);
2342 valid.setData("import QtQuick 1.1; TextEdit { " + code.toUtf8() + " }", QUrl(""));
2343 obj = valid.create();
2345 QVERIFY(valid.errorString().isEmpty());
2348 QDeclarativeComponent invalid(&engine);
2349 invalid.setData("import QtQuick 1.0; TextEdit { " + code.toUtf8() + " }", QUrl(""));
2350 QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
2351 obj = invalid.create();
2352 QCOMPARE(invalid.errorString(), error);
2356 void tst_qdeclarativetextedit::testQtQuick11Attributes_data()
2358 QTest::addColumn<QString>("code");
2359 QTest::addColumn<QString>("warning");
2360 QTest::addColumn<QString>("error");
2362 QTest::newRow("canPaste") << "property bool foo: canPaste"
2363 << "<Unknown File>:1: ReferenceError: Can't find variable: canPaste"
2366 QTest::newRow("lineCount") << "property int foo: lineCount"
2367 << "<Unknown File>:1: ReferenceError: Can't find variable: lineCount"
2370 QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)"
2371 << "<Unknown File>:1: ReferenceError: Can't find variable: moveCursorSelection"
2374 QTest::newRow("deselect") << "Component.onCompleted: deselect()"
2375 << "<Unknown File>:1: ReferenceError: Can't find variable: deselect"
2378 QTest::newRow("onLinkActivated") << "onLinkActivated: {}"
2379 << "QDeclarativeComponent: Component is not ready"
2380 << ":1 \"TextEdit.onLinkActivated\" is not available in QtQuick 1.0.\n";
2383 void tst_qdeclarativetextedit::preeditMicroFocus()
2385 QString preeditText = "super";
2386 PlatformInputContext ic;
2387 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
2388 inputPanelPrivate->testContext = ⁣
2390 QGraphicsScene scene;
2391 QGraphicsView view(&scene);
2392 QDeclarative1TextEdit edit;
2393 edit.setFocus(true);
2394 scene.addItem(&edit);
2396 QApplication::setActiveWindow(&view);
2397 QTest::qWaitForWindowShown(&view);
2398 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2400 QSignalSpy cursorRectangleSpy(&edit, SIGNAL(cursorRectangleChanged()));
2403 QRect previousRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect();
2405 // Verify that the micro focus rect is positioned the same for position 0 as
2406 // it would be if there was no preedit text.
2408 sendPreeditText(preeditText, 0);
2409 currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect();
2410 QCOMPARE(currentRect, previousRect);
2411 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
2412 QCOMPARE(ic.updateCallCount, 0); // The cursor position hasn't changed.
2414 QCOMPARE(cursorRectangleSpy.count(), 0);
2416 // Verify that the micro focus rect moves to the left as the cursor position
2418 for (int i = 1; i <= 5; ++i) {
2420 sendPreeditText(preeditText, i);
2421 currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect();
2422 QVERIFY(previousRect.left() < currentRect.left());
2423 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
2424 QVERIFY(ic.updateCallCount > 0);
2426 QVERIFY(cursorRectangleSpy.count() > 0);
2427 cursorRectangleSpy.clear();
2428 previousRect = currentRect;
2431 // Verify that if there is no preedit cursor then the micro focus rect is the
2432 // same as it would be if it were positioned at the end of the preedit text.
2433 sendPreeditText(preeditText, 0);
2435 QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
2436 QApplication::sendEvent(qApp->inputPanel()->inputItem(), &imEvent);
2437 currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect();
2438 QCOMPARE(currentRect, previousRect);
2439 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
2440 QVERIFY(ic.updateCallCount > 0);
2442 QVERIFY(cursorRectangleSpy.count() > 0);
2445 void tst_qdeclarativetextedit::inputContextMouseHandler()
2447 QString text = "supercalifragisiticexpialidocious!";
2448 PlatformInputContext ic;
2449 QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
2450 inputPanelPrivate->testContext = ⁣
2452 QGraphicsScene scene;
2453 QGraphicsView view(&scene);
2454 QDeclarative1TextEdit edit;
2457 edit.setText(text.mid(0, 12));
2459 edit.setCursorPosition(12);
2460 edit.setFocus(true);
2461 scene.addItem(&edit);
2463 QApplication::setActiveWindow(&view);
2464 QTest::qWaitForWindowShown(&view);
2465 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2468 QFontMetricsF fm(edit.font());
2469 const qreal y = fm.height() / 2;
2471 QPoint position2 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 2)), y)));
2473 QInputMethodEvent inputEvent(text.mid(0, 12), QList<QInputMethodEvent::Attribute>());
2474 QApplication::sendEvent(&view, &inputEvent);
2476 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
2477 QTest::mouseRelease(view.viewport(), Qt::RightButton, Qt::ControlModifier, position2);
2478 QApplication::processEvents();
2480 QCOMPARE(ic.m_action, QInputPanel::Click);
2481 QCOMPARE(ic.m_invokeActionCallCount, 1);
2482 QCOMPARE(ic.m_cursorPosition, 2);
2485 void tst_qdeclarativetextedit::inputMethodComposing()
2487 QString text = "supercalifragisiticexpialidocious!";
2489 QGraphicsScene scene;
2490 QGraphicsView view(&scene);
2491 QDeclarative1TextEdit edit;
2493 edit.setText(text.mid(0, 12));
2494 edit.setCursorPosition(12);
2496 edit.setFocus(true);
2497 scene.addItem(&edit);
2499 QApplication::setActiveWindow(&view);
2500 QTest::qWaitForWindowShown(&view);
2501 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2503 QSignalSpy spy(&edit, SIGNAL(inputMethodComposingChanged()));
2505 QCOMPARE(edit.isInputMethodComposing(), false);
2507 QInputMethodEvent imEvent(text.mid(3), QList<QInputMethodEvent::Attribute>());
2508 QApplication::sendEvent(&view, &imEvent);
2510 QCOMPARE(edit.isInputMethodComposing(), true);
2511 QCOMPARE(spy.count(), 1);
2514 QInputMethodEvent imEvent(text.mid(12), QList<QInputMethodEvent::Attribute>());
2515 QApplication::sendEvent(&view, &imEvent);
2517 QCOMPARE(edit.isInputMethodComposing(), true);
2518 QCOMPARE(spy.count(), 1);
2521 QInputMethodEvent imEvent;
2522 QApplication::sendEvent(&view, &imEvent);
2524 QCOMPARE(edit.isInputMethodComposing(), false);
2525 QCOMPARE(spy.count(), 2);
2528 void tst_qdeclarativetextedit::cursorRectangleSize()
2530 QDeclarativeView *canvas = createView(SRCDIR "/data/CursorRect.qml");
2531 QVERIFY(canvas->rootObject() != 0);
2534 QApplication::setActiveWindow(canvas);
2535 QTest::qWaitForWindowShown(canvas);
2537 QDeclarative1TextEdit *textEdit = qobject_cast<QDeclarative1TextEdit *>(canvas->rootObject());
2538 QVERIFY(textEdit != 0);
2539 textEdit->setFocus(Qt::OtherFocusReason);
2540 QRectF cursorRect = textEdit->positionToRectangle(textEdit->cursorPosition());
2541 QRectF microFocusFromScene = canvas->scene()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
2542 QRectF microFocusFromApp= QApplication::focusWidget()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
2544 QCOMPARE(microFocusFromScene.size(), cursorRect.size());
2545 QCOMPARE(microFocusFromApp.size(), cursorRect.size());
2547 QTEST_MAIN(tst_qdeclarativetextedit)
2549 #include "tst_qdeclarativetextedit.moc"