fix(widget): harden TimelineAndTrackView teardown and TimeScaledObject limits
- TimelineAndTrackView: disconnect the scrollbar sync connections in the destructor. Child views reset their scene during destruction, which can re-emit QScrollBar::valueChanged into a half-destroyed object and trip Qt's assertObjectType abort. - TimeScaledObject: keep minimum <= maximum when setting scale limits so set_scale()'s std::clamp is never called with inverted limits (UB). Setting the maximum below the minimum now pulls the minimum down, and vice versa, matching QAbstractSlider conventions.
This commit is contained in:
@@ -116,6 +116,12 @@ void TimeScaledObject::set_maximum_scale(const double &max)
|
||||
{
|
||||
max_scale_ = max;
|
||||
|
||||
// Keep min <= max so the clamp in set_scale() is never called with
|
||||
// inverted limits (undefined behavior)
|
||||
if (min_scale_ > max_scale_) {
|
||||
min_scale_ = max_scale_;
|
||||
}
|
||||
|
||||
if (get_scale() > max_scale_) {
|
||||
set_scale(max_scale_);
|
||||
}
|
||||
@@ -125,6 +131,12 @@ void TimeScaledObject::set_minimum_scale(const double &min)
|
||||
{
|
||||
min_scale_ = min;
|
||||
|
||||
// Keep min <= max so the clamp in set_scale() is never called with
|
||||
// inverted limits (undefined behavior)
|
||||
if (max_scale_ < min_scale_) {
|
||||
max_scale_ = min_scale_;
|
||||
}
|
||||
|
||||
if (get_scale() < min_scale_) {
|
||||
set_scale(min_scale_);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,16 @@ TimelineAndTrackView::TimelineAndTrackView(Qt::Alignment vertical_alignment,
|
||||
splitter_->setSizes({ 180, width() });
|
||||
}
|
||||
|
||||
TimelineAndTrackView::~TimelineAndTrackView()
|
||||
{
|
||||
// When the child views are destroyed they reset their scene, which can
|
||||
// push a valueChanged through these connections while this object is
|
||||
// already half-destroyed (Qt aborts on a slot invoked past its class's
|
||||
// destructor). Detach first so teardown emissions go nowhere.
|
||||
disconnect(view_->verticalScrollBar(), nullptr, this, nullptr);
|
||||
disconnect(track_view_->verticalScrollBar(), nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
QSplitter *TimelineAndTrackView::splitter() const
|
||||
{
|
||||
return splitter_;
|
||||
|
||||
@@ -42,6 +42,8 @@ public:
|
||||
|
||||
TrackView *track_view() const;
|
||||
|
||||
virtual ~TimelineAndTrackView() override;
|
||||
|
||||
private:
|
||||
QSplitter *splitter_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user