/****************************************************************************
**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
#include <QMimeData>
#include <private/qquicktextcontrol_p.h>
#include "../../shared/util.h"
+#include "../../shared/platformquirks.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)
DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
void width();
void wrap();
void textFormat();
- void alignments();
- void alignments_data();
// ### these tests may be trivial
void hAlign();
void hAlign_RightToLeft();
+ void hAlignVisual();
void vAlign();
void font();
void color();
void mouseSelectionMode_data();
void mouseSelectionMode();
void dragMouseSelection();
+ void mouseSelectionMode_accessors();
+ void selectByMouse();
+ void renderType();
void inputMethodHints();
+ void positionAt_data();
void positionAt();
void linkActivated();
void cursorDelegate_data();
void cursorDelegate();
+ void remoteCursorDelegate();
void cursorVisible();
void delegateLoading_data();
void delegateLoading();
void navigation();
void readOnly();
+#ifndef QT_NO_CLIPBOARD
void copyAndPaste();
void canPaste();
void canPasteEmpty();
+ void middleClickPaste();
+#endif
void textInput();
void inputMethodUpdate();
void openInputPanel();
void geometrySignals();
+#ifndef QT_NO_CLIPBOARD
void pastingRichText_QTBUG_14003();
+#endif
void implicitSize_data();
void implicitSize();
void contentSize();
+ void boundingRect();
+ void clipRect();
+ void implicitSizeBinding_data();
+ void implicitSizeBinding();
void preeditCursorRectangle();
void inputMethodComposing();
void simulateKeys(QWindow *window, const QList<Key> &keys);
void simulateKeys(QWindow *window, const QKeySequence &sequence);
- void simulateKey(QQuickView *, int key, Qt::KeyboardModifiers modifiers = 0);
+ void simulateKey(QWindow *, int key, Qt::KeyboardModifiers modifiers = 0);
QStringList standard;
QStringList richText;
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)
QVERIFY(textEditObject != 0);
QCOMPARE(textEditObject->width(), 300.);
}
+ {
+ 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);
+
+ QSignalSpy spy(edit, SIGNAL(wrapModeChanged()));
+
+ QCOMPARE(edit->wrapMode(), QQuickTextEdit::NoWrap);
+
+ edit->setWrapMode(QQuickTextEdit::Wrap);
+ QCOMPARE(edit->wrapMode(), QQuickTextEdit::Wrap);
+ QCOMPARE(spy.count(), 1);
+
+ edit->setWrapMode(QQuickTextEdit::Wrap);
+ QCOMPARE(spy.count(), 1);
+
+ edit->setWrapMode(QQuickTextEdit::NoWrap);
+ QCOMPARE(edit->wrapMode(), QQuickTextEdit::NoWrap);
+ QCOMPARE(spy.count(), 2);
+ }
}
QVERIFY(textObject != 0);
QVERIFY(textObject->textFormat() == QQuickTextEdit::PlainText);
}
-}
-
-void tst_qquicktextedit::alignments_data()
-{
- QTest::addColumn<int>("hAlign");
- QTest::addColumn<int>("vAlign");
- QTest::addColumn<QString>("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_qquicktextedit::alignments()
-{
- QSKIP("Image comparison of text is almost guaranteed to fail during development");
-
- QFETCH(int, hAlign);
- QFETCH(int, vAlign);
- QFETCH(QString, expectfile);
-
- QQuickView canvas(testFileUrl("alignments.qml"));
+ {
+ 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);
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+ QSignalSpy spy(edit, SIGNAL(textFormatChanged(TextFormat)));
- 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.grabFrameBuffer();
+ QCOMPARE(edit->textFormat(), QQuickTextEdit::PlainText);
- expectfile = createExpectedFileIfNotFound(expectfile, actual);
+ edit->setTextFormat(QQuickTextEdit::RichText);
+ QCOMPARE(edit->textFormat(), QQuickTextEdit::RichText);
+ QCOMPARE(spy.count(), 1);
- QImage expect(expectfile);
+ edit->setTextFormat(QQuickTextEdit::RichText);
+ QCOMPARE(spy.count(), 1);
- QCOMPARE(actual,expect);
+ edit->setTextFormat(QQuickTextEdit::PlainText);
+ QCOMPARE(edit->textFormat(), QQuickTextEdit::PlainText);
+ QCOMPARE(spy.count(), 2);
+ }
}
-
//the alignment tests may be trivial o.oa
void tst_qquicktextedit::hAlign()
{
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.requestActivate();
+ 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();
+ QVERIFY(QTest::qWaitForWindowExposed(&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()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QQuickTextEditPrivate *textEditPrivate = static_cast<QQuickTextEditPrivate*>(QQuickItemPrivate::get(textEditObject));
-
QVERIFY(textEditObject);
- QVERIFY(textEditPrivate);
- QVERIFY(textEditPrivate->control);
- QCOMPARE(textEditPrivate->color, QColor("black"));
+ QCOMPARE(textEditObject->color(), QColor("black"));
+ QCOMPARE(textEditObject->selectionColor(), QColor::fromRgba(0xFF000080));
+ QCOMPARE(textEditObject->selectedTextColor(), QColor("white"));
+
+ QSignalSpy colorSpy(textEditObject, SIGNAL(colorChanged(QColor)));
+ QSignalSpy selectionColorSpy(textEditObject, SIGNAL(selectionColorChanged(QColor)));
+ QSignalSpy selectedTextColorSpy(textEditObject, SIGNAL(selectedTextColorChanged(QColor)));
+
+ textEditObject->setColor(QColor("white"));
+ QCOMPARE(textEditObject->color(), QColor("white"));
+ QCOMPARE(colorSpy.count(), 1);
+
+ textEditObject->setSelectionColor(QColor("black"));
+ QCOMPARE(textEditObject->selectionColor(), QColor("black"));
+ QCOMPARE(selectionColorSpy.count(), 1);
+
+ textEditObject->setSelectedTextColor(QColor("blue"));
+ QCOMPARE(textEditObject->selectedTextColor(), QColor("blue"));
+ QCOMPARE(selectedTextColorSpy.count(), 1);
+
+ textEditObject->setColor(QColor("white"));
+ QCOMPARE(colorSpy.count(), 1);
+
+ textEditObject->setSelectionColor(QColor("black"));
+ QCOMPARE(selectionColorSpy.count(), 1);
+
+ textEditObject->setSelectedTextColor(QColor("blue"));
+ QCOMPARE(selectedTextColorSpy.count(), 1);
+
+ textEditObject->setColor(QColor("black"));
+ QCOMPARE(textEditObject->color(), QColor("black"));
+ QCOMPARE(colorSpy.count(), 2);
+
+ textEditObject->setSelectionColor(QColor("blue"));
+ QCOMPARE(textEditObject->selectionColor(), QColor("blue"));
+ QCOMPARE(selectionColorSpy.count(), 2);
+
+ textEditObject->setSelectedTextColor(QColor("white"));
+ QCOMPARE(textEditObject->selectedTextColor(), QColor("white"));
+ QCOMPARE(selectedTextColorSpy.count(), 2);
}
+
//test normal
for (int i = 0; i < colorStrings.size(); i++)
{
void tst_qquicktextedit::persistentSelection()
{
- QQuickView canvas(testFileUrl("persistentSelection.qml"));
- canvas.show();
- canvas.requestActivateWindow();
- QTest::qWaitForWindowShown(&canvas);
- QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
- canvas.requestActivateWindow();
+ QQuickView window(testFileUrl("persistentSelection.qml"));
+ window.show();
+ window.requestActivate();
+ QTest::qWaitForWindowActive(&window);
- QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(edit);
QVERIFY(edit->hasActiveFocus());
void tst_qquicktextedit::focusOnPress()
{
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { activeFocusOnPress: true; text: \"Hello World\" }";
- QQmlComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->focusOnPress(), true);
- }
+ QString componentStr =
+ "import QtQuick 2.0\n"
+ "TextEdit {\n"
+ "property bool selectOnFocus: false\n"
+ "width: 100; height: 50\n"
+ "activeFocusOnPress: true\n"
+ "text: \"Hello World\"\n"
+ "onFocusChanged: { if (focus && selectOnFocus) selectAll() }"
+ " }";
+ QQmlComponent texteditComponent(&engine);
+ texteditComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->focusOnPress(), true);
+ QCOMPARE(textEditObject->hasFocus(), false);
- {
- QString componentStr = "import QtQuick 2.0\nTextEdit { activeFocusOnPress: false; text: \"Hello World\" }";
- QQmlComponent texteditComponent(&engine);
- texteditComponent.setData(componentStr.toLatin1(), QUrl());
- QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
- QCOMPARE(textEditObject->focusOnPress(), false);
- }
+ QSignalSpy focusSpy(textEditObject, SIGNAL(focusChanged(bool)));
+ QSignalSpy activeFocusSpy(textEditObject, SIGNAL(focusChanged(bool)));
+ QSignalSpy activeFocusOnPressSpy(textEditObject, SIGNAL(activeFocusOnPressChanged(bool)));
+
+ textEditObject->setFocusOnPress(true);
+ QCOMPARE(textEditObject->focusOnPress(), true);
+ QCOMPARE(activeFocusOnPressSpy.count(), 0);
+
+ QQuickWindow window;
+ window.resize(100, 50);
+ textEditObject->setParentItem(window.contentItem());
+ window.show();
+ window.requestActivate();
+ QTest::qWaitForWindowActive(&window);
+
+ QCOMPARE(textEditObject->hasFocus(), false);
+ QCOMPARE(textEditObject->hasActiveFocus(), false);
+
+ QPoint centerPoint(window.width()/2, window.height()/2);
+ Qt::KeyboardModifiers noModifiers = 0;
+ 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(&window, Qt::LeftButton, noModifiers, centerPoint);
+
+ textEditObject->setFocusOnPress(false);
+ QCOMPARE(textEditObject->focusOnPress(), false);
+ QCOMPARE(activeFocusOnPressSpy.count(), 1);
+
+ textEditObject->setFocus(false);
+ QCOMPARE(textEditObject->hasFocus(), false);
+ QCOMPARE(textEditObject->hasActiveFocus(), false);
+ QCOMPARE(focusSpy.count(), 2);
+ QCOMPARE(activeFocusSpy.count(), 2);
+
+ // Wait for double click timeout to expire before clicking again.
+ QTest::qWait(400);
+ 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(&window, Qt::LeftButton, noModifiers, centerPoint);
+
+ textEditObject->setFocusOnPress(true);
+ QCOMPARE(textEditObject->focusOnPress(), true);
+ QCOMPARE(activeFocusOnPressSpy.count(), 2);
+
+ // Test a selection made in the on(Active)FocusChanged handler isn't overwritten.
+ textEditObject->setProperty("selectOnFocus", true);
+
+ QTest::qWait(400);
+ 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(&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.requestActivate();
+ 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<int>("from");
QTest::addColumn<int>("to");
QTest::addColumn<QString>("selectedText");
+ QTest::addColumn<bool>("focus");
+ QTest::addColumn<bool>("focusOnPress");
+ QTest::addColumn<int>("clicks");
// import installed
- QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678";
- QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString();
- QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString();
- QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString();
- QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789";
- QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ 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(int, from);
QFETCH(int, to);
QFETCH(QString, selectedText);
+ QFETCH(bool, focus);
+ QFETCH(bool, focusOnPress);
+ 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.requestActivate();
+ 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);
+ textEditObject->setFocusOnPress(focusOnPress);
+
// press-and-drag-and-release from x1 to x2
QPoint p1 = textEditObject->positionToRectangle(from).center().toPoint();
QPoint p2 = textEditObject->positionToRectangle(to).center().toPoint();
- 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);
- 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.requestActivate();
+ 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.requestActivate();
+ 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::mouseSelectionMode_accessors()
+{
+ 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);
+
+ QSignalSpy spy(edit, SIGNAL(mouseSelectionModeChanged(SelectionMode)));
+
+ QCOMPARE(edit->mouseSelectionMode(), QQuickTextEdit::SelectCharacters);
+
+ edit->setMouseSelectionMode(QQuickTextEdit::SelectWords);
+ QCOMPARE(edit->mouseSelectionMode(), QQuickTextEdit::SelectWords);
+ QCOMPARE(spy.count(), 1);
+
+ edit->setMouseSelectionMode(QQuickTextEdit::SelectWords);
+ QCOMPARE(spy.count(), 1);
+
+ edit->setMouseSelectionMode(QQuickTextEdit::SelectCharacters);
+ QCOMPARE(edit->mouseSelectionMode(), QQuickTextEdit::SelectCharacters);
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_qquicktextedit::selectByMouse()
+{
+ 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);
+
+ QSignalSpy spy(edit, SIGNAL(selectByMouseChanged(bool)));
+
+ QCOMPARE(edit->selectByMouse(), false);
+
+ edit->setSelectByMouse(true);
+ QCOMPARE(edit->selectByMouse(), true);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), true);
+
+ edit->setSelectByMouse(true);
+ QCOMPARE(spy.count(), 1);
+
+ edit->setSelectByMouse(false);
+ QCOMPARE(edit->selectByMouse(), false);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.at(1).at(0).toBool(), false);
+}
+
+void tst_qquicktextedit::renderType()
+{
+ 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);
+
+ QSignalSpy spy(edit, SIGNAL(renderTypeChanged()));
+
+ QCOMPARE(edit->renderType(), QQuickTextEdit::QtRendering);
+
+ edit->setRenderType(QQuickTextEdit::NativeRendering);
+ QCOMPARE(edit->renderType(), QQuickTextEdit::NativeRendering);
+ QCOMPARE(spy.count(), 1);
+
+ edit->setRenderType(QQuickTextEdit::NativeRendering);
+ QCOMPARE(spy.count(), 1);
+
+ edit->setRenderType(QQuickTextEdit::QtRendering);
+ QCOMPARE(edit->renderType(), QQuickTextEdit::QtRendering);
+ QCOMPARE(spy.count(), 2);
+}
+
void tst_qquicktextedit::inputMethodHints()
{
- QQuickView canvas(testFileUrl("inputmethodhints.qml"));
- canvas.show();
- canvas.requestActivateWindow();
+ QQuickView window(testFileUrl("inputmethodhints.qml"));
+ window.show();
+ window.requestActivate();
- 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);
+ QFETCH(QQuickTextEdit::HAlignment, horizontalAlignment);
+ QFETCH(QQuickTextEdit::VAlignment, verticalAlignment);
+
+ QQuickView window(testFileUrl("positionAt.qml"));
+ QVERIFY(window.rootObject() != 0);
+ window.show();
+ window.requestActivate();
+ QTest::qWaitForWindowActive(&window);
- QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+ 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.requestActivate();
+ 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);
}
QFETCH(QUrl, source);
QQuickView view(source);
view.show();
- view.requestActivateWindow();
+ view.requestActivate();
QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
QVERIFY(textEditObject != 0);
- QVERIFY(textEditObject->findChild<QQuickItem*>("cursorInstance"));
+ // Delegate creation is deferred until focus in or cursor visibility 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::cursorVisible()
+void tst_qquicktextedit::remoteCursorDelegate()
{
- QQuickView view(testFileUrl("cursorVisible.qml"));
+ 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();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ view.requestActivate();
+ 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;
+ edit.componentComplete();
QSignalSpy spy(&edit, SIGNAL(cursorVisibleChanged(bool)));
+ QQuickView view(testFileUrl("cursorVisible.qml"));
+ view.show();
+ view.requestActivate();
+ QTest::qWaitForWindowActive(&view);
+ QCOMPARE(&view, qGuiApp->focusWindow());
+
QCOMPARE(edit.isCursorVisible(), false);
edit.setCursorVisible(true);
QCOMPARE(edit.isCursorVisible(), true);
QCOMPARE(spy.count(), 5);
- QQuickView alternateView;
+ QWindow alternateView;
alternateView.show();
- alternateView.requestActivateWindow();
- QTest::qWaitForWindowShown(&alternateView);
+ alternateView.requestActivate();
+ QTest::qWaitForWindowActive(&alternateView);
QCOMPARE(edit.isCursorVisible(), false);
QCOMPARE(spy.count(), 6);
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
+ view.requestActivate();
+ QTest::qWaitForWindowActive(&view);
QCOMPARE(edit.isCursorVisible(), true);
QCOMPARE(spy.count(), 7);
+
+ { // Cursor attribute with 0 length hides cursor.
+ QInputMethodEvent ev(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
+ QCoreApplication::sendEvent(&edit, &ev);
+ }
+ QCOMPARE(edit.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 8);
+
+ { // Cursor attribute with non zero length shows cursor.
+ QInputMethodEvent ev(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 1, QVariant()));
+ QCoreApplication::sendEvent(&edit, &ev);
+ }
+ QCOMPARE(edit.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 9);
+
+
+ { // If the cursor is hidden by the input method and the text is changed it should be visible again.
+ QInputMethodEvent ev(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
+ QCoreApplication::sendEvent(&edit, &ev);
+ }
+ QCOMPARE(edit.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 10);
+
+ edit.setText("something");
+ QCOMPARE(edit.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 11);
+
+ { // If the cursor is hidden by the input method and the cursor position is changed it should be visible again.
+ QInputMethodEvent ev(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
+ QCoreApplication::sendEvent(&edit, &ev);
+ }
+ QCOMPARE(edit.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 12);
+
+ edit.setCursorPosition(5);
+ QCOMPARE(edit.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 13);
}
void tst_qquicktextedit::delegateLoading_data()
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();
+ view.requestActivate();
if (!error.isEmpty()) {
QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
*/
void tst_qquicktextedit::navigation()
{
- QQuickView canvas(testFileUrl("navigation.qml"));
- canvas.show();
- canvas.requestActivateWindow();
+ QQuickView window(testFileUrl("navigation.qml"));
+ window.show();
+ window.requestActivate();
- 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() {
#ifndef QT_NO_CLIPBOARD
-
-#ifdef Q_OS_MAC
- {
- PasteboardRef pasteboard;
- OSStatus status = PasteboardCreate(0, &pasteboard);
- if (status == noErr)
- CFRelease(pasteboard);
- else
- QSKIP("This machine doesn't support the clipboard");
- }
-#endif
+void tst_qquicktextedit::copyAndPaste()
+{
+ if (!PlatformQuirks::isClipboardAvailable())
+ QSKIP("This machine doesn't support the clipboard");
QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
QQmlComponent textEditComponent(&engine);
QVERIFY(textEdit->canPaste());
textEdit->setReadOnly(true);
QVERIFY(!textEdit->canPaste());
+ textEdit->paste();
+ QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
+ QCOMPARE(textEdit->text().length(), 24);
textEdit->setReadOnly(false);
QVERIFY(textEdit->canPaste());
QQuickTextEditPrivate *editPrivate = static_cast<QQuickTextEditPrivate*>(pri);
QCOMPARE(textEdit->text(), editPrivate->text);
+ // cut: no selection
+ textEdit->cut();
+ QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
+
// select word
textEdit->setCursorPosition(0);
textEdit->selectWord();
QCOMPARE(textEdit->selectedText(), QString("Hello"));
+ // cut: read only.
+ textEdit->setReadOnly(true);
+ textEdit->cut();
+ QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
+ textEdit->setReadOnly(false);
+
// select all and cut
textEdit->selectAll();
textEdit->cut();
textEdit->paste();
QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
QCOMPARE(textEdit->text().length(), 24);
-#endif
+
+ // Copy first word.
+ textEdit->setCursorPosition(0);
+ textEdit->selectWord();
+ textEdit->copy();
+ // copy: no selection, previous copy retained;
+ textEdit->setCursorPosition(0);
+ QCOMPARE(textEdit->selectedText(), QString());
+ textEdit->copy();
+ textEdit->setText(QString());
+ textEdit->paste();
+ QCOMPARE(textEdit->text(), QString("Hello"));
}
+#endif
-void tst_qquicktextedit::canPaste() {
#ifndef QT_NO_CLIPBOARD
-
+void tst_qquicktextedit::canPaste()
+{
QGuiApplication::clipboard()->setText("Some text");
QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
QVERIFY(textEdit != 0);
// check initial value - QTBUG-17765
- QQuickTextControl tc(0);
+ QTextDocument document;
+ QQuickTextControl tc(&document);
QCOMPARE(textEdit->canPaste(), tc.canPaste());
-
-#endif
}
+#endif
-void tst_qquicktextedit::canPasteEmpty() {
#ifndef QT_NO_CLIPBOARD
-
+void tst_qquicktextedit::canPasteEmpty()
+{
QGuiApplication::clipboard()->clear();
QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
QVERIFY(textEdit != 0);
// check initial value - QTBUG-17765
- QQuickTextControl tc(0);
+ QTextDocument document;
+ QQuickTextControl tc(&document);
QCOMPARE(textEdit->canPaste(), tc.canPaste());
-
+}
#endif
+
+#ifndef QT_NO_CLIPBOARD
+void tst_qquicktextedit::middleClickPaste()
+{
+ if (!PlatformQuirks::isClipboardAvailable())
+ QSKIP("This machine doesn't support the clipboard");
+
+ QQuickView window(testFileUrl("mouseselection_true.qml"));
+
+ window.show();
+ window.requestActivate();
+ QTest::qWaitForWindowActive(&window);
+
+ QVERIFY(window.rootObject() != 0);
+ QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
+ QVERIFY(textEditObject != 0);
+
+ textEditObject->setFocus(true);
+
+ QString originalText = textEditObject->text();
+ QString selectedText = "234567";
+
+ // press-and-drag-and-release from x1 to x2
+ const QPoint p1 = textEditObject->positionToRectangle(2).center().toPoint();
+ const QPoint p2 = textEditObject->positionToRectangle(8).center().toPoint();
+ const QPoint p3 = textEditObject->positionToRectangle(1).center().toPoint();
+ 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);
+
+ // Middle click pastes the selected text, assuming the platform supports it.
+ QTest::mouseClick(&window, Qt::MiddleButton, Qt::NoModifier, p3);
+
+ // ### This is to prevent double click detection from carrying over to the next test.
+ QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 10);
+
+ if (QGuiApplication::clipboard()->supportsSelection())
+ QCOMPARE(textEditObject->text().mid(1, selectedText.length()), selectedText);
+ else
+ QCOMPARE(textEditObject->text(), originalText);
}
+#endif
void tst_qquicktextedit::readOnly()
{
- QQuickView canvas(testFileUrl("readOnly.qml"));
- canvas.show();
- canvas.requestActivateWindow();
+ QQuickView window(testFileUrl("readOnly.qml"));
+ window.show();
+ window.requestActivate();
- 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);
QCOMPARE(edit->cursorPosition(), edit->text().length());
}
-void tst_qquicktextedit::simulateKey(QQuickView *view, int key, Qt::KeyboardModifiers modifiers)
+void tst_qquicktextedit::simulateKey(QWindow *view, int key, Qt::KeyboardModifiers modifiers)
{
QKeyEvent press(QKeyEvent::KeyPress, key, modifiers);
QKeyEvent release(QKeyEvent::KeyRelease, key, modifiers);
{
QQuickView view(testFileUrl("inputMethodEvent.qml"));
view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ view.requestActivate();
+ 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);
QQuickTextEditPrivate *editPrivate = static_cast<QQuickTextEditPrivate*>(QQuickItemPrivate::get(edit));
QCOMPARE(editPrivate->text, QString("Hello world!"));
- // test that tentative commit is included in text property
- edit->setText("");
- spy.clear();
- QList<QInputMethodEvent::Attribute> attributes;
- QInputMethodEvent event2("preedit", attributes);
- event2.setTentativeCommitString("string");
- QGuiApplication::sendEvent(qGuiApp->focusObject(), &event2);
- QCOMPARE(spy.count(), 1);
- QCOMPARE(edit->text(), QString("string"));
-
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());
+ view.requestActivate();
+ QTest::qWaitForWindowActive(&view);
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
QVERIFY(edit->hasActiveFocus() == true);
QVERIFY(edit->selectionStart() != edit->selectionEnd());
QVERIFY(platformInputContext.m_updateCallCount > 0);
+ // programmatical selections trigger update
+ platformInputContext.clear();
+ edit->selectAll();
+ QCOMPARE(platformInputContext.m_updateCallCount, 1);
+
// font changes
platformInputContext.clear();
QFont font = edit->font();
QQuickView view(testFileUrl("openInputPanel.qml"));
view.show();
- view.requestActivateWindow();
- QTest::qWaitForWindowShown(&view);
- QTRY_COMPARE(&view, qGuiApp->focusWindow());
+ view.requestActivate();
+ 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);
anotherEdit.setFocus(false);
QVERIFY(qApp->focusObject() != &anotherEdit);
- QCOMPARE(view.activeFocusItem(), view.rootItem());
+ QCOMPARE(view.activeFocusItem(), view.contentItem());
anotherEdit.setFocus(true);
qApp->inputMethod()->hide();
// 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;
}
delete o;
}
+#ifndef QT_NO_CLIPBOARD
void tst_qquicktextedit::pastingRichText_QTBUG_14003()
{
-#ifndef QT_NO_CLIPBOARD
QString componentStr = "import QtQuick 2.0\nTextEdit { textFormat: TextEdit.PlainText }";
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
obj->paste();
QTRY_VERIFY(obj->text() == "");
QTRY_VERIFY(obj->textFormat() == QQuickTextEdit::PlainText);
-#endif
}
+#endif
void tst_qquicktextedit::implicitSize_data()
{
QTest::addColumn<QString>("text");
QTest::addColumn<QString>("wrap");
- QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap";
- QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.NoWrap";
- QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap";
- QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.Wrap";
+ QTest::addColumn<QString>("format");
+ QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap" << "TextEdit.PlainText";
+ QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.NoWrap" << "TextEdit.RichText";
+ QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap" << "TextEdit.PlainText";
+ QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.Wrap" << "TextEdit.RichText";
}
void tst_qquicktextedit::implicitSize()
{
QFETCH(QString, text);
QFETCH(QString, wrap);
- QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }";
+ QFETCH(QString, format);
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + "; textFormat: " + format + " }";
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
QCOMPARE(spy.count(), 3);
}
+void tst_qquicktextedit::implicitSizeBinding_data()
+{
+ implicitSize_data();
+}
+
+void tst_qquicktextedit::implicitSizeBinding()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, wrap);
+ QFETCH(QString, format);
+ QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + "; textFormat: " + format + " }";
+ QQmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QScopedPointer<QObject> object(textComponent.create());
+ QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit *>(object.data());
+
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
+
+ textObject->resetWidth();
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ QCOMPARE(textObject->height(), textObject->implicitHeight());
+
+ textObject->resetHeight();
+ QCOMPARE(textObject->width(), textObject->implicitWidth());
+ 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);
+ view.requestActivate();
+ 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());
+ view.requestActivate();
+ 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);
}
QCOMPARE(edit->isInputMethodComposing(), false);
QCOMPARE(spy.count(), 2);
+
+ // Changing the text while not composing doesn't alter the composing state.
+ edit->setText(text.mid(0, 16));
+ QCOMPARE(edit->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 2);
+
+ {
+ QInputMethodEvent event(text.mid(16), QList<QInputMethodEvent::Attribute>());
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 3);
+
+ // Changing the text while composing cancels composition.
+ edit->setText(text.mid(0, 12));
+ QCOMPARE(edit->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 4);
+
+ { // Preedit cursor positioned outside (empty) preedit; composing.
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, -2, 1, QVariant()));
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 5);
+
+ { // Cursor hidden; composing
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 5);
+
+ { // Default cursor attributes; composing.
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 1, QVariant()));
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 5);
+
+ { // Selections are persisted: not composing
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 2, 4, QVariant()));
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 6);
+
+ edit->setCursorPosition(0);
+
+ { // Formatting applied; composing.
+ QTextCharFormat format;
+ format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 2, 4, format));
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 7);
+
+ {
+ QInputMethodEvent event;
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 8);
}
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->requestActivate();
+ 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);
QTest::addColumn<int>("cursorPosition");
QTest::addColumn<QString>("expectedText");
QTest::addColumn<QString>("selectedText");
+ QTest::addColumn<Qt::Key>("layoutDirection");
// standard[0] == "the [4]quick [10]brown [16]fox [20]jumped [27]over [32]the [36]lazy [41]dog"
QTest::newRow("select all")
<< standard.at(0) << QKeySequence(QKeySequence::SelectAll) << 0 << 0
- << 44 << standard.at(0) << standard.at(0);
+ << 44 << standard.at(0) << standard.at(0)
+ << Qt::Key_Direction_L;
+ QTest::newRow("select start of line")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfLine) << 5 << 5
+ << 0 << standard.at(0) << standard.at(0).mid(0, 5)
+ << Qt::Key_Direction_L;
+ QTest::newRow("select start of block")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfBlock) << 5 << 5
+ << 0 << standard.at(0) << standard.at(0).mid(0, 5)
+ << Qt::Key_Direction_L;
QTest::newRow("select end of line")
<< standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5
- << 44 << standard.at(0) << standard.at(0).mid(5);
+ << 44 << standard.at(0) << standard.at(0).mid(5)
+ << Qt::Key_Direction_L;
QTest::newRow("select end of document")
<< standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3
- << 44 << standard.at(0) << standard.at(0).mid(3);
+ << 44 << standard.at(0) << standard.at(0).mid(3)
+ << Qt::Key_Direction_L;
QTest::newRow("select end of block")
<< standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18
- << 44 << standard.at(0) << standard.at(0).mid(18);
+ << 44 << standard.at(0) << standard.at(0).mid(18)
+ << Qt::Key_Direction_L;
QTest::newRow("delete end of line")
<< standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24
- << 24 << standard.at(0).mid(0, 24) << QString();
+ << 24 << standard.at(0).mid(0, 24) << QString()
+ << Qt::Key_Direction_L;
QTest::newRow("move to start of line")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31
- << 0 << standard.at(0) << QString();
+ << 0 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
QTest::newRow("move to start of block")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25
- << 0 << standard.at(0) << QString();
+ << 0 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
QTest::newRow("move to next char")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToNextChar) << 12 << 12
- << 13 << standard.at(0) << QString();
- QTest::newRow("move to previous char")
+ << 13 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
+ QTest::newRow("move to previous char (ltr)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3
+ << 2 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
+ QTest::newRow("move to previous char (rtl)")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3
- << 2 << standard.at(0) << QString();
- QTest::newRow("select next char")
+ << 4 << standard.at(0) << QString()
+ << Qt::Key_Direction_R;
+ QTest::newRow("move to previous char with selection")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 7
+ << 3 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
+ QTest::newRow("select next char (ltr)")
<< standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23
- << 24 << standard.at(0) << standard.at(0).mid(23, 1);
- QTest::newRow("select previous char")
+ << 24 << standard.at(0) << standard.at(0).mid(23, 1)
+ << Qt::Key_Direction_L;
+ QTest::newRow("select next char (rtl)")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23
+ << 22 << standard.at(0) << standard.at(0).mid(22, 1)
+ << Qt::Key_Direction_R;
+ QTest::newRow("select previous char (ltr)")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19
+ << 18 << standard.at(0) << standard.at(0).mid(18, 1)
+ << Qt::Key_Direction_L;
+ QTest::newRow("select previous char (rtl)")
<< standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19
- << 18 << standard.at(0) << standard.at(0).mid(18, 1);
- QTest::newRow("move to next word")
+ << 20 << standard.at(0) << standard.at(0).mid(19, 1)
+ << Qt::Key_Direction_R;
+ QTest::newRow("move to next word (ltr)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
+ << 10 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
+ QTest::newRow("move to next word (rtl)")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
- << 10 << standard.at(0) << QString();
- QTest::newRow("move to previous word")
+ << 4 << standard.at(0) << QString()
+ << Qt::Key_Direction_R;
+ QTest::newRow("move to previous word (ltr)")
<< standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
- << 4 << standard.at(0) << QString();
+ << 4 << standard.at(0) << QString()
+ << Qt::Key_Direction_L;
+ QTest::newRow("move to previous word (rlt)")
+ << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
+ << 10 << standard.at(0) << QString()
+ << Qt::Key_Direction_R;
+ QTest::newRow("select next word")
+ << standard.at(0) << QKeySequence(QKeySequence::SelectNextWord) << 11 << 11
+ << 16 << standard.at(0) << standard.at(0).mid(11, 5)
+ << Qt::Key_Direction_L;
QTest::newRow("select previous word")
<< standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11
- << 10 << standard.at(0) << standard.at(0).mid(10, 1);
+ << 10 << standard.at(0) << standard.at(0).mid(10, 1)
+ << Qt::Key_Direction_L;
QTest::newRow("delete (selection)")
<< standard.at(0) << QKeySequence(QKeySequence::Delete) << 12 << 15
- << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString();
+ << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString()
+ << Qt::Key_Direction_L;
QTest::newRow("delete (no selection)")
<< standard.at(0) << QKeySequence(QKeySequence::Delete) << 15 << 15
- << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString();
+ << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString()
+ << Qt::Key_Direction_L;
QTest::newRow("delete end of word")
<< standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfWord) << 24 << 24
- << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString();
+ << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString()
+ << Qt::Key_Direction_L;
QTest::newRow("delete start of word")
<< standard.at(0) << QKeySequence(QKeySequence::DeleteStartOfWord) << 7 << 7
- << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString();
+ << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString()
+ << Qt::Key_Direction_L;
}
void tst_qquicktextedit::keySequence()
QFETCH(int, cursorPosition);
QFETCH(QString, expectedText);
QFETCH(QString, selectedText);
+ QFETCH(Qt::Key, layoutDirection);
if (sequence.isEmpty()) {
QSKIP("Key sequence is undefined");
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.contentItem());
+ window.show();
+ window.requestActivate();
+ QTest::qWaitForWindowActive(&window);
+
+ QVERIFY(textEdit->hasActiveFocus());
+
+ simulateKey(&window, layoutDirection);
textEdit->select(selectionStart, selectionEnd);
- simulateKeys(&canvas, sequence);
+ simulateKeys(&window, sequence);
QCOMPARE(textEdit->cursorPosition(), cursorPosition);
QCOMPARE(textEdit->text(), expectedText);
insertString << " unique instance.";
expectedString << "Ensuring a unique instance.";
- expectedString << "Ensuring a "; // ### Not present in TextInput.
+ expectedString << "Ensuring a "; // ### Not present in TextEdit.
expectedString << "Ensuring an instan";
expectedString << "Ensuring instan";
expectedString << "";
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.contentItem());
+ window.show();
+ window.requestActivate();
+ 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.contentItem());
+ window.show();
+ window.requestActivate();
+ 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());
}
<< "ABC";
expectedString << "ABC";
- // ### One operation in TextInput.
+ // ### One operation in TextEdit.
expectedString << "A";
expectedString << "123";
QTest::newRow("Inserts,moving,selection and overwriting") << keys << expectedString;
}
+
+ bool canCopyPaste = PlatformQuirks::isClipboardAvailable();
+
+ if (canCopyPaste) {
+ KeyList keys;
+ keys << "123"
+ << QKeySequence(QKeySequence::SelectStartOfLine)
+ << QKeySequence(QKeySequence::Cut)
+ << "ABC"
+ << QKeySequence(QKeySequence::Paste);
+ QStringList expectedString = QStringList()
+ << "ABC123"
+ << "ABC"
+ << ""
+ << "123";
+ QTest::newRow("Cut,paste") << keys << expectedString;
+ }
+ if (canCopyPaste) {
+ KeyList keys;
+ keys << "123"
+ << QKeySequence(QKeySequence::SelectStartOfLine)
+ << QKeySequence(QKeySequence::Copy)
+ << "ABC"
+ << QKeySequence(QKeySequence::Paste);
+ QStringList expectedString = QStringList()
+ << "ABC123"
+ << "ABC"
+ << "A"
+ << "123";
+ QTest::newRow("Copy,paste") << keys << expectedString;
+ }
}
void tst_qquicktextedit::undo_keypressevents()
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.contentItem());
+ window.show();
+ window.requestActivate();
+ 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.requestActivate();
+ QTest::qWaitForWindowActive(&window);
+ QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("inputField")));
QVERIFY(input->hasActiveFocus());
QInputMethodEvent event("", QList<QInputMethodEvent::Attribute>());