From 8903bb3d64f6c47cd7e616fcba0a8e972c68b387 Mon Sep 17 00:00:00 2001 From: Vladimir Belyavsky Date: Mon, 11 Dec 2023 21:45:22 +0300 Subject: [PATCH] TextArea/TextField: properly update placeholder text alignment Placeholder text alignment depends on actual alignment of a parent control, e.g. TextArea or TextField. Thus, if the horizontal text alignment of the parent control is set explicitly, the placeholder text must have the same alignment. Otherwise, the placeholder text alignment should respect to the natural alignment of the text. In order to do this QQuickPlaceholderText is connected to effectiveHorizontalAlignmentChanged() signal of the parent control. The problem is that the signal may not be emitted when alignment is set explicitly after the component creation, so the placeholder text alignment will not be updated respectively. To solve this we need to make sure that the signal is forcibly emitted every time when the alignment is set explicitly. Fixes: QTBUG-120052 Pick-to: 6.5 Change-Id: Ib66a7a46d523777cc54ca6b6883d3fecc800dfb2 Reviewed-by: Mitch Curtis (cherry picked from commit 694a677535ef11f9c966920c5e99d304bdbd94a5) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 8b12eb7ed530d419538615ac85ec815a8fa6ff43) --- src/quick/items/qquicktextedit.cpp | 58 ++++++++++++++++++----------- src/quick/items/qquicktextinput.cpp | 55 ++++++++++++++++++--------- 2 files changed, 73 insertions(+), 40 deletions(-) diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 1f54a5fe11..df83d2abf8 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -715,9 +715,8 @@ QQuickTextEdit::HAlignment QQuickTextEdit::hAlign() const void QQuickTextEdit::setHAlign(HAlignment align) { Q_D(QQuickTextEdit); - bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror; - d->hAlignImplicit = false; - if (d->setHAlign(align, forceAlign) && isComponentComplete()) { + + if (d->setHAlign(align, true) && isComponentComplete()) { d->updateDefaultTextOption(); updateSize(); } @@ -752,21 +751,34 @@ QQuickTextEdit::HAlignment QQuickTextEdit::effectiveHAlign() const return effectiveAlignment; } -bool QQuickTextEditPrivate::setHAlign(QQuickTextEdit::HAlignment alignment, bool forceAlign) +bool QQuickTextEditPrivate::setHAlign(QQuickTextEdit::HAlignment align, bool forceAlign) { Q_Q(QQuickTextEdit); - if (hAlign != alignment || forceAlign) { - QQuickTextEdit::HAlignment oldEffectiveHAlign = q->effectiveHAlign(); - hAlign = alignment; - emit q->horizontalAlignmentChanged(alignment); - if (oldEffectiveHAlign != q->effectiveHAlign()) - emit q->effectiveHorizontalAlignmentChanged(); + if (hAlign == align && !forceAlign) + return false; + + const bool wasImplicit = hAlignImplicit; + const auto oldEffectiveHAlign = q->effectiveHAlign(); + + hAlignImplicit = !forceAlign; + if (hAlign != align) { + hAlign = align; + emit q->horizontalAlignmentChanged(align); + } + + if (q->effectiveHAlign() != oldEffectiveHAlign) { + emit q->effectiveHorizontalAlignmentChanged(); return true; } + + if (forceAlign && wasImplicit) { + // QTBUG-120052 - when horizontal text alignment is set explicitly, + // we need notify any other controls that may depend on it, like QQuickPlaceholderText + emit q->effectiveHorizontalAlignmentChanged(); + } return false; } - Qt::LayoutDirection QQuickTextEditPrivate::textDirection(const QString &text) const { const QChar *character = text.constData(); @@ -789,20 +801,22 @@ Qt::LayoutDirection QQuickTextEditPrivate::textDirection(const QString &text) co bool QQuickTextEditPrivate::determineHorizontalAlignment() { Q_Q(QQuickTextEdit); - if (hAlignImplicit && q->isComponentComplete()) { - Qt::LayoutDirection direction = contentDirection; + if (!hAlignImplicit || !q->isComponentComplete()) + return false; + + Qt::LayoutDirection direction = contentDirection; #if QT_CONFIG(im) - if (direction == Qt::LayoutDirectionAuto) { - const QString preeditText = control->textCursor().block().layout()->preeditAreaText(); - direction = textDirection(preeditText); - } - if (direction == Qt::LayoutDirectionAuto) - direction = qGuiApp->inputMethod()->inputDirection(); + if (direction == Qt::LayoutDirectionAuto) { + const QString preeditText = control->textCursor().block().layout()->preeditAreaText(); + direction = textDirection(preeditText); + } + if (direction == Qt::LayoutDirectionAuto) + direction = qGuiApp->inputMethod()->inputDirection(); #endif - return setHAlign(direction == Qt::RightToLeft ? QQuickTextEdit::AlignRight : QQuickTextEdit::AlignLeft); - } - return false; + const auto implicitHAlign = direction == Qt::RightToLeft ? + QQuickTextEdit::AlignRight : QQuickTextEdit::AlignLeft; + return setHAlign(implicitHAlign); } void QQuickTextEditPrivate::mirrorChange() diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 550a53b888..f8c68b3f7b 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -540,9 +540,8 @@ QQuickTextInput::HAlignment QQuickTextInput::hAlign() const void QQuickTextInput::setHAlign(HAlignment align) { Q_D(QQuickTextInput); - bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror; - d->hAlignImplicit = false; - if (d->setHAlign(align, forceAlign) && isComponentComplete()) { + + if (d->setHAlign(align, true) && isComponentComplete()) { d->updateLayout(); updateCursorRectangle(); } @@ -577,17 +576,34 @@ QQuickTextInput::HAlignment QQuickTextInput::effectiveHAlign() const return effectiveAlignment; } -bool QQuickTextInputPrivate::setHAlign(QQuickTextInput::HAlignment alignment, bool forceAlign) +bool QQuickTextInputPrivate::setHAlign(QQuickTextInput::HAlignment align, bool forceAlign) { Q_Q(QQuickTextInput); - if ((hAlign != alignment || forceAlign) && alignment <= QQuickTextInput::AlignHCenter) { // justify not supported - QQuickTextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign(); - hAlign = alignment; - emit q->horizontalAlignmentChanged(alignment); - if (oldEffectiveHAlign != q->effectiveHAlign()) - emit q->effectiveHorizontalAlignmentChanged(); + if (align > QQuickTextInput::AlignHCenter) + return false; // justify is not supported + + if (hAlign == align && !forceAlign) + return false; + + const bool wasImplicit = hAlignImplicit; + const auto oldEffectiveHAlign = q->effectiveHAlign(); + + hAlignImplicit = !forceAlign; + if (hAlign != align) { + hAlign = align; + emit q->horizontalAlignmentChanged(align); + } + + if (q->effectiveHAlign() != oldEffectiveHAlign) { + emit q->effectiveHorizontalAlignmentChanged(); return true; } + + if (forceAlign && wasImplicit) { + // QTBUG-120052 - when horizontal text alignment is set explicitly, + // we need notify any other controls that may depend on it, like QQuickPlaceholderText + emit q->effectiveHorizontalAlignmentChanged(); + } return false; } @@ -631,16 +647,19 @@ Qt::LayoutDirection QQuickTextInputPrivate::layoutDirection() const bool QQuickTextInputPrivate::determineHorizontalAlignment() { - if (hAlignImplicit) { - // if no explicit alignment has been set, follow the natural layout direction of the text - Qt::LayoutDirection direction = textDirection(); + if (!hAlignImplicit) + return false; + + // if no explicit alignment has been set, follow the natural layout direction of the text + Qt::LayoutDirection direction = textDirection(); #if QT_CONFIG(im) - if (direction == Qt::LayoutDirectionAuto) - direction = QGuiApplication::inputMethod()->inputDirection(); + if (direction == Qt::LayoutDirectionAuto) + direction = QGuiApplication::inputMethod()->inputDirection(); #endif - return setHAlign(direction == Qt::RightToLeft ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft); - } - return false; + + const auto implicitHAlign = direction == Qt::RightToLeft ? + QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft; + return setHAlign(implicitHAlign); } QQuickTextInput::VAlignment QQuickTextInput::vAlign() const