diff -r 5dc02b23752f -r 3e2da88830cd tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp Tue Jul 06 15:10:48 2010 +0300 +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp Wed Aug 18 10:37:55 2010 +0300 @@ -39,6 +39,7 @@ ** ****************************************************************************/ #include +#include #include "../../../shared/util.h" #include "../shared/testhttpserver.h" #include @@ -49,10 +50,36 @@ #include #include #include +#include #include #include +#include #include #include +#include +#include + +#ifdef Q_OS_SYMBIAN +// In Symbian OS test data is located in applications private dir +#define SRCDIR "." +#endif + +QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual) +{ + // XXX This will be replaced by some clever persistent platform image store. + QString persistent_dir = SRCDIR "/data"; + QString arch = "unknown-architecture"; // QTest needs to help with this. + + QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png"; + + if (!QFile::exists(expectfile)) { + actual.save(expectfile); + qWarning() << "created" << expectfile; + } + + return expectfile; +} + class tst_qdeclarativetextedit : public QObject @@ -66,6 +93,8 @@ void width(); void wrap(); void textFormat(); + void alignments(); + void alignments_data(); // ### these tests may be trivial void hAlign(); @@ -85,7 +114,10 @@ void delegateLoading(); void navigation(); void readOnly(); - void sendRequestSoftwareInputPanelEvent(); + void copyAndPaste(); + void textInput(); + void openInputPanelOnClick(); + void openInputPanelOnFocus(); void geometrySignals(); private: void simulateKey(QDeclarativeView *, int key); @@ -196,7 +228,7 @@ QDeclarativeTextEdit *textEditObject = qobject_cast(texteditComponent.create()); QVERIFY(textEditObject != 0); - QCOMPARE(textEditObject->width(), 1.);//+1 for cursor + QCOMPARE(textEditObject->width(), 0.0); } for (int i = 0; i < standard.size(); i++) @@ -212,7 +244,7 @@ QDeclarativeTextEdit *textEditObject = qobject_cast(texteditComponent.create()); QVERIFY(textEditObject != 0); - QCOMPARE(textEditObject->width(), qreal(metricWidth + 1 + 3));//+3 is the current way of accounting for space between cursor and last character. + QCOMPARE(textEditObject->width(), qreal(metricWidth)); } for (int i = 0; i < richText.size(); i++) @@ -229,7 +261,7 @@ QDeclarativeTextEdit *textEditObject = qobject_cast(texteditComponent.create()); QVERIFY(textEditObject != 0); - QCOMPARE(textEditObject->width(), qreal(documentWidth + 1 + 3)); + QCOMPARE(textEditObject->width(), qreal(documentWidth)); } } @@ -289,6 +321,57 @@ } } +void tst_qdeclarativetextedit::alignments_data() +{ + QTest::addColumn("hAlign"); + QTest::addColumn("vAlign"); + QTest::addColumn("expectfile"); + + QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << "alignments_lt"; + QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << "alignments_rt"; + QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << "alignments_ct"; + + QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << "alignments_lb"; + QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << "alignments_rb"; + QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << "alignments_cb"; + + QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << "alignments_lc"; + QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << "alignments_rc"; + QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << "alignments_cc"; +} + + +void tst_qdeclarativetextedit::alignments() +{ + QFETCH(int, hAlign); + QFETCH(int, vAlign); + QFETCH(QString, expectfile); + + QDeclarativeView *canvas = createView(SRCDIR "/data/alignments.qml"); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(canvas)); + + QObject *ob = canvas->rootObject(); + QVERIFY(ob != 0); + ob->setProperty("horizontalAlignment",hAlign); + ob->setProperty("verticalAlignment",vAlign); + QTRY_COMPARE(ob->property("running").toBool(),false); + QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32); + actual.fill(qRgb(255,255,255)); + QPainter p(&actual); + canvas->render(&p); + + expectfile = createExpectedFileIfNotFound(expectfile, actual); + + QImage expect(expectfile); + + QCOMPARE(actual,expect); +} + + //the alignment tests may be trivial o.oa void tst_qdeclarativetextedit::hAlign() { @@ -420,6 +503,23 @@ void tst_qdeclarativetextedit::color() { + //test initial color + { + QString componentStr = "import Qt 4.7\nTextEdit { text: \"Hello World\" }"; + QDeclarativeComponent texteditComponent(&engine); + texteditComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextEdit *textEditObject = qobject_cast(texteditComponent.create()); + + QDeclarativeTextEditPrivate *textEditPrivate = static_cast(QDeclarativeItemPrivate::get(textEditObject)); + + QVERIFY(textEditObject); + QVERIFY(textEditPrivate); + QVERIFY(textEditPrivate->control); + + QPalette pal = textEditPrivate->control->palette(); + QCOMPARE(textEditPrivate->color, QColor("black")); + QCOMPARE(textEditPrivate->color, pal.color(QPalette::Text)); + } //test normal for (int i = 0; i < colorStrings.size(); i++) { @@ -505,7 +605,7 @@ void tst_qdeclarativetextedit::focusOnPress() { { - QString componentStr = "import Qt 4.7\nTextEdit { focusOnPress: true; text: \"Hello World\" }"; + QString componentStr = "import Qt 4.7\nTextEdit { activeFocusOnPress: true; text: \"Hello World\" }"; QDeclarativeComponent texteditComponent(&engine); texteditComponent.setData(componentStr.toLatin1(), QUrl()); QDeclarativeTextEdit *textEditObject = qobject_cast(texteditComponent.create()); @@ -514,7 +614,7 @@ } { - QString componentStr = "import Qt 4.7\nTextEdit { focusOnPress: false; text: \"Hello World\" }"; + QString componentStr = "import Qt 4.7\nTextEdit { activeFocusOnPress: false; text: \"Hello World\" }"; QDeclarativeComponent texteditComponent(&engine); texteditComponent.setData(componentStr.toLatin1(), QUrl()); QDeclarativeTextEdit *textEditObject = qobject_cast(texteditComponent.create()); @@ -550,11 +650,11 @@ //Test selection for(int i=0; i<= testStr.size(); i++) { - textEditObject->setSelectionEnd(i); + textEditObject->select(0,i); QCOMPARE(testStr.mid(0,i), textEditObject->selectedText()); } for(int i=0; i<= testStr.size(); i++) { - textEditObject->setSelectionStart(i); + textEditObject->select(i,testStr.size()); QCOMPARE(testStr.mid(i,testStr.size()-i), textEditObject->selectedText()); } @@ -564,43 +664,26 @@ QVERIFY(textEditObject->selectionEnd() == 0); QVERIFY(textEditObject->selectedText().isNull()); - for(int i=0; i< testStr.size(); i++) { - textEditObject->setSelectionStart(i); - QCOMPARE(textEditObject->selectionEnd(), i); - QCOMPARE(testStr.mid(i,0), textEditObject->selectedText()); - textEditObject->setSelectionEnd(i+1); - QCOMPARE(textEditObject->selectionStart(), i); - QCOMPARE(testStr.mid(i,1), textEditObject->selectedText()); - } - - for(int i= testStr.size() - 1; i>0; i--) { - textEditObject->setSelectionEnd(i); - QCOMPARE(testStr.mid(i,0), textEditObject->selectedText()); - textEditObject->setSelectionStart(i-1); - QCOMPARE(testStr.mid(i-1,1), textEditObject->selectedText()); - } - //Test Error Ignoring behaviour textEditObject->setCursorPosition(0); QVERIFY(textEditObject->selectedText().isNull()); - textEditObject->setSelectionStart(-10); + textEditObject->select(-10,0); QVERIFY(textEditObject->selectedText().isNull()); - textEditObject->setSelectionStart(100); + textEditObject->select(100,101); QVERIFY(textEditObject->selectedText().isNull()); - textEditObject->setSelectionEnd(-10); + textEditObject->select(0,-10); QVERIFY(textEditObject->selectedText().isNull()); - textEditObject->setSelectionEnd(100); + textEditObject->select(0,100); QVERIFY(textEditObject->selectedText().isNull()); - textEditObject->setSelectionStart(0); - textEditObject->setSelectionEnd(10); + textEditObject->select(0,10); QVERIFY(textEditObject->selectedText().size() == 10); - textEditObject->setSelectionStart(-10); + textEditObject->select(-10,0); QVERIFY(textEditObject->selectedText().size() == 10); - textEditObject->setSelectionStart(100); + textEditObject->select(100,101); QVERIFY(textEditObject->selectedText().size() == 10); - textEditObject->setSelectionEnd(-10); + textEditObject->select(0,-10); QVERIFY(textEditObject->selectedText().size() == 10); - textEditObject->setSelectionEnd(100); + textEditObject->select(0,100); QVERIFY(textEditObject->selectedText().size() == 10); } @@ -676,12 +759,12 @@ //Test Delegate gets moved for(int i=0; i<= textEditObject->text().length(); i++){ textEditObject->setCursorPosition(i); - QCOMPARE(textEditObject->cursorRect().x(), qRound(delegateObject->x())); - QCOMPARE(textEditObject->cursorRect().y(), qRound(delegateObject->y())); + QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x())); + QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y())); } textEditObject->setCursorPosition(0); - QCOMPARE(textEditObject->cursorRect().x(), qRound(delegateObject->x())); - QCOMPARE(textEditObject->cursorRect().y(), qRound(delegateObject->y())); + QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x())); + QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y())); //Test Delegate gets deleted textEditObject->setCursorDelegate(0); QVERIFY(!textEditObject->findChild("cursorInstance")); @@ -758,15 +841,67 @@ QDeclarativeItem *input = qobject_cast(qvariant_cast(canvas->rootObject()->property("myInput"))); QVERIFY(input != 0); - QTRY_VERIFY(input->hasFocus() == true); + QTRY_VERIFY(input->hasActiveFocus() == true); simulateKey(canvas, Qt::Key_Left); - QVERIFY(input->hasFocus() == false); + QVERIFY(input->hasActiveFocus() == false); + simulateKey(canvas, Qt::Key_Right); + QVERIFY(input->hasActiveFocus() == true); simulateKey(canvas, Qt::Key_Right); - QVERIFY(input->hasFocus() == true); - simulateKey(canvas, Qt::Key_Right); - QVERIFY(input->hasFocus() == false); + QVERIFY(input->hasActiveFocus() == false); simulateKey(canvas, Qt::Key_Left); - QVERIFY(input->hasFocus() == true); + QVERIFY(input->hasActiveFocus() == true); +} + +void tst_qdeclarativetextedit::copyAndPaste() { +#ifndef QT_NO_CLIPBOARD + +#ifdef Q_WS_MAC + { + PasteboardRef pasteboard; + OSStatus status = PasteboardCreate(0, &pasteboard); + if (status == noErr) + CFRelease(pasteboard); + else + QSKIP("This machine doesn't support the clipboard", SkipAll); + } +#endif + + QString componentStr = "import Qt 4.7\nTextEdit { text: \"Hello world!\" }"; + QDeclarativeComponent textEditComponent(&engine); + textEditComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextEdit *textEdit = qobject_cast(textEditComponent.create()); + QVERIFY(textEdit != 0); + + // copy and paste + QCOMPARE(textEdit->text().length(), 12); + textEdit->select(0, textEdit->text().length());; + textEdit->copy(); + QCOMPARE(textEdit->selectedText(), QString("Hello world!")); + QCOMPARE(textEdit->selectedText().length(), 12); + textEdit->setCursorPosition(0); + textEdit->paste(); + QCOMPARE(textEdit->text(), QString("Hello world!Hello world!")); + QCOMPARE(textEdit->text().length(), 24); + + // QTBUG-12339 + // test that document and internal text attribute are in sync + QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(textEdit); + QDeclarativeTextEditPrivate *editPrivate = static_cast(pri); + QCOMPARE(textEdit->text(), editPrivate->text); + + // select word + textEdit->setCursorPosition(0); + textEdit->selectWord(); + QCOMPARE(textEdit->selectedText(), QString("Hello")); + + // select all and cut + textEdit->selectAll(); + textEdit->cut(); + QCOMPARE(textEdit->text().length(), 0); + textEdit->paste(); + QCOMPARE(textEdit->text(), QString("Hello world!Hello world!")); + QCOMPARE(textEdit->text().length(), 24); +#endif } void tst_qdeclarativetextedit::readOnly() @@ -780,7 +915,7 @@ QDeclarativeTextEdit *edit = qobject_cast(qvariant_cast(canvas->rootObject()->property("myInput"))); QVERIFY(edit != 0); - QTRY_VERIFY(edit->hasFocus() == true); + QTRY_VERIFY(edit->hasActiveFocus() == true); QVERIFY(edit->isReadOnly() == true); QString initial = edit->text(); for(int k=Qt::Key_0; k<=Qt::Key_Z; k++) @@ -811,7 +946,7 @@ class MyInputContext : public QInputContext { public: - MyInputContext() : softwareInputPanelEventReceived(false) {} + MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false) {} ~MyInputContext() {} QString identifierName() { return QString(); } @@ -824,21 +959,98 @@ bool filterEvent( const QEvent *event ) { if (event->type() == QEvent::RequestSoftwareInputPanel) - softwareInputPanelEventReceived = true; + openInputPanelReceived = true; + if (event->type() == QEvent::CloseSoftwareInputPanel) + closeInputPanelReceived = true; return QInputContext::filterEvent(event); } - bool softwareInputPanelEventReceived; + bool openInputPanelReceived; + bool closeInputPanelReceived; }; -void tst_qdeclarativetextedit::sendRequestSoftwareInputPanelEvent() +void tst_qdeclarativetextedit::textInput() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + QDeclarativeTextEdit edit; + QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&edit); + QDeclarativeTextEditPrivate *editPrivate = static_cast(pri); + edit.setPos(0, 0); + scene.addItem(&edit); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); + edit.setFocus(true); + QVERIFY(edit.hasActiveFocus() == true); + + // test that input method event is committed + QInputMethodEvent event; + event.setCommitString( "Hello world!", 0, 0); + QApplication::sendEvent(&view, &event); + QCOMPARE(edit.text(), QString("Hello world!")); + + // QTBUG-12339 + // test that document and internal text attribute are in sync + QCOMPARE(editPrivate->text, QString("Hello world!")); +} + +void tst_qdeclarativetextedit::openInputPanelOnClick() { QGraphicsScene scene; QGraphicsView view(&scene); MyInputContext ic; - view.viewport()->setInputContext(&ic); + view.setInputContext(&ic); + QDeclarativeTextEdit edit; + QSignalSpy focusOnPressSpy(&edit, SIGNAL(activeFocusOnPressChanged(bool))); + edit.setText("Hello world"); + edit.setPos(0, 0); + scene.addItem(&edit); + view.show(); + qApp->setAutoSipEnabled(true); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); + + QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&edit); + QDeclarativeTextEditPrivate *editPrivate = static_cast(pri); + + // input panel on click + editPrivate->showInputPanelOnFocus = false; + QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel( view.style()->styleHint(QStyle::SH_RequestSoftwareInputPanel)); + QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos())); + QApplication::processEvents(); + if (behavior == QStyle::RSIP_OnMouseClickAndAlreadyFocused) { + QCOMPARE(ic.openInputPanelReceived, false); + QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos())); + QApplication::processEvents(); + QCOMPARE(ic.openInputPanelReceived, true); + } else if (behavior == QStyle::RSIP_OnMouseClick) { + QCOMPARE(ic.openInputPanelReceived, true); + } + ic.openInputPanelReceived = false; + + // focus should not cause input panels to open or close + edit.setFocus(false); + edit.setFocus(true); + edit.setFocus(false); + edit.setFocus(true); + edit.setFocus(false); + QApplication::processEvents(); + QCOMPARE(ic.openInputPanelReceived, false); + QCOMPARE(ic.closeInputPanelReceived, false); +} + +void tst_qdeclarativetextedit::openInputPanelOnFocus() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); QDeclarativeTextEdit edit; + QSignalSpy focusOnPressSpy(&edit, SIGNAL(activeFocusOnPressChanged(bool))); edit.setText("Hello world"); edit.setPos(0, 0); scene.addItem(&edit); @@ -847,16 +1059,109 @@ QApplication::setActiveWindow(&view); QTest::qWaitForWindowShown(&view); QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); - QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos())); + + QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(&edit); + QDeclarativeTextEditPrivate *editPrivate = static_cast(pri); + editPrivate->showInputPanelOnFocus = true; + + // test default values + QVERIFY(edit.focusOnPress()); + QCOMPARE(ic.openInputPanelReceived, false); + QCOMPARE(ic.closeInputPanelReceived, false); + + // focus on press, input panel on focus + QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos())); + QApplication::processEvents(); + QVERIFY(edit.hasActiveFocus()); + QCOMPARE(ic.openInputPanelReceived, true); + ic.openInputPanelReceived = false; + + // no events on release + QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos())); + QCOMPARE(ic.openInputPanelReceived, false); + ic.openInputPanelReceived = false; + + // if already focused, input panel can be opened on press + QVERIFY(edit.hasActiveFocus()); + QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos())); + QApplication::processEvents(); + QCOMPARE(ic.openInputPanelReceived, true); + ic.openInputPanelReceived = false; + + // input method should stay enabled if focus + // is lost to an item that also accepts inputs + QDeclarativeTextEdit anotherEdit; + scene.addItem(&anotherEdit); + anotherEdit.setFocus(true); + QApplication::processEvents(); + QCOMPARE(ic.openInputPanelReceived, true); + ic.openInputPanelReceived = false; + QCOMPARE(view.inputContext(), &ic); + QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled)); + + // input method should be disabled if focus + // is lost to an item that doesn't accept inputs + QDeclarativeItem item; + scene.addItem(&item); + item.setFocus(true); QApplication::processEvents(); - if (behavior == QStyle::RSIP_OnMouseClickAndAlreadyFocused) { - QCOMPARE(ic.softwareInputPanelEventReceived, false); - QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos())); - QApplication::processEvents(); - QCOMPARE(ic.softwareInputPanelEventReceived, true); - } else if (behavior == QStyle::RSIP_OnMouseClick) { - QCOMPARE(ic.softwareInputPanelEventReceived, true); - } + QCOMPARE(ic.openInputPanelReceived, false); + QVERIFY(view.inputContext() == 0); + QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled)); + + // no automatic input panel events should + // be sent if activeFocusOnPress is false + edit.setFocusOnPress(false); + QCOMPARE(focusOnPressSpy.count(),1); + edit.setFocusOnPress(false); + QCOMPARE(focusOnPressSpy.count(),1); + edit.setFocus(false); + edit.setFocus(true); + QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos())); + QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(edit.scenePos())); + QApplication::processEvents(); + QCOMPARE(ic.openInputPanelReceived, false); + QCOMPARE(ic.closeInputPanelReceived, false); + + // one show input panel event should + // be set when openSoftwareInputPanel is called + edit.openSoftwareInputPanel(); + QCOMPARE(ic.openInputPanelReceived, true); + QCOMPARE(ic.closeInputPanelReceived, false); + ic.openInputPanelReceived = false; + + // one close input panel event should + // be sent when closeSoftwareInputPanel is called + edit.closeSoftwareInputPanel(); + QCOMPARE(ic.openInputPanelReceived, false); + QCOMPARE(ic.closeInputPanelReceived, true); + ic.closeInputPanelReceived = false; + + // set activeFocusOnPress back to true + edit.setFocusOnPress(true); + QCOMPARE(focusOnPressSpy.count(),2); + edit.setFocusOnPress(true); + QCOMPARE(focusOnPressSpy.count(),2); + edit.setFocus(false); + QApplication::processEvents(); + QCOMPARE(ic.openInputPanelReceived, false); + QCOMPARE(ic.closeInputPanelReceived, false); + ic.closeInputPanelReceived = false; + + // input panel should not re-open + // if focus has already been set + edit.setFocus(true); + QCOMPARE(ic.openInputPanelReceived, true); + ic.openInputPanelReceived = false; + edit.setFocus(true); + QCOMPARE(ic.openInputPanelReceived, false); + + // input method should be disabled + // if TextEdit loses focus + edit.setFocus(false); + QApplication::processEvents(); + QVERIFY(view.inputContext() == 0); + QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled)); } void tst_qdeclarativetextedit::geometrySignals()