diff --git a/libmscore/paste.cpp b/libmscore/paste.cpp index e9af8af8203c..48a8dd889525 100644 --- a/libmscore/paste.cpp +++ b/libmscore/paste.cpp @@ -562,13 +562,30 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t, const Interval& src { Fraction tick(t); // qDebug("pasteChordRest %s at %d, len %d/%d", cr->name(), tick, cr->ticks().numerator(), cr->ticks().denominator() ); - if (cr->isChord()) - transposeChord(toChord(cr), srcTranspose, tick); Measure* measure = tick2measure(tick); if (!measure) return; + int twoNoteTremoloFactor = 1; + if (cr->isChord()) { + transposeChord(toChord(cr), srcTranspose, tick); + if (toChord(cr)->tremolo() && toChord(cr)->tremolo()->twoNotes()) + twoNoteTremoloFactor = 2; + else if (cr->durationTypeTicks() == (cr->actualTicks() * 2)) { + // this could be the 2nd note of a two-note tremolo + // check previous CR on same track, if it has a two-note tremolo, then set twoNoteTremoloFactor to 2 + Segment* seg = measure->undoGetSegment(SegmentType::ChordRest, tick); + ChordRest* crt = seg->nextChordRest(cr->track(), true); + if (crt && crt->isChord()) { + Chord* chrt = toChord(crt); + Tremolo* tr = chrt->tremolo(); + if (tr && tr->twoNotes()) + twoNoteTremoloFactor = 2; + } + } + } + // we can paste a measure rest as such only at start of measure // and only if the lengths of the rest and measure match // otherwise, we need to convert to duration rest(s) @@ -584,7 +601,7 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t, const Interval& src if (cr->isRepeatMeasure()) partialCopy = toRepeatMeasure(cr)->actualTicks() != measure->ticks(); else if (!isGrace && !cr->tuplet()) - partialCopy = cr->durationTypeTicks() != cr->actualTicks(); + partialCopy = cr->durationTypeTicks() != (cr->actualTicks() * twoNoteTremoloFactor); // if note is too long to fit in measure, split it up with a tie across the barline // exclude tuplets from consideration diff --git a/mtest/libmscore/copypaste/copypaste_tremolo-ref.mscx b/mtest/libmscore/copypaste/copypaste_tremolo-ref.mscx new file mode 100644 index 000000000000..47fbde33421e --- /dev/null +++ b/mtest/libmscore/copypaste/copypaste_tremolo-ref.mscx @@ -0,0 +1,247 @@ + + + + + 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-paste + + + + + + G + G + + + 4 + 4 + + + quarter + + + 1 + half + 3/8 + + 72 + 14 + + + c16 + + + + 1 + half + 3/8 + + 76 + 18 + + + + + + quarter + + + quarter + + 62 + 16 + + + + quarter + + 64 + 18 + + + + quarter + + 65 + 13 + + + + + + + + 1 + quarter + + 72 + 14 + + + + eighth + + 76 + 18 + + + + half + + + + + quarter + + 62 + 16 + + + + quarter + + 64 + 18 + + + + + + + + 1 + half + 3/8 + + 72 + 14 + + + c16 + + + + 1 + half + 3/8 + + 76 + 18 + + + + quarter + + + + + quarter + + 62 + 16 + + + + quarter + + 64 + 18 + + + + quarter + + 65 + 13 + + + + + + + + measure + 4/4 + + + end + 1 + + + + + + diff --git a/mtest/libmscore/copypaste/copypaste_tremolo.mscx b/mtest/libmscore/copypaste/copypaste_tremolo.mscx new file mode 100644 index 000000000000..248d1c1ca9bf --- /dev/null +++ b/mtest/libmscore/copypaste/copypaste_tremolo.mscx @@ -0,0 +1,174 @@ + + + + + 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-paste + + + + + + G + G + + + 4 + 4 + + + quarter + + + 1 + half + 3/8 + + 72 + 14 + + + c16 + + + + 1 + half + 3/8 + + 76 + 18 + + + + + + quarter + + + quarter + + 62 + 16 + + + + quarter + + 64 + 18 + + + + quarter + + 65 + 13 + + + + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + end + 1 + + + + + + diff --git a/mtest/libmscore/copypaste/tst_copypaste.cpp b/mtest/libmscore/copypaste/tst_copypaste.cpp index d60a3d818890..f80906dbb44b 100644 --- a/mtest/libmscore/copypaste/tst_copypaste.cpp +++ b/mtest/libmscore/copypaste/tst_copypaste.cpp @@ -36,6 +36,7 @@ class TestCopyPaste : public QObject, public MTest void copypastestaff(const char*); void copypastevoice(const char*, int); void copypastetuplet(const char*); + void copypastetremolo(); private slots: void initTestCase(); @@ -72,6 +73,8 @@ class TestCopyPaste : public QObject, public MTest void copyPasteTuplet01() { copypastetuplet("01"); } void copyPasteTuplet02() { copypastetuplet("02"); } + + void copyPasteTremolo01() { copypastetremolo(); } }; //--------------------------------------------------------- @@ -409,6 +412,67 @@ void TestCopyPaste::copypastetuplet(const char* idx) delete score; } +//--------------------------------------------------------- +// copypastetremolo +// copy-paste of tremolo between two notes +//--------------------------------------------------------- + +void TestCopyPaste::copypastetremolo() + { + MasterScore* score = readScore(DIR + QString("copypaste_tremolo.mscx")); + Measure* m1 = score->firstMeasure(); + Measure* m2 = m1->nextMeasure(); + Measure* m3 = m2->nextMeasure(); + + QVERIFY(m1 != 0); + QVERIFY(m2 != 0); + QVERIFY(m3 != 0); + + // create a range selection on 2nd to 3rd beat (voice 1) of first measure + SegmentType segTypeCR = SegmentType::ChordRest; + Segment* s = m1->first(segTypeCR)->next1(segTypeCR); + score->select(static_cast(s->element(1))->notes().at(0)); + s = s->next1(segTypeCR); + score->select(s->element(1), 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 to second measure + score->select(m2->first()->element(0)); + + score->startCmd(); + score->cmdPaste(mimeData,0); + score->endCmd(); + + // create a range selection on 2nd to 4th beat (voice 0) of first measure + s = m1->first(segTypeCR)->next1(segTypeCR); + score->select(static_cast(s->element(0))->notes().at(0)); + s = s->next1(segTypeCR)->next1(segTypeCR); + score->select(s->element(0), SelectType::RANGE); + + QVERIFY(score->selection().canCopy()); + mimeType = score->selection().mimeType(); + QVERIFY(!mimeType.isEmpty()); + mimeData->setData(mimeType, score->selection().mimeData()); + QApplication::clipboard()->setMimeData(mimeData); + + //paste to third measure + score->select(m3->first()->element(0)); + + score->startCmd(); + score->cmdPaste(mimeData,0); + score->endCmd(); + + QVERIFY(saveCompareScore(score, QString("copypaste_tremolo.mscx"), + DIR + QString("copypaste_tremolo-ref.mscx"))); + delete score; + } + QTEST_MAIN(TestCopyPaste) #include "tst_copypaste.moc"