fix placement of placeholder text in QLineEdits with action icons
authorDebian Qt/KDE Maintainers <debian-qt-kde@lists.debian.org>
Fri, 1 Jul 2022 19:49:23 +0000 (20:49 +0100)
committerDmitry Shachnev <mitya57@debian.org>
Fri, 1 Jul 2022 19:49:23 +0000 (20:49 +0100)
Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=0e6b31019f01c72e
Last-Update: 2021-08-10

After dc794f7622bc00f7ca50fab65d6965695d6d2972, side widgets only got
space if they were not fading out, but the logic was not correctly
accounting for side widgets that never fade, such as buttons added via
QLineEdit::addAction.

Fix this to give visible widgets space, unless they are fading out. That
was the intent of the original change. Rename the variable to make its
purpose clearer, and reset it at the end of the fade-out animation.

Add a much-needed test that relies on private APIs to verify that the
effective margins are calculated correctly.

Gbp-Pq: Name fix-placement-of-placeholder-text-in-QLineEdits-with-action-icons.diff

src/widgets/widgets/qlineedit_p.cpp
src/widgets/widgets/qlineedit_p.h
tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp

index 1d4be0fde9123610141c4f12b14764905825f7a2..80c9258da476e2982f18a657cab640a00c17f1bd 100644 (file)
@@ -407,8 +407,9 @@ void QLineEditIconButton::setHideWithText(bool hide)
 
 void QLineEditIconButton::onAnimationFinished()
 {
-    if (shouldHideWithText() && isVisible() && !m_wasHidden) {
+    if (shouldHideWithText() && isVisible() && m_fadingOut) {
         hide();
+        m_fadingOut = false;
 
         // Invalidate previous geometry to take into account new size of side widgets
         if (auto le = lineEditPrivate())
@@ -418,7 +419,7 @@ void QLineEditIconButton::onAnimationFinished()
 
 void QLineEditIconButton::animateShow(bool visible)
 {
-    m_wasHidden = visible;
+    m_fadingOut = !visible;
 
     if (shouldHideWithText() && !isVisible()) {
         show();
index bbe3e8ea640b756246c76a6477ec91836f18a0e5..f55210fc7f859e3d282a6b17187e9f381c4c04e3 100644 (file)
@@ -95,8 +95,11 @@ public:
 
     bool shouldHideWithText() const;
     void setHideWithText(bool hide);
-    // m_wasHidden is true unless the button is fading out
-    bool needsSpace() const { return m_wasHidden; }
+    bool needsSpace() const {
+        if (m_fadingOut)
+            return false;
+        return isVisibleTo(parentWidget());
+    }
 #endif
 
 protected:
@@ -120,7 +123,7 @@ private:
 
 #if QT_CONFIG(animation)
     bool m_hideWithText = false;
-    bool m_wasHidden = false;
+    bool m_fadingOut = false;
 #endif
 
 };
index 6408df3f112a46e9e13d9c3e87196f658f21695f..7c2203deb4bfcec8db271f42a715b92a726434e8 100644 (file)
@@ -292,6 +292,7 @@ private slots:
     void clearButtonVisibleAfterSettingText_QTBUG_45518();
     void sideWidgets();
     void sideWidgetsActionEvents();
+    void sideWidgetsEffectiveMargins();
 
     void shouldShowPlaceholderText_data();
     void shouldShowPlaceholderText();
@@ -4646,6 +4647,71 @@ void tst_QLineEdit::sideWidgetsActionEvents()
     QCOMPARE(toolButton2->x(), toolButton1X);
 }
 
+/*!
+    Verify that side widgets are positioned correctly and result in
+    correct effective text margins.
+*/
+void tst_QLineEdit::sideWidgetsEffectiveMargins()
+{
+#ifndef QT_BUILD_INTERNAL
+    QSKIP("This test requires a developer build.");
+#else
+    QLineEdit edit;
+    edit.setPlaceholderText("placeholder");
+    edit.setClearButtonEnabled(true);
+    edit.show();
+    QLineEditPrivate *priv = QLineEditPrivate::get(&edit);
+    const auto sideWidgetParameters = priv->sideWidgetParameters();
+    const int sideWidgetWidth = sideWidgetParameters.widgetWidth + sideWidgetParameters.margin;
+    QVERIFY(QTest::qWaitForWindowExposed(&edit));
+
+    QCOMPARE(priv->effectiveTextMargins().left(), 0);
+    QCOMPARE(priv->effectiveTextMargins().right(), 0);
+
+    edit.setText("Left to right"); // clear button fades in on the right
+    QCOMPARE(priv->effectiveTextMargins().left(), 0);
+    QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+    edit.clear();
+    QCOMPARE(priv->effectiveTextMargins().left(), 0);
+    QCOMPARE(priv->effectiveTextMargins().right(), 0);
+
+    edit.setLayoutDirection(Qt::RightToLeft);
+    edit.setText("ئۇيغۇر تىلى"); // clear button fades in on the left
+    QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+    QCOMPARE(priv->effectiveTextMargins().right(), 0);
+    edit.clear();
+    QCOMPARE(priv->effectiveTextMargins().left(), 0);
+    QCOMPARE(priv->effectiveTextMargins().right(), 0);
+
+    edit.setLayoutDirection(Qt::LeftToRight);
+
+    const QIcon leftIcon = edit.style()->standardIcon(QStyle::SP_FileIcon);
+    const QIcon rightIcon = edit.style()->standardIcon(QStyle::SP_DirIcon);
+    edit.addAction(leftIcon, QLineEdit::ActionPosition::LeadingPosition);
+    QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+    QCOMPARE(priv->effectiveTextMargins().right(), 0);
+
+    edit.addAction(rightIcon, QLineEdit::ActionPosition::TrailingPosition);
+    QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+    QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+
+    edit.setText("Left to right"); // clear button on the right
+    QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+    QCOMPARE(priv->effectiveTextMargins().right(), 2 * sideWidgetWidth);
+    edit.clear();
+    QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+    QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+
+    edit.setLayoutDirection(Qt::RightToLeft);
+    edit.setText("ئۇيغۇر تىلى"); // clear button fades in on the left
+    QCOMPARE(priv->effectiveTextMargins().left(), 2 * sideWidgetWidth);
+    QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+    edit.clear();
+    QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+    QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+#endif
+}
+
 Q_DECLARE_METATYPE(Qt::AlignmentFlag)
 void tst_QLineEdit::shouldShowPlaceholderText_data()
 {