From 44a2dd16ed00d11e5625e9eea029c2b58c9d93b6 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Mon, 21 Aug 2023 15:43:12 +0200 Subject: [PATCH] QDialogButtonBox: Use separate eventFilter class bbb71e7e80f292c2e69faef81b1624832981147e added an eventFilter override to QDialogButtonBox, in order to fix QTBUG-114377. The approach added a symbol to QDialogButtonBox, which breaks binary compatibility between patch releases. => Use a separate class to install an event filter => Remove the symbol (eventFilter override) in QDialogButtonBox Fixes: QTBUG-116287 Change-Id: I920deca9f45f6246ed1fcbf5346f681dd5dd12f6 Reviewed-by: Marc Mutz Reviewed-by: Volker Hilsheimer (cherry picked from commit aff0915352dda0cfaa11a249b665fbe47be21d69) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/widgets/qdialogbuttonbox.cpp | 47 ++++++++++++------------ src/widgets/widgets/qdialogbuttonbox.h | 2 - src/widgets/widgets/qdialogbuttonbox_p.h | 4 +- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/widgets/widgets/qdialogbuttonbox.cpp b/src/widgets/widgets/qdialogbuttonbox.cpp index f319db7e10f..69fea049145 100644 --- a/src/widgets/widgets/qdialogbuttonbox.cpp +++ b/src/widgets/widgets/qdialogbuttonbox.cpp @@ -115,6 +115,22 @@ QT_BEGIN_NAMESPACE QDialogButtonBoxPrivate::QDialogButtonBoxPrivate(Qt::Orientation orient) : orientation(orient), buttonLayout(nullptr), center(false) { + struct EventFilter : public QObject + { + EventFilter(QDialogButtonBoxPrivate *d) : d(d) {}; + + bool eventFilter(QObject *obj, QEvent *event) override + { + QAbstractButton *button = qobject_cast(obj); + return button ? d->handleButtonShowAndHide(button, event) : false; + } + + private: + QDialogButtonBoxPrivate *d; + + }; + + filter.reset(new EventFilter(this)); } void QDialogButtonBoxPrivate::initLayout() @@ -171,7 +187,7 @@ void QDialogButtonBoxPrivate::layoutButtons() Q_Q(QDialogButtonBox); const int MacGap = 36 - 8; // 8 is the default gap between a widget and a spacer item - QBoolBlocker blocker(byPassEventFilter); + QBoolBlocker blocker(ignoreShowAndHide); for (int i = buttonLayout->count() - 1; i >= 0; --i) { QLayoutItem *item = buttonLayout->takeAt(i); if (QWidget *widget = item->widget()) @@ -369,7 +385,6 @@ QPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardBut void QDialogButtonBoxPrivate::addButton(QAbstractButton *button, QDialogButtonBox::ButtonRole role, LayoutRule layoutRule, AddRule addRule) { - Q_Q(QDialogButtonBox); buttonLists[role].append(button); switch (addRule) { case AddRule::Connect: @@ -377,7 +392,7 @@ void QDialogButtonBoxPrivate::addButton(QAbstractButton *button, QDialogButtonBo this, &QDialogButtonBoxPrivate::handleButtonClicked); QObjectPrivate::connect(button, &QAbstractButton::destroyed, this, &QDialogButtonBoxPrivate::handleButtonDestroyed); - button->installEventFilter(q); + button->installEventFilter(filter.get()); break; case AddRule::SkipConnect: break; @@ -466,7 +481,7 @@ QDialogButtonBox::~QDialogButtonBox() { Q_D(QDialogButtonBox); - d->byPassEventFilter = true; + d->ignoreShowAndHide = true; // QObjectPrivate::connect requires explicit disconnect in destructor // otherwise the connection may kick in on child destruction and reach @@ -694,7 +709,6 @@ void QDialogButtonBox::removeButton(QAbstractButton *button) void QDialogButtonBoxPrivate::removeButton(QAbstractButton *button, RemoveRule rule) { - Q_Q(QDialogButtonBox); if (!button) return; @@ -713,7 +727,7 @@ void QDialogButtonBoxPrivate::removeButton(QAbstractButton *button, RemoveRule r this, &QDialogButtonBoxPrivate::handleButtonClicked); QObjectPrivate::disconnect(button, &QAbstractButton::destroyed, this, &QDialogButtonBoxPrivate::handleButtonDestroyed); - button->removeEventFilter(q); + button->removeEventFilter(filter.get()); break; case RemoveRule::KeepConnections: break; @@ -870,30 +884,15 @@ void QDialogButtonBoxPrivate::handleButtonDestroyed() removeButton(reinterpret_cast(object), RemoveRule::KeepConnections); } -bool QDialogButtonBox::eventFilter(QObject *object, QEvent *event) -{ - Q_D(QDialogButtonBox); - if (d->byPassEventFilter) - return false; - - QAbstractButton *button = qobject_cast(object); - if (!button) - return false; - - - const QEvent::Type type = event->type(); - if (type == QEvent::HideToParent || type == QEvent::ShowToParent) - return d->handleButtonShowAndHide(button, event); - - return false; -} - bool QDialogButtonBoxPrivate::handleButtonShowAndHide(QAbstractButton *button, QEvent *event) { Q_Q(QDialogButtonBox); const QEvent::Type type = event->type(); + if ((type != QEvent::HideToParent && type != QEvent::ShowToParent) || ignoreShowAndHide) + return false; + switch (type) { case QEvent::HideToParent: { const QDialogButtonBox::ButtonRole role = q->buttonRole(button); diff --git a/src/widgets/widgets/qdialogbuttonbox.h b/src/widgets/widgets/qdialogbuttonbox.h index 4c116b5bab7..d967494d0df 100644 --- a/src/widgets/widgets/qdialogbuttonbox.h +++ b/src/widgets/widgets/qdialogbuttonbox.h @@ -107,8 +107,6 @@ public: void setCenterButtons(bool center); bool centerButtons() const; - bool eventFilter(QObject *object, QEvent *event) override; - Q_SIGNALS: void clicked(QAbstractButton *button); void accepted(); diff --git a/src/widgets/widgets/qdialogbuttonbox_p.h b/src/widgets/widgets/qdialogbuttonbox_p.h index 5911c96a469..1aa60712412 100644 --- a/src/widgets/widgets/qdialogbuttonbox_p.h +++ b/src/widgets/widgets/qdialogbuttonbox_p.h @@ -19,6 +19,7 @@ #include QT_BEGIN_NAMESPACE + class Q_AUTOTEST_EXPORT QDialogButtonBoxPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QDialogButtonBox) @@ -46,8 +47,9 @@ public: Qt::Orientation orientation; QDialogButtonBox::ButtonLayout layoutPolicy; QBoxLayout *buttonLayout; + std::unique_ptr filter; bool center; - bool byPassEventFilter = false; + bool ignoreShowAndHide = false; void createStandardButtons(QDialogButtonBox::StandardButtons buttons);