TextEdit to honor input direction on neutral text
authorPekka Vuorela <pekka.ta.vuorela@nokia.com>
Tue, 24 Apr 2012 13:46:27 +0000 (16:46 +0300)
committerQt by Nokia <qt-info@nokia.com>
Fri, 27 Apr 2012 11:47:34 +0000 (13:47 +0200)
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
src/quick/items/qquicktextedit_p_p.h
tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp

index fc02815..0e5023f 100644 (file)
@@ -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);
+    }
 }
 
 
index f0a35d5..e556367 100644 (file)
@@ -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;
 };
index 0bc48c9..51b04cf 100644 (file)
@@ -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");