QmlDesigner: Fix assert

TimelineWidget::invalidateTimelineDuration() is called
by TimelineView::instancePropertyChanged(), which is a callback
from the model.

Those callbacks are not supposed to mutate the model and write
access to the model will trigger an assert.
The method setCurrentFrame() calls ModelNode::setAuxiliaryData().
The reasoning for this behavior is to avoid events casades from
the get go and to avoid that a view has a side effect on
the operation of another view.
This way we also avoid any circular information flow in the application.

In theory a view should never act as a 'gatekeeper' like in this case.
The simple 'hack' for trivial cases is to use a timer.
Generally we try to move the logic into the model in such cases.

Change-Id: I0b46bb38ee0a9603d4617f1a13d8cfcd2e7378b8
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Thomas Hartmann
2019-10-15 10:31:01 +02:00
parent c13b20f160
commit 41a7cd15be

View File

@@ -453,7 +453,11 @@ void TimelineWidget::invalidateTimelineDuration(const QmlTimeline &timeline)
else if (playHeadFrame > timeline.endKeyframe()) else if (playHeadFrame > timeline.endKeyframe())
playHeadFrame = timeline.endKeyframe(); playHeadFrame = timeline.endKeyframe();
graphicsScene()->setCurrentFrame(playHeadFrame); /* We have to set the current frame asynchronously,
* because callbacks are not supposed to mutate the model. */
QTimer::singleShot(0, [this, playHeadFrame] {
graphicsScene()->setCurrentFrame(playHeadFrame);
});
} }
} }
} }