From 7684abeccf27075b0b2bbcb68baf289577f22e57 Mon Sep 17 00:00:00 2001 From: Dmitri Ovodok Date: Wed, 4 Dec 2019 02:22:55 +0200 Subject: [PATCH] fix #298061: fix a crash on "set as style" if score ends with a frame - Don't pass staff number to adjustCanvasPosition if trying to adjust viewport to a frame. This avoids a crash itself. - Implement a more robust approach to determine a measure relevant to the current edit operation in CmdState. This avoids trying to unnecessarily jump to the frame at the end of a score. --- libmscore/cmd.cpp | 48 +++++++++++++++++++++++++++++++------------- libmscore/score.h | 7 +++++-- mscore/scoreview.cpp | 2 +- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/libmscore/cmd.cpp b/libmscore/cmd.cpp index 9f966a42ec778..34bfbabfd588f 100644 --- a/libmscore/cmd.cpp +++ b/libmscore/cmd.cpp @@ -92,7 +92,8 @@ void CmdState::reset() _endStaff = -1; _el = nullptr; _oneElement = true; - _elIsMeasureBase = false; + _mb = nullptr; + _oneMeasureBase = true; _locked = false; } @@ -128,6 +129,19 @@ void CmdState::setStaff(int st) _endStaff = st; } +//--------------------------------------------------------- +// setMeasureBase +//--------------------------------------------------------- + +void CmdState::setMeasureBase(const MeasureBase* mb) + { + if (!mb || _mb == mb || _locked) + return; + + _oneMeasureBase = !_mb; + _mb = mb; + } + //--------------------------------------------------------- // setElement //--------------------------------------------------------- @@ -137,20 +151,11 @@ void CmdState::setElement(const Element* e) if (!e || _el == e || _locked) return; - // prefer measures and frames as edit targets - const bool oldIsMeasureBase = _elIsMeasureBase; - const bool newIsMeasureBase = e->isMeasureBase(); - if (newIsMeasureBase && !oldIsMeasureBase) { - _oneElement = true; - return; - } - else if (oldIsMeasureBase && !newIsMeasureBase) - return; // don't remember the new element - else - _oneElement = !_el; - + _oneElement = !_el; _el = e; - _elIsMeasureBase = newIsMeasureBase; + + if (_oneMeasureBase) + setMeasureBase(e->findMeasureBase()); } //--------------------------------------------------------- @@ -161,6 +166,21 @@ void CmdState::unsetElement(const Element* e) { if (_el == e) _el = nullptr; + if (_mb == e) + _mb = nullptr; + } + +//--------------------------------------------------------- +// element +//--------------------------------------------------------- + +const Element* CmdState::element() const + { + if (_oneElement) + return _el; + if (_oneMeasureBase) + return _mb; + return nullptr; } //--------------------------------------------------------- diff --git a/libmscore/score.h b/libmscore/score.h index 7297ceea258c8..b37cd2133e203 100644 --- a/libmscore/score.h +++ b/libmscore/score.h @@ -260,11 +260,14 @@ class CmdState { int _startStaff = -1; int _endStaff = -1; const Element* _el = nullptr; + const MeasureBase* _mb = nullptr; bool _oneElement = true; - bool _elIsMeasureBase = false; + bool _oneMeasureBase = true; bool _locked = false; + void setMeasureBase(const MeasureBase* mb); + public: LayoutFlags layoutFlags; @@ -286,7 +289,7 @@ class CmdState { Fraction endTick() const { return _endTick; } int startStaff() const { return _startStaff; } int endStaff() const { return _endStaff; } - const Element* element() const { return _oneElement ? _el : nullptr; } + const Element* element() const; void lock() { _locked = true; } void unlock() { _locked = false; } diff --git a/mscore/scoreview.cpp b/mscore/scoreview.cpp index 170f2fd65d6e2..b67f1cf04298f 100644 --- a/mscore/scoreview.cpp +++ b/mscore/scoreview.cpp @@ -4926,7 +4926,7 @@ void ScoreView::moveViewportToLastEdit() const Element* viewportElement = (editElement && editElement->bbox().isValid() && !mb->isMeasure()) ? editElement : mb; - const int staff = sc->isMaster() ? st.startStaff() : -1; // TODO: choose the closest staff to the current viewport? + const int staff = sc->isMaster() && mb->isMeasure() ? st.startStaff() : -1; // TODO: choose the closest staff to the current viewport? adjustCanvasPosition(viewportElement, /* playback */ false, staff); } }