void TestMeasure::checkMeasure() { MasterScore* score = readScore(DIR + "checkMeasure.mscx"); Element* tst = 0; Measure* m = score->firstMeasure()->nextMeasure(); Segment* s = m->undoGetSegment(Segment::Type::ChordRest, 2880); tst = s->element(1); Q_ASSERT(tst); QVERIFY(tst->isRest() && toRest(tst)->isGap() && toRest(tst)->actualTicks() == 480/*&& toRest(tst)->durationType() == TDuration::DurationType::V_HALF*/); m = m->nextMeasure(); // s = m->undoGetSegment(Segment::Type::ChordRest, 3840); // tst = s->element(2); // Q_ASSERT(tst); // QVERIFY(tst->isRest() && toRest(tst)->isGap() && toRest(tst)->actualTicks() == 480/*&& toRest(tst)->durationType() == TDuration::DurationType::V_HALF*/); m = m->nextMeasure(); s = m->undoGetSegment(Segment::Type::ChordRest, 6240); tst = s->element(1); Q_ASSERT(tst); QVERIFY(tst->isRest() && toRest(tst)->isGap() && toRest(tst)->actualTicks() == 120/*&& toRest(tst)->durationType() == TDuration::DurationType::V_HALF*/); s = m->undoGetSegment(Segment::Type::ChordRest, 6480); tst = s->element(1); Q_ASSERT(tst); QVERIFY(tst->isRest() && toRest(tst)->isGap() && toRest(tst)->actualTicks() == 120/*&& toRest(tst)->durationType() == TDuration::DurationType::V_HALF*/); delete score; }
Element* Clef::drop(const DropData& data) { Element* e = data.element; Clef* c = 0; if (e->isClef()) { Clef* clef = toClef(e); ClefType stype = clef->clefType(); if (clefType() != stype) { score()->undoChangeClef(staff(), segment(), stype); c = this; } } else if (e->isAmbitus()) { /*if (!generated())*/ { Measure* meas = measure(); Segment* segm = meas->getSegment(Segment::Type::Ambitus, meas->tick()); if (segm->element(track())) score()->undoRemoveElement(segm->element(track())); Ambitus* r = new Ambitus(score()); r->setParent(segm); r->setTrack(track()); score()->undoAddElement(r); } } delete e; return c; }
void TestBarline::barline04() { Score* score = readScore(DIR + "barline04.mscx"); QVERIFY(score); score->doLayout(); score->startCmd(); // 'go' to 5th measure Measure* msr = score->firstMeasure(); for (int i=0; i < 4; i++) msr = msr->nextMeasure(); // check span data of measure-initial start-repeat bar line Segment* seg = msr->findSegment(SegmentType::StartRepeatBarLine, msr->tick()); QVERIFY2(seg != nullptr, "No SegStartRepeatBarLine segment in measure 5."); BarLine* bar = static_cast<BarLine*>(seg->element(0)); QVERIFY2(bar != nullptr, "No start-repeat barline in measure 5."); bar->undoChangeProperty(Pid::BARLINE_SPAN, 2); bar->undoChangeProperty(Pid::BARLINE_SPAN_FROM, 2); bar->undoChangeProperty(Pid::BARLINE_SPAN_TO, 6); score->endCmd(); QVERIFY2(bar->spanStaff() && bar->spanFrom() == 2 && bar->spanTo() == 6, "Wrong span data in start-repeat barline of measure 5."); // check start-repeat bar ine in second staff is gone QVERIFY2(seg->element(1) == nullptr, "Extra start-repeat barline in 2nd staff of measure 5."); // QVERIFY(saveCompareScore(score, "barline04.mscx", DIR + "barline04-ref.mscx")); delete score; }
void Glissando::layout() { Chord* chord = static_cast<Chord*>(parent()); if (chord == 0) { return; } Note* anchor2 = chord->upNote(); Segment* s = chord->segment(); s = s->prev1(); while (s) { if ((s->subtype() & (Segment::SegChordRestGrace)) && s->element(track())) break; s = s->prev1(); } if (s == 0) { qDebug("no segment for first note of glissando found\n"); return; } ChordRest* cr = static_cast<ChordRest*>(s->element(track())); if (cr == 0 || cr->type() != CHORD) { qDebug("no first note for glissando found, track %d\n", track()); return; } Note* anchor1 = static_cast<Chord*>(cr)->upNote(); setPos(0.0, 0.0); QPointF cp1 = anchor1->pagePos(); QPointF cp2 = anchor2->pagePos(); // construct line from notehead to notehead qreal x1 = (anchor1->headWidth()) - (cp2.x() - cp1.x()); qreal y1 = anchor1->pos().y(); qreal x2 = anchor2->pos().x(); qreal y2 = anchor2->pos().y(); // on TAB's, adjust lower end point from string line height to base of note height (= ca. half line spacing) if (chord->staff()->isTabStaff()) { qreal yOff = chord->staff()->lineDistance() * 0.5 * spatium(); if (anchor1->pitch() > anchor2->pitch()) // descending glissando: y2 += yOff; // move ending point to base of note else // ascending glissando: y1 += yOff; // move starting point to base of note } QLineF fullLine(x1, y1, x2, y2); // shorten line on each side by offsets qreal xo = spatium() * .5; qreal yo = xo; // spatium() * .5; QPointF p1 = fullLine.pointAt(xo / fullLine.length()); QPointF p2 = fullLine.pointAt(1 - (yo / fullLine.length())); line = QLineF(p1, p2); qreal lw = spatium() * .15 * .5; QRectF r = QRectF(line.p1(), line.p2()).normalized(); setbbox(r.adjusted(-lw, -lw, lw, lw)); }
void TestClefCourtesy::clef_courtesy02() { Score* score = readScore(DIR + "clef_courtesy02.mscx"); score->doLayout(); // 'go' to 4th measure Measure* m1 = score->firstMeasure(); for (int i=0; i < 3; i++) m1 = m1->nextMeasure(); // make a clef-drop object and drop it to the measure Clef* clef = new Clef(score); // create a new element, as Measure::drop() will eventually delete it clef->setClefType(ClefType::G1); DropData dropData; dropData.pos = m1->pagePos(); dropData.element = clef; m1->drop(dropData); // 'go' to 7th measure Measure* m2 = m1; for (int i=0; i < 3; i++) m2 = m2->nextMeasure(); // make a clef-drop object and drop it to the measure clef = new Clef(score); // create a new element, as Measure::drop() will eventually delete it clef->setClefType(ClefType::G); dropData.pos = m2->pagePos(); dropData.element = clef; m2->drop(dropData); score->doLayout(); // check both clef elements are there, but none is shown Clef* clefCourt = nullptr; Measure* m = m1->prevMeasure(); Segment* seg = m->findSegment(SegmentType::Clef, m1->tick()); QVERIFY2(seg != nullptr, "No SegClef in measure 3."); clefCourt = static_cast<Clef*>(seg->element(0)); QVERIFY2(clefCourt != nullptr, "No courtesy clef element in measure 3."); QVERIFY2(clefCourt->bbox().width() == 0, "Courtesy clef in measure 3 is NOT hidden."); clefCourt = nullptr; m = m2->prevMeasure(); seg = m->findSegment(SegmentType::Clef, m2->tick()); QVERIFY2(seg != nullptr, "No SegClef in measure 6."); clefCourt = static_cast<Clef*>(seg->element(0)); QVERIFY2(clefCourt != nullptr, "No courtesy clef element in measure 6."); QVERIFY2(clefCourt->bbox().width() == 0, "Courtesy clef in measure 3 is NOT hidden."); QVERIFY(saveCompareScore(score, "clef_courtesy02.mscx", DIR + "clef_courtesy02-ref.mscx")); delete score; }
Segment* InputState::nextInputPos() const { Measure* m = _segment->measure(); Segment* s = _segment->next1(Segment::Type::ChordRest); for (; s; s = s->next1(Segment::Type::ChordRest)) { if (s->element(_track) || s->measure() != m) { if (s->element(_track)) { if (s->element(_track)->isRest() && toRest(s->element(_track))->isGap()) continue; } return s; } } return 0; }
void Glissando::layout() { Chord* chord = static_cast<Chord*>(parent()); if (chord == 0) { return; } Note* anchor2 = chord->upNote(); Segment* s = chord->segment(); s = s->prev1(); while (s) { if ((s->subtype() == SegChordRest || s->subtype() == SegGrace) && s->element(track())) break; s = s->prev1(); } if (s == 0) { qDebug("no segment for first note of glissando found\n"); return; } ChordRest* cr = static_cast<ChordRest*>(s->element(track())); if (cr == 0 || cr->type() != CHORD) { qDebug("no first note for glissando found, track %d\n", track()); return; } Note* anchor1 = static_cast<Chord*>(cr)->upNote(); setPos(0.0, 0.0); QPointF cp1 = anchor1->pagePos(); QPointF cp2 = anchor2->pagePos(); // construct line from notehead to notehead qreal x1 = (anchor1->headWidth()) - (cp2.x() - cp1.x()); qreal y1 = anchor1->pos().y(); qreal x2 = anchor2->pos().x(); qreal y2 = anchor2->pos().y(); QLineF fullLine(x1, y1, x2, y2); // shorten line on each side by offsets qreal xo = spatium() * .5; qreal yo = xo; // spatium() * .5; QPointF p1 = fullLine.pointAt(xo / fullLine.length()); QPointF p2 = fullLine.pointAt(1 - (yo / fullLine.length())); line = QLineF(p1, p2); qreal lw = spatium() * .15 * .5; QRectF r = QRectF(line.p1(), line.p2()).normalized(); setbbox(r.adjusted(-lw, -lw, lw, lw)); }
Clef* Clef::otherClef() { // if not in a clef-segment-measure hierarchy, do nothing if (!parent() || !parent()->isSegment()) return nullptr; Segment* segm = toSegment(parent()); int segmTick = segm->tick(); if (!segm->parent() || !segm->parent()->isMeasure()) return nullptr; Measure* meas = toMeasure(segm->parent()); Measure* otherMeas = nullptr; Segment* otherSegm = nullptr; if (segmTick == meas->tick()) // if clef segm is measure-initial otherMeas = meas->prevMeasure(); // look for a previous measure else if (segmTick == meas->tick() + meas->ticks()) // if clef segm is measure-final otherMeas = meas->nextMeasure(); // look for a next measure if (!otherMeas) return nullptr; // look for a clef segment in the 'other' measure at the same tick of this clef segment otherSegm = otherMeas->findSegment(SegmentType::Clef | SegmentType::HeaderClef, segmTick); if (!otherSegm) return nullptr; // if any 'other' segment found, look for a clef in the same track as this return toClef(otherSegm->element(track())); }
void TestBarline::barline02() { char msg[256]; Score* score = readScore(DIR + "barline02.mscx"); QVERIFY(score); Measure* msr = score->firstMeasure()->nextMeasure(); TimeSig* ts = new TimeSig(score); ts->setSig(Fraction(3, 4), TimeSigType::NORMAL); score->cmdAddTimeSig(msr, 0, ts, false); score->doLayout(); msr = score->firstMeasure(); int msrNo = 1; while ((msr = msr->nextMeasure())) { ++msrNo; Segment* seg = msr->findSegment(SegmentType::EndBarLine, msr->tick()+msr->ticks()); sprintf(msg, "No SegEndBarLine in measure %d.", msrNo); QVERIFY2(seg != nullptr, msg); BarLine* bar = static_cast<BarLine*>(seg->element(0)); sprintf(msg, "No barline in measure %d.", msrNo); QVERIFY2(bar != nullptr, msg); // bar line should be generated if NORMAL, except the END one at the end sprintf(msg, "Barline in measure %d changed into 'non-generated'.", msrNo); // ws: end barline is also generated // bool test = (bar->barLineType() == BarLineType::NORMAL) ? bar->generated() : !bar->generated(); bool test = bar->generated(); QVERIFY2(test, msg); } // QVERIFY(saveCompareScore(score, "barline02.mscx", DIR + "barline02-ref.mscx")); delete score; }
Note* Score::upAlt(Element* element) { Element* re = 0; if (element->type() == Element::REST) { if (_is.track() <= 0) return 0; _is.setTrack(_is.track() - 1); re = searchNote(static_cast<Rest*>(element)->tick(), _is.track()); } else if (element->type() == Element::NOTE) { // find segment Chord* chord = static_cast<Note*>(element)->chord(); Segment* segment = chord->segment(); // collect all notes for this segment in noteList: QList<Note*> rnl; int tracks = nstaves() * VOICES; for (int track = 0; track < tracks; ++track) { Element* el = segment->element(track); if (!el || el->type() != Element::CHORD) continue; rnl.append(static_cast<Chord*>(el)->notes()); qSort(rnl.begin(), rnl.end(), noteLessThan); int idx = rnl.indexOf(static_cast<Note*>(element)); if (idx < rnl.size()-1) ++idx; re = rnl.value(idx); } } if (re == 0) return 0; if (re->type() == Element::CHORD) re = ((Chord*)re)->notes().front(); return (Note*)re; }
bool haveTupletsEnoughElements(const Staff *staff) { const int strack = staff->idx() * VOICES; for (int voice = 0; voice < VOICES; ++voice) { for (Segment *seg = staff->score()->firstSegment(); seg; seg = seg->next1()) { if (seg->segmentType() == Segment::Type::ChordRest) { const ChordRest *cr = static_cast<ChordRest *>(seg->element(strack + voice)); if (!cr) continue; const Tuplet *tuplet = cr->tuplet(); if (tuplet) { if (tuplet->elements().size() <= 1) { printInvalidTupletLocation(seg->measure()->no(), staff->idx()); return false; } int chordCount = 0; for (const auto &e: tuplet->elements()) { const ChordRest *cr = static_cast<ChordRest *>(e); if (cr && cr->type() == Element::Type::CHORD) ++chordCount; } if (chordCount == 0) { printInvalidTupletLocation(seg->measure()->no(), staff->idx()); return false; } } } } } return true; }
void Fermata::layout() { Segment* s = segment(); setPos(QPointF()); if (!s) { // for use in palette setOffset(0.0, 0.0); QRectF b(symBbox(_symId)); setbbox(b.translated(-0.5 * b.width(), 0.0)); return; } if (isStyled(Pid::OFFSET)) setOffset(propertyDefault(Pid::OFFSET).toPointF()); Element* e = s->element(track()); if (e) { if (e->isChord()) rxpos() += score()->noteHeadWidth() * staff()->mag(Fraction(0, 1)) * .5; else rxpos() += e->x() + e->width() * staff()->mag(Fraction(0, 1)) * .5; } QString name = Sym::id2name(_symId); if (placeAbove()) { if (name.endsWith("Below")) _symId = Sym::name2id(name.left(name.size() - 5) + "Above"); } else { rypos() += staff()->height(); if (name.endsWith("Above")) _symId = Sym::name2id(name.left(name.size() - 5) + "Below"); } QRectF b(symBbox(_symId)); setbbox(b.translated(-0.5 * b.width(), 0.0)); autoplaceSegmentElement(styleP(Sid::fermataMinDistance)); }
ChordRest* Score::nextTrack(ChordRest* cr) { if (!cr) return 0; ChordRest* el = 0; Measure* measure = cr->measure(); int track = cr->track(); int tracks = nstaves() * VOICES; while (!el) { // find next non-empty track while (++track < tracks){ if (measure->hasVoice(track)) break; } // no more tracks, return original element if (track == tracks) return cr; // find element at same or previous segment within this track for (Segment* segment = cr->segment(); segment; segment = segment->prev(Segment::Type::ChordRest)) { el = static_cast<ChordRest*>(segment->element(track)); if (el) break; } } return el; }
void Fermata::layout() { Segment* s = segment(); if (!s) { // for use in palette setPos(QPointF()); return; } qreal x = 0.0; Element* e = s->element(track()); if (e) { if (e->isChord()) x = score()->noteHeadWidth() * staff()->mag(0) * .5; else x = e->x() + e->width() * staff()->mag(0) * .5; } qreal y = placeAbove() ? styleP(Sid::fermataPosAbove) : styleP(Sid::fermataPosBelow) + staff()->height(); setPos(QPointF(x, y)); // check used symbol QString name = Sym::id2name(_symId); if (placeAbove()) { if (name.endsWith("Below")) _symId = Sym::name2id(name.left(name.size() - 5) + "Above"); } else { if (name.endsWith("Above")) _symId = Sym::name2id(name.left(name.size() - 5) + "Below"); } QRectF b(symBbox(_symId)); setbbox(b.translated(-0.5 * b.width(), 0.0)); autoplaceSegmentElement(styleP(Sid::fermataMinDistance)); }
void InspectorClef::setElement() { otherClef = nullptr; // no 'other clef' yet InspectorElementBase::setElement(); // try to locate the 'other clef' of a courtesy / main pair Clef* clef = toClef(inspector->element()); // if not in a clef-segment-measure hierarchy, do nothing if (!clef->parent() || clef->parent()->type() != ElementType::SEGMENT) return; Segment* segm = toSegment(clef->parent()); int segmTick = segm->tick(); if (!segm->parent() || segm->parent()->type() != ElementType::MEASURE) return; Measure* meas = toMeasure(segm->parent()); Measure* otherMeas = nullptr; Segment* otherSegm = nullptr; if (segmTick == meas->tick()) // if clef segm is measure-initial otherMeas = meas->prevMeasure(); // look for a previous measure else if (segmTick == meas->tick()+meas->ticks()) // if clef segm is measure-final otherMeas = meas->nextMeasure(); // look for a next measure // look for a clef segment in the 'other' measure at the same tick of this clef segment if (otherMeas) otherSegm = otherMeas->findSegment(SegmentType::Clef, segmTick); // if any 'other' segment found, look for a clef in the same track as this if (otherSegm) otherClef = toClef(otherSegm->element(clef->track())); }
void Dynamic::layout() { if (!readPos().isNull()) { if (score()->mscVersion() < 118) { setReadPos(QPointF()); // hack: 1.2 boundingBoxes are a bit wider which results // in symbols moved right setUserXoffset(userOff().x() - spatium() * .6); } } Text::layout(); Segment* s = segment(); for (int voice = 0; voice < VOICES; ++voice) { int t = (track() & ~0x3) + voice; Chord* c = static_cast<Chord*>(s->element(t)); if (!c) continue; if (c->type() == CHORD) { qreal noteHeadWidth = score()->noteHeadWidth() * c->mag(); if (c->stem() && !c->up()) // stem down rxpos() += noteHeadWidth * .25; // center on stem + optical correction else rxpos() += noteHeadWidth * .5; // center on note head } else rxpos() += c->width() * .5; break; } }
Note* searchTieNote114(Note* note) { Note* note2 = 0; Chord* chord = note->chord(); Segment* seg = chord->segment(); Part* part = chord->staff()->part(); int strack = part->staves()->front()->idx() * VOICES; int etrack = strack + part->staves()->size() * VOICES; while ((seg = seg->next1(Segment::SegChordRest))) { for (int track = strack; track < etrack; ++track) { Chord* c = static_cast<Chord*>(seg->element(track)); if (c == 0 || (c->type() != Element::CHORD) || (c->track() != chord->track())) continue; int staffIdx = c->staffIdx() + c->staffMove(); if (staffIdx != chord->staffIdx() + chord->staffMove()) // cannot happen? continue; for (Note* n : c->notes()) { if (n->pitch() == note->pitch()) { if (note2 == 0 || c->track() == chord->track()) note2 = n; } } } if (note2) break; } return note2; }
Segment* Score::tick2segmentEnd(int track, int tick) const { Measure* m = tick2measure(tick); if (m == 0) { qDebug("tick2segment(): not found tick %d\n", tick); return 0; } // loop over all segments for (Segment* segment = m->first(Segment::SegChordRest); segment; segment = segment->next(Segment::SegChordRest)) { ChordRest* cr = static_cast<ChordRest*>(segment->element(track)); if (!cr) continue; // TODO LVI: check if following is correct, see exceptions in // ExportMusicXml::chord() and ExportMusicXml::rest() int endTick = cr->tick() + cr->actualTicks(); if (endTick < tick) continue; // not found yet else if (endTick == tick) { return segment; // found it } else { // endTick > tick (beyond the tick we are looking for) return 0; } } return 0; }
void ScoreView::lyricsReturn() { Lyrics* lyrics = (Lyrics*)editObject; Segment* segment = lyrics->segment(); endEdit(); _score->startCmd(); Lyrics* oldLyrics = lyrics; lyrics = static_cast<Lyrics*>(Element::create(lyrics->type(), _score)); lyrics->setTrack(oldLyrics->track()); lyrics->setParent(segment->element(oldLyrics->track())); lyrics->setNo(oldLyrics->no() + 1); _score->undoAddElement(lyrics); _score->select(lyrics, SELECT_SINGLE, 0); startEdit(lyrics, -1); mscore->changeState(mscoreState()); adjustCanvasPosition(lyrics, false); _score->setLayoutAll(true); _score->end2(); _score->end1(); }
void detectSwing(Staff *staff, MidiOperation::Swing swingType) { Score *score = staff->score(); const int strack = staff->idx() * VOICES; SwingDetector swingDetector(swingType); for (Segment *seg = score->firstSegment(Segment::SegChordRest); seg; seg = seg->next1(Segment::SegChordRest)) { for (int voice = 0; voice < VOICES; ++voice) { ChordRest *cr = static_cast<ChordRest *>(seg->element(strack + voice)); if (!cr) continue; swingDetector.add(cr); } } if (swingDetector.wasSwingApplied()) { // add swing label to the score StaffText* st = new StaffText(score); st->setTextStyleType(TEXT_STYLE_STAFF); st->setText(swingCaption(swingType)); Segment* seg = score->firstSegment(Segment::SegChordRest); st->setParent(seg); st->setTrack(strack); // voice == 0 score->addElement(st); } }
ChordRest* Score::prevTrack(ChordRest* cr) { if (!cr) return 0; ChordRest* el = 0; Measure* measure = cr->measure(); int track = cr->track(); while (!el) { // find next non-empty track while (--track >= 0){ if (measure->hasVoice(track)) break; } // no more tracks, return original element if (track < 0) return cr; // find element at same or previous segment within this track for (Segment* segment = cr->segment(); segment != 0; segment = segment->prev(Segment::SegChordRest)) { el = static_cast<ChordRest*>(segment->element(track)); if (el) break; } } return el; }
void TestSpanners::spanners07() { DropData dropData; Glissando* gliss; MasterScore* score = readScore(DIR + "glissando-cloning04.mscx"); QVERIFY(score); score->doLayout(); // DROP A GLISSANDO ON FIRST NOTE 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); dropData.pos = note->pagePos(); dropData.element = gliss; note->drop(dropData); QVERIFY(saveCompareScore(score, "glissando-cloning04.mscx", DIR + "glissando-cloning04-ref.mscx")); delete score; }
void ScoreView::lyricsEndEdit() { Lyrics* lyrics = toLyrics(editData.element); // if not empty, make sure this new lyrics does not fall in the middle // of an existing melisma from a previous lyrics; in case, shorten it int verse = lyrics->no(); Placement placement = lyrics->placement(); int track = lyrics->track(); // search previous lyric Lyrics* prevLyrics = 0; Segment* prevSegment = lyrics->segment()->prev1(SegmentType::ChordRest); Segment* segment = prevSegment; while (segment) { ChordRest* cr = toChordRest(segment->element(track)); if (cr) { prevLyrics = cr->lyrics(verse, placement); if (prevLyrics) break; } segment = segment->prev1(SegmentType::ChordRest); } if (prevLyrics && prevLyrics->syllabic() == Lyrics::Syllabic::END) { int endTick = prevSegment->tick(); // a prev. melisma should not go beyond this segment if (prevLyrics->endTick() >= endTick) prevLyrics->undoChangeProperty(Pid::LYRIC_TICKS, endTick - prevLyrics->segment()->tick()); } }
Element* Rest::drop(const DropData& data) { Element* e = data.element; switch (e->type()) { case ARTICULATION: if (e->subtype() == Articulation_Fermata) score()->addArticulation(this, (Articulation*)e); return 0; case ICON: { switch(e->subtype()) { case ICON_SBEAM: score()->undoChangeBeamMode(this, BEAM_BEGIN); break; case ICON_MBEAM: score()->undoChangeBeamMode(this, BEAM_MID); break; case ICON_NBEAM: score()->undoChangeBeamMode(this, BEAM_NO); break; case ICON_BEAM32: score()->undoChangeBeamMode(this, BEAM_BEGIN32); break; case ICON_BEAM64: score()->undoChangeBeamMode(this, BEAM_BEGIN64); break; case ICON_AUTOBEAM: score()->undoChangeBeamMode(this, BEAM_AUTO); break; } } delete e; break; case CHORD: { Chord* c = static_cast<Chord*>(e); Note* n = c->upNote(); Direction dir = c->stemDirection(); score()->select(0, SELECT_SINGLE, 0); NoteVal nval; nval.pitch = n->pitch(); nval.headGroup = n->headGroup(); Fraction d = score()->inputState().duration().fraction(); if (!d.isZero()) { Segment* seg = score()->setNoteRest(segment(), track(), nval, d, dir); if (seg) { ChordRest* cr = static_cast<ChordRest*>(seg->element(track())); if (cr) score()->nextInputPos(cr, true); } } delete e; } break; default: return ChordRest::drop(data); } return 0; }
void TestTools::undoChangeVoice() { QString readFile(DIR + "undoChangeVoice.mscx"); QString writeFile1("undoChangeVoice01-test.mscx"); QString reference1(DIR + "undoChangeVoice01-ref.mscx"); QString writeFile2("undoChangeVoice02-test.mscx"); QString reference2(DIR + "undoChangeVoice02-ref.mscx"); Score* score = readScore(readFile); score->doLayout(); // do score->deselectAll(); // select bottom note of all voice 1 chords for (Segment* s = score->firstSegment(Segment::Type::ChordRest); s; s = s->next1()) { ChordRest* cr = static_cast<ChordRest*>(s->element(0)); if (cr && cr->type() == Element::Type::CHORD) { Ms::Chord* c = static_cast<Ms::Chord*>(cr); score->select(c->downNote(), SelectType::ADD); } } // change voice score->changeVoice(1); QVERIFY(saveCompareScore(score, writeFile1, reference1)); // undo score->undo()->undo(); QVERIFY(saveCompareScore(score, writeFile2, reference2)); delete score; }
bool areTiesConsistent(const Staff *staff) { const int strack = staff->idx() * VOICES; for (int voice = 0; voice < VOICES; ++voice) { bool isTie = false; for (Segment *seg = staff->score()->firstSegment(); seg; seg = seg->next1()) { if (seg->segmentType() == Segment::Type::ChordRest) { ChordRest *cr = static_cast<ChordRest *>(seg->element(strack + voice)); if (cr && cr->type() == Element::Type::REST && isTie) { printInconsistentTieLocation(seg->measure()->no(), staff->idx()); return false; } if (isTiedBack(seg, strack, voice)) { if (!isTie) { printInconsistentTieLocation(seg->measure()->no(), staff->idx()); return false; } isTie = false; } if (isTiedFor(seg, strack, voice)) { if (isTie) { printInconsistentTieLocation(seg->measure()->no(), staff->idx()); return false; } isTie = true; } } } if (isTie) return false; } return true; }
QPointF Pedal::linePos(GripLine grip, System** sys) const { qreal x; qreal nhw = score()->noteHeadWidth(); System* s = nullptr; if (grip == GripLine::START) { ChordRest* c = static_cast<ChordRest*>(startElement()); s = c->segment()->system(); x = c->pos().x() + c->segment()->pos().x() + c->segment()->measure()->pos().x(); if (beginHook() && beginHookType() == HookType::HOOK_45) x += nhw * .5; } else { ChordRest* c = nullptr; Element* e = endElement(); if (!e || e == startElement()) { // pedal marking on single note - extend to next note or end of measure Segment* seg = startSegment(); if (seg) { seg = seg->next(); for ( ; seg; seg = seg->next()) { if (seg->segmentType() == Segment::Type::ChordRest) { if (seg->element(track())) break; } else if (seg->segmentType() == Segment::Type::EndBarLine) { break; } } } if (seg) { s = seg->system(); x = seg->pos().x() + seg->measure()->pos().x() - nhw * 2; } } else { c = static_cast<ChordRest*>(endElement()); if (c) { s = c->segment()->system(); x = c->pos().x() + c->segment()->pos().x() + c->segment()->measure()->pos().x(); } } if (!s) { int t = tick2(); Measure* m = score()->tick2measure(t); s = m->system(); x = m->tick2pos(t); } if (endHook() && endHookType() == HookType::HOOK_45) x += nhw * .5; else x += nhw; } *sys = s; return QPointF(x, 0); }
void Ambitus::updateRange() { if (!segment()) return; Chord* chord; int firstTrack = track(); int lastTrack = firstTrack + VOICES-1; int pitchTop = -1000; int pitchBottom = 1000; int tpcTop = 0; // Initialized to prevent warning int tpcBottom = 0; // Initialized to prevent warning int trk; Measure* meas = segment()->measure(); Segment* segm = meas->findSegment(SegmentType::ChordRest, segment()->tick()); bool stop = meas->sectionBreak(); while (segm) { // moved to another measure? if (segm->measure() != meas) { // if section break has been found, stop here if (stop) break; // update meas and stop condition meas = segm->measure(); stop = meas->sectionBreak(); } // scan all relevant tracks of this segment for chords for (trk = firstTrack; trk <= lastTrack; trk++) { Element* e = segm->element(trk); if (!e || !e->isChord()) continue; chord = toChord(e); // update pitch range (with associated tpc's) for (Note* n : chord->notes()) { if (!n->play()) // skip notes which are not to be played continue; int pitch = n->ppitch(); if (pitch > pitchTop) { pitchTop = pitch; tpcTop = n->tpc(); } if (pitch < pitchBottom) { pitchBottom = pitch; tpcBottom = n->tpc(); } } } segm = segm->nextCR(); } if (pitchTop > -1000) { // if something has been found, update this _topPitch = pitchTop; _bottomPitch = pitchBottom; _topTpc = tpcTop; _bottomTpc = tpcBottom; } }
Element* Score::lastElement() { Element* re =0; Segment* seg = this->lastSegment(); while (true) { for(int i = (this->staves().size() -1) * VOICES; i < this->staves().size() * VOICES; i++){ if(seg->element(i) != 0){ re = seg->element(i); } } if(re){ if(re->type() == Element::Type::CHORD){ return static_cast<Chord*>(re)->notes().first(); } return re; } seg = seg->prev1MM(Segment::Type::All); } }
Segment* InputState::nextInputPos() const { Measure* m = _segment->measure(); Segment* s = _segment->next1(Segment::Type::ChordRest); for (; s; s = s->next1(Segment::Type::ChordRest)) { if (s->element(_track) || s->measure() != m) return s; } return 0; }