isEnabled(true),
hadSelectionOnMousePress(false),
wordSelectionEnabled(false),
- hasImState(false)
+ hasImState(false),
+ cursorRectangleChanged(false)
{}
bool QQuickTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e)
if (moved) {
if (cursor.position() != oldCursorPos)
emit q->cursorPositionChanged();
- emit q->cursorRectangleChanged();
+ q->updateCursorRectangle(true);
} else if (isNavigationEvent && oldSelection.anchor() == cursor.anchor()) {
return false;
}
lastCharFormat = fmt;
emit q->currentCharFormatChanged(fmt);
- emit q->cursorRectangleChanged();
+ cursorRectangleChanged = true;
}
void QQuickTextControlPrivate::init(Qt::TextFormat format, const QString &text, QTextDocument *document)
if (!document)
doc->setModified(false);
- emit q->cursorRectangleChanged();
+ q->updateCursorRectangle(true);
emit q->cursorPositionChanged();
}
qGuiApp->inputMethod()->update(Qt::ImCurrentSelection);
emit q->selectionChanged();
}
- emit q->cursorRectangleChanged();
+ q->updateCursorRectangle(true);
}
void QQuickTextControlPrivate::_q_updateCurrentCharFormatAndSelection()
Q_Q(QQuickTextControl);
if (someCursor.isCopyOf(cursor)) {
emit q->cursorPositionChanged();
- emit q->cursorRectangleChanged();
+ cursorRectangleChanged = true;
}
}
d->doc->undo(&d->cursor);
if (d->cursor.position() != oldCursorPos)
emit cursorPositionChanged();
- emit cursorRectangleChanged();
+ updateCursorRectangle(true);
}
void QQuickTextControl::redo()
d->repaintSelection();
const int oldCursorPos = d->cursor.position();
d->doc->redo(&d->cursor);
- if (d->cursor.position() != oldCursorPos)
+ if (d->cursor.position() != oldCursorPos)
emit cursorPositionChanged();
- emit cursorRectangleChanged();
+ updateCursorRectangle(true);
}
QQuickTextControl::QQuickTextControl(QTextDocument *doc, QObject *parent)
return d->doc;
}
+void QQuickTextControl::updateCursorRectangle(bool force)
+{
+ Q_D(QQuickTextControl);
+ const bool update = d->cursorRectangleChanged || force;
+ d->cursorRectangleChanged = false;
+ if (update)
+ emit cursorRectangleChanged();
+}
+
void QQuickTextControl::setTextCursor(const QTextCursor &cursor)
{
Q_D(QQuickTextControl);
d->cursor = cursor;
d->cursorOn = d->hasFocus && (d->interactionFlags & Qt::TextEditable);
d->_q_updateCurrentCharFormatAndSelection();
- emit cursorRectangleChanged();
+ updateCursorRectangle(true);
d->repaintOldAndNewSelection(oldSelection);
if (posChanged)
emit cursorPositionChanged();
e->accept();
cursorOn = true;
- emit q->cursorRectangleChanged();
-
+ q->updateCursorRectangle(true);
updateCurrentCharFormat();
}
}
if (interactionFlags & Qt::TextEditable) {
- emit q->cursorRectangleChanged();
+ q->updateCursorRectangle(true);
if (cursor.position() != oldCursorPos)
emit q->cursorPositionChanged();
_q_updateCurrentCharFormatAndSelection();
} else {
if (cursor.position() != oldCursorPos) {
emit q->cursorPositionChanged();
- emit q->cursorRectangleChanged();
+ q->updateCursorRectangle(true);
}
selectionChanged();
}
if (cursor.position() != oldCursorPos) {
emit q->cursorPositionChanged();
- emit q->cursorRectangleChanged();
+ q->updateCursorRectangle(true);
}
if (interactionFlags & Qt::LinksAccessibleByMouse) {
int blockStart = a.start + cursor.block().position();
cursor.setPosition(blockStart, QTextCursor::MoveAnchor);
cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
- emit q->cursorRectangleChanged();
repaintOldAndNewSelection(oldCursor);
forceSelectionChanged = true;
}
QTextCursorPrivate *cursor_d = QTextCursorPrivate::getPrivate(&cursor);
if (cursor_d)
cursor_d->setX();
- if (oldPreeditCursor != preeditCursor)
- emit q->cursorRectangleChanged();
+ q->updateCursorRectangle(oldPreeditCursor != preeditCursor || forceSelectionChanged);
selectionChanged(forceSelectionChanged);
}
const QTextCursor oldSelection = d->cursor;
const bool moved = d->cursor.movePosition(op, mode);
d->_q_updateCurrentCharFormatAndSelection();
- emit cursorRectangleChanged();
+ updateCursorRectangle(true);
d->repaintOldAndNewSelection(oldSelection);
if (moved)
emit cursorPositionChanged();
if (hasData)
d->cursor.insertFragment(fragment);
- emit cursorRectangleChanged();
+ updateCursorRectangle(true);
}
void QQuickTextControlPrivate::activateLinkUnderCursor(QString href)
void setCursorIsFocusIndicator(bool b);
void setWordSelectionEnabled(bool enabled);
+ void updateCursorRectangle(bool force);
+
virtual int hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const;
virtual QRectF blockBoundingRect(const QTextBlock &block) const;
bool hadSelectionOnMousePress : 1;
bool wordSelectionEnabled : 1;
bool hasImState : 1;
+ bool cursorRectangleChanged : 1;
void _q_copyLink();
void _q_updateBlock(const QTextBlock &);
return;
cursor.setPosition(pos);
d->control->setTextCursor(cursor);
+ d->control->updateCursorRectangle(true);
}
/*!
const QRectF &oldGeometry)
{
Q_D(QQuickTextEdit);
- if (newGeometry.width() != oldGeometry.width() && d->wrapMode != NoWrap && !d->inLayout)
+ if (newGeometry.width() != oldGeometry.width() && d->wrapMode != NoWrap && !d->inLayout) {
updateSize();
+ moveCursorDelegate();
+ }
QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
+
}
/*!
} else {
cursor.insertText(text);
}
+ d->control->updateCursorRectangle(false);
}
/*!
cursor.setPosition(start, QTextCursor::MoveAnchor);
cursor.setPosition(end, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
+ d->control->updateCursorRectangle(false);
}
QT_END_NAMESPACE
text: "Hello world!"
id: textEditObject;
objectName: "textEditObject"
+ wrapMode: TextEdit.WordWrap
cursorDelegate: Cursor {
id:cursorInstance;
objectName: "cursorInstance";
TextEdit {
text: "Hello world!"
id: textEditObject
+ wrapMode: TextEdit.Wrap
objectName: "textEditObject"
cursorDelegate: Item {
id:cursorInstance
TextEdit {
focus: true
+
+ cursorDelegate: Item {
+ objectName: "cursor"
+ }
}
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());
+
+ // 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(&view, &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"));
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;
QInputMethodQueryEvent query(Qt::ImCursorRectangle);
QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
- QRect previousRect = query.value(Qt::ImCursorRectangle).toRect();
+ 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::Attribute(QInputMethodEvent::Cursor, 0, preeditText.length(), QVariant()));
QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ 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);
+ QCOMPARE(editSpy.count(), 0); editSpy.clear();
+ QCOMPARE(panelSpy.count(), 0); panelSpy.clear();
// Verify that the micro focus rect moves to the left as the cursor position
// is incremented.
<< QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, preeditText.length(), QVariant()));
QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ 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;
}
{ QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent); }
QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ 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()
text: "Hello world!"
id: textInputObject;
objectName: "textInputObject"
+ wrapMode: TextInput.Wrap
cursorDelegate: Cursor {
id:cursorInstance;
objectName: "cursorInstance";
text: "Hello world!"
id: textInputObject
objectName: "textInputObject"
+ wrapMode: TextInput.WordWrap
cursorDelegate: Item {
id:cursorInstance
objectName: "cursorInstance"
TextInput {
focus: true
autoScroll: false
+
+ cursorDelegate: Item { objectName: "cursor" }
}
textInputObject->setCursorPosition(0);
QCOMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
QCOMPARE(textInputObject->cursorRectangle().y(), delegateObject->y());
+
+
+ // Test delegate gets moved on mouse press.
+ textInputObject->setSelectByMouse(true);
+ textInputObject->setCursorPosition(0);
+ const QPoint point1 = textInputObject->positionToRectangle(5).center().toPoint();
+ QTest::qWait(400); //ensure this isn't treated as a double-click
+ QTest::mouseClick(&view, Qt::LeftButton, 0, point1);
+ QTest::qWait(50);
+ QTRY_VERIFY(textInputObject->cursorPosition() != 0);
+ QCOMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
+ QCOMPARE(textInputObject->cursorRectangle().y(), delegateObject->y());
+
+ // Test delegate gets moved on mouse drag
+ textInputObject->setCursorPosition(0);
+ const QPoint point2 = textInputObject->positionToRectangle(10).center().toPoint();
+ QTest::qWait(400); //ensure this isn't treated as a double-click
+ QTest::mousePress(&view, Qt::LeftButton, 0, point1);
+ QMouseEvent mv(QEvent::MouseMove, point2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QGuiApplication::sendEvent(&view, &mv);
+ QTest::mouseRelease(&view, Qt::LeftButton, 0, point2);
+ QTest::qWait(50);
+ QTRY_COMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
+ QCOMPARE(textInputObject->cursorRectangle().y(), delegateObject->y());
+
+ textInputObject->setReadOnly(true);
+ textInputObject->setCursorPosition(0);
+ QTest::qWait(400); //ensure this isn't treated as a double-click
+ QTest::mouseClick(&view, Qt::LeftButton, 0, textInputObject->positionToRectangle(5).center().toPoint());
+ QTest::qWait(50);
+ QTRY_VERIFY(textInputObject->cursorPosition() != 0);
+ QCOMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
+ QCOMPARE(textInputObject->cursorRectangle().y(), delegateObject->y());
+
+ textInputObject->setCursorPosition(0);
+ QTest::qWait(400); //ensure this isn't treated as a double-click
+ QTest::mouseClick(&view, Qt::LeftButton, 0, textInputObject->positionToRectangle(5).center().toPoint());
+ QTest::qWait(50);
+ QTRY_VERIFY(textInputObject->cursorPosition() != 0);
+ QCOMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
+ QCOMPARE(textInputObject->cursorRectangle().y(), delegateObject->y());
+
+ textInputObject->setCursorPosition(0);
+ QCOMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
+ QCOMPARE(textInputObject->cursorRectangle().y(), delegateObject->y());
+
+ // Delegate moved when text is entered
+ textInputObject->setText(QString());
+ for (int i = 0; i < 20; ++i) {
+ QTest::keyClick(&view, Qt::Key_A);
+ QCOMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
+ QCOMPARE(textInputObject->cursorRectangle().y(), delegateObject->y());
+ }
+
+ // Delegate moved when text is entered by im.
+ textInputObject->setText(QString());
+ for (int i = 0; i < 20; ++i) {
+ QInputMethodEvent event;
+ event.setCommitString("a");
+ QGuiApplication::sendEvent(&view, &event);
+ QCOMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
+ QCOMPARE(textInputObject->cursorRectangle().y(), delegateObject->y());
+ }
+
//Test Delegate gets deleted
textInputObject->setCursorDelegate(0);
QVERIFY(!textInputObject->findChild<QQuickItem*>("cursorInstance"));
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
QVERIFY(input);
- QRect currentRect;
+ QQuickItem *cursor = input->findChild<QQuickItem *>("cursor");
+ QVERIFY(cursor);
+
+ QRectF currentRect;
QInputMethodQueryEvent query(Qt::ImCursorRectangle);
QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
- QRect previousRect = query.value(Qt::ImCursorRectangle).toRect();
+ 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.
sendPreeditText(preeditText, 0);
QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ currentRect = query.value(Qt::ImCursorRectangle).toRectF();
QCOMPARE(currentRect, previousRect);
+ QCOMPARE(input->cursorRectangle(), currentRect);
+ QCOMPARE(cursor->pos(), currentRect.topLeft());
QSignalSpy inputSpy(input, SIGNAL(cursorRectangleChanged()));
QSignalSpy panelSpy(qGuiApp->inputMethod(), SIGNAL(cursorRectangleChanged()));
for (int i = 1; i <= 5; ++i) {
sendPreeditText(preeditText, i);
QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ currentRect = query.value(Qt::ImCursorRectangle).toRectF();
QVERIFY(previousRect.left() < currentRect.left());
+ QCOMPARE(input->cursorRectangle(), currentRect);
+ QCOMPARE(cursor->pos(), currentRect.topLeft());
QVERIFY(inputSpy.count() > 0); inputSpy.clear();
QVERIFY(panelSpy.count() > 0); panelSpy.clear();
previousRect = currentRect;
QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
- currentRect = query.value(Qt::ImCursorRectangle).toRect();
+ currentRect = query.value(Qt::ImCursorRectangle).toRectF();
QCOMPARE(currentRect, previousRect);
+ QCOMPARE(input->cursorRectangle(), currentRect);
+ QCOMPARE(cursor->pos(), currentRect.topLeft());
QVERIFY(inputSpy.count() > 0);
QVERIFY(panelSpy.count() > 0);
}