diff --git a/libmscore/barline.cpp b/libmscore/barline.cpp index d4ec5e779fecd..c3b807f726f50 100644 --- a/libmscore/barline.cpp +++ b/libmscore/barline.cpp @@ -203,9 +203,6 @@ void BarLine::getY(qreal* y1, qreal* y2) const int staffIdx1 = staffIdx(); int staffIdx2 = staffIdx1 + _span - 1; if (staffIdx2 >= score()->nstaves()) { - // this can happen on read - // as we may be laying out a barline that spans multiple staves - // before we have read the staves it spans qDebug("BarLine: bad _span %d", _span); staffIdx2 = score()->nstaves() - 1; } @@ -740,6 +737,13 @@ void BarLine::endEdit() // if bar line belongs to a system (system-initial bar line), edit is local if (parent() && parent()->type() == Element::Type::SYSTEM) ctrlDrag = true; + // for mid-measure barlines, edit is local + bool midMeasure = false; + if (parent()->type() == Element::Type::SEGMENT + && static_cast(parent())->segmentType() == Segment::Type::BarLine) { + ctrlDrag = true; + midMeasure = true; + } if (ctrlDrag) { // if single bar line edit ctrlDrag = false; @@ -750,6 +754,55 @@ void BarLine::endEdit() _span = _origSpan; // restore original span values _spanFrom = _origSpanFrom; _spanTo = _origSpanTo; + // for mid-measure barline in root score, update parts + if (midMeasure && score()->parentScore() == nullptr && score()->excerpts().size() > 0) { + int currIdx = staffIdx(); + Measure* m = static_cast(parent())->measure(); + // change linked barlines as necessary + int lastIdx = currIdx + qMax(_span, newSpan); + for (int idx = currIdx; idx < lastIdx; ++idx) { + Staff* staff = score()->staff(idx); + LinkedStaves* ls = staff->linkedStaves(); + if (ls) { + for (Staff* lstaff : ls->staves()) { + Score* lscore = lstaff->score(); + // don't change barlines in root score + if (lscore == staff->score()) + continue; + // change barline only in top staff of part + if (lstaff != lscore->staff(0)) + continue; + int spannedStaves = qMax(currIdx + newSpan - idx, 0); + int lNewSpan = qMin(spannedStaves, lscore->nstaves()); + Measure* lm = lscore->tick2measure(m->tick()); + Segment* lseg = lm->undoGetSegment(Segment::Type::BarLine, tick()); + BarLine* lbl = static_cast(lseg->element(0)); + if (lbl) { + // already a barline here + if (lNewSpan > 0) { + // keep barline, but update span if necessary + if (lbl->span() != lNewSpan) + lbl->undoChangeProperty(P_ID::BARLINE_SPAN, lNewSpan); + } + else { + // remove barline + lbl->unlink(); + lbl->score()->undoRemoveElement(lbl); + } + } + else { + // new barline needed + lbl = static_cast(linkedClone()); + lbl->setSpan(lNewSpan); + lbl->setTrack(lstaff->idx() * VOICES); + lbl->setScore(lscore); + lbl->setParent(lseg); + lscore->undoAddElement(lbl); + } + } + } + } + } score()->undoChangeSingleBarLineSpan(this, newSpan, newSpanFrom, newSpanTo); return; } diff --git a/libmscore/excerpt.cpp b/libmscore/excerpt.cpp index 44e714175b9a9..559488d7da201 100644 --- a/libmscore/excerpt.cpp +++ b/libmscore/excerpt.cpp @@ -39,6 +39,7 @@ #include "beam.h" #include "utils.h" #include "tremolo.h" +#include "barline.h" #include "undo.h" namespace Ms { @@ -393,6 +394,37 @@ void cloneStaves(Score* oscore, Score* score, const QList& map) continue; Element* oe = oseg->element(srcTrack); + int adjustedBarlineSpan = 0; + if (srcTrack % VOICES == 0 && oseg->segmentType() == Segment::Type::BarLine) { + // mid-measure barline segment + // may need to clone barline from a previous staff and/or adjust span + int oIdx = srcTrack / VOICES; + if (!oe) { + // no barline on this staff in original score, + // but check previous staves + for (int i = oIdx - 1; i >= 0; --i) { + oe = oseg->element(i * VOICES); + if (oe) + break; + } + } + if (oe) { + // barline found, now check span + BarLine* bl = static_cast(oe); + int oSpan1 = bl->staff()->idx(); + int oSpan2 = oSpan1 + bl->span(); + if (oSpan1 <= oIdx && oIdx < oSpan2) { + // this staff is within span + // calculate adjusted span for excerpt + int oSpan = oSpan2 - oIdx; + adjustedBarlineSpan = qMin(oSpan, score->nstaves()); + } + else { + // this staff is not within span + oe = nullptr; + } + } + } if (oe == 0) continue; Element* ne; @@ -403,7 +435,11 @@ void cloneStaves(Score* oscore, Score* score, const QList& map) ne->setTrack(track); ne->scanElements(score, localSetScore); //necessary? ne->setScore(score); - if (oe->isChordRest()) { + if (oe->type() == Element::Type::BAR_LINE && adjustedBarlineSpan) { + BarLine* nbl = static_cast(ne); + nbl->setSpan(adjustedBarlineSpan); + } + else if (oe->isChordRest()) { ChordRest* ocr = static_cast(oe); ChordRest* ncr = static_cast(ne);