Delete replaced delegates after Component.completed() is emitted

This avoids the issue "Object destroyed during incubation" error.
A proper fix is still required in the QML engine.

Change-Id: I3c168cfe2d8c295662bcb5886e99a0f95748e302
Task-number: QTBUG-50992
Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
This commit is contained in:
Mitch Curtis 2016-09-07 15:49:37 +02:00
parent 04779d6db3
commit d99e0764e2
15 changed files with 101 additions and 12 deletions

View File

@ -438,7 +438,7 @@ void QQuickAbstractButton::setIndicator(QQuickItem *indicator)
if (d->indicator == indicator)
return;
delete d->indicator;
d->deleteDelegate(d->indicator);
d->indicator = indicator;
if (indicator) {
if (!indicator->parentItem())

View File

@ -627,7 +627,7 @@ void QQuickComboBox::setIndicator(QQuickItem *indicator)
if (d->indicator == indicator)
return;
delete d->indicator;
d->deleteDelegate(d->indicator);
d->indicator = indicator;
if (indicator) {
if (!indicator->parentItem())
@ -655,7 +655,7 @@ void QQuickComboBox::setPopup(QQuickPopup *popup)
if (d->popup == popup)
return;
delete d->popup;
d->deleteDelegate(d->popup);
if (popup) {
QQuickPopupPrivate::get(popup)->allowVerticalFlip = true;
popup->setClosePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutsideParent);

View File

@ -717,6 +717,18 @@ QLocale QQuickControlPrivate::calcLocale(const QQuickItem *item)
return QLocale();
}
/*
Deletes "delegate" if Component.completed() has been emitted,
otherwise stores it in pendingDeletions.
*/
void QQuickControlPrivate::deleteDelegate(QObject *delegate)
{
if (componentComplete)
delete delegate;
else
extra.value().pendingDeletions.append(delegate);
}
void QQuickControlPrivate::updateLocale(const QLocale &l, bool e)
{
Q_Q(QQuickControl);
@ -943,7 +955,7 @@ void QQuickControl::setBackground(QQuickItem *background)
if (d->background == background)
return;
delete d->background;
d->deleteDelegate(d->background);
d->background = background;
if (background) {
background->setParentItem(this);
@ -975,7 +987,7 @@ void QQuickControl::setContentItem(QQuickItem *item)
return;
contentItemChange(item, d->contentItem);
delete d->contentItem;
d->deleteDelegate(d->contentItem);
d->contentItem = item;
if (item) {
if (!item->parentItem())
@ -1003,6 +1015,11 @@ void QQuickControl::componentComplete()
if (!d->accessibleAttached && QAccessible::isActive())
accessibilityActiveChanged(true);
#endif
if (d->extra.isAllocated()) {
qDeleteAll(d->extra.value().pendingDeletions);
d->extra.value().pendingDeletions.clear();
}
}
QFont QQuickControl::defaultFont() const

View File

@ -109,9 +109,15 @@ public:
static void updateLocaleRecur(QQuickItem *item, const QLocale &l);
static QLocale calcLocale(const QQuickItem *item);
void deleteDelegate(QObject *object);
struct ExtraData {
ExtraData();
QFont font;
// This list contains the default delegates which were
// replaced with custom ones via declarative assignments
// before Component.completed() was emitted. See QTBUG-50992.
QVector<QObject*> pendingDeletions;
};
QLazilyAllocated<ExtraData> extra;

View File

@ -480,6 +480,7 @@ void QQuickDial::setHandle(QQuickItem *handle)
if (handle == d->handle)
return;
d->deleteDelegate(d->handle);
d->handle = handle;
if (d->handle && !d->handle->parentItem())
d->handle->setParentItem(this);

View File

@ -137,7 +137,7 @@ void QQuickGroupBox::setLabel(QQuickItem *label)
if (d->label == label)
return;
delete d->label;
d->deleteDelegate(d->label);
d->label = label;
if (label && !label->parentItem())
label->setParentItem(this);

View File

@ -167,6 +167,18 @@ QAccessible::Role QQuickLabelPrivate::accessibleRole() const
}
#endif
/*
Deletes "delegate" if Component.completed() has been emitted,
otherwise stores it in pendingDeletions.
*/
void QQuickLabelPrivate::deleteDelegate(QObject *delegate)
{
if (componentComplete)
delete delegate;
else
pendingDeletions.append(delegate);
}
QFont QQuickLabel::font() const
{
return QQuickText::font();
@ -205,7 +217,7 @@ void QQuickLabel::setBackground(QQuickItem *background)
if (d->background == background)
return;
delete d->background;
d->deleteDelegate(d->background);
d->background = background;
if (background) {
background->setParentItem(this);
@ -230,6 +242,9 @@ void QQuickLabel::componentComplete()
if (!d->accessibleAttached && QAccessible::isActive())
d->accessibilityActiveChanged(true);
#endif
qDeleteAll(d->pendingDeletions);
d->pendingDeletions.clear();
}
void QQuickLabel::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)

View File

@ -83,9 +83,15 @@ public:
QAccessible::Role accessibleRole() const override;
#endif
void deleteDelegate(QObject *object);
QFont font;
QQuickItem *background;
QQuickAccessibleAttached *accessibleAttached;
// This list contains the default delegates which were
// replaced with custom ones via declarative assignments
// before Component.completed() was emitted. See QTBUG-50992.
QVector<QObject *> pendingDeletions;
};
QT_END_NAMESPACE

View File

@ -226,7 +226,7 @@ void QQuickRangeSliderNode::setHandle(QQuickItem *handle)
if (d->handle == handle)
return;
delete d->handle;
QQuickControlPrivate::get(d->slider)->deleteDelegate(d->handle);
d->handle = handle;
if (handle) {
if (!handle->parentItem())

View File

@ -411,7 +411,7 @@ void QQuickSlider::setHandle(QQuickItem *handle)
if (d->handle == handle)
return;
delete d->handle;
d->deleteDelegate(d->handle);
d->handle = handle;
if (handle && !handle->parentItem())
handle->setParentItem(this);

View File

@ -768,8 +768,14 @@ void QQuickSpinButton::setIndicator(QQuickItem *indicator)
if (d->indicator == indicator)
return;
delete d->indicator;
QQuickControl *control = qobject_cast<QQuickControl*>(d->parent);
if (control)
QQuickControlPrivate::get(control)->deleteDelegate(d->indicator);
else
delete d->indicator;
d->indicator = indicator;
if (indicator) {
if (!indicator->parentItem())
indicator->setParentItem(static_cast<QQuickItem *>(parent()));

View File

@ -363,6 +363,14 @@ QAccessible::Role QQuickTextAreaPrivate::accessibleRole() const
}
#endif
void QQuickTextAreaPrivate::deleteDelegate(QObject *delegate)
{
if (componentComplete)
delete delegate;
else
pendingDeletions.append(delegate);
}
QFont QQuickTextArea::font() const
{
return QQuickTextEdit::font();
@ -401,7 +409,7 @@ void QQuickTextArea::setBackground(QQuickItem *background)
if (d->background == background)
return;
delete d->background;
d->deleteDelegate(d->background);
d->background = background;
if (background) {
background->setParentItem(this);
@ -497,6 +505,9 @@ void QQuickTextArea::componentComplete()
if (!d->accessibleAttached && QAccessible::isActive())
d->accessibilityActiveChanged(true);
#endif
qDeleteAll(d->pendingDeletions);
d->pendingDeletions.clear();
}
void QQuickTextArea::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)

View File

@ -102,6 +102,8 @@ public:
QAccessible::Role accessibleRole() const override;
#endif
void deleteDelegate(QObject *object);
QFont font;
QQuickItem *background;
QString placeholder;
@ -109,6 +111,10 @@ public:
QQuickPressHandler pressHandler;
QQuickAccessibleAttached *accessibleAttached;
QQuickFlickable *flickable;
// This list contains the default delegates which were
// replaced with custom ones via declarative assignments
// before Component.completed() was emitted. See QTBUG-50992.
QVector<QObject *> pendingDeletions;
};
QT_END_NAMESPACE

View File

@ -239,6 +239,18 @@ QAccessible::Role QQuickTextFieldPrivate::accessibleRole() const
}
#endif
/*
Deletes "delegate" if Component.completed() has been emitted,
otherwise stores it in pendingDeletions.
*/
void QQuickTextFieldPrivate::deleteDelegate(QObject *delegate)
{
if (componentComplete)
delete delegate;
else
pendingDeletions.append(delegate);
}
QFont QQuickTextField::font() const
{
return QQuickTextInput::font();
@ -277,7 +289,7 @@ void QQuickTextField::setBackground(QQuickItem *background)
if (d->background == background)
return;
delete d->background;
d->deleteDelegate(d->background);
d->background = background;
if (background) {
background->setParentItem(this);
@ -365,6 +377,9 @@ void QQuickTextField::componentComplete()
if (!d->accessibleAttached && QAccessible::isActive())
d->accessibilityActiveChanged(true);
#endif
qDeleteAll(d->pendingDeletions);
d->pendingDeletions.clear();
}
void QQuickTextField::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)

View File

@ -93,12 +93,18 @@ public:
QAccessible::Role accessibleRole() const override;
#endif
void deleteDelegate(QObject *object);
QFont font;
QQuickItem *background;
QString placeholder;
Qt::FocusReason focusReason;
QQuickPressHandler pressHandler;
QQuickAccessibleAttached *accessibleAttached;
// This list contains the default delegates which were
// replaced with custom ones via declarative assignments
// before Component.completed() was emitted. See QTBUG-50992.
QVector<QObject *> pendingDeletions;
};
QT_END_NAMESPACE