Skip to content

Commit

Permalink
fix #279183: fix clefs and keysig handling on rewriting measures
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitrio95 committed Dec 21, 2018
1 parent 1eecf01 commit 298a4da
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 5 deletions.
8 changes: 4 additions & 4 deletions libmscore/range.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -557,12 +557,12 @@ bool TrackList::write(Score* score, int tick) const
Segment* seg;
if (remains == m->len() && m->tick() > 0) {
Measure* pm = m->prevMeasure();
seg = pm->undoGetSegment(SegmentType::Clef, pm->len());
seg = pm->getSegment(SegmentType::Clef, pm->len());
}
else if (remains != m->len())
seg = m->undoGetSegment(SegmentType::Clef, m->len() - remains);
seg = m->getSegment(SegmentType::Clef, m->len() - remains);
else
seg = m->undoGetSegmentR(SegmentType::HeaderClef, 0);
seg = m->getSegmentR(SegmentType::HeaderClef, 0);
Element* ne = e->clone();
ne->setScore(score);
ne->setTrack(_track);
Expand All @@ -574,7 +574,7 @@ bool TrackList::write(Score* score, int tick) const
// add the element in its own segment;
// but KeySig has to be at start of (current) measure

Segment* seg = m->undoGetSegment(Segment::segmentType(e->type()), e->isKeySig() ? Fraction() : m->len() - remains);
Segment* seg = m->getSegment(Segment::segmentType(e->type()), e->isKeySig() ? Fraction() : m->len() - remains);
Element* ne = e->clone();
ne->setScore(score);
ne->setTrack(_track);
Expand Down
39 changes: 38 additions & 1 deletion libmscore/undo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1570,6 +1570,29 @@ void ChangeMStaffProperties::flip(EditData*)
slashStyle = s;
}

//---------------------------------------------------------
// getCourtesyClefs
// remember clefs at the end of previous measure
//---------------------------------------------------------

std::vector<Clef*> InsertRemoveMeasures::getCourtesyClefs(Measure* m)
{
Score* score = m->score();
std::vector<Clef*> startClefs;
if (m->prev() && m->prev()->isMeasure()) {
Measure* prevMeasure = toMeasure(m->prev());
const Segment* clefSeg = prevMeasure->findSegmentR(SegmentType::Clef | SegmentType::HeaderClef, prevMeasure->ticks());
if (clefSeg) {
for (int st = 0; st < score->nstaves(); ++st) {
Element* clef = clefSeg->element(staff2track(st));
if (clef->isClef())
startClefs.push_back(toClef(clef));
}
}
}
return startClefs;
}

//---------------------------------------------------------
// insertMeasures
//---------------------------------------------------------
Expand All @@ -1578,6 +1601,7 @@ void InsertRemoveMeasures::insertMeasures()
{
Score* score = fm->score();
QList<Clef*> clefs;
std::vector<Clef*> prevMeasureClefs;
QList<KeySig*> keys;
Segment* fs = 0;
Segment* ls = 0;
Expand All @@ -1586,7 +1610,7 @@ void InsertRemoveMeasures::insertMeasures()
fs = toMeasure(fm)->first();
ls = toMeasure(lm)->last();
for (Segment* s = fs; s && s != ls; s = s->next1()) {
if (!s->enabled() || !(s->segmentType() & (SegmentType::Clef | SegmentType::KeySig)))
if (!s->enabled() || !(s->segmentType() & (SegmentType::Clef | SegmentType::HeaderClef | SegmentType::KeySig)))
continue;
for (int track = 0; track < score->ntracks(); track += VOICES) {
Element* e = s->element(track);
Expand All @@ -1598,6 +1622,7 @@ void InsertRemoveMeasures::insertMeasures()
keys.append(toKeySig(e));
}
}
prevMeasureClefs = getCourtesyClefs(toMeasure(fm));
}
score->measures()->insert(fm, lm);

Expand All @@ -1613,6 +1638,8 @@ void InsertRemoveMeasures::insertMeasures()
}
}
}
for (Clef* clef : prevMeasureClefs)
clef->staff()->setClef(clef);
for (Clef* clef : clefs)
clef->staff()->setClef(clef);
for (KeySig* key : keys)
Expand Down Expand Up @@ -1693,8 +1720,18 @@ void InsertRemoveMeasures::removeMeasures()
}
}
}

// remember clefs at the end of previous measure
const auto clefs = getCourtesyClefs(toMeasure(fm));

if (score->firstMeasure())
score->insertTime(tick1, -(tick2 - tick1));

// Restore clefs that were backed up. Events for them could be lost
// as a result of the recent insertTime() call.
for (Clef* clef : clefs)
clef->staff()->setClef(clef);

for (Spanner* sp : score->unmanagedSpanners()) {
if ((sp->tick() >= tick1 && sp->tick() < tick2) || (sp->tick2() >= tick1 && sp->tick2() < tick2))
sp->removeUnmanaged();
Expand Down
2 changes: 2 additions & 0 deletions libmscore/undo.h
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,8 @@ class InsertRemoveMeasures : public UndoCommand {
MeasureBase* fm;
MeasureBase* lm;

static std::vector<Clef*> getCourtesyClefs(Measure* m);

protected:
void removeMeasures();
void insertMeasures();
Expand Down

0 comments on commit 298a4da

Please sign in to comment.