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:
parent
52f357df83
commit
b5d53248ab
9 changed files with 61 additions and 33 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue