1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2002-2012 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12
13 #include "note.h"
14 #include "rest.h"
15 #include "chord.h"
16 #include "key.h"
17 #include "sig.h"
18 #include "clef.h"
19 #include "score.h"
20 #include "slur.h"
21 #include "tie.h"
22 #include "hairpin.h"
23 #include "segment.h"
24 #include "staff.h"
25 #include "part.h"
26 #include "timesig.h"
27 #include "page.h"
28 #include "barline.h"
29 #include "tuplet.h"
30 #include "lyrics.h"
31 #include "image.h"
32 #include "keysig.h"
33 #include "beam.h"
34 #include "utils.h"
35 #include "harmony.h"
36 #include "system.h"
37 #include "navigate.h"
38 #include "articulation.h"
39 #include "drumset.h"
40 #include "measure.h"
41 #include "undo.h"
42 #include "tupletmap.h"
43 #include "tiemap.h"
44 #include "stem.h"
45 #include "iname.h"
46 #include "range.h"
47 #include "hook.h"
48 #include "repeat.h"
49 #include "textframe.h"
50 #include "accidental.h"
51 #include "ottava.h"
52 #include "instrchange.h"
53 #include "bracket.h"
54 #include "excerpt.h"
55 #include "breath.h"
56 #include "glissando.h"
57 #include "fermata.h"
58
59 namespace Ms {
60
61 //---------------------------------------------------------
62 // getSelectedNote
63 //---------------------------------------------------------
64
getSelectedNote()65 Note* Score::getSelectedNote()
66 {
67 Element* el = selection().element();
68 if (el && el->isNote())
69 return toNote(el);
70 MScore::setError(NO_NOTE_SELECTED);
71 return 0;
72 }
73
74 //---------------------------------------------------------
75 // getSelectedChordRest
76 //---------------------------------------------------------
77
getSelectedChordRest() const78 ChordRest* Score::getSelectedChordRest() const
79 {
80 Element* el = selection().element();
81 if (el) {
82 if (el->isNote())
83 return toNote(el)->chord();
84 else if (el->isRest() || el->isRepeatMeasure())
85 return toRest(el);
86 else if (el->isChord())
87 return toChord(el);
88 }
89 MScore::setError(NO_NOTE_REST_SELECTED);
90 return 0;
91 }
92
93 //---------------------------------------------------------
94 // getSelectedChordRest2
95 //---------------------------------------------------------
96
getSelectedChordRest2(ChordRest ** cr1,ChordRest ** cr2) const97 void Score::getSelectedChordRest2(ChordRest** cr1, ChordRest** cr2) const
98 {
99 *cr1 = 0;
100 *cr2 = 0;
101 for (Element* e : selection().elements()) {
102 if (e->isNote())
103 e = e->parent();
104 if (e->isChordRest()) {
105 ChordRest* cr = toChordRest(e);
106 if (*cr1 == 0 || (*cr1)->tick() > cr->tick())
107 *cr1 = cr;
108 if (*cr2 == 0 || (*cr2)->tick() < cr->tick())
109 *cr2 = cr;
110 }
111 }
112 if (*cr1 == 0)
113 MScore::setError(NO_NOTE_REST_SELECTED);
114 if (*cr1 == *cr2)
115 *cr2 = 0;
116 }
117
118 //---------------------------------------------------------
119 // getSelectedChordRests
120 //---------------------------------------------------------
121
getSelectedChordRests() const122 QSet<ChordRest*> Score::getSelectedChordRests() const
123 {
124 QSet<ChordRest*> set;
125 for (Element* e : selection().elements()) {
126 if (e->isNote())
127 e = e->parent();
128 if (e->isChordRest()) {
129 set.insert(toChordRest(e));
130 }
131 }
132 return set;
133 }
134
135 //---------------------------------------------------------
136 // pos
137 //---------------------------------------------------------
138
pos()139 Fraction Score::pos()
140 {
141 Element* el = selection().element();
142 if (selection().activeCR())
143 el = selection().activeCR();
144 if (el) {
145 switch (el->type()) {
146 case ElementType::NOTE:
147 el = el->parent();
148 // fall through
149 case ElementType::REPEAT_MEASURE:
150 case ElementType::REST:
151 case ElementType::CHORD:
152 return toChordRest(el)->tick();
153 default:
154 break;
155 }
156 }
157 return Fraction(-1, 1);
158 }
159
160 //---------------------------------------------------------
161 // addRest
162 // create one Rest at tick with duration d
163 // create segment if necessary
164 //---------------------------------------------------------
165
addRest(const Fraction & tick,int track,TDuration d,Tuplet * tuplet)166 Rest* Score::addRest(const Fraction& tick, int track, TDuration d, Tuplet* tuplet)
167 {
168 Measure* measure = tick2measure(tick);
169 Rest* rest = new Rest(this, d);
170 if (d.type() == TDuration::DurationType::V_MEASURE)
171 rest->setTicks(measure->stretchedLen(staff(track/VOICES)));
172 else
173 rest->setTicks(d.fraction());
174 rest->setTrack(track);
175 rest->setTuplet(tuplet);
176 undoAddCR(rest, measure, tick);
177 return rest;
178 }
179
180 //---------------------------------------------------------
181 // addRest
182 //---------------------------------------------------------
183
addRest(Segment * s,int track,TDuration d,Tuplet * tuplet)184 Rest* Score::addRest(Segment* s, int track, TDuration d, Tuplet* tuplet)
185 {
186 Rest* rest = new Rest(this, d);
187 if (d.type() == TDuration::DurationType::V_MEASURE)
188 rest->setTicks(s->measure()->stretchedLen(staff(track/VOICES)));
189 else
190 rest->setTicks(d.fraction());
191 rest->setTrack(track);
192 rest->setParent(s);
193 rest->setTuplet(tuplet);
194 undoAddCR(rest, tick2measure(s->tick()), s->tick());
195 return rest;
196 }
197
198 //---------------------------------------------------------
199 // addChord
200 // Create one Chord at tick with duration d
201 // - create segment if necessary.
202 // - Use chord "oc" as prototype;
203 // - if "genTie" then tie to chord "oc"
204 //---------------------------------------------------------
205
addChord(const Fraction & tick,TDuration d,Chord * oc,bool genTie,Tuplet * tuplet)206 Chord* Score::addChord(const Fraction& tick, TDuration d, Chord* oc, bool genTie, Tuplet* tuplet)
207 {
208 Measure* measure = tick2measure(tick);
209 if (measure->endTick() <= tick) {
210 qDebug("Score::addChord(): end of score?");
211 return 0;
212 }
213
214 Chord* chord = new Chord(this);
215 chord->setTuplet(tuplet);
216 chord->setTrack(oc->track());
217 chord->setDurationType(d);
218 chord->setTicks(d.fraction());
219
220 for (Note* n : oc->notes()) {
221 Note* nn = new Note(this);
222 nn->setPitch(n->pitch());
223 nn->setTpc1(n->tpc1());
224 nn->setTpc2(n->tpc2());
225 chord->add(nn);
226 }
227 undoAddCR(chord, measure, tick);
228
229 //
230 // now as both chords are in place
231 // (have segments as parent) we can add ties:
232 //
233 if (genTie) {
234 size_t n = oc->notes().size();
235 for(size_t i = 0; i < n; ++i) {
236 Note* n1 = oc->notes()[i];
237 Note* n2 = chord->notes()[i];
238 Tie* tie = new Tie(this);
239 tie->setStartNote(n1);
240 tie->setEndNote(n2);
241 tie->setTick(tie->startNote()->tick());
242 tie->setTick2(tie->endNote()->tick());
243 tie->setTrack(n1->track());
244 undoAddElement(tie);
245 }
246 }
247
248 return chord;
249 }
250
251 //---------------------------------------------------------
252 // addClone
253 //---------------------------------------------------------
254
addClone(ChordRest * cr,const Fraction & tick,const TDuration & d)255 ChordRest* Score::addClone(ChordRest* cr, const Fraction& tick, const TDuration& d)
256 {
257 ChordRest* newcr;
258 // change a RepeatMeasure() into an Rest()
259 if (cr->isRepeatMeasure())
260 newcr = new Rest(*toRest(cr));
261 else
262 newcr = toChordRest(cr->clone());
263 newcr->rxpos() = 0.0;
264 newcr->setDurationType(d);
265 newcr->setTicks(d.fraction());
266 newcr->setTuplet(cr->tuplet());
267 newcr->setSelected(false);
268
269 undoAddCR(newcr, cr->measure(), tick);
270 return newcr;
271 }
272
273 //---------------------------------------------------------
274 // setRest
275 // create one or more rests to fill "l"
276 //---------------------------------------------------------
277
setRest(const Fraction & _tick,int track,const Fraction & _l,bool useDots,Tuplet * tuplet,bool useFullMeasureRest)278 Rest* Score::setRest(const Fraction& _tick, int track, const Fraction& _l, bool useDots, Tuplet* tuplet, bool useFullMeasureRest)
279 {
280 Fraction l = _l;
281 Fraction tick = _tick;
282 Measure* measure = tick2measure(tick);
283 Rest* r = 0;
284 Staff* staff = Score::staff(track / VOICES);
285
286 while (!l.isZero()) {
287 //
288 // divide into measures
289 //
290 Fraction f;
291 if (tuplet) {
292 f = tuplet->baseLen().fraction() * tuplet->ratio().numerator();
293 for (DurationElement* de : tuplet->elements()) {
294 if (de->tick() >= tick)
295 break;
296 f -= de->ticks();
297 }
298 //
299 // restrict to tuplet len
300 //
301 if (f < l)
302 l = f;
303 }
304 else {
305 if (measure->tick() < tick)
306 f = measure->tick() + measure->ticks() - tick;
307 else
308 f = measure->ticks();
309 f *= staff->timeStretch(tick);
310 }
311
312 if (f > l)
313 f = l;
314
315 if ((track % VOICES) && !measure->hasVoice(track) && (tick == measure->tick())) {
316 l -= f;
317 measure = measure->nextMeasure();
318 if (!measure)
319 break;
320 tick = measure->tick();
321 continue;
322 }
323
324 if ((measure->timesig() == measure->ticks()) // not in pickup measure
325 && (measure->tick() == tick)
326 && (measure->stretchedLen(staff) == f)
327 && !tuplet
328 && (useFullMeasureRest)) {
329 Rest* rest = addRest(tick, track, TDuration(TDuration::DurationType::V_MEASURE), tuplet);
330 tick += rest->actualTicks();
331 if (r == 0)
332 r = rest;
333 }
334 else {
335 //
336 // compute list of durations which will fit l
337 //
338 std::vector<TDuration> dList;
339 if (tuplet || staff->isLocalTimeSignature(tick)) {
340 dList = toDurationList(l, useDots);
341 std::reverse(dList.begin(), dList.end());
342 }
343 else {
344 dList = toRhythmicDurationList(f, true, tick - measure->tick(), sigmap()->timesig(tick).nominal(), measure, useDots ? 1 : 0);
345 }
346 if (dList.empty())
347 return 0;
348
349 Rest* rest = 0;
350 for (const TDuration& d : dList) {
351 rest = addRest(tick, track, d, tuplet);
352 if (r == 0)
353 r = rest;
354 tick += rest->actualTicks();
355 }
356 }
357 l -= f;
358
359 measure = measure->nextMeasure();
360 if (!measure)
361 break;
362 tick = measure->tick();
363 }
364 return r;
365 }
366
367 //---------------------------------------------------------
368 // addNote from NoteVal
369 //---------------------------------------------------------
370
addNote(Chord * chord,const NoteVal & noteVal,bool forceAccidental,InputState * externalInputState)371 Note* Score::addNote(Chord* chord, const NoteVal& noteVal, bool forceAccidental, InputState* externalInputState)
372 {
373 InputState& is = externalInputState ? (*externalInputState) : _is;
374
375 Note* note = new Note(this);
376 note->setParent(chord);
377 note->setTrack(chord->track());
378 note->setNval(noteVal);
379 undoAddElement(note);
380 if (forceAccidental) {
381 int tpc = styleB(Sid::concertPitch) ? noteVal.tpc1 : noteVal.tpc2;
382 AccidentalVal alter = tpc2alter(tpc);
383 AccidentalType at = Accidental::value2subtype(alter);
384 Accidental* a = new Accidental(this);
385 a->setAccidentalType(at);
386 a->setRole(AccidentalRole::USER);
387 a->setParent(note);
388 undoAddElement(a);
389 }
390 setPlayNote(true);
391 setPlayChord(true);
392
393 if (externalInputState) {
394 is.setTrack(note->track());
395 is.setLastSegment(is.segment());
396 is.setSegment(note->chord()->segment());
397 }
398 else {
399 select(note, SelectType::SINGLE, 0);
400 }
401
402 if (!chord->staff()->isTabStaff(chord->tick())) {
403 NoteEntryMethod entryMethod = is.noteEntryMethod();
404 if (entryMethod != NoteEntryMethod::REALTIME_AUTO && entryMethod != NoteEntryMethod::REALTIME_MANUAL)
405 is.moveToNextInputPos();
406 }
407 return note;
408 }
409
410 //---------------------------------------------------------
411 // rewriteMeasures
412 // rewrite all measures from fm to lm (including)
413 // If staffIdx is valid (>= 0), then rewrite a local
414 // timesig change.
415 //---------------------------------------------------------
416
rewriteMeasures(Measure * fm,Measure * lm,const Fraction & ns,int staffIdx)417 bool Score::rewriteMeasures(Measure* fm, Measure* lm, const Fraction& ns, int staffIdx)
418 {
419 if (staffIdx >= 0) {
420 // local timesig
421 // don't actually rewrite, just update measure rest durations
422 // abort if there is anything other than measure rests in range
423 int strack = staffIdx * VOICES;
424 int etrack = strack + VOICES;
425 for (Measure* m = fm; ; m = m->nextMeasure()) {
426 for (Segment* s = m->first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
427 for (int track = strack; track < etrack; ++track) {
428 ChordRest* cr = toChordRest(s->element(track));
429 if (!cr)
430 continue;
431 if (cr->isRest() && cr->durationType() == TDuration::DurationType::V_MEASURE)
432 cr->undoChangeProperty(Pid::DURATION, QVariant::fromValue(ns));
433 else
434 return false;
435 }
436 }
437 if (m == lm)
438 break;
439 }
440 return true;
441 }
442 int measures = 1;
443 bool fmr = true;
444
445 // Format: chord 1 tick, chord 2 tick, tremolo, track
446 std::vector<std::tuple<Fraction, Fraction, Tremolo*, int>> tremoloChordTicks;
447
448 int strack, etrack;
449 if (staffIdx < 0) {
450 strack = 0;
451 etrack = ntracks();
452 }
453 else {
454 strack = staffIdx * VOICES;
455 etrack = strack + VOICES;
456 }
457
458 for (Measure* m = fm; m; m = m->nextMeasure()) {
459 if (!m->isFullMeasureRest())
460 fmr = false;
461
462 for (Segment* s = m->first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
463 for (int track = strack; track < etrack; ++track) {
464 ChordRest* cr = toChordRest(s->element(track));
465 if (cr && cr->isChord()) {
466 Chord* chord = toChord(cr);
467 if (chord->tremolo() && chord->tremolo()->twoNotes()) {
468 Tremolo* trem = chord->tremolo();
469
470 // Don't add same chord twice
471 if (trem->chord2() == chord)
472 continue;
473 auto newP = std::tuple<Fraction, Fraction, Tremolo*, int>(cr->tick(), trem->chord2()->segment()->tick(), trem, track);
474 tremoloChordTicks.push_back(newP);
475 }
476 }
477 }
478 }
479
480 if (m == lm)
481 break;
482 ++measures;
483 }
484
485 if (!fmr) {
486 // check for local time signatures
487 for (Measure* m = fm; m; m = m -> nextMeasure()) {
488 for (int si = 0; si < nstaves(); ++si) {
489 if (staff(si)->timeStretch(m->tick()) != Fraction(1,1)) {
490 // we cannot change a staff with a local time signature
491 return false;
492 }
493 if (m == lm)
494 break;
495 }
496 }
497 }
498
499 ScoreRange range;
500 range.read(fm->first(), lm->last());
501
502 //
503 // calculate number of required measures = nm
504 //
505 Fraction k = range.ticks() / ns;
506 int nm = (k.numerator() + k.denominator() - 1)/ k.denominator();
507
508 Fraction nd = ns * Fraction(nm,1);
509
510 // evtl. we have to fill the last measure
511 Fraction fill = nd - range.ticks();
512 range.fill(fill);
513
514 for (Score* s : scoreList()) {
515 Measure* m1 = s->tick2measure(fm->tick());
516 Measure* m2 = s->tick2measure(lm->tick());
517
518 Fraction tick1 = m1->tick();
519 Fraction tick2 = m2->endTick();
520 auto spanners = s->spannerMap().findOverlapping(tick1.ticks(), tick2.ticks());
521 for (auto i : spanners) {
522 if (i.value->tick() >= tick1)
523 undo(new RemoveElement(i.value));
524 }
525 s->undoRemoveMeasures(m1, m2, true);
526
527 Measure* nfm = 0;
528 Measure* nlm = 0;
529 Fraction tick = { 0, 1};
530 for (int i = 0; i < nm; ++i) {
531 Measure* m = new Measure(s);
532 m->setPrev(nlm);
533 if (nlm)
534 nlm->setNext(m);
535 m->setTimesig(ns);
536 m->setTicks(ns);
537 m->setTick(tick);
538 tick += m->ticks();
539 nlm = m;
540 if (nfm == 0)
541 nfm = m;
542 }
543 // nlm->setEndBarLineType(m2->endBarLineType(), m2->endBarLineGenerated(),
544 // m2->endBarLineVisible(), m2->endBarLineColor());
545 //
546 // insert new calculated measures
547 //
548 nfm->setPrev(m1->prev());
549 nlm->setNext(m2->next());
550 s->undo(new InsertMeasures(nfm, nlm));
551 }
552 if (!fill.isZero())
553 undoInsertTime(lm->endTick(), fill);
554
555 if (!range.write(masterScore(), fm->tick()))
556 return false;
557 connectTies(true);
558
559 // Attempt to move tremolos to correct chords
560 for (auto tremPair : tremoloChordTicks) {
561 Fraction chord1Tick = std::get<0>(tremPair);
562 Fraction chord2Tick = std::get<1>(tremPair);
563 Tremolo* trem = std::get<2>(tremPair);
564 int track = std::get<3>(tremPair);
565
566 undo(new MoveTremolo(trem->score(), chord1Tick, chord2Tick, trem, track));
567 }
568
569 if (noteEntryMode()) {
570 // set input cursor to possibly re-written segment
571 Fraction icTick = inputPos();
572 Segment* icSegment = tick2segment(icTick, false, SegmentType::ChordRest);
573 if (!icSegment) {
574 // this can happen if cursor was on a rest
575 // and in the rewriting it got subsumed into a full measure rest
576 Measure* icMeasure = tick2measure(icTick);
577 if (!icMeasure) // shouldn't happen, but just in case
578 icMeasure = firstMeasure();
579 icSegment = icMeasure->first(SegmentType::ChordRest);
580 }
581 inputState().setSegment(icSegment);
582 }
583
584 return true;
585 }
586
587 //---------------------------------------------------------
588 // rewriteMeasures
589 // rewrite all measures up to the next time signature or section break
590 //---------------------------------------------------------
591
rewriteMeasures(Measure * fm,const Fraction & ns,int staffIdx)592 bool Score::rewriteMeasures(Measure* fm, const Fraction& ns, int staffIdx)
593 {
594 Measure* lm = fm;
595 Measure* fm1 = fm;
596 Measure* nm = nullptr;
597 LayoutBreak* sectionBreak = nullptr;
598
599 // disable local time sig modifications in linked staves
600 if (staffIdx != -1 && excerpts().size() > 0) {
601 MScore::setError(CANNOT_CHANGE_LOCAL_TIMESIG);
602 return false;
603 }
604
605 //
606 // split into Measure segments fm-lm
607 //
608 for (MeasureBase* measure = fm; ; measure = measure->next()) {
609
610 if (!measure || !measure->isMeasure() || lm->sectionBreak()
611 || (toMeasure(measure)->first(SegmentType::TimeSig) && measure != fm))
612 {
613
614 // save section break to reinstate after rewrite
615 if (lm->sectionBreak())
616 sectionBreak = new LayoutBreak(*lm->sectionBreakElement());
617
618 if (!rewriteMeasures(fm1, lm, ns, staffIdx)) {
619 if (staffIdx >= 0) {
620 MScore::setError(CANNOT_CHANGE_LOCAL_TIMESIG);
621 // restore measure rests that were prematurely modified
622 Fraction fr(staff(staffIdx)->timeSig(fm->tick())->sig());
623 for (Measure* m = fm1; m; m = m->nextMeasure()) {
624 ChordRest* cr = m->findChordRest(m->tick(), staffIdx * VOICES);
625 if (cr && cr->isRest() && cr->durationType() == TDuration::DurationType::V_MEASURE)
626 cr->undoChangeProperty(Pid::DURATION, QVariant::fromValue(fr));
627 else
628 break;
629 }
630 }
631 else {
632 // this can be hit for local time signatures as well
633 // (if we are rewriting all staves, but one has a local time signature)
634 // TODO: detect error conditions better, have clearer error messages
635 // and perform necessary fixups
636 MScore::setError(TUPLET_CROSSES_BAR);
637 }
638 for (Measure* m = fm1; m; m = m->nextMeasure()) {
639 if (m->first(SegmentType::TimeSig))
640 break;
641 Fraction fr(ns);
642 m->undoChangeProperty(Pid::TIMESIG_NOMINAL, QVariant::fromValue(fr));
643 }
644 return false;
645 }
646
647 // after rewrite, lm is not necessarily valid
648 // m is first MeasureBase after rewritten range
649 // m->prevMeasure () is new last measure of range
650 // set nm to first true Measure after rewritten range
651 // we may use this to reinstate time signatures
652 if (measure && measure->prevMeasure())
653 nm = measure->prevMeasure()->nextMeasure();
654 else
655 nm = nullptr;
656
657 if (sectionBreak) {
658 // reinstate section break, then stop rewriting
659 if (measure && measure->prevMeasure()) {
660 sectionBreak->setParent(measure->prevMeasure());
661 undoAddElement(sectionBreak);
662 }
663 else if (!measure) {
664 sectionBreak->setParent(lastMeasure());
665 undoAddElement(sectionBreak);
666 }
667 else {
668 qDebug("unable to restore section break");
669 nm = nullptr;
670 sectionBreak = nullptr;
671 }
672 break;
673 }
674
675 // stop rewriting at end of score
676 // or at a measure (which means we found a time signature segment)
677 if (!measure || measure->isMeasure())
678 break;
679
680 // skip frames
681 while (!measure->isMeasure()) {
682 if (measure->sectionBreak()) {
683 // frame has a section break; we can stop skipping ahead
684 sectionBreak = measure->sectionBreakElement();
685 break;
686 }
687 measure = measure->next();
688 if (!measure)
689 break;
690 }
691 // stop rewriting if we encountered a section break on a frame
692 // or if there is a time signature on first measure after the frame
693 if (sectionBreak || (measure && toMeasure(measure)->first(SegmentType::TimeSig)))
694 break;
695
696 // set up for next range to rewrite
697 fm1 = toMeasure(measure);
698 if (fm1 == 0)
699 break;
700 }
701
702 // if we didn't break the loop already,
703 // we must have an ordinary measure
704 // add measure to range to rewrite
705 lm = toMeasure(measure);
706 }
707
708 // if any staves don't have time signatures at the point where we stopped,
709 // we need to reinstate their previous time signatures
710 if (!nm)
711 return true;
712 Segment* s = nm->undoGetSegment(SegmentType::TimeSig, nm->tick());
713 for (int i = 0; i < nstaves(); ++i) {
714 if (!s->element(i * VOICES)) {
715 TimeSig* ots = staff(i)->timeSig(nm->tick());
716 if (ots) {
717 TimeSig* nts = new TimeSig(*ots);
718 nts->setParent(s);
719 if (sectionBreak) {
720 nts->setGenerated(false);
721 nts->setShowCourtesySig(false);
722 }
723 undoAddElement(nts);
724 }
725 }
726 }
727
728 return true;
729 }
730
731 //---------------------------------------------------------
732 // cmdAddTimeSig
733 //
734 // Add or change time signature at measure in response
735 // to gui command (drop timesig on measure or timesig)
736 //---------------------------------------------------------
737
cmdAddTimeSig(Measure * fm,int staffIdx,TimeSig * ts,bool local)738 void Score::cmdAddTimeSig(Measure* fm, int staffIdx, TimeSig* ts, bool local)
739 {
740 deselectAll();
741
742 if (fm->isMMRest())
743 fm = fm->mmRestFirst();
744
745 Fraction ns = ts->sig();
746 Fraction tick = fm->tick();
747 TimeSig* lts = staff(staffIdx)->timeSig(tick);
748 if (local) {
749 Fraction stretch = (ns / fm->timesig()).reduced();
750 ts->setStretch(stretch);
751 }
752
753 Fraction stretch;
754 Fraction lsig; // last signature
755 if (lts) {
756 stretch = lts->stretch();
757 lsig = lts->sig();
758 }
759 else {
760 stretch.set(1,1);
761 lsig.set(4,4); // set to default
762 }
763
764 int track = staffIdx * VOICES;
765 Segment* seg = fm->undoGetSegment(SegmentType::TimeSig, tick);
766 TimeSig* ots = toTimeSig(seg->element(track));
767
768 if (ots && (*ots == *ts)) {
769 //
770 // ignore if there is already a timesig
771 // with same values
772 //
773 delete ts;
774 return;
775 }
776
777 auto getStaffIdxRange = [this, local, staffIdx](const Score* score) -> std::pair<int /*start*/, int /*end*/> {
778 int startStaffIdx, endStaffIdx;
779 if (local) {
780 if (score == this) {
781 startStaffIdx = staffIdx;
782 endStaffIdx = startStaffIdx + 1;
783 }
784 else {
785 // TODO: get index for this score
786 qDebug("cmdAddTimeSig: unable to write local time signature change to linked score");
787 startStaffIdx = 0;
788 endStaffIdx = 0;
789 }
790 }
791 else {
792 startStaffIdx = 0;
793 endStaffIdx = score->nstaves();
794 }
795 return std::make_pair(startStaffIdx, endStaffIdx);
796 };
797
798 if (ots && ots->sig() == ns && ots->stretch() == ts->stretch()) {
799 //
800 // the measure duration does not change,
801 // so its ok to just update the time signatures
802 //
803 TimeSig* nts = staff(staffIdx)->nextTimeSig(tick + Fraction::fromTicks(1));
804 const Fraction lmTick = nts ? nts->segment()->tick() : Fraction(-1, 1);
805 for (Score* score : scoreList()) {
806 Measure* mf = score->tick2measure(tick);
807 Measure* lm = (lmTick != Fraction(-1, 1)) ? score->tick2measure(lmTick) : nullptr;
808 for (Measure* m = mf; m != lm; m = m->nextMeasure()) {
809 bool changeActual = m->ticks() == m->timesig();
810 m->undoChangeProperty(Pid::TIMESIG_NOMINAL, QVariant::fromValue(ns));
811 if (changeActual)
812 m->undoChangeProperty(Pid::TIMESIG_ACTUAL, QVariant::fromValue(ns));
813 }
814 std::pair<int, int> staffIdxRange = getStaffIdxRange(score);
815 for (int si = staffIdxRange.first; si < staffIdxRange.second; ++si) {
816 TimeSig* nsig = toTimeSig(seg->element(si * VOICES));
817 if (!nsig)
818 continue;
819 nsig->undoChangeProperty(Pid::SHOW_COURTESY, ts->showCourtesySig());
820 nsig->undoChangeProperty(Pid::TIMESIG, QVariant::fromValue(ts->sig()));
821 nsig->undoChangeProperty(Pid::TIMESIG_TYPE, int(ts->timeSigType()));
822 nsig->undoChangeProperty(Pid::NUMERATOR_STRING, ts->numeratorString());
823 nsig->undoChangeProperty(Pid::DENOMINATOR_STRING, ts->denominatorString());
824 nsig->undoChangeProperty(Pid::TIMESIG_STRETCH, QVariant::fromValue(ts->stretch()));
825 nsig->undoChangeProperty(Pid::GROUPS, QVariant::fromValue(ts->groups()));
826 nsig->setSelected(false);
827 nsig->setDropTarget(0);
828 }
829 }
830 }
831 else {
832 Score* mScore = masterScore();
833 Measure* mf = mScore->tick2measure(tick);
834
835 //
836 // rewrite all measures up to the next time signature
837 //
838 if (mf == mScore->firstMeasure() && mf->nextMeasure() && (mf->ticks() != mf->timesig())) {
839 // handle upbeat
840 mf->undoChangeProperty(Pid::TIMESIG_NOMINAL, QVariant::fromValue(ns));
841 Measure* m = mf->nextMeasure();
842 Segment* s = m->findSegment(SegmentType::TimeSig, m->tick());
843 mf = s ? 0 : mf->nextMeasure();
844 }
845 else {
846 if (sigmap()->timesig(seg->tick().ticks()).nominal().identical(ns)) {
847 // no change to global time signature,
848 // but we need to rewrite any staves with local time signatures
849 for (int i = 0; i < nstaves(); ++i) {
850 if (staff(i)->timeSig(tick) && staff(i)->timeSig(tick)->isLocal()) {
851 if (!mScore->rewriteMeasures(mf, ns, i)) {
852 undoStack()->current()->unwind();
853 return;
854 }
855 }
856 }
857 mf = 0;
858 }
859 }
860
861 // try to rewrite the measures first
862 // we will only add time signatures if this succeeds
863 // this means, however, that the rewrite cannot depend on the time signatures being in place
864 if (mf) {
865 if (!mScore->rewriteMeasures(mf, ns, local ? staffIdx : -1)) {
866 undoStack()->current()->unwind();
867 return;
868 }
869 }
870 // add the time signatures
871 std::map<int, TimeSig*> masterTimeSigs;
872 for (Score* score : scoreList()) {
873 Measure* nfm = score->tick2measure(tick);
874 seg = nfm->undoGetSegment(SegmentType::TimeSig, nfm->tick());
875 std::pair<int, int> staffIdxRange = getStaffIdxRange(score);
876 for (int si = staffIdxRange.first; si < staffIdxRange.second; ++si) {
877 TimeSig* nsig = toTimeSig(seg->element(si * VOICES));
878 if (nsig == 0) {
879 nsig = new TimeSig(*ts);
880 nsig->setScore(score);
881 nsig->setTrack(si * VOICES);
882 nsig->setParent(seg);
883 undoAddElement(nsig);
884 if (score->excerpt()) {
885 const int masterTrack = score->excerpt()->tracks().key(nsig->track());
886 TimeSig* masterTimeSig = masterTimeSigs[masterTrack];
887 if (masterTimeSig)
888 undo(new Link(masterTimeSig, nsig));
889 }
890 }
891 else {
892 nsig->undoChangeProperty(Pid::SHOW_COURTESY, ts->showCourtesySig());
893 nsig->undoChangeProperty(Pid::TIMESIG_TYPE, int(ts->timeSigType()));
894 nsig->undoChangeProperty(Pid::TIMESIG, QVariant::fromValue(ts->sig()));
895 nsig->undoChangeProperty(Pid::NUMERATOR_STRING, ts->numeratorString());
896 nsig->undoChangeProperty(Pid::DENOMINATOR_STRING, ts->denominatorString());
897
898 // HACK do it twice to accommodate undo
899 nsig->undoChangeProperty(Pid::TIMESIG_TYPE, int(ts->timeSigType()));
900 nsig->undoChangeProperty(Pid::TIMESIG_STRETCH, QVariant::fromValue(ts->stretch()));
901 nsig->undoChangeProperty(Pid::GROUPS, QVariant::fromValue(ts->groups()));
902 nsig->setSelected(false);
903 nsig->setDropTarget(0); // DEBUG
904 }
905
906 if (score->isMaster())
907 masterTimeSigs[nsig->track()] = nsig;
908 }
909 }
910 }
911 delete ts;
912 }
913
914 //---------------------------------------------------------
915 // cmdRemoveTimeSig
916 //---------------------------------------------------------
917
cmdRemoveTimeSig(TimeSig * ts)918 void Score::cmdRemoveTimeSig(TimeSig* ts)
919 {
920 if (ts->isLocal() && excerpts().size() > 0) {
921 MScore::setError(CANNOT_CHANGE_LOCAL_TIMESIG);
922 return;
923 }
924
925 Measure* m = ts->measure();
926 Segment* s = ts->segment();
927
928 //
929 // we cannot remove a courtesy time signature
930 //
931 if (m->tick() != s->tick())
932 return;
933 Fraction tick = m->tick();
934
935 // if we remove all time sigs from segment, segment will be already removed by now
936 // but this would leave us no means of detecting that we have have measures in a local timesig
937 // in cases where we try deleting the local time sig
938 // known bug: this means we do not correctly detect non-empty measures when deleting global timesig change after a local one
939 // see http://musescore.org/en/node/51596
940 // Delete the time sig segment from the root score, we will rewriteMeasures from it
941 // since it contains all the music while the part doesn't
942 Score* rScore = masterScore();
943 Measure* rm = rScore->tick2measure(m->tick());
944 Segment* rs = rm->findSegment(SegmentType::TimeSig, s->tick());
945 if (rs)
946 rScore->undoRemoveElement(rs);
947
948 Measure* pm = m->prevMeasure();
949 Fraction ns(pm ? pm->timesig() : Fraction(4,4));
950
951 if (!rScore->rewriteMeasures(rm, ns, -1)) {
952 undoStack()->current()->unwind();
953 }
954 else {
955 m = tick2measure(tick); // old m may have been replaced
956 // hack: fix measure rest durations for staves with local time signatures
957 // if a time signature was deleted to reveal a previous local one,
958 // then rewriteMeasures() got the measure rest durations wrong
959 // (if we fixed it to work for delete, it would fail for add)
960 // so we will fix measure rest durations here
961 // TODO: fix rewriteMeasures() to get this right
962 for (int i = 0; i < nstaves(); ++i) {
963 TimeSig* tsig = staff(i)->timeSig(tick);
964 if (tsig && tsig->isLocal()) {
965 for (Measure* nm = m; nm; nm = nm->nextMeasure()) {
966 // stop when time signature changes
967 if (staff(i)->timeSig(nm->tick()) != tsig)
968 break;
969 // fix measure rest duration
970 ChordRest* cr = nm->findChordRest(nm->tick(), i * VOICES);
971 if (cr && cr->isRest() && cr->durationType() == TDuration::DurationType::V_MEASURE)
972 cr->undoChangeProperty(Pid::DURATION, QVariant::fromValue(nm->stretchedLen(staff(i))));
973 //cr->setTicks(nm->stretchedLen(staff(i)));
974 }
975 }
976 }
977 }
978 }
979
980 //---------------------------------------------------------
981 // addTiedMidiPitch
982 //---------------------------------------------------------
983
addTiedMidiPitch(int pitch,bool addFlag,Chord * prevChord)984 Note* Score::addTiedMidiPitch(int pitch, bool addFlag, Chord* prevChord)
985 {
986 Note* n = addMidiPitch(pitch, addFlag);
987 if (prevChord) {
988 Note* nn = prevChord->findNote(n->pitch());
989 if (nn) {
990 Tie* tie = new Tie(this);
991 tie->setStartNote(nn);
992 tie->setEndNote(n);
993 tie->setTick(tie->startNote()->tick());
994 tie->setTick2(tie->endNote()->tick());
995 tie->setTrack(n->track());
996 n->setTieBack(tie);
997 nn->setTieFor(tie);
998 undoAddElement(tie);
999 }
1000 }
1001 return n;
1002 }
1003
1004 //---------------------------------------------------------
1005 // addMidiPitch
1006 //---------------------------------------------------------
1007
addMidiPitch(int pitch,bool addFlag)1008 Note* Score::addMidiPitch(int pitch, bool addFlag)
1009 {
1010 NoteVal nval(pitch);
1011 Staff* st = staff(inputState().track() / VOICES);
1012
1013 // if transposing, interpret MIDI pitch as representing desired written pitch
1014 // set pitch based on corresponding sounding pitch
1015 if (!styleB(Sid::concertPitch))
1016 nval.pitch += st->part()->instrument(inputState().tick())->transpose().chromatic;
1017 // let addPitch calculate tpc values from pitch
1018 //Key key = st->key(inputState().tick());
1019 //nval.tpc1 = pitch2tpc(nval.pitch, key, Prefer::NEAREST);
1020 return addPitch(nval, addFlag);
1021 }
1022
1023 //---------------------------------------------------------
1024 // searchNote
1025 // search for note or rest before or at tick position tick
1026 // in staff
1027 //---------------------------------------------------------
1028
searchNote(const Fraction & tick,int track) const1029 ChordRest* Score::searchNote(const Fraction& tick, int track) const
1030 {
1031 ChordRest* ipe = 0;
1032 SegmentType st = SegmentType::ChordRest;
1033 for (Segment* segment = firstSegment(st); segment; segment = segment->next1(st)) {
1034 ChordRest* cr = segment->cr(track);
1035 if (!cr)
1036 continue;
1037 if (cr->tick() == tick)
1038 return cr;
1039 if (cr->tick() > tick)
1040 return ipe ? ipe : cr;
1041 ipe = cr;
1042 }
1043 return 0;
1044 }
1045
1046 //---------------------------------------------------------
1047 // regroupNotesAndRests
1048 // * combine consecutive rests into fewer rests of longer duration.
1049 // * combine tied notes/chords into fewer notes of longer duration.
1050 // Only operates on one voice - protects manual layout adjustment, etc.
1051 //---------------------------------------------------------
1052
regroupNotesAndRests(const Fraction & startTick,const Fraction & endTick,int track)1053 void Score::regroupNotesAndRests(const Fraction& startTick, const Fraction& endTick, int track)
1054 {
1055 Segment* inputSegment = _is.segment(); // store this so we can get back to it later.
1056 Segment* seg = tick2segment(startTick, true, SegmentType::ChordRest);
1057 for (Measure* msr = seg->measure(); msr && msr->tick() < endTick; msr = msr->nextMeasure()) {
1058 Fraction maxTick = endTick > msr->endTick() ? msr->endTick() : endTick;
1059 if (!seg || seg->measure() != msr)
1060 seg = msr->first(SegmentType::ChordRest);
1061 for (; seg; seg = seg->next(SegmentType::ChordRest)) {
1062 ChordRest* curr = seg->cr(track);
1063 if (!curr)
1064 continue; // this voice is empty here (CR overlaps with CR in other track)
1065 if (seg->tick() + curr->actualTicks() > maxTick)
1066 break; // outside range
1067 if (curr->isRest() && !(curr->tuplet()) && !(toRest(curr)->isGap())) {
1068 // combine consecutive rests
1069 ChordRest* lastRest = curr;
1070 for (Segment* s = seg->next(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
1071 ChordRest* cr = s->cr(track);
1072 if (!cr)
1073 continue; // this voice is empty here
1074 if (!cr->isRest() || s->tick() + cr->actualTicks() > maxTick || toRest(cr)->isGap())
1075 break; // next element in the same voice is not a rest, or it exceeds the selection, or it is a gap
1076 lastRest = cr;
1077 }
1078 Fraction restTicks = lastRest->tick() + lastRest->ticks() - curr->tick();
1079 seg = setNoteRest(seg, curr->track(), NoteVal(), restTicks, Direction::AUTO, false, true);
1080 }
1081 else if (curr->isChord()) {
1082 // combine tied chords
1083 Chord* chord = toChord(curr);
1084 Chord* lastTiedChord = chord;
1085 for (Chord* next = chord->nextTiedChord(); next && next->tick() + next->ticks() <= maxTick; next = next->nextTiedChord()) {
1086 lastTiedChord = next;
1087 }
1088 if (!lastTiedChord)
1089 lastTiedChord = chord;
1090 Fraction noteTicks = lastTiedChord->tick() + lastTiedChord->ticks() - chord->tick();
1091 if (!(curr->tuplet())) {
1092 // store start/end note for backward/forward ties ending/starting on the group of notes being rewritten
1093 size_t numNotes = chord->notes().size();
1094 #if (!defined (_MSCVER) && !defined (_MSC_VER))
1095 Note* tieBack[numNotes];
1096 Note* tieFor[numNotes];
1097 #else
1098 // MSVC does not support VLA. Replace with std::vector. If profiling determines that the
1099 // heap allocation is slow, an optimization might be used.
1100 std::vector<Note *> tieBack(numNotes);
1101 std::vector<Note *> tieFor(numNotes);
1102 #endif
1103 for (size_t i = 0; i < numNotes; i++) {
1104 Note* n = chord->notes()[i];
1105 Note* nn = lastTiedChord->notes()[i];
1106 if (n->tieBack())
1107 tieBack[i] = n->tieBack()->startNote();
1108 else
1109 tieBack[i] = 0;
1110 if (nn->tieFor())
1111 tieFor[i] = nn->tieFor()->endNote();
1112 else
1113 tieFor[i] = 0;
1114 }
1115 Fraction tick = seg->tick();
1116 int tr = chord->track();
1117 Fraction sd = noteTicks;
1118 Tie* tie = 0;
1119 Segment* segment = seg;
1120 ChordRest* cr = toChordRest(segment->element(tr));
1121 Chord* nchord = toChord(chord->clone());
1122 for (size_t i = 0; i < numNotes; i++) { // strip ties from cloned chord
1123 Note* n = nchord->notes()[i];
1124 n->setTieFor(0);
1125 n->setTieBack(0);
1126 }
1127 Chord* startChord = nchord;
1128 Measure* measure = 0;
1129 bool firstpart = true;
1130 for (;;) {
1131 if (tr % VOICES)
1132 expandVoice(segment, tr);
1133 // the returned gap ends at the measure boundary or at tuplet end
1134 Fraction dd = makeGap(segment, tr, sd, cr->tuplet());
1135 if (dd.isZero())
1136 break;
1137 measure = segment->measure();
1138 std::vector<TDuration> dl;
1139 dl = toRhythmicDurationList(dd, false, segment->rtick(), sigmap()->timesig(tick.ticks()).nominal(), measure, 1);
1140 size_t n = dl.size();
1141 for (size_t i = 0; i < n; ++i) {
1142 const TDuration& d = dl[i];
1143 Chord* nchord2 = toChord(nchord->clone());
1144 if (!firstpart)
1145 nchord2->removeMarkings(true);
1146 nchord2->setDurationType(d);
1147 nchord2->setTicks(d.fraction());
1148 std::vector<Note*> nl1 = nchord->notes();
1149 std::vector<Note*> nl2 = nchord2->notes();
1150 if (!firstpart)
1151 for (size_t j = 0; j < nl1.size(); ++j) {
1152 tie = new Tie(this);
1153 tie->setStartNote(nl1[j]);
1154 tie->setEndNote(nl2[j]);
1155 tie->setTick(tie->startNote()->tick());
1156 tie->setTick2(tie->endNote()->tick());
1157 tie->setTrack(tr);
1158 nl1[j]->setTieFor(tie);
1159 nl2[j]->setTieBack(tie);
1160 }
1161 undoAddCR(nchord2, measure, tick);
1162 segment = nchord2->segment();
1163 tick += nchord2->actualTicks();
1164 nchord = nchord2;
1165 firstpart = false;
1166 }
1167 sd -= dd;
1168 if (sd.isZero())
1169 break;
1170 Segment* nseg = tick2segment(tick, false, SegmentType::ChordRest);
1171 if (nseg == 0)
1172 break;
1173 segment = nseg;
1174 cr = toChordRest(segment->element(tr));
1175 if (cr == 0) {
1176 if (tr % VOICES)
1177 cr = addRest(segment, tr, TDuration(TDuration::DurationType::V_MEASURE), 0);
1178 else
1179 break;
1180 }
1181 }
1182 if (_is.slur()) {
1183 // extend slur
1184 _is.slur()->undoChangeProperty(Pid::SPANNER_TICKS, nchord->tick() - _is.slur()->tick());
1185 for (ScoreElement* e : _is.slur()->linkList()) {
1186 Slur* slur = toSlur(e);
1187 for (ScoreElement* ee : nchord->linkList()) {
1188 Element* e1 = static_cast<Element*>(ee);
1189 if (e1->score() == slur->score() && e1->track() == slur->track2()) {
1190 slur->score()->undo(new ChangeSpannerElements(slur, slur->startElement(), e1));
1191 break;
1192 }
1193 }
1194 }
1195 }
1196 // recreate previously stored pending ties
1197 for (size_t i = 0; i < numNotes; i++) {
1198 Note* n = startChord->notes()[i];
1199 Note* nn = nchord->notes()[i];
1200 if (tieBack[i]) {
1201 tie = new Tie(this);
1202 tie->setStartNote(tieBack[i]);
1203 tie->setEndNote(n);
1204 tie->setTick(tie->startNote()->tick());
1205 tie->setTick2(tie->endNote()->tick());
1206 tie->setTrack(track);
1207 n->setTieBack(tie);
1208 tieBack[i]->setTieFor(tie);
1209 undoAddElement(tie);
1210 }
1211 if (tieFor[i]) {
1212 tie = new Tie(this);
1213 tie->setStartNote(nn);
1214 tie->setEndNote(tieFor[i]);
1215 tie->setTick(tie->startNote()->tick());
1216 tie->setTick2(tie->endNote()->tick());
1217 tie->setTrack(track);
1218 n->setTieFor(tie);
1219 tieFor[i]->setTieBack(tie);
1220 undoAddElement(tie);
1221 }
1222 }
1223 if (tie) // at least one tie was created
1224 connectTies();
1225 }
1226 }
1227 }
1228 }
1229 // now put the input state back where it was before
1230 _is.setSegment(inputSegment);
1231 }
1232
1233 //---------------------------------------------------------
1234 // cmdTieNoteList
1235 //---------------------------------------------------------
1236
cmdTieNoteList(const Selection & selection,bool noteEntryMode)1237 std::vector<Note*> Score::cmdTieNoteList(const Selection& selection, bool noteEntryMode)
1238 {
1239 Element* el = selection.element();
1240 if (Note* n = InputState::note(el)) {
1241 if (noteEntryMode)
1242 return n->chord()->notes();
1243 else
1244 return { n };
1245 }
1246 else {
1247 ChordRest* cr = InputState::chordRest(el);
1248 if (cr && cr->isChord())
1249 return toChord(cr)->notes();
1250 }
1251 return selection.noteList();
1252 }
1253
1254 //---------------------------------------------------------
1255 // cmdAddTie
1256 //---------------------------------------------------------
1257
cmdAddTie(bool addToChord)1258 void Score::cmdAddTie(bool addToChord)
1259 {
1260 const std::vector<Note*> noteList = cmdTieNoteList(selection(), noteEntryMode());
1261
1262 if (noteList.empty()) {
1263 qDebug("no notes selected");
1264 return;
1265 }
1266
1267 startCmd();
1268 Chord* lastAddedChord = 0;
1269 for (Note* note : noteList) {
1270 if (note->tieFor()) {
1271 qDebug("cmdAddTie: note %p has already tie? noteFor: %p", note, note->tieFor());
1272 continue;
1273 }
1274
1275 if (noteEntryMode()) {
1276 ChordRest* cr = nullptr;
1277 Chord* c = note->chord();
1278
1279 // set cursor at position after note
1280 if (c->isGraceBefore()) {
1281 // tie grace note before to main note
1282 cr = toChord(c->parent());
1283 addToChord = true;
1284 }
1285 else {
1286 _is.setSegment(note->chord()->segment());
1287 _is.moveToNextInputPos();
1288 _is.setLastSegment(_is.segment());
1289
1290 if (_is.cr() == 0)
1291 expandVoice();
1292 cr = _is.cr();
1293 }
1294 if (cr == 0)
1295 break;
1296
1297 bool addFlag = lastAddedChord != nullptr;
1298
1299 // try to re-use existing note or chord
1300 Note* n = nullptr;
1301 if (addToChord && cr->isChord()) {
1302 Chord* chord = toChord(cr);
1303 Note* nn = chord->findNote(note->pitch());
1304 if (nn && nn->tpc() == note->tpc())
1305 n = nn; // re-use note
1306 else
1307 addFlag = true; // re-use chord
1308 }
1309
1310 // if no note to re-use, create one
1311 NoteVal nval(note->noteVal());
1312 if (!n)
1313 n = addPitch(nval, addFlag);
1314 else
1315 select(n);
1316
1317 if (n) {
1318 if (!lastAddedChord)
1319 lastAddedChord = n->chord();
1320 // n is not necessarily next note if duration span over measure
1321 Note* nnote = searchTieNote(note);
1322 while (nnote) {
1323 // DEBUG: if duration spans over measure
1324 // this does not set line for intermediate notes
1325 // tpc was set correctly already
1326 //n->setLine(note->line());
1327 //n->setTpc(note->tpc());
1328 Tie* tie = new Tie(this);
1329 tie->setStartNote(note);
1330 tie->setEndNote(nnote);
1331 tie->setTrack(note->track());
1332 tie->setTick(note->chord()->segment()->tick());
1333 tie->setTicks(nnote->chord()->segment()->tick() - note->chord()->segment()->tick());
1334 undoAddElement(tie);
1335 if (!addFlag || nnote->chord()->tick() >= lastAddedChord->tick() || nnote->chord()->isGrace()) {
1336 break;
1337 }
1338 else {
1339 note = nnote;
1340 _is.setLastSegment(_is.segment());
1341 nnote = addPitch(nval, true);
1342 }
1343 }
1344 }
1345 }
1346 else {
1347 Note* note2 = searchTieNote(note);
1348 if (note2) {
1349 Tie* tie = new Tie(this);
1350 tie->setStartNote(note);
1351 tie->setEndNote(note2);
1352 tie->setTrack(note->track());
1353 tie->setTick(note->chord()->segment()->tick());
1354 tie->setTicks(note2->chord()->segment()->tick() - note->chord()->segment()->tick());
1355 undoAddElement(tie);
1356 }
1357 }
1358 }
1359 if (lastAddedChord)
1360 nextInputPos(lastAddedChord, false);
1361 endCmd();
1362 }
1363
1364 //---------------------------------------------------------
1365 // cmdRemoveTie
1366 //---------------------------------------------------------
1367
cmdToggleTie()1368 void Score::cmdToggleTie()
1369 {
1370 const std::vector<Note*> noteList = cmdTieNoteList(selection(), noteEntryMode());
1371
1372 if (noteList.empty()) {
1373 qDebug("no notes selected");
1374 return;
1375 }
1376
1377 bool canAddTies = false;
1378 const size_t notes = noteList.size();
1379 std::vector<Note*> tieNoteList(notes);
1380
1381 for (size_t i = 0; i < notes; ++i) {
1382 Note* n = noteList[i];
1383 if (n->tieFor()) {
1384 tieNoteList[i] = nullptr;
1385 }
1386 else {
1387 Note* tieNote = searchTieNote(n);
1388 tieNoteList[i] = tieNote;
1389 if (tieNote)
1390 canAddTies = true;
1391 }
1392 }
1393
1394 startCmd();
1395
1396 if (canAddTies) {
1397 for (size_t i = 0; i < notes; ++i) {
1398 Note* note2 = tieNoteList[i];
1399 if (note2) {
1400 Note* note = noteList[i];
1401
1402 Tie* tie = new Tie(this);
1403 tie->setStartNote(note);
1404 tie->setEndNote(note2);
1405 tie->setTrack(note->track());
1406 tie->setTick(note->chord()->segment()->tick());
1407 tie->setTicks(note2->chord()->segment()->tick() - note->chord()->segment()->tick());
1408 undoAddElement(tie);
1409 }
1410 }
1411 }
1412 else {
1413 for (Note* n : noteList) {
1414 Tie* tie = n->tieFor();
1415 if (tie)
1416 undoRemoveElement(tie);
1417 }
1418 }
1419
1420 endCmd();
1421 }
1422
1423
1424 //---------------------------------------------------------
1425 // cmdAddOttava
1426 //---------------------------------------------------------
1427
cmdAddOttava(OttavaType type)1428 void Score::cmdAddOttava(OttavaType type)
1429 {
1430 const Selection sel = selection(); // copy selection state before the operation.
1431 // add on each staff if possible
1432 if (sel.isRange() && sel.staffStart() != sel.staffEnd() - 1) {
1433 for (int staffIdx = sel.staffStart() ; staffIdx < sel.staffEnd(); ++staffIdx) {
1434 ChordRest* cr1 = sel.firstChordRest(staffIdx * VOICES);
1435 ChordRest* cr2 = sel.lastChordRest(staffIdx * VOICES);
1436 if (!cr1)
1437 continue;
1438 if (cr2 == 0)
1439 cr2 = cr1;
1440 Ottava* ottava = new Ottava(this);
1441 ottava->setOttavaType(type);
1442 ottava->setTrack(cr1->track());
1443 ottava->setTrack2(cr1->track());
1444 ottava->setTick(cr1->tick());
1445 ottava->setTick2(cr2->tick() + cr2->actualTicks());
1446 undoAddElement(ottava);
1447 }
1448 }
1449 else {
1450 ChordRest* cr1;
1451 ChordRest* cr2;
1452 getSelectedChordRest2(&cr1, &cr2);
1453 if (!cr1)
1454 return;
1455 if (cr2 == 0)
1456 cr2 = cr1;
1457
1458 Ottava* ottava = new Ottava(this);
1459 ottava->setOttavaType(type);
1460
1461 ottava->setTrack(cr1->track());
1462 ottava->setTrack2(cr1->track());
1463 ottava->setTick(cr1->tick());
1464 ottava->setTick2(cr2->tick() + cr2->actualTicks());
1465 undoAddElement(ottava);
1466 if (!noteEntryMode())
1467 select(ottava, SelectType::SINGLE, 0);
1468 }
1469 }
1470
1471 //---------------------------------------------------------
1472 // cmdSetBeamMode
1473 //---------------------------------------------------------
1474
cmdSetBeamMode(Beam::Mode mode)1475 void Score::cmdSetBeamMode(Beam::Mode mode)
1476 {
1477 for (ChordRest* cr : getSelectedChordRests()) {
1478 if (cr)
1479 cr->undoChangeProperty(Pid::BEAM_MODE, int(mode));
1480 }
1481 }
1482
1483 //---------------------------------------------------------
1484 // cmdFlip
1485 //---------------------------------------------------------
1486
cmdFlip()1487 void Score::cmdFlip()
1488 {
1489 const QList<Element*>& el = selection().elements();
1490 if (el.empty()) {
1491 MScore::setError(NO_FLIPPABLE_SELECTED);
1492 return;
1493 }
1494
1495 std::set<const Element*> alreadyFlippedElements;
1496 auto flipOnce = [&alreadyFlippedElements](const Element* element, std::function<void()> flipFunction) -> void {
1497 if (alreadyFlippedElements.count(element) == 0) {
1498 alreadyFlippedElements.insert(element);
1499 flipFunction();
1500 }
1501 };
1502 for (Element* e : el) {
1503 if (e->isNote() || e->isStem() || e->isHook()) {
1504 Chord* chord = nullptr;
1505 if (e->isNote()) {
1506 auto note = toNote(e);
1507 chord = note->chord();
1508 }
1509 else if (e->isStem())
1510 chord = toStem(e)->chord();
1511 else
1512 chord = toHook(e)->chord();
1513
1514 if (chord->beam()) {
1515 if (!selection().isRange())
1516 e = chord->beam();
1517 else
1518 continue;
1519 }
1520 else {
1521 flipOnce(chord, [chord](){
1522 Direction dir = chord->up() ? Direction::DOWN : Direction::UP;
1523 chord->undoChangeProperty(Pid::STEM_DIRECTION, QVariant::fromValue<Direction>(dir));
1524 });
1525 }
1526 }
1527
1528 if (e->isBeam()) {
1529 auto beam = toBeam(e);
1530 flipOnce(beam, [beam](){
1531 Direction dir = beam->up() ? Direction::DOWN : Direction::UP;
1532 beam->undoChangeProperty(Pid::STEM_DIRECTION, QVariant::fromValue<Direction>(dir));
1533 });
1534 }
1535 else if (e->isSlurTieSegment()) {
1536 auto slurTieSegment = toSlurTieSegment(e)->slurTie();
1537 flipOnce(slurTieSegment, [slurTieSegment](){
1538 Direction dir = slurTieSegment->up() ? Direction::DOWN : Direction::UP;
1539 slurTieSegment->undoChangeProperty(Pid::SLUR_DIRECTION, QVariant::fromValue<Direction>(dir));
1540 });
1541 }
1542 else if (e->isArticulation()) {
1543 auto articulation = toArticulation(e);
1544 flipOnce(articulation, [articulation](){
1545 ArticulationAnchor articAnchor = articulation->anchor();
1546 switch (articAnchor) {
1547 case ArticulationAnchor::TOP_CHORD:
1548 articAnchor = ArticulationAnchor::BOTTOM_CHORD;
1549 break;
1550 case ArticulationAnchor::BOTTOM_CHORD:
1551 articAnchor = ArticulationAnchor::TOP_CHORD;
1552 break;
1553 case ArticulationAnchor::CHORD:
1554 articAnchor = articulation->up() ? ArticulationAnchor::BOTTOM_CHORD : ArticulationAnchor::TOP_CHORD;
1555 break;
1556 case ArticulationAnchor::TOP_STAFF:
1557 articAnchor = ArticulationAnchor::BOTTOM_STAFF;
1558 break;
1559 case ArticulationAnchor::BOTTOM_STAFF:
1560 articAnchor = ArticulationAnchor::TOP_STAFF;
1561 break;
1562 }
1563 PropertyFlags pf = articulation->propertyFlags(Pid::ARTICULATION_ANCHOR);
1564 if (pf == PropertyFlags::STYLED)
1565 pf = PropertyFlags::UNSTYLED;
1566 articulation->undoChangeProperty(Pid::ARTICULATION_ANCHOR, int(articAnchor), pf);
1567 });
1568 }
1569 else if (e->isTuplet()) {
1570 auto tuplet = toTuplet(e);
1571 flipOnce(tuplet, [tuplet](){
1572 Direction dir = tuplet->isUp() ? Direction::DOWN : Direction::UP;
1573 tuplet->undoChangeProperty(Pid::DIRECTION, QVariant::fromValue<Direction>(dir), PropertyFlags::UNSTYLED);
1574 });
1575 }
1576 else if (e->isNoteDot() && e->parent()->isNote()) {
1577 Note* note = toNote(e->parent());
1578 Direction d = note->dotIsUp() ? Direction::DOWN : Direction::UP;
1579 note->undoChangeProperty(Pid::DOT_POSITION, QVariant::fromValue<Direction>(d));
1580 }
1581 else if (e->isTempoText()
1582 || e->isSystemText()
1583 || e->isJump()
1584 || e->isMarker()
1585 || e->isStaffText()
1586 || e->isSticking()
1587 || e->isFingering()
1588 || e->isDynamic()
1589 || e->isHarmony()
1590 || e->isInstrumentChange()
1591 || e->isRehearsalMark()
1592 || e->isMeasureNumber()
1593 || e->isFretDiagram()
1594 || e->isHairpin()
1595 || e->isHairpinSegment()
1596 || e->isOttavaSegment()
1597 || e->isTextLineSegment()
1598 || e->isPedalSegment()
1599 || e->isLetRingSegment()
1600 || e->isPalmMuteSegment()
1601 || e->isFermata()
1602 || e->isLyrics()
1603 || e->isTrillSegment()
1604 || e->isBreath()) {
1605 e->undoChangeProperty(Pid::AUTOPLACE, true);
1606 // getProperty() delegates call from spannerSegment to Spanner
1607 Placement p = Placement(e->getProperty(Pid::PLACEMENT).toInt());
1608 p = (p == Placement::ABOVE) ? Placement::BELOW : Placement::ABOVE;
1609 // TODO: undoChangeProperty() should probably do this directly
1610 // see https://musescore.org/en/node/281432
1611 Element* ee = e->propertyDelegate(Pid::PLACEMENT);
1612 if (!ee)
1613 ee = e;
1614 PropertyFlags pf = ee->propertyFlags(Pid::PLACEMENT);
1615 if (pf == PropertyFlags::STYLED)
1616 pf = PropertyFlags::UNSTYLED;
1617 qreal oldDefaultY = ee->propertyDefault(Pid::OFFSET).toPointF().y();
1618 ee->undoChangeProperty(Pid::PLACEMENT, int(p), pf);
1619 // flip and rebase user offset to new default now that placement has changed
1620 qreal newDefaultY = ee->propertyDefault(Pid::OFFSET).toPointF().y();
1621 if (ee->isSpanner()) {
1622 Spanner* spanner = toSpanner(ee);
1623 for (SpannerSegment* ss : spanner->spannerSegments()) {
1624 if (!ss->isStyled(Pid::OFFSET)) {
1625 QPointF off = ss->getProperty(Pid::OFFSET).toPointF();
1626 qreal oldY = off.y() - oldDefaultY;
1627 off.ry() = newDefaultY - oldY;
1628 ss->undoChangeProperty(Pid::OFFSET, off);
1629 ss->setOffsetChanged(false);
1630 }
1631 }
1632 }
1633 else if (!ee->isStyled(Pid::OFFSET)) {
1634 QPointF off = ee->getProperty(Pid::OFFSET).toPointF();
1635 qreal oldY = off.y() - oldDefaultY;
1636 off.ry() = newDefaultY - oldY;
1637 ee->undoChangeProperty(Pid::OFFSET, off);
1638 ee->setOffsetChanged(false);
1639 }
1640 }
1641 }
1642 }
1643
1644 //---------------------------------------------------------
1645 // deleteItem
1646 //---------------------------------------------------------
1647
deleteItem(Element * el)1648 void Score::deleteItem(Element* el)
1649 {
1650 if (!el)
1651 return;
1652 // cannot remove generated elements
1653 if (el->generated() && !(el->isBracket() || el->isBarLine() || el->isClef() || el->isMeasureNumber()))
1654 return;
1655 // qDebug("%s", el->name());
1656
1657 switch (el->type()) {
1658 case ElementType::INSTRUMENT_NAME: {
1659 Part* part = el->part();
1660 InstrumentName* in = toInstrumentName(el);
1661 if (in->instrumentNameType() == InstrumentNameType::LONG)
1662 undo(new ChangeInstrumentLong(Fraction(0,1), part, QList<StaffName>()));
1663 else if (in->instrumentNameType() == InstrumentNameType::SHORT)
1664 undo(new ChangeInstrumentShort(Fraction(0,1), part, QList<StaffName>()));
1665 }
1666 break;
1667
1668 case ElementType::TIMESIG: {
1669 // timesig might already be removed
1670 TimeSig* ts = toTimeSig(el);
1671 Segment* s = ts->segment();
1672 Measure* m = s->measure();
1673 Segment* ns = m->findSegment(s->segmentType(), s->tick());
1674 if (!ns || (ns->element(ts->track()) != ts)) {
1675 qDebug("deleteItem: not found");
1676 break;
1677 }
1678 cmdRemoveTimeSig(ts);
1679 }
1680 break;
1681
1682 case ElementType::KEYSIG:
1683 {
1684 KeySig* k = toKeySig(el);
1685 undoRemoveElement(k);
1686 for (int i = 0; i < k->part()->nstaves(); i++) {
1687 Staff* staff = k->part()->staff(i);
1688 KeySigEvent e = staff->keySigEvent(k->tick());
1689 updateInstrumentChangeTranspositions(e, staff, k->tick());
1690 }
1691 }
1692 break;
1693
1694 case ElementType::NOTE:
1695 {
1696 Chord* chord = toChord(el->parent());
1697 if (chord->notes().size() > 1) {
1698 undoRemoveElement(el);
1699 select(chord->downNote(), SelectType::SINGLE, 0);
1700 break;
1701 }
1702 // else fall through
1703 el = chord;
1704 }
1705 // fall through
1706
1707 case ElementType::CHORD:
1708 {
1709 Chord* chord = toChord(el);
1710 removeChordRest(chord, false);
1711
1712 // replace with rest
1713 if (chord->noteType() == NoteType::NORMAL) {
1714 Rest* rest = new Rest(this, chord->durationType());
1715 rest->setDurationType(chord->durationType());
1716 rest->setTicks(chord->ticks());
1717
1718 rest->setTrack(el->track());
1719 rest->setParent(chord->parent());
1720
1721 Segment* segment = chord->segment();
1722 undoAddCR(rest, segment->measure(), segment->tick());
1723
1724 Tuplet* tuplet = chord->tuplet();
1725 if (tuplet) {
1726 QList<ScoreElement*> tl = tuplet->linkList();
1727 for (ScoreElement* e : rest->linkList()) {
1728 DurationElement* de = toDurationElement(e);
1729 for (ScoreElement* ee : qAsConst(tl)) {
1730 Tuplet* t = toTuplet(ee);
1731 if (t->score() == de->score() && t->track() == de->track()) {
1732 de->setTuplet(t);
1733 t->add(de);
1734 break;
1735 }
1736 }
1737 }
1738 }
1739 //select(rest, SelectType::SINGLE, 0);
1740 }
1741 else {
1742 // remove segment if empty
1743 Segment* seg = chord->segment();
1744 if (seg->empty())
1745 undoRemoveElement(seg);
1746 }
1747 }
1748 break;
1749
1750 case ElementType::REPEAT_MEASURE:
1751 {
1752 RepeatMeasure* rm = toRepeatMeasure(el);
1753 removeChordRest(rm, false);
1754 Rest* rest = new Rest(this);
1755 rest->setDurationType(TDuration::DurationType::V_MEASURE);
1756 rest->setTicks(rm->measure()->stretchedLen(rm->staff()));
1757 rest->setTrack(rm->track());
1758 rest->setParent(rm->parent());
1759 Segment* segment = rm->segment();
1760 undoAddCR(rest, segment->measure(), segment->tick());
1761 }
1762 // fall through
1763
1764 case ElementType::REST:
1765 //
1766 // only allow for voices != 0
1767 // e.g. voice 0 rests cannot be removed
1768 //
1769 {
1770 Rest* rest = toRest(el);
1771 if (rest->tuplet() && rest->tuplet()->elements().empty())
1772 undoRemoveElement(rest->tuplet());
1773 if ((el->voice() != 0) && !rest->tuplet()) {
1774 rest->undoChangeProperty(Pid::GAP, true);
1775 for (ScoreElement* r : el->linkList()) {
1776 Rest* rr = toRest(r);
1777 if (rr->track() % VOICES)
1778 rr->undoChangeProperty(Pid::GAP, true);
1779 }
1780
1781 // delete them really when only gap rests are in the actual measure.
1782 Measure* m = toRest(el)->measure();
1783 int track = el->track();
1784 if (m->isOnlyDeletedRests(track)) {
1785 static const SegmentType st { SegmentType::ChordRest };
1786 for (const Segment* s = m->first(st); s; s = s->next(st)) {
1787 Element* del = s->element(track);
1788 if (s->segmentType() != st || !del)
1789 continue;
1790 if (toRest(del)->isGap())
1791 undoRemoveElement(del);
1792 }
1793 checkSpanner(m->tick(), m->endTick());
1794 }
1795 else {
1796 // check if the other rest could be combined
1797 Segment* s = toRest(el)->segment();
1798
1799 std::vector<Rest*> rests;
1800 // find previous segment with cr in this track
1801 Element* pe = 0;
1802 for (Segment* ps = s->prev(SegmentType::ChordRest); ps; ps = ps->prev(SegmentType::ChordRest)) {
1803 Element* elm = ps->element(track);
1804 if (elm && elm->isRest() && toRest(elm)->isGap()) {
1805 pe = el;
1806 rests.push_back(toRest(elm));
1807 }
1808 else if (elm)
1809 break;
1810 }
1811 // find next segment with cr in this track
1812 Segment* ns;
1813 Element* ne = 0;
1814 for (ns = s->next(SegmentType::ChordRest); ns; ns = ns->next(SegmentType::ChordRest)) {
1815 Element* elm = ns->element(track);
1816 if (elm && elm->isRest() && toRest(elm)->isGap()) {
1817 ne = elm;
1818 rests.push_back(toRest(elm));
1819 }
1820 else if (elm)
1821 break;
1822 }
1823
1824 Fraction stick = pe ? pe->tick() : s->tick();
1825 Fraction ticks = { 0, 1 };
1826
1827 if (ne)
1828 ticks = ne->tick() - stick + toRest(ne)->actualTicks();
1829 else if (ns)
1830 ticks = ns->tick() - stick;
1831 else
1832 ticks = m->ticks() + m->tick() - stick;
1833
1834 if (ticks != m->ticks() && ticks != s->ticks()) {
1835 undoRemoveElement(rest);
1836 for (Rest* r : rests) {
1837 undoRemoveElement(r);
1838 }
1839
1840 Fraction f = ticks;
1841
1842 std::vector<TDuration> dList = toDurationList(f, true);
1843 if (dList.empty())
1844 break;
1845
1846 for (const TDuration& d : dList) {
1847 Rest* rr = new Rest(this);
1848 rr->setTicks(d.fraction());
1849 rr->setDurationType(d);
1850 rr->setTrack(track);
1851 rr->setGap(true);
1852 undoAddCR(rr, m, stick);
1853 }
1854 }
1855 }
1856 // Set input position
1857 // TODO If deleted element is last of a sequence, use prev?
1858 if (noteEntryMode())
1859 score()->move("prev-chord");
1860 }
1861 }
1862 break;
1863
1864 case ElementType::ACCIDENTAL:
1865 if (el->parent()->isNote())
1866 changeAccidental(toNote(el->parent()), AccidentalType::NONE);
1867 else
1868 undoRemoveElement(el);
1869 break;
1870
1871 case ElementType::BAR_LINE: {
1872 BarLine* bl = toBarLine(el);
1873 Segment* s = bl->segment();
1874 Measure* m = s->measure();
1875 if (s->isBeginBarLineType() || s->isBarLineType()) {
1876 undoRemoveElement(el);
1877 }
1878 else {
1879 if (bl->barLineType() == BarLineType::START_REPEAT) {
1880 Measure* m2 = m->isMMRest() ? m->mmRestFirst() : m;
1881 for (Score* lscore : score()->scoreList()) {
1882 Measure* lmeasure = lscore->tick2measure(m2->tick());
1883 if (lmeasure)
1884 lmeasure->undoChangeProperty(Pid::REPEAT_START, false);
1885 }
1886 }
1887 else if (bl->barLineType() == BarLineType::END_REPEAT) {
1888 Measure* m2 = m->isMMRest() ? m->mmRestLast() : m;
1889 for (Score* lscore : score()->scoreList()) {
1890 Measure* lmeasure = lscore->tick2measure(m2->tick());
1891 if (lmeasure)
1892 lmeasure->undoChangeProperty(Pid::REPEAT_END, false);
1893 }
1894 }
1895 else {
1896 bl->undoChangeProperty(Pid::BARLINE_TYPE, QVariant::fromValue(BarLineType::NORMAL));
1897 }
1898 }
1899 }
1900 break;
1901
1902 case ElementType::TUPLET:
1903 cmdDeleteTuplet(toTuplet(el), true);
1904 break;
1905
1906 case ElementType::MEASURE: {
1907 Measure* m = toMeasure(el);
1908 undoRemoveMeasures(m, m);
1909 undoInsertTime(m->tick(), -(m->endTick() - m->tick()));
1910 }
1911 break;
1912
1913 case ElementType::BRACKET:
1914 undoRemoveBracket(toBracket(el));
1915 break;
1916
1917 case ElementType::LAYOUT_BREAK:
1918 {
1919 undoRemoveElement(el);
1920 LayoutBreak* lb = toLayoutBreak(el);
1921 MeasureBase* mb = lb->measure();
1922 Measure* m = mb && mb->isMeasure() ? toMeasure(mb) : nullptr;
1923 if (m && m->isMMRest()) {
1924 // propagate to original measure
1925 m = m->mmRestLast();
1926 for (Element* e : m->el()) {
1927 if (e->isLayoutBreak()) {
1928 undoRemoveElement(e);
1929 break;
1930 }
1931 }
1932 }
1933 }
1934 break;
1935
1936 case ElementType::CLEF:
1937 {
1938 Clef* clef = toClef(el);
1939 Measure* m = clef->measure();
1940 if (m->isMMRest()) {
1941 // propagate to original measure
1942 m = m->mmRestLast();
1943 Segment* s = m->findSegment(SegmentType::Clef, clef->segment()->tick());
1944 if (s && s->element(clef->track())) {
1945 Clef* c = toClef(s->element(clef->track()));
1946 undoRemoveElement(c);
1947 }
1948 }
1949 else {
1950 if (clef->generated()) {
1951 // find the real clef if this is a cautionary one
1952 if (m && m->prevMeasure()) {
1953 Fraction tick = m->tick();
1954 m = m->prevMeasure();
1955 Segment* s = m->findSegment(SegmentType::Clef, tick);
1956 if (s && s->element(clef->track()))
1957 clef = toClef(s->element(clef->track()));
1958 }
1959 }
1960 undoRemoveElement(clef);
1961 }
1962 }
1963 break;
1964
1965 case ElementType::MEASURE_NUMBER:
1966 {
1967 Measure* mea = toMeasure(el->parent());
1968 switch (mea->measureNumberMode()) {
1969 // If the user tries to remove an automatically generated measure number,
1970 // we should force the measure not to show any measure number
1971 case MeasureNumberMode::AUTO:
1972 mea->undoChangeProperty(Pid::MEASURE_NUMBER_MODE, static_cast<int>(MeasureNumberMode::HIDE));
1973 break;
1974
1975 // If the user tries to remove a measure number that he added manually,
1976 // then we should set the MeasureNumberMode to AUTO only if will not show if set to auto.
1977 // If after setting the MeasureNumberMode to AUTO, the measure number still shows,
1978 // We need to force the measure to hide its measure number.
1979 case MeasureNumberMode::SHOW:
1980 if (mea->showsMeasureNumberInAutoMode())
1981 mea->undoChangeProperty(Pid::MEASURE_NUMBER_MODE, static_cast<int>(MeasureNumberMode::HIDE));
1982 else
1983 mea->undoChangeProperty(Pid::MEASURE_NUMBER_MODE, static_cast<int>(MeasureNumberMode::AUTO));
1984 break;
1985 case MeasureNumberMode::HIDE:
1986 break;
1987 }
1988 }
1989 break;
1990 case ElementType::REHEARSAL_MARK:
1991 case ElementType::TEMPO_TEXT:
1992 {
1993 Segment* s = toSegment(el->parent());
1994 Measure* m = s->measure();
1995 if (m->isMMRest()) {
1996 // propagate to original measure/element
1997 m = m->mmRestFirst();
1998 Segment* ns = m->findSegment(SegmentType::ChordRest, s->tick());
1999 for (Element* e : ns->annotations()) {
2000 if (e->type() == el->type() && e->track() == el->track()) {
2001 el = e;
2002 undoRemoveElement(el);
2003 break;
2004 }
2005 }
2006 }
2007 else
2008 undoRemoveElement(el);
2009 }
2010 break;
2011
2012 case ElementType::OTTAVA_SEGMENT:
2013 case ElementType::HAIRPIN_SEGMENT:
2014 case ElementType::TRILL_SEGMENT:
2015 case ElementType::VIBRATO_SEGMENT:
2016 case ElementType::TEXTLINE_SEGMENT:
2017 case ElementType::VOLTA_SEGMENT:
2018 case ElementType::SLUR_SEGMENT:
2019 case ElementType::TIE_SEGMENT:
2020 case ElementType::LYRICSLINE_SEGMENT:
2021 case ElementType::PEDAL_SEGMENT:
2022 case ElementType::GLISSANDO_SEGMENT:
2023 case ElementType::LET_RING_SEGMENT:
2024 case ElementType::PALM_MUTE_SEGMENT:
2025 {
2026 el = toSpannerSegment(el)->spanner();
2027 undoRemoveElement(el);
2028 }
2029 break;
2030
2031 case ElementType::STEM_SLASH: // cannot delete this elements
2032 case ElementType::HOOK:
2033 qDebug("cannot remove %s", el->name());
2034 break;
2035
2036 case ElementType::TEXT:
2037 if ((el->parent() && el->parent()->isTBox()) || el->isTBox())
2038 el->undoChangeProperty(Pid::TEXT, QString());
2039 else
2040 undoRemoveElement(el);
2041 break;
2042
2043 case ElementType::INSTRUMENT_CHANGE:
2044 {
2045 InstrumentChange* ic = static_cast<InstrumentChange*>(el);
2046 Fraction tickStart = ic->segment()->tick();
2047 Part* part = ic->part();
2048 Interval oldV = part->instrument(tickStart)->transpose();
2049 undoRemoveElement(el);
2050 for (KeySig* keySig : ic->keySigs())
2051 deleteItem(keySig);
2052 for (Clef* clef : ic->clefs())
2053 deleteItem(clef);
2054 if (part->instrument(tickStart)->transpose() != oldV) {
2055 auto i = part->instruments()->upper_bound(tickStart.ticks());
2056 Fraction tickEnd;
2057 if (i == part->instruments()->end())
2058 tickEnd = Fraction(-1, 1);
2059 else
2060 tickEnd = Fraction::fromTicks(i->first);
2061 transpositionChanged(part, oldV, tickStart, tickEnd);
2062 }
2063 }
2064 break;
2065
2066 case ElementType::MARKER:
2067 {
2068 Measure* m = toMeasure(el->parent());
2069 if (m->isMMRest()) {
2070 // find corresponding marker in underlying measure
2071 bool found = false;
2072 // the marker may be in the first measure...
2073 for (Element* e : m->mmRestFirst()->el()) {
2074 if (e->isMarker() && e->subtype() == el->subtype()) {
2075 undoRemoveElement(e);
2076 found = true;
2077 break;
2078 }
2079 }
2080 if (!found) {
2081 // ...or it may be in the last measure
2082 for (Element* e : m->mmRestLast()->el()) {
2083 if (e->isMarker() && e->subtype() == el->subtype()) {
2084 undoRemoveElement(e);
2085 break;
2086 }
2087 }
2088 }
2089 }
2090 // whether m is an mmrest or not, we still need to remove el
2091 undoRemoveElement(el);
2092 }
2093 break;
2094
2095 case ElementType::JUMP:
2096 {
2097 Measure* m = toMeasure(el->parent());
2098 if (m->isMMRest()) {
2099 // find corresponding jump in underlying measure
2100 for (Element* e : m->mmRestLast()->el()) {
2101 if (e->isJump() && e->subtype() == el->subtype()) {
2102 undoRemoveElement(e);
2103 break;
2104 }
2105 }
2106 }
2107 // whether m is an mmrest or not, we still need to remove el
2108 undoRemoveElement(el);
2109 }
2110 break;
2111
2112 default:
2113 undoRemoveElement(el);
2114 break;
2115 }
2116 }
2117
2118 //---------------------------------------------------------
2119 // deleteMeasures
2120 //---------------------------------------------------------
2121
deleteMeasures(MeasureBase * is,MeasureBase * ie,bool preserveTies)2122 void Score::deleteMeasures(MeasureBase* is, MeasureBase* ie, bool preserveTies)
2123 {
2124 // qDebug("deleteMeasures %p %p", is, ie);
2125
2126 #if 0
2127 if (!selection().isRange())
2128 return;
2129
2130 MeasureBase* is = selection().startSegment()->measure();
2131 if (is->isMeasure() && toMeasure(is)->isMMRest())
2132 is = toMeasure(is)->mmRestFirst();
2133 Segment* seg = selection().endSegment();
2134 MeasureBase* ie;
2135
2136 // choose the correct last measure based on the end segment
2137 // this depends on whether a whole measure is selected or only a few notes within it
2138 if (seg)
2139 ie = seg->prev() ? seg->measure() : seg->measure()->prev();
2140 else
2141 ie = lastMeasure();
2142 #endif
2143
2144 select(0, SelectType::SINGLE, 0);
2145
2146 // createEndBar if last measure is deleted
2147 bool createEndBar = false;
2148 if (ie->isMeasure()) {
2149 Measure* iem = toMeasure(ie);
2150 if (iem->isMMRest())
2151 ie = /*iem = */iem->mmRestLast();
2152 //TODO createEndBar = (iem == lastMeasureMM()) && (iem->endBarLineType() == BarLineType::END);
2153 createEndBar = false;
2154 }
2155
2156
2157 // get the last deleted timesig & keysig in order to restore after deletion
2158 KeySigEvent lastDeletedKeySigEvent;
2159 TimeSig* lastDeletedSig = 0;
2160 KeySig* lastDeletedKeySig = 0;
2161 bool transposeKeySigEvent = false;
2162
2163 for (MeasureBase* mb = ie;; mb = mb->prev()) {
2164 if (mb->isMeasure()) {
2165 Measure* m = toMeasure(mb);
2166 Segment* sts = m->findSegment(SegmentType::TimeSig, m->tick());
2167 if (sts && !lastDeletedSig)
2168 lastDeletedSig = toTimeSig(sts->element(0));
2169 sts = m->findSegment(SegmentType::KeySig, m->tick());
2170 if (sts && !lastDeletedKeySig) {
2171 lastDeletedKeySig = toKeySig(sts->element(0));
2172 if (lastDeletedKeySig) {
2173 lastDeletedKeySigEvent = lastDeletedKeySig->keySigEvent();
2174 if (!styleB(Sid::concertPitch) && !lastDeletedKeySigEvent.isAtonal() && !lastDeletedKeySigEvent.custom()) {
2175 // convert to concert pitch
2176 transposeKeySigEvent = true;
2177 Interval v = staff(0)->part()->instrument(m->tick())->transpose();
2178 if (!v.isZero())
2179 lastDeletedKeySigEvent.setKey(transposeKey(lastDeletedKeySigEvent.key(), v, lastDeletedKeySig->part()->preferSharpFlat()));
2180 }
2181 }
2182 }
2183 if (lastDeletedSig && lastDeletedKeySig)
2184 break;
2185 }
2186 if (mb == is)
2187 break;
2188 }
2189 Fraction startTick = is->tick();
2190 Fraction endTick = ie->tick();
2191
2192 undoInsertTime(is->tick(), -(ie->endTick() - is->tick()));
2193 for (Score* score : scoreList()) {
2194 Measure* mis = score->tick2measure(startTick);
2195 Measure* mie = score->tick2measure(endTick);
2196
2197 score->undoRemoveMeasures(mis, mie, preserveTies);
2198
2199 // adjust views
2200 Measure* focusOn = mis->prevMeasure() ? mis->prevMeasure() : score->firstMeasure();
2201 for (MuseScoreView* v : qAsConst(score->viewer))
2202 v->adjustCanvasPosition(focusOn, false);
2203
2204 if (createEndBar) {
2205 // Measure* lastMeasure = score->lastMeasure();
2206 //TODO if (lastMeasure && lastMeasure->endBarLineType() == BarLineType::NORMAL)
2207 // score->undoChangeEndBarLineType(lastMeasure, BarLineType::END);
2208 }
2209
2210 // insert correct timesig after deletion
2211 Measure* mBeforeSel = mis->prevMeasure();
2212 Measure* mAfterSel = mBeforeSel ? mBeforeSel->nextMeasure() : score->firstMeasure();
2213 if (mAfterSel && lastDeletedSig) {
2214 bool changed = true;
2215 if (mBeforeSel) {
2216 if (mBeforeSel->timesig() == mAfterSel->timesig()) {
2217 changed = false;
2218 }
2219 }
2220 Segment* s = mAfterSel->findSegment(SegmentType::TimeSig, mAfterSel->tick());
2221 if (!s && changed) {
2222 Segment* ns = mAfterSel->undoGetSegment(SegmentType::TimeSig, mAfterSel->tick());
2223 for (int staffIdx = 0; staffIdx < score->nstaves(); staffIdx++) {
2224 TimeSig* nts = new TimeSig(score);
2225 nts->setTrack(staffIdx * VOICES);
2226 nts->setParent(ns);
2227 nts->setSig(lastDeletedSig->sig(), lastDeletedSig->timeSigType());
2228 score->undoAddElement(nts);
2229 }
2230 }
2231 }
2232 // insert correct keysig if necessary
2233 if (mAfterSel && !mBeforeSel && lastDeletedKeySig) {
2234 Segment* s = mAfterSel->findSegment(SegmentType::KeySig, mAfterSel->tick());
2235 if (!s) {
2236 Segment* ns = mAfterSel->undoGetSegment(SegmentType::KeySig, mAfterSel->tick());
2237 for (int staffIdx = 0; staffIdx < score->nstaves(); staffIdx++) {
2238 KeySigEvent nkse = lastDeletedKeySigEvent;
2239 if (transposeKeySigEvent) {
2240 Interval v = score->staff(staffIdx)->part()->instrument(Fraction(0,1))->transpose();
2241 v.flip();
2242 nkse.setKey(transposeKey(nkse.key(), v, lastDeletedKeySig->part()->preferSharpFlat()));
2243 }
2244 KeySig* nks = new KeySig(score);
2245 nks->setTrack(staffIdx * VOICES);
2246 nks->setParent(ns);
2247 nks->setKeySigEvent(nkse);
2248 score->undoAddElement(nks);
2249 }
2250 }
2251 }
2252 }
2253
2254 _is.setSegment(0); // invalidate position
2255 }
2256
2257 //---------------------------------------------------------
2258 // deleteSpannersFromRange
2259 /// Deletes spanners in the given range that match the
2260 /// given selection filter.
2261 //---------------------------------------------------------
2262
deleteSpannersFromRange(const Fraction & t1,const Fraction & t2,int track1,int track2,const SelectionFilter & filter)2263 void Score::deleteSpannersFromRange(const Fraction& t1, const Fraction& t2, int track1, int track2, const SelectionFilter& filter)
2264 {
2265 auto spanners = _spanner.findOverlapping(t1.ticks(), t2.ticks() - 1);
2266 for (auto i : spanners) {
2267 Spanner* sp = i.value;
2268 if (sp->isVolta())
2269 continue;
2270 if (!filter.canSelectVoice(sp->track()))
2271 continue;
2272 if (sp->track() >= track1 && sp->track() < track2) {
2273 if (sp->tick() >= t1 && sp->tick() < t2
2274 && sp->tick2() >= t1 && sp->tick2() <= t2) {
2275 undoRemoveElement(sp);
2276 }
2277 else if (sp->isSlur() && ((sp->tick() >= t1 && sp->tick() < t2)
2278 || (sp->tick2() >= t1 && sp->tick2() < t2))) {
2279 undoRemoveElement(sp);
2280 }
2281 }
2282 }
2283 }
2284
2285 //---------------------------------------------------------
2286 // deleteAnnotationsFromRange
2287 /// Deletes annotations in the given range that match the
2288 /// given selection filter.
2289 //---------------------------------------------------------
2290
deleteAnnotationsFromRange(Segment * s1,Segment * s2,int track1,int track2,const SelectionFilter & filter)2291 void Score::deleteAnnotationsFromRange(Segment* s1, Segment* s2, int track1, int track2, const SelectionFilter& filter)
2292 {
2293 if (!s1)
2294 return;
2295 if (s2 && (*s2) < (*s1))
2296 return;
2297
2298 for (int track = track1; track < track2; ++track) {
2299 if (!filter.canSelectVoice(track))
2300 continue;
2301 for (Segment* s = s1; s && s != s2; s = s->next1()) {
2302 const auto annotations = s->annotations(); // make a copy since we alter the list
2303 for (Element* annotation : annotations) {
2304 // skip if not included in selection (eg, filter)
2305 if (!filter.canSelect(annotation))
2306 continue;
2307 if (!annotation->systemFlag() && annotation->track() == track)
2308 deleteItem(annotation);
2309 }
2310 }
2311 }
2312 }
2313
2314 //---------------------------------------------------------
2315 // deleteRange
2316 /// Deletes elements in the given range that match the
2317 /// given selection filter.
2318 /// \return A chord/rest inside the selected range
2319 /// that can be used to establish a selection after this
2320 /// deletion operation.
2321 //---------------------------------------------------------
2322
deleteRange(Segment * s1,Segment * s2,int track1,int track2,const SelectionFilter & filter)2323 ChordRest* Score::deleteRange(Segment* s1, Segment* s2, int track1, int track2, const SelectionFilter& filter)
2324 {
2325 ChordRest* cr = nullptr;
2326
2327 if (s1) {
2328 // delete content from measures underlying mmrests
2329 if (s1 && s1->measure() && s1->measure()->isMMRest())
2330 s1 = s1->measure()->mmRestFirst()->first();
2331 if (s2 && s2->measure() && s2->measure()->isMMRest())
2332 s2 = s2->measure()->mmRestLast()->last();
2333
2334 const Fraction stick1 = s1->tick();
2335 const Fraction stick2 = s2 ? s2->tick() : lastMeasure()->endTick();
2336
2337 Segment* ss1 = s1;
2338 if (!ss1->isChordRestType())
2339 ss1 = ss1->next1(SegmentType::ChordRest);
2340 bool fullMeasure = ss1 && (ss1->measure()->first(SegmentType::ChordRest) == ss1)
2341 && (s2 == 0 || s2->isEndBarLineType());
2342
2343 Fraction tick2 = s2 ? s2->tick() : Fraction(INT_MAX, 1);
2344
2345 deleteSpannersFromRange(stick1, stick2, track1, track2, filter);
2346
2347 for (int track = track1; track < track2; ++track) {
2348 if (!filter.canSelectVoice(track))
2349 continue;
2350 Fraction f;
2351 Fraction tick = Fraction(-1, 1);
2352 Tuplet* tuplet = 0;
2353 for (Segment* s = s1; s && (s->tick() < stick2); s = s->next1()) {
2354 if (s->element(track) && s->isBreathType()) {
2355 deleteItem(s->element(track));
2356 continue;
2357 }
2358 // delete annotations just from this segment and track
2359 deleteAnnotationsFromRange(s, s->next1(), track, track + 1, filter);
2360
2361 Element* e = s->element(track);
2362 if (!e)
2363 continue;
2364 if (!s->isChordRestType()) {
2365 // do not delete TimeSig/KeySig,
2366 // it doesn't make sense to do it, except on full system
2367 if (s->segmentType() != SegmentType::TimeSig && s->segmentType() != SegmentType::KeySig) {
2368 if (!(e->isBarLine()))
2369 undoRemoveElement(e);
2370 }
2371 continue;
2372 }
2373 ChordRest* cr1 = toChordRest(e);
2374 if (tick == Fraction(-1, 1)) {
2375 // first ChordRest found:
2376 Fraction offset = cr1->rtick();
2377 if (cr1->measure()->tick() >= s1->tick() && offset.isNotZero()) {
2378 f = offset;
2379 tick = s->measure()->tick();
2380 }
2381 else {
2382 tick = s->tick();
2383 f = Fraction(0, 1);
2384 }
2385 tuplet = cr1->tuplet();
2386 if (tuplet && (tuplet->tick() == tick) && ((tuplet->tick() + tuplet->actualTicks()) <= tick2) ) {
2387 // remove complete top level tuplet
2388
2389 Tuplet* t = cr1->tuplet();
2390 while (t->tuplet())
2391 t = t->tuplet();
2392 cmdDeleteTuplet(t, false);
2393 f += t->ticks();
2394 tuplet = 0;
2395 continue;
2396 }
2397 }
2398 if (tuplet != cr1->tuplet()) {
2399 Tuplet* t = cr1->tuplet();
2400 if (t && (((t->tick() + t->actualTicks()) <= tick2) || fullMeasure)) {
2401 // remove complete top level tuplet
2402
2403 while (t->tuplet())
2404 t = t->tuplet();
2405 cmdDeleteTuplet(t, false);
2406 f += t->ticks();
2407 tuplet = 0;
2408 continue;
2409 }
2410 if (f.isValid())
2411 setRest(tick, track, f, false, tuplet);
2412 tick = cr1->tick();
2413 tuplet = cr1->tuplet();
2414 removeChordRest(cr1, true);
2415 f = cr1->ticks();
2416 }
2417 else {
2418 removeChordRest(cr1, true);
2419 f += cr1->ticks();
2420 }
2421 }
2422 if (f.isValid() && !f.isZero()) {
2423 if (fullMeasure) {
2424 // handle this as special case to be able to
2425 // fix broken measures:
2426 Staff* staff = Score::staff(track / VOICES);
2427 for (Measure* m = s1->measure(); m; m = m->nextMeasure()) {
2428 Fraction tick3 = m->tick();
2429 Fraction ff = m->stretchedLen(staff);
2430 Rest* r = setRest(tick3, track, ff, false, 0);
2431 if (!cr)
2432 cr = r;
2433 if (s2 && (m == s2->measure()))
2434 break;
2435 }
2436 }
2437 else {
2438 Rest* r = setRest(tick, track, f, false, tuplet);
2439 if (!cr)
2440 cr = r;
2441 }
2442 }
2443 }
2444 }
2445 return cr;
2446 }
2447
2448 //---------------------------------------------------------
2449 // cmdDeleteSelection
2450 //---------------------------------------------------------
2451
cmdDeleteSelection()2452 void Score::cmdDeleteSelection()
2453 {
2454 ChordRest* cr = 0; // select something after deleting notes
2455
2456 if (selection().isRange()) {
2457 Segment* s1 = selection().startSegment();
2458 Segment* s2 = selection().endSegment();
2459 const Fraction stick1 = selection().tickStart();
2460 const Fraction stick2 = selection().tickEnd();
2461 cr = deleteRange(s1, s2, staff2track(selection().staffStart()), staff2track(selection().staffEnd()), selectionFilter());
2462 s1 = tick2segment(stick1);
2463 s2 = tick2segment(stick2, true);
2464 if (s1 == 0 || s2 == 0)
2465 deselectAll();
2466 else {
2467 _selection.setStartSegment(s1);
2468 _selection.setEndSegment(s2);
2469 _selection.updateSelectedElements();
2470 }
2471 }
2472 else {
2473 // deleteItem modifies selection().elements() list,
2474 // so we need a local copy:
2475 QList<Element*> el = selection().elements();
2476
2477 // keep track of linked elements that are deleted implicitly
2478 // so we don't try to delete them twice if they are also in selection
2479 QList<ScoreElement*> deletedElements;
2480 // Similarly, deleting one spanner segment, will delete all of them
2481 // so we don't try to delete them twice if they are also in selection
2482 QList<Spanner*> deletedSpanners;
2483
2484 for (Element* e : el) {
2485 // these are the linked elements we are about to delete
2486 QList<ScoreElement*> links;
2487 if (e->links())
2488 links = *e->links();
2489
2490 // find location of element to select after deleting notes
2491 // get tick of element itself if that is valid
2492 // or of spanner or parent if that is more valid
2493 Fraction tick = { -1, 1 };
2494 int track = -1;
2495 if (!cr) {
2496 if (e->isNote())
2497 tick = toNote(e)->chord()->tick();
2498 else if (e->isRest())
2499 tick = toRest(e)->tick();
2500 else if (e->isSpannerSegment())
2501 tick = toSpannerSegment(e)->spanner()->tick();
2502 else if (e->parent()
2503 && (e->parent()->isSegment() || e->parent()->isChord() || e->parent()->isNote() || e->parent()->isRest()))
2504 tick = e->parent()->tick();
2505 //else tick < 0
2506 track = e->track();
2507 }
2508
2509 // delete element if we have not done so already
2510 if (!deletedElements.contains(e)) {
2511 // do not delete two spanner segments from the same spanner
2512 if (e->isSpannerSegment()) {
2513 Spanner* spanner = toSpannerSegment(e)->spanner();
2514 if (deletedSpanners.contains(spanner))
2515 continue;
2516 else {
2517 QList<ScoreElement*> linkedSpanners;
2518 if (spanner->links())
2519 linkedSpanners = *spanner->links();
2520 else
2521 linkedSpanners.append(spanner);
2522 for (ScoreElement* se : qAsConst(linkedSpanners))
2523 deletedSpanners.append(toSpanner(se));
2524 }
2525 }
2526 deleteItem(e);
2527 }
2528
2529 // find element to select
2530 if (!cr && tick >= Fraction(0,1) && track >= 0)
2531 cr = findCR(tick, track);
2532
2533 // add these linked elements to list of already-deleted elements
2534 for (ScoreElement* se : qAsConst(links))
2535 deletedElements.append(se);
2536 }
2537
2538 }
2539
2540 deselectAll();
2541 // make new selection if appropriate
2542 if (noteEntryMode())
2543 cr = _is.cr();
2544 if (cr) {
2545 if (cr->isChord())
2546 select(toChord(cr)->upNote(), SelectType::SINGLE);
2547 else
2548 select(cr, SelectType::SINGLE);
2549 }
2550 }
2551
2552 //---------------------------------------------------------
2553 // cmdFullMeasureRest
2554 //---------------------------------------------------------
2555
cmdFullMeasureRest()2556 void Score::cmdFullMeasureRest()
2557 {
2558 Segment* s1 = nullptr;
2559 Segment* s2 = nullptr;
2560 Fraction stick1 = { -1, 1 };
2561 Fraction stick2 = { -1, 1 };
2562 int track1 = -1;
2563 int track2 = -1;
2564 Rest* r = nullptr;
2565
2566 if (noteEntryMode()) {
2567 s1 = inputState().segment();
2568 if (!s1 || s1->rtick().isNotZero())
2569 return;
2570 Measure* m = s1->measure();
2571 s2 = m->last();
2572 stick1 = s1->tick();
2573 stick2 = s2->tick();
2574 track1 = inputState().track();
2575 track2 = track1 + 1;
2576 }
2577 else if (selection().isRange()) {
2578 s1 = selection().startSegment();
2579 s2 = selection().endSegment();
2580 if (styleB(Sid::createMultiMeasureRests)) {
2581 // use underlying measures
2582 if (s1 && s1->measure()->isMMRest())
2583 s1 = tick2segment(stick1);
2584 if (s2 && s2->measure()->isMMRest())
2585 s2 = tick2segment(stick2, true);
2586 }
2587 stick1 = selection().tickStart();
2588 stick2 = selection().tickEnd();
2589 Segment* ss1 = s1;
2590 if (ss1 && ss1->segmentType() != SegmentType::ChordRest)
2591 ss1 = ss1->next1(SegmentType::ChordRest);
2592 bool fullMeasure = ss1 && (ss1->measure()->first(SegmentType::ChordRest) == ss1)
2593 && (s2 == 0 || (s2->segmentType() == SegmentType::EndBarLine)
2594 || (s2->segmentType() == SegmentType::TimeSigAnnounce)
2595 || (s2->segmentType() == SegmentType::KeySigAnnounce));
2596 if (!fullMeasure) {
2597 return;
2598 }
2599 track1 = selection().staffStart() * VOICES;
2600 track2 = selection().staffEnd() * VOICES;
2601 }
2602 else if (selection().cr()) {
2603 ChordRest* cr = selection().cr();
2604 if (!cr || cr->rtick().isNotZero())
2605 return;
2606 Measure* m = cr->measure();
2607 s1 = m->first();
2608 s2 = m->last();
2609 stick1 = s1->tick();
2610 stick2 = s2->tick();
2611 track1 = selection().cr()->track();
2612 track2 = track1 + 1;
2613 }
2614 else {
2615 return;
2616 }
2617
2618 for (int track = track1; track < track2; ++track) {
2619 if (selection().isRange() && !selectionFilter().canSelectVoice(track))
2620 continue;
2621 // first pass - remove non-initial rests from empty measures/voices
2622 for (Segment* s = s1; s != s2; s = s->next1()) {
2623 if (!(s->measure()->isOnlyRests(track))) // Don't remove anything from measures that contain notes
2624 continue;
2625 if (s->segmentType() != SegmentType::ChordRest || !s->element(track))
2626 continue;
2627 ChordRest* cr = toChordRest(s->element(track));
2628 // keep first rest of measure as placeholder (replaced in second pass)
2629 // but delete all others
2630 if (s->rtick().isNotZero())
2631 removeChordRest(cr, true);
2632 }
2633 // second pass - replace placeholders with full measure rests
2634 for (Measure* m = s1->measure(); m; m = m->nextMeasure()) {
2635 if (m->isOnlyRests(track)) {
2636 ChordRest* cr = m->findChordRest(m->tick(), track);
2637 if (cr) {
2638 removeChordRest(cr, true);
2639 r = addRest(m->tick(), track, TDuration(TDuration::DurationType::V_MEASURE), 0);
2640 }
2641 else if (noteEntryMode()) {
2642 // might be no cr at input position
2643 r = addRest(m->tick(), track, TDuration(TDuration::DurationType::V_MEASURE), 0);
2644 }
2645 }
2646 if (s2 && (m == s2->measure()))
2647 break;
2648 }
2649 }
2650
2651 // selected range is probably empty now and possibly subsumed by an mmrest
2652 // so updating selection requires forcing mmrests to be updated first
2653 //TODO-ws if (styleB(Sid::createMultiMeasureRests))
2654 // createMMRests();
2655 s1 = tick2segmentMM(stick1);
2656 s2 = tick2segmentMM(stick2, true);
2657 if (selection().isRange() && s1 && s2) {
2658 _selection.setStartSegment(s1);
2659 _selection.setEndSegment(s2);
2660 _selection.updateSelectedElements();
2661 }
2662 else if (r) {
2663 // note entry mode
2664 select(r, SelectType::SINGLE);
2665 }
2666 else {
2667 deselectAll();
2668 }
2669 }
2670
2671 //---------------------------------------------------------
2672 // addLyrics
2673 // called from Keyboard Accelerator & menu
2674 //---------------------------------------------------------
2675
addLyrics()2676 Lyrics* Score::addLyrics()
2677 {
2678 Element* el = selection().element();
2679 if (el == 0 || (!el->isNote() && !el->isLyrics() && !el->isRest())) {
2680 MScore::setError(NO_LYRICS_SELECTED);
2681 return 0;
2682 }
2683 ChordRest* cr;
2684 if (el->isNote()) {
2685 cr = toNote(el)->chord();
2686 if(cr->isGrace())
2687 cr = toChordRest(cr->parent());
2688 }
2689 else if (el->isLyrics())
2690 cr = toLyrics(el)->chordRest();
2691 else if (el->isRest())
2692 cr = toChordRest(el);
2693 else
2694 return 0;
2695
2696 int no = int(cr->lyrics().size());
2697 Lyrics* lyrics = new Lyrics(this);
2698 lyrics->setTrack(cr->track());
2699 lyrics->setParent(cr);
2700 lyrics->setNo(no);
2701 undoAddElement(lyrics);
2702 select(lyrics, SelectType::SINGLE, 0);
2703 return lyrics;
2704 }
2705
2706 //---------------------------------------------------------
2707 // addHairpin
2708 //---------------------------------------------------------
2709
addHairpin(HairpinType t,const Fraction & tickStart,const Fraction & tickEnd,int track)2710 Hairpin* Score::addHairpin(HairpinType t, const Fraction& tickStart, const Fraction& tickEnd, int track)
2711 {
2712 Hairpin* pin = new Hairpin(this);
2713 pin->setHairpinType(t);
2714 if (t == HairpinType::CRESC_LINE) {
2715 pin->setBeginText("cresc.");
2716 pin->setContinueText("(cresc.)");
2717 }
2718 else if (t == HairpinType::DECRESC_LINE) {
2719 pin->setBeginText("dim.");
2720 pin->setContinueText("(dim.)");
2721 }
2722 pin->setTrack(track);
2723 pin->setTrack2(track);
2724 pin->setTick(tickStart);
2725 pin->setTick2(tickEnd);
2726 undoAddElement(pin);
2727 return pin;
2728 }
2729
2730 //---------------------------------------------------------
2731 // Score::addHairpin
2732 //---------------------------------------------------------
2733
addHairpin(HairpinType type,ChordRest * cr1,ChordRest * cr2,bool toCr2End)2734 Hairpin* Score::addHairpin(HairpinType type, ChordRest* cr1, ChordRest* cr2, bool toCr2End)
2735 {
2736 if (!cr1)
2737 return nullptr;
2738 if (!cr2)
2739 cr2 = cr1;
2740 Q_ASSERT(cr1->staffIdx() == cr2->staffIdx());
2741 const Fraction end = toCr2End ? cr2->tick() + cr2->actualTicks() : cr2->tick();
2742 return addHairpin(type, cr1->tick(), end, cr1->track());
2743 }
2744
2745 //---------------------------------------------------------
2746 // cmdCreateTuplet
2747 // replace cr with tuplet
2748 //---------------------------------------------------------
2749
cmdCreateTuplet(ChordRest * ocr,Tuplet * tuplet)2750 void Score::cmdCreateTuplet(ChordRest* ocr, Tuplet* tuplet)
2751 {
2752 int track = ocr->track();
2753 Measure* measure = ocr->measure();
2754 Fraction tick = ocr->tick();
2755
2756 if (ocr->tuplet())
2757 tuplet->setTuplet(ocr->tuplet());
2758 undoRemoveElement(ocr);
2759
2760 ChordRest* cr;
2761 if (ocr->isChord()) {
2762 cr = new Chord(this);
2763 foreach (Note* oldNote, toChord(ocr)->notes()) {
2764 Note* note = new Note(this);
2765 note->setPitch(oldNote->pitch());
2766 note->setTpc1(oldNote->tpc1());
2767 note->setTpc2(oldNote->tpc2());
2768 cr->add(note);
2769 }
2770 }
2771 else
2772 cr = new Rest(this);
2773
2774 Fraction an = (tuplet->ticks() * tuplet->ratio()) / tuplet->baseLen().fraction();
2775 int actualNotes = an.numerator() / an.denominator();
2776
2777 tuplet->setTrack(track);
2778 cr->setTuplet(tuplet);
2779 cr->setTrack(track);
2780 cr->setDurationType(tuplet->baseLen());
2781 cr->setTicks(tuplet->baseLen().fraction());
2782
2783 undoAddCR(cr, measure, tick);
2784
2785 Fraction ticks = cr->actualTicks();
2786
2787 for (int i = 0; i < (actualNotes-1); ++i) {
2788 tick += ticks;
2789 Rest* rest = new Rest(this);
2790 rest->setTuplet(tuplet);
2791 rest->setTrack(track);
2792 rest->setDurationType(tuplet->baseLen());
2793 rest->setTicks(tuplet->baseLen().fraction());
2794 undoAddCR(rest, measure, tick);
2795 }
2796 }
2797
2798 //---------------------------------------------------------
2799 // colorItem
2800 //---------------------------------------------------------
2801
colorItem(Element * element)2802 void Score::colorItem(Element* element)
2803 {
2804 QColor sc(element->color());
2805 QColor c = QColorDialog::getColor(sc);
2806 if (!c.isValid())
2807 return;
2808
2809 for (Element* e : selection().elements()) {
2810 if (e->color() != c) {
2811 e->undoChangeProperty(Pid::COLOR, c);
2812 e->setGenerated(false);
2813 addRefresh(e->abbox());
2814 if (e->isBarLine()) {
2815 // Element* ep = e->parent();
2816 // if (ep->isSegment() && toSegment(ep)->isEndBarLineType()) {
2817 // Measure* m = toSegment(ep)->measure();
2818 // BarLine* bl = toBarLine(e);
2819 // m->setEndBarLineType(bl->barLineType(), false, e->visible(), e->color());
2820 // }
2821 }
2822 }
2823 }
2824 deselectAll();
2825 }
2826
2827 //---------------------------------------------------------
2828 // cmdExchangeVoice
2829 //---------------------------------------------------------
2830
cmdExchangeVoice(int s,int d)2831 void Score::cmdExchangeVoice(int s, int d)
2832 {
2833 if (!selection().isRange()) {
2834 MScore::setError(NO_STAFF_SELECTED);
2835 return;
2836 }
2837 Fraction t1 = selection().tickStart();
2838 Fraction t2 = selection().tickEnd();
2839
2840 Measure* m1 = tick2measure(t1);
2841 Measure* m2 = tick2measure(t2);
2842
2843 if (selection().score()->excerpt())
2844 return;
2845
2846 if (t2 > m2->tick())
2847 m2 = m2->nextMeasure();
2848
2849 for (;;) {
2850 undoExchangeVoice(m1, s, d, selection().staffStart(), selection().staffEnd());
2851 m1 = m1->nextMeasure();
2852 if ((m1 == 0) || (m2 && (m1->tick() == m2->tick())))
2853 break;
2854 }
2855 }
2856
2857 //---------------------------------------------------------
2858 // cmdEnterRest
2859 //---------------------------------------------------------
2860
cmdEnterRest(const TDuration & d)2861 void Score::cmdEnterRest(const TDuration& d)
2862 {
2863 if (_is.track() == -1) {
2864 qDebug("cmdEnterRest: track -1");
2865 return;
2866 }
2867 startCmd();
2868 enterRest(d);
2869 endCmd();
2870 }
2871
2872 //---------------------------------------------------------
2873 // enterRest
2874 //---------------------------------------------------------
2875
enterRest(const TDuration & d,InputState * externalInputState)2876 void Score::enterRest(const TDuration& d, InputState* externalInputState)
2877 {
2878 InputState& is = externalInputState ? (*externalInputState) : _is;
2879
2880 expandVoice(is.segment(), is.track());
2881
2882 if (!is.cr()) {
2883 qDebug("cannot enter rest here");
2884 return;
2885 }
2886
2887 const int track = is.track();
2888 NoteVal nval;
2889 setNoteRest(is.segment(), track, nval, d.fraction(), Direction::AUTO, /* forceAccidental */ false, /* rhythmic */ false, externalInputState);
2890 is.moveToNextInputPos();
2891 if (!is.noteEntryMode() || is.usingNoteEntryMethod(NoteEntryMethod::STEPTIME))
2892 is.setRest(false); // continue with normal note entry
2893 }
2894
2895 //---------------------------------------------------------
2896 // removeChordRest
2897 // remove chord or rest
2898 // remove associated segment if empty
2899 // remove beam
2900 // remove slurs
2901 //---------------------------------------------------------
2902
removeChordRest(ChordRest * cr,bool clearSegment)2903 void Score::removeChordRest(ChordRest* cr, bool clearSegment)
2904 {
2905 QList<Segment*> segments;
2906 for (ScoreElement* e : cr->linkList()) {
2907 undo(new RemoveElement(static_cast<Element*>(e)));
2908 if (clearSegment) {
2909 Segment* s = cr->segment();
2910 if (!segments.contains(s))
2911 segments.append(s);
2912 }
2913 }
2914 for (Segment* s : segments) {
2915 if (s->empty())
2916 undo(new RemoveElement(s));
2917 }
2918 if (cr->beam()) {
2919 Beam* beam = cr->beam();
2920 if (beam->generated()) {
2921 beam->parent()->remove(beam);
2922 delete beam;
2923 }
2924 else
2925 undoRemoveElement(beam);
2926 }
2927 }
2928
2929 //---------------------------------------------------------
2930 // cmdDeleteTuplet
2931 // remove tuplet and replace with rest
2932 //---------------------------------------------------------
2933
cmdDeleteTuplet(Tuplet * tuplet,bool replaceWithRest)2934 void Score::cmdDeleteTuplet(Tuplet* tuplet, bool replaceWithRest)
2935 {
2936 foreach(DurationElement* de, tuplet->elements()) {
2937 if (de->isChordRest())
2938 removeChordRest(toChordRest(de), true);
2939 else {
2940 Q_ASSERT(de->isTuplet());
2941 cmdDeleteTuplet(toTuplet(de), false);
2942 }
2943 }
2944 if (replaceWithRest)
2945 setRest(tuplet->tick(), tuplet->track(), tuplet->ticks(), true, tuplet->tuplet());
2946 }
2947
2948 //---------------------------------------------------------
2949 // nextInputPos
2950 //---------------------------------------------------------
2951
nextInputPos(ChordRest * cr,bool doSelect)2952 void Score::nextInputPos(ChordRest* cr, bool doSelect)
2953 {
2954 ChordRest* ncr = nextChordRest(cr);
2955 if ((ncr == 0) && (_is.track() % VOICES)) {
2956 Segment* s = tick2segment(cr->tick() + cr->actualTicks(), false, SegmentType::ChordRest);
2957 int track = (cr->track() / VOICES) * VOICES;
2958 ncr = s ? toChordRest(s->element(track)) : 0;
2959 }
2960 if (ncr) {
2961 _is.setSegment(ncr->segment());
2962 if (doSelect)
2963 select(ncr, SelectType::SINGLE, 0);
2964 setPlayPos(ncr->tick());
2965 for (MuseScoreView* v : qAsConst(viewer))
2966 v->moveCursor();
2967 }
2968 }
2969
2970 //---------------------------------------------------------
2971 // insertMeasure
2972 // Create a new MeasureBase of type type and insert
2973 // before measure.
2974 // If measure is zero, append new MeasureBase.
2975 //---------------------------------------------------------
2976
insertMeasure(ElementType type,MeasureBase * measure,bool createEmptyMeasures,bool moveSignaturesClef)2977 void Score::insertMeasure(ElementType type, MeasureBase* measure, bool createEmptyMeasures, bool moveSignaturesClef)
2978 {
2979 Fraction tick;
2980 if (measure) {
2981 if (measure->isMeasure() && toMeasure(measure)->isMMRest()) {
2982 measure = toMeasure(measure)->prev();
2983 measure = measure ? measure->next() : firstMeasure();
2984 deselectAll();
2985 }
2986 tick = measure->tick();
2987 }
2988 else
2989 tick = last() ? last()->endTick() : Fraction(0,1);
2990
2991 Fraction f = sigmap()->timesig(tick.ticks()).nominal(); // use nominal time signature of current measure
2992 Measure* om = 0; // measure base in "this" score
2993 MeasureBase* rmb = 0; // measure base in root score (for linking)
2994 Fraction ticks = { 0, 1 };
2995
2996 for (Score* score : scoreList()) {
2997 MeasureBase* im = 0;
2998 if (measure) {
2999 if (measure->isMeasure())
3000 im = score->tick2measure(tick);
3001 else {
3002 if (!measure->links()) {
3003 if (measure->score() == score)
3004 im = measure;
3005 else
3006 qDebug("no links");
3007 }
3008 else {
3009 for (ScoreElement* m : *measure->links()) {
3010 if (measure->score() == score) {
3011 im = toMeasureBase(m);
3012 break;
3013 }
3014 }
3015 }
3016 }
3017 if (!im)
3018 qDebug("measure not found");
3019 }
3020 MeasureBase* mb = toMeasureBase(Element::create(type, score));
3021 mb->setTick(tick);
3022
3023 if (im)
3024 im = im->top(); // don't try to insert in front of nested frame
3025 mb->setNext(im);
3026 mb->setPrev(im ? im->prev() : score->last());
3027 if (mb->isMeasure()) {
3028 Measure* m = toMeasure(mb);
3029 m->setTimesig(f);
3030 m->setTicks(f);
3031 }
3032 undo(new InsertMeasures(mb, mb));
3033
3034 if (type == ElementType::MEASURE) {
3035 Measure* m = toMeasure(mb); // new measure
3036 ticks = m->ticks();
3037 Measure* mi = nullptr; // insert before
3038 if (im) {
3039 if (im->isMeasure())
3040 mi = toMeasure(im);
3041 else
3042 mi = score->tick2measure(im->tick());
3043 }
3044
3045 if (score->isMaster())
3046 om = m;
3047
3048 QList<TimeSig*> tsl;
3049 QList<KeySig*> ksl;
3050 QList<Clef*> cl;
3051 QList<Clef*> pcl;
3052
3053 //
3054 // remove clef, time and key signatures
3055 //
3056 if (moveSignaturesClef && mi) {
3057 for (int staffIdx = 0; staffIdx < score->nstaves(); ++staffIdx) {
3058 Measure* pm = mi->prevMeasure();
3059 if (pm) {
3060 Segment* ps = pm->findSegment(SegmentType::Clef, tick);
3061 if (ps && ps->enabled()) {
3062 Element* pc = ps->element(staffIdx * VOICES);
3063 if (pc) {
3064 pcl.push_back(toClef(pc));
3065 undo(new RemoveElement(pc));
3066 if (ps->empty())
3067 undoRemoveElement(ps);
3068 }
3069 }
3070 }
3071 for (Segment* s = mi->first(); s && s->rtick().isZero(); s = s->next()) {
3072 if (!s->enabled())
3073 continue;
3074 Element* e = s->element(staffIdx * VOICES);
3075 if (!e || e->generated())
3076 continue;
3077 Element* ee = 0;
3078 if (e->isKeySig()) {
3079 KeySig* ks = toKeySig(e);
3080 ksl.push_back(ks);
3081 ee = e;
3082 }
3083 else if (e->isTimeSig()) {
3084 TimeSig* ts = toTimeSig(e);
3085 tsl.push_back(ts);
3086 ee = e;
3087 }
3088 if (tick.isZero() && e->isClef()) {
3089 Clef* clef = toClef(e);
3090 cl.push_back(clef);
3091 ee = e;
3092 }
3093 if (ee) {
3094 undo(new RemoveElement(ee));
3095 if (s->empty())
3096 undoRemoveElement(s);
3097 }
3098 }
3099 }
3100 }
3101
3102
3103 //
3104 // move clef, time, key signatrues
3105 //
3106 for (TimeSig* ts : tsl) {
3107 TimeSig* nts = new TimeSig(*ts);
3108 Segment* s = m->undoGetSegmentR(SegmentType::TimeSig, Fraction(0,1));
3109 nts->setParent(s);
3110 undoAddElement(nts);
3111 }
3112 for (KeySig* ks : ksl) {
3113 KeySig* nks = new KeySig(*ks);
3114 Segment* s = m->undoGetSegmentR(SegmentType::KeySig, Fraction(0,1));
3115 nks->setParent(s);
3116 undoAddElement(nks);
3117 }
3118 for (Clef* clef : cl) {
3119 Clef* nClef = new Clef(*clef);
3120 Segment* s = m->undoGetSegmentR(SegmentType::HeaderClef, Fraction(0,1));
3121 nClef->setParent(s);
3122 undoAddElement(nClef);
3123 }
3124 Measure* pm = m->prevMeasure();
3125 for (Clef* clef : pcl) {
3126 Clef* nClef = new Clef(*clef);
3127 Segment* s = pm->undoGetSegment(SegmentType::Clef, tick);
3128 nClef->setParent(s);
3129 undoAddElement(nClef);
3130 }
3131 }
3132 else {
3133 // a frame, not a measure
3134 if (score->isMaster())
3135 rmb = mb;
3136 else if (rmb && mb != rmb) {
3137 mb->linkTo(rmb);
3138 if (rmb->isTBox())
3139 toTBox(mb)->text()->linkTo(toTBox(rmb)->text());
3140 }
3141 }
3142 }
3143
3144 undoInsertTime(tick, ticks);
3145
3146 if (om && !createEmptyMeasures) {
3147 //
3148 // fill measure with rest
3149 //
3150 Score* score = om->score();
3151
3152 // add rest to all staves and to all the staves linked to it
3153 for (int staffIdx = 0; staffIdx < score->nstaves(); ++staffIdx) {
3154 int track = staffIdx * VOICES;
3155 Rest* rest = new Rest(score, TDuration(TDuration::DurationType::V_MEASURE));
3156 Fraction timeStretch(score->staff(staffIdx)->timeStretch(om->tick()));
3157 rest->setTicks(om->ticks() * timeStretch);
3158 rest->setTrack(track);
3159 score->undoAddCR(rest, om, tick);
3160 }
3161 }
3162 deselectAll();
3163 }
3164
3165 //---------------------------------------------------------
3166 // checkSpanner
3167 // check if spanners are still valid as anchors may
3168 // have changed or be removed.
3169 // Spanners need to have a start anchor. Slurs need a
3170 // start and end anchor.
3171 //---------------------------------------------------------
3172
checkSpanner(const Fraction & startTick,const Fraction & endTick)3173 void Score::checkSpanner(const Fraction& startTick, const Fraction& endTick)
3174 {
3175 QList<Spanner*> sl; // spanners to remove
3176 QList<Spanner*> sl2; // spanners to shorten
3177 auto spanners = _spanner.findOverlapping(startTick.ticks(), endTick.ticks());
3178
3179 // DEBUG: check all spanner
3180 // there may be spanners outside of score bc. some measures were deleted
3181
3182 Fraction lastTick = lastMeasure()->endTick();
3183
3184 for (auto i : _spanner.map()) {
3185 Spanner* s = i.second;
3186
3187 if (s->isSlur()) {
3188 Segment* seg = tick2segmentMM(s->tick(), false, SegmentType::ChordRest);
3189 if (!seg || !seg->element(s->track()))
3190 sl.append(s);
3191 else {
3192 seg = tick2segmentMM(s->tick2(), false, SegmentType::ChordRest);
3193 if (!seg || !seg->element(s->track2()))
3194 sl.append(s);
3195 }
3196 }
3197 else {
3198 // remove spanner if there is no start element
3199 s->computeStartElement();
3200 if (!s->startElement()) {
3201 sl.append(s);
3202 qDebug("checkSpanner::remove (3)");
3203 }
3204 else {
3205 if (s->tick2() > lastTick)
3206 sl2.append(s); //s->undoChangeProperty(Pid::SPANNER_TICKS, lastTick - s->tick());
3207 else
3208 s->computeEndElement();
3209 }
3210 }
3211 }
3212 for (auto s : sl) // actually remove scheduled spanners
3213 undo(new RemoveElement(s));
3214 for (auto s : sl2) { // shorten spanners that extended past end of score
3215 undo(new ChangeProperty(s, Pid::SPANNER_TICKS, lastTick - s->tick()));
3216 s->computeEndElement();
3217 }
3218 }
3219
3220 static constexpr SegmentType CR_TYPE = SegmentType::ChordRest;
3221
3222 //---------------------------------------------------------
3223 // checkTimeDelete
3224 //---------------------------------------------------------
3225
checkTimeDelete(Segment * startSegment,Segment * endSegment)3226 bool Score::checkTimeDelete(Segment* startSegment, Segment* endSegment)
3227 {
3228 Measure* m = startSegment->measure();
3229 Measure* endMeasure;
3230
3231 if (endSegment)
3232 endMeasure = endSegment->prev() ? endSegment->measure() : endSegment->measure()->prevMeasure();
3233 else
3234 endMeasure = lastMeasure();
3235
3236 Fraction endTick = endSegment ? endSegment->tick() : endMeasure->endTick();
3237 Fraction tick = startSegment->tick();
3238 Fraction etick = (m == endMeasure ? endTick : m->endTick());
3239 bool canDeleteTime = true;
3240
3241 while (canDeleteTime) {
3242 for (int track = 0; canDeleteTime && track < _staves.size() * VOICES; ++track) {
3243 if (m->hasVoice(track)) {
3244 Segment* fs = m->first(CR_TYPE);
3245 for (Segment* s = fs; s; s = s->next(CR_TYPE)) {
3246 if (s->element(track)) {
3247 ChordRest* cr = toChordRest(s->element(track));
3248 Tuplet* t = cr->tuplet();
3249 DurationElement* de = t ? toDurationElement(t) : toDurationElement(cr);
3250 Fraction f = de->tick() + de->actualTicks();
3251 Fraction cetick = f;
3252 if (cetick <= tick)
3253 continue;
3254 if (de->tick() >= etick)
3255 break;
3256 if (t && (t->tick() < tick || cetick > etick)) {
3257 canDeleteTime = false;
3258 break;
3259 }
3260 }
3261 }
3262 }
3263 }
3264 if (m == endMeasure)
3265 break;
3266 m = endMeasure;
3267 tick = m->tick();
3268 etick = endTick;
3269 }
3270 if (!canDeleteTime) {
3271 QMessageBox::information(0, "MuseScore",
3272 tr("Please select the complete tuplet and retry the command"),
3273 QMessageBox::Ok, QMessageBox::NoButton);
3274 return false;
3275 }
3276 return true;
3277 }
3278
3279 //---------------------------------------------------------
3280 // globalTimeDelete
3281 //---------------------------------------------------------
3282
globalTimeDelete()3283 void Score::globalTimeDelete()
3284 {
3285 qDebug("not implemented");
3286 }
3287
3288 //---------------------------------------------------------
3289 // localTimeDelete
3290 //---------------------------------------------------------
3291
localTimeDelete()3292 void Score::localTimeDelete()
3293 {
3294 Segment* startSegment;
3295 Segment* endSegment;
3296
3297 if (selection().state() != SelState::RANGE) {
3298 Element* el = selection().element();
3299 if (!el)
3300 return;
3301 ChordRest* cr = 0;
3302 if (el->isNote())
3303 cr = toNote(el)->chord();
3304 else if (el->isChordRest())
3305 cr = toChordRest(el);
3306 else
3307 return;
3308 startSegment = cr->segment();
3309 Fraction endTick = startSegment->tick() + cr->actualTicks();
3310 endSegment = tick2measure(endTick)->findSegment(CR_TYPE, endTick);
3311 }
3312 else {
3313 startSegment = selection().startSegment();
3314 endSegment = selection().endSegment();
3315 }
3316
3317 if (!checkTimeDelete(startSegment, endSegment))
3318 return;
3319
3320 MeasureBase* is = startSegment->measure();
3321 if (is->isMeasure() && toMeasure(is)->isMMRest())
3322 is = toMeasure(is)->mmRestFirst();
3323 MeasureBase* ie;
3324
3325 if (endSegment)
3326 ie = endSegment->prev(SegmentType::ChordRest) ? endSegment->measure() : endSegment->measure()->prev();
3327 else
3328 ie = lastMeasure();
3329
3330 Fraction endTick = endSegment ? endSegment->tick() : ie->endTick();
3331
3332 for (;;) {
3333 if (is->tick() != startSegment->tick()) {
3334 Fraction tick = startSegment->tick();
3335 Fraction len;
3336 if (ie == is)
3337 len = endTick - tick;
3338 else
3339 len = is->endTick() - tick;
3340 timeDelete(toMeasure(is), startSegment, len);
3341 if (is == ie)
3342 break;
3343 is = is->next();
3344 }
3345 endTick = endSegment ? endSegment->tick() : ie->endTick();
3346 if (ie->endTick() != endTick) {
3347 Fraction len = endTick - ie->tick();
3348 timeDelete(toMeasure(ie), toMeasure(ie)->first(), len);
3349 if (is == ie)
3350 break;
3351 ie = ie->prev();
3352 }
3353 deleteMeasures(is, ie);
3354 break;
3355 };
3356
3357 if (noteEntryMode()) {
3358 Segment* currentSegment = endSegment;
3359 ChordRest* cr = nullptr;
3360 if (!currentSegment && lastMeasureMM()) {
3361 // deleted to end of score - get last cr on current track
3362 currentSegment = lastMeasureMM()->last();
3363 if (currentSegment) {
3364 cr = currentSegment->nextChordRest(_is.track(), true);
3365 if (cr)
3366 currentSegment = cr->segment();
3367 }
3368 }
3369 if (!currentSegment) {
3370 // no cr found - append a new measure
3371 appendMeasures(1);
3372 currentSegment = lastMeasureMM()->first(SegmentType::ChordRest);
3373 }
3374 _is.setSegment(currentSegment);
3375 cr = _is.cr();
3376 if (cr) {
3377 if (cr->isChord())
3378 select(toChord(cr)->upNote(), SelectType::SINGLE);
3379 else
3380 select(cr, SelectType::SINGLE);
3381 }
3382 else {
3383 // could not find cr to select,
3384 // may be that there is a "hole" in the current track
3385 deselectAll();
3386 }
3387 }
3388 else {
3389 deselectAll();
3390 }
3391 }
3392
3393 //---------------------------------------------------------
3394 // timeDelete
3395 //---------------------------------------------------------
3396
timeDelete(Measure * m,Segment * startSegment,const Fraction & f)3397 void Score::timeDelete(Measure* m, Segment* startSegment, const Fraction& f)
3398 {
3399 if (f.isZero())
3400 return;
3401
3402 const Fraction tick = startSegment->rtick();
3403 const Fraction len = f;
3404 const Fraction etick = tick + len;
3405
3406 Segment* fs = m->first(CR_TYPE);
3407
3408 for (int track = 0; track < _staves.size() * VOICES; ++track) {
3409 if (m->hasVoice(track)) {
3410 for (Segment* s = fs; s; s = s->next(CR_TYPE)) {
3411 if (s->element(track)) {
3412 ChordRest* cr = toChordRest(s->element(track));
3413 Fraction cetick = cr->rtick() + cr->actualTicks();
3414
3415 if (cetick <= tick)
3416 continue;
3417 if (s->rtick() >= etick)
3418 break;
3419
3420 if (cr->isFullMeasureRest()) {
3421 if (cr->rtick() >= tick) {
3422 // Move full-measure rest from the deleted area
3423 undoRemoveElement(cr);
3424 ChordRest* newCR = toChordRest(cr->clone());
3425 newCR->setTicks(cr->ticks() - f);
3426 undoAddCR(newCR, m, m->tick() + etick);
3427 }
3428 else
3429 cr->undoChangeProperty(Pid::DURATION, cr->ticks() - f);
3430 }
3431 // inside deleted area
3432 else if (s->rtick() >= tick && cetick <= etick) {
3433 // inside
3434 undoRemoveElement(cr);
3435 }
3436 else if (s->rtick() >= tick) {
3437 // running out
3438 Fraction ff = cetick - etick;
3439 undoRemoveElement(cr);
3440 createCRSequence(ff, cr, tick + len);
3441 }
3442 else if (s->rtick() < tick && cetick <= etick) {
3443 // running in
3444 Fraction f1 = tick - s->rtick();
3445 changeCRlen(cr, f1, false);
3446 }
3447 else {
3448 // running in/out
3449 Fraction f1 = cr->ticks() - f;
3450 changeCRlen(cr, f1, false);
3451 }
3452 }
3453 }
3454 }
3455 }
3456 const Fraction abstick = startSegment->tick();
3457 undoInsertTime(abstick, -len);
3458
3459 std::vector<Segment*> emptySegments;
3460
3461 for (Score* score : masterScore()->scoreList()) {
3462 Measure* localMeasure = score->tick2measure(abstick);
3463
3464 undo(new InsertTime(score, abstick, -len));
3465
3466 Fraction updatedTick = tick;
3467 for (Segment* s = localMeasure->first(CR_TYPE); s; s = s->next()) {
3468 if (s->rtick() < etick || s->rtick() == updatedTick)
3469 continue;
3470
3471 s->undoChangeProperty(Pid::TICK, updatedTick);
3472 updatedTick += s->ticks();
3473
3474 if (score->isMaster()) {
3475 if (s->isChordRestType() && !s->hasElements())
3476 emptySegments.push_back(s);
3477 }
3478 }
3479
3480 undo(new ChangeMeasureLen(localMeasure, localMeasure->ticks() - f));
3481 }
3482
3483 for (Segment* s : emptySegments) {
3484 if (Segment* ns = s->next(CR_TYPE)) {
3485 // Move annotations from the empty segment.
3486 // TODO: do we need to preserve annotations at all?
3487 // Maybe only some types (Tempo etc.)?
3488 for (Element* a : s->annotations()) {
3489 Element* a1 = a->clone();
3490 a1->setParent(ns);
3491 undoRemoveElement(a);
3492 undoAddElement(a1);
3493 }
3494 }
3495 }
3496 }
3497
3498 //---------------------------------------------------------
3499 // cloneVoice
3500 //---------------------------------------------------------
3501
cloneVoice(int strack,int dtrack,Segment * sf,const Fraction & lTick,bool link,bool spanner)3502 void Score::cloneVoice(int strack, int dtrack, Segment* sf, const Fraction& lTick, bool link, bool spanner)
3503 {
3504 Fraction start = sf->tick();
3505 TieMap tieMap;
3506 TupletMap tupletMap; // tuplets cannot cross measure boundaries
3507 Score* score = sf->score();
3508 Tremolo* tremolo = 0;
3509
3510 for (Segment* oseg = sf; oseg && oseg->tick() < lTick; oseg = oseg->next1()) {
3511 Segment* ns = 0; //create segment later, on demand
3512 Measure* dm = tick2measure(oseg->tick());
3513
3514 Element* oe = oseg->element(strack);
3515
3516 if (oe && !oe->generated() && oe->isChordRest()) {
3517 Element* ne;
3518 //does a linked clone to create just this element
3519 //otherwise element will be add in every linked stave
3520 if (link)
3521 ne = oe->linkedClone();
3522 else
3523 ne = oe->clone();
3524 ne->setTrack(dtrack);
3525
3526 //Don't clone gaps to a first voice
3527 if (!(ne->track() % VOICES) && ne->isRest())
3528 toRest(ne)->setGap(false);
3529
3530 ne->setScore(this);
3531 ChordRest* ocr = toChordRest(oe);
3532 ChordRest* ncr = toChordRest(ne);
3533
3534 //Handle beams
3535 if (ocr->beam() && !ocr->beam()->empty() && ocr->beam()->elements().front() == ocr) {
3536 Beam* nb = ocr->beam()->clone();
3537 nb->clear();
3538 nb->setTrack(dtrack);
3539 nb->setScore(this);
3540 nb->add(ncr);
3541 ncr->setBeam(nb);
3542 }
3543
3544 // clone Tuplets
3545 Tuplet* ot = ocr->tuplet();
3546 if (ot) {
3547 ot->setTrack(strack);
3548 Tuplet* nt = tupletMap.findNew(ot);
3549 if (nt == 0) {
3550 if (link)
3551 nt = toTuplet(ot->linkedClone());
3552 else
3553 nt = toTuplet(ot->clone());
3554 nt->setTrack(dtrack);
3555 nt->setParent(dm);
3556 tupletMap.add(ot, nt);
3557
3558 Tuplet* nt1 = nt;
3559 while (ot->tuplet()) {
3560 Tuplet* nt2 = tupletMap.findNew(ot->tuplet());
3561 if (nt2 == 0) {
3562 if (link)
3563 nt2 = toTuplet(ot->tuplet()->linkedClone());
3564 else
3565 nt2 = toTuplet(ot->tuplet()->clone());
3566 nt2->setTrack(dtrack);
3567 nt2->setParent(dm);
3568 tupletMap.add(ot->tuplet(), nt2);
3569 }
3570 nt2->add(nt1);
3571 nt1->setTuplet(nt2);
3572 ot = ot->tuplet();
3573 nt1 = nt2;
3574 }
3575 }
3576 nt->add(ncr);
3577 ncr->setTuplet(nt);
3578 }
3579
3580 // clone additional settings
3581 if (oe->isChordRest()) {
3582 if (oe->isRest()) {
3583 Rest* ore = toRest(ocr);
3584 // If we would clone a full measure rest just don't clone this rest
3585 if (ore->isFullMeasureRest() && (dtrack % VOICES)) {
3586 continue;
3587 }
3588 }
3589
3590 if (oe->isChord()) {
3591 Chord* och = toChord(ocr);
3592 Chord* nch = toChord(ncr);
3593
3594 size_t n = och->notes().size();
3595 for (size_t i = 0; i < n; ++i) {
3596 Note* on = och->notes().at(i);
3597 Note* nn = nch->notes().at(i);
3598 int idx = track2staff(dtrack);
3599 Fraction tick = oseg->tick();
3600 Interval v = staff(idx) ? staff(idx)->part()->instrument(tick)->transpose() : Interval();
3601 nn->setTpc1(on->tpc1());
3602 if (v.isZero())
3603 nn->setTpc2(on->tpc1());
3604 else {
3605 v.flip();
3606 nn->setTpc2(Ms::transposeTpc(nn->tpc1(), v, true));
3607 }
3608
3609 if (on->tieFor()) {
3610 Tie* tie;
3611 if (link)
3612 tie = toTie(on->tieFor()->linkedClone());
3613 else
3614 tie = toTie(on->tieFor()->clone());
3615 tie->setScore(this);
3616 nn->setTieFor(tie);
3617 tie->setStartNote(nn);
3618 tie->setTrack(nn->track());
3619 tie->setEndNote(nn);
3620 tieMap.add(on->tieFor(), tie);
3621 }
3622 if (on->tieBack()) {
3623 Tie* tie = tieMap.findNew(on->tieBack());
3624 if (tie) {
3625 nn->setTieBack(tie);
3626 tie->setEndNote(nn);
3627 }
3628 else {
3629 qDebug("cloneVoices: cannot find tie");
3630 }
3631 }
3632 // add back spanners (going back from end to start spanner element
3633 // makes sure the 'other' spanner anchor element is already set up)
3634 // 'on' is the old spanner end note and 'nn' is the new spanner end note
3635 for (Spanner* oldSp : on->spannerBack()) {
3636 Note* newStart = Spanner::startElementFromSpanner(oldSp, nn);
3637 if (newStart) {
3638 Spanner* newSp;
3639 if (link)
3640 newSp = toSpanner(oldSp->linkedClone());
3641 else
3642 newSp = toSpanner(oldSp->clone());
3643 newSp->setNoteSpan(newStart, nn);
3644 addElement(newSp);
3645 }
3646 else {
3647 qDebug("cloneVoices: cannot find spanner start note");
3648 }
3649 }
3650 }
3651 // two note tremolo
3652 if (och->tremolo() && och->tremolo()->twoNotes()) {
3653 if (och == och->tremolo()->chord1()) {
3654 if (tremolo)
3655 qDebug("unconnected two note tremolo");
3656 if (link)
3657 tremolo = toTremolo(och->tremolo()->linkedClone());
3658 else
3659 tremolo = toTremolo(och->tremolo()->clone());
3660 tremolo->setScore(nch->score());
3661 tremolo->setParent(nch);
3662 tremolo->setTrack(nch->track());
3663 tremolo->setChords(nch, 0);
3664 nch->setTremolo(tremolo);
3665 }
3666 else if (och == och->tremolo()->chord2()) {
3667 if (!tremolo)
3668 qDebug("first note for two note tremolo missing");
3669 else {
3670 tremolo->setChords(tremolo->chord1(), nch);
3671 nch->setTremolo(tremolo);
3672 }
3673 }
3674 else
3675 qDebug("inconsistent two note tremolo");
3676 }
3677 }
3678
3679 // Add element (link -> just in this measure)
3680 if (link) {
3681 if (!ns)
3682 ns = dm->getSegment(oseg->segmentType(), oseg->tick());
3683 ns->add(ne);
3684 }
3685 else {
3686 undoAddCR(toChordRest(ne), dm, oseg->tick());
3687 }
3688 }
3689 }
3690 Segment* tst = dm->segments().firstCRSegment();
3691 if (strack % VOICES && !(dtrack % VOICES) && (!tst || (!tst->element(dtrack)))) {
3692 Rest* rest = new Rest(this);
3693 rest->setTicks(dm->ticks());
3694 rest->setDurationType(TDuration::DurationType::V_MEASURE);
3695 rest->setTrack(dtrack);
3696 if (link) {
3697 Segment* segment = dm->getSegment(SegmentType::ChordRest, dm->tick());
3698 segment->add(rest);
3699 }
3700 else
3701 undoAddCR(toChordRest(rest), dm, dm->tick());
3702 }
3703 }
3704
3705 if (spanner) {
3706 // Find and add corresponding slurs
3707 auto spanners = score->spannerMap().findOverlapping(start.ticks(), lTick.ticks());
3708 for (auto i = spanners.begin(); i < spanners.end(); i++) {
3709 Spanner* sp = i->value;
3710 Fraction spStart = sp->tick();
3711 int track = sp->track();
3712 int track2 = sp->track2();
3713 Fraction spEnd = spStart + sp->ticks();
3714
3715 if (sp->isSlur() && (spStart >= start && spEnd < lTick)) {
3716 if (track == strack && track2 == strack){
3717 Spanner* ns = toSpanner(link ? sp->linkedClone() : sp->clone());
3718
3719 ns->setScore(this);
3720 ns->setParent(0);
3721 ns->setTrack(dtrack);
3722 ns->setTrack2(dtrack);
3723
3724 // set start/end element for slur
3725 ChordRest* cr1 = sp->startCR();
3726 ChordRest* cr2 = sp->endCR();
3727
3728 ns->setStartElement(0);
3729 ns->setEndElement(0);
3730 if (cr1 && cr1->links()) {
3731 for (ScoreElement* e : *cr1->links()) {
3732 ChordRest* cr = toChordRest(e);
3733 if (cr == cr1)
3734 continue;
3735 if ((cr->score() == this) && (cr->tick() == ns->tick()) && cr->track() == dtrack) {
3736 ns->setStartElement(cr);
3737 break;
3738 }
3739 }
3740 }
3741 if (cr2 && cr2->links()) {
3742 for (ScoreElement* e : *cr2->links()) {
3743 ChordRest* cr = toChordRest(e);
3744 if (cr == cr2)
3745 continue;
3746 if ((cr->score() == this) && (cr->tick() == ns->tick2()) && cr->track() == dtrack) {
3747 ns->setEndElement(cr);
3748 break;
3749 }
3750 }
3751 }
3752 undo(new AddElement(ns));
3753 }
3754 }
3755 }
3756 }
3757
3758 //Layout
3759 //TODO ?? doLayoutRange(start, lTick);
3760 }
3761
3762 //---------------------------------------------------------
3763 // undoPropertyChanged
3764 // return true if an property was actually changed
3765 //---------------------------------------------------------
3766
undoPropertyChanged(Element * e,Pid t,const QVariant & st,PropertyFlags ps)3767 bool Score::undoPropertyChanged(Element* e, Pid t, const QVariant& st, PropertyFlags ps)
3768 {
3769 bool changed = false;
3770
3771 if (propertyLink(t) && e->links()) {
3772 for (ScoreElement* ee : *e->links()) {
3773 if (ee == e) {
3774 if (ee->getProperty(t) != st) {
3775 undoStack()->push1(new ChangeProperty(ee, t, st, ps));
3776 changed = true;
3777 }
3778 }
3779 else {
3780 // property in linked element has not changed yet
3781 // push() calls redo() to change it
3782 if (ee->getProperty(t) != e->getProperty(t)) {
3783 undoStack()->push(new ChangeProperty(ee, t, e->getProperty(t), ps), 0);
3784 changed = true;
3785 }
3786 }
3787 }
3788 }
3789 else {
3790 PropertyFlags po = e->propertyFlags(t);
3791 if ((e->getProperty(t) != st) || (ps != po)) {
3792 e->setPropertyFlags(t, ps);
3793 undoStack()->push1(new ChangeProperty(e, t, st, po));
3794 changed = true;
3795 }
3796 }
3797 return changed;
3798 }
3799
undoPropertyChanged(ScoreElement * e,Pid t,const QVariant & st,PropertyFlags ps)3800 void Score::undoPropertyChanged(ScoreElement* e, Pid t, const QVariant& st, PropertyFlags ps)
3801 {
3802 if (e->getProperty(t) != st)
3803 undoStack()->push1(new ChangeProperty(e, t, st, ps));
3804 }
3805
3806 //---------------------------------------------------------
3807 // undoChangeStyleVal
3808 //---------------------------------------------------------
3809
undoChangeStyleVal(Sid idx,const QVariant & v)3810 void Score::undoChangeStyleVal(Sid idx, const QVariant& v)
3811 {
3812 undo(new ChangeStyleVal(this, idx, v));
3813 }
3814
3815 //---------------------------------------------------------
3816 // undoChangePageNumberOffset
3817 //---------------------------------------------------------
3818
undoChangePageNumberOffset(int po)3819 void Score::undoChangePageNumberOffset(int po)
3820 {
3821 undo(new ChangePageNumberOffset(this, po));
3822 }
3823
3824 //---------------------------------------------------------
3825 // undoChangeElement
3826 //---------------------------------------------------------
3827
undoChangeElement(Element * oldElement,Element * newElement)3828 void Score::undoChangeElement(Element* oldElement, Element* newElement)
3829 {
3830 if (!oldElement)
3831 undoAddElement(newElement);
3832 else
3833 undo(new ChangeElement(oldElement, newElement));
3834 }
3835
3836 //---------------------------------------------------------
3837 // undoChangePitch
3838 //---------------------------------------------------------
3839
undoChangePitch(Note * note,int pitch,int tpc1,int tpc2)3840 void Score::undoChangePitch(Note* note, int pitch, int tpc1, int tpc2)
3841 {
3842 for (ScoreElement* e : note->linkList()) {
3843 Note* n = toNote(e);
3844 undoStack()->push(new ChangePitch(n, pitch, tpc1, tpc2), 0);
3845 }
3846 }
3847
3848 //---------------------------------------------------------
3849 // undoChangeFretting
3850 //
3851 // To use with tablatures to force a specific note fretting;
3852 // Pitch, string and fret must be changed all together; otherwise,
3853 // if they are not consistent among themselves, the refretting algorithm may re-assign
3854 // fret and string numbers for (potentially) all the notes of all the chords of a segment.
3855 //---------------------------------------------------------
3856
undoChangeFretting(Note * note,int pitch,int string,int fret,int tpc1,int tpc2)3857 void Score::undoChangeFretting(Note* note, int pitch, int string, int fret, int tpc1, int tpc2)
3858 {
3859 const LinkedElements* l = note->links();
3860 if (l) {
3861 for (ScoreElement* e : *l) {
3862 Note* n = toNote(e);
3863 undo(new ChangeFretting(n, pitch, string, fret, tpc1, tpc2));
3864 }
3865 }
3866 else
3867 undo(new ChangeFretting(note, pitch, string, fret, tpc1, tpc2));
3868 }
3869
3870 //---------------------------------------------------------
3871 // undoChangeKeySig
3872 //---------------------------------------------------------
3873
undoChangeKeySig(Staff * ostaff,const Fraction & tick,KeySigEvent key)3874 void Score::undoChangeKeySig(Staff* ostaff, const Fraction& tick, KeySigEvent key)
3875 {
3876 KeySig* lks = 0;
3877
3878 for (Staff* staff : ostaff->staffList()) {
3879 if (staff->isDrumStaff(tick))
3880 continue;
3881
3882 Score* score = staff->score();
3883 Measure* measure = score->tick2measure(tick);
3884 KeySigEvent currentKeySigEvent = staff->keySigEvent(tick);
3885 if (!measure) {
3886 qWarning("measure for tick %d not found!", tick.ticks());
3887 continue;
3888 }
3889 Segment* s = measure->undoGetSegment(SegmentType::KeySig, tick);
3890
3891 int staffIdx = staff->idx();
3892 int track = staffIdx * VOICES;
3893 KeySig* ks = toKeySig(s->element(track));
3894
3895 Interval interval = staff->part()->instrument(tick)->transpose();
3896 KeySigEvent nkey = key;
3897 bool concertPitch = score->styleB(Sid::concertPitch);
3898
3899 if (interval.chromatic && !concertPitch && !nkey.custom() && !nkey.isAtonal()) {
3900 interval.flip();
3901 nkey.setKey(transposeKey(key.key(), interval, staff->part()->preferSharpFlat()));
3902 }
3903
3904 updateInstrumentChangeTranspositions(key, staff, tick);
3905 if (ks) {
3906 ks->undoChangeProperty(Pid::GENERATED, false);
3907 undo(new ChangeKeySig(ks, nkey, ks->showCourtesy()));
3908 }
3909 else {
3910 // do not create empty keysig unless custom or atonal
3911 if (tick.isNotZero() || nkey.key() != Key::C || nkey.custom() || nkey.isAtonal()) {
3912 KeySig* nks = new KeySig(score);
3913 nks->setParent(s);
3914 nks->setTrack(track);
3915 nks->setKeySigEvent(nkey);
3916 undo(new AddElement(nks));
3917 if (lks)
3918 undo(new Link(lks, nks));
3919 else
3920 lks = nks;
3921 }
3922 }
3923 }
3924 }
3925
updateInstrumentChangeTranspositions(KeySigEvent & key,Staff * staff,const Fraction & tick)3926 void Score::updateInstrumentChangeTranspositions(KeySigEvent& key, Staff* staff, const Fraction& tick)
3927 {
3928 if (!key.forInstrumentChange()) {
3929 KeyList* kl = staff->keyList();
3930 int nextTick = kl->nextKeyTick(tick.ticks());
3931
3932 while (nextTick != -1) {
3933 KeySigEvent e = kl->key(nextTick);
3934 if (e.forInstrumentChange()) {
3935 Measure* m = tick2measure(Fraction::fromTicks(nextTick));
3936 Segment* s = m->tick2segment(Fraction::fromTicks(nextTick), SegmentType::KeySig);
3937 int track = staff->idx() * VOICES;
3938 KeySig* keySig = toKeySig(s->element(track));
3939 if (key.isAtonal() && !e.isAtonal()) {
3940 e.setMode(KeyMode::NONE);
3941 e.setKey(Key::C);
3942 }
3943 else {
3944 e.setMode(key.mode());
3945 Interval transposeInterval = staff->part()->instrument(Fraction::fromTicks(nextTick))->transpose();
3946 Interval previousTranspose = staff->part()->instrument(tick)->transpose();
3947 transposeInterval.flip();
3948 Key nkey = transposeKey(key.key(), transposeInterval);
3949 nkey = transposeKey(nkey, previousTranspose);
3950 e.setKey(nkey);
3951 }
3952 undo(new ChangeKeySig(keySig, e, keySig->showCourtesy()));
3953 nextTick = kl->nextKeyTick(nextTick);
3954 }
3955 else
3956 nextTick = -1;
3957 }
3958 }
3959 }
3960
3961 //---------------------------------------------------------
3962 // undoChangeClef
3963 // change clef if e is a clef
3964 // else
3965 // create a clef before element e
3966 //---------------------------------------------------------
3967
undoChangeClef(Staff * ostaff,Element * e,ClefType ct,bool forInstrumentChange)3968 void Score::undoChangeClef(Staff* ostaff, Element* e, ClefType ct, bool forInstrumentChange)
3969 {
3970 bool moveClef = false;
3971 SegmentType st = SegmentType::Clef;
3972 if (e->isMeasure()) {
3973 if (toMeasure(e)->prevMeasure())
3974 moveClef = true;
3975 else
3976 st = SegmentType::HeaderClef;
3977 }
3978 else if (e->isClef()) {
3979 Clef* clef = toClef(e);
3980 if (clef->segment()->isHeaderClefType()) {
3981 if (clef->measure()->prevMeasure())
3982 moveClef = true;
3983 else
3984 st = SegmentType::HeaderClef;
3985 }
3986 else if (clef->rtick() == clef->measure()->ticks())
3987 moveClef = true;
3988 }
3989
3990 Clef* gclef = 0;
3991 Fraction tick = e->tick();
3992 Fraction rtick = e->rtick();
3993 bool small = (st == SegmentType::Clef);
3994 for (Staff* staff : ostaff->staffList()) {
3995 // if (staff->staffType(tick)->group() != ClefInfo::staffGroup(ct))
3996 // continue;
3997
3998 Score* score = staff->score();
3999 Measure* measure = score->tick2measure(tick);
4000
4001 if (!measure) {
4002 qWarning("measure for tick %d not found!", tick.ticks());
4003 continue;
4004 }
4005
4006 Segment* destSeg;
4007 Fraction rt;
4008 if (moveClef) { // if at start of measure and there is a previous measure
4009 measure = measure->prevMeasure();
4010 rt = measure->ticks();
4011 }
4012 else
4013 rt = rtick;
4014 destSeg = measure->undoGetSegmentR(st, rt);
4015
4016 int staffIdx = staff->idx();
4017 int track = staffIdx * VOICES;
4018 Clef* clef = toClef(destSeg->element(track));
4019
4020 if (clef) {
4021 //
4022 // for transposing instruments, differentiate
4023 // clef type for concertPitch
4024 //
4025 Instrument* i = staff->part()->instrument(tick);
4026 ClefType cp, tp;
4027 if (i->transpose().isZero()) {
4028 cp = ct;
4029 tp = ct;
4030 }
4031 else {
4032 bool concertPitch = clef->concertPitch();
4033 if (concertPitch) {
4034 cp = ct;
4035 tp = clef->transposingClef();
4036 }
4037 else {
4038 cp = clef->concertClef();
4039 tp = ct;
4040 }
4041 }
4042 clef->setGenerated(false);
4043 score->undo(new ChangeClefType(clef, cp, tp));
4044 Clef* oClef = clef->otherClef();
4045 if (oClef && !(oClef->generated()))
4046 score->undo(new ChangeClefType(oClef, cp, tp));
4047 // change the clef in the mmRest if any
4048 if (measure->hasMMRest()) {
4049 Measure* mmMeasure = measure->mmRest();
4050 Segment* mmDestSeg = mmMeasure->findSegment(SegmentType::Clef, tick);
4051 if (mmDestSeg) {
4052 Clef* mmClef = toClef(mmDestSeg->element(clef->track()));
4053 if (mmClef)
4054 score->undo(new ChangeClefType(mmClef, cp, tp));
4055 }
4056 }
4057 }
4058 else {
4059 if (gclef) {
4060 clef = toClef(gclef->linkedClone());
4061 clef->setScore(score);
4062 }
4063 else {
4064 clef = new Clef(score);
4065 gclef = clef;
4066 }
4067 clef->setTrack(track);
4068 clef->setClefType(ct);
4069 clef->setParent(destSeg);
4070 score->undo(new AddElement(clef));
4071 clef->layout();
4072 }
4073 if (forInstrumentChange) {
4074 clef->setForInstrumentChange(true);
4075 }
4076 clef->setSmall(small);
4077 }
4078 }
4079
4080 //---------------------------------------------------------
4081 // findLinkedVoiceElement
4082 //---------------------------------------------------------
4083
findLinkedVoiceElement(Element * e,Staff * nstaff)4084 static Element* findLinkedVoiceElement(Element* e, Staff* nstaff)
4085 {
4086 Excerpt* se = e->score()->excerpt();
4087 Excerpt* de = nstaff->score()->excerpt();
4088 int strack = e->track();
4089 int dtrack = nstaff->idx() * VOICES + e->voice();
4090
4091 if (se)
4092 strack = se->tracks().key(strack);
4093
4094 if (de) {
4095 QList<int> l = de->tracks().values(strack);
4096 if (l.isEmpty()) {
4097 // simply return the first linked element whose staff is equal to nstaff
4098 for (ScoreElement* ee : e->linkList()) {
4099 Element* el = toElement(ee);
4100 if (el->staff() == nstaff)
4101 return el;
4102 }
4103 return 0;
4104 }
4105 for (int i : qAsConst(l)) {
4106 if (nstaff->idx() * VOICES <= i && (nstaff->idx() + 1) * VOICES > i) {
4107 dtrack = i;
4108 break;
4109 }
4110 }
4111 }
4112
4113 Score* score = nstaff->score();
4114 Segment* segment = toSegment(e->parent());
4115 Measure* measure = segment->measure();
4116 Measure* m = score->tick2measure(measure->tick());
4117 Segment* s = m->findSegment(segment->segmentType(), segment->tick());
4118 return s->element(dtrack);
4119 }
4120
4121 //---------------------------------------------------------
4122 // findLinkedChord
4123 //---------------------------------------------------------
4124
findLinkedChord(Chord * c,Staff * nstaff)4125 static Chord* findLinkedChord(Chord* c, Staff* nstaff)
4126 {
4127 Excerpt* se = c->score()->excerpt();
4128 Excerpt* de = nstaff->score()->excerpt();
4129 int strack = c->track();
4130 int dtrack = nstaff->idx() * VOICES + c->voice();
4131
4132 if (se)
4133 strack = se->tracks().key(strack);
4134
4135 if (de) {
4136 QList<int> l = de->tracks().values(strack);
4137 if (l.isEmpty()) {
4138 // simply return the first linked chord whose staff is equal to nstaff
4139 for (ScoreElement* ee : c->linkList()) {
4140 Chord* ch = toChord(ee);
4141 if (ch->staff() == nstaff)
4142 return ch;
4143 }
4144 return 0;
4145 }
4146 for (int i : qAsConst(l)) {
4147 if (nstaff->idx() * VOICES <= i && (nstaff->idx() + 1) * VOICES > i) {
4148 dtrack = i;
4149 break;
4150 }
4151 }
4152 }
4153
4154 Segment* s = c->segment();
4155 Measure* nm = nstaff->score()->tick2measure(s->tick());
4156 Segment* ns = nm->findSegment(s->segmentType(), s->tick());
4157 Element* ne = ns->element(dtrack);
4158 if (!ne->isChord())
4159 return 0;
4160 Chord* nc = toChord(ne);
4161 if (c->isGrace()) {
4162 Chord* pc = toChord(c->parent());
4163 int index = 0;
4164 for (Chord* gc : pc->graceNotes()) {
4165 if (c == gc)
4166 break;
4167 index++;
4168 }
4169 if (index < nc->graceNotes().length())
4170 nc = nc->graceNotes().at(index);
4171 }
4172 return nc;
4173 }
4174
4175 //---------------------------------------------------------
4176 // undoChangeChordRestLen
4177 //---------------------------------------------------------
4178
undoChangeChordRestLen(ChordRest * cr,const TDuration & d)4179 void Score::undoChangeChordRestLen(ChordRest* cr, const TDuration& d)
4180 {
4181 auto sl = cr->staff()->staffList();
4182 for (Staff* staff : qAsConst(sl)) {
4183 ChordRest *ncr;
4184 if (cr->isGrace())
4185 ncr = findLinkedChord(toChord(cr), staff);
4186 else
4187 ncr = toChordRest(findLinkedVoiceElement(cr, staff));
4188 if (!ncr)
4189 continue;
4190 ncr->undoChangeProperty(Pid::DURATION_TYPE, QVariant::fromValue(d));
4191 ncr->undoChangeProperty(Pid::DURATION, QVariant::fromValue(d.fraction()));
4192 }
4193 }
4194
4195 //---------------------------------------------------------
4196 // undoTransposeHarmony
4197 //---------------------------------------------------------
4198
undoTransposeHarmony(Harmony * h,int rootTpc,int baseTpc)4199 void Score::undoTransposeHarmony(Harmony* h, int rootTpc, int baseTpc)
4200 {
4201 undo(new TransposeHarmony(h, rootTpc, baseTpc));
4202 }
4203
4204 //---------------------------------------------------------
4205 // undoExchangeVoice
4206 //---------------------------------------------------------
4207
undoExchangeVoice(Measure * measure,int srcVoice,int dstVoice,int srcStaff,int dstStaff)4208 void Score::undoExchangeVoice(Measure* measure, int srcVoice, int dstVoice, int srcStaff, int dstStaff)
4209 {
4210 Fraction tick = measure->tick();
4211
4212 for (int staffIdx = srcStaff; staffIdx < dstStaff; ++staffIdx) {
4213 QSet<Staff*> staffList;
4214 for (Staff* s : staff(staffIdx)->staffList())
4215 staffList.insert(s);
4216
4217 int srcStaffTrack = staffIdx * VOICES;
4218 int srcTrack = srcStaffTrack + srcVoice;
4219 int dstTrack = srcStaffTrack + dstVoice;
4220 int trackDiff = dstVoice - srcVoice;
4221
4222 //handle score and complete measures first
4223 undo(new ExchangeVoice(measure, srcTrack, dstTrack, staffIdx));
4224
4225 for (Staff* st : staffList) {
4226 int staffTrack = st->idx() * VOICES;
4227 Measure* measure2 = st->score()->tick2measure(tick);
4228 Excerpt* ex = st->score()->excerpt();
4229
4230 if (ex) {
4231 QMultiMap<int, int> tracks = ex->tracks();
4232 QList<int> srcTrackList = tracks.values(srcTrack);
4233 QList<int> dstTrackList = tracks.values(dstTrack);
4234
4235 for (int srcTrack2 : qAsConst(srcTrackList)) {
4236 // don't care about other linked staves
4237 if (!(staffTrack <= srcTrack2) || !(srcTrack2 < staffTrack + VOICES))
4238 continue;
4239
4240 int tempTrack = tracks.key(srcTrack2);
4241 QList<int> testTracks = tracks.values(tempTrack + trackDiff);
4242 bool hasVoice = false;
4243 for (int testTrack : qAsConst(testTracks)) {
4244 if (staffTrack <= testTrack && testTrack < staffTrack + VOICES && dstTrackList.contains(testTrack)) {
4245 hasVoice = true;
4246 // voice is simply exchangeable now (deal directly)
4247 undo(new ExchangeVoice(measure2, srcTrack2, testTrack, staffTrack / 4));
4248 }
4249 }
4250
4251 // only source voice is in this staff
4252 if (!hasVoice) {
4253 undo(new CloneVoice(measure->first(), measure2->endTick(), measure2->first(), tempTrack, srcTrack2, tempTrack + trackDiff));
4254 srcTrackList.removeOne(srcTrack2);
4255 }
4256 }
4257
4258 for (int dstTrack2 : qAsConst(dstTrackList)) {
4259 // don't care about other linked staves
4260 if (!(staffTrack <= dstTrack2) || !(dstTrack2 < staffTrack + VOICES))
4261 continue;
4262
4263 int tempTrack = tracks.key(dstTrack2);
4264 QList<int> testTracks = tracks.values(tempTrack - trackDiff);
4265 bool hasVoice = false;
4266 for (int testTrack : qAsConst(testTracks)) {
4267 if (staffTrack <= testTrack && testTrack < staffTrack + VOICES &&
4268 srcTrackList.contains(testTrack))
4269 hasVoice = true;
4270 }
4271
4272 // only destination voice is in this staff
4273 if (!hasVoice) {
4274 undo(new CloneVoice(measure->first(), measure2->endTick(), measure2->first(), tempTrack, dstTrack2, tempTrack - trackDiff));
4275 dstTrackList.removeOne(dstTrack2);
4276 }
4277 }
4278 }
4279 else if (srcStaffTrack != staffTrack) {
4280 // linked staff in same score (all voices present can be assumed)
4281 undo(new ExchangeVoice(measure2, staffTrack + srcVoice, staffTrack + dstVoice, st->idx()));
4282 }
4283 }
4284 }
4285
4286 // make sure voice 0 is complete
4287
4288 if (srcVoice == 0 || dstVoice == 0) {
4289 for (int staffIdx = srcStaff; staffIdx < dstStaff; ++staffIdx) {
4290 // check for complete timeline of voice 0
4291 Fraction ctick = measure->tick();
4292 int track = staffIdx * VOICES;
4293 for (Segment* s = measure->first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
4294 ChordRest* cr = toChordRest(s->element(track));
4295 if (cr == 0)
4296 continue;
4297 if (cr->isRest()) {
4298 Rest* r = toRest(cr);
4299 if (r->isGap())
4300 r->undoChangeProperty(Pid::GAP, false);
4301 }
4302 if (ctick < s->tick())
4303 setRest(ctick, track, s->tick() - ctick, false, 0); // fill gap
4304 ctick = s->tick() + cr->actualTicks();
4305 }
4306 Fraction etick = measure->endTick();
4307 if (ctick < etick)
4308 setRest(ctick, track, etick - ctick, false, 0); // fill gap
4309 }
4310 }
4311 }
4312
4313 //---------------------------------------------------------
4314 // undoRemovePart
4315 //---------------------------------------------------------
4316
undoRemovePart(Part * part,int idx)4317 void Score::undoRemovePart(Part* part, int idx)
4318 {
4319 undo(new RemovePart(part, idx));
4320 }
4321
4322 //---------------------------------------------------------
4323 // undoInsertPart
4324 //---------------------------------------------------------
4325
undoInsertPart(Part * part,int idx)4326 void Score::undoInsertPart(Part* part, int idx)
4327 {
4328 undo(new InsertPart(part, idx));
4329 }
4330
4331 //---------------------------------------------------------
4332 // undoRemoveStaff
4333 // idx - index of staff in part
4334 //---------------------------------------------------------
4335
undoRemoveStaff(Staff * staff)4336 void Score::undoRemoveStaff(Staff* staff)
4337 {
4338 const int idx = staff->idx();
4339 Q_ASSERT(idx >= 0);
4340
4341 std::vector<Spanner*> toRemove;
4342 for (auto i = _spanner.cbegin(); i != _spanner.cend(); ++i) {
4343 Spanner* s = i->second;
4344 if (s->staffIdx() == idx && (idx != 0 || !s->systemFlag()))
4345 toRemove.push_back(s);
4346 }
4347 for (Spanner* s : _unmanagedSpanner) {
4348 if (s->staffIdx() == idx && (idx != 0 || !s->systemFlag()))
4349 toRemove.push_back(s);
4350 }
4351 for (Spanner* s : toRemove) {
4352 s->undoUnlink();
4353 undo(new RemoveElement(s));
4354 }
4355
4356 //
4357 // adjust measures
4358 //
4359 for (Measure* m = staff->score()->firstMeasure(); m; m = m->nextMeasure()) {
4360 m->cmdRemoveStaves(idx, idx+1);
4361 if (m->hasMMRest())
4362 m->mmRest()->cmdRemoveStaves(idx, idx+1);
4363 }
4364
4365 undo(new RemoveStaff(staff));
4366 }
4367
4368 //---------------------------------------------------------
4369 // undoInsertStaff
4370 // idx - index of staff in part
4371 //---------------------------------------------------------
4372
undoInsertStaff(Staff * staff,int ridx,bool createRests)4373 void Score::undoInsertStaff(Staff* staff, int ridx, bool createRests)
4374 {
4375 undo(new InsertStaff(staff, ridx));
4376 int idx = staffIdx(staff->part()) + ridx;
4377 for (Measure* m = firstMeasure(); m; m = m->nextMeasure()) {
4378 m->cmdAddStaves(idx, idx+1, createRests);
4379 if (m->hasMMRest())
4380 m->mmRest()->cmdAddStaves(idx, idx+1, false);
4381 }
4382 // when newly adding an instrument,
4383 // this was already set when we created the staff
4384 // we don't have any better info at this point
4385 // and it dooesn't work to adjust bracket & barlines until all staves are added
4386 // TODO: adjust brackets only when appropriate
4387 //adjustBracketsIns(idx, idx+1);
4388 }
4389
4390 //---------------------------------------------------------
4391 // undoChangeInvisible
4392 //---------------------------------------------------------
4393
undoChangeInvisible(Element * e,bool v)4394 void Score::undoChangeInvisible(Element* e, bool v)
4395 {
4396 e->undoChangeProperty(Pid::VISIBLE, v);
4397 e->setGenerated(false);
4398 }
4399
4400 //---------------------------------------------------------
4401 // undoAddElement
4402 //---------------------------------------------------------
4403
undoAddElement(Element * element)4404 void Score::undoAddElement(Element* element)
4405 {
4406 QList<Staff* > staffList;
4407 Staff* ostaff = element->staff();
4408 int strack = -1;
4409 if (ostaff) {
4410 strack = ostaff->idx() * VOICES + element->track() % VOICES;
4411 if (ostaff->score()->excerpt() && !ostaff->score()->excerpt()->tracks().isEmpty() && strack > -1)
4412 strack = ostaff->score()->excerpt()->tracks().key(strack, -1);
4413 }
4414
4415 ElementType et = element->type();
4416
4417 //
4418 // some elements are replicated for all parts regardless of
4419 // linking:
4420 //
4421
4422 if ((et == ElementType::REHEARSAL_MARK)
4423 || (et == ElementType::SYSTEM_TEXT)
4424 || (et == ElementType::JUMP)
4425 || (et == ElementType::MARKER)
4426 || (et == ElementType::TEMPO_TEXT)
4427 || (et == ElementType::VOLTA)
4428 || ((et == ElementType::TEXTLINE) && element->systemFlag())
4429 ) {
4430 for (Score* s : scoreList())
4431 staffList.append(s->staff(0));
4432
4433 for (Staff* staff : staffList) {
4434 Score* score = staff->score();
4435 int staffIdx = staff->idx();
4436 int ntrack = staffIdx * VOICES;
4437 Element* ne;
4438
4439 if (ostaff && staff->score() == ostaff->score())
4440 ne = element;
4441 else {
4442 // only create linked volta/systemTextLine for first staff
4443 if (((et == ElementType::VOLTA) || (et == ElementType::TEXTLINE)) && element->track() != 0)
4444 continue;
4445 ne = element->linkedClone();
4446 ne->setScore(score);
4447 ne->setSelected(false);
4448 ne->setTrack(staffIdx * VOICES + element->voice());
4449 }
4450
4451 if (et == ElementType::VOLTA || (et == ElementType::TEXTLINE)) {
4452 Spanner* nsp = toSpanner(ne);
4453 Spanner* sp = toSpanner(element);
4454 int staffIdx1 = sp->track() / VOICES;
4455 int staffIdx2 = sp->track2() / VOICES;
4456 int diff = staffIdx2 - staffIdx1;
4457 nsp->setTrack2((staffIdx + diff) * VOICES + (sp->track2() % VOICES));
4458 undo(new AddElement(nsp));
4459 }
4460 else if (et == ElementType::MARKER || et == ElementType::JUMP) {
4461 Measure* om = toMeasure(element->parent());
4462 Measure* m = score->tick2measure(om->tick());
4463 ne->setTrack(element->track());
4464 ne->setParent(m);
4465 undo(new AddElement(ne));
4466 }
4467 else if (et == ElementType::MEASURE_NUMBER) {
4468 toMeasure(element->parent())->undoChangeProperty(Pid::MEASURE_NUMBER_MODE, static_cast<int>(MeasureNumberMode::SHOW));
4469 }
4470 else {
4471 Segment* segment = toSegment(element->parent());
4472 Fraction tick = segment->tick();
4473 Measure* m = score->tick2measure(tick);
4474 Segment* seg = m->undoGetSegment(SegmentType::ChordRest, tick);
4475 ne->setTrack(ntrack);
4476 ne->setParent(seg);
4477 undo(new AddElement(ne));
4478 }
4479 }
4480 return;
4481 }
4482
4483 if (et == ElementType::FINGERING
4484 || (et == ElementType::IMAGE && !element->parent()->isSegment())
4485 || (et == ElementType::SYMBOL && !element->parent()->isSegment())
4486 || et == ElementType::NOTE
4487 || et == ElementType::TEXT
4488 || et == ElementType::GLISSANDO
4489 || et == ElementType::BEND
4490 || (et == ElementType::CHORD && toChord(element)->isGrace())
4491 ) {
4492 Element* parent = element->parent();
4493 const LinkedElements* links = parent->links();
4494 // don't link part name
4495 if (et == ElementType::TEXT) {
4496 Text* t = toText(element);
4497 if (t->tid() == Tid::INSTRUMENT_EXCERPT)
4498 links = 0;
4499 }
4500 if (links == 0) {
4501 undo(new AddElement(element));
4502 return;
4503 }
4504 for (ScoreElement* ee : *links) {
4505 Element* e = static_cast<Element*>(ee);
4506 Element* ne;
4507 if (e == parent)
4508 ne = element;
4509 else {
4510 if (element->isGlissando()) { // and other spanners with Anchor::NOTE
4511 Note* newEnd = Spanner::endElementFromSpanner(toGlissando(element), e);
4512 if (newEnd) {
4513 ne = element->linkedClone();
4514 toSpanner(ne)->setNoteSpan(toNote(e), newEnd);
4515 }
4516 else //couldn't find suitable start note
4517 continue;
4518 }
4519 else if (element->isFingering()) {
4520 bool tabFingering = e->staff()->staffType(e->tick())->showTabFingering();
4521 if (e->staff()->isTabStaff(e->tick()) && !tabFingering)
4522 continue;
4523 ne = element->linkedClone();
4524 }
4525 else
4526 ne = element->linkedClone();
4527 }
4528 ne->setScore(e->score());
4529 ne->setSelected(false);
4530 ne->setParent(e);
4531 undo(new AddElement(ne));
4532 }
4533 return;
4534 }
4535
4536 if (et == ElementType::LAYOUT_BREAK) {
4537 LayoutBreak* lb = toLayoutBreak(element);
4538 if (lb->layoutBreakType() == LayoutBreak::Type::SECTION) {
4539 MeasureBase* m = lb->measure();
4540 for (Score* s : scoreList()) {
4541 if (s == lb->score())
4542 undo(new AddElement(lb));
4543 else {
4544 Element* e = lb->linkedClone();
4545 e->setScore(s);
4546 Measure* nm = s->tick2measure(m->tick());
4547 e->setParent(nm);
4548 undo(new AddElement(e));
4549 }
4550 }
4551 return;
4552 }
4553 }
4554
4555 if (ostaff == 0 || (
4556 et != ElementType::ARTICULATION
4557 && et != ElementType::CHORDLINE
4558 && et != ElementType::LYRICS
4559 && et != ElementType::SLUR
4560 && et != ElementType::TIE
4561 && et != ElementType::NOTE
4562 && et != ElementType::INSTRUMENT_CHANGE
4563 && et != ElementType::HAIRPIN
4564 && et != ElementType::OTTAVA
4565 && et != ElementType::TRILL
4566 && et != ElementType::VIBRATO
4567 && et != ElementType::TEXTLINE
4568 && et != ElementType::PEDAL
4569 && et != ElementType::BREATH
4570 && et != ElementType::DYNAMIC
4571 && et != ElementType::STAFF_TEXT
4572 && et != ElementType::SYSTEM_TEXT
4573 && et != ElementType::STICKING
4574 && et != ElementType::TREMOLO
4575 && et != ElementType::ARPEGGIO
4576 && et != ElementType::SYMBOL
4577 && et != ElementType::IMAGE
4578 && et != ElementType::TREMOLOBAR
4579 && et != ElementType::FRET_DIAGRAM
4580 && et != ElementType::FERMATA
4581 && et != ElementType::HARMONY)
4582 ) {
4583 undo(new AddElement(element));
4584 return;
4585 }
4586
4587 // For linked staves the length of staffList is always > 1 since the list contains the staff itself too!
4588 const bool linked = ostaff->staffList().length() > 1;
4589
4590 for (Staff* staff : ostaff->staffList()) {
4591 Score* score = staff->score();
4592 int staffIdx = staff->idx();
4593
4594 QList<int> tr;
4595 if (!staff->score()->excerpt()) {
4596 // On masterScore.
4597 int track = staff->idx() * VOICES + (strack % VOICES);
4598 tr.append(track);
4599 }
4600 else {
4601 QMultiMap<int, int> mapping = staff->score()->excerpt()->tracks();
4602 if (mapping.isEmpty()) {
4603 // This can happen during reading the score and there is
4604 // no Tracklist tag specified.
4605 // TODO solve this in read302.cpp.
4606 tr.append(strack);
4607 }
4608 else {
4609 for (int track : mapping.values(strack)) {
4610 // linkedPart : linked staves within same part/instrument.
4611 // linkedScore: linked staves over different scores via excerpts.
4612 const bool linkedPart = linked && (staff != ostaff) && (staff->score() == ostaff->score());
4613 const bool linkedScore = linked && (staff != ostaff) && (staff->score() != ostaff->score());
4614 if (linkedPart && !linkedScore) {
4615 tr.append(staff->idx() * VOICES + mapping.value(track));
4616 }
4617 else if (!linkedPart && linkedScore) {
4618 if ((track >> 2) != staffIdx)
4619 track += (staffIdx - (track >> 2)) * VOICES;
4620 tr.append(track);
4621 }
4622 else {
4623 tr.append(track);
4624 }
4625 }
4626 }
4627 }
4628
4629
4630 // Some elements in voice 1 of a staff should be copied to every track which has a linked voice in this staff
4631
4632 if (tr.isEmpty() && (element->isSymbol()
4633 || element->isImage()
4634 || element->isTremoloBar()
4635 || element->isDynamic()
4636 || element->isStaffText()
4637 || element->isSticking()
4638 || element->isFretDiagram()
4639 || element->isHarmony()
4640 || element->isHairpin()
4641 || element->isOttava()
4642 || element->isTrill()
4643 || element->isSlur()
4644 || element->isVibrato()
4645 || element->isTextLine()
4646 || element->isPedal()
4647 || element->isLyrics())) {
4648 tr.append(staffIdx * VOICES);
4649 }
4650
4651 for (int ntrack : tr) {
4652 Element* ne;
4653 if (staff == ostaff)
4654 ne = element;
4655 else {
4656 if (staff->rstaff() != ostaff->rstaff()) {
4657 switch (element->type()) {
4658 // exclude certain element types except on corresponding staff in part
4659 // this should be same list excluded in cloneStaff()
4660 case ElementType::STAFF_TEXT:
4661 case ElementType::SYSTEM_TEXT:
4662 case ElementType::FRET_DIAGRAM:
4663 case ElementType::HARMONY:
4664 case ElementType::FIGURED_BASS:
4665 case ElementType::DYNAMIC:
4666 case ElementType::LYRICS: // not normally segment-attached
4667 continue;
4668 default:
4669 break;
4670 }
4671 }
4672 ne = element->linkedClone();
4673 ne->setScore(score);
4674 ne->setSelected(false);
4675 ne->setTrack(staffIdx * VOICES + element->voice());
4676
4677 if (ne->isFretDiagram()) {
4678 FretDiagram* fd = toFretDiagram(ne);
4679 Harmony* fdHarmony = fd->harmony();
4680 if (fdHarmony) {
4681 fdHarmony->setScore(score);
4682 fdHarmony->setSelected(false);
4683 fdHarmony->setTrack(staffIdx * VOICES + element->voice());
4684 }
4685 }
4686 }
4687
4688 if (element->isArticulation()) {
4689 Articulation* a = toArticulation(element);
4690 Segment* segment;
4691 SegmentType st;
4692 Measure* m;
4693 Fraction tick;
4694 if (a->parent()->isChordRest()) {
4695 ChordRest* cr = a->chordRest();
4696 segment = cr->segment();
4697 st = SegmentType::ChordRest;
4698 tick = segment->tick();
4699 m = score->tick2measure(tick);
4700 }
4701 else {
4702 segment = toSegment(a->parent()->parent());
4703 st = SegmentType::EndBarLine;
4704 tick = segment->tick();
4705 m = score->tick2measure(tick);
4706 if (m->tick() == tick)
4707 m = m->prevMeasure();
4708 }
4709 Segment* seg = m->findSegment(st, tick);
4710 if (seg == 0) {
4711 qWarning("undoAddSegment: segment not found");
4712 break;
4713 }
4714 Articulation* na = toArticulation(ne);
4715 na->setTrack(ntrack);
4716 if (a->parent()->isChordRest()) {
4717 ChordRest* cr = a->chordRest();
4718 ChordRest* ncr;
4719 if (cr->isGrace())
4720 ncr = findLinkedChord(toChord(cr), score->staff(staffIdx));
4721 else
4722 ncr = toChordRest(seg->element(ntrack));
4723 na->setParent(ncr);
4724 }
4725 else {
4726 BarLine* bl = toBarLine(seg->element(ntrack));
4727 na->setParent(bl);
4728 }
4729 undo(new AddElement(na));
4730 }
4731 else if (element->isChordLine() || element->isLyrics()) {
4732 ChordRest* cr = toChordRest(element->parent());
4733 Segment* segment = cr->segment();
4734 Fraction tick = segment->tick();
4735 Measure* m = score->tick2measure(tick);
4736 Segment* seg = m->findSegment(SegmentType::ChordRest, tick);
4737 if (seg == 0) {
4738 qWarning("undoAddSegment: segment not found");
4739 break;
4740 }
4741 ne->setTrack(ntrack);
4742 ChordRest* ncr = toChordRest(seg->element(ntrack));
4743 ne->setParent(ncr);
4744 undo(new AddElement(ne));
4745 }
4746 //
4747 // elements with Segment as parent
4748 //
4749 else if (element->isSymbol()
4750 || element->isImage()
4751 || element->isTremoloBar()
4752 || element->isDynamic()
4753 || element->isStaffText()
4754 || element->isSticking()
4755 || element->isFretDiagram()
4756 || element->isFermata()
4757 || element->isHarmony()) {
4758 Segment* segment = element->parent()->isFretDiagram() ? toSegment(element->parent()->parent()) : toSegment(element->parent());
4759 Fraction tick = segment->tick();
4760 Measure* m = score->tick2measure(tick);
4761 if ((segment->segmentType() == SegmentType::EndBarLine) && (m->tick() == tick))
4762 m = m->prevMeasure();
4763 Segment* seg = m->undoGetSegment(segment->segmentType(), tick);
4764 ne->setTrack(ntrack);
4765 ne->setParent(seg);
4766
4767 // make harmony child of fret diagram if possible
4768 if (ne->isHarmony()) {
4769 for (Element* segel : segment->annotations()) {
4770 if (segel && segel->isFretDiagram() && segel->track() == ntrack) {
4771 segel->add(ne);
4772 break;
4773 }
4774 }
4775 }
4776 else if (ne->isFretDiagram()) {
4777 // update track of child harmony
4778 FretDiagram* fd = toFretDiagram(ne);
4779 if (fd->harmony())
4780 fd->harmony()->setTrack(ntrack);
4781 }
4782
4783 undo(new AddElement(ne));
4784 // transpose harmony if necessary
4785 if (element->isHarmony() && ne != element) {
4786 Harmony* h = toHarmony(ne);
4787 if (score->styleB(Sid::concertPitch) != element->score()->styleB(Sid::concertPitch)) {
4788 Part* partDest = h->part();
4789 Interval interval = partDest->instrument(tick)->transpose();
4790 if (!interval.isZero()) {
4791 if (!score->styleB(Sid::concertPitch))
4792 interval.flip();
4793 int rootTpc = transposeTpc(h->rootTpc(), interval, true);
4794 int baseTpc = transposeTpc(h->baseTpc(), interval, true);
4795 score->undoTransposeHarmony(h, rootTpc, baseTpc);
4796 }
4797 }
4798 }
4799 }
4800 else if (element->isSlur()
4801 || element->isHairpin()
4802 || element->isOttava()
4803 || element->isTrill()
4804 || element->isVibrato()
4805 || element->isTextLine()
4806 || element->isPedal()) {
4807 Spanner* sp = toSpanner(element);
4808 Spanner* nsp = toSpanner(ne);
4809 int staffIdx1 = sp->track() / VOICES;
4810 int tr2 = sp->effectiveTrack2();
4811 int staffIdx2 = tr2 / VOICES;
4812 int diff = staffIdx2 - staffIdx1;
4813 nsp->setTrack2((staffIdx + diff) * VOICES + (tr2 % VOICES));
4814 nsp->setTrack(ntrack);
4815
4816 #if 0 //whatdoesitdo?
4817 QList<int> tl2;
4818 if (staff->score()->excerpt() && element->isSlur()) {
4819 nsp->setTrack(ntrack);
4820 tl2 = staff->score()->excerpt()->tracks().values(sp->track2());
4821 if (tl2.isEmpty()) {
4822 it++;
4823 continue;
4824 }
4825 nsp->setTrack2(tl2.at(it));
4826 }
4827 else if (!element->isSlur())
4828 nsp->setTrack(ntrack & ~3);
4829 #endif
4830
4831 // determine start/end element for slurs
4832 // this is only necessary if start/end element is
4833 // a grace note, otherwise the element can be set to zero
4834 // and will later be calculated from tick/track values
4835 //
4836 if (element->isSlur() && sp != nsp) {
4837 if (sp->startElement()) {
4838 QList<ScoreElement*> sel = sp->startElement()->linkList();
4839 for (ScoreElement* ee : qAsConst(sel)) {
4840 Element* e = static_cast<Element*>(ee);
4841 if (e->score() == nsp->score() && e->track() == nsp->track()) {
4842 nsp->setStartElement(e);
4843 break;
4844 }
4845 }
4846 }
4847 if (sp->endElement()) {
4848 QList<ScoreElement*> eel = sp->endElement()->linkList();
4849 for (ScoreElement* ee : qAsConst(eel)) {
4850 Element* e = static_cast<Element*>(ee);
4851 if (e->score() == nsp->score() && e->track() == nsp->track2()) {
4852 nsp->setEndElement(e);
4853 break;
4854 }
4855 }
4856 }
4857 }
4858 undo(new AddElement(nsp));
4859 }
4860 else if (et == ElementType::GLISSANDO)
4861 undo(new AddElement(toSpanner(ne)));
4862 else if (element->isTremolo() && toTremolo(element)->twoNotes()) {
4863 Tremolo* tremolo = toTremolo(element);
4864 ChordRest* cr1 = toChordRest(tremolo->chord1());
4865 ChordRest* cr2 = toChordRest(tremolo->chord2());
4866 Segment* s1 = cr1->segment();
4867 Segment* s2 = cr2->segment();
4868 Measure* m1 = s1->measure();
4869 Measure* m2 = s2->measure();
4870 Measure* nm1 = score->tick2measure(m1->tick());
4871 Measure* nm2 = score->tick2measure(m2->tick());
4872 Segment* ns1 = nm1->findSegment(s1->segmentType(), s1->tick());
4873 Segment* ns2 = nm2->findSegment(s2->segmentType(), s2->tick());
4874 Chord* c1 = toChord(ns1->element(staffIdx * VOICES + cr1->voice()));
4875 Chord* c2 = toChord(ns2->element(staffIdx * VOICES + cr2->voice()));
4876 Tremolo* ntremolo = toTremolo(ne);
4877 ntremolo->setChords(c1, c2);
4878 ntremolo->setParent(c1);
4879 undo(new AddElement(ntremolo));
4880 }
4881 else if (element->isTremolo() && !toTremolo(element)->twoNotes()) {
4882 Chord* cr = toChord(element->parent());
4883 Chord* c1 = findLinkedChord(cr, score->staff(staffIdx));
4884 ne->setParent(c1);
4885 undo(new AddElement(ne));
4886 }
4887 else if (element->isArpeggio()) {
4888 ChordRest* cr = toChordRest(element->parent());
4889 Segment* s = cr->segment();
4890 Measure* m = s->measure();
4891 Measure* nm = score->tick2measure(m->tick());
4892 Segment* ns = nm->findSegment(s->segmentType(), s->tick());
4893 Chord* c1 = toChord(ns->element(staffIdx * VOICES + cr->voice()));
4894 ne->setParent(c1);
4895 undo(new AddElement(ne));
4896 }
4897 else if (element->isTie()) {
4898 Tie* tie = toTie(element);
4899 Note* n1 = tie->startNote();
4900 Note* n2 = tie->endNote();
4901 Chord* cr1 = n1->chord();
4902 Chord* cr2 = n2 ? n2->chord() : 0;
4903
4904 // find corresponding notes in linked staff
4905 // accounting for grace notes and cross-staff notation
4906 int sm = 0;
4907 if (cr1->staffIdx() != cr2->staffIdx())
4908 sm = cr2->staffIdx() - cr1->staffIdx();
4909 Chord* c1 = findLinkedChord(cr1, score->staff(staffIdx));
4910 Chord* c2 = findLinkedChord(cr2, score->staff(staffIdx + sm));
4911 Note* nn1 = c1->findNote(n1->pitch(), n1->unisonIndex());
4912 Note* nn2 = c2 ? c2->findNote(n2->pitch(), n2->unisonIndex()) : 0;
4913
4914 // create tie
4915 Tie* ntie = toTie(ne);
4916 ntie->eraseSpannerSegments();
4917 ntie->setTrack(c1->track());
4918 ntie->setStartNote(nn1);
4919 ntie->setEndNote(nn2);
4920 undo(new AddElement(ntie));
4921 }
4922 else if (element->isInstrumentChange()) {
4923 InstrumentChange* is = toInstrumentChange(element);
4924 Segment* s1 = is->segment();
4925 Measure* m1 = s1->measure();
4926 Measure* nm1 = score->tick2measure(m1->tick());
4927 Segment* ns1 = nm1->findSegment(s1->segmentType(), s1->tick());
4928 InstrumentChange* nis = toInstrumentChange(ne);
4929 nis->setParent(ns1);
4930 Fraction tickStart = nis->segment()->tick();
4931 Part* part = nis->part();
4932 Interval oldV = nis->part()->instrument(tickStart)->transpose();
4933 // ws: instrument should not be changed here
4934 if (is->instrument()->channel().empty() || is->instrument()->channel(0)->program() == -1)
4935 nis->setInstrument(*staff->part()->instrument(s1->tick()));
4936 else if (nis != is)
4937 nis->setInstrument(*is->instrument());
4938 undo(new AddElement(nis));
4939 // transpose root score; parts will follow
4940 if (score->isMaster() && part->instrument(tickStart)->transpose() != oldV) {
4941 auto i = part->instruments()->upper_bound(tickStart.ticks());
4942 Fraction tickEnd = i == part->instruments()->end() ? Fraction(-1, 1) : Fraction::fromTicks(i->first);
4943 transpositionChanged(part, oldV, tickStart, tickEnd);
4944 }
4945 }
4946 else if (element->isBreath()) {
4947 Breath* breath = toBreath(element);
4948 Fraction tick = breath->segment()->tick();
4949 Measure* m = score->tick2measure(tick);
4950 // breath appears before barline
4951 if (m->tick() == tick)
4952 m = m->prevMeasure();
4953 Segment* seg = m->undoGetSegment(SegmentType::Breath, tick);
4954 Breath* nbreath = toBreath(ne);
4955 nbreath->setScore(score);
4956 nbreath->setTrack(ntrack);
4957 nbreath->setParent(seg);
4958 undo(new AddElement(nbreath));
4959 }
4960 else
4961 qWarning("undoAddElement: unhandled: <%s>", element->name());
4962 }
4963 }
4964 }
4965
4966 //---------------------------------------------------------
4967 // undoAddCR
4968 //---------------------------------------------------------
4969
undoAddCR(ChordRest * cr,Measure * measure,const Fraction & tick)4970 void Score::undoAddCR(ChordRest* cr, Measure* measure, const Fraction& tick)
4971 {
4972 Q_ASSERT(!cr->isChord() || !(toChord(cr)->notes()).empty());
4973 if (!cr->lyrics().empty()) {
4974 // Add chordrest and lyrics separately for correct
4975 // handling of adding lyrics to linked staves.
4976 std::vector<Lyrics*> lyrics;
4977 std::swap(lyrics, cr->lyrics());
4978 undoAddCR(cr, measure, tick);
4979 for (Lyrics* l : lyrics)
4980 undoAddElement(l);
4981 return;
4982 }
4983
4984 Staff* ostaff = cr->staff();
4985 int strack = ostaff->idx() * VOICES + cr->voice();
4986
4987 if (ostaff->score()->excerpt() && !ostaff->score()->excerpt()->tracks().isEmpty())
4988 strack = ostaff->score()->excerpt()->tracks().key(strack, -1);
4989
4990 SegmentType segmentType = SegmentType::ChordRest;
4991
4992 Tuplet* crTuplet = cr->tuplet();
4993
4994 // For linked staves the length of staffList is always > 1 since the list contains the staff itself too!
4995 const bool linked = ostaff->staffList().length() > 1;
4996
4997 for (const Staff* staff : ostaff->staffList()) {
4998 QList<int> tracks;
4999 if (!staff->score()->excerpt()) {
5000 // On masterScore.
5001 int track = staff->idx() * VOICES + (strack % VOICES);
5002 tracks.append(track);
5003 }
5004 else {
5005 QMultiMap<int, int> mapping = staff->score()->excerpt()->tracks();
5006 if (mapping.isEmpty()) {
5007 // This can happen during reading the score and there is
5008 // no Tracklist tag specified.
5009 // TODO solve this in read302.cpp.
5010 tracks.append(strack);
5011 }
5012 else {
5013 // linkedPart : linked staves within same part/instrument.
5014 // linkedScore: linked staves over different scores via excerpts.
5015 const bool linkedPart = linked && (staff != ostaff) && (staff->score() == ostaff->score());
5016 const bool linkedScore = linked && (staff != ostaff) && (staff->score() != ostaff->score());
5017 for (int track : mapping.values(strack)) {
5018 if (linkedPart && !linkedScore) {
5019 tracks.append(staff->idx() * VOICES + mapping.value(track));
5020 }
5021 else if (!linkedPart && linkedScore) {
5022 if ((track >> 2) != staff->idx())
5023 track += (staff->idx() - (track >> 2)) * VOICES;
5024 tracks.append(track);
5025 }
5026 else {
5027 tracks.append(track);
5028 }
5029 }
5030 }
5031 }
5032
5033 for (int ntrack : tracks) {
5034 if (ntrack < staff->part()->startTrack() || ntrack >= staff->part()->endTrack())
5035 continue;
5036
5037 Score* score = staff->score();
5038 Measure* m = (score == this) ? measure : score->tick2measure(tick);
5039 if (!m) {
5040 qDebug("measure not found");
5041 break;
5042 }
5043 Segment* seg = m->undoGetSegment(segmentType, tick);
5044
5045 Q_ASSERT(seg->segmentType() == segmentType);
5046
5047 ChordRest* newcr = (staff == ostaff) ? cr : toChordRest(cr->linkedClone());
5048 newcr->setScore(score);
5049
5050 newcr->setTrack(ntrack);
5051 newcr->setParent(seg);
5052
5053 #ifndef QT_NO_DEBUG
5054 if (newcr->isChord()) {
5055 Chord* chord = toChord(newcr);
5056 // setTpcFromPitch needs to know the note tick position
5057 for (Note* note : chord->notes()) {
5058 // if (note->tpc() == Tpc::TPC_INVALID)
5059 // note->setTpcFromPitch();
5060 Q_ASSERT(note->tpc() != Tpc::TPC_INVALID);
5061 }
5062 }
5063 #endif
5064 if (crTuplet && staff != ostaff) {
5065 // In case of nested tuplets, get the parent tuplet.
5066 Tuplet* parTuplet { nullptr };
5067 if (crTuplet->tuplet()) {
5068 // Look for a tuplet, linked to the parent tuplet of crTuplet but
5069 // which is on the same staff as the new ChordRest.
5070 for (auto e : crTuplet->tuplet()->linkList()) {
5071 Tuplet* t = toTuplet(e);
5072 if (t->staff() == newcr->staff()) {
5073 parTuplet = t;
5074 break;
5075 }
5076 }
5077 }
5078
5079 // Look for a tuplet linked to crTuplet but is on the same staff as
5080 // the new ChordRest. Create a new tuplet if not found.
5081 Tuplet* newTuplet { nullptr };
5082 for (auto e : crTuplet->linkList()) {
5083 Tuplet* t = toTuplet(e);
5084 if (t->staff() == newcr->staff()) {
5085 newTuplet = t;
5086 break;
5087 }
5088 }
5089
5090 if (!newTuplet) {
5091 newTuplet = toTuplet(crTuplet->linkedClone());
5092 newTuplet->setTuplet(parTuplet);
5093 newTuplet->setScore(score);
5094 newTuplet->setTrack(newcr->track());
5095 newTuplet->setParent(m);
5096 }
5097
5098 newcr->setTuplet(newTuplet);
5099 }
5100
5101 if (newcr->isRest() && (toRest(newcr)->isGap()) && !(toRest(newcr)->track() % VOICES))
5102 toRest(newcr)->setGap(false);
5103
5104 undo(new AddElement(newcr));
5105 }
5106 }
5107 }
5108
5109 //---------------------------------------------------------
5110 // undoRemoveElement
5111 //---------------------------------------------------------
5112
undoRemoveElement(Element * element)5113 void Score::undoRemoveElement(Element* element)
5114 {
5115 if (!element)
5116 return;
5117 QList<Segment*> segments;
5118 for (ScoreElement* ee : element->linkList()) {
5119 Element* e = static_cast<Element*>(ee);
5120 undo(new RemoveElement(e));
5121 if (e->parent() && (e->parent()->isSegment())) {
5122 Segment* s = toSegment(e->parent());
5123 if (!segments.contains(s))
5124 segments.append(s);
5125 }
5126 if (e->parent() && e->parent()->isSystem()) {
5127 e->setParent(0); // systems will be regenerated upon redo, so detach
5128 }
5129 }
5130 for (Segment* s : segments) {
5131 if (s->empty()) {
5132 if (s->header() || s->trailer()) // probably more segment types (system header)
5133 s->setEnabled(false);
5134 else
5135 undo(new RemoveElement(s));
5136 }
5137 }
5138 }
5139
5140 //---------------------------------------------------------
5141 // undoChangeSpannerElements
5142 //---------------------------------------------------------
5143
undoChangeSpannerElements(Spanner * spanner,Element * startElement,Element * endElement)5144 void Score::undoChangeSpannerElements(Spanner* spanner, Element* startElement, Element* endElement)
5145 {
5146 Element* oldStartElement = spanner->startElement();
5147 Element* oldEndElement = spanner->endElement();
5148 int startDeltaTrack = startElement && oldStartElement ? startElement->track() - oldStartElement->track() : 0;
5149 int endDeltaTrack = endElement && oldEndElement ? endElement->track() - oldEndElement->track() : 0;
5150 // scan all spanners linked to this one
5151 for (ScoreElement* el : spanner->linkList()) {
5152 Spanner* sp = toSpanner(el);
5153 Element* newStartElement = nullptr;
5154 Element* newEndElement = nullptr;
5155 // if not the current spanner, but one linked to it, determine its new start and end elements
5156 // as modifications 'parallel' to the modifications of the current spanner's start and end elements
5157 if (sp != spanner) {
5158 if (startElement) {
5159 // determine the track where to expect the 'parallel' start element
5160 int newTrack = sp->startElement() ? sp->startElement()->track() + startDeltaTrack : sp->track();
5161 // look in elements linked to new start element for an element with
5162 // same score as linked spanner and appropriate track
5163 for (ScoreElement* ee : startElement->linkList()) {
5164 Element* e = toElement(ee);
5165 if (e->score() == sp->score() && e->track() == newTrack) {
5166 newStartElement = e;
5167 break;
5168 }
5169 }
5170 }
5171 // similarly to determine the 'parallel' end element
5172 if (endElement) {
5173 int newTrack = sp->endElement() ? sp->endElement()->track() + endDeltaTrack : sp->track2();
5174 for (ScoreElement* ee : endElement->linkList()) {
5175 Element* e = toElement(ee);
5176 if (e->score() == sp->score() && e->track() == newTrack) {
5177 newEndElement = e;
5178 break;
5179 }
5180 }
5181 }
5182 }
5183 // if current spanner, just use stored start and end elements
5184 else {
5185 newStartElement = startElement;
5186 newEndElement = endElement;
5187 }
5188 sp->score()->undo(new ChangeSpannerElements(sp, newStartElement, newEndElement));
5189 }
5190 }
5191
5192 //---------------------------------------------------------
5193 // undoChangeTuning
5194 //---------------------------------------------------------
5195
undoChangeTuning(Note * n,qreal v)5196 void Score::undoChangeTuning(Note* n, qreal v)
5197 {
5198 n->undoChangeProperty(Pid::TUNING, v);
5199 }
5200
undoChangeUserMirror(Note * n,MScore::DirectionH d)5201 void Score::undoChangeUserMirror(Note* n, MScore::DirectionH d)
5202 {
5203 n->undoChangeProperty(Pid::MIRROR_HEAD, int(d));
5204 }
5205
5206 //---------------------------------------------------------
5207 // undoChangeTpc
5208 // TODO-TPC: check
5209 //---------------------------------------------------------
5210
undoChangeTpc(Note * note,int v)5211 void Score::undoChangeTpc(Note* note, int v)
5212 {
5213 note->undoChangeProperty(Pid::TPC1, v);
5214 }
5215
5216 //---------------------------------------------------------
5217 // undoAddBracket
5218 //---------------------------------------------------------
5219
undoAddBracket(Staff * staff,int level,BracketType type,int span)5220 void Score::undoAddBracket(Staff* staff, int level, BracketType type, int span)
5221 {
5222 undo(new AddBracket(staff, level, type, span));
5223 }
5224
5225 //---------------------------------------------------------
5226 // undoRemoveBracket
5227 //---------------------------------------------------------
5228
undoRemoveBracket(Bracket * b)5229 void Score::undoRemoveBracket(Bracket* b)
5230 {
5231 undo(new RemoveBracket(b->staff(), b->column(), b->bracketType(), b->span()));
5232 }
5233
5234 //---------------------------------------------------------
5235 // undoInsertTime
5236 // acts on the linked scores as well
5237 //---------------------------------------------------------
5238
undoInsertTime(const Fraction & tick,const Fraction & len)5239 void Score::undoInsertTime(const Fraction& tick, const Fraction& len)
5240 {
5241 if (len.isZero())
5242 return;
5243
5244 QList<Spanner*> sl;
5245 for (auto i : _spanner.map()) {
5246 Spanner* s = i.second;
5247 if (s->tick2() < tick)
5248 continue;
5249 bool append = false;
5250 if (len > Fraction(0, 1)) {
5251 if (tick > s->tick() && tick < s->tick2())
5252 append = true;
5253 else if (tick <= s->tick())
5254 append = true;
5255 }
5256 else {
5257 Fraction tick2 = tick - len;
5258 if (s->tick() >= tick2)
5259 append = true;
5260 else if (s->tick() >= tick && s->tick2() <= tick2)
5261 append = true;
5262 else if ((s->tick() <= tick) && (s->tick2() >= tick2)) {
5263 Fraction t2 = s->tick2() + len;
5264 if (t2 > s->tick())
5265 append = true;
5266 }
5267 else if (s->tick() > tick && s->tick2() > tick2)
5268 append = true;
5269 else if (s->tick() < tick && s->tick2() < tick2)
5270 append = true;
5271 }
5272 for (Spanner* ss : sl) {
5273 if (ss->linkList().contains(s)) {
5274 append = false;
5275 break;
5276 }
5277 }
5278 if (append)
5279 sl.append(s);
5280 }
5281 for (Spanner* s : sl) {
5282 if (len > Fraction(0, 1)) {
5283 if (tick > s->tick() && tick < s->tick2()) {
5284 //
5285 // case a:
5286 // +----spanner--------+
5287 // +---add---
5288 //
5289 s->undoChangeProperty(Pid::SPANNER_TICKS, s->ticks() + len);
5290 }
5291 else if (tick <= s->tick()) {
5292 //
5293 // case b:
5294 // +----spanner--------
5295 // +---add---
5296 // and
5297 // +----spanner--------
5298 // +---add---+
5299 Element* startElement = s->startElement();
5300 Element* endElement = s->endElement();
5301 undoChangeSpannerElements(s, nullptr, nullptr);
5302 s->undoChangeProperty(Pid::SPANNER_TICK, s->tick() + len);
5303 undoChangeSpannerElements(s, startElement, endElement);
5304 }
5305 }
5306 else {
5307 Fraction tick2 = tick - len;
5308 if (s->tick() >= tick2) {
5309 //
5310 // case A:
5311 // +----remove---+ +---spanner---+
5312 //
5313 Fraction t = s->tick() + len;
5314 if (t < Fraction(0,1))
5315 t = Fraction(0,1);
5316 Element* startElement = s->startElement();
5317 Element* endElement = s->endElement();
5318 undoChangeSpannerElements(s, nullptr, nullptr);
5319 s->undoChangeProperty(Pid::SPANNER_TICK, t);
5320 undoChangeSpannerElements(s, startElement, endElement);
5321 }
5322 else if (s->tick() >= tick && s->tick2() <= tick2) {
5323 //
5324 // case B:
5325 // +---spanner---+
5326 // +----remove--------+
5327 //
5328 undoRemoveElement(s);
5329 }
5330 else if ((s->tick() <= tick) && (s->tick2() >= tick2)) {
5331 //
5332 // case C:
5333 // +----spanner--------+
5334 // +---remove---+
5335 //
5336 Fraction t2 = s->tick2() + len;
5337 if (t2 > s->tick())
5338 s->undoChangeProperty(Pid::SPANNER_TICKS, s->ticks() + len);
5339 }
5340 else if (s->tick() > tick && s->tick2() > tick2) {
5341 //
5342 // case D:
5343 // +----spanner--------+
5344 // +---remove---+
5345 //
5346 Fraction d1 = s->tick() - tick;
5347 Fraction d2 = tick2 - s->tick();
5348 Fraction le = s->ticks() - d2;
5349 if (le.isZero())
5350 undoRemoveElement(s);
5351 else {
5352 s->undoChangeProperty(Pid::SPANNER_TICK, s->tick() - d1);
5353 s->undoChangeProperty(Pid::SPANNER_TICKS, le);
5354 }
5355 }
5356 else if (s->tick() < tick && s->tick2() < tick2) {
5357 //
5358 // case E:
5359 // +----spanner--------+
5360 // +---remove---+
5361 //
5362 Fraction d = s->tick2() - tick;
5363 Fraction le = s->ticks() - d;
5364 if (le.isZero())
5365 undoRemoveElement(s);
5366 else
5367 s->undoChangeProperty(Pid::SPANNER_TICKS, le);
5368 }
5369 }
5370 }
5371
5372 undo(new InsertTimeUnmanagedSpanner(this, tick, len));
5373 }
5374
5375 //---------------------------------------------------------
5376 // undoRemoveMeasures
5377 //---------------------------------------------------------
5378
undoRemoveMeasures(Measure * m1,Measure * m2,bool preserveTies)5379 void Score::undoRemoveMeasures(Measure* m1, Measure* m2, bool preserveTies)
5380 {
5381 Q_ASSERT(m1 && m2);
5382
5383 const Fraction startTick = m1->tick();
5384 const Fraction endTick = m2->endTick();
5385 std::set<Spanner*> spannersToRemove;
5386
5387 //
5388 // handle ties which start before m1 and end in (m1-m2)
5389 //
5390 for (Segment* s = m1->first(); s != m2->last(); s = s->next1()) {
5391 if (!s->isChordRestType())
5392 continue;
5393 for (int track = 0; track < ntracks(); ++track) {
5394 Element* e = s->element(track);
5395 if (!e || !e->isChord())
5396 continue;
5397 Chord* c = toChord(e);
5398 for (Note* n : c->notes()) {
5399 // Remove ties crossing measure range boundaries
5400 Tie* t = n->tieBack();
5401 if (t && (t->startNote()->chord()->tick() < startTick)) {
5402 if (preserveTies)
5403 t->setEndNote(0);
5404 else
5405 undoRemoveElement(t);
5406 }
5407 t = n->tieFor();
5408 if (t && (t->endNote()->chord()->tick() >= endTick))
5409 undoRemoveElement(t);
5410
5411 // Do the same for other note-anchored spanners (e.g. glissandi).
5412 // Delay actual removing to avoid modifying lists inside loops over them.
5413 for (Spanner* sb : n->spannerBack()) {
5414 if (sb->tick() < startTick)
5415 spannersToRemove.insert(sb);
5416 }
5417 for (Spanner* sf : n->spannerFor()) {
5418 if (sf->tick2() >= endTick)
5419 spannersToRemove.insert(sf);
5420 }
5421 }
5422 }
5423 }
5424
5425 for (Spanner* s : spannersToRemove)
5426 undoRemoveElement(s);
5427
5428 undo(new RemoveMeasures(m1, m2));
5429 }
5430
5431 }
5432