Handle action events in QLineEditIconButton.
authorFriedemann Kleint <Friedemann.Kleint@theqtcompany.com>
Fri, 22 May 2015 07:39:52 +0000 (09:39 +0200)
committerDavid Faure <david.faure@kdab.com>
Tue, 18 Aug 2015 12:47:17 +0000 (12:47 +0000)
Ensure QAction::setVisible() is
handled and reposition if visibility changes.

Task-number: QTBUG-39660
Change-Id: I14f0659aedc8dc89ddef3159d3a500b40b1563ff
Reviewed-by: David Faure <david.faure@kdab.com>
src/widgets/widgets/qlineedit_p.cpp
src/widgets/widgets/qlineedit_p.h
tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp

index 3f768bfbd34e4ba9efa5c48a95f36947561c25b7..6645a375a7393163a3f41172702591b17e004657 100644 (file)
@@ -324,6 +324,24 @@ void QLineEditIconButton::paintEvent(QPaintEvent *)
     painter.drawPixmap(pixmapRect, iconPixmap);
 }
 
+void QLineEditIconButton::actionEvent(QActionEvent *e)
+{
+    switch (e->type()) {
+    case QEvent::ActionChanged: {
+        const QAction *action = e->action();
+        if (isVisible() != action->isVisible()) {
+            setVisible(action->isVisible());
+            if (QLineEdit *le = qobject_cast<QLineEdit *>(parentWidget()))
+                static_cast<QLineEditPrivate *>(qt_widget_private(le))->positionSideWidgets();
+        }
+    }
+        break;
+    default:
+        break;
+    }
+    QToolButton::actionEvent(e);
+}
+
 void QLineEditIconButton::setOpacity(qreal value)
 {
     if (!qFuzzyCompare(m_opacity, value)) {
@@ -415,12 +433,14 @@ void QLineEditPrivate::positionSideWidgets()
         QRect widgetGeometry(QPoint(QLineEditIconButton::IconMargin, (contentRect.height() - iconSize.height()) / 2), iconSize);
         foreach (const SideWidgetEntry &e, leftSideWidgetList()) {
             e.widget->setGeometry(widgetGeometry);
-            widgetGeometry.moveLeft(widgetGeometry.left() + delta);
+            if (e.widget->isVisible())
+                widgetGeometry.moveLeft(widgetGeometry.left() + delta);
         }
         widgetGeometry.moveLeft(contentRect.width() - iconSize.width() - QLineEditIconButton::IconMargin);
         foreach (const SideWidgetEntry &e, rightSideWidgetList()) {
             e.widget->setGeometry(widgetGeometry);
-            widgetGeometry.moveLeft(widgetGeometry.left() - delta);
+            if (e.widget->isVisible())
+                widgetGeometry.moveLeft(widgetGeometry.left() - delta);
         }
     }
 }
index 4654262ea736ed3887d6bddb8ab916aa37d2e97e..5a222851496cc0aec1031e28a71fd4e92ae19178 100644 (file)
@@ -61,6 +61,8 @@
 
 #include "private/qwidgetlinecontrol_p.h"
 
+#include <algorithm>
+
 QT_BEGIN_NAMESPACE
 
 // QLineEditIconButton: This is a simple helper class that represents clickable icons that fade in with text
@@ -81,6 +83,7 @@ public:
 #endif
 
 protected:
+    void actionEvent(QActionEvent *e) Q_DECL_OVERRIDE;
     void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
 
 private slots:
@@ -226,14 +229,23 @@ private:
     mutable QSize m_iconSize;
 };
 
+static bool isSideWidgetVisible(const QLineEditPrivate::SideWidgetEntry &e)
+{
+   return e.widget->isVisible();
+}
+
 inline int QLineEditPrivate::effectiveLeftTextMargin() const
 {
-    return leftTextMargin + leftSideWidgetList().size() * (QLineEditIconButton::IconMargin + iconSize().width());
+    return leftTextMargin + (QLineEditIconButton::IconMargin + iconSize().width())
+        * int(std::count_if(leftSideWidgetList().constBegin(), leftSideWidgetList().constEnd(),
+                            isSideWidgetVisible));
 }
 
 inline int QLineEditPrivate::effectiveRightTextMargin() const
 {
-    return rightTextMargin + rightSideWidgetList().size() * (QLineEditIconButton::IconMargin + iconSize().width());
+    return rightTextMargin + (QLineEditIconButton::IconMargin + iconSize().width())
+        * int(std::count_if(rightSideWidgetList().constBegin(), rightSideWidgetList().constEnd(),
+                            isSideWidgetVisible));
 }
 
 #endif // QT_NO_LINEEDIT
index adedc601a96588dbee9048b2d33a05b7cfb847c2..e6d63ee4d91a207f26c531e2ea40d3a1aa51c8a4 100644 (file)
@@ -306,6 +306,7 @@ private slots:
     void clearButton();
     void clearButtonVisibleAfterSettingText_QTBUG_45518();
     void sideWidgets();
+    void sideWidgetsActionEvents();
 
     void shouldShowPlaceholderText_data();
     void shouldShowPlaceholderText();
@@ -4318,6 +4319,13 @@ void tst_QLineEdit::clearButtonVisibleAfterSettingText_QTBUG_45518()
 #endif // QT_BUILD_INTERNAL
 }
 
+static inline QIcon sideWidgetTestIcon()
+{
+    QImage image(QSize(20, 20), QImage::Format_ARGB32);
+    image.fill(Qt::yellow);
+    return QIcon(QPixmap::fromImage(image));
+}
+
 void tst_QLineEdit::sideWidgets()
 {
     QWidget testWidget;
@@ -4325,9 +4333,7 @@ void tst_QLineEdit::sideWidgets()
     QLineEdit *lineEdit = new QLineEdit(&testWidget);
     l->addWidget(lineEdit);
     l->addSpacerItem(new QSpacerItem(0, 50, QSizePolicy::Ignored, QSizePolicy::Fixed));
-    QImage image(QSize(20, 20), QImage::Format_ARGB32);
-    image.fill(Qt::yellow);
-    QAction *iconAction = new QAction(QIcon(QPixmap::fromImage(image)), QString(), lineEdit);
+    QAction *iconAction = new QAction(sideWidgetTestIcon(), QString(), lineEdit);
     QWidgetAction *label1Action = new QWidgetAction(lineEdit);
     label1Action->setDefaultWidget(new QLabel(QStringLiteral("l1")));
     QWidgetAction *label2Action = new QWidgetAction(lineEdit);
@@ -4354,6 +4360,38 @@ void tst_QLineEdit::sideWidgets()
     lineEdit->addAction(iconAction);
 }
 
+void tst_QLineEdit::sideWidgetsActionEvents()
+{
+    // QTBUG-39660, verify whether action events are handled by the widget.
+    QWidget testWidget;
+    QVBoxLayout *l = new QVBoxLayout(&testWidget);
+    QLineEdit *lineEdit = new QLineEdit(&testWidget);
+    l->addWidget(lineEdit);
+    l->addSpacerItem(new QSpacerItem(0, 50, QSizePolicy::Ignored, QSizePolicy::Fixed));
+    QAction *iconAction = lineEdit->addAction(sideWidgetTestIcon(), QLineEdit::LeadingPosition);
+    testWidget.move(300, 300);
+    testWidget.show();
+    QVERIFY(QTest::qWaitForWindowExposed(&testWidget));
+
+    QWidget *toolButton = Q_NULLPTR;
+    foreach (QWidget *w, iconAction->associatedWidgets()) {
+        if (qobject_cast<QToolButton *>(w)) {
+            toolButton = w;
+            break;
+        }
+    }
+    QVERIFY(toolButton);
+
+    QVERIFY(toolButton->isVisible());
+    QVERIFY(toolButton->isEnabled());
+
+    iconAction->setEnabled(false);
+    QVERIFY(!toolButton->isEnabled());
+
+    iconAction->setVisible(false);
+    QVERIFY(!toolButton->isVisible());
+}
+
 Q_DECLARE_METATYPE(Qt::AlignmentFlag)
 void tst_QLineEdit::shouldShowPlaceholderText_data()
 {