Merge pull request #3694 from mattmcclinch/272887-midmeasure-clef

fix #272887: Unable to add mid-measure clef on the first tick of a measure
This commit is contained in:
anatoly-os 2019-02-15 16:59:18 +02:00 committed by GitHub
commit bab29bf4e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 70 additions and 38 deletions

View file

@ -252,7 +252,7 @@ Element* Clef::drop(EditData& data)
Clef* clef = toClef(e); Clef* clef = toClef(e);
ClefType stype = clef->clefType(); ClefType stype = clef->clefType();
if (clefType() != stype) { if (clefType() != stype) {
score()->undoChangeClef(staff(), segment(), stype); score()->undoChangeClef(staff(), this, stype);
c = this; c = this;
} }
} }

View file

@ -2415,7 +2415,7 @@ void Score::cmdInsertClef(ClefType type)
{ {
if (!noteEntryMode()) if (!noteEntryMode())
return; return;
undoChangeClef(staff(inputTrack()/VOICES), inputState().segment(), type); undoChangeClef(staff(inputTrack()/VOICES), inputState().cr(), type);
} }
//--------------------------------------------------------- //---------------------------------------------------------
@ -2425,7 +2425,7 @@ void Score::cmdInsertClef(ClefType type)
void Score::cmdInsertClef(Clef* clef, ChordRest* cr) void Score::cmdInsertClef(Clef* clef, ChordRest* cr)
{ {
undoChangeClef(cr->staff(), cr->segment(), clef->clefType()); undoChangeClef(cr->staff(), cr, clef->clefType());
delete clef; delete clef;
} }

View file

@ -3543,29 +3543,37 @@ void Score::undoChangeKeySig(Staff* ostaff, int tick, KeySigEvent key)
//--------------------------------------------------------- //---------------------------------------------------------
// undoChangeClef // undoChangeClef
// change clef if seg contains a clef // change clef if e is a clef
// else // else
// create a clef before segment seg // create a clef before element e
//--------------------------------------------------------- //---------------------------------------------------------
void Score::undoChangeClef(Staff* ostaff, Segment* seg, ClefType ct) void Score::undoChangeClef(Staff* ostaff, Element* e, ClefType ct)
{ {
SegmentType st; bool moveClef = false;
if (seg->isHeaderClefType()) SegmentType st = SegmentType::Clef;
st = SegmentType::HeaderClef; if (e->isMeasure()) {
else if (seg->isClefType()) if (toMeasure(e)->prevMeasure())
st = SegmentType::Clef; moveClef = true;
else if (seg->rtick() == 0) else
st = SegmentType::HeaderClef; st = SegmentType::HeaderClef;
else }
st = SegmentType::Clef; else if (e->isClef()) {
Clef* clef = toClef(e);
bool moveClef = (st == SegmentType::HeaderClef) && seg->measure()->prevMeasure(); if (clef->segment()->isHeaderClefType()) {
bool small = !seg->header() || moveClef; if (clef->measure()->prevMeasure())
moveClef = true;
else
st = SegmentType::HeaderClef;
}
else if (clef->rtick() == clef->measure()->ticks())
moveClef = true;
}
Clef* gclef = 0; Clef* gclef = 0;
int tick = seg->tick(); int tick = e->tick();
int rtick = seg->rtick(); int rtick = e->rtick();
bool small = (st == SegmentType::Clef);
for (Staff* staff : ostaff->staffList()) { for (Staff* staff : ostaff->staffList()) {
if (staff->staffType(tick)->group() != ClefInfo::staffGroup(ct)) if (staff->staffType(tick)->group() != ClefInfo::staffGroup(ct))
continue; continue;

View file

@ -106,8 +106,18 @@ void KeySig::layout()
// determine current clef for this staff // determine current clef for this staff
ClefType clef = ClefType::G; ClefType clef = ClefType::G;
if (staff()) if (staff()) {
clef = staff()->clef(tick()); // Look for a clef before the key signature at the same tick
Clef* c = nullptr;
for (Segment* seg = segment()->prev1(); !c && seg && seg->tick() == tick(); seg = seg->prev1())
if (seg->isClefType() || seg->isHeaderClefType())
c = toClef(seg->element(track()));
if (c)
clef = c->clefType();
else
// no clef found, so get the clef type from the clefs list, using the previous tick
clef = staff()->clef(tick() - 1);
}
int accidentals = 0, naturals = 0; int accidentals = 0, naturals = 0;
int t1 = int(_sig.key()); int t1 = int(_sig.key());

View file

@ -1433,7 +1433,7 @@ Element* Measure::drop(EditData& data)
return 0; return 0;
case ElementType::CLEF: case ElementType::CLEF:
score()->undoChangeClef(staff, first(), toClef(e)->clefType()); score()->undoChangeClef(staff, this, toClef(e)->clefType());
delete e; delete e;
break; break;
@ -3673,7 +3673,17 @@ void Measure::addSystemHeader(bool isFirstSystem)
} }
if (isFirstSystem || score()->styleB(Sid::genClef)) { if (isFirstSystem || score()->styleB(Sid::genClef)) {
ClefTypeList cl = staff->clefType(tick()); // find the clef type at the previous tick
ClefTypeList cl = staff->clefType(tick() - 1);
// look for a clef change at the end of the previous measure
if (prevMeasure()) {
Segment* s = prevMeasure()->findSegment(SegmentType::Clef, tick());
if (s) {
Clef* c = toClef(s->element(track));
if (c)
cl = c->clefTypeList();
}
}
Clef* clef; Clef* clef;
if (!cSegment) { if (!cSegment) {
cSegment = new Segment(this, SegmentType::HeaderClef, 0); cSegment = new Segment(this, SegmentType::HeaderClef, 0);

View file

@ -2028,7 +2028,7 @@ bool Score::appendScore(Score* score, bool addPageBreak, bool addSectionBreak)
if (clef && clef->generated() && clef->clefType() != this->staff(staffIdx)->clef(tickOfAppend)) { if (clef && clef->generated() && clef->clefType() != this->staff(staffIdx)->clef(tickOfAppend)) {
// then convert that generated clef into a real non-generated clef // then convert that generated clef into a real non-generated clef
// so that its different type will be copied to joined score // so that its different type will be copied to joined score
score->undoChangeClef(staff, seg, clef->clefType()); score->undoChangeClef(staff, clef, clef->clefType());
} }
} }
} }

View file

@ -619,8 +619,8 @@ class Score : public QObject, public ScoreElement {
void undoChangeTuning(Note*, qreal); void undoChangeTuning(Note*, qreal);
void undoChangeUserMirror(Note*, MScore::DirectionH); void undoChangeUserMirror(Note*, MScore::DirectionH);
void undoChangeKeySig(Staff* ostaff, int tick, KeySigEvent); void undoChangeKeySig(Staff* ostaff, int tick, KeySigEvent);
void undoChangeClef(Staff* ostaff, Segment*, ClefType st); void undoChangeClef(Staff* ostaff, Element* e, ClefType ct);
bool undoPropertyChanged(Element* e, Pid t, const QVariant& st, PropertyFlags ps = PropertyFlags::NOSTYLE); bool undoPropertyChanged(Element*, Pid, const QVariant& v, PropertyFlags ps = PropertyFlags::NOSTYLE);
void undoPropertyChanged(ScoreElement*, Pid, const QVariant& v, PropertyFlags ps = PropertyFlags::NOSTYLE); void undoPropertyChanged(ScoreElement*, Pid, const QVariant& v, PropertyFlags ps = PropertyFlags::NOSTYLE);
inline virtual UndoStack* undoStack() const; inline virtual UndoStack* undoStack() const;
void undo(UndoCommand*, EditData* = 0) const; void undo(UndoCommand*, EditData* = 0) const;

View file

@ -391,8 +391,10 @@ void Staff::setClef(Clef* clef)
if (clef->generated()) if (clef->generated())
return; return;
int tick = clef->segment()->tick(); int tick = clef->segment()->tick();
for (Segment* s = clef->segment()->next(); s && s->tick() == tick; s = s->next()) { for (Segment* s = clef->segment()->next1(); s && s->tick() == tick; s = s->next1()) {
if (s->segmentType() == SegmentType::Clef && s->element(clef->track())) { if ((s->segmentType() == SegmentType::Clef || s->segmentType() == SegmentType::HeaderClef)
&& s->element(clef->track())
&& !s->element(clef->track())->generated()) {
// adding this clef has no effect on the clefs list // adding this clef has no effect on the clefs list
return; return;
} }
@ -411,15 +413,17 @@ void Staff::removeClef(Clef* clef)
if (clef->generated()) if (clef->generated())
return; return;
int tick = clef->segment()->tick(); int tick = clef->segment()->tick();
for (Segment* s = clef->segment()->next(); s && s->tick() == tick; s = s->next()) { for (Segment* s = clef->segment()->next1(); s && s->tick() == tick; s = s->next1()) {
if (s->segmentType() == SegmentType::Clef && s->element(clef->track())) { if ((s->segmentType() == SegmentType::Clef || s->segmentType() == SegmentType::HeaderClef)
&& s->element(clef->track())
&& !s->element(clef->track())->generated()) {
// removal of this clef has no effect on the clefs list // removal of this clef has no effect on the clefs list
return; return;
} }
} }
clefs.erase(clef->segment()->tick()); clefs.erase(clef->segment()->tick());
for (Segment* s = clef->segment()->prev(); s && s->tick() == tick; s = s->prev()) { for (Segment* s = clef->segment()->prev1(); s && s->tick() == tick; s = s->prev1()) {
if (s->segmentType() == SegmentType::Clef if ((s->segmentType() == SegmentType::Clef || s->segmentType() == SegmentType::HeaderClef)
&& s->element(clef->track()) && s->element(clef->track())
&& !s->element(clef->track())->generated()) { && !s->element(clef->track())->generated()) {
// a previous clef at the same tick position gets valid // a previous clef at the same tick position gets valid

View file

@ -88,7 +88,7 @@ void TestClefCourtesy::clef_courtesy01()
// check the required courtesy clef is there and it is shown // check the required courtesy clef is there and it is shown
Clef* clefCourt = 0; Clef* clefCourt = 0;
Measure* m = m1->prevMeasure(); Measure* m = m1->prevMeasure();
Segment* seg = m->findSegment(SegmentType::HeaderClef, m1->tick()); Segment* seg = m->findSegment(SegmentType::Clef, m1->tick());
QVERIFY2(seg, "No SegClef in measure 3."); QVERIFY2(seg, "No SegClef in measure 3.");
clefCourt = static_cast<Clef*>(seg->element(0)); clefCourt = static_cast<Clef*>(seg->element(0));
QVERIFY2(clefCourt, "No courtesy clef element in measure 3."); QVERIFY2(clefCourt, "No courtesy clef element in measure 3.");
@ -97,7 +97,7 @@ void TestClefCourtesy::clef_courtesy01()
// check the not required courtesy clef element is there but it is not shown // check the not required courtesy clef element is there but it is not shown
clefCourt = nullptr; clefCourt = nullptr;
m = m2->prevMeasure(); m = m2->prevMeasure();
seg = m->findSegment(SegmentType::HeaderClef, m2->tick()); seg = m->findSegment(SegmentType::Clef, m2->tick());
QVERIFY2(seg, "No SegClef in measure 6."); QVERIFY2(seg, "No SegClef in measure 6.");
clefCourt = toClef(seg->element(0)); clefCourt = toClef(seg->element(0));
QVERIFY2(clefCourt, "No courtesy clef element in measure 6."); QVERIFY2(clefCourt, "No courtesy clef element in measure 6.");
@ -144,7 +144,7 @@ void TestClefCourtesy::clef_courtesy02()
// check both clef elements are there, but none is shown // check both clef elements are there, but none is shown
Clef* clefCourt = nullptr; Clef* clefCourt = nullptr;
Measure* m = m1->prevMeasure(); Measure* m = m1->prevMeasure();
Segment* seg = m->findSegment(SegmentType::HeaderClef, m1->tick()); Segment* seg = m->findSegment(SegmentType::Clef, m1->tick());
QVERIFY2(seg != nullptr, "No SegClef in measure 3."); QVERIFY2(seg != nullptr, "No SegClef in measure 3.");
clefCourt = toClef(seg->element(0)); clefCourt = toClef(seg->element(0));
QVERIFY2(clefCourt != nullptr, "No courtesy clef element in measure 3."); QVERIFY2(clefCourt != nullptr, "No courtesy clef element in measure 3.");
@ -152,7 +152,7 @@ void TestClefCourtesy::clef_courtesy02()
clefCourt = nullptr; clefCourt = nullptr;
m = m2->prevMeasure(); m = m2->prevMeasure();
seg = m->findSegment(SegmentType::HeaderClef, m2->tick()); seg = m->findSegment(SegmentType::Clef, m2->tick());
QVERIFY2(seg != nullptr, "No SegClef in measure 6."); QVERIFY2(seg != nullptr, "No SegClef in measure 6.");
clefCourt = static_cast<Clef*>(seg->element(0)); clefCourt = static_cast<Clef*>(seg->element(0));
QVERIFY2(clefCourt != nullptr, "No courtesy clef element in measure 6."); QVERIFY2(clefCourt != nullptr, "No courtesy clef element in measure 6.");
@ -188,7 +188,7 @@ void TestClefCourtesy::clef_courtesy03()
// verify the not required courtesy clef element is on end of m1 but is not shown // verify the not required courtesy clef element is on end of m1 but is not shown
Clef *clefCourt = nullptr; Clef *clefCourt = nullptr;
Segment *seg = m1->findSegment(SegmentType::HeaderClef, m2->tick()); Segment *seg = m1->findSegment(SegmentType::Clef, m2->tick());
QVERIFY2(seg != nullptr, "No SegClef in measure 1."); QVERIFY2(seg != nullptr, "No SegClef in measure 1.");
clefCourt = static_cast<Clef*>(seg->element(0)); clefCourt = static_cast<Clef*>(seg->element(0));
QVERIFY2(clefCourt != nullptr, "No courtesy clef element in measure 1."); QVERIFY2(clefCourt != nullptr, "No courtesy clef element in measure 1.");