From 51eff608eb18b01d36fdab442930300a4af3df20 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 2 Feb 2017 15:16:08 +0100 Subject: Cancel incubation of replaced/destroyed delegates Resolves the "Object destroyed during incubation" issues. Task-number: QTBUG-50992 Change-Id: Ie58c958dafbf915da7494dac25351be98106c6ea Reviewed-by: Mitch Curtis --- src/quicktemplates2/qquickabstractbutton.cpp | 2 +- src/quicktemplates2/qquickapplicationwindow.cpp | 2 +- src/quicktemplates2/qquickcombobox.cpp | 7 ++++--- src/quicktemplates2/qquickcontrol.cpp | 22 ++++++++-------------- src/quicktemplates2/qquickcontrol_p_p.h | 6 +----- src/quicktemplates2/qquickdial.cpp | 2 +- src/quicktemplates2/qquickgroupbox.cpp | 2 +- src/quicktemplates2/qquicklabel.cpp | 17 +---------------- src/quicktemplates2/qquicklabel_p_p.h | 6 ------ src/quicktemplates2/qquickrangeslider.cpp | 2 +- src/quicktemplates2/qquickslider.cpp | 2 +- src/quicktemplates2/qquickspinbox.cpp | 7 +------ src/quicktemplates2/qquicktextarea.cpp | 13 +------------ src/quicktemplates2/qquicktextarea_p_p.h | 6 ------ src/quicktemplates2/qquicktextfield.cpp | 17 +---------------- src/quicktemplates2/qquicktextfield_p_p.h | 6 ------ 16 files changed, 23 insertions(+), 96 deletions(-) diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp index 17e0abea..1012061c 100644 --- a/src/quicktemplates2/qquickabstractbutton.cpp +++ b/src/quicktemplates2/qquickabstractbutton.cpp @@ -548,7 +548,7 @@ void QQuickAbstractButton::setIndicator(QQuickItem *indicator) if (d->indicator == indicator) return; - d->deleteDelegate(d->indicator); + QQuickControlPrivate::destroyDelegate(d->indicator, this); d->indicator = indicator; if (indicator) { if (!indicator->parentItem()) diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp index a66861da..c094d454 100644 --- a/src/quicktemplates2/qquickapplicationwindow.cpp +++ b/src/quicktemplates2/qquickapplicationwindow.cpp @@ -333,7 +333,7 @@ void QQuickApplicationWindow::setBackground(QQuickItem *background) if (d->background == background) return; - delete d->background; + QQuickControlPrivate::destroyDelegate(d->background, this); d->background = background; if (background) { background->setParentItem(QQuickWindow::contentItem()); diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index 59d66d99..f1ff9994 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -1069,7 +1069,7 @@ void QQuickComboBox::setIndicator(QQuickItem *indicator) if (d->indicator == indicator) return; - d->deleteDelegate(d->indicator); + QQuickControlPrivate::destroyDelegate(d->indicator, this); d->indicator = indicator; if (indicator) { if (!indicator->parentItem()) @@ -1103,9 +1103,10 @@ void QQuickComboBox::setPopup(QQuickPopup *popup) if (d->popup == popup) return; - if (d->popup) + if (d->popup) { QObjectPrivate::disconnect(d->popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged); - d->deleteDelegate(d->popup); + QQuickControlPrivate::destroyDelegate(d->popup, this); + } if (popup) { QQuickPopupPrivate::get(popup)->allowVerticalFlip = true; popup->setClosePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutsideParent); diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index 57191b71..cf626e90 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -51,6 +51,7 @@ #include #include +#include #ifndef QT_NO_ACCESSIBILITY #include @@ -865,15 +866,13 @@ QLocale QQuickControlPrivate::calcLocale(const QQuickItem *item) } /* - Deletes "delegate" if Component.completed() has been emitted, - otherwise stores it in pendingDeletions. + Cancels incubation to avoid "Object destroyed during incubation" (QTBUG-50992) */ -void QQuickControlPrivate::deleteDelegate(QObject *delegate) +void QQuickControlPrivate::destroyDelegate(QObject *delegate, QObject *parent) { - if (componentComplete) - delete delegate; - else if (delegate) - extra.value().pendingDeletions.append(delegate); + if (delegate && parent) + QQmlIncubatorPrivate::cancel(delegate, qmlContext(parent)); + delete delegate; } void QQuickControlPrivate::updateLocale(const QLocale &l, bool e) @@ -1145,7 +1144,7 @@ void QQuickControl::setBackground(QQuickItem *background) if (d->background == background) return; - d->deleteDelegate(d->background); + QQuickControlPrivate::destroyDelegate(d->background, this); d->background = background; if (background) { background->setParentItem(this); @@ -1198,7 +1197,7 @@ void QQuickControl::setContentItem(QQuickItem *item) return; contentItemChange(item, d->contentItem); - d->deleteDelegate(d->contentItem); + QQuickControlPrivate::destroyDelegate(d->contentItem, this); d->contentItem = item; if (item) { if (!item->parentItem()) @@ -1231,11 +1230,6 @@ 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 diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h index 029bb1e9..56a17834 100644 --- a/src/quicktemplates2/qquickcontrol_p_p.h +++ b/src/quicktemplates2/qquickcontrol_p_p.h @@ -117,15 +117,11 @@ public: static bool calcHoverEnabled(const QQuickItem *item); #endif - void deleteDelegate(QObject *object); + static void destroyDelegate(QObject *object, QObject *parent); 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 pendingDeletions; }; QLazilyAllocated extra; diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp index f05cc63f..15399c7f 100644 --- a/src/quicktemplates2/qquickdial.cpp +++ b/src/quicktemplates2/qquickdial.cpp @@ -588,7 +588,7 @@ void QQuickDial::setHandle(QQuickItem *handle) if (handle == d->handle) return; - d->deleteDelegate(d->handle); + QQuickControlPrivate::destroyDelegate(d->handle, this); d->handle = handle; if (d->handle && !d->handle->parentItem()) d->handle->setParentItem(this); diff --git a/src/quicktemplates2/qquickgroupbox.cpp b/src/quicktemplates2/qquickgroupbox.cpp index 7d1a5826..55f59080 100644 --- a/src/quicktemplates2/qquickgroupbox.cpp +++ b/src/quicktemplates2/qquickgroupbox.cpp @@ -141,7 +141,7 @@ void QQuickGroupBox::setLabel(QQuickItem *label) if (d->label == label) return; - d->deleteDelegate(d->label); + QQuickControlPrivate::destroyDelegate(d->label, this); d->label = label; if (label && !label->parentItem()) label->setParentItem(this); diff --git a/src/quicktemplates2/qquicklabel.cpp b/src/quicktemplates2/qquicklabel.cpp index 108e92e4..a2a9fa59 100644 --- a/src/quicktemplates2/qquicklabel.cpp +++ b/src/quicktemplates2/qquicklabel.cpp @@ -155,18 +155,6 @@ 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 if (delegate) - pendingDeletions.append(delegate); -} - QQuickLabel::QQuickLabel(QQuickItem *parent) : QQuickText(*(new QQuickLabelPrivate), parent) { @@ -212,7 +200,7 @@ void QQuickLabel::setBackground(QQuickItem *background) if (d->background == background) return; - d->deleteDelegate(d->background); + QQuickControlPrivate::destroyDelegate(d->background, this); d->background = background; if (background) { background->setParentItem(this); @@ -237,9 +225,6 @@ 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) diff --git a/src/quicktemplates2/qquicklabel_p_p.h b/src/quicktemplates2/qquicklabel_p_p.h index 9bc7c36d..40445d36 100644 --- a/src/quicktemplates2/qquicklabel_p_p.h +++ b/src/quicktemplates2/qquicklabel_p_p.h @@ -84,15 +84,9 @@ 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 pendingDeletions; }; QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickrangeslider.cpp b/src/quicktemplates2/qquickrangeslider.cpp index 258a2f91..b4d5a2f2 100644 --- a/src/quicktemplates2/qquickrangeslider.cpp +++ b/src/quicktemplates2/qquickrangeslider.cpp @@ -230,7 +230,7 @@ void QQuickRangeSliderNode::setHandle(QQuickItem *handle) if (d->handle == handle) return; - QQuickControlPrivate::get(d->slider)->deleteDelegate(d->handle); + QQuickControlPrivate::destroyDelegate(d->handle, d->slider); d->handle = handle; if (handle) { if (!handle->parentItem()) diff --git a/src/quicktemplates2/qquickslider.cpp b/src/quicktemplates2/qquickslider.cpp index eb21af4a..6c03536f 100644 --- a/src/quicktemplates2/qquickslider.cpp +++ b/src/quicktemplates2/qquickslider.cpp @@ -521,7 +521,7 @@ void QQuickSlider::setHandle(QQuickItem *handle) if (d->handle == handle) return; - d->deleteDelegate(d->handle); + QQuickControlPrivate::destroyDelegate(d->handle, this); d->handle = handle; if (handle && !handle->parentItem()) handle->setParentItem(this); diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp index 4368236a..da3ea40e 100644 --- a/src/quicktemplates2/qquickspinbox.cpp +++ b/src/quicktemplates2/qquickspinbox.cpp @@ -992,12 +992,7 @@ void QQuickSpinButton::setIndicator(QQuickItem *indicator) if (d->indicator == indicator) return; - QQuickControl *control = qobject_cast(d->parent); - if (control) - QQuickControlPrivate::get(control)->deleteDelegate(d->indicator); - else - delete d->indicator; - + QQuickControlPrivate::destroyDelegate(d->indicator, d->parent); d->indicator = indicator; if (indicator) { diff --git a/src/quicktemplates2/qquicktextarea.cpp b/src/quicktemplates2/qquicktextarea.cpp index 380ea978..a4be1303 100644 --- a/src/quicktemplates2/qquicktextarea.cpp +++ b/src/quicktemplates2/qquicktextarea.cpp @@ -389,14 +389,6 @@ QAccessible::Role QQuickTextAreaPrivate::accessibleRole() const } #endif -void QQuickTextAreaPrivate::deleteDelegate(QObject *delegate) -{ - if (componentComplete) - delete delegate; - else if (delegate) - pendingDeletions.append(delegate); -} - QQuickTextArea::QQuickTextArea(QQuickItem *parent) : QQuickTextEdit(*(new QQuickTextAreaPrivate), parent) { @@ -453,7 +445,7 @@ void QQuickTextArea::setBackground(QQuickItem *background) if (d->background == background) return; - d->deleteDelegate(d->background); + QQuickControlPrivate::destroyDelegate(d->background, this); d->background = background; if (background) { background->setParentItem(this); @@ -615,9 +607,6 @@ 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) diff --git a/src/quicktemplates2/qquicktextarea_p_p.h b/src/quicktemplates2/qquicktextarea_p_p.h index 60995080..48336353 100644 --- a/src/quicktemplates2/qquicktextarea_p_p.h +++ b/src/quicktemplates2/qquicktextarea_p_p.h @@ -108,8 +108,6 @@ public: QAccessible::Role accessibleRole() const override; #endif - void deleteDelegate(QObject *object); - #if QT_CONFIG(quicktemplates2_hover) bool hovered; bool explicitHoverEnabled; @@ -121,10 +119,6 @@ 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 pendingDeletions; }; QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquicktextfield.cpp b/src/quicktemplates2/qquicktextfield.cpp index 36c284f0..ec46b15c 100644 --- a/src/quicktemplates2/qquicktextfield.cpp +++ b/src/quicktemplates2/qquicktextfield.cpp @@ -263,18 +263,6 @@ 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 if (delegate) - pendingDeletions.append(delegate); -} - QQuickTextField::QQuickTextField(QQuickItem *parent) : QQuickTextInput(*(new QQuickTextFieldPrivate), parent) { @@ -326,7 +314,7 @@ void QQuickTextField::setBackground(QQuickItem *background) if (d->background == background) return; - d->deleteDelegate(d->background); + QQuickControlPrivate::destroyDelegate(d->background, this); d->background = background; if (background) { background->setParentItem(this); @@ -480,9 +468,6 @@ 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) diff --git a/src/quicktemplates2/qquicktextfield_p_p.h b/src/quicktemplates2/qquicktextfield_p_p.h index b35446ec..443e2f14 100644 --- a/src/quicktemplates2/qquicktextfield_p_p.h +++ b/src/quicktemplates2/qquicktextfield_p_p.h @@ -97,8 +97,6 @@ public: QAccessible::Role accessibleRole() const override; #endif - void deleteDelegate(QObject *object); - #if QT_CONFIG(quicktemplates2_hover) bool hovered; bool explicitHoverEnabled; @@ -109,10 +107,6 @@ public: 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 pendingDeletions; }; QT_END_NAMESPACE -- cgit v1.2.3