void ScoreView::lyricsReturn() { Lyrics* lyrics = toLyrics(editData.element); changeState(ViewState::NORMAL); _score->startCmd(); int newVerse; newVerse = lyrics->no() + 1; Lyrics* oldLyrics = lyrics; lyrics = new Lyrics(_score); lyrics->setTrack(oldLyrics->track()); lyrics->setParent(oldLyrics->segment()->element(oldLyrics->track())); lyrics->setPlacement(oldLyrics->placement()); lyrics->setPropertyFlags(Pid::PLACEMENT, oldLyrics->propertyFlags(Pid::PLACEMENT)); lyrics->setNo(newVerse); _score->undoAddElement(lyrics); _score->endCmd(); _score->select(lyrics, SelectType::SINGLE, 0); startEdit(lyrics, Grip::NO_GRIP); adjustCanvasPosition(lyrics, false); }
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 ScoreView::lyricsUpDown(bool up, bool end) { Lyrics* lyrics = toLyrics(editData.element); int track = lyrics->track(); ChordRest* cr = lyrics->chordRest(); int verse = lyrics->no(); Placement placement = lyrics->placement(); PropertyFlags pFlags = lyrics->propertyFlags(Pid::PLACEMENT); if (up) { if (verse == 0) return; --verse; } else { ++verse; if (verse > cr->lastVerse(placement)) return; } changeState(ViewState::NORMAL); lyrics = cr->lyrics(verse, placement); if (!lyrics) { lyrics = new Lyrics(_score); lyrics->setTrack(track); lyrics->setParent(cr); lyrics->setNo(verse); lyrics->setPlacement(placement); lyrics->setPropertyFlags(Pid::PLACEMENT, pFlags); _score->startCmd(); _score->undoAddElement(lyrics); _score->endCmd(); } _score->select(lyrics, SelectType::SINGLE, 0); startEdit(lyrics, Grip::NO_GRIP); mscore->changeState(mscoreState()); adjustCanvasPosition(lyrics, false); lyrics = toLyrics(editData.element); TextCursor* cursor = lyrics->cursor(editData); if (end) { cursor->movePosition(QTextCursor::Start, QTextCursor::MoveAnchor); cursor->movePosition(QTextCursor::End, QTextCursor::KeepAnchor); } else { cursor->movePosition(QTextCursor::End, QTextCursor::MoveAnchor); cursor->movePosition(QTextCursor::Start, QTextCursor::KeepAnchor); } _score->setLayoutAll(); _score->update(); }
void ScoreView::lyricsUpDown(bool up, bool end) { Lyrics* lyrics = toLyrics(editObject); int track = lyrics->track(); ChordRest* cr = lyrics->chordRest(); int verse = lyrics->no(); Element::Placement placement = lyrics->placement(); if (placement == Element::Placement::ABOVE) up = !up; if (up) { if (verse == 0) return; --verse; } else { ++verse; if (verse > cr->lastVerse(placement)) return; } endEdit(); _score->startCmd(); lyrics = cr->lyrics(verse, placement); if (!lyrics) { lyrics = new Lyrics(_score); lyrics->setTrack(track); lyrics->setParent(cr); lyrics->setNo(verse); lyrics->setPlacement(placement); _score->undoAddElement(lyrics); } _score->select(lyrics, SelectType::SINGLE, 0); startEdit(lyrics, Grip::NO_GRIP); mscore->changeState(mscoreState()); adjustCanvasPosition(lyrics, false); if (end) { ((Lyrics*)editObject)->movePosition(QTextCursor::Start, QTextCursor::MoveAnchor); ((Lyrics*)editObject)->movePosition(QTextCursor::End, QTextCursor::KeepAnchor); } else { ((Lyrics*)editObject)->movePosition(QTextCursor::End, QTextCursor::MoveAnchor); ((Lyrics*)editObject)->movePosition(QTextCursor::Start, QTextCursor::KeepAnchor); } _score->setLayoutAll(); _score->update(); }
void ScoreView::lyricsReturn() { Lyrics* lyrics = (Lyrics*)editObject; Segment* segment = lyrics->segment(); endEdit(); _score->startCmd(); Lyrics* oldLyrics = lyrics; int newVerse; if (lyrics->placeAbove()) { newVerse = oldLyrics->no() - 1; if (newVerse == -1) { // raise all lyrics above newVerse = 0; for (Segment* s = _score->firstSegment(Segment::Type::ChordRest); s; s = s->next1(Segment::Type::ChordRest)) { ChordRest* cr = s->cr(lyrics->track()); if (cr) { for (Lyrics* l : cr->lyrics()) { if (l->placement() == oldLyrics->placement()) l->undoChangeProperty(P_ID::VERSE, l->no() + 1); } } } } } else newVerse = oldLyrics->no() + 1; lyrics = static_cast<Lyrics*>(Element::create(lyrics->type(), _score)); lyrics->setTrack(oldLyrics->track()); lyrics->setParent(segment->element(oldLyrics->track())); lyrics->setPlacement(oldLyrics->placement()); lyrics->setNo(newVerse); _score->undoAddElement(lyrics); _score->select(lyrics, SelectType::SINGLE, 0); startEdit(lyrics, Grip::NO_GRIP); mscore->changeState(mscoreState()); adjustCanvasPosition(lyrics, false); _score->setLayoutAll(); _score->update(); }
void ScoreView::lyricsUpDown(bool up, bool end) { Lyrics* lyrics = static_cast<Lyrics*>(editObject); int track = lyrics->track(); ChordRest* cr = lyrics->chordRest(); int verse = lyrics->no(); const QList<Lyrics*>* ll = &lyrics->chordRest()->lyricsList(); if (up) { if (verse == 0) return; --verse; } else { ++verse; if (verse >= ll->size()) return; } endEdit(); _score->startCmd(); lyrics = ll->value(verse); if (!lyrics) { lyrics = new Lyrics(_score); lyrics->setTrack(track); lyrics->setParent(cr); lyrics->setNo(verse); _score->undoAddElement(lyrics); } _score->select(lyrics, SELECT_SINGLE, 0); startEdit(lyrics, -1); mscore->changeState(mscoreState()); adjustCanvasPosition(lyrics, false); if (end) ((Lyrics*)editObject)->moveCursorToEnd(); else ((Lyrics*)editObject)->moveCursorToStart(); _score->setLayoutAll(true); _score->end2(); _score->end1(); }
void ScoreView::lyricsUnderscore() { Lyrics* lyrics = toLyrics(editData.element); int track = lyrics->track(); Segment* segment = lyrics->segment(); int verse = lyrics->no(); Placement placement = lyrics->placement(); PropertyFlags pFlags = lyrics->propertyFlags(Pid::PLACEMENT); int endTick = segment->tick(); // a previous melisma cannot extend beyond this point changeState(ViewState::NORMAL); // search next chord Segment* nextSegment = segment; while ((nextSegment = nextSegment->next1(SegmentType::ChordRest))) { Element* el = nextSegment->element(track); if (el && el->isChord()) break; } // look for the lyrics we are moving from; may be the current lyrics or a previous one // we are extending with several underscores Lyrics* fromLyrics = 0; while (segment) { ChordRest* cr = toChordRest(segment->element(track)); if (cr) { fromLyrics = cr->lyrics(verse, placement); if (fromLyrics) break; } segment = segment->prev1(SegmentType::ChordRest); // if the segment has a rest in this track, stop going back Element* e = segment ? segment->element(track) : 0; if (e && !e->isChord()) break; } // one-chord melisma? // if still at melisma initial chord and there is a valid next chord (if not, // there will be no melisma anyway), set a temporary melisma duration if (fromLyrics == lyrics && nextSegment) { _score->startCmd(); lyrics->undoChangeProperty(Pid::LYRIC_TICKS, Lyrics::TEMP_MELISMA_TICKS); _score->setLayoutAll(); _score->endCmd(); } if (nextSegment == 0) { _score->startCmd(); if (fromLyrics) { switch(fromLyrics->syllabic()) { case Lyrics::Syllabic::SINGLE: case Lyrics::Syllabic::END: break; default: fromLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::END)); break; } if (fromLyrics->segment()->tick() < endTick) fromLyrics->undoChangeProperty(Pid::LYRIC_TICKS, endTick - fromLyrics->segment()->tick()); } // leave edit mode, select something (just for user feedback) and update to show extended melisam mscore->changeState(STATE_NORMAL); if (fromLyrics) _score->select(fromLyrics, SelectType::SINGLE, 0); _score->setLayoutAll(); _score->endCmd(); return; } // if a place for a new lyrics has been found, create a lyrics there ChordRest* cr = toChordRest(nextSegment->element(track)); Lyrics* toLyrics = cr->lyrics(verse, placement); bool newLyrics = (toLyrics == 0); if (!toLyrics) { toLyrics = new Lyrics(_score); toLyrics->setTrack(track); toLyrics->setParent(nextSegment->element(track)); toLyrics->setNo(verse); toLyrics->setPlacement(placement); toLyrics->setPropertyFlags(Pid::PLACEMENT, pFlags); toLyrics->setSyllabic(Lyrics::Syllabic::SINGLE); } // as we arrived at toLyrics by an underscore, it cannot have syllabic dashes before else if (toLyrics->syllabic() == Lyrics::Syllabic::MIDDLE) toLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::BEGIN)); else if (toLyrics->syllabic() == Lyrics::Syllabic::END) toLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::SINGLE)); if (fromLyrics) { // as we moved away from fromLyrics by an underscore, // it can be isolated or terminal but cannot have dashes after switch(fromLyrics->syllabic()) { case Lyrics::Syllabic::SINGLE: case Lyrics::Syllabic::END: break; default: fromLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::END)); break; } // for the same reason, if it has a melisma, this cannot extend beyond toLyrics if (fromLyrics->segment()->tick() < endTick) fromLyrics->undoChangeProperty(Pid::LYRIC_TICKS, endTick - fromLyrics->segment()->tick()); } if (newLyrics) _score->undoAddElement(toLyrics); _score->endCmd(); _score->select(toLyrics, SelectType::SINGLE, 0); startEdit(toLyrics, Grip::NO_GRIP); adjustCanvasPosition(toLyrics, false); TextCursor* cursor = Ms::toLyrics(editData.element)->cursor(editData); Ms::toLyrics(editData.element)->selectAll(cursor); }
void ScoreView::lyricsMinus() { Lyrics* lyrics = toLyrics(editData.element); int track = lyrics->track(); Segment* segment = lyrics->segment(); int verse = lyrics->no(); Placement placement = lyrics->placement(); PropertyFlags pFlags = lyrics->propertyFlags(Pid::PLACEMENT); changeState(ViewState::NORMAL); // search next chord Segment* nextSegment = segment; while ((nextSegment = nextSegment->next1(SegmentType::ChordRest))) { Element* el = nextSegment->element(track); if (el && el->isChord()) break; } if (nextSegment == 0) return; // look for the lyrics we are moving from; may be the current lyrics or a previous one // we are extending with several dashes Lyrics* fromLyrics = 0; while (segment) { ChordRest* cr = toChordRest(segment->element(track)); if (!cr) { segment = segment->prev1(SegmentType::ChordRest); continue; } fromLyrics = cr->lyrics(verse, placement); if (fromLyrics) break; segment = segment->prev1(SegmentType::ChordRest); } _score->startCmd(); ChordRest* cr = toChordRest(nextSegment->element(track)); Lyrics* toLyrics = cr->lyrics(verse, placement); bool newLyrics = (toLyrics == 0); if (!toLyrics) { toLyrics = new Lyrics(_score); toLyrics->setTrack(track); toLyrics->setParent(nextSegment->element(track)); toLyrics->setNo(verse); toLyrics->setPlacement(placement); toLyrics->setPropertyFlags(Pid::PLACEMENT, pFlags); toLyrics->setSyllabic(Lyrics::Syllabic::END); } else { // as we arrived at toLyrics by a dash, it cannot be initial or isolated if (toLyrics->syllabic() == Lyrics::Syllabic::BEGIN) toLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::MIDDLE)); else if (toLyrics->syllabic() == Lyrics::Syllabic::SINGLE) toLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::END)); } if (fromLyrics) { // as we moved away from fromLyrics by a dash, // it can have syll. dashes before and after but cannot be isolated or terminal switch(fromLyrics->syllabic()) { case Lyrics::Syllabic::BEGIN: case Lyrics::Syllabic::MIDDLE: break; case Lyrics::Syllabic::SINGLE: fromLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::BEGIN)); break; case Lyrics::Syllabic::END: fromLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::MIDDLE)); break; } // for the same reason, it cannot have a melisma fromLyrics->undoChangeProperty(Pid::LYRIC_TICKS, 0); } if (newLyrics) _score->undoAddElement(toLyrics); _score->endCmd(); _score->select(toLyrics, SelectType::SINGLE, 0); startEdit(toLyrics, Grip::NO_GRIP); adjustCanvasPosition(toLyrics, false); TextCursor* cursor = Ms::toLyrics(editData.element)->cursor(editData); Ms::toLyrics(editData.element)->selectAll(cursor); _score->setLayoutAll(); }
void MuseData::readNote(Part* part, const QString& s) { // a b c d e f g static int table[7] = { 9, 11, 0, 2, 4, 5, 7 }; int step = s[0].toLatin1() - 'A'; int alter = 0; int octave = 0; for (int i = 1; i < 3; ++i) { if (s[i] == '#') alter += 1; else if (s[i] == 'f') alter -= 1; else if (s[i].isDigit()) { octave = s.mid(i,1).toInt(); break; } } MScore::Direction dir = MScore::AUTO; if (s.size() >= 23) { if (s[22] == 'u') dir = MScore::UP; else if (s[22] == 'd') dir = MScore::DOWN; } int staffIdx = 0; if (s.size() >= 24) { if (s[23].isDigit()) staffIdx = s.mid(23,1).toInt() - 1; } Staff* staff = part->staff(staffIdx); int gstaff = staff->idx(); int pitch = table[step] + alter + (octave + 1) * 12; if (pitch < 0) pitch = 0; if (pitch > 127) pitch = 127; int ticks = s.mid(5, 3).toInt(); ticks = (ticks * MScore::division + _division/2) / _division; int tick = curTick; curTick += ticks; Tuplet* tuplet = 0; if (s.size() >= 22) { int a = 1; int b = 1; if (s[19] != ' ') { a = s[19].toLatin1() - '0'; if (a == 3 && s[20] != ':') b = 2; else { b = s[21].toLatin1() - '0'; } } if (a == 3 && b == 2) { // triplet if (chordRest && chordRest->tuplet() && ntuplet) { tuplet = chordRest->tuplet(); } else { tuplet = new Tuplet(score); tuplet->setTrack(gstaff * VOICES); tuplet->setTick(tick); ntuplet = a; tuplet->setRatio(Fraction(a, b)); measure->add(tuplet); } } else if (a == 1 && b == 1) ; else qDebug("unsupported tuple %d/%d", a, b); } Chord* chord = new Chord(score); chordRest = chord; chord->setTrack(gstaff * VOICES); chord->setStemDirection(dir); if (tuplet) { chord->setTuplet(tuplet); tuplet->add(chord); --ntuplet; } TDuration d; d.setVal(ticks); chord->setDurationType(d); Segment* segment = measure->getSegment(chord, tick); voice = 0; for (; voice < VOICES; ++voice) { Element* e = segment->element(gstaff * VOICES + voice); if (e == 0) { chord->setTrack(gstaff * VOICES + voice); segment->add(chord); break; } } if (voice == VOICES) { qDebug("cannot allocate voice"); delete chord; return; } Note* note = new Note(score); note->setPitch(pitch); note->setTpcFromPitch(); note->setTrack(gstaff * VOICES + voice); chord->add(note); QString dynamics; QString an = s.mid(31, 11); for (int i = 0; i < an.size(); ++i) { if (an[i] == '(') openSlur(0, tick, staff, voice); else if (an[i] == ')') closeSlur(0, tick, staff, voice); else if (an[i] == '[') openSlur(1, tick, staff, voice); else if (an[i] == ']') closeSlur(1, tick, staff, voice); else if (an[i] == '{') openSlur(2, tick, staff, voice); else if (an[i] == '}') closeSlur(2, tick, staff, voice); else if (an[i] == 'z') openSlur(3, tick, staff, voice); else if (an[i] == 'x') closeSlur(3, tick, staff, voice); else if (an[i] == '.') { Articulation* atr = new Articulation(score); atr->setArticulationType(Articulation_Staccato); chord->add(atr); } else if (an[i] == '_') { Articulation* atr = new Articulation(score); atr->setArticulationType(Articulation_Tenuto); chord->add(atr); } else if (an[i] == 'v') { Articulation* atr = new Articulation(score); atr->setArticulationType(Articulation_Upbow); chord->add(atr); } else if (an[i] == 'n') { Articulation* atr = new Articulation(score); atr->setArticulationType(Articulation_Downbow); chord->add(atr); } else if (an[i] == 't') { Articulation* atr = new Articulation(score); atr->setArticulationType(Articulation_Trill); chord->add(atr); } else if (an[i] == 'F') { Articulation* atr = new Articulation(score); atr->setUp(true); atr->setArticulationType(Articulation_Fermata); chord->add(atr); } else if (an[i] == 'E') { Articulation* atr = new Articulation(score); atr->setUp(false); atr->setArticulationType(Articulation_Fermata); chord->add(atr); } else if (an[i] == 'O') { // Articulation* atr = new Articulation(score); // atr->setArticulationType(Articulation_Downbow); // chord->add(atr); qDebug("%06d: open string '%c' not implemented", tick, an[i].toLatin1()); } else if (an[i] == '&') { // skip editorial level if (i <= an.size() && an[i+1].isDigit()) ++i; } else if (an[i] == 'p') dynamics += "p"; else if (an[i] == 'm') dynamics += "m"; else if (an[i] == 'f') dynamics += "f"; else if (an[i] == '-') // tie ; else if (an[i] == '*') // start tuplet ; else if (an[i] == '!') // stop tuplet ; else if (an[i] == '+') // cautionary accidental ; else if (an[i] == 'X') // ??? ; else if (an[i] == ' ') ; else { qDebug("%06d: notation '%c' not implemented", tick, an[i].toLatin1()); } } if (!dynamics.isEmpty()) { Dynamic* dyn = new Dynamic(score); dyn->setDynamicType(dynamics); dyn->setTrack(gstaff * VOICES); Segment* s = measure->getSegment(Segment::SegChordRest, tick); s->add(dyn); } QString txt = s.mid(43, 36); if (!txt.isEmpty()) { QStringList sl = txt.split("|"); int no = 0; foreach(QString w, sl) { w = diacritical(w); Lyrics* l = new Lyrics(score); l->setText(w); l->setNo(no++); l->setTrack(gstaff * VOICES); Segment* segment = measure->tick2segment(tick); segment->add(l); }
void ScoreView::lyricsTab(bool back, bool end, bool moveOnly) { Lyrics* lyrics = (Lyrics*)editObject; int track = lyrics->track(); Segment* segment = lyrics->segment(); int verse = lyrics->no(); Segment* nextSegment = segment; if (back) { // search prev chord while ((nextSegment = nextSegment->prev1(Segment::Type::ChordRest))) { Element* el = nextSegment->element(track); if (el && el->type() == Element::Type::CHORD) break; } } else { // search next chord while ((nextSegment = nextSegment->next1(Segment::Type::ChordRest))) { Element* el = nextSegment->element(track); if (el && el->type() == Element::Type::CHORD) break; } } if (nextSegment == 0) return; endEdit(); // search previous lyric Lyrics* oldLyrics = 0; if (!back) { while (segment) { const QList<Lyrics*>* nll = segment->lyricsList(track); if (nll) { oldLyrics = nll->value(verse); if (oldLyrics) break; } segment = segment->prev1(Segment::Type::ChordRest); } } const QList<Lyrics*>* ll = nextSegment->lyricsList(track); if (ll == 0) { qDebug("no next lyrics list: %s", nextSegment->element(track)->name()); return; } lyrics = ll->value(verse); bool newLyrics = false; if (!lyrics) { lyrics = new Lyrics(_score); lyrics->setTrack(track); ChordRest* cr = static_cast<ChordRest*>(nextSegment->element(track)); lyrics->setParent(cr); lyrics->setNo(verse); lyrics->setSyllabic(Lyrics::Syllabic::SINGLE); newLyrics = true; } _score->startCmd(); if (oldLyrics && !moveOnly) { switch(lyrics->syllabic()) { case Lyrics::Syllabic::SINGLE: case Lyrics::Syllabic::BEGIN: break; case Lyrics::Syllabic::END: lyrics->undoChangeProperty(P_ID::SYLLABIC, int(Lyrics::Syllabic::SINGLE)); break; case Lyrics::Syllabic::MIDDLE: lyrics->undoChangeProperty(P_ID::SYLLABIC, int(Lyrics::Syllabic::BEGIN)); break; } switch(oldLyrics->syllabic()) { case Lyrics::Syllabic::SINGLE: case Lyrics::Syllabic::END: break; case Lyrics::Syllabic::BEGIN: oldLyrics->undoChangeProperty(P_ID::SYLLABIC, int(Lyrics::Syllabic::SINGLE)); break; case Lyrics::Syllabic::MIDDLE: oldLyrics->undoChangeProperty(P_ID::SYLLABIC, int(Lyrics::Syllabic::END)); break; } } if (newLyrics) _score->undoAddElement(lyrics); _score->select(lyrics, SelectType::SINGLE, 0); startEdit(lyrics, -1); mscore->changeState(mscoreState()); adjustCanvasPosition(lyrics, false); if (end) ((Lyrics*)editObject)->moveCursorToEnd(); else ((Lyrics*)editObject)->moveCursorToStart(); _score->setLayoutAll(true); _score->update(); }
void ScoreView::lyricsUnderscore() { Lyrics* lyrics = static_cast<Lyrics*>(editObject); int track = lyrics->track(); Segment* segment = lyrics->segment(); int verse = lyrics->no(); int endTick = segment->tick(); endEdit(); // search next chord Segment* nextSegment = segment; while ((nextSegment = nextSegment->next1(Segment::Type::ChordRest))) { Element* el = nextSegment->element(track); if (el && el->type() == Element::Type::CHORD) break; } // search previous lyric Lyrics* oldLyrics = 0; while (segment) { const QList<Lyrics*>* nll = segment->lyricsList(track); if (nll) { oldLyrics = nll->value(verse); if (oldLyrics) break; } segment = segment->prev1(Segment::Type::ChordRest); } if (nextSegment == 0) { if (oldLyrics) { switch(oldLyrics->syllabic()) { case Lyrics::Syllabic::SINGLE: case Lyrics::Syllabic::END: break; default: oldLyrics->undoChangeProperty(P_ID::SYLLABIC, int(Lyrics::Syllabic::END)); break; } if (oldLyrics->segment()->tick() < endTick) oldLyrics->undoChangeProperty(P_ID::LYRIC_TICKS, endTick - oldLyrics->segment()->tick()); } return; } _score->startCmd(); const QList<Lyrics*>* ll = nextSegment->lyricsList(track); lyrics = ll->value(verse); bool newLyrics = (lyrics == 0); if (!lyrics) { lyrics = new Lyrics(_score); lyrics->setTrack(track); lyrics->setParent(nextSegment->element(track)); lyrics->setNo(verse); lyrics->setSyllabic(Lyrics::Syllabic::SINGLE); } else lyrics->undoChangeProperty(P_ID::SYLLABIC, int(Lyrics::Syllabic::SINGLE)); if (oldLyrics) { switch(oldLyrics->syllabic()) { case Lyrics::Syllabic::SINGLE: case Lyrics::Syllabic::END: break; default: oldLyrics->undoChangeProperty(P_ID::SYLLABIC, int(Lyrics::Syllabic::END)); break; } if (oldLyrics->segment()->tick() < endTick) oldLyrics->undoChangeProperty(P_ID::LYRIC_TICKS, endTick - oldLyrics->segment()->tick()); } if (newLyrics) _score->undoAddElement(lyrics); _score->select(lyrics, SelectType::SINGLE, 0); startEdit(lyrics, -1); mscore->changeState(mscoreState()); adjustCanvasPosition(lyrics, false); ((Lyrics*)editObject)->moveCursorToEnd(); _score->setLayoutAll(true); _score->update(); }
void ScoreView::lyricsTab(bool back, bool end, bool moveOnly) { Lyrics* lyrics = (Lyrics*)editObject; int track = lyrics->track(); Segment* segment = lyrics->segment(); int verse = lyrics->no(); Element::Placement placement = lyrics->placement(); Segment* nextSegment = segment; if (back) { // search prev chord while ((nextSegment = nextSegment->prev1(Segment::Type::ChordRest))) { Element* el = nextSegment->element(track); if (el && el->type() == ElementType::CHORD) break; } } else { // search next chord while ((nextSegment = nextSegment->next1(Segment::Type::ChordRest))) { Element* el = nextSegment->element(track); if (el && el->type() == ElementType::CHORD) break; } } if (nextSegment == 0) return; endEdit(); // look for the lyrics we are moving from; may be the current lyrics or a previous one // if we are skipping several chords with spaces Lyrics* fromLyrics = 0; if (!back) { while (segment) { ChordRest* cr = toChordRest(segment->element(track)); if (cr) { fromLyrics = cr->lyrics(verse, placement); if (fromLyrics) break; } segment = segment->prev1(Segment::Type::ChordRest); } } ChordRest* cr = toChordRest(nextSegment->element(track)); if (!cr) { qDebug("no next lyrics list: %s", nextSegment->element(track)->name()); return; } Lyrics* toLyrics = cr->lyrics(verse, placement); bool newLyrics = false; if (!toLyrics) { toLyrics = new Lyrics(_score); toLyrics->setTrack(track); ChordRest* cr = static_cast<ChordRest*>(nextSegment->element(track)); toLyrics->setParent(cr); toLyrics->setNo(verse); toLyrics->setPlacement(placement); toLyrics->setSyllabic(Lyrics::Syllabic::SINGLE); newLyrics = true; } _score->startCmd(); if (fromLyrics && !moveOnly) { switch(toLyrics->syllabic()) { // as we arrived at toLyrics by a [Space], it can be the beginning // of a multi-syllable, but cannot have syllabic dashes before case Lyrics::Syllabic::SINGLE: case Lyrics::Syllabic::BEGIN: break; case Lyrics::Syllabic::END: toLyrics->undoChangeProperty(P_ID::SYLLABIC, int(Lyrics::Syllabic::SINGLE)); break; case Lyrics::Syllabic::MIDDLE: toLyrics->undoChangeProperty(P_ID::SYLLABIC, int(Lyrics::Syllabic::BEGIN)); break; } // as we moved away from fromLyrics by a [Space], it can be // the end of a multi-syllable, but cannot have syllabic dashes after switch(fromLyrics->syllabic()) { case Lyrics::Syllabic::SINGLE: case Lyrics::Syllabic::END: break; case Lyrics::Syllabic::BEGIN: fromLyrics->undoChangeProperty(P_ID::SYLLABIC, int(Lyrics::Syllabic::SINGLE)); break; case Lyrics::Syllabic::MIDDLE: fromLyrics->undoChangeProperty(P_ID::SYLLABIC, int(Lyrics::Syllabic::END)); break; } // for the same reason, it cannot have a melisma fromLyrics->undoChangeProperty(P_ID::LYRIC_TICKS, 0); } if (newLyrics) _score->undoAddElement(toLyrics); _score->select(toLyrics, SelectType::SINGLE, 0); startEdit(toLyrics, Grip::NO_GRIP); mscore->changeState(mscoreState()); adjustCanvasPosition(toLyrics, false); if (end) { ((Lyrics*)editObject)->movePosition(QTextCursor::Start, QTextCursor::MoveAnchor); ((Lyrics*)editObject)->movePosition(QTextCursor::End, QTextCursor::KeepAnchor); } else { ((Lyrics*)editObject)->movePosition(QTextCursor::End, QTextCursor::MoveAnchor); ((Lyrics*)editObject)->movePosition(QTextCursor::Start, QTextCursor::KeepAnchor); } _score->setLayoutAll(); _score->update(); }
void ScoreView::lyricsMinus() { Lyrics* lyrics = (Lyrics*)editObject; int track = lyrics->track(); int staffIdx = lyrics->staffIdx(); Segment* segment = lyrics->segment(); int verse = lyrics->no(); endEdit(); // search next chord Segment* nextSegment = segment; while ((nextSegment = nextSegment->next1(Segment::SegChordRest | Segment::SegGrace))) { Element* el = nextSegment->element(track); if (el && el->type() == Element::CHORD) break; } if (nextSegment == 0) { return; } // search previous lyric Lyrics* oldLyrics = 0; while (segment) { const QList<Lyrics*>* nll = segment->lyricsList(staffIdx); if (!nll) { segment = segment->prev1(Segment::SegChordRest | Segment::SegGrace); continue; } oldLyrics = nll->value(verse); if (oldLyrics) break; segment = segment->prev1(Segment::SegChordRest | Segment::SegGrace); } _score->startCmd(); const QList<Lyrics*>* ll = nextSegment->lyricsList(staffIdx); lyrics = ll->value(verse); bool newLyrics = (lyrics == 0); if (!lyrics) { lyrics = new Lyrics(_score); lyrics->setTrack(track); lyrics->setParent(nextSegment->element(track)); lyrics->setNo(verse); lyrics->setSyllabic(Lyrics::END); } if(lyrics->syllabic()==Lyrics::BEGIN) { lyrics->setSyllabic(Lyrics::MIDDLE); } else if(lyrics->syllabic()==Lyrics::SINGLE) { lyrics->setSyllabic(Lyrics::END); } if (oldLyrics) { switch(oldLyrics->syllabic()) { case Lyrics::BEGIN: case Lyrics::MIDDLE: break; case Lyrics::SINGLE: oldLyrics->setSyllabic(Lyrics::BEGIN); break; case Lyrics::END: oldLyrics->setSyllabic(Lyrics::MIDDLE); break; } } if(newLyrics) _score->undoAddElement(lyrics); _score->select(lyrics, SELECT_SINGLE, 0); startEdit(lyrics, -1); mscore->changeState(mscoreState()); adjustCanvasPosition(lyrics, false); ((Lyrics*)editObject)->moveCursorToEnd(); _score->setLayoutAll(true); _score->end2(); _score->end1(); }