diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2018-08-28 11:51:57 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2018-08-30 09:06:40 +0000 |
commit | e56e964aa5975b08eb003f0280118fb6f6b5f95f (patch) | |
tree | 26670a773b0359133629bf5992d02f5f0f900a50 | |
parent | 8ef4964168ccca6153cd9dbfc631043d8293e370 (diff) | |
download | qt-creator-e56e964aa5975b08eb003f0280118fb6f6b5f95f.tar.gz |
Tracing: Properly signal destruction of non-owned properties
When the zoomer, model, or notes properties for TimelineAbstractRenderer
are destroyed, the QPointers become null, and therefore the change
signals need to be emitted, and an update to the widget should be
scheduled.
If this is not done, clients using the property might keep a dangling
pointer in some cache and dereference it later.
Change-Id: I63fb657afb8138e9ac54c7d839d4a52271f8f3e8
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r-- | src/libs/tracing/timelineabstractrenderer.cpp | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/src/libs/tracing/timelineabstractrenderer.cpp b/src/libs/tracing/timelineabstractrenderer.cpp index 4b9f775c3b..c2e8886ee1 100644 --- a/src/libs/tracing/timelineabstractrenderer.cpp +++ b/src/libs/tracing/timelineabstractrenderer.cpp @@ -108,9 +108,12 @@ void TimelineAbstractRenderer::setModel(TimelineModel *model) this, &TimelineAbstractRenderer::setRowHeightsDirty); disconnect(d->model, &TimelineModel::contentChanged, this, &TimelineAbstractRenderer::setModelDirty); + disconnect(d->model, &QObject::destroyed, this, nullptr); + d->renderPasses.clear(); } d->model = model; + if (d->model) { connect(d->model, &TimelineModel::expandedChanged, this, &QQuickItem::update); connect(d->model, &TimelineModel::hiddenChanged, this, &QQuickItem::update); @@ -118,6 +121,13 @@ void TimelineAbstractRenderer::setModel(TimelineModel *model) this, &TimelineAbstractRenderer::setRowHeightsDirty); connect(d->model, &TimelineModel::contentChanged, this, &TimelineAbstractRenderer::setModelDirty); + connect(d->model, &QObject::destroyed, this, [this, d]() { + // Weak pointers are supposed to be notified before the destroyed() signal is sent. + Q_ASSERT(d->model.isNull()); + d->renderPasses.clear(); + setModelDirty(); + emit modelChanged(d->model); + }); d->renderPasses = d->model->supportedRenderPasses(); } @@ -137,14 +147,23 @@ void TimelineAbstractRenderer::setNotes(TimelineNotesModel *notes) if (d->notes == notes) return; - if (d->notes) + if (d->notes) { disconnect(d->notes, &TimelineNotesModel::changed, this, &TimelineAbstractRenderer::setNotesDirty); + disconnect(d->notes, &QObject::destroyed, this, nullptr); + } d->notes = notes; - if (d->notes) + if (d->notes) { connect(d->notes, &TimelineNotesModel::changed, this, &TimelineAbstractRenderer::setNotesDirty); + connect(d->notes, &QObject::destroyed, this, [this, d]() { + // Weak pointers are supposed to be notified before the destroyed() signal is sent. + Q_ASSERT(d->notes.isNull()); + setNotesDirty(); + emit notesChanged(d->notes); + }); + } setNotesDirty(); emit notesChanged(d->notes); @@ -160,11 +179,20 @@ void TimelineAbstractRenderer::setZoomer(TimelineZoomControl *zoomer) { Q_D(TimelineAbstractRenderer); if (zoomer != d->zoomer) { - if (d->zoomer != 0) + if (d->zoomer) { disconnect(d->zoomer, &TimelineZoomControl::windowChanged, this, &QQuickItem::update); + disconnect(d->zoomer, &QObject::destroyed, this, nullptr); + } d->zoomer = zoomer; - if (d->zoomer != 0) + if (d->zoomer) { connect(d->zoomer, &TimelineZoomControl::windowChanged, this, &QQuickItem::update); + connect(d->zoomer, &QObject::destroyed, this, [this, d]() { + // Weak pointers are supposed to be notified before the destroyed() signal is sent. + Q_ASSERT(d->zoomer.isNull()); + emit zoomerChanged(d->zoomer); + update(); + }); + } emit zoomerChanged(zoomer); update(); } @@ -191,22 +219,28 @@ bool TimelineAbstractRenderer::rowHeightsDirty() const void TimelineAbstractRenderer::setModelDirty() { Q_D(TimelineAbstractRenderer); - d->modelDirty = true; - update(); + if (!d->modelDirty) { + d->modelDirty = true; + update(); + } } void TimelineAbstractRenderer::setRowHeightsDirty() { Q_D(TimelineAbstractRenderer); - d->rowHeightsDirty = true; - update(); + if (!d->rowHeightsDirty) { + d->rowHeightsDirty = true; + update(); + } } void TimelineAbstractRenderer::setNotesDirty() { Q_D(TimelineAbstractRenderer); - d->notesDirty = true; - update(); + if (!d->notesDirty) { + d->notesDirty = true; + update(); + } } // Reset the dirty flags, delete the old node (if given), and return 0 |