diff options
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 2 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 18 | ||||
-rw-r--r-- | tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 100 |
3 files changed, 119 insertions, 1 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 0d97266f4f..9d0854f3a9 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -766,7 +766,7 @@ QObject::~QObject() delete sharedRefcount; } - if (d->isSignalConnected(0)) { + if (!d->isWidget && d->isSignalConnected(0)) { QT_TRY { emit destroyed(this); } QT_CATCH(...) { diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 83dc406e17..d05f53697a 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1429,11 +1429,29 @@ QWidget::~QWidget() delete d->needsFlush; d->needsFlush = 0; + // The next 20 lines are duplicated from QObject, but required here + // since QWidget deletes is children itself + bool blocked = d->blockSig; + d->blockSig = 0; // unblock signals so we always emit destroyed() + + if (d->isSignalConnected(0)) { + QT_TRY { + emit destroyed(this); + } QT_CATCH(...) { + // all the signal/slots connections are still in place - if we don't + // quit now, we will crash pretty soon. + qWarning("Detected an unexpected exception in ~QWidget while emitting destroyed()."); + QT_RETHROW; + } + } + if (d->declarativeData) { QAbstractDeclarativeData::destroyed(d->declarativeData, this); d->declarativeData = 0; // don't activate again in ~QObject } + d->blockSig = blocked; + #ifdef Q_WS_MAC // QCocoaView holds a pointer back to this widget. Clear it now // to make sure it's not followed later on. The lifetime of the diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index f3f63b2067..2a5e59f825 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -396,6 +396,8 @@ private slots: void touchEventSynthesizedMouseEvent(); void styleSheetPropagation(); + + void destroyedSignal(); private: bool ensureScreenSize(int width, int height); QWidget *testWidget; @@ -9592,6 +9594,104 @@ void tst_QWidget::styleSheetPropagation() } } +class DestroyTester : public QObject +{ + Q_OBJECT +public: + DestroyTester(QObject *parent) : QObject(parent) { parentDestroyed = 0; } + static int parentDestroyed; +public slots: + void parentDestroyedSlot() { + ++parentDestroyed; + } +}; + +int DestroyTester::parentDestroyed = 0; + +void tst_QWidget::destroyedSignal() +{ + { + QWidget *w = new QWidget; + DestroyTester *t = new DestroyTester(w); + connect(w, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot())); + QCOMPARE(DestroyTester::parentDestroyed, 0); + delete w; + QCOMPARE(DestroyTester::parentDestroyed, 1); + } + + { + QWidget *w = new QWidget; + DestroyTester *t = new DestroyTester(w); + connect(w, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot())); + w->blockSignals(true); + QCOMPARE(DestroyTester::parentDestroyed, 0); + delete w; + QCOMPARE(DestroyTester::parentDestroyed, 1); + } + + { + QObject *o = new QWidget; + DestroyTester *t = new DestroyTester(o); + connect(o, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot())); + QCOMPARE(DestroyTester::parentDestroyed, 0); + delete o; + QCOMPARE(DestroyTester::parentDestroyed, 1); + } + + { + QObject *o = new QWidget; + DestroyTester *t = new DestroyTester(o); + connect(o, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot())); + o->blockSignals(true); + QCOMPARE(DestroyTester::parentDestroyed, 0); + delete o; + QCOMPARE(DestroyTester::parentDestroyed, 1); + } + + { + QWidget *w = new QWidget; + DestroyTester *t = new DestroyTester(0); + connect(w, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot())); + QCOMPARE(DestroyTester::parentDestroyed, 0); + delete w; + QCOMPARE(DestroyTester::parentDestroyed, 1); + delete t; + } + + { + QWidget *w = new QWidget; + DestroyTester *t = new DestroyTester(0); + connect(w, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot())); + w->blockSignals(true); + QCOMPARE(DestroyTester::parentDestroyed, 0); + delete w; + QCOMPARE(DestroyTester::parentDestroyed, 1); + delete t; + } + + { + QObject *o = new QWidget; + DestroyTester *t = new DestroyTester(0); + connect(o, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot())); + QCOMPARE(DestroyTester::parentDestroyed, 0); + delete o; + QCOMPARE(DestroyTester::parentDestroyed, 1); + delete t; + } + + { + QObject *o = new QWidget; + DestroyTester *t = new DestroyTester(0); + connect(o, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot())); + o->blockSignals(true); + QCOMPARE(DestroyTester::parentDestroyed, 0); + delete o; + QCOMPARE(DestroyTester::parentDestroyed, 1); + delete t; + } + +} + #ifndef QTEST_NO_CURSOR void tst_QWidget::underMouse() { |