QStyleSheetStyle::repolish: only run on direct children

When re-parenting, some widgets change their children. For example
QLabel, when set to rich text, will not update, until receiving a polish
call, at which time getting a list of all children recursively and then
trying to call functions on them will crash, since the children change
in the middle of this operation.

Fixes: QTBUG-69204
Fixes: QTBUG-74667
Change-Id: I95dd83ebeed14c017e22552ddd47658ae8a09353
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Frederik Gladhorn 2018-10-15 16:39:03 +02:00 committed by Shawn Rutledge
parent 2593463eaf
commit 21dcb96ddc
2 changed files with 25 additions and 1 deletions

View File

@ -2905,7 +2905,10 @@ void QStyleSheetStyle::polish(QPalette &pal)
void QStyleSheetStyle::repolish(QWidget *w)
{
QList<const QObject *> children = w->findChildren<const QObject *>(QString());
QList<const QObject *> children;
children.reserve(w->children().size() + 1);
for (auto child: qAsConst(w->children()))
children.append(child);
children.append(w);
styleSheetCaches->styleSheetCache.remove(w);
updateObjects(children);

View File

@ -48,6 +48,7 @@ public:
private slots:
void init();
void repolish();
void repolish_without_crashing();
void numinstances();
void widgetsBeforeAppStyleSheet();
void widgetsAfterAppStyleSheet();
@ -367,6 +368,26 @@ void tst_QStyleSheetStyle::repolish()
QCOMPARE(BACKGROUND(p1), APPBACKGROUND(p1));
}
void tst_QStyleSheetStyle::repolish_without_crashing()
{
// This used to crash, QTBUG-69204
QMainWindow w;
QScopedPointer<QSplitter> splitter1(new QSplitter(w.centralWidget()));
QScopedPointer<QSplitter> splitter2(new QSplitter);
QScopedPointer<QSplitter> splitter3(new QSplitter);
splitter2->addWidget(splitter3.data());
splitter2->setStyleSheet("color: red");
QScopedPointer<QLabel> label(new QLabel);
label->setTextFormat(Qt::RichText);
splitter3->addWidget(label.data());
label->setText("hey");
splitter1->addWidget(splitter2.data());
w.show();
QCOMPARE(COLOR(*label), QColor(Qt::red));
}
void tst_QStyleSheetStyle::widgetStyle()
{
qApp->setStyleSheet("");