1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2002-2011 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 /**
14  \file
15  Implementation of class Score (partial).
16 */
17 
18 #include <assert.h>
19 #include "score.h"
20 #include "fermata.h"
21 #include "imageStore.h"
22 #include "key.h"
23 #include "sig.h"
24 #include "clef.h"
25 #include "tempo.h"
26 #include "measure.h"
27 #include "page.h"
28 #include "undo.h"
29 #include "system.h"
30 #include "select.h"
31 #include "segment.h"
32 #include "xml.h"
33 #include "text.h"
34 #include "note.h"
35 #include "chord.h"
36 #include "rest.h"
37 #include "slur.h"
38 #include "staff.h"
39 #include "part.h"
40 #include "style.h"
41 #include "tuplet.h"
42 #include "lyrics.h"
43 #include "pitchspelling.h"
44 #include "line.h"
45 #include "volta.h"
46 #include "repeat.h"
47 #include "ottava.h"
48 #include "barline.h"
49 #include "box.h"
50 #include "utils.h"
51 #include "excerpt.h"
52 #include "stafftext.h"
53 #include "repeatlist.h"
54 #include "keysig.h"
55 #include "beam.h"
56 #include "stafftype.h"
57 #include "tempotext.h"
58 #include "articulation.h"
59 #include "revisions.h"
60 #include "tie.h"
61 #include "tiemap.h"
62 #include "layoutbreak.h"
63 #include "harmony.h"
64 #include "mscore.h"
65 #include "scoreOrder.h"
66 #ifdef OMR
67 #include "omr/omr.h"
68 #endif
69 #include "bracket.h"
70 #include "audio.h"
71 #include "instrtemplate.h"
72 #include "sym.h"
73 #include "rehearsalmark.h"
74 #include "breath.h"
75 #include "instrchange.h"
76 #include "synthesizerstate.h"
77 
78 namespace Ms {
79 
80 MasterScore* gscore;                 ///< system score, used for palettes etc.
81 std::set<Score*> Score::validScores;
82 
83 bool noSeq           = false;
84 bool noMidi          = false;
85 bool midiInputTrace  = false;
86 bool midiOutputTrace = false;
87 
88 //---------------------------------------------------------
89 //   MeasureBaseList
90 //---------------------------------------------------------
91 
MeasureBaseList()92 MeasureBaseList::MeasureBaseList()
93       {
94       _first = 0;
95       _last  = 0;
96       _size  = 0;
97       };
98 
99 //---------------------------------------------------------
100 //   push_back
101 //---------------------------------------------------------
102 
push_back(MeasureBase * e)103 void MeasureBaseList::push_back(MeasureBase* e)
104       {
105       ++_size;
106       if (_last) {
107             _last->setNext(e);
108             e->setPrev(_last);
109             e->setNext(0);
110             }
111       else {
112             _first = e;
113             e->setPrev(0);
114             e->setNext(0);
115             }
116       _last = e;
117       }
118 
119 //---------------------------------------------------------
120 //   push_front
121 //---------------------------------------------------------
122 
push_front(MeasureBase * e)123 void MeasureBaseList::push_front(MeasureBase* e)
124       {
125       ++_size;
126       if (_first) {
127             _first->setPrev(e);
128             e->setNext(_first);
129             e->setPrev(0);
130             }
131       else {
132             _last = e;
133             e->setPrev(0);
134             e->setNext(0);
135             }
136       _first = e;
137       }
138 
139 //---------------------------------------------------------
140 //   add
141 //    insert e before e->next()
142 //---------------------------------------------------------
143 
add(MeasureBase * e)144 void MeasureBaseList::add(MeasureBase* e)
145       {
146       MeasureBase* el = e->next();
147       if (el == 0) {
148             push_back(e);
149             return;
150             }
151       if (el == _first) {
152             push_front(e);
153             return;
154             }
155       ++_size;
156       e->setPrev(el->prev());
157       el->prev()->setNext(e);
158       el->setPrev(e);
159       }
160 
161 //---------------------------------------------------------
162 //   remove
163 //---------------------------------------------------------
164 
remove(MeasureBase * el)165 void MeasureBaseList::remove(MeasureBase* el)
166       {
167       --_size;
168       if (el->prev())
169             el->prev()->setNext(el->next());
170       else
171             _first = el->next();
172       if (el->next())
173             el->next()->setPrev(el->prev());
174       else
175             _last = el->prev();
176       }
177 
178 //---------------------------------------------------------
179 //   insert
180 //---------------------------------------------------------
181 
insert(MeasureBase * fm,MeasureBase * lm)182 void MeasureBaseList::insert(MeasureBase* fm, MeasureBase* lm)
183       {
184       ++_size;
185       for (MeasureBase* m = fm; m != lm; m = m->next())
186             ++_size;
187       MeasureBase* pm = fm->prev();
188       if (pm)
189             pm->setNext(fm);
190       else
191             _first = fm;
192       MeasureBase* nm = lm->next();
193       if (nm)
194             nm->setPrev(lm);
195       else
196             _last = lm;
197       }
198 
199 //---------------------------------------------------------
200 //   remove
201 //---------------------------------------------------------
202 
remove(MeasureBase * fm,MeasureBase * lm)203 void MeasureBaseList::remove(MeasureBase* fm, MeasureBase* lm)
204       {
205       --_size;
206       for (MeasureBase* m = fm; m != lm; m = m->next())
207             --_size;
208       MeasureBase* pm = fm->prev();
209       MeasureBase* nm = lm->next();
210       if (pm)
211             pm->setNext(nm);
212       else
213             _first = nm;
214       if (nm)
215             nm->setPrev(pm);
216       else
217             _last = pm;
218       }
219 
220 //---------------------------------------------------------
221 //   change
222 //---------------------------------------------------------
223 
change(MeasureBase * ob,MeasureBase * nb)224 void MeasureBaseList::change(MeasureBase* ob, MeasureBase* nb)
225       {
226       nb->setPrev(ob->prev());
227       nb->setNext(ob->next());
228       if (ob->prev())
229             ob->prev()->setNext(nb);
230       if (ob->next())
231             ob->next()->setPrev(nb);
232       if (ob == _last)
233             _last = nb;
234       if (ob == _first)
235             _first = nb;
236       if (nb->type() == ElementType::HBOX || nb->type() == ElementType::VBOX
237          || nb->type() == ElementType::TBOX || nb->type() == ElementType::FBOX)
238             nb->setSystem(ob->system());
239       foreach(Element* e, nb->el())
240             e->setParent(nb);
241       }
242 
243 //---------------------------------------------------------
244 //   Score
245 //---------------------------------------------------------
246 
Score()247 Score::Score()
248    : ScoreElement(this), _headersText(MAX_HEADERS, nullptr), _footersText(MAX_FOOTERS, nullptr), _selection(this), _selectionFilter(this)
249       {
250       Score::validScores.insert(this);
251       _masterScore = 0;
252       Layer l;
253       l.name          = "default";
254       l.tags          = 1;
255       _layer.append(l);
256       _layerTags[0]   = "default";
257 
258       _scoreFont = ScoreFont::fontFactory("Leland");
259 
260       _fileDivision           = MScore::division;
261       _style  = MScore::defaultStyle();
262 //      accInfo = tr("No selection");     // ??
263       accInfo = "No selection";
264       _scoreOrder = nullptr;
265       }
266 
Score(MasterScore * parent,bool forcePartStyle)267 Score::Score(MasterScore* parent, bool forcePartStyle /* = true */)
268    : Score{}
269       {
270       Score::validScores.insert(this);
271       _masterScore = parent;
272       if (MScore::defaultStyleForParts())
273             _style = *MScore::defaultStyleForParts();
274       else {
275             // inherit most style settings from parent
276             _style = parent->style();
277 
278             static const Sid styles[] = {
279                   Sid::pageWidth,
280                   Sid::pageHeight,
281                   Sid::pagePrintableWidth,
282                   Sid::pageEvenLeftMargin,
283                   Sid::pageOddLeftMargin,
284                   Sid::pageEvenTopMargin,
285                   Sid::pageEvenBottomMargin,
286                   Sid::pageOddTopMargin,
287                   Sid::pageOddBottomMargin,
288                   Sid::pageTwosided,
289                   Sid::spatium
290                   };
291             // but borrow defaultStyle page layout settings
292             for (auto i : styles)
293                   _style.set(i, MScore::defaultStyle().value(i));
294             // and force some style settings that just make sense for parts
295             if (forcePartStyle) {
296                   style().set(Sid::concertPitch, false);
297                   style().set(Sid::createMultiMeasureRests, true);
298                   style().set(Sid::dividerLeft, false);
299                   style().set(Sid::dividerRight, false);
300                   }
301             }
302       // update style values
303       _style.precomputeValues();
304       _synthesizerState = parent->_synthesizerState;
305       _mscVersion = parent->_mscVersion;
306       }
307 
Score(MasterScore * parent,const MStyle & s)308 Score::Score(MasterScore* parent, const MStyle& s)
309    : Score{parent}
310       {
311       Score::validScores.insert(this);
312       _style  = s;
313       }
314 
315 //---------------------------------------------------------
316 //   ~Score
317 //---------------------------------------------------------
318 
~Score()319 Score::~Score()
320       {
321       Score::validScores.erase(this);
322 
323       foreach(MuseScoreView* v, viewer)
324             v->removeScore();
325       // deselectAll();
326       qDeleteAll(_systems); // systems are layout-only objects so we delete
327                             // them prior to measures.
328       for (MeasureBase* m = _measures.first(); m;) {
329             MeasureBase* nm = m->next();
330             if (m->isMeasure() && toMeasure(m)->mmRest())
331                   delete toMeasure(m)->mmRest();
332             delete m;
333             m = nm;
334             }
335 
336       for (auto it = _spanner.cbegin(); it != _spanner.cend(); ++it)
337             delete it->second;
338       _spanner.clear();
339 
340       qDeleteAll(_parts);
341       qDeleteAll(_staves);
342 //      qDeleteAll(_pages);         // TODO: check
343       _masterScore = 0;
344 
345       imageStore.clearUnused();
346       }
347 
348 //---------------------------------------------------------
349 //   Score::clone
350 //         To create excerpt clone to show when changing PageSettings
351 //         Use MasterScore::clone() instead
352 //---------------------------------------------------------
353 
clone()354 Score* Score::clone()
355       {
356       QBuffer buffer;
357       buffer.open(QIODevice::WriteOnly);
358       XmlWriter xml(this, &buffer);
359       xml.header();
360 
361       xml.stag("museScore version=\"" MSC_VERSION "\"");
362       write(xml, false);
363       xml.etag();
364 
365       buffer.close();
366 
367       XmlReader r(buffer.buffer());
368       MasterScore* score = new MasterScore(style());
369       score->read1(r, true);
370 
371       score->addLayoutFlags(LayoutFlag::FIX_PITCH_VELO);
372       score->doLayout();
373       return score;
374       }
375 
376 //---------------------------------------------------------
377 //   Score::onElementDestruction
378 //    Ensure correct state of the score after destruction
379 //    of the element (e.g. remove invalid pointers etc.).
380 //---------------------------------------------------------
381 
onElementDestruction(Element * e)382 void Score::onElementDestruction(Element* e)
383       {
384       Score* score = e->score();
385       if (!score || Score::validScores.find(score) == Score::validScores.end()) {
386             // No score or the score is already deleted
387             return;
388             }
389       score->selection().remove(e);
390       score->cmdState().unsetElement(e);
391       for (MuseScoreView* v : qAsConst(score->viewer))
392             v->onElementDestruction(e);
393       }
394 
395 //---------------------------------------------------------
396 //   addMeasure
397 //---------------------------------------------------------
398 
addMeasure(MeasureBase * m,MeasureBase * pos)399 void Score::addMeasure(MeasureBase* m, MeasureBase* pos)
400       {
401       m->setNext(pos);
402       _measures.add(m);
403       }
404 
405 //---------------------------------------------------------
406 //    fixTicks
407 //    update:
408 //      - measure ticks
409 //      - tempo map
410 //      - time signature map
411 //---------------------------------------------------------
412 
413 /**
414  This is needed after
415       - inserting or removing a measure
416       - changing the sigmap
417       - after inserting/deleting time (changes the sigmap)
418 */
419 
fixTicks()420 void Score::fixTicks()
421       {
422       Fraction tick = Fraction(0,1);
423       Measure* fm = firstMeasure();
424       if (fm == 0)
425             return;
426 
427       for (Staff* staff : qAsConst(_staves))
428             staff->clearTimeSig();
429 
430       if (isMaster()) {
431             tempomap()->clear();
432             sigmap()->clear();
433             sigmap()->add(0, SigEvent(fm->ticks(),  fm->timesig(), 0));
434             }
435 
436       for (MeasureBase* mb = first(); mb; mb = mb->next()) {
437             if (mb->type() != ElementType::MEASURE) {
438                   mb->setTick(tick);
439                   continue;
440                   }
441             Measure* m            = toMeasure(mb);
442             Fraction mtick        = m->tick();
443             Fraction diff         = tick - mtick;
444             Fraction measureTicks = m->ticks();
445             m->moveTicks(diff);
446             if (m->mmRest())
447                   m->mmRest()->moveTicks(diff);
448 
449             rebuildTempoAndTimeSigMaps(m);
450 
451             tick += measureTicks;
452             }
453       // Now done in getNextMeasure(), do we keep?
454       if (tempomap()->empty())
455             tempomap()->setTempo(0, _defaultTempo);
456       }
457 
458 //---------------------------------------------------------
459 //    fixTicks
460 ///    updates tempomap and time sig map for a measure
461 //---------------------------------------------------------
462 
rebuildTempoAndTimeSigMaps(Measure * measure)463 void Score::rebuildTempoAndTimeSigMaps(Measure* measure)
464       {
465       if (isMaster()) {
466             // Reset tempo to set correct time stretch for fermata.
467             const Fraction& startTick = measure->tick();
468             resetTempoRange(startTick, measure->endTick());
469 
470             // Implement section break rest
471             for (MeasureBase* mb = measure->prev(); mb && mb->endTick() == startTick; mb = mb->prev()) {
472                   if (mb->pause())
473                         setPause(startTick, mb->pause());
474                   }
475 
476             // Add pauses from the end of the previous measure (at measure->tick()):
477             for (Segment* s = measure->first(); s && s->tick() == startTick; s = s->prev1()) {
478                   if (!s->isBreathType())
479                         continue;
480                   qreal length = 0.0;
481                   for (Element* e : s->elist()) {
482                         if (e && e->isBreath())
483                               length = qMax(length, toBreath(e)->pause());
484                         }
485                   if (length != 0.0)
486                         setPause(startTick, length);
487                   }
488             }
489 
490       for (Segment& segment : measure->segments()) {
491             if (segment.isBreathType()) {
492                   if (!isMaster())
493                         continue;
494                   qreal length = 0.0;
495                   Fraction tick = segment.tick();
496                   // find longest pause
497                   for (int i = 0, n = ntracks(); i < n; ++i) {
498                         Element* e = segment.element(i);
499                         if (e && e->isBreath()) {
500                               Breath* b = toBreath(e);
501                               length = qMax(length, b->pause());
502                               }
503                         }
504                   if (length != 0.0)
505                         setPause(tick, length);
506                   }
507             else if (segment.isTimeSigType()) {
508                   for (int staffIdx = 0; staffIdx < _staves.size(); ++staffIdx) {
509                         TimeSig* ts = toTimeSig(segment.element(staffIdx * VOICES));
510                         if (ts)
511                               staff(staffIdx)->addTimeSig(ts);
512                         }
513                   }
514             else if (segment.isChordRestType()) {
515                   if (!isMaster())
516                         continue;
517                   qreal stretch = 0.0;
518                   for (Element* e : segment.annotations()) {
519                         if (e->isFermata() && toFermata(e)->play())
520                               stretch = qMax(stretch, toFermata(e)->timeStretch());
521                         else if (e->isTempoText()) {
522                               TempoText* tt = toTempoText(e);
523                               if (tt->isRelative())
524                                     tt->updateRelative();
525                               setTempo(tt->segment(), tt->tempo());
526                               }
527                         }
528                   if (stretch != 0.0 && stretch != 1.0) {
529                         qreal otempo = tempomap()->tempo(segment.tick().ticks());
530                         qreal ntempo = otempo / stretch;
531                         setTempo(segment.tick(), ntempo);
532                         Fraction etick = segment.tick() + segment.ticks() - Fraction(1, 480*4);
533                         auto e = tempomap()->find(etick.ticks());
534                         if (e == tempomap()->end())
535                               setTempo(etick, otempo);
536                         }
537                   }
538             }
539 
540       // update time signature map
541       // create event if measure len and time signature are different
542       // even if they are equivalent 4/4 vs 2/2
543       // also check if nominal time signature has changed
544 
545       if (isMaster()) {
546             const Measure* m = measure;
547             const Fraction mTicks = m->isMMRest() ? m->mmRestFirst()->ticks() : m->ticks(); // for time signature the underlying measure length matters for MM rests
548 
549             const Measure* pm = measure->prevMeasure();
550             // prevMeasure() doesn't return MM rest so we don't handle it here
551 
552             if (pm && (!mTicks.identical(pm->ticks()) || !m->timesig().identical(pm->timesig())))
553                   sigmap()->add(m->tick().ticks(), SigEvent(mTicks, m->timesig(), m->no()));
554             }
555       }
556 
557 //---------------------------------------------------------
558 //   pos2measure
559 //     Return measure for canvas relative position \a p.
560 //---------------------------------------------------------
561 
pos2measure(const QPointF & p,int * rst,int * pitch,Segment ** seg,QPointF * offset) const562 Measure* Score::pos2measure(const QPointF& p, int* rst, int* pitch, Segment** seg, QPointF* offset) const
563       {
564       Measure* m = searchMeasure(p);
565       if (m == 0)
566             return 0;
567 
568       System* s = m->system();
569       qreal y   = p.y() - s->canvasPos().y();
570 
571       const int i = s->searchStaff(y);
572 
573       // search for segment + offset
574       QPointF pppp = p - m->canvasPos();
575       int strack = i * VOICES;
576       if (!staff(i))
577             return 0;
578 //      int etrack = staff(i)->part()->nstaves() * VOICES + strack;
579       int etrack = VOICES + strack;
580 
581       constexpr SegmentType st = SegmentType::ChordRest;
582       Segment* segment = m->searchSegment(pppp.x(), st, strack, etrack);
583       if (segment) {
584             SysStaff* sstaff = m->system()->staff(i);
585             *rst = i;
586             if (pitch) {
587                   Staff* s1 = _staves[i];
588                   Fraction tick  = segment->tick();
589                   ClefType clef = s1->clef(tick);
590                   *pitch = y2pitch(pppp.y() - sstaff->bbox().y(), clef, s1->spatium(tick));
591                   }
592             if (offset)
593                   *offset = pppp - QPointF(segment->x(), sstaff->bbox().y());
594             if (seg)
595                   *seg = segment;
596             return m;
597             }
598 
599       return 0;
600       }
601 
602 //---------------------------------------------------------
603 //   dragPosition
604 ///   \param p   drag position in canvas coordinates
605 ///   \param rst \b input: current staff index \n
606 ///              \b output: new staff index for drag position
607 ///   \param seg \b input: current segment \n
608 ///              \b output: new segment for drag position
609 //---------------------------------------------------------
610 
dragPosition(const QPointF & p,int * rst,Segment ** seg,qreal spacingFactor) const611 void Score::dragPosition(const QPointF& p, int* rst, Segment** seg, qreal spacingFactor) const
612       {
613       const System* preferredSystem = (*seg) ? (*seg)->system() : nullptr;
614       Measure* m = searchMeasure(p, preferredSystem, spacingFactor);
615       if (m == 0 || m->isMMRest())
616             return;
617 
618       System* s = m->system();
619       qreal y   = p.y() - s->canvasPos().y();
620 
621       const int i = s->searchStaff(y, *rst, spacingFactor);
622 
623       // search for segment + offset
624       QPointF pppp = p - m->canvasPos();
625       int strack = staff2track(i);
626       if (!staff(i))
627             return;
628       int etrack = staff2track(i + 1);
629 
630       constexpr SegmentType st = SegmentType::ChordRest;
631       Segment* segment = m->searchSegment(pppp.x(), st, strack, etrack, *seg, spacingFactor);
632       if (segment) {
633             *rst = i;
634             *seg = segment;
635             return;
636             }
637 
638       return;
639       }
640 
641 //---------------------------------------------------------
642 //   setShowInvisible
643 //---------------------------------------------------------
644 
setShowInvisible(bool v)645 void Score::setShowInvisible(bool v)
646       {
647       _showInvisible = v;
648       // BSP tree does not include elements which are not
649       // displayed, so we need to refresh it to get
650       // invisible elements displayed or properly hidden.
651       rebuildBspTree();
652       setUpdateAll();
653       }
654 
655 //---------------------------------------------------------
656 //   setShowUnprintable
657 //---------------------------------------------------------
658 
setShowUnprintable(bool v)659 void Score::setShowUnprintable(bool v)
660       {
661       _showUnprintable = v;
662       setUpdateAll();
663       }
664 
665 //---------------------------------------------------------
666 //   setShowFrames
667 //---------------------------------------------------------
668 
setShowFrames(bool v)669 void Score::setShowFrames(bool v)
670       {
671       _showFrames = v;
672       setUpdateAll();
673       }
674 
675 //---------------------------------------------------------
676 //   setShowPageborders
677 //---------------------------------------------------------
678 
setShowPageborders(bool v)679 void Score::setShowPageborders(bool v)
680       {
681       _showPageborders = v;
682       setUpdateAll();
683       }
684 
685 //---------------------------------------------------------
686 //   setMarkIrregularMeasures
687 //---------------------------------------------------------
688 
setMarkIrregularMeasures(bool v)689 void Score::setMarkIrregularMeasures(bool v)
690       {
691       _markIrregularMeasures = v;
692       setUpdateAll();
693       }
694 
695 //---------------------------------------------------------
696 //   readOnly
697 //---------------------------------------------------------
698 
readOnly() const699 bool Score::readOnly() const
700       {
701       return _masterScore->readOnly();
702       }
703 
704 //---------------------------------------------------------
705 //   dirty
706 //---------------------------------------------------------
707 
dirty() const708 bool Score::dirty() const
709       {
710       return !undoStack()->isClean();
711       }
712 
713 //---------------------------------------------------------
714 //   state
715 //---------------------------------------------------------
716 
state() const717 ScoreContentState Score::state() const
718       {
719       return ScoreContentState(this, undoStack()->state());
720       }
721 
722 //---------------------------------------------------------
723 //   playlistDirty
724 //---------------------------------------------------------
725 
playlistDirty() const726 bool Score::playlistDirty() const
727       {
728       return masterScore()->playlistDirty();
729       }
730 
731 //---------------------------------------------------------
732 //   setPlaylistDirty
733 //---------------------------------------------------------
734 
setPlaylistDirty()735 void Score::setPlaylistDirty()
736       {
737       masterScore()->setPlaylistDirty();
738       }
739 
740 //---------------------------------------------------------
741 //   setPlaylistDirty
742 //---------------------------------------------------------
743 
setPlaylistDirty()744 void MasterScore::setPlaylistDirty()
745       {
746       _playlistDirty = true;
747       _repeatList->setScoreChanged();
748       _repeatList2->setScoreChanged();
749       }
750 
751 //---------------------------------------------------------
752 //   spell
753 //---------------------------------------------------------
754 
spell()755 void Score::spell()
756       {
757       for (int i = 0; i < nstaves(); ++i) {
758             std::vector<Note*> notes;
759             for (Segment* s = firstSegment(SegmentType::All); s; s = s->next1()) {
760                   int strack = i * VOICES;
761                   int etrack = strack + VOICES;
762                   for (int track = strack; track < etrack; ++track) {
763                         Element* e = s->element(track);
764                         if (e && e->type() == ElementType::CHORD)
765                               notes.insert(notes.end(),
766                                  toChord(e)->notes().begin(),
767                                  toChord(e)->notes().end());
768                         }
769                   }
770             spellNotelist(notes);
771             }
772       }
773 
spell(int startStaff,int endStaff,Segment * startSegment,Segment * endSegment)774 void Score::spell(int startStaff, int endStaff, Segment* startSegment, Segment* endSegment)
775       {
776       for (int i = startStaff; i < endStaff; ++i) {
777             std::vector<Note*> notes;
778             for (Segment* s = startSegment; s && s != endSegment; s = s->next()) {
779                   int strack = i * VOICES;
780                   int etrack = strack + VOICES;
781                   for (int track = strack; track < etrack; ++track) {
782                         Element* e = s->element(track);
783                         if (e && e->type() == ElementType::CHORD)
784                               notes.insert(notes.end(),
785                                  toChord(e)->notes().begin(),
786                                  toChord(e)->notes().end());
787                         }
788                   }
789             spellNotelist(notes);
790             }
791       }
792 
793 //---------------------------------------------------------
794 //   prevNote
795 //---------------------------------------------------------
796 
prevNote(Note * n)797 Note* prevNote(Note* n)
798       {
799       Chord* chord = n->chord();
800       Segment* seg = chord->segment();
801       const std::vector<Note*> nl = chord->notes();
802       auto i = std::find(nl.begin(), nl.end(), n);
803       if (i != nl.begin())
804             return *(i-1);
805       int staff      = n->staffIdx();
806       int startTrack = staff * VOICES + n->voice() - 1;
807       int endTrack   = 0;
808       while (seg) {
809             if (seg->segmentType() == SegmentType::ChordRest) {
810                   for (int track = startTrack; track >= endTrack; --track) {
811                         Element* e = seg->element(track);
812                         if (e && e->type() == ElementType::CHORD)
813                               return toChord(e)->upNote();
814                         }
815                   }
816             seg = seg->prev1();
817             startTrack = staff * VOICES + VOICES - 1;
818             }
819       return n;
820       }
821 
822 //---------------------------------------------------------
823 //   nextNote
824 //---------------------------------------------------------
825 
nextNote(Note * n)826 static Note* nextNote(Note* n)
827       {
828       Chord* chord = n->chord();
829       const std::vector<Note*> nl = chord->notes();
830       auto i = std::find(nl.begin(), nl.end(), n);
831       if (i != nl.end()) {
832             ++i;
833             if (i != nl.end())
834                   return *i;
835             }
836       Segment* seg   = chord->segment();
837       int staff      = n->staffIdx();
838       int startTrack = staff * VOICES + n->voice() + 1;
839       int endTrack   = staff * VOICES + VOICES;
840       while (seg) {
841             if (seg->segmentType() == SegmentType::ChordRest) {
842                   for (int track = startTrack; track < endTrack; ++track) {
843                         Element* e = seg->element(track);
844                         if (e && e->type() == ElementType::CHORD) {
845                               return ((Chord*)e)->downNote();
846                               }
847                         }
848                   }
849             seg = seg->next1();
850             startTrack = staff * VOICES;
851             }
852       return n;
853       }
854 
855 //---------------------------------------------------------
856 //   spell
857 //---------------------------------------------------------
858 
spell(Note * note)859 void Score::spell(Note* note)
860       {
861       std::vector<Note*> notes;
862 
863       notes.push_back(note);
864       Note* nn = nextNote(note);
865       notes.push_back(nn);
866       nn = nextNote(nn);
867       notes.push_back(nn);
868       nn = nextNote(nn);
869       notes.push_back(nn);
870 
871       nn = prevNote(note);
872       notes.insert(notes.begin(), nn);
873       nn = prevNote(nn);
874       notes.insert(notes.begin(), nn);
875       nn = prevNote(nn);
876       notes.insert(notes.begin(), nn);
877 
878       int opt = Ms::computeWindow(notes, 0, 7);
879       note->setTpc(Ms::tpc(3, note->pitch(), opt));
880       }
881 
882 //---------------------------------------------------------
883 //   appendPart
884 //---------------------------------------------------------
885 
appendPart(Part * p)886 void Score::appendPart(Part* p)
887       {
888       _parts.append(p);
889       }
890 
891 //---------------------------------------------------------
892 //   searchPage
893 //    p is in canvas coordinates
894 //---------------------------------------------------------
895 
searchPage(const QPointF & p) const896 Page* Score::searchPage(const QPointF& p) const
897       {
898       for (Page* page : pages()) {
899             QRectF r = page->bbox().translated(page->pos());
900             if (r.contains(p))
901                   return page;
902             }
903       return 0;
904       }
905 
906 //---------------------------------------------------------
907 //   searchSystem
908 ///   Returns list of systems as there may be more than
909 ///   one system in a row
910 ///   \param pos Position in canvas coordinates
911 ///   \param preferredSystem If not nullptr, will give more
912 ///   space to the given system when searching it by its
913 ///   coordinate.
914 ///   \returns List of found systems.
915 //---------------------------------------------------------
916 
searchSystem(const QPointF & pos,const System * preferredSystem,qreal spacingFactor,qreal preferredSpacingFactor) const917 QList<System*> Score::searchSystem(const QPointF& pos, const System* preferredSystem, qreal spacingFactor, qreal preferredSpacingFactor) const
918       {
919       QList<System*> systems;
920       Page* page = searchPage(pos);
921       if (page == 0)
922             return systems;
923       qreal y = pos.y() - page->pos().y();  // transform to page relative
924       const QList<System*>* sl = &page->systems();
925       qreal y2;
926       int n = sl->size();
927       for (int i = 0; i < n; ++i) {
928             System* s = sl->at(i);
929             System* ns = 0;               // next system row
930             int ii = i + 1;
931             for (; ii < n; ++ii) {
932                   ns = sl->at(ii);
933                   if (ns->y() != s->y())
934                         break;
935                   }
936             if ((ii == n) || (ns == 0))
937                   y2 = page->height();
938             else {
939                   qreal currentSpacingFactor;
940                   qreal sy2 = s->y() + s->bbox().height();
941                   if (s == preferredSystem)
942                         currentSpacingFactor = preferredSpacingFactor; //y2 = ns->y();
943                   else if (ns == preferredSystem)
944                         currentSpacingFactor = 1.0 - preferredSpacingFactor; //y2 = sy2;
945                   else
946                         currentSpacingFactor = spacingFactor;
947                   y2 = sy2 + (ns->y() - sy2) * currentSpacingFactor;
948                   }
949             if (y < y2) {
950                   systems.append(s);
951                   for (int iii = i+1; ii < n; ++iii) {
952                         if (sl->at(iii)->y() != s->y())
953                               break;
954                         systems.append(sl->at(iii));
955                         }
956                   return systems;
957                   }
958             }
959       return systems;
960       }
961 
962 //---------------------------------------------------------
963 //   searchMeasure
964 ///   \param p Position in canvas coordinates
965 ///   \param preferredSystem If not nullptr, will give more
966 ///   space to measures in this system when searching.
967 //---------------------------------------------------------
968 
searchMeasure(const QPointF & p,const System * preferredSystem,qreal spacingFactor,qreal preferredSpacingFactor) const969 Measure* Score::searchMeasure(const QPointF& p, const System* preferredSystem, qreal spacingFactor, qreal preferredSpacingFactor) const
970       {
971       QList<System*> systems = searchSystem(p, preferredSystem, spacingFactor, preferredSpacingFactor);
972       for (System* system : qAsConst(systems)) {
973             qreal x = p.x() - system->canvasPos().x();
974             for (MeasureBase* mb : system->measures()) {
975                   if (mb->isMeasure() && (x < (mb->x() + mb->bbox().width())))
976                         return toMeasure(mb);
977                   }
978             }
979       return 0;
980       }
981 
982 //---------------------------------------------------------
983 //    getNextValidInputSegment
984 //    - s is of type SegmentType::ChordRest
985 //---------------------------------------------------------
986 
getNextValidInputSegment(Segment * s,int track,int voice)987 static Segment* getNextValidInputSegment(Segment* s, int track, int voice)
988       {
989       if (s == 0)
990             return 0;
991       Q_ASSERT(s->segmentType() == SegmentType::ChordRest);
992       // Segment* s1 = s;
993       ChordRest* cr1 = nullptr;
994       for (Segment* s1 = s; s1; s1 = s1->prev(SegmentType::ChordRest)) {
995             cr1 = toChordRest(s1->element(track + voice));
996             if (cr1)
997                   break;
998             }
999       Fraction nextTick = (cr1 == nullptr) ? s->measure()->tick() : cr1->tick() + cr1->actualTicks();
1000 
1001       static const SegmentType st { SegmentType::ChordRest };
1002       while (s) {
1003             if (s->element(track + voice))
1004                   break;
1005             if (voice && s->tick() == nextTick)
1006                   return s;
1007 #if 0
1008             int v;
1009             for (v = 0; v < VOICES; ++v) {
1010                   if (s->element(track + v))
1011                         break;
1012                   }
1013             if ((v != VOICES) && voice) {
1014                   int ntick;
1015                   bool skipChord = false;
1016                   bool ns        = false;
1017                   for (Segment* s1 = s->measure()->first(st); s1; s1 = s1->next(st)) {
1018                         ChordRest* cr = toChordRest(s1->element(track + voice));
1019                         if (cr) {
1020                               if (ns)
1021                                     return s1;
1022                               ntick = s1->tick() + cr->actualTicks();
1023                               skipChord = true;
1024                               }
1025                         if (s1 == s)
1026                               ns = true;
1027                         if (skipChord) {
1028                               if (s->tick() >= ntick)
1029                                     skipChord = false;
1030                               }
1031                         if (!skipChord && ns)
1032                               return s1;
1033                         }
1034                   if (!skipChord)
1035                         return s;
1036                   }
1037 #endif
1038             s = s->next(st);
1039             }
1040       return s;
1041       }
1042 
1043 //---------------------------------------------------------
1044 //   getPosition
1045 //    return true if valid position found
1046 //---------------------------------------------------------
1047 
getPosition(Position * pos,const QPointF & p,int voice) const1048 bool Score::getPosition(Position* pos, const QPointF& p, int voice) const
1049       {
1050       System* preferredSystem = nullptr;
1051       int preferredStaffIdx = -1;
1052       const qreal spacingFactor = 0.5;
1053       const qreal preferredSpacingFactor = 0.75;
1054       if (noteEntryMode() && inputState().staffGroup() != StaffGroup::TAB) {
1055             // for non-tab staves, prefer the current system & staff
1056             // this makes it easier to add notes far above or below the staff
1057             // not helpful for tab since notes are not entered above or below
1058             Segment* seg = inputState().segment();
1059             if (seg)
1060                   preferredSystem = seg->system();
1061             int track = inputState().track();
1062             if (track >= 0)
1063                   preferredStaffIdx = track >> 2;
1064             }
1065       Measure* measure = searchMeasure(p, preferredSystem, spacingFactor, preferredSpacingFactor);
1066       if (measure == 0)
1067             return false;
1068 
1069       pos->fret = FRET_NONE;
1070       //
1071       //    search staff
1072       //
1073       pos->staffIdx      = 0;
1074       SysStaff* sstaff   = 0;
1075       System* system     = measure->system();
1076       qreal y           = p.y() - system->pagePos().y();
1077       for (; pos->staffIdx < nstaves(); ++pos->staffIdx) {
1078             Staff* st = staff(pos->staffIdx);
1079             if (!st->part()->show())
1080                   continue;
1081             qreal sy2;
1082             SysStaff* ss = system->staff(pos->staffIdx);
1083             if (!ss->show())
1084                   continue;
1085             int nidx = -1;
1086             SysStaff* nstaff = 0;
1087 
1088             // find next visible staff
1089             for (int i = pos->staffIdx + 1; i < nstaves(); ++i) {
1090                   Staff* sti = staff(i);
1091                   if (!sti->part()->show())
1092                         continue;
1093                   nstaff = system->staff(i);
1094                   if (!nstaff->show()) {
1095                         nstaff = 0;
1096                         continue;
1097                         }
1098                   if (i == preferredStaffIdx)
1099                         nidx = i;
1100                   break;
1101                   }
1102 
1103             if (nstaff) {
1104                   qreal currentSpacingFactor;
1105                   if (pos->staffIdx == preferredStaffIdx)
1106                         currentSpacingFactor = preferredSpacingFactor;
1107                   else if (nidx == preferredStaffIdx)
1108                         currentSpacingFactor = 1.0 - preferredSpacingFactor;
1109                   else
1110                         currentSpacingFactor = spacingFactor;
1111                   qreal s1y2 = ss->bbox().bottom();
1112                   sy2        = system->page()->canvasPos().y() + s1y2 + (nstaff->bbox().y() - s1y2) * currentSpacingFactor;
1113                   }
1114             else
1115                   sy2 = system->page()->canvasPos().y() + system->page()->height() - system->pagePos().y();   // system->height();
1116             if (y < sy2) {
1117                   sstaff = ss;
1118                   break;
1119                   }
1120             }
1121       if (sstaff == 0)
1122             return false;
1123 
1124       //
1125       //    search segment
1126       //
1127       QPointF pppp(p - measure->canvasPos());
1128       qreal x         = pppp.x();
1129       Segment* segment = 0;
1130       pos->segment     = 0;
1131 
1132       // int track = pos->staffIdx * VOICES + voice;
1133       int track = pos->staffIdx * VOICES;
1134 
1135       for (segment = measure->first(SegmentType::ChordRest); segment;) {
1136             segment = getNextValidInputSegment(segment, track, voice);
1137             if (segment == 0)
1138                   break;
1139             Segment* ns = getNextValidInputSegment(segment->next(SegmentType::ChordRest), track, voice);
1140 
1141             qreal x1 = segment->x();
1142             qreal x2;
1143             qreal d;
1144             if (ns) {
1145                   x2    = ns->x();
1146                   d     = x2 - x1;
1147                   }
1148             else {
1149                   x2    = measure->bbox().width();
1150                   d     = (x2 - x1) * 2.0;
1151                   x     = x1;
1152                   pos->segment = segment;
1153                   break;
1154                   }
1155 
1156             if (x < (x1 + d * .5)) {
1157                   x = x1;
1158                   pos->segment = segment;
1159                   break;
1160                   }
1161             segment = ns;
1162             }
1163       if (segment == 0)
1164             return false;
1165       //
1166       // TODO: restrict to reasonable values (pitch 0-127)
1167       //
1168       const Staff* s      = staff(pos->staffIdx);
1169       const Fraction tick = segment->tick();
1170       const qreal mag     = s->mag(tick);
1171       // in TABs, step from one string to another; in other staves, step on and between lines
1172       qreal lineDist = s->staffType(tick)->lineDistance().val() * (s->isTabStaff(measure->tick()) ? 1 : .5) * mag * spatium();
1173 
1174       const qreal yOff = sstaff->yOffset();  // Get system staff vertical offset (usually for 1-line staves)
1175       pos->line  = lrint((pppp.y() - sstaff->bbox().y() - yOff) / lineDist);
1176       if (s->isTabStaff(measure->tick())) {
1177             if (pos->line < -1 || pos->line > s->lines(tick)+1)
1178                   return false;
1179             if (pos->line < 0)
1180                   pos->line = 0;
1181             else if (pos->line >= s->lines(tick))
1182                   pos->line = s->lines(tick) - 1;
1183             }
1184       else {
1185             int minLine   = absStep(0);
1186             ClefType clef = s->clef(pos->segment->tick());
1187             minLine       = relStep(minLine, clef);
1188             int maxLine   = absStep(127);
1189             maxLine       = relStep(maxLine, clef);
1190 
1191             if (pos->line > minLine || pos->line < maxLine)
1192                   return false;
1193             }
1194 
1195       y         = sstaff->y() + pos->line * lineDist;
1196       pos->pos  = QPointF(x, y) + measure->canvasPos();
1197       return true;
1198       }
1199 
1200 //---------------------------------------------------------
1201 //   checkHasMeasures
1202 //---------------------------------------------------------
1203 
checkHasMeasures() const1204 bool Score::checkHasMeasures() const
1205       {
1206       Page* page = pages().isEmpty() ? 0 : pages().front();
1207       const QList<System*>* sl = page ? &page->systems() : 0;
1208       if (sl == 0 || sl->empty() || sl->front()->measures().empty()) {
1209             qDebug("first create measure, then repeat operation");
1210             return false;
1211             }
1212       return true;
1213       }
1214 
1215 #if 0
1216 //---------------------------------------------------------
1217 //   moveBracket
1218 //    columns are counted from right to left
1219 //---------------------------------------------------------
1220 
1221 void Score::moveBracket(int staffIdx, int srcCol, int dstCol)
1222       {
1223       for (System* system : systems())
1224             system->moveBracket(staffIdx, srcCol, dstCol);
1225       }
1226 #endif
1227 
1228 //---------------------------------------------------------
1229 //   spatiumHasChanged
1230 //---------------------------------------------------------
1231 
spatiumHasChanged(void * data,Element * e)1232 static void spatiumHasChanged(void* data, Element* e)
1233       {
1234       qreal* val = (qreal*)data;
1235       e->spatiumChanged(val[0], val[1]);
1236       }
1237 
1238 //---------------------------------------------------------
1239 //   spatiumChanged
1240 //---------------------------------------------------------
1241 
spatiumChanged(qreal oldValue,qreal newValue)1242 void Score::spatiumChanged(qreal oldValue, qreal newValue)
1243       {
1244       qreal data[2];
1245       data[0] = oldValue;
1246       data[1] = newValue;
1247       scanElements(data, spatiumHasChanged, true);
1248       for (Staff* staff : qAsConst(_staves))
1249             staff->spatiumChanged(oldValue, newValue);
1250       _noteHeadWidth = _scoreFont->width(SymId::noteheadBlack, newValue / SPATIUM20);
1251       }
1252 
1253 //---------------------------------------------------------
1254 //   updateStyle
1255 //---------------------------------------------------------
1256 
updateStyle(void *,Element * e)1257 static void updateStyle(void*, Element* e)
1258       {
1259       bool v = e->generated();
1260       e->styleChanged();
1261       e->setGenerated(v);
1262       }
1263 
1264 //---------------------------------------------------------
1265 //   styleChanged
1266 //    must be called after every style change
1267 //---------------------------------------------------------
1268 
styleChanged()1269 void Score::styleChanged()
1270       {
1271       scanElements(0, updateStyle);
1272       for(int i = 0; i < MAX_HEADERS; i++)
1273             if (headerText(i))
1274                   headerText(i)->styleChanged();
1275       for(int i = 0; i < MAX_FOOTERS; i++)
1276             if (footerText(i))
1277                   footerText(i)->styleChanged();
1278       setLayoutAll();
1279       }
1280 
1281 //---------------------------------------------------------
1282 //   getCreateMeasure
1283 //    - return Measure for tick
1284 //    - create new Measure(s) if there is no measure for
1285 //      this tick
1286 //---------------------------------------------------------
1287 
getCreateMeasure(const Fraction & tick)1288 Measure* Score::getCreateMeasure(const Fraction& tick)
1289       {
1290       Measure* last = lastMeasure();
1291       if (last == 0 || ((last->tick() + last->ticks()) <= tick)) {
1292             Fraction lastTick  = last ? (last->tick()+last->ticks()) : Fraction(0,1);
1293             while (tick >= lastTick) {
1294                   Measure* m = new Measure(this);
1295                   Fraction ts = sigmap()->timesig(lastTick).timesig();
1296                   m->setTick(lastTick);
1297                   m->setTimesig(ts);
1298                   m->setTicks(ts);
1299                   measures()->add(toMeasureBase(m));
1300                   lastTick += Fraction::fromTicks(ts.ticks());
1301                   }
1302             }
1303       return tick2measure(tick);
1304       }
1305 
1306 //---------------------------------------------------------
1307 //   addElement
1308 //---------------------------------------------------------
1309 
1310 /**
1311  Add \a element to its parent.
1312 
1313  Several elements (clef, keysig, timesig) need special handling, as they may cause
1314  changes throughout the score.
1315 */
1316 
addElement(Element * element)1317 void Score::addElement(Element* element)
1318       {
1319       Element* parent = element->parent();
1320       element->triggerLayout();
1321 
1322 //      qDebug("Score(%p) Element(%p)(%s) parent %p(%s)",
1323 //         this, element, element->name(), parent, parent ? parent->name() : "");
1324 
1325       ElementType et = element->type();
1326       if (et == ElementType::MEASURE
1327          || (et == ElementType::HBOX && !(parent && parent->isVBox()))
1328          || et == ElementType::VBOX
1329          || et == ElementType::TBOX
1330          || et == ElementType::FBOX
1331          ) {
1332             measures()->add(toMeasureBase(element));
1333             element->triggerLayout();
1334             return;
1335             }
1336 
1337       if (parent)
1338             parent->add(element);
1339 
1340       switch (et) {
1341             case ElementType::BEAM:
1342                   {
1343                   Beam* b = toBeam(element);
1344                   int n = b->elements().size();
1345                   for (int i = 0; i < n; ++i)
1346                         b->elements().at(i)->setBeam(b);
1347                   }
1348                   break;
1349 
1350             case ElementType::SLUR:
1351                   addLayoutFlags(LayoutFlag::PLAY_EVENTS);
1352                   // fall through
1353 
1354             case ElementType::VOLTA:
1355             case ElementType::TRILL:
1356             case ElementType::VIBRATO:
1357             case ElementType::PEDAL:
1358             case ElementType::TEXTLINE:
1359             case ElementType::HAIRPIN:
1360             case ElementType::LET_RING:
1361             case ElementType::PALM_MUTE:
1362                   {
1363                   Spanner* spanner = toSpanner(element);
1364                   if (et == ElementType::TEXTLINE && spanner->anchor() == Spanner::Anchor::NOTE)
1365                         break;
1366                   addSpanner(spanner);
1367                   for (SpannerSegment* ss : spanner->spannerSegments()) {
1368                         if (ss->system())
1369                               ss->system()->add(ss);
1370                         }
1371                   }
1372                   break;
1373 
1374             case ElementType::OTTAVA:
1375                   {
1376                   Ottava* o = toOttava(element);
1377                   addSpanner(o);
1378                   foreach(SpannerSegment* ss, o->spannerSegments()) {
1379                         if (ss->system())
1380                               ss->system()->add(ss);
1381                         }
1382                   cmdState().layoutFlags |= LayoutFlag::FIX_PITCH_VELO;
1383                   o->staff()->updateOttava();
1384                   setPlaylistDirty();
1385                   }
1386                   break;
1387 
1388             case ElementType::DYNAMIC:
1389                   cmdState().layoutFlags |= LayoutFlag::FIX_PITCH_VELO;
1390                   setPlaylistDirty();
1391                   break;
1392 
1393             case ElementType::TEMPO_TEXT:
1394                   fixTicks(); // rebuilds tempomap
1395                   break;
1396 
1397             case ElementType::INSTRUMENT_CHANGE: {
1398                   InstrumentChange* ic = toInstrumentChange(element);
1399                   ic->part()->setInstrument(ic->instrument(), ic->segment()->tick());
1400 #if 0
1401                   int tickStart = ic->segment()->tick();
1402                   auto i = ic->part()->instruments()->upper_bound(tickStart);
1403                   int tickEnd;
1404                   if (i == ic->part()->instruments()->end())
1405                         tickEnd = -1;
1406                   else
1407                         tickEnd = i->first;
1408                   Interval oldV = ic->part()->instrument(tickStart)->transpose();
1409                   ic->part()->setInstrument(ic->instrument(), tickStart);
1410                   transpositionChanged(ic->part(), oldV, tickStart, tickEnd);
1411 #endif
1412                   addLayoutFlags(LayoutFlag::REBUILD_MIDI_MAPPING);
1413                   cmdState()._instrumentsChanged = true;
1414                   }
1415                   break;
1416 
1417             case ElementType::CHORD:
1418                   setPlaylistDirty();
1419                   // create playlist does not work here bc. tremolos may not be complete
1420                   // createPlayEvents(toChord(element));
1421                   break;
1422 
1423             case ElementType::NOTE:
1424             case ElementType::TREMOLO:
1425             case ElementType::ARTICULATION:
1426             case ElementType::ARPEGGIO:
1427                   {
1428                   if (parent && parent->isChord())
1429                         createPlayEvents(toChord(parent));
1430                   }
1431                   break;
1432             case ElementType::HARMONY:
1433                   element->part()->updateHarmonyChannels(true);
1434                   break;
1435 
1436             default:
1437                   break;
1438             }
1439       element->triggerLayout();
1440       }
1441 
1442 //---------------------------------------------------------
1443 //   removeElement
1444 ///   Remove \a element from its parent.
1445 ///   Several elements (clef, keysig, timesig) need special handling, as they may cause
1446 ///   changes throughout the score.
1447 //---------------------------------------------------------
1448 
removeElement(Element * element)1449 void Score::removeElement(Element* element)
1450       {
1451       Element* parent = element->parent();
1452       element->triggerLayout();
1453 
1454 //      qDebug("Score(%p) Element(%p)(%s) parent %p(%s)",
1455 //         this, element, element->name(), parent, parent ? parent->name() : "");
1456 
1457       // special for MEASURE, HBOX, VBOX
1458       // their parent is not static
1459 
1460       ElementType et = element->type();
1461 
1462       if (et == ElementType::MEASURE
1463          || (et == ElementType::HBOX && !parent->isVBox())
1464          || et == ElementType::VBOX
1465          || et == ElementType::TBOX
1466          || et == ElementType::FBOX
1467             ) {
1468             MeasureBase* mb = toMeasureBase(element);
1469             measures()->remove(mb);
1470             System* system = mb->system();
1471 
1472             if (!system) { // vertical boxes are not shown in continuous view so no system
1473                   Q_ASSERT(lineMode() && (element->isVBox() || element->isTBox()));
1474                   return;
1475                   }
1476 
1477             Page* page = system->page();
1478             if (element->isBox() && system->measures().size() == 1) {
1479                   auto i = std::find(page->systems().begin(), page->systems().end(), system);
1480                   page->systems().erase(i);
1481                   mb->setSystem(0);
1482                   if (page->systems().isEmpty()) {
1483                         // Remove this page, since it is now empty.
1484                         // This involves renumbering and repositioning all subsequent pages.
1485                         QPointF pos = page->pos();
1486                         auto ii = std::find(pages().begin(), pages().end(), page);
1487                         pages().erase(ii);
1488                         while (ii != pages().end()) {
1489                               page = *ii;
1490                               page->setNo(page->no() - 1);
1491                               QPointF p = page->pos();
1492                               page->setPos(pos);
1493                               pos = p;
1494                               ii++;
1495                               }
1496                         }
1497                   }
1498 //            setLayout(mb->tick());
1499             return;
1500             }
1501 
1502       if (et == ElementType::BEAM) {          // beam parent does not survive layout
1503             element->setParent(0);
1504             parent = 0;
1505             }
1506 
1507       if (parent)
1508             parent->remove(element);
1509 
1510       switch (et) {
1511             case ElementType::BEAM:
1512                   for (ChordRest* cr : toBeam(element)->elements())
1513                         cr->setBeam(0);
1514                   break;
1515 
1516             case ElementType::SLUR:
1517                   addLayoutFlags(LayoutFlag::PLAY_EVENTS);
1518                   // fall through
1519 
1520             case ElementType::VOLTA:
1521             case ElementType::TRILL:
1522             case ElementType::VIBRATO:
1523             case ElementType::PEDAL:
1524             case ElementType::LET_RING:
1525             case ElementType::PALM_MUTE:
1526             case ElementType::TEXTLINE:
1527             case ElementType::HAIRPIN:
1528                   {
1529                   Spanner* spanner = toSpanner(element);
1530                   if (et == ElementType::TEXTLINE && spanner->anchor() == Spanner::Anchor::NOTE)
1531                         break;
1532                   spanner->triggerLayout();
1533                   removeSpanner(spanner);
1534                   }
1535                   break;
1536 
1537             case ElementType::OTTAVA:
1538                   {
1539                   Ottava* o = toOttava(element);
1540                   o->triggerLayout();
1541                   removeSpanner(o);
1542                   o->staff()->updateOttava();
1543                   cmdState().layoutFlags |= LayoutFlag::FIX_PITCH_VELO;
1544                   setPlaylistDirty();
1545                   }
1546                   break;
1547 
1548             case ElementType::DYNAMIC:
1549                   cmdState().layoutFlags |= LayoutFlag::FIX_PITCH_VELO;
1550                   setPlaylistDirty();
1551                   break;
1552 
1553             case ElementType::CHORD:
1554             case ElementType::REST:
1555                   {
1556                   ChordRest* cr = toChordRest(element);
1557                   if (cr->beam())
1558                         cr->beam()->remove(cr);
1559                   for (Lyrics* lyr : cr->lyrics())
1560                         lyr->removeFromScore();
1561                   // TODO: check for tuplet?
1562                   }
1563                   break;
1564             case ElementType::TEMPO_TEXT:
1565                   fixTicks(); // rebuilds tempomap
1566                   break;
1567             case ElementType::INSTRUMENT_CHANGE: {
1568                   InstrumentChange* ic = toInstrumentChange(element);
1569                   ic->part()->removeInstrument(ic->segment()->tick());
1570 #if 0
1571                   int tickStart = ic->segment()->tick();
1572                   auto i = ic->part()->instruments()->upper_bound(tickStart);
1573                   int tickEnd;
1574                   if (i == ic->part()->instruments()->end())
1575                         tickEnd = -1;
1576                   else
1577                         tickEnd = i->first;
1578                   Interval oldV = ic->part()->instrument(tickStart)->transpose();
1579                   ic->part()->removeInstrument(tickStart);
1580                   transpositionChanged(ic->part(), oldV, tickStart, tickEnd);
1581 #endif
1582                   addLayoutFlags(LayoutFlag::REBUILD_MIDI_MAPPING);
1583                   cmdState()._instrumentsChanged = true;
1584                   }
1585                   break;
1586 
1587             case ElementType::TREMOLO:
1588             case ElementType::ARTICULATION:
1589             case ElementType::ARPEGGIO:
1590                   {
1591                   Element* cr = element->parent();
1592                   if (cr->isChord())
1593                         createPlayEvents(toChord(cr));
1594                   }
1595                   break;
1596             case ElementType::HARMONY:
1597                   element->part()->updateHarmonyChannels(true, true);
1598                   break;
1599 
1600             default:
1601                   break;
1602             }
1603       }
1604 
1605 //---------------------------------------------------------
1606 //   firstMeasure
1607 //---------------------------------------------------------
1608 
firstMeasure() const1609 Measure* Score::firstMeasure() const
1610       {
1611       MeasureBase* mb = _measures.first();
1612       while (mb && mb->type() != ElementType::MEASURE)
1613             mb = mb->next();
1614 
1615       return toMeasure(mb);
1616       }
1617 
1618 //---------------------------------------------------------
1619 //   firstMeasureMM
1620 //---------------------------------------------------------
1621 
firstMeasureMM() const1622 Measure* Score::firstMeasureMM() const
1623       {
1624       Measure* m = firstMeasure();
1625       if (m && styleB(Sid::createMultiMeasureRests) && m->hasMMRest())
1626             return m->mmRest();
1627       return m;
1628       }
1629 
1630 //---------------------------------------------------------
1631 //   firstMM
1632 //---------------------------------------------------------
1633 
firstMM() const1634 MeasureBase* Score::firstMM() const
1635       {
1636       MeasureBase* m = _measures.first();
1637       if (m
1638          && m->type() == ElementType::MEASURE
1639          && styleB(Sid::createMultiMeasureRests)
1640          && toMeasure(m)->hasMMRest()) {
1641             return toMeasure(m)->mmRest();
1642             }
1643       return m;
1644       }
1645 
1646 //---------------------------------------------------------
1647 //   measure
1648 //---------------------------------------------------------
1649 
measure(int idx) const1650 MeasureBase* Score::measure(int idx) const
1651       {
1652       MeasureBase* mb = _measures.first();
1653       for (int i = 0; i < idx; ++i) {
1654             mb = mb->next();
1655             if (mb == 0)
1656                   return 0;
1657             }
1658       return mb;
1659       }
1660 
1661 //---------------------------------------------------------
1662 //   crMeasure
1663 //    Returns a measure containing chords an rests
1664 //    by its index skipping other MeasureBase descendants
1665 //---------------------------------------------------------
1666 
crMeasure(int idx) const1667 Measure* Score::crMeasure(int idx) const
1668       {
1669       int i = -1;
1670       for (MeasureBase* mb = _measures.first(); mb; mb = mb->next()) {
1671             if (mb->isMeasure())
1672                   ++i;
1673             if (i == idx)
1674                   return toMeasure(mb);
1675             }
1676       return nullptr;
1677       }
1678 
1679 //---------------------------------------------------------
1680 //   lastMeasure
1681 //---------------------------------------------------------
1682 
lastMeasure() const1683 Measure* Score::lastMeasure() const
1684       {
1685       MeasureBase* mb = _measures.last();
1686       while (mb && mb->type() != ElementType::MEASURE)
1687             mb = mb->prev();
1688       return toMeasure(mb);
1689       }
1690 
1691 //---------------------------------------------------------
1692 //   lastMeasureMM
1693 //---------------------------------------------------------
1694 
lastMeasureMM() const1695 Measure* Score::lastMeasureMM() const
1696       {
1697       Measure* m = lastMeasure();
1698       if (m && styleB(Sid::createMultiMeasureRests)) {
1699             Measure* m1 = const_cast<Measure*>(toMeasure(m->mmRest1()));
1700             if (m1)
1701                   return m1;
1702             }
1703       return m;
1704       }
1705 
1706 //---------------------------------------------------------
1707 //   endTick
1708 //---------------------------------------------------------
1709 
endTick() const1710 Fraction Score::endTick() const
1711       {
1712       Measure* m = lastMeasure();
1713       return m ? m->endTick() : Fraction(0,1);
1714       }
1715 
1716 //---------------------------------------------------------
1717 //   firstSegment
1718 //---------------------------------------------------------
1719 
firstSegment(SegmentType segType) const1720 Segment* Score::firstSegment(SegmentType segType) const
1721       {
1722       Segment* seg;
1723       Measure* m = firstMeasure();
1724       if (!m)
1725             seg = 0;
1726       else {
1727             seg = m->first();
1728             if (seg && !(seg->segmentType() & segType))
1729                   seg = seg->next1(segType);
1730             }
1731 
1732 #ifdef SCRIPT_INTERFACE
1733       // if called from QML/JS, tell QML engine not to garbage collect this object
1734 //      if (seg)
1735 //            QQmlEngine::setObjectOwnership(seg, QQmlEngine::CppOwnership);
1736 #endif
1737       return seg;
1738       }
1739 
1740 //---------------------------------------------------------
1741 //   firstSegmentMM
1742 //---------------------------------------------------------
1743 
firstSegmentMM(SegmentType segType) const1744 Segment* Score::firstSegmentMM(SegmentType segType) const
1745       {
1746       Measure* m = firstMeasureMM();
1747       return m ? m->first(segType) : 0;
1748       }
1749 
1750 //---------------------------------------------------------
1751 //   lastSegment
1752 //---------------------------------------------------------
1753 
lastSegment() const1754 Segment* Score::lastSegment() const
1755       {
1756       Measure* m = lastMeasure();
1757       return m ? m->last() : 0;
1758       }
1759 
1760 //---------------------------------------------------------
1761 //   lastSegmentMM
1762 //---------------------------------------------------------
1763 
lastSegmentMM() const1764 Segment* Score::lastSegmentMM() const
1765       {
1766       Measure* m = lastMeasureMM();
1767       return m ? m->last() : 0;
1768       }
1769 
1770 //---------------------------------------------------------
1771 //   utick2utime
1772 //---------------------------------------------------------
1773 
utick2utime(int tick) const1774 qreal Score::utick2utime(int tick) const
1775       {
1776       return repeatList().utick2utime(tick);
1777       }
1778 
1779 //---------------------------------------------------------
1780 //   utime2utick
1781 //---------------------------------------------------------
1782 
utime2utick(qreal utime) const1783 int Score::utime2utick(qreal utime) const
1784       {
1785       return repeatList().utime2utick(utime);
1786       }
1787 
1788 //---------------------------------------------------------
1789 //   setExpandRepeats
1790 //---------------------------------------------------------
1791 
setExpandRepeats(bool expand)1792 void MasterScore::setExpandRepeats(bool expand)
1793       {
1794       if (_expandRepeats == expand)
1795             return;
1796       _expandRepeats = expand;
1797       setPlaylistDirty();
1798       }
1799 
1800 //---------------------------------------------------------
1801 //   updateRepeatListTempo
1802 ///   needed for usage in Seq::processMessages
1803 //---------------------------------------------------------
1804 
updateRepeatListTempo()1805 void MasterScore::updateRepeatListTempo()
1806       {
1807       _repeatList->updateTempo();
1808       _repeatList2->updateTempo();
1809       }
1810 
1811 //---------------------------------------------------------
1812 //   repeatList
1813 //---------------------------------------------------------
1814 
repeatList() const1815 const RepeatList& MasterScore::repeatList() const
1816       {
1817       _repeatList->update(_expandRepeats);
1818       return *_repeatList;
1819       }
1820 
1821 //---------------------------------------------------------
1822 //   repeatList2
1823 //---------------------------------------------------------
1824 
repeatList2() const1825 const RepeatList& MasterScore::repeatList2() const
1826       {
1827       _repeatList2->update(false);
1828       return *_repeatList2;
1829       }
1830 
1831 //---------------------------------------------------------
1832 //   inputPos
1833 //---------------------------------------------------------
1834 
inputPos() const1835 Fraction Score::inputPos() const
1836       {
1837       return _is.tick();
1838       }
1839 
1840 //---------------------------------------------------------
1841 //   scanElements
1842 //    scan all elements
1843 //---------------------------------------------------------
1844 
scanElements(void * data,void (* func)(void *,Element *),bool all)1845 void Score::scanElements(void* data, void (*func)(void*, Element*), bool all)
1846       {
1847       for (MeasureBase* mb = first(); mb; mb = mb->next()) {
1848             mb->scanElements(data, func, all);
1849             if (mb->type() == ElementType::MEASURE) {
1850                   Measure* m = toMeasure(mb);
1851                   Measure* mmr = m->mmRest();
1852                   if (mmr)
1853                         mmr->scanElements(data, func, all);
1854                   }
1855             }
1856       for (Page* page : pages()) {
1857             for (System* s :page->systems())
1858                   s->scanElements(data, func, all);
1859             func(data, page);
1860             }
1861       }
1862 
1863 //---------------------------------------------------------
1864 //   scanElementsInRange
1865 //---------------------------------------------------------
1866 
scanElementsInRange(void * data,void (* func)(void *,Element *),bool all)1867 void Score::scanElementsInRange(void* data, void (*func)(void*, Element*), bool all)
1868       {
1869       Segment* startSeg = _selection.startSegment();
1870       for (Segment* s = startSeg; s && s !=_selection.endSegment(); s = s->next1()) {
1871             s->scanElements(data, func, all);
1872             Measure* m = s->measure();
1873             if (m && s == m->first()) {
1874                   Measure* mmr = m->mmRest();
1875                   if (mmr)
1876                         mmr->scanElements(data, func, all);
1877                   }
1878             }
1879       for (Element* e : _selection.elements()) {
1880             if (e->isSpanner()) {
1881                   Spanner* spanner = toSpanner(e);
1882                   for (SpannerSegment* ss : spanner->spannerSegments()) {
1883                         ss->scanElements(data, func, all);
1884                         }
1885                   }
1886             }
1887       }
1888 
1889 //---------------------------------------------------------
1890 //   setSelection
1891 //---------------------------------------------------------
1892 
setSelection(const Selection & s)1893 void Score::setSelection(const Selection& s)
1894       {
1895       deselectAll();
1896       _selection = s;
1897 
1898       foreach(Element* e, _selection.elements())
1899             e->setSelected(true);
1900       }
1901 
1902 //---------------------------------------------------------
1903 //   getText
1904 //---------------------------------------------------------
1905 
getText(Tid tid)1906 Text* Score::getText(Tid tid)
1907       {
1908       MeasureBase* m = first();
1909       if (m && m->isVBox()) {
1910             for (Element* e : m->el()) {
1911                   if (e->isText() && toText(e)->tid() == tid)
1912                         return toText(e);
1913                   }
1914             }
1915       return 0;
1916       }
1917 
1918 //---------------------------------------------------------
1919 //   metaTag
1920 //---------------------------------------------------------
1921 
metaTag(const QString & s) const1922 QString Score::metaTag(const QString& s) const
1923       {
1924       if (_metaTags.contains(s))
1925             return _metaTags.value(s);
1926       return _masterScore->_metaTags.value(s);
1927       }
1928 
1929 //---------------------------------------------------------
1930 //   setMetaTag
1931 //---------------------------------------------------------
1932 
setMetaTag(const QString & tag,const QString & val)1933 void Score::setMetaTag(const QString& tag, const QString& val)
1934       {
1935       _metaTags.insert(tag, val);
1936       }
1937 
1938 //---------------------------------------------------------
1939 //   addExcerpt
1940 //---------------------------------------------------------
1941 
addExcerpt(Excerpt * ex)1942 void MasterScore::addExcerpt(Excerpt* ex)
1943       {
1944       Score* score = ex->partScore();
1945 
1946       int nstaves { 1 }; // Initialise to 1 to force writing of the first part.
1947       for (Staff* s : score->staves()) {
1948             const LinkedElements* ls = s->links();
1949             if (ls == 0)
1950                   continue;
1951             for (auto le : *ls) {
1952                   if (le->score() != this)
1953                         continue;
1954 
1955                   // For instruments with multiple staves, every staff will point to the
1956                   // same part. To prevent adding the same part several times to the excerpt,
1957                   // add only the part of the first staff pointing to the part.
1958                   Staff* ps = toStaff(le);
1959                   if (!(--nstaves)) {
1960                         ex->parts().append(ps->part());
1961                         nstaves = ps->part()->nstaves();
1962                         }
1963                   break;
1964                   }
1965             }
1966       if (ex->tracks().isEmpty()) {      // SHOULDN'T HAPPEN, protected in the UI, but it happens during read-in!!!
1967             QMultiMap<int, int> tracks;
1968             for (Staff* s : score->staves()) {
1969                   const LinkedElements* ls = s->links();
1970                   if (ls == 0)
1971                         continue;
1972                   for (auto le : *ls) {
1973                         Staff* ps = toStaff(le);
1974                         if (ps->primaryStaff()) {
1975                               for (int i = 0; i < VOICES; i++)
1976                                     tracks.insert(ps->idx() * VOICES + i % VOICES, s->idx() * VOICES + i % VOICES);
1977                               break;
1978                               }
1979                         }
1980                   }
1981             ex->setTracks(tracks);
1982             }
1983       excerpts().append(ex);
1984       setExcerptsChanged(true);
1985       }
1986 
1987 //---------------------------------------------------------
1988 //   removeExcerpt
1989 //---------------------------------------------------------
1990 
removeExcerpt(Excerpt * ex)1991 void MasterScore::removeExcerpt(Excerpt* ex)
1992       {
1993       if (excerpts().removeOne(ex)) {
1994             setExcerptsChanged(true);
1995             // delete ex;
1996             }
1997       else
1998             qDebug("removeExcerpt:: ex not found");
1999       }
2000 
2001 //---------------------------------------------------------
2002 //   clone
2003 //---------------------------------------------------------
2004 
clone()2005 MasterScore* MasterScore::clone()
2006       {
2007       QBuffer buffer;
2008       buffer.open(QIODevice::WriteOnly);
2009       XmlWriter xml(this, &buffer);
2010       xml.header();
2011 
2012       xml.stag("museScore version=\"" MSC_VERSION "\"");
2013       write(xml, false);
2014       xml.etag();
2015 
2016       buffer.close();
2017 
2018       XmlReader r(buffer.buffer());
2019       MasterScore* score = new MasterScore(style());
2020       score->read1(r, true);
2021 
2022       score->addLayoutFlags(LayoutFlag::FIX_PITCH_VELO);
2023       score->doLayout();
2024       return score;
2025       }
2026 
2027 //---------------------------------------------------------
2028 //   setSynthesizerState
2029 //---------------------------------------------------------
2030 
setSynthesizerState(const SynthesizerState & s)2031 void Score::setSynthesizerState(const SynthesizerState& s)
2032       {
2033       // TODO: make undoable
2034       _synthesizerState = s;
2035       }
2036 
2037 //---------------------------------------------------------
2038 //   removeAudio
2039 //---------------------------------------------------------
2040 
removeAudio()2041 void Score::removeAudio()
2042       {
2043       delete _audio;
2044       _audio = 0;
2045       }
2046 
2047 //---------------------------------------------------------
2048 //   appendScore
2049 //---------------------------------------------------------
2050 
appendScore(Score * score,bool addPageBreak,bool addSectionBreak)2051 bool Score::appendScore(Score* score, bool addPageBreak, bool addSectionBreak)
2052       {
2053       if (parts().size() < score->parts().size() || staves().size() < score->staves().size()) {
2054             qDebug("Score to append has %d parts and %d staves, but this score only has %d parts and %d staves.", score->parts().size(), score->staves().size(), parts().size(), staves().size());
2055             return false;
2056             }
2057 
2058       if (!last()) {
2059             qDebug("This score doesn't have any MeasureBase objects.");
2060             return false;
2061             }
2062 
2063       // apply Page/Section Breaks if desired
2064       if (addPageBreak) {
2065             if (!last()->pageBreak()) {
2066                   last()->undoSetBreak(false, LayoutBreak::Type::LINE); // remove line break if exists
2067                   last()->undoSetBreak(true, LayoutBreak::Type::PAGE);  // apply page break
2068                   }
2069             }
2070       else if (!last()->lineBreak() && !last()->pageBreak()) {
2071             last()->undoSetBreak(true, LayoutBreak::Type::LINE);
2072             }
2073 
2074       if (addSectionBreak && !last()->sectionBreak())
2075             last()->undoSetBreak(true, LayoutBreak::Type::SECTION);
2076 
2077       // match concert pitch states
2078       if (styleB(Sid::concertPitch) != score->styleB(Sid::concertPitch))
2079             score->cmdConcertPitchChanged(styleB(Sid::concertPitch), true);
2080 
2081       // clone the measures
2082       appendMeasuresFromScore(score, Fraction(0, 1), score->last()->endTick());
2083 
2084       setLayoutAll();
2085       return true;
2086       }
2087 
2088 //---------------------------------------------------------
2089 //   appendMeasuresFromScore
2090 //     clone measures from another score to the end of this
2091 //---------------------------------------------------------
2092 
appendMeasuresFromScore(Score * score,const Fraction & startTick,const Fraction & endTick)2093 bool Score::appendMeasuresFromScore(Score* score, const Fraction& startTick, const Fraction& endTick)
2094       {
2095       Fraction tickOfAppend = last()->endTick();
2096       MeasureBase* pmb = last();
2097       TieMap tieMap;
2098 
2099       MeasureBase* fmb = score->tick2measureBase(startTick);
2100       MeasureBase* emb = score->tick2measureBase(endTick);
2101       Fraction curTick = tickOfAppend;
2102       for (MeasureBase* cmb = fmb; cmb != emb; cmb = cmb->next()) {
2103             MeasureBase* nmb;
2104             if (cmb->isMeasure()) {
2105                   Measure* nm = toMeasure(cmb)->cloneMeasure(this, curTick, &tieMap);
2106                   curTick += nm->ticks();
2107                   nmb = toMeasureBase(nm);
2108                   }
2109             else {
2110                   nmb = cmb->clone();
2111                   }
2112 
2113             addMeasure(nmb, 0);
2114             nmb->setNext(0);
2115             nmb->setPrev(pmb);
2116             nmb->setScore(this);
2117 
2118             pmb->setNext(nmb);
2119             pmb = nmb;
2120             }
2121 
2122       Measure* firstAppendedMeasure = tick2measure(tickOfAppend);
2123 
2124       // if the appended score has less staves,
2125       // make sure the measures have full measure rest
2126       for (Measure* m = firstAppendedMeasure; m; m = m->nextMeasure())
2127             for (int staffIdx = 0; staffIdx < nstaves(); ++staffIdx) {
2128                   Fraction f;
2129                   for (Segment* s = m->first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest))
2130                         for (int v = 0; v < VOICES; ++v) {
2131                               ChordRest* cr = toChordRest(s->element(staffIdx * VOICES + v));
2132                               if (cr == 0) continue;
2133                               f += cr->actualTicks();
2134                               }
2135                   if (f.isZero())
2136                         addRest(m->tick(), staffIdx*VOICES, TDuration(TDuration::DurationType::V_MEASURE), 0);
2137                   }
2138 
2139       // at first added measure, check if we need to add Clef/Key/TimeSig
2140       //  this is needed if it was changed and needs to be changed back
2141       int n = nstaves();
2142       Fraction otick = fmb->tick(), ctick = tickOfAppend;
2143       for (int staffIdx = 0; staffIdx < n; ++staffIdx) { // iterate over all staves
2144             int trackIdx = staff2track(staffIdx); // idx of irst track on the staff
2145             Staff* staff = this->staff(staffIdx);
2146             Staff* ostaff = score->staff(staffIdx);
2147 
2148             // check if key signature needs to be changed
2149             if (ostaff->key(otick) != staff->key(ctick)) {
2150                   Segment* ns = firstAppendedMeasure->undoGetSegment(SegmentType::KeySig, ctick);
2151                   KeySigEvent nkse = KeySigEvent(ostaff->keySigEvent(otick));
2152                   KeySig* nks = new KeySig(this);
2153                   nks->setScore(this);
2154                   nks->setTrack(trackIdx);
2155 
2156                   nks->setKeySigEvent(nkse);
2157                   staff->setKey(ctick, nkse);
2158                   ns->add(nks);
2159                   }
2160             // check if a key signature is present but is spurious (i.e. no actual change)
2161             else if (staff->currentKeyTick(ctick) == ctick &&
2162                      staff->key(ctick - Fraction::fromTicks(1)) == ostaff->key(otick)) {
2163                         Segment* ns = firstAppendedMeasure->first(SegmentType::KeySig);
2164                         if (ns)
2165                               ns->remove(ns->element(trackIdx));
2166                   }
2167 
2168             // check if time signature needs to be changed
2169             TimeSig* ots = ostaff->timeSig(otick), * cts = staff->timeSig(ctick);
2170             TimeSig* pts = staff->timeSig(ctick - Fraction::fromTicks(1));
2171             if (ots && cts && *ots != *cts) {
2172                   Segment* ns = firstAppendedMeasure->undoGetSegment(SegmentType::TimeSig, ctick);
2173                   TimeSig* nsig = new TimeSig(*ots);
2174 
2175                   nsig->setScore(this);
2176                   nsig->setTrack(trackIdx);
2177                   ns->add(nsig);
2178                   }
2179             // check if a time signature is present but is spurious (i.e. no actual change)
2180             else if (staff->currentTimeSigTick(ctick) == ctick &&
2181                      ots && pts && *pts == *ots) {
2182                         Segment* ns = firstAppendedMeasure->first(SegmentType::TimeSig);
2183                         if (ns)
2184                               ns->remove(ns->element(trackIdx));
2185                   }
2186 
2187             // check if clef signature needs to be changed
2188             if (ostaff->clef(otick) != staff->clef(ctick)) {
2189                   undoChangeClef(staff, firstAppendedMeasure, ostaff->clef(otick));
2190                   }
2191             // check if a clef change is present but is spurious (i.e. no actual change)
2192             else if (staff->currentClefTick(ctick) == ctick &&
2193                      staff->clef(ctick - Fraction::fromTicks(1)) == ostaff->clef(otick)) {
2194                         Segment* ns = firstAppendedMeasure->first(SegmentType::Clef);
2195                         if (!ns)
2196                               ns = firstAppendedMeasure->first(SegmentType::HeaderClef);
2197                         if (ns)
2198                               ns->remove(ns->element(trackIdx));
2199                   }
2200             }
2201 
2202       // check if section starts with a pick-up measure to be merged with end of previous section
2203       Measure* cm = firstAppendedMeasure, * pm = cm->prevMeasure();
2204       if (pm->timesig() == cm->timesig() && pm->ticks() + cm->ticks() == cm->timesig())
2205             cmdJoinMeasure(pm, cm);
2206 
2207       // clone the spanners (only in the range currently copied)
2208       auto ospans = score->spanner();
2209       auto lb = ospans.lower_bound(startTick.ticks()), ub = ospans.upper_bound(endTick.ticks());
2210       for (auto sp = lb; sp != ub; sp++) {
2211             Spanner* spanner = sp->second;
2212 
2213             if (spanner->tick2() > endTick) continue; // map is by tick() so this can still happen in theory...
2214 
2215             Spanner* ns = toSpanner(spanner->clone());
2216             ns->setScore(this);
2217             ns->setParent(0);
2218             ns->setTick(spanner->tick() - startTick + tickOfAppend);
2219             ns->setTick2(spanner->tick2() - startTick + tickOfAppend);
2220             ns->computeStartElement();
2221             ns->computeEndElement();
2222             addElement(ns);
2223             }
2224 
2225       return true;
2226       }
2227 
2228 //---------------------------------------------------------
2229 //   splitStaff
2230 //---------------------------------------------------------
2231 
splitStaff(int staffIdx,int splitPoint)2232 void Score::splitStaff(int staffIdx, int splitPoint)
2233       {
2234 //      qDebug("split staff %d point %d", staffIdx, splitPoint);
2235 
2236       //
2237       // create second staff
2238       //
2239       Staff* st = staff(staffIdx);
2240       Part*  p  = st->part();
2241       Staff* ns = new Staff(this);
2242       ns->init(st);
2243       ns->setPart(p);
2244       // convert staffIdx from score-relative to part-relative
2245       int staffIdxPart = staffIdx - p->staff(0)->idx();
2246       undoInsertStaff(ns, staffIdxPart + 1, false);
2247 
2248       Clef* clef = new Clef(this);
2249       clef->setClefType(ClefType::F);
2250       clef->setTrack((staffIdx+1) * VOICES);
2251       Segment* seg = firstMeasure()->getSegment(SegmentType::HeaderClef, Fraction(0, 1));
2252       clef->setParent(seg);
2253       undoAddElement(clef);
2254       clef->layout();
2255 
2256       undoChangeKeySig(ns, Fraction(0, 1), st->keySigEvent(Fraction(0, 1)));
2257 
2258       masterScore()->rebuildMidiMapping();
2259       cmdState()._instrumentsChanged = true;
2260       doLayout();
2261 
2262       //
2263       // move notes
2264       //
2265       select(0, SelectType::SINGLE, 0);
2266       int strack = staffIdx * VOICES;
2267       int dtrack = (staffIdx + 1) * VOICES;
2268 
2269       // Keep track of ties to be reconnected.
2270       struct OldTie {
2271             Tie* tie;
2272             Note* nnote;
2273             };
2274       QMap<Note*, OldTie> oldTies;
2275 
2276       // Notes under the split point can be part of a tuplet, so keep track
2277       // of the tuplet mapping too!
2278       QMap<Tuplet*, Tuplet*> tupletMapping;
2279       Tuplet* tupletSrc[VOICES] = { };
2280       Tuplet* tupletDst[VOICES] = { };
2281 
2282       for (Segment* s = firstSegment(SegmentType::ChordRest); s; s = s->next1(SegmentType::ChordRest)) {
2283             for (int voice = 0; voice < VOICES; ++voice) {
2284                   Element* e = s->element(strack + voice);
2285 
2286                   if (!e)
2287                         continue;
2288                   if (toDurationElement(e)->tuplet()) {
2289                         tupletSrc[voice] = toDurationElement(e)->tuplet();
2290                         if (tupletMapping.contains(tupletSrc[voice]))
2291                               tupletDst[voice] = tupletMapping[tupletSrc[voice]];
2292                         else {
2293                               tupletDst[voice] = new Tuplet(*tupletSrc[voice]);
2294                               tupletDst[voice]->setTrack(dtrack);
2295                               tupletMapping.insert(tupletSrc[voice], tupletDst[voice]);
2296                               }
2297                         }
2298                   else {
2299                         tupletSrc[voice] = nullptr;
2300                         tupletDst[voice] = nullptr;
2301                         }
2302 
2303                   bool createRestDst = true;
2304                   bool createRestSrc = false;
2305                   TDuration lengthDst = toChordRest(e)->actualDurationType();
2306                   TDuration lengthSrc = TDuration();
2307 
2308                   if (e->isChord()) {
2309                         Chord* c = toChord(e);
2310                         QList<Note*> removeNotes;
2311                         for(Note* note : c->notes()) {
2312                               if (note->pitch() >= splitPoint)
2313                                     continue;
2314                               else {
2315                                     Chord* chord = toChord(s->element(dtrack + voice));
2316                                     Q_ASSERT(!chord || (chord->isChord()));
2317                                     if (!chord) {
2318                                           chord = new Chord(*c);
2319                                           qDeleteAll(chord->notes());
2320                                           chord->notes().clear();
2321                                           chord->setTuplet(tupletDst[voice]);
2322                                           chord->setTrack(dtrack + voice);
2323                                           undoAddElement(chord);
2324                                           }
2325                                     Note* nnote = new Note(*note);
2326                                     if (note->tieFor())
2327                                           // Save the note and the tie for processing later.
2328                                           // Use the end note as index in the map so, when this is found
2329                                           // we know the tie has to be recreated.
2330                                           oldTies.insert(note->tieFor()->endNote(), OldTie{note->tieFor(), nnote});
2331                                     nnote->setTrack(dtrack + voice);
2332                                     chord->add(nnote);
2333                                     nnote->updateLine();
2334                                     removeNotes.append(note);
2335                                     createRestDst = false;
2336                                     lengthDst = chord->actualDurationType();
2337 
2338                                     // Is the note the last note of a tie?
2339                                     if (oldTies.contains(note)) {
2340                                           // Yes! Create a tie between the new notes and remove the
2341                                           // old tie.
2342                                           Tie* tie = oldTies[note].tie->clone();
2343                                           tie->setStartNote(oldTies[note].nnote);
2344                                           tie->setEndNote(nnote);
2345                                           tie->setTrack(nnote->track());
2346                                           undoAddElement(tie);
2347                                           undoRemoveElement(oldTies[note].tie);
2348                                           oldTies.remove(note);
2349                                           }
2350                                     }
2351                               }
2352                         createRestSrc = false;
2353                         for (Note* note : removeNotes) {
2354                               undoRemoveElement(note);
2355                               Chord* chord = note->chord();
2356                               if (chord->notes().empty()) {
2357                                     for (auto sp : spanner()) {
2358                                           Slur* slur = toSlur(sp.second);
2359                                           if (slur->type() != ElementType::SLUR)
2360                                                 continue;
2361                                           if (slur->startCR() == chord) {
2362                                                 slur->undoChangeProperty(Pid::TRACK, slur->track()+VOICES);
2363                                                 for (ScoreElement* ee : slur->linkList()) {
2364                                                       Slur* lslur = toSlur(ee);
2365                                                       lslur->setStartElement(0);
2366                                                       }
2367                                                 }
2368                                           if (slur->endCR() == chord) {
2369                                                 slur->undoChangeProperty(Pid::SPANNER_TRACK2, slur->track2()+VOICES);
2370                                                 for (ScoreElement* ee : slur->linkList()) {
2371                                                       Slur* lslur = toSlur(ee);
2372                                                       lslur->setEndElement(0);
2373                                                       }
2374                                                 }
2375                                           }
2376                                     createRestSrc = true;
2377                                     lengthSrc = chord->actualDurationType();
2378                                     undoRemoveElement(chord);
2379                                     }
2380                               }
2381                         }
2382 
2383                   if (createRestSrc)
2384                         addRest(s, strack + voice, lengthSrc, tupletSrc[voice]);
2385                   if (createRestDst)
2386                         addRest(s, dtrack + voice, lengthDst, tupletDst[voice]);
2387                   }
2388             }
2389       }
2390 
2391 //---------------------------------------------------------
2392 //   cmdRemovePart
2393 //---------------------------------------------------------
2394 
cmdRemovePart(Part * part)2395 void Score::cmdRemovePart(Part* part)
2396       {
2397       int sidx   = staffIdx(part);
2398       int n      = part->nstaves();
2399 
2400       for (int i = 0; i < n; ++i)
2401             cmdRemoveStaff(sidx);
2402 
2403       undoRemovePart(part, sidx);
2404       }
2405 
2406 //---------------------------------------------------------
2407 //   insertPart
2408 //---------------------------------------------------------
2409 
insertPart(Part * part,int idx)2410 void Score::insertPart(Part* part, int idx)
2411       {
2412       bool inserted = false;
2413       int staff = 0;
2414       for (QList<Part*>::iterator i = _parts.begin(); i != _parts.end(); ++i) {
2415             if (staff >= idx) {
2416                   _parts.insert(i, part);
2417                   inserted = true;
2418                   break;
2419                   }
2420             staff += (*i)->nstaves();
2421             }
2422       if (!inserted)
2423             _parts.push_back(part);
2424       masterScore()->rebuildMidiMapping();
2425       setInstrumentsChanged(true);
2426       }
2427 
2428 //---------------------------------------------------------
2429 //   removePart
2430 //---------------------------------------------------------
2431 
removePart(Part * part)2432 void Score::removePart(Part* part)
2433       {
2434       _parts.removeAt(_parts.indexOf(part));
2435       masterScore()->rebuildMidiMapping();
2436       setInstrumentsChanged(true);
2437       }
2438 
2439 //---------------------------------------------------------
2440 //   insertStaff
2441 //---------------------------------------------------------
2442 
insertStaff(Staff * staff,int ridx)2443 void Score::insertStaff(Staff* staff, int ridx)
2444       {
2445       staff->part()->insertStaff(staff, ridx);
2446 
2447       int idx = staffIdx(staff->part()) + ridx;
2448       _staves.insert(idx, staff);
2449 
2450       for (auto i = staff->score()->spanner().cbegin(); i != staff->score()->spanner().cend(); ++i) {
2451             Spanner* s = i->second;
2452             if (s->systemFlag())
2453                   continue;
2454             if (s->staffIdx() >= idx) {
2455                   int t = s->track() + VOICES;
2456                   if (t >= ntracks())
2457                         t = ntracks() - 1;
2458                   s->setTrack(t);
2459                   for (SpannerSegment* ss : s->spannerSegments())
2460                         ss->setTrack(t);
2461                   if (s->track2() != -1) {
2462                         t = s->track2() + VOICES;
2463                         s->setTrack2(t < ntracks() ? t : s->track());
2464                         }
2465                   }
2466             }
2467 #if 0
2468       for (Spanner* s : staff->score()->unmanagedSpanners()) {
2469             if (s->systemFlag())
2470                   continue;
2471             if (s->staffIdx() >= idx) {
2472                   int t = s->track() + VOICES;
2473                   s->setTrack(t < ntracks() ? t : ntracks() - 1);
2474                   if (s->track2() != -1) {
2475                         t = s->track2() + VOICES;
2476                         s->setTrack2(t < ntracks() ? t : s->track());
2477                         }
2478                   }
2479             }
2480 #endif
2481       }
2482 
2483 //---------------------------------------------------------
2484 //   removeStaff
2485 //---------------------------------------------------------
2486 
removeStaff(Staff * staff)2487 void Score::removeStaff(Staff* staff)
2488       {
2489       int idx = staff->idx();
2490       for (auto i = staff->score()->spanner().cbegin(); i != staff->score()->spanner().cend(); ++i) {
2491             Spanner* s = i->second;
2492             if (s->staffIdx() > idx) {
2493                   int t = s->track() - VOICES;
2494                   if (t < 0)
2495                         t = 0;
2496                   s->setTrack(t);
2497                   for (SpannerSegment* ss : s->spannerSegments())
2498                         ss->setTrack(t);
2499                   if (s->track2() != -1) {
2500                         t = s->track2() - VOICES;
2501                         s->setTrack2(t >= 0 ? t : s->track());
2502                         }
2503                   }
2504             }
2505 #if 0
2506       for (Spanner* s : staff->score()->unmanagedSpanners()) {
2507             if (s->staffIdx() > idx) {
2508                   int t = s->track() - VOICES;
2509                   s->setTrack(t >= 0 ? t : 0);
2510                   if (s->track2() != -1) {
2511                         t = s->track2() - VOICES;
2512                         s->setTrack2(t >= 0 ? t : s->track());
2513                         }
2514                   }
2515             }
2516 #endif
2517       _staves.removeAll(staff);
2518       staff->part()->removeStaff(staff);
2519       }
2520 
2521 //---------------------------------------------------------
2522 //   adjustBracketsDel
2523 //---------------------------------------------------------
2524 
adjustBracketsDel(int sidx,int eidx)2525 void Score::adjustBracketsDel(int sidx, int eidx)
2526       {
2527       for (int staffIdx = 0; staffIdx < _staves.size(); ++staffIdx) {
2528             Staff* staff = _staves[staffIdx];
2529             for (BracketItem* bi : staff->brackets()) {
2530                   int span = bi->bracketSpan();
2531                   if ((span == 0) || ((staffIdx + span) < sidx) || (staffIdx > eidx))
2532                         continue;
2533                   if ((sidx >= staffIdx) && (eidx <= (staffIdx + span)))
2534                         bi->undoChangeProperty(Pid::BRACKET_SPAN, span - (eidx-sidx));
2535                   }
2536 #if 0 // TODO
2537             int span = staff->barLineSpan();
2538             if ((sidx >= staffIdx) && (eidx <= (staffIdx + span))) {
2539                   int newSpan = span - (eidx-sidx) + 1;
2540                   int lastSpannedStaffIdx = staffIdx + newSpan - 1;
2541                   int tick = 0;
2542                   undoChangeBarLineSpan(staff, newSpan, 0, (_staves[lastSpannedStaffIdx]->lines(0)-1)*2);
2543                   }
2544 #endif
2545             }
2546       }
2547 
2548 //---------------------------------------------------------
2549 //   adjustBracketsIns
2550 //---------------------------------------------------------
2551 
adjustBracketsIns(int sidx,int eidx)2552 void Score::adjustBracketsIns(int sidx, int eidx)
2553       {
2554       for (int staffIdx = 0; staffIdx < _staves.size(); ++staffIdx) {
2555             Staff* staff = _staves[staffIdx];
2556             for (BracketItem* bi : staff->brackets()) {
2557                   int span = bi->bracketSpan();
2558                   if ((span == 0) || ((staffIdx + span) < sidx) || (staffIdx > eidx))
2559                         continue;
2560                   if ((sidx >= staffIdx) && (eidx < (staffIdx + span)))
2561                         bi->undoChangeProperty(Pid::BRACKET_SPAN, span + (eidx-sidx));
2562                   }
2563 #if 0 // TODO
2564             int span = staff->barLineSpan();
2565             if ((sidx >= staffIdx) && (eidx < (staffIdx + span))) {
2566                   int idx = staffIdx + span - 1;
2567                   if (idx >= _staves.size())
2568                         idx = _staves.size() - 1;
2569                   undoChangeBarLineSpan(staff, span, 0, (_staves[idx]->lines()-1)*2);
2570                   }
2571 #endif
2572             }
2573       }
2574 
2575 //---------------------------------------------------------
2576 //   adjustKeySigs
2577 //---------------------------------------------------------
2578 
adjustKeySigs(int sidx,int eidx,KeyList km)2579 void Score::adjustKeySigs(int sidx, int eidx, KeyList km)
2580       {
2581       for (int staffIdx = sidx; staffIdx < eidx; ++staffIdx) {
2582             Staff* staff = _staves[staffIdx];
2583             for (auto i = km.begin(); i != km.end(); ++i) {
2584                   Fraction tick = Fraction::fromTicks(i->first);
2585                   Measure* measure = tick2measure(tick);
2586                   if (!measure)
2587                         continue;
2588                   if (staff->isDrumStaff(tick))
2589                         continue;
2590                   KeySigEvent oKey = i->second;
2591                   KeySigEvent nKey = oKey;
2592                   int diff = -staff->part()->instrument(tick)->transpose().chromatic;
2593                   if (diff != 0 && !styleB(Sid::concertPitch) && !oKey.custom() && !oKey.isAtonal())
2594                         nKey.setKey(transposeKey(nKey.key(), diff, staff->part()->preferSharpFlat()));
2595                   staff->setKey(tick, nKey);
2596                   KeySig* keysig = new KeySig(this);
2597                   keysig->setTrack(staffIdx * VOICES);
2598                   keysig->setKeySigEvent(nKey);
2599                   Segment* s = measure->getSegment(SegmentType::KeySig, tick);
2600                   s->add(keysig);
2601                   }
2602             }
2603       }
2604 
2605 //---------------------------------------------------------
2606 //   cmdRemoveStaff
2607 //---------------------------------------------------------
2608 
cmdRemoveStaff(int staffIdx)2609 void Score::cmdRemoveStaff(int staffIdx)
2610       {
2611       Staff* s = staff(staffIdx);
2612       adjustBracketsDel(staffIdx, staffIdx+1);
2613 
2614       undoRemoveStaff(s);
2615 
2616       // remove linked staff and measures in linked staves in excerpts
2617       // unlink staff in the same score
2618 
2619       if (s->links()) {
2620             Staff* sameScoreLinkedStaff = 0;
2621             auto staves = s->links();
2622             for (auto le : *staves) {
2623                   Staff* staff = toStaff(le);
2624                   if (staff == s)
2625                         continue;
2626                   Score* lscore = staff->score();
2627                   if (lscore != this) {
2628                         lscore->undoRemoveStaff(staff);
2629                         s->score()->undo(new Unlink(staff));
2630                         if (staff->part()->nstaves() == 0) {
2631                               int pIndex    = lscore->staffIdx(staff->part());
2632                               lscore->undoRemovePart(staff->part(), pIndex);
2633                               }
2634                         }
2635                   else // linked staff in the same score
2636                        sameScoreLinkedStaff = staff;
2637                   }
2638             if (sameScoreLinkedStaff)
2639 //                  s->score()->undo(new Unlink(sameScoreLinkedStaff)); // once should be enough
2640                   s->score()->undo(new Unlink(s)); // once should be enough
2641             }
2642       }
2643 
2644 //---------------------------------------------------------
2645 //   sortStaves
2646 //---------------------------------------------------------
2647 
sortStaves(QList<int> & dst)2648 void Score::sortStaves(QList<int>& dst)
2649       {
2650       qDeleteAll(systems());
2651       systems().clear();  //??
2652       _parts.clear();
2653       Part* curPart = 0;
2654       QList<Staff*> dl;
2655       QMap<int, int> trackMap;
2656       int track = 0;
2657       foreach (int idx, dst) {
2658             Staff* staff = _staves[idx];
2659             if (staff->part() != curPart) {
2660                   curPart = staff->part();
2661                   curPart->staves()->clear();
2662                   _parts.push_back(curPart);
2663                   }
2664             curPart->staves()->push_back(staff);
2665             dl.push_back(staff);
2666             for (int itrack = 0; itrack < VOICES; ++itrack)
2667                   trackMap.insert(idx * VOICES + itrack, track++);
2668             }
2669       _staves = dl;
2670 
2671       for (Measure* m = firstMeasure(); m; m = m->nextMeasure()) {
2672             m->sortStaves(dst);
2673             if (m->hasMMRest())
2674                   m->mmRest()->sortStaves(dst);
2675             }
2676       for (auto i : _spanner.map()) {
2677             Spanner* sp = i.second;
2678             if (sp->systemFlag())
2679                   continue;
2680             int voice    = sp->voice();
2681             int staffIdx = sp->staffIdx();
2682             int idx = dst.indexOf(staffIdx);
2683             if (idx >=0) {
2684                   sp->setTrack(idx * VOICES + voice);
2685                   if (sp->track2() != -1)
2686                         sp->setTrack2(idx * VOICES +(sp->track2() % VOICES)); // at least keep the voice...
2687                   }
2688             }
2689       setLayoutAll();
2690       }
2691 
2692 //---------------------------------------------------------
2693 //   mapExcerptTracks
2694 //---------------------------------------------------------
2695 
mapExcerptTracks(QList<int> & dst)2696 void Score::mapExcerptTracks(QList<int> &dst)
2697       {
2698       for (Excerpt* e : excerpts()) {
2699             QMultiMap<int, int> tr = e->tracks();
2700             QMultiMap<int, int> tracks;
2701             for (QMap<int, int>::iterator it = tr.begin(); it != tr.end(); ++it) {
2702                   int prvStaffIdx = it.key() / VOICES;
2703                   int curStaffIdx = dst.indexOf(prvStaffIdx);
2704                   int offset = (curStaffIdx - prvStaffIdx) * VOICES;
2705                   tracks.insert(it.key() + offset, it.value());
2706                   }
2707             e->tracks() = tracks;
2708             }
2709       }
2710 
2711 //---------------------------------------------------------
2712 //   cmdConcertPitchChanged
2713 //---------------------------------------------------------
2714 
cmdConcertPitchChanged(bool flag,bool)2715 void Score::cmdConcertPitchChanged(bool flag, bool /*useDoubleSharpsFlats*/)
2716       {
2717       undoChangeStyleVal(Sid::concertPitch, flag);       // change style flag
2718 
2719       for (Staff* staff : qAsConst(_staves)) {
2720             if (staff->staffType(Fraction(0,1))->group() == StaffGroup::PERCUSSION)       // TODO
2721                   continue;
2722             // if this staff has no transposition, and no instrument changes, we can skip it
2723             Interval interval = staff->part()->instrument()->transpose(); //tick?
2724             if (interval.isZero() && staff->part()->instruments()->size() == 1)
2725                   continue;
2726             if (!flag)
2727                   interval.flip();
2728 
2729             int staffIdx   = staff->idx();
2730             int startTrack = staffIdx * VOICES;
2731             int endTrack   = startTrack + VOICES;
2732 
2733             transposeKeys(staffIdx, staffIdx + 1, Fraction(0,1), lastSegment()->tick(), interval, true, !flag);
2734 
2735             for (Segment* segment = firstSegment(SegmentType::ChordRest); segment; segment = segment->next1(SegmentType::ChordRest)) {
2736                   interval = staff->part()->instrument(segment->tick())->transpose();
2737                   if (!flag)
2738                         interval.flip();
2739                   for (Element* e : segment->annotations()) {
2740                         if (!e->isHarmony() || (e->track() < startTrack) || (e->track() >= endTrack))
2741                               continue;
2742                         Harmony* h  = toHarmony(e);
2743                         int rootTpc = transposeTpc(h->rootTpc(), interval, true);
2744                         int baseTpc = transposeTpc(h->baseTpc(), interval, true);
2745                         for (ScoreElement* se : h->linkList()) {
2746                               // don't transpose all links
2747                               // just ones resulting from mmrests
2748                               Harmony* he = toHarmony(se);    // toHarmony() does not work as e is an ScoreElement
2749                               if (he->staff() == h->staff()) {
2750                                     undoTransposeHarmony(he, rootTpc, baseTpc);
2751                                     }
2752                               }
2753                         //realized harmony should be invalid after a transpose command
2754                         Q_ASSERT(!h->realizedHarmony().valid());
2755                         }
2756                   }
2757             }
2758       }
2759 
2760 //---------------------------------------------------------
2761 //   addAudioTrack
2762 //---------------------------------------------------------
2763 
addAudioTrack()2764 void Score::addAudioTrack()
2765       {
2766       // TODO
2767       }
2768 
2769 //---------------------------------------------------------
2770 //   padToggle
2771 //---------------------------------------------------------
2772 
padToggle(Pad p,const EditData & ed)2773 void Score::padToggle(Pad p, const EditData& ed)
2774       {
2775       int oldDots = _is.duration().dots();
2776       switch (p) {
2777             case Pad::NOTE00:
2778                   _is.setDuration(TDuration::DurationType::V_LONG);
2779                   break;
2780             case Pad::NOTE0:
2781                   _is.setDuration(TDuration::DurationType::V_BREVE);
2782                   break;
2783             case Pad::NOTE1:
2784                   _is.setDuration(TDuration::DurationType::V_WHOLE);
2785                   break;
2786             case Pad::NOTE2:
2787                   _is.setDuration(TDuration::DurationType::V_HALF);
2788                   break;
2789             case Pad::NOTE4:
2790                   _is.setDuration(TDuration::DurationType::V_QUARTER);
2791                   break;
2792             case Pad::NOTE8:
2793                   _is.setDuration(TDuration::DurationType::V_EIGHTH);
2794                   break;
2795             case Pad::NOTE16:
2796                   _is.setDuration(TDuration::DurationType::V_16TH);
2797                   break;
2798             case Pad::NOTE32:
2799                   _is.setDuration(TDuration::DurationType::V_32ND);
2800                   break;
2801             case Pad::NOTE64:
2802                   _is.setDuration(TDuration::DurationType::V_64TH);
2803                   break;
2804             case Pad::NOTE128:
2805                   _is.setDuration(TDuration::DurationType::V_128TH);
2806                   break;
2807             case Pad::NOTE256:
2808                   _is.setDuration(TDuration::DurationType::V_256TH);
2809                   break;
2810             case Pad::NOTE512:
2811                   _is.setDuration(TDuration::DurationType::V_512TH);
2812                   break;
2813             case Pad::NOTE1024:
2814                   _is.setDuration(TDuration::DurationType::V_1024TH);
2815                   break;
2816             case Pad::REST:
2817                   if (noteEntryMode()) {
2818                         _is.setRest(!_is.rest());
2819                         _is.setAccidentalType(AccidentalType::NONE);
2820                         }
2821                   else if (selection().isNone()) {
2822                         ed.view->startNoteEntryMode();
2823                         _is.setDuration(TDuration::DurationType::V_QUARTER);
2824                         _is.setRest(true);
2825                         }
2826                   else {
2827                         for (ChordRest* cr : getSelectedChordRests()) {
2828                               if (!cr->isRest())
2829                                     setNoteRest(cr->segment(), cr->track(), NoteVal(), cr->durationTypeTicks());
2830                               }
2831                         }
2832                   break;
2833             case Pad::DOT:
2834                   if ((_is.duration().dots() == 1) || (_is.duration() == TDuration::DurationType::V_1024TH))
2835                         _is.setDots(0);
2836                   else
2837                         _is.setDots(1);
2838                   break;
2839             case Pad::DOTDOT:
2840                   if ((_is.duration().dots() == 2)
2841                      || (_is.duration() == TDuration::DurationType::V_512TH)
2842                      || (_is.duration() == TDuration::DurationType::V_1024TH))
2843                         _is.setDots(0);
2844                   else
2845                         _is.setDots(2);
2846                   break;
2847             case Pad::DOT3:
2848                   if ((_is.duration().dots() == 3)
2849                      || (_is.duration() == TDuration::DurationType::V_256TH)
2850                      || (_is.duration() == TDuration::DurationType::V_512TH)
2851                      || (_is.duration() == TDuration::DurationType::V_1024TH))
2852                         _is.setDots(0);
2853                   else
2854                         _is.setDots(3);
2855                   break;
2856             case Pad::DOT4:
2857                   if ((_is.duration().dots() == 4)
2858                      || (_is.duration() == TDuration::DurationType::V_128TH)
2859                      || (_is.duration() == TDuration::DurationType::V_256TH)
2860                      || (_is.duration() == TDuration::DurationType::V_512TH)
2861                      || (_is.duration() == TDuration::DurationType::V_1024TH))
2862                         _is.setDots(0);
2863                   else
2864                         _is.setDots(4);
2865                   break;
2866             }
2867       if (p >= Pad::NOTE00 && p <= Pad::NOTE1024) {
2868             _is.setDots(0);
2869             //
2870             // if in "note enter" mode, reset
2871             // rest flag
2872             //
2873             if (noteEntryMode()) {
2874                   if (usingNoteEntryMethod(NoteEntryMethod::RHYTHM)) {
2875                         switch (oldDots) {
2876                               case 1:
2877                                     padToggle(Pad::DOT, ed);
2878                                     break;
2879                               case 2:
2880                                     padToggle(Pad::DOTDOT, ed);
2881                                     break;
2882                               case 3:
2883                                     padToggle(Pad::DOT3, ed);
2884                                     break;
2885                               case 4:
2886                                     padToggle(Pad::DOT4, ed);
2887                                     break;
2888                               }
2889                         NoteVal nval;
2890                         Direction stemDirection = Direction::AUTO;
2891                         if (_is.rest()) {
2892                               // Enter a rest
2893                               nval = NoteVal();
2894                               }
2895                         else {
2896                               Element* e = selection().element();
2897                               if (e && e->isNote()) {
2898                                     // use same pitch etc. as previous note
2899                                     Note* n = toNote(e);
2900                                     nval = n->noteVal();
2901                                     stemDirection = n->chord()->stemDirection();
2902                                     }
2903                               else {
2904                                     // enter a reasonable default note
2905                                     Staff* s = staff(_is.track() / VOICES);
2906                                     Fraction tick = _is.tick();
2907                                     if (s->isTabStaff(tick)) {
2908                                           // tab - use fret 0 on current string
2909                                           nval.fret = 0;
2910                                           nval.string = _is.string();
2911                                           const Instrument* instr = s->part()->instrument(tick);
2912                                           const StringData* stringData = instr->stringData();
2913                                           nval.pitch = stringData->getPitch(nval.string, nval.fret, s, tick);
2914                                           }
2915                                     else if (s->isDrumStaff(tick)) {
2916                                           // drum - use selected drum palette note
2917                                           int n = _is.drumNote();
2918                                           if (n == -1) {
2919                                                 // no selection on palette - find next valid pitch
2920                                                 const Drumset* ds = _is.drumset();
2921                                                 n = ds->nextPitch(n);
2922                                                 }
2923                                           nval = NoteVal(n);
2924                                           }
2925                                     else {
2926                                           // standard staff - use middle line
2927                                           ClefType clef = s->clef(tick);
2928                                           Key key = s->key(tick);
2929                                           int line = ((s->lines(tick) - 1) / 2) * 2;
2930                                           nval = NoteVal(line2pitch(line, clef, key));
2931                                           }
2932                                     }
2933                               }
2934                         setNoteRest(_is.segment(), _is.track(), nval, _is.duration().fraction(), stemDirection);
2935                         _is.moveToNextInputPos();
2936                         }
2937                   else
2938                         _is.setRest(false);
2939                   }
2940             }
2941 
2942       if (noteEntryMode())
2943             return;
2944 
2945       std::vector<ChordRest*> crs;
2946 
2947       if (selection().isSingle()) {
2948             Element* e = selection().element();
2949             ChordRest* cr = InputState::chordRest(e);
2950 
2951             // do not allow to add a dot on a full measure rest
2952             if (cr && cr->isRest()) {
2953                   Rest* r = toRest(cr);
2954                   if (r->isFullMeasureRest())
2955                         _is.setDots(0);
2956                   }
2957 
2958             // on measure rest, select the first actual rest
2959             if (cr && cr->isRest() && cr->measure()->isMMRest()) {
2960                   Measure* m = cr->measure()->mmRestFirst();
2961                   if (m)
2962                         cr = m->findChordRest(m->tick(), 0);
2963                   }
2964 
2965             if (cr) {
2966                   crs.push_back(cr);
2967                   }
2968             else {
2969                   ed.view->startNoteEntryMode();
2970                   deselect(e);
2971                   }
2972             }
2973       else if (selection().isNone() && p != Pad::REST) {
2974             TDuration td = _is.duration();
2975             ed.view->startNoteEntryMode();
2976             _is.setDuration(td);
2977             _is.setAccidentalType(AccidentalType::NONE);
2978             }
2979       else {
2980             const auto elements = selection().uniqueElements();
2981             bool canAdjustLength = true;
2982             for (Element* e : elements) {
2983                   ChordRest* cr = InputState::chordRest(e);
2984                   if (!cr)
2985                         continue;
2986                   if (cr->isRepeatMeasure() || (cr->isRest() && toRest(cr)->measure() && toRest(cr)->measure()->isMMRest())) {
2987                         canAdjustLength = false;
2988                         break;
2989                         }
2990                   crs.push_back(cr);
2991                   }
2992 
2993             if (canAdjustLength) {
2994                   // Change length from last to first chord/rest
2995                   std::sort(crs.begin(), crs.end(), [](const ChordRest* cr1, const ChordRest* cr2) {
2996                         if (cr2->track() == cr1->track())
2997                               return cr2->isBefore(cr1);
2998                         return cr2->track() < cr1->track();
2999                         });
3000                   // Remove duplicates from the list
3001                   crs.erase(std::unique(crs.begin(), crs.end()), crs.end());
3002                   }
3003             else
3004                   crs.clear();
3005             }
3006 
3007       for (ChordRest* cr : crs) {
3008             if (cr->isChord() && (toChord(cr)->isGrace())) {
3009                   //
3010                   // handle appoggiatura and acciaccatura
3011                   //
3012                   undoChangeChordRestLen(cr, _is.duration());
3013                   }
3014             else
3015                   changeCRlen(cr, _is.duration());
3016             }
3017       }
3018 
3019 //---------------------------------------------------------
3020 //   deselect
3021 //---------------------------------------------------------
3022 
deselect(Element * el)3023 void Score::deselect(Element* el)
3024       {
3025       addRefresh(el->abbox());
3026       _selection.remove(el);
3027       setSelectionChanged(true);
3028       _selection.update();
3029       }
3030 
3031 //---------------------------------------------------------
3032 //   select
3033 //    staffIdx is valid, if element is of type MEASURE
3034 //---------------------------------------------------------
3035 
select(Element * e,SelectType type,int staffIdx)3036 void Score::select(Element* e, SelectType type, int staffIdx)
3037       {
3038       // Move the playhead to the selected element's preferred play position.
3039       if (e) {
3040             const auto playTick = e->playTick();
3041             if (masterScore()->playPos() != playTick)
3042                   masterScore()->setPlayPos(playTick);
3043             }
3044 
3045       if (MScore::debugMode)
3046             qDebug("select element <%s> type %d(state %d) staff %d",
3047                e ? e->name() : "", int(type), int(selection().state()), e ? e->staffIdx() : -1);
3048 
3049       switch (type) {
3050             case SelectType::SINGLE:
3051                   selectSingle(e, staffIdx);
3052                   break;
3053             case SelectType::ADD:
3054                   selectAdd(e);
3055                   break;
3056             case SelectType::RANGE:
3057                   selectRange(e, staffIdx);
3058                   break;
3059             }
3060       setSelectionChanged(true);
3061       }
3062 
3063 //---------------------------------------------------------
3064 //   selectSingle
3065 //    staffIdx is valid, if element is of type MEASURE
3066 //---------------------------------------------------------
3067 
selectSingle(Element * e,int staffIdx)3068 void Score::selectSingle(Element* e, int staffIdx)
3069       {
3070       SelState selState = _selection.state();
3071       deselectAll();
3072       if (e == 0) {
3073             selState = SelState::NONE;
3074             setUpdateAll();
3075             }
3076       else {
3077             if (e->isMeasure()) {
3078                   select(e, SelectType::RANGE, staffIdx);
3079                   return;
3080                   }
3081             addRefresh(e->abbox());
3082             _selection.add(e);
3083             _is.setTrack(e->track());
3084             selState = SelState::LIST;
3085             if (e->type() == ElementType::NOTE) {
3086                   e = e->parent();
3087                   }
3088             if (e->isChordRest()) {
3089                   _is.setLastSegment(_is.segment());
3090                   _is.setSegment(toChordRest(e)->segment());
3091                   }
3092             }
3093       _selection.setActiveSegment(0);
3094       _selection.setActiveTrack(0);
3095 
3096       _selection.setState(selState);
3097       }
3098 
3099 //---------------------------------------------------------
3100 //   switchToPageMode
3101 //---------------------------------------------------------
3102 
switchToPageMode()3103 void Score::switchToPageMode()
3104       {
3105             if (_layoutMode != LayoutMode::PAGE) {
3106                   setLayoutMode(LayoutMode::PAGE);
3107                   doLayout();
3108             }
3109       }
3110 
3111 //---------------------------------------------------------
3112 //   selectAdd
3113 //---------------------------------------------------------
3114 
selectAdd(Element * e)3115 void Score::selectAdd(Element* e)
3116       {
3117       SelState selState = _selection.state();
3118 
3119       if (_selection.isRange()) {
3120             select(0, SelectType::SINGLE, 0);
3121             return;
3122             }
3123 
3124       if (e->isMeasure()) {
3125             Measure* m = toMeasure(e);
3126             Fraction tick  = m->tick();
3127             if (_selection.isNone()) {
3128                   _selection.setRange(m->tick2segment(tick),
3129                                       m == lastMeasure() ? 0 : m->last(),
3130                                       0,
3131                                       nstaves());
3132                   setUpdateAll();
3133                   selState = SelState::RANGE;
3134                   _selection.updateSelectedElements();
3135                   }
3136             }
3137       else if (!_selection.elements().contains(e)) {
3138             addRefresh(e->abbox());
3139             selState = SelState::LIST;
3140             _selection.add(e);
3141             }
3142 
3143       _selection.setState(selState);
3144       }
3145 
3146 //---------------------------------------------------------
3147 //   selectRange
3148 //    staffIdx is valid, if element is of type MEASURE
3149 //---------------------------------------------------------
3150 
selectRange(Element * e,int staffIdx)3151 void Score::selectRange(Element* e, int staffIdx)
3152       {
3153       int activeTrack = e->track();
3154       // current selection is range extending to end of score?
3155       bool endRangeSelected = selection().isRange() && selection().endSegment() == nullptr;
3156       if (e->isMeasure()) {
3157             Measure* m  = toMeasure(e);
3158             Fraction tick    = m->tick();
3159             Fraction etick   = tick + m->ticks();
3160             activeTrack = staffIdx * VOICES;
3161             Segment* s1 = m->tick2segment(tick);
3162             if (!s1)                      // m is corrupted!
3163                   s1 = m->first(SegmentType::ChordRest);
3164             Segment* s2 = m == lastMeasure() ? 0 : m->last();
3165             if (_selection.isNone() || (_selection.isList() && !_selection.isSingle())) {
3166                   if (_selection.isList())
3167                         deselectAll();
3168                   _selection.setRange(s1, s2, staffIdx, staffIdx + 1);
3169                   }
3170             else if (_selection.isRange())
3171                   _selection.extendRangeSelection(s1, s2, staffIdx, tick, etick);
3172             else if (_selection.isSingle()) {
3173                   Element* oe = selection().element();
3174                   if (oe->isNote() || oe->isChordRest()) {
3175                         if (oe->isNote())
3176                               oe = oe->parent();
3177                         ChordRest* cr = toChordRest(oe);
3178                         Fraction oetick = cr->segment()->tick();
3179                         Segment* startSegment = cr->segment();
3180                         Segment* endSegment = m->last();
3181                         if (tick < oetick) {
3182                               startSegment = m->tick2segment(tick);
3183                               if (etick <= oetick) {
3184                                     SegmentType st = SegmentType::ChordRest | SegmentType::EndBarLine | SegmentType::Clef;
3185                                     endSegment = cr->nextSegmentAfterCR(st);
3186                                     }
3187                               }
3188                         int staffStart = staffIdx;
3189                         int endStaff = staffIdx + 1;
3190                         if (staffStart > cr->staffIdx())
3191                               staffStart = cr->staffIdx();
3192                         else if (cr->staffIdx() >= endStaff)
3193                               endStaff = cr->staffIdx() + 1;
3194                         _selection.setRange(startSegment, endSegment, staffStart, endStaff);
3195                         }
3196                   else {
3197                         deselectAll();
3198                         _selection.setRange(s1, s2, staffIdx, staffIdx + 1);
3199                         }
3200                   }
3201             else {
3202                   qDebug("SELECT_RANGE: measure: sel state %d", int(_selection.state()));
3203                   return;
3204                   }
3205             }
3206       else if (e->isNote() || e->isChordRest()) {
3207             if (e->isNote())
3208                   e = e->parent();
3209             ChordRest* cr = toChordRest(e);
3210 
3211             if (_selection.isNone() || (_selection.isList() && !_selection.isSingle())) {
3212                   if (_selection.isList())
3213                         deselectAll();
3214                   SegmentType st = SegmentType::ChordRest | SegmentType::EndBarLine | SegmentType::Clef;
3215                   _selection.setRange(cr->segment(), cr->nextSegmentAfterCR(st), e->staffIdx(), e->staffIdx() + 1);
3216                   activeTrack = cr->track();
3217                   }
3218             else if (_selection.isSingle()) {
3219                   Element* oe = _selection.element();
3220                   if (oe && (oe->isNote() || oe->isRest())) {
3221                         if (oe->isNote())
3222                               oe = oe->parent();
3223                         ChordRest* ocr = toChordRest(oe);
3224 
3225                         Segment* endSeg = tick2segmentMM(ocr->segment()->tick() + ocr->actualTicks(), true);
3226                         if (!endSeg)
3227                               endSeg = ocr->segment()->next();
3228 
3229                         _selection.setRange(ocr->segment(), endSeg, oe->staffIdx(), oe->staffIdx() + 1);
3230                         _selection.extendRangeSelection(cr);
3231                         }
3232                   else {
3233                         select(e, SelectType::SINGLE, 0);
3234                         return;
3235                         }
3236                   }
3237             else if (_selection.isRange()) {
3238                   _selection.extendRangeSelection(cr);
3239                   }
3240             else {
3241                   qDebug("sel state %d", int(_selection.state()));
3242                   return;
3243                   }
3244             if (!endRangeSelected && !_selection.endSegment())
3245                   _selection.setEndSegment(cr->segment()->nextCR());
3246             if (!_selection.startSegment())
3247                   _selection.setStartSegment(cr->segment());
3248             }
3249       else {
3250             // try to select similar in range
3251             Element* selectedElement = _selection.element();
3252             if (selectedElement && e->type() == selectedElement->type()) {
3253                   int idx1 = selectedElement->staffIdx();
3254                   int idx2 = e->staffIdx();
3255                   if (idx1 >= 0 && idx2 >= 0) {
3256                         Fraction t1 = selectedElement->tick();
3257                         Fraction t2 = e->tick();
3258                         if (t1 > t2) {
3259                               Fraction temp = t1;
3260                               t1 = t2;
3261                               t2 = temp;
3262                               }
3263                         Segment* s1 = tick2segmentMM(t1, true, SegmentType::ChordRest);
3264                         Segment* s2 = tick2segmentMM(t2, true, SegmentType::ChordRest);
3265                         if (s2)
3266                               s2 = s2->next1MM(SegmentType::ChordRest);
3267                         if (s1 && s2) {
3268                               _selection.setRange(s1, s2, idx1, idx2 + 1);
3269                               selectSimilarInRange(e);
3270                               if (selectedElement->track() == e->track()) {
3271                                     // limit to this voice only
3272                                     const QList<Element*>& list = _selection.elements();
3273                                     for (Element* el : list) {
3274                                           if (el->track() != e->track())
3275                                                 _selection.remove(el);
3276                                           }
3277                                     }
3278                               return;
3279                               }
3280                         }
3281                   }
3282             select(e, SelectType::SINGLE, staffIdx);
3283             return;
3284             }
3285 
3286       _selection.setActiveTrack(activeTrack);
3287 
3288       // doing this in note entry mode can clear selection
3289       if (_selection.startSegment() && !noteEntryMode()) {
3290             Fraction tick = _selection.startSegment()->tick();
3291             if (masterScore()->playPos() != tick)
3292                   masterScore()->setPlayPos(tick);
3293             }
3294 
3295       _selection.updateSelectedElements();
3296       }
3297 
3298 //---------------------------------------------------------
3299 //   collectMatch
3300 //---------------------------------------------------------
3301 
collectMatch(void * data,Element * e)3302 void Score::collectMatch(void* data, Element* e)
3303       {
3304       ElementPattern* p = static_cast<ElementPattern*>(data);
3305       if (p->type != int(e->type()))
3306             return;
3307 
3308       if (p->type == int(ElementType::NOTE)) {
3309             if (p->subtype < 0) {
3310                   if (!(toNote(e)->chord()->isGrace()))
3311                         return;
3312                   }
3313             else if ((toNote(e)->chord()->isGrace()) || (p->subtype != e->subtype()))
3314                   return;
3315             }
3316       else if (p->subtypeValid && p->subtype != e->subtype())
3317             return;
3318 
3319       if ((p->staffStart != -1)
3320          && ((p->staffStart > e->staffIdx()) || (p->staffEnd <= e->staffIdx())))
3321             return;
3322 
3323       if (p->voice != -1 && p->voice != e->voice())
3324             return;
3325 
3326       if (p->system) {
3327             Element* ee = e;
3328             do {
3329                   if (ee->type() == ElementType::SYSTEM) {
3330                         if (p->system != ee)
3331                               return;
3332                         break;
3333                         }
3334                   ee = ee->parent();
3335                   } while (ee);
3336             }
3337 
3338       if (e->isRest() && p->durationTicks != Fraction(-1,1)) {
3339             const Rest* r = toRest(e);
3340             if (p->durationTicks != r->actualTicks())
3341                   return;
3342             }
3343 
3344       if (p->measure && (p->measure != e->findMeasure()))
3345             return;
3346 
3347       if ((p->beat.isValid()) && (p->beat != e->beat()))
3348             return;
3349 
3350       p->el.append(e);
3351       }
3352 
3353 //---------------------------------------------------------
3354 //   collectNoteMatch
3355 //---------------------------------------------------------
3356 
collectNoteMatch(void * data,Element * e)3357 void Score::collectNoteMatch(void* data, Element* e)
3358       {
3359       NotePattern* p = static_cast<NotePattern*>(data);
3360       if (!e->isNote())
3361             return;
3362       Note* n = toNote(e);
3363       if (p->type != NoteType::INVALID && p->type != n->noteType())
3364             return;
3365       if (p->pitch != -1 && p->pitch != n->pitch())
3366             return;
3367       if (p->string != STRING_NONE && p->string != n->string())
3368             return;
3369       if (p->tpc != Tpc::TPC_INVALID && p->tpc != n->tpc())
3370             return;
3371       if (p->notehead != NoteHead::Group::HEAD_INVALID && p->notehead != n->headGroup())
3372             return;
3373       if (p->durationType.type() != TDuration::DurationType::V_INVALID && p->durationType != n->chord()->actualDurationType())
3374             return;
3375       if (p->durationTicks != Fraction(-1,1) && p->durationTicks != n->chord()->actualTicks())
3376             return;
3377       if ((p->staffStart != -1)
3378          && ((p->staffStart > e->staffIdx()) || (p->staffEnd <= e->staffIdx())))
3379             return;
3380       if (p->voice != -1 && p->voice != e->voice())
3381             return;
3382       if (p->system && (p->system != n->chord()->segment()->system()))
3383             return;
3384       if (p->measure && (p->measure != n->findMeasure()))
3385             return;
3386       if ((p->beat.isValid()) && (p->beat != n->beat()))
3387             return;
3388       p->el.append(n);
3389       }
3390 
3391 
3392 //---------------------------------------------------------
3393 //   selectSimilar
3394 //---------------------------------------------------------
3395 
selectSimilar(Element * e,bool sameStaff)3396 void Score::selectSimilar(Element* e, bool sameStaff)
3397       {
3398       ElementType type = e->type();
3399       Score* score = e->score();
3400 
3401       ElementPattern pattern;
3402       pattern.type = int(type);
3403       pattern.subtype = 0;
3404       pattern.subtypeValid = false;
3405       if (type == ElementType::NOTE) {
3406             if (toNote(e)->chord()->isGrace())
3407                   pattern.subtype = -1; // hack
3408             else
3409                   pattern.subtype = e->subtype();
3410             }
3411       pattern.staffStart = sameStaff ? e->staffIdx() : -1;
3412       pattern.staffEnd = sameStaff ? e->staffIdx() + 1 : -1;
3413       pattern.voice   = -1;
3414       pattern.system  = 0;
3415       pattern.durationTicks = Fraction(-1,1);
3416 
3417       score->scanElements(&pattern, collectMatch);
3418 
3419       score->select(0, SelectType::SINGLE, 0);
3420       for (Element* ee : qAsConst(pattern.el))
3421             score->select(ee, SelectType::ADD, 0);
3422       }
3423 
3424 //---------------------------------------------------------
3425 //   selectSimilarInRange
3426 //---------------------------------------------------------
3427 
selectSimilarInRange(Element * e)3428 void Score::selectSimilarInRange(Element* e)
3429       {
3430       ElementType type = e->type();
3431       Score* score = e->score();
3432 
3433       ElementPattern pattern;
3434       pattern.type    = int(type);
3435       pattern.subtype = 0;
3436       pattern.subtypeValid = false;
3437       if (type == ElementType::NOTE) {
3438             if (toNote(e)->chord()->isGrace())
3439                   pattern.subtype = -1; //hack
3440             else
3441                   pattern.subtype = e->subtype();
3442             pattern.subtypeValid = true;
3443             }
3444       pattern.staffStart = selection().staffStart();
3445       pattern.staffEnd = selection().staffEnd();
3446       pattern.voice   = -1;
3447       pattern.system  = 0;
3448       pattern.durationTicks = Fraction(-1,1);
3449 
3450       score->scanElementsInRange(&pattern, collectMatch);
3451 
3452       score->select(0, SelectType::SINGLE, 0);
3453       for (Element* ee : qAsConst(pattern.el))
3454             score->select(ee, SelectType::ADD, 0);
3455       }
3456 
3457 //---------------------------------------------------------
3458 //   enableVerticalSpread
3459 //---------------------------------------------------------
3460 
enableVerticalSpread() const3461 bool Score::enableVerticalSpread() const
3462       {
3463       return styleB(Sid::enableVerticalSpread) && (layoutMode() != LayoutMode::SYSTEM);
3464       }
3465 
3466 //---------------------------------------------------------
3467 //   setEnableVerticalSpread
3468 //---------------------------------------------------------
3469 
setEnableVerticalSpread(bool val)3470 void Score::setEnableVerticalSpread(bool val)
3471       {
3472       setStyleValue(Sid::enableVerticalSpread, val);
3473       }
3474 
3475 //---------------------------------------------------------
3476 //   maxSystemDistance
3477 //---------------------------------------------------------
3478 
maxSystemDistance() const3479 qreal Score::maxSystemDistance() const
3480       {
3481       if (enableVerticalSpread())
3482             return styleP(Sid::maxSystemSpread);
3483       else
3484             return styleP(Sid::maxSystemDistance);
3485       }
3486 
3487 //---------------------------------------------------------
3488 //   lassoSelect
3489 //---------------------------------------------------------
3490 
lassoSelect(const QRectF & bbox)3491 void Score::lassoSelect(const QRectF& bbox)
3492       {
3493       select(0, SelectType::SINGLE, 0);
3494       QRectF fr(bbox.normalized());
3495       foreach(Page* page, pages()) {
3496             QRectF pr(page->bbox());
3497             QRectF frr(fr.translated(-page->pos()));
3498             if (pr.right() < frr.left())
3499                   continue;
3500             if (pr.left() > frr.right())
3501                   break;
3502 
3503             QList<Element*> el = page->items(frr);
3504             for (int i = 0; i < el.size(); ++i) {
3505                   Element* e = el.at(i);
3506                   if (frr.contains(e->abbox())) {
3507                         if (e->type() != ElementType::MEASURE && e->selectable())
3508                               select(e, SelectType::ADD, 0);
3509                         }
3510                   }
3511             }
3512       }
3513 
3514 //---------------------------------------------------------
3515 //   lassoSelectEnd
3516 //---------------------------------------------------------
3517 
lassoSelectEnd()3518 void Score::lassoSelectEnd()
3519       {
3520       int noteRestCount     = 0;
3521       Segment* startSegment = 0;
3522       Segment* endSegment   = 0;
3523       int startStaff        = 0x7fffffff;
3524       int endStaff          = 0;
3525       const ChordRest* endCR = 0;
3526 
3527       if (_selection.elements().empty()) {
3528             _selection.setState(SelState::NONE);
3529             setUpdateAll();
3530             return;
3531             }
3532       _selection.setState(SelState::LIST);
3533 
3534       foreach(const Element* e, _selection.elements()) {
3535             if (e->type() != ElementType::NOTE && e->type() != ElementType::REST)
3536                   continue;
3537             ++noteRestCount;
3538             if (e->type() == ElementType::NOTE)
3539                   e = e->parent();
3540             Segment* seg = static_cast<const ChordRest*>(e)->segment();
3541             if ((startSegment == 0) || (*seg < *startSegment))
3542                   startSegment = seg;
3543             if ((endSegment == 0) || (*seg > *endSegment)) {
3544                   endSegment = seg;
3545                   endCR = static_cast<const ChordRest*>(e);
3546                   }
3547             int idx = e->staffIdx();
3548             if (idx < startStaff)
3549                   startStaff = idx;
3550             if (idx > endStaff)
3551                   endStaff = idx;
3552             }
3553       if (noteRestCount > 0) {
3554             endSegment = endCR->nextSegmentAfterCR(SegmentType::ChordRest
3555                | SegmentType::EndBarLine
3556                | SegmentType::Clef);
3557             _selection.setRange(startSegment, endSegment, startStaff, endStaff+1);
3558             if (!_selection.isRange())
3559                   _selection.setState(SelState::RANGE);
3560             _selection.updateSelectedElements();
3561             }
3562       setUpdateAll();
3563       }
3564 
3565 //---------------------------------------------------------
3566 //   addLyrics
3567 //---------------------------------------------------------
3568 
addLyrics(const Fraction & tick,int staffIdx,const QString & txt)3569 void Score::addLyrics(const Fraction& tick, int staffIdx, const QString& txt)
3570       {
3571       if (txt.trimmed().isEmpty())
3572             return;
3573       Measure* measure = tick2measure(tick);
3574       Segment* seg     = measure->findSegment(SegmentType::ChordRest, tick);
3575       if (seg == 0) {
3576             qDebug("no segment found for lyrics<%s> at tick %d",
3577                qPrintable(txt), tick.ticks());
3578             return;
3579             }
3580 
3581       bool lyricsAdded = false;
3582       for (int voice = 0; voice < VOICES; ++voice) {
3583             int track = staffIdx * VOICES + voice;
3584             ChordRest* cr = toChordRest(seg->element(track));
3585             if (cr) {
3586                   Lyrics* l = new Lyrics(this);
3587                   l->setXmlText(txt);
3588                   l->setTrack(track);
3589                   cr->add(l);
3590                   lyricsAdded = true;
3591                   break;
3592                   }
3593             }
3594       if (!lyricsAdded) {
3595             qDebug("no chord/rest for lyrics<%s> at tick %d, staff %d",
3596                qPrintable(txt), tick.ticks(), staffIdx);
3597             }
3598       }
3599 
3600 //---------------------------------------------------------
3601 //   setTempo
3602 //    convenience function to access TempoMap
3603 //---------------------------------------------------------
3604 
setTempo(Segment * segment,qreal tempo)3605 void Score::setTempo(Segment* segment, qreal tempo)
3606       {
3607       setTempo(segment->tick(), tempo);
3608       }
3609 
setTempo(const Fraction & tick,qreal tempo)3610 void Score::setTempo(const Fraction& tick, qreal tempo)
3611       {
3612       tempomap()->setTempo(tick.ticks(), tempo);
3613       setPlaylistDirty();
3614       }
3615 
3616 //---------------------------------------------------------
3617 //   removeTempo
3618 //---------------------------------------------------------
3619 
removeTempo(const Fraction & tick)3620 void Score::removeTempo(const Fraction& tick)
3621       {
3622       tempomap()->delTempo(tick.ticks());
3623       setPlaylistDirty();
3624       }
3625 
3626 //---------------------------------------------------------
3627 //   resetTempo
3628 //---------------------------------------------------------
3629 
resetTempo()3630 void Score::resetTempo()
3631       {
3632       resetTempoRange(Fraction(0,1), Fraction(std::numeric_limits<int>::max(), 1));
3633       }
3634 
3635 //---------------------------------------------------------
3636 //   resetTempoRange
3637 //    Reset tempo and timesig maps in the given range.
3638 //    Start tick included, end tick excluded.
3639 //---------------------------------------------------------
3640 
resetTempoRange(const Fraction & tick1,const Fraction & tick2)3641 void Score::resetTempoRange(const Fraction& tick1, const Fraction& tick2)
3642       {
3643       const bool zeroInRange = (tick1 <= Fraction(0,1) && tick2 > Fraction(0,1));
3644       tempomap()->clearRange(tick1.ticks(), tick2.ticks());
3645       if (zeroInRange)
3646             tempomap()->setTempo(0, _defaultTempo);
3647       sigmap()->clearRange(tick1.ticks(), tick2.ticks());
3648       if (zeroInRange) {
3649             Measure* m = firstMeasure();
3650             if (m)
3651                   sigmap()->add(0, SigEvent(m->ticks(),  m->timesig(), 0));
3652             }
3653       }
3654 
3655 //---------------------------------------------------------
3656 //   setPause
3657 //---------------------------------------------------------
3658 
setPause(const Fraction & tick,qreal seconds)3659 void Score::setPause(const Fraction& tick, qreal seconds)
3660       {
3661       tempomap()->setPause(tick.ticks(), seconds);
3662       setPlaylistDirty();
3663       }
3664 
3665 //---------------------------------------------------------
3666 //   tempo
3667 //---------------------------------------------------------
3668 
tempo(const Fraction & tick) const3669 qreal Score::tempo(const Fraction& tick) const
3670       {
3671       return tempomap()->tempo(tick.ticks());
3672       }
3673 
3674 //---------------------------------------------------------
3675 //   loWidth
3676 //---------------------------------------------------------
3677 
loWidth() const3678 qreal Score::loWidth() const
3679       {
3680       return styleD(Sid::pageWidth) * DPI;
3681       }
3682 
3683 //---------------------------------------------------------
3684 //   loHeight
3685 //---------------------------------------------------------
3686 
loHeight() const3687 qreal Score::loHeight() const
3688       {
3689       return styleD(Sid::pageHeight) * DPI;
3690       }
3691 
3692 //---------------------------------------------------------
3693 //   cmdSelectAll
3694 //---------------------------------------------------------
3695 
cmdSelectAll()3696 void Score::cmdSelectAll()
3697       {
3698       if (_measures.size() == 0)
3699             return;
3700       deselectAll();
3701       Measure* first = firstMeasureMM();
3702       if (!first)
3703             return;
3704       Measure* last = lastMeasureMM();
3705       selectRange(first, 0);
3706       selectRange(last, nstaves() - 1);
3707       setUpdateAll();
3708       update();
3709       }
3710 
3711 //---------------------------------------------------------
3712 //   cmdSelectSection
3713 //---------------------------------------------------------
3714 
cmdSelectSection()3715 void Score::cmdSelectSection()
3716       {
3717       Segment* s = _selection.startSegment();
3718       if (s == 0)
3719             return;
3720       MeasureBase* sm = s->measure();
3721       MeasureBase* em = sm;
3722       while (sm->prev()) {
3723             if (sm->prev()->sectionBreak())
3724                   break;
3725             sm = sm->prev();
3726             }
3727       while (em->next()) {
3728             if (em->sectionBreak())
3729                   break;
3730             em = em->next();
3731             }
3732       while (sm && sm->type() != ElementType::MEASURE)
3733             sm = sm->next();
3734       while (em && em->type() != ElementType::MEASURE)
3735             em = em->next();
3736       if (sm == 0 || em == 0)
3737             return;
3738 
3739       _selection.setRange(toMeasure(sm)->first(), toMeasure(em)->last(), 0, nstaves());
3740       }
3741 
3742 //---------------------------------------------------------
3743 //   undo
3744 //---------------------------------------------------------
3745 
undo(UndoCommand * cmd,EditData * ed) const3746 void Score::undo(UndoCommand* cmd, EditData* ed) const
3747       {
3748       undoStack()->push(cmd, ed);
3749       }
3750 
3751 //---------------------------------------------------------
3752 //   linkId
3753 //---------------------------------------------------------
3754 
linkId()3755 int Score::linkId()
3756       {
3757       return (masterScore()->_linkId)++;
3758       }
3759 
3760 // val is a used link id
linkId(int val)3761 void Score::linkId(int val)
3762       {
3763       Score* s = masterScore();
3764       if (val >= s->_linkId)
3765             s->_linkId = val + 1;   // update unused link id
3766       }
3767 
3768 //---------------------------------------------------------
3769 //   scoreList
3770 //    return a list of scores containing the root score
3771 //    and all part scores (if there are any)
3772 //---------------------------------------------------------
3773 
scoreList()3774 QList<Score*> Score::scoreList()
3775       {
3776       QList<Score*> scores;
3777       Score* root = masterScore();
3778       scores.append(root);
3779       for (const Excerpt* ex : root->excerpts()) {
3780             if (ex->partScore())
3781                   scores.append(ex->partScore());
3782             }
3783       return scores;
3784       }
3785 
3786 //---------------------------------------------------------
3787 //   switchLayer
3788 //---------------------------------------------------------
3789 
switchLayer(const QString & s)3790 bool Score::switchLayer(const QString& s)
3791       {
3792       int layerIdx = 0;
3793       for (const Layer& l : layer()) {
3794             if (s == l.name) {
3795                   setCurrentLayer(layerIdx);
3796                   return true;
3797                   }
3798             ++layerIdx;
3799             }
3800       return false;
3801       }
3802 
3803 //---------------------------------------------------------
3804 //   appendPart
3805 //---------------------------------------------------------
3806 
appendPart(const InstrumentTemplate * t)3807 void Score::appendPart(const InstrumentTemplate* t)
3808       {
3809       Part* part = new Part(this);
3810       part->initFromInstrTemplate(t);
3811       int n = nstaves();
3812       for (int i = 0; i < t->nstaves(); ++i) {
3813             Staff* staff = new Staff(this);
3814             staff->setPart(part);
3815             StaffType* stt = staff->staffType(Fraction(0,1));
3816             stt->setLines(t->staffLines[i]);
3817             stt->setSmall(t->smallStaff[i]);
3818             if (i == 0) {
3819                   staff->setBracketType(0, t->bracket[0]);
3820                   staff->setBracketSpan(0, t->nstaves());
3821                   }
3822             undoInsertStaff(staff, i);
3823             }
3824       part->staves()->front()->setBarLineSpan(part->nstaves());
3825       undoInsertPart(part, n);
3826       fixTicks();
3827       masterScore()->rebuildMidiMapping();
3828       }
3829 
3830 //---------------------------------------------------------
3831 //   appendMeasures
3832 //---------------------------------------------------------
3833 
appendMeasures(int n)3834 void Score::appendMeasures(int n)
3835       {
3836       for (int i = 0; i < n; ++i)
3837             insertMeasure(ElementType::MEASURE, 0, false);
3838       }
3839 
3840 //---------------------------------------------------------
3841 //   addSpanner
3842 //---------------------------------------------------------
3843 
addSpanner(Spanner * s)3844 void Score::addSpanner(Spanner* s)
3845       {
3846       _spanner.addSpanner(s);
3847       }
3848 
3849 //---------------------------------------------------------
3850 //   removeSpanner
3851 //---------------------------------------------------------
3852 
removeSpanner(Spanner * s)3853 void Score::removeSpanner(Spanner* s)
3854       {
3855       _spanner.removeSpanner(s);
3856       }
3857 
3858 //---------------------------------------------------------
3859 //   isSpannerStartEnd
3860 //    does is spanner start or end at tick position tick
3861 //    for track ?
3862 //---------------------------------------------------------
3863 
isSpannerStartEnd(const Fraction & tick,int track) const3864 bool Score::isSpannerStartEnd(const Fraction& tick, int track) const
3865       {
3866       for (auto i : _spanner.map()) {
3867             if (i.second->track() != track)
3868                   continue;
3869             if (i.second->tick() == tick || i.second->tick2() == tick)
3870                   return true;
3871             }
3872       return false;
3873       }
3874 
insertTime(const Fraction & tick,const Fraction & len)3875 void Score::insertTime(const Fraction& tick, const Fraction& len)
3876       {
3877       for (Staff* staff : staves())
3878             staff->insertTime(tick, len);
3879       for (Part* part : parts())
3880             part->insertTime(tick, len);
3881       }
3882 
3883 //---------------------------------------------------------
3884 //   addUnmanagedSpanner
3885 //---------------------------------------------------------
3886 
addUnmanagedSpanner(Spanner * s)3887 void Score::addUnmanagedSpanner(Spanner* s)
3888       {
3889       _unmanagedSpanner.insert(s);
3890       }
3891 
3892 //---------------------------------------------------------
3893 //   removeSpanner
3894 //---------------------------------------------------------
3895 
removeUnmanagedSpanner(Spanner * s)3896 void Score::removeUnmanagedSpanner(Spanner* s)
3897       {
3898       _unmanagedSpanner.erase(s);
3899       }
3900 
3901 //---------------------------------------------------------
3902 //   setPos
3903 //---------------------------------------------------------
3904 
setPos(POS pos,Fraction tick)3905 void MasterScore::setPos(POS pos, Fraction tick)
3906       {
3907       if (tick < Fraction(0,1))
3908             tick = Fraction(0,1);
3909       if (tick > lastMeasure()->endTick()) {
3910             // End Reverb may last longer than written notation, but cursor position should not
3911             tick = lastMeasure()->endTick();
3912             }
3913 
3914       _pos[int(pos)] = tick;
3915       // even though tick position might not have changed, layout might have
3916       // so we should update cursor here
3917       // however, we must be careful not to call setPos() again while handling posChanged, or recursion results
3918       for (Score* s : scoreList())
3919             emit s->posChanged(pos, unsigned(tick.ticks()));
3920       }
3921 
3922 //---------------------------------------------------------
3923 //   uniqueStaves
3924 //---------------------------------------------------------
3925 
uniqueStaves() const3926 QList<int> Score::uniqueStaves() const
3927       {
3928       QList<int> sl;
3929 
3930       for (int staffIdx = 0; staffIdx < nstaves(); ++staffIdx) {
3931             Staff* s = staff(staffIdx);
3932             if (s->links()) {
3933                   bool alreadyInList = false;
3934                   for (int idx : sl) {
3935                         if (s->links()->contains(staff(idx))) {
3936                               alreadyInList = true;
3937                               break;
3938                               }
3939                         }
3940                   if (alreadyInList)
3941                         continue;
3942                   }
3943             sl.append(staffIdx);
3944             }
3945       return sl;
3946       }
3947 
3948 //---------------------------------------------------------
3949 //   findCR
3950 //    find chord/rest <= tick in track
3951 //---------------------------------------------------------
3952 
findCR(Fraction tick,int track) const3953 ChordRest* Score::findCR(Fraction tick, int track) const
3954       {
3955       Measure* m = tick2measureMM(tick);
3956       if (!m) {
3957             qDebug("findCR: no measure for tick %d", tick.ticks());
3958             return nullptr;
3959             }
3960       // attach to first rest all spanner when mmRest
3961       if (m->isMMRest())
3962             tick = m->tick();
3963       Segment* s = m->first(SegmentType::ChordRest);
3964       for (Segment* ns = s; ; ns = ns->next(SegmentType::ChordRest)) {
3965             if (!ns || ns->tick() > tick)
3966                   break;
3967             Element* el = ns->element(track);
3968             if (el && el->isRest() && toRest(el)->isGap())
3969                   continue;
3970             else if (el)
3971                   s = ns;
3972             }
3973       if (!s)
3974             return nullptr;
3975       Element* el = s->element(track);
3976       if (el && el->isRest() && toRest(el)->isGap())
3977             s = 0;
3978       if (s)
3979             return toChordRest(s->element(track));
3980       return nullptr;
3981       }
3982 
3983 //---------------------------------------------------------
3984 //   findCRinStaff
3985 //    find last chord/rest on staff that ends before tick
3986 //---------------------------------------------------------
3987 
findCRinStaff(const Fraction & tick,int staffIdx) const3988 ChordRest* Score::findCRinStaff(const Fraction& tick, int staffIdx) const
3989       {
3990       Fraction ptick = tick - Fraction::fromTicks(1);
3991       Measure* m = tick2measureMM(ptick);
3992       if (!m) {
3993             qDebug("findCRinStaff: no measure for tick %d", ptick.ticks());
3994             return 0;
3995             }
3996       // attach to first rest all spanner when mmRest
3997       if (m->isMMRest())
3998             ptick = m->tick();
3999 
4000       Segment* s      = m->first(SegmentType::ChordRest);
4001       int strack      = staffIdx * VOICES;
4002       int etrack      = strack + VOICES;
4003       int actualTrack = strack;
4004 
4005       Fraction lastTick = Fraction(-1,1);
4006       for (Segment* ns = s; ; ns = ns->next(SegmentType::ChordRest)) {
4007             if (ns == 0 || ns->tick() > ptick)
4008                   break;
4009             // found a segment; now find longest cr on this staff that does not overlap tick
4010             for (int t = strack; t < etrack; ++t) {
4011                   ChordRest* cr = toChordRest(ns->element(t));
4012                   if (cr) {
4013                         Fraction endTick = cr->tick() + cr->actualTicks();
4014                         if (endTick >= lastTick && endTick <= tick) {
4015                               s = ns;
4016                               actualTrack = t;
4017                               lastTick = endTick;
4018                               }
4019                         }
4020                   }
4021             }
4022       if (s)
4023             return toChordRest(s->element(actualTrack));
4024       return 0;
4025       }
4026 
4027 //---------------------------------------------------------
4028 //   cmdNextPrevSystem
4029 //---------------------------------------------------------
4030 
cmdNextPrevSystem(ChordRest * cr,bool next)4031 ChordRest* Score::cmdNextPrevSystem(ChordRest* cr, bool next)
4032       {
4033       auto newCR = cr;
4034       auto currentMeasure = cr->measure();
4035       auto currentSystem = currentMeasure->system() ? currentMeasure->system() : currentMeasure->mmRest1()->system();
4036       if (!currentSystem)
4037             return cr;
4038       auto destinationMeasure = currentSystem->firstMeasure();
4039       auto firstSegment = destinationMeasure->first(SegmentType::ChordRest);
4040 
4041       // Case: Go to next system
4042       if (next) {
4043             if ((destinationMeasure = currentSystem->lastMeasure()->nextMeasure())) {
4044                   // There is a next system present: get it and accommodate for MMRest
4045                   currentSystem = destinationMeasure->system() ? destinationMeasure->system() : destinationMeasure->mmRest1()->system();
4046                   if ((destinationMeasure = currentSystem->firstMeasure()))
4047                         if ((newCR = destinationMeasure->first()->nextChordRest(trackZeroVoice(cr->track()), false)))
4048                               cr = newCR;
4049                   }
4050             else if (currentMeasure != lastMeasure()) {
4051                   // There is no next system present: go to last measure of current system
4052                   if ((destinationMeasure = lastMeasure())) {
4053                         if ((newCR = destinationMeasure->first()->nextChordRest(trackZeroVoice(cr->track()), false))) {
4054                               if (!destinationMeasure->isMMRest())
4055                                     cr = newCR;
4056                               // Last visual measure is a MMRest: go to very last measure within that MMRest
4057                               else if ((destinationMeasure = lastMeasureMM()) && (newCR = destinationMeasure->first()->nextChordRest(trackZeroVoice(cr->track()), false)))
4058                                     cr = newCR;
4059                               }
4060                         }
4061                   }
4062             }
4063 
4064       // Case: Go to previous system
4065       else {
4066             auto currentSegment = cr->segment();
4067             // Only go to previous system's beginning if user is already at the absolute beginning of current system
4068             // and not in first measure of entire score
4069             if ((destinationMeasure != firstMeasure() && destinationMeasure != firstMeasureMM()) &&
4070                (currentSegment == firstSegment || (currentMeasure->mmRest() && currentMeasure->mmRest()->isFirstInSystem()))) {
4071                   if (!(destinationMeasure = destinationMeasure->prevMeasure()))
4072                         if (!(destinationMeasure = destinationMeasure->prevMeasureMM()))
4073                               return cr;
4074                   if (!(currentSystem = destinationMeasure->system() ? destinationMeasure->system() : destinationMeasure->mmRest1()->system()))
4075                         return cr;
4076                   destinationMeasure = currentSystem->firstMeasure();
4077                   }
4078             if (destinationMeasure)
4079                   if ((newCR = destinationMeasure->first()->nextChordRest(trackZeroVoice(cr->track()), false)))
4080                         cr = newCR;
4081             }
4082       return cr;
4083       }
4084 
4085 //---------------------------------------------------------
4086 //   cmdNextPrevFrame
4087 //   Return next/previous [Vertical/Horizontal/Text] frame
4088 //   to be used as a navigation command
4089 //---------------------------------------------------------
4090 
cmdNextPrevFrame(MeasureBase * currentMeasureBase,bool next) const4091 Box* Score::cmdNextPrevFrame(MeasureBase* currentMeasureBase, bool next) const
4092       {
4093       Box* selectedBox { nullptr };
4094       while (!selectedBox && (currentMeasureBase = (next ? currentMeasureBase->next() : currentMeasureBase->prev()))) {
4095             if (currentMeasureBase->isBox())
4096                   selectedBox = toBox(currentMeasureBase);
4097             }
4098       return selectedBox;
4099       }
4100 
4101 //---------------------------------------------------------
4102 //   cmdNextPrevSection
4103 //    Return [Box* or ChordRest*] of next/previous section
4104 //---------------------------------------------------------
4105 
cmdNextPrevSection(Element * el,bool dir) const4106 Element* Score::cmdNextPrevSection(Element* el, bool dir) const
4107       {
4108       auto currentMeasureBase = el->findMeasureBase();
4109       auto destination = currentMeasureBase;
4110       if (currentMeasureBase) {
4111             // -----------------------
4112             // Next Section of Score
4113             // -----------------------
4114             if (dir) {
4115                   if ((destination = getNextPrevSectionBreak(currentMeasureBase, true))) {
4116                         el = getScoreElementOfMeasureBase(destination->next());
4117                         }
4118                   }
4119             // -------------------------
4120             // Previous Section of Score
4121             // -------------------------
4122             else {
4123                   auto currentSegment = el->isChordRest() ? toChordRest(el)->segment() : nullptr;
4124                   if ((destination = getNextPrevSectionBreak(currentMeasureBase, false))) {
4125                         if (currentSegment) {
4126                               if ((el = getScoreElementOfMeasureBase((score()->first() == destination) ? destination : destination->next()))) {
4127                                     if (el->isChordRest() && (toChordRest(el)->segment() == currentSegment)) {
4128                                           if ((destination = getNextPrevSectionBreak(destination, false))) {
4129                                                 el = !(destination->sectionBreak()) ? destination : getScoreElementOfMeasureBase(destination->next());
4130                                                 }
4131                                           }
4132                                     }
4133                               }
4134                         else if ((score()->first() != currentMeasureBase) && (el = getScoreElementOfMeasureBase(destination->next()))) {
4135                               if (el->findMeasureBase() == currentMeasureBase) {
4136                                     if ((destination = getNextPrevSectionBreak(destination, false))) {
4137                                           el = !(destination->sectionBreak()) ? el : getScoreElementOfMeasureBase(destination->next());
4138                                           }
4139                                     }
4140                               }
4141                         }
4142                   }
4143             }
4144       return el;
4145       }
4146 
4147 //---------------------------------------------------------
4148 //   getNextPrevSectionBreak
4149 //    Condition: MeasureBase* must be valid before call
4150 //    If no previous section break exists selects first
4151 //    MeasureBase within score
4152 //---------------------------------------------------------
4153 
getNextPrevSectionBreak(MeasureBase * mb,bool dir) const4154 MeasureBase* Score::getNextPrevSectionBreak(MeasureBase* mb, bool dir) const
4155       {
4156       auto destination = mb;
4157       if (destination) {
4158             if (dir) {
4159                   // Find next section break
4160                   auto endOfSection { false };
4161                   while (!endOfSection) {
4162                         if ((destination = destination->next()))
4163                               endOfSection = destination->sectionBreak();
4164                         else break;
4165                         }
4166                   }
4167             else {
4168                   // Find previous section break
4169                   auto inCurrentSection { true };
4170                   while (inCurrentSection && destination) {
4171                         if (destination->index()) {
4172                               // Safety: SegFaults if invoking prev() when index=0
4173                               //         even when MeasureBase* is valid!
4174                               destination = destination->prev();
4175                               inCurrentSection = !(destination->sectionBreak());
4176                               }
4177                         else destination = nullptr;
4178                         }
4179                   if (inCurrentSection || !destination)
4180                         destination = score()->first();
4181                   }
4182             }
4183       return destination;
4184       }
4185 
4186 
4187 //---------------------------------------------------------
4188 //   getScoreElementOfMeasureBase
4189 //    Helper function
4190 //    Get an Element* as Box or ChordRest depending on
4191 //    MeasureBase
4192 //---------------------------------------------------------
4193 
getScoreElementOfMeasureBase(MeasureBase * mb) const4194 Element* Score::getScoreElementOfMeasureBase(MeasureBase* mb) const
4195       {
4196       Element* el { nullptr };
4197       ChordRest* cr { nullptr };
4198       const Measure* currentMeasure { nullptr };
4199       if (mb) {
4200             if (mb->isBox())
4201                   el = toBox(mb);
4202             else if ((currentMeasure = mb->findMeasure())) {
4203                   // Accommodate for MMRest
4204                   if (score()->styleB(Sid::createMultiMeasureRests) && currentMeasure->hasMMRest())
4205                         currentMeasure = currentMeasure->mmRest1();
4206                   if ((cr = currentMeasure->first()->nextChordRest(0, false)))
4207                         el = cr;
4208                   }
4209             }
4210       return el;
4211       }
4212 
4213 //---------------------------------------------------------
4214 //   setSoloMute
4215 //   called once at opening file, adds soloMute marks
4216 //---------------------------------------------------------
4217 
setSoloMute()4218 void MasterScore::setSoloMute()
4219       {
4220       for (unsigned i = 0; i < _midiMapping.size(); i++) {
4221             Channel* b = _midiMapping[i].articulation();
4222             if (b->solo()) {
4223                   b->setSoloMute(false);
4224                   for (unsigned j = 0; j < _midiMapping.size(); j++) {
4225                         Channel* a = _midiMapping[j].articulation();
4226                         bool sameMidiMapping = _midiMapping[i].port() == _midiMapping[j].port() && _midiMapping[i].channel() == _midiMapping[j].channel();
4227                         a->setSoloMute((i != j && !a->solo() && !sameMidiMapping));
4228                         a->setSolo(i == j || a->solo() || sameMidiMapping);
4229                         }
4230                   }
4231             }
4232       }
4233 
4234 //---------------------------------------------------------
4235 //   setImportedFilePath
4236 //---------------------------------------------------------
4237 
setImportedFilePath(const QString & filePath)4238 void Score::setImportedFilePath(const QString& filePath)
4239       {
4240       _importedFilePath = filePath;
4241       }
4242 
4243 //---------------------------------------------------------
4244 //   nmeasure
4245 //---------------------------------------------------------
4246 
nmeasures() const4247 int Score::nmeasures() const
4248       {
4249       int n = 0;
4250       for (const Measure* m = firstMeasure(); m; m = m->nextMeasure())
4251             n++;
4252       return n;
4253       }
4254 
4255 //---------------------------------------------------------
4256 //   firstTrailingMeasure
4257 //---------------------------------------------------------
4258 
firstTrailingMeasure(ChordRest ** cr)4259 Measure* Score::firstTrailingMeasure(ChordRest** cr)
4260       {
4261       Measure* firstMeasure = nullptr;
4262       auto m = lastMeasure();
4263 
4264       // No active selection: prepare first empty trailing measure of entire score
4265       if (!cr)
4266             for (; m && m->isFullMeasureRest(); firstMeasure = m, m = m->prevMeasure());
4267       // Active selection: select full measure rest of active staff's empty trailing measure
4268       else {
4269             ChordRest* tempCR = *cr;
4270             while (m && (tempCR = m->first()->nextChordRest(trackZeroVoice((*cr)->track()), false))->isFullMeasureRest()) {
4271                   *cr = tempCR;
4272                   firstMeasure = m;
4273                   m = m->prevMeasure();
4274                   }
4275             }
4276       return firstMeasure;
4277       }
4278 
4279 //---------------------------------------------------------
4280 //   cmdTopStaff
4281 //---------------------------------------------------------
4282 
cmdTopStaff(ChordRest * cr)4283 ChordRest* Score::cmdTopStaff(ChordRest* cr)
4284       {
4285       // Go to top-most staff of current or first measure depending upon active selection
4286       const auto* destinationMeasure = cr ? cr->measure() : firstMeasure();
4287       if (destinationMeasure) {
4288             // Accommodate for MMRest
4289             if (score()->styleB(Sid::createMultiMeasureRests) && destinationMeasure->hasMMRest())
4290                   destinationMeasure = destinationMeasure->mmRest1();
4291             // Get first ChordRest of top staff
4292             cr = destinationMeasure->first()->nextChordRest(0, false);
4293             }
4294       return cr;
4295       }
4296 
4297 //---------------------------------------------------------
4298 //   hasLyrics
4299 //---------------------------------------------------------
4300 
hasLyrics()4301 bool Score::hasLyrics()
4302       {
4303       if (!firstMeasure())
4304             return false;
4305 
4306       SegmentType st = SegmentType::ChordRest;
4307       for (Segment* seg = firstMeasure()->first(st); seg; seg = seg->next1(st)) {
4308             for (int i = 0; i < ntracks(); ++i) {
4309                   ChordRest* cr = toChordRest(seg->element(i));
4310                   if (cr && !cr->lyrics().empty())
4311                         return true;
4312                   }
4313             }
4314       return false;
4315       }
4316 
4317 //---------------------------------------------------------
4318 //   hasHarmonies
4319 //---------------------------------------------------------
4320 
hasHarmonies()4321 bool Score::hasHarmonies()
4322       {
4323       if (!firstMeasure())
4324             return false;
4325 
4326       SegmentType st = SegmentType::ChordRest;
4327       for (Segment* seg = firstMeasure()->first(st); seg; seg = seg->next1(st)) {
4328             for (Element* e : seg->annotations()) {
4329                   if (e->type() == ElementType::HARMONY)
4330                         return true;
4331                   }
4332             }
4333       return false;
4334       }
4335 
4336 //---------------------------------------------------------
4337 //   lyricCount
4338 //---------------------------------------------------------
4339 
lyricCount()4340 int Score::lyricCount()
4341       {
4342       size_t count = 0;
4343       SegmentType st = SegmentType::ChordRest;
4344       for (Segment* seg = firstMeasure()->first(st); seg; seg = seg->next1(st)) {
4345             for (int i = 0; i < ntracks(); ++i) {
4346                   ChordRest* cr = toChordRest(seg->element(i));
4347                   if (cr)
4348                         count += cr->lyrics().size();
4349                   }
4350             }
4351       return int(count);
4352       }
4353 
4354 //---------------------------------------------------------
4355 //   harmonyCount
4356 //---------------------------------------------------------
4357 
harmonyCount()4358 int Score::harmonyCount()
4359       {
4360       int count = 0;
4361       SegmentType st = SegmentType::ChordRest;
4362       for (Segment* seg = firstMeasure()->first(st); seg; seg = seg->next1(st)) {
4363             for (Element* e : seg->annotations()) {
4364                   if (e->type() == ElementType::HARMONY)
4365                         count++;
4366                   }
4367             }
4368       return count;
4369       }
4370 
4371 //---------------------------------------------------------
4372 //   extractLyrics
4373 //---------------------------------------------------------
4374 
extractLyrics()4375 QString Score::extractLyrics()
4376       {
4377       QString result;
4378       masterScore()->setExpandRepeats(true);
4379       SegmentType st = SegmentType::ChordRest;
4380       for (int track = 0; track < ntracks(); track += VOICES) {
4381             bool found = false;
4382             size_t maxLyrics = 1;
4383             const RepeatList& rlist = repeatList();
4384             for (Measure* m = firstMeasure(); m; m = m->nextMeasure()) {
4385                   m->setPlaybackCount(0);
4386                   }
4387             // follow the repeat segments
4388             for (const RepeatSegment* rs : rlist) {
4389                   Fraction startTick  = Fraction::fromTicks(rs->tick);
4390                   Fraction endTick    = startTick + Fraction::fromTicks(rs->len());
4391                   for (Measure* m = tick2measure(startTick); m; m = m->nextMeasure()) {
4392                         int playCount = m->playbackCount();
4393                         for (Segment* seg = m->first(st); seg; seg = seg->next(st)) {
4394                               // consider voice 1 only
4395                               ChordRest* cr = toChordRest(seg->element(track));
4396                               if (!cr || cr->lyrics().empty())
4397                                     continue;
4398                               if (cr->lyrics().size() > maxLyrics)
4399                                     maxLyrics = cr->lyrics().size();
4400                               if (playCount >= int(cr->lyrics().size()))
4401                                     continue;
4402                               Lyrics* l = cr->lyrics(playCount, Placement::BELOW);  // TODO: ABOVE
4403                               if (!l)
4404                                     continue;
4405                               found = true;
4406                               QString lyric = l->plainText().trimmed();
4407                               if (l->syllabic() == Lyrics::Syllabic::SINGLE || l->syllabic() == Lyrics::Syllabic::END)
4408                                     result += lyric + " ";
4409                               else if (l->syllabic() == Lyrics::Syllabic::BEGIN || l->syllabic() == Lyrics::Syllabic::MIDDLE)
4410                                     result += lyric;
4411                               }
4412                         m->setPlaybackCount(m->playbackCount() + 1);
4413                         if (m->endTick() >= endTick)
4414                               break;
4415                         }
4416                   }
4417             // consider remaining lyrics
4418             for (unsigned lyricsNumber = 0; lyricsNumber < maxLyrics; lyricsNumber++) {
4419                   for (Measure* m = firstMeasure(); m; m = m->nextMeasure()) {
4420                         unsigned playCount = m->playbackCount();
4421                         if (lyricsNumber >= playCount) {
4422                               for (Segment* seg = m->first(st); seg; seg = seg->next(st)) {
4423                                     // consider voice 1 only
4424                                     ChordRest* cr = toChordRest(seg->element(track));
4425                                     if (!cr || cr->lyrics().empty())
4426                                           continue;
4427                                     if (cr->lyrics().size() > maxLyrics)
4428                                           maxLyrics = cr->lyrics().size();
4429                                     if (lyricsNumber >= cr->lyrics().size())
4430                                           continue;
4431                                     Lyrics* l = cr->lyrics(lyricsNumber, Placement::BELOW);  // TODO
4432                                     if (!l)
4433                                           continue;
4434                                     found = true;
4435                                     QString lyric = l->plainText().trimmed();
4436                                     if (l->syllabic() == Lyrics::Syllabic::SINGLE || l->syllabic() == Lyrics::Syllabic::END)
4437                                           result += lyric + " ";
4438                                     else if (l->syllabic() == Lyrics::Syllabic::BEGIN || l->syllabic() == Lyrics:: Syllabic::MIDDLE)
4439                                           result += lyric;
4440                                     }
4441                               }
4442                         }
4443                   }
4444             if (found)
4445                   result += "\n\n";
4446             }
4447       return result.trimmed();
4448       }
4449 
4450 //---------------------------------------------------------
4451 //   keysig
4452 //---------------------------------------------------------
4453 
keysig()4454 int Score::keysig()
4455       {
4456       Key result = Key::C;
4457       for (int staffIdx = 0; staffIdx < nstaves(); ++staffIdx) {
4458             Staff* st = staff(staffIdx);
4459             constexpr Fraction t(0,1);
4460             Key key = st->key(t);
4461             if (st->staffType(t)->group() == StaffGroup::PERCUSSION || st->keySigEvent(t).custom() || st->keySigEvent(t).isAtonal())       // ignore percussion and custom / atonal key
4462                   continue;
4463             result = key;
4464             int diff = st->part()->instrument()->transpose().chromatic; //TODO keySigs and pitched to unpitched instr changes
4465             if (!styleB(Sid::concertPitch) && diff)
4466                   result = transposeKey(key, diff, st->part()->preferSharpFlat());
4467             break;
4468             }
4469       return int(result);
4470       }
4471 
4472 //---------------------------------------------------------
4473 //   duration
4474 //---------------------------------------------------------
4475 
duration()4476 int Score::duration()
4477       {
4478       masterScore()->setExpandRepeats(true);
4479       const RepeatList& rl = repeatList();
4480       if (rl.empty())
4481             return 0;
4482       const RepeatSegment* rs = rl.last();
4483       return lrint(utick2utime(rs->utick + rs->len()));
4484       }
4485 
4486 //---------------------------------------------------------
4487 //   durationWithoutRepeats
4488 //---------------------------------------------------------
4489 
durationWithoutRepeats()4490 int Score::durationWithoutRepeats()
4491       {
4492       const RepeatList& rl = repeatList2();
4493       if (rl.empty())
4494             return 0;
4495       const RepeatSegment* rs = rl.last();
4496       return lrint(utick2utime(rs->utick + rs->len()));
4497       }
4498 
4499 //---------------------------------------------------------
4500 //   createRehearsalMarkText
4501 //---------------------------------------------------------
4502 
createRehearsalMarkText(RehearsalMark * current) const4503 QString Score::createRehearsalMarkText(RehearsalMark* current) const
4504       {
4505       Fraction tick = current->segment()->tick();
4506       RehearsalMark* before = 0;
4507       RehearsalMark* after = 0;
4508       for (Segment* s = firstSegment(SegmentType::All); s; s = s->next1()) {
4509             for (Element* e : s->annotations()) {
4510                   if (e && e->type() == ElementType::REHEARSAL_MARK) {
4511                         if (s->tick() < tick)
4512                               before = toRehearsalMark(e);
4513                         else if (s->tick() > tick) {
4514                               after = toRehearsalMark(e);
4515                               break;
4516                               }
4517                         }
4518                   }
4519             if (after)
4520                   break;
4521             }
4522       QString s = "A";
4523       QString s1 = before ? before->xmlText() : "";
4524       QString s2 = after ? after->xmlText()  : "";
4525       if (s1.isEmpty())
4526             return s;
4527       s = nextRehearsalMarkText(before, current);     // try to sequence
4528       if (s == current->xmlText()) {
4529             // no sequence detected (or current happens to be correct)
4530             return s;
4531             }
4532       else if (s == s2) {
4533             // next in sequence already present
4534             if (s1[0].isLetter()) {
4535                   if (s1.size() == 2)
4536                         s = s1[0] + QChar::fromLatin1(s1[1].toLatin1() + 1);  // BB, BC, CC
4537                   else
4538                         s = s1 + QChar::fromLatin1('1');                      // B, B1, C
4539                   }
4540             else {
4541                   s = s1 + QChar::fromLatin1('A');                            // 2, 2A, 3
4542                   }
4543             }
4544       return s;
4545       }
4546 
4547 //---------------------------------------------------------
4548 //   nextRehearsalMarkText
4549 //    finds next rehearsal in sequence established by previous
4550 //     Alphabetic sequences:
4551 //      A, B, ..., Y, Z, AA, BB, ..., YY, ZZ
4552 //      a, b, ..., y, z, aa, bb, ..., yy, zz
4553 //     Numeric sequences:
4554 //      1, 2, 3, ...
4555 //      If number of previous rehearsal mark matches measure number, assume use of measure numbers throughout
4556 //---------------------------------------------------------
4557 
nextRehearsalMarkText(RehearsalMark * previous,RehearsalMark * current) const4558 QString Score::nextRehearsalMarkText(RehearsalMark* previous, RehearsalMark* current) const
4559       {
4560       QString previousText = previous->xmlText();
4561       QString fallback = current ? current->xmlText() : previousText + "'";
4562 
4563       if (previousText.length() == 1 && previousText[0].isLetter()) {
4564             // single letter sequence
4565             if (previousText == "Z")
4566                   return "AA";
4567             else if (previousText == "z")
4568                   return "aa";
4569             else
4570                   return QChar::fromLatin1(previousText[0].toLatin1() + 1);
4571             }
4572       else if (previousText.length() == 2 && previousText[0].isLetter() && previousText[1].isLetter()) {
4573             // double letter sequence
4574             if (previousText[0] == previousText[1]) {
4575                   // repeated letter sequence
4576                   if (previousText.toUpper() != "ZZ") {
4577                         QString c = QChar::fromLatin1(previousText[0].toLatin1() + 1);
4578                         return c + c;
4579                         }
4580                   else {
4581                         return fallback;
4582                         }
4583                   }
4584             else {
4585                   return fallback;
4586                   }
4587             }
4588       else {
4589             // try to interpret as number
4590             bool ok;
4591             int n = previousText.toInt(&ok);
4592             if (!ok) {
4593                   return fallback;
4594                   }
4595             else if (current && n == previous->segment()->measure()->no() + 1) {
4596                   // use measure number
4597                   n = current->segment()->measure()->no() + 1;
4598                   return QString("%1").arg(n);
4599                   }
4600             else {
4601                   // use number sequence
4602                   n = previousText.toInt() + 1;
4603                   return QString("%1").arg(n);
4604                   }
4605             }
4606       }
4607 
4608 //---------------------------------------------------------
4609 //   changeVoice
4610 //    moves selected notes into specified voice if possible
4611 //---------------------------------------------------------
4612 
changeVoice(int voice)4613 void Score::changeVoice(int voice)
4614       {
4615       startCmd();
4616       QList<Element*> el;
4617       QList<Element*> oel = selection().elements();     // make copy
4618       for (Element* e : oel) {
4619             if (e->type() == ElementType::NOTE) {
4620                   Note* note   = toNote(e);
4621                   Chord* chord = note->chord();
4622 
4623                   // move grace notes with main chord only
4624                   if (chord->isGrace())
4625                         continue;
4626 
4627                   if (chord->voice() != voice) {
4628                         Segment* s       = chord->segment();
4629                         Measure* m       = s->measure();
4630                         size_t notes     = chord->notes().size();
4631                         int dstTrack     = chord->staffIdx() * VOICES + voice;
4632                         ChordRest* dstCR = toChordRest(s->element(dstTrack));
4633                         Chord* dstChord  = nullptr;
4634 
4635                         if (excerpt() && excerpt()->tracks().key(dstTrack, -1) == -1)
4636                               break;
4637 
4638                         // set up destination chord
4639 
4640                         if (dstCR && dstCR->type() == ElementType::CHORD && dstCR->globalTicks() == chord->globalTicks()) {
4641                               // existing chord in destination with correct duration;
4642                               //   can simply move note in
4643                               dstChord = toChord(dstCR);
4644                               }
4645 
4646                         else if (dstCR && dstCR->type() == ElementType::REST && dstCR->globalTicks() == chord->globalTicks()) {
4647                               // existing rest in destination with correct duration;
4648                               //   replace with chord, then move note in
4649                               //   this case allows for tuplets, unlike the more general case below
4650                               dstChord = new Chord(this);
4651                               dstChord->setTrack(dstTrack);
4652                               dstChord->setDurationType(chord->durationType());
4653                               dstChord->setTicks(chord->ticks());
4654                               dstChord->setTuplet(dstCR->tuplet());
4655                               dstChord->setParent(s);
4656                               undoRemoveElement(dstCR);
4657                               }
4658 
4659                         else if (!chord->tuplet()) {
4660                               // rests or gap in destination
4661                               //   insert new chord if the rests / gap are long enough
4662                               //   then move note in
4663                               ChordRest* pcr = nullptr;
4664                               ChordRest* ncr = nullptr;
4665                               for (Segment* s2 = m->first(SegmentType::ChordRest); s2; s2 = s2->next()) {
4666                                     if (s2->segmentType() != SegmentType::ChordRest)
4667                                           continue;
4668                                     ChordRest* cr2 = toChordRest(s2->element(dstTrack));
4669                                     if (!cr2 || cr2->type() == ElementType::REST)
4670                                           continue;
4671                                     if (s2->tick() < s->tick()) {
4672                                           pcr = cr2;
4673                                           continue;
4674                                           }
4675                                     else if (s2->tick() >= s->tick()) {
4676                                           ncr = cr2;
4677                                           break;
4678                                           }
4679                                     }
4680                               Fraction gapStart = pcr ? pcr->tick() + pcr->actualTicks() : m->tick();
4681                               Fraction gapEnd   = ncr ? ncr->tick() : m->tick() + m->ticks();
4682                               if (gapStart <= s->tick() && gapEnd >= s->tick() + chord->actualTicks()) {
4683                                     // big enough gap found
4684                                     dstChord = new Chord(this);
4685                                     dstChord->setTrack(dstTrack);
4686                                     dstChord->setDurationType(chord->durationType());
4687                                     dstChord->setTicks(chord->ticks());
4688                                     dstChord->setParent(s);
4689                                     // makeGapVoice will not back-fill an empty voice
4690                                     if (voice && !dstCR)
4691                                           expandVoice(s, /*m->first(SegmentType::ChordRest,*/ dstTrack);
4692                                     makeGapVoice(s, dstTrack, chord->actualTicks(), s->tick());
4693                                     }
4694                               }
4695 
4696                         // move note to destination chord
4697                         if (dstChord) {
4698                               // create & add new note
4699                               Note* newNote = new Note(*note);
4700                               newNote->setSelected(false);
4701                               newNote->setParent(dstChord);
4702                               undoAddElement(newNote);
4703                               el.append(newNote);
4704                               // add new chord if one was created
4705                               if (dstChord != dstCR)
4706                                     undoAddCR(dstChord, m, s->tick());
4707                               // reconnect the tie to this note, if any
4708                               Tie* tie = note->tieBack();
4709                               if (tie)
4710                                     undoChangeSpannerElements(tie, tie->startNote(), newNote);
4711                               // reconnect the tie from this note, if any
4712                               tie = note->tieFor();
4713                               if (tie)
4714                                     undoChangeSpannerElements(tie, newNote, tie->endNote());
4715                               // remove original note
4716                               if (notes > 1) {
4717                                     undoRemoveElement(note);
4718                                     }
4719                               else if (notes == 1) {
4720                                     // create rest to leave behind
4721                                     Rest* r = new Rest(this);
4722                                     r->setTrack(chord->track());
4723                                     r->setDurationType(chord->durationType());
4724                                     r->setTicks(chord->ticks());
4725                                     r->setTuplet(chord->tuplet());
4726                                     r->setParent(s);
4727                                     // if there were grace notes, move them
4728                                     while (!chord->graceNotes().empty()) {
4729                                           Chord* gc = chord->graceNotes().first();
4730                                           Chord* ngc = new Chord(*gc);
4731                                           undoRemoveElement(gc);
4732                                           ngc->setParent(dstChord);
4733                                           ngc->setTrack(dstChord->track());
4734                                           undoAddElement(ngc);
4735                                           }
4736                                     // remove chord, replace with rest
4737                                     undoRemoveElement(chord);
4738                                     undoAddCR(r, m, s->tick());
4739                                     }
4740                               }
4741                         }
4742                   }
4743             }
4744 
4745       if (!el.empty())
4746             selection().clear();
4747       for (Element* e : el)
4748             select(e, SelectType::ADD, -1);
4749       setLayoutAll();
4750       endCmd();
4751       }
4752 
4753 #if 0
4754 //---------------------------------------------------------
4755 //   cropPage - crop a single page score to the content
4756 ///    margins will be applied on the 4 sides
4757 //---------------------------------------------------------
4758 
4759 void Score::cropPage(qreal margins)
4760       {
4761       if (npages() == 1) {
4762             Page* page = pages()[0];
4763             if (page) {
4764                   QRectF ttbox = page->tbbox();
4765 
4766                   qreal margin = margins / INCH;
4767                   f.setSize(QSizeF((ttbox.width() / DPI) + 2 * margin, (ttbox.height()/ DPI) + 2 * margin));
4768 
4769                   qreal offset = curFormat->oddLeftMargin() - ttbox.x() / DPI;
4770                   if (offset < 0)
4771                         offset = 0.0;
4772                   f.setOddLeftMargin(margin + offset);
4773                   f.setEvenLeftMargin(margin + offset);
4774                   f.setOddBottomMargin(margin);
4775                   f.setOddTopMargin(margin);
4776                   f.setEvenBottomMargin(margin);
4777                   f.setEvenTopMargin(margin);
4778 
4779                   undoChangePageFormat(&f, spatium(), pageNumberOffset());
4780                   }
4781             }
4782       }
4783 #endif
4784 
4785 //---------------------------------------------------------
4786 //   getProperty
4787 //---------------------------------------------------------
4788 
getProperty(Pid) const4789 QVariant Score::getProperty(Pid /*id*/) const
4790       {
4791       qDebug("Score::getProperty: unhandled id");
4792       return QVariant();
4793       }
4794 
4795 //---------------------------------------------------------
4796 //   setProperty
4797 //---------------------------------------------------------
4798 
setProperty(Pid,const QVariant &)4799 bool Score::setProperty(Pid /*id*/, const QVariant& /*v*/)
4800       {
4801       qDebug("Score::setProperty: unhandled id");
4802       setLayoutAll();
4803       return true;
4804       }
4805 
4806 //---------------------------------------------------------
4807 //   propertyDefault
4808 //---------------------------------------------------------
4809 
propertyDefault(Pid) const4810 QVariant Score::propertyDefault(Pid /*id*/) const
4811       {
4812       return QVariant();
4813       }
4814 
4815 //---------------------------------------------------------
4816 //   setStyle
4817 //---------------------------------------------------------
4818 
setStyle(const MStyle & s,const bool overlap)4819 void Score::setStyle(const MStyle& s, const bool overlap)
4820       {
4821       if (!overlap) {
4822             style() = s;
4823             return;
4824             }
4825 
4826       MStyle styleCopy = s;
4827 
4828       for (int i = static_cast<int>(Sid::NOSTYLE) + 1; i < static_cast<int>(Sid::STYLES); i++) {
4829           Sid sid = static_cast<Sid>(i);
4830 
4831           if (!styleCopy.isDefault(sid))
4832                 style().set(sid, styleCopy.value(sid));
4833           }
4834       }
4835 
4836 //---------------------------------------------------------
4837 //   getTextStyleUserName
4838 //---------------------------------------------------------
4839 
getTextStyleUserName(Tid tid)4840 QString Score::getTextStyleUserName(Tid tid)
4841       {
4842       QString name = "";
4843       if (int(tid) >= int(Tid::USER1) && int(tid) <= int(Tid::USER12)) {
4844             int idx = int(tid) - int(Tid::USER1);
4845             Sid sid[] = { Sid::user1Name, Sid::user2Name, Sid::user3Name, Sid::user4Name, Sid::user5Name, Sid::user6Name,
4846                           Sid::user7Name, Sid::user8Name, Sid::user9Name, Sid::user10Name, Sid::user11Name, Sid::user12Name};
4847             name = styleSt(sid[idx]);
4848             }
4849       if (name == "")
4850             name = textStyleUserName(tid);
4851       return name;
4852       }
4853 
4854 //---------------------------------------------------------
4855 //   MasterScore
4856 //---------------------------------------------------------
4857 
MasterScore()4858 MasterScore::MasterScore()
4859    : Score()
4860       {
4861       _tempomap    = new TempoMap;
4862       _sigmap      = new TimeSigMap();
4863       _repeatList  = new RepeatList(this);
4864       _repeatList2 = new RepeatList(this);
4865       _revisions   = new Revisions;
4866       setMasterScore(this);
4867 
4868       _pos[int(POS::CURRENT)] = Fraction(0,1);
4869       _pos[int(POS::LEFT)]    = Fraction(0,1);
4870       _pos[int(POS::RIGHT)]   = Fraction(0,1);
4871 
4872 #if defined(Q_OS_WIN)
4873       metaTags().insert("platform", "Microsoft Windows");
4874 #elif defined(Q_OS_MAC)
4875       metaTags().insert("platform", "Apple Macintosh");
4876 #elif defined(Q_OS_LINUX)
4877       metaTags().insert("platform", "Linux");
4878 #else
4879       metaTags().insert("platform", "Unknown");
4880 #endif
4881       metaTags().insert("movementNumber", "");
4882       metaTags().insert("movementTitle", "");
4883       metaTags().insert("workNumber", "");
4884       metaTags().insert("workTitle", "");
4885       metaTags().insert("arranger", "");
4886       metaTags().insert("composer", "");
4887       metaTags().insert("lyricist", "");
4888       metaTags().insert("poet", "");
4889       metaTags().insert("translator", "");
4890       metaTags().insert("source", "");
4891       metaTags().insert("copyright", "");
4892       metaTags().insert("creationDate", QDate::currentDate().toString(Qt::ISODate));
4893       }
4894 
MasterScore(const MStyle & s)4895 MasterScore::MasterScore(const MStyle& s)
4896    : MasterScore{}
4897       {
4898       _movements = new Movements;
4899       _movements->push_back(this);
4900       setStyle(s);
4901       }
4902 
~MasterScore()4903 MasterScore::~MasterScore()
4904       {
4905       delete _revisions;
4906       delete _repeatList;
4907       delete _repeatList2;
4908       delete _sigmap;
4909       delete _tempomap;
4910       qDeleteAll(_excerpts);
4911       }
4912 
4913 //---------------------------------------------------------
4914 //   setMovements
4915 //---------------------------------------------------------
4916 
setMovements(Movements * m)4917 void MasterScore::setMovements(Movements* m)
4918       {
4919       _movements = m;
4920       if (_movements)
4921             _movements->push_back(this);
4922       }
4923 
4924 //---------------------------------------------------------
4925 //   isSavable
4926 //---------------------------------------------------------
4927 
isSavable() const4928 bool MasterScore::isSavable() const
4929       {
4930       // TODO: check if file can be created if it does not exist
4931       return fileInfo()->isWritable() || !fileInfo()->exists();
4932       }
4933 
4934 //---------------------------------------------------------
4935 //   setTempomap
4936 //---------------------------------------------------------
4937 
setTempomap(TempoMap * tm)4938 void MasterScore::setTempomap(TempoMap* tm)
4939       {
4940       delete _tempomap;
4941       _tempomap = tm;
4942       }
4943 
4944 //---------------------------------------------------------
4945 //   removeOmr
4946 //---------------------------------------------------------
4947 
removeOmr()4948 void MasterScore::removeOmr()
4949       {
4950       _showOmr = false;
4951 #ifdef OMR
4952       delete _omr;
4953 #endif
4954       _omr = 0;
4955       }
4956 
4957 //---------------------------------------------------------
4958 //   setName
4959 //---------------------------------------------------------
4960 
setName(const QString & ss)4961 void MasterScore::setName(const QString& ss)
4962       {
4963       QString s(ss);
4964       s.replace('/', '_');    // for sanity
4965       if (!(s.endsWith(".mscz") || s.endsWith(".mscx")))
4966             s += ".mscz";
4967       info.setFile(s);
4968       }
4969 
4970 //---------------------------------------------------------
4971 //   title
4972 //---------------------------------------------------------
4973 
title() const4974 QString MasterScore::title() const
4975       {
4976       return fileInfo()->completeBaseName();
4977       }
4978 
title() const4979 QString Score::title() const
4980       {
4981       return _excerpt->title();
4982       }
4983 
4984 //---------------------------------------------------------
4985 //   addRefresh
4986 //---------------------------------------------------------
4987 
addRefresh(const QRectF & r)4988 void Score::addRefresh(const QRectF& r)
4989       {
4990       _updateState.refresh |= r;
4991       cmdState().setUpdateMode(UpdateMode::Update);
4992       }
4993 
4994 //---------------------------------------------------------
4995 //   staffIdx
4996 //
4997 ///  Return index for the first staff of \a part.
4998 //---------------------------------------------------------
4999 
staffIdx(const Part * part) const5000 int Score::staffIdx(const Part* part) const
5001       {
5002       int idx = 0;
5003       for (Part* p : _parts) {
5004             if (p == part)
5005                   break;
5006             idx += p->nstaves();
5007             }
5008       return idx;
5009       }
5010 
5011 //---------------------------------------------------------
5012 //   setUpdateAll
5013 //---------------------------------------------------------
5014 
setUpdateAll()5015 void MasterScore::setUpdateAll()
5016       {
5017       _cmdState.setUpdateMode(UpdateMode::UpdateAll);
5018       }
5019 
5020 //---------------------------------------------------------
5021 //   setLayoutAll
5022 //---------------------------------------------------------
5023 
setLayoutAll(int staff,const Element * e)5024 void MasterScore::setLayoutAll(int staff, const Element* e)
5025       {
5026       _cmdState.setTick(Fraction(0,1));
5027       _cmdState.setTick(measures()->last() ? measures()->last()->endTick() : Fraction(0,1));
5028 
5029       if (e && e->score() == this) {
5030             // TODO: map staff number properly
5031             const int startStaff = staff == -1 ? 0 : staff;
5032             const int endStaff = staff == -1 ? (nstaves() - 1) : staff;
5033             _cmdState.setStaff(startStaff);
5034             _cmdState.setStaff(endStaff);
5035 
5036             _cmdState.setElement(e);
5037             }
5038       }
5039 
5040 //---------------------------------------------------------
5041 //   setLayout
5042 //---------------------------------------------------------
5043 
setLayout(const Fraction & t,int staff,const Element * e)5044 void MasterScore::setLayout(const Fraction& t, int staff, const Element* e)
5045       {
5046       if (t >= Fraction(0,1))
5047             _cmdState.setTick(t);
5048 
5049       if (e && e->score() == this) {
5050             // TODO: map staff number properly
5051             _cmdState.setStaff(staff);
5052             _cmdState.setElement(e);
5053             }
5054       }
5055 
setLayout(const Fraction & tick1,const Fraction & tick2,int staff1,int staff2,const Element * e)5056 void MasterScore::setLayout(const Fraction& tick1, const Fraction& tick2, int staff1, int staff2, const Element* e)
5057       {
5058       if (tick1 >= Fraction(0,1))
5059             _cmdState.setTick(tick1);
5060       if (tick2 >= Fraction(0,1))
5061             _cmdState.setTick(tick2);
5062 
5063       if (e && e->score() == this) {
5064             // TODO: map staff number properly
5065             _cmdState.setStaff(staff1);
5066             _cmdState.setStaff(staff2);
5067 
5068             _cmdState.setElement(e);
5069             }
5070       }
5071 
5072 //---------------------------------------------------------
5073 //   setPlaybackScore
5074 //---------------------------------------------------------
5075 
setPlaybackScore(Score * score)5076 void MasterScore::setPlaybackScore(Score* score)
5077       {
5078       if (_playbackScore == score)
5079             return;
5080 
5081       _playbackScore = score;
5082       _playbackSettingsLinks.clear();
5083 
5084       if (!_playbackScore)
5085             return;
5086 
5087       for (MidiMapping& mm : _midiMapping)
5088             mm.articulation()->setSoloMute(true);
5089       for (Part* part : score->parts()) {
5090             for (auto& i : *part->instruments()) {
5091                   Instrument* instr = i.second;
5092                   for (Channel* ch : instr->channel()) {
5093                         Channel* pChannel = playbackChannel(ch);
5094                         Q_ASSERT(pChannel);
5095                         if (!pChannel)
5096                               continue;
5097                         _playbackSettingsLinks.emplace_back(pChannel, ch, /* excerpt */ true);
5098                         }
5099                   }
5100             }
5101       }
5102 
5103 //---------------------------------------------------------
5104 //   updateExpressive
5105 //    change patches to their expressive equivalent or vica versa, if possible
5106 //    This works only with MuseScore general soundfont
5107 //
5108 //    The first version of the function decides whether to make patches expressive
5109 //    or not, based on the synth settings. The second will switch patches based on
5110 //    the value of the expressive parameter.
5111 //---------------------------------------------------------
5112 
updateExpressive(Synthesizer * synth)5113 void MasterScore::updateExpressive(Synthesizer* synth)
5114       {
5115       SynthesizerState s = synthesizerState();
5116       SynthesizerGroup g = s.group("master");
5117 
5118       int method = 1;
5119       for (const IdValue &idVal : g) {
5120             if (idVal.id == 4) {
5121                   method = idVal.data.toInt();
5122                   break;
5123                   }
5124             }
5125 
5126       updateExpressive(synth, (method != 0));
5127       }
5128 
5129 
updateExpressive(Synthesizer * synth,bool expressive,bool force)5130 void MasterScore::updateExpressive(Synthesizer* synth, bool expressive, bool force /* = false */)
5131       {
5132       if (!synth)
5133             return;
5134 
5135       if (!force) {
5136             SynthesizerState s = synthesizerState();
5137             SynthesizerGroup g = s.group("master");
5138 
5139             for (const IdValue &idVal : g) {
5140                   if (idVal.id == 4) {
5141                         int method = idVal.data.toInt();
5142                         if (expressive == (method == 0))
5143                               return; // method and expression change don't match, so don't switch}
5144                         }
5145                   }
5146             }
5147 
5148       for (Part* p : parts()) {
5149             const InstrumentList* il = p->instruments();
5150             for (auto it = il->begin(); it != il->end(); it++) {
5151                   Instrument* i = it->second;
5152                   i->switchExpressive(this, synth, expressive, force);
5153                   }
5154             }
5155 
5156       }
5157 
5158 //---------------------------------------------------------
5159 //   rebuildAndUpdateExpressive
5160 //    implicitly rebuild midi mappings as well. Should be preferred over
5161 //    just updateExpressive, in most cases.
5162 //---------------------------------------------------------
5163 
rebuildAndUpdateExpressive(Synthesizer * synth)5164 void MasterScore::rebuildAndUpdateExpressive(Synthesizer* synth)
5165       {
5166       // Rebuild midi mappings to make sure we have playback channels
5167       rebuildMidiMapping();
5168 
5169       updateExpressive(synth);
5170 
5171       // Rebuild midi mappings again to be safe
5172       rebuildMidiMapping();
5173       }
5174 
5175 //---------------------------------------------------------
5176 //   isTopScore
5177 //---------------------------------------------------------
5178 
isTopScore() const5179 bool Score::isTopScore() const
5180       {
5181       return !(isMaster() && static_cast<const MasterScore*>(this)->prev());
5182       }
5183 
5184 //---------------------------------------------------------
5185 //   Movements
5186 //---------------------------------------------------------
5187 
Movements()5188 Movements::Movements()
5189    : std::vector<MasterScore*>()
5190       {
5191       _undo = new UndoStack();
5192       }
5193 
~Movements()5194 Movements::~Movements()
5195       {
5196       qDeleteAll(_pages);
5197       delete _undo;
5198       }
5199 
5200 //---------------------------------------------------------
5201 //   ScoreLoad::_loading
5202 //    If the _loading > 0 then pushes and pops to
5203 //    the undo stack do not emit a warning.
5204 //    Usually pushes and pops to the undo stack are only
5205 //    valid inside a startCmd() - endCmd(). Exceptions
5206 //    occurred during score loading.
5207 //---------------------------------------------------------
5208 
5209 int ScoreLoad::_loading = 0;
5210 
5211 }
5212 
5213