Skip to content

Commit

Permalink
Made QQuickTextInput follow input direction changes
Browse files Browse the repository at this point in the history
Cursor of empty field should align based on input method
direction. Now input method allowed to change direction
on run time.

Also earlier cursor wasn't properly drawn on correct alignment
at all.

Change-Id: I4601f10e6b5dde09591bd484b05f001add6c1573
Reviewed-by: Andrew den Exter <andrew.den-exter@nokia.com>
Reviewed-by: Joona Petrell <joona.t.petrell@nokia.com>
  • Loading branch information
Pekka Vuorela authored and Qt by Nokia committed Jan 17, 2012
1 parent dc7aecd commit 6a5b9cb
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 24 deletions.
36 changes: 30 additions & 6 deletions src/quick/items/qquicktextinput.cpp
Expand Up @@ -2316,6 +2316,12 @@ void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
if (!hasFocus) {
d->commitPreedit();
d->deselect();
disconnect(qApp->inputPanel(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
this, SLOT(q_updateAlignment()));
} else {
q_updateAlignment();
connect(qApp->inputPanel(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
this, SLOT(q_updateAlignment()));
}
}
QQuickItem::itemChange(change, value);
Expand Down Expand Up @@ -2444,6 +2450,15 @@ void QQuickTextInput::q_canPasteChanged()

}

void QQuickTextInput::q_updateAlignment()
{
Q_D(QQuickTextInput);
if (d->determineHorizontalAlignment()) {
d->updateLayout();
updateCursorRectangle();
}
}

// ### these should come from QStyleHints
const int textCursorWidth = 1;
const bool fullWidthSelection = true;
Expand Down Expand Up @@ -2510,7 +2525,7 @@ void QQuickTextInputPrivate::updateLayout()
return;

QTextOption option = m_textLayout.textOption();
option.setTextDirection(m_layoutDirection);
option.setTextDirection(layoutDirection());
option.setFlags(QTextOption::IncludeTrailingSpaces);
option.setWrapMode(QTextOption::WrapMode(wrapMode));
option.setAlignment(Qt::Alignment(q->effectiveHAlign()));
Expand Down Expand Up @@ -2984,6 +2999,7 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo

Q_UNUSED(update)
bool notifyInputPanel = m_textDirty || m_selDirty;
bool alignmentChanged = false;

if (m_textDirty) {
// do validation
Expand Down Expand Up @@ -3026,18 +3042,21 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo
if (m_textDirty) {
m_textDirty = false;
m_preeditDirty = false;
determineHorizontalAlignment();
alignmentChanged = determineHorizontalAlignment();
emit q->textChanged();
}

updateDisplayText();
updateDisplayText(alignmentChanged);

if (m_validInput != wasValidInput)
emit q->acceptableInputChanged();
}
if (m_preeditDirty) {
m_preeditDirty = false;
determineHorizontalAlignment();
if (determineHorizontalAlignment()) {
alignmentChanged = true;
updateLayout();
}
}

if (m_selDirty) {
Expand All @@ -3049,7 +3068,9 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo
if (notifyInputPanel)
q->updateMicroFocus();
emitUndoRedoChanged();
emitCursorPositionChanged();

if (!emitCursorPositionChanged() && alignmentChanged)
q->updateCursorRectangle();

return true;
}
Expand Down Expand Up @@ -3683,7 +3704,7 @@ void QQuickTextInputPrivate::emitUndoRedoChanged()
If the current cursor position differs from the last emitted cursor
position, emits cursorPositionChanged().
*/
void QQuickTextInputPrivate::emitCursorPositionChanged()
bool QQuickTextInputPrivate::emitCursorPositionChanged()
{
Q_Q(QQuickTextInput);
if (m_cursor != m_lastCursorPos) {
Expand All @@ -3710,7 +3731,10 @@ void QQuickTextInputPrivate::emitCursorPositionChanged()
#ifndef QT_NO_ACCESSIBILITY
QAccessible::updateAccessibility(q, 0, QAccessible::TextCaretMoved);
#endif

return true;
}
return false;
}


Expand Down
1 change: 1 addition & 0 deletions src/quick/items/qquicktextinput_p.h
Expand Up @@ -323,6 +323,7 @@ private Q_SLOTS:
void createCursor();
void updateCursorRectangle();
void q_canPasteChanged();
void q_updateAlignment();

private:
Q_DECLARE_PRIVATE(QQuickTextInput)
Expand Down
2 changes: 1 addition & 1 deletion src/quick/items/qquicktextinput_p_p.h
Expand Up @@ -424,7 +424,7 @@ class Q_AUTOTEST_EXPORT QQuickTextInputPrivate : public QQuickImplicitSizeItemPr
void internalRedo();
void emitUndoRedoChanged();

void emitCursorPositionChanged();
bool emitCursorPositionChanged();

bool finishChange(int validateFromState = -1, bool update = false, bool edited = true);

Expand Down
52 changes: 36 additions & 16 deletions tests/auto/qtquick2/qquicktextinput/tst_qquicktextinput.cpp
Expand Up @@ -1219,6 +1219,10 @@ void tst_qquicktextinput::horizontalAlignment()

void tst_qquicktextinput::horizontalAlignment_RightToLeft()
{
PlatformInputContext platformInputContext;
QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
inputPanelPrivate->testContext = &platformInputContext;

QQuickView canvas(testFileUrl("horizontalAlignment_RightToLeft.qml"));
QQuickTextInput *textInput = canvas.rootObject()->findChild<QQuickTextInput*>("text");
QVERIFY(textInput != 0);
Expand Down Expand Up @@ -1314,26 +1318,42 @@ void tst_qquicktextinput::horizontalAlignment_RightToLeft()
// empty text with implicit alignment follows the system locale-based
// keyboard input direction from QInputPanel::inputDirection()
textInput->setText("");
QCOMPARE(textInput->hAlign(), qApp->inputPanel()->inputDirection() == Qt::LeftToRight ?
QQuickTextInput::AlignLeft : QQuickTextInput::AlignRight);
if (qApp->inputPanel()->inputDirection() == Qt::LeftToRight) {
QCOMPARE(textInputPrivate->boundingRect.left() - textInputPrivate->hscroll, qreal(0));
} else {
QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);
}
textInput->setHAlign(QQuickTextInput::AlignRight);
platformInputContext.setInputDirection(Qt::LeftToRight);
QVERIFY(qApp->inputPanel()->inputDirection() == Qt::LeftToRight);
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
QCOMPARE(textInputPrivate->boundingRect.left() - textInputPrivate->hscroll, qreal(0));

QSignalSpy cursorRectangleSpy(textInput, SIGNAL(cursorRectangleChanged()));
platformInputContext.setInputDirection(Qt::RightToLeft);
QVERIFY(qApp->inputPanel()->inputDirection() == Qt::RightToLeft);
QCOMPARE(cursorRectangleSpy.count(), 1);
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);

// set input direction while having content
platformInputContext.setInputDirection(Qt::LeftToRight);
textInput->setText("a");
platformInputContext.setInputDirection(Qt::RightToLeft);
QTest::keyClick(&canvas, Qt::Key_Backspace);
QVERIFY(textInput->text().isEmpty());
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);

// input direction changed while not having focus
platformInputContext.setInputDirection(Qt::LeftToRight);
textInput->setFocus(false);
platformInputContext.setInputDirection(Qt::RightToLeft);
textInput->setFocus(true);
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);

QString componentStr = "import QtQuick 2.0\nTextInput {}";
QDeclarativeComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create());
QCOMPARE(textObject->hAlign(), qApp->inputPanel()->inputDirection() == Qt::LeftToRight ?
QQuickTextInput::AlignLeft : QQuickTextInput::AlignRight);
delete textObject;
textInput->setHAlign(QQuickTextInput::AlignRight);
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);
}

void tst_qquicktextinput::verticalAlignment()
Expand Down
22 changes: 21 additions & 1 deletion tests/auto/shared/platforminputcontext.h
Expand Up @@ -48,7 +48,7 @@ class PlatformInputContext : public QPlatformInputContext
PlatformInputContext()
: m_visible(false), m_action(QInputPanel::Click), m_cursorPosition(0),
m_invokeActionCallCount(0), m_showInputPanelCallCount(0), m_hideInputPanelCallCount(0),
m_updateCallCount(0)
m_updateCallCount(0), m_direction(Qt::LeftToRight)
{
}

Expand Down Expand Up @@ -77,6 +77,25 @@ class PlatformInputContext : public QPlatformInputContext
m_updateCallCount++;
}

virtual QLocale locale() const
{
if (m_direction == Qt::RightToLeft)
return QLocale(QLocale::Arabic);
else
return QLocale(QLocale::English);
}

virtual Qt::LayoutDirection inputDirection() const
{
return m_direction;
}

void setInputDirection(Qt::LayoutDirection direction) {
m_direction = direction;
emitLocaleChanged();
emitInputDirectionChanged(inputDirection());
}

void clear() {
m_cursorPosition = 0;
m_invokeActionCallCount = 0;
Expand All @@ -93,4 +112,5 @@ class PlatformInputContext : public QPlatformInputContext
int m_showInputPanelCallCount;
int m_hideInputPanelCallCount;
int m_updateCallCount;
Qt::LayoutDirection m_direction;
};

0 comments on commit 6a5b9cb

Please sign in to comment.