diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-05-26 13:05:34 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-05-31 18:32:35 +0000 |
commit | 84a1087bf672f04eb24cccc8efb3a5b24f3b16d4 (patch) | |
tree | 7cfe27c5671fa737f7a7190009596d0d1f50ea4e | |
parent | QLocalSocket: fix inclusions in namespaced builds (diff) | |
download | qtbase-84a1087bf672f04eb24cccc8efb3a5b24f3b16d4.tar.xz qtbase-84a1087bf672f04eb24cccc8efb3a5b24f3b16d4.zip |
QComboBox: propagate style change on widget to internal container
When changing the style of the combobox, the change will not propagate
to the internal container widget, so the changeEvent handler won't be
called. This is correct (as per QWidget::setStyle documentation).
QComboBoxPrivateContainer asks the combobox style for relevant settings,
such as the frame style, which is then used for sizing and positioning.
If the combobox's and container's settings become inconsistent, then the
combobox popup will not get the correct size and/or position.
Move some of the style-dependent changes into a separate function and
call it when the QComboBox::changeEvent handles the style change so that
both widgets have a consistent set of settings.
Add a test case that verifies that the style is asked for the relevant
setting when the style changes.
Note: QComboBox does a lot of style-dependent setup work in different
places, which is quite messy and complex. Trying to consolidate that
further breaks tests though, so this change is doing the minimum
necessary to fix the reported issue.
Fixes: QTBUG-92488
Change-Id: Ia957d504b2d800add26fc0565be727b5c08a5358
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
(cherry picked from commit d36ef40d18b40cfc6f57c1002079f02a15eb41d3)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/widgets/widgets/qcombobox.cpp | 24 | ||||
-rw-r--r-- | src/widgets/widgets/qcombobox_p.h | 1 | ||||
-rw-r--r-- | tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp | 46 |
3 files changed, 62 insertions, 9 deletions
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 894d8ce36d..49489565a3 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -547,8 +547,6 @@ QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView setLineWidth(1); } - setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo)); - if (top) { layout->insertWidget(0, top); connect(top, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int))); @@ -561,7 +559,7 @@ QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView // Some styles (Mac) have a margin at the top and bottom of the popup. layout->insertSpacing(0, 0); layout->addSpacing(0); - updateTopBottomMargin(); + updateStyleSettings(); } void QComboBoxPrivateContainer::scrollItemView(int action) @@ -744,14 +742,20 @@ void QComboBoxPrivateContainer::updateTopBottomMargin() boxLayout->invalidate(); } +void QComboBoxPrivateContainer::updateStyleSettings() +{ + // add scroller arrows if style needs them + QStyleOptionComboBox opt = comboStyleOption(); + view->setMouseTracking(combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) || + combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo)); + setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo)); + updateTopBottomMargin(); +} + void QComboBoxPrivateContainer::changeEvent(QEvent *e) { - if (e->type() == QEvent::StyleChange) { - QStyleOptionComboBox opt = comboStyleOption(); - view->setMouseTracking(combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) || - combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo)); - setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo)); - } + if (e->type() == QEvent::StyleChange) + updateStyleSettings(); QFrame::changeEvent(e); } @@ -3114,6 +3118,8 @@ void QComboBox::changeEvent(QEvent *e) Q_D(QComboBox); switch (e->type()) { case QEvent::StyleChange: + if (d->container) + d->container->updateStyleSettings(); d->updateDelegate(); #ifdef Q_OS_MAC case QEvent::MacSizeChange: diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h index 107bd8ea4e..58b5342a5b 100644 --- a/src/widgets/widgets/qcombobox_p.h +++ b/src/widgets/widgets/qcombobox_p.h @@ -223,6 +223,7 @@ public: int topMargin() const; int bottomMargin() const { return topMargin(); } void updateTopBottomMargin(); + void updateStyleSettings(); QTimer blockMouseReleaseTimer; QBasicTimer adjustSizeTimer; diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp index d8bb34933a..32437050f5 100644 --- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp @@ -167,6 +167,7 @@ private slots: void task_QTBUG_52027_mapCompleterIndex(); void checkMenuItemPosWhenStyleSheetIsSet(); void checkEmbeddedLineEditWhenStyleSheetIsSet(); + void propagateStyleChanges(); private: PlatformInputContext m_platformInputContext; @@ -3586,5 +3587,50 @@ void tst_QComboBox::checkEmbeddedLineEditWhenStyleSheetIsSet() qApp->setStyleSheet(oldCss); } +/*! + Tests that the style-based frame style propagates to the internal container + widget of QComboBox when the style changes by verifying that the respective + styleHint is asked for when the style changes. + + See QTBUG-92488 +*/ +void tst_QComboBox::propagateStyleChanges() +{ + class FrameStyle : public QProxyStyle + { + public: + FrameStyle(int frameStyle, QStyle *style = nullptr) + : QProxyStyle(style), frameStyle(frameStyle) + {} + + int styleHint(QStyle::StyleHint hint, const QStyleOption *opt, + const QWidget *widget, QStyleHintReturn *returnData) const + { + if (hint == QStyle::SH_ComboBox_PopupFrameStyle) { + inquired = true; + return frameStyle; + } + return QProxyStyle::styleHint(hint, opt, widget, returnData); + } + + int frameStyle; + mutable bool inquired = false; + }; + + FrameStyle framelessStyle(QFrame::NoFrame); + FrameStyle frameStyle(QFrame::Plain | QFrame::Sunken); + + QComboBox combo; + // container will be created and take settings from this style + combo.setStyle(&framelessStyle); + QVERIFY(framelessStyle.inquired); + combo.addItem(QLatin1String("Open")); + combo.addItem(QLatin1String("Close")); + // needed because of QComboBox's adjustSizeTimer not doing anything otherwise + combo.setSizeAdjustPolicy(QComboBox::AdjustToContents); + combo.setStyle(&frameStyle); + QVERIFY(frameStyle.inquired); +} + QTEST_MAIN(tst_QComboBox) #include "tst_qcombobox.moc" |