#include "../../shared/util.h"
#include "../../shared/platforminputcontext.h"
#include <private/qinputmethod_p.h>
+#include <QtGui/qstylehints.h>
#ifdef Q_OS_MAC
#include <Carbon/Carbon.h>
#endif
+#define SERVER_PORT 42332
+#define SERVER_ADDR "http://localhost:42332"
Q_DECLARE_METATYPE(QQuickTextEdit::SelectionMode)
Q_DECLARE_METATYPE(Qt::Key)
// ### these tests may be trivial
void hAlign();
void hAlign_RightToLeft();
+ void hAlignVisual();
void vAlign();
void font();
void color();
void dragMouseSelection();
void inputMethodHints();
+ void positionAt_data();
void positionAt();
void linkActivated();
void cursorDelegate_data();
void cursorDelegate();
+ void remoteCursorDelegate();
void cursorVisible();
void delegateLoading_data();
void delegateLoading();
void implicitSize_data();
void implicitSize();
void contentSize();
+ void boundingRect();
+ void clipRect();
void implicitSizeBinding_data();
void implicitSizeBinding();
typedef QList<Key> KeyList;
Q_DECLARE_METATYPE(KeyList)
+Q_DECLARE_METATYPE(QQuickTextEdit::HAlignment)
+Q_DECLARE_METATYPE(QQuickTextEdit::VAlignment)
Q_DECLARE_METATYPE(QQuickTextEdit::TextFormat)
void tst_qquicktextedit::simulateKeys(QWindow *window, const QList<Key> &keys)
QFETCH(int, vAlign);
QFETCH(QString, expectfile);
- QQuickView canvas(testFileUrl("alignments.qml"));
+ QQuickView window(testFileUrl("alignments.qml"));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+ window.show();
+ QTest::qWaitForWindowShown(&window);
- QObject *ob = canvas.rootObject();
+ QObject *ob = window.rootObject();
QVERIFY(ob != 0);
ob->setProperty("horizontalAlignment",hAlign);
ob->setProperty("verticalAlignment",vAlign);
QTRY_COMPARE(ob->property("running").toBool(),false);
- QImage actual = canvas.grabFrameBuffer();
+ QImage actual = window.grabWindow();
expectfile = createExpectedFileIfNotFound(expectfile, actual);
QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
inputMethodPrivate->testContext = &platformInputContext;
- QQuickView canvas(testFileUrl("horizontalAlignment_RightToLeft.qml"));
- QQuickTextEdit *textEdit = canvas.rootObject()->findChild<QQuickTextEdit*>("text");
+ QQuickView window(testFileUrl("horizontalAlignment_RightToLeft.qml"));
+ QQuickTextEdit *textEdit = window.rootObject()->findChild<QQuickTextEdit*>("text");
QVERIFY(textEdit != 0);
- canvas.show();
+ window.show();
const QString rtlText = textEdit->text();
// implicit alignment should follow the reading direction of text
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
// explicitly left aligned
textEdit->setHAlign(QQuickTextEdit::AlignLeft);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
- QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() < window.width()/2);
// explicitly right aligned
textEdit->setHAlign(QQuickTextEdit::AlignRight);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
QString textString = textEdit->text();
textEdit->setText(QString("<i>") + textString + QString("</i>"));
// implicitly aligned rich text should follow the reading direction of RTL text
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
// explicitly left aligned rich text
textEdit->setHAlign(QQuickTextEdit::AlignLeft);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
- QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() < window.width()/2);
// explicitly right aligned rich text
textEdit->setHAlign(QQuickTextEdit::AlignRight);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
textEdit->setText(textString);
// explicitly center aligned
textEdit->setHAlign(QQuickTextEdit::AlignHCenter);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignHCenter);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
// reseted alignment should go back to following the text reading direction
textEdit->resetHAlign();
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
// mirror the text item
QQuickItemPrivate::get(textEdit)->setLayoutMirror(true);
// mirrored implicit alignment should continue to follow the reading direction of the text
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
// mirrored explicitly right aligned behaves as left aligned
textEdit->setHAlign(QQuickTextEdit::AlignRight);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignLeft);
- QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() < window.width()/2);
// mirrored explicitly left aligned behaves as right aligned
textEdit->setHAlign(QQuickTextEdit::AlignLeft);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
// disable mirroring
QQuickItemPrivate::get(textEdit)->setLayoutMirror(false);
// English text should be implicitly left aligned
textEdit->setText("Hello world!");
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
- QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() < window.width()/2);
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
+ QVERIFY(textEdit->hasActiveFocus());
textEdit->setText(QString());
- { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev); }
+ { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(textEdit, &ev); }
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev); }
+ { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(textEdit, &ev); }
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
// Clear pre-edit text. TextEdit should maybe do this itself on setText, but that may be
// redundant as an actual input method may take care of it.
- { QInputMethodEvent ev; QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev); }
+ { QInputMethodEvent ev; QGuiApplication::sendEvent(textEdit, &ev); }
// empty text with implicit alignment follows the system locale-based
// keyboard input direction from qApp->inputMethod()->inputDirection
platformInputContext.setInputDirection(Qt::LeftToRight);
QVERIFY(qApp->inputMethod()->inputDirection() == Qt::LeftToRight);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
- QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() < window.width()/2);
QSignalSpy cursorRectangleSpy(textEdit, SIGNAL(cursorRectangleChanged()));
QCOMPARE(cursorRectangleSpy.count(), 1);
QVERIFY(qApp->inputMethod()->inputDirection() == Qt::RightToLeft);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
+
+ // neutral text follows also input method direction
+ textEdit->resetHAlign();
+ textEdit->setText(" ()((=<>");
+ platformInputContext.setInputDirection(Qt::LeftToRight);
+ QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignLeft);
+ QVERIFY(textEdit->cursorRectangle().left() < window.width()/2);
+ platformInputContext.setInputDirection(Qt::RightToLeft);
+ QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight);
+ QVERIFY(textEdit->cursorRectangle().left() > window.width()/2);
// set input direction while having content
platformInputContext.setInputDirection(Qt::LeftToRight);
textEdit->setText("a");
textEdit->setCursorPosition(1);
platformInputContext.setInputDirection(Qt::RightToLeft);
- QTest::keyClick(&canvas, Qt::Key_Backspace);
+ QTest::keyClick(&window, Qt::Key_Backspace);
QVERIFY(textEdit->text().isEmpty());
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->cursorRectangle().left() > canvas.width()/2);
+ QVERIFY(textEdit->cursorRectangle().left() > window.width()/2);
// input direction changed while not having focus
platformInputContext.setInputDirection(Qt::LeftToRight);
platformInputContext.setInputDirection(Qt::RightToLeft);
textEdit->setFocus(true);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->cursorRectangle().left() > canvas.width()/2);
+ QVERIFY(textEdit->cursorRectangle().left() > window.width()/2);
textEdit->setHAlign(QQuickTextEdit::AlignRight);
QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
- QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+ QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
+
+ // make sure editor doesn't rely on input for updating size
+ QQuickTextEdit *emptyEdit = window.rootObject()->findChild<QQuickTextEdit*>("emptyTextEdit");
+ QVERIFY(emptyEdit != 0);
+ platformInputContext.setInputDirection(Qt::RightToLeft);
+ emptyEdit->setFocus(true);
+ QCOMPARE(emptyEdit->hAlign(), QQuickTextEdit::AlignRight);
+ QVERIFY(emptyEdit->cursorRectangle().left() > window.width()/2);
+}
+
+
+static int numberOfNonWhitePixels(int fromX, int toX, const QImage &image)
+{
+ int pixels = 0;
+ for (int x = fromX; x < toX; ++x) {
+ for (int y = 0; y < image.height(); ++y) {
+ if (image.pixel(x, y) != qRgb(255, 255, 255))
+ pixels++;
+ }
+ }
+ return pixels;
+}
+
+void tst_qquicktextedit::hAlignVisual()
+{
+ QQuickView view(testFileUrl("hAlignVisual.qml"));
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QQuickText *text = view.rootObject()->findChild<QQuickText*>("textItem");
+ QVERIFY(text != 0);
+ {
+ // Left Align
+ QImage image = view.grabWindow();
+ int left = numberOfNonWhitePixels(0, image.width() / 3, image);
+ int mid = numberOfNonWhitePixels(image.width() / 3, 2 * image.width() / 3, image);
+ int right = numberOfNonWhitePixels( 2 * image.width() / 3, image.width(), image);
+ QVERIFY(left > mid);
+ QVERIFY(mid > right);
+ }
+ {
+ // HCenter Align
+ text->setHAlign(QQuickText::AlignHCenter);
+ QImage image = view.grabWindow();
+ int left = numberOfNonWhitePixels(0, image.width() / 3, image);
+ int mid = numberOfNonWhitePixels(image.width() / 3, 2 * image.width() / 3, image);
+ int right = numberOfNonWhitePixels( 2 * image.width() / 3, image.width(), image);
+ QVERIFY(left < mid);
+ QVERIFY(mid > right);
+ }
+ {
+ // Right Align
+ text->setHAlign(QQuickText::AlignRight);
+ QImage image = view.grabWindow();
+ int left = numberOfNonWhitePixels(0, image.width() / 3, image);
+ int mid = numberOfNonWhitePixels(image.width() / 3, 2 * image.width() / 3, image);
+ int right = numberOfNonWhitePixels( 2 * image.width() / 3, image.width(), image);
+ QVERIFY(left < mid);
+ QVERIFY(mid < right);
+ }
+
+ text->setWidth(200);
+
+ {
+ // Left Align
+ QImage image = view.grabWindow();
+ int x = qCeil(text->implicitWidth());
+ int left = numberOfNonWhitePixels(0, x, image);
+ int right = numberOfNonWhitePixels(x, image.width() - x, image);
+ QVERIFY(left > 0);
+ QVERIFY(right == 0);
+ }
+ {
+ // HCenter Align
+ text->setHAlign(QQuickText::AlignHCenter);
+ QImage image = view.grabWindow();
+ int x1 = qFloor(image.width() - text->implicitWidth()) / 2;
+ int x2 = image.width() - x1;
+ int left = numberOfNonWhitePixels(0, x1, image);
+ int mid = numberOfNonWhitePixels(x1, x2 - x1, image);
+ int right = numberOfNonWhitePixels(x2, image.width() - x2, image);
+ QVERIFY(left == 0);
+ QVERIFY(mid > 0);
+ QVERIFY(right == 0);
+ }
+ {
+ // Right Align
+ text->setHAlign(QQuickText::AlignRight);
+ QImage image = view.grabWindow();
+ int x = image.width() - qCeil(text->implicitWidth());
+ int left = numberOfNonWhitePixels(0, x, image);
+ int right = numberOfNonWhitePixels(x, image.width() - x, image);
+ QVERIFY(left == 0);
+ QVERIFY(right > 0);
+ }
}
void tst_qquicktextedit::vAlign()
void tst_qquicktextedit::persistentSelection()
{
- QQuickView canvas(testFileUrl("persistentSelection.qml"));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
- canvas.requestActivateWindow();
-
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QQuickView window(testFileUrl("persistentSelection.qml"));
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
+
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(edit);
QVERIFY(edit->hasActiveFocus());
QCOMPARE(textEditObject->focusOnPress(), true);
QCOMPARE(activeFocusOnPressSpy.count(), 0);
- QQuickCanvas canvas;
- canvas.resize(100, 50);
- textEditObject->setParentItem(canvas.rootItem());
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+ QQuickWindow window;
+ window.resize(100, 50);
+ textEditObject->setParentItem(window.rootItem());
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
QCOMPARE(textEditObject->hasFocus(), false);
QCOMPARE(textEditObject->hasActiveFocus(), false);
- QPoint centerPoint(canvas.width()/2, canvas.height()/2);
+ QPoint centerPoint(window.width()/2, window.height()/2);
Qt::KeyboardModifiers noModifiers = 0;
- QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(textEditObject->hasFocus(), true);
QCOMPARE(textEditObject->hasActiveFocus(), true);
QCOMPARE(focusSpy.count(), 1);
QCOMPARE(activeFocusSpy.count(), 1);
QCOMPARE(textEditObject->selectedText(), QString());
- QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mouseRelease(&window, Qt::LeftButton, noModifiers, centerPoint);
textEditObject->setFocusOnPress(false);
QCOMPARE(textEditObject->focusOnPress(), false);
// Wait for double click timeout to expire before clicking again.
QTest::qWait(400);
- QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(textEditObject->hasFocus(), false);
QCOMPARE(textEditObject->hasActiveFocus(), false);
QCOMPARE(focusSpy.count(), 2);
QCOMPARE(activeFocusSpy.count(), 2);
- QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mouseRelease(&window, Qt::LeftButton, noModifiers, centerPoint);
textEditObject->setFocusOnPress(true);
QCOMPARE(textEditObject->focusOnPress(), true);
textEditObject->setProperty("selectOnFocus", true);
QTest::qWait(400);
- QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(textEditObject->hasFocus(), true);
QCOMPARE(textEditObject->hasActiveFocus(), true);
QCOMPARE(focusSpy.count(), 3);
QCOMPARE(activeFocusSpy.count(), 3);
QCOMPARE(textEditObject->selectedText(), textEditObject->text());
- QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+ QTest::mouseRelease(&window, Qt::LeftButton, noModifiers, centerPoint);
}
void tst_qquicktextedit::selection()
void tst_qquicktextedit::keySelection()
{
- QQuickView canvas(testFileUrl("navigation.qml"));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
- canvas.requestActivateWindow();
+ QQuickView window(testFileUrl("navigation.qml"));
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
- QVERIFY(canvas.rootObject() != 0);
+ QVERIFY(window.rootObject() != 0);
- QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+ QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
QVERIFY(input != 0);
- QTRY_VERIFY(input->hasActiveFocus() == true);
+ QVERIFY(input->hasActiveFocus());
- QSignalSpy spy(input, SIGNAL(selectionChanged()));
+ QSignalSpy spy(input, SIGNAL(selectedTextChanged()));
- simulateKey(&canvas, Qt::Key_Right, Qt::ShiftModifier);
+ simulateKey(&window, Qt::Key_Right, Qt::ShiftModifier);
QVERIFY(input->hasActiveFocus() == true);
QCOMPARE(input->selectedText(), QString("a"));
QCOMPARE(spy.count(), 1);
- simulateKey(&canvas, Qt::Key_Right);
+ simulateKey(&window, Qt::Key_Right);
QVERIFY(input->hasActiveFocus() == true);
QCOMPARE(input->selectedText(), QString());
QCOMPARE(spy.count(), 2);
- simulateKey(&canvas, Qt::Key_Right);
+ simulateKey(&window, Qt::Key_Right);
QVERIFY(input->hasActiveFocus() == false);
QCOMPARE(input->selectedText(), QString());
QCOMPARE(spy.count(), 2);
- simulateKey(&canvas, Qt::Key_Left);
+ simulateKey(&window, Qt::Key_Left);
QVERIFY(input->hasActiveFocus() == true);
QCOMPARE(spy.count(), 2);
- simulateKey(&canvas, Qt::Key_Left, Qt::ShiftModifier);
+ simulateKey(&window, Qt::Key_Left, Qt::ShiftModifier);
QVERIFY(input->hasActiveFocus() == true);
QCOMPARE(input->selectedText(), QString("a"));
QCOMPARE(spy.count(), 3);
- simulateKey(&canvas, Qt::Key_Left);
+ simulateKey(&window, Qt::Key_Left);
QVERIFY(input->hasActiveFocus() == true);
QCOMPARE(input->selectedText(), QString());
QCOMPARE(spy.count(), 4);
- simulateKey(&canvas, Qt::Key_Left);
+ simulateKey(&window, Qt::Key_Left);
QVERIFY(input->hasActiveFocus() == false);
QCOMPARE(input->selectedText(), QString());
QCOMPARE(spy.count(), 4);
QTest::addColumn<QString>("selectedText");
QTest::addColumn<bool>("focus");
QTest::addColumn<bool>("focusOnPress");
- QTest::addColumn<bool>("doubleClick");
+ QTest::addColumn<int>("clicks");
// import installed
- QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << true << true << false;
- QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString() << true << true << false;
- QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString() << true << true << false;
- QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString() << true << true << false;
- QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << true << true << false;
-
- QTest::newRow("on unfocused") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << false << false;
- QTest::newRow("on word selection (4,9) unfocused") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << false << false;
-
- QTest::newRow("on focus on press") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << true << false;
- QTest::newRow("on word selection (4,9) focus on press") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << true << false;
-
- QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
- QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
- QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
- QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
- QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
- QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
- QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
- QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
-
- QTest::newRow("off double click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789" << true << true << true;
- QTest::newRow("off double click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
- QTest::newRow("off double click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
- QTest::newRow("off double click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
- QTest::newRow("off double click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
- QTest::newRow("off double click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
- QTest::newRow("off double click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
- QTest::newRow("off double click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
- QTest::newRow("off double click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
+ QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << true << true << 1;
+ QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString() << true << true << 1;
+ QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString() << true << true << 1;
+ QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString() << true << true << 1;
+ QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << true << true << 1;
+
+ QTest::newRow("on unfocused") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << false << 1;
+ QTest::newRow("on word selection (4,9) unfocused") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << false << 1;
+
+ QTest::newRow("on focus on press") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << true << 1;
+ QTest::newRow("on word selection (4,9) focus on press") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << true << 1;
+
+ QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+ QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+
+ QTest::newRow("on double click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789" << true << true << 2;
+ QTest::newRow("on double click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+ QTest::newRow("on double click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+
+ QTest::newRow("on triple click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+ QTest::newRow("on triple click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+
+ QTest::newRow("on triple click (2,40)") << testFile("mouseselection_true.qml") << 2 << 40 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n" << true << true << 3;
+ QTest::newRow("on triple click (2,50)") << testFile("mouseselection_true.qml") << 2 << 50 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+ QTest::newRow("on triple click (25,40)") << testFile("mouseselection_true.qml") << 25 << 40 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n" << true << true << 3;
+ QTest::newRow("on triple click (25,50)") << testFile("mouseselection_true.qml") << 25 << 50 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+ QTest::newRow("on triple click (40,25)") << testFile("mouseselection_true.qml") << 40 << 25 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n" << true << true << 3;
+ QTest::newRow("on triple click (40,50)") << testFile("mouseselection_true.qml") << 40 << 50 << "9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+ QTest::newRow("on triple click (50,25)") << testFile("mouseselection_true.qml") << 50 << 25 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+ QTest::newRow("on triple click (50,40)") << testFile("mouseselection_true.qml") << 50 << 40 << "9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+
+ QTest::newRow("on tr align") << testFile("mouseselection_align_tr.qml") << 4 << 9 << "45678" << true << true << 1;
+ QTest::newRow("on center align") << testFile("mouseselection_align_center.qml") << 4 << 9 << "45678" << true << true << 1;
+ QTest::newRow("on bl align") << testFile("mouseselection_align_bl.qml") << 4 << 9 << "45678" << true << true << 1;
}
void tst_qquicktextedit::mouseSelection()
QFETCH(QString, selectedText);
QFETCH(bool, focus);
QFETCH(bool, focusOnPress);
- QFETCH(bool, doubleClick);
+ QFETCH(int, clicks);
- QQuickView canvas(QUrl::fromLocalFile(qmlfile));
+ QQuickView window(QUrl::fromLocalFile(qmlfile));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QVERIFY(window.rootObject() != 0);
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(textEditObject != 0);
textEditObject->setFocus(focus);
// press-and-drag-and-release from x1 to x2
QPoint p1 = textEditObject->positionToRectangle(from).center().toPoint();
QPoint p2 = textEditObject->positionToRectangle(to).center().toPoint();
- if (doubleClick)
- QTest::mouseClick(&canvas, Qt::LeftButton, 0, p1);
- QTest::mousePress(&canvas, Qt::LeftButton, 0, p1);
- QTest::mouseMove(&canvas, p2);
- QTest::mouseRelease(&canvas, Qt::LeftButton, 0, p2);
- QTest::qWait(50);
+ if (clicks == 2)
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
+ else if (clicks == 3)
+ QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTest::mouseMove(&window, p2);
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p2);
QTRY_COMPARE(textEditObject->selectedText(), selectedText);
// Clicking and shift to clicking between the same points should select the same text.
textEditObject->setCursorPosition(0);
- if (doubleClick)
- QTest::mouseDClick(&canvas, Qt::LeftButton, 0, p1);
- else
- QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, p1);
- QTest::mouseClick(&canvas, Qt::LeftButton, Qt::ShiftModifier, p2);
- QTest::qWait(50);
+ if (clicks > 1)
+ QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
+ if (clicks != 2)
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::ShiftModifier, p2);
QTRY_COMPARE(textEditObject->selectedText(), selectedText);
+
+ // ### This is to prevent double click detection from carrying over to the next test.
+ QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 10);
}
void tst_qquicktextedit::dragMouseSelection()
{
QString qmlfile = testFile("mouseselection_true.qml");
- QQuickView canvas(QUrl::fromLocalFile(qmlfile));
+ QQuickView window(QUrl::fromLocalFile(qmlfile));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QVERIFY(window.rootObject() != 0);
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(textEditObject != 0);
// press-and-drag-and-release from x1 to x2
int x1 = 10;
int x2 = 70;
- int y = textEditObject->height()/2;
- QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
- QTest::mouseMove(&canvas, QPoint(x2, y));
- QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
+ int y = QFontMetrics(textEditObject->font()).height() / 2;
+ QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mouseMove(&window, QPoint(x2, y));
+ QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y));
QTest::qWait(300);
QString str1;
QTRY_VERIFY((str1 = textEditObject->selectedText()).length() > 3);
// press and drag the current selection.
x1 = 40;
x2 = 100;
- QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
- QTest::mouseMove(&canvas, QPoint(x2, y));
- QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mouseMove(&window, QPoint(x2, y));
+ QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y));
QTest::qWait(300);
QString str2;
QTRY_VERIFY((str2 = textEditObject->selectedText()).length() > 3);
QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and not the first moved.
+
}
void tst_qquicktextedit::mouseSelectionMode_data()
QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QQuickView canvas(QUrl::fromLocalFile(qmlfile));
+ QQuickView window(QUrl::fromLocalFile(qmlfile));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QVERIFY(window.rootObject() != 0);
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(textEditObject != 0);
// press-and-drag-and-release from x1 to x2
int x1 = 10;
int x2 = 70;
int y = textEditObject->height()/2;
- QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
- QTest::mouseMove(&canvas, QPoint(x2, y));
- //QTest::mouseMove(canvas, QPoint(x2,y)); // doesn't work
-// QMouseEvent mv(QEvent::MouseMove, QPoint(x2,y), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
-// QGuiApplication::sendEvent(&canvas, &mv);
- QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mouseMove(&window, QPoint(x2, y));
+ QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y));
QString str = textEditObject->selectedText();
if (selectWords) {
QTRY_COMPARE(textEditObject->selectedText(), text);
void tst_qquicktextedit::inputMethodHints()
{
- QQuickView canvas(testFileUrl("inputmethodhints.qml"));
- canvas.show();
- canvas.requestActivateWindow();
+ QQuickView window(testFileUrl("inputmethodhints.qml"));
+ window.show();
+ window.requestActivateWindow();
- QVERIFY(canvas.rootObject() != 0);
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QVERIFY(window.rootObject() != 0);
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(textEditObject != 0);
QVERIFY(textEditObject->inputMethodHints() & Qt::ImhNoPredictiveText);
QSignalSpy inputMethodHintSpy(textEditObject, SIGNAL(inputMethodHintsChanged()));
QCOMPARE(plainTextEdit.inputMethodHints(), Qt::ImhNone);
}
+void tst_qquicktextedit::positionAt_data()
+{
+ QTest::addColumn<QQuickTextEdit::HAlignment>("horizontalAlignment");
+ QTest::addColumn<QQuickTextEdit::VAlignment>("verticalAlignment");
+
+ QTest::newRow("top-left") << QQuickTextEdit::AlignLeft << QQuickTextEdit::AlignTop;
+ QTest::newRow("bottom-left") << QQuickTextEdit::AlignLeft << QQuickTextEdit::AlignBottom;
+ QTest::newRow("center-left") << QQuickTextEdit::AlignLeft << QQuickTextEdit::AlignVCenter;
+
+ QTest::newRow("top-right") << QQuickTextEdit::AlignRight << QQuickTextEdit::AlignTop;
+ QTest::newRow("top-center") << QQuickTextEdit::AlignHCenter << QQuickTextEdit::AlignTop;
+
+ QTest::newRow("center") << QQuickTextEdit::AlignHCenter << QQuickTextEdit::AlignVCenter;
+}
+
void tst_qquicktextedit::positionAt()
{
- QQuickView canvas(testFileUrl("positionAt.qml"));
- QVERIFY(canvas.rootObject() != 0);
- canvas.show();
- canvas.requestActivateWindow();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
-
- QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QFETCH(QQuickTextEdit::HAlignment, horizontalAlignment);
+ QFETCH(QQuickTextEdit::VAlignment, verticalAlignment);
+
+ QQuickView window(testFileUrl("positionAt.qml"));
+ QVERIFY(window.rootObject() != 0);
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
+
+ QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(texteditObject != 0);
+ texteditObject->setHAlign(horizontalAlignment);
+ texteditObject->setVAlign(verticalAlignment);
- QTextLayout layout(texteditObject->text());
+ QTextLayout layout(texteditObject->text().replace(QLatin1Char('\n'), QChar::LineSeparator));
layout.setFont(texteditObject->font());
if (!qmlDisableDistanceField()) {
layout.beginLayout();
QTextLine line = layout.createLine();
+ line.setLineWidth(texteditObject->width());
+ QTextLine secondLine = layout.createLine();
+ secondLine.setLineWidth(texteditObject->width());
layout.endLayout();
- const int y0 = line.height() / 2;
- const int y1 = line.height() * 3 / 2;
+ qreal y0;
+ qreal y1;
+
+ switch (verticalAlignment) {
+ case QQuickTextEdit::AlignTop:
+ y0 = line.height() / 2;
+ y1 = line.height() * 3 / 2;
+ break;
+ case QQuickTextEdit::AlignVCenter:
+ y0 = (texteditObject->height() - line.height()) / 2;
+ y1 = (texteditObject->height() + line.height()) / 2;
+ break;
+ case QQuickTextEdit::AlignBottom:
+ y0 = texteditObject->height() - line.height() * 3 / 2;
+ y1 = texteditObject->height() - line.height() / 2;
+ break;
+ }
+ qreal xoff;
+ switch (horizontalAlignment) {
+ case QQuickTextEdit::AlignLeft:
+ xoff = 0;
+ break;
+ case QQuickTextEdit::AlignHCenter:
+ xoff = (texteditObject->width() - secondLine.naturalTextWidth()) / 2;
+ break;
+ case QQuickTextEdit::AlignRight:
+ xoff = texteditObject->width() - secondLine.naturalTextWidth();
+ break;
+ }
int pos = texteditObject->positionAt(texteditObject->width()/2, y0);
- int widthBegin = floor(line.cursorToX(pos - 1));
- int widthEnd = ceil(line.cursorToX(pos + 1));
+ int widthBegin = floor(xoff + line.cursorToX(pos - 1));
+ int widthEnd = ceil(xoff + line.cursorToX(pos + 1));
QVERIFY(widthBegin <= texteditObject->width() / 2);
QVERIFY(widthEnd >= texteditObject->width() / 2);
texteditObject->setCursorPosition(0);
QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
- QGuiApplication::sendEvent(qGuiApp->focusObject(), &inputEvent);
+ QGuiApplication::sendEvent(texteditObject, &inputEvent);
// Check all points within the preedit text return the same position.
QCOMPARE(texteditObject->positionAt(0, y0), 0);
void tst_qquicktextedit::linkActivated()
{
- QQuickView canvas(testFileUrl("linkActivated.qml"));
- QVERIFY(canvas.rootObject() != 0);
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
+ QQuickView window(testFileUrl("linkActivated.qml"));
+ QVERIFY(window.rootObject() != 0);
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
- QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(texteditObject != 0);
QSignalSpy spy(texteditObject, SIGNAL(linkActivated(QString)));
const QPointF linkPos = texteditObject->positionToRectangle(7).center();
const QPointF textPos = texteditObject->positionToRectangle(2).center();
- QTest::mouseClick(&canvas, Qt::LeftButton, 0, linkPos.toPoint());
+ QTest::mouseClick(&window, Qt::LeftButton, 0, linkPos.toPoint());
QTRY_COMPARE(spy.count(), 1);
QCOMPARE(spy.last()[0].toString(), link);
- QTest::mouseClick(&canvas, Qt::LeftButton, 0, textPos.toPoint());
+ QTest::mouseClick(&window, Qt::LeftButton, 0, textPos.toPoint());
QTest::qWait(50);
QCOMPARE(spy.count(), 1);
texteditObject->setReadOnly(true);
- QTest::mouseClick(&canvas, Qt::LeftButton, 0, linkPos.toPoint());
+ QTest::mouseClick(&window, Qt::LeftButton, 0, linkPos.toPoint());
QTRY_COMPARE(spy.count(), 2);
QCOMPARE(spy.last()[0].toString(), link);
- QTest::mouseClick(&canvas, Qt::LeftButton, 0, textPos.toPoint());
+ QTest::mouseClick(&window, Qt::LeftButton, 0, textPos.toPoint());
QTest::qWait(50);
QCOMPARE(spy.count(), 2);
}
view.requestActivateWindow();
QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
QVERIFY(textEditObject != 0);
- QVERIFY(textEditObject->findChild<QQuickItem*>("cursorInstance"));
+ // Delegate creation is deferred until focus in or cursor visiblity is forced.
+ QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
+ QVERIFY(!textEditObject->isCursorVisible());
//Test Delegate gets created
textEditObject->setFocus(true);
+ QVERIFY(textEditObject->isCursorVisible());
QQuickItem* delegateObject = textEditObject->findChild<QQuickItem*>("cursorInstance");
QVERIFY(delegateObject);
QCOMPARE(delegateObject->property("localProperty").toString(), QString("Hello"));
QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
}
- // Clear preedit text;
- QInputMethodEvent event;
- QGuiApplication::sendEvent(&view, &event);
-
// Test delegate gets moved on mouse press.
textEditObject->setSelectByMouse(true);
textEditObject->setCursorPosition(0);
QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
+
+ textEditObject->setReadOnly(false);
+
+ // Delegate moved when text is entered
+ textEditObject->setText(QString());
+ for (int i = 0; i < 20; ++i) {
+ QTest::keyClick(&view, Qt::Key_A);
+ QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
+ QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
+ }
+
+ // Delegate moved when text is entered by im.
+ textEditObject->setText(QString());
+ for (int i = 0; i < 20; ++i) {
+ QInputMethodEvent event;
+ event.setCommitString("a");
+ QGuiApplication::sendEvent(textEditObject, &event);
+ QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
+ QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
+ }
+ // Delegate moved when text is removed by im.
+ for (int i = 19; i > 1; --i) {
+ QInputMethodEvent event;
+ event.setCommitString(QString(), -1, 1);
+ QGuiApplication::sendEvent(textEditObject, &event);
+ QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
+ QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
+ }
+ { // Delegate moved the text is changed in place by im.
+ QInputMethodEvent event;
+ event.setCommitString("i", -1, 1);
+ QGuiApplication::sendEvent(textEditObject, &event);
+ QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
+ QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
+ }
+
//Test Delegate gets deleted
textEditObject->setCursorDelegate(0);
QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
}
+void tst_qquicktextedit::remoteCursorDelegate()
+{
+ TestHTTPServer server(SERVER_PORT);
+ server.serveDirectory(dataDirectory());
+
+ QQuickView view;
+
+ QQmlComponent component(view.engine(), QUrl(SERVER_ADDR "/RemoteCursor.qml"));
+
+ view.rootContext()->setContextProperty("contextDelegate", &component);
+ view.setSource(testFileUrl("cursorTestRemote.qml"));
+ view.show();
+ view.requestActivateWindow();
+ QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
+ QVERIFY(textEditObject != 0);
+
+ // Delegate is created on demand, and so won't be available immediately. Focus in or
+ // setCursorVisible(true) will trigger creation.
+ QTRY_VERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
+ QVERIFY(!textEditObject->isCursorVisible());
+
+ textEditObject->setFocus(true);
+ QVERIFY(textEditObject->isCursorVisible());
+
+ QCOMPARE(component.status(), QQmlComponent::Loading);
+ QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
+
+ // Wait for component to load.
+ QTRY_COMPARE(component.status(), QQmlComponent::Ready);
+ QVERIFY(textEditObject->findChild<QQuickItem*>("cursorInstance"));
+}
+
void tst_qquicktextedit::cursorVisible()
{
QQuickTextEdit edit;
QQuickView view(testFileUrl("cursorVisible.qml"));
view.show();
view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ QTest::qWaitForWindowActive(&view);
+ QCOMPARE(&view, qGuiApp->focusWindow());
QCOMPARE(edit.isCursorVisible(), false);
QWindow alternateView;
alternateView.show();
alternateView.requestActivateWindow();
- QTest::qWaitForWindowShown(&alternateView);
+ QTest::qWaitForWindowActive(&alternateView);
QCOMPARE(edit.isCursorVisible(), false);
QCOMPARE(spy.count(), 6);
view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
+ QTest::qWaitForWindowActive(&view);
QCOMPARE(edit.isCursorVisible(), true);
QCOMPARE(spy.count(), 7);
void tst_qquicktextedit::delegateLoading()
{
-#ifdef Q_OS_MAC
- QSKIP("Test crashes during canvas tear down. QTBUG-23010");
-#endif
QFETCH(QString, qmlfile);
QFETCH(QString, error);
- TestHTTPServer server(42332);
+ TestHTTPServer server(SERVER_PORT);
server.serveDirectory(testFile("httpfail"), TestHTTPServer::Disconnect);
server.serveDirectory(testFile("httpslow"), TestHTTPServer::Delay);
server.serveDirectory(testFile("http"));
- QQuickView view(QUrl(QLatin1String("http://localhost:42332/") + qmlfile));
+ QQuickView view(QUrl(QLatin1String(SERVER_ADDR "/") + qmlfile));
view.show();
view.requestActivateWindow();
*/
void tst_qquicktextedit::navigation()
{
- QQuickView canvas(testFileUrl("navigation.qml"));
- canvas.show();
- canvas.requestActivateWindow();
+ QQuickView window(testFileUrl("navigation.qml"));
+ window.show();
+ window.requestActivateWindow();
- QVERIFY(canvas.rootObject() != 0);
+ QVERIFY(window.rootObject() != 0);
- QQuickItem *input = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+ QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
QVERIFY(input != 0);
QTRY_VERIFY(input->hasActiveFocus() == true);
- simulateKey(&canvas, Qt::Key_Left);
+ simulateKey(&window, Qt::Key_Left);
QVERIFY(input->hasActiveFocus() == false);
- simulateKey(&canvas, Qt::Key_Right);
+ simulateKey(&window, Qt::Key_Right);
QVERIFY(input->hasActiveFocus() == true);
- simulateKey(&canvas, Qt::Key_Right);
+ simulateKey(&window, Qt::Key_Right);
QVERIFY(input->hasActiveFocus() == true);
- simulateKey(&canvas, Qt::Key_Right);
+ simulateKey(&window, Qt::Key_Right);
QVERIFY(input->hasActiveFocus() == false);
- simulateKey(&canvas, Qt::Key_Left);
+ simulateKey(&window, Qt::Key_Left);
QVERIFY(input->hasActiveFocus() == true);
+
+ // Test left and right navigation works if the TextEdit is empty (QTBUG-25447).
+ input->setText(QString());
+ QCOMPARE(input->cursorPosition(), 0);
+ simulateKey(&window, Qt::Key_Right);
+ QCOMPARE(input->hasActiveFocus(), false);
+ simulateKey(&window, Qt::Key_Left);
+ QCOMPARE(input->hasActiveFocus(), true);
+ simulateKey(&window, Qt::Key_Left);
+ QCOMPARE(input->hasActiveFocus(), false);
}
void tst_qquicktextedit::copyAndPaste() {
QVERIFY(textEdit != 0);
// check initial value - QTBUG-17765
- QQuickTextControl tc(0);
+ QTextDocument document;
+ QQuickTextControl tc(&document);
QCOMPARE(textEdit->canPaste(), tc.canPaste());
#endif
QVERIFY(textEdit != 0);
// check initial value - QTBUG-17765
- QQuickTextControl tc(0);
+ QTextDocument document;
+ QQuickTextControl tc(&document);
QCOMPARE(textEdit->canPaste(), tc.canPaste());
#endif
void tst_qquicktextedit::readOnly()
{
- QQuickView canvas(testFileUrl("readOnly.qml"));
- canvas.show();
- canvas.requestActivateWindow();
+ QQuickView window(testFileUrl("readOnly.qml"));
+ window.show();
+ window.requestActivateWindow();
- QVERIFY(canvas.rootObject() != 0);
+ QVERIFY(window.rootObject() != 0);
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
QVERIFY(edit != 0);
QTRY_VERIFY(edit->hasActiveFocus() == true);
QVERIFY(edit->isReadOnly() == true);
QString initial = edit->text();
for (int k=Qt::Key_0; k<=Qt::Key_Z; k++)
- simulateKey(&canvas, k);
- simulateKey(&canvas, Qt::Key_Return);
- simulateKey(&canvas, Qt::Key_Space);
- simulateKey(&canvas, Qt::Key_Escape);
+ simulateKey(&window, k);
+ simulateKey(&window, Qt::Key_Return);
+ simulateKey(&window, Qt::Key_Space);
+ simulateKey(&window, Qt::Key_Escape);
QCOMPARE(edit->text(), initial);
edit->setCursorPosition(3);
QQuickView view(testFileUrl("inputMethodEvent.qml"));
view.show();
view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ QTest::qWaitForWindowActive(&view);
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
QVERIFY(edit->hasActiveFocus() == true);
QSignalSpy spy(edit, SIGNAL(textChanged()));
QInputMethodEvent event;
event.setCommitString( "Hello world!", 0, 0);
- QGuiApplication::sendEvent(qGuiApp->focusObject(), &event);
+ QGuiApplication::sendEvent(edit, &event);
QCOMPARE(edit->text(), QString("Hello world!"));
QCOMPARE(spy.count(), 1);
QCOMPARE(editPrivate->text, QString("Hello world!"));
QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- QGuiApplication::sendEvent(qGuiApp->focusObject(), &queryEvent);
+ QGuiApplication::sendEvent(edit, &queryEvent);
QCOMPARE(queryEvent.value(Qt::ImEnabled).toBool(), true);
edit->setReadOnly(true);
QQuickView view(testFileUrl("inputMethodEvent.qml"));
view.show();
view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ QTest::qWaitForWindowActive(&view);
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
QVERIFY(edit->hasActiveFocus() == true);
QQuickView view(testFileUrl("openInputPanel.qml"));
view.show();
view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ QTest::qWaitForWindowActive(&view);
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
// check default values
QVERIFY(edit->focusOnPress());
QVERIFY(!edit->hasActiveFocus());
- qDebug() << &edit << qApp->focusObject();
QVERIFY(qApp->focusObject() != edit);
- QCOMPARE(qApp->inputMethod()->visible(), false);
+ QCOMPARE(qApp->inputMethod()->isVisible(), false);
// input panel should open on focus
QPoint centerPoint(view.width()/2, view.height()/2);
QGuiApplication::processEvents();
QVERIFY(edit->hasActiveFocus());
QCOMPARE(qApp->focusObject(), edit);
- QCOMPARE(qApp->inputMethod()->visible(), true);
+ QCOMPARE(qApp->inputMethod()->isVisible(), true);
QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
// input panel should be re-opened when pressing already focused TextEdit
qApp->inputMethod()->hide();
- QCOMPARE(qApp->inputMethod()->visible(), false);
+ QCOMPARE(qApp->inputMethod()->isVisible(), false);
QVERIFY(edit->hasActiveFocus());
QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
- QCOMPARE(qApp->inputMethod()->visible(), true);
+ QCOMPARE(qApp->inputMethod()->isVisible(), true);
QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
// input panel should stay visible if focus is lost to another text editor
QQuickTextEdit anotherEdit;
anotherEdit.setParentItem(view.rootObject());
anotherEdit.setFocus(true);
- QCOMPARE(qApp->inputMethod()->visible(), true);
+ QCOMPARE(qApp->inputMethod()->isVisible(), true);
QCOMPARE(qApp->focusObject(), qobject_cast<QObject*>(&anotherEdit));
QCOMPARE(inputPanelVisibilitySpy.count(), 0);
// input panel should not be opened if TextEdit is read only
edit->setReadOnly(true);
edit->setFocus(true);
- QCOMPARE(qApp->inputMethod()->visible(), false);
+ QCOMPARE(qApp->inputMethod()->isVisible(), false);
QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
- QCOMPARE(qApp->inputMethod()->visible(), false);
+ QCOMPARE(qApp->inputMethod()->isVisible(), false);
// input panel should not be opened if focusOnPress is set to false
edit->setFocusOnPress(false);
edit->setFocus(false);
edit->setFocus(true);
- QCOMPARE(qApp->inputMethod()->visible(), false);
+ QCOMPARE(qApp->inputMethod()->isVisible(), false);
QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
- QCOMPARE(qApp->inputMethod()->visible(), false);
-
- // input panel should open when openSoftwareInputPanel is called
- edit->openSoftwareInputPanel();
- QCOMPARE(qApp->inputMethod()->visible(), true);
-
- // input panel should close when closeSoftwareInputPanel is called
- edit->closeSoftwareInputPanel();
- QCOMPARE(qApp->inputMethod()->visible(), false);
+ QCOMPARE(qApp->inputMethod()->isVisible(), false);
inputMethodPrivate->testContext = 0;
}
QCOMPARE(textObject->height(), textObject->implicitHeight());
}
+void tst_qquicktextedit::clipRect()
+{
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\n TextEdit {}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(object.data());
+ QVERIFY(edit);
+
+ QCOMPARE(edit->clipRect().x(), qreal(0));
+ QCOMPARE(edit->clipRect().y(), qreal(0));
+
+ QCOMPARE(edit->clipRect().width(), edit->width() + edit->cursorRectangle().width());
+ QCOMPARE(edit->clipRect().height(), edit->height());
+
+ edit->setText("Hello World");
+ QCOMPARE(edit->clipRect().x(), qreal(0));
+ QCOMPARE(edit->clipRect().y(), qreal(0));
+ // XXX: TextEdit allows an extra 3 pixels boundary for the cursor beyond it's width for non
+ // empty text. TextInput doesn't.
+ QCOMPARE(edit->clipRect().width(), edit->width() + edit->cursorRectangle().width() + 3);
+ QCOMPARE(edit->clipRect().height(), edit->height());
+
+ // clip rect shouldn't exceed the size of the item, expect for the cursor width;
+ edit->setWidth(edit->width() / 2);
+ QCOMPARE(edit->clipRect().x(), qreal(0));
+ QCOMPARE(edit->clipRect().y(), qreal(0));
+ QCOMPARE(edit->clipRect().width(), edit->width() + edit->cursorRectangle().width() + 3);
+ QCOMPARE(edit->clipRect().height(), edit->height());
+
+ edit->setHeight(edit->height() * 2);
+ QCOMPARE(edit->clipRect().x(), qreal(0));
+ QCOMPARE(edit->clipRect().y(), qreal(0));
+ QCOMPARE(edit->clipRect().width(), edit->width() + edit->cursorRectangle().width() + 3);
+ QCOMPARE(edit->clipRect().height(), edit->height());
+
+ QQmlComponent cursorComponent(&engine);
+ cursorComponent.setData("import QtQuick 2.0\nRectangle { height: 20; width: 8 }", QUrl());
+
+ edit->setCursorDelegate(&cursorComponent);
+ edit->setCursorVisible(true);
+
+ // If a cursor delegate is used it's size should determine the excess width.
+ QCOMPARE(edit->clipRect().x(), qreal(0));
+ QCOMPARE(edit->clipRect().y(), qreal(0));
+ QCOMPARE(edit->clipRect().width(), edit->width() + 8 + 3);
+ QCOMPARE(edit->clipRect().height(), edit->height());
+
+ // Alignment and wrapping don't affect the clip rect.
+ edit->setHAlign(QQuickTextEdit::AlignRight);
+ QCOMPARE(edit->clipRect().x(), qreal(0));
+ QCOMPARE(edit->clipRect().y(), qreal(0));
+ QCOMPARE(edit->clipRect().width(), edit->width() + 8 + 3);
+ QCOMPARE(edit->clipRect().height(), edit->height());
+
+ edit->setWrapMode(QQuickTextEdit::Wrap);
+ QCOMPARE(edit->clipRect().x(), qreal(0));
+ QCOMPARE(edit->clipRect().y(), qreal(0));
+ QCOMPARE(edit->clipRect().width(), edit->width() + 8 + 3);
+ QCOMPARE(edit->clipRect().height(), edit->height());
+
+ edit->setVAlign(QQuickTextEdit::AlignBottom);
+ QCOMPARE(edit->clipRect().x(), qreal(0));
+ QCOMPARE(edit->clipRect().y(), qreal(0));
+ QCOMPARE(edit->clipRect().width(), edit->width() + 8 + 3);
+ QCOMPARE(edit->clipRect().height(), edit->height());
+}
+
+void tst_qquicktextedit::boundingRect()
+{
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\n TextEdit {}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(object.data());
+ QVERIFY(edit);
+
+ QTextLayout layout;
+ layout.setFont(edit->font());
+
+ if (!qmlDisableDistanceField()) {
+ QTextOption option;
+ option.setUseDesignMetrics(true);
+ layout.setTextOption(option);
+ }
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ QCOMPARE(edit->boundingRect().x(), qreal(0));
+ QCOMPARE(edit->boundingRect().y(), qreal(0));
+ QCOMPARE(edit->boundingRect().width(), edit->cursorRectangle().width());
+ QCOMPARE(edit->boundingRect().height(), line.height());
+
+ edit->setText("Hello World");
+
+ layout.setText(edit->text());
+ layout.beginLayout();
+ line = layout.createLine();
+ layout.endLayout();
+
+ QCOMPARE(edit->boundingRect().x(), qreal(0));
+ QCOMPARE(edit->boundingRect().y(), qreal(0));
+ QCOMPARE(edit->boundingRect().width(), line.naturalTextWidth() + edit->cursorRectangle().width() + 3);
+ QCOMPARE(edit->boundingRect().height(), line.height());
+
+ // the size of the bounding rect shouldn't be bounded by the size of item.
+ edit->setWidth(edit->width() / 2);
+ QCOMPARE(edit->boundingRect().x(), qreal(0));
+ QCOMPARE(edit->boundingRect().y(), qreal(0));
+ QCOMPARE(edit->boundingRect().width(), line.naturalTextWidth() + edit->cursorRectangle().width() + 3);
+ QCOMPARE(edit->boundingRect().height(), line.height());
+
+ edit->setHeight(edit->height() * 2);
+ QCOMPARE(edit->boundingRect().x(), qreal(0));
+ QCOMPARE(edit->boundingRect().y(), qreal(0));
+ QCOMPARE(edit->boundingRect().width(), line.naturalTextWidth() + edit->cursorRectangle().width() + 3);
+ QCOMPARE(edit->boundingRect().height(), line.height());
+
+ QQmlComponent cursorComponent(&engine);
+ cursorComponent.setData("import QtQuick 2.0\nRectangle { height: 20; width: 8 }", QUrl());
+
+ edit->setCursorDelegate(&cursorComponent);
+ edit->setCursorVisible(true);
+
+ // Don't include the size of a cursor delegate as it has its own bounding rect.
+ QCOMPARE(edit->boundingRect().x(), qreal(0));
+ QCOMPARE(edit->boundingRect().y(), qreal(0));
+ QCOMPARE(edit->boundingRect().width(), line.naturalTextWidth());
+ QCOMPARE(edit->boundingRect().height(), line.height());
+
+ edit->setHAlign(QQuickTextEdit::AlignRight);
+ QCOMPARE(edit->boundingRect().x(), edit->width() - line.naturalTextWidth());
+ QCOMPARE(edit->boundingRect().y(), qreal(0));
+ QCOMPARE(edit->boundingRect().width(), line.naturalTextWidth());
+ QCOMPARE(edit->boundingRect().height(), line.height());
+
+ edit->setWrapMode(QQuickTextEdit::Wrap);
+ QCOMPARE(edit->boundingRect().right(), edit->width());
+ QCOMPARE(edit->boundingRect().y(), qreal(0));
+ QVERIFY(edit->boundingRect().width() < line.naturalTextWidth());
+ QVERIFY(edit->boundingRect().height() > line.height());
+
+ edit->setVAlign(QQuickTextEdit::AlignBottom);
+ QCOMPARE(edit->boundingRect().right(), edit->width());
+ QCOMPARE(edit->boundingRect().bottom(), edit->height());
+ QVERIFY(edit->boundingRect().width() < line.naturalTextWidth());
+ QVERIFY(edit->boundingRect().height() > line.height());
+}
+
void tst_qquicktextedit::preeditCursorRectangle()
{
QString preeditText = "super";
QQuickView view(testFileUrl("inputMethodEvent.qml"));
view.show();
view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
+ QTest::qWaitForWindowActive(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
+ QQuickItem *cursor = edit->findChild<QQuickItem *>("cursor");
+ QVERIFY(cursor);
+
QSignalSpy editSpy(edit, SIGNAL(cursorRectangleChanged()));
QSignalSpy panelSpy(qGuiApp->inputMethod(), SIGNAL(cursorRectangleChanged()));
- QRect currentRect;
+ QRectF currentRect;
+ QCOMPARE(QGuiApplication::focusObject(), static_cast<QObject *>(edit));
QInputMethodQueryEvent query(Qt::ImCursorRectangle);
- QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
- QRect previousRect = query.value(Qt::ImCursorRectangle).toRect();
+ QCoreApplication::sendEvent(edit, &query);
+ QRectF previousRect = query.value(Qt::ImCursorRectangle).toRectF();
// Verify that the micro focus rect is positioned the same for position 0 as
// it would be if there was no preedit text.
QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>()
<< QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, preeditText.length(), QVariant()));
- QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
- QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ QCoreApplication::sendEvent(edit, &imEvent);
+ QCoreApplication::sendEvent(edit, &query);
+ currentRect = query.value(Qt::ImCursorRectangle).toRectF();
+ QCOMPARE(edit->cursorRectangle(), currentRect);
+ QCOMPARE(cursor->pos(), currentRect.topLeft());
QCOMPARE(currentRect, previousRect);
- QCOMPARE(editSpy.count(), 0);
- QCOMPARE(panelSpy.count(), 0);
// Verify that the micro focus rect moves to the left as the cursor position
// is incremented.
+ editSpy.clear();
+ panelSpy.clear();
for (int i = 1; i <= 5; ++i) {
QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>()
<< QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, preeditText.length(), QVariant()));
- QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
- QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ QCoreApplication::sendEvent(edit, &imEvent);
+ QCoreApplication::sendEvent(edit, &query);
+ currentRect = query.value(Qt::ImCursorRectangle).toRectF();
+ QCOMPARE(edit->cursorRectangle(), currentRect);
+ QCOMPARE(cursor->pos(), currentRect.topLeft());
QVERIFY(previousRect.left() < currentRect.left());
- QVERIFY(editSpy.count() > 0); editSpy.clear();
- QVERIFY(panelSpy.count() > 0); panelSpy.clear();
+ QCOMPARE(editSpy.count(), 1); editSpy.clear();
+ QCOMPARE(panelSpy.count(), 1); panelSpy.clear();
previousRect = currentRect;
}
+ // Verify that if the cursor rectangle is updated if the pre-edit text changes
+ // but the (non-zero) cursor position is the same.
+ editSpy.clear();
+ panelSpy.clear();
+ { QInputMethodEvent imEvent("wwwww", QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 5, 1, QVariant()));
+ QCoreApplication::sendEvent(edit, &imEvent); }
+ QCoreApplication::sendEvent(edit, &query);
+ currentRect = query.value(Qt::ImCursorRectangle).toRectF();
+ QCOMPARE(edit->cursorRectangle(), currentRect);
+ QCOMPARE(cursor->pos(), currentRect.topLeft());
+ QCOMPARE(editSpy.count(), 1);
+ QCOMPARE(panelSpy.count(), 1);
+
// Verify that if there is no preedit cursor then the micro focus rect is the
// same as it would be if it were positioned at the end of the preedit text.
- QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
editSpy.clear();
panelSpy.clear();
{ QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
- QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent); }
- QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ QCoreApplication::sendEvent(edit, &imEvent); }
+ QCoreApplication::sendEvent(edit, &query);
+ currentRect = query.value(Qt::ImCursorRectangle).toRectF();
+ QCOMPARE(edit->cursorRectangle(), currentRect);
+ QCOMPARE(cursor->pos(), currentRect.topLeft());
QCOMPARE(currentRect, previousRect);
- QVERIFY(editSpy.count() > 0);
- QVERIFY(panelSpy.count() > 0);
+ QCOMPARE(editSpy.count(), 1);
+ QCOMPARE(panelSpy.count(), 1);
}
void tst_qquicktextedit::inputMethodComposing()
QQuickView view(testFileUrl("inputContext.qml"));
view.show();
view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ QTest::qWaitForWindowActive(&view);
+
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
+ QCOMPARE(QGuiApplication::focusObject(), static_cast<QObject *>(edit));
+
QSignalSpy spy(edit, SIGNAL(inputMethodComposingChanged()));
edit->setCursorPosition(12);
void tst_qquicktextedit::cursorRectangleSize()
{
- QQuickView *canvas = new QQuickView(testFileUrl("positionAt.qml"));
- QVERIFY(canvas->rootObject() != 0);
- QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(canvas->rootObject());
+ QQuickView *window = new QQuickView(testFileUrl("positionAt.qml"));
+ QVERIFY(window->rootObject() != 0);
+ QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window->rootObject());
// make sure cursor rectangle is not at (0,0)
textEdit->setX(10);
textEdit->setCursorPosition(3);
QVERIFY(textEdit != 0);
textEdit->setFocus(true);
- canvas->show();
- canvas->requestActivateWindow();
- QTest::qWaitForWindowShown(canvas);
+ window->show();
+ window->requestActivateWindow();
+ QTest::qWaitForWindowActive(window);
QInputMethodQueryEvent event(Qt::ImCursorRectangle);
- qApp->sendEvent(qApp->focusObject(), &event);
+ qApp->sendEvent(textEdit, &event);
QRectF cursorRectFromQuery = event.value(Qt::ImCursorRectangle).toRectF();
QRectF cursorRectFromItem = textEdit->cursorRectangle();
// item cursor rectangle and positionToRectangle calculations match
QCOMPARE(cursorRectFromItem, cursorRectFromPositionToRectangle);
- // item-canvas transform and input item transform match
- QCOMPARE(QQuickItemPrivate::get(textEdit)->itemToCanvasTransform(), qApp->inputMethod()->inputItemTransform());
+ // item-window transform and input item transform match
+ QCOMPARE(QQuickItemPrivate::get(textEdit)->itemToWindowTransform(), qApp->inputMethod()->inputItemTransform());
// input panel cursorRectangle property and tranformed item cursor rectangle match
- QRectF sceneCursorRect = QQuickItemPrivate::get(textEdit)->itemToCanvasTransform().mapRect(cursorRectFromItem);
+ QRectF sceneCursorRect = QQuickItemPrivate::get(textEdit)->itemToWindowTransform().mapRect(cursorRectFromItem);
QCOMPARE(sceneCursorRect, qApp->inputMethod()->cursorRectangle());
- delete canvas;
+ delete window;
}
void tst_qquicktextedit::getText_data()
const QString richBoldText = QStringLiteral("This is some <b>bold</b> text");
const QString plainBoldText = QStringLiteral("This is some bold text");
+ const QString richBoldTextLB = QStringLiteral("This is some<br/><b>bold</b> text");
+ const QString plainBoldTextLB = QString(QStringLiteral("This is some\nbold text")).replace(QLatin1Char('\n'), QChar(QChar::LineSeparator));
QTest::newRow("all plain text")
<< standard.at(0)
<< richBoldText
<< 14 << 21
<< plainBoldText.mid(14, 7);
+
+ // Line break.
+ QTest::newRow("all plain text (line break)")
+ << standard.at(1)
+ << 0 << standard.at(1).length()
+ << standard.at(1);
+
+ QTest::newRow("plain text sub string (line break)")
+ << standard.at(1)
+ << 0 << 12
+ << standard.at(1).mid(0, 12);
+
+ QTest::newRow("plain text sub string reversed (line break)")
+ << standard.at(1)
+ << 12 << 0
+ << standard.at(1).mid(0, 12);
+
+ QTest::newRow("plain text cropped beginning (line break)")
+ << standard.at(1)
+ << -3 << 4
+ << standard.at(1).mid(0, 4);
+
+ QTest::newRow("plain text cropped end (line break)")
+ << standard.at(1)
+ << 23 << standard.at(1).length() + 8
+ << standard.at(1).mid(23);
+
+ QTest::newRow("plain text cropped beginning and end (line break)")
+ << standard.at(1)
+ << -9 << standard.at(1).length() + 4
+ << standard.at(1);
+
+ QTest::newRow("all rich text (line break)")
+ << richBoldTextLB
+ << 0 << plainBoldTextLB.length()
+ << plainBoldTextLB;
+
+ QTest::newRow("rich text sub string (line break)")
+ << richBoldTextLB
+ << 14 << 21
+ << plainBoldTextLB.mid(14, 7);
}
void tst_qquicktextedit::getText()
textEdit->setTextFormat(textFormat);
textEdit->select(selectionStart, selectionEnd);
- QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged()));
+ QSignalSpy selectionSpy(textEdit, SIGNAL(selectedTextChanged()));
QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged()));
QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged()));
QSignalSpy textSpy(textEdit, SIGNAL(textChanged()));
if (selectionStart > selectionEnd)
qSwap(selectionStart, selectionEnd);
- QEXPECT_FAIL("into selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
- QEXPECT_FAIL("into reversed selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
+ QEXPECT_FAIL("into selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
+ QEXPECT_FAIL("into reversed selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
QCOMPARE(selectionSpy.count() > 0, selectionChanged);
QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
QEXPECT_FAIL("into reversed selection", "selectionEndChanged signal not emitted", Continue);
textEdit->setTextFormat(textFormat);
textEdit->select(selectionStart, selectionEnd);
- QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged()));
+ QSignalSpy selectionSpy(textEdit, SIGNAL(selectedTextChanged()));
QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged()));
QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged()));
QSignalSpy textSpy(textEdit, SIGNAL(textChanged()));
QCOMPARE(textEdit->selectionEnd(), expectedSelectionEnd);
QCOMPARE(textEdit->cursorPosition(), expectedCursorPosition);
- QEXPECT_FAIL("from selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
- QEXPECT_FAIL("from reversed selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
+ QEXPECT_FAIL("from selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
+ QEXPECT_FAIL("from reversed selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
QCOMPARE(selectionSpy.count() > 0, selectionChanged);
QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
QEXPECT_FAIL("from reversed selection", "selectionEndChanged signal not emitted", Continue);
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
QVERIFY(textEdit != 0);
- QQuickCanvas canvas;
- textEdit->setParentItem(canvas.rootItem());
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+ QQuickWindow window;
+ textEdit->setParentItem(window.rootItem());
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
+
+ QVERIFY(textEdit->hasActiveFocus());
- simulateKey(&canvas, layoutDirection);
+ simulateKey(&window, layoutDirection);
textEdit->select(selectionStart, selectionEnd);
- simulateKeys(&canvas, sequence);
+ simulateKeys(&window, sequence);
QCOMPARE(textEdit->cursorPosition(), cursorPosition);
QCOMPARE(textEdit->text(), expectedText);
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
QVERIFY(textEdit != 0);
- QQuickCanvas canvas;
- textEdit->setParentItem(canvas.rootItem());
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+ QQuickWindow window;
+ textEdit->setParentItem(window.rootItem());
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
+ QVERIFY(textEdit->hasActiveFocus());
QVERIFY(!textEdit->canUndo());
QSignalSpy spy(textEdit, SIGNAL(canUndoChanged()));
}
for (int j = 0; j < insertString.at(i).length(); j++)
- QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
+ QTest::keyClick(&window, insertString.at(i).at(j).toLatin1());
}
QCOMPARE(spy.count(), 1);
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
QVERIFY(textEdit != 0);
- QQuickCanvas canvas;
- textEdit->setParentItem(canvas.rootItem());
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+ QQuickWindow window;
+ textEdit->setParentItem(window.rootItem());
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
+ QVERIFY(textEdit->hasActiveFocus());
QVERIFY(!textEdit->canUndo());
QVERIFY(!textEdit->canRedo());
if (insertIndex[i] > -1)
textEdit->setCursorPosition(insertIndex[i]);
for (int j = 0; j < insertString.at(i).length(); j++)
- QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
+ QTest::keyClick(&window, insertString.at(i).at(j).toLatin1());
QVERIFY(textEdit->canUndo());
QVERIFY(!textEdit->canRedo());
}
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
QVERIFY(textEdit != 0);
- QQuickCanvas canvas;
- textEdit->setParentItem(canvas.rootItem());
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+ QQuickWindow window;
+ textEdit->setParentItem(window.rootItem());
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
+ QVERIFY(textEdit->hasActiveFocus());
- simulateKeys(&canvas, keys);
+ simulateKeys(&window, keys);
for (int i = 0; i < expectedString.size(); ++i) {
QCOMPARE(textEdit->text() , expectedString[i]);
QFETCH(QUrl, qmlfile);
QFETCH(QString, error);
- TestHTTPServer server(42332);
+ TestHTTPServer server(SERVER_PORT);
server.serveDirectory(testFile("http"));
if (!error.isEmpty())
void tst_qquicktextedit::emptytags_QTBUG_22058()
{
- QQuickView canvas(testFileUrl("qtbug-22058.qml"));
- QVERIFY(canvas.rootObject() != 0);
+ QQuickView window(testFileUrl("qtbug-22058.qml"));
+ QVERIFY(window.rootObject() != 0);
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("inputField")));
+ window.show();
+ window.requestActivateWindow();
+ QTest::qWaitForWindowActive(&window);
+ QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("inputField")));
QVERIFY(input->hasActiveFocus());
QInputMethodEvent event("", QList<QInputMethodEvent::Attribute>());