mirror of https://github.com/qt/qtbase.git
QWidget: fix propagating style with descendant selectors
The fix for QTBUG-133332 introduced a check to avoid an endless
recursion within setStyle_helper() but it prevents the correct
propagation of the style with a descendant selector. Therefore use
another approach and make sure QWidgetPrivate::inheritStyle() is not
called recursivly.
This amends 3252e1808c
.
Pick-to: 6.10 6.9
Task-number: QTBUG-133332
Fixes: QTBUG-139924
Change-Id: Ia0a1eec652380397f861364bbdc303dfd17b34f3
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
parent
71707eadfa
commit
14aa698cc3
|
@ -161,6 +161,7 @@ QWidgetPrivate::QWidgetPrivate(decltype(QObjectPrivateVersion) version)
|
|||
, childrenHiddenByWState(0)
|
||||
, childrenShownByExpose(0)
|
||||
, dontSetExplicitShowHide(0)
|
||||
, inheritStyleRecursionGuard(0)
|
||||
#if defined(Q_OS_WIN)
|
||||
, noPaintOnScreen(0)
|
||||
#endif
|
||||
|
@ -2692,7 +2693,7 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
|
|||
extra->style = newStyle;
|
||||
|
||||
// repolish
|
||||
if (polished && q->windowType() != Qt::Desktop && oldStyle != q->style()) {
|
||||
if (polished && q->windowType() != Qt::Desktop) {
|
||||
oldStyle->unpolish(q);
|
||||
q->style()->polish(q);
|
||||
}
|
||||
|
@ -2740,6 +2741,12 @@ void QWidgetPrivate::inheritStyle()
|
|||
proxy->repolish(q);
|
||||
return;
|
||||
}
|
||||
if (inheritStyleRecursionGuard)
|
||||
return;
|
||||
inheritStyleRecursionGuard = true;
|
||||
const auto resetGuard = qScopeGuard([&]() {
|
||||
inheritStyleRecursionGuard = false;
|
||||
});
|
||||
|
||||
QStyle *origStyle = proxy ? proxy->base : extraStyle;
|
||||
QWidget *parent = q->parentWidget();
|
||||
|
|
|
@ -742,6 +742,7 @@ public:
|
|||
uint childrenHiddenByWState : 1;
|
||||
uint childrenShownByExpose : 1;
|
||||
uint dontSetExplicitShowHide : 1;
|
||||
uint inheritStyleRecursionGuard : 1;
|
||||
|
||||
// *************************** Focus abstraction ************************************
|
||||
enum class FocusDirection {
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
#include <qlabel.h>
|
||||
#include <qlayout.h>
|
||||
#include <qlineedit.h>
|
||||
#include <qlistview.h>
|
||||
#if QT_CONFIG(listwidget)
|
||||
#include <qlistwidget.h>
|
||||
#endif
|
||||
#include <qmessagebox.h>
|
||||
#include <qmimedata.h>
|
||||
#include <qpainter.h>
|
||||
|
@ -22,6 +24,7 @@
|
|||
#include <qstylefactory.h>
|
||||
#include <private/qwidget_p.h>
|
||||
#include <private/qwidgetrepaintmanager_p.h>
|
||||
#include <private/qwindowsstyle_p.h>
|
||||
#include <private/qapplication_p.h>
|
||||
#include <private/qhighdpiscaling_p.h>
|
||||
#include <qcalendarwidget.h>
|
||||
|
@ -6806,7 +6809,32 @@ void tst_QWidget::deleteStyle()
|
|||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
class TestStyle : public QCommonStyle
|
||||
|
||||
#if QT_CONFIG(listwidget)
|
||||
class DontCrashOnSetStyleWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DontCrashOnSetStyleWidget()
|
||||
{
|
||||
lw = new QListWidget;
|
||||
lwi = new QListWidgetItem;
|
||||
lw->addItem(lwi);
|
||||
lw->setItemWidget(lwi, new QLabel(u"test"_s));
|
||||
auto l = new QVBoxLayout(this);
|
||||
l->addWidget(lw);
|
||||
}
|
||||
bool testStyleSheetTarget() const
|
||||
{
|
||||
return lw->itemWidget(lwi)->testAttribute(Qt::WA_StyleSheetTarget);
|
||||
}
|
||||
private:
|
||||
QListWidget *lw = nullptr;
|
||||
QListWidgetItem *lwi = nullptr;
|
||||
};
|
||||
#endif
|
||||
|
||||
class TestStyle : public QWindowsStyle
|
||||
{
|
||||
void polish(QWidget *w) override
|
||||
{
|
||||
|
@ -6827,13 +6855,17 @@ void tst_QWidget::dontCrashOnSetStyle()
|
|||
});
|
||||
{
|
||||
qApp->setStyle(new TestStyle);
|
||||
qApp->setStyleSheet("blub");
|
||||
qApp->setStyleSheet(u"DontCrashOnSetStyleWidget QLabel {color:red;}"_s);
|
||||
QComboBox w;
|
||||
w.show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&w));
|
||||
// this created an infinite loop / stack overflow inside setStyle_helper()
|
||||
// directly call polish instead waiting for the polish event
|
||||
qApp->style()->polish(&w);
|
||||
#if QT_CONFIG(listwidget)
|
||||
DontCrashOnSetStyleWidget widget;
|
||||
QVERIFY(widget.testStyleSheetTarget());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue