void TestMeasure::spanner_C() { MasterScore* score = readScore(DIR + "measure-8.mscx"); Measure* m = score->firstMeasure()->nextMeasure(); score->select(m); score->startCmd(); score->localTimeDelete(); score->endCmd(); QVERIFY(saveCompareScore(score, "measure-8.mscx", DIR + "measure-8-ref.mscx")); delete score; }
void TestInstrumentChange::testMixer() { MasterScore* score = test_pre("mixer"); Measure* m = score->firstMeasure()->nextMeasure(); Segment* s = m->first(Segment::Type::ChordRest); InstrumentChange* ic = static_cast<InstrumentChange*>(s->annotations()[0]); int idx = score->staff(0)->channel(s->tick(), 0); Channel* c = score->staff(0)->part()->instrument(s->tick())->channel(idx); MidiPatch* mp = new MidiPatch; mp->bank = 0; mp->drum = false; mp->name = "Viola"; mp->prog = 41; mp->synti = "Fluid"; score->startCmd(); ic->setXmlText("Mixer Viola"); score->undo(new ChangePatch(score, c, mp)); score->endCmd(); score->doLayout(); test_post(score, "mixer"); }
void TestMeasure::deleteLast() { MasterScore* score = readScore(DIR + "measure-10.mscx"); Measure* m = score->lastMeasure(); score->select(m); score->startCmd(); score->localTimeDelete(); score->endCmd(); QVERIFY(saveCompareScore(score, "measure-10.mscx", DIR + "measure-10-ref.mscx")); delete score; }
void TestBarline::deleteSkipBarlines() { MasterScore* score = readScore(DIR + "barlinedelete.mscx"); Measure* m1 = score->firstMeasure(); QVERIFY(m1); score->startCmd(); score->cmdSelectAll(); score->cmdDeleteSelection(); score->endCmd(); score->doLayout(); QVERIFY(saveCompareScore(score, QString("barlinedelete.mscx"), DIR + QString("barlinedelete-ref.mscx"))); delete score; }
void TestSpanners::spanners12() { MasterScore* score = readScore(DIR + "lyricsline05.mscx"); QVERIFY(score); score->doLayout(); // DELETE SECOND MEASURE AND VERIFY Measure* msr = score->firstMeasure(); QVERIFY(msr); msr = msr->nextMeasure(); QVERIFY(msr); score->startCmd(); score->select(msr); score->cmdTimeDelete(); score->endCmd(); QVERIFY(saveCompareScore(score, "lyricsline05.mscx", DIR + "lyricsline05-ref.mscx")); // UNDO AND VERIFY score->undoStack()->undo(); QVERIFY(saveCompareScore(score, "lyricsline05.mscx", DIR + "lyricsline05.mscx")); delete score; }
MasterScore* MTest::readCreatedScore(const QString& name) { MasterScore* score = new MasterScore(mscore->baseStyle()); QFileInfo fi(name); score->setName(fi.completeBaseName()); QString csl = fi.suffix().toLower(); ScoreLoad sl; Score::FileError rv; if (csl == "cap") { rv = importCapella(score, name); score->setMetaTag("originalFormat", csl); } else if (csl == "capx") { rv = importCapXml(score, name); score->setMetaTag("originalFormat", csl); } else if (csl == "ove") rv = importOve(score, name); else if (csl == "sgu") rv = importBB(score, name); else if (csl == "mscz" || csl == "mscx") rv = score->loadMsc(name, false); else if (csl == "mxl") rv = importCompressedMusicXml(score, name); #ifdef OMR else if (csl == "pdf") rv = importPdf(score, name); #endif else if (csl == "xml" || csl == "musicxml") rv = importMusicXml(score, name); else if (csl == "gp3" || csl == "gp4" || csl == "gp5" || csl == "gpx") rv = importGTP(score, name); else rv = Score::FileError::FILE_UNKNOWN_TYPE; if (rv != Score::FileError::FILE_NO_ERROR) { QWARN(qPrintable(QString("readScore: cannot load <%1> type <%2>\n").arg(name).arg(csl))); delete score; score = 0; } else { for (Score* s : score->scoreList()) s->doLayout(); } return score; }
void AlbumManager::addNewClicked() { MasterScore* score = mscore->getNewFile(); if (!score) return; delete score->movements(); MasterScore* topScore = album->front(); scoreList->blockSignals(true); topScore->addMovement(score); QString name = getScoreTitle(score); QListWidgetItem* li = new QListWidgetItem(name, scoreList); li->setFlags(Qt::ItemFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled)); scoreList->blockSignals(false); topScore->setLayoutAll(); topScore->update(); }
Score* QmlPlugin::newScore(const QString& /*name*/, const QString& /*part*/, int /*measures*/) { #if 0 // TODO if (msc->currentScore()) msc->currentScore()->endCmd(); MasterScore* score = new MasterScore(MScore::defaultStyle()); score->setName(name); score->appendPart(part); score->appendMeasures(measures); score->doLayout(); int view = msc->appendScore(score); msc->setCurrentView(0, view); qApp->processEvents(); // tell QML not to garbage collect this score QQmlEngine::setObjectOwnership(score, QQmlEngine::CppOwnership); score->startCmd(); return score; #endif return 0; }
void TestTools::undoResequencePart() { QString readFile(DIR + "undoResequencePart.mscx"); QString writeFile1("undoResequencePart01-test.mscx"); QString reference1(DIR + "undoResequencePart01-ref.mscx"); QString writeFile2("undoResequencePart02-test.mscx"); QString reference2(DIR + "undoResequencePart02-ref.mscx"); MasterScore* score = readScore(readFile); score->doLayout(); // do score->startCmd(); score->cmdResequenceRehearsalMarks(); score->endCmd(); QVERIFY(saveCompareScore(score, writeFile1, reference1)); // undo score->undoStack()->undo(); QVERIFY(saveCompareScore(score, writeFile2, reference2)); delete score; }
void TestMeasure::undoDelInitialVBox_269919() { MasterScore* score = readScore(DIR + "undoDelInitialVBox_269919.mscx"); // 1. delete initial VBox score->startCmd(); MeasureBase* initialVBox = score->measure(0); score->select(initialVBox); score->cmdDeleteSelection(); score->endCmd(); // 2. change duration of first chordrest score->startCmd(); Measure* m = score->firstMeasure(); ChordRest* cr = m->findChordRest(Fraction(0,1), 0); Fraction quarter(4, 1); score->changeCRlen(cr, quarter); score->endCmd(); // 3. Undo to restore first chordrest score->undoRedo(true, 0); // 4. Undo to restore initial VBox resulted in assert failure crash score->undoRedo(true, 0); QVERIFY(saveCompareScore(score, "undoDelInitialVBox_269919.mscx", DIR + "undoDelInitialVBox_269919-ref.mscx")); delete score; }
void TestSpanners::spanners08() { MasterScore* score = readScore(DIR + "lyricsline01.mscx"); QVERIFY(score); score->doLayout(); // verify initial LyricsLine setup System* sys = score->systems().at(0); QVERIFY(sys->spannerSegments().size() == 1); QVERIFY(score->unmanagedSpanners().size() == 1); // DELETE LYRICS Measure* msr = score->firstMeasure(); QVERIFY(msr); Segment* seg = msr->findSegment(Segment::Type::ChordRest, 0); QVERIFY(seg); Ms::Chord* chord = static_cast<Ms::Chord*>(seg->element(0)); QVERIFY(chord && chord->type() == Element::Type::CHORD); QVERIFY(chord->lyrics().size() > 0); Lyrics* lyr = chord->lyrics(0, Element::Placement::BELOW); score->startCmd(); score->undoRemoveElement(lyr); score->endCmd(); // verify setup after deletion QVERIFY(sys->spannerSegments().size() == 0); QVERIFY(score->unmanagedSpanners().size() == 0); // save and verify score after deletion QVERIFY(saveCompareScore(score, "lyricsline01.mscx", DIR + "lyricsline01-ref.mscx")); // UNDO score->undoStack()->undo(); score->doLayout(); // verify setup after undo QVERIFY(sys->spannerSegments().size() == 1); QVERIFY(score->unmanagedSpanners().size() == 1); // save and verify score after undo QVERIFY(saveCompareScore(score, "lyricsline01.mscx", DIR + "lyricsline01.mscx")); delete score; }
void TestSpanners::spanners03() { DropData dropData; Glissando* gliss; MasterScore* score = readScore(DIR + "glissando-graces01.mscx"); QVERIFY(score); score->doLayout(); // GLISSANDO FROM MAIN NOTE TO AFTER-GRACE // go to top note of first chord Measure* msr = score->firstMeasure(); QVERIFY(msr); Segment* seg = msr->findSegment(Segment::Type::ChordRest, 0); QVERIFY(seg); Ms::Chord* chord = static_cast<Ms::Chord*>(seg->element(0)); QVERIFY(chord && chord->type() == Element::Type::CHORD); Note* note = chord->upNote(); QVERIFY(note); // drop a glissando on note gliss = new Glissando(score); // create a new element each time, as drop() will eventually delete it dropData.pos = note->pagePos(); dropData.element = gliss; note->drop(dropData); // GLISSANDO FROM AFTER-GRACE TO BEFORE-GRACE OF NEXT CHORD // go to last after-grace of chord and drop a glissando on it Ms::Chord* grace = chord->graceNotesAfter().last(); QVERIFY(grace && grace->type() == Element::Type::CHORD); note = grace->upNote(); QVERIFY(note); gliss = new Glissando(score); dropData.pos = note->pagePos(); dropData.element = gliss; note->drop(dropData); // GLISSANDO FROM MAIN NOTE TO BEFORE-GRACE OF NEXT CHORD // go to next chord seg = seg->nextCR(0); QVERIFY(seg); chord = static_cast<Ms::Chord*>(seg->element(0)); QVERIFY(chord && chord->type() == Element::Type::CHORD); note = chord->upNote(); QVERIFY(note); gliss = new Glissando(score); dropData.pos = note->pagePos(); dropData.element = gliss; note->drop(dropData); // GLISSANDO FROM BEFORE-GRACE TO MAIN NOTE // go to next chord seg = seg->nextCR(0); QVERIFY(seg); chord = static_cast<Ms::Chord*>(seg->element(0)); QVERIFY(chord && chord->type() == Element::Type::CHORD); // go to its last before-grace note grace = chord->graceNotesBefore().last(); QVERIFY(grace && grace->type() == Element::Type::CHORD); note = grace->upNote(); QVERIFY(note); gliss = new Glissando(score); dropData.pos = note->pagePos(); dropData.element = gliss; note->drop(dropData); QVERIFY(saveCompareScore(score, "glissando-graces01.mscx", DIR + "glissando-graces01-ref.mscx")); delete score; }
bool Score::read(XmlReader& e) { while (e.readNextStartElement()) { e.setTrack(-1); const QStringRef& tag(e.name()); if (tag == "Staff") readStaff(e); else if (tag == "Omr") { #ifdef OMR masterScore()->setOmr(new Omr(this)); masterScore()->omr()->read(e); #else e.skipCurrentElement(); #endif } else if (tag == "Audio") { _audio = new Audio; _audio->read(e); } else if (tag == "showOmr") masterScore()->setShowOmr(e.readInt()); else if (tag == "playMode") _playMode = PlayMode(e.readInt()); else if (tag == "LayerTag") { int id = e.intAttribute("id"); const QString& t = e.attribute("tag"); QString val(e.readElementText()); if (id >= 0 && id < 32) { _layerTags[id] = t; _layerTagComments[id] = val; } } else if (tag == "Layer") { Layer layer; layer.name = e.attribute("name"); layer.tags = e.attribute("mask").toUInt(); _layer.append(layer); e.readNext(); } else if (tag == "currentLayer") _currentLayer = e.readInt(); else if (tag == "Synthesizer") _synthesizerState.read(e); else if (tag == "page-offset") _pageNumberOffset = e.readInt(); else if (tag == "Division") _fileDivision = e.readInt(); else if (tag == "showInvisible") _showInvisible = e.readInt(); else if (tag == "showUnprintable") _showUnprintable = e.readInt(); else if (tag == "showFrames") _showFrames = e.readInt(); else if (tag == "showMargins") _showPageborders = e.readInt(); else if (tag == "Style") { qreal sp = style().value(Sid::spatium).toDouble(); style().load(e); // if (_layoutMode == LayoutMode::FLOAT || _layoutMode == LayoutMode::SYSTEM) { if (_layoutMode == LayoutMode::FLOAT) { // style should not change spatium in // float mode style().set(Sid::spatium, sp); } _scoreFont = ScoreFont::fontFactory(style().value(Sid::MusicalSymbolFont).toString()); } else if (tag == "copyright" || tag == "rights") { Text* text = new Text(this); text->read(e); setMetaTag("copyright", text->xmlText()); delete text; } else if (tag == "movement-number") setMetaTag("movementNumber", e.readElementText()); else if (tag == "movement-title") setMetaTag("movementTitle", e.readElementText()); else if (tag == "work-number") setMetaTag("workNumber", e.readElementText()); else if (tag == "work-title") setMetaTag("workTitle", e.readElementText()); else if (tag == "source") setMetaTag("source", e.readElementText()); else if (tag == "metaTag") { QString name = e.attribute("name"); setMetaTag(name, e.readElementText()); } else if (tag == "Part") { Part* part = new Part(this); part->read(e); _parts.push_back(part); } else if ((tag == "HairPin") || (tag == "Ottava") || (tag == "TextLine") || (tag == "Volta") || (tag == "Trill") || (tag == "Slur") || (tag == "Pedal")) { Spanner* s = toSpanner(Element::name2Element(tag, this)); s->read(e); addSpanner(s); } else if (tag == "Excerpt") { if (MScore::noExcerpts) e.skipCurrentElement(); else { if (isMaster()) { Excerpt* ex = new Excerpt(static_cast<MasterScore*>(this)); ex->read(e); excerpts().append(ex); } else { qDebug("Score::read(): part cannot have parts"); e.skipCurrentElement(); } } } else if (e.name() == "Tracklist") { int strack = e.intAttribute("sTrack", -1); int dtrack = e.intAttribute("dstTrack", -1); if (strack != -1 && dtrack != -1) e.tracks().insert(strack, dtrack); e.skipCurrentElement(); } else if (tag == "Score") { // recursion if (MScore::noExcerpts) e.skipCurrentElement(); else { e.tracks().clear(); // ??? MasterScore* m = masterScore(); Score* s = new Score(m, MScore::baseStyle()); Excerpt* ex = new Excerpt(m); ex->setPartScore(s); e.setLastMeasure(nullptr); s->read(e); ex->setTracks(e.tracks()); m->addExcerpt(ex); } } else if (tag == "name") { QString n = e.readElementText(); if (!isMaster()) //ignore the name if it's not a child score excerpt()->setTitle(n); } else if (tag == "layoutMode") { QString s = e.readElementText(); if (s == "line") _layoutMode = LayoutMode::LINE; else if (s == "system") _layoutMode = LayoutMode::SYSTEM; else qDebug("layoutMode: %s", qPrintable(s)); } else e.unknown(); } e.reconnectBrokenConnectors(); if (e.error() != QXmlStreamReader::NoError) { qDebug("%s: xml read error at line %lld col %lld: %s", qPrintable(e.getDocName()), e.lineNumber(), e.columnNumber(), e.name().toUtf8().data()); MScore::lastError = QObject::tr("XML read error at line %1, column %2: %3").arg(e.lineNumber()).arg(e.columnNumber()).arg(e.name().toString()); return false; } connectTies(); _fileDivision = MScore::division; #if 0 // TODO:barline // // sanity check for barLineSpan // for (Staff* st : staves()) { int barLineSpan = st->barLineSpan(); int idx = st->idx(); int n = nstaves(); if (idx + barLineSpan > n) { qDebug("bad span: idx %d span %d staves %d", idx, barLineSpan, n); // span until last staff barLineSpan = n - idx; st->setBarLineSpan(barLineSpan); } else if (idx == 0 && barLineSpan == 0) { qDebug("bad span: idx %d span %d staves %d", idx, barLineSpan, n); // span from the first staff until the start of the next span barLineSpan = 1; for (int i = 1; i < n; ++i) { if (staff(i)->barLineSpan() == 0) ++barLineSpan; else break; } st->setBarLineSpan(barLineSpan); } // check spanFrom int minBarLineFrom = st->lines(0) == 1 ? BARLINE_SPAN_1LINESTAFF_FROM : MIN_BARLINE_SPAN_FROMTO; if (st->barLineFrom() < minBarLineFrom) st->setBarLineFrom(minBarLineFrom); if (st->barLineFrom() > st->lines(0) * 2) st->setBarLineFrom(st->lines(0) * 2); // check spanTo Staff* stTo = st->barLineSpan() <= 1 ? st : staff(idx + st->barLineSpan() - 1); // 1-line staves have special bar line spans int maxBarLineTo = stTo->lines(0) == 1 ? BARLINE_SPAN_1LINESTAFF_TO : stTo->lines(0) * 2; if (st->barLineTo() < MIN_BARLINE_SPAN_FROMTO) st->setBarLineTo(MIN_BARLINE_SPAN_FROMTO); if (st->barLineTo() > maxBarLineTo) st->setBarLineTo(maxBarLineTo); // on single staff span, check spanFrom and spanTo are distant enough if (st->barLineSpan() == 1) { if (st->barLineTo() - st->barLineFrom() < MIN_BARLINE_FROMTO_DIST) { st->setBarLineFrom(0); st->setBarLineTo(0); } } } #endif if (!masterScore()->omr()) masterScore()->setShowOmr(false); fixTicks(); masterScore()->rebuildMidiMapping(); masterScore()->updateChannel(); // createPlayEvents(); return true; }
void TestMeasure::gap() { MasterScore* score = readScore(DIR + "gaps.mscx"); Element* tst = 0; //Select and delete third quarter rest in first Measure (voice 2) score->startCmd(); Measure* m = score->firstMeasure(); Segment* s = m->undoGetSegment(Segment::Type::ChordRest, 960); Element* el = s->element(1); score->select(el); score->cmdDeleteSelection(); score->endCmd(); tst = s->element(1); Q_ASSERT(tst); QVERIFY(tst->isRest() && toRest(tst)->isGap() /*&& toRest(tst)->durationType() == TDuration::DurationType::V_QUARTER*/); //Select and delete second quarter rest in third Measure (voice 4) score->startCmd(); m = m->nextMeasure()->nextMeasure(); s = m->undoGetSegment(Segment::Type::ChordRest, 4320); el = s->element(3); score->select(el); score->cmdDeleteSelection(); score->endCmd(); tst = s->element(3); Q_ASSERT(tst); QVERIFY(tst->isRest() && toRest(tst)->isGap() /*&& toRest(tst)->durationType() == TDuration::DurationType::V_QUARTER*/); //Select and delete first quarter rest in third Measure (voice 4) score->startCmd(); s = m->undoGetSegment(Segment::Type::ChordRest, 3840); el = s->element(3); score->select(el); score->cmdDeleteSelection(); score->endCmd(); tst = s->element(3); Q_ASSERT(tst); QVERIFY(tst->isRest() && toRest(tst)->isGap() && toRest(tst)->actualTicks() == 960/*&& toRest(tst)->durationType() == TDuration::DurationType::V_HALF*/); delete score; }
void TestMeasure::insertBfKeyChange() { MasterScore* score = readScore(DIR + "measure-insert_bf_key.mscx"); // 4th measure Measure* m = score->firstMeasure()->nextMeasure(); m = m->nextMeasure()->nextMeasure(); score->startCmd(); score->insertMeasure(ElementType::MEASURE, m); score->endCmd(); QVERIFY(score->checkKeys()); QVERIFY(saveCompareScore(score, "measure-insert_bf_key.mscx", DIR + "measure-insert_bf_key-ref.mscx")); score->undoRedo(true); QVERIFY(score->checkKeys()); QVERIFY(saveCompareScore(score, "measure-insert_bf_key_undo.mscx", DIR + "measure-insert_bf_key.mscx")); m = score->firstMeasure()->nextMeasure()->nextMeasure()->nextMeasure()->nextMeasure()->nextMeasure(); score->startCmd(); score->insertMeasure(ElementType::MEASURE, m); score->endCmd(); QVERIFY(score->checkKeys()); QVERIFY(saveCompareScore(score, "measure-insert_bf_key-2.mscx", DIR + "measure-insert_bf_key-2-ref.mscx")); score->undoRedo(true); QVERIFY(score->checkKeys()); QVERIFY(saveCompareScore(score, "measure-insert_bf_key_undo.mscx", DIR + "measure-insert_bf_key.mscx")); delete score; }
void MuseScore::editInstrList() { if (cs == 0) return; if (!instrList) instrList = new InstrumentsDialog(this); else if (instrList->isVisible()) { instrList->done(0); return; } instrList->init(); MasterScore* masterScore = cs->masterScore(); instrList->genPartList(masterScore); masterScore->startCmd(); masterScore->deselectAll(); int rv = instrList->exec(); if (rv == 0) { masterScore->endCmd(); return; } ScoreView* csv = currentScoreView(); if (csv && csv->noteEntryMode()) { csv->cmd(getAction("escape")); qApp->processEvents(); updateInputState(csv->score()); } masterScore->inputState().setTrack(-1); // keep the keylist of the first pitched staff to apply it to new ones KeyList tmpKeymap; Staff* firstStaff = 0; for (Staff* s : masterScore->staves()) { KeyList* km = s->keyList(); if (!s->isDrumStaff(Fraction(0,1))) { // TODO tmpKeymap.insert(km->begin(), km->end()); firstStaff = s; break; } } Key normalizedC = Key::C; // normalize the keyevents to concert pitch if necessary if (firstStaff && !masterScore->styleB(Sid::concertPitch) && firstStaff->part()->instrument()->transpose().chromatic ) { int interval = firstStaff->part()->instrument()->transpose().chromatic; normalizedC = transposeKey(normalizedC, interval); for (auto i = tmpKeymap.begin(); i != tmpKeymap.end(); ++i) { int tick = i->first; Key oKey = i->second.key(); tmpKeymap[tick].setKey(transposeKey(oKey, interval)); } } // create initial keyevent for transposing instrument if necessary auto i = tmpKeymap.begin(); if (i == tmpKeymap.end() || i->first != 0) tmpKeymap[0].setKey(normalizedC); // // process modified partitur list // QTreeWidget* pl = instrList->partiturList(); Part* part = 0; int staffIdx = 0; QTreeWidgetItem* item = 0; for (int idx = 0; (item = pl->topLevelItem(idx)); ++idx) { PartListItem* pli = static_cast<PartListItem*>(item); // check if the part contains any remaining staves // mark to remove part if not QTreeWidgetItem* ci = 0; int staves = 0; for (int cidx = 0; (ci = pli->child(cidx)); ++cidx) { StaffListItem* sli = static_cast<StaffListItem*>(ci); if (sli->op() != ListItemOp::I_DELETE) ++staves; } if (staves == 0) pli->op = ListItemOp::I_DELETE; } item = 0; for (int idx = 0; (item = pl->topLevelItem(idx)); ++idx) { int rstaff = 0; PartListItem* pli = static_cast<PartListItem*>(item); if (pli->op == ListItemOp::I_DELETE) masterScore->cmdRemovePart(pli->part); else if (pli->op == ListItemOp::ADD) { const InstrumentTemplate* t = ((PartListItem*)item)->it; part = new Part(masterScore); part->initFromInstrTemplate(t); masterScore->undo(new InsertPart(part, staffIdx)); pli->part = part; QList<Staff*> linked; for (int cidx = 0; pli->child(cidx); ++cidx) { StaffListItem* sli = static_cast<StaffListItem*>(pli->child(cidx)); Staff* staff = new Staff(masterScore); staff->setPart(part); sli->setStaff(staff); staff->init(t, sli->staffType(), cidx); staff->setDefaultClefType(sli->defaultClefType()); if (staffIdx > 0) staff->setBarLineSpan(masterScore->staff(staffIdx - 1)->barLineSpan()); masterScore->undoInsertStaff(staff, cidx); ++staffIdx; Staff* linkedStaff = part->staves()->front(); if (sli->linked() && linkedStaff != staff) { Excerpt::cloneStaff(linkedStaff, staff); linked.append(staff); } } //insert keysigs int sidx = masterScore->staffIdx(part); int eidx = sidx + part->nstaves(); if (firstStaff) masterScore->adjustKeySigs(sidx, eidx, tmpKeymap); } else { part = pli->part; if (part->show() != pli->visible()) part->undoChangeProperty(Pid::VISIBLE, pli->visible()); for (int cidx = 0; pli->child(cidx); ++cidx) { StaffListItem* sli = static_cast<StaffListItem*>(pli->child(cidx)); if (sli->op() == ListItemOp::I_DELETE) { Staff* staff = sli->staff(); int sidx = staff->idx(); masterScore->cmdRemoveStaff(sidx); } else if (sli->op() == ListItemOp::ADD) { Staff* staff = new Staff(masterScore); staff->setPart(part); staff->initFromStaffType(sli->staffType()); sli->setStaff(staff); staff->setDefaultClefType(sli->defaultClefType()); if (staffIdx > 0) staff->setBarLineSpan(masterScore->staff(staffIdx - 1)->barLineSpan()); KeySigEvent ke; if (part->staves()->empty()) ke.setKey(Key::C); else ke = part->staff(0)->keySigEvent(Fraction(0,1)); staff->setKey(Fraction(0,1), ke); Staff* linkedStaff = 0; if (sli->linked()) { if (rstaff > 0) linkedStaff = part->staves()->front(); else { for (Staff* st : *part->staves()) { if (st != staff) { linkedStaff = st; break; } } } } if (linkedStaff) { // do not create a link if linkedStaff will be removed, for (int k = 0; pli->child(k); ++k) { StaffListItem* li = static_cast<StaffListItem*>(pli->child(k)); if (li->op() == ListItemOp::I_DELETE && li->staff() == linkedStaff) { linkedStaff = 0; break; } } } masterScore->undoInsertStaff(staff, rstaff, linkedStaff == 0); if (linkedStaff) Excerpt::cloneStaff(linkedStaff, staff); else { if (firstStaff) masterScore->adjustKeySigs(staffIdx, staffIdx+1, tmpKeymap); } ++staffIdx; ++rstaff; } else if (sli->op() == ListItemOp::UPDATE) { // check changes in staff type Staff* staff = sli->staff(); const StaffType* stfType = sli->staffType(); // use selected staff type if (stfType->name() != staff->staffType(Fraction(0,1))->name()) masterScore->undo(new ChangeStaffType(staff, *stfType)); } else { ++staffIdx; ++rstaff; } } } } // // sort staves // QList<Staff*> dst; for (int idx = 0; idx < pl->topLevelItemCount(); ++idx) { PartListItem* pli = (PartListItem*)pl->topLevelItem(idx); if (pli->op == ListItemOp::I_DELETE) continue; QTreeWidgetItem* ci = 0; for (int cidx = 0; (ci = pli->child(cidx)); ++cidx) { StaffListItem* sli = (StaffListItem*) ci; if (sli->op() == ListItemOp::I_DELETE) continue; dst.push_back(sli->staff()); } } QList<int> dl; int idx2 = 0; bool sort = false; for (Staff* staff : dst) { int idx = masterScore->staves().indexOf(staff); if (idx == -1) qDebug("staff in dialog(%p) not found in score", staff); else dl.push_back(idx); if (idx != idx2) sort = true; ++idx2; } if (sort) masterScore->undo(new SortStaves(masterScore, dl)); // // check for valid barLineSpan and bracketSpan // in all staves // for (Score* s : masterScore->scoreList()) { int n = s->nstaves(); int curSpan = 0; for (int j = 0; j < n; ++j) { Staff* staff = s->staff(j); int span = staff->barLineSpan(); int setSpan = -1; // determine if we need to update barline span if (curSpan == 0) { // no current span; this staff must start a new one if (span == 0) { // no span; this staff must have been within a span // update it to a span of 1 setSpan = j; } else if (span > (n - j)) { // span too big; staves must have been removed // reduce span to last staff setSpan = n - j; } else if (span > 1 && staff->barLineTo() > 0) { // TODO: check if span is still valid // (true if the last staff is the same as it was before this edit) // the code here fixes https://musescore.org/en/node/41786 // but by forcing an update, // we lose custom modifications to staff barLineTo // at least this happens only for span > 1, and not for Mensurstrich (barLineTo<=0) setSpan = span; // force update to pick up new barLineTo value } else { // this staff starts a span curSpan = span; } } else if (span && staff->barLineTo() > 0) { // within a current span; staff must have span of 0 // except for Mensurstrich (barLineTo<=0) // for consistency with Barline::endEdit, // don't special case 1-line staves //TODO s->undoChangeBarLineSpan(staff, 0, 0, (staff->lines() - 1) * 2); } // update barline span if necessary if (setSpan > 0) { // this staff starts a span curSpan = setSpan; // calculate spanFrom and spanTo values // int spanFrom = staff->lines() == 1 ? BARLINE_SPAN_1LINESTAFF_FROM : 0; // int linesTo = masterScore->staff(i + setSpan - 1)->lines(); // int spanTo = linesTo == 1 ? BARLINE_SPAN_1LINESTAFF_TO : (linesTo - 1) * 2; //TODO s->undoChangeBarLineSpan(staff, setSpan, spanFrom, spanTo); } // count off one from barline span --curSpan; // update brackets for (BracketItem* bi : staff->brackets()) { if ((bi->bracketSpan() > (n - j))) bi->undoChangeProperty(Pid::BRACKET_SPAN, n - j); } } } // // there should be at least one measure // if (masterScore->measures()->size() == 0) masterScore->insertMeasure(ElementType::MEASURE, 0, false); const QList<Excerpt*> excerpts(masterScore->excerpts()); // excerpts list may change in the loop below for (Excerpt* excerpt : excerpts) { QList<Staff*> sl = excerpt->partScore()->staves(); QMultiMap<int, int> tr = excerpt->tracks(); if (sl.size() == 0) masterScore->undo(new RemoveExcerpt(excerpt)); else { for (Staff* s : sl) { const LinkedElements* sll = s->links(); for (auto le : *sll) { Staff* ss = toStaff(le); if (ss->primaryStaff()) { for (int j = s->idx() * VOICES; j < (s->idx() + 1) * VOICES; j++) { int strack = tr.key(j, -1); if (strack != -1 && ((strack & ~3) == ss->idx())) break; else if (strack != -1) tr.insert(ss->idx() + strack % VOICES, tr.value(strack, -1)); } } } } } } masterScore->setLayoutAll(); masterScore->endCmd(); masterScore->rebuildAndUpdateExpressive(MuseScore::synthesizer("Fluid")); seq->initInstruments(); }
void AlbumManager::itemChanged(QListWidgetItem* item) { int row = scoreList->row(item); MasterScore* ms = *(album->begin() + row); ms->undo(new ChangeMetaText(ms, "movementTitle", item->text())); }
void TestLinks::test5LinkedParts_94911() { MCursor c; c.setTimeSig(Fraction(4,4)); c.createScore("test"); c.addPart("electric-guitar"); c.move(0, 0); // move to track 0 tick 0 c.addKeySig(Key(1)); c.addTimeSig(Fraction(4,4)); c.addChord(60, TDuration(TDuration::DurationType::V_WHOLE)); MasterScore* score = c.score(); score->addText("title", "Title"); score->doLayout(); // delete chord Measure* m = score->firstMeasure(); Segment* s = m->first(Segment::Type::ChordRest); Element* e = s->element(0); QVERIFY(e->type() == ElementType::CHORD); score->select(e); score->cmdDeleteSelection(); e = s->element(0); QVERIFY(e->type() == ElementType::REST); QVERIFY(e->links() == nullptr); // create parts// score->startCmd(); QList<Part*> parts; parts.append(score->parts().at(0)); Score* nscore = new Score(score); Excerpt ex(score); ex.setPartScore(nscore); ex.setTitle("Guitar"); ex.setParts(parts); Excerpt::createExcerpt(&ex); QVERIFY(nscore); score->undo(new AddExcerpt(&ex)); score->endCmd(); // we should have now 1 staff and 2 linked rests QVERIFY(score->staves().size() == 1); e = s->element(0); QVERIFY(e->type() == ElementType::REST); QVERIFY(e->links()->size() == 2); // add a linked staff score->startCmd(); Staff* oStaff = score->staff(0); Staff* staff = new Staff(score); staff->setPart(oStaff->part()); score->undoInsertStaff(staff, 1); Excerpt::cloneStaff(oStaff, staff); score->endCmd(); // we should have now 2 staves and 3 linked rests QCOMPARE(score->staves().size(), 2); QCOMPARE(nscore->staves().size(), 1); QVERIFY(score->staves()[0]->linkedStaves()->staves().size() == 3); e = s->element(0); QVERIFY(e->type() == ElementType::REST); QVERIFY(e->links()->size() == 3); e = s->element(4); QVERIFY(e->type() == ElementType::REST); QVERIFY(e->links()->size() == 3); QVERIFY(score->excerpts().size() == 1); // undo score->undoStack()->undo(); // we should have now 1 staves and 2 linked rests QVERIFY(score->staves().size() == 1); QVERIFY(score->staves()[0]->linkedStaves()->staves().size() == 2); e = s->element(0); QVERIFY(e->type() == ElementType::REST); QVERIFY(e->links()->size() == 2); QVERIFY(score->excerpts().size() == 1); // redo score->undoStack()->redo(); // we should have now 2 staves and 3 linked rests QVERIFY(score->staves().size() == 2); QVERIFY(score->staves()[0]->linkedStaves()->staves().size() == 3); e = s->element(0); QVERIFY(e->type() == ElementType::REST); QVERIFY(e->links()->size() == 3); e = s->element(4); QVERIFY(e->type() == ElementType::REST); QVERIFY(e->links()->size() == 3); QVERIFY(score->excerpts().size() == 1); }
void TestNote::noteLimits() { MasterScore* score = readScore(DIR + "empty.mscx"); score->inputState().setTrack(0); score->inputState().setSegment(score->tick2segment(0, false, Segment::Type::ChordRest)); score->inputState().setDuration(TDuration::DurationType::V_QUARTER); score->inputState().setNoteEntryMode(true); // over 127 shouldn't crash score->cmdAddPitch(140, false, false); // below 0 shouldn't crash score->cmdAddPitch(-40, false, false); // stack chords score->cmdAddPitch(42, false, false); for (int i = 1; i < 20; i++) score->cmdAddPitch(42 + i * 7, true, false); // interval below score->cmdAddPitch(42, false, false); for (int i = 0; i < 20; i++) { std::vector<Note*> nl = score->selection().noteList(); score->cmdAddInterval(-8, nl); } // interval above score->cmdAddPitch(42, false, false); for (int i = 0; i < 20; i++) { std::vector<Note*> nl = score->selection().noteList(); score->cmdAddInterval(8, nl); } QVERIFY(saveCompareScore(score, "notelimits-test.mscx", DIR + "notelimits-ref.mscx")); }
void TestNote::tpcTranspose() { MasterScore* score = readScore(DIR + "tpc-transpose.mscx"); score->startCmd(); Measure* m = score->firstMeasure(); score->select(m, SelectType::SINGLE, 0); score->changeAccidental(AccidentalType::FLAT); score->endCmd(); score->startCmd(); m = m->nextMeasure(); score->select(m, SelectType::SINGLE, 0); score->upDown(false, UpDownMode::CHROMATIC); score->endCmd(); score->startCmd(); score->cmdConcertPitchChanged(true, true); score->endCmd(); QVERIFY(saveCompareScore(score, "tpc-transpose-test.mscx", DIR + "tpc-transpose-ref.mscx")); }
void TestNote::tpc() { MasterScore* score = readScore(DIR + "tpc.mscx"); score->inputState().setTrack(0); score->inputState().setSegment(score->tick2segment(0, false, Segment::Type::ChordRest)); score->inputState().setDuration(TDuration::DurationType::V_QUARTER); score->inputState().setNoteEntryMode(true); int octave = 5 * 7; score->cmdAddPitch(octave + 1, false, false); score->cmdAddPitch(octave + 2, false, false); score->cmdAddPitch(octave + 3, false, false); score->cmdAddPitch(octave + 4, false, false); score->cmdAddPitch(octave + 5, false, false); score->cmdAddPitch(octave + 6, false, false); score->cmdAddPitch(octave + 7, false, false); score->cmdAddPitch(octave + 8, false, false); score->cmdConcertPitchChanged(true, true); QVERIFY(saveCompareScore(score, "tpc-test.mscx", DIR + "tpc-ref.mscx")); }
void TestNote::grace() { MasterScore* score = readScore(DIR + "grace.mscx"); score->doLayout(); Ms::Chord* chord = score->firstMeasure()->findChord(0, 0); Note* note = chord->upNote(); // create score->setGraceNote(chord, note->pitch(), NoteType::APPOGGIATURA, MScore::division/2); Ms::Chord* gc = chord->graceNotes().first(); Note* gn = gc->notes().front(); // Note* n = static_cast<Note*>(writeReadElement(gn)); // QCOMPARE(n->noteType(), NoteType::APPOGGIATURA); // delete n; // tie score->select(gn); score->cmdAddTie(); // n = static_cast<Note*>(writeReadElement(gn)); // QVERIFY(n->tieFor() != 0); // delete n; // tremolo score->startCmd(); Tremolo* tr = new Tremolo(score); tr->setTremoloType(TremoloType::R16); tr->setParent(gc); tr->setTrack(gc->track()); score->undoAddElement(tr); score->endCmd(); // Ms::Chord* c = static_cast<Ms::Chord*>(writeReadElement(gc)); // QVERIFY(c->tremolo() != 0); // delete c; // articulation score->startCmd(); Articulation* ar = new Articulation(SymId::articAccentAbove, score); ar->setParent(gc); ar->setTrack(gc->track()); score->undoAddElement(ar); score->endCmd(); // c = static_cast<Ms::Chord*>(writeReadElement(gc)); // QVERIFY(c->articulations().size() == 1); // delete c; QVERIFY(saveCompareScore(score, "grace-test.mscx", DIR + "grace-ref.mscx")); }