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)
|
, childrenHiddenByWState(0)
|
||||||
, childrenShownByExpose(0)
|
, childrenShownByExpose(0)
|
||||||
, dontSetExplicitShowHide(0)
|
, dontSetExplicitShowHide(0)
|
||||||
|
, inheritStyleRecursionGuard(0)
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
, noPaintOnScreen(0)
|
, noPaintOnScreen(0)
|
||||||
#endif
|
#endif
|
||||||
|
@ -2692,7 +2693,7 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
|
||||||
extra->style = newStyle;
|
extra->style = newStyle;
|
||||||
|
|
||||||
// repolish
|
// repolish
|
||||||
if (polished && q->windowType() != Qt::Desktop && oldStyle != q->style()) {
|
if (polished && q->windowType() != Qt::Desktop) {
|
||||||
oldStyle->unpolish(q);
|
oldStyle->unpolish(q);
|
||||||
q->style()->polish(q);
|
q->style()->polish(q);
|
||||||
}
|
}
|
||||||
|
@ -2740,6 +2741,12 @@ void QWidgetPrivate::inheritStyle()
|
||||||
proxy->repolish(q);
|
proxy->repolish(q);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (inheritStyleRecursionGuard)
|
||||||
|
return;
|
||||||
|
inheritStyleRecursionGuard = true;
|
||||||
|
const auto resetGuard = qScopeGuard([&]() {
|
||||||
|
inheritStyleRecursionGuard = false;
|
||||||
|
});
|
||||||
|
|
||||||
QStyle *origStyle = proxy ? proxy->base : extraStyle;
|
QStyle *origStyle = proxy ? proxy->base : extraStyle;
|
||||||
QWidget *parent = q->parentWidget();
|
QWidget *parent = q->parentWidget();
|
||||||
|
|
|
@ -742,6 +742,7 @@ public:
|
||||||
uint childrenHiddenByWState : 1;
|
uint childrenHiddenByWState : 1;
|
||||||
uint childrenShownByExpose : 1;
|
uint childrenShownByExpose : 1;
|
||||||
uint dontSetExplicitShowHide : 1;
|
uint dontSetExplicitShowHide : 1;
|
||||||
|
uint inheritStyleRecursionGuard : 1;
|
||||||
|
|
||||||
// *************************** Focus abstraction ************************************
|
// *************************** Focus abstraction ************************************
|
||||||
enum class FocusDirection {
|
enum class FocusDirection {
|
||||||
|
|
|
@ -11,7 +11,9 @@
|
||||||
#include <qlabel.h>
|
#include <qlabel.h>
|
||||||
#include <qlayout.h>
|
#include <qlayout.h>
|
||||||
#include <qlineedit.h>
|
#include <qlineedit.h>
|
||||||
#include <qlistview.h>
|
#if QT_CONFIG(listwidget)
|
||||||
|
#include <qlistwidget.h>
|
||||||
|
#endif
|
||||||
#include <qmessagebox.h>
|
#include <qmessagebox.h>
|
||||||
#include <qmimedata.h>
|
#include <qmimedata.h>
|
||||||
#include <qpainter.h>
|
#include <qpainter.h>
|
||||||
|
@ -22,6 +24,7 @@
|
||||||
#include <qstylefactory.h>
|
#include <qstylefactory.h>
|
||||||
#include <private/qwidget_p.h>
|
#include <private/qwidget_p.h>
|
||||||
#include <private/qwidgetrepaintmanager_p.h>
|
#include <private/qwidgetrepaintmanager_p.h>
|
||||||
|
#include <private/qwindowsstyle_p.h>
|
||||||
#include <private/qapplication_p.h>
|
#include <private/qapplication_p.h>
|
||||||
#include <private/qhighdpiscaling_p.h>
|
#include <private/qhighdpiscaling_p.h>
|
||||||
#include <qcalendarwidget.h>
|
#include <qcalendarwidget.h>
|
||||||
|
@ -6806,7 +6809,32 @@ void tst_QWidget::deleteStyle()
|
||||||
QCoreApplication::processEvents();
|
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
|
void polish(QWidget *w) override
|
||||||
{
|
{
|
||||||
|
@ -6827,13 +6855,17 @@ void tst_QWidget::dontCrashOnSetStyle()
|
||||||
});
|
});
|
||||||
{
|
{
|
||||||
qApp->setStyle(new TestStyle);
|
qApp->setStyle(new TestStyle);
|
||||||
qApp->setStyleSheet("blub");
|
qApp->setStyleSheet(u"DontCrashOnSetStyleWidget QLabel {color:red;}"_s);
|
||||||
QComboBox w;
|
QComboBox w;
|
||||||
w.show();
|
w.show();
|
||||||
QVERIFY(QTest::qWaitForWindowExposed(&w));
|
QVERIFY(QTest::qWaitForWindowExposed(&w));
|
||||||
// this created an infinite loop / stack overflow inside setStyle_helper()
|
// this created an infinite loop / stack overflow inside setStyle_helper()
|
||||||
// directly call polish instead waiting for the polish event
|
// directly call polish instead waiting for the polish event
|
||||||
qApp->style()->polish(&w);
|
qApp->style()->polish(&w);
|
||||||
|
#if QT_CONFIG(listwidget)
|
||||||
|
DontCrashOnSetStyleWidget widget;
|
||||||
|
QVERIFY(widget.testStyleSheetTarget());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue