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