bool Ottava::setProperty(P_ID propertyId, const QVariant& val) { switch (propertyId) { case P_ID::OTTAVA_TYPE: setOttavaType(OttavaType(val.toInt())); break; case P_ID::LINE_WIDTH: lineWidthStyle = PropertyStyle::UNSTYLED; TextLine::setProperty(propertyId, val); break; case P_ID::LINE_STYLE: lineStyleStyle = PropertyStyle::UNSTYLED; TextLine::setProperty(propertyId, val); break; case P_ID::NUMBERS_ONLY: setNumbersOnly(val.toBool()); setOttavaType(_ottavaType); numbersOnlyStyle = PropertyStyle::UNSTYLED; break; case P_ID::SPANNER_TICK2: staff()->pitchOffsets().remove(tick2()); setTick2(val.toInt()); staff()->updateOttava(this); break; case P_ID::SPANNER_TICK: staff()->pitchOffsets().remove(tick()); setTick(val.toInt()); staff()->updateOttava(this); break; default: if (!TextLine::setProperty(propertyId, val)) return false; break; } score()->setLayoutAll(true); return true; }
void LyricsLine::layout() { bool tempMelismaTicks = (lyrics()->ticks() == Lyrics::TEMP_MELISMA_TICKS); if (lyrics()->ticks()) { // melisma setLineWidth(score()->styleP(Sid::lyricsLineThickness)); // if lyrics has a temporary one-chord melisma, set to 0 ticks (just its own chord) if (tempMelismaTicks) lyrics()->setTicks(0); // Lyrics::_ticks points to the beginning of the last spanned segment, // but the line shall include it: // include the duration of this last segment in the melisma duration Segment* lyricsSegment = lyrics()->segment(); int lyricsStartTick = lyricsSegment->tick(); int lyricsEndTick = lyrics()->endTick(); int lyricsTrack = lyrics()->track(); // find segment with tick >= endTick Segment* s = lyricsSegment; while (s && s->tick() < lyricsEndTick) s = s->nextCR(lyricsTrack, true); if (!s) { // user probably deleted measures at end of score, leaving this melisma too long // set s to last segment and reset lyricsEndTick to trigger FIXUP code below s = score()->lastSegment(); lyricsEndTick = -1; } Element* se = s->element(lyricsTrack); // everything is OK if we have reached a chord at right tick on right track if (s->tick() == lyricsEndTick && se && se->type() == ElementType::CHORD) { // advance to next CR, or last segment if no next CR s = s->nextCR(lyricsTrack, true); if (!s) s = score()->lastSegment(); } else { // FIXUP - lyrics tick count not valid // this happens if edits to score have removed the original end segment // so let's fix it here // s is already pointing to segment past endTick (or to last segment) // we should shorten the lyrics tick count to make this work Segment* ns = s; Segment* ps = s->prev1(SegmentType::ChordRest); while (ps && ps != lyricsSegment) { Element* pe = ps->element(lyricsTrack); // we're looking for an actual chord on this track if (pe && pe->type() == ElementType::CHORD) break; s = ps; ps = ps->prev1(SegmentType::ChordRest); } if (!ps || ps == lyricsSegment) { // no valid previous CR, so try to lengthen melisma instead ps = ns; s = ps->nextCR(lyricsTrack, true); Element* e = s ? s->element(lyricsTrack) : nullptr; // check to make sure we have a chord if (!e || e->type() != ElementType::CHORD) { // nothing to do but set ticks to 0 // this will result in melisma being deleted later lyrics()->undoChangeProperty(Pid::LYRIC_TICKS, 0); setTicks(0); return; } } lyrics()->undoChangeProperty(Pid::LYRIC_TICKS, ps->tick() - lyricsStartTick); } setTicks(s->tick() - lyricsStartTick); } else { // dash(es) _nextLyrics = searchNextLyrics(lyrics()->segment(), staffIdx(), lyrics()->no(), lyrics()->placement()); setTick2(_nextLyrics ? _nextLyrics->segment()->tick() : tick()); } if (ticks()) { // only do layout if some time span // do layout with non-0 duration if (tempMelismaTicks) lyrics()->setTicks(Lyrics::TEMP_MELISMA_TICKS); SLine::layout(); // if temp melisma and there is a first line segment, // extend it to be after the lyrics syllable (otherwise // the melisma segment will be often covered by the syllable itself) if (tempMelismaTicks && segments.size() > 0) segmentAt(0)->rxpos2() += lyrics()->width(); } }