Skip to content

Commit

Permalink
fix #40686: handling of voice of explode/implode
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcSabatella committed Dec 4, 2014
1 parent a68454e commit 651d3c8
Show file tree
Hide file tree
Showing 5 changed files with 1,240 additions and 8 deletions.
43 changes: 35 additions & 8 deletions libmscore/cmd.cpp
Expand Up @@ -2442,20 +2442,23 @@ void Score::cmdExplode()
int n = 0;
for (Segment* s = startSegment; s && s != endSegment; s = s->next1()) {
Element* e = s->element(srcTrack);
if (e->type() == Element::Type::CHORD) {
if (e && e->type() == Element::Type::CHORD) {
Chord* c = static_cast<Chord*>(e);
n = qMax(n, c->notes().size());
}
}
lastStaff = qMin(nstaves(), srcStaff + n);
}

// make our own copy of selection, since pasting modifies actual selection
Selection srcSelection(selection());

// copy to all destination staves
for (int i = 1; srcStaff + i < lastStaff; ++i) {
int track = (srcStaff + i) * VOICES;
ChordRest* cr = startMeasure->findChordRest(0, track);
if (cr) {
XmlReader e(selection().mimeData());
XmlReader e(srcSelection.mimeData());
e.setPasteMode(true);
if (!pasteStaff(e, cr->segment(), cr->staffIdx()))
qDebug("explode: paste failed");
Expand Down Expand Up @@ -2495,6 +2498,7 @@ void Score::cmdExplode()
//---------------------------------------------------------
// cmdImplode
/// implodes contents of selected staves into top staff
/// for single staff, merge voices
//---------------------------------------------------------

void Score::cmdImplode()
Expand All @@ -2503,9 +2507,20 @@ void Score::cmdImplode()
return;

int dstStaff = selection().staffStart();
int lastStaff = selection().staffEnd();
if (dstStaff == lastStaff - 1)
return;
int endStaff = selection().staffEnd();
int startTrack = dstStaff * VOICES;
int endTrack;
int trackInc;
// if single staff selected, combine voices
// otherwise combine staves
if (dstStaff == endStaff - 1) {
endTrack = startTrack + VOICES;
trackInc = 1;
}
else {
endTrack = endStaff * VOICES;
trackInc = VOICES;
}

Segment* startSegment = selection().startSegment();
Segment* endSegment = selection().endSegment();
Expand All @@ -2528,9 +2543,9 @@ void Score::cmdImplode()
break;
}
}
// loop through each subsequent staff looking for notes to add
for (int i = 1; dstStaff + i < lastStaff; ++i) {
int srcTrack = (dstStaff + i) * VOICES;
// loop through each subsequent staff (or track within staff)
// looking for notes to add
for (int srcTrack = startTrack + trackInc; srcTrack < endTrack; srcTrack += trackInc) {
Element* src = s->element(srcTrack);
if (src && src->type() == Element::Type::CHORD) {
Chord* srcChord = static_cast<Chord*>(src);
Expand Down Expand Up @@ -2558,6 +2573,18 @@ void Score::cmdImplode()
}
}
}
// delete chordrest from source track if possible
if (src && src->voice())
undoRemoveElement(src);
}
}
else if (trackInc == 1) {
// destination track has either a rest or nothing
// either way, remove everything from other voices if in "voice mode"
for (int i = 1; i < VOICES; ++i) {
Element* e = s->element(dstTrack + i);
if (e)
undoRemoveElement(e);
}
}
}
Expand Down
30 changes: 30 additions & 0 deletions mtest/libmscore/tools/tst_tools.cpp
Expand Up @@ -32,6 +32,7 @@ class TestTools : public QObject, public MTest
void initTestCase();
void undoExplode();
void undoImplode();
void undoImplodeVoice();
void undoSlashFill();
void undoSlashRhythm();
};
Expand Down Expand Up @@ -107,6 +108,35 @@ void TestTools::undoImplode()
delete score;
}

void TestTools::undoImplodeVoice()
{
QString readFile(DIR + "undoImplodeVoice.mscx");
QString writeFile1("undoImplodeVoice01-test.mscx");
QString reference1(DIR + "undoImplodeVoice01-ref.mscx");
QString writeFile2("undoImplodeVoice02-test.mscx");
QString reference2(DIR + "undoImplodeVoice02-ref.mscx");

Score* score = readScore(readFile);
score->doLayout();

// select all
score->startCmd();
score->cmdSelectAll();
score->endCmd();

// do
score->startCmd();
score->cmdImplode();
score->endCmd();
QVERIFY(saveCompareScore(score, writeFile1, reference1));

// undo
score->undo()->undo();
QVERIFY(saveCompareScore(score, writeFile2, reference2));

delete score;
}

void TestTools::undoSlashFill()
{
QString readFile(DIR + "undoSlashFill.mscx");
Expand Down

0 comments on commit 651d3c8

Please sign in to comment.