From 70e17b48e751c9a9f9d456404c8df61cb5080037 Mon Sep 17 00:00:00 2001 From: Pekka Vuorela <pekka.ta.vuorela@nokia.com> Date: Tue, 24 Apr 2012 16:46:27 +0300 Subject: [PATCH] TextEdit to honor input direction on neutral text Text with neutral direction, such as e.g. plain spaces, do not need to make text left aligned on arabic input method. Change-Id: I9aab5244ec47cf80fb2ba0f83e7087430eb2c7bb Reviewed-by: Joona Petrell <joona.t.petrell@nokia.com> --- src/quick/items/qquicktextedit.cpp | 63 ++++++++++++++----- src/quick/items/qquicktextedit_p_p.h | 6 +- .../qquicktextedit/tst_qquicktextedit.cpp | 10 +++ 3 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index fc02815adf..0e5023f272 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -537,20 +537,39 @@ bool QQuickTextEditPrivate::setHAlign(QQuickTextEdit::HAlignment alignment, bool return false; } + +Qt::LayoutDirection QQuickTextEditPrivate::textDirection(const QString &text) const +{ + const QChar *character = text.constData(); + while (!character->isNull()) { + switch (character->direction()) { + case QChar::DirL: + return Qt::LeftToRight; + case QChar::DirR: + case QChar::DirAL: + case QChar::DirAN: + return Qt::RightToLeft; + default: + break; + } + character++; + } + return Qt::LayoutDirectionAuto; +} + bool QQuickTextEditPrivate::determineHorizontalAlignment() { Q_Q(QQuickTextEdit); if (hAlignImplicit && q->isComponentComplete()) { - bool alignToRight; - if (document->isEmpty()) { + Qt::LayoutDirection direction = contentDirection; + if (direction == Qt::LayoutDirectionAuto) { const QString preeditText = control->textCursor().block().layout()->preeditAreaText(); - alignToRight = preeditText.isEmpty() - ? qApp->inputMethod()->inputDirection() == Qt::RightToLeft - : preeditText.isRightToLeft(); - } else { - alignToRight = rightToLeftText; + direction = textDirection(preeditText); } - return setHAlign(alignToRight ? QQuickTextEdit::AlignRight : QQuickTextEdit::AlignLeft); + if (direction == Qt::LayoutDirectionAuto) + direction = qGuiApp->inputMethod()->inputDirection(); + + return setHAlign(direction == Qt::RightToLeft ? QQuickTextEdit::AlignRight : QQuickTextEdit::AlignLeft); } return false; } @@ -1781,7 +1800,11 @@ void QQuickTextEdit::q_textChanged() { Q_D(QQuickTextEdit); d->textCached = false; - d->rightToLeftText = d->document->begin().layout()->engine()->isRightToLeft(); + for (QTextBlock it = d->document->begin(); it != d->document->end(); it = it.next()) { + d->contentDirection = d->textDirection(it.text()); + if (d->contentDirection != Qt::LayoutDirectionAuto) + break; + } d->determineHorizontalAlignment(); d->updateDefaultTextOption(); updateSize(); @@ -2016,24 +2039,34 @@ void QQuickTextEditPrivate::updateDefaultTextOption() Q_Q(QQuickTextEdit); QTextOption opt = document->defaultTextOption(); int oldAlignment = opt.alignment(); + Qt::LayoutDirection oldTextDirection = opt.textDirection(); QQuickTextEdit::HAlignment horizontalAlignment = q->effectiveHAlign(); - if (rightToLeftText) { + if (contentDirection == Qt::RightToLeft) { if (horizontalAlignment == QQuickTextEdit::AlignLeft) horizontalAlignment = QQuickTextEdit::AlignRight; else if (horizontalAlignment == QQuickTextEdit::AlignRight) horizontalAlignment = QQuickTextEdit::AlignLeft; } - opt.setAlignment((Qt::Alignment)(int)(horizontalAlignment | vAlign)); + if (!hAlignImplicit) + opt.setAlignment((Qt::Alignment)(int)(horizontalAlignment | vAlign)); + else + opt.setAlignment(Qt::Alignment(vAlign)); + + if (contentDirection == Qt::LayoutDirectionAuto) { + opt.setTextDirection(qGuiApp->inputMethod()->inputDirection()); + } else { + opt.setTextDirection(contentDirection); + } QTextOption::WrapMode oldWrapMode = opt.wrapMode(); opt.setWrapMode(QTextOption::WrapMode(wrapMode)); opt.setUseDesignMetrics(true); - if (oldWrapMode == opt.wrapMode() && oldAlignment == opt.alignment()) - return; - - document->setDefaultTextOption(opt); + if (oldWrapMode != opt.wrapMode() || oldAlignment != opt.alignment() + || oldTextDirection != opt.textDirection()) { + document->setDefaultTextOption(opt); + } } diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h index f0a35d5266..e556367bcf 100644 --- a/src/quick/items/qquicktextedit_p_p.h +++ b/src/quick/items/qquicktextedit_p_p.h @@ -73,12 +73,13 @@ public: , lastSelectionStart(0), lastSelectionEnd(0), lineCount(0) , hAlign(QQuickTextEdit::AlignLeft), vAlign(QQuickTextEdit::AlignTop) , format(QQuickTextEdit::PlainText), wrapMode(QQuickTextEdit::NoWrap) + , contentDirection(Qt::LayoutDirectionAuto) , mouseSelectionMode(QQuickTextEdit::SelectCharacters), inputMethodHints(Qt::ImhNone) , updateType(UpdatePaintNode) , documentDirty(true), dirty(false), richText(false), cursorVisible(false) , focusOnPress(true), persistentSelection(false), requireImplicitWidth(false) , selectByMouse(false), canPaste(false), canPasteValid(false), hAlignImplicit(true) - , rightToLeftText(false), textCached(false), inLayout(false) + , textCached(false), inLayout(false) { } @@ -93,6 +94,7 @@ public: bool setHAlign(QQuickTextEdit::HAlignment, bool forceAlign = false); void mirrorChange(); qreal getImplicitWidth() const; + Qt::LayoutDirection textDirection(const QString &text) const; QColor color; QColor selectionColor; @@ -127,6 +129,7 @@ public: QQuickTextEdit::VAlignment vAlign; QQuickTextEdit::TextFormat format; QQuickTextEdit::WrapMode wrapMode; + Qt::LayoutDirection contentDirection; QQuickTextEdit::SelectionMode mouseSelectionMode; Qt::InputMethodHints inputMethodHints; UpdateType updateType; @@ -142,7 +145,6 @@ public: bool canPaste:1; bool canPasteValid:1; bool hAlignImplicit:1; - bool rightToLeftText:1; bool textCached:1; bool inLayout:1; }; diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index 0bc48c98da..51b04cf7a0 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -751,6 +751,16 @@ void tst_qquicktextedit::hAlign_RightToLeft() QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight); QVERIFY(textEdit->positionToRectangle(0).x() > canvas.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() < canvas.width()/2); + platformInputContext.setInputDirection(Qt::RightToLeft); + QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight); + QVERIFY(textEdit->cursorRectangle().left() > canvas.width()/2); + // set input direction while having content platformInputContext.setInputDirection(Qt::LeftToRight); textEdit->setText("a"); -- GitLab