Skip to content

Commit

Permalink
fix #290096: fix parts corruption on timewise delete of individual beats
Browse files Browse the repository at this point in the history
Ensure that all operations in Score::timeDelete() act on all excerpts
rather than only on the current one.
  • Loading branch information
dmitrio95 committed Jan 23, 2020
1 parent 4af45f8 commit ea62a4a
Show file tree
Hide file tree
Showing 4 changed files with 274 additions and 21 deletions.
56 changes: 35 additions & 21 deletions libmscore/edit.cpp
Expand Up @@ -3282,9 +3282,9 @@ void Score::localTimeDelete()

void Score::timeDelete(Measure* m, Segment* startSegment, const Fraction& f)
{
Fraction tick = startSegment->rtick();
Fraction len = f;
Fraction etick = tick + len;
const Fraction tick = startSegment->rtick();
const Fraction len = f;
const Fraction etick = tick + len;

Segment* fs = m->first(CR_TYPE);

Expand Down Expand Up @@ -3336,32 +3336,46 @@ void Score::timeDelete(Measure* m, Segment* startSegment, const Fraction& f)
}
}
}
Fraction abstick = startSegment->tick();
const Fraction abstick = startSegment->tick();
undoInsertTime(abstick, -len);
undo(new InsertTime(this, abstick, -len));

Fraction updatedTick = tick;
for (Segment* s = startSegment; s; s = s->next()) {
if (s->rtick() >= etick && s->rtick() != updatedTick) {
std::vector<Segment*> emptySegments;

for (Score* score : masterScore()->scoreList()) {
Measure* localMeasure = score->tick2measure(abstick);

undo(new InsertTime(score, abstick, -len));

Fraction updatedTick = tick;
for (Segment* s = localMeasure->first(CR_TYPE); s; s = s->next()) {
if (s->rtick() < etick || s->rtick() == updatedTick)
continue;

s->undoChangeProperty(Pid::TICK, updatedTick);
updatedTick += s->ticks();
}
if (s->isChordRestType() && !s->hasElements()) {
if (Segment* ns = s->next(CR_TYPE)) {
// Move annotations from the empty segment.
// TODO: do we need to preserve annotations at all?
// Maybe only some types (Tempo etc.)?
for (Element* a : s->annotations()) {
Element* a1 = a->clone();
a1->setParent(ns);
undoRemoveElement(a);
undoAddElement(a1);
}

if (score->isMaster()) {
if (s->isChordRestType() && !s->hasElements())
emptySegments.push_back(s);
}
}

undo(new ChangeMeasureLen(localMeasure, localMeasure->ticks() - f));
}

undo(new ChangeMeasureLen(m, m->ticks() - f));
for (Segment* s : emptySegments) {
if (Segment* ns = s->next(CR_TYPE)) {
// Move annotations from the empty segment.
// TODO: do we need to preserve annotations at all?
// Maybe only some types (Tempo etc.)?
for (Element* a : s->annotations()) {
Element* a1 = a->clone();
a1->setParent(ns);
undoRemoveElement(a);
undoAddElement(a1);
}
}
}
}

//---------------------------------------------------------
Expand Down
@@ -0,0 +1,9 @@
init init/TrebleWithPart.mscx
cmd note-input
cmd escape
cmd pad-note-4
cmd del-empty-measures
cmd note-input
cmd escape
cmd time-delete
test score 290096-remove-beat-parts-corruption.mscx
@@ -0,0 +1,11 @@
init init/TrebleWithPart.mscx
cmd note-input
cmd escape
cmd pad-note-4
cmd del-empty-measures
cmd note-input
cmd escape
# In this scenario remove the second rest instead of the first one
cmd next-chord
cmd time-delete
test score 290096-remove-beat-parts-corruption.mscx
219 changes: 219 additions & 0 deletions mtest/testscript/scripts/290096-remove-beat-parts-corruption.mscx
@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="UTF-8"?>
<museScore version="3.01">
<programVersion>3.4.0</programVersion>
<programRevision>042303c</programRevision>
<Score>
<LayerTag id="0" tag="default"></LayerTag>
<currentLayer>0</currentLayer>
<Division>480</Division>
<Style>
<pageWidth>8.27</pageWidth>
<pageHeight>11.69</pageHeight>
<pagePrintableWidth>7.4826</pagePrintableWidth>
<lastSystemFillLimit>0</lastSystemFillLimit>
<Spatium>1.76389</Spatium>
</Style>
<showInvisible>1</showInvisible>
<showUnprintable>1</showUnprintable>
<showFrames>1</showFrames>
<showMargins>0</showMargins>
<metaTag name="arranger"></metaTag>
<metaTag name="composer"></metaTag>
<metaTag name="copyright"></metaTag>
<metaTag name="creationDate">2018-11-12</metaTag>
<metaTag name="lyricist"></metaTag>
<metaTag name="movementNumber"></metaTag>
<metaTag name="movementTitle"></metaTag>
<metaTag name="platform">Linux</metaTag>
<metaTag name="poet"></metaTag>
<metaTag name="source"></metaTag>
<metaTag name="translator"></metaTag>
<metaTag name="workNumber"></metaTag>
<metaTag name="workTitle">Treble</metaTag>
<Part>
<Staff id="1">
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
</Staff>
<trackName>Piano</trackName>
<Instrument>
<longName>Piano</longName>
<shortName>Pno.</shortName>
<trackName>Piano</trackName>
<minPitchP>21</minPitchP>
<maxPitchP>108</maxPitchP>
<minPitchA>21</minPitchA>
<maxPitchA>108</maxPitchA>
<instrumentId>keyboard.piano</instrumentId>
<Articulation>
<velocity>100</velocity>
<gateTime>95</gateTime>
</Articulation>
<Articulation name="staccatissimo">
<velocity>100</velocity>
<gateTime>33</gateTime>
</Articulation>
<Articulation name="staccato">
<velocity>100</velocity>
<gateTime>50</gateTime>
</Articulation>
<Articulation name="portato">
<velocity>100</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="tenuto">
<velocity>100</velocity>
<gateTime>100</gateTime>
</Articulation>
<Articulation name="marcato">
<velocity>120</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="sforzato">
<velocity>120</velocity>
<gateTime>100</gateTime>
</Articulation>
<Channel>
<program value="0"/>
<synti>Fluid</synti>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<VBox>
<height>10</height>
<linkedMain/>
<Text>
<linkedMain/>
<style>Title</style>
<text>Treble</text>
</Text>
</VBox>
<Measure len="3/4">
<voice>
<TimeSig>
<linkedMain/>
<sigN>4</sigN>
<sigD>4</sigD>
</TimeSig>
<Rest>
<linkedMain/>
<durationType>quarter</durationType>
</Rest>
<Rest>
<linkedMain/>
<durationType>half</durationType>
</Rest>
</voice>
</Measure>
</Staff>
<Score>
<LayerTag id="0" tag="default"></LayerTag>
<currentLayer>0</currentLayer>
<Division>480</Division>
<Style>
<pageWidth>8.27</pageWidth>
<pageHeight>11.69</pageHeight>
<pagePrintableWidth>7.4826</pagePrintableWidth>
<lastSystemFillLimit>0</lastSystemFillLimit>
<createMultiMeasureRests>1</createMultiMeasureRests>
<Spatium>1.76389</Spatium>
</Style>
<showInvisible>1</showInvisible>
<showUnprintable>1</showUnprintable>
<showFrames>1</showFrames>
<showMargins>0</showMargins>
<metaTag name="partName">Piano</metaTag>
<Part>
<Staff id="1">
<linkedTo>1</linkedTo>
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
</Staff>
<trackName>Piano</trackName>
<Instrument>
<longName>Piano</longName>
<shortName>Pno.</shortName>
<trackName>Piano</trackName>
<minPitchP>21</minPitchP>
<maxPitchP>108</maxPitchP>
<minPitchA>21</minPitchA>
<maxPitchA>108</maxPitchA>
<instrumentId>keyboard.piano</instrumentId>
<Articulation>
<velocity>100</velocity>
<gateTime>95</gateTime>
</Articulation>
<Articulation name="staccatissimo">
<velocity>100</velocity>
<gateTime>33</gateTime>
</Articulation>
<Articulation name="staccato">
<velocity>100</velocity>
<gateTime>50</gateTime>
</Articulation>
<Articulation name="portato">
<velocity>100</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="tenuto">
<velocity>100</velocity>
<gateTime>100</gateTime>
</Articulation>
<Articulation name="marcato">
<velocity>120</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="sforzato">
<velocity>120</velocity>
<gateTime>100</gateTime>
</Articulation>
<Channel>
<program value="0"/>
<synti>Fluid</synti>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<VBox>
<height>10</height>
<linked>
</linked>
<Text>
<linked>
</linked>
<style>Title</style>
<text>Treble</text>
</Text>
<Text>
<style>Instrument Name (Part)</style>
<text>Piano</text>
</Text>
</VBox>
<Measure len="3/4">
<voice>
<TimeSig>
<linked>
</linked>
<sigN>4</sigN>
<sigD>4</sigD>
</TimeSig>
<Rest>
<linked>
</linked>
<durationType>quarter</durationType>
</Rest>
<Rest>
<linked>
</linked>
<durationType>half</durationType>
</Rest>
</voice>
</Measure>
</Staff>
<name>Piano</name>
</Score>
</Score>
</museScore>

0 comments on commit ea62a4a

Please sign in to comment.