From f4b028114a9040147fa98ca8c8cfc58dcb2f6102 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 28 Oct 2022 14:13:01 +0200 Subject: [PATCH] QComboBox: refactor item flashing code in hidePopup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of using a local event loop, control the flashing through timers and lambdas. Move the actual hiding of the popup then into a helper that gets called when the flashing is done. Note: this changes behavior -the popup will not be hidden when hidePopup returns. And since events continue get processed during the flashing effect, we might still get reentrancy (so the code added in accc833e556ba54038d1cc7e261a936492145240 has to stay anyway). Change-Id: I2ce20520dea16bd3be78544e9fdd059a2969a795 Reviewed-by: Tor Arne Vestbø --- src/widgets/widgets/qcombobox.cpp | 61 +++++++++++++++++++------------ src/widgets/widgets/qcombobox_p.h | 1 + 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 7c5de0e2cb..4b5508575a 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -2813,41 +2813,54 @@ void QComboBox::hidePopup() auto resetHidingPopup = qScopeGuard([d]{ d->hidingPopup = false; }); - if (d->container && d->container->isVisible()) { + + if (!d->container || !d->container->isVisible()) + return; + #if QT_CONFIG(effects) - QSignalBlocker modelBlocker(d->model); - QSignalBlocker viewBlocker(d->container->itemView()); - QSignalBlocker containerBlocker(d->container); - // Flash selected/triggered item (if any). - if (style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem)) { - QItemSelectionModel *selectionModel = view() ? view()->selectionModel() : nullptr; - if (selectionModel && selectionModel->hasSelection()) { - QEventLoop eventLoop; - const QItemSelection selection = selectionModel->selection(); + // Flash selected/triggered item (if any). + if (style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem)) { + QItemSelectionModel *selectionModel = d->container->itemView() + ? d->container->itemView()->selectionModel() : nullptr; + if (selectionModel && selectionModel->hasSelection()) { + const QItemSelection selection = selectionModel->selection(); + + QTimer::singleShot(0, d->container, [d, selection, selectionModel]{ + QSignalBlocker modelBlocker(d->model); + QSignalBlocker viewBlocker(d->container->itemView()); + QSignalBlocker containerBlocker(d->container); // Deselect item and wait 60 ms. selectionModel->select(selection, QItemSelectionModel::Toggle); - QTimer::singleShot(60, &eventLoop, SLOT(quit())); - eventLoop.exec(); - - // Select item and wait 20 ms. - selectionModel->select(selection, QItemSelectionModel::Toggle); - QTimer::singleShot(20, &eventLoop, SLOT(quit())); - eventLoop.exec(); - } + QTimer::singleShot(60, d->container, [d, selection, selectionModel]{ + QSignalBlocker modelBlocker(d->model); + QSignalBlocker viewBlocker(d->container->itemView()); + QSignalBlocker containerBlocker(d->container); + selectionModel->select(selection, QItemSelectionModel::Toggle); + QTimer::singleShot(20, d->container, [d] { + d->doHidePopup(); + }); + }); + }); } - - containerBlocker.unblock(); - viewBlocker.unblock(); - modelBlocker.unblock(); + } else #endif // QT_CONFIG(effects) - d->container->hide(); + { + d->doHidePopup(); } +} + +void QComboBoxPrivate::doHidePopup() +{ + if (container && container->isVisible()) + container->hide(); + #ifdef QT_KEYPAD_NAVIGATION if (QApplicationPrivate::keypadNavigationEnabled() && isEditable() && hasFocus()) setEditFocus(true); #endif - d->_q_resetButton(); + + _q_resetButton(); } /*! diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h index a26f3a34d4..8e686ac79a 100644 --- a/src/widgets/widgets/qcombobox_p.h +++ b/src/widgets/widgets/qcombobox_p.h @@ -352,6 +352,7 @@ public: void updateViewContainerPaletteAndOpacity(); void updateFocusPolicy(); void showPopupFromMouseEvent(QMouseEvent *e); + void doHidePopup(); #ifdef Q_OS_MAC void cleanupNativePopup();