Skip to content

Commit

Permalink
fix #295703: Slurs to grace notes disappear after inserting bars
Browse files Browse the repository at this point in the history
Resolves: https://musescore.org/en/node/295703.

When the SPANNER_TICK property of a spanner changes, the spanner's startElement and endElement are invalidated. Usually the spanner's start and end elements can be recalculated from the SPANNER_TICK and SPANNER_TICKS properties, but since grace notes occur on the same tick as their parent notes, determining the real start and elements for grace note slurs is tricky. The solution here is to invalidate the start and end elements in an undoable manner before changing the SPANNER_TICK property of the spanner when time is added or removed before the spanner's start, and then set the start and end elements back to what they were. This required modifying Score::undoChangeSpannerElements() so that the start and end elements can be changed to or from nullptr.
  • Loading branch information
mattmcclinch committed Oct 29, 2019
1 parent ff43723 commit a37fda3
Showing 1 changed file with 29 additions and 17 deletions.
46 changes: 29 additions & 17 deletions libmscore/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4861,8 +4861,8 @@ void Score::undoChangeSpannerElements(Spanner* spanner, Element* startElement, E
{
Element* oldStartElement = spanner->startElement();
Element* oldEndElement = spanner->endElement();
int startDeltaTrack = startElement->track() - oldStartElement->track();
int endDeltaTrack = endElement->track() - oldEndElement->track();
int startDeltaTrack = startElement && oldStartElement ? startElement->track() - oldStartElement->track() : 0;
int endDeltaTrack = endElement && oldEndElement ? endElement->track() - oldEndElement->track() : 0;
// scan all spanners linked to this one
for (ScoreElement* el : spanner->linkList()) {
Spanner* sp = toSpanner(el);
Expand All @@ -4871,24 +4871,28 @@ void Score::undoChangeSpannerElements(Spanner* spanner, Element* startElement, E
// if not the current spanner, but one linked to it, determine its new start and end elements
// as modifications 'parallel' to the modifications of the current spanner's start and end elements
if (sp != spanner) {
// determine the track where to expect the 'parallel' start element
int newTrack = sp->startElement()->track() + startDeltaTrack;
// look in elements linked to new start element for an element with
// same score as linked spanner and appropriate track
for (ScoreElement* ee : startElement->linkList()) {
Element* e = toElement(ee);
if (e->score() == sp->score() && e->track() == newTrack) {
newStartElement = e;
break;
if (startElement) {
// determine the track where to expect the 'parallel' start element
int newTrack = sp->startElement() ? sp->startElement()->track() + startDeltaTrack : 0;
// look in elements linked to new start element for an element with
// same score as linked spanner and appropriate track
for (ScoreElement* ee : startElement->linkList()) {
Element* e = toElement(ee);
if (e->score() == sp->score() && e->track() == newTrack) {
newStartElement = e;
break;
}
}
}
// similarly to determine the 'parallel' end element
newTrack = sp->endElement()->track() + endDeltaTrack;
for (ScoreElement* ee : endElement->linkList()) {
Element* e = toNote(ee);
if (e->score() == sp->score() && e->track() == newTrack) {
newEndElement = e;
break;
if (endElement) {
int newTrack = sp->endElement() ? sp->endElement()->track() + endDeltaTrack : 0;
for (ScoreElement* ee : endElement->linkList()) {
Element* e = toElement(ee);
if (e->score() == sp->score() && e->track() == newTrack) {
newEndElement = e;
break;
}
}
}
}
Expand Down Expand Up @@ -5008,7 +5012,11 @@ void Score::undoInsertTime(const Fraction& tick, const Fraction& len)
// and
// +----spanner--------
// +---add---+
Element* startElement = s->startElement();
Element* endElement = s->endElement();
undoChangeSpannerElements(s, nullptr, nullptr);
s->undoChangeProperty(Pid::SPANNER_TICK, s->tick() + len);
undoChangeSpannerElements(s, startElement, endElement);
}
}
else {
Expand All @@ -5021,7 +5029,11 @@ void Score::undoInsertTime(const Fraction& tick, const Fraction& len)
Fraction t = s->tick() + len;
if (t < Fraction(0,1))
t = Fraction(0,1);
Element* startElement = s->startElement();
Element* endElement = s->endElement();
undoChangeSpannerElements(s, nullptr, nullptr);
s->undoChangeProperty(Pid::SPANNER_TICK, t);
undoChangeSpannerElements(s, startElement, endElement);
}
else if (s->tick() >= tick && s->tick2() <= tick2) {
//
Expand Down

0 comments on commit a37fda3

Please sign in to comment.