fix #301436: invalid selection when navigating with mmrests

Resolves: https://musescore.org/en/node/301436

The accessibility navigation commands
(Alt+Left/Right, also Ctrl+Alt+Shift+Left/Right)
were not properly checking for mmrests,
resulting in selection of elements in the underlying measures
that were not valid in the current layout.
This adds the necessary checks.
Mostly just a matter of adding "MM" to various function calls.
In a couple of places, the appropriate function did not exist,
so I added it.
Also corrected errors in Ctrl+Alt+Shift+Left/Right
that occurs when going past the end of a staff,
the code to wrap around to the next staff this case well.
In part this is because the implementation of barlines changed
since the code was written.
Barlines are per-staff now even when spanned,
so the use and management of prevTrack is no longer appropriate.
This commit is contained in:
MarcSabatella 2020-02-21 12:23:26 -07:00
parent 52f357df83
commit b5d53248ab
9 changed files with 61 additions and 33 deletions

View file

@ -1574,7 +1574,7 @@ Pid BarLine::propertyId(const QStringRef& name) const
Element* BarLine::nextSegmentElement()
{
return segment()->firstInNextSegments(score()->inputState().prevTrack() / VOICES);
return segment()->firstInNextSegments(staffIdx()); //score()->inputState().prevTrack() / VOICES);
}
//---------------------------------------------------------
@ -1583,7 +1583,7 @@ Element* BarLine::nextSegmentElement()
Element* BarLine::prevSegmentElement()
{
return segment()->lastInPrevSegments(score()->inputState().prevTrack() / VOICES);
return segment()->lastInPrevSegments(staffIdx()); //score()->inputState().prevTrack() / VOICES);
}
//---------------------------------------------------------

View file

@ -502,6 +502,20 @@ MeasureBase* MeasureBase::nextMM() const
return _next;
}
//---------------------------------------------------------
// prevMM
//---------------------------------------------------------
MeasureBase* MeasureBase::prevMM() const
{
if (_prev
&& _prev->isMeasure()
&& score()->styleB(Sid::createMultiMeasureRests)) {
return const_cast<Measure*>(toMeasure(_prev)->mmRest1());
}
return _prev;
}
//---------------------------------------------------------
// writeProperties
//---------------------------------------------------------

View file

@ -86,6 +86,7 @@ class MeasureBase : public Element {
MeasureBase* nextMM() const;
void setNext(MeasureBase* e) { _next = e; }
MeasureBase* prev() const { return _prev; }
MeasureBase* prevMM() const;
void setPrev(MeasureBase* e) { _prev = e; }
Ms::Measure* nextMeasure() const;

View file

@ -277,7 +277,7 @@ Element* Score::firstElement(bool frame)
if (mb && mb->isBox())
return mb;
}
Segment *s = firstSegment(SegmentType::All);
Segment *s = firstSegmentMM(SegmentType::All);
return s ? s->element(0) : nullptr;
}
@ -293,7 +293,7 @@ Element* Score::lastElement(bool frame)
return mb;
}
Element* re = 0;
Segment* seg = lastSegment();
Segment* seg = lastSegmentMM();
if (!seg)
return nullptr;
while (true) {
@ -598,7 +598,7 @@ Element* Score::nextElement()
Element* nextEl = nextSegment->firstElementOfSegment(nextSegment, staffId);
if (nextEl)
return nextEl;
nextSegment = nextSegment->next1();
nextSegment = nextSegment->next1MM();
}
}
break;
@ -618,7 +618,7 @@ Element* Score::nextElement()
case ElementType::VBOX:
case ElementType::HBOX:
case ElementType::TBOX: {
MeasureBase* mb = toMeasureBase(e)->next();
MeasureBase* mb = toMeasureBase(e)->nextMM();
if (!mb) {
break;
}
@ -741,7 +741,7 @@ Element* Score::prevElement()
case ElementType::VBOX:
case ElementType::HBOX:
case ElementType::TBOX: {
MeasureBase* mb = toMeasureBase(e)->prev();
MeasureBase* mb = toMeasureBase(e)->prevMM();
if (!mb) {
break;
}

View file

@ -1812,6 +1812,16 @@ Segment* Score::lastSegment() const
return m ? m->last() : 0;
}
//---------------------------------------------------------
// lastSegmentMM
//---------------------------------------------------------
Segment* Score::lastSegmentMM() const
{
Measure* m = lastMeasureMM();
return m ? m->last() : 0;
}
//---------------------------------------------------------
// utick2utime
//---------------------------------------------------------

View file

@ -821,8 +821,8 @@ class Score : public QObject, public ScoreElement {
Segment* tick2segmentMM(const Fraction& tick, bool first, SegmentType st) const;
Segment* tick2segmentMM(const Fraction& tick) const;
Segment* tick2segmentMM(const Fraction& tick, bool first) const;
Segment* tick2leftSegment(const Fraction& tick) const;
Segment* tick2rightSegment(const Fraction& tick) const;
Segment* tick2leftSegment(const Fraction& tick, bool useMMrest = false) const;
Segment* tick2rightSegment(const Fraction& tick, bool useMMrest = false) const;
void fixTicks();
void rebuildTempoAndTimeSigMaps(Measure* m);
Element* nextElement();
@ -998,6 +998,7 @@ class Score : public QObject, public ScoreElement {
Segment* firstSegment(SegmentType s) const;
Segment* firstSegmentMM(SegmentType s) const;
Segment* lastSegment() const;
Segment* lastSegmentMM() const;
void connectTies(bool silent=false);

View file

@ -1259,8 +1259,10 @@ Element* Segment::firstInNextSegments(int activeStaff)
return re;
if (!seg) { //end of staff
seg = score()->firstSegment(SegmentType::All);
return seg->element( (activeStaff + 1) * VOICES );
if (activeStaff + 1 >= score()->nstaves()) //end of score
return 0;
seg = score()->firstSegmentMM(SegmentType::All);
return seg->element((activeStaff + 1) * VOICES);
}
return 0;
}
@ -1520,12 +1522,12 @@ Element* Segment::nextElement(int activeStaff)
if (s)
return s->spannerSegments().front();
}
Segment* nextSegment = this->next1enabled();
Segment* nextSegment = this->next1MMenabled();
while (nextSegment) {
Element* nextEl = nextSegment->firstElementOfSegment(nextSegment, activeStaff);
if (nextEl)
return nextEl;
nextSegment = nextSegment->next1enabled();
nextSegment = nextSegment->next1MMenabled();
}
break;
}
@ -1539,12 +1541,12 @@ Element* Segment::nextElement(int activeStaff)
if (sp)
return sp->spannerSegments().front();
Segment* nextSegment = this->next1enabled();
Segment* nextSegment = this->next1MMenabled();
while (nextSegment) {
Element* nextEl = nextSegment->firstElementOfSegment(nextSegment, activeStaff);
if (nextEl)
return nextEl;
nextSegment = nextSegment->next1enabled();
nextSegment = nextSegment->next1MMenabled();
}
break;
}
@ -1578,7 +1580,7 @@ Element* Segment::nextElement(int activeStaff)
Spanner* s = firstSpanner(activeStaff);
if (s)
return s->spannerSegments().front();
Segment* nextSegment = seg->next1enabled();
Segment* nextSegment = seg->next1MMenabled();
if (!nextSegment) {
MeasureBase* mb = measure()->next();
return mb && mb->isBox() ? mb : score()->lastElement();
@ -1587,7 +1589,7 @@ Element* Segment::nextElement(int activeStaff)
Measure* nsm = nextSegment->measure();
if (nsm != measure()) {
// check for frame, measure elements
MeasureBase* nmb = measure()->next();
MeasureBase* nmb = measure()->nextMM();
Element* nme = nsm->el().empty() ? nullptr : nsm->el().front();
if (nsm != nmb)
return nmb;
@ -1599,7 +1601,7 @@ Element* Segment::nextElement(int activeStaff)
nextEl = nextSegment->firstElementOfSegment(nextSegment, activeStaff);
if (nextEl)
return nextEl;
nextSegment = nextSegment->next1enabled();
nextSegment = nextSegment->next1MMenabled();
}
}
break;
@ -1652,7 +1654,7 @@ Element* Segment::prevElement(int activeStaff)
el = s->element(--track);
if (track == 0) {
track = score()->nstaves() * VOICES - 1;
s = s->prev1enabled();
s = s->prev1MMenabled();
}
}
if (el->staffIdx() != activeStaff)
@ -1723,7 +1725,7 @@ Element* Segment::prevElement(int activeStaff)
return prev;
}
}
Segment* prevSeg = seg->prev1enabled();
Segment* prevSeg = seg->prev1MMenabled();
if (!prevSeg) {
MeasureBase* mb = measure()->prev();
return mb && mb->isBox() ? mb : score()->firstElement();
@ -1732,7 +1734,7 @@ Element* Segment::prevElement(int activeStaff)
Measure* psm = prevSeg->measure();
if (psm != measure()) {
// check for frame, measure elements
MeasureBase* pmb = measure()->prev();
MeasureBase* pmb = measure()->prevMM();
Element* me = measure()->el().empty() ? nullptr : measure()->el().back();
if (me && me->isTextBase() && me->staffIdx() == e->staffIdx())
return me;
@ -1742,7 +1744,7 @@ Element* Segment::prevElement(int activeStaff)
prev = lastElementOfSegment(prevSeg, activeStaff);
while (!prev && prevSeg) {
prevSeg = prevSeg->prev1enabled();
prevSeg = prevSeg->prev1MMenabled();
prev = lastElementOfSegment(prevSeg, activeStaff);
}
if (!prevSeg)
@ -1812,19 +1814,19 @@ Element* Segment::lastInPrevSegments(int activeStaff)
return re;
if (!seg) { //end of staff
if (activeStaff -1 < 0) //end of score
if (activeStaff - 1 < 0) //end of score
return 0;
re = 0;
seg = score()->lastSegment();
seg = score()->lastSegmentMM();
while (true) {
if (seg->segmentType() == SegmentType::EndBarLine)
score()->inputState().setTrack( (activeStaff -1) * VOICES ); //correction
//if (seg->segmentType() == SegmentType::EndBarLine)
// score()->inputState().setTrack((activeStaff - 1) * VOICES ); //correction
if ((re = seg->lastElement(activeStaff -1)) != 0)
if ((re = seg->lastElement(activeStaff - 1)) != 0)
return re;
seg = seg->prev1enabled();
seg = seg->prev1MMenabled();
}
}

View file

@ -171,7 +171,7 @@ ChordRest* Selection::currentCR() const
// no selection yet - start at very beginning, not first cr
if (_currentTick == Fraction(-1, 1))
return nullptr;
Segment* s = score()->tick2rightSegment(_currentTick);
Segment* s = score()->tick2rightSegment(_currentTick, true);
if (!s)
return nullptr;
int track = _currentTrack;

View file

@ -178,9 +178,9 @@ Segment* Score::tick2segment(const Fraction& tick, bool first) const
/// the first segment *before* this tick position
//---------------------------------------------------------
Segment* Score::tick2leftSegment(const Fraction& tick) const
Segment* Score::tick2leftSegment(const Fraction& tick, bool useMMrest) const
{
Measure* m = tick2measure(tick);
Measure* m = useMMrest ? tick2measureMM(tick) : tick2measure(tick);
if (m == 0) {
qDebug("tick2leftSegment(): not found tick %d", tick.ticks());
return 0;
@ -203,9 +203,9 @@ Segment* Score::tick2leftSegment(const Fraction& tick) const
/// the first segment *after* this tick position
//---------------------------------------------------------
Segment* Score::tick2rightSegment(const Fraction& tick) const
Segment* Score::tick2rightSegment(const Fraction& tick, bool useMMrest) const
{
Measure* m = tick2measure(tick);
Measure* m = useMMrest ? tick2measureMM(tick) : tick2measure(tick);
if (m == 0) {
qDebug("tick2nearestSegment(): not found tick %d", tick.ticks());
return 0;