void Tie::endEdit() { if (editStartNote != startNote() || editEndNote != endNote()) { score()->undo()->push1(new ChangeSpannerElements(this, editStartNote, editEndNote)); } SlurTie::endEdit(); score()->setLayoutAll(true); }
void Tie::calculateDirection() { Chord* c1 = startNote()->chord(); Chord* c2 = endNote()->chord(); Measure* m1 = c1->measure(); Measure* m2 = c2->measure(); if (_slurDirection == MScore::Direction::AUTO) { QList<Note*> notes = c1->notes(); int n = notes.size(); if (m1->mstaff(c1->staffIdx())->hasVoices || m2->mstaff(c2->staffIdx())->hasVoices) { // in polyphonic passage, ties go on the stem side _up = c1->up(); } else if (n == 1) { // // single note // if (c1->up() != c2->up()) { // if stem direction is mixed, always up _up = true; } else _up = !c1->up(); } else { // // chords // QList<int> ties; int idx = 0; for (int i = 0; i < n; ++i) { if (notes[i]->tieFor()) { ties.append(notes[i]->line()); if (notes[i] == startNote()) idx = ties.size() - 1; } } if (idx == 0) _up = false; else if (idx == ties.size() - 1) _up = true; else { if (ties[idx] <= 4) _up = ((ties[idx-1] - ties[idx]) <= 1) || ((ties[idx] - ties[idx+1]) > 1); else _up = ((ties[idx-1] - ties[idx]) <= 1) && ((ties[idx] - ties[idx+1]) > 1); } } } else _up = _slurDirection == MScore::Direction::UP ? true : false; }
void Tie::startEdit(MuseScoreView* v, const QPointF& p) { editStartNote = startNote(); editEndNote = endNote(); SlurTie::startEdit(v, p); }
void Tie::layout() { qreal _spatium = spatium(); // // show short bow // if (startNote() == 0 || endNote() == 0) { if (startNote() == 0) { qDebug("Tie::layout(): no start note"); return; } Chord* c1 = startNote()->chord(); if (_slurDirection == MScore::Direction::AUTO) { if (c1->measure()->mstaff(c1->staffIdx())->hasVoices) { // in polyphonic passage, ties go on the stem side _up = c1->up(); } else _up = !c1->up(); } else _up = _slurDirection == MScore::Direction::UP ? true : false; fixupSegments(1); SlurSegment* segment = segmentAt(0); segment->setSpannerSegmentType(SpannerSegmentType::SINGLE); segment->setSystem(startNote()->chord()->segment()->measure()->system()); SlurPos sPos; slurPos(&sPos); segment->layout(sPos.p1, sPos.p2); return; } calculateDirection(); qreal w = startNote()->headWidth(); qreal xo1 = w * 1.12; qreal h = w * 0.3; qreal yo = _up ? -h : h; QPointF off1(xo1, yo); QPointF off2(0.0, yo); #if 0 // yet(?) unused QPointF ppos(pagePos()); #endif // TODO: cleanup SlurPos sPos; slurPos(&sPos); // p1, p2, s1, s2 QList<System*>* systems = score()->systems(); setPos(0, 0); //--------------------------------------------------------- // count number of segments, if no change, all // user offsets (drags) are retained //--------------------------------------------------------- int sysIdx1 = systems->indexOf(sPos.system1); if (sysIdx1 == -1) { qDebug("system not found"); foreach(System* s, *systems) qDebug(" search %p in %p", sPos.system1, s); return; } int sysIdx2 = systems->indexOf(sPos.system2); if (sysIdx2 < 0) sysIdx2 = sysIdx1; unsigned nsegs = sysIdx2 - sysIdx1 + 1; fixupSegments(nsegs); int i = 0; for (uint ii = 0; ii < nsegs; ++ii) { System* system = (*systems)[sysIdx1++]; if (system->isVbox()) continue; SlurSegment* segment = segmentAt(i); segment->setSystem(system); // case 1: one segment if (sPos.system1 == sPos.system2) { segment->layout(sPos.p1, sPos.p2); segment->setSpannerSegmentType(SpannerSegmentType::SINGLE); } // case 2: start segment else if (i == 0) { qreal x = system->bbox().width(); segment->layout(sPos.p1, QPointF(x, sPos.p1.y())); segment->setSpannerSegmentType(SpannerSegmentType::BEGIN); } // case 4: end segment else { qreal x = firstNoteRestSegmentX(system) - 2 * _spatium; segment->layout(QPointF(x, sPos.p2.y()), sPos.p2); segment->setSpannerSegmentType(SpannerSegmentType::END); } ++i; } }
void Tie::slurPos(SlurPos* sp) { bool useTablature = staff() != nullptr && staff()->isTabStaff(); StaffType* stt = nullptr; if (useTablature) stt = staff()->staffType(); qreal _spatium = spatium(); qreal hw = startNote()->tabHeadWidth(stt); // if stt == 0, defaults to headWidth() qreal __up = _up ? -1.0 : 1.0; // y offset for ties inside chord margins (typically multi-note chords): lined up with note top or bottom margin // or outside (typically single-note chord): overlaps note and is above/below it // Outside: Tab: uses font size and may be asymmetric placed above/below line (frets ON or ABOVE line) // Std: assumes notehead is 1 sp high, 1/2 sp above and 1/2 below line; add 1/4 sp to it // Inside: Tab: 1/2 of Outside offset // Std: use a fixed pecentage of note width qreal yOffOutside = useTablature ? (_up ? stt->fretBoxY() : stt->fretBoxY() + stt->fretBoxH()) * magS() : 0.75 * _spatium * __up; qreal yOffInside = useTablature ? yOffOutside * 0.5 : hw * .3 * __up; Chord* sc = startNote()->chord(); Q_ASSERT(sc); sp->system1 = sc->measure()->system(); if (!sp->system1) { Measure* m = sc->measure(); qDebug("No system: measure is %d has %d count %d", m->isMMRest(), m->hasMMRest(), m->mmRestCount()); } Q_ASSERT(sp->system1); qreal xo; qreal yo; bool shortStart = false; // determine attachment points // similar code is used in Chord::layoutPitched() // to allocate extra space to enforce minTieLength // so keep these in sync //------p1 if ((sc->notes().size() > 1) || (sc->stem() && (sc->up() == _up))) { xo = startNote()->x() + hw * 1.12; yo = startNote()->pos().y() + yOffInside; shortStart = true; } else { xo = startNote()->x() + hw * 0.65; yo = startNote()->pos().y() + yOffOutside; } sp->p1 = sc->pagePos() - sp->system1->pagePos() + QPointF(xo, yo); //------p2 if (endNote() == 0) { sp->p2 = sp->p1 + QPointF(_spatium * 3, 0.0); sp->system2 = sp->system1; return; } Chord* ec = endNote()->chord(); sp->system2 = ec->measure()->system(); if (!sp->system2) { qDebug("Tie::slurPos no system2"); sp->system2 = sp->system1; } hw = endNote()->tabHeadWidth(stt); if ((ec->notes().size() > 1) || (ec->stem() && !ec->up() && !_up)) xo = endNote()->x() - hw * 0.12; else if (shortStart) xo = endNote()->x() + hw * 0.15; else xo = endNote()->x() + hw * 0.35; sp->p2 = ec->pagePos() - sp->system2->pagePos() + QPointF(xo, yo); }