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);
ClefType stype = clef->clefType();
if (clefType() != stype) {
score()->undoChangeClef(staff(), segment(), stype);
score()->undoChangeClef(staff(), this, stype);
c = this;
}
}

View file

@ -2415,7 +2415,7 @@ void Score::cmdInsertClef(ClefType type)
{
if (!noteEntryMode())
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)
{
undoChangeClef(cr->staff(), cr->segment(), clef->clefType());
undoChangeClef(cr->staff(), cr, clef->clefType());
delete clef;
}

View file

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

View file

@ -106,8 +106,18 @@ void KeySig::layout()
// determine current clef for this staff
ClefType clef = ClefType::G;
if (staff())
clef = staff()->clef(tick());
if (staff()) {
// 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 t1 = int(_sig.key());

View file

@ -1433,7 +1433,7 @@ Element* Measure::drop(EditData& data)
return 0;
case ElementType::CLEF:
score()->undoChangeClef(staff, first(), toClef(e)->clefType());
score()->undoChangeClef(staff, this, toClef(e)->clefType());
delete e;
break;
@ -3673,7 +3673,17 @@ void Measure::addSystemHeader(bool isFirstSystem)
}
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;
if (!cSegment) {
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)) {
// then convert that generated clef into a real non-generated clef
// 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 undoChangeUserMirror(Note*, MScore::DirectionH);
void undoChangeKeySig(Staff* ostaff, int tick, KeySigEvent);
void undoChangeClef(Staff* ostaff, Segment*, ClefType st);
bool undoPropertyChanged(Element* e, Pid t, const QVariant& st, PropertyFlags ps = PropertyFlags::NOSTYLE);
void undoChangeClef(Staff* ostaff, Element* e, ClefType ct);
bool undoPropertyChanged(Element*, Pid, const QVariant& v, PropertyFlags ps = PropertyFlags::NOSTYLE);
void undoPropertyChanged(ScoreElement*, Pid, const QVariant& v, PropertyFlags ps = PropertyFlags::NOSTYLE);
inline virtual UndoStack* undoStack() const;
void undo(UndoCommand*, EditData* = 0) const;

View file

@ -391,8 +391,10 @@ void Staff::setClef(Clef* clef)
if (clef->generated())
return;
int tick = clef->segment()->tick();
for (Segment* s = clef->segment()->next(); s && s->tick() == tick; s = s->next()) {
if (s->segmentType() == SegmentType::Clef && s->element(clef->track())) {
for (Segment* s = clef->segment()->next1(); s && s->tick() == tick; s = s->next1()) {
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
return;
}
@ -411,15 +413,17 @@ void Staff::removeClef(Clef* clef)
if (clef->generated())
return;
int tick = clef->segment()->tick();
for (Segment* s = clef->segment()->next(); s && s->tick() == tick; s = s->next()) {
if (s->segmentType() == SegmentType::Clef && s->element(clef->track())) {
for (Segment* s = clef->segment()->next1(); s && s->tick() == tick; s = s->next1()) {
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
return;
}
}
clefs.erase(clef->segment()->tick());
for (Segment* s = clef->segment()->prev(); s && s->tick() == tick; s = s->prev()) {
if (s->segmentType() == SegmentType::Clef
for (Segment* s = clef->segment()->prev1(); s && s->tick() == tick; s = s->prev1()) {
if ((s->segmentType() == SegmentType::Clef || s->segmentType() == SegmentType::HeaderClef)
&& s->element(clef->track())
&& !s->element(clef->track())->generated()) {
// 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
Clef* clefCourt = 0;
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.");
clefCourt = static_cast<Clef*>(seg->element(0));
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
clefCourt = nullptr;
m = m2->prevMeasure();
seg = m->findSegment(SegmentType::HeaderClef, m2->tick());
seg = m->findSegment(SegmentType::Clef, m2->tick());
QVERIFY2(seg, "No SegClef in measure 6.");
clefCourt = toClef(seg->element(0));
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
Clef* clefCourt = nullptr;
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.");
clefCourt = toClef(seg->element(0));
QVERIFY2(clefCourt != nullptr, "No courtesy clef element in measure 3.");
@ -152,7 +152,7 @@ void TestClefCourtesy::clef_courtesy02()
clefCourt = nullptr;
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.");
clefCourt = static_cast<Clef*>(seg->element(0));
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
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.");
clefCourt = static_cast<Clef*>(seg->element(0));
QVERIFY2(clefCourt != nullptr, "No courtesy clef element in measure 1.");