diff --git a/libmscore/cmd.cpp b/libmscore/cmd.cpp index f790f613147f..6e9f37cfaab5 100644 --- a/libmscore/cmd.cpp +++ b/libmscore/cmd.cpp @@ -15,65 +15,56 @@ Handling of several GUI commands. */ -#include - -#include "types.h" -#include "musescoreCore.h" -#include "score.h" -#include "utils.h" -#include "key.h" +#include "accidental.h" +#include "articulation.h" +#include "barline.h" +#include "beam.h" +#include "box.h" +#include "chord.h" +#include "chordlist.h" #include "clef.h" +#include "drumset.h" +#include "dynamic.h" +#include "hairpin.h" +#include "harmony.h" +#include "key.h" +#include "keysig.h" +#include "lyrics.h" +#include "measure.h" +#include "mscore.h" +#include "musescoreCore.h" #include "navigate.h" -#include "slur.h" -#include "tie.h" #include "note.h" +#include "noteevent.h" +#include "ottava.h" +#include "page.h" +#include "part.h" +#include "pitchspelling.h" +#include "rehearsalmark.h" +#include "repeat.h" #include "rest.h" -#include "chord.h" -#include "text.h" +#include "score.h" +#include "segment.h" +#include "sequencer.h" #include "sig.h" +#include "slur.h" #include "staff.h" -#include "part.h" +#include "stafftype.h" +#include "stringdata.h" #include "style.h" -#include "page.h" -#include "barline.h" -#include "tuplet.h" -#include "xml.h" -#include "ottava.h" -#include "trill.h" -#include "pedal.h" -#include "hairpin.h" #include "textline.h" -#include "keysig.h" -#include "volta.h" -#include "dynamic.h" -#include "box.h" -#include "harmony.h" +#include "sym.h" #include "system.h" -#include "stafftext.h" -#include "articulation.h" -#include "layoutbreak.h" -#include "drumset.h" -#include "beam.h" -#include "lyrics.h" -#include "pitchspelling.h" -#include "measure.h" -#include "tempo.h" -#include "undo.h" +#include "tie.h" #include "timesig.h" -#include "repeat.h" -#include "tempotext.h" -#include "noteevent.h" -#include "breath.h" -#include "stringdata.h" -#include "stafftype.h" -#include "segment.h" -#include "chordlist.h" -#include "mscore.h" -#include "accidental.h" -#include "sequencer.h" #include "tremolo.h" -#include "rehearsalmark.h" -#include "sym.h" +#include "trill.h" +#include "tuplet.h" +#include "types.h" +#include "undo.h" +#include "utils.h" +#include "volta.h" +#include "xml.h" namespace Ms { @@ -1382,10 +1373,16 @@ void Score::changeCRlen(ChordRest* cr, const Fraction& dstF, bool fillWithRest) Fraction f = dstF; ChordRest* cr1 = cr; Chord* oc = 0; + Segment* s = cr->segment(); bool first = true; Fraction totalLen = cr->rtick() + f; - for (Fraction f2 : qAsConst(flist)) { + for (const Fraction& f2 : flist) { + if (!cr1) { + expandVoice(s, track); + cr1 = toChordRest(s->element(track)); + } + f -= f2; if (totalLen.reduced() > Fraction(1, 1)) { if (auto nm = cr1->measure()->nextMeasure()) { @@ -1469,11 +1466,11 @@ void Score::changeCRlen(ChordRest* cr, const Fraction& dstF, bool fillWithRest) } } } - Measure* m = cr1->measure(); - Measure* m1 = m->nextMeasure(); + const Measure* m = cr1->measure(); + const Measure* m1 = m->nextMeasure(); if (!m1) break; - Segment* s = m1->first(SegmentType::ChordRest); + s = m1->first(SegmentType::ChordRest); cr1 = toChordRest(s->element(track)); if (!cr1) break; diff --git a/libmscore/edit.cpp b/libmscore/edit.cpp index 257e488304a0..c68da09c1886 100644 --- a/libmscore/edit.cpp +++ b/libmscore/edit.cpp @@ -214,6 +214,7 @@ Chord* Score::addChord(const Fraction& tick, TDuration d, Chord* oc, bool genTie chord->setTrack(oc->track()); chord->setDurationType(d); chord->setTicks(d.fraction()); + chord->setStemDirection(oc->stemDirection()); for (Note* n : oc->notes()) { Note* nn = new Note(this); diff --git a/libmscore/note.cpp b/libmscore/note.cpp index 071093d626b2..e7f3aa3de54c 100644 --- a/libmscore/note.cpp +++ b/libmscore/note.cpp @@ -1858,6 +1858,7 @@ Element* Note::drop(EditData& data) { // calculate correct transposed tpc Note* n = toNote(e); + const Segment* segment = ch->segment(); Interval v = part()->instrument(ch->tick())->transpose(); v.flip(); n->setTpc2(Ms::transposeTpc(n->tpc1(), v, true)); @@ -1868,6 +1869,15 @@ Element* Note::drop(EditData& data) n->tieBack()->setEndNote(n); this->setTieBack(nullptr); } + // Set correct stem direction for drum staves + const StaffGroup staffGroup = st->staffType(segment->tick())->group(); + Direction stemDirection = Direction::AUTO; + if (staffGroup == StaffGroup::PERCUSSION) { + const Drumset* ds = st->part()->instrument(segment->tick())->drumset(); + stemDirection = ds->stemDirection(n->noteVal().pitch); + } + ch->setStemDirection(stemDirection); + score()->undoRemoveElement(this); score()->undoAddElement(n); return n; diff --git a/libmscore/paste.cpp b/libmscore/paste.cpp index 8ea9afcd5639..ccdb150a27d9 100644 --- a/libmscore/paste.cpp +++ b/libmscore/paste.cpp @@ -10,32 +10,30 @@ // the file LICENCE.GPL //============================================================================= -#include "score.h" - -#include "rest.h" -#include "staff.h" -#include "measure.h" -#include "harmony.h" -#include "fret.h" -#include "breath.h" +#include "articulation.h" #include "beam.h" +#include "breath.h" +#include "chord.h" +#include "drumset.h" #include "figuredbass.h" -#include "ottava.h" -#include "part.h" -#include "lyrics.h" +#include "fret.h" #include "hairpin.h" +#include "harmony.h" +#include "image.h" +#include "lyrics.h" +#include "measure.h" +#include "part.h" +#include "repeat.h" +#include "rest.h" +#include "score.h" +#include "sig.h" +#include "staff.h" #include "tie.h" #include "timesig.h" +#include "tremolo.h" #include "tuplet.h" #include "utils.h" #include "xml.h" -#include "image.h" -#include "repeat.h" -#include "chord.h" -#include "tremolo.h" -#include "slur.h" -#include "articulation.h" -#include "sig.h" namespace Ms { @@ -1011,8 +1009,17 @@ static Note* prepareTarget(ChordRest* target, Note* with, const Fraction& durati Measure* m = segment->measure()->mmRestFirst(); segment = m->findSegment(SegmentType::ChordRest, m->tick()); } + + const Staff* staff = target->staff(); + const StaffGroup staffGroup = staff->staffType(segment->tick())->group(); + Direction stemDirection = Direction::AUTO; + if (staffGroup == StaffGroup::PERCUSSION) { + const Drumset* ds = staff->part()->instrument(segment->tick())->drumset(); + stemDirection = ds->stemDirection(with->noteVal().pitch); + } + segment = target->score()->setNoteRest(segment, target->track(), - with->noteVal(), duration, Direction::AUTO, false, false, &target->score()->inputState()); + with->noteVal(), duration, stemDirection, false, false, &target->score()->inputState()); return toChord(segment->nextChordRest(target->track()))->upNote(); } diff --git a/libmscore/sym.cpp b/libmscore/sym.cpp index 3727cef56271..5693e9e460af 100644 --- a/libmscore/sym.cpp +++ b/libmscore/sym.cpp @@ -10,15 +10,15 @@ // the file LICENCE.GPL //============================================================================= +#include + +#include "mscore.h" +#include "score.h" #include "style.h" #include "sym.h" -#include "utils.h" -#include "score.h" -#include "xml.h" -#include "mscore.h" + #include "mscore/preferences.h" -#include #include FT_GLYPH_H #include FT_IMAGE_H @@ -6655,7 +6655,7 @@ void ScoreFont::scanUserFonts(const QString& path, bool system) } - qDebug() << "Found" << userfonts.count() << (system ? "system" : "user") << "score fonts in" << path <<"."; + qDebug() << "Found" << userfonts.count() << (system ? "system" : "user") << "score font" << (userfonts.count() > 1? "s" : "") << " in" << path <<"."; // TODO: Check for fonts that duplicate built-in fonts if (!system) // reset list when re-reading due to changed Preferences diff --git a/mtest/libmscore/copypaste/copypasteNote12-ref.mscx b/mtest/libmscore/copypaste/copypasteNote12-ref.mscx new file mode 100644 index 000000000000..b3c47bf02fc4 --- /dev/null +++ b/mtest/libmscore/copypaste/copypasteNote12-ref.mscx @@ -0,0 +1,191 @@ + + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + Composer / arranger + + + + + + + + Subtitle + + + Untitled score + + Orchestra + + Drums + +
+ flutes + oboes + clarinets + saxophones + bassoons + +
+
+ horns + trumpets + cornets + flugelhorns + trombones + baritone-horns + euphoniums + tubas +
+
+ timpani +
+
+ keyboard-percussion + drums + unpitched-metal-percussion + unpitched-wooden-percussion + other-percussion +
+ keyboards + harps + organs + synths +
+ plucked-strings +
+ +
+ voices +
+
+ orchestral-strings +
+ +
+ + + + perc1Line + 1 + 0 + + PERC + + Snare Drum + + Snare Drum + SD + Snare Drum + drum.snare-drum + 1 + + cross + 0 + 0 + Side Stick + 1 + A + + + normal + 0 + 0 + Snare + 1 + B + + PERC + + + + + + + + + + 10 + + + Test + + + + Copy-Paste + + + + + + 1 + none + + + 4 + 4 + + + quarter + up + + 38 + 16 + + + + quarter + + + half + + + + + + + quarter + up + + 38 + 16 + + + + quarter + + + half + + + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + +
+
diff --git a/mtest/libmscore/copypaste/copypasteNote12.mscx b/mtest/libmscore/copypaste/copypasteNote12.mscx new file mode 100644 index 000000000000..a707e0962666 --- /dev/null +++ b/mtest/libmscore/copypaste/copypasteNote12.mscx @@ -0,0 +1,196 @@ + + + 3.6.3 + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + Composer / arranger + + 2024-04-25 + + + + Apple Macintosh + + + + Subtitle + + + Untitled score + + Orchestra + + Drums + +
+ flutes + oboes + clarinets + saxophones + bassoons + +
+
+ horns + trumpets + cornets + flugelhorns + trombones + baritone-horns + euphoniums + tubas +
+
+ timpani +
+
+ keyboard-percussion + drums + unpitched-metal-percussion + unpitched-wooden-percussion + other-percussion +
+ keyboards + harps + organs + synths +
+ plucked-strings +
+ +
+ voices +
+
+ orchestral-strings +
+ +
+ + + + perc1Line + 1 + 0 + + PERC + + Snare Drum + + Snare Drum + SD + Snare Drum + drum.snare-drum + 1 + + cross + 0 + 0 + Side Stick + 1 + A + + + normal + 0 + 0 + Snare + 1 + B + + PERC + + + + + + + + + + 10 + + + Test + + + + Copy-Paste + + + + + + 1 + none + + + 4 + 4 + + + quarter + down + + 37 + 21 + cross + + + + quarter + + + half + + + + + + + quarter + up + + 38 + 16 + + + + quarter + + + half + + + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + +
+
diff --git a/mtest/libmscore/copypaste/copypasteSplit04-ref.mscx b/mtest/libmscore/copypaste/copypasteSplit04-ref.mscx new file mode 100644 index 000000000000..c888edc73af4 --- /dev/null +++ b/mtest/libmscore/copypaste/copypasteSplit04-ref.mscx @@ -0,0 +1,223 @@ + + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + Composer / arranger + + + + + + + + Subtitle + + + Untitled score + + Orchestra + + Drums + +
+ flutes + oboes + clarinets + saxophones + bassoons + +
+
+ horns + trumpets + cornets + flugelhorns + trombones + baritone-horns + euphoniums + tubas +
+
+ timpani +
+
+ keyboard-percussion + drums + unpitched-metal-percussion + unpitched-wooden-percussion + other-percussion +
+ keyboards + harps + organs + synths +
+ plucked-strings +
+ +
+ voices +
+
+ orchestral-strings +
+ +
+ + + + perc1Line + 1 + 0 + + PERC + + Snare Drum + + Snare Drum + SD + Snare Drum + drum.snare-drum + 1 + + cross + 0 + 0 + Side Stick + 1 + A + + + normal + 0 + 0 + Snare + 1 + B + + PERC + + + + + Fluid + + + + + + 10 + + + Test + + + + Copy-Paste + + + + + + 1 + none + + + 4 + 4 + + + half + + + quarter + + + eighth + + + eighth + up + + + + + + + 1 + -7/8 + + + + 38 + 16 + + + + + + + + + + eighth + up + + + + + -1 + 7/8 + + + + 38 + 16 + + + + eighth + up + + 38 + 16 + + + + quarter + + + half + + + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + +
+
diff --git a/mtest/libmscore/copypaste/copypasteSplit04.mscx b/mtest/libmscore/copypaste/copypasteSplit04.mscx new file mode 100644 index 000000000000..dd5fd7667167 --- /dev/null +++ b/mtest/libmscore/copypaste/copypasteSplit04.mscx @@ -0,0 +1,193 @@ + + + 4.4.0 + + + 480 + 1 + 1 + 1 + 0 + 1 + + + Composer / arranger + + 2024-04-25 + + + + Apple Macintosh + + + Subtitle + + + Untitled score + + Orchestra + + Drums + +
+ flutes + oboes + clarinets + saxophones + bassoons + +
+
+ horns + trumpets + cornets + flugelhorns + trombones + tubas + +
+
+ timpani +
+
+ keyboard-percussion + + drums + unpitched-metal-percussion + unpitched-wooden-percussion + other-percussion + +
+ keyboards + harps + organs + synths + + +
+ voices + voice-groups +
+
+ orchestral-strings +
+
+ + + + perc1Line + 1 + 0 + + PERC + + Snare Drum + + Snare Drum + SD + Snare Drum + drum.snare-drum + 1 + + cross + 0 + 0 + Side Stick + 1 + A + + + normal + 0 + 0 + Snare + 1 + B + + PERC + + + + + Fluid + + + + + + 10 + + + Test + + + + Copy-Paste + + + + + + 1 + none + + + 4 + 4 + + + half + + + quarter + + + eighth + + + eighth + + 37 + 21 + cross + + + + + + + + quarter + up + + 38 + 16 + + + + quarter + + + half + + + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + +
+
diff --git a/mtest/libmscore/copypaste/tst_copypaste.cpp b/mtest/libmscore/copypaste/tst_copypaste.cpp index 6d481cfbc37a..1978e16aedf3 100644 --- a/mtest/libmscore/copypaste/tst_copypaste.cpp +++ b/mtest/libmscore/copypaste/tst_copypaste.cpp @@ -11,14 +11,16 @@ //============================================================================= #include -#include "mtest/testutils.h" -#include "libmscore/score.h" + +#include "libmscore/chord.h" +#include "libmscore/chordrest.h" +#include "libmscore/durationtype.h" #include "libmscore/measure.h" +#include "libmscore/score.h" #include "libmscore/segment.h" -#include "libmscore/chordrest.h" -#include "libmscore/chord.h" #include "libmscore/xml.h" -#include "libmscore/durationtype.h" + +#include "mtest/testutils.h" #define DIR QString("libmscore/copypaste/") @@ -36,6 +38,7 @@ class TestCopyPaste : public QObject, public MTest void copypastestaff(const char*); void copypastevoice(const char*, int); void copypastetuplet(const char*); + void copypasteSplitNoteOverBarDrumStave(); void copypastetremolo(); void copypastenote(const QString&, Fraction = Fraction(1, 1)); @@ -86,6 +89,7 @@ class TestCopyPaste : public QObject, public MTest void copypasteQtrNoteIntoChord() { copypastenote("09"); } void copypasteQtrNoteOntoMMRest() { copypastenote("10"); } void copypasteQtrNoteDoubleDuration() { copypastenote("11", Fraction(2, 1)); } + void copyPasteNoteDrumStaff() { copypastenote("12"); } void copyPasteTremolo01() { copypastetremolo(); } }; @@ -130,7 +134,7 @@ void TestCopyPaste::copypaste(const char* idx) score->select(m4->first()->element(0)); score->startCmd(); - score->cmdPaste(mimeData,0); + score->cmdPaste(mimeData, 0); score->endCmd(); QVERIFY(saveCompareScore(score, QString("copypaste%1.mscx").arg(idx), @@ -165,7 +169,7 @@ void TestCopyPaste::copypastestaff(const char* idx) score->select(m2, SelectType::RANGE, 1); score->startCmd(); - score->cmdPaste(mimeData,0); + score->cmdPaste(mimeData, 0); score->endCmd(); QVERIFY(saveCompareScore(score, QString("copypaste%1.mscx").arg(idx), @@ -195,7 +199,7 @@ void TestCopyPaste::copyPastePartial() score->select(m1->first(SegmentType::ChordRest)->element(0)); score->startCmd(); - score->cmdPaste(mimeData,0); + score->cmdPaste(mimeData, 0); score->endCmd(); QVERIFY(saveCompareScore(score, QString("copypaste_partial_01.mscx"), @@ -230,7 +234,7 @@ void TestCopyPaste::copyPaste2Voice() score->select(secondCRSeg->element(0)); score->startCmd(); - score->cmdPaste(mimeData,0); + score->cmdPaste(mimeData, 0); score->endCmd(); QVERIFY(saveCompareScore(score, QString("copypaste13.mscx"), @@ -270,7 +274,7 @@ void TestCopyPaste::copypastevoice(const char* idx, int voice) score->select(m2->first()->element(0)); score->startCmd(); - score->cmdPaste(mimeData,0); + score->cmdPaste(mimeData, 0); score->endCmd(); QVERIFY(saveCompareScore(score, QString("copypaste%1.mscx").arg(idx), @@ -308,7 +312,7 @@ void TestCopyPaste::copyPaste2Voice5() score->select(dest); score->startCmd(); - score->cmdPaste(mimeData,0); + score->cmdPaste(mimeData, 0); score->endCmd(); QVERIFY(saveCompareScore(score, QString("copypaste17.mscx"), @@ -344,7 +348,7 @@ void TestCopyPaste::copyPasteOnlySecondVoice() score->select(m2,SelectType::RANGE); score->startCmd(); - score->cmdPaste(mimeData,0); + score->cmdPaste(mimeData, 0); score->endCmd(); QVERIFY(saveCompareScore(score, QString("copypaste18.mscx"), @@ -382,7 +386,7 @@ void TestCopyPaste::copypaste2Voice6() score->select(dest); score->startCmd(); - score->cmdPaste(mimeData,0); + score->cmdPaste(mimeData, 0); score->endCmd(); QVERIFY(saveCompareScore(score, QString("copypaste20.mscx"), @@ -416,7 +420,7 @@ void TestCopyPaste::copypastetuplet(const char* idx) Element* dest = m2->first(SegmentType::ChordRest)->element(0); score->select(dest); score->startCmd(); - score->cmdPaste(mimeData,0); + score->cmdPaste(mimeData, 0); score->endCmd(); QVERIFY(saveCompareScore(score, QString("copypaste_tuplet_%1.mscx").arg(idx), @@ -424,6 +428,33 @@ void TestCopyPaste::copypastetuplet(const char* idx) delete score; } +void TestCopyPaste::copypasteSplitNoteOverBarDrumStave() + { + // Copy first note m2 to last note m1 + MasterScore* score = readScore(DIR + "copypasteSplit04.mscx"); + QVERIFY(score); + + Measure* m1 = score->firstMeasure(); + Measure* m2 = m1->nextMeasure(); + + QVERIFY(m1); + QVERIFY(m2); + + Segment* s = m2->first(SegmentType::ChordRest); + score->select(toChord(s->element(0))->notes().at(0)); + QMimeData* mimeData = new QMimeData; + mimeData->setData(score->selection().mimeType(), score->selection().mimeData()); + ChordRest* cr = m1->findChordRest(Fraction(7, 8), 0); + score->select(cr->isChord() ? toChord(cr)->upNote() : static_cast(cr)); + score->startCmd(); + QApplication::clipboard()->setMimeData(mimeData); + score->cmdPaste(mimeData, 0); + score->endCmd(); + + QVERIFY(saveCompareScore(score, QString("copypasteSplit04.mscx"), + DIR + "copypasteSplit04-ref.mscx")); +} + //--------------------------------------------------------- // copypastetremolo // copy-paste of tremolo between two notes @@ -458,7 +489,7 @@ void TestCopyPaste::copypastetremolo() score->select(m2->first()->element(0)); score->startCmd(); - score->cmdPaste(mimeData,0); + score->cmdPaste(mimeData, 0); score->endCmd(); // create a range selection on 2nd to 4th beat (voice 0) of first measure @@ -477,7 +508,7 @@ void TestCopyPaste::copypastetremolo() score->select(m3->first()->element(0)); score->startCmd(); - score->cmdPaste(mimeData,0); + score->cmdPaste(mimeData, 0); score->endCmd(); QVERIFY(saveCompareScore(score, QString("copypaste_tremolo.mscx"), @@ -488,8 +519,14 @@ void TestCopyPaste::copypastetremolo() void TestCopyPaste::copypastenote(const QString& idx, Fraction scale) { score = readScore(DIR + "copypasteNote" + idx + ".mscx"); + QVERIFY(score); + Measure* m1 = score->firstMeasure(); Measure* m2 = m1->nextMeasure(); + + QVERIFY(m1); + QVERIFY(m2); + Segment* s = m2->first(SegmentType::ChordRest); score->select(toChord(s->element(0))->notes().at(0)); QMimeData mimeData;