From 920a89ddd920060be544f1d6db3e5c1c58e5c62a Mon Sep 17 00:00:00 2001 From: Bartlomiej Lewandowski Date: Sun, 27 Jul 2014 11:15:46 +0200 Subject: [PATCH 1/3] fix #12960 --- libmscore/cmd.cpp | 15 ++++++++++++--- libmscore/score.h | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libmscore/cmd.cpp b/libmscore/cmd.cpp index b98d9a97bba2f..e6c0135ca2522 100644 --- a/libmscore/cmd.cpp +++ b/libmscore/cmd.cpp @@ -729,13 +729,23 @@ Fraction Score::makeGap(Segment* segment, int track, const Fraction& _sd, Tuplet bool Score::makeGap1(int tick, int staffIdx, Fraction len) { - ChordRest* cr = 0; Segment* seg = tick2segment(tick, true, Segment::Type::ChordRest); if (!seg) { qDebug("1:makeGap1: no segment at %d", tick); return false; } - int track = staffIdx * VOICES; + int strack = staffIdx * VOICES; + for (int track = strack; track < strack + 4; track++) { + bool result = makeGapVoice(seg, track, len, tick); + if(track == strack && !result) + return false; + } + return true; + } + +bool Score::makeGapVoice(Segment* seg, int track, Fraction len, int tick) + { + ChordRest* cr = 0; cr = static_cast(seg->element(track)); if (!cr) { // check if we are in the middle of a chord/rest @@ -761,7 +771,6 @@ bool Score::makeGap1(int tick, int staffIdx, Fraction len) return false; } if (seg1->element(track)) { - tick = seg1->tick(); cr = static_cast(seg1->element(track)); break; } diff --git a/libmscore/score.h b/libmscore/score.h index fe2d386d74458..bf56427b3325f 100644 --- a/libmscore/score.h +++ b/libmscore/score.h @@ -546,6 +546,7 @@ class Score : public QObject { Fraction makeGap(Segment*, int track, const Fraction&, Tuplet*, bool keepChord = false); bool makeGap1(int tick, int staffIdx, Fraction len); + bool makeGapVoice(Segment* seg, int track, Fraction len, int tick); Rest* addRest(int tick, int track, TDuration, Tuplet*); Rest* addRest(Segment* seg, int track, TDuration d, Tuplet*); From 92d1db9d8141bfecd519b390372ab879721cee1e Mon Sep 17 00:00:00 2001 From: Bartlomiej Lewandowski Date: Mon, 28 Jul 2014 13:08:14 +0200 Subject: [PATCH 2/3] Added test for paste of 2 voice --- .../libmscore/copypaste/copypaste13-ref.mscx | 221 ++++++++++++++++++ mtest/libmscore/copypaste/copypaste13.mscx | 206 ++++++++++++++++ mtest/libmscore/copypaste/tst_copypaste.cpp | 39 ++++ 3 files changed, 466 insertions(+) create mode 100644 mtest/libmscore/copypaste/copypaste13-ref.mscx create mode 100644 mtest/libmscore/copypaste/copypaste13.mscx diff --git a/mtest/libmscore/copypaste/copypaste13-ref.mscx b/mtest/libmscore/copypaste/copypaste13-ref.mscx new file mode 100644 index 0000000000000..56112c47ce718 --- /dev/null +++ b/mtest/libmscore/copypaste/copypaste13-ref.mscx @@ -0,0 +1,221 @@ + + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + + + + + + + + + voice-paste1 + + + + + + + + + + + + Standard + + + + Violin + + Violin + Vln. + Violin + 55 + 103 + 55 + 88 + + 24 + 55 + 62 + 69 + 76 + + + 100 + 100 + + + 100 + 50 + + + 100 + 100 + + + 120 + 100 + + + + + + + + + + + + + + + 10 + + + voice-paste1 + + + + + G + G + + + 0 + + + 4 + 4 + 1 + + + quarter + + 76 + 18 + + + + quarter + + 79 + 15 + + + + half + + + normal + 1 + + 0 + + 1 + half + + + 1 + half + + + + + quarter + + 72 + 14 + + + + quarter + + 76 + 18 + + + + quarter + + 79 + 15 + + + + quarter + + + normal + 1 + + 1920 + + 1 + quarter + + 1 + 64 + 18 + + + + 1 + half + + + 1 + quarter + + + + + measure + + + + normal + 1 + + + + + measure + + + + end + 1 + + + + + diff --git a/mtest/libmscore/copypaste/copypaste13.mscx b/mtest/libmscore/copypaste/copypaste13.mscx new file mode 100644 index 0000000000000..082a71f3dd4f2 --- /dev/null +++ b/mtest/libmscore/copypaste/copypaste13.mscx @@ -0,0 +1,206 @@ + + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + + + + + + + + + voice-paste1 + + + + + + + + + + + + Standard + + + + Violin + + Violin + Vln. + Violin + 55 + 103 + 55 + 88 + + 24 + 55 + 62 + 69 + 76 + + + 100 + 100 + + + 100 + 50 + + + 100 + 100 + + + 120 + 100 + + + + + + + + + + + + + + + 10 + + + voice-paste1 + + + + + G + G + + + 0 + + + 4 + 4 + 1 + + + quarter + + 76 + 18 + + + + quarter + + 79 + 15 + + + + half + + + normal + 1 + + 0 + + 1 + half + + + 1 + half + + + + + quarter + + 72 + 14 + + + + quarter + + + half + + + normal + 1 + + 1920 + + 1 + half + + 1 + 64 + 18 + + + + 1 + half + + + + + measure + + + + normal + 1 + + + + + measure + + + + end + 1 + + + + + diff --git a/mtest/libmscore/copypaste/tst_copypaste.cpp b/mtest/libmscore/copypaste/tst_copypaste.cpp index d185dd645cbf8..cc4c1a74633af 100644 --- a/mtest/libmscore/copypaste/tst_copypaste.cpp +++ b/mtest/libmscore/copypaste/tst_copypaste.cpp @@ -49,6 +49,7 @@ class TestCopyPaste : public QObject, public MTest void copypaste10() { copypaste("10"); } // two slurs void copypaste11() { copypaste("11"); } // grace notes void copypaste12() { copypaste("12"); } // voices + void copyPaste2Voice(); // voices-partial void copypastestaff50() { copypastestaff("50"); } // staff & slurs @@ -173,6 +174,44 @@ void TestCopyPaste::copyPastePartial() { delete score; } +void TestCopyPaste::copyPaste2Voice() + { + Score* score = readScore(DIR + QString("copypaste13.mscx")); + score->doLayout(); + Measure* m1 = score->firstMeasure(); + Measure* m2 = m1->nextMeasure(); + + QVERIFY(m1 != 0); + QVERIFY(m2 != 0); + + // select 2 chord rests at the start of the first measure + Segment* s = m1->first(Segment::Type::ChordRest); + score->select(static_cast(s->element(0))->notes().at(0)); + s = s->next(Segment::Type::ChordRest); + score->select(s->element(0), SelectType::RANGE); + + QVERIFY(score->selection().canCopy()); + QString mimeType = score->selection().mimeType(); + QVERIFY(!mimeType.isEmpty()); + QMimeData* mimeData = new QMimeData; + mimeData->setData(mimeType, score->selection().mimeData()); + QApplication::clipboard()->setMimeData(mimeData); + + // paste into the second CR of second measure + Segment* secondCRSeg = m2->first()->next1(Segment::Type::ChordRest); + score->select(secondCRSeg->element(0)); + + score->startCmd(); + score->cmdPaste(mimeData,0); + score->endCmd(); + + score->doLayout(); + + QVERIFY(saveCompareScore(score, QString("copypaste13.mscx"), + DIR + QString("copypaste13-ref.mscx"))); + delete score; + } + QTEST_MAIN(TestCopyPaste) #include "tst_copypaste.moc" From cf658a24b1712d5a8b161bcc6dcce0c99c66edac Mon Sep 17 00:00:00 2001 From: Bartlomiej Lewandowski Date: Mon, 28 Jul 2014 18:40:02 +0200 Subject: [PATCH 3/3] Added voice data to staff mime. Changed paste staff behavior to overwrite only the voices included in staff mime. --- libmscore/cmd.cpp | 4 +++- libmscore/paste.cpp | 3 ++- libmscore/score.h | 2 +- libmscore/select.cpp | 18 +++++++++++++++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/libmscore/cmd.cpp b/libmscore/cmd.cpp index e6c0135ca2522..623abe148fe53 100644 --- a/libmscore/cmd.cpp +++ b/libmscore/cmd.cpp @@ -727,7 +727,7 @@ Fraction Score::makeGap(Segment* segment, int track, const Fraction& _sd, Tuplet // - do not stop at measure end //--------------------------------------------------------- -bool Score::makeGap1(int tick, int staffIdx, Fraction len) +bool Score::makeGap1(int tick, int staffIdx, Fraction len, int voices) { Segment* seg = tick2segment(tick, true, Segment::Type::ChordRest); if (!seg) { @@ -736,6 +736,8 @@ bool Score::makeGap1(int tick, int staffIdx, Fraction len) } int strack = staffIdx * VOICES; for (int track = strack; track < strack + 4; track++) { + if (!(voices & (1 << (track-strack)))) + continue; bool result = makeGapVoice(seg, track, len, tick); if(track == strack && !result) return false; diff --git a/libmscore/paste.cpp b/libmscore/paste.cpp index 79c03fb79137a..3ea5e8aace2fc 100644 --- a/libmscore/paste.cpp +++ b/libmscore/paste.cpp @@ -72,6 +72,7 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int staffIdx) e.setTransposeDiatonic(0); int srcStaffIdx = e.attribute("id", "0").toInt(); + int voices = e.attribute("voices","0").toInt(); int dstStaffIdx = srcStaffIdx - srcStaffStart + dstStaffStart; if (dstStaffIdx >= nstaves()) { @@ -93,7 +94,7 @@ bool Score::pasteStaff(XmlReader& e, Segment* dst, int staffIdx) int tick = e.readInt(); e.initTick(tick); int shift = tick - tickStart; - if (makeGap && !makeGap1(dstTick + shift, dstStaffIdx, Fraction::fromTicks(tickLen - shift))) { + if (makeGap && !makeGap1(dstTick + shift, dstStaffIdx, Fraction::fromTicks(tickLen - shift), voices)) { qDebug("cannot make gap in staff %d at tick %d", dstStaffIdx, dstTick + shift); done = true; // break main loop, cannot make gap break; diff --git a/libmscore/score.h b/libmscore/score.h index bf56427b3325f..de078a1b4acfd 100644 --- a/libmscore/score.h +++ b/libmscore/score.h @@ -545,7 +545,7 @@ class Score : public QObject { void changeCRlen(ChordRest* cr, const TDuration&); Fraction makeGap(Segment*, int track, const Fraction&, Tuplet*, bool keepChord = false); - bool makeGap1(int tick, int staffIdx, Fraction len); + bool makeGap1(int tick, int staffIdx, Fraction len, int voices); bool makeGapVoice(Segment* seg, int track, Fraction len, int tick); Rest* addRest(int tick, int track, TDuration, Tuplet*); diff --git a/libmscore/select.cpp b/libmscore/select.cpp index fa80ca716af7c..456a9aaf3a74d 100644 --- a/libmscore/select.cpp +++ b/libmscore/select.cpp @@ -521,6 +521,16 @@ QByteArray Selection::mimeData() const return a; } + +bool hasElementInTrack(Segment* startSeg, Segment* endSeg, int track) + { + for (Segment* seg = startSeg; seg != endSeg; seg = seg->next1MM()) { + if (seg->element(track)) + return true; + } + return false; + } + //--------------------------------------------------------- // staffMimeData //--------------------------------------------------------- @@ -540,9 +550,15 @@ QByteArray Selection::staffMimeData() const Segment* seg2 = _endSegment; for (int staffIdx = staffStart(); staffIdx < staffEnd(); ++staffIdx) { - xml.stag(QString("Staff id=\"%1\"").arg(staffIdx)); int startTrack = staffIdx * VOICES; int endTrack = startTrack + VOICES; + + int voices = 0; + for(int voice = 0; voice < 4; voice++) { + voices |= hasElementInTrack(seg1, seg2, startTrack + voice) << voice; + } + xml.stag(QString("Staff id=\"%1\" voices=\"%2\"").arg(staffIdx).arg(voices)); + Staff* staff = score()->staff(staffIdx); Part* part = staff->part(); Interval interval = part->instr(seg1->tick())->transpose();